initial commit

This commit is contained in:
2022-10-23 23:45:43 -07:00
commit e190fa5193
6450 changed files with 8626944 additions and 0 deletions
@@ -0,0 +1,209 @@
/*********************************************************************
* (c) SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
* www.segger.com *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : AMA3B2KK-KBR.JLinkScript
Purpose : Handle reset for AmbiqMicro AMA3B2KK series of MCUs
Literature:
[1] J-Link User Guide (UM08001_JLink.pdf)
Additional information:
For more information about public functions that can be implemented
in order to customize J-Link actions, please refer to [1]
*********************************************************************/
/*********************************************************************
*
* ResetTarget()
* Reset and wait until CPU is halted.
*********************************************************************/
void ResetTarget(void) {
// Register Address Values
int AIRCR_ADDR ;
int DHCSR_ADDR ;
int DEMCR_ADDR ;
int AHBAP_REG_CTRL ;
int AHBAP_REG_ADDR ;
int AHBAP_REG_DATA ;
int DP_REG_SELECT ;
int MCUCTRL_SCRATCH0 ;
int MCUCTRL_BOOTLDR ;
int JDEC_PID ;
// Internal Variables
int Ctrl;
int demcr;
int scratch0;
int bootldr;
int jdecpid;
int v;
int Tries;
int Done;
int nonsecure;
int timeout;
// Initialize the Register Address and Internal vars.
AIRCR_ADDR = 0xE000ED0C;
DHCSR_ADDR = 0xE000EDF0;
DEMCR_ADDR = 0xE000EDFC;
MCUCTRL_SCRATCH0 = 0x400401B0;
MCUCTRL_BOOTLDR = 0x400401A0;
JDEC_PID = 0xF0000FE0;
AHBAP_REG_CTRL = 0;
AHBAP_REG_ADDR = 1;
AHBAP_REG_DATA = 3;
DP_REG_SELECT = 2;
nonsecure = 1;
timeout = 0;
// Check global variable to detect whether debugger is using JTAG or SWO and configure JTAG is necessary.
if (MAIN_ActiveTIF == JLINK_TIF_JTAG) {
JLINK_CORESIGHT_Configure("IRPre=0;DRPre=0;IRPost=0;DRPost=0;IRLenDevice=4");
} else {
JLINK_CORESIGHT_Configure(""); // For SWD, no special setup is needed, just output the switching sequence
}
// Power-up complete DAP
Ctrl = 0
| (1 << 30) // System power-up
| (1 << 28) // Debug popwer-up
| (1 << 5) // Clear STICKYERR
;
JLINK_CORESIGHT_WriteDP(1, Ctrl);
// Select AHB-AP and configure it
JLINK_CORESIGHT_WriteDP(DP_REG_SELECT, (0 << 4) | (0 << 24)); // Select AP[0] (AHB-AP) bank 0
JLINK_CORESIGHT_WriteAP(AHBAP_REG_CTRL, (1 << 4) | (1 << 24) | (1 << 25) | (1 << 29) | (2 << 0)); // Auto-increment, Private access, HMASTER = DEBUG, Access size: word
// Enable Debug and Halt the MCU Core.
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DHCSR_ADDR);
v = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
v &= 0x3F; // Mask out "debug" bits
v |= 0xA05F0000; // Debug key to make a write to the DHCSR a valid one
v |= 0x00000002; // Halt the core
v |= 0x00000001; // Enable debug functionalities of the core
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DHCSR_ADDR);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_DATA, v);
// Read the Peripheral ID.
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, JDEC_PID);
jdecpid = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
Report1("JDEC PID ", jdecpid);
// Is this Apollo3-Blue or Apollo3-Blue-Plus MCU?
if ((jdecpid & 0xF0) == 0xC0)
{
// Apollo3-Blue or Apollo3-Blue-Plus
Report("Ambiq Apollo3-Blue ResetTarget");
// Read MCUCTRL_BOOTLDR to determine if it is a secure or non-secure chip
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, MCUCTRL_BOOTLDR);
bootldr = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
Report1("Bootldr = ", bootldr);
if ((bootldr & 0x0C000000) == 0x04000000)
{
Report("Secure Part.");
nonsecure = 0;
}
}
if (nonsecure == 0)
{
// Set MCUCTRL Scratch0, indicating that the Bootloader needs to run, then halt when it is finished.
Report("Secure Chip. Bootloader needs to run which will then halt when finish.");
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, MCUCTRL_SCRATCH0);
scratch0 = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, MCUCTRL_SCRATCH0);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_DATA, scratch0 | 0x1);
} else
{
// Set VC_CORERESET in the DEMCR.
Report("Non-Secure Chip. Following normal Reset procedure.");
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DEMCR_ADDR);
demcr = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DEMCR_ADDR);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_DATA, demcr | 0x00000001);
}
// Set the SYSRESETREQ bit in the AIRCR.
// This will request the MCU Core to reset.
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, AIRCR_ADDR);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_DATA, 0x05FA0004);
// Wait until CPU is halted
Tries = 0;
Done = 0;
do {
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DHCSR_ADDR);
v = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
// Check if CPU is halted. If so, we are done
if (Tries >= 25) // wait for up to 2.5 seconds.
{
Report("Apollo3 (connect): Timeout while waiting for CPU to halt after reset. Manually halting CPU.");
Done = 1;
timeout = 1;
}
else if ((v != 0xFFFFFFFF) && (v & 0x00020000)) // Bit 17: S_HALT in the DHCSR.
{
Report1("CPU halted after reset. Num Tries = ", Tries);
Done = 1;
}
Tries = Tries + 1;
SYS_Sleep(100); // Go to sleep for 100 msec.
} while(Done == 0);
// Let's try one more time using regular reset method
if ((timeout == 1) && (nonsecure == 0))
{
// Set VC_CORERESET
Report("Secure Part Reset timed out. Reverting to normal Reset procedure.");
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DEMCR_ADDR);
demcr = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DEMCR_ADDR);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_DATA, demcr | 0x00000001);
// SYSRESETREQ
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, AIRCR_ADDR);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_DATA, 0x05FA0004);
//
// Wait until CPU is halted
//
Tries = 0;
Done = 0;
do {
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DHCSR_ADDR);
v = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
// Check if CPU is halted. If so, we are done
if (Tries >= 25) // wait for up to 2.5 seconds.
{
Report("Apollo3 (connect): Timeout while waiting for CPU to halt after reset. Manually halting CPU.");
Done = 1;
timeout = 1;
}
else if ((v != 0xFFFFFFFF) && (v & 0x00020000)) // Bit 17: S_HALT in the DHCSR.
{
Report1("CPU halted after reset. Num Tries = ", Tries);
Done = 1;
}
Tries = Tries + 1;
SYS_Sleep(100); // Go to sleep for 100 msec.
} while(Done == 0);
}
// If non-secure part,...
if (nonsecure == 1)
{
// Clear VC_CORERESET in the DEMCR.
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DEMCR_ADDR);
demcr = JLINK_CORESIGHT_ReadAP(AHBAP_REG_DATA);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_ADDR, DEMCR_ADDR);
JLINK_CORESIGHT_WriteAP(AHBAP_REG_DATA, (demcr & 0xFFFFFFFE));
}
}
@@ -0,0 +1,357 @@
#!/usr/bin/env python3
# Utility functioins
import sys
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
import array
import hashlib
import hmac
import os
import binascii
ivVal0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
FLASH_PAGE_SIZE = 0x2000 # 8K
MAX_DOWNLOAD_SIZE = 0x48000 # 288K
AM_SECBOOT_DEFAULT_NONSECURE_MAIN = 0xC000
AM_SECBOOT_AESCBC_BLOCK_SIZE_WORDS = 4
AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES = 4*AM_SECBOOT_AESCBC_BLOCK_SIZE_WORDS
AM_SECBOOT_MIN_KEYIDX_INFO0 = 8 ## KeyIdx 8 - 15
AM_SECBOOT_MAX_KEYIDX_INFO0 = 15
AM_SECBOOT_MIN_KEYIDX_INFO1 = 0 ## KeyIdx 0 - 7
AM_SECBOOT_MAX_KEYIDX_INFO1 = 7
AM_SECBOOT_KEYIDX_BYTES = 16
# Encryption Algorithm
AM_SECBOOT_ENC_ALGO_NONE = 0
AM_SECBOOT_ENC_ALGO_AES128 = 1
AM_SECBOOT_ENC_ALGO_MAX = AM_SECBOOT_ENC_ALGO_AES128
# String constants
helpEncAlgo = 'Encryption Algo? (0(default) = none, 1 = AES128)'
# Authentication Algorithm
AM_SECBOOT_AUTH_ALGO_NONE = 0
AM_SECBOOT_AUTH_ALGO_SHA256HMAC = 1
AM_SECBOOT_AUTH_ALGO_MAX = AM_SECBOOT_AUTH_ALGO_SHA256HMAC
# String constants
helpAuthAlgo = 'Authentication Algo? (0(default) = none, 1 = SHA256)'
FLASH_INVALID = 0xFFFFFFFF
# KeyWrap Mode
AM_SECBOOT_KEYWRAP_NONE = 0
AM_SECBOOT_KEYWRAP_XOR = 1
AM_SECBOOT_KEYWRAP_AES128 = 2
AM_SECBOOT_KEYWRAP_MAX = AM_SECBOOT_KEYWRAP_AES128
#******************************************************************************
#
# Magic Numbers
#
#******************************************************************************
AM_IMAGE_MAGIC_MAIN = 0xC0
AM_IMAGE_MAGIC_CHILD = 0xCC
AM_IMAGE_MAGIC_NONSECURE = 0xCB
AM_IMAGE_MAGIC_INFO0 = 0xCF
# Dummy for creating images for customer - not understood by SBL
# This could be any value from the definition:
# #define AM_IMAGE_MAGIC_CUST(x) ((((x) & 0xF0) == 0xC0) && ((x) != 0xC0) && ((x) != 0xCC) && ((x) != 0xCB) && ((x) != 0xCF))
AM_IMAGE_MAGIC_CUSTPATCH = 0xC1
#******************************************************************************
#
# Image Types
#
#******************************************************************************
AM_SECBOOT_WIRED_IMAGETYPE_SBL = 0
AM_SECBOOT_WIRED_IMAGETYPE_AM3P = 1
AM_SECBOOT_WIRED_IMAGETYPE_PATCH = 2
AM_SECBOOT_WIRED_IMAGETYPE_MAIN = 3
AM_SECBOOT_WIRED_IMAGETYPE_CHILD = 4
AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH = 5
AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE = 6
AM_SECBOOT_WIRED_IMAGETYPE_INFO0 = 7
AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA = 32
AM_SECBOOT_WIRED_IMAGETYPE_INVALID = 0xFF
#******************************************************************************
#
# Wired Message Types
#
#******************************************************************************
AM_SECBOOT_WIRED_MSGTYPE_HELLO = 0
AM_SECBOOT_WIRED_MSGTYPE_STATUS = 1
AM_SECBOOT_WIRED_MSGTYPE_OTADESC = 2
AM_SECBOOT_WIRED_MSGTYPE_UPDATE = 3
AM_SECBOOT_WIRED_MSGTYPE_ABORT = 4
AM_SECBOOT_WIRED_MSGTYPE_RECOVER = 5
AM_SECBOOT_WIRED_MSGTYPE_RESET = 6
AM_SECBOOT_WIRED_MSGTYPE_ACK = 7
AM_SECBOOT_WIRED_MSGTYPE_DATA = 8
#******************************************************************************
#
# Wired Message ACK Status
#
#******************************************************************************
AM_SECBOOT_WIRED_ACK_STATUS_SUCCESS = 0
AM_SECBOOT_WIRED_ACK_STATUS_FAILURE = 1
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_INFO0 = 2
AM_SECBOOT_WIRED_ACK_STATUS_CRC = 3
AM_SECBOOT_WIRED_ACK_STATUS_SEC = 4
AM_SECBOOT_WIRED_ACK_STATUS_MSG_TOO_BIG = 5
AM_SECBOOT_WIRED_ACK_STATUS_UNKNOWN_MSGTYPE = 6
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_ADDR = 7
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_OPERATION = 8
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_PARAM = 9
AM_SECBOOT_WIRED_ACK_STATUS_SEQ = 10
AM_SECBOOT_WIRED_ACK_STATUS_TOO_MUCH_DATA = 11
#******************************************************************************
#
# Definitions related to Image Headers
#
#******************************************************************************
AM_HMAC_SIG_SIZE = 32
AM_KEK_SIZE = 16
AM_CRC_SIZE = 4
AM_MAX_UART_MSG_SIZE = 8192 # 8K buffer in SBL
# Wiredupdate Image Header
AM_WU_IMAGEHDR_OFFSET_SIG = 16
AM_WU_IMAGEHDR_OFFSET_IV = 48
AM_WU_IMAGEHDR_OFFSET_KEK = 64
AM_WU_IMAGEHDR_OFFSET_IMAGETYPE = (AM_WU_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_WU_IMAGEHDR_OFFSET_OPTIONS = (AM_WU_IMAGEHDR_OFFSET_IMAGETYPE + 1)
AM_WU_IMAGEHDR_OFFSET_KEY = (AM_WU_IMAGEHDR_OFFSET_IMAGETYPE + 4)
AM_WU_IMAGEHDR_OFFSET_ADDR = (AM_WU_IMAGEHDR_OFFSET_KEY + 4)
AM_WU_IMAGEHDR_OFFSET_SIZE = (AM_WU_IMAGEHDR_OFFSET_ADDR + 4)
AM_WU_IMAGEHDR_START_HMAC = (AM_WU_IMAGEHDR_OFFSET_SIG + AM_HMAC_SIG_SIZE)
AM_WU_IMAGEHDR_START_ENCRYPT = (AM_WU_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_WU_IMAGEHDR_SIZE = (AM_WU_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE + 16)
# Image Header
AM_IMAGEHDR_SIZE_MAIN = 256
AM_IMAGEHDR_SIZE_AUX = (112 + AM_KEK_SIZE)
AM_IMAGEHDR_OFFSET_CRC = 4
AM_IMAGEHDR_OFFSET_SIG = 16
AM_IMAGEHDR_OFFSET_IV = 48
AM_IMAGEHDR_OFFSET_KEK = 64
AM_IMAGEHDR_OFFSET_SIGCLR = (AM_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_IMAGEHDR_START_CRC = (AM_IMAGEHDR_OFFSET_CRC + AM_CRC_SIZE)
AM_IMAGEHDR_START_HMAC_INST = (AM_IMAGEHDR_OFFSET_SIG + AM_HMAC_SIG_SIZE)
AM_IMAGEHDR_START_ENCRYPT = (AM_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_IMAGEHDR_START_HMAC = (AM_IMAGEHDR_OFFSET_SIGCLR + AM_HMAC_SIG_SIZE)
AM_IMAGEHDR_OFFSET_ADDR = AM_IMAGEHDR_START_HMAC
AM_IMAGEHDR_OFFSET_VERKEY = (AM_IMAGEHDR_OFFSET_ADDR + 4)
AM_IMAGEHDR_OFFSET_CHILDPTR = (AM_IMAGEHDR_OFFSET_VERKEY + 4)
# Recover message
AM_WU_RECOVERY_HDR_SIZE = 44
AM_WU_RECOVERY_HDR_OFFSET_CUSTID = 8
AM_WU_RECOVERY_HDR_OFFSET_RECKEY = (AM_WU_RECOVERY_HDR_OFFSET_CUSTID + 4)
AM_WU_RECOVERY_HDR_OFFSET_NONCE = (AM_WU_RECOVERY_HDR_OFFSET_RECKEY + 16)
AM_WU_RECOVERY_HDR_OFFSET_RECBLOB = (AM_WU_RECOVERY_HDR_OFFSET_NONCE + 16)
#******************************************************************************
#
# INFOSPACE related definitions
#
#******************************************************************************
AM_SECBOOT_INFO0_SIGN_PROGRAMMED0 = 0x48EAAD88
AM_SECBOOT_INFO0_SIGN_PROGRAMMED1 = 0xC9705737
AM_SECBOOT_INFO0_SIGN_PROGRAMMED2 = 0x0A6B8458
AM_SECBOOT_INFO0_SIGN_PROGRAMMED3 = 0xE41A9D74
AM_SECBOOT_INFO0_SIGN_UINIT0 = 0x5B75A5FA
AM_SECBOOT_INFO0_SIGN_UINIT1 = 0x7B9C8674
AM_SECBOOT_INFO0_SIGN_UINIT2 = 0x869A96FE
AM_SECBOOT_INFO0_SIGN_UINIT3 = 0xAEC90860
INFO_SIZE_BYTES = (8 * 1024)
INFO_MAX_AUTH_KEY_WORDS = 32
INFO_MAX_ENC_KEY_WORDS = 32
INFO_MAX_AUTH_KEYS = (INFO_MAX_AUTH_KEY_WORDS*4//AM_SECBOOT_KEYIDX_BYTES)
INFO_MAX_ENC_KEYS = (INFO_MAX_ENC_KEY_WORDS*4//AM_SECBOOT_KEYIDX_BYTES)
#******************************************************************************
#
# CRC using ethernet poly, as used by Corvette hardware for validation
#
#******************************************************************************
def crc32(L):
return (binascii.crc32(L) & 0xFFFFFFFF)
#******************************************************************************
#
# Pad the text to the block_size. bZeroPad determines how to handle text which
# is already multiple of block_size
#
#******************************************************************************
def pad_to_block_size(text, block_size, bZeroPad):
text_length = len(text)
amount_to_pad = block_size - (text_length % block_size)
if (amount_to_pad == block_size):
if (bZeroPad == 0):
amount_to_pad = 0
for i in range(0, amount_to_pad, 1):
text += bytes(chr(amount_to_pad), 'ascii')
return text
#******************************************************************************
#
# AES CBC encryption
#
#******************************************************************************
def encrypt_app_aes(cleartext, encKey, iv):
key = array.array('B', encKey).tostring()
ivVal = array.array('B', iv).tostring()
plaintext = array.array('B', cleartext).tostring()
encryption_suite = AES.new(key, AES.MODE_CBC, ivVal)
cipher_text = encryption_suite.encrypt(plaintext)
return cipher_text
#******************************************************************************
#
# AES 128 CBC encryption
#
#******************************************************************************
def encrypt_app_aes128(cleartext, encKey, iv):
key = array.array('B', encKey).tostring()
ivVal = array.array('B', iv).tostring()
plaintext = array.array('B', cleartext).tostring()
encryption_suite = AES.new(key, AES.MODE_CBC, ivVal)
cipher_text = encryption_suite.encrypt(plaintext)
return cipher_text
#******************************************************************************
#
# SHA256 HMAC
#
#******************************************************************************
def compute_hmac(key, data):
sig = hmac.new(array.array('B', key).tostring(), array.array('B', data).tostring(), hashlib.sha256).digest()
return sig
#******************************************************************************
#
# RSA PKCS1_v1_5 sign
#
#******************************************************************************
def compute_rsa_sign(prvKeyFile, data):
key = open(prvKeyFile, "r").read()
rsakey = RSA.importKey(key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(bytes(data))
sign = signer.sign(digest)
return sign
#******************************************************************************
#
# RSA PKCS1_v1_5 sign verification
#
#******************************************************************************
def verify_rsa_sign(pubKeyFile, data, sign):
key = open(pubKeyFile, "r").read()
rsakey = RSA.importKey(key)
#print(hex(rsakey.n))
verifier = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(bytes(data))
return verifier.verify(digest, sign)
#******************************************************************************
#
# Fill one word in bytearray
#
#******************************************************************************
def fill_word(barray, offset, w):
barray[offset + 0] = (w >> 0) & 0x000000ff;
barray[offset + 1] = (w >> 8) & 0x000000ff;
barray[offset + 2] = (w >> 16) & 0x000000ff;
barray[offset + 3] = (w >> 24) & 0x000000ff;
#******************************************************************************
#
# Turn a 32-bit number into a series of bytes for transmission.
#
# This command will split a 32-bit integer into an array of bytes, ordered
# LSB-first for transmission over the UART.
#
#******************************************************************************
def int_to_bytes(n):
A = [n & 0xFF,
(n >> 8) & 0xFF,
(n >> 16) & 0xFF,
(n >> 24) & 0xFF]
return A
#******************************************************************************
#
# Extract a word from a byte array
#
#******************************************************************************
def word_from_bytes(B, n):
return (B[n] + (B[n + 1] << 8) + (B[n + 2] << 16) + (B[n + 3] << 24))
#******************************************************************************
#
# automatically figure out the integer format (base 10 or 16)
#
#******************************************************************************
def auto_int(x):
return int(x, 0)
#******************************************************************************
#
# User controllable Prints control
#
#******************************************************************************
# Defined print levels
AM_PRINT_LEVEL_MIN = 0
AM_PRINT_LEVEL_NONE = AM_PRINT_LEVEL_MIN
AM_PRINT_LEVEL_ERROR = 1
AM_PRINT_LEVEL_INFO = 2
AM_PRINT_LEVEL_VERBOSE = 4
AM_PRINT_LEVEL_DEBUG = 5
AM_PRINT_LEVEL_MAX = AM_PRINT_LEVEL_DEBUG
# Global variable to control the prints
AM_PRINT_VERBOSITY = AM_PRINT_LEVEL_INFO
helpPrintLevel = 'Set Log Level (0: None), (1: Error), (2: INFO), (4: Verbose), (5: Debug) [Default = Info]'
def am_set_print_level(level):
global AM_PRINT_VERBOSITY
AM_PRINT_VERBOSITY = level
def am_print(*args, level=AM_PRINT_LEVEL_INFO, **kwargs):
global AM_PRINT_VERBOSITY
if (AM_PRINT_VERBOSITY >= level):
print(*args, **kwargs)
@@ -0,0 +1,178 @@
from am_defines import *
#******************************************************************************
#
# INFOSPACE related definitions
#
#******************************************************************************
INFO0_SIGNATURE0_O = 0x00000000
INFO0_SIGNATURE1_O = 0x00000004
INFO0_SIGNATURE2_O = 0x00000008
INFO0_SIGNATURE3_O = 0x0000000c
INFO0_SECURITY_O = 0x00000010
INFO0_CUSTOMER_TRIM_O = 0x00000014
INFO0_CUSTOMER_TRIM2_O = 0x00000018
INFO0_SECURITY_OVR_O = 0x00000020
INFO0_SECURITY_WIRED_CFG_O = 0x00000024
INFO0_SECURITY_WIRED_IFC_CFG0_O = 0x00000028
INFO0_SECURITY_WIRED_IFC_CFG1_O = 0x0000002C
INFO0_SECURITY_WIRED_IFC_CFG2_O = 0x00000030
INFO0_SECURITY_WIRED_IFC_CFG3_O = 0x00000034
INFO0_SECURITY_WIRED_IFC_CFG4_O = 0x00000038
INFO0_SECURITY_WIRED_IFC_CFG5_O = 0x0000003C
INFO0_SECURITY_VERSION_O = 0x00000040
INFO0_SECURITY_SRAM_RESV_O = 0x00000050
AM_REG_INFO0_SECURITY_SRAM_RESV_SRAM_RESV_M = 0x0000FFFF
INFO0_WRITE_PROTECT_L_O = 0x000001f8
INFO0_WRITE_PROTECT_H_O = 0x000001fc
INFO0_COPY_PROTECT_L_O = 0x00000200
INFO0_COPY_PROTECT_H_O = 0x00000204
INFO0_WRITE_PROTECT_SBL_L_O = 0x000009f8
INFO0_WRITE_PROTECT_SBL_H_O = 0x000009fc
INFO0_COPY_PROTECT_SBL_L_O = 0x00000A00
INFO0_COPY_PROTECT_SBL_H_O = 0x00000A04
INFO0_MAIN_PTR1_O = 0x00000C00
INFO0_MAIN_PTR2_O = 0x00000C04
INFO0_KREVTRACK_O = 0x00000C08
INFO0_AREVTRACK_O = 0x00000C0C
INFO0_MAIN_CNT0_O = 0x00000FF8
INFO0_MAIN_CNT1_O = 0x00000FFC
INFO0_CUST_KEK_W0_O = 0x00001800
INFO0_CUST_KEK_W1_O = 0x00001804
INFO0_CUST_KEK_W2_O = 0x00001808
INFO0_CUST_KEK_W3_O = 0x0000180c
INFO0_CUST_KEK_W4_O = 0x00001810
INFO0_CUST_KEK_W5_O = 0x00001814
INFO0_CUST_KEK_W6_O = 0x00001818
INFO0_CUST_KEK_W7_O = 0x0000181c
INFO0_CUST_KEK_W8_O = 0x00001820
INFO0_CUST_KEK_W9_O = 0x00001824
INFO0_CUST_KEK_W10_O = 0x00001828
INFO0_CUST_KEK_W11_O = 0x0000182c
INFO0_CUST_KEK_W12_O = 0x00001830
INFO0_CUST_KEK_W13_O = 0x00001834
INFO0_CUST_KEK_W14_O = 0x00001838
INFO0_CUST_KEK_W15_O = 0x0000183c
INFO0_CUST_KEK_W16_O = 0x00001840
INFO0_CUST_KEK_W17_O = 0x00001844
INFO0_CUST_KEK_W18_O = 0x00001848
INFO0_CUST_KEK_W19_O = 0x0000184c
INFO0_CUST_KEK_W20_O = 0x00001850
INFO0_CUST_KEK_W21_O = 0x00001854
INFO0_CUST_KEK_W22_O = 0x00001858
INFO0_CUST_KEK_W23_O = 0x0000185c
INFO0_CUST_KEK_W24_O = 0x00001860
INFO0_CUST_KEK_W25_O = 0x00001864
INFO0_CUST_KEK_W26_O = 0x00001868
INFO0_CUST_KEK_W27_O = 0x0000186c
INFO0_CUST_KEK_W28_O = 0x00001870
INFO0_CUST_KEK_W29_O = 0x00001874
INFO0_CUST_KEK_W30_O = 0x00001878
INFO0_CUST_KEK_W31_O = 0x0000187c
INFO0_CUST_AUTH_W0_O = 0x00001880
INFO0_CUST_AUTH_W1_O = 0x00001884
INFO0_CUST_AUTH_W2_O = 0x00001888
INFO0_CUST_AUTH_W3_O = 0x0000188c
INFO0_CUST_AUTH_W4_O = 0x00001890
INFO0_CUST_AUTH_W5_O = 0x00001894
INFO0_CUST_AUTH_W6_O = 0x00001898
INFO0_CUST_AUTH_W7_O = 0x0000189c
INFO0_CUST_AUTH_W8_O = 0x000018a0
INFO0_CUST_AUTH_W9_O = 0x000018a4
INFO0_CUST_AUTH_W10_O = 0x000018a8
INFO0_CUST_AUTH_W11_O = 0x000018ac
INFO0_CUST_AUTH_W12_O = 0x000018b0
INFO0_CUST_AUTH_W13_O = 0x000018b4
INFO0_CUST_AUTH_W14_O = 0x000018b8
INFO0_CUST_AUTH_W15_O = 0x000018bc
INFO0_CUST_AUTH_W16_O = 0x000018c0
INFO0_CUST_AUTH_W17_O = 0x000018c4
INFO0_CUST_AUTH_W18_O = 0x000018c8
INFO0_CUST_AUTH_W19_O = 0x000018cc
INFO0_CUST_AUTH_W20_O = 0x000018d0
INFO0_CUST_AUTH_W21_O = 0x000018d4
INFO0_CUST_AUTH_W22_O = 0x000018d8
INFO0_CUST_AUTH_W23_O = 0x000018dc
INFO0_CUST_AUTH_W24_O = 0x000018e0
INFO0_CUST_AUTH_W25_O = 0x000018e4
INFO0_CUST_AUTH_W26_O = 0x000018e8
INFO0_CUST_AUTH_W27_O = 0x000018ec
INFO0_CUST_AUTH_W28_O = 0x000018f0
INFO0_CUST_AUTH_W29_O = 0x000018f4
INFO0_CUST_AUTH_W30_O = 0x000018f8
INFO0_CUST_AUTH_W31_O = 0x000018fc
INFO0_CUST_PUBKEY_W0_O = 0x00001900
INFO0_CUST_PUBKEY_W1_O = 0x00001904
INFO0_CUST_PUBKEY_W2_O = 0x00001908
INFO0_CUST_PUBKEY_W3_O = 0x0000190c
INFO0_CUST_PUBKEY_W4_O = 0x00001910
INFO0_CUST_PUBKEY_W5_O = 0x00001914
INFO0_CUST_PUBKEY_W6_O = 0x00001918
INFO0_CUST_PUBKEY_W7_O = 0x0000191c
INFO0_CUST_PUBKEY_W8_O = 0x00001920
INFO0_CUST_PUBKEY_W9_O = 0x00001924
INFO0_CUST_PUBKEY_W10_O = 0x00001928
INFO0_CUST_PUBKEY_W11_O = 0x0000192c
INFO0_CUST_PUBKEY_W12_O = 0x00001930
INFO0_CUST_PUBKEY_W13_O = 0x00001934
INFO0_CUST_PUBKEY_W14_O = 0x00001938
INFO0_CUST_PUBKEY_W15_O = 0x0000193c
INFO0_CUST_PUBKEY_W16_O = 0x00001940
INFO0_CUST_PUBKEY_W17_O = 0x00001944
INFO0_CUST_PUBKEY_W18_O = 0x00001948
INFO0_CUST_PUBKEY_W19_O = 0x0000194c
INFO0_CUST_PUBKEY_W20_O = 0x00001950
INFO0_CUST_PUBKEY_W21_O = 0x00001954
INFO0_CUST_PUBKEY_W22_O = 0x00001958
INFO0_CUST_PUBKEY_W23_O = 0x0000195c
INFO0_CUST_PUBKEY_W24_O = 0x00001960
INFO0_CUST_PUBKEY_W25_O = 0x00001964
INFO0_CUST_PUBKEY_W26_O = 0x00001968
INFO0_CUST_PUBKEY_W27_O = 0x0000196c
INFO0_CUST_PUBKEY_W28_O = 0x00001970
INFO0_CUST_PUBKEY_W29_O = 0x00001974
INFO0_CUST_PUBKEY_W30_O = 0x00001978
INFO0_CUST_PUBKEY_W31_O = 0x0000197c
INFO0_CUST_PUBKEY_W32_O = 0x00001980
INFO0_CUST_PUBKEY_W33_O = 0x00001984
INFO0_CUST_PUBKEY_W34_O = 0x00001988
INFO0_CUST_PUBKEY_W35_O = 0x0000198c
INFO0_CUST_PUBKEY_W36_O = 0x00001990
INFO0_CUST_PUBKEY_W37_O = 0x00001994
INFO0_CUST_PUBKEY_W38_O = 0x00001998
INFO0_CUST_PUBKEY_W39_O = 0x0000199c
INFO0_CUST_PUBKEY_W40_O = 0x000019a0
INFO0_CUST_PUBKEY_W41_O = 0x000019a4
INFO0_CUST_PUBKEY_W42_O = 0x000019a8
INFO0_CUST_PUBKEY_W43_O = 0x000019ac
INFO0_CUST_PUBKEY_W44_O = 0x000019b0
INFO0_CUST_PUBKEY_W45_O = 0x000019b4
INFO0_CUST_PUBKEY_W46_O = 0x000019b8
INFO0_CUST_PUBKEY_W47_O = 0x000019bc
INFO0_CUST_PUBKEY_W48_O = 0x000019c0
INFO0_CUST_PUBKEY_W49_O = 0x000019c4
INFO0_CUST_PUBKEY_W50_O = 0x000019c8
INFO0_CUST_PUBKEY_W51_O = 0x000019cc
INFO0_CUST_PUBKEY_W52_O = 0x000019d0
INFO0_CUST_PUBKEY_W53_O = 0x000019d4
INFO0_CUST_PUBKEY_W54_O = 0x000019d8
INFO0_CUST_PUBKEY_W55_O = 0x000019dc
INFO0_CUST_PUBKEY_W56_O = 0x000019e0
INFO0_CUST_PUBKEY_W57_O = 0x000019e4
INFO0_CUST_PUBKEY_W58_O = 0x000019e8
INFO0_CUST_PUBKEY_W59_O = 0x000019ec
INFO0_CUST_PUBKEY_W60_O = 0x000019f0
INFO0_CUST_PUBKEY_W61_O = 0x000019f4
INFO0_CUST_PUBKEY_W62_O = 0x000019f8
INFO0_CUST_PUBKEY_W63_O = 0x000019fc
INFO0_CUSTOMER_KEY0_O = 0x00001a00
INFO0_CUSTOMER_KEY1_O = 0x00001a04
INFO0_CUSTOMER_KEY2_O = 0x00001a08
INFO0_CUSTOMER_KEY3_O = 0x00001a0c
INFO0_CUST_PUBHASH_W0_O = 0x00001a10
INFO0_CUST_PUBHASH_W1_O = 0x00001a14
INFO0_CUST_PUBHASH_W2_O = 0x00001a18
INFO0_CUST_PUBHASH_W3_O = 0x00001a1c
@@ -0,0 +1,180 @@
#from am_defines import *
INFO0_SIGNATURE0_O = 0x00000000
INFO0_SIGNATURE1_O = 0x00000004
INFO0_SIGNATURE2_O = 0x00000008
INFO0_SIGNATURE3_O = 0x0000000c
INFO0_SECURITY_O = 0x00000010
INFO0_CUSTOMER_TRIM_O = 0x00000014
INFO0_CUSTOMER_TRIM2_O = 0x00000018
INFO0_SECURITY_OVR_O = 0x00000020
INFO0_SECURITY_WIRED_CFG_O = 0x00000024
INFO0_SECURITY_WIRED_IFC_CFG0_O = 0x00000028
INFO0_SECURITY_WIRED_IFC_CFG1_O = 0x0000002C
INFO0_SECURITY_WIRED_IFC_CFG2_O = 0x00000030
INFO0_SECURITY_WIRED_IFC_CFG3_O = 0x00000034
INFO0_SECURITY_WIRED_IFC_CFG4_O = 0x00000038
INFO0_SECURITY_WIRED_IFC_CFG5_O = 0x0000003C
INFO0_SECURITY_VERSION_O = 0x00000040
INFO0_SECURITY_SRAM_RESV_O = 0x00000050
AM_REG_INFO0_SECURITY_SRAM_RESV_SRAM_RESV_M = 0x0000FFFF
INFO0_WRITE_PROTECT0_O = 0x000001f0
INFO0_WRITE_PROTECT1_O = 0x000001f4
INFO0_WRITE_PROTECT2_O = 0x000001f8
INFO0_WRITE_PROTECT3_O = 0x000001fc
INFO0_COPY_PROTECT0_O = 0x00000200
INFO0_COPY_PROTECT1_O = 0x00000204
INFO0_COPY_PROTECT2_O = 0x00000208
INFO0_COPY_PROTECT3_O = 0x0000020C
INFO0_WRITE_PROTECT0_SBL_O = 0x000009f0
INFO0_WRITE_PROTECT1_SBL_O = 0x000009f4
INFO0_WRITE_PROTECT2_SBL_O = 0x000009f8
INFO0_WRITE_PROTECT3_SBL_O = 0x000009fc
INFO0_COPY_PROTECT0_SBL_O = 0x00000A00
INFO0_COPY_PROTECT1_SBL_O = 0x00000A04
INFO0_COPY_PROTECT2_SBL_O = 0x00000A08
INFO0_COPY_PROTECT3_SBL_O = 0x00000A0C
INFO0_MAIN_PTR1_O = 0x00000C00
INFO0_MAIN_PTR2_O = 0x00000C04
INFO0_KREVTRACK_O = 0x00000C08
INFO0_AREVTRACK_O = 0x00000C0C
INFO0_MAIN_CNT0_O = 0x00000FF8
INFO0_MAIN_CNT1_O = 0x00000FFC
INFO0_CUST_KEK_W0_O = 0x00001800
INFO0_CUST_KEK_W1_O = 0x00001804
INFO0_CUST_KEK_W2_O = 0x00001808
INFO0_CUST_KEK_W3_O = 0x0000180c
INFO0_CUST_KEK_W4_O = 0x00001810
INFO0_CUST_KEK_W5_O = 0x00001814
INFO0_CUST_KEK_W6_O = 0x00001818
INFO0_CUST_KEK_W7_O = 0x0000181c
INFO0_CUST_KEK_W8_O = 0x00001820
INFO0_CUST_KEK_W9_O = 0x00001824
INFO0_CUST_KEK_W10_O = 0x00001828
INFO0_CUST_KEK_W11_O = 0x0000182c
INFO0_CUST_KEK_W12_O = 0x00001830
INFO0_CUST_KEK_W13_O = 0x00001834
INFO0_CUST_KEK_W14_O = 0x00001838
INFO0_CUST_KEK_W15_O = 0x0000183c
INFO0_CUST_KEK_W16_O = 0x00001840
INFO0_CUST_KEK_W17_O = 0x00001844
INFO0_CUST_KEK_W18_O = 0x00001848
INFO0_CUST_KEK_W19_O = 0x0000184c
INFO0_CUST_KEK_W20_O = 0x00001850
INFO0_CUST_KEK_W21_O = 0x00001854
INFO0_CUST_KEK_W22_O = 0x00001858
INFO0_CUST_KEK_W23_O = 0x0000185c
INFO0_CUST_KEK_W24_O = 0x00001860
INFO0_CUST_KEK_W25_O = 0x00001864
INFO0_CUST_KEK_W26_O = 0x00001868
INFO0_CUST_KEK_W27_O = 0x0000186c
INFO0_CUST_KEK_W28_O = 0x00001870
INFO0_CUST_KEK_W29_O = 0x00001874
INFO0_CUST_KEK_W30_O = 0x00001878
INFO0_CUST_KEK_W31_O = 0x0000187c
INFO0_CUST_AUTH_W0_O = 0x00001880
INFO0_CUST_AUTH_W1_O = 0x00001884
INFO0_CUST_AUTH_W2_O = 0x00001888
INFO0_CUST_AUTH_W3_O = 0x0000188c
INFO0_CUST_AUTH_W4_O = 0x00001890
INFO0_CUST_AUTH_W5_O = 0x00001894
INFO0_CUST_AUTH_W6_O = 0x00001898
INFO0_CUST_AUTH_W7_O = 0x0000189c
INFO0_CUST_AUTH_W8_O = 0x000018a0
INFO0_CUST_AUTH_W9_O = 0x000018a4
INFO0_CUST_AUTH_W10_O = 0x000018a8
INFO0_CUST_AUTH_W11_O = 0x000018ac
INFO0_CUST_AUTH_W12_O = 0x000018b0
INFO0_CUST_AUTH_W13_O = 0x000018b4
INFO0_CUST_AUTH_W14_O = 0x000018b8
INFO0_CUST_AUTH_W15_O = 0x000018bc
INFO0_CUST_AUTH_W16_O = 0x000018c0
INFO0_CUST_AUTH_W17_O = 0x000018c4
INFO0_CUST_AUTH_W18_O = 0x000018c8
INFO0_CUST_AUTH_W19_O = 0x000018cc
INFO0_CUST_AUTH_W20_O = 0x000018d0
INFO0_CUST_AUTH_W21_O = 0x000018d4
INFO0_CUST_AUTH_W22_O = 0x000018d8
INFO0_CUST_AUTH_W23_O = 0x000018dc
INFO0_CUST_AUTH_W24_O = 0x000018e0
INFO0_CUST_AUTH_W25_O = 0x000018e4
INFO0_CUST_AUTH_W26_O = 0x000018e8
INFO0_CUST_AUTH_W27_O = 0x000018ec
INFO0_CUST_AUTH_W28_O = 0x000018f0
INFO0_CUST_AUTH_W29_O = 0x000018f4
INFO0_CUST_AUTH_W30_O = 0x000018f8
INFO0_CUST_AUTH_W31_O = 0x000018fc
INFO0_CUST_PUBKEY_W0_O = 0x00001900
INFO0_CUST_PUBKEY_W1_O = 0x00001904
INFO0_CUST_PUBKEY_W2_O = 0x00001908
INFO0_CUST_PUBKEY_W3_O = 0x0000190c
INFO0_CUST_PUBKEY_W4_O = 0x00001910
INFO0_CUST_PUBKEY_W5_O = 0x00001914
INFO0_CUST_PUBKEY_W6_O = 0x00001918
INFO0_CUST_PUBKEY_W7_O = 0x0000191c
INFO0_CUST_PUBKEY_W8_O = 0x00001920
INFO0_CUST_PUBKEY_W9_O = 0x00001924
INFO0_CUST_PUBKEY_W10_O = 0x00001928
INFO0_CUST_PUBKEY_W11_O = 0x0000192c
INFO0_CUST_PUBKEY_W12_O = 0x00001930
INFO0_CUST_PUBKEY_W13_O = 0x00001934
INFO0_CUST_PUBKEY_W14_O = 0x00001938
INFO0_CUST_PUBKEY_W15_O = 0x0000193c
INFO0_CUST_PUBKEY_W16_O = 0x00001940
INFO0_CUST_PUBKEY_W17_O = 0x00001944
INFO0_CUST_PUBKEY_W18_O = 0x00001948
INFO0_CUST_PUBKEY_W19_O = 0x0000194c
INFO0_CUST_PUBKEY_W20_O = 0x00001950
INFO0_CUST_PUBKEY_W21_O = 0x00001954
INFO0_CUST_PUBKEY_W22_O = 0x00001958
INFO0_CUST_PUBKEY_W23_O = 0x0000195c
INFO0_CUST_PUBKEY_W24_O = 0x00001960
INFO0_CUST_PUBKEY_W25_O = 0x00001964
INFO0_CUST_PUBKEY_W26_O = 0x00001968
INFO0_CUST_PUBKEY_W27_O = 0x0000196c
INFO0_CUST_PUBKEY_W28_O = 0x00001970
INFO0_CUST_PUBKEY_W29_O = 0x00001974
INFO0_CUST_PUBKEY_W30_O = 0x00001978
INFO0_CUST_PUBKEY_W31_O = 0x0000197c
INFO0_CUST_PUBKEY_W32_O = 0x00001980
INFO0_CUST_PUBKEY_W33_O = 0x00001984
INFO0_CUST_PUBKEY_W34_O = 0x00001988
INFO0_CUST_PUBKEY_W35_O = 0x0000198c
INFO0_CUST_PUBKEY_W36_O = 0x00001990
INFO0_CUST_PUBKEY_W37_O = 0x00001994
INFO0_CUST_PUBKEY_W38_O = 0x00001998
INFO0_CUST_PUBKEY_W39_O = 0x0000199c
INFO0_CUST_PUBKEY_W40_O = 0x000019a0
INFO0_CUST_PUBKEY_W41_O = 0x000019a4
INFO0_CUST_PUBKEY_W42_O = 0x000019a8
INFO0_CUST_PUBKEY_W43_O = 0x000019ac
INFO0_CUST_PUBKEY_W44_O = 0x000019b0
INFO0_CUST_PUBKEY_W45_O = 0x000019b4
INFO0_CUST_PUBKEY_W46_O = 0x000019b8
INFO0_CUST_PUBKEY_W47_O = 0x000019bc
INFO0_CUST_PUBKEY_W48_O = 0x000019c0
INFO0_CUST_PUBKEY_W49_O = 0x000019c4
INFO0_CUST_PUBKEY_W50_O = 0x000019c8
INFO0_CUST_PUBKEY_W51_O = 0x000019cc
INFO0_CUST_PUBKEY_W52_O = 0x000019d0
INFO0_CUST_PUBKEY_W53_O = 0x000019d4
INFO0_CUST_PUBKEY_W54_O = 0x000019d8
INFO0_CUST_PUBKEY_W55_O = 0x000019dc
INFO0_CUST_PUBKEY_W56_O = 0x000019e0
INFO0_CUST_PUBKEY_W57_O = 0x000019e4
INFO0_CUST_PUBKEY_W58_O = 0x000019e8
INFO0_CUST_PUBKEY_W59_O = 0x000019ec
INFO0_CUST_PUBKEY_W60_O = 0x000019f0
INFO0_CUST_PUBKEY_W61_O = 0x000019f4
INFO0_CUST_PUBKEY_W62_O = 0x000019f8
INFO0_CUST_PUBKEY_W63_O = 0x000019fc
INFO0_CUSTOMER_KEY0_O = 0x00001a00
INFO0_CUSTOMER_KEY1_O = 0x00001a04
INFO0_CUSTOMER_KEY2_O = 0x00001a08
INFO0_CUSTOMER_KEY3_O = 0x00001a0c
INFO0_CUST_PUBHASH_W0_O = 0x00001a10
INFO0_CUST_PUBHASH_W1_O = 0x00001a14
INFO0_CUST_PUBHASH_W2_O = 0x00001a18
INFO0_CUST_PUBHASH_W3_O = 0x00001a1c
@@ -0,0 +1,299 @@
#!/usr/bin/env python3
# Utility to create image blobs for Corvette Secure Boot
import argparse
import sys
from Crypto.Cipher import AES
import array
import hashlib
import hmac
import os
import binascii
import importlib
from am_defines import *
#from keys_info import keyTblAes, keyTblHmac, minAesKeyIdx, maxAesKeyIdx, minHmacKeyIdx, maxHmacKeyIdx, INFO_KEY
#******************************************************************************
#
# Generate the image blob as per command line parameters
#
#******************************************************************************
def process(loadaddress, appFile, magicNum, crcI, crcB, authI, authB, protection, authKeyIdx, output, encKeyIdx, version, erasePrev, child0, child1, authalgo, encalgo, keyFile):
app_binarray = bytearray()
# Open the file, and read it into an array of integers.
with appFile as f_app:
app_binarray.extend(f_app.read())
f_app.close()
filenames = keyFile.split('.')
keys = importlib.import_module(filenames[0])
encVal = 0
if (encalgo != 0):
encVal = 1
if ((encKeyIdx < keys.minAesKeyIdx) or (encKeyIdx > keys.maxAesKeyIdx)):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
if (encalgo == 2):
if (encKeyIdx & 0x1):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
keySize = 32
else:
keySize = 16
if (authalgo != 0):
if ((authKeyIdx < keys.minHmacKeyIdx) or (authKeyIdx > keys.maxHmacKeyIdx) or (authKeyIdx & 0x1)):
am_print("Invalid authKey Idx ", authKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
if (magicNum == AM_IMAGE_MAGIC_MAIN):
hdr_length = AM_IMAGEHDR_SIZE_MAIN; #fixed header length
elif ((magicNum == AM_IMAGE_MAGIC_CHILD) or (magicNum == AM_IMAGE_MAGIC_CUSTPATCH) or (magicNum == AM_IMAGE_MAGIC_NONSECURE) or (magicNum == AM_IMAGE_MAGIC_INFO0)):
hdr_length = AM_IMAGEHDR_SIZE_AUX; #fixed header length
else:
am_print("magic number", hex(magicNum), " not supported", level=AM_PRINT_LEVEL_ERROR)
return
am_print("Header Size = ", hex(hdr_length))
#generate mutable byte array for the header
hdr_binarray = bytearray([0x00]*hdr_length);
orig_app_length = (len(app_binarray))
am_print("original app_size ",hex(orig_app_length), "(",orig_app_length,")")
am_print("load_address ",hex(loadaddress), "(",loadaddress,")")
if (loadaddress & 0x3):
am_print("load address needs to be word aligned", level=AM_PRINT_LEVEL_ERROR)
return
if (loadaddress & (FLASH_PAGE_SIZE - 1)):
am_print("WARNING!!! - load address is not page aligned", level=AM_PRINT_LEVEL_ERROR)
if (magicNum == AM_IMAGE_MAGIC_INFO0):
if (orig_app_length & 0x3):
am_print("INFO0 blob length needs to be multiple of 4", level=AM_PRINT_LEVEL_ERROR)
return
if ((loadaddress + orig_app_length) > INFO_SIZE_BYTES):
am_print("INFO0 Offset and length exceed size", level=AM_PRINT_LEVEL_ERROR)
return
if (encVal == 1):
block_size = AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES
app_binarray = pad_to_block_size(app_binarray, block_size, 1)
else:
# Add Padding
app_binarray = pad_to_block_size(app_binarray, 4, 0)
app_length = (len(app_binarray))
am_print("app_size ",hex(app_length), "(",app_length,")")
# Create Image blobs
# w0
blobLen = hdr_length + app_length
w0 = (magicNum << 24) | ((encVal & 0x1) << 23) | blobLen
am_print("w0 =", hex(w0))
fill_word(hdr_binarray, 0, w0)
# w2
securityVal = ((authI << 1) | crcI) << 4 | (authB << 1) | crcB
am_print("Security Value ", hex(securityVal))
w2 = ((securityVal << 24) & 0xff000000) | ((authalgo) & 0xf) | ((authKeyIdx << 4) & 0xf0) | ((encalgo << 8) & 0xf00) | ((encKeyIdx << 12) & 0xf000)
fill_word(hdr_binarray, 8, w2)
am_print("w2 = ",hex(w2))
if (magicNum == AM_IMAGE_MAGIC_INFO0):
# Insert the INFO0 size and offset
addrWord = ((orig_app_length>>2) << 16) | ((loadaddress>>2) & 0xFFFF)
versionKeyWord = keys.INFO_KEY
else:
# Insert the application binary load address.
addrWord = loadaddress | (protection & 0x3)
# Initialize versionKeyWord
versionKeyWord = (version & 0x7FFF) | ((erasePrev & 0x1) << 15)
am_print("addrWord = ",hex(addrWord))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_ADDR, addrWord)
am_print("versionKeyWord = ",hex(versionKeyWord))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_VERKEY, versionKeyWord)
# Initialize child (Child Ptr/ Feature key)
am_print("child0/feature = ",hex(child0))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_CHILDPTR, child0)
am_print("child1 = ",hex(child1))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_CHILDPTR + 4, child1)
authKeyIdx = authKeyIdx - keys.minHmacKeyIdx
if (authB != 0): # Authentication needed
am_print("Boot Authentication Enabled")
# am_print("Key used for HMAC")
# am_print([hex(keys.keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, AM_HMAC_SIG_SIZE)])
# Initialize the clear image HMAC
sigClr = compute_hmac(keys.keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES:(authKeyIdx*AM_SECBOOT_KEYIDX_BYTES+AM_HMAC_SIG_SIZE)], (hdr_binarray[AM_IMAGEHDR_START_HMAC:hdr_length] + app_binarray))
am_print("HMAC Clear")
am_print([hex(n) for n in sigClr])
# Fill up the HMAC
for x in range(0, AM_HMAC_SIG_SIZE):
hdr_binarray[AM_IMAGEHDR_OFFSET_SIGCLR + x] = sigClr[x]
# All the header fields part of the encryption are now final
if (encVal == 1):
am_print("Encryption Enabled")
encKeyIdx = encKeyIdx - keys.minAesKeyIdx
ivValAes = os.urandom(AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES)
am_print("Initialization Vector")
am_print([hex(ivValAes[n]) for n in range (0, AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES)])
keyAes = os.urandom(keySize)
am_print("AES Key used for encryption")
am_print([hex(keyAes[n]) for n in range (0, keySize)])
# Encrypted Part
am_print("Encrypting blob of size " , (hdr_length - AM_IMAGEHDR_START_ENCRYPT + app_length))
enc_binarray = encrypt_app_aes((hdr_binarray[AM_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray), keyAes, ivValAes)
# am_print("Key used for encrypting AES Key")
# am_print([hex(keys.keyTblAes[encKeyIdx*keySize + n]) for n in range (0, keySize)])
# Encrypted Key
enc_key = encrypt_app_aes(keyAes, keys.keyTblAes[encKeyIdx*keySize:encKeyIdx*keySize + keySize], ivVal0)
am_print("Encrypted Key")
am_print([hex(enc_key[n]) for n in range (0, keySize)])
# Fill up the IV
for x in range(0, AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES):
hdr_binarray[AM_IMAGEHDR_OFFSET_IV + x] = ivValAes[x]
# Fill up the Encrypted Key
for x in range(0, keySize):
hdr_binarray[AM_IMAGEHDR_OFFSET_KEK + x] = enc_key[x]
else:
enc_binarray = hdr_binarray[AM_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray
if (authI != 0): # Install Authentication needed
am_print("Install Authentication Enabled")
# am_print("Key used for HMAC")
# am_print([hex(keys.keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, AM_HMAC_SIG_SIZE)])
# Initialize the top level HMAC
sig = compute_hmac(keys.keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES:(authKeyIdx*AM_SECBOOT_KEYIDX_BYTES+AM_HMAC_SIG_SIZE)], (hdr_binarray[AM_IMAGEHDR_START_HMAC_INST:AM_IMAGEHDR_START_ENCRYPT] + enc_binarray))
am_print("Generated Signature")
am_print([hex(n) for n in sig])
# Fill up the HMAC
for x in range(0, AM_HMAC_SIG_SIZE):
hdr_binarray[AM_IMAGEHDR_OFFSET_SIG + x] = sig[x]
# compute the CRC for the blob - this is done on a clear image
crc = crc32(hdr_binarray[AM_IMAGEHDR_START_CRC:hdr_length] + app_binarray)
am_print("crc = ",hex(crc));
w1 = crc
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_CRC, w1)
# now output all three binary arrays in the proper order
output = output + '.bin'
am_print("Writing to file ", output)
with open(output, mode = 'wb') as out:
out.write(hdr_binarray[0:AM_IMAGEHDR_START_ENCRYPT])
out.write(enc_binarray)
def parse_arguments():
parser = argparse.ArgumentParser(description =
'Generate Corvette Image Blob')
parser.add_argument('--bin', dest='appFile', type=argparse.FileType('rb'),
help='binary file (blah.bin)')
parser.add_argument('--load-address', dest='loadaddress', type=auto_int, default=hex(AM_SECBOOT_DEFAULT_NONSECURE_MAIN),
help='Load address of the binary.')
parser.add_argument('--magic-num', dest='magic_num', default=hex(AM_IMAGE_MAGIC_NONSECURE),
type=lambda x: x.lower(),
# type = str.lower,
choices = [
hex(AM_IMAGE_MAGIC_MAIN),
hex(AM_IMAGE_MAGIC_CHILD),
hex(AM_IMAGE_MAGIC_CUSTPATCH),
hex(AM_IMAGE_MAGIC_NONSECURE),
hex(AM_IMAGE_MAGIC_INFO0)
],
help = 'Magic Num ('
+ str(hex(AM_IMAGE_MAGIC_MAIN)) + ': Main, '
+ str(hex(AM_IMAGE_MAGIC_CHILD)) + ': Child, '
+ str(hex(AM_IMAGE_MAGIC_CUSTPATCH)) + ': CustOTA, '
+ str(hex(AM_IMAGE_MAGIC_NONSECURE)) + ': NonSecure, '
+ str(hex(AM_IMAGE_MAGIC_INFO0)) + ': Info0) '
'- default[Main]'
)
parser.add_argument('-o', dest = 'output', default='outimage',
help = 'Output filename (without the extension)')
parser.add_argument('--authkey', dest = 'authkey', type=auto_int, default=(AM_SECBOOT_MIN_KEYIDX_INFO0), choices = range(AM_SECBOOT_MIN_KEYIDX_INFO0, AM_SECBOOT_MAX_KEYIDX_INFO0 + 1),
help = 'Authentication Key Idx? (' + str(AM_SECBOOT_MIN_KEYIDX_INFO0) + ' to ' + str(AM_SECBOOT_MAX_KEYIDX_INFO0) + ')')
parser.add_argument('--kek', dest = 'kek', type=auto_int, default=(AM_SECBOOT_MIN_KEYIDX_INFO0), choices = range(AM_SECBOOT_MIN_KEYIDX_INFO0, AM_SECBOOT_MAX_KEYIDX_INFO0 + 1),
help = 'KEK Index? (' + str(AM_SECBOOT_MIN_KEYIDX_INFO0) + ' to ' + str(AM_SECBOOT_MAX_KEYIDX_INFO0) + ')')
parser.add_argument('--authalgo', dest = 'authalgo', type=auto_int, default=0, choices=range(0, AM_SECBOOT_AUTH_ALGO_MAX+1),
help = helpAuthAlgo)
parser.add_argument('--encalgo', dest = 'encalgo', type=auto_int, default=0, choices = range(0, AM_SECBOOT_ENC_ALGO_MAX+1),
help = helpEncAlgo)
parser.add_argument('--child0', dest = 'child0', type=auto_int, default=hex(0xFFFFFFFF),
help = 'child (blobPtr#0 for Main / feature key for AM3P)')
parser.add_argument('--child1', dest = 'child1', type=auto_int, default=hex(0xFFFFFFFF),
help = 'child (blobPtr#1 for Main)')
parser.add_argument('--version', dest = 'version', type=auto_int, default=0,
help = 'version (15 bit)')
parser.add_argument('--crcI', dest = 'crcI', type=auto_int, default=1, choices=[0,1],
help = 'Install CRC check enabled (Default = Y)?')
parser.add_argument('--crcB', dest = 'crcB', type=auto_int, default=0, choices=[0,1],
help = 'Boot CRC check enabled (Default = N)?')
parser.add_argument('--authI', dest = 'authI', type=auto_int, default=0, choices=[0,1],
help = 'Install Authentication check enabled (Default = N)?')
parser.add_argument('--authB', dest = 'authB', type=auto_int, default=0, choices=[0,1],
help = 'Boot Authentication check enabled (Default = N)?')
parser.add_argument('--erasePrev', dest = 'erasePrev', type=auto_int, default=0, choices=[0,1],
help = 'erasePrev (Valid only for main)')
parser.add_argument('-p', dest = 'protection', type=auto_int, default=0, choices = [0x0, 0x1, 0x2, 0x3],
help = 'protection info 2 bit C W')
parser.add_argument('-k', type=str, dest='keyFile', nargs='?', default='keys_info.py',
help='key file in specified format [default = keys_info.py]')
parser.add_argument('--loglevel', dest='loglevel', type=auto_int, default=AM_PRINT_LEVEL_INFO,
choices = range(AM_PRINT_LEVEL_MIN, AM_PRINT_LEVEL_MAX+1),
help=helpPrintLevel)
args = parser.parse_args()
args.magic_num = int(args.magic_num, 16)
return args
#******************************************************************************
#
# Main function.
#
#******************************************************************************
def main():
# Read the arguments.
args = parse_arguments()
am_set_print_level(args.loglevel)
process(args.loadaddress, args.appFile, args.magic_num, args.crcI, args.crcB, args.authI, args.authB, args.protection, args.authkey, args.output, args.kek, args.version, args.erasePrev, args.child0, args.child1, args.authalgo, args.encalgo, args.keyFile)
if __name__ == '__main__':
main()
@@ -0,0 +1,241 @@
#!/usr/bin/env python3
# Utility to generate image blobs for Corvette Bootloader assisted Wired updates
import argparse
import sys
from Crypto.Cipher import AES
import array
import hashlib
import hmac
import os
import binascii
import importlib
from am_defines import *
#from keys_info import keyTblAes, keyTblHmac, minAesKeyIdx, maxAesKeyIdx, minHmacKeyIdx, maxHmacKeyIdx , INFO_KEY, FLASH_KEY
#******************************************************************************
#
# Generate the image blob as per command line parameters
#
#******************************************************************************
def process(appFile, imagetype, loadaddress, authalgo, encalgo, authKeyIdx, encKeyIdx, optionsVal, maxSize, output, keyFile):
app_binarray = bytearray()
# Open the file, and read it into an array of integers.
with appFile as f_app:
app_binarray.extend(f_app.read())
f_app.close()
# Make sure it is page multiple
if ((maxSize & (FLASH_PAGE_SIZE - 1)) != 0):
am_print ("split needs to be multiple of flash page size", level=AM_PRINT_LEVEL_ERROR)
return
filenames = keyFile.split('.')
keys = importlib.import_module(filenames[0])
if (encalgo != 0):
if ((encKeyIdx < keys.minAesKeyIdx) or (encKeyIdx > keys.maxAesKeyIdx)):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR)
return
if (encalgo == 2):
if (encKeyIdx & 0x1):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
keySize = 32
else:
keySize = 16
if (authalgo != 0):
if ((authKeyIdx < keys.minHmacKeyIdx) or (authKeyIdx > keys.maxHmacKeyIdx) or (authKeyIdx & 0x1)):
am_print("Invalid authKey Idx ", authKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
hdr_length = AM_WU_IMAGEHDR_SIZE; #fixed header length
am_print("Header Size = ", hex(hdr_length))
orig_app_length = (len(app_binarray))
if (encalgo != 0):
block_size = keySize
app_binarray = pad_to_block_size(app_binarray, block_size, 1)
else:
# Add Padding
app_binarray = pad_to_block_size(app_binarray, 4, 0)
app_length = (len(app_binarray))
am_print("app_size ",hex(app_length), "(",app_length,")")
if (app_length + hdr_length > maxSize):
am_print("Image size bigger than max - Creating Split image")
start = 0
# now output all three binary arrays in the proper order
output = output + '.bin'
out = open(output, mode = 'wb')
while (start < app_length):
#generate mutable byte array for the header
hdr_binarray = bytearray([0x00]*hdr_length);
if (app_length - start > maxSize):
end = start + maxSize
else:
end = app_length
if (imagetype == AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA):
key = keys.INFO_KEY
# word offset
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_ADDR, loadaddress>>2)
else:
key = keys.FLASH_KEY
# load address
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_ADDR, loadaddress)
if (loadaddress & (FLASH_PAGE_SIZE - 1)):
am_print("WARNING!!! - load address is not page aligned", level=AM_PRINT_LEVEL_ERROR)
# Create imageType & options
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_IMAGETYPE] = imagetype
# Set the options only for the first block
if (start == 0):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_OPTIONS] = optionsVal
else:
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_OPTIONS] = 0
# Create Info0 Update Blob for wired update
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_KEY, key)
# update size
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_SIZE, end-start)
w0 = ((authalgo & 0xf) | ((authKeyIdx << 8) & 0xf00) | ((encalgo << 16) & 0xf0000) | ((encKeyIdx << 24) & 0x0f000000))
fill_word(hdr_binarray, 0, w0)
if (encalgo != 0):
keyIdx = encKeyIdx - keys.minAesKeyIdx
ivValAes = os.urandom(AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES)
am_print("Initialization Vector")
am_print([hex(n) for n in ivValAes])
keyAes = os.urandom(keySize)
am_print("AES Key used for encryption")
am_print([hex(keyAes[n]) for n in range (0, keySize)])
# Encrypted Part - after security header
enc_binarray = encrypt_app_aes((hdr_binarray[AM_WU_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray[start:end]), keyAes, ivValAes)
# am_print("Key used for encrypting AES Key")
# am_print([hex(keys.keyTblAes[keyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, keySize)])
# Encrypted Key
enc_key = encrypt_app_aes(keyAes, keys.keyTblAes[keyIdx*AM_SECBOOT_KEYIDX_BYTES:(keyIdx*AM_SECBOOT_KEYIDX_BYTES + keySize)], ivVal0)
am_print("Encrypted Key")
am_print([hex(enc_key[n]) for n in range (0, keySize)])
# Fill up the IV
for x in range(0, AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_IV + x] = ivValAes[x]
# Fill up the Encrypted Key
for x in range(0, keySize):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_KEK + x] = enc_key[x]
else:
enc_binarray = hdr_binarray[AM_WU_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray[start:end]
if (authalgo != 0): # Authentication needed
keyIdx = authKeyIdx - keys.minHmacKeyIdx
# am_print("Key used for HMAC")
# am_print([hex(keys.keyTblHmac[keyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, AM_HMAC_SIG_SIZE)])
# Initialize the HMAC - Sign is computed on image following the signature
sig = compute_hmac(keys.keyTblHmac[keyIdx*AM_SECBOOT_KEYIDX_BYTES:(keyIdx*AM_SECBOOT_KEYIDX_BYTES+AM_HMAC_SIG_SIZE)], hdr_binarray[AM_WU_IMAGEHDR_START_HMAC:AM_WU_IMAGEHDR_START_ENCRYPT] + enc_binarray)
am_print("HMAC")
am_print([hex(n) for n in sig])
# Fill up the HMAC
for x in range(0, AM_HMAC_SIG_SIZE):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_SIG + x] = sig[x]
am_print("Writing to file ", output)
am_print("Image from ", str(hex(start)), " to ", str(hex(end)), " will be loaded at", str(hex(loadaddress)))
out.write(hdr_binarray[0:AM_WU_IMAGEHDR_START_ENCRYPT])
out.write(enc_binarray)
# Reset start for next chunk
start = end
loadaddress = loadaddress + maxSize
def parse_arguments():
parser = argparse.ArgumentParser(description =
'Generate Corvette Wired Update Blob')
parser.add_argument('--load-address', dest='loadaddress', type=auto_int, default=hex(0x60000),
help='Load address of the binary - Where in flash the blob will be stored (could be different than install address of binary within).')
parser.add_argument('--bin', dest='appFile', type=argparse.FileType('rb'),
help='binary file (blah.bin)')
parser.add_argument('-i', dest = 'imagetype', default=AM_SECBOOT_WIRED_IMAGETYPE_MAIN, type=int,
choices = [
(AM_SECBOOT_WIRED_IMAGETYPE_SBL),
(AM_SECBOOT_WIRED_IMAGETYPE_AM3P),
(AM_SECBOOT_WIRED_IMAGETYPE_PATCH),
(AM_SECBOOT_WIRED_IMAGETYPE_MAIN),
(AM_SECBOOT_WIRED_IMAGETYPE_CHILD),
(AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH),
(AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE),
(AM_SECBOOT_WIRED_IMAGETYPE_INFO0),
(AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA)
],
help = 'ImageType ('
+ str(AM_SECBOOT_WIRED_IMAGETYPE_SBL) + ': SBL, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_AM3P) + ': AM3P, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_PATCH) + ': Patch, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_MAIN) + ': Main, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_CHILD) + ': Child, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH) + ': CustOTA, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE) + ': NonSecure, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INFO0) + ': Info0, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA) + ': Info0-NoOTA) '
'- default[Main]')
parser.add_argument('--options', dest = 'options', type=auto_int, default=0x1,
help = 'Options (16b hex value) - bit0 instructs to perform OTA of the image after wired download (set to 0 if only downloading & skipping OTA flow)')
parser.add_argument('-o', dest = 'output', default='wuimage',
help = 'Output filename (without the extension)')
parser.add_argument('--authkey', dest = 'authkey', type=auto_int, default=(AM_SECBOOT_MIN_KEYIDX_INFO0), choices = range(AM_SECBOOT_MIN_KEYIDX_INFO0, AM_SECBOOT_MAX_KEYIDX_INFO0 + 1),
help = 'Authentication Key Idx? (' + str(AM_SECBOOT_MIN_KEYIDX_INFO0) + ' to ' + str(AM_SECBOOT_MAX_KEYIDX_INFO0) + ')')
parser.add_argument('--kek', dest = 'kek', type=auto_int, default=(AM_SECBOOT_MIN_KEYIDX_INFO0), choices = range(AM_SECBOOT_MIN_KEYIDX_INFO0, AM_SECBOOT_MAX_KEYIDX_INFO0 + 1),
help = 'KEK Index? (' + str(AM_SECBOOT_MIN_KEYIDX_INFO0) + ' to ' + str(AM_SECBOOT_MAX_KEYIDX_INFO0) + ')')
parser.add_argument('--authalgo', dest = 'authalgo', type=auto_int, default=0, choices=range(0, AM_SECBOOT_AUTH_ALGO_MAX+1),
help = helpAuthAlgo)
parser.add_argument('--encalgo', dest = 'encalgo', type=auto_int, default=0, choices = range(0, AM_SECBOOT_ENC_ALGO_MAX+1),
help = helpEncAlgo)
parser.add_argument('--split', dest='split', type=auto_int, default=hex(MAX_DOWNLOAD_SIZE),
help='Specify the max block size if the image will be downloaded in pieces')
parser.add_argument('-k', type=str, dest='keyFile', nargs='?', default='keys_info.py',
help='key file in specified format [default = keys_info.py]')
parser.add_argument('--loglevel', dest='loglevel', type=auto_int, default=AM_PRINT_LEVEL_INFO,
choices = range(AM_PRINT_LEVEL_MIN, AM_PRINT_LEVEL_MAX+1),
help=helpPrintLevel)
args = parser.parse_args()
return args
#******************************************************************************
#
# Main function.
#
#******************************************************************************
def main():
# Read the arguments.
args = parse_arguments()
am_set_print_level(args.loglevel)
process(args.appFile, args.imagetype, args.loadaddress, args.authalgo, args.encalgo, args.authkey, args.kek, args.options, args.split, args.output, args.keyFile)
if __name__ == '__main__':
main()
@@ -0,0 +1,409 @@
#!/usr/bin/env python3
# Utility to create info0 for Apollo3
import argparse
import sys
from Crypto.Cipher import AES
import array
import hashlib
import hmac
import os
import binascii
import importlib
from am_defines import *
#from keys_info import keyTblAes, keyTblHmac, custKey
def copy_keys(binarray, offset, key, size):
for i in range (0, size):
binarray[offset + i] = key[i]
#******************************************************************************
#
# Generate the info0 blob as per command line parameters
#
#******************************************************************************
def process(valid, version, output, mainPtr, secPol, keyWrap, secBoot, secBootOnRst, plOnExit, sDbg, bEnErase, infoProg, bNoSramWipe, bSwoCtrl, bDbgAllowed, custTrim, custTrim2, overrideGpio, overridePol, wiredIfMask, wiredSlvInt, wiredI2cAddr, wiredTimeout, u0, u1, u2, u3, u4, u5, krev, arev, chipId0, chipId1, sresv, wprot0, wprot1, rprot0, rprot1, swprot0, swprot1, srprot0, srprot1, wprot2, wprot3, rprot2, rprot3, swprot2, swprot3, srprot2, srprot3, chip, keyFile):
if (chip == 'apollo3'):
import apollo3_info0 as info0
am_print("Apollo3 INFO0")
elif (chip == 'apollo3p'):
import apollo3p_info0 as info0
am_print("Apollo3P INFO0")
filenames = keyFile.split('.')
keys = importlib.import_module(filenames[0])
#generate mutable byte array for the header
hdr_binarray = bytearray([0xFF]*INFO_SIZE_BYTES);
# initialize signature
if (valid == 1):
fill_word(hdr_binarray, info0.INFO0_SIGNATURE0_O, AM_SECBOOT_INFO0_SIGN_PROGRAMMED0)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE1_O, AM_SECBOOT_INFO0_SIGN_PROGRAMMED1)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE2_O, AM_SECBOOT_INFO0_SIGN_PROGRAMMED2)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE3_O, AM_SECBOOT_INFO0_SIGN_PROGRAMMED3)
elif (valid == 0):
fill_word(hdr_binarray, info0.INFO0_SIGNATURE0_O, AM_SECBOOT_INFO0_SIGN_UINIT0)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE1_O, AM_SECBOOT_INFO0_SIGN_UINIT1)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE2_O, AM_SECBOOT_INFO0_SIGN_UINIT2)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE3_O, AM_SECBOOT_INFO0_SIGN_UINIT3)
else:
fill_word(hdr_binarray, info0.INFO0_SIGNATURE0_O, FLASH_INVALID)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE1_O, FLASH_INVALID)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE2_O, FLASH_INVALID)
fill_word(hdr_binarray, info0.INFO0_SIGNATURE3_O, FLASH_INVALID)
am_print("info0 Signature...")
am_print([hex(hdr_binarray[n]) for n in range(0, 16)])
# Flash wipe is no longer supported
bNoFlashWipe = 1
if (valid == 1):
# Build Security word
blAtReset = 1
if (secBoot == 0):
secBoot = 0x5
else:
secBoot = 0x2
if (secBootOnRst == 0):
secBootOnRst = 0x5
else:
secBootOnRst = 0x2
security = (((secPol & 0x7) << 24) | ((keyWrap & 0xf) << 20) | (secBootOnRst << 16) | (secBoot << 12) | ((plOnExit & 0x1) << 11) | ((sDbg & 0x1) << 10) | ((blAtReset & 0x1) << 9) | ((bEnErase & 0x1) << 8) | ((infoProg & 0xf) << 4) | ((bNoFlashWipe & 0x1) << 3) | ((bNoSramWipe & 0x1) << 2) | ((bSwoCtrl & 0x1) << 1) | ((bDbgAllowed & 0x1)))
am_print("Security Word = ", hex(security))
fill_word(hdr_binarray, info0.INFO0_SECURITY_O, security)
# Customer trim
am_print("Customer Trim = ", hex(custTrim))
fill_word(hdr_binarray, info0.INFO0_CUSTOMER_TRIM_O, custTrim)
am_print("Customer Trim2 = ", hex(custTrim2))
fill_word(hdr_binarray, info0.INFO0_CUSTOMER_TRIM2_O, custTrim2)
# Override
override = ((overridePol & 0x1) << 7) | (overrideGpio & 0x7f)
am_print("Override = ", hex(override))
fill_word(hdr_binarray, info0.INFO0_SECURITY_OVR_O, override)
# Wired interface config
wired = ((wiredIfMask & 0x7) | ((wiredSlvInt & 0x3f) << 3) | ((wiredI2cAddr & 0x7f) << 9) | ((wiredTimeout & 0xffff) << 16))
am_print("WiredCfg = ", hex(wired))
fill_word(hdr_binarray, info0.INFO0_SECURITY_WIRED_CFG_O, wired)
# Wired UART cfg
if (wiredIfMask & 0x1): # UART
am_print("UART Config ", hex(u0), hex(u1), hex(u2), hex(u3), hex(u4), hex(u5))
fill_word(hdr_binarray, info0.INFO0_SECURITY_WIRED_IFC_CFG0_O, u0)
fill_word(hdr_binarray, info0.INFO0_SECURITY_WIRED_IFC_CFG1_O, u1)
fill_word(hdr_binarray, info0.INFO0_SECURITY_WIRED_IFC_CFG2_O, u2)
fill_word(hdr_binarray, info0.INFO0_SECURITY_WIRED_IFC_CFG3_O, u3)
fill_word(hdr_binarray, info0.INFO0_SECURITY_WIRED_IFC_CFG4_O, u4)
fill_word(hdr_binarray, info0.INFO0_SECURITY_WIRED_IFC_CFG5_O, u5)
# version
am_print("Version = ", hex(version))
fill_word(hdr_binarray, info0.INFO0_SECURITY_VERSION_O, version)
# main ptr
am_print("Main Ptr = ", hex(mainPtr))
fill_word(hdr_binarray, info0.INFO0_MAIN_PTR1_O, mainPtr)
# SRAM Reservation
am_print("SRAM Reservation = ", hex(sresv))
fill_word(hdr_binarray, info0.INFO0_SECURITY_SRAM_RESV_O, sresv)
# Flash Protections
if (chip == 'apollo3'):
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT_L_O, wprot0)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT_H_O, wprot1)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT_L_O, rprot0)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT_H_O, rprot1)
am_print("Permanent Write Protections = ", hex(wprot0), ":", hex(wprot1))
am_print("Permanent Copy Protections = ", hex(rprot0), ":", hex(rprot1))
elif (chip == 'apollo3p'):
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT0_O, wprot0)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT1_O, wprot1)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT0_O, rprot0)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT1_O, rprot1)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT2_O, wprot2)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT3_O, wprot3)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT2_O, rprot2)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT3_O, rprot3)
am_print("Permanent Write Protections = ", hex(wprot0), ":", hex(wprot1), ":", hex(wprot2), ":", hex(wprot3))
am_print("Permanent Copy Protections = ", hex(rprot0), ":", hex(rprot1), ":", hex(rprot2), ":", hex(rprot3))
if (chip == 'apollo3'):
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT_SBL_L_O, swprot0)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT_SBL_H_O, swprot1)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT_SBL_L_O, srprot0)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT_SBL_H_O, srprot1)
am_print("SBL Overridable Write Protections = ", hex(swprot0), ":", hex(swprot1))
am_print("SBL Overridable Copy Protections = ", hex(srprot0), ":", hex(srprot1))
elif (chip == 'apollo3p'):
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT0_SBL_O, swprot0)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT1_SBL_O, swprot1)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT0_SBL_O, srprot0)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT1_SBL_O, srprot1)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT2_SBL_O, swprot2)
fill_word(hdr_binarray, info0.INFO0_WRITE_PROTECT3_SBL_O, swprot3)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT2_SBL_O, srprot2)
fill_word(hdr_binarray, info0.INFO0_COPY_PROTECT3_SBL_O, srprot3)
am_print("SBL Overridable Write Protections = ", hex(swprot0), ":", hex(swprot1), ":", hex(swprot2), ":", hex(swprot3))
am_print("SBL Overridable Copy Protections = ", hex(srprot0), ":", hex(srprot1), ":", hex(srprot2), ":", hex(srprot3))
# Customer Key
am_print("Customer Key")
am_print([hex(n) for n in keys.custKey])
copy_keys(hdr_binarray, info0.INFO0_CUSTOMER_KEY0_O, keys.custKey, 16)
# Keys
chipId = int_to_bytes(chipId0) + int_to_bytes(chipId1)
while (len(chipId) != AM_SECBOOT_KEYIDX_BYTES):
chipId = chipId + chipId
am_print("chipID 16")
am_print([hex(n) for n in chipId])
kekOffset = info0.INFO0_CUST_KEK_W0_O
authKeyOffset = info0.INFO0_CUST_AUTH_W0_O
if (keyWrap == 0): ## None
am_print("wrap mode 0")
am_print("KEK")
for i in range (0, INFO_MAX_ENC_KEYS):
am_print([hex(n) for n in keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]])
copy_keys(hdr_binarray, kekOffset + i*AM_SECBOOT_KEYIDX_BYTES, keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)], AM_SECBOOT_KEYIDX_BYTES)
am_print("AuthKey")
for i in range (0, INFO_MAX_AUTH_KEYS):
am_print([hex(n) for n in keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]])
copy_keys(hdr_binarray, authKeyOffset + i*AM_SECBOOT_KEYIDX_BYTES, keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)], AM_SECBOOT_KEYIDX_BYTES)
elif (keyWrap == 1): ## XOR
am_print("wrap mode 1")
am_print("KEK")
for i in range (0, INFO_MAX_ENC_KEYS):
scrambledKey = keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]
for j in range (0, AM_SECBOOT_KEYIDX_BYTES):
scrambledKey[j] = scrambledKey[j] ^ keys.custKey[j] ^ chipId[j]
am_print([hex(n) for n in scrambledKey])
copy_keys(hdr_binarray, kekOffset + i*AM_SECBOOT_KEYIDX_BYTES, scrambledKey, AM_SECBOOT_KEYIDX_BYTES)
am_print("AuthKey")
for i in range (0, INFO_MAX_AUTH_KEYS):
scrambledKey = keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]
for j in range (0, AM_SECBOOT_KEYIDX_BYTES):
scrambledKey[j] = scrambledKey[j] ^ keys.custKey[j] ^ chipId[j]
am_print([hex(n) for n in scrambledKey])
copy_keys(hdr_binarray, authKeyOffset + i*AM_SECBOOT_KEYIDX_BYTES, scrambledKey, AM_SECBOOT_KEYIDX_BYTES)
elif (keyWrap == 2): ## AES128
am_print("wrap mode 2")
am_print("KEK")
for i in range (0, INFO_MAX_ENC_KEYS):
scrambledKey = encrypt_app_aes(keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)], keys.custKey, chipId)
am_print([hex(n) for n in scrambledKey])
copy_keys(hdr_binarray, kekOffset + i*AM_SECBOOT_KEYIDX_BYTES, scrambledKey, AM_SECBOOT_KEYIDX_BYTES)
am_print("AuthKey")
for i in range (0, INFO_MAX_AUTH_KEYS):
scrambledKey = encrypt_app_aes(keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)], keys.custKey, chipId)
am_print([hex(n) for n in scrambledKey])
copy_keys(hdr_binarray, authKeyOffset + i*AM_SECBOOT_KEYIDX_BYTES, scrambledKey, AM_SECBOOT_KEYIDX_BYTES)
else:
am_print("Unknown wrap mode")
# Revocation Masks
am_print("KREV Mask = ", hex(krev))
fill_word(hdr_binarray, info0.INFO0_KREVTRACK_O, krev)
am_print("AREV Mask = ", hex(arev))
fill_word(hdr_binarray, info0.INFO0_AREVTRACK_O, arev)
# now output all three binary arrays in the proper order
with open(output + '.bin', mode = 'wb') as out:
am_print("Writing to file ", output + '.bin')
out.write(hdr_binarray)
def parse_arguments():
parser = argparse.ArgumentParser(description =
'Generate Corvette Info0 Blob')
parser.add_argument('output',
help = 'Output filename (without the extension)')
parser.add_argument('--valid', dest = 'valid', type=auto_int, default=1, choices = [0,1,2],
help = 'INFO0 Valid 0 = Uninitialized, 1 = Valid, 2 = Invalid (Default = 1)?')
parser.add_argument('--version', dest = 'version', type=auto_int, default=0,
help = 'version (Default = 0)?')
parser.add_argument('--main', dest = 'mainPtr', type=auto_int, default=hex(AM_SECBOOT_DEFAULT_NONSECURE_MAIN),
help = 'Main Firmware location (Default = ' + str(hex(AM_SECBOOT_DEFAULT_NONSECURE_MAIN)) + ')?')
parser.add_argument('--secpol', dest = 'secPol', type=auto_int, default=hex(0x0), choices = [0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7],
help = 'Security Policy Bitmask (Default = 0)? (bit 0 = Auth, bit 1 = Enc, bit 2 = Version Rollback)')
parser.add_argument('--wrap', dest = 'keyWrap', type=auto_int, default=0, choices = [0,1,2],
help = 'KeyWrap Algo (Default = 0)? (0 = none, 1 = XOR, 2 = AES128)')
parser.add_argument('--sRst', dest = 'secBootOnRst', type=auto_int, default=0, choices = [0,1],
help = 'Secure Boot on Soft Reset (Default = 0) ?')
parser.add_argument('-s', dest = 'secBoot', type=auto_int, default=0, choices = [0,1],
help = 'Secure Boot (Default = 0) ?')
parser.add_argument('--pl', dest = 'plOnExit', type=auto_int, default=0, choices = [0,1],
help = 'Protection Lock Enabled (Default = 0) ?')
parser.add_argument('--sDbgAllowed', dest = 'sDbg', type=auto_int, default=1, choices = [0,1],
help = 'Debugger allowed during (optional) Secondary Bootloader (Default = 1) ?')
parser.add_argument('--erase', dest = 'bEnErase', type=auto_int, default=1, choices = [0,1],
help = 'Info0 Erase Allowed (Default = 1) ?')
parser.add_argument('--prog', dest = 'infoProg', type=auto_int, default=hex(0xf),
help = 'INFO0 Program allowed (1 bit per quadrant) (Default = 0xf) ?')
parser.add_argument('--snowipe', dest = 'bNoSramWipe', type=auto_int, default=1, choices = [0,1],
help = ' Do not wipe SRAM on debugger connection (Default = 1) ?')
parser.add_argument('--swo', dest = 'bSwoCtrl', type=auto_int, default=1, choices = [0,1],
help = 'debugger connection allowed (Default = 1) ?')
parser.add_argument('--dbgprot', dest = 'bDbgAllowed', type=auto_int, default=1, choices = [0,1],
help = 'Do not lock debugger (Default = 1) ?')
parser.add_argument('--trim', dest = 'custTrim', type=auto_int, default=hex(0xFFFFFFFF),
help = 'customer trim ?')
parser.add_argument('--trim2', dest = 'custTrim2', type=auto_int, default=hex(0xFFFFFFFF),
help = 'customer trim 2?')
parser.add_argument('--gpio', dest = 'overrideGpio', type=auto_int, default=hex(0x7f),
help = 'Override GPIO (7 bit - in hex) - 0x7f for disabled (Default = 0x7f)')
parser.add_argument('--gpiolvl', dest = 'overridePol', type=auto_int, default=0, choices = [0,1],
help = 'Override GPIO Polarity (0 = low, 1 = hi) (Default = 0)')
parser.add_argument('--wmask', dest = 'wiredIfMask', type=auto_int, default=0x1,
help = 'Wired interface mask (bit 0 = UART, bit 1 = SPI, bit 2 = I2C) (default = UART)')
parser.add_argument('--wSlInt', dest = 'wiredSlvInt', type=auto_int, default=4,
help = 'Wired IOS interface handshake pin (default = 4)')
parser.add_argument('--wI2c', dest = 'wiredI2cAddr', type=auto_int, default=hex(0x20),
help = 'Wired IOS interface I2C Address (default = 0x20)')
parser.add_argument('--wTO', dest = 'wiredTimeout', type=auto_int, default=20000,
help = 'Wired interface timeout in millisec (default = 20000)')
parser.add_argument('--u0', dest = 'u0', type=auto_int, default=hex(0xFFFFFFFF),
help = 'UART Config 0 (default = 0xFFFFFFFF)')
parser.add_argument('--u1', dest = 'u1', type=auto_int, default=hex(0xFFFFFFFF),
help = 'UART Config 1 (default = 0xFFFFFFFF)')
parser.add_argument('--u2', dest = 'u2', type=auto_int, default=hex(0xFFFFFFFF),
help = 'UART Config 2 (default = 0xFFFFFFFF)')
parser.add_argument('--u3', dest = 'u3', type=auto_int, default=hex(0xFFFFFFFF),
help = 'UART Config 3 (default = 0xFFFFFFFF)')
parser.add_argument('--u4', dest = 'u4', type=auto_int, default=hex(0xFFFFFFFF),
help = 'UART Config 4 (default = 0xFFFFFFFF)')
parser.add_argument('--u5', dest = 'u5', type=auto_int, default=hex(0xFFFFFFFF),
help = 'UART Config 5 (default = 0xFFFFFFFF)')
parser.add_argument('--krev', dest='krev', type=auto_int, default = hex(0xFFFFFFFF),
help='KEK Revocation Mask (Default 0xFFFFFFFF)')
parser.add_argument('--arev', dest='arev', type=auto_int, default = hex(0xFFFFFFFF),
help='AuthKey Revocation Mask (Default 0xFFFFFFFF)')
parser.add_argument('--sresv', dest='sresv', type=auto_int, default = hex(0x0),
help='SRAM Reservation (Default 0x0)')
parser.add_argument('--chipid0', dest='chipId0', type=auto_int, default = 0,
help='CHIPID0 for the device (Default 0)')
parser.add_argument('--chipid1', dest='chipId1', type=auto_int, default = 0,
help='CHIPID1 for the device (Default 0)')
parser.add_argument('--wprot0', dest='wprot0', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Write Protections Mask for flash#0 (Default 0xFFFFFFFF)')
parser.add_argument('--wprot1', dest='wprot1', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Write Protections Mask for flash#1 (Default 0xFFFFFFFF)')
parser.add_argument('--rprot0', dest='rprot0', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Copy Protections Mask for flash#0 (Default 0xFFFFFFFF)')
parser.add_argument('--rprot1', dest='rprot1', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Copy Protections Mask for flash#1 (Default 0xFFFFFFFF)')
parser.add_argument('--swprot0', dest='swprot0', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Write Protections Mask for flash#0 (Default 0xFFFFFFFF)')
parser.add_argument('--swprot1', dest='swprot1', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Write Protections Mask for flash#1 (Default 0xFFFFFFFF)')
parser.add_argument('--srprot0', dest='srprot0', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Copy Protections Mask for flash#0 (Default 0xFFFFFFFF)')
parser.add_argument('--srprot1', dest='srprot1', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Copy Protections Mask for flash#1 (Default 0xFFFFFFFF)')
parser.add_argument('--wprot2', dest='wprot2', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Write Protections Mask for flash#2 (Default 0xFFFFFFFF)')
parser.add_argument('--wprot3', dest='wprot3', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Write Protections Mask for flash#3 (Default 0xFFFFFFFF)')
parser.add_argument('--rprot2', dest='rprot2', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Copy Protections Mask for flash#2 (Default 0xFFFFFFFF)')
parser.add_argument('--rprot3', dest='rprot3', type=auto_int, default = hex(0xFFFFFFFF),
help='Permanent Copy Protections Mask for flash#3 (Default 0xFFFFFFFF)')
parser.add_argument('--swprot2', dest='swprot2', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Write Protections Mask for flash#2 (Default 0xFFFFFFFF)')
parser.add_argument('--swprot3', dest='swprot3', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Write Protections Mask for flash#3 (Default 0xFFFFFFFF)')
parser.add_argument('--srprot2', dest='srprot2', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Copy Protections Mask for flash#2 (Default 0xFFFFFFFF)')
parser.add_argument('--srprot3', dest='srprot3', type=auto_int, default = hex(0xFFFFFFFF),
help='SBL overridable Copy Protections Mask for flash#3 (Default 0xFFFFFFFF)')
parser.add_argument('--chipType', dest='chip', type=str, required=True,
choices = ['apollo3', 'apollo3p'],
help='Chip Type: apollo3, apollo3p (default = apollo3)')
parser.add_argument('-k', type=str, dest='keyFile', nargs='?', default='keys_info.py',
help='key file in specified format [default = keys_info.py]')
parser.add_argument('--loglevel', dest='loglevel', type=auto_int, default=AM_PRINT_LEVEL_INFO,
choices = range(AM_PRINT_LEVEL_MIN, AM_PRINT_LEVEL_MAX+1),
help=helpPrintLevel)
args = parser.parse_args()
return args
#******************************************************************************
#
# Main function.
#
#******************************************************************************
def main():
# Read the arguments.
args = parse_arguments()
am_set_print_level(args.loglevel)
process(args.valid, args.version, args.output, args.mainPtr, args.secPol, args.keyWrap, args.secBoot, args.secBootOnRst, args.plOnExit, args.sDbg, args.bEnErase, args.infoProg, args.bNoSramWipe, args.bSwoCtrl, args.bDbgAllowed, args.custTrim, args.custTrim2, args.overrideGpio, args.overridePol, args.wiredIfMask, args.wiredSlvInt, args.wiredI2cAddr, args.wiredTimeout, args.u0, args.u1, args.u2, args.u3, args.u4, args.u5, args.krev, args.arev, args.chipId0, args.chipId1, args.sresv, args.wprot0, args.wprot1, args.rprot0, args.rprot1, args.swprot0, args.swprot1, args.srprot0, args.srprot1, args.wprot2, args.wprot3, args.rprot2, args.rprot3, args.swprot2, args.swprot3, args.srprot2, args.srprot3, args.chip, args.keyFile)
if __name__ == '__main__':
main()
@@ -0,0 +1,133 @@
#!/usr/bin/env python3
import argparse
import sys
from Crypto.Cipher import AES
import array
import os
import binascii
import importlib
from am_defines import *
#from keys_info import keyTblAes, keyTblHmac, wrapKey, minWrapMode
#******************************************************************************
#
# Generate the device keys for a given chipId based on well known keys and key Wrap mode
#
#******************************************************************************
def process(wrapMode, chipId0, chipId1, inFile, keyFile):
filenames = keyFile.split('.')
keys = importlib.import_module(filenames[0])
if (inFile is not None):
for line in inFile:
linecontent = line.rstrip()
if linecontent:
chipids = line.split(':')
process_chip(wrapMode, int(chipids[0], 16), int(chipids[1], 16), keys)
else:
process_chip(wrapMode, chipId0, chipId1, keys)
def process_chip(wrapMode, chipId0, chipId1, keys):
output = str(hex(chipId0)) + '_' + str(hex(chipId1))
chipId = int_to_bytes(chipId0) + int_to_bytes(chipId1)
while (len(chipId) != AM_SECBOOT_KEYIDX_BYTES):
chipId = chipId + chipId
am_print("ChipID: ", [hex(n) for n in chipId], level=AM_PRINT_LEVEL_VERBOSE)
if (wrapMode < keys.minWrapMode):
am_print("Invalid Wrap Mode", level=AM_PRINT_LEVEL_ERROR)
return
if (wrapMode == AM_SECBOOT_KEYWRAP_NONE): ## None
am_print("wrap mode None")
with open(output + '_info_kek.bin', mode = 'wb') as out_info_kek:
am_print("writing to " + output + '_info_kek.bin')
for i in range (0, INFO_MAX_ENC_KEYS):
am_print([hex(n) for n in keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]], level=AM_PRINT_LEVEL_DEBUG)
out_info_kek.write(bytearray(keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]))
with open(output + '_info_authkey.bin', mode = 'wb') as out_info_authkey:
am_print("writing to " + output + '_info_authkey.bin')
for i in range (0, INFO_MAX_AUTH_KEYS):
am_print([hex(n) for n in keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]], level=AM_PRINT_LEVEL_DEBUG)
out_info_authkey.write(bytearray(keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]))
elif (wrapMode == AM_SECBOOT_KEYWRAP_XOR): ## XOR
am_print("wrap mode XOR")
with open(output + '_info_kek.bin', mode = 'wb') as out_info_kek:
am_print("writing to " + output + '_info_kek.bin')
for i in range (0, INFO_MAX_ENC_KEYS):
scrambledKey = keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]
for j in range (0, AM_SECBOOT_KEYIDX_BYTES):
scrambledKey[j] = scrambledKey[j] ^ keys.wrapKey[j] ^ chipId[j]
am_print([hex(n) for n in scrambledKey], level=AM_PRINT_LEVEL_DEBUG)
out_info_kek.write(bytearray(scrambledKey))
with open(output + '_info_authkey.bin', mode = 'wb') as out_info_authkey:
am_print("writing to " + output + '_info_authkey.bin')
for i in range (0, INFO_MAX_AUTH_KEYS):
scrambledKey = keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)]
for j in range (0, AM_SECBOOT_KEYIDX_BYTES):
scrambledKey[j] = scrambledKey[j] ^ keys.wrapKey[j] ^ chipId[j]
am_print([hex(n) for n in scrambledKey], level=AM_PRINT_LEVEL_DEBUG)
out_info_authkey.write(bytearray(scrambledKey))
elif (wrapMode == AM_SECBOOT_KEYWRAP_AES128): ## AES128
am_print("wrap mode AES128")
with open(output + '_info_kek.bin', mode = 'wb') as out_info_kek:
am_print("writing to " + output + '_info_kek.bin')
for i in range (0, INFO_MAX_ENC_KEYS):
scrambledKey = encrypt_app_aes(keys.keyTblAes[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)], keys.wrapKey, chipId)
am_print([hex(n) for n in scrambledKey], level=AM_PRINT_LEVEL_DEBUG)
out_info_kek.write(bytearray(scrambledKey))
with open(output + '_info_authkey.bin', mode = 'wb') as out_info_authkey:
am_print("writing to " + output + '_info_authkey.bin')
for i in range (0, INFO_MAX_AUTH_KEYS):
scrambledKey = encrypt_app_aes(keys.keyTblHmac[i*AM_SECBOOT_KEYIDX_BYTES:(i*AM_SECBOOT_KEYIDX_BYTES + AM_SECBOOT_KEYIDX_BYTES)], keys.wrapKey, chipId)
am_print([hex(n) for n in scrambledKey], level=AM_PRINT_LEVEL_DEBUG)
out_info_authkey.write(bytearray(scrambledKey))
else:
am_print("Unknown wrap mode", level=AM_PRINT_LEVEL_ERROR)
return
def parse_arguments():
parser = argparse.ArgumentParser(description =
'Generate Corvette Device keys')
parser.add_argument('--wrap', dest='wrap', type=auto_int, default=AM_SECBOOT_KEYWRAP_NONE, choices = range(AM_SECBOOT_KEYWRAP_NONE, AM_SECBOOT_KEYWRAP_MAX+1),
help='wrap mode (0 = None, 1 = XOR, 2 = AES128) [default ' + str(AM_SECBOOT_KEYWRAP_NONE) +'] ')
parser.add_argument('--chipid0', dest='chipId0', type=auto_int, default=0,
help='CHIPID0 for the device')
parser.add_argument('--chipid1', dest='chipId1', type=auto_int, default=0,
help='CHIPID1 for the device')
parser.add_argument('-k', type=str, dest='keyFile', nargs='?', default='keys_info.py',
help='key file in specified format [default = keys_info.py]')
parser.add_argument('-f', type=argparse.FileType('r'), dest='inFile', nargs='?',
help='Input text file with chip ID Tuples (chipID0:chipID1 in each line)')
parser.add_argument('--loglevel', dest='loglevel', type=auto_int, default=AM_PRINT_LEVEL_INFO,
choices = range(AM_PRINT_LEVEL_MIN, AM_PRINT_LEVEL_MAX+1),
help=helpPrintLevel)
args = parser.parse_args()
return args
#******************************************************************************
#
# Main function.
#
#******************************************************************************
def main():
# Read the arguments.
args = parse_arguments()
am_set_print_level(args.loglevel)
process(args.wrap, args.chipId0, args.chipId1, args.inFile, args.keyFile)
if __name__ == '__main__':
main()
@@ -0,0 +1,107 @@
#!/usr/bin/env python3
# Utility to generate Recover Message for Corvette Bootloader assisted Wired updates
import argparse
import sys
from Crypto.Cipher import AES
import array
import hashlib
import hmac
import os
import binascii
import importlib
from am_defines import *
#from keys_info import recoveryKey
#******************************************************************************
#
# Generate the image blob as per command line parameters
#
#******************************************************************************
def process(binfile, n0, n1, n2, n3, custId, output, keyFile):
if (binfile != ''):
# Read the binary file from the command line.
with open(binfile, mode='rb') as binfile:
blob = binfile.read()
# Gather the important binary metadata.
blobLen = len(blob)
else:
blob = bytearray()
blobLen = 0
filenames = keyFile.split('.')
keys = importlib.import_module(filenames[0])
# Send Recover command
print('Building Recover Command.')
hdr_binarray = bytearray([0x00]*(AM_WU_RECOVERY_HDR_SIZE))
fill_word(hdr_binarray, 4, (((blobLen + AM_WU_RECOVERY_HDR_SIZE) << 16) | AM_SECBOOT_WIRED_MSGTYPE_RECOVER))
# CustId
fill_word(hdr_binarray, AM_WU_RECOVERY_HDR_OFFSET_CUSTID, custId)
# Recovery key
for x in range(0, AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES):
hdr_binarray[AM_WU_RECOVERY_HDR_OFFSET_RECKEY + x] = keys.recoveryKey[x]
# Nonce
fill_word(hdr_binarray, AM_WU_RECOVERY_HDR_OFFSET_NONCE + 0, n0)
fill_word(hdr_binarray, AM_WU_RECOVERY_HDR_OFFSET_NONCE + 4, n1)
fill_word(hdr_binarray, AM_WU_RECOVERY_HDR_OFFSET_NONCE + 8, n2)
fill_word(hdr_binarray, AM_WU_RECOVERY_HDR_OFFSET_NONCE + 12, n3)
# Compute crc
crc = crc32(hdr_binarray[4:AM_WU_RECOVERY_HDR_SIZE] + blob)
fill_word(hdr_binarray, 0, crc)
# Write the message as a raw message
with open(output + '.msg', mode = 'wb') as out:
print("Writing to file ", output + '.msg')
out.write(hdr_binarray + blob)
def parse_arguments():
parser = argparse.ArgumentParser(description =
'Generate Corvette Recovery Message')
parser.add_argument('-f', dest='binfile', default='',
help = 'Binary file representing the raw Recovery Blob provided by Ambiq')
parser.add_argument('-o', dest = 'output',
help = 'Output filename (without the extension)')
parser.add_argument('--n0', dest = 'n0', type=auto_int, default=0xFFFFFFFF,
help = 'Nonce 0 - should correspond to the value provided to Ambiq (default = 0xFFFFFFFF)')
parser.add_argument('--n1', dest = 'n1', type=auto_int, default=0xFFFFFFFF,
help = 'Nonce 1 - should correspond to the value provided to Ambiq (default = 0xFFFFFFFF)')
parser.add_argument('--n2', dest = 'n2', type=auto_int, default=0xFFFFFFFF,
help = 'Nonce 2 - should correspond to the value provided to Ambiq (default = 0xFFFFFFFF)')
parser.add_argument('--n3', dest = 'n3', type=auto_int, default=0xFFFFFFFF,
help = 'Nonce 3 - should correspond to the value provided to Ambiq (default = 0xFFFFFFFF)')
parser.add_argument('--custId', dest='custId', type=auto_int, default=0xFFFFFFFF,
help='Customer ID - should correspond to the value provided to Ambiq (default = 0xFFFFFFFF)')
parser.add_argument('-k', type=str, dest='keyFile', nargs='?', default='keys_info.py',
help='key file in specified format [default = keys_info.py]')
args = parser.parse_args()
return args
#******************************************************************************
#
# Main function.
#
#******************************************************************************
def main():
# Read the arguments.
args = parse_arguments()
process(args.binfile, args.n0, args.n1, args.n2, args.n3, args.custId, args.output, args.keyFile)
if __name__ == '__main__':
main()
@@ -0,0 +1,36 @@
// connect to device
// NEED to specify -device AMA3B2KK-KBR (for Apollo3P) or -device AMA3B1KK-KBR/KCR (for Apollo3) from command line
si SWD
speed 1000
r
sleep 10
//set C runtime environment
wreg MSP, 0x10000100
// erase info0
w4 0x10000000 0 // flash info instance
w4 0x10000004 0xd894e09e // info 0 key
w4 0x10000008 0xFFFFFFFF // clear return value
setPC 0x08000085 // call the ROM helper function flash_info_erase_from_sram
g
sleep 50
mem32 0x10000008 1 // dump return value for check
// program info0
w4 0x10000000 0 // flash info instance
w4 0x10000004 0 // offset
w4 0x10000008 0x800 // length in words
w4 0x1000000C 0xd894e09e // info 0 key
w4 0x10000010 0xFFFFFFFF // clear return value
loadbin info0.bin 0x10001000 //load the info0 binary into sram
setPC 0x08000061 // call the ROM helper function flash_program_info_area_from_sram
g
sleep 50
mem32 0x10000010 1 // dump return value for check
// perform software POI
w4 0x40000004 0x1B
// quit
qc
@@ -0,0 +1,20 @@
//connect to device
// NEED to specify -device AMA3B2KK-KBR (for Apollo3P) or -device AMA3B1KK-KBR/KCR (for Apollo3) from command line
si SWD
speed 1000
r
sleep 10
// download image to 0x80000 - **** Change this based on device flashmap ****
loadbin sbl.bin 0x80000 //load the SBL binary into temp location in flash
// Set up OTA Descriptor at 0xF0000 // **** Change this based on device flashmap ****
w4 0xF0000 0x80003
w4 0xF0004 0xFFFFFFFF
// Set up OTAPointer
w4 0x40020264 0xF0003
// Reset POI
w4 0x40000004 0x1B
// quit
qc
@@ -0,0 +1,25 @@
//connect to device
// NEED to specify -device AMA3B2KK-KBR (for Apollo3P) or -device AMA3B1KK-KBR/KCR (for Apollo3) from command line
si SWD
speed 1000
r
sleep 10
//set C runtime environment
wreg MSP, 0x10000100
// unlock info0 access
w4 0x40030078 1 // unlock the info0 secured portion
w4 0x40030080 DEADBEEF DEADBEEF DEADBEEF DEADBEEF // write the unlock key
// this should be replaced with actual customer key!!!
mem32 0x4003007C 1 // dump the lock status for check
// read back info0 for verify
verifybin info0.bin 0x50020000 // verify the info 0 content with the original source file
savebin info0_dump.bin 0x50020000 0x2000 // read out the info 0 content for saving
w4 0x40030080 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF // lock the secured portion
// reset and quit
r
qc
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
from am_defines import *
minAesKeyIdx = 8
maxAesKeyIdx = 15
minHmacKeyIdx = 8
maxHmacKeyIdx = 15
###### Following are just dummy keys - Should be substituted with real keys #######
keyTblAes = [
# Info0 Keys - Starting at index 8
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
keyTblHmac = [
# Info0 Keys - Starting at index 8
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
custKey = [
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
# These are dummy values. Contact AMBIQ to get the real Recovery Key
recoveryKey = [
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
###################################################################################
wrapKey = custKey
minWrapMode = AM_SECBOOT_KEYWRAP_NONE
INFO_KEY = 0xd894e09e
FLASH_KEY = 0x12344321
@@ -0,0 +1,11 @@
@echo off
if [%1]==[] goto usage
jlink -device %1 -CommanderScript jlink-prog-info0.txt
pause
goto :eof
:usage
@echo Usage: %0 ^<Chip Part#^>
exit /B 1
@@ -0,0 +1,9 @@
sbl_v2_3_93e8 SBL v2 created on 7/26/2018. Change to disable Encap OTA Support.
SBL_v2 Release candidate #2. Header version 3
sbl_v3_4_994c SBL v3 created on 2/19/2019. Adds IOS SPI and I2C support.
Header version 4.
sbl_v3_5_99a0 SBL v4 created on 3/8/2019. Eliminates setting of HFADJ in
am_secboot_config_wired_uart() for B0. Header version 5.
@@ -0,0 +1,5 @@
sbl3p_v2_2_a0a5 (OTA: 0xA3009400:0x53D5B051) - SBL v2
enhancement for SRAM Reservation feature
with fix to GPIO macro to allow GPIO>63 to be used
Header Version 2
@@ -0,0 +1,345 @@
#!/usr/bin/env python3
# UART wired update host for Corvette Bootloader
import argparse
import serial
import sys
import array
import os
import binascii
from am_defines import *
#******************************************************************************
#
# Main function
#
#******************************************************************************
def main():
# Open a serial port, and communicate with Device
#
# We will use a UART timeout value of 12 second. This should be long
# enough that the slave will respond to us, but short enough that a human
# operator should see errors quickly..
# Max flashing time depends on the amount of SRAM available.
# For very large images, the flashing happens page by page.
# However if the image can fit in the free SRAM, it could take a long time
# for the whole image to be flashed at the end.
# The largest image which can be stored depends on the max SRAM.
# Assuming worst case ~100 ms/page of flashing time, and allowing for the
# image to be close to occupying full SRAM (256K) which is 128 pages.
print('Connecting with Corvette over serial port {}...'.format(args.port), flush=True)
with serial.Serial(args.port, args.baud, timeout=12) as ser:
connect_device(ser)
print('Done.')
#******************************************************************************
#
# Communicate with Device
#
# Given a serial port, connects to the target device using the
# UART.
#
#******************************************************************************
def connect_device(ser):
# Send Hello
#generate mutable byte array for the header
hello = bytearray([0x00]*4);
fill_word(hello, 0, ((8 << 16) | AM_SECBOOT_WIRED_MSGTYPE_HELLO))
print('Sending Hello.')
response = send_command(hello, 88, ser)
print("Received response for Hello")
word = word_from_bytes(response, 4)
if ((word & 0xFFFF) == AM_SECBOOT_WIRED_MSGTYPE_STATUS):
# Received Status
print("Received Status")
print("length = ", hex((word >> 16)))
print("version = ", hex(word_from_bytes(response, 8)))
print("Max Storage = ", hex(word_from_bytes(response, 12)))
print("Status = ", hex(word_from_bytes(response, 16)))
print("State = ", hex(word_from_bytes(response, 20)))
print("AMInfo = ")
for x in range(24, 88, 4):
print(hex(word_from_bytes(response, x)))
abort = args.abort
if (abort != -1):
# Send OTA Desc
print('Sending Abort command.')
abortMsg = bytearray([0x00]*8);
fill_word(abortMsg, 0, ((12 << 16) | AM_SECBOOT_WIRED_MSGTYPE_ABORT))
fill_word(abortMsg, 4, abort)
send_ackd_command(abortMsg, ser)
otadescaddr = args.otadesc
if (otadescaddr != 0xFFFFFFFF):
# Send OTA Desc
print('Sending OTA Descriptor = ', hex(otadescaddr))
otaDesc = bytearray([0x00]*8);
fill_word(otaDesc, 0, ((12 << 16) | AM_SECBOOT_WIRED_MSGTYPE_OTADESC))
fill_word(otaDesc, 4, otadescaddr)
send_ackd_command(otaDesc, ser)
imageType = args.imagetype
if (args.binfile != ''):
# Read the binary file from the command line.
with open(args.binfile, mode='rb') as binfile:
application = binfile.read()
# Gather the important binary metadata.
totalLen = len(application)
# Send Update command
print('Sending Update Command.')
# It is assumed that maxSize is 256b multiple
maxImageSize = args.split
if ((maxImageSize & (FLASH_PAGE_SIZE - 1)) != 0):
print ("split needs to be multiple of flash page size")
return
# Each Block of image consists of AM_WU_IMAGEHDR_SIZE Bytes Image header and the Image blob
maxUpdateSize = AM_WU_IMAGEHDR_SIZE + maxImageSize
numUpdates = (totalLen + maxUpdateSize - 1) // maxUpdateSize # Integer division
print("number of updates needed = ", numUpdates)
end = totalLen
for numUpdates in range(numUpdates, 0 , -1):
start = (numUpdates-1)*maxUpdateSize
crc = crc32(application[start:end])
applen = end - start
print("Sending block of size ", str(hex(applen)), " from ", str(hex(start)), " to ", str(hex(end)))
end = end - applen
update = bytearray([0x00]*16);
fill_word(update, 0, ((20 << 16) | AM_SECBOOT_WIRED_MSGTYPE_UPDATE))
fill_word(update, 4, applen)
fill_word(update, 8, crc)
# Size = 0 => We're not piggybacking any data to IMAGE command
fill_word(update, 12, 0)
send_ackd_command(update, ser)
# Loop over the bytes in the image, and send them to the target.
resp = 0
# Max chunk size is AM_MAX_UART_MSG_SIZE adjusted for the header for Data message
maxChunkSize = AM_MAX_UART_MSG_SIZE - 12
for x in range(0, applen, maxChunkSize):
# Split the application into chunks of maxChunkSize bytes.
# This is the max chunk size supported by the UART bootloader
if ((x + maxChunkSize) > applen):
chunk = application[start+x:start+applen]
# print(str(hex(start+x)), " to ", str(hex(applen)))
else:
chunk = application[start+x:start+x+maxChunkSize]
# print(str(hex(start+x)), " to ", str(hex(start + x + maxChunkSize)))
chunklen = len(chunk)
# Build a data packet with a "data command" a "length" and the actual
# payload bytes, and send it to the target.
dataMsg = bytearray([0x00]*8);
fill_word(dataMsg, 0, (((chunklen + 12) << 16) | AM_SECBOOT_WIRED_MSGTYPE_DATA))
# seqNo
fill_word(dataMsg, 4, x)
print("Sending Data Packet of length ", chunklen)
send_ackd_command(dataMsg + chunk, ser)
if (args.raw != ''):
# Read the binary file from the command line.
with open(args.raw, mode='rb') as rawfile:
blob = rawfile.read()
# Send Raw command
print('Sending Raw Command.')
ser.write(blob)
if (args.reset != 0):
# Send reset
print('Sending Reset Command.')
resetmsg = bytearray([0x00]*8);
fill_word(resetmsg, 0, ((12 << 16) | AM_SECBOOT_WIRED_MSGTYPE_RESET))
# options
fill_word(resetmsg, 4, args.reset)
send_ackd_command(resetmsg, ser)
else:
# Received Wrong message
print("Received Unknown Message")
word = word_from_bytes(response, 4)
print("msgType = ", hex(word & 0xFFFF))
print("Length = ", hex(word >> 16))
print([hex(n) for n in response])
print("!!!Wired Upgrade Unsuccessful!!!....Terminating the script")
exit()
#******************************************************************************
#
# Send ACK'd command
#
# Sends a command, and waits for an ACK.
#
#******************************************************************************
def send_ackd_command(command, ser):
for numTries in range(1, 5 , 1):
response = send_command(command, 20, ser)
word = word_from_bytes(response, 4)
if ((word & 0xFFFF) == AM_SECBOOT_WIRED_MSGTYPE_ACK):
# Received ACK
if (word_from_bytes(response, 12) != AM_SECBOOT_WIRED_ACK_STATUS_SUCCESS):
print("Received NACK")
print("msgType = ", hex(word_from_bytes(response, 8)))
print("error = ", hex(word_from_bytes(response, 12)))
print("seqNo = ", hex(word_from_bytes(response, 16)))
if (numTries < 4):
print("Retry # ", numTries)
else:
print("Exceed number of retries")
else:
break
else:
print("!!!Wired Upgrade Unsuccessful!!!....unexpected respose - Terminating the script")
exit()
if (numTries == 4):
print("!!!Wired Upgrade Unsuccessful!!!....numTries exceeded - Terminating the script")
exit()
return response
#******************************************************************************
#
# Send command
#
# Sends a command, and waits for the response.
#
#******************************************************************************
def send_command(params, response_len, ser):
# Compute crc
crc = crc32(params)
# print([hex(n) for n in int_to_bytes(crc)])
# print([hex(n) for n in params])
# send crc first
ser.write(int_to_bytes(crc))
# Next, send the parameters.
ser.write(params)
response = ''
response = ser.read(response_len)
# Make sure we got the number of bytes we asked for.
if len(response) != response_len:
print('No response for command 0x{:08X}'.format(word_from_bytes(params, 0) & 0xFFFF))
n = len(response)
if (n != 0):
print("received bytes ", len(response))
print([hex(n) for n in response])
raise NoResponseError
return response
#******************************************************************************
#
# Send a command that uses an array of bytes as its parameters.
#
#******************************************************************************
def send_bytewise_command(command, params, response_len, ser):
# Send the command first.
ser.write(int_to_bytes(command))
# Next, send the parameters.
ser.write(params)
response = ''
response = ser.read(response_len)
# Make sure we got the number of bytes we asked for.
if len(response) != response_len:
print('No response for command 0x{:08X}'.format(command))
raise NoResponseError
return response
#******************************************************************************
#
# Errors
#
#******************************************************************************
class BootError(Exception):
pass
class NoAckError(BootError):
pass
class NoResponseError(BootError):
pass
#******************************************************************************
#
# Main program flow
#
#******************************************************************************
if __name__ == '__main__':
parser = argparse.ArgumentParser(description =
'UART Wired Update Host for Apollo3')
parser.add_argument('port', help = 'Serial COMx Port')
parser.add_argument('-b', dest='baud', default=115200, type=int,
help = 'Baud Rate (default is 115200)')
parser.add_argument('--raw', dest='raw', default='',
help = 'Binary file for raw message')
parser.add_argument('-f', dest='binfile', default='',
help = 'Binary file to program into the target device')
parser.add_argument('-i', dest = 'imagetype', default=AM_SECBOOT_WIRED_IMAGETYPE_INVALID, type=auto_int,
choices = [
(AM_SECBOOT_WIRED_IMAGETYPE_SBL),
(AM_SECBOOT_WIRED_IMAGETYPE_AM3P),
(AM_SECBOOT_WIRED_IMAGETYPE_PATCH),
(AM_SECBOOT_WIRED_IMAGETYPE_MAIN),
(AM_SECBOOT_WIRED_IMAGETYPE_CHILD),
(AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH),
(AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE),
(AM_SECBOOT_WIRED_IMAGETYPE_INFO0),
(AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA),
(AM_SECBOOT_WIRED_IMAGETYPE_INVALID)
],
help = 'ImageType ('
+ str(AM_SECBOOT_WIRED_IMAGETYPE_SBL) + ': SBL, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_AM3P) + ': AM3P, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_PATCH) + ': Patch, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_MAIN) + ': Main, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_CHILD) + ': Child, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH) + ': CustOTA, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE) + ': NonSecure, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INFO0) + ': Info0 '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA) + ': Info0_NOOTA) '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INVALID) + ': Invalid) '
'- default[Invalid]')
parser.add_argument('-o', dest = 'otadesc', type=auto_int, default=0xFE000,
help = 'OTA Descriptor Page address (hex) - (Default is 0xFE000 - at the end of main flash) - enter 0xFFFFFFFF to instruct SBL to skip OTA')
parser.add_argument('-r', dest = 'reset', default=1, type=auto_int, choices = [0,1,2],
help = 'Should it send reset command after image download? (0 = no reset, 1 = POI, 2 = POR) (default is 1)')
parser.add_argument('-a', dest = 'abort', default=-1, type=int, choices = [0,1,-1],
help = 'Should it send abort command? (0 = abort, 1 = abort and quit, -1 = no abort) (default is -1)')
parser.add_argument('--split', dest='split', type=auto_int, default=hex(MAX_DOWNLOAD_SIZE),
help='Specify the max block size if the image will be downloaded in pieces')
args = parser.parse_args()
main()
@@ -0,0 +1,17 @@
@echo off
if [%1]==[] goto usage
jlink -device %1 -CommanderScript jlink-read-info0.txt
diff info0.bin info0_dump.bin
@ECHO OFF
if ERRORLEVEL 1 (
echo "INFO0 Invalid"
) else (
echo "INFO0 Valid"
)
pause
goto :eof
:usage
@echo Usage: %0 ^<Chip Part#^>
exit /B 1