diff options
author | Tom Hughes <tomhughes@chromium.org> | 2022-09-21 14:10:01 -0700 |
---|---|---|
committer | Tom Hughes <tomhughes@chromium.org> | 2022-09-22 12:49:33 -0700 |
commit | 2bcf863b492fe7ed8105c853814dba6ed32ba719 (patch) | |
tree | fcf6ce5810f9ff9e3c8cce434812dd75492269ed /chip/mchp/util/pack_ec_mec152x.py | |
parent | e5fb0b9ba488614b5684e640530f00821ab7b943 (diff) | |
parent | 28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff) | |
download | chrome-ec-2bcf863b492fe7ed8105c853814dba6ed32ba719.tar.gz |
Merge remote-tracking branch cros/main into firmware-fpmcu-bloonchipper-releasefirmware-fpmcu-bloonchipper-release
Generated by: ./util/update_release_branch.py --board bloonchipper
--relevant_paths_file ./util/fingerprint-relevant-paths.txt firmware-
fpmcu-bloonchipper-release
Relevant changes:
git log --oneline e5fb0b9ba4..28712dae9d -- board/hatch_fp
board/bloonchipper common/fpsensor docs/fingerprint driver/fingerprint
util/getversion.sh
ded9307b79 util/getversion.sh: Fix version when not in a git repo
956055e692 board: change Google USB vendor info
71b2ef709d Update license boilerplate text in source code files
33e11afda0 Revert "fpsensor: Build fpsensor source file with C++"
c8d0360723 fpsensor: Build fpsensor source file with C++
bc113abd53 fpsensor: Fix g++ compiler error
150a58a0dc fpsensor: Fix fp_set_sensor_mode return type
b33b5ce85b fpsensor: Remove nested designators for C++ compatibility
2e864b2539 tree-wide: const-ify argv for console commands
56d8b360f9 test: Add test for get ikm failure when seed not set
3a3d6c3690 test: Add test for fpsensor trivial key failure
233e6bbd08 fpsensor_crypto: Abstract calls to hmac_SHA256
0a041b285b docs/fingerprint: Typo correction
c03fab67e2 docs/fingerprint: Fix the path of fputils.py
0b5d4baf5a util/getversion.sh: Fix empty file list handling
6e128fe760 FPMCU dev board environment with Satlab
3eb29b6aa5 builtin: Move ssize_t to sys/types.h
345d62ebd1 docs/fingerprint: Update power numbers for latest dartmonkey release
c25ffdb316 common: Conditionally support printf %l and %i modifiers
9a3c514b45 test: Add a test to check if the debugger is connected
54e603413f Move standard library tests to their own file
43fa6b4bf8 docs/fingerprint: Update power numbers for latest bloonchipper release
25536f9a84 driver/fingerprint/fpc/bep/fpc_sensor_spi.c: Format with clang-format
4face99efd driver/fingerprint/fpc/libfp/fpc_sensor_pal.h: Format with clang-format
738de2b575 trng: Rename rand to trng_rand
14b8270edd docs/fingerprint: Update dragonclaw power numbers
0b268f93d1 driver/fingerprint/fpc/libfp/fpc_private.c: Format with clang-format
f80da163f2 driver/fingerprint/fpc/libfp/fpc_private.h: Format with clang-format
5e9c85c9b1 driver/fingerprint/fpc/libfp/fpc_sensor_pal.c: Format with clang-format
c1f9dd3cf8 driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h: Format with clang-format
eb1e1bed8d driver/fingerprint/fpc/libfp/fpc1145_private.h: Format with clang-format
6e7b611821 driver/fingerprint/fpc/bep/fpc_bio_algorithm.h: Format with clang-format
e0589cd5e2 driver/fingerprint/fpc/bep/fpc1035_private.h: Format with clang-format
7905e556a0 common/fpsensor/fpsensor_crypto.c: Format with clang-format
21289d170c driver/fingerprint/fpc/bep/fpc1025_private.h: Format with clang-format
98a20f937e common/fpsensor/fpsensor_state.c: Format with clang-format
a2d255d8af common/fpsensor/fpsensor.c: Format with clang-format
73055eeb3f driver/fingerprint/fpc/bep/fpc_private.c: Format with clang-format
0f7b5cb509 common/fpsensor/fpsensor_private.h: Format with clang-format
1ceade6e65 driver/fingerprint/fpc/bep/fpc_private.h: Format with clang-format
dc3e9008b8 board/hatch_fp/board.h: Format with clang-format
dca9d74321 Revert "trng: Rename rand to trng_rand"
a6b0b3554f trng: Rename rand to trng_rand
28d0b75b70 third_party/boringssl: Remove unused header
BRANCH=None
BUG=b:246424843 b:234181908 b:244781166 b:234181908 b:244387210
BUG=b:242720240 chromium:1098010 b:180945056 b:236025198 b:234181908
BUG=b:234181908 b:237344361 b:131913998 b:236386294 b:234143158
BUG=b:234781655 b:215613183 b:242720910
TEST=`make -j buildall`
TEST=./test/run_device_tests.py --board bloonchipper
Test "aes": PASSED
Test "cec": PASSED
Test "cortexm_fpu": PASSED
Test "crc": PASSED
Test "flash_physical": PASSED
Test "flash_write_protect": PASSED
Test "fpsensor_hw": PASSED
Test "fpsensor_spi_ro": PASSED
Test "fpsensor_spi_rw": PASSED
Test "fpsensor_uart_ro": PASSED
Test "fpsensor_uart_rw": PASSED
Test "mpu_ro": PASSED
Test "mpu_rw": PASSED
Test "mutex": PASSED
Test "pingpong": PASSED
Test "printf": PASSED
Test "queue": PASSED
Test "rollback_region0": PASSED
Test "rollback_region1": PASSED
Test "rollback_entropy": PASSED
Test "rtc": PASSED
Test "sha256": PASSED
Test "sha256_unrolled": PASSED
Test "static_if": PASSED
Test "stdlib": PASSED
Test "system_is_locked_wp_on": PASSED
Test "system_is_locked_wp_off": PASSED
Test "timer_dos": PASSED
Test "utils": PASSED
Test "utils_str": PASSED
Test "stm32f_rtc": PASSED
Test "panic_data_bloonchipper_v2.0.4277": PASSED
Test "panic_data_bloonchipper_v2.0.5938": PASSED
Force-Relevant-Builds: all
Signed-off-by: Tom Hughes <tomhughes@chromium.org>
Change-Id: I264ad0ffe7afcd507a1e483c6e934a9c4fea47c3
Diffstat (limited to 'chip/mchp/util/pack_ec_mec152x.py')
-rwxr-xr-x | chip/mchp/util/pack_ec_mec152x.py | 1167 |
1 files changed, 652 insertions, 515 deletions
diff --git a/chip/mchp/util/pack_ec_mec152x.py b/chip/mchp/util/pack_ec_mec152x.py index 34846cd6ba..a463a43b6c 100755 --- a/chip/mchp/util/pack_ec_mec152x.py +++ b/chip/mchp/util/pack_ec_mec152x.py @@ -1,12 +1,8 @@ #!/usr/bin/env python3 -# Copyright 2021 The Chromium OS Authors. All rights reserved. +# Copyright 2021 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# -# Ignore indention messages, since legacy scripts use 2 spaces instead of 4. -# pylint: disable=bad-indentation,docstring-section-indent -# pylint: disable=docstring-trailing-quotes # A script to pack EC binary into SPI flash image for MEC152x # Based on MEC1521/MEC1523_ROM_Description.pdf @@ -16,7 +12,7 @@ import os import struct import subprocess import tempfile -import zlib # CRC32 +import zlib # CRC32 # MEC152xH has 256KB SRAM from 0xE0000 - 0x120000 # SRAM is divided into contiguous CODE & DATA @@ -29,119 +25,159 @@ LOAD_ADDR = 0x0E0000 LOAD_ADDR_RW = 0xE1000 MEC152X_HEADER_SIZE = 0x140 MEC152X_HEADER_VERSION = 0x02 -PAYLOAD_PAD_BYTE = b'\xff' +PAYLOAD_PAD_BYTE = b"\xff" SPI_ERASE_BLOCK_SIZE = 0x1000 SPI_CLOCK_LIST = [48, 24, 16, 12] -SPI_READ_CMD_LIST = [0x3, 0xb, 0x3b, 0x6b] -SPI_DRIVE_STR_DICT = {2:0, 4:1, 8:2, 12:3} +SPI_READ_CMD_LIST = [0x3, 0xB, 0x3B, 0x6B] +SPI_DRIVE_STR_DICT = {2: 0, 4: 1, 8: 2, 12: 3} CHIP_MAX_CODE_SRAM_KB = 224 MEC152X_DICT = { - "HEADER_SIZE":0x140, - "HEADER_VER":0x02, - "PAYLOAD_OFFSET":0x140, - "PAYLOAD_GRANULARITY":128, - "EC_INFO_BLK_SZ":128, - "ENCR_KEY_HDR_SZ":128, - "COSIG_SZ":96, - "TRAILER_SZ":160, - "TAILER_PAD_BYTE":b'\xff', - "PAD_SIZE":128 - } - -CRC_TABLE = [0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, - 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d] + "HEADER_SIZE": 0x140, + "HEADER_VER": 0x02, + "PAYLOAD_OFFSET": 0x140, + "PAYLOAD_GRANULARITY": 128, + "EC_INFO_BLK_SZ": 128, + "ENCR_KEY_HDR_SZ": 128, + "COSIG_SZ": 96, + "TRAILER_SZ": 160, + "TAILER_PAD_BYTE": b"\xff", + "PAD_SIZE": 128, +} + +CRC_TABLE = [ + 0x00, + 0x07, + 0x0E, + 0x09, + 0x1C, + 0x1B, + 0x12, + 0x15, + 0x38, + 0x3F, + 0x36, + 0x31, + 0x24, + 0x23, + 0x2A, + 0x2D, +] + def mock_print(*args, **kwargs): - pass + pass + debug_print = mock_print # Debug helper routine def dumpsects(spi_list): - debug_print("spi_list has {0} entries".format(len(spi_list))) - for s in spi_list: - debug_print("0x{0:x} 0x{1:x} {2:s}".format(s[0],len(s[1]),s[2])) + debug_print("spi_list has {0} entries".format(len(spi_list))) + for s in spi_list: + debug_print("0x{0:x} 0x{1:x} {2:s}".format(s[0], len(s[1]), s[2])) + def printByteArrayAsHex(ba, title): - debug_print(title,"= ") - if ba == None: - debug_print("None") - return - - count = 0 - for b in ba: - count = count + 1 - debug_print("0x{0:02x}, ".format(b),end="") - if (count % 8) == 0: - debug_print("") - debug_print("") + debug_print(title, "= ") + if ba == None: + debug_print("None") + return + + count = 0 + for b in ba: + count = count + 1 + debug_print("0x{0:02x}, ".format(b), end="") + if (count % 8) == 0: + debug_print("") + debug_print("") + def Crc8(crc, data): - """Update CRC8 value.""" - for v in data: - crc = ((crc << 4) & 0xff) ^ (CRC_TABLE[(crc >> 4) ^ (v >> 4)]); - crc = ((crc << 4) & 0xff) ^ (CRC_TABLE[(crc >> 4) ^ (v & 0xf)]); - return crc ^ 0x55 + """Update CRC8 value.""" + for v in data: + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v >> 4)]) + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v & 0xF)]) + return crc ^ 0x55 + def GetEntryPoint(payload_file): - """Read entry point from payload EC image.""" - with open(payload_file, 'rb') as f: - f.seek(4) - s = f.read(4) - return int.from_bytes(s, byteorder='little') + """Read entry point from payload EC image.""" + with open(payload_file, "rb") as f: + f.seek(4) + s = f.read(4) + return int.from_bytes(s, byteorder="little") -def GetPayloadFromOffset(payload_file, offset, padsize): - """Read payload and pad it to padsize.""" - with open(payload_file, 'rb') as f: - f.seek(offset) - payload = bytearray(f.read()) - rem_len = len(payload) % padsize - debug_print("GetPayload: padsize={0:0x} len(payload)={1:0x} rem={2:0x}".format(padsize,len(payload),rem_len)) - if rem_len: - payload += PAYLOAD_PAD_BYTE * (padsize - rem_len) - debug_print("GetPayload: Added {0} padding bytes".format(padsize - rem_len)) +def GetPayloadFromOffset(payload_file, offset, padsize): + """Read payload and pad it to padsize.""" + with open(payload_file, "rb") as f: + f.seek(offset) + payload = bytearray(f.read()) + rem_len = len(payload) % padsize + debug_print( + "GetPayload: padsize={0:0x} len(payload)={1:0x} rem={2:0x}".format( + padsize, len(payload), rem_len + ) + ) + + if rem_len: + payload += PAYLOAD_PAD_BYTE * (padsize - rem_len) + debug_print( + "GetPayload: Added {0} padding bytes".format(padsize - rem_len) + ) + + return payload - return payload def GetPayload(payload_file, padsize): - """Read payload and pad it to padsize""" - return GetPayloadFromOffset(payload_file, 0, padsize) + """Read payload and pad it to padsize""" + return GetPayloadFromOffset(payload_file, 0, padsize) + def GetPublicKey(pem_file): - """Extract public exponent and modulus from PEM file.""" - result = subprocess.run(['openssl', 'rsa', '-in', pem_file, '-text', - '-noout'], stdout=subprocess.PIPE, encoding='utf-8') - modulus_raw = [] - in_modulus = False - for line in result.stdout.splitlines(): - if line.startswith('modulus'): - in_modulus = True - elif not line.startswith(' '): - in_modulus = False - elif in_modulus: - modulus_raw.extend(line.strip().strip(':').split(':')) - if line.startswith('publicExponent'): - exp = int(line.split(' ')[1], 10) - modulus_raw.reverse() - modulus = bytearray((int(x, 16) for x in modulus_raw[:256])) - return struct.pack('<Q', exp), modulus + """Extract public exponent and modulus from PEM file.""" + result = subprocess.run( + ["openssl", "rsa", "-in", pem_file, "-text", "-noout"], + stdout=subprocess.PIPE, + encoding="utf-8", + ) + modulus_raw = [] + in_modulus = False + for line in result.stdout.splitlines(): + if line.startswith("modulus"): + in_modulus = True + elif not line.startswith(" "): + in_modulus = False + elif in_modulus: + modulus_raw.extend(line.strip().strip(":").split(":")) + if line.startswith("publicExponent"): + exp = int(line.split(" ")[1], 10) + modulus_raw.reverse() + modulus = bytearray((int(x, 16) for x in modulus_raw[:256])) + return struct.pack("<Q", exp), modulus + def GetSpiClockParameter(args): - assert args.spi_clock in SPI_CLOCK_LIST, \ - "Unsupported SPI clock speed %d MHz" % args.spi_clock - return SPI_CLOCK_LIST.index(args.spi_clock) + assert args.spi_clock in SPI_CLOCK_LIST, ( + "Unsupported SPI clock speed %d MHz" % args.spi_clock + ) + return SPI_CLOCK_LIST.index(args.spi_clock) + def GetSpiReadCmdParameter(args): - assert args.spi_read_cmd in SPI_READ_CMD_LIST, \ - "Unsupported SPI read command 0x%x" % args.spi_read_cmd - return SPI_READ_CMD_LIST.index(args.spi_read_cmd) + assert args.spi_read_cmd in SPI_READ_CMD_LIST, ( + "Unsupported SPI read command 0x%x" % args.spi_read_cmd + ) + return SPI_READ_CMD_LIST.index(args.spi_read_cmd) + def GetEncodedSpiDriveStrength(args): - assert args.spi_drive_str in SPI_DRIVE_STR_DICT, \ - "Unsupported SPI drive strength %d mA" % args.spi_drive_str - return SPI_DRIVE_STR_DICT.get(args.spi_drive_str) + assert args.spi_drive_str in SPI_DRIVE_STR_DICT, ( + "Unsupported SPI drive strength %d mA" % args.spi_drive_str + ) + return SPI_DRIVE_STR_DICT.get(args.spi_drive_str) + # Return 0=Slow slew rate or 1=Fast slew rate def GetSpiSlewRate(args): @@ -149,12 +185,14 @@ def GetSpiSlewRate(args): return 1 return 0 + # Return SPI CPOL = 0 or 1 def GetSpiCpol(args): if args.spi_cpol == 0: return 0 return 1 + # Return SPI CPHA_MOSI # 0 = SPI Master drives data is stable on inactive to clock edge # 1 = SPI Master drives data is stable on active to inactive clock edge @@ -163,6 +201,7 @@ def GetSpiCphaMosi(args): return 0 return 1 + # Return SPI CPHA_MISO 0 or 1 # 0 = SPI Master samples data on inactive to active clock edge # 1 = SPI Master samples data on active to inactive clock edge @@ -171,14 +210,10 @@ def GetSpiCphaMiso(args): return 0 return 1 + def PadZeroTo(data, size): - data.extend(b'\0' * (size - len(data))) + data.extend(b"\0" * (size - len(data))) -# -# Boot-ROM SPI image encryption not used with Chromebooks -# -def EncryptPayload(args, chip_dict, payload): - return None # # Build SPI image header for MEC152x @@ -237,67 +272,71 @@ def EncryptPayload(args, chip_dict, payload): # header[0x110:0x140] = Header ECDSA-384 signature y-coor. = 0 Auth. disabled # def BuildHeader2(args, chip_dict, payload_len, load_addr, payload_entry): - header_size = MEC152X_HEADER_SIZE - - # allocate zero filled header - header = bytearray(b'\x00' * header_size) - debug_print("len(header) = ", len(header)) - - # Identifier and header version - header[0:4] = b'PHCM' - header[4] = MEC152X_HEADER_VERSION - - # SPI frequency, drive strength, CPOL/CPHA encoding same for both chips - spiFreqMHz = GetSpiClockParameter(args) - header[5] = (int(spiFreqMHz // 48) - 1) & 0x03 - header[5] |= ((GetEncodedSpiDriveStrength(args) & 0x03) << 2) - header[5] |= ((GetSpiSlewRate(args) & 0x01) << 4) - header[5] |= ((GetSpiCpol(args) & 0x01) << 5) - header[5] |= ((GetSpiCphaMosi(args) & 0x01) << 6) - header[5] |= ((GetSpiCphaMiso(args) & 0x01) << 7) - - # b[0]=0 VTR1 must be 3.3V - # b[1]=0(VTR2 3.3V), 1(VTR2 1.8V) - # b[2]=0(VTR3 3.3V), 1(VTR3 1.8V) - # b[5:3]=111b - # b[6]=0 No ECDSA - # b[7]=0 No encrypted FW image - header[6] = 0x7 << 3 - if args.vtr2_V18 == True: - header[6] |= 0x02 - if args.vtr3_V18 == True: - header[6] |= 0x04 - - # SPI read command set same for both chips - header[7] = GetSpiReadCmdParameter(args) & 0xFF - - # bytes 0x08 - 0x0b - header[0x08:0x0C] = load_addr.to_bytes(4, byteorder='little') - # bytes 0x0c - 0x0f - header[0x0C:0x10] = payload_entry.to_bytes(4, byteorder='little') - # bytes 0x10 - 0x11 payload length in units of 128 bytes - - payload_units = int(payload_len // chip_dict["PAYLOAD_GRANULARITY"]) - assert payload_units < 0x10000, \ - print("Payload too large: len={0} units={1}".format(payload_len, payload_units)) - - header[0x10:0x12] = payload_units.to_bytes(2, 'little') - - # bytes 0x14 - 0x17 - header[0x14:0x18] = chip_dict["PAYLOAD_OFFSET"].to_bytes(4, 'little') - - # MEC152x: Disable ECDSA and encryption - header[0x18] = 0 - - # header[0xB0:0xE0] = SHA384(header[0:0xB0]) - header[0xB0:0xE0] = hashlib.sha384(header[0:0xB0]).digest() - # When ECDSA authentication is disabled MCHP SPI image generator - # is filling the last 48 bytes of the Header with 0xff - header[-48:] = b'\xff' * 48 - - debug_print("After hash: len(header) = ", len(header)) - - return header + header_size = MEC152X_HEADER_SIZE + + # allocate zero filled header + header = bytearray(b"\x00" * header_size) + debug_print("len(header) = ", len(header)) + + # Identifier and header version + header[0:4] = b"PHCM" + header[4] = MEC152X_HEADER_VERSION + + # SPI frequency, drive strength, CPOL/CPHA encoding same for both chips + spiFreqMHz = GetSpiClockParameter(args) + header[5] = (int(spiFreqMHz // 48) - 1) & 0x03 + header[5] |= (GetEncodedSpiDriveStrength(args) & 0x03) << 2 + header[5] |= (GetSpiSlewRate(args) & 0x01) << 4 + header[5] |= (GetSpiCpol(args) & 0x01) << 5 + header[5] |= (GetSpiCphaMosi(args) & 0x01) << 6 + header[5] |= (GetSpiCphaMiso(args) & 0x01) << 7 + + # b[0]=0 VTR1 must be 3.3V + # b[1]=0(VTR2 3.3V), 1(VTR2 1.8V) + # b[2]=0(VTR3 3.3V), 1(VTR3 1.8V) + # b[5:3]=111b + # b[6]=0 No ECDSA + # b[7]=0 No encrypted FW image + header[6] = 0x7 << 3 + if args.vtr2_V18 == True: + header[6] |= 0x02 + if args.vtr3_V18 == True: + header[6] |= 0x04 + + # SPI read command set same for both chips + header[7] = GetSpiReadCmdParameter(args) & 0xFF + + # bytes 0x08 - 0x0b + header[0x08:0x0C] = load_addr.to_bytes(4, byteorder="little") + # bytes 0x0c - 0x0f + header[0x0C:0x10] = payload_entry.to_bytes(4, byteorder="little") + # bytes 0x10 - 0x11 payload length in units of 128 bytes + + payload_units = int(payload_len // chip_dict["PAYLOAD_GRANULARITY"]) + assert payload_units < 0x10000, print( + "Payload too large: len={0} units={1}".format( + payload_len, payload_units + ) + ) + + header[0x10:0x12] = payload_units.to_bytes(2, "little") + + # bytes 0x14 - 0x17 + header[0x14:0x18] = chip_dict["PAYLOAD_OFFSET"].to_bytes(4, "little") + + # MEC152x: Disable ECDSA and encryption + header[0x18] = 0 + + # header[0xB0:0xE0] = SHA384(header[0:0xB0]) + header[0xB0:0xE0] = hashlib.sha384(header[0:0xB0]).digest() + # When ECDSA authentication is disabled MCHP SPI image generator + # is filling the last 48 bytes of the Header with 0xff + header[-48:] = b"\xff" * 48 + + debug_print("After hash: len(header) = ", len(header)) + + return header + # # MEC152x 128-byte EC Info Block appended to @@ -311,8 +350,9 @@ def BuildHeader2(args, chip_dict, payload_len, load_addr, payload_entry): # byte 127 = customer current image revision # def GenEcInfoBlock(args, chip_dict): - ecinfo = bytearray(chip_dict["EC_INFO_BLK_SZ"]) - return ecinfo + ecinfo = bytearray(chip_dict["EC_INFO_BLK_SZ"]) + return ecinfo + # # Generate SPI FW image co-signature. @@ -325,7 +365,8 @@ def GenEcInfoBlock(args, chip_dict): # signature. # def GenCoSignature(args, chip_dict, payload): - return bytearray(b'\xff' * chip_dict["COSIG_SZ"]) + return bytearray(b"\xff" * chip_dict["COSIG_SZ"]) + # # Generate SPI FW Image trailer. @@ -336,22 +377,24 @@ def GenCoSignature(args, chip_dict, payload): # trailer[144:160] = 0xFF. Boot-ROM spec. says these bytes should be random. # Authentication & encryption are not used therefore random data # is not necessary. -def GenTrailer(args, chip_dict, payload, encryption_key_header, - ec_info_block, cosignature): +def GenTrailer( + args, chip_dict, payload, encryption_key_header, ec_info_block, cosignature +): trailer = bytearray(chip_dict["TAILER_PAD_BYTE"] * chip_dict["TRAILER_SZ"]) hasher = hashlib.sha384() hasher.update(payload) if ec_info_block != None: - hasher.update(ec_info_block) + hasher.update(ec_info_block) if encryption_key_header != None: - hasher.update(encryption_key_header) + hasher.update(encryption_key_header) if cosignature != None: - hasher.update(cosignature) + hasher.update(cosignature) trailer[0:48] = hasher.digest() - trailer[-16:] = 16 * b'\xff' + trailer[-16:] = 16 * b"\xff" return trailer + # MEC152xH supports two 32-bit Tags located at offsets 0x0 and 0x4 # in the SPI flash. # Tag format: @@ -362,16 +405,25 @@ def GenTrailer(args, chip_dict, payload, encryption_key_header, # to the same flash part. # def BuildTag(args): - tag = bytearray([(args.header_loc >> 8) & 0xff, - (args.header_loc >> 16) & 0xff, - (args.header_loc >> 24) & 0xff]) - tag.append(Crc8(0, tag)) - return tag + tag = bytearray( + [ + (args.header_loc >> 8) & 0xFF, + (args.header_loc >> 16) & 0xFF, + (args.header_loc >> 24) & 0xFF, + ] + ) + tag.append(Crc8(0, tag)) + return tag + def BuildTagFromHdrAddr(header_loc): - tag = bytearray([(header_loc >> 8) & 0xff, - (header_loc >> 16) & 0xff, - (header_loc >> 24) & 0xff]) + tag = bytearray( + [ + (header_loc >> 8) & 0xFF, + (header_loc >> 16) & 0xFF, + (header_loc >> 24) & 0xFF, + ] + ) tag.append(Crc8(0, tag)) return tag @@ -388,12 +440,13 @@ def BuildTagFromHdrAddr(header_loc): # Output: # bytearray of length 4 def BuildFlashMap(secondSpiFlashBaseAddr): - flashmap = bytearray(4) - flashmap[0] = (secondSpiFlashBaseAddr >> 12) & 0xff - flashmap[1] = (secondSpiFlashBaseAddr >> 20) & 0xff - flashmap[2] = (secondSpiFlashBaseAddr >> 28) & 0xff - flashmap[3] = Crc8(0, flashmap) - return flashmap + flashmap = bytearray(4) + flashmap[0] = (secondSpiFlashBaseAddr >> 12) & 0xFF + flashmap[1] = (secondSpiFlashBaseAddr >> 20) & 0xFF + flashmap[2] = (secondSpiFlashBaseAddr >> 28) & 0xFF + flashmap[3] = Crc8(0, flashmap) + return flashmap + # # Creates temporary file for read/write @@ -404,21 +457,22 @@ def BuildFlashMap(secondSpiFlashBaseAddr): # Returns temporary file name # def PacklfwRoImage(rorw_file, loader_file, image_size): - """Create a temp file with the - first image_size bytes from the loader file and append bytes - from the rorw file. - return the filename""" - fo=tempfile.NamedTemporaryFile(delete=False) # Need to keep file around - with open(loader_file,'rb') as fin1: # read 4KB loader file - pro = fin1.read() - fo.write(pro) # write 4KB loader data to temp file - with open(rorw_file, 'rb') as fin: - ro = fin.read(image_size) - - fo.write(ro) - fo.close() - - return fo.name + """Create a temp file with the + first image_size bytes from the loader file and append bytes + from the rorw file. + return the filename""" + fo = tempfile.NamedTemporaryFile(delete=False) # Need to keep file around + with open(loader_file, "rb") as fin1: # read 4KB loader file + pro = fin1.read() + fo.write(pro) # write 4KB loader data to temp file + with open(rorw_file, "rb") as fin: + ro = fin.read(image_size) + + fo.write(ro) + fo.close() + + return fo.name + # # Generate a test EC_RW image of same size @@ -429,129 +483,188 @@ def PacklfwRoImage(rorw_file, loader_file, image_size): # process hash generation. # def gen_test_ecrw(pldrw): - debug_print("gen_test_ecrw: pldrw type =", type(pldrw)) - debug_print("len pldrw =", len(pldrw), " = ", hex(len(pldrw))) - cookie1_pos = pldrw.find(b'\x99\x88\x77\xce') - cookie2_pos = pldrw.find(b'\xdd\xbb\xaa\xce', cookie1_pos+4) - t = struct.unpack("<L", pldrw[cookie1_pos+0x24:cookie1_pos+0x28]) - size = t[0] - debug_print("EC_RW size =", size, " = ", hex(size)) - - debug_print("Found cookie1 at ", hex(cookie1_pos)) - debug_print("Found cookie2 at ", hex(cookie2_pos)) - - if cookie1_pos > 0 and cookie2_pos > cookie1_pos: - for i in range(0, cookie1_pos): - pldrw[i] = 0xA5 - for i in range(cookie2_pos+4, len(pldrw)): - pldrw[i] = 0xA5 - - with open("ec_RW_test.bin", "wb") as fecrw: - fecrw.write(pldrw[:size]) + debug_print("gen_test_ecrw: pldrw type =", type(pldrw)) + debug_print("len pldrw =", len(pldrw), " = ", hex(len(pldrw))) + cookie1_pos = pldrw.find(b"\x99\x88\x77\xce") + cookie2_pos = pldrw.find(b"\xdd\xbb\xaa\xce", cookie1_pos + 4) + t = struct.unpack("<L", pldrw[cookie1_pos + 0x24 : cookie1_pos + 0x28]) + size = t[0] + debug_print("EC_RW size =", size, " = ", hex(size)) + + debug_print("Found cookie1 at ", hex(cookie1_pos)) + debug_print("Found cookie2 at ", hex(cookie2_pos)) + + if cookie1_pos > 0 and cookie2_pos > cookie1_pos: + for i in range(0, cookie1_pos): + pldrw[i] = 0xA5 + for i in range(cookie2_pos + 4, len(pldrw)): + pldrw[i] = 0xA5 + + with open("ec_RW_test.bin", "wb") as fecrw: + fecrw.write(pldrw[:size]) + def parseargs(): - #TODO I commented this out. Why? - rpath = os.path.dirname(os.path.relpath(__file__)) - - parser = argparse.ArgumentParser() - parser.add_argument("-i", "--input", - help="EC binary to pack, usually ec.bin or ec.RO.flat.", - metavar="EC_BIN", default="ec.bin") - parser.add_argument("-o", "--output", - help="Output flash binary file", - metavar="EC_SPI_FLASH", default="ec.packed.bin") - parser.add_argument("--loader_file", - help="EC loader binary", - default="ecloader.bin") - parser.add_argument("-s", "--spi_size", type=int, - help="Size of the SPI flash in KB", - default=512) - parser.add_argument("-l", "--header_loc", type=int, - help="Location of header in SPI flash", - default=0x1000) - parser.add_argument("-r", "--rw_loc", type=int, - help="Start offset of EC_RW. Default is -1 meaning 1/2 flash size", - default=-1) - parser.add_argument("--spi_clock", type=int, - help="SPI clock speed. 8, 12, 24, or 48 MHz.", - default=24) - parser.add_argument("--spi_read_cmd", type=int, - help="SPI read command. 0x3, 0xB, or 0x3B.", - default=0xb) - parser.add_argument("--image_size", type=int, - help="Size of a single image. Default 220KB", - default=(220 * 1024)) - parser.add_argument("--test_spi", action='store_true', - help="Test SPI data integrity by adding CRC32 in last 4-bytes of RO/RW binaries", - default=False) - parser.add_argument("--test_ecrw", action='store_true', - help="Use fixed pattern for EC_RW but preserve image_data", - default=False) - parser.add_argument("--verbose", action='store_true', - help="Enable verbose output", - default=False) - parser.add_argument("--tag0_loc", type=int, - help="MEC152X TAG0 SPI offset", - default=0) - parser.add_argument("--tag1_loc", type=int, - help="MEC152X TAG1 SPI offset", - default=4) - parser.add_argument("--spi_drive_str", type=int, - help="Chip SPI drive strength in mA: 2, 4, 8, or 12", - default=4) - parser.add_argument("--spi_slew_fast", action='store_true', - help="SPI use fast slew rate. Default is False", - default=False) - parser.add_argument("--spi_cpol", type=int, - help="SPI clock polarity when idle. Defealt is 0(low)", - default=0) - parser.add_argument("--spi_cpha_mosi", type=int, - help="""SPI clock phase master drives data. + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + "--input", + help="EC binary to pack, usually ec.bin or ec.RO.flat.", + metavar="EC_BIN", + default="ec.bin", + ) + parser.add_argument( + "-o", + "--output", + help="Output flash binary file", + metavar="EC_SPI_FLASH", + default="ec.packed.bin", + ) + parser.add_argument( + "--loader_file", help="EC loader binary", default="ecloader.bin" + ) + parser.add_argument( + "-s", + "--spi_size", + type=int, + help="Size of the SPI flash in KB", + default=512, + ) + parser.add_argument( + "-l", + "--header_loc", + type=int, + help="Location of header in SPI flash", + default=0x1000, + ) + parser.add_argument( + "-r", + "--rw_loc", + type=int, + help="Start offset of EC_RW. Default is -1 meaning 1/2 flash size", + default=-1, + ) + parser.add_argument( + "--spi_clock", + type=int, + help="SPI clock speed. 8, 12, 24, or 48 MHz.", + default=24, + ) + parser.add_argument( + "--spi_read_cmd", + type=int, + help="SPI read command. 0x3, 0xB, or 0x3B.", + default=0xB, + ) + parser.add_argument( + "--image_size", + type=int, + help="Size of a single image. Default 220KB", + default=(220 * 1024), + ) + parser.add_argument( + "--test_spi", + action="store_true", + help="Test SPI data integrity by adding CRC32 in last 4-bytes of RO/RW binaries", + default=False, + ) + parser.add_argument( + "--test_ecrw", + action="store_true", + help="Use fixed pattern for EC_RW but preserve image_data", + default=False, + ) + parser.add_argument( + "--verbose", + action="store_true", + help="Enable verbose output", + default=False, + ) + parser.add_argument( + "--tag0_loc", type=int, help="MEC152X TAG0 SPI offset", default=0 + ) + parser.add_argument( + "--tag1_loc", type=int, help="MEC152X TAG1 SPI offset", default=4 + ) + parser.add_argument( + "--spi_drive_str", + type=int, + help="Chip SPI drive strength in mA: 2, 4, 8, or 12", + default=4, + ) + parser.add_argument( + "--spi_slew_fast", + action="store_true", + help="SPI use fast slew rate. Default is False", + default=False, + ) + parser.add_argument( + "--spi_cpol", + type=int, + help="SPI clock polarity when idle. Defealt is 0(low)", + default=0, + ) + parser.add_argument( + "--spi_cpha_mosi", + type=int, + help="""SPI clock phase master drives data. 0=Data driven on active to inactive clock edge, 1=Data driven on inactive to active clock edge""", - default=0) - parser.add_argument("--spi_cpha_miso", type=int, - help="""SPI clock phase master samples data. + default=0, + ) + parser.add_argument( + "--spi_cpha_miso", + type=int, + help="""SPI clock phase master samples data. 0=Data sampled on inactive to active clock edge, 1=Data sampled on active to inactive clock edge""", - default=0) + default=0, + ) - parser.add_argument("--vtr2_V18", action='store_true', - help="Chip VTR2 rail is 1.8V. Default is False(3.3V)", - default=False) + parser.add_argument( + "--vtr2_V18", + action="store_true", + help="Chip VTR2 rail is 1.8V. Default is False(3.3V)", + default=False, + ) - parser.add_argument("--vtr3_V18", action='store_true', - help="Chip VTR3 rail is 1.8V. Default is False(3.3V)", - default=False) + parser.add_argument( + "--vtr3_V18", + action="store_true", + help="Chip VTR3 rail is 1.8V. Default is False(3.3V)", + default=False, + ) + + return parser.parse_args() - return parser.parse_args() def print_args(args): - debug_print("parsed arguments:") - debug_print(".input = ", args.input) - debug_print(".output = ", args.output) - debug_print(".loader_file = ", args.loader_file) - debug_print(".spi_size (KB) = ", hex(args.spi_size)) - debug_print(".image_size = ", hex(args.image_size)) - debug_print(".tag0_loc = ", hex(args.tag0_loc)) - debug_print(".tag1_loc = ", hex(args.tag1_loc)) - debug_print(".header_loc = ", hex(args.header_loc)) - if args.rw_loc < 0: - debug_print(".rw_loc = ", args.rw_loc) - else: - debug_print(".rw_loc = ", hex(args.rw_loc)) - debug_print(".spi_clock (MHz) = ", args.spi_clock) - debug_print(".spi_read_cmd = ", hex(args.spi_read_cmd)) - debug_print(".test_spi = ", args.test_spi) - debug_print(".test_ecrw = ", args.test_ecrw) - debug_print(".verbose = ", args.verbose) - debug_print(".spi_drive_str = ", args.spi_drive_str) - debug_print(".spi_slew_fast = ", args.spi_slew_fast) - debug_print(".spi_cpol = ", args.spi_cpol) - debug_print(".spi_cpha_mosi = ", args.spi_cpha_mosi) - debug_print(".spi_cpha_miso = ", args.spi_cpha_miso) - debug_print(".vtr2_V18 = ", args.vtr2_V18) - debug_print(".vtr3_V18 = ", args.vtr3_V18) + debug_print("parsed arguments:") + debug_print(".input = ", args.input) + debug_print(".output = ", args.output) + debug_print(".loader_file = ", args.loader_file) + debug_print(".spi_size (KB) = ", hex(args.spi_size)) + debug_print(".image_size = ", hex(args.image_size)) + debug_print(".tag0_loc = ", hex(args.tag0_loc)) + debug_print(".tag1_loc = ", hex(args.tag1_loc)) + debug_print(".header_loc = ", hex(args.header_loc)) + if args.rw_loc < 0: + debug_print(".rw_loc = ", args.rw_loc) + else: + debug_print(".rw_loc = ", hex(args.rw_loc)) + debug_print(".spi_clock (MHz) = ", args.spi_clock) + debug_print(".spi_read_cmd = ", hex(args.spi_read_cmd)) + debug_print(".test_spi = ", args.test_spi) + debug_print(".test_ecrw = ", args.test_ecrw) + debug_print(".verbose = ", args.verbose) + debug_print(".spi_drive_str = ", args.spi_drive_str) + debug_print(".spi_slew_fast = ", args.spi_slew_fast) + debug_print(".spi_cpol = ", args.spi_cpol) + debug_print(".spi_cpha_mosi = ", args.spi_cpha_mosi) + debug_print(".spi_cpha_miso = ", args.spi_cpha_miso) + debug_print(".vtr2_V18 = ", args.vtr2_V18) + debug_print(".vtr3_V18 = ", args.vtr3_V18) + # # Handle quiet mode build from Makefile @@ -589,215 +702,239 @@ def print_args(args): # || 48 * [0] # def main(): - global debug_print - - args = parseargs() - - if args.verbose: - debug_print = print + global debug_print + + args = parseargs() + + if args.verbose: + debug_print = print + + debug_print("Begin pack_ec_mec152x.py script") + + print_args(args) + + chip_dict = MEC152X_DICT + + # Boot-ROM requires header location aligned >= 256 bytes. + # CrOS EC flash image update code requires EC_RO/RW location to be aligned + # on a flash erase size boundary and EC_RO/RW size to be a multiple of + # the smallest flash erase block size. + # + assert (args.header_loc % SPI_ERASE_BLOCK_SIZE) == 0, ( + "Header location %d is not on a flash erase block boundary boundary" + % args.header_loc + ) + + max_image_size = CHIP_MAX_CODE_SRAM_KB - LFW_SIZE + if args.test_spi: + max_image_size -= 32 # SHA256 digest + + assert args.image_size > max_image_size, ( + "Image size exceeds maximum" % args.image_size + ) + + spi_size = args.spi_size * 1024 + debug_print("SPI Flash image size in bytes =", hex(spi_size)) + + # !!! IMPORTANT !!! + # These values MUST match chip/mchp/config_flash_layout.h + # defines. + # MEC152x Boot-ROM TAGs are at offset 0 and 4. + # lfw + EC_RO starts at beginning of second 4KB sector + # EC_RW starts at (flash size / 2) i.e. 0x40000 for a 512KB flash. + + spi_list = [] + + debug_print("args.input = ", args.input) + debug_print("args.loader_file = ", args.loader_file) + debug_print("args.image_size = ", hex(args.image_size)) + + rorofile = PacklfwRoImage(args.input, args.loader_file, args.image_size) + debug_print("Temporary file containing LFW + EC_RO is ", rorofile) + + lfw_ecro = GetPayload(rorofile, chip_dict["PAD_SIZE"]) + lfw_ecro_len = len(lfw_ecro) + debug_print("Padded LFW + EC_RO length = ", hex(lfw_ecro_len)) + + # SPI test mode compute CRC32 of EC_RO and store in last 4 bytes + if args.test_spi: + crc32_ecro = zlib.crc32(bytes(lfw_ecro[LFW_SIZE:-4])) + crc32_ecro_bytes = crc32_ecro.to_bytes(4, byteorder="little") + lfw_ecro[-4:] = crc32_ecro_bytes + debug_print("ecro len = ", hex(len(lfw_ecro) - LFW_SIZE)) + debug_print("CRC32(ecro-4) = ", hex(crc32_ecro)) + + # Reads entry point from offset 4 of file. + # This assumes binary has Cortex-M4 vector table at offset 0. + # 32-bit word at offset 0x0 initial stack pointer value + # 32-bit word at offset 0x4 address of reset handler + # NOTE: reset address will have bit[0]=1 to ensure thumb mode. + lfw_ecro_entry = GetEntryPoint(rorofile) + + # Chromebooks are not using MEC BootROM SPI header/payload authentication + # or payload encryption. In this case the header authentication signature + # is filled with the hash digest of the respective entity. + # BuildHeader2 computes the hash digest and stores it in the correct + # header location. + header = BuildHeader2( + args, chip_dict, lfw_ecro_len, LOAD_ADDR, lfw_ecro_entry + ) + printByteArrayAsHex(header, "Header(lfw_ecro)") + + ec_info_block = GenEcInfoBlock(args, chip_dict) + printByteArrayAsHex(ec_info_block, "EC Info Block") + + cosignature = GenCoSignature(args, chip_dict, lfw_ecro) + printByteArrayAsHex(cosignature, "LFW + EC_RO cosignature") + + trailer = GenTrailer( + args, chip_dict, lfw_ecro, None, ec_info_block, cosignature + ) + + printByteArrayAsHex(trailer, "LFW + EC_RO trailer") + + # Build TAG0. Set TAG1=TAG0 Boot-ROM is allowed to load EC-RO only. + tag0 = BuildTag(args) + tag1 = tag0 + + debug_print("Call to GetPayloadFromOffset") + debug_print("args.input = ", args.input) + debug_print("args.image_size = ", hex(args.image_size)) + + ecrw = GetPayloadFromOffset( + args.input, args.image_size, chip_dict["PAD_SIZE"] + ) + debug_print("type(ecrw) is ", type(ecrw)) + debug_print("len(ecrw) is ", hex(len(ecrw))) + + # truncate to args.image_size + ecrw_len = len(ecrw) + if ecrw_len > args.image_size: + debug_print( + "Truncate EC_RW len={0:0x} to image_size={1:0x}".format( + ecrw_len, args.image_size + ) + ) + ecrw = ecrw[: args.image_size] + ecrw_len = len(ecrw) + + debug_print("len(EC_RW) = ", hex(ecrw_len)) + + # SPI test mode compute CRC32 of EC_RW and store in last 4 bytes + if args.test_spi: + crc32_ecrw = zlib.crc32(bytes(ecrw[0:-4])) + crc32_ecrw_bytes = crc32_ecrw.to_bytes(4, byteorder="little") + ecrw[-4:] = crc32_ecrw_bytes + debug_print("ecrw len = ", hex(len(ecrw))) + debug_print("CRC32(ecrw) = ", hex(crc32_ecrw)) + + # Assume FW layout is standard Cortex-M style with vector + # table at start of binary. + # 32-bit word at offset 0x0 = Initial stack pointer + # 32-bit word at offset 0x4 = Address of reset handler + ecrw_entry_tuple = struct.unpack_from("<I", ecrw, 4) + debug_print("ecrw_entry_tuple[0] = ", hex(ecrw_entry_tuple[0])) + + ecrw_entry = ecrw_entry_tuple[0] + debug_print("ecrw_entry = ", hex(ecrw_entry)) + + # Note: payload_rw is a bytearray therefore is mutable + if args.test_ecrw: + gen_test_ecrw(ecrw) + + os.remove(rorofile) # clean up the temp file + + # MEC152X Add TAG's + spi_list.append((args.tag0_loc, tag0, "tag0")) + spi_list.append((args.tag1_loc, tag1, "tag1")) + + # flashmap is non-zero only for systems with two external + # SPI flash chips. + flashmap = BuildFlashMap(0) + spi_list.append((8, flashmap, "flashmap")) + + # Boot-ROM SPI image header for LFW+EC-RO + spi_list.append((args.header_loc, header, "header(lfw + ro)")) + spi_list.append( + (args.header_loc + chip_dict["PAYLOAD_OFFSET"], lfw_ecro, "lfw_ecro") + ) + + offset = args.header_loc + chip_dict["PAYLOAD_OFFSET"] + lfw_ecro_len - debug_print("Begin pack_ec_mec152x.py script") - - print_args(args) - - chip_dict = MEC152X_DICT - - # Boot-ROM requires header location aligned >= 256 bytes. - # CrOS EC flash image update code requires EC_RO/RW location to be aligned - # on a flash erase size boundary and EC_RO/RW size to be a multiple of - # the smallest flash erase block size. - # - assert (args.header_loc % SPI_ERASE_BLOCK_SIZE) == 0, \ - "Header location %d is not on a flash erase block boundary boundary" % args.header_loc - - max_image_size = CHIP_MAX_CODE_SRAM_KB - LFW_SIZE - if args.test_spi: - max_image_size -= 32 # SHA256 digest - - assert args.image_size > max_image_size, \ - "Image size exceeds maximum" % args.image_size - - spi_size = args.spi_size * 1024 - debug_print("SPI Flash image size in bytes =", hex(spi_size)) - - # !!! IMPORTANT !!! - # These values MUST match chip/mchp/config_flash_layout.h - # defines. - # MEC152x Boot-ROM TAGs are at offset 0 and 4. - # lfw + EC_RO starts at beginning of second 4KB sector - # EC_RW starts at (flash size / 2) i.e. 0x40000 for a 512KB flash. - - spi_list = [] - - debug_print("args.input = ",args.input) - debug_print("args.loader_file = ",args.loader_file) - debug_print("args.image_size = ",hex(args.image_size)) - - rorofile=PacklfwRoImage(args.input, args.loader_file, args.image_size) - debug_print("Temporary file containing LFW + EC_RO is ", rorofile) - - lfw_ecro = GetPayload(rorofile, chip_dict["PAD_SIZE"]) - lfw_ecro_len = len(lfw_ecro) - debug_print("Padded LFW + EC_RO length = ", hex(lfw_ecro_len)) - - # SPI test mode compute CRC32 of EC_RO and store in last 4 bytes - if args.test_spi: - crc32_ecro = zlib.crc32(bytes(lfw_ecro[LFW_SIZE:-4])) - crc32_ecro_bytes = crc32_ecro.to_bytes(4, byteorder='little') - lfw_ecro[-4:] = crc32_ecro_bytes - debug_print("ecro len = ", hex(len(lfw_ecro) - LFW_SIZE)) - debug_print("CRC32(ecro-4) = ", hex(crc32_ecro)) - - # Reads entry point from offset 4 of file. - # This assumes binary has Cortex-M4 vector table at offset 0. - # 32-bit word at offset 0x0 initial stack pointer value - # 32-bit word at offset 0x4 address of reset handler - # NOTE: reset address will have bit[0]=1 to ensure thumb mode. - lfw_ecro_entry = GetEntryPoint(rorofile) - - # Chromebooks are not using MEC BootROM SPI header/payload authentication - # or payload encryption. In this case the header authentication signature - # is filled with the hash digest of the respective entity. - # BuildHeader2 computes the hash digest and stores it in the correct - # header location. - header = BuildHeader2(args, chip_dict, lfw_ecro_len, - LOAD_ADDR, lfw_ecro_entry) - printByteArrayAsHex(header, "Header(lfw_ecro)") - - # If payload encryption used then encrypt payload and - # generate Payload Key Header. If encryption not used - # payload is not modified and the method returns None - encryption_key_header = EncryptPayload(args, chip_dict, lfw_ecro) - printByteArrayAsHex(encryption_key_header, - "LFW + EC_RO encryption_key_header") - - ec_info_block = GenEcInfoBlock(args, chip_dict) - printByteArrayAsHex(ec_info_block, "EC Info Block") - - cosignature = GenCoSignature(args, chip_dict, lfw_ecro) - printByteArrayAsHex(cosignature, "LFW + EC_RO cosignature") - - trailer = GenTrailer(args, chip_dict, lfw_ecro, encryption_key_header, - ec_info_block, cosignature) - - printByteArrayAsHex(trailer, "LFW + EC_RO trailer") - - # Build TAG0. Set TAG1=TAG0 Boot-ROM is allowed to load EC-RO only. - tag0 = BuildTag(args) - tag1 = tag0 - - debug_print("Call to GetPayloadFromOffset") - debug_print("args.input = ", args.input) - debug_print("args.image_size = ", hex(args.image_size)) - - ecrw = GetPayloadFromOffset(args.input, args.image_size, - chip_dict["PAD_SIZE"]) - debug_print("type(ecrw) is ", type(ecrw)) - debug_print("len(ecrw) is ", hex(len(ecrw))) - - # truncate to args.image_size - ecrw_len = len(ecrw) - if ecrw_len > args.image_size: - debug_print("Truncate EC_RW len={0:0x} to image_size={1:0x}".format(ecrw_len,args.image_size)) - ecrw = ecrw[:args.image_size] - ecrw_len = len(ecrw) - - debug_print("len(EC_RW) = ", hex(ecrw_len)) - - # SPI test mode compute CRC32 of EC_RW and store in last 4 bytes - if args.test_spi: - crc32_ecrw = zlib.crc32(bytes(ecrw[0:-4])) - crc32_ecrw_bytes = crc32_ecrw.to_bytes(4, byteorder='little') - ecrw[-4:] = crc32_ecrw_bytes - debug_print("ecrw len = ", hex(len(ecrw))) - debug_print("CRC32(ecrw) = ", hex(crc32_ecrw)) - - # Assume FW layout is standard Cortex-M style with vector - # table at start of binary. - # 32-bit word at offset 0x0 = Initial stack pointer - # 32-bit word at offset 0x4 = Address of reset handler - ecrw_entry_tuple = struct.unpack_from('<I', ecrw, 4) - debug_print("ecrw_entry_tuple[0] = ", hex(ecrw_entry_tuple[0])) - - ecrw_entry = ecrw_entry_tuple[0] - debug_print("ecrw_entry = ", hex(ecrw_entry)) - - # Note: payload_rw is a bytearray therefore is mutable - if args.test_ecrw: - gen_test_ecrw(ecrw) - - os.remove(rorofile) # clean up the temp file - - # MEC152X Add TAG's - spi_list.append((args.tag0_loc, tag0, "tag0")) - spi_list.append((args.tag1_loc, tag1, "tag1")) - - # flashmap is non-zero only for systems with two external - # SPI flash chips. - flashmap = BuildFlashMap(0) - spi_list.append((8, flashmap, "flashmap")) - - # Boot-ROM SPI image header for LFW+EC-RO - spi_list.append((args.header_loc, header, "header(lfw + ro)")) - spi_list.append((args.header_loc + chip_dict["PAYLOAD_OFFSET"], lfw_ecro, - "lfw_ecro")) - - offset = args.header_loc + chip_dict["PAYLOAD_OFFSET"] + lfw_ecro_len - - if ec_info_block != None: - spi_list.append((offset, ec_info_block, "EC Info Block")) - offset += len(ec_info_block) - - if cosignature != None: - spi_list.append((offset, cosignature, "ECRO Cosignature")) - offset += len(cosignature) - - if trailer != None: - spi_list.append((offset, trailer, "ECRO Trailer")) - offset += len(trailer) - - # EC_RW location - rw_offset = int(spi_size // 2) - if args.rw_loc >= 0: - rw_offset = args.rw_loc - - debug_print("rw_offset = 0x{0:08x}".format(rw_offset)) - - assert rw_offset >= offset, \ - print("""Offset of EC_RW at {0:08x} overlaps end - of EC_RO at {0:08x}""".format(rw_offset, offset)) - - spi_list.append((rw_offset, ecrw, "ecrw")) - offset = rw_offset + len(ecrw) - - spi_list = sorted(spi_list) - - dumpsects(spi_list) - - # - # MEC152X Boot-ROM locates TAG0/1 at SPI offset 0 - # instead of end of SPI. - # - with open(args.output, 'wb') as f: - debug_print("Write spi list to file", args.output) - addr = 0 - for s in spi_list: - if addr < s[0]: - debug_print("Offset ",hex(addr)," Length", hex(s[0]-addr), - "fill with 0xff") - f.write(b'\xff' * (s[0] - addr)) - addr = s[0] - debug_print("Offset ",hex(addr), " Length", hex(len(s[1])), "write data") - - f.write(s[1]) - addr += len(s[1]) - - if addr < spi_size: - debug_print("Offset ",hex(addr), " Length", hex(spi_size - addr), - "fill with 0xff") - f.write(b'\xff' * (spi_size - addr)) - - f.flush() + if ec_info_block != None: + spi_list.append((offset, ec_info_block, "EC Info Block")) + offset += len(ec_info_block) -if __name__ == '__main__': - main() + if cosignature != None: + spi_list.append((offset, cosignature, "ECRO Cosignature")) + offset += len(cosignature) + + if trailer != None: + spi_list.append((offset, trailer, "ECRO Trailer")) + offset += len(trailer) + + # EC_RW location + rw_offset = int(spi_size // 2) + if args.rw_loc >= 0: + rw_offset = args.rw_loc + + debug_print("rw_offset = 0x{0:08x}".format(rw_offset)) + + assert rw_offset >= offset, print( + """Offset of EC_RW at {0:08x} overlaps end + of EC_RO at {1:08x}""".format( + rw_offset, offset + ) + ) + + spi_list.append((rw_offset, ecrw, "ecrw")) + offset = rw_offset + len(ecrw) + + spi_list = sorted(spi_list) + + dumpsects(spi_list) + + # + # MEC152X Boot-ROM locates TAG0/1 at SPI offset 0 + # instead of end of SPI. + # + with open(args.output, "wb") as f: + debug_print("Write spi list to file", args.output) + addr = 0 + for s in spi_list: + if addr < s[0]: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(s[0] - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (s[0] - addr)) + addr = s[0] + debug_print( + "Offset ", + hex(addr), + " Length", + hex(len(s[1])), + "write data", + ) + + f.write(s[1]) + addr += len(s[1]) + + if addr < spi_size: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(spi_size - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (spi_size - addr)) + + f.flush() + + +if __name__ == "__main__": + main() |