1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef _PICO_BOOTROM_H
8 #define _PICO_BOOTROM_H
9
10 #include "pico.h"
11 #include "pico/bootrom_constants.h"
12
13 /** \file bootrom.h
14 * \defgroup pico_bootrom pico_bootrom
15 * \brief Access to functions and data in the bootrom
16 *
17 * This header may be included by assembly code
18 */
19
20 #ifndef __ASSEMBLER__
21 #include <string.h>
22 #include "pico/bootrom/lock.h"
23 #include "pico/flash.h"
24 // ROM FUNCTION SIGNATURES
25
26 #if PICO_RP2040
27 typedef uint32_t (*rom_popcount32_fn)(uint32_t);
28 typedef uint32_t (*rom_reverse32_fn)(uint32_t);
29 typedef uint32_t (*rom_clz32_fn)(uint32_t);
30 typedef uint32_t (*rom_ctz32_fn)(uint32_t);
31 typedef uint8_t *(*rom_memset_fn)(uint8_t *, uint8_t, uint32_t);
32 typedef uint32_t *(*rom_memset4_fn)(uint32_t *, uint8_t, uint32_t);
33 typedef uint32_t *(*rom_memcpy_fn)(uint8_t *, const uint8_t *, uint32_t);
34 typedef uint32_t *(*rom_memcpy44_fn)(uint32_t *, const uint32_t *, uint32_t);
35 #endif
36 typedef void __attribute__((noreturn)) (*rom_reset_usb_boot_fn)(uint32_t, uint32_t);
37 typedef int (*rom_reboot_fn)(uint32_t flags, uint32_t delay_ms, uint32_t p0, uint32_t p1);
38 typedef rom_reset_usb_boot_fn reset_usb_boot_fn; // kept for backwards compatibility
39 typedef void (*rom_connect_internal_flash_fn)(void);
40 typedef void (*rom_flash_exit_xip_fn)(void);
41 typedef void (*rom_flash_range_erase_fn)(uint32_t, size_t, uint32_t, uint8_t);
42 typedef void (*rom_flash_range_program_fn)(uint32_t, const uint8_t*, size_t);
43 typedef void (*rom_flash_flush_cache_fn)(void);
44 typedef void (*rom_flash_enter_cmd_xip_fn)(void);
45 #if !PICO_RP2040
46 typedef void (*rom_bootrom_state_reset_fn)(uint32_t flags);
47 typedef void (*rom_flash_reset_address_trans_fn)(void);
48 typedef void (*rom_flash_select_xip_read_mode_fn)(bootrom_xip_mode_t mode, uint8_t clkdiv);
49 typedef int (*rom_get_sys_info_fn)(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t flags);
50 typedef int (*rom_get_partition_table_info_fn)(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t partition_and_flags);
51 typedef int (*rom_explicit_buy_fn)(uint8_t *buffer, uint32_t buffer_size);
52 typedef void* (*rom_validate_ns_buffer_fn)(const void *addr, uint32_t size, uint32_t write, uint32_t *ok);
53 /**
54 * @return BOOTROM_OK if successful
55 * BOOTROM_ERROR_INVALID_ARG if ns_api_num is out of range
56 */
57 typedef intptr_t (*rom_set_rom_callback_fn)(uint callback_num, bootrom_api_callback_generic_t funcptr);
58 typedef int (*rom_chain_image_fn)(uint8_t *workarea_base, uint32_t workarea_size, uint32_t window_base, uint32_t window_size);
59 typedef int (*rom_load_partition_table_fn)(uint8_t *workarea_base, uint32_t workarea_size, bool force_reload);
60 typedef int (*rom_pick_ab_partition_fn)(uint8_t *workarea_base, uint32_t workarea_size, uint partition_a_num, uint32_t flash_update_boot_window_base);
61 typedef int (*rom_get_b_partition_fn)(uint pi_a);
62 typedef int (*rom_get_uf2_target_partition_fn)(uint8_t *workarea_base, uint32_t workarea_size, uint32_t family_id, resident_partition_t *partition_out);
63 typedef int (*rom_func_otp_access_fn)(uint8_t *buf, uint32_t buf_len, otp_cmd_t cmd);
64 // Apply the address translation currently specified in QMI_ATRANSx ("rolling window" hardware
65 // translation). Need to take care using this on the boot path, as the QMI may not yet have been
66 // set up, but this should be suitable for translating system bus addresses into flash storage
67 // addresses in user callbacks. Returns all-ones for an invalid address, which is also an invalid
68 // flash storage address, so invalidity is propagated.
69 typedef intptr_t (*rom_flash_runtime_to_storage_addr_fn)(uintptr_t flash_runtime_addr);
70
71 // Perform the specified erase/program/read operation, translating addresses according to
72 // QMI_ATRANSx if necessary, and checking flash permissions based on the resident partition table
73 // and the specified effective security level. `addr` may be either a flash runtime address or a
74 // flash storage address, depending on the ASPACE given in `flags`.
75 //
76 // NOTE: This function does not validate the buffer for NS access. This must be validated before
77 // calling if the caller is reachable from a Secure Gateway.
78 typedef int (*rom_flash_op_fn)(cflash_flags_t flags, uintptr_t addr, uint32_t size_bytes, uint8_t *buf);
79
80 #ifndef __riscv
81 typedef int (*rom_set_ns_api_permission_fn)(uint ns_api_num, bool allowed);
82 /**
83 * Note this is not strictly a C function; you must pass the function you are calling in r4
84 * @param in_r4
85 * `0b0xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx` - a "well known" function selector; do not use for your own methods
86 * `0b10xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx` - a "unique" function selector intended to be unlikely to clash with others'.
87 * The lower 30 bits should be chosen at random
88 * `0b11xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx` - a "private" function selector intended for use by tightly coupled NS and S code
89 *
90 * @return whatever the secure call returns
91 * BOOTROM_ERROR_INVALID_STATE if no secure handler has been set from the secure side
92 * via rom_set_rom_callback_fn(BOOTROM_API_CALLBACK_secure_call, ...)
93 */
94 typedef int (*rom_func_secure_call)(uintptr_t a0, ...);
95 #endif
96
97 #ifdef __riscv
98 typedef struct {
99 uint32_t *base;
100 uint32_t size;
101 } bootrom_stack_t;
102 // passed in, and out.
103 typedef int (*rom_set_bootrom_stack_fn)(bootrom_stack_t *stack);
104 #endif
105 #endif
106
107 #ifdef __cplusplus
108 extern "C" {
109 #endif
110
111 /*! \brief Return a bootrom lookup code based on two ASCII characters
112 * \ingroup pico_bootrom
113 *
114 * These codes are uses to lookup data or function addresses in the bootrom
115 *
116 * \param c1 the first character
117 * \param c2 the second character
118 * \return the 'code' to use in rom_func_lookup() or rom_data_lookup()
119 */
rom_table_code(uint8_t c1,uint8_t c2)120 static inline uint32_t rom_table_code(uint8_t c1, uint8_t c2) {
121 return ROM_TABLE_CODE((uint32_t) c1, (uint32_t) c2);
122 }
123
124 /*!
125 * \brief Lookup a bootrom function by its code
126 * \ingroup pico_bootrom
127 * \param code the code
128 * \return a pointer to the function, or NULL if the code does not match any bootrom function
129 */
130 void *rom_func_lookup(uint32_t code);
131
132 /*!
133 * \brief Lookup a bootrom data address by its code
134 * \ingroup pico_bootrom
135 * \param code the code
136 * \return a pointer to the data, or NULL if the code does not match any bootrom function
137 */
138 void *rom_data_lookup(uint32_t code);
139
140 /*!
141 * \brief Helper function to lookup the addresses of multiple bootrom functions
142 * \ingroup pico_bootrom
143 *
144 * This method looks up the 'codes' in the table, and convert each table entry to the looked up
145 * function pointer, if there is a function for that code in the bootrom.
146 *
147 * \param table an IN/OUT array, elements are codes on input, function pointers on success.
148 * \param count the number of elements in the table
149 * \return true if all the codes were found, and converted to function pointers, false otherwise
150 */
151 bool rom_funcs_lookup(uint32_t *table, unsigned int count);
152
153 // Bootrom function: rom_table_lookup
154 // Returns the 32 bit pointer into the ROM if found or NULL otherwise.
155 #if PICO_RP2040
156 typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);
157 #else
158 typedef void *(*rom_table_lookup_fn)(uint32_t code, uint32_t mask);
159 #endif
160
161 #if PICO_C_COMPILER_IS_GNU && (__GNUC__ >= 12)
162 // Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
rom_hword_as_ptr(uint16_t rom_address)163 __force_inline static void *rom_hword_as_ptr(uint16_t rom_address) {
164 #pragma GCC diagnostic push
165 #pragma GCC diagnostic ignored "-Warray-bounds"
166 return (void *)(uintptr_t)*(uint16_t *)(uintptr_t)rom_address;
167 #pragma GCC diagnostic pop
168 }
169 #else
170 // Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
171 #define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)(uintptr_t)(rom_address))
172 #endif
173
174 #ifdef __riscv
rom_size_is_64k(void)175 static __force_inline bool rom_size_is_64k(void) {
176 #ifdef RASPBERRYPI_AMETHYST_FPGA
177 return *(uint16_t*)0x14 >= 0x8000;
178 #else
179 return false;
180 #endif
181 }
182 #endif
183
184 /*!
185 * \brief Lookup a bootrom function by code. This method is forcibly inlined into the caller for FLASH/RAM sensitive code usage
186 * \ingroup pico_bootrom
187 * \param code the code
188 * \return a pointer to the function, or NULL if the code does not match any bootrom function
189 */
190 #pragma GCC diagnostic push
191 // diagnostic: GCC thinks near-zero value is a null pointer member access, but it's not
192 #pragma GCC diagnostic ignored "-Warray-bounds"
rom_func_lookup_inline(uint32_t code)193 static __force_inline void *rom_func_lookup_inline(uint32_t code) {
194 #if PICO_RP2040
195 rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET);
196 uint16_t *func_table = (uint16_t *) rom_hword_as_ptr(BOOTROM_FUNC_TABLE_OFFSET);
197 return rom_table_lookup(func_table, code);
198 #else
199 #ifdef __riscv
200 uint32_t rom_offset_adjust = rom_size_is_64k() ? 32 * 1024 : 0;
201 // on RISC-V the code (a jmp) is actually embedded in the table
202 rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_ENTRY_OFFSET + rom_offset_adjust);
203 return rom_table_lookup(code, RT_FLAG_FUNC_RISCV);
204 #else
205 // on ARM the function pointer is stored in the table, so we dereference it
206 // via lookup() rather than lookup_entry()
207 rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_OFFSET);
208 if (pico_processor_state_is_nonsecure()) {
209 return rom_table_lookup(code, RT_FLAG_FUNC_ARM_NONSEC);
210 } else {
211 return rom_table_lookup(code, RT_FLAG_FUNC_ARM_SEC);
212 }
213 #endif
214 #endif
215 }
216 #pragma GCC diagnostic pop
217
218 /*!
219 * \brief Reboot the device into BOOTSEL mode
220 * \ingroup pico_bootrom
221 *
222 * This function reboots the device into the BOOTSEL mode ('usb boot").
223 *
224 * Facilities are provided to enable an "activity light" via GPIO attached LED for the USB Mass Storage Device,
225 * and to limit the USB interfaces exposed.
226 *
227 * \param usb_activity_gpio_pin_mask 0 No pins are used as per a cold boot. Otherwise a single bit set indicating which
228 * GPIO pin should be set to output and raised whenever there is mass storage activity
229 * from the host.
230 * \param disable_interface_mask value to control exposed interfaces
231 * - 0 To enable both interfaces (as per a cold boot)
232 * - 1 To disable the USB Mass Storage Interface
233 * - 2 To disable the USB PICOBOOT Interface
234 */
235 void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask);
reset_usb_boot(uint32_t usb_activity_gpio_pin_mask,uint32_t disable_interface_mask)236 static inline void __attribute__((noreturn)) reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask) {
237 rom_reset_usb_boot(usb_activity_gpio_pin_mask, disable_interface_mask);
238 }
239
240 /*!
241 * \brief Reboot the device into BOOTSEL mode
242 * \ingroup pico_bootrom
243 *
244 * This function reboots the device into the BOOTSEL mode ('usb boot").
245 *
246 * Facilities are provided to enable an "activity light" via GPIO attached LED for the USB Mass Storage Device,
247 * and to limit the USB interfaces exposed.
248 *
249 * \param usb_activity_gpio_pin GPIO pin to be used as an activitiy pin, or -1 for none
250 * from the host.
251 * \param disable_interface_mask value to control exposed interfaces
252 * - 0 To enable both interfaces (as per a cold boot)
253 * - 1 To disable the USB Mass Storage Interface
254 * - 2 To disable the USB PICOBOOT Interface
255 * \param usb_activity_gpio_pin_active_low Activity GPIO is active low (ignored on RP2040)
256 */
257 void __attribute__((noreturn)) rom_reset_usb_boot_extra(int usb_activity_gpio_pin, uint32_t disable_interface_mask, bool usb_activity_gpio_pin_active_low);
258
259 /*!
260 * \brief Connect the SSI/QMI to the QSPI pads
261 * \ingroup pico_bootrom
262 *
263 * Restore all QSPI pad controls to their default state, and connect the SSI/QMI peripheral to the QSPI pads.
264 *
265 * \if rp2350_specific
266 * On RP2350 if a secondary flash chip select GPIO has been configured via OTP OTP_DATA_FLASH_DEVINFO, or by writing to the runtime
267 * copy of FLASH_DEVINFO in bootram, then this bank 0 GPIO is also initialised and the QMI peripheral is connected. Otherwise,
268 * bank 0 IOs are untouched.
269 * \endif
270 */
rom_connect_internal_flash(void)271 static inline void rom_connect_internal_flash(void) {
272 rom_connect_internal_flash_fn func = (rom_connect_internal_flash_fn) rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH);
273 func();
274 }
275
276 /*!
277 * \brief Return the QSPI device from its XIP state to a serial command state
278 * \ingroup pico_bootrom
279 *
280 * \if rp2040_specific
281 * On RP2040, first set up the SSI for serial-mode operations, then issue the fixed XIP exit sequence described in Section 2.8.1.2
282 * of the datasheet. Note that the bootrom code uses the IO forcing logic to drive the CS pin, which must be cleared before returning
283 * the SSI to XIP mode (e.g. by a call to _flash_flush_cache). This function configures the SSI with a fixed SCK clock divisor of /6.
284 * \endif
285 *
286 * \if rp2350_specific
287 * On RP2350, Initialise the QMI for serial operations (direct mode), and also initialise a basic XIP mode, where the QMI will perform
288 * 03h serial read commands at low speed (CLKDIV=12) in response to XIP reads.
289 *
290 * Then, issue a sequence to the QSPI device on chip select 0, designed to return it from continuous read mode ("XIP mode") and/or
291 * QPI mode to a state where it will accept serial commands. This is necessary after system reset to restore the QSPI device to a known
292 * state, because resetting RP2350 does not reset attached QSPI devices. It is also necessary when user code, having already performed
293 * some continuous-read-mode or QPI-mode accesses, wishes to return the QSPI device to a state where it will accept the serial erase and
294 * programming commands issued by the bootrom's flash access functions.
295 *
296 * If a GPIO for the secondary chip select is configured via FLASH_DEVINFO, then the XIP exit sequence is also issued to chip select 1.
297 *
298 * The QSPI device should be accessible for XIP reads after calling this function; the name flash_exit_xip refers to returning the QSPI
299 * device from its XIP state to a serial command state.
300 * \endif
301 */
rom_flash_exit_xip(void)302 static inline void rom_flash_exit_xip(void) {
303 rom_flash_exit_xip_fn func = (rom_flash_exit_xip_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP);
304 func();
305 }
306
307 /*!
308 * \brief Erase bytes in flash
309 * \ingroup pico_bootrom
310 *
311 * Erase count bytes, starting at addr (offset from start of flash). Optionally, pass a block erase command e.g. D8h block erase,
312 * and the size of the block erased by this command - this function will use the larger block erase where possible, for much higher
313 * erase speed. addr must be aligned to a 4096-byte sector, and count must be a multiple of 4096 bytes.
314 *
315 * This is a low-level flash API, and no validation of the arguments is performed.
316 *
317 * \if rp2350_specific
318 * See rom_flash_op on RP2350 for a higher-level API which checks alignment, flash bounds and partition permissions, and can transparently
319 * apply a runtime-to-storage address translation.
320 *
321 * The QSPI device must be in a serial command state before calling this API, which can be achieved by calling rom_connect_internal_flash()
322 * followed by rom_flash_exit_xip(). After the erase, the flash cache should be flushed via rom_flash_flush_cache() to ensure the modified
323 * flash data is visible to cached XIP accesses.
324 *
325 * Finally, the original XIP mode should be restored by copying the saved XIP setup function from bootram into SRAM, and executing it:
326 * the bootrom provides a default function which restores the flash mode/clkdiv discovered during flash scanning, and user programs can
327 * override this with their own XIP setup function.
328 *
329 * For the duration of the erase operation, QMI is in direct mode and attempting to access XIP from DMA, the debugger or the other core will
330 * return a bus fault. XIP becomes accessible again once the function returns.
331 * \endif
332 *
333 * \param addr the offset from start of flash to be erased
334 * \param count number of bytes to erase
335 * \param block_size optional size of block erased by block_cmd
336 * \param block_cmd optional block erase command e.g. D8h block erase
337 */
rom_flash_range_erase(uint32_t addr,size_t count,uint32_t block_size,uint8_t block_cmd)338 static inline void rom_flash_range_erase(uint32_t addr, size_t count, uint32_t block_size, uint8_t block_cmd) {
339 rom_flash_range_erase_fn func = (rom_flash_range_erase_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_ERASE);
340 func(addr, count, block_size, block_cmd);
341 }
342
343 /*!
344 * \brief Program bytes in flash
345 * \ingroup pico_bootrom
346 *
347 * Program data to a range of flash addresses starting at addr (offset from the start of flash) and count bytes in size. addr must be
348 * aligned to a 256-byte boundary, and count must be a multiple of 256.
349 *
350 * This is a low-level flash API, and no validation of the arguments is performed.
351 *
352 * \if rp2350_specific
353 * See rom_flash_op on RP2350 for a higher-level API which checks alignment, flash bounds and partition permissions,
354 * and can transparently apply a runtime-to-storage address translation.
355 *
356 * The QSPI device must be in a serial command state before calling this API - see notes on rom_flash_range_erase
357 * \endif
358 *
359 * \param addr the offset from start of flash to be erased
360 * \param data buffer containing the data to be written
361 * \param count number of bytes to erase
362 */
rom_flash_range_program(uint32_t addr,const uint8_t * data,size_t count)363 static inline void rom_flash_range_program(uint32_t addr, const uint8_t *data, size_t count) {
364 rom_flash_range_program_fn func = (rom_flash_range_program_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_PROGRAM);
365 func(addr, data, count);
366 }
367
368 /*!
369 * \brief Flush the XIP cache
370 * \ingroup pico_bootrom
371 *
372 * \if rp2040_specific
373 * Flush and enable the XIP cache. Also clears the IO forcing on QSPI CSn, so that the SSI can drive the flash chip select as normal.
374 * \endif
375 *
376 * \if rp2350_specific
377 * Flush the entire XIP cache, by issuing an invalidate by set/way maintenance operation to every cache line. This ensures that flash
378 * program/erase operations are visible to subsequent cached XIP reads.
379 *
380 * Note that this unpins pinned cache lines, which may interfere with cache-as-SRAM use of the XIP cache.
381 *
382 * No other operations are performed.
383 * \endif
384 */
rom_flash_flush_cache(void)385 static inline void rom_flash_flush_cache(void) {
386 rom_flash_flush_cache_fn func = (rom_flash_flush_cache_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);
387 func();
388 }
389
390 /*!
391 * \brief Configure the SSI/QMI with a standard command
392 * \ingroup pico_bootrom
393 *
394 * Configure the SSI/QMI to generate a standard 03h serial read command, with 24 address bits, upon each XIP access. This is a slow XIP
395 * configuration, but is widely supported. CLKDIV is set to 12 on RP2350. The debugger may call this function to ensure that flash is
396 * readable following a program/erase operation.
397 *
398 * Note that the same setup is performed by flash_exit_xip(), and the RP2350 flash program/erase functions do not leave XIP in an
399 * inaccessible state, so calls to this function are largely redundant on RP2350. It is provided on RP2350 for compatibility with RP2040.
400 */
rom_flash_enter_cmd_xip(void)401 static inline void rom_flash_enter_cmd_xip(void) {
402 rom_flash_enter_cmd_xip_fn func = (rom_flash_enter_cmd_xip_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_ENTER_CMD_XIP);
403 func();
404 }
405
406 #if !PICO_RP2040
407 #ifdef __riscv
408 /*!
409 * \brief Give the bootrom a new stack
410 * \ingroup pico_bootrom
411 *
412 * Most bootrom functions are written just once, in Arm code, to save space. As a result these functions are emulated when
413 * running under the RISC-V architecture. This is largely transparent to the user, however the stack used by the Arm emulation
414 * is separate from the calling user's stack, and is stored in boot RAM but is of quite limited size. When using certain of the more
415 * complex APIs or if nesting bootrom calls from within IRQs, you may need to provide a large stack.
416 *
417 * This method allows the caller to specify a region of RAM to use as the stack for the current core by passing a pointer to two values: the word aligned base address,
418 * and the size in bytes (multiple of 4).
419 *
420 * The method fills in the previous base/size values into the passed array before returning.
421 *
422 * \param stack bootrom_stack_t struct containing base and size
423 */
rom_set_bootrom_stack(bootrom_stack_t * stack)424 static inline int rom_set_bootrom_stack(bootrom_stack_t *stack) {
425 rom_set_bootrom_stack_fn func = (rom_set_bootrom_stack_fn) rom_func_lookup_inline(ROM_FUNC_SET_BOOTROM_STACK);
426 return func(stack);
427 }
428 #endif
429
430 /*!
431 * \brief Reboot using the watchdog
432 * \ingroup pico_bootrom
433 *
434 * Resets the chip and uses the watchdog facility to restart.
435 *
436 * The delay_ms is the millisecond delay before the reboot occurs. Note: by default this method is asynchronous
437 * (unless NO_RETURN_ON_SUCCESS is set - see below), so the method will return and the reboot will happen this many milliseconds later.
438 *
439 * The flags field contains one of the following values:
440 *
441 * REBOOT_TYPE_NORMAL - reboot into the normal boot path.
442 *
443 * REBOOT_TYPE_BOOTSEL - reboot into BOOTSEL mode.
444 * p0 - the GPIO number to use as an activity indicator (enabled by flag in p1).
445 * p1 - a set of flags:
446 * 0x01 : DISABLE_MSD_INTERFACE - Disable the BOOTSEL USB drive (see <<section_bootrom_mass_storage>>)
447 * 0x02 : DISABLE_PICOBOOT_INTERFACE - Disable the {picoboot} interface (see <<section_bootrom_picoboot>>).
448 * 0x10 : GPIO_PIN_ACTIVE_LOW - The GPIO in p0 is active low.
449 * 0x20 : GPIO_PIN_ENABLED - Enable the activity indicator on the specified GPIO.
450 *
451 * REBOOT_TYPE_RAM_IMAGE - reboot into an image in RAM. The region of RAM or XIP RAM is searched for an image to run. This is the type
452 * of reboot used when a RAM UF2 is dragged onto the BOOTSEL USB drive.
453 * p0 - the region start address (word-aligned).
454 * p1 - the region size (word-aligned).
455 *
456 * REBOOT_TYPE_FLASH_UPDATE - variant of REBOOT_TYPE_NORMAL to use when flash has been updated. This is the type
457 * of reboot used after dragging a flash UF2 onto the BOOTSEL USB drive.
458 * p0 - the address of the start of the region of flash that was updated. If this address matches the start address of a partition or slot, then that
459 * partition or slot is treated preferentially during boot (when there is a choice). This type of boot facilitates TBYB and version downgrades.
460 *
461 * REBOOT_TYPE_PC_SP - reboot to a specific PC and SP. Note: this is not allowed in the ARM-NS variant.
462 * p0 - the initial program counter (PC) to start executing at. This must have the lowest bit set for Arm and clear for RISC-V
463 * p1 - the initial stack pointer (SP).
464 *
465 * All of the above, can have optional flags ORed in:
466 *
467 * REBOOT_TO_ARM - switch both cores to the Arm architecture (rather than leaving them as is). The call will fail with BOOTROM_ERROR_INVALID_STATE if the Arm architecture is not supported.
468 * REBOOT_TO_RISCV - switch both cores to the RISC-V architecture (rather than leaving them as is). The call will fail with BOOTROM_ERROR_INVALID_STATE if the RISC-V architecture is not supported.
469 * NO_RETURN_ON_SUCCESS - the watchdog h/w is asynchronous. Setting this bit forces this method not to return if the reboot is successfully initiated.
470 *
471 * \param flags the reboot flags, as detailed above
472 * \param delay_ms millisecond delay before the reboot occurs
473 * \param p0 parameter 0, depends on flags
474 * \param p1 parameter 1, depends on flags
475 */
rom_reboot(uint32_t flags,uint32_t delay_ms,uint32_t p0,uint32_t p1)476 static inline int rom_reboot(uint32_t flags, uint32_t delay_ms, uint32_t p0, uint32_t p1) {
477 rom_reboot_fn func = (rom_reboot_fn) rom_func_lookup_inline(ROM_FUNC_REBOOT);
478 return func(flags, delay_ms, p0, p1);
479 }
480
481 bool rom_get_boot_random(uint32_t out[4]);
482
483 /*!
484 * \brief Reset bootrom state
485 * \ingroup pico_bootrom
486 *
487 * Resets internal bootrom state, based on the following flags:
488 *
489 * STATE_RESET_CURRENT_CORE - Resets any internal bootrom state for the current core into a clean state.
490 * This method should be called prior to calling any other bootrom APIs on the current core,
491 * and is called automatically by the bootrom during normal boot of core 0 and launch of code on core 1.
492 *
493 * STATE_RESET_OTHER_CORE - Resets any internal bootrom state for the other core into a clean state. This is generally called by
494 * a debugger when resetting the state of one core via code running on the other.
495 *
496 * STATE_RESET_GLOBAL_STATE - Resets all non core-specific state, including:
497 * Disables access to bootrom APIs from ARM-NS
498 * Unlocks all BOOT spinlocks
499 * Clears any secure code callbacks
500 *
501 * Note: the sdk calls this method on runtime initialisation to put the bootrom into a known state. This
502 * allows the program to function correctly if it is entered (e.g. from a debugger) without taking the usual boot path (which
503 * resets the state appropriately itself).
504 *
505 * \param flags flags, as detailed above
506 */
rom_bootrom_state_reset(uint32_t flags)507 static inline void rom_bootrom_state_reset(uint32_t flags) {
508 rom_bootrom_state_reset_fn func = (rom_bootrom_state_reset_fn) rom_func_lookup_inline(ROM_FUNC_BOOTROM_STATE_RESET);
509 return func(flags);
510 }
511
512 /*!
513 * \brief Reset address translation
514 * \ingroup pico_bootrom
515 *
516 * Restore the QMI address translation registers, QMI_ATRANS0 through QMI_ATRANS7, to their reset state. This makes the
517 * runtime-to-storage address map an identity map, i.e. the mapped and unmapped address are equal, and the entire space is
518 * fully mapped.
519 */
rom_flash_reset_address_trans(void)520 static inline void rom_flash_reset_address_trans(void) {
521 rom_flash_reset_address_trans_fn func = (rom_flash_reset_address_trans_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_RESET_ADDRESS_TRANS);
522 func();
523 }
524
525 /*!
526 * \brief Configure QMI in a XIP read mode
527 * \ingroup pico_bootrom
528 *
529 * Configure QMI for one of a small menu of XIP read modes supported by the bootrom. This mode is configured for both memory
530 * windows (both chip selects), and the clock divisor is also applied to direct mode.
531 *
532 * \param mode bootrom_xip_mode_t mode to use
533 * \param clkdiv clock divider
534 */
rom_flash_select_xip_read_mode(bootrom_xip_mode_t mode,uint8_t clkdiv)535 static inline void rom_flash_select_xip_read_mode(bootrom_xip_mode_t mode, uint8_t clkdiv) {
536 rom_flash_select_xip_read_mode_fn func = (rom_flash_select_xip_read_mode_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_SELECT_XIP_READ_MODE);
537 func(mode, clkdiv);
538 }
539
540 typedef struct {
541 cflash_flags_t flags;
542 uintptr_t addr;
543 uint32_t size_bytes;
544 uint8_t *buf;
545 int *res;
546 } rom_helper_flash_op_params_t;
547
rom_helper_flash_op(void * param)548 static inline void rom_helper_flash_op(void *param) {
549 const rom_helper_flash_op_params_t *op = (const rom_helper_flash_op_params_t *)param;
550 rom_flash_op_fn func = (rom_flash_op_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_OP);
551 *(op->res) = func(op->flags, op->addr, op->size_bytes, op->buf);
552 }
553
554 /*!
555 * \brief Perform a flash read, erase, or program operation
556 * \ingroup pico_bootrom
557 *
558 * The flash operation is bounds-checked against the known flash devices specified by the runtime value of FLASH_DEVINFO,
559 * stored in bootram. This is initialised by the bootrom to the OTP value OTP_DATA_FLASH_DEVINFO, if
560 * OTP_DATA_BOOT_FLAGS0_FLASH_DEVINFO_ENABLE is set; otherwise it is initialised to 16 MiB for chip select 0 and 0 bytes
561 * for chip select 1. FLASH_DEVINFO can be updated at runtime by writing to its location in bootram, the pointer to which
562 * can be looked up in the ROM table.
563 *
564 * If a resident partition table is in effect, then the flash operation is also checked against the partition permissions.
565 * The Secure version of this function can specify the caller's effective security level (Secure, Non-secure, bootloader)
566 * using the CFLASH_SECLEVEL_BITS bitfield of the flags argument, whereas the Non-secure function is always checked against
567 * the Non-secure permissions for the partition. Flash operations which span two partitions are not allowed, and will fail
568 * address validation.
569 *
570 * If OTP_DATA_FLASH_DEVINFO_D8H_ERASE_SUPPORTED is set, erase operations will use a D8h 64 kiB block erase command where
571 * possible (without erasing outside the specified region), for faster erase time. Otherwise, only 20h 4 kiB sector erase
572 * commands are used.
573 *
574 * Optionally, this API can translate addr from flash runtime addresses to flash storage addresses, according to the
575 * translation currently configured by QMI address translation registers, QMI_ATRANS0 through QMI_ATRANS7. For example, an
576 * image stored at a +2 MiB offset in flash (but mapped at XIP address 0 at runtime), writing to an offset of +1 MiB into
577 * the image, will write to a physical flash storage address of 3 MiB. Translation is enabled by setting the
578 * CFLASH_ASPACE_BITS bitfield in the flags argument.
579 *
580 * When translation is enabled, flash operations which cross address holes in the XIP runtime address space (created by
581 * non-maximum ATRANSx_SIZE) will return an error response. This check may tear: the transfer may be partially performed
582 * before encountering an address hole and ultimately returning failure.
583 *
584 * When translation is enabled, flash operations are permitted to cross chip select boundaries, provided this does not
585 * span an ATRANS address hole. When translation is disabled, the entire operation must target a single flash chip select
586 * (as determined by bits 24 and upward of the address), else address validation will fail.
587 *
588 * \param flags controls the security level, address space, and flash operation
589 * \param addr the address of the first flash byte to be accessed, ranging from XIP_BASE to XIP_BASE + 0x1ffffff
590 * \param size_bytes size of buf, in bytes
591 * \param buf contains data to be written to flash, for program operations, and data read back from flash, for read operations
592 */
rom_flash_op(cflash_flags_t flags,uintptr_t addr,uint32_t size_bytes,uint8_t * buf)593 static inline int rom_flash_op(cflash_flags_t flags, uintptr_t addr, uint32_t size_bytes, uint8_t *buf) {
594 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_FLASH_OP))
595 return BOOTROM_ERROR_LOCK_REQUIRED;
596 int rc = 0;
597 rom_helper_flash_op_params_t params = {
598 .flags = flags,
599 .addr = addr,
600 .size_bytes = size_bytes,
601 .buf = buf,
602 .res = &rc
603 };
604 int flash_rc = flash_safe_execute(rom_helper_flash_op, ¶ms, UINT32_MAX);
605 bootrom_release_lock(BOOTROM_LOCK_FLASH_OP);
606 if (flash_rc != PICO_OK) {
607 return flash_rc;
608 } else {
609 return rc;
610 }
611 }
612
613 /*!
614 * \brief Writes data from a buffer into OTP, or reads data from OTP into a buffer
615 * \ingroup pico_bootrom
616 *
617 * The buffer must be aligned to 2 bytes or 4 bytes according to the IS_ECC flag.
618 *
619 * This method will read and write rows until the first row it encounters that fails a key or permission check at which
620 * it will return BOOTROM_ERROR_NOT_PERMITTED.
621 *
622 * Writing will also stop at the first row where an attempt is made to set an OTP bit from a 1 to a 0, and
623 * BOOTROM_ERROR_UNSUPPORTED_MODIFICATION will be returned.
624 *
625 * If all rows are read/written successfully, then BOOTROM_OK will be returned.
626 *
627 * \param buf buffer to read to/write from
628 * \param buf_len size of buf
629 * \param cmd OTP command to execute
630 * - 0x0000ffff - ROW_NUMBER: 16 low bits are row number (0-4095)
631 * - 0x00010000 - IS_WRITE: if set, do a write (not a read)
632 * - 0x00020000 - IS_ECC: if this bit is set, each value in the buffer is 2 bytes and ECC is used when read/writing from 24
633 * bit value in OTP. If this bit is not set, each value in the buffer is 4 bytes, the low 24-bits of which are written
634 * to or read from OTP.
635
636 */
rom_func_otp_access(uint8_t * buf,uint32_t buf_len,otp_cmd_t cmd)637 static inline int rom_func_otp_access(uint8_t *buf, uint32_t buf_len, otp_cmd_t cmd) {
638 rom_func_otp_access_fn func = (rom_func_otp_access_fn) rom_func_lookup_inline(ROM_FUNC_OTP_ACCESS);
639 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_OTP))
640 return BOOTROM_ERROR_LOCK_REQUIRED;
641 int rc = func(buf, buf_len, cmd);
642 bootrom_release_lock(BOOTROM_LOCK_OTP);
643 return rc;
644 }
645
646 /*!
647 * \brief Fills a buffer with information from the partition table
648 * \ingroup pico_bootrom
649 *
650 * Fills a buffer with information from the partition table. Note that this API is also used to return information over the
651 * picoboot interface.
652 *
653 * On success, the buffer is filled, and the number of words filled in the buffer is returned. If the partition table
654 * has not been loaded (e.g. from a watchdog or RAM boot), then this method will return BOOTROM_ERROR_NO_DATA, and you
655 * should load the partition table via load_partition_table() first.
656 *
657 * Note that not all data from the partition table is kept resident in memory by the bootrom due to size constraints.
658 * To protect against changes being made in flash after the bootrom has loaded the resident portion, the bootrom keeps
659 * a hash of the partition table as of the time it loaded it. If the hash has changed by the time this method is called,
660 * then it will return BOOTROM_ERROR_INVALID_STATE.
661 *
662 * The information returned is chosen by the partition_and_flags parameter; the first word in the returned buffer,
663 * is the (sub)set of those flags that the API supports. You should always check this value before interpreting
664 * the buffer.
665 *
666 * Following the first word, returns words of data for each present flag in order. With the exception of PT_INFO,
667 * all the flags select "per partition" information, so each field is returned in flag order for one partition after
668 * the next. The special SINGLE_PARTITION flag indicates that data for only a single partition is required.
669 *
670 * \param out_buffer buffer to write data to
671 * \param out_buffer_word_size size of out_buffer, in words
672 * \param partition_and_flags partition number and flags
673 */
rom_get_partition_table_info(uint32_t * out_buffer,uint32_t out_buffer_word_size,uint32_t partition_and_flags)674 static inline int rom_get_partition_table_info(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t partition_and_flags) {
675 rom_get_partition_table_info_fn func = (rom_get_partition_table_info_fn) rom_func_lookup_inline(ROM_FUNC_GET_PARTITION_TABLE_INFO);
676 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
677 return BOOTROM_ERROR_LOCK_REQUIRED;
678 int rc = func(out_buffer, out_buffer_word_size, partition_and_flags);
679 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
680 return rc;
681 }
682
683 // todo SECURE only
684 /*!
685 * \brief Loads the current partition table from flash, if present
686 * \ingroup pico_bootrom
687 *
688 * This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
689 * As a result it requires a user provided memory buffer as a work area. The work area should byte word-aligned and of sufficient size
690 * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
691 *
692 * If force_reload is false, then this method will return BOOTROM_OK immediately if the bootrom is loaded, otherwise it will
693 * reload the partition table if it has been loaded already, allowing for the partition table to be updated in a running program.
694 *
695 * \param workarea_base base address of work area
696 * \param workarea_size size of work area
697 * \param force_reload force reloading of the partition table
698 */
rom_load_partition_table(uint8_t * workarea_base,uint32_t workarea_size,bool force_reload)699 static inline int rom_load_partition_table(uint8_t *workarea_base, uint32_t workarea_size, bool force_reload) {
700 rom_load_partition_table_fn func = (rom_load_partition_table_fn) rom_func_lookup_inline(ROM_FUNC_LOAD_PARTITION_TABLE);
701 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
702 return BOOTROM_ERROR_LOCK_REQUIRED;
703 int rc = func(workarea_base, workarea_size, force_reload);
704 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
705 return rc;
706 }
707
708 // todo SECURE only
709 /*!
710 * \brief Pick a partition from an A/B pair
711 * \ingroup pico_bootrom
712 *
713 * Determines which of the partitions has the "better" IMAGE_DEF. In the case of executable images, this is the one that would be booted
714 *
715 * This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
716 * As a result it requires a user provided memory buffer as a work area. The work area should bye word aligned, and of sufficient size
717 * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
718 *
719 * The passed partition number can be any valid partition number other than the "B" partition of an A/B pair.
720 *
721 * This method returns a negative error code, or the partition number of the picked partition if (i.e. partition_a_num or the
722 * number of its "B" partition if any).
723 *
724 * NOTE: This method does not look at owner partitions, only the A partition passed and it's corresponding B partition.
725 *
726 * \param workarea_base base address of work area
727 * \param workarea_size size of work area
728 * \param partition_a_num the A partition of the pair
729 * \param flash_update_boot_window_base the flash update base, to pick that partition instead of the normally "better" partition
730 */
rom_pick_ab_partition(uint8_t * workarea_base,uint32_t workarea_size,uint partition_a_num,uint32_t flash_update_boot_window_base)731 static inline int rom_pick_ab_partition(uint8_t *workarea_base, uint32_t workarea_size, uint partition_a_num, uint32_t flash_update_boot_window_base) {
732 rom_pick_ab_partition_fn func = (rom_pick_ab_partition_fn) rom_func_lookup_inline(ROM_FUNC_PICK_AB_PARTITION);
733 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
734 return BOOTROM_ERROR_LOCK_REQUIRED;
735 int rc = func(workarea_base, workarea_size, partition_a_num, flash_update_boot_window_base);
736 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
737 return rc;
738 }
739
740 /*!
741 * \brief Get B partition
742 * \ingroup pico_bootrom
743 *
744 * Returns the index of the B partition of partition A if a partition table is present and loaded, and there is a partition A with a B partition;
745 * otherwise returns BOOTROM_ERROR_NOT_FOUND.
746 *
747 * \param pi_a the A partition number
748 */
rom_get_b_partition(uint pi_a)749 static inline int rom_get_b_partition(uint pi_a) {
750 rom_get_b_partition_fn func = (rom_get_b_partition_fn) rom_func_lookup_inline(ROM_FUNC_GET_B_PARTITION);
751 return func(pi_a);
752 }
753
754 // todo SECURE only
755 /*!
756 * \brief Get UF2 Target Partition
757 * \ingroup pico_bootrom
758 *
759 * This method performs the same operation to decide on a target partition for a UF2 family ID as when a UF2 is dragged onto the USB
760 * drive in BOOTSEL mode.
761 *
762 * This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
763 * As a result it requires a user provided memory buffer as a work area. The work area should byte word-aligned and of sufficient size
764 * or `BOOTROM_ERROR_INSUFFICIENT_RESOURCES` will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
765 *
766 * If the partition table
767 * has not been loaded (e.g. from a watchdog or RAM boot), then this method will return `BOOTROM_ERROR_PRECONDITION_NOT_MET`, and you
768 * should load the partition table via <<api-load_partition_table, load_partition_table()>> first.
769 *
770 * \param workarea_base base address of work area
771 * \param workarea_size size of work area
772 * \param family_id the family ID to place
773 * \param partition_out pointer to the resident_partition_t to fill with the partition data
774 */
rom_get_uf2_target_partition(uint8_t * workarea_base,uint32_t workarea_size,uint32_t family_id,resident_partition_t * partition_out)775 static inline int rom_get_uf2_target_partition(uint8_t *workarea_base, uint32_t workarea_size, uint32_t family_id, resident_partition_t *partition_out) {
776 rom_get_uf2_target_partition_fn func = (rom_get_uf2_target_partition_fn) rom_func_lookup_inline(ROM_FUNC_GET_UF2_TARGET_PARTITION);
777 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
778 return BOOTROM_ERROR_LOCK_REQUIRED;
779 int rc = func(workarea_base, workarea_size, family_id, partition_out);
780 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
781 return rc;
782 }
783
784 /*!
785 * \brief Translate runtime to storage address
786 * \ingroup pico_bootrom
787 *
788 * Applies the address translation currently configured by QMI address translation registers.
789 *
790 * Translating an address outside of the XIP runtime address window, or beyond the bounds of an ATRANSx_SIZE field, returns BOOTROM_ERROR_INVALID_ADDRESS,
791 * which is not a valid flash storage address. Otherwise, return the storage address which QMI would access when presented with the runtime address addr.
792 * This is effectively a virtual-to-physical address translation for QMI.
793 *
794 * \param flash_runtime_addr the address to translate
795 */
rom_flash_runtime_to_storage_addr(uintptr_t flash_runtime_addr)796 static inline intptr_t rom_flash_runtime_to_storage_addr(uintptr_t flash_runtime_addr) {
797 rom_flash_runtime_to_storage_addr_fn func = (rom_flash_runtime_to_storage_addr_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_RUNTIME_TO_STORAGE_ADDR);
798 return func(flash_runtime_addr);
799 }
800
801 // todo SECURE only
802 /*!
803 * \brief Chain into a launchable image
804 * \ingroup pico_bootrom
805 *
806 * Searches a memory region for a launchable image, and executes it if possible.
807 *
808 * The region_base and region_size specify a word-aligned, word-multiple-sized area of RAM, XIP RAM or flash to search.
809 * The first 4 kiB of the region must contain the start of a Block Loop with an IMAGE_DEF. If the new image is launched,
810 * the call does not return otherwise an error is returned.
811 *
812 * The region_base is signed, as a negative value can be passed, which indicates that the (negated back to positive value)
813 * is both the region_base and the base of the "flash update" region.
814 *
815 * This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
816 * As a result it requires a user provided memory buffer as a work area. The work area should be word aligned, and of sufficient size
817 * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
818 *
819 * NOTE: This method is primarily expected to be used when implementing bootloaders.
820 *
821 * NOTE: When chaining into an image, the OTP_DATA_BOOT_FLAGS0_ROLLBACK_REQUIRED flag will not be set, to prevent invalidating a bootloader
822 * without a rollback version by booting a binary which has one.
823 *
824 * \param workarea_base base address of work area
825 * \param workarea_size size of work area
826 * \param region_base base address of image
827 * \param region_size size of window containing image
828 */
rom_chain_image(uint8_t * workarea_base,uint32_t workarea_size,uint32_t region_base,uint32_t region_size)829 static inline int rom_chain_image(uint8_t *workarea_base, uint32_t workarea_size, uint32_t region_base, uint32_t region_size) {
830 rom_chain_image_fn func = (rom_chain_image_fn) rom_func_lookup_inline(ROM_FUNC_CHAIN_IMAGE);
831 bootrom_release_lock(BOOTROM_LOCK_ENABLE);
832 uint32_t interrupt_flags = save_and_disable_interrupts();
833 int rc = func(workarea_base, workarea_size, region_base, region_size);
834 restore_interrupts_from_disabled(interrupt_flags);
835 bootrom_acquire_lock_blocking(BOOTROM_LOCK_ENABLE);
836 return rc;
837 }
838
839 typedef struct {
840 uint8_t *buffer;
841 uint32_t buffer_size;
842 int *res;
843 } rom_helper_explicit_buy_params_t;
844
rom_helper_explicit_buy(void * param)845 static inline void rom_helper_explicit_buy(void *param) {
846 const rom_helper_explicit_buy_params_t *op = (const rom_helper_explicit_buy_params_t *)param;
847 rom_explicit_buy_fn func = (rom_explicit_buy_fn) rom_func_lookup_inline(ROM_FUNC_EXPLICIT_BUY);
848 *(op->res) = func(op->buffer, op->buffer_size);
849 }
850
851 // todo SECURE only
852 /*!
853 * \brief Buy an image
854 * \ingroup pico_bootrom
855 *
856 * Perform an "explicit" buy of an executable launched via an IMAGE_DEF which was "explicit buy" flagged. A "flash update"
857 * boot of such an image is a way to have the image execute once, but only become the "current" image if it calls
858 * back into the bootrom via this call.
859 *
860 * This call may perform the following:
861 *
862 * - Erase and rewrite the part of flash containing the "explicit buy" flag in order to clear said flag.
863 * - Erase the first sector of the other partition in an A/B partition scenario, if this new IMAGE_DEF is a version downgrade
864 * (so this image will boot again when not doing a "flash update" boot)
865 * - Update the rollback version in OTP if the chip is secure, and a rollback version is present in the image.
866 *
867 * NOTE: The device may reboot while updating the rollback version, if multiple rollback rows need to be written - this occurs
868 * when the version crosses a multiple of 24 (for example upgrading from version 23 to 25 requires a reboot, but 23 to 24 or 24 to 25 doesn't).
869 * The application should therefore be prepared to reboot when calling this function, if rollback versions are in use.
870 *
871 * Note that the first of the above requires 4 kiB of scratch space, so you should pass a word aligned buffer of at least 4 kiB to this method,
872 * or it will return BOOTROM_ERROR_INSUFFICIENT_RESOURCES if the "explicit buy" flag needs to be cleared.
873 *
874 * \param buffer base address of scratch space
875 * \param buffer_size size of scratch space
876 */
rom_explicit_buy(uint8_t * buffer,uint32_t buffer_size)877 static inline int rom_explicit_buy(uint8_t *buffer, uint32_t buffer_size) {
878 int rc = 0;
879 rom_helper_explicit_buy_params_t params = {
880 .buffer = buffer,
881 .buffer_size = buffer_size,
882 .res = &rc
883 };
884 int flash_rc = flash_safe_execute(rom_helper_explicit_buy, ¶ms, UINT32_MAX);
885 if (flash_rc != PICO_OK) {
886 return flash_rc;
887 } else {
888 return rc;
889 }
890 }
891
892 #ifndef __riscv
893 /*!
894 * \brief Set NS API Permission
895 * \ingroup pico_bootrom
896 *
897 * Allow or disallow the specific NS API (note all NS APIs default to disabled).
898 *
899 * ns_api_num configures ARM-NS access to the given API. When an NS API is disabled,
900 * calling it will return BOOTROM_ERROR_NOT_PERMITTED.
901 *
902 * NOTE: All permissions default to disallowed after a reset.
903 *
904 * \param ns_api_num ns api number
905 * \param allowed permission
906 */
rom_set_ns_api_permission(uint ns_api_num,bool allowed)907 static inline int rom_set_ns_api_permission(uint ns_api_num, bool allowed) {
908 rom_set_ns_api_permission_fn func = (rom_set_ns_api_permission_fn) rom_func_lookup_inline(ROM_FUNC_SET_NS_API_PERMISSION);
909 return func(ns_api_num, allowed);
910 }
911 #endif
912
913 // todo SECURE only
914 /*!
915 * \brief Validate NS Buffer
916 * \ingroup pico_bootrom
917 *
918 * Utility method that can be used by secure ARM code to validate a buffer passed to it from Non-secure code.
919 *
920 * Both the write parameter and the (out) result parameter ok are RCP booleans, so 0xa500a500 for true, and 0x00c300c3
921 * for false. This enables hardening of this function, and indeed the write parameter must be one of these values or the RCP
922 * will hang the system.
923 *
924 * For success, the entire buffer must fit in range XIP_BASE -> SRAM_END, and must be accessible by the Non-secure
925 * caller according to SAU + NS MPU (privileged or not based on current processor IPSR and NS CONTROL flag). Buffers
926 * in USB RAM are also allowed if access is granted to NS via ACCESSCTRL.
927 *
928 * \param addr buffer address
929 * \param size buffer size
930 * \param write rcp boolean, true if writeable
931 * \param ok rcp boolean result
932 */
rom_validate_ns_buffer(const void * addr,uint32_t size,uint32_t write,uint32_t * ok)933 static inline void* rom_validate_ns_buffer(const void *addr, uint32_t size, uint32_t write, uint32_t *ok) {
934 rom_validate_ns_buffer_fn func = (rom_validate_ns_buffer_fn) rom_func_lookup_inline(ROM_FUNC_VALIDATE_NS_BUFFER);
935 return func(addr, size, write, ok);
936 }
937
938 /*!
939 * \brief Set ROM callback function
940 * \ingroup pico_bootrom
941 *
942 * The only currently supported callback_number is 0 which sets the callback used for the secure_call API.
943 *
944 * A callback pointer of 0 deletes the callback function, a positive callback pointer (all valid function pointers are on RP2350)
945 * sets the callback function, but a negative callback pointer can be passed to get the old value without setting a new value.
946 *
947 * If successful, returns >=0 (the existing value of the function pointer on entry to the function).
948 *
949 * \param callback_num the callback number to set - only 0 is supported on RP2350
950 * \param funcptr pointer to the callback function
951 */
rom_set_rom_callback(uint callback_num,bootrom_api_callback_generic_t funcptr)952 static inline intptr_t rom_set_rom_callback(uint callback_num, bootrom_api_callback_generic_t funcptr) {
953 rom_set_rom_callback_fn func = (rom_set_rom_callback_fn) rom_func_lookup_inline(ROM_FUNC_SET_ROM_CALLBACK);
954 return func(callback_num, funcptr);
955 }
956
957 #define BOOT_TYPE_NORMAL 0
958 #define BOOT_TYPE_BOOTSEL 2
959 #define BOOT_TYPE_RAM_IMAGE 3
960 #define BOOT_TYPE_FLASH_UPDATE 4
961
962 // values 8-15 are secure only
963 #define BOOT_TYPE_PC_SP 0xd
964
965 // ORed in if a bootloader chained into the image
966 #define BOOT_TYPE_CHAINED_FLAG 0x80
967
968 /*!
969 * \brief Get system information
970 * \ingroup pico_bootrom
971 *
972 * Fills a buffer with various system information. Note that this API is also used to return information over the picoboot interface.
973 *
974 * On success, the buffer is filled, and the number of words filled in the buffer is returned.
975 *
976 * The information returned is chosen by the flags parameter; the first word in the returned buffer,
977 * is the (sub)set of those flags that the API supports. You should always check this value before interpreting
978 * the buffer.
979 *
980 * "Boot Diagnostic" information is intended to help identify the cause of a failed boot, or booting into an unexpected binary.
981 * This information can be retrieved via picoboot after a watchdog reboot, however it will not survive
982 * a reset via the RUN pin or POWMAN reset.
983 *
984 * There is only one word of diagnostic information. What it records is based on the pp selection above, which
985 * is itself set as a parameter when rebooting programmatically into a normal boot.
986 *
987 * To get diagnostic info, pp must refer to a slot or an "A" partition; image diagnostics are automatically selected on boot
988 * from OTP or RAM image, or when chain_image() is called.)
989 *
990 * The diagnostic word thus contains data for either slot 0 and slot 1, or the "A" partition (and its "B" partition if it has one). The low half word
991 * of the diagnostic word contains information from slot 0 or partition A; the high half word contains information from slot 1 or partition B.
992 *
993 * To get a full picture of a failed boot involving slots and multiple partitions, the device can be rebooted
994 * multiple times to gather the information.
995 *
996 * \param out_buffer buffer to write data to
997 * \param out_buffer_word_size size of out_buffer, in words
998 * \param flags flags
999 */
rom_get_sys_info(uint32_t * out_buffer,uint32_t out_buffer_word_size,uint32_t flags)1000 static inline int rom_get_sys_info(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t flags) {
1001 rom_get_sys_info_fn func = (rom_get_sys_info_fn)rom_func_lookup_inline(ROM_FUNC_GET_SYS_INFO);
1002 return func(out_buffer, out_buffer_word_size, flags);
1003 }
1004
1005 typedef struct {
1006 union {
1007 struct __packed {
1008 int8_t diagnostic_partition_index; // used BOOT_PARTITION constants
1009 uint8_t boot_type;
1010 int8_t partition;
1011 uint8_t tbyb_and_update_info;
1012 };
1013 uint32_t boot_word;
1014 };
1015 uint32_t boot_diagnostic;
1016 uint32_t reboot_params[2];
1017 } boot_info_t;
1018
rom_get_boot_info(boot_info_t * info)1019 static inline int rom_get_boot_info(boot_info_t *info) {
1020 uint32_t result[5];
1021 int words_returned = rom_get_sys_info(result, 5, SYS_INFO_BOOT_INFO);
1022 if (words_returned == (sizeof(result)/sizeof(result[0])) && result[0] == SYS_INFO_BOOT_INFO) {
1023 memcpy(info, &result[1], sizeof(boot_info_t));
1024 return true;
1025 } else {
1026 return false;
1027 }
1028 }
1029
rom_get_last_boot_type_with_chained_flag(void)1030 static inline int rom_get_last_boot_type_with_chained_flag(void) {
1031 uint32_t result[5];
1032 int words_returned = rom_get_sys_info(result, 5, SYS_INFO_BOOT_INFO);
1033 if (words_returned == count_of(result) && result[0] == SYS_INFO_BOOT_INFO) {
1034 // todo use struct
1035 return (int)((result[1] & 0xff00u) >> 8);
1036 } else {
1037 return PICO_ERROR_INVALID_DATA;
1038 }
1039 }
1040
1041 // BOOT_TYPE_NORMAL 0x0
1042 // BOOT_TYPE_BOOTSEL 0x2
1043 // BOOT_TYPE_RAM_IMAGE 0x3
1044 // BOOT_TYPE_FLASH_UPDATE 0x4
1045 // BOOT_TYPE_PC_SP 0xd
rom_get_last_boot_type(void)1046 static inline int rom_get_last_boot_type(void) {
1047 int rc = rom_get_last_boot_type_with_chained_flag();
1048 if (rc >= 0) rc &= ~BOOT_TYPE_CHAINED_FLAG;
1049 return rc;
1050 }
1051
1052 /*! \brief Add a runtime partition to the partition table to specify flash permissions
1053 * \ingroup pico_bootrom
1054 *
1055 * Note that a partition is added to the runtime view of the partition table maintained by the bootrom if there is space to do so
1056 *
1057 * Note that these permissions cannot override the permissions for any pre-existing partitions, as permission matches are made on a first partition found basis.
1058 *
1059 * @param start_offset the start_offset into flash in bytes (must be a multiple of 4K)
1060 * @param size the size in byte (must be a multiple of 4K)
1061 * @param permissions the bitwise OR of permissions from PICOBIN_PARTITION_PERMISSION_ constants, e.g. \ref PICOBIN_PARTITION_PERMISSION_S_R_BITS from boot/picobin.h
1062 * @return >= 0 the partition number added if
1063 * PICO_ERROR_BAD_ALIGNMENT if the start_offset or size aren't multiples of 4K.
1064 * PICO_ERROR_INVALID_ARG if the start_offset or size are out of range, or invalid permission bits are set.
1065 */
1066 int rom_add_flash_runtime_partition(uint32_t start_offset, uint32_t size, uint32_t permissions);
1067
1068 #endif
1069
1070 #ifdef __cplusplus
1071 }
1072 #endif
1073
1074 #endif // !__ASSEMBLER__
1075 #endif
1076