77#include "pico/bootrom.h"
88#include "boot/picoboot.h"
99#include "boot/picobin.h"
10+ #if !PICO_RP2040
11+ #include "hardware/rcp.h"
12+ #endif
1013
1114/// \tag::table_lookup[]
1215
@@ -64,6 +67,23 @@ void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin
6467}
6568
6669#if !PICO_RP2040
70+
71+
72+ // Generated from adding the following code into the bootrom
73+ // scan_workarea_t* scan_workarea = (scan_workarea_t*)workarea;
74+ // printf("VERSION_DOWNGRADE_ERASE_ADDR %08x\n", &(always->zero_init.version_downgrade_erase_flash_addr));
75+ // printf("TBYB_FLAG_ADDR %08x\n", &(always->zero_init.tbyb_flag_flash_addr));
76+ // printf("IMAGE_DEF_VERIFIED %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.verified) - (uint32_t)scan_workarea);
77+ // printf("IMAGE_DEF_TBYB_FLAGGED %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.tbyb_flagged) - (uint32_t)scan_workarea);
78+ // printf("IMAGE_DEF_BASE %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.enclosing_window.base) - (uint32_t)scan_workarea);
79+ // printf("IMAGE_DEF_REL_BLOCK_OFFSET %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.window_rel_block_offset) - (uint32_t)scan_workarea);
80+ #define VERSION_DOWNGRADE_ERASE_ADDR *(uint32_t*)0x400e0338
81+ #define TBYB_FLAG_ADDR *(uint32_t*)0x400e0348
82+ #define IMAGE_DEF_VERIFIED (scan_workarea ) *(uint32_t*)(0x64 + (uint32_t)scan_workarea)
83+ #define IMAGE_DEF_TBYB_FLAGGED (scan_workarea ) *(uint32_t*)(0x4c + (uint32_t)scan_workarea)
84+ #define IMAGE_DEF_BASE (scan_workarea ) *(uint32_t*)(0x54 + (uint32_t)scan_workarea)
85+ #define IMAGE_DEF_REL_BLOCK_OFFSET (scan_workarea ) *(uint32_t*)(0x5c + (uint32_t)scan_workarea)
86+
6787bool rom_get_boot_random (uint32_t out [4 ]) {
6888 uint32_t result [5 ];
6989 rom_get_sys_info_fn func = (rom_get_sys_info_fn ) rom_func_lookup_inline (ROM_FUNC_GET_SYS_INFO );
@@ -104,4 +124,62 @@ int rom_add_flash_runtime_partition(uint32_t start_offset, uint32_t size, uint32
104124 }
105125 return PICO_ERROR_INSUFFICIENT_RESOURCES ;
106126}
127+
128+ int rom_pick_ab_update_partition (uint32_t * workarea_base , uint32_t workarea_size , uint partition_a_num ) {
129+ uint32_t flash_update_base = 0 ;
130+ bool tbyb_boot = false;
131+ uint32_t saved_erase_addr = 0 ;
132+ if (rom_get_last_boot_type () == BOOT_TYPE_FLASH_UPDATE ) {
133+ // For a flash update boot, get the flash update base
134+ boot_info_t boot_info = {};
135+ int ret = rom_get_boot_info (& boot_info );
136+ if (ret ) {
137+ flash_update_base = boot_info .reboot_params [0 ];
138+ if (boot_info .tbyb_and_update_info & BOOT_TBYB_AND_UPDATE_FLAG_BUY_PENDING ) {
139+ // A buy is pending, so the main software has not been bought
140+ tbyb_boot = true;
141+ // Save the erase address, as this will be overwritten by rom_pick_ab_partition
142+ saved_erase_addr = VERSION_DOWNGRADE_ERASE_ADDR ;
143+ }
144+ }
145+ }
146+
147+ int rc = rom_pick_ab_partition ((uint8_t * )workarea_base , workarea_size , partition_a_num , flash_update_base );
148+
149+ if (IMAGE_DEF_VERIFIED (workarea_base ) != RCP_MASK_TRUE ) {
150+ // Chosen partition failed verification
151+ return BOOTROM_ERROR_NOT_FOUND ;
152+ }
153+
154+ if (IMAGE_DEF_TBYB_FLAGGED (workarea_base )) {
155+ // The chosen partition is TBYB
156+ if (tbyb_boot ) {
157+ // The boot partition is also TBYB - cannot update both, so prioritise boot partition
158+ // Restore the erase address saved earlier
159+ VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr ;
160+ return BOOTROM_ERROR_NOT_PERMITTED ;
161+ } else {
162+ // Update the tbyb flash address, so that explicit_buy will clear the flag for the chosen partition
163+ TBYB_FLAG_ADDR =
164+ IMAGE_DEF_BASE (workarea_base )
165+ + IMAGE_DEF_REL_BLOCK_OFFSET (workarea_base ) + 4 ;
166+ }
167+ } else {
168+ // The chosen partition is not TBYB
169+ if (tbyb_boot && saved_erase_addr ) {
170+ // The boot partition was TBYB, and requires an erase
171+ if (VERSION_DOWNGRADE_ERASE_ADDR ) {
172+ // But both the chosen partition requires an erase too
173+ // As before, prioritise the boot partition, and restore it's saved erase_address
174+ VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr ;
175+ return BOOTROM_ERROR_NOT_PERMITTED ;
176+ } else {
177+ // The chosen partition doesn't require an erase, so we're fine
178+ VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr ;
179+ }
180+ }
181+ }
182+
183+ return rc ;
184+ }
107185#endif
0 commit comments