How can I place a variable at an absolute address? Pass value between bootloader hook and application.

NotMyRealName
Posts: 41
Joined: Thu Feb 13, 2020 1:35 am

How can I place a variable at an absolute address? Pass value between bootloader hook and application.

Postby NotMyRealName » Mon Mar 07, 2022 1:53 am

Hi,

I've been reading through various posts for a few hours now and I'm not really getting anywhere so hoping someone can give me some pointers.

I've written a custom bootloader (using hooks in IDF4.4) for ESP32 that allows me to still write/erase (but not read) everything other than the bootloader itself. This is for a commercial project and we need to be able to reprogram the devices even when encrypted and using secure boot (V2).

All I want to do is set a global at a fixed address in both the custom BL and the APP so that the app can read and store the BL version to present this to the associated cloud platform etc. I need the version in case we discover a vulnerability and I have to disable it (I've added an efuse for this).

I've looked at the docs for linker fragments and can't figure out if its possible to specify a section address. It sort of doesn't look like it will allow it? I'm trying to put it in the RTC slow memory, but don't really care where it is to be honest.

For example, I think I'm after something similar to this in my linker file (sorry, not an expert at linker stuff):

Code: Select all

  
  .bl_meta 0x50000000 (NOLOAD):
  {
    . = ALIGN(4);
    _bl_meta_start = ABSOLUTE(.);
    *(.bl_meta)
    . = ALIGN(4) ;
    _bl_meta_end = ABSOLUTE(.);
  } > rtc_data_location
I'd appreciate any pointers anyone has! Preferably ones that don't involve modifying my IDF repo so it's not standard...

Thanks

boarchuz
Posts: 606
Joined: Tue Aug 21, 2018 5:28 am

Re: How can I place a variable at an absolute address? Pass value between bootloader hook and application.

Postby boarchuz » Mon Mar 07, 2022 3:25 am

I don't think it's possible to specify an address. You would need to maintain a custom esp_system component with your new section specified in the relevant linker script.

I had a need for the same thing this week - reserved RTC slow memory without having to have an entire esp_system hanging about to do so. My solution is mostly here: https://github.com/espressif/esp-idf/pu ... 1059076664

It basically just guarantees (at build time) that there's x bytes unused in the tail end of RTC slow memory (assuming that there's nothing after rtc_force_slow; careful IDF doesn't change this in future). You can do whatever you want with that memory then. It's up to you to initialise it on boot and/or checksum failure.

If you're not using the ULP you could use its config to reserve some memory at the start of RTC slow mem instead.

NotMyRealName
Posts: 41
Joined: Thu Feb 13, 2020 1:35 am

Re: How can I place a variable at an absolute address? Pass value between bootloader hook and application.

Postby NotMyRealName » Fri Apr 01, 2022 12:26 am

Thanks Boarchuz,

I have revisited this and put used the custom reserved RTC slow memory to pass my bootloader version. For me the 16 byte max size restriction is ample so no need to maintain any custom code! Yaay! :D

Thanks for the tip!

wilkxt
Posts: 15
Joined: Sun Mar 06, 2016 7:46 pm

Re: How can I place a variable at an absolute address? Pass value between bootloader hook and application.

Postby wilkxt » Mon Aug 07, 2023 7:22 am

Hi
NotMyRealName could you give an example how to write to RTC slow memory in bootloader (i use hook), and read it an application?
best regards, Tom

NotMyRealName
Posts: 41
Joined: Thu Feb 13, 2020 1:35 am

Re: How can I place a variable at an absolute address? Pass value between bootloader hook and application.

Postby NotMyRealName » Mon Aug 07, 2023 9:31 pm

Hi Tom,

I can't pen up an exact example for you sorry, but I did end up following the suggestion in the link from boarchuz.

Here is a snippet from my bootloader hooks file (called from bootloader_after_init() hook). This is probably not entirely my own work, can't remember if I copied bits of this from an example somewhere.

Code: Select all

void bootloader_SetVersionInRetainRam(){
    rtc_retain_mem_t *rtc_retain_mem = bootloader_common_get_rtc_retain_mem();
    int CRC_OK = esp_rom_crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc)) == rtc_retain_mem->crc && rtc_retain_mem->crc != UINT32_MAX;
    if(!CRC_OK){
        //I don't think it's actually going to get here? I think other areas of code call these bits first to set it valid.
        bootloader_common_reset_rtc_retain_mem();
    }
    rtc_retain_mem->custom[0] = BOOTLOADER_VERSION & 0xFF;
    rtc_retain_mem->custom[1] = (BOOTLOADER_VERSION>>8) & 0xFF;
    rtc_retain_mem->custom[2] = ESP_IDF_VERSION_MAJOR;
    rtc_retain_mem->custom[3] = ESP_IDF_VERSION_MINOR;
    rtc_retain_mem->custom[4] = ESP_IDF_VERSION_PATCH;



    /* This function will only update partition if not null. Only updates reboot counter if true.
     * It recalculates the CRC no matter what. This is our main reason for calling it.
     */
    bootloader_common_update_rtc_retain_mem(NULL, 0);

}
In my main application:

Code: Select all

static void sysReg_checkMbsBootloader(){

    rtc_retain_mem_t * retainMem = bootloader_common_get_rtc_retain_mem();

    uint16_t bootloaderVersion = retainMem->custom[0] | (((uint16_t)retainMem->custom[1])<<8);

    uint16_t bootCount = bootloader_common_get_rtc_retain_mem_reboot_counter();

    if(bootCount){
        // Boot Count is non-zero if CRC is correct for retain memory.
        mbsBlVersion = bootloaderVersion;
    }

    ESP_LOGI(TAG,"MBS Bootloader Version: %x, %i, IDF: %i.%i.%i", bootloaderVersion, bootCount, retainMem->custom[2],retainMem->custom[3],retainMem->custom[4]);
}
You should be able to find docs online for the bootloader retain mem functions. There will be some setup in the idf config menu as well for configuring how much memory and enabing it I think. Good luck! ;)

wilkxt
Posts: 15
Joined: Sun Mar 06, 2016 7:46 pm

Re: How can I place a variable at an absolute address? Pass value between bootloader hook and application.

Postby wilkxt » Tue Aug 08, 2023 5:58 am

Thank you very much, its works :-)
best regards, Tom

NotMyRealName
Posts: 41
Joined: Thu Feb 13, 2020 1:35 am

Re: How can I place a variable at an absolute address? Pass value between bootloader hook and application.

Postby NotMyRealName » Wed Dec 20, 2023 10:02 pm

Just found an issue with this! TAKE CARE IF YOU HAVE COPIED THIS CODE!

There is a difference in implementation between IDF 4.3 and IDF 4.4

The older code includes the custom section of the retain memory in the CRC calculation and the newer one skips it. Which is causing me compatability issues when using new application code on a device with an older bootloader.

Old implementation:
https://github.com/espressif/esp-idf/bl ... der.c#L166

New implementation:
https://github.com/espressif/esp-idf/bl ... der.c#L181

Unfortunately I have 1000s of units out there with a bootloader that has been generated from IDF 4.3 and application code that I need to update to code based on IDF 4.4. And more annoyingly, I missed this and have some with the new bootloader too! :roll:

Ideally this should have a menuconfig option for backwards compatability to optionally include the custom bytes in the CRC.

For me, its a bit late for that because I already have a mix of devices out there now. I'm going to have to rely on the checksum of the retain memory to make assumptions about the integrity of the custom memory. Going forward I might use some of the custom memory as a checksum for the rest of it. I don't have the luxury of doing that for bootloaders that are already out there of course.


Who is online

Users browsing this forum: No registered users and 169 guests