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 boot_picoboot 20 * 21 * Header file for the PICOBOOT USB interface exposed by an RP2040 in BOOTSEL mode. 22 */ 23 24 #define PICOBOOT_MAGIC 0x431fd10bu 25 26 // -------------------------------------------- 27 // CONTROL REQUESTS FOR THE PICOBOOT INTERFACE 28 // -------------------------------------------- 29 30 // size 0 OUT - unstall EPs and reset 31 #define PICOBOOT_IF_RESET 0x41 32 33 // size 16 IN - return the status of the last command 34 #define PICOBOOT_IF_CMD_STATUS 0x42 35 36 // -------------------------------------------------- 37 // COMMAND REQUESTS SENT TO THE PICOBOOT OUT ENDPOINT 38 // -------------------------------------------------- 39 // 40 // picoboot_cmd structure of size 32 is sent to OUT endpoint 41 // transfer_length bytes are transferred via IN/OUT 42 // device responds on success with 0 length ACK packet set via OUT/IN 43 // device may stall the transferring endpoint in case of error 44 45 enum picoboot_cmd_id { 46 PC_EXCLUSIVE_ACCESS = 0x1, 47 PC_REBOOT = 0x2, 48 PC_FLASH_ERASE = 0x3, 49 PC_READ = 0x84, // either RAM or FLASH 50 PC_WRITE = 5, // either RAM or FLASH (does no erase) 51 PC_EXIT_XIP = 0x6, 52 PC_ENTER_CMD_XIP = 0x7, 53 PC_EXEC = 0x8, 54 PC_VECTORIZE_FLASH = 0x9 55 }; 56 57 enum picoboot_status { 58 PICOBOOT_OK = 0, 59 PICOBOOT_UNKNOWN_CMD = 1, 60 PICOBOOT_INVALID_CMD_LENGTH = 2, 61 PICOBOOT_INVALID_TRANSFER_LENGTH = 3, 62 PICOBOOT_INVALID_ADDRESS = 4, 63 PICOBOOT_BAD_ALIGNMENT = 5, 64 PICOBOOT_INTERLEAVED_WRITE = 6, 65 PICOBOOT_REBOOTING = 7, 66 PICOBOOT_UNKNOWN_ERROR = 8, 67 }; 68 69 struct __packed picoboot_reboot_cmd { 70 uint32_t dPC; // 0 means reset into bootrom 71 uint32_t dSP; 72 uint32_t dDelayMS; 73 }; 74 75 // used for EXEC, VECTORIZE_FLASH 76 struct __packed picoboot_address_only_cmd { 77 uint32_t dAddr; 78 }; 79 80 // used for READ, WRITE, FLASH_ERASE 81 struct __packed picoboot_range_cmd { 82 uint32_t dAddr; 83 uint32_t dSize; 84 }; 85 86 enum picoboot_exclusive_type { 87 NOT_EXCLUSIVE = 0, 88 EXCLUSIVE, 89 EXCLUSIVE_AND_EJECT 90 }; 91 92 struct __packed picoboot_exclusive_cmd { 93 uint8_t bExclusive; 94 }; 95 96 // little endian 97 struct __packed __aligned(4) picoboot_cmd { 98 uint32_t dMagic; 99 uint32_t dToken; // an identifier for this token to correlate with a status response 100 uint8_t bCmdId; // top bit set for IN 101 uint8_t bCmdSize; // bytes of actual data in the arg part of this structure 102 uint16_t _unused; 103 uint32_t dTransferLength; // length of IN/OUT transfer (or 0) if none 104 union { 105 uint8_t args[16]; 106 struct picoboot_reboot_cmd reboot_cmd; 107 struct picoboot_range_cmd range_cmd; 108 struct picoboot_address_only_cmd address_only_cmd; 109 struct picoboot_exclusive_cmd exclusive_cmd; 110 }; 111 }; 112 113 static_assert(32 == sizeof(struct picoboot_cmd), "picoboot_cmd must be 32 bytes big"); 114 115 struct __packed __aligned(4) picoboot_cmd_status { 116 uint32_t dToken; 117 uint32_t dStatusCode; 118 uint8_t bCmdId; 119 uint8_t bInProgress; 120 uint8_t _pad[6]; 121 }; 122 123 static_assert(16 == sizeof(struct picoboot_cmd_status), "picoboot_cmd_status must be 16 bytes big"); 124 #endif 125