@web-font-path: "roboto-debian.css";
Loading...
Searching...
No Matches
bootrom.h
Go to the documentation of this file.
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
20#ifndef __ASSEMBLER__
21#include <string.h>
22#include "pico/bootrom/lock.h"
23// ROM FUNCTION SIGNATURES
24
25#if PICO_RP2040
26typedef uint32_t (*rom_popcount32_fn)(uint32_t);
27typedef uint32_t (*rom_reverse32_fn)(uint32_t);
28typedef uint32_t (*rom_clz32_fn)(uint32_t);
29typedef uint32_t (*rom_ctz32_fn)(uint32_t);
30typedef uint8_t *(*rom_memset_fn)(uint8_t *, uint8_t, uint32_t);
31typedef uint32_t *(*rom_memset4_fn)(uint32_t *, uint8_t, uint32_t);
32typedef uint32_t *(*rom_memcpy_fn)(uint8_t *, const uint8_t *, uint32_t);
33typedef uint32_t *(*rom_memcpy44_fn)(uint32_t *, const uint32_t *, uint32_t);
34#endif
35typedef void __attribute__((noreturn)) (*rom_reset_usb_boot_fn)(uint32_t, uint32_t);
36typedef int (*rom_reboot_fn)(uint32_t flags, uint32_t delay_ms, uint32_t p0, uint32_t p1);
37typedef rom_reset_usb_boot_fn reset_usb_boot_fn; // kept for backwards compatibility
38typedef void (*rom_connect_internal_flash_fn)(void);
39typedef void (*rom_flash_exit_xip_fn)(void);
40typedef void (*rom_flash_range_erase_fn)(uint32_t, size_t, uint32_t, uint8_t);
41typedef void (*rom_flash_range_program_fn)(uint32_t, const uint8_t*, size_t);
42typedef void (*rom_flash_flush_cache_fn)(void);
43typedef void (*rom_flash_enter_cmd_xip_fn)(void);
44#if !PICO_RP2040
45typedef void (*rom_bootrom_state_reset_fn)(uint32_t flags);
46typedef void (*rom_flash_reset_address_trans_fn)(void);
47typedef void (*rom_flash_select_xip_read_mode_fn)(bootrom_xip_mode_t mode, uint8_t clkdiv);
48typedef int (*rom_get_sys_info_fn)(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t flags);
49typedef int (*rom_get_partition_table_info_fn)(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t partition_and_flags);
50typedef int (*rom_explicit_buy_fn)(uint8_t *buffer, uint32_t buffer_size);
51typedef void* (*rom_validate_ns_buffer_fn)(const void *addr, uint32_t size, uint32_t write, uint32_t *ok);
56typedef intptr_t (*rom_set_rom_callback_fn)(uint callback_num, bootrom_api_callback_generic_t funcptr);
57typedef int (*rom_chain_image_fn)(uint8_t *workarea_base, uint32_t workarea_size, uint32_t window_base, uint32_t window_size);
58typedef int (*rom_load_partition_table_fn)(uint8_t *workarea_base, uint32_t workarea_size, bool force_reload);
59typedef 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);
60typedef int (*rom_get_b_partition_fn)(uint pi_a);
61typedef int (*rom_get_uf2_target_partition_fn)(uint8_t *workarea_base, uint32_t workarea_size, uint32_t family_id, resident_partition_t *partition_out);
62typedef int (*rom_func_otp_access_fn)(uint8_t *buf, uint32_t buf_len, otp_cmd_t cmd);
63// Apply the address translation currently specified in QMI_ATRANSx ("rolling window" hardware
64// translation). Need to take care using this on the boot path, as the QMI may not yet have been
65// set up, but this should be suitable for translating system bus addresses into flash storage
66// addresses in user callbacks. Returns all-ones for an invalid address, which is also an invalid
67// flash storage address, so invalidity is propagated.
68typedef intptr_t (*rom_flash_runtime_to_storage_addr_fn)(uintptr_t flash_runtime_addr);
69
70// Perform the specified erase/program/read operation, translating addresses according to
71// QMI_ATRANSx if necessary, and checking flash permissions based on the resident partition table
72// and the specified effective security level. `addr` may be either a flash runtime address or a
73// flash storage address, depending on the ASPACE given in `flags`.
74//
75// NOTE: This function does not validate the buffer for NS access. This must be validated before
76// calling if the caller is reachable from a Secure Gateway.
77typedef int (*rom_flash_op_fn)(cflash_flags_t flags, uintptr_t addr, uint32_t size_bytes, uint8_t *buf);
78
79#ifndef __riscv
80typedef int (*rom_set_ns_api_permission_fn)(uint ns_api_num, bool allowed);
93typedef int (*rom_func_secure_call)(uintptr_t a0, ...);
94#endif
95
96#ifdef __riscv
97typedef struct {
98 uint32_t *base;
99 uint32_t size;
100} bootrom_stack_t;
101// passed in, and out.
102typedef int (*rom_set_bootrom_stack_fn)(bootrom_stack_t *stack);
103#endif
104#endif
105
106#ifdef __cplusplus
107extern "C" {
108#endif
109
119static inline uint32_t rom_table_code(uint8_t c1, uint8_t c2) {
120 return ROM_TABLE_CODE((uint32_t) c1, (uint32_t) c2);
121}
122
129void *rom_func_lookup(uint32_t code);
130
137void *rom_data_lookup(uint32_t code);
138
150bool rom_funcs_lookup(uint32_t *table, unsigned int count);
151
152// Bootrom function: rom_table_lookup
153// Returns the 32 bit pointer into the ROM if found or NULL otherwise.
154#if PICO_RP2040
155typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);
156#else
157typedef void *(*rom_table_lookup_fn)(uint32_t code, uint32_t mask);
158#endif
159
160#if PICO_C_COMPILER_IS_GNU && (__GNUC__ >= 12)
161// Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
162__force_inline static void *rom_hword_as_ptr(uint16_t rom_address) {
163#pragma GCC diagnostic push
164#pragma GCC diagnostic ignored "-Warray-bounds"
165 return (void *)(uintptr_t)*(uint16_t *)(uintptr_t)rom_address;
166#pragma GCC diagnostic pop
167}
168#else
169// Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
170#define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)(uintptr_t)(rom_address))
171#endif
172
173#ifdef __riscv
174static __force_inline bool rom_size_is_64k(void) {
175#ifdef RASPBERRYPI_AMETHYST_FPGA
176 // Detect ROM size by testing for bus fault at +32k
177 uint result;
178 pico_default_asm_volatile (
179 "li %0, 0\n"
180 // Save and disable IRQs before touching trap vector
181 "csrr t2, mstatus\n"
182 "csrci mstatus, 0x8\n"
183 // Set up trap vector to skip the instruction which sets the %0 flag
184 "la t0, 1f\n"
185 "csrrw t0, mtvec, t0\n"
186 // This load will fault if the bootrom is no larger than 32k:
187 "li t1, 32 * 1024\n"
188 "lw t1, (t1)\n"
189 // No fault, so set return to true
190 "li %0, 1\n"
191 ".p2align 2\n"
192 // Always end up back here, restore the trap table
193 "1:\n"
194 "csrw mtvec, t0\n"
195 // Now safe to restore interrupts
196 "csrw mstatus, t2\n"
197 : "=r" (result)
198 :
199 : "t0", "t1", "t2"
200 );
201 return result;
202#else
203 return false;
204#endif
205}
206#endif
207
214#pragma GCC diagnostic push
215// diagnostic: GCC thinks near-zero value is a null pointer member access, but it's not
216#pragma GCC diagnostic ignored "-Warray-bounds"
217static __force_inline void *rom_func_lookup_inline(uint32_t code) {
218#if PICO_RP2040
219 rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET);
220 uint16_t *func_table = (uint16_t *) rom_hword_as_ptr(BOOTROM_FUNC_TABLE_OFFSET);
221 return rom_table_lookup(func_table, code);
222#else
223#ifdef __riscv
224 uint32_t rom_offset_adjust = rom_size_is_64k() ? 32 * 1024 : 0;
225 // on RISC-V the code (a jmp) is actually embedded in the table
226 rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_ENTRY_OFFSET + rom_offset_adjust);
227 return rom_table_lookup(code, RT_FLAG_FUNC_RISCV);
228#else
229 // on ARM the function pointer is stored in the table, so we dereference it
230 // via lookup() rather than lookup_entry()
231 rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_OFFSET);
232 if (pico_processor_state_is_nonsecure()) {
233 return rom_table_lookup(code, RT_FLAG_FUNC_ARM_NONSEC);
234 } else {
235 return rom_table_lookup(code, RT_FLAG_FUNC_ARM_SEC);
236 }
237#endif
238#endif
239}
240#pragma GCC diagnostic pop
241
259void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask);
260static inline void __attribute__((noreturn)) reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask) {
261 rom_reset_usb_boot(usb_activity_gpio_pin_mask, disable_interface_mask);
262}
263
276static inline void rom_connect_internal_flash() {
277 rom_connect_internal_flash_fn func = (rom_connect_internal_flash_fn) rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH);
278 func();
279}
280
307static inline void rom_flash_exit_xip() {
308 rom_flash_exit_xip_fn func = (rom_flash_exit_xip_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP);
309 func();
310}
311
343static inline void rom_flash_range_erase(uint32_t addr, size_t count, uint32_t block_size, uint8_t block_cmd) {
344 rom_flash_range_erase_fn func = (rom_flash_range_erase_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_ERASE);
345 func(addr, count, block_size, block_cmd);
346}
347
368static inline void rom_flash_range_program(uint32_t addr, const uint8_t *data, size_t count) {
369 rom_flash_range_program_fn func = (rom_flash_range_program_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_PROGRAM);
370 func(addr, data, count);
371}
372
390static inline void rom_flash_flush_cache() {
391 rom_flash_flush_cache_fn func = (rom_flash_flush_cache_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);
392 func();
393}
394
406static inline void rom_flash_enter_cmd_xip() {
407 rom_flash_enter_cmd_xip_fn func = (rom_flash_enter_cmd_xip_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_ENTER_CMD_XIP);
408 func();
409}
410
411#if !PICO_RP2040
412#ifdef __riscv
429static inline int rom_set_bootrom_stack(bootrom_stack_t *stack) {
430 rom_set_bootrom_stack_fn func = (rom_set_bootrom_stack_fn) rom_func_lookup_inline(ROM_FUNC_SET_BOOTROM_STACK);
431 return func(stack);
432}
433#endif
434
481static inline int rom_reboot(uint32_t flags, uint32_t delay_ms, uint32_t p0, uint32_t p1) {
482 rom_reboot_fn func = (rom_reboot_fn) rom_func_lookup_inline(ROM_FUNC_REBOOT);
483 return func(flags, delay_ms, p0, p1);
484}
485
486bool rom_get_boot_random(uint32_t out[4]);
487
512static inline void rom_bootrom_state_reset(uint32_t flags) {
513 rom_bootrom_state_reset_fn func = (rom_bootrom_state_reset_fn) rom_func_lookup_inline(ROM_FUNC_BOOTROM_STATE_RESET);
514 return func(flags);
515}
516
525static inline void rom_flash_reset_address_trans(void) {
526 rom_flash_reset_address_trans_fn func = (rom_flash_reset_address_trans_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_RESET_ADDRESS_TRANS);
527 func();
528}
529
540static inline void rom_flash_select_xip_read_mode(bootrom_xip_mode_t mode, uint8_t clkdiv) {
541 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);
542 func(mode, clkdiv);
543}
544
584static inline int rom_flash_op(cflash_flags_t flags, uintptr_t addr, uint32_t size_bytes, uint8_t *buf) {
585 rom_flash_op_fn func = (rom_flash_op_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_OP);
586 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_FLASH_OP))
587 return BOOTROM_ERROR_LOCK_REQUIRED;
588 int rc = func(flags, addr, size_bytes, buf);
589 bootrom_release_lock(BOOTROM_LOCK_FLASH_OP);
590 return rc;
591}
592
617static inline int rom_func_otp_access(uint8_t *buf, uint32_t buf_len, otp_cmd_t cmd) {
618 rom_func_otp_access_fn func = (rom_func_otp_access_fn) rom_func_lookup_inline(ROM_FUNC_OTP_ACCESS);
619 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_OTP))
620 return BOOTROM_ERROR_LOCK_REQUIRED;
621 int rc = func(buf, buf_len, cmd);
622 bootrom_release_lock(BOOTROM_LOCK_OTP);
623 return rc;
624}
625
654static inline int rom_get_partition_table_info(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t partition_and_flags) {
655 rom_get_partition_table_info_fn func = (rom_get_partition_table_info_fn) rom_func_lookup_inline(ROM_FUNC_GET_PARTITION_TABLE_INFO);
656 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
657 return BOOTROM_ERROR_LOCK_REQUIRED;
658 int rc = func(out_buffer, out_buffer_word_size, partition_and_flags);
659 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
660 return rc;
661}
662
663// todo SECURE only
679static inline int rom_load_partition_table(uint8_t *workarea_base, uint32_t workarea_size, bool force_reload) {
680 rom_load_partition_table_fn func = (rom_load_partition_table_fn) rom_func_lookup_inline(ROM_FUNC_LOAD_PARTITION_TABLE);
681 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
682 return BOOTROM_ERROR_LOCK_REQUIRED;
683 int rc = func(workarea_base, workarea_size, force_reload);
684 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
685 return rc;
686}
687
688// todo SECURE only
711static 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) {
712 rom_pick_ab_partition_fn func = (rom_pick_ab_partition_fn) rom_func_lookup_inline(ROM_FUNC_PICK_AB_PARTITION);
713 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
714 return BOOTROM_ERROR_LOCK_REQUIRED;
715 int rc = func(workarea_base, workarea_size, partition_a_num, flash_update_boot_window_base);
716 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
717 return rc;
718}
719
729static inline int rom_get_b_partition(uint pi_a) {
730 rom_get_b_partition_fn func = (rom_get_b_partition_fn) rom_func_lookup_inline(ROM_FUNC_GET_B_PARTITION);
731 return func(pi_a);
732}
733
734// todo SECURE only
755static inline int rom_get_uf2_target_partition(uint8_t *workarea_base, uint32_t workarea_size, uint32_t family_id, resident_partition_t *partition_out) {
756 rom_get_uf2_target_partition_fn func = (rom_get_uf2_target_partition_fn) rom_func_lookup_inline(ROM_FUNC_GET_UF2_TARGET_PARTITION);
757 if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
758 return BOOTROM_ERROR_LOCK_REQUIRED;
759 int rc = func(workarea_base, workarea_size, family_id, partition_out);
760 bootrom_release_lock(BOOTROM_LOCK_SHA_256);
761 return rc;
762}
763
776static inline intptr_t rom_flash_runtime_to_storage_addr(uintptr_t flash_runtime_addr) {
777 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);
778 return func(flash_runtime_addr);
779}
780
781// todo SECURE only
809static inline int rom_chain_image(uint8_t *workarea_base, uint32_t workarea_size, uint32_t region_base, uint32_t region_size) {
810 rom_chain_image_fn func = (rom_chain_image_fn) rom_func_lookup_inline(ROM_FUNC_CHAIN_IMAGE);
811 bootrom_release_lock(BOOTROM_LOCK_ENABLE);
812 int rc = func(workarea_base, workarea_size, region_base, region_size);
813 bootrom_acquire_lock_blocking(BOOTROM_LOCK_ENABLE);
814 return rc;
815}
816
817// todo SECURE only
843static inline int rom_explicit_buy(uint8_t *buffer, uint32_t buffer_size) {
844 rom_explicit_buy_fn func = (rom_explicit_buy_fn) rom_func_lookup_inline(ROM_FUNC_EXPLICIT_BUY);
845 return func(buffer, buffer_size);
846}
847
848#ifndef __riscv
863static inline int rom_set_ns_api_permission(uint ns_api_num, bool allowed) {
864 rom_set_ns_api_permission_fn func = (rom_set_ns_api_permission_fn) rom_func_lookup_inline(ROM_FUNC_SET_NS_API_PERMISSION);
865 return func(ns_api_num, allowed);
866}
867#endif
868
869// todo SECURE only
889static inline void* rom_validate_ns_buffer(const void *addr, uint32_t size, uint32_t write, uint32_t *ok) {
890 rom_validate_ns_buffer_fn func = (rom_validate_ns_buffer_fn) rom_func_lookup_inline(ROM_FUNC_VALIDATE_NS_BUFFER);
891 return func(addr, size, write, ok);
892}
893
908static inline intptr_t rom_set_rom_callback(uint callback_num, bootrom_api_callback_generic_t funcptr) {
909 rom_set_rom_callback_fn func = (rom_set_rom_callback_fn) rom_func_lookup_inline(ROM_FUNC_SET_ROM_CALLBACK);
910 return func(callback_num, funcptr);
911}
912
913#define BOOT_TYPE_NORMAL 0
914#define BOOT_TYPE_BOOTSEL 2
915#define BOOT_TYPE_RAM_IMAGE 3
916#define BOOT_TYPE_FLASH_UPDATE 4
917
918// values 8-15 are secure only
919#define BOOT_TYPE_PC_SP 0xd
920
921// ORed in if a bootloader chained into the image
922#define BOOT_TYPE_CHAINED_FLAG 0x80
923
956static inline int rom_get_sys_info(uint32_t *out_buffer, uint32_t out_buffer_word_size, uint32_t flags) {
957 rom_get_sys_info_fn func = (rom_get_sys_info_fn)rom_func_lookup_inline(ROM_FUNC_GET_SYS_INFO);
958 return func(out_buffer, out_buffer_word_size, flags);
959}
960
961typedef struct {
962 union {
963 struct __packed {
964 int8_t diagnostic_partition_index; // used BOOT_PARTITION constants
965 uint8_t boot_type;
966 int8_t partition;
967 uint8_t tbyb_and_update_info;
968 };
969 uint32_t boot_word;
970 };
971 uint32_t boot_diagnostic;
972 uint32_t reboot_params[2];
973} boot_info_t;
974
975static inline int rom_get_boot_info(boot_info_t *info) {
976 uint32_t result[5];
977 int words_returned = rom_get_sys_info(result, 5, SYS_INFO_BOOT_INFO);
978 if (words_returned == (sizeof(result)/sizeof(result[0])) && result[0] == SYS_INFO_BOOT_INFO) {
979 memcpy(info, &result[1], sizeof(boot_info_t));
980 return true;
981 } else {
982 return false;
983 }
984}
985
986static inline int rom_get_last_boot_type_with_chained_flag(void) {
987 uint32_t result[5];
988 int words_returned = rom_get_sys_info(result, 5, SYS_INFO_BOOT_INFO);
989 if (words_returned == count_of(result) && result[0] == SYS_INFO_BOOT_INFO) {
990 // todo use struct
991 return (int)((result[1] & 0xff00u) >> 8);
992 } else {
994 }
995}
996
997// BOOT_TYPE_NORMAL 0x0
998// BOOT_TYPE_BOOTSEL 0x2
999// BOOT_TYPE_RAM_IMAGE 0x3
1000// BOOT_TYPE_FLASH_UPDATE 0x4
1001// BOOT_TYPE_PC_SP 0xd
1002static inline int rom_get_last_boot_type(void) {
1003 int rc = rom_get_last_boot_type_with_chained_flag();
1004 if (rc >= 0) rc &= ~BOOT_TYPE_CHAINED_FLAG;
1005 return rc;
1006}
1007
1022int rom_add_flash_runtime_partition(uint32_t start_offset, uint32_t size, uint32_t permissions);
1023
1024#endif
1025
1026#ifdef __cplusplus
1027}
1028#endif
1029
1030#endif // !__ASSEMBLER__
1031#endif
@ PICO_ERROR_INVALID_DATA
A data structure failed to validate.
Definition error.h:40
void rom_reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask)
Reboot the device into BOOTSEL mode.
Definition bootrom.c:43
static uint32_t rom_table_code(uint8_t c1, uint8_t c2)
Return a bootrom lookup code based on two ASCII characters.
Definition bootrom.h:119
bool rom_funcs_lookup(uint32_t *table, unsigned int count)
Helper function to lookup the addresses of multiple bootrom functions.
Definition bootrom.c:33
static void rom_flash_exit_xip()
Return the QSPI device from its XIP state to a serial command state.
Definition bootrom.h:307
#define ROM_TABLE_CODE(c1, c2)
Return a bootrom lookup code based on two ASCII characters.
Definition bootrom_constants.h:157
static void rom_flash_range_program(uint32_t addr, const uint8_t *data, size_t count)
Program bytes in flash.
Definition bootrom.h:368
static __force_inline void * rom_func_lookup_inline(uint32_t code)
Lookup a bootrom function by code. This method is forcibly inlined into the caller for FLASH/RAM sens...
Definition bootrom.h:217
static void rom_connect_internal_flash()
Connect the SSI/QMI to the QSPI pads.
Definition bootrom.h:276
void * rom_func_lookup(uint32_t code)
Lookup a bootrom function by its code.
Definition bootrom.c:13
static void rom_flash_flush_cache()
Flush the XIP cache.
Definition bootrom.h:390
static void rom_flash_range_erase(uint32_t addr, size_t count, uint32_t block_size, uint8_t block_cmd)
Erase bytes in flash.
Definition bootrom.h:343
void * rom_data_lookup(uint32_t code)
Lookup a bootrom data address by its code.
Definition bootrom.c:20
static void rom_flash_enter_cmd_xip()
Configure the SSI/QMI with a standard command.
Definition bootrom.h:406
#define __force_inline
Attribute to force inlining of a function regardless of optimization level.
Definition compiler.h:125
#define count_of(a)
Macro to determine the number of elements in an array.
Definition compiler.h:132
Definition bootrom_constants.h:305
Definition bootrom_constants.h:273
Definition bootrom_constants.h:262