Infineon: Add cyw20829 platform, shared slot feature, json memory map, psoc6 xip
Based in 1.8.0 release of MCUBoot library
This commit adds CYW20829 Infineon platform support with following capabilities:
1. Overwrite and swap upgrade mode support
2. Multi-image with up to 4 images
3. Hardware security counter is supported for CYW20829 platform
Add XIP support for PSOC6 platform - place BOOT slot in external memory and execute it in place using SMIF in XIP mode
and some new features for Infineon devices.
1. Shared upgrade slot feature - use one shared area for upgrade slots of multiple images
2. Memory map defined using JSON file - define memory regions for bootloader and user app in conventional way using JSON file
diff --git a/boot/cypress/scripts/flashmap.py b/boot/cypress/scripts/flashmap.py
new file mode 100644
index 0000000..339e4c5
--- /dev/null
+++ b/boot/cypress/scripts/flashmap.py
@@ -0,0 +1,710 @@
+"""MCUBoot Flash Map Converter (JSON to .h)
+Copyright (c) 2022 Infineon Technologies AG
+"""
+
+import sys
+import getopt
+import json
+
+# Supported Platforms
+platDict = {
+ 'PSOC_062_2M': {
+ 'flashAddr': 0x10000000,
+ 'flashSize': 0x200000, # 2 MBytes
+ 'eraseSize': 0x200, # 512 bytes
+ 'smifAddr': 0x18000000,
+ 'smifSize': 0x8000000 # i.e., window size
+ },
+ 'PSOC_062_1M': {
+ 'flashAddr': 0x10000000,
+ 'flashSize': 0x100000, # 1 MByte
+ 'eraseSize': 0x200, # 512 bytes
+ 'smifAddr': 0x18000000,
+ 'smifSize': 0x8000000 # i.e., window size
+ },
+ 'PSOC_062_512K': {
+ 'flashAddr': 0x10000000,
+ 'flashSize': 0x80000, # 512 KBytes
+ 'eraseSize': 0x200, # 512 bytes
+ 'smifAddr': 0x18000000,
+ 'smifSize': 0x8000000 # i.e., window size
+ },
+ 'CYW20829': {
+ 'flashSize': 0, # n/a
+ 'smifAddr': 0x60000000,
+ 'smifSize': 0x8000000 # i.e., window size
+ }
+}
+
+# Supported SPI Flash ICs
+flashDict = {
+ # Fudan
+ 'FM25Q04': {
+ 'flashSize': 0x80000, # 4 Mbits
+ 'eraseSize': 0x1000, # 128 uniform sectors with 4K-byte each
+ },
+ 'FM25W04': {
+ 'flashSize': 0x80000, # 4 Mbits
+ 'eraseSize': 0x1000, # 128 uniform sectors with 4K-byte each
+ },
+ 'FM25Q08': {
+ 'flashSize': 0x100000, # 8 Mbits
+ 'eraseSize': 0x1000, # 256 uniform sectors with 4K-byte each
+ },
+ 'FM25W08': {
+ 'flashSize': 0x100000, # 8 Mbits
+ 'eraseSize': 0x1000, # 256 uniform sectors with 4K-byte each
+ },
+ # Puya
+ 'P25Q05H': {
+ 'flashSize': 0x10000, # 512 Kbits
+ 'eraseSize': 0x1000, # Uniform 4K-byte Sector Erase
+ },
+ 'P25Q10H': {
+ 'flashSize': 0x20000, # 1 Mbit
+ 'eraseSize': 0x1000, # Uniform 4K-byte Sector Erase
+ },
+ 'P25Q20H': {
+ 'flashSize': 0x40000, # 2 Mbits
+ 'eraseSize': 0x1000, # Uniform 4K-byte Sector Erase
+ },
+ 'P25Q40H': {
+ 'flashSize': 0x80000, # 4 Mbits
+ 'eraseSize': 0x1000, # Uniform 4K-byte Sector Erase
+ },
+ # Infineon
+ 'S25HS256T': {
+ 'flashSize': 0x2000000, # 256 Mbits
+ 'eraseSize': 0x40000, # Uniform Sector Architecture
+ },
+ 'S25HS512T': {
+ 'flashSize': 0x4000000, # 512 Mbits
+ 'eraseSize': 0x40000, # Uniform Sector Architecture
+ },
+ 'S25HS01GT': {
+ 'flashSize': 0x8000000, # 1 Gbit
+ 'eraseSize': 0x40000, # Uniform Sector Architecture
+ }
+}
+
+
+def is_overlap(fa1off, fa1size, fa2off, fa2size, align):
+ """Check if two flash areas on the same device overlap"""
+ mask = align - 1
+ assert align > 0 and (align & mask) == 0 # ensure align is a power of 2
+ fa1end = (fa1off + fa1size + mask) & ~mask
+ fa2end = (fa2off + fa2size + mask) & ~mask
+ fa1off = fa1off & ~mask
+ fa2off = fa2off & ~mask
+ return fa1off < fa2end and fa2off < fa1end
+
+
+def is_same_mem(fa1addr, fa2addr):
+ """Check if two addresses belong to the same memory"""
+ if fa1addr is None or fa2addr is None:
+ return False
+ mask = 0xFF000000
+ return (fa1addr & mask) == (fa2addr & mask)
+
+
+class CmdLineParams:
+ """Command line parameters"""
+
+ def __init__(self):
+ self.plat_id = ''
+ self.in_file = ''
+ self.out_file = ''
+ self.img_id = None
+
+ usage = 'USAGE:\n' + sys.argv[0] + \
+ ''' -p <platform> -i <flash_map.json> -o <flash_map.h> -d <img_id>
+
+OPTIONS:
+-h --help Display the usage information
+-p --platform= Target (e.g., PSOC_062_512K)
+-i --ifile= JSON flash map file
+-o --ofile= C header file to be generated
+-d --img_id ID of application to build'''
+
+ try:
+ opts, unused = getopt.getopt(
+ sys.argv[1:], 'hi:o:p:d:',
+ ['help', 'platform=', 'ifile=', 'ofile=', 'img_id='])
+ if len(unused) > 0:
+ print(usage, file=sys.stderr)
+ sys.exit(1)
+ except getopt.GetoptError:
+ print(usage, file=sys.stderr)
+ sys.exit(1)
+
+ for opt, arg in opts:
+ if opt in ('-h', '--help'):
+ print(usage, file=sys.stderr)
+ sys.exit()
+ elif opt in ('-p', '--platform'):
+ self.plat_id = arg
+ elif opt in ('-i', '--ifile'):
+ self.in_file = arg
+ elif opt in ('-o', '--ofile'):
+ self.out_file = arg
+ elif opt in ('-d', '--img_id'):
+ self.img_id = arg
+
+ if len(self.in_file) == 0 or len(self.out_file) == 0:
+ print(usage, file=sys.stderr)
+ sys.exit(1)
+
+
+class AreaList:
+ """List of flash areas"""
+
+ def __init__(self, plat, flash, use_overwrite):
+ self.plat = plat
+ self.flash = flash
+ self.use_overwrite = use_overwrite
+ self.areas = []
+ self.peers = {}
+ self.trailers = {}
+ self.internal_flash = False
+ self.external_flash = False
+ self.external_flash_xip = False
+
+ def get_min_erase_size(self):
+ """Calculate minimum erase block size for int./ext. Flash """
+ return self.plat['eraseSize'] if self.plat['flashSize'] > 0 \
+ else self.flash['eraseSize']
+
+ def get_img_trailer_size(self):
+ """Calculate image trailer size"""
+ return self.get_min_erase_size()
+
+ def process_int_area(self, title, fa_addr, fa_size,
+ img_trailer_size, shared_slot):
+ """Process internal flash area"""
+ fa_device_id = 'FLASH_DEVICE_INTERNAL_FLASH'
+ fa_off = fa_addr - self.plat['flashAddr']
+ if img_trailer_size is not None:
+ if self.use_overwrite:
+ if shared_slot:
+ print('Shared slot', title,
+ 'is not supported in OVERWRITE mode',
+ file=sys.stderr)
+ sys.exit(7)
+ else:
+ # Check trailer alignment (start at the sector boundary)
+ align = (fa_off + fa_size - img_trailer_size) % \
+ self.plat['eraseSize']
+ if align != 0:
+ fa_addr += self.plat['eraseSize'] - align
+ if fa_addr + fa_size <= \
+ self.plat['flashAddr'] + self.plat['flashSize']:
+ print('Misaligned', title,
+ '- suggested address', hex(fa_addr),
+ file=sys.stderr)
+ else:
+ print('Misaligned', title, file=sys.stderr)
+ sys.exit(7)
+ else:
+ # Check alignment (flash area should start at the sector boundary)
+ if fa_off % self.plat['eraseSize'] != 0:
+ print('Misaligned', title, file=sys.stderr)
+ sys.exit(7)
+ slot_sectors = int((fa_off % self.plat['eraseSize'] +
+ fa_size + self.plat['eraseSize'] - 1) //
+ self.plat['eraseSize'])
+ return fa_device_id, fa_off, slot_sectors
+
+ def process_ext_area(self, title, fa_addr, fa_size,
+ img_trailer_size, shared_slot):
+ """Process external flash area"""
+ if self.flash is None:
+ print('Unspecified SPI Flash IC',
+ file=sys.stderr)
+ sys.exit(3)
+ if fa_addr + fa_size <= \
+ self.plat['smifAddr'] + self.flash['flashSize']:
+ flash_idx = 'CY_BOOT_EXTERNAL_DEVICE_INDEX'
+ fa_device_id = f'FLASH_DEVICE_EXTERNAL_FLASH({flash_idx})'
+ fa_off = fa_addr - self.plat['smifAddr']
+ else:
+ print('Misfitting', title, file=sys.stderr)
+ sys.exit(7)
+ if img_trailer_size is not None:
+ if self.use_overwrite:
+ if shared_slot:
+ print('Shared slot', title,
+ 'is not supported in OVERWRITE mode',
+ file=sys.stderr)
+ sys.exit(7)
+ else:
+ # Check trailer alignment (start at the sector boundary)
+ align = (fa_off + fa_size - img_trailer_size) % \
+ self.flash['eraseSize']
+ if align != 0:
+ peer_addr = self.peers.get(fa_addr)
+ if shared_slot:
+ # Special case when using both int. and ext. memory
+ if self.plat['flashSize'] > 0 and \
+ align % self.plat['eraseSize'] == 0:
+ print('Note:', title, 'requires', align,
+ 'padding bytes before trailer',
+ file=sys.stderr)
+ else:
+ print('Misaligned', title, file=sys.stderr)
+ sys.exit(7)
+ elif is_same_mem(fa_addr, peer_addr) and \
+ fa_addr % self.flash['eraseSize'] == \
+ peer_addr % self.flash['eraseSize']:
+ pass # postpone checking
+ else:
+ fa_addr += self.flash['eraseSize'] - align
+ if fa_addr + fa_size <= \
+ self.plat['smifAddr'] + self.flash['flashSize']:
+ print('Misaligned', title,
+ '- suggested address', hex(fa_addr),
+ file=sys.stderr)
+ else:
+ print('Misaligned', title, file=sys.stderr)
+ sys.exit(7)
+ else:
+ # Check alignment (flash area should start at the sector boundary)
+ if fa_off % self.flash['eraseSize'] != 0:
+ print('Misaligned', title, file=sys.stderr)
+ sys.exit(7)
+ slot_sectors = int((fa_off % self.flash['eraseSize'] +
+ fa_size + self.flash['eraseSize'] - 1) //
+ self.flash['eraseSize'])
+ self.external_flash = True
+ if self.flash['XIP']:
+ self.external_flash_xip = True
+ return fa_device_id, fa_off, slot_sectors
+
+ def chk_area(self, fa_addr, fa_size, peer_addr=None):
+ """Check area location (internal/external flash)"""
+ if peer_addr is not None:
+ self.peers[peer_addr] = fa_addr
+ fa_limit = fa_addr + fa_size
+ if self.plat['flashSize'] and \
+ fa_addr >= self.plat['flashAddr'] and \
+ fa_limit <= self.plat['flashAddr'] + self.plat['flashSize']:
+ # Internal flash
+ self.internal_flash = True
+
+ def add_area(self, title,
+ fa_id, fa_addr, fa_size,
+ img_trailer_size=None, shared_slot=False):
+ """Add flash area to AreaList.
+ Internal/external flash is detected by address.
+ Returns number of sectors in a slot"""
+ if fa_size == 0:
+ print('Empty', title, file=sys.stderr)
+ sys.exit(7)
+
+ fa_limit = fa_addr + fa_size
+ if self.plat['flashSize'] and \
+ fa_addr >= self.plat['flashAddr'] and \
+ fa_limit <= self.plat['flashAddr'] + self.plat['flashSize']:
+ # Internal flash
+ fa_device_id, fa_off, slot_sectors = self.process_int_area(
+ title, fa_addr, fa_size, img_trailer_size, shared_slot)
+ align = self.plat['eraseSize']
+ elif self.plat['smifSize'] and \
+ fa_addr >= self.plat['smifAddr'] and \
+ fa_limit <= self.plat['smifAddr'] + self.plat['smifSize']:
+ # External flash
+ fa_device_id, fa_off, slot_sectors = self.process_ext_area(
+ title, fa_addr, fa_size, img_trailer_size, shared_slot)
+ align = self.flash['eraseSize']
+ else:
+ print('Invalid', title, file=sys.stderr)
+ sys.exit(7)
+
+ if shared_slot:
+ assert img_trailer_size is not None
+ tr_addr = fa_addr + fa_size - img_trailer_size
+ tr_name = self.trailers.get(tr_addr)
+ if tr_name is not None:
+ print('Same trailer address for', title, 'and', tr_name,
+ file=sys.stderr)
+ sys.exit(7)
+ self.trailers[tr_addr] = title
+
+ # Ensure no flash areas on this device will overlap, except the
+ # shared slot
+ for area in self.areas:
+ if fa_device_id == area['fa_device_id']:
+ over = is_overlap(fa_off, fa_size,
+ area['fa_off'], area['fa_size'],
+ align)
+ if shared_slot and area['shared_slot']:
+ if not over: # images in shared slot should overlap
+ print(title, 'is not shared with', area['title'],
+ file=sys.stderr)
+ sys.exit(7)
+ elif over:
+ print(title, 'overlaps with', area['title'],
+ file=sys.stderr)
+ sys.exit(7)
+
+ self.areas.append({'title': title,
+ 'shared_slot': shared_slot,
+ 'fa_id': fa_id,
+ 'fa_device_id': fa_device_id,
+ 'fa_off': fa_off,
+ 'fa_size': fa_size})
+ return slot_sectors
+
+ def generate_c_source(self, params):
+ """Generate C source"""
+ c_array = 'flash_areas'
+
+ try:
+ with open(params.out_file, "w", encoding='UTF-8') as out_f:
+ out_f.write('/* AUTO-GENERATED FILE, DO NOT EDIT.'
+ ' ALL CHANGES WILL BE LOST! */\n')
+ out_f.write(f'/* Platform: {params.plat_id} */\n')
+ out_f.write(f'\nstatic struct flash_area {c_array}[] = {{\n')
+ comma = len(self.areas)
+ area_count = 0
+ for area in self.areas:
+ comma -= 1
+ if area['fa_id'] is not None:
+ sss = ' /* Shared secondary slot */' \
+ if area['shared_slot'] else ''
+ out_f.writelines('\n'.join([
+ ' {' + sss,
+ f" .fa_id = {area['fa_id']},",
+ f" .fa_device_id = {area['fa_device_id']},",
+ f" .fa_off = {hex(area['fa_off'])}U,",
+ f" .fa_size = {hex(area['fa_size'])}U",
+ ' },' if comma else ' }', '']))
+ area_count += 1
+ out_f.write('};\n\n'
+ 'struct flash_area *boot_area_descs[] = {\n')
+ for area_index in range(area_count):
+ out_f.write(f' &{c_array}[{area_index}U],\n')
+ out_f.write(' NULL\n};\n')
+ except (FileNotFoundError, OSError):
+ print('Cannot create', params.out_file, file=sys.stderr)
+ sys.exit(4)
+
+
+def cvt_dec_or_hex(val, desc):
+ """Convert (hexa)decimal string to number"""
+ try:
+ return int(val, 0)
+ except ValueError:
+ print('Invalid value', val, 'for', desc, file=sys.stderr)
+ sys.exit(6)
+
+
+def get_val(obj, attr):
+ """Get JSON 'value'"""
+ obj = obj[attr]
+ try:
+ return cvt_dec_or_hex(obj['value'], obj['description'])
+ except KeyError as key:
+ print('Malformed JSON:', key,
+ 'is missing in', "'" + attr + "'",
+ file=sys.stderr)
+ sys.exit(5)
+
+
+def get_bool(obj, attr, def_val=False):
+ """Get JSON boolean value (returns def_val if it missing)"""
+ ret_val = def_val
+ obj = obj.get(attr)
+ if obj is not None:
+ try:
+ val = str(obj['value']).lower()
+ desc = obj['description']
+ if val == 'true':
+ ret_val = True
+ elif val == 'false':
+ ret_val = False
+ else:
+ print('Invalid value', val, 'for', desc, file=sys.stderr)
+ sys.exit(6)
+ except KeyError as key:
+ print('Malformed JSON:', key,
+ 'is missing in', "'" + attr + "'",
+ file=sys.stderr)
+ sys.exit(5)
+ return ret_val
+
+
+class AddrSize:
+ """Bootloader area"""
+
+ def __init__(self, bootloader, addr_name, size_name):
+ self.fa_addr = get_val(bootloader, addr_name)
+ self.fa_size = get_val(bootloader, size_name)
+
+
+def calc_status_size(boot_swap_status_row_sz, max_img_sectors,
+ img_number, scratch_flag=True):
+ """Estimate status size, see swap_status.h"""
+ boot_swap_status_cnt_sz = 4
+ boot_swap_status_crc_sz = 4
+ boot_swap_status_mgcrec_sz = 4
+ boot_swap_status_trailer_size = 64
+ boot_swap_status_payld_sz = \
+ boot_swap_status_row_sz - boot_swap_status_mgcrec_sz - \
+ boot_swap_status_cnt_sz - boot_swap_status_crc_sz
+ boot_swap_status_sect_rows_num = \
+ int((max_img_sectors - 1) //
+ boot_swap_status_payld_sz) + 1
+ boot_swap_status_trail_rows_num = \
+ int((boot_swap_status_trailer_size - 1) //
+ boot_swap_status_payld_sz) + 1
+ boot_swap_status_d_size = \
+ boot_swap_status_row_sz * \
+ (boot_swap_status_sect_rows_num + boot_swap_status_trail_rows_num)
+ boot_swap_status_mult = 2
+ boot_swap_status_size = boot_swap_status_mult * boot_swap_status_d_size
+ status_zone_cnt = 2 * img_number
+ if scratch_flag:
+ status_zone_cnt += 1
+ return boot_swap_status_size * status_zone_cnt
+
+
+def process_json(in_file):
+ """Process JSON"""
+ try:
+ with open(in_file, encoding='UTF-8') as in_f:
+ try:
+ flash_map = json.load(in_f)
+ except ValueError:
+ print('Cannot parse', in_file, file=sys.stderr)
+ sys.exit(4)
+ except (FileNotFoundError, OSError):
+ print('Cannot open', in_file, file=sys.stderr)
+ sys.exit(4)
+ flash = flash_map.get('external_flash')
+ if flash is not None:
+ flash = flash[0]
+ model = flash.get('model')
+ mode = flash.get('mode')
+ if model is not None:
+ try:
+ flash = flashDict[model]
+ except KeyError:
+ print('Supported SPI Flash ICs are:',
+ ', '.join(flashDict.keys()),
+ file=sys.stderr)
+ sys.exit(3)
+ else:
+ try:
+ flash = {'flashSize': cvt_dec_or_hex(flash['flash-size'],
+ 'flash-size'),
+ 'eraseSize': cvt_dec_or_hex(flash['erase-size'],
+ 'erase-size')}
+ except KeyError as key:
+ print('Malformed JSON:', key,
+ "is missing in 'external_flash'",
+ file=sys.stderr)
+ sys.exit(3)
+ flash.update({'XIP': str(mode).upper() == 'XIP'})
+ return flash_map['boot_and_upgrade'], flash
+
+
+def process_images(area_list, boot_and_upgrade):
+ """Process images"""
+ app_count = 0
+ slot_sectors_max = 0
+ all_shared = get_bool(boot_and_upgrade['bootloader'], 'shared_slot')
+ any_shared = all_shared
+
+ apps_flash_map = [None, ]
+
+ for stage in range(2):
+ for app_index in range(1, 5):
+
+ app_flash_map = {}
+
+ try:
+ app_ident = f'application_{app_index}'
+ application = boot_and_upgrade[app_ident]
+ try:
+ primary_addr = get_val(application, 'address')
+ primary_size = get_val(application, 'size')
+ secondary_addr = get_val(application, 'upgrade_address')
+ secondary_size = get_val(application, 'upgrade_size')
+ except KeyError as key:
+ print('Malformed JSON:', key, 'is missing',
+ file=sys.stderr)
+ sys.exit(5)
+ if stage == 0:
+ if primary_size != secondary_size:
+ print('Primary and secondary slot sizes'
+ ' are different for', app_ident,
+ file=sys.stderr)
+ sys.exit(6)
+ area_list.chk_area(primary_addr, primary_size)
+ area_list.chk_area(secondary_addr, secondary_size,
+ primary_addr)
+ else:
+ slot_sectors_max = max(
+ slot_sectors_max,
+ area_list.add_area(
+ f'{app_ident} (primary slot)',
+ f'FLASH_AREA_IMG_{app_index}_PRIMARY',
+ primary_addr, primary_size,
+ area_list.get_img_trailer_size()))
+ shared_slot = get_bool(application, 'shared_slot', all_shared)
+ any_shared = any_shared or shared_slot
+ slot_sectors_max = max(
+ slot_sectors_max,
+ area_list.add_area(
+ f'{app_ident} (secondary slot)',
+ f'FLASH_AREA_IMG_{app_index}_SECONDARY',
+ secondary_addr, secondary_size,
+ area_list.get_img_trailer_size(),
+ shared_slot))
+
+ app_slot_prim = {"address": hex(primary_addr), "size": hex(primary_size)}
+ app_slot_sec = {"address": hex(secondary_addr), "size": hex(secondary_size)}
+
+ app_flash_map.update({"primary": app_slot_prim, "secondary": app_slot_sec})
+ apps_flash_map.append(app_flash_map)
+
+ app_count = app_index
+
+ except KeyError:
+ break
+ if app_count == 0:
+ print('Malformed JSON: no application(s) found',
+ file=sys.stderr)
+ sys.exit(5)
+
+ return app_count, slot_sectors_max, apps_flash_map, any_shared
+
+
+def main():
+ """Flash map converter"""
+ params = CmdLineParams()
+
+ try:
+ plat = platDict[params.plat_id]
+ except KeyError:
+ print('Supported platforms are:', ', '.join(platDict.keys()),
+ file=sys.stderr)
+ sys.exit(2)
+
+ try:
+ boot_and_upgrade, flash = process_json(params.in_file)
+ bootloader = boot_and_upgrade['bootloader']
+ boot = AddrSize(bootloader, 'address', 'size')
+ except KeyError as key:
+ print('Malformed JSON:', key, 'is missing',
+ file=sys.stderr)
+ sys.exit(5)
+
+ try:
+ scratch = AddrSize(bootloader, 'scratch_address', 'scratch_size')
+ except KeyError:
+ scratch = None
+
+ try:
+ swap_status = AddrSize(bootloader, 'status_address', 'status_size')
+ except KeyError:
+ swap_status = None
+
+ # Create flash areas
+ area_list = AreaList(plat, flash, scratch is None and swap_status is None)
+ area_list.add_area('bootloader', 'FLASH_AREA_BOOTLOADER',
+ boot.fa_addr, boot.fa_size)
+
+ # Service RAM app (optional)
+ service_app = boot_and_upgrade.get('service_app')
+ app_binary = None
+ input_params = None
+ app_desc = None
+ if service_app is not None:
+ if plat['flashSize'] > 0:
+ print('service_app is unsupported on this platform',
+ file=sys.stderr)
+ sys.exit(7)
+ try:
+ app_binary = AddrSize(service_app, 'address', 'size')
+ input_params = AddrSize(service_app, 'params_address', 'params_size')
+ app_desc = AddrSize(service_app, 'desc_address', 'desc_size')
+ if input_params.fa_addr != app_binary.fa_addr + app_binary.fa_size or \
+ app_desc.fa_addr != input_params.fa_addr + input_params.fa_size or \
+ app_desc.fa_size != 0x20:
+ print('Malformed service_app definition', file=sys.stderr)
+ sys.exit(7)
+ area_list.add_area('service_app', None, app_binary.fa_addr,
+ app_binary.fa_size + input_params.fa_size + app_desc.fa_size)
+ except KeyError as key:
+ print('Malformed JSON:', key, 'is missing',
+ file=sys.stderr)
+ sys.exit(5)
+
+ # Fill flash areas
+ app_count, slot_sectors_max, apps_flash_map, shared_slot = \
+ process_images(area_list, boot_and_upgrade)
+
+ slot_sectors_max = max(slot_sectors_max, 32)
+
+ if swap_status is not None:
+ status_size_min = calc_status_size(area_list.get_min_erase_size(),
+ slot_sectors_max,
+ app_count,
+ scratch is not None)
+
+ if swap_status.fa_size < status_size_min:
+ print('Insufficient swap status area - suggested size',
+ hex(status_size_min),
+ file=sys.stderr)
+ sys.exit(7)
+ area_list.add_area('swap status partition',
+ 'FLASH_AREA_IMAGE_SWAP_STATUS',
+ swap_status.fa_addr, swap_status.fa_size)
+
+ if scratch is not None:
+ area_list.add_area('scratch area',
+ 'FLASH_AREA_IMAGE_SCRATCH',
+ scratch.fa_addr, scratch.fa_size)
+
+ # Image id parameter is not used for MCUBootApp
+ if params.img_id is None:
+ area_list.generate_c_source(params)
+
+ # Report necessary values back to make
+ print('# AUTO-GENERATED FILE, DO NOT EDIT. ALL CHANGES WILL BE LOST!')
+
+ if params.img_id is not None:
+ primary_img_start = (apps_flash_map[int(params.img_id)].get("primary")).get("address")
+ secondary_img_start = (apps_flash_map[int(params.img_id)].get("secondary")).get("address")
+ bootloader_size = (bootloader.get("size")).get("value")
+ slot_size = (apps_flash_map[int(params.img_id)].get("primary")).get("size")
+
+ print('PRIMARY_IMG_START := ' + primary_img_start)
+ print('SECONDARY_IMG_START := ' + secondary_img_start)
+ print('SLOT_SIZE := ' + slot_size)
+ print('BOOTLOADER_SIZE := ' + bootloader_size)
+ else:
+ print('MCUBOOT_IMAGE_NUMBER :=', app_count)
+ print('MAX_IMG_SECTORS :=', slot_sectors_max)
+
+ if area_list.use_overwrite:
+ print('USE_OVERWRITE := 1')
+ if area_list.external_flash:
+ print('USE_EXTERNAL_FLASH := 1')
+ if area_list.external_flash_xip:
+ print('USE_XIP := 1')
+ if shared_slot:
+ print('USE_SHARED_SLOT := 1')
+ if service_app is not None:
+ print('PLATFORM_SERVICE_APP_OFFSET :=',
+ hex(app_binary.fa_addr - plat['smifAddr']))
+ print('PLATFORM_SERVICE_APP_INPUT_PARAMS_OFFSET :=',
+ hex(input_params.fa_addr - plat['smifAddr']))
+ print('PLATFORM_SERVICE_APP_DESC_OFFSET :=',
+ hex(app_desc.fa_addr - plat['smifAddr']))
+ print('USE_HW_ROLLBACK_PROT := 1')
+
+
+if __name__ == '__main__':
+ main()