Thanks again, Petro 🙂
I think I understand the MCUboot side of things well now.
In the arm V7 <board_boot_image()> code, that I believe you're familiar
with, there's a <struct arm_vector_table> that "assumes" the stack
pointer is the first address after the number of bytes specified by the
header length as passed by MCUboot (which is the number of bytes as per
the imgtool.py option <--header-size> as you say)
I currently know/believe this is further into the vector table that
probably immediately follows the MCUboot header in the SAMA5D2 NuttX
binary...but can't find, yet, a definitive reference as to where and why.
Once I know what it is I can define a similar struct to get the
necessary address. Then I can either call it as a (void *) or, better,
work out the assembly code needed.
Microchip are also helping me here - so between your help, them, and my
reverse engineering, I'm sure I can get there!
On 31/01/2025 22:44, Petro Karashchenko wrote:
Hi Tim,
I need to look into MCUboot loading strategies since in my case I was
executing from an internal flash drive, so there was no copying of the
image to RAM.
In general MCUboot expects an image to have a proper header and since ARM
vector table may have different requirements on alignment some tweaks may
be needed.
For example in SAMv7 case I used
apps/boot/mcuboot/mcuboot/scripts/imgtool.py sign --key \
apps/boot/mcuboot/mcuboot/root-rsa-2048.pem --align 8 \
--version 1.0.0 --header-size 0x200 --pad-header \
--slot-size 0xe0000 --overwrite-only --confirm \
nuttx/nuttx.bin signed_ota.bin
to create an OTA image. The header size of 0x200 plus padding option is
needed since ARM vector table needs to be properly aligned (you need to
check what are the requirements for SAMA5) and "flash.ld.template" contains
#ifdef CONFIG_SAMV7_FORMAT_MCUBOOT
# define MCUBOOT_HEADER_SIZE CONFIG_SAMV7_MCUBOOT_HEADER_SIZE
# ifdef CONFIG_BOARDCTL_BOOT_IMAGE
# define FLASH_OFFSET 0
# define FLASH_IMG_SIZE CONFIG_SAMV7_OTA_PRIMARY_SLOT_OFFSET
# else
# define FLASH_OFFSET (CONFIG_SAMV7_OTA_PRIMARY_SLOT_OFFSET +
MCUBOOT_HEADER_SIZE)
# define FLASH_IMG_SIZE (CONFIG_SAMV7_OTA_SLOT_SIZE -
MCUBOOT_HEADER_SIZE)
# endif
#else
# define FLASH_OFFSET 0
# define FLASH_IMG_SIZE CONFIG_ARCH_CHIP_SAMV7_MEM_FLASH
#endif
And "MCUBOOT_HEADER_SIZE" is set to 0x200. The "--slot-size" option should
also correspond to slot size in MCUboot partition table build. I will need
to check some other options like "--overwrite-only --confirm" as those may
be specific to my use case and may not be needed in general.
The rest is similar to what you describe. The MCUboot verifies the
signature and then jumps to address that is with MCUboot header offset from
the start of the loaded file. No big magic there. What may be missing for
your case is the proper configuration of MCUboot loading strategy that
copies image from flash to RAM prior to verifying it. I will try to browse
those options and reply in my next e-mail. The
https://github.com/mcu-tools/mcuboot/blob/main/docs/design.md is a good
starting point and it has
https://github.com/mcu-tools/mcuboot/blob/main/docs/design.md#ram-load
Also please explore help part from
https://github.com/mcu-tools/mcuboot/blob/main/scripts/imgtool/main.py as
it has options like "-L', '--load-addr'" and it will populate "RAM_LOAD"
flag as well as load address to MCUboot header of OTA image.
Switching from u-boot to MCUboot may be a bit non-intuitive, but as soon as
you complete it things will start moving smoother.
Hope that brings some light to your use case.
BR,
Petro
пт, 31 січ. 2025 р. о 18:30 Tim Hardisty <timhardist...@gmail.com> пише:
[resend as I managed to mangle the Subject!]
Hi Petro - thanks for replying. Here're the relevant info and hope it is
not going to relult in a TLDR reponse...
* SAMA5D27C-D1G SoC, with 128Mbyte on-chip DDR2 SDRAM
* External GigaDevice 128Mbyte QSPI flash running at 80MHz
* App size is only around 2 Mybtes at the moment, not likely to grow
beyond 6 MByte. So no need for XIP etc.
* Default SAMA5 operating methodology is:
o AT91 bootstrap that loads
o Bootloader. Uboot works, but trying to switch to MCUboot. This
copies
o my app to SRAM then runs it.
Current state is:
* I know that UBoot simply copies the entire NuttX binary to
0x20008000 and then executes a "go" at address 0x20008000. This is
from my Uboot start up script.
* I can download/debug my app as a full NuttX build via JTAG which
says it is loading at 0x20008000 (as per my VS Code/CortexA5 debug
startup script) and it reports on the console output that the start
address is 0x20008040
* MCUBoot runs and verifies a signed NuttX binary with the MCUboot
header etc but I can't load it properly quite yet
As of today though, using a non-MUCboot signed NuttX binary (i.e. the
same as I use for JTAG debug):
* Read the binary as a file and by that means look at the headers in
my debugger
* Use memcpy to copy the binary, "x" bytes at a time, to the SDRAM
address (0x20008000) which is the same address my .LD file specifies.
* Simply do a call to (void *)0x20008000 and it runs
* This emulates the Uboot methodology I guess (Uboot relies on my
script to specify the source/dest copy and run-from addresses). Low
level, hard-coded, but it works.
I also know:
* When I open and read the MCUboot-validated binary file, the first
"n" (32 in my case) are to do with MCUboot and MCUBoot's call to my
image loader function passes the size of this header to me (hdr_size)
* After that address should be the arm vector table with the address
to jump to. There is an address in the file - 0x20008040 - about
0x3b bytes after the MCUBoot header (that number of bytes is from
memory as I'm not at my work PC right now) and there's no reference
to 0x20008000 - but that might be correct as it correlates with my
debugger saying this is the start address. On't know why Uboot works
with 0x20008000 as the "go" address but hey ho.
This leaves me with three things to work on:
1. Understand how NuttX builds its binary header, and therefore where
it locates the vector table - is there a relevant struct I can use
and is the offset into the binary consistent or definied somewhere,
etc.
2. Find the right assemby code to do the jump rather than the (to me)
messy call/jump from within C to the hex address. I've done this
before but I think assembler is "better"?
3. Attempt to better understand Make.defs and/or .ld files to automate
the address gathering needed to generalise all of this and "create"
the parameters needed for the call to the MCUboot image
creation/signing tool. This I think I can do by reference to
existing NuttX board code. Fingers crossed.
Once I am happy, I will try and find time to see if I can "back port" it
to the in-tree SAMA5D2 reference boards (that I have a couple of) in the
repo so the information is captured for posterity!
The "why" is that Uboot has little if anything in the way of easy-to-use
A/B image swapping with reversion so I would have to code that myself.
It is really geared to Linux and not my cup of tea!!
On 31/01/2025 15:14, Petro Karashchenko wrote:
Hello Tim,
Some time ago I was adding MCUboot support for SAMv7 family that should
be
pretty similar to your system. If you can give some more description of
your use case: RAM and ROM config, does it have internal flash or
external,
where the program is executed from, etc. maybe I will be able to help
you.
Br,
Petro
On Wed, Jan 29, 2025, 11:59 AM Tim Hardisty<timhardist...@gmail.com>
wrote:
Thanks for taking the time to reply, Lwazi.
As best as I know, the Nuttx build (with my, or any app, set as the
start app) is running from RAM. Uboot certainly copies iteself to RAM
and runs - and if I get it it to load my build (which is smaller than
than the available ram) it works fine.
I see from that arm_head.S has a #error if CONFIG_BOOT_RUNFROMFLASH is
set, which confuses me as I haven't knowingly done anything to build the
NuttX binary to specifically run from DRAM or in XIP mode. But I will
delve deeper, thanks.
Related - I think the QSPI flash would need to be be put into XIP mode
to run that way so something else I can search for clues. Also I can
look at relocatable elf files etc which I know I've seen reference to.
I also see that u-boot does a memcpy of the elf binary from flash to RAM
so examining that code further might also give me clues.
If all else fails I will revert to using u-boot; I want(ed) to use
mcuboot as it natively supports iamge upgrades and swaps along with
encryption checks and seems to boot faster than uboot does. And I find
u-boot difficult to understand and work with, whereas mcuboot seemed
more "friendly"...until now lol.
Thanks,
TimH.
On 29/01/2025 02:46, Lwazi Dube wrote:
On Tue, 28 Jan 2025 at 13:30, Tim Hardisty<timhardist...@gmail.com>
wrote:
Hi all,
I am trying to get MCUboot to work on my custom board with a SAMA5D2
(Arm V7A) and after a lot of battles am nearly there.
I can boot into MCUboot stored in flash, and I can also download/debug
it.
MCUboot is happy enough with my firmware images to call my board's
"board_boot-image" function - but no SAMA5 boards in the repo have
this
function for me to refer to.
I have never used MCUboot.
What happens if you jump into _vector_start at the beginning of the
SAMA5
image? I presume that both your bootloader and nuttx are running XIP
from
NOR flash.
The entry is _vector_start here -> arch/arm/src/arm/arm_vectortab.S
... and it jumps into __start here ->arch/arm/src/arm/arm_head.S
Is this what you are looking for?