initial commit
This commit is contained in:
@@ -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()
|
||||
+241
@@ -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.
|
||||
|
||||
+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
|
||||
Reference in New Issue
Block a user