Infineon: Switch to 1.9.0 code base, add xmc7000 family support, refactor memory layer
diff --git a/boot/cypress/scripts/memorymap.py b/boot/cypress/scripts/memorymap.py
new file mode 100644
index 0000000..5511c9a
--- /dev/null
+++ b/boot/cypress/scripts/memorymap.py
@@ -0,0 +1,1434 @@
+"""MCUBoot Flash Map Converter (JSON to .h)
+Copyright (c) 2022 Infineon Technologies AG
+"""
+
+import sys
+import getopt
+import json
+from enum import Enum
+import os.path
+
+class Error(Enum):
+ ''' Application error codes '''
+ ARG = 1
+ POLICY = 2
+ FLASH = 3
+ IO = 4
+ JSON = 5
+ VALUE = 6
+ CONFIG_MISMATCH = 7
+
+SERVICE_APP_SZ = 0x20
+
+c_array = 'flash_areas'
+
+# Supported Platforms
+cm0pCore = {
+ 'cortex-m0+': 'CM0P',
+ 'cm0+': 'CM0P',
+ 'm0+': 'CM0P',
+ 'cortex-m0p': 'CM0P',
+ 'cm0p': 'CM0P',
+ 'm0p': 'CM0P',
+ 'cortex-m0plus': 'CM0P',
+ 'cm0plus': 'CM0P',
+ 'm0plus': 'CM0P'
+}
+
+cm4Core = {
+ 'cortex-m4': 'CM4',
+ 'cm4': 'CM4',
+ 'm4': 'CM4'
+}
+
+cm33Core = {
+ 'cortex-m33': 'CM33',
+ 'cm33': 'CM33',
+ 'm33': 'CM33'
+}
+
+cm7Core = {
+ 'cortex-m7': 'CM7',
+ 'cm7': 'CM7',
+ 'm7': 'CM7'
+}
+
+allCores_PSOC_06x = {**cm0pCore, **cm4Core}
+
+common_PSOC_061 = {
+ 'flashAddr': 0x10000000,
+ 'eraseSize': 0x200, # 512 bytes
+ 'smifAddr': 0x18000000,
+ 'smifSize': 0x8000000, # i.e., window size
+ 'VTAlign': 0x400, # Vector Table alignment
+ 'allCores': cm4Core,
+ 'bootCore': 'Cortex-M4',
+ 'appCore': 'Cortex-M4'
+}
+
+common_PSOC_06x = {
+ 'flashAddr': 0x10000000,
+ 'eraseSize': 0x200, # 512 bytes
+ 'smifAddr': 0x18000000,
+ 'smifSize': 0x8000000, # i.e., window size
+ 'VTAlign': 0x400, # Vector Table alignment
+ 'allCores': allCores_PSOC_06x,
+ 'bootCore': 'Cortex-M0+',
+ 'appCore': 'Cortex-M4'
+}
+
+common_XMC7000 = {
+ 'flashAddr': 0x10000000,
+ 'eraseSize': 0x8000, # 512 bytes
+ 'smifAddr': 0x18000000,
+ 'smifSize': 0x8000000, # i.e., window size
+ 'VTAlign': 0x400, # Vector Table alignment
+ 'allCores': cm7Core,
+ 'bootCore': 'Cortex-M7',
+ 'appCore': 'Cortex-M7'
+}
+
+common_PSE84 = {
+ 'flashAddr': 0x32000000,
+ 'flashSize': 0x40000,
+ 'eraseSize': 0x20, # 32 bytes
+ 'smifAddr': 0x60000000, #secure address
+ 'smifSize': 0x4000000, # i.e., window size
+ 'VTAlign': 0x400, # Vector Table alignment
+ 'allCores': cm33Core,
+ 'bootCore': 'Cortex-M33',
+ 'appCore': 'Cortex-M33'
+}
+
+platDict = {
+ 'PSOC_061_2M': {
+ 'flashSize': 0x200000, # 2 MBytes
+ **common_PSOC_061
+ },
+ 'PSOC_061_1M': {
+ 'flashSize': 0x100000, # 1 MByte
+ **common_PSOC_061
+ },
+ 'PSOC_061_512K': {
+ 'flashSize': 0x80000, # 512 KBytes
+ **common_PSOC_061
+ },
+
+ 'PSOC_062_2M': {
+ 'flashSize': 0x200000, # 2 MBytes
+ **common_PSOC_06x
+ },
+ 'PSOC_062_1M': {
+ 'flashSize': 0x100000, # 1 MByte
+ **common_PSOC_06x
+ },
+ 'PSOC_062_512K': {
+ 'flashSize': 0x80000, # 512 KBytes
+ **common_PSOC_06x
+ },
+
+ 'PSOC_063_1M': {
+ 'flashSize': 0x100000, # 1 MByte
+ **common_PSOC_06x
+ },
+
+ 'XMC7200': {
+ 'flashSize': 0x100000, # 1 MByte
+ **common_XMC7000
+ },
+
+ 'XMC7100': {
+ 'flashSize': 0x100000, # 1 MByte
+ **common_PSOC_06x
+ },
+
+ 'CYW20829': {
+ 'flashSize': 0, # n/a
+ 'smifAddr': 0x60000000,
+ 'smifSize': 0x8000000, # i.e., window size
+ 'VTAlign': 0x200, # Vector Table alignment
+ 'allCores': cm33Core,
+ 'bootCore': 'Cortex-M33',
+ 'appCore': 'Cortex-M33',
+ 'bitsPerCnt': False
+ },
+
+ 'PSE84_L4': {
+ **common_PSE84
+ },
+
+ 'PSE84_L2': {
+ **common_PSE84
+ }
+}
+
+# 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.fa_file = ''
+ self.img_id = None
+ self.policy = None
+ self.set_core = False
+ self.image_boot_config = False
+
+ usage = 'USAGE:\n' + sys.argv[0] + \
+ ''' -p <platform> -i <flash_map.json> -o <memorymap.c> -a <memorymap.h> -d <img_id> -c <policy.json>
+
+OPTIONS:
+-h --help Display the usage information
+-p --platform= Target (e.g., PSOC_062_512K)
+-i --ifile= JSON flash map file
+-o --ofile= C file to be generated
+-a --fa_file= path where to create 'memorymap.h'
+-d --img_id ID of application to build
+-c --policy Policy file in JSON format
+-m --core Detect and set Cortex-M CORE
+-x --image_boot_config Generate image boot config structure
+'''
+
+ try:
+ opts, unused = getopt.getopt(
+ sys.argv[1:], 'hi:o:a:p:d:c:x:m',
+ ['help', 'platform=', 'ifile=', 'ofile=', "fa_file=", 'img_id=', 'policy=', 'core', 'image_boot_config'])
+ except getopt.GetoptError:
+ print(usage, file=sys.stderr)
+ sys.exit(Error.ARG)
+
+ 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 ('-a', '--fa_file'):
+ self.fa_file = arg
+ elif opt in ('-d', '--img_id'):
+ self.img_id = arg
+ elif opt in ('-c', '--policy'):
+ self.policy = arg
+ elif opt in ('-m', '--core'):
+ self.set_core = True
+ elif opt in ('x', '--image_boot_config'):
+ self.image_boot_config = True
+
+ if len(self.in_file) == 0 or len(self.out_file) == 0 or len(self.fa_file) == 0:
+ print(usage, file=sys.stderr)
+ sys.exit(Error.ARG)
+
+
+class AreaList:
+ '''
+ A List of flash areas
+ ...
+
+ Attributes
+ ----------
+ plat : dict
+ Platform settings
+
+ flash : dict
+ External flash settings
+
+ use_overwrite : bool
+ Overwrite configuration in use
+
+ areas : list
+ Flash area parameter list
+
+ peers : set
+ Peers
+
+ trailers : set
+ Flash area trailers
+
+ internal_flash : bool
+ Internal flash in use
+
+ external_flash : bool
+ External flash in use
+
+ external_flash_xip : bool
+ External XIP in use
+
+ Methods
+ -------
+ get_min_erase_size:
+ Calculate minimum erase block size for int./ext. Flash
+
+ get_img_trailer_size:
+ Calculate image trailer size
+
+ process_int_area:
+ Process internal flash area
+
+ process_ext_area:
+ Process external flash area
+
+ chk_area:
+ Check area location (internal/external flash)
+
+ add_area:
+ Add flash area to AreaList.
+ Internal/external flash is detected by address.
+
+ generate_c_source:
+ Generate C source
+
+ create_flash_area_id:
+ Creates flash_area_id.h file.
+ '''
+
+ 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, addr, fa_size,
+ img_trailer_size, shared_slot):
+ '''
+ Process internal flash area
+ Parameters:
+ ----------
+ title : str
+ Area name
+
+ addr : int
+ Area address
+
+ fa_size : int
+ Area size
+
+ img_trailer_size : int
+ Trailer size
+
+ shared_slot : bool
+ Shared slot option in use
+
+ Returns:
+ ----------
+ fa_device_id : str
+
+ fa_off : int
+
+ slot_sectors : int
+ '''
+ fa_device_id = 'FLASH_DEVICE_INTERNAL_FLASH'
+ fa_off = 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(Error.CONFIG_MISMATCH)
+ else:
+ # Check trailer alignment (start at the sector boundary)
+ align = (fa_off + fa_size - img_trailer_size) % \
+ self.plat['eraseSize']
+ if align != 0:
+ addr += self.plat['eraseSize'] - align
+ if addr + fa_size <= \
+ self.plat['flashAddr'] + self.plat['flashSize']:
+ print('Misaligned', title,
+ '- suggested address', hex(addr),
+ file=sys.stderr)
+ else:
+ print('Misaligned', title, file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+ 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(Error.CONFIG_MISMATCH)
+ 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, addr, fa_size,
+ img_trailer_size, shared_slot):
+ '''
+ Process external flash area
+ Parameters:
+ ----------
+ title : str
+ Area name
+
+ addr : int
+ Area address
+
+ fa_size : int
+ Area size
+
+ img_trailer_size : int
+ Trailer size
+
+ shared_slot : bool
+ Shared slot option in use
+
+ Returns:
+ ----------
+ fa_device_id : str
+
+ fa_off : int
+
+ slot_sectors : int
+ '''
+ if self.flash is None:
+ print('Unspecified SPI Flash IC',
+ file=sys.stderr)
+ sys.exit(Error.FLASH)
+ if 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 = addr - self.plat['smifAddr']
+ else:
+ print('Misfitting', title, file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+ 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(Error.CONFIG_MISMATCH)
+ 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(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(Error.CONFIG_MISMATCH)
+ elif is_same_mem(addr, peer_addr) and \
+ addr % self.flash['eraseSize'] == \
+ peer_addr % self.flash['eraseSize']:
+ pass # postpone checking
+ else:
+ addr += self.flash['eraseSize'] - align
+ if addr + fa_size <= \
+ self.plat['smifAddr'] + self.flash['flashSize']:
+ print('Misaligned', title,
+ '- suggested address', hex(addr),
+ file=sys.stderr)
+ else:
+ print('Misaligned', title, file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+ 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(Error.CONFIG_MISMATCH)
+ 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, addr, fa_size, peer_addr=None):
+ '''
+ Check area location (internal/external flash)
+ Parameters:
+ ----------
+ addr : int
+ Area address
+
+ fa_size : int
+ Area size
+
+ peer_addr : bool (optional)
+ Shared slot option in use
+
+ Returns:
+ ----------
+ None
+ '''
+ if peer_addr is not None:
+ self.peers[peer_addr] = addr
+ fa_limit = addr + fa_size
+ if self.plat['flashSize'] and \
+ 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, addr, fa_size,
+ img_trailer_size=None, shared_slot=False):
+ '''
+ Add flash area to AreaList.
+ Internal/external flash is detected by address.
+ Parameters:
+ ----------
+ title : str
+ Area name
+
+ fa_id : str
+ Area id
+
+ addr : int
+ Area address
+
+ fa_size : int
+ Area size
+
+ img_trailer_size : int
+ Trailer size (optional)
+
+ shared_slot : bool
+ Shared slot option in use (optional)
+
+ Returns:
+ ----------
+ slot_sectors : int
+ Number of sectors in a slot
+ '''
+ if fa_size == 0:
+ print('Empty', title, file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+
+ fa_limit = addr + fa_size
+ if self.plat['flashSize'] and \
+ 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, addr, fa_size, img_trailer_size, shared_slot)
+ align = self.plat['eraseSize']
+ elif self.plat['smifSize'] and \
+ 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, addr, fa_size, img_trailer_size, shared_slot)
+ align = self.flash['eraseSize']
+ else:
+ print('Invalid', title, file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+
+ if shared_slot:
+ assert img_trailer_size is not None
+ tr_addr = 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(Error.CONFIG_MISMATCH)
+ 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(Error.CONFIG_MISMATCH)
+ elif over:
+ print(title, 'overlaps with', area['title'],
+ file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+
+ 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
+ Parameters:
+ ----------
+ params : CmdLineParams
+ Application parameters
+
+ Returns:
+ ----------
+ None
+ '''
+ c_array = 'flash_areas'
+
+ try:
+ with open(params.out_file, "w", encoding='UTF-8') as out_f:
+
+ out_f.write(f'#include "{params.fa_file}"\n')
+ out_f.write(f'#include "flash_map_backend.h"\n\n')
+ out_f.write(f'#include "flash_map_backend_platform.h"\n\n')
+ out_f.write(f'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')
+ out_f.close()
+
+ except (FileNotFoundError, OSError):
+ print('Cannot create', params.out_file, file=sys.stderr)
+ sys.exit(Error.IO)
+
+ def create_flash_area_id(self, img_number, params):
+ """ Get 'img_number' and generate flash_area_id.h file' """
+
+ #check if params.fa_file already exists and it has FLASH_AREA_ID
+ if os.path.exists(params.fa_file):
+ with open(params.fa_file, "r", encoding='UTF-8') as fa_f:
+ content = fa_f.read()
+ res = content.find(f"FLASH_AREA_IMG_{img_number}_SECONDARY")
+ if res != -1:
+ fa_f.close()
+ return
+
+ fa_f.close()
+
+ try:
+ with open(params.fa_file, "w", encoding='UTF-8') as fa_f:
+ fa_f.write("#ifndef MEMORYMAP_H\n")
+ fa_f.write("#define MEMORYMAP_H\n\n")
+ fa_f.write('/* AUTO-GENERATED FILE, DO NOT EDIT.'
+ ' ALL CHANGES WILL BE LOST! */\n')
+ fa_f.write(f'#include "flash_map_backend.h"\n\n')
+
+ fa_f.write(f'extern struct flash_area {c_array}[];\n')
+ fa_f.write(f'extern struct flash_area *boot_area_descs[];\n')
+
+ #we always have BOOTLOADER and IMG_1_
+ fa_f.write("#define FLASH_AREA_BOOTLOADER ( 0u)\n\n")
+ fa_f.write("#define FLASH_AREA_IMG_1_PRIMARY ( 1u)\n")
+ fa_f.write("#define FLASH_AREA_IMG_1_SECONDARY ( 2u)\n\n")
+
+ fa_f.write("#define FLASH_AREA_IMAGE_SCRATCH ( 3u)\n")
+ fa_f.write("#define FLASH_AREA_IMAGE_SWAP_STATUS ( 7u)\n\n")
+
+ for img in range(2, img_number + 1):
+ """ img_id_primary and img_id_secondary must be aligned with the
+ flash_area_id, calculated in the functions
+ __STATIC_INLINE uint8_t FLASH_AREA_IMAGE_PRIMARY(uint32_t img_idx) and
+ __STATIC_INLINE uint8_t FLASH_AREA_IMAGE_SECONDARY(uint32_t img_idx),
+ in boot/cypress/platforms/memory/sysflash/sysflash.h
+ """
+
+ slots_for_image = 2
+ img_id_primary = None
+ img_id_secondary = None
+
+ if img == 2:
+ img_id_primary = int(slots_for_image * img)
+ img_id_secondary = int(slots_for_image * img + 1)
+
+ #number 7 is used for FLASH_AREA_IMAGE_SWAP_STATUS, so the next is 8
+ if img >= 3:
+ img_id_primary = int(slots_for_image * img + 2)
+ img_id_secondary = int(slots_for_image * img + 3)
+
+ fa_f.write(f"#define FLASH_AREA_IMG_{img}_PRIMARY ( {img_id_primary}u)\n")
+ fa_f.write(f"#define FLASH_AREA_IMG_{img}_SECONDARY ( {img_id_secondary}u)\n\n")
+
+ if self.plat.get('bitsPerCnt'):
+ fa_f.close()
+
+ list_counters = process_policy_20829(params.policy)
+ if list_counters is not None:
+ form_max_counter_array(list_counters, params.fa_file)
+ else:
+ fa_f.write("#endif /* MEMORYMAP_H */")
+ fa_f.close()
+
+ except (FileNotFoundError, OSError):
+ print('\nERROR: Cannot create ', params.fa_file, file=sys.stderr)
+ sys.exit(Error.IO)
+
+
+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(Error.VALUE)
+
+
+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(Error.JSON)
+
+
+def get_bool(obj, attr, def_val=False):
+ """Get JSON boolean value (returns def_val if it is 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(Error.VALUE)
+ except KeyError as key:
+ print('Malformed JSON:', key,
+ 'is missing in', "'" + attr + "'",
+ file=sys.stderr)
+ sys.exit(Error.JSON)
+ return ret_val
+
+
+def get_str(obj, attr, def_val=None):
+ """Get JSON string value (returns def_val if it is missing)"""
+ ret_val = def_val
+ obj = obj.get(attr)
+ if obj is not None:
+ try:
+ ret_val = str(obj['value'])
+ except KeyError as key:
+ print('Malformed JSON:', key,
+ 'is missing in', "'" + attr + "'",
+ file=sys.stderr)
+ sys.exit(Error.JSON)
+ return ret_val
+
+
+class AddrSize:
+ """Bootloader area"""
+
+ def __init__(self, bootloader, addr_name, size_name):
+ self.addr = get_val(bootloader, addr_name)
+ self.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(Error.IO)
+ except (FileNotFoundError, OSError):
+ print('Cannot open', in_file, file=sys.stderr)
+ sys.exit(Error.IO)
+ 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(Error.FLASH)
+ 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(Error.FLASH)
+ flash.update({'XIP': str(mode).upper() == 'XIP'})
+ return flash_map.get('boot_and_upgrade', None), flash_map.get('ram_app_staging', None), flash
+
+def process_boot_type(boot_and_upgrade):
+ image_boot_mode = []
+
+ for app_index in range(1, 5):
+ app_ident = f'application_{app_index}'
+ application = boot_and_upgrade.get(app_ident)
+
+ if application:
+ ram = application.get('ram', application.get('ram_boot'))
+
+ if ram:
+ image_boot_mode.append(
+ {
+ 'mode': 'IMAGE_BOOT_MODE_FLASH' if application.get('ram') else 'IMAGE_BOOT_MODE_RAM',
+ 'address': ram.get('address', {}).get('value', 0),
+ 'size': ram.get('size', {}).get('value', 0),
+ }
+ )
+
+ return image_boot_mode
+
+def generate_boot_type(image_boot_mode):
+ c_file = "image_boot_config.c"
+ h_file = "image_boot_config.h"
+ try:
+ with open(c_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'#include "{h_file}"\n')
+ out_f.write('\nimage_boot_config_t image_boot_config[BOOT_IMAGE_NUMBER] = {\n')
+ for mode in image_boot_mode:
+ out_f.writelines('\n'.join([
+ '\t{\n'
+ f"\t\t.mode = {mode['mode']},",
+ f"\t\t.address = {mode['address']},",
+ f"\t\t.size = {mode['size']},",
+ '\t},\n']))
+ out_f.write('};\n')
+
+ with open(h_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('#ifndef IMAGE_BOOT_CONFIG_H\n')
+ out_f.write('#define IMAGE_BOOT_CONFIG_H\n')
+ out_f.write('#include "bootutil/bootutil.h"\n')
+ out_f.writelines('\n'.join([
+ ' ',
+ 'typedef enum',
+ '{',
+ '\tIMAGE_BOOT_MODE_FLASH = 0U,',
+ '\tIMAGE_BOOT_MODE_RAM = 1U,',
+ '} image_boot_mode_t;',
+ '',
+ 'typedef struct image_boot_config_s {',
+ '\timage_boot_mode_t mode;',
+ '\tuint32_t address;',
+ '\tuint32_t size;',
+ '} image_boot_config_t;',
+ '',
+ 'extern image_boot_config_t image_boot_config[BOOT_IMAGE_NUMBER];'
+ ]))
+ out_f.write('\n#endif /* IMAGE_BOOT_CONFIG_H */\n')
+
+ except (FileNotFoundError, OSError):
+ print('Cannot create', out_f, file=sys.stderr)
+ sys.exit(Error.IO)
+
+
+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
+ app_core = None
+ apps_flash_map = [None, ]
+ apps_ram_map = [None, ]
+
+ for stage in range(2):
+ for app_index in range(1, 5):
+
+ app_flash_map = {}
+ app_ram_map = {}
+ app_ram_boot = False
+
+ try:
+ app_ident = f'application_{app_index}'
+ application = boot_and_upgrade[app_ident]
+
+ try:
+ flash = application['flash']
+ except KeyError:
+ #Backward compatibility
+ flash = application
+
+ try:
+ config = application['config']
+ except KeyError:
+ #Backward compatibility
+ config = application
+
+ try:
+ ram = application['ram']
+ except KeyError:
+ try:
+ ram = application['ram_boot']
+ app_ram_boot = True
+ except KeyError:
+ ram = None
+
+ try:
+ primary_addr = get_val(flash, 'address')
+ primary_size = get_val(flash, 'size')
+ secondary_addr = get_val(flash, 'upgrade_address')
+ secondary_size = get_val(flash, 'upgrade_size')
+
+ if ram is not None:
+ app_ram_addr = get_val(ram, 'address')
+ app_ram_size = get_val(ram, 'size')
+ else:
+ app_ram_addr = None
+ app_ram_size = None
+
+ except KeyError as key:
+ print('Malformed JSON:', key, 'is missing',
+ file=sys.stderr)
+ sys.exit(Error.JSON)
+ if stage == 0:
+ if primary_size != secondary_size:
+ print('Primary and secondary slot sizes'
+ ' are different for', app_ident,
+ file=sys.stderr)
+ sys.exit(Error.VALUE)
+ area_list.chk_area(primary_addr, primary_size)
+ area_list.chk_area(secondary_addr, secondary_size,
+ primary_addr)
+ if config is None or config.get('core') is None:
+ if app_index == 1:
+ app_core = area_list.plat['appCore']
+ elif app_index > 1:
+ print('"core" makes sense only for the 1st app',
+ file=sys.stderr)
+ sys.exit(Error.VALUE)
+ else:
+ app_core = get_str(config, 'core',
+ area_list.plat['appCore'])
+ if app_index == 1:
+ app_core = area_list.plat['allCores'].get(app_core.lower())
+ if app_core is None:
+ print('Unknown "core"', file=sys.stderr)
+ sys.exit(Error.VALUE)
+ 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(flash, '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)
+
+ if ram is not None:
+ app_ram_map.update({"address": app_ram_addr
+ , "size": app_ram_size
+ , "ram_boot": app_ram_boot})
+ apps_ram_map.append(app_ram_map)
+ else:
+ apps_ram_map = None
+
+ app_count = app_index
+
+ except KeyError:
+ break
+ if app_count == 0:
+ print('Malformed JSON: no application(s) found',
+ file=sys.stderr)
+ sys.exit(Error.JSON)
+
+ return app_core, app_count, slot_sectors_max, apps_flash_map, apps_ram_map, any_shared
+
+
+def process_policy_20829(in_policy):
+ """Process policy file to get data of NV-counter"""
+ list_counters = None
+
+ try:
+ with open(in_policy, encoding='UTF-8') as in_f:
+ try:
+ policy = json.load(in_f)
+ except ValueError:
+ print('\nERROR: Cannot parse', in_policy,'\n', file=sys.stderr)
+ sys.exit(Error.IO)
+ finally:
+ in_f.close()
+ except (FileNotFoundError, OSError):
+ print('Cannot open', in_policy, file=sys.stderr)
+ sys.exit(Error.IO)
+
+ try:
+ nv_cnt = policy["device_policy"]['reprovisioning']['nv_counter']
+ list_values = nv_cnt["value"]
+ list_counters = nv_cnt["bits_per_cnt"]
+ except KeyError:
+ print("\nERROR: Check path to 'nv_counter' and its correctness in policy file", in_policy,
+ ".\n", file=sys.stderr)
+ sys.exit(Error.POLICY)
+
+ #Check correctness of NV-counter
+ try:
+ len_list_value = len(list_values)
+ len_list_counters = len(list_counters)
+ except TypeError:
+ print("\nERROR: Fields 'value' and 'bits_per_cnt' of 'nv_counter' in policy file",
+ in_policy,"must be arrays.\n", file=sys.stderr)
+ sys.exit(Error.POLICY)
+
+ if len_list_value != len_list_counters:
+ print("\nERROR: Fields 'value' and 'bits_per_cnt' of 'nv_counter' in policy file",
+ in_policy,"must have the same size.\n", file=sys.stderr)
+ sys.exit(Error.POLICY)
+
+ sum_all_counters = 0
+ for i in range(len_list_value):
+ sum_all_counters += list_counters[i]
+ if list_values[i] > list_counters[i]:
+ print("\nERROR: Field 'value' cannot be more then 'bits_per_cnt'.", file=sys.stderr)
+ print("Check 'nv_counter' in policy file", in_policy,"\n", file=sys.stderr)
+ sys.exit(Error.POLICY)
+
+ sum_all_bit_nv_counter = 32
+ if sum_all_counters != sum_all_bit_nv_counter:
+ print("\nERROR: The sum of all 'bits_per_cnt' must be equal to 32.", file=sys.stderr)
+ print("Check 'nv_counter' in policy file", in_policy,"\n", file=sys.stderr)
+ sys.exit(Error.POLICY)
+
+ return list_counters
+
+
+def form_max_counter_array(in_list, out_file):
+ '''Write bit_per_count array to output file
+ There is expected, that "out_file" already exists'''
+
+ #ifdef here is needed to fix Rule 12.2 MISRA violation
+ out_array_str = "\n#ifdef NEED_MAX_COUNTERS\nstatic const uint8_t bits_per_cnt[] = {"
+
+ #in_list is checked in prior function 'process_policy()'
+ for i, list_member in enumerate(in_list):
+ out_array_str += str(list_member)
+ if i < len(in_list) - 1:
+ out_array_str += ", "
+ out_array_str += "};\n#endif\n"
+
+ try:
+ with open(out_file, "a", encoding='UTF-8') as out_f:
+ out_f.write(out_array_str)
+ out_f.write("\n#endif /* MEMORYMAP_H */")
+ except (FileNotFoundError, OSError):
+ print('\nERROR: Cannot open ', out_file, file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+
+
+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(Error.POLICY)
+
+ try:
+ boot_and_upgrade, ram_app_staging, flash = process_json(params.in_file)
+ bootloader = boot_and_upgrade['bootloader']
+ try:
+ bootloader_config = bootloader['config']
+ except KeyError:
+ #Backward compatibility
+ bootloader_config = bootloader
+
+ if ram_app_staging is not None:
+ try:
+ ram_app_staging_size = get_val(ram_app_staging, 'size')
+ ram_app_staging_ext_mem_addr = get_val(ram_app_staging, 'external_mememory_address')
+ ram_app_staging_sram_stage_addr = get_val(ram_app_staging, 'sram_stage_address')
+ ram_app_staging_reset_trigger = get_bool(ram_app_staging, 'reset_after_staging')
+ except KeyError:
+ ram_app_staging = None
+
+ try:
+ bootloader_flash = bootloader['flash']
+ except KeyError:
+ #Backward compatibility
+ bootloader_flash = bootloader
+
+ try:
+ bootloader_ram = bootloader['ram']
+ except KeyError:
+ #Backward compatibility
+ bootloader_ram = bootloader
+
+ boot_flash_area = AddrSize(bootloader_flash, 'address', 'size')
+ boot_ram_area = AddrSize(bootloader_ram, 'address', 'size')
+ except KeyError as key:
+ print('Malformed JSON:', key, 'is missing',
+ file=sys.stderr)
+ sys.exit(Error.JSON)
+
+ try:
+ scratch = AddrSize(bootloader_flash, 'scratch_address', 'scratch_size')
+ except KeyError:
+ scratch = None
+
+ try:
+ swap_status = AddrSize(bootloader_flash, 'status_address', 'status_size')
+ except KeyError:
+ swap_status = None
+
+ try:
+ bootloader_shared_data = bootloader['shared_data']
+ boot_shared_data_area = AddrSize(bootloader_shared_data, 'address', 'size')
+ except KeyError:
+ boot_shared_data_area = None
+
+ try:
+ bootloader_startup = get_bool(bootloader_config, 'startup')
+ except KeyError:
+ bootloader_startup = None
+
+ try:
+ ram_app_area = AddrSize(bootloader_config['ram_boot'], 'address', 'size')
+ except KeyError:
+ ram_app_area = 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_flash_area.addr, boot_flash_area.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(Error.CONFIG_MISMATCH)
+ 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.addr != app_binary.addr + app_binary.size or \
+ app_desc.addr != input_params.addr + input_params.size or \
+ app_desc.size != SERVICE_APP_SZ:
+ print('Malformed service_app definition', file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+ area_list.add_area('service_app', None, app_binary.addr,
+ app_binary.size + input_params.size + app_desc.size)
+ except KeyError as key:
+ print('Malformed JSON:', key, 'is missing',
+ file=sys.stderr)
+ sys.exit(Error.JSON)
+
+ # Fill flash areas
+ app_core, app_count, slot_sectors_max, apps_flash_map, apps_ram_map, shared_slot = \
+ process_images(area_list, boot_and_upgrade)
+
+ if params.image_boot_config:
+ image_boot_mode = process_boot_type(boot_and_upgrade)
+
+ if image_boot_mode:
+ generate_boot_type(image_boot_mode)
+
+ cy_img_hdr_size = 0x400
+ app_start = int(apps_flash_map[1].get("primary").get("address"), 0) + cy_img_hdr_size
+
+ if app_start % plat['VTAlign'] != 0:
+ print('Starting address', apps_flash_map[1].get("primary").get("address"),
+ '+', hex(cy_img_hdr_size),
+ 'must be aligned to', hex(plat['VTAlign']),
+ file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+
+ 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.size < status_size_min:
+ print('Insufficient swap status area - suggested size',
+ hex(status_size_min),
+ file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+ area_list.add_area('swap status partition',
+ 'FLASH_AREA_IMAGE_SWAP_STATUS',
+ swap_status.addr, swap_status.size)
+
+ if scratch is not None:
+ area_list.add_area('scratch area',
+ 'FLASH_AREA_IMAGE_SCRATCH',
+ scratch.addr, scratch.size)
+
+ # Compare size 'bit_per_cnt' and number of images.
+ # 'service_app' is used only when HW rollback counter exists
+ if plat.get('bitsPerCnt') is not None and service_app is not None:
+ plat['bitsPerCnt'] = True
+ list_counters = process_policy_20829(params.policy)
+ if list_counters is not None and len(list_counters) != app_count:
+ print("\nERROR: 'bits_per_cnt' must be present for each image!",
+ file=sys.stderr)
+ print("Please, check secure provisioning and reprovisioning policies.\n",
+ file=sys.stderr)
+ sys.exit(Error.CONFIG_MISMATCH)
+
+ # Image id parameter is not used for MCUBootApp
+ if params.img_id is None:
+ area_list.generate_c_source(params)
+
+ area_list.create_flash_area_id(app_count, params)
+
+ # Report necessary values back to make
+ print('# AUTO-GENERATED FILE, DO NOT EDIT. ALL CHANGES WILL BE LOST!')
+ if params.set_core:
+ print('CORE :=', plat['allCores'][plat['bootCore'].lower()])
+
+ if ram_app_staging is not None:
+ print('USE_STAGE_RAM_APPS := 1')
+ print('RAM_APP_STAGING_EXT_MEM_ADDR := ', hex(ram_app_staging_ext_mem_addr))
+ print('RAM_APP_STAGING_SRAM_MEM_ADDR :=', hex(ram_app_staging_sram_stage_addr))
+ print('RAM_APP_STAGING_SIZE := ', hex(ram_app_staging_size))
+ if ram_app_staging_reset_trigger is True:
+ print('RAM_APP_RESET_TRIGGER := 1')
+
+ if bootloader_startup is True:
+ print('BOOTLOADER_STARTUP := 1')
+
+ if ram_app_area is not None:
+ print('USE_MCUBOOT_RAM_LOAD := 1')
+ print('IMAGE_EXECUTABLE_RAM_START :=', hex(ram_app_area.addr))
+ print('IMAGE_EXECUTABLE_RAM_SIZE :=', hex(ram_app_area.size))
+
+ if boot_shared_data_area is not None:
+ print('USE_MEASURED_BOOT := 1')
+ print('USE_DATA_SHARING := 1')
+ print('BOOT_SHARED_DATA_ADDRESS :=', hex(boot_shared_data_area.addr)+'U')
+ print('BOOT_SHARED_DATA_SIZE :=', hex(boot_shared_data_area.size)+'U')
+ print('BOOT_SHARED_DATA_RECORD_SIZE :=', hex(boot_shared_data_area.size)+'U')
+
+ print('BOOTLOADER_ORIGIN :=', hex(boot_flash_area.addr))
+ print('BOOTLOADER_SIZE :=', hex(boot_flash_area.size))
+ print('BOOTLOADER_RAM_ORIGIN :=', hex(boot_ram_area.addr))
+ print('BOOTLOADER_RAM_SIZE :=', hex(boot_ram_area.size))
+ print('APP_CORE :=', app_core)
+
+ 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")
+ slot_size = apps_flash_map[int(params.img_id)].get("primary").get("size")
+
+ if apps_ram_map:
+ image_ram_address = apps_ram_map[int(params.img_id)].get("address")
+ image_ram_size = apps_ram_map[int(params.img_id)].get("size")
+ image_ram_boot = apps_ram_map[int(params.img_id)].get("ram_boot")
+ if image_ram_address and image_ram_size:
+ print('IMG_RAM_ORIGIN := ' + hex(image_ram_address))
+ print('IMG_RAM_SIZE := ' + hex(image_ram_size))
+ if image_ram_boot is True:
+ print('USE_MCUBOOT_RAM_LOAD := 1')
+
+ print('PRIMARY_IMG_START := ' + primary_img_start)
+ print('SECONDARY_IMG_START := ' + secondary_img_start)
+ print('SLOT_SIZE := ' + slot_size)
+ else:
+ if apps_ram_map:
+ ram_load_counter = 0
+ for img in apps_ram_map:
+ if img is not None and img.get("ram_boot"):
+ ram_load_counter += 1
+
+ if ram_load_counter != 0:
+ if ram_load_counter == 1 and app_count == 1:
+ print('USE_MCUBOOT_RAM_LOAD := 1')
+ print(f'IMAGE_EXECUTABLE_RAM_START := {hex(apps_ram_map[1].get("address"))}')
+ print(f'IMAGE_EXECUTABLE_RAM_SIZE := {hex(apps_ram_map[1].get("size"))}')
+ else:
+ print('USE_MCUBOOT_MULTI_MEMORY_LOAD := 1')
+
+ print('MAX_IMG_SECTORS :=', slot_sectors_max)
+
+ print('MCUBOOT_IMAGE_NUMBER :=', app_count)
+ if area_list.external_flash:
+ print('USE_EXTERNAL_FLASH := 1')
+ if area_list.external_flash_xip:
+ print('USE_XIP := 1')
+
+ if area_list.use_overwrite:
+ print('USE_OVERWRITE := 1')
+ if shared_slot:
+ print('USE_SHARED_SLOT := 1')
+ if service_app is not None:
+ print('PLATFORM_SERVICE_APP_OFFSET :=',
+ hex(app_binary.addr - plat['smifAddr']))
+ print('PLATFORM_SERVICE_APP_INPUT_PARAMS_OFFSET :=',
+ hex(input_params.addr - plat['smifAddr']))
+ print('PLATFORM_SERVICE_APP_DESC_OFFSET :=',
+ hex(app_desc.addr - plat['smifAddr']))
+ print('USE_HW_ROLLBACK_PROT := 1')
+
+
+if __name__ == '__main__':
+ main()