Skip to content

Commit cda08b7

Browse files
committed
Add rom_pick_ab_update_partition function
1 parent fa91723 commit cda08b7

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

src/rp2_common/pico_bootrom/bootrom.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
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

@@ -59,6 +62,23 @@ void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin
5962
}
6063

6164
#if !PICO_RP2040
65+
66+
67+
// Generated from adding the following code into the bootrom
68+
// scan_workarea_t* scan_workarea = (scan_workarea_t*)workarea;
69+
// printf("VERSION_DOWNGRADE_ERASE_ADDR %08x\n", &(always->zero_init.version_downgrade_erase_flash_addr));
70+
// printf("TBYB_FLAG_ADDR %08x\n", &(always->zero_init.tbyb_flag_flash_addr));
71+
// printf("IMAGE_DEF_VERIFIED %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.verified) - (uint32_t)scan_workarea);
72+
// printf("IMAGE_DEF_TBYB_FLAGGED %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.tbyb_flagged) - (uint32_t)scan_workarea);
73+
// printf("IMAGE_DEF_BASE %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.enclosing_window.base) - (uint32_t)scan_workarea);
74+
// 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);
75+
#define VERSION_DOWNGRADE_ERASE_ADDR *(uint32_t*)0x400e0338
76+
#define TBYB_FLAG_ADDR *(uint32_t*)0x400e0348
77+
#define IMAGE_DEF_VERIFIED(scan_workarea) *(uint32_t*)(0x64 + (uint32_t)scan_workarea)
78+
#define IMAGE_DEF_TBYB_FLAGGED(scan_workarea) *(uint32_t*)(0x4c + (uint32_t)scan_workarea)
79+
#define IMAGE_DEF_BASE(scan_workarea) *(uint32_t*)(0x54 + (uint32_t)scan_workarea)
80+
#define IMAGE_DEF_REL_BLOCK_OFFSET(scan_workarea) *(uint32_t*)(0x5c + (uint32_t)scan_workarea)
81+
6282
bool rom_get_boot_random(uint32_t out[4]) {
6383
uint32_t result[5];
6484
rom_get_sys_info_fn func = (rom_get_sys_info_fn) rom_func_lookup_inline(ROM_FUNC_GET_SYS_INFO);
@@ -99,4 +119,62 @@ int rom_add_flash_runtime_partition(uint32_t start_offset, uint32_t size, uint32
99119
}
100120
return PICO_ERROR_INSUFFICIENT_RESOURCES;
101121
}
122+
123+
int rom_pick_ab_update_partition(uint32_t *workarea_base, uint32_t workarea_size, uint partition_a_num) {
124+
uint32_t flash_update_base = 0;
125+
bool tbyb_boot = false;
126+
uint32_t saved_erase_addr = 0;
127+
if (rom_get_last_boot_type() == BOOT_TYPE_FLASH_UPDATE) {
128+
// For a flash update boot, get the flash update base
129+
boot_info_t boot_info = {};
130+
int ret = rom_get_boot_info(&boot_info);
131+
if (ret) {
132+
flash_update_base = boot_info.reboot_params[0];
133+
if (boot_info.tbyb_and_update_info & BOOT_TBYB_AND_UPDATE_FLAG_BUY_PENDING) {
134+
// A buy is pending, so the main software has not been bought
135+
tbyb_boot = true;
136+
// Save the erase address, as this will be overwritten by rom_pick_ab_partition
137+
saved_erase_addr = VERSION_DOWNGRADE_ERASE_ADDR;
138+
}
139+
}
140+
}
141+
142+
int rc = rom_pick_ab_partition((uint8_t*)workarea_base, workarea_size, partition_a_num, flash_update_base);
143+
144+
if (IMAGE_DEF_VERIFIED(workarea_base) != RCP_MASK_TRUE) {
145+
// Chosen partition failed verification
146+
return BOOTROM_ERROR_NOT_FOUND;
147+
}
148+
149+
if (IMAGE_DEF_TBYB_FLAGGED(workarea_base)) {
150+
// The chosen partition is TBYB
151+
if (tbyb_boot) {
152+
// The boot partition is also TBYB - cannot update both, so prioritise boot partition
153+
// Restore the erase address saved earlier
154+
VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr;
155+
return BOOTROM_ERROR_NOT_PERMITTED;
156+
} else {
157+
// Update the tbyb flash address, so that explicit_buy will clear the flag for the chosen partition
158+
TBYB_FLAG_ADDR =
159+
IMAGE_DEF_BASE(workarea_base)
160+
+ IMAGE_DEF_REL_BLOCK_OFFSET(workarea_base) + 4;
161+
}
162+
} else {
163+
// The chosen partition is not TBYB
164+
if (tbyb_boot && saved_erase_addr) {
165+
// The boot partition was TBYB, and requires an erase
166+
if (VERSION_DOWNGRADE_ERASE_ADDR) {
167+
// But both the chosen partition requires an erase too
168+
// As before, prioritise the boot partition, and restore it's saved erase_address
169+
VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr;
170+
return BOOTROM_ERROR_NOT_PERMITTED;
171+
} else {
172+
// The chosen partition doesn't require an erase, so we're fine
173+
VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr;
174+
}
175+
}
176+
}
177+
178+
return rc;
179+
}
102180
#endif

src/rp2_common/pico_bootrom/include/pico/bootrom.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,22 @@ static inline int rom_get_last_boot_type(void) {
10711071
*/
10721072
int rom_add_flash_runtime_partition(uint32_t start_offset, uint32_t size, uint32_t permissions);
10731073

1074+
/*! \brief Pick A/B partition for a separate partition
1075+
* \ingroup pico_bootrom
1076+
*
1077+
* This will perform extra checks to prevent disrupting a main image TBYB, and return errors
1078+
*
1079+
* Also checks that the chosen partition contained a valid image
1080+
*
1081+
* \param workarea_base base address of work area
1082+
* \param workarea_size size of work area
1083+
* @param partition_a_num the A partition of the pair
1084+
* @return >= 0 the partition number picked
1085+
* BOOTROM_ERROR_NOT_PERMITTED if not possible to do an update correctly, eg if both main image and data image are TBYB
1086+
* BOOTROM_ERROR_NOT_FOUND if the chosen partition failed verification
1087+
*/
1088+
int rom_pick_ab_update_partition(uint32_t *workarea_base, uint32_t workarea_size, uint partition_a_num);
1089+
10741090
#endif
10751091

10761092
#ifdef __cplusplus

0 commit comments

Comments
 (0)