Read binary from running partition

InterBilly
Posts: 13
Joined: Mon Jul 31, 2023 4:53 pm

Read binary from running partition

Postby InterBilly » Tue Oct 10, 2023 7:50 am

I am working on a hobby project where I need to copy the running application from one ESP to another (but not with WIFI or ethernet).
For guidance I looked at simple_ota_example from ESP-IDF and created a little test that should read the running binary per 8 bytes.
However, I have no idea how I should determine the amount of data to copy and how to check if the data is correct.
I tried to compare the data that is read with the binary by using the CMD command: "certutil -encodehex simple_ota.bin simple_ota.txt" but the data differs greatly.
On top of all that my C skills may be a little rusty, here is what I tried:

Code: Select all

    const char* typeNames[] = {"ESP_PARTITION_TYPE_APP", "ESP_PARTITION_TYPE_DATA", "ESP_PARTITION_TYPE_ANY"};
    const char* subtypeNames[] = {"ESP_PARTITION_SUBTYPE_APP_FACTORY", "ESP_PARTITION_SUBTYPE_APP_OTA_MIN"};


    const esp_partition_t *runnPar = esp_ota_get_running_partition();
    printf("Running partition:\n");
    printf("address: 0x%lX\n", runnPar->address);
    printf("size: %ld\n", runnPar->size); // size of partition, not binary
    printf("partition label: %s\n", runnPar->label);
    printf("type: %s\n", typeNames[runnPar->type]);
    printf("subtype: %s\n", subtypeNames[runnPar->subtype]);

    uint8_t byte_amt = 8;
    uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t) * byte_amt);    
    for (size_t i = 0; i < runnPar->size; i+=8)
    {
        esp_err_t ret = esp_partition_read(runnPar, runnPar->address + i, data, 8);
        for (int j = 0; j < byte_amt; j++)
        {
            printf("%02X ", data[i+j]);
        }
        printf("\n");
        vTaskDelay(10);
    }
Any advice is greatly appreciated.

MicroController
Posts: 1729
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Read binary from running partition

Postby MicroController » Tue Oct 10, 2023 11:44 am

The currently running application is already mmapped into the CPU's address space. That's why I would try to avoid reading the same physical address space via the partition API and instead read directly from the existing virtual address space.
I'm just not sure right now what virtual address range the application partition gets mapped to.

ESP_Sprite
Posts: 9759
Joined: Thu Nov 26, 2015 4:08 am

Re: Read binary from running partition

Postby ESP_Sprite » Wed Oct 11, 2023 3:48 am

MicroController wrote:
Tue Oct 10, 2023 11:44 am
The currently running application is already mmapped into the CPU's address space.
I don't think that is entirely true: the application consists of chunks that are loaded into RAM and chunks that are executed directly from flash. I think only the bit that executes directly from flash is mmap()ped in, not the other bits.

InterBilly: your issue is that partition->address is the offset in the flash chip, while esp_partition_read needs the offset in the partition. You should get the correct data with esp_partition_read(runnPar, i, data, 8);

The size of the binary is encoded in the application image; you can figure it out but beware it's not super-trivial. As usual, the esp-idf docs have the details. There is an API call that does this in an easier way, but for some reason there's not really any documentation for it, possibly this snippet helps.

MicroController
Posts: 1729
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Read binary from running partition

Postby MicroController » Wed Oct 11, 2023 7:04 pm

ESP_Sprite wrote:
Wed Oct 11, 2023 3:48 am
I think only the bit that executes directly from flash is mmap()ped in, not the other bits.
Makes total sense. I forgot about IRAM :roll:

ESP_Sprite
Posts: 9759
Joined: Thu Nov 26, 2015 4:08 am

Re: Read binary from running partition

Postby ESP_Sprite » Thu Oct 12, 2023 1:46 am

MicroController wrote:
Wed Oct 11, 2023 7:04 pm
Makes total sense. I forgot about IRAM :roll:
Aside from that, there's not only code in an application. For instance, the .data section will be copied to DRAM and also not mmap'ped.

InterBilly
Posts: 13
Joined: Mon Jul 31, 2023 4:53 pm

Re: Read binary from running partition

Postby InterBilly » Thu Oct 12, 2023 9:34 am

Thanks for the suggestions, now when I read the partition I can see the same data as in the .bin file so that looks good! :D

Next I tried to write this data on the OTA partition of another ESP, unfortunately I'm having difficulties again:
When I try to start a new OTA 'session' like this:

Code: Select all

const esp_partition_t *target = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL);
esp_ota_handle_t *ota_handle = NULL;
esp_err_t retv = esp_ota_begin(target, OTA_SIZE_UNKNOWN, update_handle);
esp_ota_begin() returns error code 258/0x102 : Invalid argument because the update handle is NULL. But as I understand the documentation esp_ota_begin() is supposed to initialize this handle: "out_handle – On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls.". I must be missing something here.

In the OTA example `simple_ota_example` this handle is part of the `esp_https_ota_handle` struct (which I am not using as I am not using http(s)) but I can't see anywhere where the needed handle is given a value before used in esp_ota_begin().

In the 'native_ota_example' the handle is given zero as value before handed to esp_ota_begin(), this does not make a difference for me.

Are there any examples of how to use OTA when supplying the new image yourself via your program and not https?

ghost07
Posts: 36
Joined: Mon Oct 03, 2022 11:47 am

Re: Read binary from running partition

Postby ghost07 » Thu Oct 12, 2023 9:47 am

First of all, pass the handle by reference:

Code: Select all

esp_ota_handle_t update_handle = NULL;
esp_err_t retv = esp_ota_begin(target, OTA_SIZE_UNKNOWN, &update_handle);
Notice the ampersand (&) in argument passing, and handle declaration as normal variable, not a pointer.

Second thing, check if result from esp_partition_find_first() is not NULL.

InterBilly
Posts: 13
Joined: Mon Jul 31, 2023 4:53 pm

Re: Read binary from running partition

Postby InterBilly » Thu Oct 12, 2023 7:37 pm

Rookie mistake :( my C is rusty to say the least. It works perfectly now, thanks a lot!

Who is online

Users browsing this forum: No registered users and 116 guests