1 /* 2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef _BOOT_PICOBOOT_H 8 #define _BOOT_PICOBOOT_H 9 10 #include <stdint.h> 11 #include <stdbool.h> 12 #include <assert.h> 13 14 #ifndef NO_PICO_PLATFORM 15 #include "pico/platform.h" 16 #endif 17 18 /** \file picoboot.h 19 * \defgroup boot_picoboot_headers boot_picoboot_headers 20 * 21 * \brief Header file for the PICOBOOT USB interface exposed by an RP2xxx chip in BOOTSEL mode 22 */ 23 24 #include "picoboot_constants.h" 25 26 #define PICOBOOT_MAGIC 0x431fd10bu 27 28 // -------------------------------------------- 29 // CONTROL REQUESTS FOR THE PICOBOOT INTERFACE 30 // -------------------------------------------- 31 32 // size 0 OUT - un-stall EPs and reset 33 #define PICOBOOT_IF_RESET 0x41 34 35 // size 16 IN - return the status of the last command 36 #define PICOBOOT_IF_CMD_STATUS 0x42 37 38 // -------------------------------------------------- 39 // COMMAND REQUESTS SENT TO THE PICOBOOT OUT ENDPOINT 40 // -------------------------------------------------- 41 // 42 // picoboot_cmd structure of size 32 is sent to OUT endpoint 43 // transfer_length bytes are transferred via IN/OUT 44 // device responds on success with 0 length ACK packet set via OUT/IN 45 // device may stall the transferring endpoint in case of error 46 47 enum picoboot_cmd_id { 48 PC_EXCLUSIVE_ACCESS = 0x1, 49 PC_REBOOT = 0x2, 50 PC_FLASH_ERASE = 0x3, 51 PC_READ = 0x84, // either RAM or FLASH 52 PC_WRITE = 0x5, // either RAM or FLASH (does no erase) 53 PC_EXIT_XIP = 0x6, 54 PC_ENTER_CMD_XIP = 0x7, 55 PC_EXEC = 0x8, 56 PC_VECTORIZE_FLASH = 0x9, 57 // RP2350 only below here 58 PC_REBOOT2 = 0xa, 59 PC_GET_INFO = 0x8b, 60 PC_OTP_READ = 0x8c, 61 PC_OTP_WRITE = 0xd, 62 //PC_EXEC2 = 0xe, // currently unused 63 }; 64 65 enum picoboot_status { 66 PICOBOOT_OK = 0, 67 PICOBOOT_UNKNOWN_CMD = 1, 68 PICOBOOT_INVALID_CMD_LENGTH = 2, 69 PICOBOOT_INVALID_TRANSFER_LENGTH = 3, 70 PICOBOOT_INVALID_ADDRESS = 4, 71 PICOBOOT_BAD_ALIGNMENT = 5, 72 PICOBOOT_INTERLEAVED_WRITE = 6, 73 PICOBOOT_REBOOTING = 7, 74 PICOBOOT_UNKNOWN_ERROR = 8, 75 PICOBOOT_INVALID_STATE = 9, 76 PICOBOOT_NOT_PERMITTED = 10, 77 PICOBOOT_INVALID_ARG = 11, 78 PICOBOOT_BUFFER_TOO_SMALL = 12, 79 PICOBOOT_PRECONDITION_NOT_MET = 13, 80 PICOBOOT_MODIFIED_DATA = 14, 81 PICOBOOT_INVALID_DATA = 15, 82 PICOBOOT_NOT_FOUND = 16, 83 PICOBOOT_UNSUPPORTED_MODIFICATION = 17, 84 }; 85 86 struct __packed picoboot_reboot_cmd { 87 uint32_t dPC; // 0 means reset into regular boot path 88 uint32_t dSP; 89 uint32_t dDelayMS; 90 }; 91 92 93 // note this (with pc_sp) union member has the same layout as picoboot_reboot_cmd except with extra dFlags 94 struct __packed picoboot_reboot2_cmd { 95 uint32_t dFlags; 96 uint32_t dDelayMS; 97 uint32_t dParam0; 98 uint32_t dParam1; 99 }; 100 101 // used for EXEC, VECTORIZE_FLASH 102 struct __packed picoboot_address_only_cmd { 103 uint32_t dAddr; 104 }; 105 106 // used for READ, WRITE, FLASH_ERASE 107 struct __packed picoboot_range_cmd { 108 uint32_t dAddr; 109 uint32_t dSize; 110 }; 111 112 struct __packed picoboot_exec2_cmd { 113 uint32_t image_base; 114 uint32_t image_size; 115 uint32_t workarea_base; 116 uint32_t workarea_size; 117 }; 118 119 enum picoboot_exclusive_type { 120 NOT_EXCLUSIVE = 0, 121 EXCLUSIVE, 122 EXCLUSIVE_AND_EJECT 123 }; 124 125 struct __packed picoboot_exclusive_cmd { 126 uint8_t bExclusive; 127 }; 128 129 struct __packed picoboot_otp_cmd { 130 uint16_t wRow; // OTP row 131 uint16_t wRowCount; // number of rows to transfer 132 uint8_t bEcc; // use error correction (16 bit per register vs 24 (stored as 32) bit raw) 133 }; 134 135 136 struct __packed picoboot_get_info_cmd { 137 uint8_t bType; 138 uint8_t bParam; 139 uint16_t wParam; 140 uint32_t dParams[3]; 141 }; 142 143 // little endian 144 struct __packed __aligned(4) picoboot_cmd { 145 uint32_t dMagic; 146 uint32_t dToken; // an identifier for this token to correlate with a status response 147 uint8_t bCmdId; // top bit set for IN 148 uint8_t bCmdSize; // bytes of actual data in the arg part of this structure 149 uint16_t _unused; 150 uint32_t dTransferLength; // length of IN/OUT transfer (or 0) if none 151 union { 152 uint8_t args[16]; 153 struct picoboot_reboot_cmd reboot_cmd; 154 struct picoboot_range_cmd range_cmd; 155 struct picoboot_address_only_cmd address_only_cmd; 156 struct picoboot_exclusive_cmd exclusive_cmd; 157 struct picoboot_reboot2_cmd reboot2_cmd; 158 struct picoboot_otp_cmd otp_cmd; 159 struct picoboot_get_info_cmd get_info_cmd; 160 struct picoboot_exec2_cmd exec2_cmd; 161 }; 162 }; 163 static_assert(32 == sizeof(struct picoboot_cmd), "picoboot_cmd must be 32 bytes big"); 164 165 struct __packed __aligned(4) picoboot_cmd_status { 166 uint32_t dToken; 167 uint32_t dStatusCode; 168 uint8_t bCmdId; 169 uint8_t bInProgress; 170 uint8_t _pad[6]; 171 }; 172 173 static_assert(16 == sizeof(struct picoboot_cmd_status), "picoboot_cmd_status must be 16 bytes big"); 174 175 #endif 176