From 5128e1a06c1bebe435bcc19c2e9b1ef601dbe40f Mon Sep 17 00:00:00 2001 From: James Chiang Date: Mon, 12 Aug 2024 01:08:52 -0700 Subject: [PATCH] soc: nuvoton: npcm: update esiost to support CONFIG_XIP npcm4 rom code always use first 0x600 bytes to verify image. west jlink script retrieve flash address from configuration file: if build_conf.getboolean('CONFIG_HAS_FLASH_LOAD_OFFSET'): return (build_conf['CONFIG_FLASH_BASE_ADDRESS'] + build_conf['CONFIG_FLASH_LOAD_OFFSET']) else: return build_conf['CONFIG_FLASH_BASE_ADDRESS'] jlink script will program wrong flash place if set CONFIG_FLASH_LOAD_OFFSET. change to use CONFIG_ROM_START_OFFSET and revise esiost tool. for CONFIG_XIP=n, add HEADER_SIZE for output file Signed-off-by: James Chiang --- .../npcm400f_evb/npcm400f_evb_defconfig | 2 +- soc/nuvoton/npcm/common/esiost/esiost.py | 59 ++++++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig b/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig index 7286d69b3c5595..009983fbc6a65a 100644 --- a/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig +++ b/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig @@ -8,7 +8,7 @@ CONFIG_SRAM_VECTOR_TABLE=y CONFIG_BOOTLOADER_SRAM_SIZE=0 # General Kernel Options CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=96000000 -# CONFIG_FLASH_LOAD_OFFSET=0x600 +# CONFIG_ROM_START_OFFSET=0x600 CONFIG_XIP=n # CONFIG_ARM_MPU=y diff --git a/soc/nuvoton/npcm/common/esiost/esiost.py b/soc/nuvoton/npcm/common/esiost/esiost.py index f07bfb84c3d4bf..9fa32f1e680106 100755 --- a/soc/nuvoton/npcm/common/esiost/esiost.py +++ b/soc/nuvoton/npcm/common/esiost/esiost.py @@ -42,7 +42,7 @@ HDR_FW_SEG4_HASH_OFFSET = 0x5C0 FW_IMAGE_OFFSET = 0x600 -ARM_FW_ENTRY_POINT_OFFSET = 4 +ARM_FW_ENTRY_POINT_OFFSET = 0x004 # Header field known values FW_HDR_ANCHOR = '%FiMg94@' @@ -222,6 +222,11 @@ def _set_firmware_load_start_address(output, esiost_args): fw_arm_entry_byte = input_file.read(4) fw_arm_entry_pt = int.from_bytes(fw_arm_entry_byte, "little") + if (fw_arm_entry_pt == 0): + input_file.seek(ARM_FW_ENTRY_POINT_OFFSET + HEADER_SIZE) + fw_arm_entry_byte = input_file.read(4) + fw_arm_entry_pt = int.from_bytes(fw_arm_entry_byte, "little") + if fw_arm_entry_pt > start_flash_addr and fw_arm_entry_pt < end_flash_addr: fw_load_addr = 0x0 start_flash_addr = 0x0 @@ -279,6 +284,11 @@ def _set_firmware_entry_point(output, esiost_args): fw_arm_entry_byte = input_file.read(4) fw_arm_entry_pt = int.from_bytes(fw_arm_entry_byte, "little") + if (fw_arm_entry_pt == 0): + input_file.seek(ARM_FW_ENTRY_POINT_OFFSET + HEADER_SIZE) + fw_arm_entry_byte = input_file.read(4) + fw_arm_entry_pt = int.from_bytes(fw_arm_entry_byte, "little") + if fw_arm_entry_pt > start_flash_addr and fw_arm_entry_pt < end_flash_addr: fw_entry_pt = start_flash_addr @@ -336,11 +346,14 @@ def _set_firmware_load_hash(output, esiost_args): :param output: the output file object, :param esiost_args: the object representing the command line arguments. """ + sha256_hash = hashlib.sha256() + with output.open("r+b") as f: + f.seek(HEADER_SIZE) + # Read and update hash string value in blocks of 4K + for byte_block in iter(lambda: f.read(4096), b""): + sha256_hash.update(byte_block) - input_file = Path(esiost_args.input) - input_file_size = Path(esiost_args.input).stat().st_size - - hash_data = _openssl_digest(input_file) + hash_data = bytearray(sha256_hash.digest()) with output.open("r+b") as output_file: output_file.seek(HDR_FW_LOAD_HASH_OFFSET) @@ -450,6 +463,7 @@ def _set_firmware_segment_hash(output, esiost_args): output_file.seek(HDR_FW_SEG1_SIZE_OFFSET) seg1_size = int.from_bytes(output_file.read(4), "little") output_file.seek(seg1_start) + seg1_data = output_file.read(seg1_size) seg1_file_path = Path("seg1_" + output_file.name) @@ -464,7 +478,14 @@ def _set_firmware_segment_hash(output, esiost_args): output_file.write(hash_data) # seg3 hash - hash_data = _openssl_digest(input_file) + sha256_hash = hashlib.sha256() + output_file.seek(HEADER_SIZE) + # Read and update hash string value in blocks of 4K + for byte_block in iter(lambda: output_file.read(4096), b""): + sha256_hash.update(byte_block) + + hash_data = bytearray(sha256_hash.digest()) + output_file.seek(HDR_FW_SEG3_HASH_OFFSET) output_file.write(hash_data) @@ -478,16 +499,36 @@ def _copy_image(output, esiost_args): :param output: the output file object, :param esiost_args: the object representing the command line arguments. """ + + # check input file offset + with open(esiost_args.input, "rb") as firmware_image: + firmware_image.seek(ARM_FW_ENTRY_POINT_OFFSET) + fw_arm_entry_byte = firmware_image.read(4) + fw_arm_entry_pt = int.from_bytes(fw_arm_entry_byte, "little") + if (fw_arm_entry_pt != 0): + image_offset = 0 + input_file_size = Path(esiost_args.input).stat().st_size + else: + firmware_image.seek(ARM_FW_ENTRY_POINT_OFFSET + HEADER_SIZE) + fw_arm_entry_byte = firmware_image.read(4) + fw_arm_entry_pt = int.from_bytes(fw_arm_entry_byte, "little") + if (fw_arm_entry_pt == 0): + sys.exit(EXIT_FAILURE_STATUS) + else: + image_offset = 1 + input_file_size = Path(esiost_args.input).stat().st_size - HEADER_SIZE + + firmware_image.close() + with open(esiost_args.input, "rb") as firmware_image: with open(output, "r+b") as output_file: - output_file.seek(HEADER_SIZE) + if (image_offset == 0): + output_file.seek(HEADER_SIZE) for line in firmware_image: output_file.write(line) output_file.close() firmware_image.close() - input_file_size = Path(esiost_args.input).stat().st_size - # update firmware length if needed fw_length = esiost_args.firmware_length if fw_length is None: