Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bootloader mcuboot with custom device #401

Open
lefebvresam opened this issue Dec 7, 2024 · 125 comments
Open

Bootloader mcuboot with custom device #401

lefebvresam opened this issue Dec 7, 2024 · 125 comments

Comments

@lefebvresam
Copy link

I'm doing an attempt to create a project with mcu-bootloader as described on mbed-mcuboot-demo

But with the new toolchain (git submodules, cmake, etc..)

After creating a project, importing the libs and producing the necessary files, I try to do sh build.sh -d and I get

-- Mbed: First CMake run detected, generating configs...
ERROR: Target specifies device_name HMC20 but this device is not
listed in /home/sam/git/mcuboot/mbed-os/tools/cmake/../../targets/cmsis_mcu_descriptions.json5.  Perhaps you need to use
the 'python -m mbed_tools.cli.main cmsis-mcu-descr fetch-missing' command to download
the missing MCU description?

More information may be available by using the command line option '-vv'.
CMake Error at mbed-os/tools/cmake/mbed_generate_configuration.cmake:123 (message):
  mbedtools configure failed! Cannot build this project.  Command was cd
  /home/sam/git/mcuboot/mbed-os/tools/cmake/../python &&
  /home/sam/git/mcuboot/mbed-os/venv/bin/python3.10 -m mbed_tools.cli.main -v
  configure -t GCC_ARM -m HMC20 --mbed-os-path
  /home/sam/git/mcuboot/mbed-os/tools/cmake/../..  --output-dir
  /home/sam/git/mcuboot/build --program-path /home/sam/git/mcuboot
Call Stack (most recent call first):
  mbed-os/tools/cmake/app.cmake:24 (include)
  CMakeLists.txt:7 (include)

'missing MCU description' and I have a custom_targets.json5

I made to project temporary public for testing purposes:

bitbucket.org/saleconix/mcuboot.git

Adding this

set(MBED_APP_JSON_PATH mbed_app.json5)
set(CUSTOM_TARGETS_JSON_PATH custom_targets.json5)

or this

set(MBED_APP_JSON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/mbed_app.json5)
set(CUSTOM_TARGETS_JSON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/custom_targets.json5)

is not helping

@lefebvresam
Copy link
Author

I had to remove "device_name": "HMC20" in custom targets. Strange that my original application never complained about this.

But now I have something like a loop:

/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:53: multiple definition of `mbed_error_in_progress'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:53: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_error_initialize':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:260: multiple definition of `mbed_error_initialize'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:260: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_get_first_error':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:267: multiple definition of `mbed_get_first_error'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:267: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_get_last_error':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:274: multiple definition of `mbed_get_last_error'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:274: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_get_error_count':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:281: multiple definition of `mbed_get_error_count'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:281: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `core_util_atomic_load_bool':
/home/sam/git/mcuboot/mbed-os/platform/include/platform/internal/mbed_atomic_impl.h:728: multiple definition of `mbed_get_error_in_progress'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/include/platform/internal/mbed_atomic_impl.h:728: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_warning':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:291: multiple definition of `mbed_warning'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:291: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_set_error_hook':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:351: multiple definition of `mbed_set_error_hook'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:351: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_reset_reboot_error_info':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:360: multiple definition of `mbed_reset_reboot_error_info'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:360: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_reset_reboot_count':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:387: multiple definition of `mbed_reset_reboot_count'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:387: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_get_reboot_error_info':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:404: multiple definition of `mbed_get_reboot_error_info'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:404: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_get_first_error_info':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:408: multiple definition of `mbed_get_first_error_info'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:408: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_get_last_error_info':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:415: multiple definition of `mbed_get_last_error_info'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:415: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_make_error':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:423: multiple definition of `mbed_make_error'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:423: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_error.c.obj: in function `mbed_clear_all_errors':
/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:456: multiple definition of `mbed_clear_all_errors'; mbed-os/CMakeFiles/mbed-baremetal.dir/platform/source/mbed_error.c.obj:/home/sam/git/mcuboot/mbed-os/platform/source/mbed_error.c:456: first defined here
/usr/local/gcc-arm/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: mbed-os/CMakeFiles/mbed-os.dir/platform/source/mbed_mem_trace.cpp.obj: in function `SingletonPtr<rtos::Mutex>::get() const':

I was also wondering if I need:

"requires": ["bare-metal", "mbedtls", "mcuboot", "flashiap-block-device", "spif-driver", "qspif", "mbed-trace", "sd"],

@lefebvresam
Copy link
Author

https://github.com/JohnK1987

@lefebvresam this seems like a separate issue around project configuration...

@lefebvresam
Copy link
Author

First point was not comitted yet. If you mean this:

            "target.memory_bank_config": {
                "IROM1": {
                    "size": 0x20000
                }
            },

There was a complaint that IROM1 was not existing.

Point 2: Where is the clash then?

target_link_libraries(${LIB_BOOTUTIL}
    PUBLIC
        mbed-mcuboot
        mbed-mbedtls
)

versus?

target_link_libraries(${APP_TARGET}
    mbed-baremetal
    mbed-storage
    mbed-mcuboot
)

@lefebvresam
Copy link
Author

lefebvresam commented Dec 7, 2024

I just pushed my test changes but it is still not compiling. I always have the issue with 'first defined here'

To run, just 'sh build.sh -d'

@JohnK1987
Copy link
Member

Thank you!

  1. We can say your override of IROM1 via mbed_app.json is not working because there is nothing for override.
    Memory_banks are working in default with STM32H7 targets because there is everything prepared, but rest families are not ready for this. Linker script of STM32U5 is still use old definitions like APP_START and SIZE. So you should probably use it by old way. That mean you have to use names what will override these values which are used in the linker of STM32U575xG.
    Or you can update it by your self (I am not sure what all exactly need to be done at this moment, for this is maybe better to ask directly Jamie.) for STM32U5 familly based on the STM32H7 modifications.

  2. I have no info about progress but how Jamie wrote he already started to do something with MCUBOOT, so I believe this is good start - https://github.com/mbed-ce/mbed-mcuboot-bootloader

  3. Point 2: Where is the clash then?

    target_link_libraries(${LIB_BOOTUTIL}
        PUBLIC
            mbed-mcuboot
            mbed-mbedtls
    )
    

    versus?

    target_link_libraries(${APP_TARGET}
        mbed-baremetal
        mbed-storage
        mbed-mcuboot
    )
    

    I did not write about top lvl CMakeList of your project but the one of your imported mcuboot library - https://github.com/mcu-tools/mcuboot/blob/b778ad9e163da2212677d19ad6788c63127881a1/boot/mbed/CMakeLists.txt#L38-L48
    In Jamie's fork of mcuboot you can see a modification - https://github.com/multiplemonomials/mcuboot/blob/464c79661da3409ebe4abb8c4bb09f28d5ec5907/boot/mbed/CMakeLists.txt#L32

BR, Jan

@lefebvresam
Copy link
Author

lefebvresam commented Dec 7, 2024

It compiles when I put this in omment. No clue why you need mbed-core-flags then (also compiling without). It compiles also when I put mbed-baremetal in comment and make mbed-baremetal private in the top level.

# if("_RTE_" IN_LIST MBED_CONFIG_DEFINITIONS)
#     target_link_libraries(${LIB_TARGET}
#     PUBLIC
#         mbed-os
#     )
# else()
    target_link_libraries(${LIB_TARGET}
    PUBLIC
        mbed-baremetal
    )
# endif()

However I think I best change the dependency to Jamie's version.

@JohnK1987
Copy link
Member

JohnK1987 commented Dec 7, 2024

From my point of view you should have mbed-os or mbed-baremetal (never both at once) just one time per app.
However libraries (mcuboot is one of them) which use some dependencies from mbed-os need an access to mbed-os library, then you need link the library to mbed-core-flags or mbed-rtos-flags if the library needs to use RTOS features.

However I think I best change the dependency to Jamie's version.

Agreed.

@lefebvresam
Copy link
Author

I updated the project with the new lib and the branch.

Why this IROM1 setting is needed?
Do I have to reduce this setting to 0x20000 by overwriting it somewhere in the config?

#define MBED_ROM_SIZE 0x100000 // 1MB

A macro at custom targets?
@multiplemonomials can you elaborate on this?

@lefebvresam
Copy link
Author

What I also do not really understand is if you follow the procedure on AGlass0fMilk you get a file with rsa_pub_key[], and in the example I see enc_priv_key[].

@multiplemonomials
Copy link
Collaborator

Sorry I really just started on the mcuboot stuff, I haven't really done anything other than update the build system yet. You should definitely use my fork of mcuboot to fix the link errors, but I still need to actually get a basic example working

@multiplemonomials
Copy link
Collaborator

In order to make things work properly with the bootloader, you will need to use memory_bank_config to configure the ROM base address. This also requires that your target's linker script support memory bank configuration, which a lot of them currently don't

@lefebvresam
Copy link
Author

I use a custom target inherited from MCU_STM32U575xG. Are there some examples how to change/adapt the linker script?

@multiplemonomials
Copy link
Collaborator

Actually, yeah! Been working on an update for the K64F here: https://github.com/mbed-ce/mbed-os/tree/dev/k64f-linker-script-refactor

@lefebvresam
Copy link
Author

Is it the purpose that this:

image

Is in line with this:

image

Or where do you find the right details specific for the controller?

@multiplemonomials
Copy link
Collaborator

Yeah, you will find this info in the memory map section of the datasheet, or (apparently) in CubeIDE

@lefebvresam
Copy link
Author

I see it's essentially renaming stuff. In my case there is no differentiation between RAM1, 2 or 3. I'm I right that the only purpose is to let the compiler believe that the size of the flash is only 0x20000 in order to have the code fit in that part before adding different hex files to create the complete image? I have no clue what .text and .bss and others exaclty mean.

@JohnK1987
Copy link
Member

JohnK1987 commented Dec 8, 2024

These definitions allow you to change memory settings according to your requirements via configuration without direct intervention to the linker script.

It should working probably like that

  1. prepare custom_targets.json
    In case of custom target you should fill necessary information to custom_targets_json file as default target definition. For example your one

    For content click here
    	"HMC20": {
    		"inherits": [
    			"MCU_STM32U575xG"
    		],
    		"components_add" : ["SD", "SPIF"],
    		"overrides": {
    			"clock_source" : "USE_PLL_HSE_XTAL",
    			"lse_available" : "1",
    			"lse_drive_load_level" : "RCC_LSEDRIVE_HIGH"
    		},
    		"macros_add": [
    			"HSE_VALUE=10000000UL"
    		],
    		"device_has_remove": [
    			"ANALOGOUT",...
    		],
    		"device_name": "STM32U575VGTx"
    	}
    

    To device_name we will fill almost exact MCU name what we have. In our case STM32U575VG (not sure which one you really have). Then we will see error what you had

    -- Mbed: First CMake run detected, generating configs...
    ERROR: Target specifies device_name HMC20 but this device is not
    listed in /home/sam/git/mcuboot/mbed-os/tools/cmake/../../targets/cmsis_mcu_descriptions.json5.  Perhaps you need to use
    the 'python -m mbed_tools.cli.main cmsis-mcu-descr fetch-missing' command to download
    the missing MCU description?
    

    Then we go to '...project_name\mbed-os\tools\python' and call 'python -m mbed_tools.cli.main cmsis-mcu-descr fetch-missing'.
    If our device name is not correct then we will see something like this

    RuntimeError: MCU STM32U575VG is not present in the CMSIS MCU index (C:\Users\user\AppData\Local\cmsis-pack-manager\cmsis-pack-manager\index.json).  Maybe wrong part number, or this MCU simply doesn't exist in the CMSIS index and has to be added manually?
    

    So we check the name one more time or visit mentioned file index.json and look for best match. In our case "STM32U575VGTx". Then we update device_name parametr and perform 'fetch-missing' (from above) one more time. Then we update device_name parameter and perform 'fetch-missing' (from above) one more time. Then we see output in console like

    For console output click here
    PS ...project_name\mbed-os\tools\python> python -m mbed_tools.cli.main cmsis-mcu-descr fetch-missing
    INFO: Custom_targets file detected -  ...project_name\custom_targets\custom_targets.json5
    INFO: Scanning targets.json5 for used MCU names...
    INFO: Scanning custom_targets.json/json5. for used MCU names...
    INFO: Scanning cmsis_mcu_descriptions.json5 file for missing MCUs...
    INFO: CMSIS MCU description cache was last updated: a day ago
    INFO: In case of Custom target remove 'device_name' from your custom_targets.json5 file and add
    just the 'memories' section as 'memory_banks' section from content below.
    Otherwise add the whole following entries to  ...project_name\mbed-os\targets\cmsis_mcu_descriptions.json5:
    {
    	"STM32U575VGTx": {
    		"algorithms": [
    			{
    				"default": true,
    				"file_name": "CMSIS/Flash/STM32U5xx_1M_0800.FLM",
    				"ram_size": 32768,
    				"ram_start": 536870912,
    				"size": 1048576,
    				"start": 134217728,
    				"style": "Keil"
    			},
    			{
    				"default": true,
    				"file_name": "CMSIS/Flash/STM32U5xx_1M_0C00.FLM",
    				"ram_size": 32768,
    				"ram_start": 536870912,
    				"size": 1048576,
    				"start": 201326592,
    				"style": "Keil"
    			},
    			{
    				"default": false,
    				"file_name": "CMSIS/Flash/MX25LM51245G_STM32U575I-EVAL.FLM",
    				"ram_size": 655360,
    				"ram_start": 536870912,
    				"size": 67108864,
    				"start": 1879048192,
    				"style": "Keil"
    			},
    			{
    				"default": false,
    				"file_name": "CMSIS/Flash/MX25LM51245G_STM32U585I_IOT02A.FLM",
    				"ram_size": 655360,
    				"ram_start": 536870912,
    				"size": 67108864,
    				"start": 1879048192,
    				"style": "Keil"
    			},
    			{
    				"default": false,
    				"file_name": "CMSIS/Flash/MX25LM51245G_STM32U599J-DK.FLM",
    				"ram_size": 65524,
    				"ram_start": 536870912,
    				"size": 67108864,
    				"start": 2415919104,
    				"style": "Keil"
    			}
    		],
    		"family": "STM32U5 Series",
    		"from_pack": {
    			"pack": "STM32U5xx_DFP",
    			"url": "https://www.keil.com/pack/",
    			"vendor": "Keil",
    			"version": "3.0.0"
    		},
    		"memories": {
    			"Flash": {
    				"access": {
    					"execute": true,
    					"non_secure": false,
    					"non_secure_callable": false,
    					"peripheral": false,
    					"read": true,
    					"secure": false,
    					"write": false
    				},
    				"default": true,
    				"p_name": null,
    				"size": 1048576,
    				"start": 134217728,
    				"startup": true
    			},
    			"SRAM1_2": {
    				"access": {
    					"execute": true,
    					"non_secure": false,
    					"non_secure_callable": false,
    					"peripheral": false,
    					"read": true,
    					"secure": false,
    					"write": true
    				},
    				"default": true,
    				"p_name": null,
    				"size": 262144,
    				"start": 536870912,
    				"startup": false
    			},
    			"SRAM3": {
    				"access": {
    					"execute": true,
    					"non_secure": false,
    					"non_secure_callable": false,
    					"peripheral": false,
    					"read": true,
    					"secure": false,
    					"write": true
    				},
    				"default": false,
    				"p_name": null,
    				"size": 524288,
    				"start": 537133056,
    				"startup": false
    			}
    		},
    		"name": "STM32U575VGTx",
    		"processors": [
    			{
    				"address": null,
    				"ap": 0,
    				"apid": null,
    				"core": "CortexM33",
    				"default_reset_sequence": null,
    				"dp": 0,
    				"fpu": "SinglePrecision",
    				"mpu": "Present",
    				"name": null,
    				"svd": "CMSIS/SVD/STM32U575.svd",
    				"unit": 0
    			}
    		],
    		"sub_family": "STM32U575",
    		"vendor": "STMicroelectronics:13"
    	}
    }
    

    Then we will copy memories section into our custom_targets.json file but under new section name memory_banks and then we delete the device_name section. When we will try call again command 'fetch-missing', then we will see INFO: No missing MCUs, no work to do.

    For final content click here
    	"HMC20": {
    		"inherits": [
    			"MCU_STM32U575xG"
    		],
    		"components_add" : ["SD", "SPIF"],
    		"overrides": {
    			"clock_source" : "USE_PLL_HSE_XTAL",
    			"lse_available" : "1",
    			"lse_drive_load_level" : "RCC_LSEDRIVE_HIGH"
    		},
    		"macros_add": [
    			"HSE_VALUE=10000000UL"
    		],
    		"device_has_remove": [
    			"ANALOGOUT",...
    		],
    		"memory_banks": {
    			"IROM1": {
    				"access": {
    					"execute": true,
    					"non_secure": false,
    					"non_secure_callable": false,
    					"peripheral": false,
    					"read": true,
    					"secure": false,
    					"write": false
    				},
    				"default": true,
    				"p_name": null,
    				"size": 1048576,
    				"start": 134217728,
    				"startup": true
    			},
    			"SRAM1_2": {
    				"access": {
    					"execute": true,
    					"non_secure": false,
    					"non_secure_callable": false,
    					"peripheral": false,
    					"read": true,
    					"secure": false,
    					"write": true
    				},
    				"default": true,
    				"p_name": null,
    				"size": 262144,
    				"start": 536870912,
    				"startup": false
    			},
    			"SRAM3": {
    				"access": {
    					"execute": true,
    					"non_secure": false,
    					"non_secure_callable": false,
    					"peripheral": false,
    					"read": true,
    					"secure": false,
    					"write": true
    				},
    				"default": false,
    				"p_name": null,
    				"size": 524288,
    				"start": 537133056,
    				"startup": false
    			}
    		}
    	}
    
  2. prepare linker script
    Because only linker script for STM32H7 is prepared then we need PR for modification of STM32U575 linker script where we need to see macros from memory_banks.
    I believe it will be something like below.
    From current

    MEMORY
    {
        FLASH (rx)  : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE
        RAM (rwx)   : ORIGIN = MBED_RAM_START + VECTORS_SIZE, LENGTH = MBED_RAM_SIZE - VECTORS_SIZE
    }
    

    to something like

    MEMORY
    {
        FLASH (rx)   : ORIGIN = MBED_CONFIGURED_ROM_BANK_IROM1_START, LENGTH = MBED_CONFIGURED_ROM_BANK_IROM1_SIZE
        RAM (rwx)    : ORIGIN = MBED_RAM_BANK_SRAM1_2_START + VECTORS_SIZE, LENGTH = (MBED_RAM_BANK_SRAM1_2_SIZE + MBED_RAM_BANK_SRAM3_SIZE) - VECTORS_SIZE
    }
    

    Also this file should be modified.

    This is not definitely optimal but I believe it is enough for a start and you do not need care rest of linker script.
    About names of macros I am not exactly sure but it seems like they should be generated by a python script, right @multiplemonomials ?

    EDIT: https://github.com/mbed-ce/mbed-os/wiki/Mbed-Memory-Bank-Information#32-specific-behavior

  3. preparation for bootloder and its app
    As soon as linker will be ready then you can place target.memory_bank_config into mbed_app.json5 with specific parts what should override default target definition just for specific application.
    The mbed_app.json5 of a bootloader:

             "target.memory_bank_config": {
                 "IROM1": {
                     "size": 0x20000
                 }
             },
    

    In this case we will set Flash size to just 128KB because we are sure or we want our bootloader will be not bigger than that. And according to RM0456 (section 7.3.1 Flash memory organization on page 290) the size must be divisible by 8kb (from my understanding the FlashIAP is able to erase and program only by whole sectors/pages).
    This size is also important for later calculation. It will be use like offset for app start address, app flash size reduction and also like address where bootloader should jump to.
    The mbed_app.json5 of an app:

             "target.memory_bank_config": {
                 "IROM1": {
                     "size": 0x80000
                     "start": 0x20000
                 }
             },
    

These are basics how to achieve or understand a simple bootloader and also handy for start with Mcuboot I think. Only a method how to merge both binaries to one is missing.

EDIT:
Good point

hexmerge.py utility from the intelhex

@lefebvresam
Copy link
Author

Thank you very much. I will test this procedure tomorrow. To be honest I never worked with linker scripts and I was starting to read a bit about this topic but it requires a deeper knowledge about ARM architecture I guess. I even didn't know exactly what to change and why. What is missing or wrong in the current linker scripts? Fyi the controller I use is STM32U575RGT6.

To merge the hexes my idea is to test the procedure described on mbed-mcuboot-demo. The memory size is exactly the same as in my case (1MB) and my idea is to write a piece of software to transfer a bin file from the SD card to a separate flash chip I already use to store my images in my HMI display application to provide the secondary slot.

@lefebvresam
Copy link
Author

I did the whole procedure and it compiles without errors, but the strange this is that I still see:

ROM Bank Flash: 80505(+0)/1048576 bytes used, 7.7% (+0.0%) used -> that's still 1MB

[410/410] Linking CXX executable mbed-mcuboot-bootloader.elf
-- built: /home/sam/git/mcuboot/build/mbed-mcuboot-bootloader.bin
-- built: /home/sam/git/mcuboot/build/mbed-mcuboot-bootloader.hex
/home/sam/git/mcuboot/mbed-os/tools/python/memap/memap.py:63: DeprecationWarning: the 'HEADER' constant is deprecated, use the 'HRuleStyle' and 'VRuleStyle' enums instead
  from prettytable import PrettyTable, HEADER
| Module                                 |         .text |     .data |          .bss |
|----------------------------------------|---------------|-----------|---------------|
| CMakeFiles/mbed-mcuboot-bootloader.dir |     516(+516) |     0(+0) |     408(+408) |
| [fill]                                 |       99(+99) |     4(+4) |       20(+20) |
| [lib]/bootutil.a                       |   7001(+7001) |     8(+8) | 10612(+10612) |
| [lib]/c_nano.a                         |   4648(+4648) |   92(+92) |     329(+329) |
| [lib]/gcc.a                            |   2748(+2748) |     0(+0) |         0(+0) |
| [lib]/mbed-mbedtls.a                   |   7978(+7978) |     0(+0) |         0(+0) |
| [lib]/mbed-mcuboot.a                   |   1644(+1644) |   16(+16) |     132(+132) |
| [lib]/mbed-storage-blockdevice.a       |   5172(+5172) |     0(+0) |         0(+0) |
| [lib]/mbed-storage-flashiap.a          |     997(+997) |     0(+0) |         0(+0) |
| [lib]/mbed-storage-spif.a              |   5373(+5373) |     0(+0) |       40(+40) |
| [lib]/misc                             |     296(+296) |   12(+12) |       25(+25) |
| [lib]/stdc++_nano.a                    |         1(+1) |     0(+0) |         0(+0) |
| mbed-os/CMakeFiles                     | 43528(+43528) | 364(+364) |   2026(+2026) |
| Subtotals                              | 80001(+80001) | 496(+496) | 13592(+13592) |
Total Static RAM memory (data + bss): 14088(+14088) bytes
Total Flash memory (text + data): 80497(+80497) bytes

RAM Bank SRAM1_2: 14112(+0)/262144 bytes used, 5.4% (+0.0%) used
RAM Bank SRAM3: 0(+0)/524288 bytes used, 0.0% (+0.0%) used
ROM Bank Flash: 80505(+0)/1048576 bytes used, 7.7% (+0.0%) used

@lefebvresam
Copy link
Author

This looks better, the "target.memory_bank_config" was not member of the HMC20 custom device.

[410/410] Linking CXX executable mbed-mcuboot-bootloader.elf
-- built: /home/sam/git/mcuboot/build/mbed-mcuboot-bootloader.bin
-- built: /home/sam/git/mcuboot/build/mbed-mcuboot-bootloader.hex
/home/sam/git/mcuboot/mbed-os/tools/python/memap/memap.py:63: DeprecationWarning: the 'HEADER' constant is deprecated, use the 'HRuleStyle' and 'VRuleStyle' enums instead
  from prettytable import PrettyTable, HEADER
| Module                                 |         .text |     .data |          .bss |
|----------------------------------------|---------------|-----------|---------------|
| CMakeFiles/mbed-mcuboot-bootloader.dir |     516(+516) |     0(+0) |     408(+408) |
| [fill]                                 |       99(+99) |     4(+4) |       20(+20) |
| [lib]/bootutil.a                       |   7001(+7001) |     8(+8) | 10612(+10612) |
| [lib]/c_nano.a                         |   4648(+4648) |   92(+92) |     329(+329) |
| [lib]/gcc.a                            |   2748(+2748) |     0(+0) |         0(+0) |
| [lib]/mbed-mbedtls.a                   |   7978(+7978) |     0(+0) |         0(+0) |
| [lib]/mbed-mcuboot.a                   |   1644(+1644) |   16(+16) |     132(+132) |
| [lib]/mbed-storage-blockdevice.a       |   5172(+5172) |     0(+0) |         0(+0) |
| [lib]/mbed-storage-flashiap.a          |     997(+997) |     0(+0) |         0(+0) |
| [lib]/mbed-storage-spif.a              |   5373(+5373) |     0(+0) |       40(+40) |
| [lib]/misc                             |     296(+296) |   12(+12) |       25(+25) |
| [lib]/stdc++_nano.a                    |         1(+1) |     0(+0) |         0(+0) |
| mbed-os/CMakeFiles                     | 43528(+43528) | 364(+364) |   2026(+2026) |
| Subtotals                              | 80001(+80001) | 496(+496) | 13592(+13592) |
Total Static RAM memory (data + bss): 14088(+14088) bytes
Total Flash memory (text + data): 80497(+80497) bytes

RAM Bank SRAM1_2: 14112(+0)/262144 bytes used, 5.4% (+0.0%) used
RAM Bank SRAM3: 0(+0)/524288 bytes used, 0.0% (+0.0%) used
ROM Bank Flash: 80505(+0)/131072 bytes used, 61.4% (+0.0%) used

@JohnK1987
Copy link
Member

This looks better, the "target.memory_bank_config" was not member of the HMC20 custom device.

Just for clarification. The "target.memory_bank_config" should be just in mbed_app.json5 file under the override section. In custom_targets.json5 should be "memory_banks" like I wrote above. Because let say you want to set custom target settings for your HMC20 just once and then only copy&paste it to every new project. For application specific offsets like for bootloader or its apps you should use mbed_app.json5 file.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 10, 2024

Is this still necessary in mbed_app.json5?
"target.restrict_size": "0x20000",

And why the modficiations are needed in the linker script as you proposed in issuecomment-2526407974? It compiles exactly the same without these modifications.

@JohnK1987
Copy link
Member

JohnK1987 commented Dec 10, 2024

Is this still necessary in mbed_app.json5?
"target.restrict_size": "0x20000",

Nope, this one was working in ARM Mbed, in MbedCE this is not implemented.
It was just for define that the bootloader can not be bigger than 128KB (0x20000), which we are able to do with mbed_app.json5 and content below

         "target.memory_bank_config": {
             "IROM1": {
                 "size": 0x20000
             }
         }

@lefebvresam
Copy link
Author

lefebvresam commented Dec 10, 2024

I'm now preparing my main application. Do I also have to switch to bare metal? I currently have:

target_link_libraries(${APP_TARGET} PRIVATE
    mbed-os
...

I'm also facing this now:

CMake Error at mcuboot/boot/mbed/mcuboot_imgtool.cmake:32 (message):
  Must specify path to valid image signing key via MCUBOOT_SIGNING_KEY in
  order to build this project.
Call Stack (most recent call first):
  mcuboot/boot/mbed/CMakeLists.txt:49 (include)

@JohnK1987
Copy link
Member

That is up to you.

@lefebvresam
Copy link
Author

I see this error is invoked because of the latest commit in the branch mbed-ce-update-cmakelists, "Start on automation for creating images". Is this something I already have to deal with or do I need to stay on the previous commit?

@JohnK1987
Copy link
Member

JohnK1987 commented Dec 10, 2024

Sorry, I don't understand your description. Do you mean a commit in Jamie's McuBoot? I do not see any error.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 10, 2024

The requirement to define variabele MCUBOOT_SIGNING_KEY is something thas has been added in this recent commit of the mbed-ce-update-cmakelists branch of https://github.com/multiplemonomials/mcuboot.git. Is this something I can already use and how, or just neglect and still use the previous commit?

@JohnK1987
Copy link
Member

Ok, so it is related to McuBoot and Jamie's current work. I have no idea about this, sorry.

@lefebvresam
Copy link
Author

After doing all the right configuration for the primary application it looks like the start address is not picked up in the right way:

// This file contains application specific settings.
{
    "macros": [
        "MBED_HEAP_STATS_ENABLED=true",
        "MBED_THREAD_STATS_ENABLED=true",
        "OS_TIMERS=0"
    ],
    "config": {
        "serial-bootloader-enable": {
            "help": "Build bootloader with serial update support",
            "value": 0
        },
        "secondary-slot-in-flash": {
            "help": "If enabled, store the secondary slot in the application flash immediately after the primary slot.",
            "value": false
        }
    },    
    "target_overrides": {
        "*": {
            "mcuboot.bootloader-build": false,
            "target.c_lib": "small",
            "mcuboot.log-level": "MCUBOOT_LOG_LEVEL_DEBUG",
            "platform.stdio-baud-rate": 67800,
            "platform.stdio-buffered-serial": true,
            "platform.memory-tracing-enabled": true,
            "platform.callback-nontrivial": true,
            "target.printf_lib": "std",
            "mbed-trace.enable": true,
            "mbed-trace.max-level": "TRACE_LEVEL_DEBUG",
            "mbed-trace.fea-ipv6": false            
        },
        "HMC20": {
            "events.shared-dispatch-from-application": true,            
            "rtos.main-thread-stack-size": 11240,
            "drivers.uart-serial-rxbuf-size": 512,
            "drivers.uart-serial-txbuf-size": 512,
            "sd.SPI_CS": "SD_CS",
            "sd.SPI_MOSI": "SD_MOSI",
            "sd.SPI_MISO": "SD_MISO",
            "sd.SPI_CLK": "SD_CLK",
            "sd.TRX_FREQUENCY": 40000000,
            "spif-driver.SPI_CS": "SPIF_CS",
            "spif-driver.SPI_MOSI": "SPIF_MOSI",
            "spif-driver.SPI_MISO": "SPIF_MISO",
            "spif-driver.SPI_CLK": "SPIF_CLK",            
            "spif-driver.SPI_FREQ": 40000000,
            "mcuboot.primary-slot-address": "0x8020000",
            "mcuboot.slot-size": "0xC0000",
            "mcuboot.scratch-address": "0x80E0000",
            "mcuboot.scratch-size": "0x20000",
            "mcuboot.max-img-sectors": "0x180",
            "mcuboot.read-granularity": 1,
            // This replaces "target.restrict_size":
            "target.memory_bank_config": {
                "Flash": {
                    "size": 0xE0000,
                    "start": 0x8020000
                }
            }
        }
    }
}

And I get a lot of those messages:

...
Warning: Symbol .text._ZN6RA887514_readColorTrioEh (at address 0x801f40c, size 84) is not inside a defined memory bank for this target.
Warning: Symbol .text._ZN6RA887530SetBackgroundTransparencyColorEt (at address 0x801f460, size 28) is not inside a defined memory bank for this target.
Warning: Symbol .text._ZN6RA887530GetBackgroundTransparencyColorEv (at address 0x801f47c, size 6) is not inside a defined memory bank for this target.
Warning: Symbol .text._ZN6RA88759fontwidthEv (at address 0x801f482, size 30) is not inside a defined memory bank for this target.
Warning: Symbol .text._ZN6RA88757columnsEv (at address 0x801f4a0, size 16) is not inside a defined memory bank for this target.
Warning: Symbol .text._ZN6RA887512GetTextWidthEPKcb (at address 0x801f4b0, size 108) is not inside a defined memory bank for this target.
...

Is there something I miss in the configuration?

@lefebvresam
Copy link
Author

lefebvresam commented Dec 19, 2024

My test application boots but the first time I cannot confirm, which could be normal.

[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=bad, swap_type=0x0, copy_done=0x2, image_ok=0x2
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: none
[INFO][BL]: Booting firmware image at 0x8021000
[ERR ][main]: Failed to confirm boot: 4
[ERR ][main]: Failed to load version information: 1
[INFO][main]: > Press button to erase secondary slot
[INFO][main]: Secondary BlockDevice inited
[INFO][main]: Erasing secondary BlockDevice...
[INFO][main]: Secondary BlockDevice erased
[INFO][main]: > Press button to copy update image to secondary BlockDevice
[INFO][main]: FlashIAPBlockDevice inited
[INFO][main]: > Image copied to secondary BlockDevice, press button to activate
[INFO][main]: > Secondary image pending, reboot to update

I took over almost everything exactly in my head application and the primary image won't boot:

[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=bad, swap_type=0x0, copy_done=0x2, image_ok=0x2
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: none
[INFO][BL]: Booting firmware image at 0x8021000
-> hanging

To ensure I have something on the screen I print some text at start:

int main()
{
    // Enable traces from relevant trace groups
    mbed_trace_init();
    mbed_trace_include_filters_set("main,MCUb,BL");
    
    tr_info("The boot has been started\n");
    fflush(stdout);
    while(true) ThisThread::sleep_for(1s);
...

I also tested with printf(...) but no difference.

@zhiyong-ft
Copy link

@lefebvresam did you encrypt your initial image? We shall only encrypt images used for upgrade.

@multiplemonomials
Copy link
Collaborator

@zhiyong-ft I followed your instructions to add encryption support to the CMake build scripts. Please give it a shot if you get a chance, all the updates are pushed. Unfortunately it is not working on my end, have not had time to debug:

[INFO][MCUb]: Image index: 0, Swap type: test
[DBG ][MCUb]: flash area 1 open count: 2 (+)
[DBG ][MCUb]: flash area 1 open count: 3 (+)
[DBG ][MCUb]: flash area 1 open count: 2 (-)
[ERR ][MCUb]: Image in the secondary slot is not valid!
[DBG ][MCUb]: flash area 1 open count: 1 (-)
[DBG ][MCUb]: flash area 0 open count: 2 (+)
[DBG ][MCUb]: flash area 0 open count: 3 (+)
[DBG ][MCUb]: flash area 0 open count: 2 (-)
[DBG ][MCUb]: flash area 0 open count: 1 (-)
[DBG ][MCUb]: flash area 2 open count: 0 (-)

@multiplemonomials
Copy link
Collaborator

but what I did do is redraw George's diagram to be more accurate to Mbed CE!

mem bank diagram

@lefebvresam
Copy link
Author

lefebvresam commented Dec 19, 2024

@lefebvresam did you encrypt your initial image? We shall only encrypt images used for upgrade.

I don't use ecryption currently, just performed the same steps:

  cp ../hmipanel/build/develop/source/hmc20.hex .
  mcuboot/scripts/imgtool.py sign -k signing-keys.pem --align 4 -v 1.2.3+4 --header-size 4096 --pad-header -S 0xC0000 --pad hmc20.hex signed.hex
  hexmerge.py -o merged.hex --no-start-addr build/mbed-mcuboot-bootloader.hex signed.hex
  hexinfo.py merged.hex
  arm-none-eabi-objcopy -I ihex -O binary merged.hex merged.bin
  st-flash --freq=4M --reset write merged.bin  0x8000000

I also tested with --align 8

@zhiyong-ft
Copy link

@multiplemonomials I can confirm that encrypted image works on F767 as well, at least once. The SPIF block device driver for S25FL256L is still a bit funky, so anything related to SPIF doesn't work reliably. We are switching to a known QSPIF chip in next version of PCB, so I will stop fighting it. But encrypted images work reliably on DISCO_F746NG with QSPIF as secondary block device.

This test was done with mcuboot as of commit: 0fa393ad641ce651f7380c10dbb6def26e5ffe9e, I will test newer version later.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 19, 2024

@lefebvresam did you encrypt your initial image? We shall only encrypt images used for upgrade.

I don't use ecryption currently, just performed the same steps:

  cp ../hmipanel/build/develop/source/hmc20.hex .
  mcuboot/scripts/imgtool.py sign -k signing-keys.pem --align 4 -v 1.2.3+4 --header-size 4096 --pad-header -S 0xC0000 --pad hmc20.hex signed.hex
  hexmerge.py -o merged.hex --no-start-addr build/mbed-mcuboot-bootloader.hex signed.hex
  hexinfo.py merged.hex
  arm-none-eabi-objcopy -I ihex -O binary merged.hex merged.bin
  st-flash --freq=4M --reset write merged.bin  0x8000000

I also tested with --align 8

The root cause here is because I read version number outside the main function, and after a long chain of calls there is bd->init();in flash_area_open() of flash_map_backend.cpp. And initialization of block devices outside main is hanging in mbed-ce.

@zhiyong-ft
Copy link

zhiyong-ft commented Dec 19, 2024

@multiplemonomials I got encrypted image to work reliably on F767. I made some stupid mistakes when juggling around the erase sector sizes. So as far as I am concerned, mcuboot just works fine. Not sure why you had problems, my guess is that you either encrypted initial image, or there is something related to SD card if you used it as secondary block device.

I am still using imgtool.py from v1.8.0 to sign and encrypt images, but I doubt that could be the reason it is working on my hands but not your.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 20, 2024

I sign a primary image with version 1.1.3+4, then I create a test update signed-update.bin with version 1.2.4+6. I can clearly see those version numbers in the application headers of both images. I combine the primary image with the boatloader and flash with st-flash. It starts and the first time, the version cannot be read out and the boot cannot be confirmed. After the copy from the file signed-update.bin on SD card to SPI flash (Secondary slot) I reboot, magic is still bad, the swap is done, the new image starts and still the old version number is read out. After a second reboot, the swapped image starts again, magic is good but version number is still the old one. It looks like version number is not updated in the primary application header when the magic is bad, and you need several swaps to get it good. Maybe version number only updates when magic is good? Is there something I miss here of could it be a bug?

merged.bin:
image

signed-update.bin:
image

[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=bad, swap_type=0x0, copy_done=0x2, image_ok=0x2
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: none
[INFO][BL]: Booting firmware image at 0x8021000
[INFO][HMC20]: Starting main thread
[ERROR   DISPLAY     1149] cannot read version number: error_nr 1
[WARN][HMC20]: The boot could not been confirmed
[INFO][HMC20]: Secondary block device initialized
[INFO][HMC20]: Secondary block device erased
[INFO][HMC20]: copy chunk 0 at 0x00000
[INFO][HMC20]: copy chunk 1 at 0x04000
[INFO][HMC20]: copy chunk 2 at 0x08000
[INFO][HMC20]: copy chunk 3 at 0x0C000
[INFO][HMC20]: copy chunk 4 at 0x10000
[INFO][HMC20]: Copy done
[INFO][HMC20]: Reset MCU to update
[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=bad, swap_type=0x0, copy_done=0x2, image_ok=0x2
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: test
[INFO][MCUb]: Starting swap using scratch algorithm.
[INFO][BL]: Booting firmware image at 0x8021000
[INFO][main]: Boot confirmed
[INFO][main]: Hello version 1.1.3+4
I am new
[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=good, swap_type=0x2, copy_done=0x1, image_ok=0x1
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: none
[INFO][BL]: Booting firmware image at 0x8021000
[INFO][main]: Boot confirmed
[INFO][main]: Hello version 1.1.3+4
I am new

Reading the flash:
image

@lefebvresam lefebvresam reopened this Dec 20, 2024
@lefebvresam
Copy link
Author

lefebvresam commented Dec 20, 2024

If you call boot_get_current_version(&version);, you call boot_read_image_header(&state, 1, &hdr, &status); where '1' is int slot, in swap_scratch.c. To read the version in the primary slot, you need the id of the secundary slot (1) because of the line:

boot_read_image_header() in swap_scratch.c:

#define BOOT_PRIMARY_SLOT               0
#define BOOT_SECONDARY_SLOT             1
...
/* If all segments have been swapped, the header is located in the other slot */
hdr_slot = (slot == BOOT_PRIMARY_SLOT) ? BOOT_SECONDARY_SLOT : BOOT_PRIMARY_SLOT;

This seems not to be logical.

swap_count 1
bs->idx 134399953
BOOT_STATUS_IDX_0 1
If all segments have been swapped, the header is located in the other slot
hdr_slot 0
area_id 0
[INFO][main]: Hello version 1.2.4+6
I am new

@zhiyong-ft
Copy link

zhiyong-ft commented Dec 20, 2024

@lefebvresam what MCU are you using? The starting address 0x8021000 looks suspicious.

[INFO][BL]: Booting firmware image at 0x8021000

Keep in mind the region for application header has to be an erasable block or sector.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 20, 2024

This is correct. But I'm hunting for the issue. I recuperated a (wrong) piece of code to get the version number. If you don't offer the right data to the calls, the wrong parts in the calls are executed with unexpecting behavior. In the original one, the struct status was not filled in which gives garbage and wrong selections. (like bs->idx 134399953)

/**
 * Populates the version information of the
 * currently installed primary application
 *
 * @param[in] version Destination version structure buffer
 * @return 0 on success; nonzero on failure.
 */
int boot_get_current_version(struct image_version *version)
{
    assert(version != NULL);

    struct boot_loader_state boot_data;
    struct boot_loader_state *state = &boot_data;
    
    struct boot_status _bs;
    struct boot_status *bs = &_bs;

    memset(&boot_data, 0, sizeof(struct boot_loader_state));
    
    boot_status_reset(bs);
    int rc = swap_read_status(state, bs);
    if (rc != 0) {
        BOOT_LOG_WRN("Failed reading boot status; Image=%u", BOOT_CURR_IMG(state));
        return 1;
    }
    
    struct image_header _hdr;
    struct image_header *hdr = &_hdr;
   
    rc = boot_read_image_header(state, BOOT_PRIMARY_SLOT, hdr, bs);
    if (rc != 0) {
        return rc;
    }
    
    /** Copy the header's version struct over into the caller-supplied buffer */
    memcpy(version, &hdr->ih_ver, sizeof(struct image_version));
    return 0;
}

Alternative is skipping the call to boot_read_image_header and do directly:

    rc = flash_area_open(area_id, &fap);
    if (rc == 0) {
        rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr);
        flash_area_close(fap);
    }

Reading out version numbers of images is a very essential feature. I don't know why this is deleted in the current codebase.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 21, 2024

"mcuboot.encrypt-rsa": true,

I did the whole procedure to encrypt the images and I get:

[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=bad, swap_type=0x0, copy_done=0x2, image_ok=0x2
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: none
[ERR ][MCUb]: Image in the primary slot is not valid!
[ERR ][BL]: Failed to locate firmware image, error: -1
  echo "Sign the image and fit in the primary slot"
  mcuboot/scripts/imgtool.py sign -k signing-keys.pem --align 4 -v 1.2.3+4 --header-size 4096 --pad-header -S 0xC0000 -E enc_key_pub.pem --pad $HEX_APP_FILE signed.hex
  
  echo "Sign the update image and schrink"
  mcuboot/scripts/imgtool.py sign -k signing-keys.pem --align 4 -v 1.2.3+5 --header-size 4096 --pad-header -S 0x13000 -E enc_key_pub.pem $HEX_APP_FILE signed-update.hex 
  
  echo "Shift the update image"
  arm-none-eabi-objcopy --change-addresses 0x40000 --set-start 0x7FC0345 signed-update.hex signed-update.hex

  echo "Combine the 3 images" 
  hexmerge.py -o merged.hex --no-start-addr $HEX_DIR signed.hex signed-update.hex
  
  echo "Details of the combined image:"
  hexinfo.py merged.hex

  echo "Convert hex to bin"
  arm-none-eabi-objcopy -I ihex -O binary merged.hex merged.bin

  echo "Flash the chip with merged.bin"
  st-flash --freq=4M erase  0x8000000 0x100000
  st-flash --freq=4M --reset write merged.bin  0x8000000

I also edited the cmake file:

add_executable(${APP_TARGET}
    default_bd.cpp
    signing_keys.c
    enc_key.c
)

@zhiyong-ft
Copy link

echo "Shift the update image"
arm-none-eabi-objcopy --change-addresses 0x40000 --set-start 0x7FC0345 signed-update.hex signed-update.hex

The update image doesn't seem to have been encrypted. I used the imgtool from mcuboot v1.8.0 to manually sign and encrypt images, only used the latest version as bootloader.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 21, 2024

I pulled all the latest upstream updates in my mcuboot branch.

image

@lefebvresam
Copy link
Author

lefebvresam commented Dec 21, 2024

echo "Shift the update image"
arm-none-eabi-objcopy --change-addresses 0x40000 --set-start 0x7FC0345 signed-update.hex signed-update.hex

The update image doesn't seem to have been encrypted. I used the imgtool from mcuboot v1.8.0 to manually sign and encrypt images, only used the latest version as bootloader.

Why the update image must not be encrypted? The bootloader won't start the primary image, as at the error point has nothing to do with update image.

@lefebvresam
Copy link
Author

lefebvresam commented Dec 22, 2024

mcuboot mbed_app.json

// This file contains application specific settings.
{
    "macros": [
        "MCUBOOT_BOOT_MAX_ALIGN=16",
        "MBEDTLS_CIPHER_MODE_CTR"
    ],
    "config": {
        "serial-bootloader-enable": {
            "help": "Build bootloader with serial update support",
            "value": 0
        },
        "secondary-slot-in-flash": {
            "help": "If enabled, store the secondary slot in the application flash immediately after the primary slot.",
            "value": false
        }
    },
    "target_overrides": {
        "*": {
            "mcuboot.bootloader-build": true,
            "target.c_lib": "small",
            "mcuboot.log-enable": true,
            "mcuboot.log-level": "MCUBOOT_LOG_LEVEL_INFO",
            "mcuboot.log-bootloader-only": true,
            "mcuboot.encrypt-rsa": true,
            "platform.stdio-baud-rate": 67800,
            "mbed-trace.enable": true,
            "mbed-trace.max-level": "TRACE_LEVEL_DEBUG",
            "mbed-trace.fea-ipv6": false
        },
        "HMC20": {
            "events.shared-dispatch-from-application": true,            
            "rtos.main-thread-stack-size": 11240,
            "drivers.uart-serial-rxbuf-size": 512,
            "drivers.uart-serial-txbuf-size": 512,
            "sd.SPI_CS": "SD_CS",
            "sd.SPI_MOSI": "SD_MOSI",
            "sd.SPI_MISO": "SD_MISO",
            "sd.SPI_CLK": "SD_CLK",
            "sd.TRX_FREQUENCY": 40000000,
            "spif-driver.SPI_CS": "SPIF_CS",
            "spif-driver.SPI_MOSI": "SPIF_MOSI",
            "spif-driver.SPI_MISO": "SPIF_MISO",
            "spif-driver.SPI_CLK": "SPIF_CLK",            
            "spif-driver.SPI_FREQ": 40000000,
            "mcuboot.primary-slot-address": "0x8020000",
            "mcuboot.slot-size": "0xC0000",
            "mcuboot.header-size": "0x1000",
            "mcuboot.scratch-address": "0x80E0000",
            "mcuboot.scratch-size": "0x20000",
            "mcuboot.max-img-sectors": "0x180", // 0xC0000 / 1024 / 2 (based on the smallest sectors)
            "mcuboot.read-granularity": 1,
            // This replaces "target.restrict_size":
            "target.memory_bank_config": {
                "FLASH": {
                    "size": 0x20000
                }
            }
        }
    }
}

@lefebvresam
Copy link
Author

It looks like mcuboot don't know to start an encrypted image. And I did 'full' compiles by deleting the build folder first.

@zhiyong-ft
Copy link

zhiyong-ft commented Dec 22, 2024

mcuboot/scripts/imgtool.py sign -k signing-keys.pem --align 4 -v 1.2.3+4 --header-size 4096 --pad-header -S 0xC0000 -E enc_key_pub.pem --pad $HEX_APP_FILE signed.hex

Image for initial download shall NOT be encrypted. Encryption only applies to update image, to prevent them from being stolen during transportation or being stored in external devices such as SPIF or SD card. Remove `-E enc_key_pub.pem' and try again. I manually signed and encrypted images so I didn't notice this.

@multiplemonomials could you remove encryption from signing tool for initial image?

@lefebvresam
Copy link
Author

lefebvresam commented Dec 22, 2024

That looks better:

[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=bad, swap_type=0x0, copy_done=0x2, image_ok=0x2
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: none
[INFO][BL]: Booting firmware image at 0x8021000
[INFO][main]: Hello version 1.2.3+4
[INFO][main]: > Press button to erase secondary slot
[INFO][main]: Secondary BlockDevice inited
[INFO][main]: Erasing secondary BlockDevice...
[INFO][main]: Secondary BlockDevice erased
[INFO][main]: > Press button to copy update image to secondary BlockDevice
[INFO][main]: FlashIAPBlockDevice inited
[DBG ][main]: Copy chunk 0 at 0x00000
[DBG ][main]: Copy chunk 1 at 0x01000
[DBG ][main]: Copy chunk 2 at 0x02000
[DBG ][main]: Copy chunk 3 at 0x03000
[DBG ][main]: Copy chunk 4 at 0x04000
[DBG ][main]: Copy chunk 5 at 0x05000
[DBG ][main]: Copy chunk 6 at 0x06000
[DBG ][main]: Copy chunk 7 at 0x07000
[DBG ][main]: Copy chunk 8 at 0x08000
[DBG ][main]: Copy chunk 9 at 0x09000
[DBG ][main]: Copy chunk 10 at 0x0A000
[DBG ][main]: Copy chunk 11 at 0x0B000
[DBG ][main]: Copy chunk 12 at 0x0C000
[DBG ][main]: Copy chunk 13 at 0x0D000
[DBG ][main]: Copy chunk 14 at 0x0E000
[DBG ][main]: Copy chunk 15 at 0x0F000
[DBG ][main]: Copy chunk 16 at 0x10000
[DBG ][main]: Copy chunk 17 at 0x11000
[DBG ][main]: Copy chunk 18 at 0x12000
[INFO][main]: > Image copied to secondary BlockDevice, press button to activate
[INFO][main]: > Secondary image pending, reboot to update
[INFO][BL]: Starting MCUboot
[INFO][MCUb]: Primary image: magic=bad, swap_type=0x0, copy_done=0x2, image_ok=0x2
[INFO][MCUb]: Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INFO][MCUb]: Boot source: none
[INFO][MCUb]: Image index: 0, Swap type: test
[INFO][MCUb]: Starting swap using scratch algorithm.
[INFO][BL]: Booting firmware image at 0x8021000
[INFO][main]: Hello version 1.2.3+5
[INFO][main]: Boot confirmed
[INFO][main]: > Press button to erase secondary slot
[INFO][main]: Secondary BlockDevice inited
[INFO][main]: Erasing secondary BlockDevice...
[INFO][main]: Secondary BlockDevice erased
[INFO][main]: > Update finished

I updated my demo project with:

Confirming the primary image is not necessary and gives an error:

    if(version.iv_build_num > 4) {
        ret = boot_set_confirmed();
        if (ret == 0) {
            tr_info("Boot confirmed");
        } else {
            tr_error("Failed to confirm boot: %d", ret);
        }
    }

Avoid endless loop:

if(version.iv_build_num > 4) goto end; // update finished

Do automatic reboot:

void mbed_reset() {
    fflush(stdout); // flush to kernel
    fsync(fileno(stdout)); // wait for kernel flush
    HAL_NVIC_SystemReset();
} 

I updated my two test projects:

[email protected]:saleconix/mcuboot_app.git
[email protected]:saleconix/mcuboot.git

@lefebvresam
Copy link
Author

What I do not understand is why you don't need to append application trailer TLV's in the update image during signing while they are a part of the secundary slot.

@lefebvresam
Copy link
Author

And also, how to protect against copycat? Can you still do mcuboot updates when you protect the flash for readout?

@zhiyong-ft
Copy link

zhiyong-ft commented Dec 22, 2024

What I do not understand is why you don't need to append application trailer TLV's in the update image during signing while they are a part of the secundary slot.

I didn't particularly look into this. My understanding is that this is mostly a workflow issue. Supposedly primary image will need to do some verification after acquiring/noticing the existence of image in secondary slot, then add necessary TLVs before handing it to bootloader.

I actually padded update image as well to work around some other issues. The caveat is that once reboot, bootloader will always try to upgrade. If the update image is not padded, primary application needs to call boot_set_pending() first before bootloader will try to upgrade.

But my understanding above is based on MCUBoot v1.8.0 and reading documentation from Mr. Beckstein's repo. In a later discussion with Mr. Smith, he mentioned that we shall/can use the same un-padded image for both initial download and upgrade, at least with the latest version of MCUBoot. So I might be wrong/out of dated. Please do some investigation and report back.

@zhiyong-ft
Copy link

And also, how to protect against copycat? Can you still do mcuboot updates when you protect the flash for readout?

That's what is encryption is for. Bootloader has a copy of private key, stored in enc_key.c, it will use this key to decrypt encrypted images in secondary slot. If a party acquires a copy of encrypted image signed by enc_key_pub.pem, they won't be able to make sensor of it without corresponding private key.

@lefebvresam
Copy link
Author

What I do not understand is why you don't need to append application trailer TLV's in the update image during signing while they are a part of the secundary slot.

I didn't particularly look into this. My understanding is that this is mostly a workflow issue. Supposedly primary image will need to do some verification after acquiring/noticing the existence of image in secondary slot, then add necessary TLVs before handing it to bootloader.

I actually padded update image as well to work around some other issues. The caveat is that once reboot, bootloader will always try to upgrade. If the update image is not padded, primary application needs to call boot_set_pending() first before bootloader will try to upgrade.

Do you mean that primary image is adding some TLV's in the secundary slot after calling 'boot_set_pending'?

@lefebvresam
Copy link
Author

lefebvresam commented Dec 22, 2024

And also, how to protect against copycat? Can you still do mcuboot updates when you protect the flash for readout?

That's what is encryption is for. Bootloader has a copy of private key, stored in enc_key.c, it will use this key to decrypt encrypted images in secondary slot. If a party acquires a copy of encrypted image signed by enc_key_pub.pem, they won't be able to make sensor of it without corresponding private key.

So it means that the update image is deccrypted by the bootloader before it will be copied to the primary slot. So you need additional flash protection to protect against copy cat? (By using a programming device) And can you still write an update then?

@zhiyong-ft
Copy link

Do you mean that primary image is adding some TLV's in the secundary slot after calling 'boot_set_pending'?

That's my understanding. When I tested on DISCO_F746NG, without calling this function, bootloader will ignore image stored in secondary slot, even it is a newer version. I treat this as some kind of feature, because sometimes you do want user's input/approval and just blindly update whatever image in the secondary slot.

@lefebvresam
Copy link
Author

And is there a way to allow only upgrade and not downgrade or do you need to program it by yourself in your application by using my new function to read-out image versions?

@zhiyong-ft
Copy link

So it means that the update image is deccrypted by the bootloader before it will be copied to the primary slot. So you need additional flash protection to protect against copy cat? (By using a programming device) And can you still write an update then?

MCUboot will decrypt encrypted image stored in secondary slot chunk by chunk before writing decrypted chunks into primary slot. There is some discussion about treatment of scratch/swap in the MCUboot documentation but I don't recall. For this and your other question, you will have to consult documentation of MCUboot. My understanding is once image chunk is decrypted and stored in primary slot, MCUboot will think it is secure and don't do anything about it. You will have to do something to prevent people from reading the entire internal flash through JTAG or similar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants