Infineon: Add support for CYW89829 devices, improve swap with status algorithm speed
diff --git a/boot/cypress/scripts/feature.py b/boot/cypress/scripts/feature.py
index 4bc428c..01dbb1e 100644
--- a/boot/cypress/scripts/feature.py
+++ b/boot/cypress/scripts/feature.py
@@ -33,7 +33,7 @@
 
     except FileNotFoundError:
         print(f'\nERROR: Cannot find {file_path}')
-        sys.exit(-1)
+        sys.exit(1)
 
     return data_json
 
@@ -66,19 +66,24 @@
         if f_security_setup:
 
             if p_security_setup is None:
-                raise AttributeError("This platform doesn't have any 'secure_setup' features")
+                print("\nThis platform doesn't have any 'secure_setup' features")
+                sys.exit(1)
 
             if f_security_setup.get('hw_rollback_prot'):
                 if p_security_setup.get('hw_rollback_prot') is None:
-                    raise AttributeError("This platform doesn't have HW anti roll-back counter")
+                    print("\nThis platform doesn't have HW anti roll-back counter")
+                    sys.exit(1)
 
             if f_security_setup.get('hw_crypto_acceleration'):
                 if p_security_setup.get('hw_crypto_acceleration') is None:
-                    raise AttributeError("The platform doesn't support HW crypto acceleration")
+                    print("\nThe platform doesn't support HW crypto acceleration")
+                    sys.exit(1)
 
             if f_security_setup.get('validate_upgrade').get('value') is False:
-                raise AttributeError("Deactivation of image validation during the upgrade \
-                                        process isn't implemented yet")
+                if f_security_setup.get('validate_boot').get('value'):
+                    print("\nERROR: Boot slot validation cannot be enabled if upgrade "\
+                                "slot validation is disabled")
+                    sys.exit(1)
 
 
 class FeatureProcessor:
@@ -88,10 +93,11 @@
     """
 
     settings_dict = {
-        'validate_boot'             :   'MCUBOOT_SKIP_IMAGE_VALIDATION',
+        'validate_boot'             :   'MCUBOOT_SKIP_BOOT_VALIDATION',
         'validate_upgrade'          :   'MCUBOOT_SKIP_UPGRADE_VALIDATION',
         'dependency_check'          :   'MCUBOOT_DEPENDENCY_CHECK',
         'serial_logging'            :   'MCUBOOT_LOG_LEVEL',
+        'watch_dog_timer'           :   'USE_WDT',
         'hw_rollback_prot'          :   'USE_HW_ROLLBACK_PROT',
         'hw_crypto_acceleration'    :   "USE_CRYPTO_HW",
         'sw_downgrade_prev'         :   'USE_SW_DOWNGRADE_PREV',
diff --git a/boot/cypress/scripts/memorymap.py b/boot/cypress/scripts/memorymap.py
index 5511c9a..d0799d6 100644
--- a/boot/cypress/scripts/memorymap.py
+++ b/boot/cypress/scripts/memorymap.py
@@ -8,6 +8,8 @@
 from enum import Enum
 import os.path
 
+MAX_IMAGE_NUMBERS = 16
+
 class Error(Enum):
     ''' Application error codes '''
     ARG             = 1
@@ -77,9 +79,20 @@
     'appCore': 'Cortex-M4'
 }
 
+common_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
+}
+
 common_XMC7000 = {
     'flashAddr': 0x10000000,
-    'eraseSize': 0x8000,  # 512 bytes
+    'eraseSize': 0x8000,  # 32k
     'smifAddr': 0x18000000,
     'smifSize': 0x8000000,  # i.e., window size
     'VTAlign': 0x400,  # Vector Table alignment
@@ -88,18 +101,6 @@
     '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
@@ -143,22 +144,11 @@
     },
 
     '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
+        **common_CYW20829
     },
 
-    'PSE84_L4': {
-        **common_PSE84
-    },
-
-    'PSE84_L2': {
-        **common_PSE84
+    'CYW89829': {
+        **common_CYW20829
     }
 }
 
@@ -632,7 +622,6 @@
                     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)
@@ -646,7 +635,7 @@
                            'fa_size': fa_size})
         return slot_sectors
 
-    def generate_c_source(self, params):
+    def generate_c_source(self, params, boot_and_upgrade):
         '''
         Generate C source
         Parameters:
@@ -686,7 +675,24 @@
                             '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.write('    NULL\n};\n')
+
+                image_boot_mode = None
+
+                if params.image_boot_config:
+                    image_boot_mode = process_boot_type(boot_and_upgrade)
+
+                if image_boot_mode:
+                    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')
+
                 out_f.close()
 
         except (FileNotFoundError, OSError):
@@ -709,11 +715,11 @@
 
         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("#pragma once\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('#include "bootutil/bootutil.h"\n')
 
                 fa_f.write(f'extern struct flash_area {c_array}[];\n')
                 fa_f.write(f'extern struct flash_area *boot_area_descs[];\n')
@@ -749,15 +755,29 @@
 
                     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 */")
+                        form_max_counter_array(list_counters, fa_f)
+
+                fa_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];'
+                ]))
+
                 fa_f.close()
 
         except (FileNotFoundError, OSError):
@@ -906,67 +926,28 @@
         application = boot_and_upgrade.get(app_ident)
 
         if application:
-            ram = application.get('ram', application.get('ram_boot'))
+            mem = application.get('ram_boot')
 
-            if ram:
+            if mem:
                 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),
+                        'mode': 'IMAGE_BOOT_MODE_RAM',
+                        'address': mem.get('address', {}).get('value', 0),
+                        'size': mem.get('size', {}).get('value', 0),
+                    }
+                )
+            else :
+                mem = application.get('flash')
+                image_boot_mode.append(
+                    {
+                        'mode': 'IMAGE_BOOT_MODE_FLASH',
+                        'address': mem.get('address', {}).get('value', 0),
+                        'size': mem.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
@@ -978,7 +959,7 @@
     apps_ram_map = [None, ]
 
     for stage in range(2):
-        for app_index in range(1, 5):
+        for app_index in range(1, MAX_IMAGE_NUMBERS):
 
             app_flash_map = {}
             app_ram_map = {}
@@ -1152,10 +1133,8 @@
     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'''
-
+def form_max_counter_array(in_list, fa_f):
+    '''Write bit_per_count array to output file '''
     #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[] = {"
 
@@ -1166,13 +1145,7 @@
             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)
+    fa_f.write(out_array_str)
 
 
 def main():
@@ -1285,12 +1258,6 @@
     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
 
@@ -1337,7 +1304,7 @@
 
     # Image id parameter is not used for MCUBootApp
     if params.img_id is None:
-        area_list.generate_c_source(params)
+        area_list.generate_c_source(params, boot_and_upgrade)
 
     area_list.create_flash_area_id(app_count, params)
 
@@ -1375,6 +1342,7 @@
     print('BOOTLOADER_RAM_SIZE :=', hex(boot_ram_area.size))
     print('APP_CORE :=', app_core)
 
+    # for blinky
     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")
@@ -1393,6 +1361,7 @@
         print('PRIMARY_IMG_START := ' + primary_img_start)
         print('SECONDARY_IMG_START := ' + secondary_img_start)
         print('SLOT_SIZE := ' + slot_size)
+    # for bootloader
     else:
         if apps_ram_map:
             ram_load_counter = 0
@@ -1401,8 +1370,8 @@
                     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('USE_MCUBOOT_RAM_LOAD := 1')
+                if ram_load_counter == 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:
diff --git a/boot/cypress/scripts/memorymap_rework.py b/boot/cypress/scripts/memorymap_rework.py
index 47e681e..855cf23 100644
--- a/boot/cypress/scripts/memorymap_rework.py
+++ b/boot/cypress/scripts/memorymap_rework.py
@@ -40,6 +40,7 @@
     ,   'bootloader_app_size'       :   'BOOTLOADER_SIZE'
     ,   'bootloader_ram_address'    :   'BOOTLOADER_RAM_ORIGIN'
     ,   'bootloader_ram_size'       :   'BOOTLOADER_RAM_SIZE'
+    ,   'bootloader_area'           :   'BOOTLOADER_AREA'
     ,   'application_count'         :   'MCUBOOT_IMAGE_NUMBER'
     ,   'boot_image'                :   'BOOT_IMAGE_NUMBER'
     ,   'sectors_count'             :   'MAX_IMG_SECTORS'
@@ -47,19 +48,27 @@
     ,   'image_ram_address'         :   'IMG_RAM_ORIGIN'
     ,   'image_ram_size'            :   'IMG_RAM_SIZE'
     ,   'primary_image_start'       :   'PRIMARY_IMG_START'
+    ,   'primary_image_area'        :   'PRIMARY_IMG_AREA'
     ,   'secondary_image_start'     :   'SECONDARY_IMG_START'
+    ,   'secondary_image_area'      :   'SECONDARY_IMG_AREA'
     ,   'image_size'                :   'SLOT_SIZE'
 }
 
 def header_guard_generate(file):
+    '''
+        Header quard generation
+    '''
     file.write('/* AUTO-GENERATED FILE, DO NOT EDIT.'
                     ' ALL CHANGES WILL BE LOST! */\n')
     file.write("#pragma once\n\n")
 
-def is_overlap(x : int, y : int) -> bool:
-    if x.start == x.stop or y.start == y.stop:
+def is_overlap(x_region, y_region) -> bool:
+    '''
+        Check if memory regions are overlapped
+    '''
+    if x_region.start == x_region.stop or y_region.start == y_region.stop:
         return False
-    return x.start < y.stop and y.start < x.stop
+    return x_region.start < y_region.stop and y_region.start < x_region.stop
 
 def is_aligned(addr : int, sz : int) -> bool:
     ''' Check address alignment '''
@@ -82,7 +91,8 @@
 
     def fits_with(self, other) -> bool:
         '''
-
+            Checks if "self" belongs "other".
+            @return True, if "self" fits into "other".
         '''
         return \
             self.addr >= other.addr and \
@@ -90,11 +100,11 @@
 
 class MemoryRegion(Memory):
     ''' Memory region handler '''
-    def __init__(self, addr, sz, erase_sz, erase_val, type):
+    def __init__(self, addr, sz, erase_sz, erase_val, mem_type):
         super().__init__(addr, sz)
-        self.erase_sz   : int   = erase_sz
-        self.erase_val  : int   = erase_val
-        self.type               = type
+        self.erase_sz           : int       = erase_sz
+        self.erase_val          : int       = erase_val
+        self.mem_type           : [str]     = mem_type
 
 class BootloaderLayout:
     '''
@@ -143,7 +153,8 @@
                 self.core_name = core
 
         except KeyError as key:
-            print('Malformed JSON:', key, 'is missing')
+            print('Malformed JSON:', key, 'is missing', file=sys.stderr)
+            sys.exit(-3)
 
 class MemoryAreaConfig:
     '''
@@ -211,19 +222,21 @@
         General handler
     '''
     def __init__(self):
-        self.boot_layout    : BootloaderLayout      = None
-        self.regions        : MemoryRegion          = []
-        self.region_types   : str                   = []
-        self.apps           : ApplicationLayout     = []
-        self.primary_slots  : str                   = []
-        self.secondary_slots: str                   = []
-        self.mem_areas      : MemoryAreaConfig      = []
-        self.param_dict                             = {}
-        self.map_json       : json                  = None
-        self.platform_json  : json                  = None
-        self.output_folder                          = None
-        self.output_name                            = None
-        self.max_sectors                            = 32
+        self.boot_layout        : BootloaderLayout      = None
+        self.regions            : MemoryRegion          = []
+        self.region_types       : str                   = []
+        self.region_types_alt   : str                   = []
+        self.apps               : ApplicationLayout     = []
+        self.app_id             : int                   = None
+        self.primary_slots      : str                   = []
+        self.secondary_slots    : str                   = []
+        self.mem_areas          : MemoryAreaConfig      = []
+        self.param_dict                                 = {}
+        self.map_json           : json                  = None
+        self.platform_json      : json                  = None
+        self.output_folder                              = None
+        self.output_name                                = None
+        self.max_sectors                                = 32
 
     def __apps_init(self):
         for image_number in range(1, APP_LIMIT):
@@ -243,21 +256,28 @@
         self.boot_layout.parse(self.map_json['bootloader'])
 
     def __memory_regions_init(self):
+        '''
+            Parser for "platform.json".
+            It fills memory_regions.
+        '''
         memory_regions = self.platform_json['memory_regions']
+
+        # it's critical to use 'regions' here!
+        # If not, please align the code with enum generation in the __header_gen()
         for region in memory_regions:
             try:
                 addr        = int(region['address'], 0)
                 size        = int(region['size'], 0)
                 erase_size  = int(region['erase_size'], 0)
                 erase_value = int(region['erase_value'], 0)
-                type        = str(region['type'])
+                mem_type    = region['mem_type'] if isinstance(region['mem_type'],\
+                                    list) else [region['mem_type']]
 
-                if type not in self.region_types:
-                    self.region_types.append(type)
+                self.regions.append(MemoryRegion(addr, size, erase_size, erase_value, mem_type))
 
-                self.regions.append(MemoryRegion(addr, size, erase_size, erase_value, type))
             except KeyError as key:
-                print('Malformed JSON:', key, 'is missing')
+                print('Malformed JSON:', key, 'is missing', file=sys.stderr)
+                sys.exit(-2)
 
         # Check regions for overlap
         for this in self.regions:
@@ -281,7 +301,13 @@
 
         region_id = self.__memory_area_find_region_id(area)
         region = self.regions[region_id]
-        region_name = region.type
+        region_name = region.mem_type[0]
+        region_name_alt = region.mem_type[1] if len(region.mem_type) > 1 else None
+
+        if region_name_alt:
+            if "boot" in key:
+                if region_name_alt not in self.region_types_alt:
+                    self.region_types_alt.append(region_name_alt)
 
         offset = area.addr - region.addr
         size = area.sz
@@ -293,6 +319,9 @@
 
         self.mem_areas.append(area_config)
 
+        if region_name not in self.region_types:
+            self.region_types.append(region_name)
+
         # Update max sectors
         slot_sectors = int((offset % region.erase_sz +
                             size + region.erase_sz - 1) //
@@ -350,6 +379,9 @@
             self.__memory_area_config_create(key)
 
     def __source_gen(self):
+        '''
+            C-file generation, file name and path must be given by script user
+        '''
         path = f'{self.output_folder}/{self.output_name}.c'
         include = f'{self.output_name}.h'
 
@@ -359,13 +391,14 @@
             f_out.write('struct flash_device flash_devices[] =\n')
             f_out.write('{\n')
             for region in self.regions:
-                f_out.write('\t{\n')
-                f_out.write(f'\t\t.address      = {hex(region.addr)}U,\n')
-                f_out.write(f'\t\t.size         = {hex(region.sz)}U,\n')
-                f_out.write(f'\t\t.erase_size   = {hex(region.erase_sz)}U,\n')
-                f_out.write(f'\t\t.erase_val    = {hex(region.erase_val)}U,\n')
-                f_out.write(f'\t\t.device_id    = {str(region.type)},\n')
-                f_out.write('\t},\n')
+                if region.mem_type[0] in self.region_types:
+                    f_out.write(f'\t[{region.mem_type[0]}] = ' + '{\n')
+                    f_out.write(f'\t\t.address      = {hex(region.addr)}U,\n')
+                    f_out.write(f'\t\t.size         = {hex(region.sz)}U,\n')
+                    f_out.write(f'\t\t.erase_size   = {hex(region.erase_sz)}U,\n')
+                    f_out.write(f'\t\t.erase_val    = {hex(region.erase_val)}U,\n')
+                    f_out.write(f'\t\t.device_id    = {str(region.mem_type[0])},\n')
+                    f_out.write('\t},\n')
             f_out.write('};\n\n')
 
             f_out.write(f'struct flash_area flash_areas[] =\n')
@@ -387,23 +420,34 @@
             f_out.write('\tNULL\n};\n\n')
 
             f_out.write('uint8_t memory_areas_primary[] =\n')
-            f_out.write('{\n')
+            f_out.write('{')
             for slot in self.primary_slots:
-                f_out.write(f'\t{slot}, ')
+                f_out.write(f'\n\t{slot}, ')
             f_out.write('\n};\n\n')
 
             f_out.write('uint8_t memory_areas_secondary[] =\n')
-            f_out.write('{\n')
+            f_out.write('{')
             for slot in self.secondary_slots:
-                f_out.write(f'\t{slot}, ')
+                f_out.write(f'\n\t{slot}, ')
             f_out.write('\n};\n\n')
 
+            f_out.write('image_boot_config_t image_boot_config[BOOT_IMAGE_NUMBER] = {\n')
+            for app in self.apps:
+                f_out.writelines('\n'.join([
+                    '\t{\n'
+                    f"\t\t.mode     = {'IMAGE_BOOT_MODE_RAM'    if app.has_ram_boot else 'IMAGE_BOOT_MODE_FLASH'},",
+                    f"\t\t.address  = {hex(app.ram_boot.addr)   if app.has_ram_boot else hex(app.boot_area.addr)},",
+                    f"\t\t.size     = {hex(app.ram_boot.sz)     if app.has_ram_boot else hex(app.boot_area.sz)},",
+                    '\t},\n']))
+            f_out.write('};\n')
+
     def __header_gen(self):
         path = f'{self.output_folder}/{self.output_name}.h'
         with open(path, "w", encoding='UTF-8') as f_out:
             header_guard_generate(f_out)
 
             f_out.write(f'#include <stdint.h>\n')
+            f_out.write('#include "bootutil/bootutil.h"\n')
             f_out.write(f'#include "flash_map_backend.h"\n\n')
             f_out.write(f'#define MEMORYMAP_GENERATED_AREAS 1\n\n')
             f_out.write('extern struct flash_device flash_devices[];\n')
@@ -412,8 +456,12 @@
             f_out.write('extern uint8_t memory_areas_secondary[];\n\n')
 
             f_out.write('enum \n{\n')
-            for id, type in enumerate(self.region_types):
-                f_out.write(f'\t{type} = {id}U,\n')
+
+            # it's critical to use 'regions' here!
+            # because it fixes the bug when enum {INTERNAL_RRAM, EXTERNAL_FLASH,}
+            # is generated in incorrect sequence.
+            for region in self.regions:
+                    f_out.write(f'\t{str(region.mem_type[0])},\n')
             f_out.write('};\n\n')
 
             f_out.write('enum \n{\n')
@@ -421,18 +469,38 @@
                 f_out.write(f'\t{area_param[1]} = {area_param[2]}U,\n')
             f_out.write('};\n\n')
 
+            f_out.write('typedef enum \n{\n')
+            f_out.write('\tIMAGE_BOOT_MODE_FLASH = 0U,\n')
+            f_out.write('\tIMAGE_BOOT_MODE_RAM = 1U,\n')
+            f_out.write('} image_boot_mode_t;\n\n')
+
+            f_out.write('typedef struct image_boot_config_s \n{\n')
+            f_out.write('\timage_boot_mode_t mode;\n')
+            f_out.write('\tuint32_t address;\n')
+            f_out.write('\tuint32_t size;\n')
+            f_out.write('} image_boot_config_t;\n\n')
+
+            f_out.write('extern image_boot_config_t image_boot_config[BOOT_IMAGE_NUMBER];\n\n')
+
     def __bootloader_mk_file_gen(self):
         boot = self.boot_layout
+
+        for mem_type in self.region_types:
+            print(f'USE_{mem_type} := 1')
+
+        for mem_type in self.region_types_alt:
+            print(f'USE_{mem_type} := 1')
+
         # Upgrade mode
         if boot.scratch_area is None and boot.status_area is None:
             print(settings_dict['overwrite'], ':= 1')
         else:
-            print(settings_dict['overwrite'], ':= 0')
             print(settings_dict['swap'], ':= 1')
             print(settings_dict['scratch'], f':= {0 if boot.scratch_area is None else 1}')
             print(settings_dict['status'], f':= {0 if boot.status_area is None else 1}')
-        print('# Shared data')
+
         if boot.shared_data is not None:
+            print('# Shared data')
             shared_data = boot.shared_data
             print(settings_dict['measured_boot'], ':= 1')
             print(settings_dict['data_sharing'], ':= 1')
@@ -442,25 +510,30 @@
             print(f'{settings_dict["shared_data_record_size"]} :=', hex(shared_data.sz))
 
         print('# Bootloader app area')
+        for region in self.regions:
+            if boot.bootloader_area.fits_with(region):
+                print(f'{settings_dict["bootloader_area"]} :=', str(region.mem_type[0]))
+                break
+
         print(f'{settings_dict["bootloader_app_address"]} :=', hex(boot.bootloader_area.addr))
         print(f'{settings_dict["bootloader_app_size"]} :=', hex(boot.bootloader_area.sz))
 
-        print('# Bootloader ram area')
         if boot.ram is not None:
+            print('# Bootloader ram area')
             print(f'{settings_dict["bootloader_ram_address"]} :=', hex(boot.ram.addr))
             print(f'{settings_dict["bootloader_ram_size"]} :=', hex(boot.ram.sz))
 
         print('# Application area')
-        for id, app in enumerate(self.apps):
-            print(f'APPLICATION_{id+1}_BOOT_SLOT_ADDRESS := {hex(app.boot_area.addr)}')
-            print(f'APPLICATION_{id+1}_BOOT_SLOT_SIZE := {hex(app.boot_area.sz)}')
-            print(f'APPLICATION_{id+1}_UPGRADE_SLOT_ADDRESS := {hex(app.upgrade_area.addr)}')
-            print(f'APPLICATION_{id+1}_UPGRADE_SLOT_SIZE := {hex(app.upgrade_area.sz)}')
+        for img_id, app in enumerate(self.apps):
+            print(f'APPLICATION_{img_id+1}_BOOT_SLOT_ADDRESS := {hex(app.boot_area.addr)}')
+            print(f'APPLICATION_{img_id+1}_BOOT_SLOT_SIZE := {hex(app.boot_area.sz)}')
+            print(f'APPLICATION_{img_id+1}_UPGRADE_SLOT_ADDRESS := {hex(app.upgrade_area.addr)}')
+            print(f'APPLICATION_{img_id+1}_UPGRADE_SLOT_SIZE := {hex(app.upgrade_area.sz)}')
 
-        print('# Ram load')
         # Ram load single
         if len(self.apps) == 1:
             if self.apps[0].ram_boot is not None:
+                print('# Ram load')
                 ram_boot = self.apps[0].ram_boot
                 print(settings_dict['ram_load'], ':= 1')
                 print(f'{settings_dict["ram_load_address"]} :=', hex(ram_boot.addr))
@@ -477,13 +550,13 @@
                     if app1.overlaps_with(app2):
                         ram_addr_overlap_counter += 1
 
-            for id, app in enumerate(self.apps):
+            for img_id, app in enumerate(self.apps):
                 if app.ram_boot is not None:
                     ram_boot_counter += 1
                     ram_boot = app.ram_boot
 
-                    print(f'APPLICATION_{id+1}_RAM_LOAD_ADDRESS := {hex(ram_boot.addr)}')
-                    print(f'APPLICATION_{id+1}_RAM_LOAD_SIZE := {hex(ram_boot.sz)}')
+                    print(f'APPLICATION_{img_id+1}_RAM_LOAD_ADDRESS := {hex(ram_boot.addr)}')
+                    print(f'APPLICATION_{img_id+1}_RAM_LOAD_SIZE := {hex(ram_boot.sz)}')
 
             if ram_boot_counter != 0:
                 print(settings_dict['ram_load'], ':= 1')
@@ -494,8 +567,15 @@
         print('# Mcuboot')
         print(settings_dict['application_count'], f'= {len(self.apps)}')
         print(settings_dict['sectors_count'], f'= {self.max_sectors}')
+        print('\n',settings_dict['application_count'], f'= {len(self.apps)}', file=sys.stderr)
 
     def __application_mk_file_gen(self):
+        for mem_type in self.region_types:
+            print(f'USE_{mem_type} := 1')
+
+        for mem_type in self.region_types_alt:
+            print(f'USE_{mem_type} := 1')
+
         app = self.apps[self.app_id-1]
         boot = self.boot_layout
         # Upgrade mode
@@ -512,8 +592,17 @@
         print(settings_dict['primary_image_start'], ':=', hex(app.boot_area.addr))
         print(settings_dict['secondary_image_start'], ':=', hex(app.upgrade_area.addr))
         print(settings_dict['image_size'], ':=', hex(app.boot_area.sz))
+
+        for region in self.regions:
+            if app.boot_area.fits_with(region):
+                print(settings_dict['primary_image_area'], ':=', str(region.mem_type[0]))
+            if app.upgrade_area.fits_with(region):
+                print(settings_dict['secondary_image_area'], ':=', str(region.mem_type[0]))
+
         if app.ram_boot:
             print(settings_dict['ram_load'], ':= 1')
+            print(settings_dict['image_ram_address'], ':=',  hex(app.ram_boot.addr))
+            print(settings_dict['image_ram_size'], ':=',  hex(app.ram_boot.sz))
         if app.ram:
             print(settings_dict['image_ram_address'], ':=',  hex(app.ram.addr))
             print(settings_dict['image_ram_size'], ':=',  hex(app.ram.sz))
@@ -521,6 +610,9 @@
             print(settings_dict['core'], ':=',  app.core_name)
 
     def parse(self, memory_map, platform_config, output_folder, output_name, app_id):
+        ''''
+            Parser to process memory maps, platform config and generation of all need files
+        '''
         try:
             with open(memory_map, "r", encoding='UTF-8') as f_in:
                 self.map_json = json.load(f_in)
@@ -539,10 +631,9 @@
             self.__apps_init()
             self.__memory_areas_create()
 
-            self.__source_gen()
-            self.__header_gen()
-
             if app_id is None:
+                self.__source_gen()
+                self.__header_gen()
                 self.__bootloader_mk_file_gen()
             else:
                 self.__application_mk_file_gen()
@@ -571,12 +662,15 @@
               help='application image number')
 
 def run(memory_config, platform_config, output_folder, output_name, image_id):
-    map = MemoryMap()
-    map.parse(memory_config,
+    ''''
+        The main method to be used by cli()
+    '''
+    imemmap = MemoryMap()
+    imemmap.parse(memory_config,
               platform_config,
               output_folder,
               output_name,
               image_id)
 
 if __name__ == '__main__':
-    cli()
\ No newline at end of file
+    cli()