mirror of
https://gitee.com/openharmony/update_packaging_tools
synced 2024-11-26 16:31:21 +00:00
b710369958
fix:fix unpack tool
214 lines
8.5 KiB
Python
214 lines
8.5 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright (c) 2022 Huawei Device Co., Ltd.
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""
|
|
Description : Unpack updater package
|
|
"""
|
|
import os
|
|
import struct
|
|
import time
|
|
from create_update_package import UPGRADE_FILE_HEADER_LEN
|
|
from create_update_package import UPGRADE_COMPINFO_SIZE
|
|
from create_update_package import UPGRADE_COMPINFO_SIZE_L2
|
|
from create_update_package import COMPONENT_ADDR_SIZE
|
|
from create_update_package import COMPONENT_ADDR_SIZE_L2
|
|
from create_update_package import UPGRADE_RESERVE_LEN
|
|
|
|
from create_hashdata import HASH_TYPE_SIZE
|
|
from create_hashdata import HASH_LENGTH_SIZE
|
|
from create_hashdata import HASH_TLV_SIZE
|
|
from create_hashdata import UPGRADE_HASHINFO_SIZE
|
|
from create_hashdata import CreateHash
|
|
from create_hashdata import HashType
|
|
|
|
from log_exception import UPDATE_LOGGER
|
|
from utils import OPTIONS_MANAGER
|
|
|
|
COMPINFO_LEN_OFFSET = 178
|
|
COMPINFO_LEN_SIZE = 2
|
|
COMPONENT_ADDR_OFFSET = UPGRADE_FILE_HEADER_LEN
|
|
COMPONENT_TYPE_OFFSET = COMPONENT_ADDR_OFFSET + COMPONENT_ADDR_SIZE + 4
|
|
COMPONENT_TYPE_OFFSET_L2 = COMPONENT_ADDR_OFFSET + COMPONENT_ADDR_SIZE_L2 + 4
|
|
COMPONENT_TYPE_SIZE = 1
|
|
COMPONENT_SIZE_OFFSET = 11
|
|
COMPONENT_SIZE_SIZE = 4
|
|
|
|
"""
|
|
Format
|
|
H: unsigned short
|
|
I: unsigned int
|
|
B: unsigned char
|
|
s: char[]
|
|
"""
|
|
COMPINFO_LEN_FMT = "H"
|
|
COMPONENT_TYPE_FMT = "B"
|
|
COMPONENT_SIZE_FMT = "I"
|
|
|
|
|
|
class UnpackPackage(object):
|
|
"""
|
|
Unpack the update.bin file
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.count = 0
|
|
self.component_offset = 0
|
|
self.save_path = None
|
|
|
|
if OPTIONS_MANAGER.not_l2:
|
|
self.compinfo_size = UPGRADE_COMPINFO_SIZE
|
|
self.type_offset = COMPONENT_TYPE_OFFSET
|
|
self.addr_size = COMPONENT_ADDR_SIZE
|
|
else:
|
|
self.compinfo_size = UPGRADE_COMPINFO_SIZE_L2
|
|
self.type_offset = COMPONENT_TYPE_OFFSET_L2
|
|
self.addr_size = COMPONENT_ADDR_SIZE_L2
|
|
|
|
self.addr_offset = COMPONENT_ADDR_OFFSET
|
|
self.size_offset = self.type_offset + COMPONENT_SIZE_OFFSET
|
|
|
|
def check_args(self):
|
|
if not os.access(OPTIONS_MANAGER.unpack_package_path, os.R_OK) and \
|
|
not os.path.exists(self.save_path):
|
|
UPDATE_LOGGER.print_log(
|
|
"Access unpack_package_path fail! path: %s" % \
|
|
OPTIONS_MANAGER.unpack_package_path, UPDATE_LOGGER.ERROR_LOG)
|
|
return False
|
|
return True
|
|
|
|
def parse_package_file(self, package_file):
|
|
try:
|
|
package_file.seek(COMPINFO_LEN_OFFSET)
|
|
compinfo_len_buffer = package_file.read(COMPINFO_LEN_SIZE)
|
|
compinfo_len = struct.unpack(COMPINFO_LEN_FMT, compinfo_len_buffer)
|
|
except (struct.error, IOError):
|
|
return False
|
|
|
|
self.count = compinfo_len[0] // self.compinfo_size
|
|
self.component_offset = UPGRADE_FILE_HEADER_LEN + compinfo_len[0] + UPGRADE_RESERVE_LEN
|
|
|
|
try:
|
|
package_file.seek(self.component_offset)
|
|
next_tlv_type_buffer = package_file.read(HASH_TYPE_SIZE)
|
|
next_tlv_type = struct.unpack(COMPINFO_LEN_FMT, next_tlv_type_buffer)
|
|
if next_tlv_type[0] == 0x06:
|
|
UPDATE_LOGGER.print_log("parse update.bin in SDcard package")
|
|
self.component_offset += HASH_TLV_SIZE + UPGRADE_HASHINFO_SIZE + HASH_TYPE_SIZE
|
|
package_file.seek(self.component_offset)
|
|
hashdata_len_buffer = package_file.read(HASH_LENGTH_SIZE)
|
|
hashdata_len = struct.unpack(COMPONENT_SIZE_FMT, hashdata_len_buffer)
|
|
self.component_offset += HASH_LENGTH_SIZE + hashdata_len[0] + HASH_TYPE_SIZE
|
|
elif next_tlv_type[0] == 0x08:
|
|
self.component_offset += HASH_TYPE_SIZE
|
|
|
|
package_file.seek(self.component_offset)
|
|
sign_len_buffer = package_file.read(HASH_LENGTH_SIZE)
|
|
sign_len = struct.unpack(COMPONENT_SIZE_FMT, sign_len_buffer)
|
|
UPDATE_LOGGER.print_log(
|
|
"signdata offset:%d length:%d" % (self.component_offset + HASH_LENGTH_SIZE, sign_len[0]))
|
|
self.component_offset += HASH_LENGTH_SIZE + sign_len[0]
|
|
except (struct.error, IOError):
|
|
return False
|
|
|
|
UPDATE_LOGGER.print_log("parse package file success! components: %d" % self.count)
|
|
return True
|
|
|
|
def parse_component(self, package_file):
|
|
try:
|
|
package_file.seek(self.addr_offset)
|
|
component_addr = package_file.read(self.addr_size)
|
|
component_addr = component_addr.split(b"\x00")[0].decode('utf-8')
|
|
|
|
package_file.seek(self.type_offset)
|
|
component_type_buffer = package_file.read(COMPONENT_TYPE_SIZE)
|
|
component_type = struct.unpack(COMPONENT_TYPE_FMT, component_type_buffer)
|
|
|
|
package_file.seek(self.size_offset)
|
|
component_size_buffer = package_file.read(COMPONENT_SIZE_SIZE)
|
|
component_size = struct.unpack(COMPONENT_SIZE_FMT, component_size_buffer)
|
|
except (struct.error, IOError):
|
|
UPDATE_LOGGER.print_log(
|
|
"parse component failed!", UPDATE_LOGGER.ERROR_LOG)
|
|
return False, False, False
|
|
|
|
return component_addr, component_type[0], component_size[0]
|
|
|
|
def create_image_file(self, package_file):
|
|
component_name, component_type, component_size = \
|
|
self.parse_component(package_file)
|
|
if component_name is None or component_type is None or component_size is None:
|
|
UPDATE_LOGGER.print_log("get component_info failed!", UPDATE_LOGGER.ERROR_LOG)
|
|
return False
|
|
component_name = component_name.strip('/')
|
|
if component_name == "version_list":
|
|
component_name = "VERSION.mbn"
|
|
elif component_name == "board_list":
|
|
component_name = "BOARD.list"
|
|
elif component_type == 0:
|
|
component_name = ''.join([component_name, '.img'])
|
|
elif component_type == 1:
|
|
component_name = ''.join([component_name, '.zip'])
|
|
|
|
image_file_path = os.path.join(self.save_path, component_name)
|
|
|
|
package_file.seek(self.component_offset)
|
|
|
|
UPDATE_LOGGER.print_log("component name: %s" % component_name)
|
|
UPDATE_LOGGER.print_log("component offset: %s" % self.component_offset)
|
|
UPDATE_LOGGER.print_log("component size: %s" % component_size)
|
|
|
|
image_fd = os.open(image_file_path, os.O_RDWR | os.O_CREAT | os.O_TRUNC, 0o755)
|
|
with os.fdopen(image_fd, "wb") as image_file:
|
|
image_buffer = package_file.read(component_size)
|
|
image_file.write(image_buffer)
|
|
|
|
self.addr_offset += self.compinfo_size
|
|
self.type_offset += self.compinfo_size
|
|
self.size_offset += self.compinfo_size
|
|
self.component_offset += component_size
|
|
UPDATE_LOGGER.print_log("Create file: %s" % image_file_path)
|
|
return True
|
|
|
|
def unpack_package(self):
|
|
"""
|
|
Unpack the update.bin file
|
|
return: result
|
|
"""
|
|
UPDATE_LOGGER.print_log(
|
|
"Start unpack updater package: %s" % OPTIONS_MANAGER.unpack_package_path)
|
|
filename = ''.join(['unpack_result_', time.strftime("%H%M%S", time.localtime())])
|
|
self.save_path = os.path.join(OPTIONS_MANAGER.target_package, filename)
|
|
os.makedirs(self.save_path)
|
|
|
|
if not self.check_args():
|
|
UPDATE_LOGGER.print_log(
|
|
"check args failed!", UPDATE_LOGGER.ERROR_LOG)
|
|
return False
|
|
|
|
with open(OPTIONS_MANAGER.unpack_package_path, "rb") as package_file:
|
|
if not self.parse_package_file(package_file):
|
|
UPDATE_LOGGER.print_log(
|
|
"parse package file failed!", UPDATE_LOGGER.ERROR_LOG)
|
|
return False
|
|
|
|
for image_id in range(0, self.count):
|
|
UPDATE_LOGGER.print_log("Start to parse component_%d" % image_id)
|
|
if not self.create_image_file(package_file):
|
|
UPDATE_LOGGER.print_log(
|
|
"create image file failed!", UPDATE_LOGGER.ERROR_LOG)
|
|
return False
|
|
return True
|
|
|