blob: 8645d52d738dbf5a11c1c474c94ce93edad6b5d8 [file] [log] [blame]
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT_PICOBOOT_H
#define _BOOT_PICOBOOT_H
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#ifndef NO_PICO_PLATFORM
#include "pico/platform.h"
#endif
/** \file picoboot.h
* \defgroup boot_picoboot_headers boot_picoboot_headers
*
* \brief Header file for the PICOBOOT USB interface exposed by an RP2xxx chip in BOOTSEL mode
*/
#include "picoboot_constants.h"
#define PICOBOOT_MAGIC 0x431fd10bu
// --------------------------------------------
// CONTROL REQUESTS FOR THE PICOBOOT INTERFACE
// --------------------------------------------
// size 0 OUT - un-stall EPs and reset
#define PICOBOOT_IF_RESET 0x41
// size 16 IN - return the status of the last command
#define PICOBOOT_IF_CMD_STATUS 0x42
// --------------------------------------------------
// COMMAND REQUESTS SENT TO THE PICOBOOT OUT ENDPOINT
// --------------------------------------------------
//
// picoboot_cmd structure of size 32 is sent to OUT endpoint
// transfer_length bytes are transferred via IN/OUT
// device responds on success with 0 length ACK packet set via OUT/IN
// device may stall the transferring endpoint in case of error
enum picoboot_cmd_id {
PC_EXCLUSIVE_ACCESS = 0x1,
PC_REBOOT = 0x2,
PC_FLASH_ERASE = 0x3,
PC_READ = 0x84, // either RAM or FLASH
PC_WRITE = 0x5, // either RAM or FLASH (does no erase)
PC_EXIT_XIP = 0x6,
PC_ENTER_CMD_XIP = 0x7,
PC_EXEC = 0x8,
PC_VECTORIZE_FLASH = 0x9,
// RP2350 only below here
PC_REBOOT2 = 0xa,
PC_GET_INFO = 0x8b,
PC_OTP_READ = 0x8c,
PC_OTP_WRITE = 0xd,
//PC_EXEC2 = 0xe, // currently unused
};
enum picoboot_status {
PICOBOOT_OK = 0,
PICOBOOT_UNKNOWN_CMD = 1,
PICOBOOT_INVALID_CMD_LENGTH = 2,
PICOBOOT_INVALID_TRANSFER_LENGTH = 3,
PICOBOOT_INVALID_ADDRESS = 4,
PICOBOOT_BAD_ALIGNMENT = 5,
PICOBOOT_INTERLEAVED_WRITE = 6,
PICOBOOT_REBOOTING = 7,
PICOBOOT_UNKNOWN_ERROR = 8,
PICOBOOT_INVALID_STATE = 9,
PICOBOOT_NOT_PERMITTED = 10,
PICOBOOT_INVALID_ARG = 11,
PICOBOOT_BUFFER_TOO_SMALL = 12,
PICOBOOT_PRECONDITION_NOT_MET = 13,
PICOBOOT_MODIFIED_DATA = 14,
PICOBOOT_INVALID_DATA = 15,
PICOBOOT_NOT_FOUND = 16,
PICOBOOT_UNSUPPORTED_MODIFICATION = 17,
};
struct __packed picoboot_reboot_cmd {
uint32_t dPC; // 0 means reset into regular boot path
uint32_t dSP;
uint32_t dDelayMS;
};
// note this (with pc_sp) union member has the same layout as picoboot_reboot_cmd except with extra dFlags
struct __packed picoboot_reboot2_cmd {
uint32_t dFlags;
uint32_t dDelayMS;
uint32_t dParam0;
uint32_t dParam1;
};
// used for EXEC, VECTORIZE_FLASH
struct __packed picoboot_address_only_cmd {
uint32_t dAddr;
};
// used for READ, WRITE, FLASH_ERASE
struct __packed picoboot_range_cmd {
uint32_t dAddr;
uint32_t dSize;
};
struct __packed picoboot_exec2_cmd {
uint32_t image_base;
uint32_t image_size;
uint32_t workarea_base;
uint32_t workarea_size;
};
enum picoboot_exclusive_type {
NOT_EXCLUSIVE = 0,
EXCLUSIVE,
EXCLUSIVE_AND_EJECT
};
struct __packed picoboot_exclusive_cmd {
uint8_t bExclusive;
};
struct __packed picoboot_otp_cmd {
uint16_t wRow; // OTP row
uint16_t wRowCount; // number of rows to transfer
uint8_t bEcc; // use error correction (16 bit per register vs 24 (stored as 32) bit raw)
};
struct __packed picoboot_get_info_cmd {
uint8_t bType;
uint8_t bParam;
uint16_t wParam;
uint32_t dParams[3];
};
// little endian
struct __packed __aligned(4) picoboot_cmd {
uint32_t dMagic;
uint32_t dToken; // an identifier for this token to correlate with a status response
uint8_t bCmdId; // top bit set for IN
uint8_t bCmdSize; // bytes of actual data in the arg part of this structure
uint16_t _unused;
uint32_t dTransferLength; // length of IN/OUT transfer (or 0) if none
union {
uint8_t args[16];
struct picoboot_reboot_cmd reboot_cmd;
struct picoboot_range_cmd range_cmd;
struct picoboot_address_only_cmd address_only_cmd;
struct picoboot_exclusive_cmd exclusive_cmd;
struct picoboot_reboot2_cmd reboot2_cmd;
struct picoboot_otp_cmd otp_cmd;
struct picoboot_get_info_cmd get_info_cmd;
struct picoboot_exec2_cmd exec2_cmd;
};
};
static_assert(32 == sizeof(struct picoboot_cmd), "picoboot_cmd must be 32 bytes big");
struct __packed __aligned(4) picoboot_cmd_status {
uint32_t dToken;
uint32_t dStatusCode;
uint8_t bCmdId;
uint8_t bInProgress;
uint8_t _pad[6];
};
static_assert(16 == sizeof(struct picoboot_cmd_status), "picoboot_cmd_status must be 16 bytes big");
#endif