microchip: mec: zephyr spi image generation
Added mchp mec zephyr image generator python script. It takes zephyr.bin as input and produces zephyr.mchp.bin. The default behavior is to not pad to SPI flash size. (Enable through CONFIG_MCHP_MEC_UNSIGNED_HEADER=y and CONFIG_MCHP_MEC_HEADER_FLASH_SIZE_256K=y) zephyr.mchp.bin is composed of: 1. First 4KB contains TAG at offset 0 and header at offset 0x100 2. Offset 0x1000 is the start of zephyr.bin which has been padded to a multiple of 128 bytes. 3. Boot-ROM EC Info Block (128 bytes) 4. Boot-ROM Co-Signature Block (96 bytes) 5. Boot-ROM trailer (160 bytes) contains the SHA-384 digest of 2-4. Signed-off-by: Jay Vasanth <jay.vasanth@microchip.com>
This commit is contained in:
parent
816449c138
commit
e74978cc03
3 changed files with 712 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
# Microchip MEC MCU line
|
||||
|
||||
# Copyright (c) 2018, Intel Corporation
|
||||
# Copyright (c) 2022, Microchip Technology Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config SOC_FAMILY_MEC
|
||||
|
@ -11,6 +12,210 @@ config SOC_FAMILY
|
|||
string
|
||||
default "microchip_mec"
|
||||
|
||||
menuconfig MCHP_MEC_UNSIGNED_HEADER
|
||||
bool "Create an unsigned output binary with MCHP MEC binary header"
|
||||
help
|
||||
On Microchip MEC series chip, the ROM code loads firmware image from flash
|
||||
to RAM using a TAG to locate a Header which specifies the location and
|
||||
size of the firmware image. Enable this to invoke the mec_spi_gen tool
|
||||
which generates an SPI image with TAG, Header, and firmware binary. This
|
||||
tool does not produce a signed image which can be authenticated by the
|
||||
Boot-ROM. Use the full Microchip SPI image generator program for
|
||||
authentication and all other Boot-ROM loader features. Refer to the MCHP
|
||||
EVB boards for an example.
|
||||
|
||||
if MCHP_MEC_UNSIGNED_HEADER
|
||||
|
||||
config MCHP_MEC_HEADER_CHIP
|
||||
string
|
||||
default "mec152x" if SOC_SERIES_MEC1501X
|
||||
default "mec172x" if SOC_SERIES_MEC172X
|
||||
|
||||
choice MCHP_MEC_HEADER_SPI_FREQ_MHZ_CHOICE
|
||||
prompt "Clock rate to use for SPI flash"
|
||||
default MCHP_MEC_HEADER_SPI_FREQ_MHZ_12
|
||||
help
|
||||
This selects the SPI clock frequency that will be used for loading
|
||||
firmware binary from flash to RAM.
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_FREQ_MHZ_12
|
||||
bool "SPI flash clock rate of 12 MHz"
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_FREQ_MHZ_16
|
||||
bool "SPI flash clock rate of 16 MHz"
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_FREQ_MHZ_24
|
||||
bool "SPI flash clock rate of 24 MHz"
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_FREQ_MHZ_48
|
||||
bool "SPI flash clock rate of 48 MHz"
|
||||
|
||||
endchoice
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_FREQ_MHZ
|
||||
int
|
||||
default 12 if MCHP_MEC_HEADER_SPI_FREQ_MHZ_12
|
||||
default 25 if MCHP_MEC_HEADER_SPI_FREQ_MHZ_16
|
||||
default 24 if MCHP_MEC_HEADER_SPI_FREQ_MHZ_24
|
||||
default 48 if MCHP_MEC_HEADER_SPI_FREQ_MHZ_48
|
||||
|
||||
choice MCHP_MEC_HEADER_SPI_READ_MODE_CHOICE
|
||||
prompt "Reading mode used by the SPI flash"
|
||||
default MCHP_MEC_HEADER_SPI_READ_MODE_FAST
|
||||
help
|
||||
This sets the reading mode that can be used by the SPI flash.
|
||||
Reading modes supported are normal, fast, dual, and quad.
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_READ_MODE_NORMAL
|
||||
bool "SPI flash operates full-duplex with frequency (< 25 MHz)"
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_READ_MODE_FAST
|
||||
bool "SPI flash operates full-duplex with fast reading mode"
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_READ_MODE_DUAL
|
||||
bool "SPI flash operates with dual data reading mode"
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_READ_MODE_QUAD
|
||||
bool "SPI flash operates with quad data reading mode"
|
||||
|
||||
endchoice
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_READ_MODE
|
||||
string
|
||||
default "slow" if MCHP_MEC_HEADER_SPI_READ_MODE_NORMAL
|
||||
default "fast" if MCHP_MEC_HEADER_SPI_READ_MODE_FAST
|
||||
default "dual" if MCHP_MEC_HEADER_SPI_READ_MODE_DUAL
|
||||
default "quad" if MCHP_MEC_HEADER_SPI_READ_MODE_QUAD
|
||||
|
||||
choice MCHP_MEC_HEADER_FLASH_SIZE_CHOICE
|
||||
prompt "Flash size"
|
||||
default MCHP_MEC_HEADER_FLASH_SIZE_16M
|
||||
help
|
||||
This sets the SPI flash size.
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE_256K
|
||||
bool "SPI flash size 256K Bytes"
|
||||
help
|
||||
The SPI flash size is 256K Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE_512K
|
||||
bool "SPI flash size 512K Bytes"
|
||||
help
|
||||
The SPI flash size is 512K Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE_1M
|
||||
bool "SPI flash size 1M Bytes"
|
||||
help
|
||||
The SPI flash size is 1M Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE_2M
|
||||
bool "SPI flash size 2M Bytes"
|
||||
help
|
||||
The SPI flash size is 2M Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE_4M
|
||||
bool "SPI flash size 4M Bytes"
|
||||
help
|
||||
The SPI flash size is 4M Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE_8M
|
||||
bool "SPI flash size 8M Bytes"
|
||||
help
|
||||
The SPI flash size is 8M Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE_16M
|
||||
bool "SPI flash size 16M Bytes"
|
||||
help
|
||||
The SPI flash size is 16M Bytes.
|
||||
|
||||
endchoice
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SIZE
|
||||
int
|
||||
default 256 if MCHP_MEC_HEADER_FLASH_SIZE_256K
|
||||
default 512 if MCHP_MEC_HEADER_FLASH_SIZE_512K
|
||||
default 1024 if MCHP_MEC_HEADER_FLASH_SIZE_1M
|
||||
default 2048 if MCHP_MEC_HEADER_FLASH_SIZE_2M
|
||||
default 4096 if MCHP_MEC_HEADER_FLASH_SIZE_4M
|
||||
default 8192 if MCHP_MEC_HEADER_FLASH_SIZE_8M
|
||||
default 16384 if MCHP_MEC_HEADER_FLASH_SIZE_16M
|
||||
|
||||
choice MCHP_MEC_HEADER_SPI_DRVSTR_CHOICE
|
||||
prompt "Flash drive strength"
|
||||
default MCHP_MEC_HEADER_SPI_DRVSTR_1X
|
||||
help
|
||||
This sets the SPI flash size.
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_DRVSTR_1X
|
||||
bool "SPI flash drive strength multiplier 1"
|
||||
help
|
||||
The SPI flash size is 256K Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_DRVSTR_2X
|
||||
bool "SPI flash drive strength multiplier 2"
|
||||
help
|
||||
The SPI flash size is 256K Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_DRVSTR_4X
|
||||
bool "SPI flash drive strength multiplier 4"
|
||||
help
|
||||
The SPI flash size is 512K Bytes.
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_DRVSTR_6X
|
||||
bool "SPI flash drive strength multiplier 6"
|
||||
help
|
||||
The SPI flash size is 1M Bytes.
|
||||
|
||||
endchoice
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_DRVSTR
|
||||
string
|
||||
default "1x" if MCHP_MEC_HEADER_SPI_DRVSTR_1X
|
||||
default "2x" if MCHP_MEC_HEADER_SPI_DRVSTR_2X
|
||||
default "4x" if MCHP_MEC_HEADER_SPI_DRVSTR_4X
|
||||
default "6x" if MCHP_MEC_HEADER_SPI_DRVSTR_6X
|
||||
|
||||
choice MCHP_MEC_HEADER_SPI_SLEW_RATE_CHOICE
|
||||
prompt "Slew rate of SPI pins"
|
||||
default MCHP_MEC_HEADER_SPI_SLEW_RATE_SLOW
|
||||
help
|
||||
This sets the slew rate of the SPI pins. Default is slow
|
||||
slew rate which is 1/2 the AHB clock rate. Fast slew is the
|
||||
AHB clock rate.
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_SLEW_RATE_SLOW
|
||||
bool "SPI pins slew rate is 1/2 AHB frequency"
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_SLEW_RATE_FAST
|
||||
bool "SPI pins slew rate is 1x AHB frequency"
|
||||
|
||||
endchoice
|
||||
|
||||
config MCHP_MEC_HEADER_SPI_SLEW_RATE
|
||||
string
|
||||
default "slow" if MCHP_MEC_HEADER_SPI_SLEW_RATE_SLOW
|
||||
default "fast" if MCHP_MEC_HEADER_SPI_SLEW_RATE_FAST
|
||||
|
||||
config MCHP_MEC_HEADER_FLASH_SPI_MODE
|
||||
int "Flash SPI Mode"
|
||||
range 0 7
|
||||
default 0
|
||||
help
|
||||
This three bit value corresponds to the QMSPI controllers clock idle and
|
||||
input/output data phases. Bits[0:2] are CPOL:CPHA_MOSI:CPHA_MISO. Refer
|
||||
to the data sheet. Default value is 0 corresponding to SPI Mode 0
|
||||
signalling.
|
||||
Setting this field to 0 selects mode 0, CPOL=0, CPHA_MOSI=0, CPHA_MISO=0
|
||||
Setting this filed to 7 selects mode 3, CPOL=1, CPHA_MOSI=1, CPHA_MISO=1
|
||||
|
||||
config MCHP_HEADER_VERBOSE_OUTPUT
|
||||
bool "Debug console output"
|
||||
default n
|
||||
help
|
||||
Enable print output from SPI generator script for debug
|
||||
|
||||
endif # MCHP_MEC_UNSIGNED_HEADER
|
||||
|
||||
# Select SoC Part No. and configuration options
|
||||
source "soc/arm/microchip_mec/*/Kconfig.soc"
|
||||
|
||||
|
|
|
@ -4,3 +4,24 @@ zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_MEC172X .)
|
|||
zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_MEC172X
|
||||
soc_i2c.c
|
||||
)
|
||||
|
||||
if (DEFINED CONFIG_MCHP_HEADER_VERBOSE_OUTPUT)
|
||||
set(MCHP_HEADER_VERBOSE_OPTION "-v")
|
||||
endif()
|
||||
|
||||
if (DEFINED CONFIG_MCHP_MEC_UNSIGNED_HEADER)
|
||||
set(MCHP_MEC_BIN_NAME ${CONFIG_KERNEL_BIN_NAME}.mchp.bin)
|
||||
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${SOC_DIR}/${ARCH}/${SOC_FAMILY}/common/spigen/mec_spi_gen.py
|
||||
-i ${KERNEL_BIN_NAME}
|
||||
-o ${MCHP_MEC_BIN_NAME}
|
||||
-c ${CONFIG_MCHP_MEC_HEADER_CHIP}
|
||||
-s ${CONFIG_MCHP_MEC_HEADER_FLASH_SIZE}
|
||||
-f ${CONFIG_MCHP_MEC_HEADER_SPI_FREQ_MHZ}
|
||||
-r ${CONFIG_MCHP_MEC_HEADER_SPI_READ_MODE}
|
||||
-m ${CONFIG_MCHP_MEC_HEADER_FLASH_SPI_MODE}
|
||||
--drvstr ${CONFIG_MCHP_MEC_HEADER_SPI_DRVSTR}
|
||||
--slewrate ${CONFIG_MCHP_MEC_HEADER_SPI_SLEW_RATE}
|
||||
${MCHP_HEADER_VERBOSE_OPTION}
|
||||
)
|
||||
endif()
|
||||
|
|
486
soc/arm/microchip_mec/common/spigen/mec_spi_gen.py
Executable file
486
soc/arm/microchip_mec/common/spigen/mec_spi_gen.py
Executable file
|
@ -0,0 +1,486 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2022 Microchip Technology Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import hashlib
|
||||
|
||||
verbose_mode = False
|
||||
|
||||
# Header parameters
|
||||
HDR_SIZE = 0x140
|
||||
HDR_VER_MEC172X = 0x03
|
||||
HDR_VER_MEC152X = 0x02
|
||||
HDR_SPI_CLK_12MHZ = 0x3
|
||||
HDR_SPI_CLK_16MHZ = 0x2
|
||||
HDR_SPI_CLK_24MHZ = 0x1
|
||||
HDR_SPI_CLK_48MHZ = 0
|
||||
HDR_SPI_DRV_STR_1X = 0
|
||||
HDR_SPI_DRV_STR_2X = 0x4
|
||||
HDR_SPI_DRV_STR_4X = 0x8
|
||||
HDR_SPI_DRV_STR_6X = 0xc
|
||||
HDR_SPI_SLEW_SLOW = 0
|
||||
HDR_SPI_SLEW_FAST = 0x10
|
||||
HDR_SPI_CPOL_LO = 0
|
||||
HDR_SPI_CPOL_HI = 0x20
|
||||
HDR_SPI_CHPHA_MOSI_EDGE_2 = 0
|
||||
HDR_SPI_CHPHA_MOSI_EDGE_1 = 0x40
|
||||
HDR_SPI_CHPHA_MISO_EDGE_1 = 0
|
||||
HDR_SPI_CHPHA_MISO_EDGE_2 = 0x80
|
||||
|
||||
# User defined constants HDR_SPI_RD_ (0, 1, 2, 3) as per boot rom spec.
|
||||
# 1st digit - number of I/O pins used to transmit the opcode
|
||||
# 2nd digit - number of I/O pins used to transmit the SPI address
|
||||
# 3rd digit - number of pins used to read data from flash
|
||||
# 4th digit (if present) - dummy clocks between address and data phase
|
||||
HDR_SPI_RD_111 = 0
|
||||
HDR_SPI_RD_1118 = 1
|
||||
HDR_SPI_RD_1128 = 2
|
||||
HDR_SPI_RD_1148 = 3
|
||||
|
||||
# Payload parameters
|
||||
PLD_LOAD_ADDR = 0xc0000
|
||||
PLD_LOAD_ADDR_MEC172X = 0xc0000
|
||||
PLD_LOAD_ADDR_MEC152X = 0xe0000
|
||||
PLD_ENTRY_ADDR = 0
|
||||
PLD_GRANULARITY = 128
|
||||
PLD_PAD_SIZE = 128
|
||||
PLD_PAD_BYTE = b'\xff'
|
||||
|
||||
MCHP_CHAR_P = 0x50
|
||||
MCHP_CHAR_H = 0x48
|
||||
MCHP_CHAR_C = 0x43
|
||||
MCHP_CHAR_M = 0x4D
|
||||
|
||||
EC_INFO_BLOCK_SIZE = 128
|
||||
ENCR_KEY_HDR_SIZE = 128
|
||||
COSIG_SIZE = 96
|
||||
TRAILER_SIZE = 160
|
||||
TRAILER_PAD_BYTE = b'\xff'
|
||||
|
||||
TAG_SPI_LOC = 0
|
||||
HDR_SPI_LOC = 0x100
|
||||
PLD_SPI_LOC = 0x1000
|
||||
|
||||
CRC_TABLE = [0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
|
||||
0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d]
|
||||
|
||||
CHIP_DICT = {
|
||||
'mec152x': { 'sram_base': 0xe0000, 'sram_size': 0x40000, 'header_ver': 2 },
|
||||
'mec172x': { 'sram_base': 0xc0000, 'sram_size': 0x68000, 'header_ver': 3 },
|
||||
}
|
||||
|
||||
CHIP_DEFAULT = 'mec172x'
|
||||
SPI_READ_MODE_DEFAULT = 'fast'
|
||||
SPI_FREQ_MHZ_DEFAULT = 12
|
||||
SPI_MODE_DEFAULT = 0
|
||||
SPI_MODE_MIN = 0
|
||||
SPI_MODE_MAX = 7
|
||||
SPI_DRIVE_STRENGTH_MULT_DEFAULT = "1x"
|
||||
SPI_SLEW_RATE_DEFAULT = "slow"
|
||||
|
||||
def print_bytes(title, b):
|
||||
"""Print bytes or bytearray as hex values"""
|
||||
print("{0} = {{ ".format(title), end='')
|
||||
count = 1
|
||||
for v in b:
|
||||
print("0x{0:02x}, ".format(v), end='')
|
||||
if (count % 8) == 0:
|
||||
print("")
|
||||
count = count + 1
|
||||
|
||||
print("}")
|
||||
|
||||
def crc8(crc, data):
|
||||
"""Update CRC8 value.
|
||||
|
||||
CRC8-ITU calculation
|
||||
"""
|
||||
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 build_tag(hdr_spi_loc):
|
||||
"""Build MEC172x Boot-ROM TAG
|
||||
|
||||
MEC172x Boot-ROM TAG is 4 bytes
|
||||
bits[23:0] = bits[31:8] of the Header SPI address
|
||||
Header location must be a mutliple of 256 bytes
|
||||
bits[31:24] = CRC8-ITU of bits[23:0]
|
||||
return immutable bytes type
|
||||
"""
|
||||
tag = bytearray([(hdr_spi_loc >> 8) & 0xff,
|
||||
(hdr_spi_loc >> 16) & 0xff,
|
||||
(hdr_spi_loc >> 24) & 0xff])
|
||||
tag.append(crc8(0, tag))
|
||||
|
||||
return bytes(tag)
|
||||
|
||||
def build_header(chip, spi_config, hdr_spi_loc, pld_spi_loc, pld_entry_addr, pld_len):
|
||||
"""Build MEC152x/MEC172x Boot-ROM SPI image header
|
||||
|
||||
Args:
|
||||
chip: mec152x or mec172x
|
||||
spi_config: spi configuration
|
||||
hdr_spi_loc: Header location in SPI Image
|
||||
pld_spi_loc: Payload(FW binary) location in SPI Image
|
||||
pld_entry_addr: Payload load address in MEC172x SPI SRAM
|
||||
Payload entry point address: index 0 instructs Boot-ROM to assume
|
||||
ARM vector table at beginning of payload and reset handler
|
||||
address is at offset 4 of payload.
|
||||
pld_len: Payload length, must be multiple of PLD_GRANULARITY
|
||||
|
||||
return: immutable bytes type for built header
|
||||
"""
|
||||
hdr = bytearray(HDR_SIZE)
|
||||
|
||||
hdr[0] = MCHP_CHAR_P
|
||||
hdr[1] = MCHP_CHAR_H
|
||||
hdr[2] = MCHP_CHAR_C
|
||||
hdr[3] = MCHP_CHAR_M
|
||||
|
||||
hdr[4] = CHIP_DICT[chip]['header_ver'] & 0xff
|
||||
|
||||
if spi_config['spi_freq_mhz'] == 48:
|
||||
hdr[5] = HDR_SPI_CLK_48MHZ
|
||||
elif spi_config['spi_freq_mhz'] == 24:
|
||||
hdr[5] = HDR_SPI_CLK_24MHZ
|
||||
elif spi_config['spi_freq_mhz'] == 16:
|
||||
hdr[5] = HDR_SPI_CLK_16MHZ
|
||||
else:
|
||||
hdr[5] = HDR_SPI_CLK_12MHZ
|
||||
|
||||
if spi_config['spi_mode'] & 0x01:
|
||||
hdr[5] |= HDR_SPI_CPOL_HI
|
||||
if spi_config['spi_mode'] & 0x02:
|
||||
hdr[5] |= HDR_SPI_CHPHA_MOSI_EDGE_1
|
||||
if spi_config['spi_mode'] & 0x04:
|
||||
hdr[5] |= HDR_SPI_CHPHA_MISO_EDGE_2
|
||||
|
||||
# translate 1x, 2x, 4x, 6x to 0, 1, 2, 3
|
||||
if spi_config['spi_drive_str'] == "6x":
|
||||
hdr[5] |= HDR_SPI_DRV_STR_6X
|
||||
elif spi_config['spi_drive_str'] == "4x":
|
||||
hdr[5] |= HDR_SPI_DRV_STR_4X
|
||||
elif spi_config['spi_drive_str'] == "2x":
|
||||
hdr[5] |= HDR_SPI_DRV_STR_2X
|
||||
else:
|
||||
hdr[5] |= HDR_SPI_DRV_STR_1X
|
||||
|
||||
# translate "slow", "fast" to 0, 1
|
||||
if spi_config['spi_slew_rate'] == "fast":
|
||||
hdr[5] |= HDR_SPI_SLEW_FAST
|
||||
|
||||
# MEC172x b[0]=0 do not allow 96MHz SPI clock
|
||||
hdr[6] = 0 # not using authentication or encryption
|
||||
|
||||
if spi_config['spi_read_mode'] == 'quad':
|
||||
hdr[7] = HDR_SPI_RD_1148
|
||||
elif spi_config['spi_read_mode'] == 'dual':
|
||||
hdr[7] = HDR_SPI_RD_1128
|
||||
elif spi_config['spi_read_mode'] == 'normal':
|
||||
hdr[7] = HDR_SPI_RD_111
|
||||
else:
|
||||
hdr[7] = HDR_SPI_RD_1118
|
||||
|
||||
# payload load address in SRAM
|
||||
pld_load_addr = CHIP_DICT[chip]['sram_base']
|
||||
hdr[8] = pld_load_addr & 0xff
|
||||
hdr[9] = (pld_load_addr >> 8) & 0xff
|
||||
hdr[0xA] = (pld_load_addr >> 16) & 0xff
|
||||
hdr[0xB] = (pld_load_addr >> 24) & 0xff
|
||||
|
||||
# payload entry point address in SRAM
|
||||
hdr[0xC] = pld_entry_addr & 0xff
|
||||
hdr[0xD] = (pld_entry_addr >> 8) & 0xff
|
||||
hdr[0xE] = (pld_entry_addr >> 16) & 0xff
|
||||
hdr[0xF] = (pld_entry_addr >> 24) & 0xff
|
||||
|
||||
# payload size (16-bit) in granularity units
|
||||
pld_units = pld_len // PLD_GRANULARITY
|
||||
hdr[0x10] = pld_units & 0xff
|
||||
hdr[0x11] = (pld_units >> 8) & 0xff
|
||||
# hdr[0x12:0x13] = 0 reserved
|
||||
|
||||
# Unsigned offset from start of Header to start of FW Binary
|
||||
# FW binary(payload) must always be located after header
|
||||
pld_offset = pld_spi_loc - hdr_spi_loc
|
||||
hdr[0x14] = pld_offset & 0xff
|
||||
hdr[0x15] = (pld_offset >> 8) & 0xff
|
||||
hdr[0x16] = (pld_offset >> 16) & 0xff
|
||||
hdr[0x17] = (pld_offset >> 24) & 0xff
|
||||
|
||||
# hdr[0x18] = 0 not using authentication
|
||||
# hdr[0x19] = 0 not adjusting SPI flash device drive strength
|
||||
# hdr[0x1A through 0x1F] = 0 reserved
|
||||
# hdr[0x20 through 0x27] = 0 not adjust SPI flash device drive strength
|
||||
# hdr[0x28 through 0x47] = 0 reserved
|
||||
# hdr[0x48 through 0x4F] = 0 reserved
|
||||
# hdr[0x50 through 0x7F] = ECDSA P-384 Public key x-component
|
||||
# hdr[0x80 through 0xAF] = ECDSA P-384 Public key y-component
|
||||
# hdr[0xB0 through 0xDF] = SHA-384 digest of hdr[0 through 0xAF] Always required
|
||||
# hdr[0xE0 through 0x10F] = ECDSA signature R-component of hdr[0 through 0xDF]
|
||||
# hdr[0x110 through 0x13F] = ECDSA signature S-component of hdr[0 through 0xDF]
|
||||
|
||||
h = hashlib.sha384()
|
||||
h.update(hdr[0:0xB0])
|
||||
hdr_digest = h.digest()
|
||||
|
||||
if verbose_mode:
|
||||
print_bytes("hdr_sha384_digest", hdr_digest)
|
||||
|
||||
hdr[0xB0:0xE0] = hdr_digest
|
||||
|
||||
return bytes(hdr)
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
# Use a lambda to handle base 10 or base 16 (hex) input
|
||||
parser.add_argument("-c",
|
||||
type=str,
|
||||
dest="chip",
|
||||
choices = ["mec152x", "mec172x"],
|
||||
default="mec172x",
|
||||
help="Chip name: mec172x(default) or mec152x")
|
||||
parser.add_argument("-i",
|
||||
type=str,
|
||||
dest="infilename",
|
||||
default="zephyr.bin",
|
||||
help="Input firmware binary file path/name (default: %(default)s)")
|
||||
parser.add_argument("-o",
|
||||
type=str,
|
||||
dest="outfilename",
|
||||
default="zephyr.mchp.bin",
|
||||
help="Output SPI image file path/name (default: %(default)s)")
|
||||
parser.add_argument("-s",
|
||||
type=int,
|
||||
dest="spi_size_kb",
|
||||
default=256,
|
||||
help="SPI image size in kilobytes (default: %(default)s)")
|
||||
parser.add_argument("-e",
|
||||
type=int,
|
||||
dest="entry_point",
|
||||
default=0,
|
||||
help="FW entry point address Lookup in image (default: %(default)s)")
|
||||
parser.add_argument("-f",
|
||||
type=int,
|
||||
dest="spi_freq_mhz",
|
||||
choices = [12, 16, 24, 48],
|
||||
default=12,
|
||||
help="SPI frequency: 12, 16, 24, or 48 MHz")
|
||||
parser.add_argument("-r",
|
||||
type=str,
|
||||
dest="spi_read_mode",
|
||||
choices = ["normal", "fast", "dual", "quad"],
|
||||
default="fast",
|
||||
help="SPI read mode: normal, fast, dual or quad")
|
||||
parser.add_argument("-m",
|
||||
type=int,
|
||||
dest="spi_mode",
|
||||
choices = [0, 1, 2, 3, 4, 5, 6, 7],
|
||||
default=0,
|
||||
help="SPI signalling mode 3-bit field: 0-7")
|
||||
parser.add_argument("--drvstr",
|
||||
type=str,
|
||||
dest="spi_drive_strength",
|
||||
choices = ["1x", "2x", "4x", "6x"],
|
||||
default="1x",
|
||||
help="SPI pin driver strength multiplier encoded")
|
||||
parser.add_argument("--slewrate",
|
||||
type=str,
|
||||
dest="spi_slew_rate",
|
||||
choices = ["slow", "fast"],
|
||||
default="slow",
|
||||
help="SPI pins slew rate")
|
||||
parser.add_argument("--fill",
|
||||
dest="fill",
|
||||
action='store_true',
|
||||
help="Fill with 0xFF to flash size")
|
||||
parser.add_argument("-v",
|
||||
dest="verbose",
|
||||
action='store_true',
|
||||
help="Enable messages to console")
|
||||
|
||||
ret_args = parser.parse_args()
|
||||
|
||||
return ret_args
|
||||
|
||||
def main():
|
||||
"""MEC SPI Gen"""
|
||||
args = parse_args()
|
||||
|
||||
verbose_mode = args.verbose
|
||||
|
||||
if verbose_mode:
|
||||
print("Command line arguments/defaults")
|
||||
print(" chip = {0}".format(args.chip))
|
||||
print(" infilename = {0}".format(args.infilename))
|
||||
print(" outfilename = {0}".format(args.outfilename))
|
||||
print(" SPI size (kilobytes) = {0}".format(args.spi_size_kb))
|
||||
print(" Entry point address = {0}".format(args.entry_point))
|
||||
print(" SPI frequency MHz = {0}".format(args.spi_freq_mhz))
|
||||
print(" SPI Read Mode = {0}".format(args.spi_read_mode))
|
||||
print(" SPI Signalling Mode = {0}".format(args.spi_mode))
|
||||
print(" SPI drive strength = {0}".format(args.spi_drive_strength))
|
||||
print(" SPI slew rate fast = {0}".format(args.spi_slew_rate))
|
||||
print(" Verbose = {0}".format(args.verbose))
|
||||
|
||||
if args.infilename is None:
|
||||
print("ERROR: Specify input binary file name with -i")
|
||||
sys.exit(-1)
|
||||
|
||||
if args.outfilename is None:
|
||||
print("ERROR: Specify output binary file name with -o")
|
||||
sys.exit(-1)
|
||||
|
||||
chip = args.chip
|
||||
spi_read_mode = args.spi_read_mode
|
||||
spi_freq_mhz = args.spi_freq_mhz
|
||||
spi_mode = args.spi_mode
|
||||
spi_drive_str_mult = args.spi_drive_strength
|
||||
spi_slew = args.spi_slew_rate
|
||||
|
||||
spi_size = args.spi_size_kb * 1024
|
||||
|
||||
indata = None
|
||||
with open(args.infilename, "rb") as fin:
|
||||
indata = fin.read()
|
||||
|
||||
indata_len = len(indata)
|
||||
if verbose_mode:
|
||||
print("Read input FW binary: length = {0}".format(indata_len))
|
||||
|
||||
# if necessary pad input data to PLD_GRANULARITY required by Boot-ROM loader
|
||||
pad_len = 0
|
||||
if (indata_len % PLD_GRANULARITY) != 0:
|
||||
pad_len = PLD_GRANULARITY - (indata_len % PLD_GRANULARITY)
|
||||
# NOTE: MCHP Production SPI Image Gen. pads with 0
|
||||
padding = PLD_PAD_BYTE * pad_len
|
||||
indata = indata + padding
|
||||
|
||||
indata_len += pad_len
|
||||
|
||||
if verbose_mode:
|
||||
print("Padded FW binary: length = {0}".format(indata_len))
|
||||
|
||||
# Do we have enough space for 4KB block containing TAG and Header, padded FW binary,
|
||||
# EC Info Block, Co-Sig Block, and Trailer?
|
||||
mec_add_info_size = PLD_SPI_LOC + EC_INFO_BLOCK_SIZE + COSIG_SIZE + TRAILER_SIZE
|
||||
if indata_len > (spi_size - mec_add_info_size):
|
||||
print("ERROR: FW binary exceeds flash size! indata_len = {0} spi_size = {1}".format(indata_len, spi_size))
|
||||
sys.exit(-1)
|
||||
|
||||
entry_point = args.entry_point
|
||||
if args.entry_point == 0:
|
||||
# Look up entry point in image
|
||||
# Assumes Cortex-M4 vector table
|
||||
# at beginning of image and second
|
||||
# word in table is address of reset handler
|
||||
entry_point = int.from_bytes(indata[4:8], byteorder="little")
|
||||
|
||||
tag = build_tag(HDR_SPI_LOC)
|
||||
|
||||
if verbose_mode:
|
||||
print_bytes("TAG", tag)
|
||||
print("Build Header at {0}: Load Address = 0x{1:0x} Entry Point Address = 0x{2:0x}".format(
|
||||
HDR_SPI_LOC, PLD_LOAD_ADDR, entry_point))
|
||||
|
||||
spi_config_info = {
|
||||
"spi_freq_mhz": spi_freq_mhz,
|
||||
"spi_mode": spi_mode,
|
||||
"spi_read_mode": spi_read_mode,
|
||||
"spi_drive_str": spi_drive_str_mult,
|
||||
"spi_slew_rate": spi_slew,
|
||||
}
|
||||
|
||||
header = build_header(chip, spi_config_info, HDR_SPI_LOC, PLD_SPI_LOC, entry_point, indata_len)
|
||||
|
||||
if verbose_mode:
|
||||
print_bytes("HEADER", header)
|
||||
print("")
|
||||
|
||||
# appended to end of padded payload
|
||||
ec_info_block = bytearray(EC_INFO_BLOCK_SIZE)
|
||||
ec_info_loc = PLD_SPI_LOC + len(indata)
|
||||
|
||||
# appended to end of (padded payload + ec_info_block)
|
||||
cosig = bytearray(b'\xff' * COSIG_SIZE)
|
||||
cosig_loc = ec_info_loc + EC_INFO_BLOCK_SIZE
|
||||
|
||||
# appended to end of (padded payload + ec_info_block + cosig)
|
||||
# trailer[0:0x30] = SHA384(indata || ec_info_block || cosig)
|
||||
# trailer[0x30:] = 0xFF
|
||||
trailer = bytearray(b'\xff' * TRAILER_SIZE)
|
||||
trailer_loc = cosig_loc + COSIG_SIZE
|
||||
|
||||
h = hashlib.sha384()
|
||||
h.update(indata)
|
||||
h.update(ec_info_block)
|
||||
h.update(cosig)
|
||||
image_digest = h.digest()
|
||||
trailer[0:len(image_digest)] = image_digest
|
||||
|
||||
if verbose_mode:
|
||||
print("SHA-384 digest (paddedFW || ec_info_block || cosig)")
|
||||
print_bytes("digest", image_digest)
|
||||
|
||||
spi_bufs = []
|
||||
spi_bufs.append(("TAG", TAG_SPI_LOC, tag))
|
||||
spi_bufs.append(("HEADER", HDR_SPI_LOC, header))
|
||||
spi_bufs.append(("PAYLOAD", PLD_SPI_LOC, indata))
|
||||
spi_bufs.append(("EC_INFO", ec_info_loc, ec_info_block))
|
||||
spi_bufs.append(("COSIG", cosig_loc, cosig))
|
||||
spi_bufs.append(("TRAILER", trailer_loc, trailer))
|
||||
|
||||
spi_bufs.sort(key=lambda x: x[1])
|
||||
|
||||
if verbose_mode:
|
||||
i = 0
|
||||
for sb in spi_bufs:
|
||||
print("buf[{0}]: {1} location=0x{2:0x} length=0x{3:0x}".format(i, sb[0], sb[1], len(sb[2])))
|
||||
print("")
|
||||
|
||||
fill = bytes(b'\xff' * 256)
|
||||
if verbose_mode:
|
||||
print("len(fill) = {0}".format(len(fill)))
|
||||
|
||||
loc = 0
|
||||
with open(args.outfilename, "wb") as fout:
|
||||
for sb in spi_bufs:
|
||||
if verbose_mode:
|
||||
print("sb: {0} location=0x{1:0x} len=0x{2:0x}".format(sb[0], sb[1], len(sb[2])))
|
||||
if loc < sb[1]:
|
||||
fill_len = sb[1] - loc
|
||||
if verbose_mode:
|
||||
print("loc = 0x{0:0x}: Fill with 0xFF len=0x{1:0x}".format(loc, fill_len))
|
||||
nfill = fill_len // 256
|
||||
rem = fill_len % 256
|
||||
for _ in range(nfill):
|
||||
fout.write(fill)
|
||||
if rem > 0:
|
||||
fout.write(fill[0:rem])
|
||||
loc = loc + fill_len
|
||||
if verbose_mode:
|
||||
print("loc = 0x{0:0x}: write {1} len=0x{2:0x}".format(loc, sb[0], len(sb[2])))
|
||||
fout.write(sb[2])
|
||||
loc = loc + len(sb[2])
|
||||
if args.fill and (loc < spi_size):
|
||||
fill_len = spi_size - loc
|
||||
nfill = fill_len // 256
|
||||
rem = fill_len % 256
|
||||
for _ in range(nfill):
|
||||
fout.write(fill)
|
||||
if rem > 0:
|
||||
fout.write(fill[0:rem])
|
||||
loc = loc + fill_len
|
||||
if verbose_mode:
|
||||
print("Final loc = 0x{0:0x}".format(loc))
|
||||
|
||||
if verbose_mode:
|
||||
print("MEC SPI Gen done")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue