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

Invalidate specific OTA slot. (IDFGH-13982) #14808

Open
ddomnik opened this issue Oct 31, 2024 · 4 comments
Open

Invalidate specific OTA slot. (IDFGH-13982) #14808

ddomnik opened this issue Oct 31, 2024 · 4 comments
Assignees
Labels
Resolution: NA Issue resolution is unavailable Status: Done Issue is done internally Type: Feature Request Feature request for IDF

Comments

@ddomnik
Copy link

ddomnik commented Oct 31, 2024

Is your feature request related to a problem?

Let's assume we have two valid OTA partitions (ota0 and ota1) and both ota_state's are set to ESP_OTA_IMG_VALID.
Now ota1 partition gets erased and we perform this incomplete update sequence:

  • esp_ota_begin (does not update otadata)
  • esp_partition_write (does not update otadata)
  • esp_ota_end (does not update otadata)
  • esp_image_verify (does not update otadata)
  • esp_ota_set_boot_partition is not called. Because of a reset or a failed custom "header" check after esp_image_verify.

This would assume we have a valid image in ota1, even tho the update sequence has not been completed.

The same issue would appear if a factory partition is used to reflash ota0 that previously was marked as valid.

Describe the solution you'd like.

esp_ota_begin() should mark the to be flashed partition as ESP_OTA_IMG_INVALID.
To be more flexible and also to be able to mark specific partitions as invalid a generic function like these would be better:

esp_ota_mark_app_invalid(const esp_partition_t *partition);

esp_ota_set_state(const esp_partition_t *partition, esp_ota_img_states_t ota_state);

Describe alternatives you've considered.

  1. Rewriting the ota_data partition manually, but this seems to be hacky.
  2. Erase the partition content, but then the ota_state flag is still valid and the bootloader tries to load it.

Additional context.

The logic of the OTA data is quite complex to me and I am not even sure if ota_data actually behaves like this. As I think not every ota partition has a dedicated slot where the ota_state is stored? If so I may makes sense to make a function available like esp_ota_mark_app_invalid_rollback_and_reboot without the rollback and reboot part.

@ddomnik ddomnik added the Type: Feature Request Feature request for IDF label Oct 31, 2024
@github-actions github-actions bot changed the title Invalidate specific OTA slot. Invalidate specific OTA slot. (IDFGH-13982) Oct 31, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Oct 31, 2024
@mahavirj
Copy link
Member

mahavirj commented Nov 26, 2024

@ddomnik

OTA data partition contains 2 identical flash sectors each storing copies of esp_ota_select_entry_t otadata[2] data structure. Sequence number (ota_seq) and the state (ota_state) are 2 important fields in this data structure that helps to define the active partition. Following code should help to clear the logic behind the usage of sequence number:

//esp32_idf use two sector for store information about which partition is running
//it defined the two sector as ota data partition,two structure esp_ota_select_entry_t is saved in the two sector
//named data in first sector as otadata[0], second sector data as otadata[1]
//e.g.
//if otadata[0].ota_seq == otadata[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
//so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
//if otadata[0].ota_seq != 0 and otadata[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
//and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
//for example, if otadata[0].ota_seq = 4, otadata[1].ota_seq = 5, and there are 8 ota application,
//current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
//we should add otadata[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
//if A=(B - C)%D
//then B=(A + C)%D + D*n ,n= (0,1,2...)
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
//seq will add (x + n*1 + 1 - seq)%n

API esp_ota_set_boot_partition is responsible to correctly update both the fields ota_seq and ota_state in the OTA data partition. If there is a failure in calling this API then the new partition won't be activated yet and hence state (valid or invalid) does not really matter.

May I ask if you are observing any problem due to incorrect state of the image in the OTA data partition? If yes, could you please supply the detailed console logs here?

PS: you may use idf.py read-otadata to read out the OTA data partition on the device

@Alvin1Zhang
Copy link
Collaborator

Thanks for reporting, will close due to short of feedback, feel free to reopen with more updates.

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally and removed Status: Opened Issue is new labels Dec 10, 2024
@KonstantinKondrashov
Copy link
Collaborator

Hi @ddomnik!
You might use esp_ota_erase_last_boot_app_partition it erases the inactive ota_data slot and app partition as well. So you can use it.
Also, I see that we can improve the OTA lib as well. And erase the inactive ota_data slot in esp_ota_begin.

@espressif-bot espressif-bot added Status: In Progress Work is in progress and removed Status: Done Issue is done internally Resolution: Done Issue is done internally labels Dec 20, 2024
@ddomnik
Copy link
Author

ddomnik commented Dec 20, 2024

@KonstantinKondrashov thank you for your reply.

Also, I see that we can improve the OTA lib as well. And erase the inactive ota_data slot in esp_ota_begin.

This sounds great!

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: NA Issue resolution is unavailable and removed Status: In Progress Work is in progress labels Dec 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: NA Issue resolution is unavailable Status: Done Issue is done internally Type: Feature Request Feature request for IDF
Projects
None yet
Development

No branches or pull requests

5 participants