iBoot/apps/SecureROM/tests/test_generator_mx.py

925 lines
37 KiB
Python
Raw Permalink Normal View History

2023-07-08 13:03:17 -07:00
#!/usr/bin/python2.7
import optparse
import os
import plistlib
import textwrap
import shutil
import subprocess
import sys
import time
import hashlib
import binascii
# ECID: This is the value passed on the personalize_img4 -e option.
kDefaultEcid = 0x000012345678abcd
# BNCN: This is the value passed on the personalize_img4 -r option.
kDefaultApNonce = 0x12345678aabbccdd
# Old fashioned terminal size.
kLogWidth = 78
kOutputDirPrefix = 'test.'
kLogFileName = 'README.txt'
kDefaultPlatform = 't8002'
kDefaultChipId = 0x8002
kDefaultBoardId = 0x3f
kDefaultBlinkyGPIOReg = '0x47500000'
kDefaultBlinkyGPIOValue = '0x70203'
kDefaultDFUGPIOReg = '0x47500220'
kDefaultDFUGPIOValue = '0x00478283'
kBoardIdStrapBits = 4
kSecurityDomainDarwin = 1
# The following calculates the nonce hash and formats it correctly so that a
# person doesn't have to deal with generating the a hash, truncating it, and
# getting the endian-ness right.
kDefaultApNonceHashTruncatedSize = 256
kDefaultApNonceByteArray = bytearray.fromhex(hex(kDefaultApNonce)[2:])
kDefaultApNonceString = binascii.hexlify(kDefaultApNonceByteArray)
kDefaultApNonceLittleEndian = int("".join(reversed([kDefaultApNonceString[i:i+2] for i in range(0, len(kDefaultApNonceString), 2)])), 16)
kDefaultApNonceHash384 = hashlib.sha384(kDefaultApNonceByteArray).hexdigest()
kDefaultApNonceHash = int(kDefaultApNonceHash384[:kDefaultApNonceHashTruncatedSize/4], 16)
kDefaultSepNonceHash = 0x1234567823456789345678904567890156789012
# <rdar://problem/15199519> certificate epoch for server signing fixed at 1
kDefaultEpochForServerSigning = 1
# Supported platforms
kSupported_platforms = ['t8002']
# Image sources
kImageSourceDfu = 1
kImageSourceNand = 2
kImageSourceNor = 3
# Outcomes
kOutcomeBlinky = 1
kOutcomeDfu = 2
kOutcomeBlinkyVcoOverride = 3
kOutcomeBlinkyVcoDefault = 4
# Can be overidden by command line options.
kImg4DecodeTestTool = 'xcrun -sdk iphoneos.internal -run img4decodetest'
kPersonalizeImg4Tool = 'xcrun -sdk iphoneos.internal -run personalize_img4'
kBfnMaker = 'xcrun -sdk iphoneos.internal -run bfn_maker'
kBfnMakerPageSize = 8224
kBfnMakerFormat = 'h6'
def ErrorText(text):
RedColor = '\033[91m'
NormalColor = '\033[0m'
return RedColor + text + NormalColor
def WarningText(text):
YellowColor = '\033[93m'
NormalColor = '\033[0m'
return YellowColor + text + NormalColor
def PassText(text):
GreenColor = '\033[92m'
NormalColor = '\033[0m'
return GreenColor + text + NormalColor
def ByteSwap(value, bits):
assert (bits % 8) == 0
result = 0
for i in xrange(0, bits / 8):
result <<= 8
result |= value & 0xff
value >>= 8
return result
class LogSettings:
def __init__(self):
self._all_settings = []
def Append(self, text, settings):
self._all_settings.append((text, settings))
def Log(self, log):
# Get a format string which aligns everything.
longest_entry = 0
for settings in self._all_settings:
for s in settings[1]:
if len(s[0]) > longest_entry:
longest_entry = len(s[0])
format = ' %%-%ds %%s\n' % longest_entry
# Dump all settings.
for settings in self._all_settings:
log.write(settings[0] + ':\n')
for s in settings[1]:
if (type(s[1]) == int) or (type(s[1]) == long):
if s[1] < 16:
out = format % (s[0], '%d' % s[1])
else:
out = format % (s[0], '0x%x' % s[1])
else:
out = format % (s[0], str(s[1]))
log.write(out)
log.write('\n')
class PersonalizeImg4:
def __init__(self,
description = None,
manifest = True,
platform = kDefaultPlatform,
options = None,
log = None,
test_number = None,
outcome = None,
image_source = None,
fuse_production_status = None,
fuse_security_mode = None,
fuse_security_domain = kSecurityDomainDarwin,
fuse_epoch = None,
fuse_ecid = kDefaultEcid,
fuse_cfg_fuse9 = None,
boot_device = None,
test_mode = False,
boot_device_empty = False,
epoch = kDefaultEpochForServerSigning,
chip_id = None,
board_id = None,
force_dfu = 0,
ecid = None,
production_status = None,
security_mode = None,
security_domain = kSecurityDomainDarwin,
allow_mix_and_match = None,
ap_boot_nonce_hash = None,
sep_boot_nonce_hash = None,
enable_keys = None,
encryption = None,
crypto_hash_method = 'sha2-384',
restore_info_nonce = None,
demote_production = None,
demote_secure = None,
lock_fuses = None,
):
# Validate required arguments.
assert options is not None
assert log is not None
assert type(test_number) == int
assert outcome in [kOutcomeBlinky, kOutcomeDfu, kOutcomeBlinkyVcoOverride, kOutcomeBlinkyVcoDefault]
assert image_source in [kImageSourceDfu, kImageSourceNand, kImageSourceNor]
assert boot_device is not None
assert type(boot_device_empty) == bool
assert type(fuse_production_status) == bool
assert type(fuse_security_mode) == bool
assert ((type(fuse_security_domain) == int) and
(fuse_security_domain >= 0) and (fuse_security_domain <= 3))
assert ((type(fuse_epoch) == int) and
(fuse_epoch >= 0) and (fuse_epoch <= 0x7f))
assert ((fuse_ecid is not None) and
(fuse_ecid >= 0) and (fuse_ecid < (1 << 64)))
if manifest:
assert ((type(epoch) == int) and
(epoch >= 0) and (epoch <= 0x7f))
assert ((type(chip_id) == int) and
(chip_id >= 0) and (chip_id < (1 << 16)))
assert ((type(board_id) == int) and
(board_id >= 0) and (board_id < (1 << 8)))
assert (ecid is not None) and (ecid >= 0) and (ecid < (1 << 64))
assert type(production_status) == bool
assert type(security_mode) == bool
assert ((type(security_domain) == int) and
(security_domain >= 0) and (security_domain <= 3))
assert type(allow_mix_and_match) == bool
assert type(enable_keys) == bool
assert type(encryption) == bool
if sep_boot_nonce_hash is None:
sep_boot_nonce_hash = kDefaultSepNonceHash
# Set members.
self._description = description
self._manifest = manifest
self._platform = platform
self._images_dir = 'images_{}'.format(platform)
self._options = options
self._log = log
self._test_number = test_number
self._outcome = outcome
self._image_source = image_source
self._fuse_production_status = fuse_production_status
self._fuse_security_mode = fuse_security_mode
self._fuse_security_domain = fuse_security_domain
self._fuse_epoch = fuse_epoch
self._fuse_ecid = fuse_ecid
if fuse_cfg_fuse9 is None:
self._fuse_cfg_fuse9 = '0x00000000'
else:
assert (type(fuse_cfg_fuse9) == int)
self._fuse_cfg_fuse9 = '0x%08x' % fuse_cfg_fuse9
self._epoch = epoch
self._chip_id = chip_id
self._board_id = board_id
self._boot_device = boot_device
self._test_mode = test_mode
self._boot_device_empty = boot_device_empty
self._force_dfu = force_dfu
self._ecid = ecid
self._production_status = production_status
self._security_mode = security_mode
self._security_domain = security_domain
self._allow_mix_and_match = allow_mix_and_match
self._ap_boot_nonce_hash = ap_boot_nonce_hash
self._sep_boot_nonce_hash = sep_boot_nonce_hash
self._enable_keys = enable_keys
self._encryption = encryption
self._crypto_hash_method = crypto_hash_method
self._restore_info_nonce = restore_info_nonce
self._demote_production = demote_production
self._demote_secure = demote_secure
self._lock_fuses = lock_fuses
def Personalize(self, im4p, output_dir):
# Form args.
if self._options.personalize_img4:
args = self._options.personalize_img4.split(' ')
else:
args = kPersonalizeImg4Tool.split(' ')
args += ['-i', im4p, '-o', output_dir]
if not self._manifest:
args += ['-O']
else:
if self._chip_id is not None:
args += ['-c', '0x%04x' % self._chip_id]
if self._board_id is not None:
args += ['-b', '0x%x' % self._board_id]
if self._ecid is not None:
args += ['-e', '0x%x' % self._ecid]
if self._production_status:
args += ['-p']
if self._security_mode:
args += ['-m']
args += ['-W']
if self._security_domain is not None:
args += ['-d', '%d' % self._security_domain]
if self._allow_mix_and_match:
args += ['-a']
if self._ap_boot_nonce_hash is not None:
args += ['-n', '0x%x' % self._ap_boot_nonce_hash]
if self._sep_boot_nonce_hash is not None:
args += ['-s', '0x%x' % self._sep_boot_nonce_hash]
if self._crypto_hash_method == 'sha2-384':
args += ['-g 384']
# disabling keys or demotions require a plist file with Trusted, EPRO, and ESEC defined
if (not self._enable_keys) or (self._demote_production) or (self._demote_secure):
object_properties = {'Trusted': self._enable_keys}
if self._demote_production is not None:
object_properties['DPRO'] = True
if self._demote_production:
assert self._production_status == True
object_properties['EPRO'] = False
else:
object_properties['EPRO'] = self._production_status
if self._demote_secure:
assert self._security_mode == True
object_properties['ESEC'] = False
else:
object_properties['ESEC'] = self._security_mode
all_properties = {'OBJP': object_properties}
plist_str = plistlib.writePlistToString(all_properties)
plist_file = '/tmp/personalize-{}.plist'.format(self._test_number)
f = open(plist_file, 'w')
f.write(plist_str)
f.close()
args += ['-f', plist_file]
# personalize_img4 tool expects RestoreInfo nonce in big endian (only for LLB)
if (im4p.find('ibss') == -1) and self._restore_info_nonce is not None:
args += ['-r', '0x%x' % ByteSwap(self._restore_info_nonce, 64)]
args += ['-X']
# Convert args to an shell string.
invoke_string = ' '.join(args)
# Execute personalize_img4 utility.
print('Invoking: %s' % invoke_string)
pipe = subprocess.Popen(invoke_string, shell=True)
if pipe.wait() == 0:
return True
else:
self._log.write('Invocation of personalize_img4 failed\n')
sys.stderr.write(ErrorText('Test %d: Invocation of personalize_img4 failed\n' % self._test_number))
return False
def DecodeTest(self, img4):
if self._options.img4decodetest:
args = self._options.img4decodetest.split(' ')
else:
args = kImg4DecodeTestTool.split(' ')
args += ['-c', '-i', img4]
if self._crypto_hash_method == 'sha2-384':
args += ['-n']
invoke_string = ' '.join(args)
print('Invoking: %s' % invoke_string)
pipe = subprocess.Popen(invoke_string, shell=True)
if pipe.wait() == 0:
return True
else:
self._log.write('Invocation of img4decodetest failed\n')
sys.stderr.write(ErrorText('Test %d: Invocation of img4decodetest failed\n' % self._test_number))
return False
def BfnMaker(self, input, output):
if self._options.bfn_maker:
args = self._options.bfn_maker.split(' ')
else:
args = kBfnMaker.split(' ')
args += ['--pageSize', str(kBfnMakerPageSize)]
args += ['--format', str(kBfnMakerFormat)]
args += [input, output]
invoke_string = ' '.join(args)
pipe = subprocess.Popen(invoke_string, shell=True)
if pipe.wait() == 0:
return True
else:
self._log.write('Invocation of bfn_maker failed\n')
sys.stderr.write(ErrorText('Test %d: Invocation of bfn_maker failed\n' % self._test_number))
return False
def Execute(self):
# Log header.
self._log.write('-' * kLogWidth + '\n')
self._log.write('Test %d\n' % self._test_number)
self._log.write(textwrap.fill(self._description, width=kLogWidth) + '\n\n')
# Figure out the input file variant.
image_type, location = {kImageSourceDfu: ('ibss', 'DFU'),
kImageSourceNand: ('illb', 'NAND'),
kImageSourceNor: ('illb', 'NOR')}[self._image_source]
# FAST_NOR boot device is currenly only supported for test mode
if self._boot_device in ['FAST_NOR', 'SLOW_NOR']:
if self._test_mode == False:
self._log.write(' Skipping: FAST_NOR/SLOW_NOR boot device requires test mode\n\n')
sys.stderr.write(WarningText('Test %d: FAST_NOR/SLOW_NOR boot device requires test mode\n' % self._test_number))
return False
if self._boot_device == 'NOR':
self._boot_config = '0x%x' % (0 + (1 if self._test_mode else 0))
elif self._boot_device == 'NAND':
self._boot_config = '0x%x' % (2 + (1 if self._test_mode else 0))
elif self._boot_device == 'SLOW_NOR':
self._boot_config = '0x6'
elif self._boot_device == 'FAST_NOR':
self._boot_config = '0x7'
else:
assert 0, '_boot_device ' + self._boot_device + ' is unsupported'
if self._encryption:
encryption_name = 'encrypted'
else:
encryption_name = 'unencrypted'
im4p_basename = 'rom_test_%s_%s' % (image_type, encryption_name)
im4p_filename = im4p_basename + '.im4p'
im4p_path = os.path.join(self._images_dir, im4p_filename)
# If valid image in boot device, but force_dfu is set, we also need ibss
if self._force_dfu and self._boot_device_empty == False:
dfu_im4p_basename = 'rom_test_ibss_%s' % encryption_name
dfu_im4p_filename = dfu_im4p_basename + '.im4p'
dfu_im4p_path = os.path.join(self._images_dir, dfu_im4p_filename)
# Output filename.
output_dir = kOutputDirPrefix + self._platform
pretty_filename_base = 'test_%d_%s_%s' % (
self._test_number, image_type, encryption_name)
pretty_filename_img4 = pretty_filename_base + '.img4'
pretty_path_base = os.path.join(output_dir, pretty_filename_base)
pretty_path_img4 = pretty_path_base + '.img4'
# If valid image in boot device, but force_dfu is set, we also need ibss
if self._force_dfu and self._boot_device_empty == False:
pretty_dfu_filename_base = 'test_%d_ibss_%s' % (
self._test_number, encryption_name)
pretty_dfu_filename_img4 = pretty_dfu_filename_base + '.img4'
pretty_dfu_path_base = os.path.join(output_dir, pretty_dfu_filename_base)
pretty_dfu_path_img4 = pretty_dfu_path_base + '.img4'
# Remove old output file if it exists.
img4 = os.path.join(output_dir, im4p_basename + '.img4')
if self._force_dfu and self._boot_device_empty == False:
dfu_img4 = os.path.join(output_dir, dfu_im4p_basename + '.img4')
try:
os.unlink(img4)
if dfu_img4 is not None:
os.unlink(dfu_img4)
except:
pass
# Personalize this case.
print('Personalize %s -> %s' % (im4p_filename, img4))
if not self.Personalize(im4p_path, output_dir):
sys.stderr.write(ErrorText('Test %d failed to generate\n' % self._test_number))
# Log failure
self._log.write(' Failed to generate!\n\n')
return False
# Now, if force_dfu is set, personalize the 2nd image
if self._force_dfu and self._boot_device_empty == False:
print('Personalize %s -> %s' % (dfu_im4p_filename, dfu_img4))
if not self.Personalize(dfu_im4p_path, output_dir):
sys.stderr.write(ErrorText('Test %d failed to generate\n' % self._test_number))
# Log failure
self._log.write(' Failed to generate!\n\n')
return False
# Rename the output file to the path we want for this test case.
os.rename(img4, pretty_path_img4)
print('Test %d generated %s' % (self._test_number, pretty_filename_img4))
if self._force_dfu and self._boot_device_empty == False:
os.rename(dfu_img4, pretty_dfu_path_img4)
print('Test %d generated %s' % (self._test_number, pretty_dfu_filename_img4))
# Test that there isn't a certificate vs manifest problem, because
# it's not worth burning a huge amount of DV time running it.
if self._manifest:
if not self.DecodeTest(pretty_path_img4):
self._log.write(' Failed decode test!\n')
self._log.write(' Check manifest vs cert is compatible\n\n')
sys.stderr.write(ErrorText('Test %d: Failed decode test\n' % self._test_number))
return False
if self._force_dfu and self._boot_device_empty == False:
if not self.DecodeTest(pretty_dfu_path_img4):
self._log.write(' Failed decode test!\n')
self._log.write(' Check manifest vs cert is compatible\n\n')
sys.stderr.write(ErrorText('Test %d: Failed decode test\n' % self._test_number))
return False
# If the source is NAND, we need to pass it through bfn_maker
if self._image_source == kImageSourceNand:
nand_filename = pretty_filename_base + '.nand'
nand_path = os.path.join(output_dir, nand_filename)
if not self.BfnMaker(pretty_path_img4, nand_path):
self._log.write(' Failed to create NAND image\n')
sys.stderr.write(ErrorText('Test %d: Failed to create NAND image\n' % self._test_number))
return False
pretty_filename = nand_filename
else:
pretty_filename = pretty_filename_img4
# Log success.
settings = LogSettings()
settings.Append(
'Fuses',
[('Production Status', int(self._fuse_production_status)),
('Security Mode', int(self._fuse_security_mode)),
('Security Domain', self._fuse_security_domain),
('Board ID', '0x%x' % ((self._board_id or kDefaultBoardId) >> kBoardIdStrapBits)),
('Epoch', self._fuse_epoch),
('SE Required', 0),
('ECID_LO', '0x%08x' % (kDefaultEcid & 0xffffffff)),
('ECID_HI', '0x%08x' % ((kDefaultEcid >> 32) & 0xffffffff)),
('CFG_FUSE9', self._fuse_cfg_fuse9),
])
settings.Append(
'Straps',
[('Boot-device', self._boot_device),
('Test mode', self._test_mode),
('Boot-config', self._boot_config),
('Board-id', (self._board_id or kDefaultBoardId) & ((1 << kBoardIdStrapBits) - 1)),
('Force-dfu', self._force_dfu),
('Boot Device Empty', self._boot_device_empty),
])
if self._force_dfu and self._boot_device_empty == False:
pretty_dfu_filename = pretty_dfu_filename_img4
else:
pretty_dfu_filename = ''
settings.Append(
'Images',
[(pretty_filename, ''),
(pretty_dfu_filename, ''),
])
outcome_string = {kOutcomeBlinky: 'Blinky - AP writes {} to {}'.format(kDefaultBlinkyGPIOValue, kDefaultBlinkyGPIOReg),
kOutcomeDfu: 'DFU - AP writes {} to {}'.format(kDefaultDFUGPIOValue, kDefaultDFUGPIOReg),
kOutcomeBlinkyVcoOverride: 'Blinky: SecureROM PLLs (4, CPU) VCO_RCTRL_OW & VCO_RCTRL_SEL overridden',
kOutcomeBlinkyVcoDefault: 'Blinky: SecureROM PLLs (4, CPU) VCO_RCTRL_OW & VCO_RCTRL_SEL default values',
}[self._outcome]
if self._outcome == kOutcomeDfu:
check_usb_clk = 'USB clock frequency'
check_usbotg = 'USB20PHY_CFG0/USB20PHY_CFG1'
check_usbotg_text = 'set to tunables values for Device mode'
else:
check_usb_clk = ''
check_usbotg = ''
check_usbotg_text = ''
# JTAG gets enabled on a production part if it is demoted.
if self._fuse_production_status == True and self._demote_production == True and self._outcome == kOutcomeBlinky:
check_jtag = 'JTAG'
check_jtag_text = 'Starts disabled before test, but enabled after test'
else:
check_jtag = ''
check_jtag_text = ''
keys_state = {True: 'Enabled',
False: 'Disabled',
None: 'Disabled'}[self._enable_keys]
if self._outcome == kOutcomeDfu:
fuses_locked_default = 'Unlocked (CFG_FUSE1.AP_LOCK = 0)'
else:
fuses_locked_default = 'Locked (CFG_FUSE1.AP_LOCK = 1)'
fuses_locked_state = {True: 'Locked (CFG_FUSE1.AP_LOCK = 1)',
False: 'Unlocked (CFG_FUSE1.AP_LOCK = 0)',
None: fuses_locked_default}[self._lock_fuses]
# For LLB boot, boot nonce pre-set to 0xdeadbeefdeadbeef. For iBSS boot, set to 0xddccbbaa78563412
if pretty_filename.find('llb') != -1 and self._force_dfu == 0:
boot_nonce = 0xdeadbeefdeadbeef
else:
if self._restore_info_nonce is not None:
boot_nonce = self._restore_info_nonce
else:
boot_nonce = kDefaultApNonceLittleEndian
if self._force_dfu and self._outcome == kOutcomeBlinky:
outcome_string += ' via iBSS in DFU mode'
rom_state = {True: 'r/w access enabled',
False: 'r/w access disabled'}[self._outcome == kOutcomeDfu]
settings.Append(
'Boot Nonce in PMGR Scratch Registers',
[('PMGR_SCRATCH_10', '0x%x' % (boot_nonce & 0xffffffff)),
('PMGR_SCRATCH_11', '0x%x' % ((boot_nonce >> 32) & 0xffffffff)),
])
settings.Append(
'PASS',
[('Outcome', outcome_string),
('ROM', rom_state),
('Keys - UID and GIDs', keys_state),
('Fuses', fuses_locked_state),
(check_usb_clk, ''),
(check_usbotg, check_usbotg_text),
(check_jtag, check_jtag_text),
])
settings.Append(
'FAIL',
[('All PASS conditions not met', ''),
])
if self._manifest:
settings.Append(
'(Informational only - Image4 Personalization Settings Used)',
[('Encryption', self._encryption),
('Crypto Hash Method', self._crypto_hash_method),
('Epoch', self._epoch),
('Chip ID', self._chip_id),
('Board ID', self._board_id),
('ECID', self._ecid),
('Production Status', self._production_status),
('Security Mode', self._security_mode),
('Enable Keys', self._enable_keys),
('DPRO', self._demote_production),
('DSEC', self._demote_secure),
('Security Domain', self._security_domain),
('Allow Mix and Match', self._allow_mix_and_match),
('AP Boot Nonce Hash', self._ap_boot_nonce_hash),
('Restore Info Nonce', self._restore_info_nonce),
('SEP Boot Nonce Hash', self._sep_boot_nonce_hash),
])
settings.Log(self._log)
return True
def main():
help_str = ('Use the source.\n')
class MyParser(optparse.OptionParser):
def format_epilog(self, formatter):
return self.epilog
parser = MyParser(epilog=help_str)
parser.add_option(
'--platform',
help='Override the default platform value of ' + kDefaultPlatform)
parser.add_option(
'--personalize_img4',
help='Override path to personalize_img4 tool')
parser.add_option(
'--img4decodetest',
help='Override path to img4decodetest tool')
parser.add_option(
'--bfn_maker',
help='Override path to bfn_maker tool')
(options, args) = parser.parse_args(sys.argv[1:])
if args:
sys.stderr.write(ErrorText('Unused trailing options: ' + ' '.join(args) + '\n'))
return 1
thisPlat = options.platform
if thisPlat is None:
thisPlat = kDefaultPlatform
output_dir = kOutputDirPrefix + str(thisPlat)
# Determine the chip_id and board_id based on the platform
if thisPlat not in kSupported_platforms:
sys.stderr.write(ErrorText('Only the following platforms are supported by this script: ' + str(kSupported_platforms)))
return 1
elif thisPlat == kDefaultPlatform:
thisChip_id = kDefaultChipId
thisBoard_id = kDefaultBoardId
else:
assert false, "Unknown platform"
# Prune any existing output and re-create the directory.
shutil.rmtree(output_dir, ignore_errors=True)
os.makedirs(output_dir)
log = open(os.path.join(output_dir, kLogFileName), 'w')
log.write('This file generated by iBoot/apps/SecureROM/test_generator_img4\n')
log.write('Generated on: %s GMT\n\n' % time.asctime(time.gmtime()))
# Result code
rc = True
# Test 1:
# Boot from SPI NOR without a manifest in testmode. This facility is sometimes used in the factory
# environment and the test is to ensure that we can successfully
# boot in this environment. This is booting a non-secure image on a
# non-secure part in testmode.
rc &= PersonalizeImg4(manifest = False,
platform = thisPlat,
options = options,
log = log,
test_number = 1,
outcome = kOutcomeBlinky,
image_source = kImageSourceNor,
fuse_production_status = False,
fuse_security_mode = False,
fuse_epoch = 0,
boot_device = 'NOR',
test_mode = True,
description = ('Boot image without manifest in testmode with SPI NOR')
).Execute()
# Test 2:
# Boot from SPI NOR with manifest that disables keys. This is booting a non-secure
# image on a non-secure part.
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 2,
outcome = kOutcomeBlinky,
image_source = kImageSourceNor,
fuse_production_status = False,
fuse_security_mode = False,
fuse_epoch = 0,
production_status = False,
security_mode = False,
boot_device = 'NOR',
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = True,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = False,
encryption = False,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Boot image with manifest that disables keys on an insecure part')
).Execute()
# Test 3:
# Fail to boot a non-production image on a Production part in test mode.
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 3,
outcome = kOutcomeDfu,
image_source = kImageSourceNor,
fuse_production_status = True,
fuse_security_mode = True,
fuse_epoch = 0,
production_status = False,
security_mode = True,
boot_device = 'NOR',
test_mode = True,
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = False,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Fail to boot a non-production image on a Production part in test mode')
).Execute()
# Test 4:
# Boot a development image on a development part.
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 4,
outcome = kOutcomeBlinky,
image_source = kImageSourceNand,
fuse_production_status = False,
fuse_security_mode = True,
fuse_epoch = 0,
production_status = False,
security_mode = True,
boot_device = 'NAND',
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = False,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Boot a development image on a development part')
).Execute()
# Test 5:
# Boot a production image on a production part.
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 5,
outcome = kOutcomeBlinky,
image_source = kImageSourceNor,
fuse_production_status = True,
fuse_security_mode = True,
fuse_epoch = 1,
production_status = True,
security_mode = True,
epoch = kDefaultEpochForServerSigning,
boot_device = 'NOR',
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = True,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Boot a production image on a production part')
).Execute()
# Test 6:
# Test Epoch changes by having a chip epoch greater then the
# certificate epoch, and verifying that the object is rejected.
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 6,
outcome = kOutcomeDfu,
image_source = kImageSourceNor,
fuse_production_status = False,
fuse_security_mode = True,
fuse_epoch = 2,
production_status = False,
security_mode = True,
boot_device = 'NOR',
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = False,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Fail to boot an image with epoch less than chip epoch')
).Execute()
# Test 7:
# Test USB DFU mode on a development device.
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 7,
outcome = kOutcomeBlinky,
image_source = kImageSourceDfu,
fuse_production_status = False,
fuse_security_mode = True,
fuse_epoch = 0,
production_status = False,
security_mode = True,
boot_device = 'NOR',
boot_device_empty = True,
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = False,
description = ('Boot from USB in DFU mode with boot device set to NOR, but NOR is empty')
).Execute()
# Test 8:
# Test Force DFU when a valid image is in NOR. i.e. ignore valid NOR image
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 8,
outcome = kOutcomeBlinky,
image_source = kImageSourceNor,
fuse_production_status = False,
fuse_security_mode = True,
fuse_epoch = 0,
production_status = False,
security_mode = True,
boot_device = 'NOR',
chip_id = thisChip_id,
board_id = thisBoard_id,
force_dfu = 1,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = False,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Boot from USB in DFU mode with boot device set to NOR, and valid image in NOR, but force dfu set')
).Execute()
# Test 9:
# Boot an image in development mode on a production part (Demotion)
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 9,
outcome = kOutcomeBlinky,
image_source = kImageSourceNor,
fuse_production_status = True,
fuse_security_mode = True,
fuse_epoch = 0,
production_status = True,
security_mode = True,
epoch = kDefaultEpochForServerSigning,
boot_device = 'NOR',
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = True,
demote_production = True,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Boot an image in development mode on a production part (Demotion)')
).Execute()
# Test 10:
# Boot from NOR (slow mode) a development image on a development part.
rc &= PersonalizeImg4(platform = thisPlat,
options = options,
log = log,
test_number = 10,
outcome = kOutcomeBlinky,
image_source = kImageSourceNor,
fuse_production_status = False,
fuse_security_mode = True,
fuse_epoch = 0,
production_status = False,
security_mode = True,
boot_device = 'SLOW_NOR',
test_mode = True,
chip_id = thisChip_id,
board_id = thisBoard_id,
ecid = kDefaultEcid,
allow_mix_and_match = False,
ap_boot_nonce_hash = kDefaultApNonceHash,
enable_keys = True,
encryption = False,
restore_info_nonce = kDefaultApNonceLittleEndian,
description = ('Boot from SPI NOR in slow mode a development image on a development part')
).Execute()
log.write("In addition, provide a clock-tree dump (including spare clocks). Please pick a test from 1 to 10 for this dump.\n")
log.close()
if rc:
sys.stdout.write(PassText('\nSuccess\n'))
return 0
else:
sys.stderr.write(ErrorText('\nTest plan contains errors\n'))
return 1
if __name__ == '__main__':
sys.exit(main())