mirror of
https://codeberg.org/libreboot/picotool.git
synced 2025-07-04 08:17:03 +00:00
Compare commits
68 commits
Author | SHA1 | Date | |
---|---|---|---|
|
df21059f7c | ||
|
3a476024ad | ||
|
6c3f0901c4 | ||
|
fa69a49bfb | ||
|
4a403bb277 | ||
|
081a386153 | ||
|
fb85aca4cf | ||
|
dcff4d08d1 | ||
|
2f2e8dffdb | ||
|
877282d19d | ||
|
7350867a23 | ||
|
78c9bd121b | ||
|
ae9a188b4d | ||
|
dc9b5494fe | ||
|
0f9977ea71 | ||
|
a86abb73b5 | ||
|
f41f7fa450 | ||
|
3ea1bb5d3e | ||
|
439062512e | ||
|
19226d169b | ||
|
0dcea9c2bb | ||
|
afb5f26532 | ||
|
c2fca5a6a7 | ||
|
c4550ad0a7 | ||
|
de42044be7 | ||
|
0d259e7f76 | ||
|
b62ead341f | ||
|
afdfa928d2 | ||
|
7e2f756a00 | ||
|
333a03b819 | ||
|
fb9a4f0d30 | ||
|
08bbcf7b42 | ||
|
d0d0f29af3 | ||
|
3ff7c3e710 | ||
|
971ee85176 | ||
|
154692d6bf | ||
|
1721716c5e | ||
|
bf33c6ddd7 | ||
|
9fa08571cb | ||
|
818d3bcf51 | ||
|
fb2e6b9b97 | ||
|
f0232cd544 | ||
|
930fcb6108 | ||
|
94a96f3af1 | ||
|
05ae05532a | ||
|
b4590fa43b | ||
|
6ad9c2352c | ||
|
3027a54423 | ||
|
f5064f76fd | ||
|
4545546271 | ||
|
a98a52e5d7 | ||
|
4a523ede0c | ||
|
e66f13bb2f | ||
|
29f5b0bec7 | ||
|
9bb1ab41ef | ||
|
4086910226 | ||
|
29c5431092 | ||
|
f98850637b | ||
|
ef03bd2d90 | ||
|
e1bfb36497 | ||
|
4ea7e634d4 | ||
|
deecc43c5f | ||
|
468ba2f5c4 | ||
|
6b63c0636b | ||
|
0c8dcc16e3 | ||
|
3783fb42c0 | ||
|
3c457839d1 | ||
|
51d83031fa |
41 changed files with 2408 additions and 706 deletions
1
.bazelignore
Normal file
1
.bazelignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
lib/pico-sdk
|
36
.github/workflows/bazel_build.yml
vendored
Normal file
36
.github/workflows/bazel_build.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
name: Bazel presubmit checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bazel-build-check:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Get Bazel
|
||||||
|
uses: bazel-contrib/setup-bazel@0.9.0
|
||||||
|
with:
|
||||||
|
# Avoid downloading Bazel every time.
|
||||||
|
bazelisk-cache: true
|
||||||
|
# Store build cache per workflow.
|
||||||
|
disk-cache: ${{ github.workflow }}
|
||||||
|
# Share repository cache between workflows.
|
||||||
|
repository-cache: true
|
||||||
|
- name: Fetch latest Pico SDK
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: raspberrypi/pico-sdk
|
||||||
|
ref: develop
|
||||||
|
fetch-depth: 0
|
||||||
|
path: lib/pico-sdk
|
||||||
|
- name: Bazel Picotool with develop pico-sdk
|
||||||
|
run: bazel build @picotool//:picotool --override_module=pico-sdk=lib/pico-sdk
|
7
.github/workflows/choco_packages.config
vendored
Normal file
7
.github/workflows/choco_packages.config
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="gcc-arm-embedded" version="10.2.1" />
|
||||||
|
<package id="cmake" version="3.25.2" installArguments="ADD_CMAKE_TO_PATH=System" />
|
||||||
|
<package id="mingw" version="12.2.0" />
|
||||||
|
<package id="ninja" version="1.11.1" />
|
||||||
|
</packages>
|
73
.github/workflows/test.yml
vendored
Normal file
73
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# Prevent running twice for PRs from same repo
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
|
||||||
|
name: Build & Test
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
generator: ["Ninja", "Unix Makefiles"]
|
||||||
|
mbedtls: ["mbedtls", ""]
|
||||||
|
libusb: ["libusb", ""]
|
||||||
|
compile: ["compile", ""]
|
||||||
|
exclude:
|
||||||
|
- os: 'windows-latest'
|
||||||
|
generator: "Unix Makefiles"
|
||||||
|
- libusb: ""
|
||||||
|
compile: "compile"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: |
|
||||||
|
choco install -y .github/workflows/choco_packages.config
|
||||||
|
curl -L https://github.com/libusb/libusb/releases/download/v1.0.27/libusb-1.0.27.7z -o libusb.7z
|
||||||
|
7z x libusb.7z -olibusb
|
||||||
|
- name: Set LIBUSB_ROOT (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: bash
|
||||||
|
run: echo "LIBUSB_ROOT=$(pwd)/libusb" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Install dependencies (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
brew install libusb ninja
|
||||||
|
brew install --cask gcc-arm-embedded
|
||||||
|
|
||||||
|
- name: Install dependencies (Linux)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: sudo apt install cmake ninja-build python3 build-essential gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib libusb-1.0-0-dev
|
||||||
|
- name: Checkout Pico SDK
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: raspberrypi/pico-sdk
|
||||||
|
ref: develop
|
||||||
|
path: pico-sdk
|
||||||
|
submodules: ${{ !(!matrix.mbedtls) }}
|
||||||
|
|
||||||
|
- name: Build and Install
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build -G "${{ matrix.generator }}" -D PICO_SDK_PATH="${{ github.workspace }}/pico-sdk" ${{ !matrix.libusb && '-D PICOTOOL_NO_LIBUSB=1' || '' }} ${{ matrix.compile && '-D USE_PRECOMPILED=false' || '' }}
|
||||||
|
cmake --build build
|
||||||
|
${{ runner.os != 'Windows' && 'sudo' || '' }} cmake --install build
|
||||||
|
- name: Add to path (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: echo "C:\Program Files (x86)\picotool\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
picotool help
|
||||||
|
curl -L https://datasheets.raspberrypi.com/soft/blink.uf2 -o blink.uf2
|
||||||
|
curl -L https://datasheets.raspberrypi.com/soft/hello_world.uf2 -o hello_world.uf2
|
||||||
|
curl -L https://datasheets.raspberrypi.com/soft/flash_nuke.uf2 -o flash_nuke.uf2
|
||||||
|
picotool info -a blink.uf2
|
||||||
|
picotool info -a hello_world.uf2
|
||||||
|
picotool info -a flash_nuke.uf2
|
31
BUILD.bazel
31
BUILD.bazel
|
@ -2,6 +2,8 @@ load("//bazel:defs.bzl", "otp_header_parse", "picotool_binary_data_header")
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
PICOTOOL_SDK_VERSION_STRING = module_version() if module_version() != None else "0.0.1-WORKSPACE"
|
||||||
|
|
||||||
picotool_binary_data_header(
|
picotool_binary_data_header(
|
||||||
name = "rp2350_rom",
|
name = "rp2350_rom",
|
||||||
src = "bootrom.end.bin",
|
src = "bootrom.end.bin",
|
||||||
|
@ -15,6 +17,13 @@ picotool_binary_data_header(
|
||||||
out = "xip_ram_perms_elf.h",
|
out = "xip_ram_perms_elf.h",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: Make it possible to build the prebuilt from source.
|
||||||
|
picotool_binary_data_header(
|
||||||
|
name = "flash_id_bin",
|
||||||
|
src = "//picoboot_flash_id:picoboot_flash_id_prebuilt",
|
||||||
|
out = "flash_id_bin.h",
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "xip_ram_perms",
|
name = "xip_ram_perms",
|
||||||
srcs = ["xip_ram_perms.cpp"],
|
srcs = ["xip_ram_perms.cpp"],
|
||||||
|
@ -37,6 +46,10 @@ otp_header_parse(
|
||||||
name = "otp_header",
|
name = "otp_header",
|
||||||
src = "@pico-sdk//src/rp2350/hardware_regs:otp_data_header",
|
src = "@pico-sdk//src/rp2350/hardware_regs:otp_data_header",
|
||||||
out = "rp2350.json.h",
|
out = "rp2350.json.h",
|
||||||
|
target_compatible_with = select({
|
||||||
|
"@rules_cc//cc/compiler:msvc-cl": ["@platforms//:incompatible"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
|
@ -47,10 +60,14 @@ cc_binary(
|
||||||
"main.cpp",
|
"main.cpp",
|
||||||
"otp.cpp",
|
"otp.cpp",
|
||||||
"otp.h",
|
"otp.h",
|
||||||
"rp2350.json.h",
|
|
||||||
"rp2350.rom.h",
|
"rp2350.rom.h",
|
||||||
"xip_ram_perms.cpp",
|
"xip_ram_perms.cpp",
|
||||||
],
|
] + select({
|
||||||
|
# MSVC can't handle long strings, so use this manually generated
|
||||||
|
# header instead.
|
||||||
|
"@rules_cc//cc/compiler:msvc-cl": [],
|
||||||
|
"//conditions:default": ["rp2350.json.h"],
|
||||||
|
}),
|
||||||
copts = select({
|
copts = select({
|
||||||
"@rules_cc//cc/compiler:msvc-cl": [
|
"@rules_cc//cc/compiler:msvc-cl": [
|
||||||
"/std:c++20",
|
"/std:c++20",
|
||||||
|
@ -64,8 +81,7 @@ cc_binary(
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
defines = [
|
defines = [
|
||||||
# TODO: There's probably a nicer way to share the version with CMake.
|
'PICOTOOL_VERSION=\\"{}\\"'.format(PICOTOOL_SDK_VERSION_STRING),
|
||||||
'PICOTOOL_VERSION=\\"2.0.0\\"',
|
|
||||||
'SYSTEM_VERSION=\\"host\\"',
|
'SYSTEM_VERSION=\\"host\\"',
|
||||||
'COMPILER_INFO=\\"local\\"',
|
'COMPILER_INFO=\\"local\\"',
|
||||||
"SUPPORT_A0=0",
|
"SUPPORT_A0=0",
|
||||||
|
@ -98,5 +114,10 @@ cc_binary(
|
||||||
"@pico-sdk//src/rp2350/hardware_regs:otp_data",
|
"@pico-sdk//src/rp2350/hardware_regs:otp_data",
|
||||||
"@pico-sdk//src/rp2_common/pico_bootrom:pico_bootrom_headers",
|
"@pico-sdk//src/rp2_common/pico_bootrom:pico_bootrom_headers",
|
||||||
"@pico-sdk//src/rp2_common/pico_stdio_usb:reset_interface_headers",
|
"@pico-sdk//src/rp2_common/pico_stdio_usb:reset_interface_headers",
|
||||||
],
|
] + select({
|
||||||
|
# MSVC can't handle long strings, so use this manually generated
|
||||||
|
# header instead.
|
||||||
|
"@rules_cc//cc/compiler:msvc-cl": ["//otp_header_parser:pre_generated_otp_header"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -35,7 +35,7 @@ if (PICOTOOL_FLAT_INSTALL)
|
||||||
set(INSTALL_DATADIR picotool)
|
set(INSTALL_DATADIR picotool)
|
||||||
set(INSTALL_BINDIR picotool)
|
set(INSTALL_BINDIR picotool)
|
||||||
else()
|
else()
|
||||||
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/picotool)
|
set(INSTALL_CONFIGDIR lib/cmake/picotool)
|
||||||
set(INSTALL_DATADIR ${CMAKE_INSTALL_DATADIR}/picotool)
|
set(INSTALL_DATADIR ${CMAKE_INSTALL_DATADIR}/picotool)
|
||||||
set(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
|
set(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
|
||||||
endif()
|
endif()
|
||||||
|
@ -70,6 +70,7 @@ if (NOT PICOTOOL_NO_LIBUSB)
|
||||||
"-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}"
|
"-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}"
|
||||||
"-DPICO_SDK_PATH:FILEPATH=${PICO_SDK_PATH}"
|
"-DPICO_SDK_PATH:FILEPATH=${PICO_SDK_PATH}"
|
||||||
"-DUSE_PRECOMPILED:BOOL=${USE_PRECOMPILED}"
|
"-DUSE_PRECOMPILED:BOOL=${USE_PRECOMPILED}"
|
||||||
|
"-DPICO_DEBUG_INFO_IN_RELEASE=OFF"
|
||||||
BUILD_ALWAYS 1 # todo remove this
|
BUILD_ALWAYS 1 # todo remove this
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
)
|
)
|
||||||
|
@ -84,6 +85,30 @@ if (NOT PICOTOOL_NO_LIBUSB)
|
||||||
DEPENDS xip_ram_perms
|
DEPENDS xip_ram_perms
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# compile flash_id
|
||||||
|
ExternalProject_Add(flash_id
|
||||||
|
PREFIX picoboot_flash_id
|
||||||
|
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/picoboot_flash_id
|
||||||
|
BINARY_DIR ${CMAKE_BINARY_DIR}/picoboot_flash_id
|
||||||
|
CMAKE_ARGS
|
||||||
|
"-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}"
|
||||||
|
"-DPICO_SDK_PATH:FILEPATH=${PICO_SDK_PATH}"
|
||||||
|
"-DUSE_PRECOMPILED:BOOL=${USE_PRECOMPILED}"
|
||||||
|
"-DPICO_DEBUG_INFO_IN_RELEASE=OFF"
|
||||||
|
BUILD_ALWAYS 1 # todo remove this
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FLASH_ID_BIN ${CMAKE_BINARY_DIR}/picoboot_flash_id/flash_id.bin)
|
||||||
|
add_executable(flash_id_bin IMPORTED)
|
||||||
|
add_dependencies(flash_id_bin flash_id)
|
||||||
|
set_property(TARGET flash_id_bin PROPERTY IMPORTED_LOCATION ${FLASH_ID_BIN})
|
||||||
|
# copy flash_id.bin into build directory
|
||||||
|
add_custom_command(TARGET flash_id
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${FLASH_ID_BIN} ${CMAKE_BINARY_DIR}/flash_id.bin
|
||||||
|
DEPENDS flash_id
|
||||||
|
)
|
||||||
|
|
||||||
# We want to generate headers from WELCOME.HTM etc.
|
# We want to generate headers from WELCOME.HTM etc.
|
||||||
ExternalProject_Add(otp_header_parser
|
ExternalProject_Add(otp_header_parser
|
||||||
PREFIX otp_header_parser
|
PREFIX otp_header_parser
|
||||||
|
@ -144,7 +169,10 @@ if (NOT PICOTOOL_NO_LIBUSB)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target(binary_data DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/rp2350.rom.h ${CMAKE_CURRENT_BINARY_DIR}/xip_ram_perms_elf.h)
|
add_custom_target(binary_data DEPENDS
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/rp2350.rom.h
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/xip_ram_perms_elf.h
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/flash_id_bin.h)
|
||||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/rp2350.rom.h
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/rp2350.rom.h
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-D BINARY_FILE=${CMAKE_CURRENT_LIST_DIR}/bootrom.end.bin
|
-D BINARY_FILE=${CMAKE_CURRENT_LIST_DIR}/bootrom.end.bin
|
||||||
|
@ -160,6 +188,14 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xip_ram_perms_elf.h
|
||||||
DEPENDS xip_ram_perms
|
DEPENDS xip_ram_perms
|
||||||
COMMENT "Configuring xip_ram_perms_elf.h"
|
COMMENT "Configuring xip_ram_perms_elf.h"
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_id_bin.h
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-D BINARY_FILE=${FLASH_ID_BIN}
|
||||||
|
-D OUTPUT_NAME=flash_id_bin
|
||||||
|
-P ${CMAKE_CURRENT_LIST_DIR}/cmake/binh.cmake
|
||||||
|
DEPENDS flash_id
|
||||||
|
COMMENT "Configuring flash_id_bin.h"
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
add_subdirectory(errors)
|
add_subdirectory(errors)
|
||||||
|
|
||||||
|
@ -188,10 +224,9 @@ add_subdirectory(${PICO_SDK_PATH}/src/common/boot_uf2_headers boot_uf2_headers)
|
||||||
add_subdirectory(${PICO_SDK_PATH}/src/common/boot_picoboot_headers boot_picoboot_headers)
|
add_subdirectory(${PICO_SDK_PATH}/src/common/boot_picoboot_headers boot_picoboot_headers)
|
||||||
add_subdirectory(${PICO_SDK_PATH}/src/common/boot_picobin_headers boot_picobin_headers)
|
add_subdirectory(${PICO_SDK_PATH}/src/common/boot_picobin_headers boot_picobin_headers)
|
||||||
add_subdirectory(${PICO_SDK_PATH}/src/common/pico_usb_reset_interface_headers pico_usb_reset_interface_headers)
|
add_subdirectory(${PICO_SDK_PATH}/src/common/pico_usb_reset_interface_headers pico_usb_reset_interface_headers)
|
||||||
|
add_subdirectory(${PICO_SDK_PATH}/src/rp2_common/boot_bootrom_headers boot_bootrom_headers)
|
||||||
add_subdirectory(${PICO_SDK_PATH}/src/host/pico_platform pico_platform)
|
add_subdirectory(${PICO_SDK_PATH}/src/host/pico_platform pico_platform)
|
||||||
|
|
||||||
add_library(pico_bootrom_headers INTERFACE)
|
|
||||||
target_include_directories(pico_bootrom_headers INTERFACE ${PICO_SDK_PATH}/src/rp2_common/pico_bootrom/include)
|
|
||||||
add_library(regs_headers INTERFACE)
|
add_library(regs_headers INTERFACE)
|
||||||
target_include_directories(regs_headers INTERFACE ${PICO_SDK_PATH}/src/rp2350/hardware_regs/include)
|
target_include_directories(regs_headers INTERFACE ${PICO_SDK_PATH}/src/rp2350/hardware_regs/include)
|
||||||
|
|
||||||
|
@ -204,8 +239,8 @@ if (NOT PICOTOOL_NO_LIBUSB)
|
||||||
target_sources(picotool PRIVATE xip_ram_perms.cpp)
|
target_sources(picotool PRIVATE xip_ram_perms.cpp)
|
||||||
add_dependencies(picotool generate_otp_header xip_ram_perms_elf binary_data)
|
add_dependencies(picotool generate_otp_header xip_ram_perms_elf binary_data)
|
||||||
endif()
|
endif()
|
||||||
set(PROJECT_VERSION 2.0.0)
|
set(PROJECT_VERSION 2.1.0)
|
||||||
set(PICOTOOL_VERSION 2.0.0)
|
set(PICOTOOL_VERSION 2.1.0)
|
||||||
set(SYSTEM_VERSION "${CMAKE_SYSTEM_NAME}")
|
set(SYSTEM_VERSION "${CMAKE_SYSTEM_NAME}")
|
||||||
set(COMPILER_INFO "${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}, ${CMAKE_BUILD_TYPE}")
|
set(COMPILER_INFO "${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}, ${CMAKE_BUILD_TYPE}")
|
||||||
target_compile_definitions(picotool PRIVATE
|
target_compile_definitions(picotool PRIVATE
|
||||||
|
@ -224,7 +259,7 @@ target_link_libraries(picotool
|
||||||
boot_uf2_headers
|
boot_uf2_headers
|
||||||
boot_picoboot_headers
|
boot_picoboot_headers
|
||||||
boot_picobin_headers
|
boot_picobin_headers
|
||||||
pico_bootrom_headers
|
boot_bootrom_headers
|
||||||
pico_platform_headers
|
pico_platform_headers
|
||||||
pico_usb_reset_interface_headers
|
pico_usb_reset_interface_headers
|
||||||
regs_headers
|
regs_headers
|
||||||
|
@ -242,7 +277,11 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT LIBUSB_FOUND)
|
if (NOT LIBUSB_FOUND)
|
||||||
message("libUSB is not found - no USB support will be built")
|
if (PICOTOOL_NO_LIBUSB)
|
||||||
|
message("PICOTOOL_NO_LIBUSB is set - no USB support will be built")
|
||||||
|
else()
|
||||||
|
message("libUSB is not found - no USB support will be built")
|
||||||
|
endif()
|
||||||
target_compile_definitions(picotool PRIVATE HAS_LIBUSB=0)
|
target_compile_definitions(picotool PRIVATE HAS_LIBUSB=0)
|
||||||
target_link_libraries(picotool
|
target_link_libraries(picotool
|
||||||
picoboot_connection_header)
|
picoboot_connection_header)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
module(
|
module(
|
||||||
name = "picotool",
|
name = "picotool",
|
||||||
version = "2.0.0",
|
version = "2.1.0",
|
||||||
)
|
)
|
||||||
|
|
||||||
bazel_dep(name = "rules_libusb", version = "0.1.0-rc1")
|
bazel_dep(name = "rules_libusb", version = "0.1.0-rc1")
|
||||||
bazel_dep(name = "pico-sdk", version = "2.0.0")
|
bazel_dep(name = "pico-sdk", version = "2.1.0")
|
||||||
bazel_dep(name = "rules_cc", version = "0.0.9")
|
bazel_dep(name = "rules_cc", version = "0.0.9")
|
||||||
bazel_dep(name = "bazel_skylib", version = "1.6.1")
|
bazel_dep(name = "bazel_skylib", version = "1.6.1")
|
||||||
bazel_dep(name = "rules_python", version = "0.22.1")
|
bazel_dep(name = "rules_python", version = "0.22.1")
|
||||||
|
|
199
README.md
199
README.md
|
@ -16,6 +16,8 @@ Use your favorite package tool to install dependencies. For example, on Ubuntu:
|
||||||
sudo apt install build-essential pkg-config libusb-1.0-0-dev cmake
|
sudo apt install build-essential pkg-config libusb-1.0-0-dev cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> If libusb-1.0-0-dev is not installed, picotool still builds, but it omits all options that deal with managing a pico via USB (load, save, erase, verify, reboot). Builds that do not include USB support can be recognized because these commands also do not appear in the help command. The build output message 'libUSB is not found - no USB support will be built' also appears in the build logs.
|
||||||
|
|
||||||
Then simply build like a normal CMake project:
|
Then simply build like a normal CMake project:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
|
@ -66,32 +68,33 @@ No need to download libusb separately or set `LIBUSB_ROOT`.
|
||||||
pacman -S $MINGW_PACKAGE_PREFIX-{toolchain,cmake,libusb}
|
pacman -S $MINGW_PACKAGE_PREFIX-{toolchain,cmake,libusb}
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
MSYS2_ARG_CONV_EXCL=- cmake .. -G"MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX
|
cmake .. -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX
|
||||||
make
|
cmake --build .
|
||||||
make install DESTDIR=/ # optional
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage by the Raspberry Pi Pico SDK
|
## Usage by the Raspberry Pi Pico SDK
|
||||||
|
|
||||||
The Raspberry Pi Pico SDK ([pico-sdk](https://github.com/raspberrypi/pico-sdk)) version 2.0.0 and above, uses `picotool` to do the ELF->UF2 conversion previously handled by the `elf2uf2` tool in the SDK. `picootol` is also used by the SDK for hashing and/or signing binaries.
|
The Raspberry Pi Pico SDK ([pico-sdk](https://github.com/raspberrypi/pico-sdk)) version 2.0.0 and above uses `picotool` to do the ELF-to-UF2 conversion previously handled by the `elf2uf2` tool in the SDK. The SDK also uses `picotool` to hash and sign binaries.
|
||||||
|
|
||||||
Whilst the SDK can download picotool on its own per project, if you have multiple projects or build configurations, it is preferable to install a single copy of `picotool` locally.
|
Whilst the SDK can download picotool on its own per project, if you have multiple projects or build configurations, it is preferable to install a single copy of `picotool` locally. This can be done most simply with `make install` or `cmake --install .`, using `sudo` if required; the SDK will use this installed version by default.
|
||||||
|
|
||||||
This can be done most simply with `make install`; the SDK will use this installed version by default.
|
> On some Linux systems, the `~/.local` prefix may be used for an install without `sudo`; from your build directory simply run
|
||||||
|
> ```console
|
||||||
|
> cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||||
|
> make install
|
||||||
|
> ```
|
||||||
|
> This will only work if `~/.local` is included in your `PATH`
|
||||||
|
|
||||||
Alternatively you can install in a custom path via:
|
Alternatively, you can install to a custom path via:
|
||||||
|
|
||||||
```
|
```console
|
||||||
cmake -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR -DPICOTOOL_FLAT_INSTALL=1 ..
|
cmake -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR -DPICOTOOL_FLAT_INSTALL=1 ..
|
||||||
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
In order for the SDK to find `picotool` in this custom path, you will need to set the `picotool_DIR` variable in your project, either by passing to `-Dpicotool_DIR=$MY_INSTALL_DIR/picotool` to your SDK `cmake` command, or by adding
|
In order for the SDK to find `picotool` in this custom folder, you will usually need to set the `picotool_DIR` variable in your project. This can be achieved either by setting the `picotool_DIR` environment variable to `$MY_INSTALL_DIR/picotool`, by passing `-Dpicotool_DIR=$MY_INSTALL_DIR/picotool` to your `cmake` command, or by adding `set(picotool_DIR $MY_INSTALL_DIR/picotool)` to your CMakeLists.txt file.
|
||||||
|
|
||||||
```CMake
|
> See the [find_package documentation](https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure) for more details
|
||||||
set(picotool_DIR $MY_INSTALL_DIR/picotool)
|
|
||||||
```
|
|
||||||
|
|
||||||
to your CMakeLists.txt file.
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
@ -102,20 +105,23 @@ Note for additional documentation see https://rptl.io/pico-get-started
|
||||||
```
|
```
|
||||||
$ picotool help
|
$ picotool help
|
||||||
PICOTOOL:
|
PICOTOOL:
|
||||||
Tool for interacting with RP2040/RP2350 device(s) in BOOTSEL mode, or with an RP2040/RP2350 binary
|
Tool for interacting with RP-series device(s) in BOOTSEL mode, or with an RP-series binary
|
||||||
|
|
||||||
SYNOPSIS:
|
SYNOPSIS:
|
||||||
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] [device-selection]
|
picotool info [-b] [-m] [-p] [-d] [--debug] [-l] [-a] [device-selection]
|
||||||
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] <filename> [-t <type>]
|
picotool info [-b] [-m] [-p] [-d] [--debug] [-l] [-a] <filename> [-t <type>]
|
||||||
picotool config [-s <key> <value>] [-g <group>] [device-selection]
|
picotool config [-s <key> <value>] [-g <group>] [device-selection]
|
||||||
picotool config [-s <key> <value>] [-g <group>] <filename> [-t <type>]
|
picotool config [-s <key> <value>] [-g <group>] <filename> [-t <type>]
|
||||||
picotool load [-p] [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [device-selection]
|
picotool load [--ignore-partitions] [--family <family_id>] [-p <partition>] [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o <offset>] [device-selection]
|
||||||
picotool encrypt [--quiet] [--verbose] [--hash] [--sign] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] <aes_key> [-t <type>] [<signing_key>] [-t <type>]
|
picotool encrypt [--quiet] [--verbose] [--hash] [--sign] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] <aes_key> [-t <type>] [<signing_key>] [-t <type>]
|
||||||
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] [<key>] [-t <type>] [<otp>] [-t <type>] [--major <major>] [--minor <minor>] [--rollback <rollback> [<rows>..]]
|
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] [<key>] [-t <type>] [<otp>] [-t <type>] [--major <major>] [--minor <minor>] [--rollback <rollback> [<rows>..]]
|
||||||
picotool link [--quiet] [--verbose] <outfile> [-t <type>] <infile1> [-t <type>] <infile2> [-t <type>] [<infile3>] [-t <type>] [-p] <pad>
|
picotool link [--quiet] [--verbose] <outfile> [-t <type>] <infile1> [-t <type>] <infile2> [-t <type>] [<infile3>] [-t <type>] [-p] <pad>
|
||||||
picotool save [-p] [device-selection]
|
picotool save [-p] [-v] [--family <family_id>] [device-selection]
|
||||||
picotool save -a [device-selection]
|
picotool save -a [-v] [--family <family_id>] [device-selection]
|
||||||
picotool save -r <from> <to> [device-selection]
|
picotool save -r <from> <to> [-v] [--family <family_id>] [device-selection]
|
||||||
|
picotool erase [-a] [device-selection]
|
||||||
|
picotool erase -p <partition> [device-selection]
|
||||||
|
picotool erase -r <from> <to> [device-selection]
|
||||||
picotool verify [device-selection]
|
picotool verify [device-selection]
|
||||||
picotool reboot [-a] [-u] [-g <partition>] [-c <cpu>] [device-selection]
|
picotool reboot [-a] [-u] [-g <partition>] [-c <cpu>] [device-selection]
|
||||||
picotool otp list|get|set|load|dump|permissions|white-label
|
picotool otp list|get|set|load|dump|permissions|white-label
|
||||||
|
@ -127,20 +133,21 @@ SYNOPSIS:
|
||||||
|
|
||||||
COMMANDS:
|
COMMANDS:
|
||||||
info Display information from the target device(s) or file.
|
info Display information from the target device(s) or file.
|
||||||
Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode
|
Without any arguments, this will display basic information for all connected RP-series devices in BOOTSEL mode
|
||||||
config Display or change program configuration settings from the target device(s) or file.
|
config Display or change program configuration settings from the target device(s) or file.
|
||||||
load Load the program / memory range stored in a file onto the device.
|
load Load the program / memory range stored in a file onto the device.
|
||||||
encrypt Encrypt the program.
|
encrypt Encrypt the program.
|
||||||
seal Add final metadata to a binary, optionally including a hash and/or signature.
|
seal Add final metadata to a binary, optionally including a hash and/or signature.
|
||||||
link Link multiple binaries into one block loop.
|
link Link multiple binaries into one block loop.
|
||||||
save Save the program / memory stored in flash on the device to a file.
|
save Save the program / memory stored in flash on the device to a file.
|
||||||
|
erase Erase the program / memory stored in flash on the device.
|
||||||
verify Check that the device contents match those in the file.
|
verify Check that the device contents match those in the file.
|
||||||
reboot Reboot the device
|
reboot Reboot the device
|
||||||
otp Commands related to the RP2350 OTP (One-Time-Programmable) Memory
|
otp Commands related to the RP2350 OTP (One-Time-Programmable) Memory
|
||||||
partition Commands related to RP2350 Partition Tables
|
partition Commands related to RP2350 Partition Tables
|
||||||
uf2 Commands related to UF2 creation and status
|
uf2 Commands related to UF2 creation and status
|
||||||
version Display picotool version
|
version Display picotool version
|
||||||
coprodis Post-process coprocessor instructions in dissassembly files.
|
coprodis Post-process coprocessor instructions in disassembly files.
|
||||||
help Show general help or help for a specific command
|
help Show general help or help for a specific command
|
||||||
|
|
||||||
Use "picotool help <cmd>" for more info
|
Use "picotool help <cmd>" for more info
|
||||||
|
@ -160,16 +167,18 @@ a file. This file can be an ELF, a UF2 or a BIN file.
|
||||||
$ picotool help info
|
$ picotool help info
|
||||||
INFO:
|
INFO:
|
||||||
Display information from the target device(s) or file.
|
Display information from the target device(s) or file.
|
||||||
Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode
|
Without any arguments, this will display basic information for all connected RP-series devices in BOOTSEL mode
|
||||||
|
|
||||||
SYNOPSIS:
|
SYNOPSIS:
|
||||||
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] [device-selection]
|
picotool info [-b] [-m] [-p] [-d] [--debug] [-l] [-a] [device-selection]
|
||||||
picotool info [-b] [-p] [-d] [--debug] [-l] [-a] <filename> [-t <type>]
|
picotool info [-b] [-m] [-p] [-d] [--debug] [-l] [-a] <filename> [-t <type>]
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
Information to display
|
Information to display
|
||||||
-b, --basic
|
-b, --basic
|
||||||
Include basic information. This is the default
|
Include basic information. This is the default
|
||||||
|
-m, --metadata
|
||||||
|
Include all metadata blocks
|
||||||
-p, --pins
|
-p, --pins
|
||||||
Include pin information
|
Include pin information
|
||||||
-d, --device
|
-d, --device
|
||||||
|
@ -182,7 +191,7 @@ OPTIONS:
|
||||||
Include all information
|
Include all information
|
||||||
|
|
||||||
TARGET SELECTION:
|
TARGET SELECTION:
|
||||||
To target one or more connected RP2040 device(s) in BOOTSEL mode (the default)
|
To target one or more connected RP-series device(s) in BOOTSEL mode (the default)
|
||||||
--bus <bus>
|
--bus <bus>
|
||||||
Filter devices by USB bus number
|
Filter devices by USB bus number
|
||||||
--address <addr>
|
--address <addr>
|
||||||
|
@ -290,7 +299,7 @@ OPTIONS:
|
||||||
Filter by feature group
|
Filter by feature group
|
||||||
|
|
||||||
TARGET SELECTION:
|
TARGET SELECTION:
|
||||||
To target one or more connected RP2040 device(s) in BOOTSEL mode (the default)
|
To target one or more connected RP-series device(s) in BOOTSEL mode (the default)
|
||||||
--bus <bus>
|
--bus <bus>
|
||||||
Filter devices by USB bus number
|
Filter devices by USB bus number
|
||||||
--address <addr>
|
--address <addr>
|
||||||
|
@ -364,7 +373,7 @@ OPTIONS:
|
||||||
--family
|
--family
|
||||||
Specify the family ID of the file to load
|
Specify the family ID of the file to load
|
||||||
<family_id>
|
<family_id>
|
||||||
family id to use for load
|
family ID to use for load
|
||||||
-p, --partition
|
-p, --partition
|
||||||
Specify the partition to load into
|
Specify the partition to load into
|
||||||
<partition>
|
<partition>
|
||||||
|
@ -428,9 +437,9 @@ SAVE:
|
||||||
Save the program / memory stored in flash on the device to a file.
|
Save the program / memory stored in flash on the device to a file.
|
||||||
|
|
||||||
SYNOPSIS:
|
SYNOPSIS:
|
||||||
picotool save [-p] [device-selection]
|
picotool save [-p] [-v] [--family <family_id>] [device-selection]
|
||||||
picotool save -a [device-selection]
|
picotool save -a [-v] [--family <family_id>] [device-selection]
|
||||||
picotool save -r <from> <to> [device-selection]
|
picotool save -r <from> <to> [-v] [--family <family_id>] [device-selection]
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
Selection of data to save
|
Selection of data to save
|
||||||
|
@ -445,6 +454,13 @@ OPTIONS:
|
||||||
The lower address bound in hex
|
The lower address bound in hex
|
||||||
<to>
|
<to>
|
||||||
The upper address bound in hex
|
The upper address bound in hex
|
||||||
|
Other
|
||||||
|
-v, --verify
|
||||||
|
Verify the data was saved correctly
|
||||||
|
--family
|
||||||
|
Specify the family ID to save the file as
|
||||||
|
<family_id>
|
||||||
|
family id to save file as
|
||||||
Source device selection
|
Source device selection
|
||||||
--bus <bus>
|
--bus <bus>
|
||||||
Filter devices by USB bus number
|
Filter devices by USB bus number
|
||||||
|
@ -495,6 +511,95 @@ name: lcd_1602_i2c
|
||||||
web site: https://github.com/raspberrypi/pico-examples/tree/HEAD/i2c/lcd_1602_i2c
|
web site: https://github.com/raspberrypi/pico-examples/tree/HEAD/i2c/lcd_1602_i2c
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## erase
|
||||||
|
|
||||||
|
`erase` allows you to erase all of flash, a partition of flash, or an explicit range of flash on the device.
|
||||||
|
It defaults to erasing all of flash.
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ picotool help erase
|
||||||
|
ERASE:
|
||||||
|
Erase the program / memory stored in flash on the device.
|
||||||
|
|
||||||
|
SYNOPSIS:
|
||||||
|
picotool erase [-a] [device-selection]
|
||||||
|
picotool erase [-p <partition>] [device-selection]
|
||||||
|
picotool erase -r <from> <to> [device-selection]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
Selection of data to erase
|
||||||
|
-a, --all
|
||||||
|
Erase all of flash memory. This is the default
|
||||||
|
-p, --partition
|
||||||
|
Erase a partition
|
||||||
|
<partition>
|
||||||
|
Partition number to erase
|
||||||
|
-r, --range
|
||||||
|
Erase a range of memory. Note that erases must be 4096 byte-aligned, so the range is expanded accordingly
|
||||||
|
<from>
|
||||||
|
The lower address bound in hex
|
||||||
|
<to>
|
||||||
|
The upper address bound in hex
|
||||||
|
Source device selection
|
||||||
|
--bus <bus>
|
||||||
|
Filter devices by USB bus number
|
||||||
|
--address <addr>
|
||||||
|
Filter devices by USB device address
|
||||||
|
--vid <vid>
|
||||||
|
Filter by vendor id
|
||||||
|
--pid <pid>
|
||||||
|
Filter by product id
|
||||||
|
--ser <ser>
|
||||||
|
Filter by serial number
|
||||||
|
-f, --force
|
||||||
|
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
|
||||||
|
command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
|
||||||
|
-F, --force-no-reboot
|
||||||
|
Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing the
|
||||||
|
command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but without the
|
||||||
|
RPI-RP2 drive mounted
|
||||||
|
```
|
||||||
|
|
||||||
|
e.g. first looking at what is on the device...
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ picotool info
|
||||||
|
Partition 0
|
||||||
|
Program Information
|
||||||
|
none
|
||||||
|
|
||||||
|
Partition 1
|
||||||
|
Program Information
|
||||||
|
name: blink
|
||||||
|
web site: https://github.com/raspberrypi/pico-examples/tree/HEAD/blink
|
||||||
|
features: UART stdin / stdout
|
||||||
|
binary start: 0x10000000
|
||||||
|
binary end: 0x1000a934
|
||||||
|
target chip: RP2350
|
||||||
|
image type: ARM Secure
|
||||||
|
```
|
||||||
|
|
||||||
|
... then erase partition 1 ...
|
||||||
|
```text
|
||||||
|
$ picotool erase -p 1
|
||||||
|
Erasing partition 1:
|
||||||
|
0007f000->000fc000
|
||||||
|
Erasing: [==============================] 100%
|
||||||
|
Erased 512000 bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
... and looking at the device again:
|
||||||
|
```text
|
||||||
|
$ picotool info
|
||||||
|
Partition 0
|
||||||
|
Program Information
|
||||||
|
none
|
||||||
|
|
||||||
|
Partition 1
|
||||||
|
Program Information
|
||||||
|
none
|
||||||
|
```
|
||||||
|
|
||||||
## seal
|
## seal
|
||||||
|
|
||||||
`seal` allows you to sign and/or hash a binary to run on RP2350.
|
`seal` allows you to sign and/or hash a binary to run on RP2350.
|
||||||
|
@ -653,14 +758,14 @@ un-partitioned_space : S(rw) NSBOOT(rw) NS(rw), uf2 { absolute }
|
||||||
partitions:
|
partitions:
|
||||||
0(A) 00002000->00201000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000000, "A", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
|
0(A) 00002000->00201000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000000, "A", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
|
||||||
1(B w/ 0) 00201000->00400000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000001, "B", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
|
1(B w/ 0) 00201000->00400000 S(rw) NSBOOT(rw) NS(rw), id=0000000000000001, "B", uf2 { rp2350-arm-s, rp2350-riscv }, arm_boot 1, riscv_boot 1
|
||||||
Family id 'rp2350-arm-s' can be downloaded in partition 0:
|
Family ID 'rp2350-arm-s' can be downloaded in partition 0:
|
||||||
00002000->00201000
|
00002000->00201000
|
||||||
```
|
```
|
||||||
|
|
||||||
### create
|
### create
|
||||||
|
|
||||||
This command allows you to create partition tables, and additionally embed them into the block loop if ELF files (for example, for bootloaders).
|
This command allows you to create partition tables, and additionally embed them into the block loop if ELF files (for example, for bootloaders).
|
||||||
By default, all partition tables are hashed, and you can also sign them.
|
By default, all partition tables are hashed, and you can also sign them. The schema for this JSON file is [here](json/schemas/partition-table-schema.json).
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ picotool help partition create
|
$ picotool help partition create
|
||||||
|
@ -694,7 +799,7 @@ OPTIONS:
|
||||||
--family
|
--family
|
||||||
Specify the family if for UF2 file output
|
Specify the family if for UF2 file output
|
||||||
<family_id>
|
<family_id>
|
||||||
family id for UF2 (default absolute)
|
family ID for UF2 (default absolute)
|
||||||
embed partition table into bootloader ELF
|
embed partition table into bootloader ELF
|
||||||
<bootloader>
|
<bootloader>
|
||||||
The file name
|
The file name
|
||||||
|
@ -709,7 +814,7 @@ OPTIONS:
|
||||||
Don't hash the partition table
|
Don't hash the partition table
|
||||||
--singleton
|
--singleton
|
||||||
Singleton partition table
|
Singleton partition table
|
||||||
Errata RP2350-E9 Fix
|
Errata RP2350-E10 Fix
|
||||||
--abs-block
|
--abs-block
|
||||||
Enforce support for an absolute block
|
Enforce support for an absolute block
|
||||||
<abs_block_loc>
|
<abs_block_loc>
|
||||||
|
@ -718,7 +823,7 @@ OPTIONS:
|
||||||
|
|
||||||
## uf2
|
## uf2
|
||||||
|
|
||||||
The `uf2` commands allow for creation of UF2s, and cam provide information when if a UF2 download has failed.
|
The `uf2` commands allow for creation of UF2s, and can provide information if a UF2 download has failed.
|
||||||
|
|
||||||
### convert
|
### convert
|
||||||
|
|
||||||
|
@ -755,8 +860,8 @@ OPTIONS:
|
||||||
Load offset (memory address; default 0x10000000 for BIN file)
|
Load offset (memory address; default 0x10000000 for BIN file)
|
||||||
UF2 Family options
|
UF2 Family options
|
||||||
<family_id>
|
<family_id>
|
||||||
family id for UF2
|
family ID for UF2
|
||||||
Errata RP2350-E9 Fix
|
Errata RP2350-E10 Fix
|
||||||
--abs-block
|
--abs-block
|
||||||
Add an absolute block
|
Add an absolute block
|
||||||
<abs_block_loc>
|
<abs_block_loc>
|
||||||
|
@ -804,7 +909,7 @@ The `otp` commands are for interacting with the RP2350 OTP Memory. They are not
|
||||||
Note that the OTP Memory is One-Time-Programmable, which means that once a bit has been changed from 0 to 1, it cannot be changed back.
|
Note that the OTP Memory is One-Time-Programmable, which means that once a bit has been changed from 0 to 1, it cannot be changed back.
|
||||||
Therefore, caution should be used when using these commands, as they risk bricking your RP2350 device. For example, if you set SECURE_BOOT_ENABLE but don't set a boot key, and disable the PICOBOOT interface, then your device will be unusable.
|
Therefore, caution should be used when using these commands, as they risk bricking your RP2350 device. For example, if you set SECURE_BOOT_ENABLE but don't set a boot key, and disable the PICOBOOT interface, then your device will be unusable.
|
||||||
|
|
||||||
For the `list`, `set`, `get` and `load` commands, you can define your own OTP layout in a JSON file and pass that in with the `-i` argument. These rows will be added to the default rows when parsing.
|
For the `list`, `set`, `get` and `load` commands, you can define your own OTP layout in a JSON file and pass that in with the `-i` argument. These rows will be added to the default rows when parsing. The schema for this JSON file is [here](json/schemas/otp-contents-schema.json)
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ picotool help otp
|
$ picotool help otp
|
||||||
|
@ -812,9 +917,9 @@ OTP:
|
||||||
Commands related to the RP2350 OTP (One-Time-Programmable) Memory
|
Commands related to the RP2350 OTP (One-Time-Programmable) Memory
|
||||||
|
|
||||||
SYNOPSIS:
|
SYNOPSIS:
|
||||||
picotool otp list [-p] [-n] [-i <filename>] [<selector>..]
|
picotool otp list [-p] [-n] [-f] [-i <filename>] [<selector>..]
|
||||||
picotool otp get [-c <copies>] [-r] [-e] [-n] [-i <filename>] [device-selection] [-z] [<selector>..]
|
picotool otp get [-c <copies>] [-r] [-e] [-n] [-i <filename>] [device-selection] [-z] [<selector>..]
|
||||||
picotool otp set [-c <copies>] [-r] [-e] [-i <filename>] [-z] <selector> <value> [device-selection]
|
picotool otp set [-c <copies>] [-r] [-e] [-s] [-i <filename>] [-z] <selector> <value> [device-selection]
|
||||||
picotool otp load [-r] [-e] [-s <row>] [-i <filename>] <filename> [-t <type>] [device-selection]
|
picotool otp load [-r] [-e] [-s <row>] [-i <filename>] <filename> [-t <type>] [device-selection]
|
||||||
picotool otp dump [-r] [-e] [device-selection]
|
picotool otp dump [-r] [-e] [device-selection]
|
||||||
picotool otp permissions <filename> [-t <type>] [--led <pin>] [--hash] [--sign] [<key>] [-t <type>] [device-selection]
|
picotool otp permissions <filename> [-t <type>] [--led <pin>] [--hash] [--sign] [<key>] [-t <type>] [device-selection]
|
||||||
|
@ -837,7 +942,7 @@ These commands will set/get specific rows of OTP. By default, they will write/re
|
||||||
|
|
||||||
### load
|
### load
|
||||||
|
|
||||||
This command allows loading of a range of OTP rows onto the device. The source can be a binary file, or a JSON file such as the one output by `picotool sign`.
|
This command allows loading of a range of OTP rows onto the device. The source can be a binary file, or a JSON file such as the one output by `picotool sign`. The schema for this JSON file is [here](json/schemas/otp-schema.json)
|
||||||
For example, if you wish to sign a binary and then test secure boot with it, you can run the following set of commands:
|
For example, if you wish to sign a binary and then test secure boot with it, you can run the following set of commands:
|
||||||
```text
|
```text
|
||||||
$ picotool sign hello_world.elf hello_world.signed.elf private.pem otp.json
|
$ picotool sign hello_world.elf hello_world.signed.elf private.pem otp.json
|
||||||
|
@ -849,7 +954,7 @@ $ picotool reboot
|
||||||
### white-label
|
### white-label
|
||||||
|
|
||||||
This command allows for OTP white-labelling, which sets the USB configuration used by the device in BOOTSEL mode.
|
This command allows for OTP white-labelling, which sets the USB configuration used by the device in BOOTSEL mode.
|
||||||
This can be configured from a JSON file, an example of which is in [sample-wl.json](sample-wl.json).
|
This can be configured from a JSON file, an example of which is in [sample-wl.json](json/sample-wl.json). The schema for this JSON file is [here](json/schemas/whitelabel-schema.json)
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ picotool help otp white-label
|
$ picotool help otp white-label
|
||||||
|
@ -887,7 +992,7 @@ OPTIONS:
|
||||||
```
|
```
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ picotool otp white-label -s 0x100 ../sample-wl.json
|
$ picotool otp white-label -s 0x100 sample-wl.json
|
||||||
Setting attributes 20e0
|
Setting attributes 20e0
|
||||||
0x2e8b, 0x000e, 0x0215, 0x0c09, 0x1090, 0x200c, 0x2615, 0x20e0, 0x310b, 0x3706, 0x3a04, 0x3c04, 0x3e21, 0x4f15, 0x5a0a, 0x5f0a, 0x007a, 0x00df, 0x6c34, 0xd83c, 0xdf4c, 0x0020, 0x0054, 0x0065, 0x0073, 0x0074, 0x0027, 0x0073,
|
0x2e8b, 0x000e, 0x0215, 0x0c09, 0x1090, 0x200c, 0x2615, 0x20e0, 0x310b, 0x3706, 0x3a04, 0x3c04, 0x3e21, 0x4f15, 0x5a0a, 0x5f0a, 0x007a, 0x00df, 0x6c34, 0xd83c, 0xdf4c, 0x0020, 0x0054, 0x0065, 0x0073, 0x0074, 0x0027, 0x0073,
|
||||||
0x0020, 0x0050, 0x0069, 0x0073, 0x6554, 0x7473, 0x5220, 0x3250, 0x3533, 0x3f30, 0x6f6e, 0x6e74, 0x6365, 0x7365, 0x6173, 0x6972, 0x796c, 0x6e61, 0x6d75, 0x6562, 0x0072, 0x6554, 0x7473, 0x6950, 0x4220, 0x6f6f, 0x0074, 0x6554,
|
0x0020, 0x0050, 0x0069, 0x0073, 0x6554, 0x7473, 0x5220, 0x3250, 0x3533, 0x3f30, 0x6f6e, 0x6e74, 0x6365, 0x7365, 0x6173, 0x6972, 0x796c, 0x6e61, 0x6d75, 0x6562, 0x0072, 0x6554, 0x7473, 0x6950, 0x4220, 0x6f6f, 0x0074, 0x6554,
|
||||||
|
@ -929,7 +1034,7 @@ Device Descriptor:
|
||||||
This command will run a binary on your device in order to set the OTP permissions, as these are not directly accessible from `picotool` on due to the default permissions settings required to fix errata XXX on RP2350.
|
This command will run a binary on your device in order to set the OTP permissions, as these are not directly accessible from `picotool` on due to the default permissions settings required to fix errata XXX on RP2350.
|
||||||
Because it runs a binary, the binary needs to be sign it if secure boot is enabled. The binary will print what it is doing over uart, which
|
Because it runs a binary, the binary needs to be sign it if secure boot is enabled. The binary will print what it is doing over uart, which
|
||||||
can be configured using the UART Configuration arguments. You can define your OTP permissions in a json file, an example of which
|
can be configured using the UART Configuration arguments. You can define your OTP permissions in a json file, an example of which
|
||||||
is in [sample-permissions.json](sample-permissions.json).
|
is in [sample-permissions.json](json/sample-permissions.json). The schema for this JSON file is [here](json/schemas/permissions-schema.json)
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ picotool help otp permissions
|
$ picotool help otp permissions
|
||||||
|
@ -978,7 +1083,7 @@ OPTIONS:
|
||||||
```
|
```
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ picotool otp permissions --sign private.pem --tx 46 ../sample-permissions.json
|
$ picotool otp permissions --sign private.pem --tx 46 sample-permissions.json
|
||||||
Picking file ./xip_ram_perms.elf
|
Picking file ./xip_ram_perms.elf
|
||||||
page10
|
page10
|
||||||
page10 = 0
|
page10 = 0
|
||||||
|
|
|
@ -9,10 +9,10 @@ cc_library(
|
||||||
"library/*.h",
|
"library/*.h",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
includes = ["include"],
|
||||||
linkopts = select({
|
linkopts = select({
|
||||||
"@rules_cc//cc/compiler:msvc-cl": ["-DEFAULTLIB:AdvAPI32.Lib"],
|
"@rules_cc//cc/compiler:msvc-cl": ["-DEFAULTLIB:AdvAPI32.Lib"],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}),
|
}),
|
||||||
includes = ["include"],
|
|
||||||
deps = ["@picotool//lib:mbedtls_config"],
|
deps = ["@picotool//lib:mbedtls_config"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,7 @@ cc_library(
|
||||||
"metadata.h",
|
"metadata.h",
|
||||||
],
|
],
|
||||||
copts = select({
|
copts = select({
|
||||||
|
"@rules_cc//cc/compiler:msvc-cl": ["/std:c++20"],
|
||||||
"@platforms//os:windows": [],
|
"@platforms//os:windows": [],
|
||||||
"//conditions:default": [
|
"//conditions:default": [
|
||||||
"-Wno-unused-variable",
|
"-Wno-unused-variable",
|
||||||
|
|
|
@ -453,6 +453,120 @@ block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::uni
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checksum stuff
|
||||||
|
uint32_t poly8_lookup[256] =
|
||||||
|
{
|
||||||
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||||
|
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
|
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||||
|
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||||
|
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
|
||||||
|
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||||
|
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
|
||||||
|
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||||
|
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
||||||
|
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||||
|
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
|
||||||
|
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||||
|
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
|
||||||
|
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||||
|
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||||
|
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||||
|
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
|
||||||
|
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||||
|
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
|
||||||
|
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||||
|
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||||
|
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||||
|
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
|
||||||
|
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||||
|
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
|
||||||
|
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||||
|
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
||||||
|
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||||
|
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
|
||||||
|
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||||
|
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
|
||||||
|
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||||
|
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
||||||
|
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||||
|
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||||
|
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||||
|
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
|
||||||
|
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||||
|
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
||||||
|
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||||
|
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
|
||||||
|
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||||
|
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
|
||||||
|
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||||
|
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||||
|
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||||
|
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
|
||||||
|
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||||
|
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
|
||||||
|
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||||
|
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
||||||
|
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||||
|
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
|
||||||
|
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||||
|
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
|
||||||
|
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||||
|
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
||||||
|
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||||
|
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
|
||||||
|
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||||
|
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
||||||
|
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||||
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||||
|
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t crc32_byte(const uint8_t *p, uint32_t bytelength)
|
||||||
|
{
|
||||||
|
uint32_t crc = 0xffffffff;
|
||||||
|
while (bytelength-- !=0) crc = poly8_lookup[((uint8_t) crc ^ *(p++))] ^ (crc >> 8);
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rev_8(uint8_t b) {
|
||||||
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||||
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||||
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rev_32(uint32_t b) {
|
||||||
|
uint8_t b0 = rev_8(b >> 24);
|
||||||
|
uint8_t b1 = rev_8(b >> 16);
|
||||||
|
uint8_t b2 = rev_8(b >> 8);
|
||||||
|
uint8_t b3 = rev_8(b);
|
||||||
|
return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc32(const uint8_t *data, size_t len, uint32_t* cs_out) {
|
||||||
|
uint8_t rev_data[252] = {};
|
||||||
|
for (size_t i=0; i < sizeof(rev_data); i++) {
|
||||||
|
rev_data[i] = rev_8(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t crc = crc32_byte(rev_data, sizeof(rev_data));
|
||||||
|
|
||||||
|
crc = rev_32(crc);
|
||||||
|
|
||||||
|
*cs_out = crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t calc_checksum(std::vector<uint8_t> bin) {
|
||||||
|
assert(bin.size() == 252);
|
||||||
|
|
||||||
|
uint32_t checksum = 0;
|
||||||
|
crc32(bin.data(), bin.size(), &checksum);
|
||||||
|
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if HAS_MBEDTLS
|
#if HAS_MBEDTLS
|
||||||
void hash_andor_sign_block(block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, std::vector<uint8_t> to_hash) {
|
void hash_andor_sign_block(block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, std::vector<uint8_t> to_hash) {
|
||||||
std::shared_ptr<hash_def_item> hash_def = std::make_shared<hash_def_item>(PICOBIN_HASH_SHA256);
|
std::shared_ptr<hash_def_item> hash_def = std::make_shared<hash_def_item>(PICOBIN_HASH_SHA256);
|
||||||
|
@ -554,21 +668,29 @@ std::vector<uint8_t> get_lm_hash_data(elf_file *elf, block *new_block, bool clea
|
||||||
for(const auto &entry : load_map->entries) {
|
for(const auto &entry : load_map->entries) {
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
uint32_t current_storage_address = entry.storage_address;
|
uint32_t current_storage_address = entry.storage_address;
|
||||||
while (data.size() < entry.size) {
|
if (current_storage_address == 0) {
|
||||||
auto seg = elf->segment_from_physical_address(current_storage_address);
|
std::copy(
|
||||||
if (seg == nullptr) {
|
(uint8_t*)&entry.size,
|
||||||
fail(ERROR_NOT_POSSIBLE, "The ELF file does not contain the storage address %x", current_storage_address);
|
(uint8_t*)&entry.size + sizeof(entry.size),
|
||||||
|
std::back_inserter(to_hash));
|
||||||
|
DEBUG_LOG("CLEAR %08x + %08x\n", (int)entry.runtime_address, (int)entry.size);
|
||||||
|
} else {
|
||||||
|
while (data.size() < entry.size) {
|
||||||
|
auto seg = elf->segment_from_physical_address(current_storage_address);
|
||||||
|
if (seg == nullptr) {
|
||||||
|
fail(ERROR_NOT_POSSIBLE, "The ELF file does not contain the storage address %x", current_storage_address);
|
||||||
|
}
|
||||||
|
const auto new_data = elf->content(*seg);
|
||||||
|
|
||||||
|
uint32_t offset = current_storage_address - seg->physical_address();
|
||||||
|
|
||||||
|
std::copy(new_data.begin()+offset, new_data.end(), std::back_inserter(data));
|
||||||
|
current_storage_address += new_data.size();
|
||||||
}
|
}
|
||||||
const auto new_data = elf->content(*seg);
|
data.resize(entry.size);
|
||||||
|
std::copy(data.begin(), data.end(), std::back_inserter(to_hash));
|
||||||
uint32_t offset = current_storage_address - seg->physical_address();
|
DEBUG_LOG("HASH %08x + %08x\n", (int)entry.storage_address, (int)data.size());
|
||||||
|
|
||||||
std::copy(new_data.begin()+offset, new_data.end(), std::back_inserter(data));
|
|
||||||
current_storage_address += new_data.size();
|
|
||||||
}
|
}
|
||||||
data.resize(entry.size);
|
|
||||||
std::copy(data.begin(), data.end(), std::back_inserter(to_hash));
|
|
||||||
DEBUG_LOG("HASH %08x + %08x\n", (int)entry.storage_address, (int)data.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,7 +735,7 @@ std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage
|
||||||
(uint8_t*)&entry.size,
|
(uint8_t*)&entry.size,
|
||||||
(uint8_t*)&entry.size + sizeof(entry.size),
|
(uint8_t*)&entry.size + sizeof(entry.size),
|
||||||
std::back_inserter(to_hash));
|
std::back_inserter(to_hash));
|
||||||
DEBUG_LOG("HASH CLEAR %08x + %08x\n", (int)entry.storage_address, (int)entry.size);
|
DEBUG_LOG("CLEAR %08x + %08x\n", (int)entry.runtime_address, (int)entry.size);
|
||||||
} else {
|
} else {
|
||||||
uint32_t rel_addr = entry.storage_address - storage_addr;
|
uint32_t rel_addr = entry.storage_address - storage_addr;
|
||||||
std::copy(
|
std::copy(
|
||||||
|
|
|
@ -34,6 +34,7 @@ std::unique_ptr<block> find_first_block(std::vector<uint8_t> bin, uint32_t stora
|
||||||
std::unique_ptr<block> get_last_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
|
std::unique_ptr<block> get_last_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
|
||||||
std::vector<std::unique_ptr<block>> get_all_blocks(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
|
std::vector<std::unique_ptr<block>> get_all_blocks(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
|
||||||
block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block);
|
block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block);
|
||||||
|
uint32_t calc_checksum(std::vector<uint8_t> bin);
|
||||||
#if HAS_MBEDTLS
|
#if HAS_MBEDTLS
|
||||||
std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
|
std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
|
||||||
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const private_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
|
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const private_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
|
||||||
|
|
|
@ -225,8 +225,55 @@ struct partition_table_item : public single_byte_size_item {
|
||||||
partition_table_item() = default;
|
partition_table_item() = default;
|
||||||
|
|
||||||
explicit partition_table_item(uint32_t unpartitioned_flags, bool singleton) : unpartitioned_flags(unpartitioned_flags), singleton(singleton) {}
|
explicit partition_table_item(uint32_t unpartitioned_flags, bool singleton) : unpartitioned_flags(unpartitioned_flags), singleton(singleton) {}
|
||||||
template <typename I> static std::shared_ptr<item> parse(I it, I end, uint32_t header) {
|
template <typename I> static std::shared_ptr<item> parse(I& it, I end, uint32_t header) {
|
||||||
return nullptr;
|
uint32_t size = decode_size(header);
|
||||||
|
uint8_t singleton_count = header >> 24;
|
||||||
|
bool singleton = singleton_count & 0x80;
|
||||||
|
uint8_t partition_count = singleton_count & 0x0f;
|
||||||
|
uint32_t unpartitioned_flags = *it++;
|
||||||
|
|
||||||
|
auto pt = std::make_shared<partition_table_item>(unpartitioned_flags, singleton);
|
||||||
|
|
||||||
|
std::vector<uint32_t> data;
|
||||||
|
for (unsigned int i=2; i < size; i++) {
|
||||||
|
data.push_back(*it++);
|
||||||
|
}
|
||||||
|
int i=0;
|
||||||
|
while (i < data.size()) {
|
||||||
|
partition new_p;
|
||||||
|
uint32_t permissions_locations = data[i++];
|
||||||
|
new_p.permissions = (permissions_locations & PICOBIN_PARTITION_PERMISSIONS_BITS) >> PICOBIN_PARTITION_PERMISSIONS_LSB;
|
||||||
|
new_p.first_sector = (permissions_locations & PICOBIN_PARTITION_LOCATION_FIRST_SECTOR_BITS) >> PICOBIN_PARTITION_LOCATION_FIRST_SECTOR_LSB;
|
||||||
|
new_p.last_sector = (permissions_locations & PICOBIN_PARTITION_LOCATION_LAST_SECTOR_BITS) >> PICOBIN_PARTITION_LOCATION_LAST_SECTOR_LSB;
|
||||||
|
|
||||||
|
uint32_t permissions_flags = data[i++];
|
||||||
|
uint8_t permissions2 = (permissions_flags & PICOBIN_PARTITION_PERMISSIONS_BITS) >> PICOBIN_PARTITION_PERMISSIONS_LSB;
|
||||||
|
if (new_p.permissions != permissions2) {
|
||||||
|
printf("Permissions mismatch %02x %02x\n", new_p.permissions, permissions2);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
new_p.flags = permissions_flags & (~PICOBIN_PARTITION_PERMISSIONS_BITS);
|
||||||
|
|
||||||
|
if (new_p.flags & PICOBIN_PARTITION_FLAGS_HAS_ID_BITS) {
|
||||||
|
new_p.id = (uint64_t)data[i++] | ((uint64_t)data[i++] << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t num_extra_families = (new_p.flags & PICOBIN_PARTITION_FLAGS_ACCEPTS_NUM_EXTRA_FAMILIES_BITS) >> PICOBIN_PARTITION_FLAGS_ACCEPTS_NUM_EXTRA_FAMILIES_LSB;
|
||||||
|
for (int fam=0; fam < num_extra_families; fam++) {
|
||||||
|
new_p.extra_families.push_back(data[i++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_p.flags & PICOBIN_PARTITION_FLAGS_HAS_NAME_BITS) {
|
||||||
|
auto bytes = words_to_lsb_bytes(data.begin() + i++, data.end());
|
||||||
|
int name_size = bytes[0];
|
||||||
|
// This works neatly - accounts for the size byte at the start
|
||||||
|
i += name_size / 4;
|
||||||
|
new_p.name = std::string((char*)(bytes.data() + 1), name_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pt->partitions.push_back(new_p);
|
||||||
|
}
|
||||||
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> to_words(item_writer_context& ctx) const override {
|
std::vector<uint32_t> to_words(item_writer_context& ctx) const override {
|
||||||
|
@ -367,7 +414,11 @@ struct load_map_item : public item {
|
||||||
if (absolute) {
|
if (absolute) {
|
||||||
rc.push_back(entry.storage_address);
|
rc.push_back(entry.storage_address);
|
||||||
rc.push_back(entry.runtime_address);
|
rc.push_back(entry.runtime_address);
|
||||||
rc.push_back(entry.runtime_address + entry.size);
|
if (entry.storage_address != 0) {
|
||||||
|
rc.push_back(entry.runtime_address + entry.size);
|
||||||
|
} else {
|
||||||
|
rc.push_back(entry.size);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (entry.storage_address != 0) {
|
if (entry.storage_address != 0) {
|
||||||
rc.push_back(entry.storage_address - ctx.base_addr - ctx.word_offset * 4);
|
rc.push_back(entry.storage_address - ctx.base_addr - ctx.word_offset * 4);
|
||||||
|
@ -570,7 +621,7 @@ struct block {
|
||||||
i = image_type_item::parse(it, end, header);
|
i = image_type_item::parse(it, end, header);
|
||||||
break;
|
break;
|
||||||
case PICOBIN_BLOCK_ITEM_PARTITION_TABLE:
|
case PICOBIN_BLOCK_ITEM_PARTITION_TABLE:
|
||||||
i = ignored_item::parse(it, end, header);
|
i = partition_table_item::parse(it, end, header);
|
||||||
break;
|
break;
|
||||||
case PICOBIN_BLOCK_ITEM_1BS_VECTOR_TABLE:
|
case PICOBIN_BLOCK_ITEM_1BS_VECTOR_TABLE:
|
||||||
i = vector_table_item::parse(it, end, header);
|
i = vector_table_item::parse(it, end, header);
|
||||||
|
|
7
cli.h
7
cli.h
|
@ -432,13 +432,18 @@ namespace cli {
|
||||||
base = 2;
|
base = 2;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
lvalue = std::stoll(value, &pos, base);
|
if (std::is_signed<T>()) {
|
||||||
|
lvalue = std::stoll(value, &pos, base);
|
||||||
|
} else {
|
||||||
|
lvalue = std::stoull(value, &pos, base);
|
||||||
|
}
|
||||||
if (pos != value.length()) {
|
if (pos != value.length()) {
|
||||||
return "Garbage after integer value: " + value.substr(pos);
|
return "Garbage after integer value: " + value.substr(pos);
|
||||||
}
|
}
|
||||||
} catch (std::invalid_argument&) {
|
} catch (std::invalid_argument&) {
|
||||||
return value + " is not a valid integer";
|
return value + " is not a valid integer";
|
||||||
} catch (std::out_of_range&) {
|
} catch (std::out_of_range&) {
|
||||||
|
return value + " is out of range";
|
||||||
}
|
}
|
||||||
if (lvalue != (int64_t)lvalue) {
|
if (lvalue != (int64_t)lvalue) {
|
||||||
return value + " is too big";
|
return value + " is too big";
|
||||||
|
|
|
@ -25,7 +25,9 @@ else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||||
|
|
||||||
if (PKG_CONFIG_FOUND)
|
if (PKG_CONFIG_FOUND)
|
||||||
pkg_check_modules(PC_LIBUSB libusb-1.0)
|
pkg_check_modules(PC_LIBUSB libusb-1.0)
|
||||||
else ()
|
endif()
|
||||||
|
|
||||||
|
if (NOT PC_LIBUSB_FOUND)
|
||||||
# As the pkg-config was not found we are probably building under windows.
|
# As the pkg-config was not found we are probably building under windows.
|
||||||
# Determine the architecture of the host, to choose right library
|
# Determine the architecture of the host, to choose right library
|
||||||
if (NOT DEFINED ARCHITECTURE)
|
if (NOT DEFINED ARCHITECTURE)
|
||||||
|
@ -56,5 +58,10 @@ else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR)
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR)
|
||||||
|
|
||||||
|
# Don't use .dll.a libraries, as they require the .dll file to be in the correct location
|
||||||
|
# Replace with .a for static linking instead
|
||||||
|
string(REPLACE ".dll.a" ".a" LIBUSB_LIBRARIES ${LIBUSB_LIBRARIES})
|
||||||
|
|
||||||
MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
|
MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
|
||||||
endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"version": [1, 0],
|
|
||||||
"unpartitioned": {
|
|
||||||
"families": ["absolute"],
|
|
||||||
"permissions": {
|
|
||||||
"secure": "rw",
|
|
||||||
"nonsecure": "rw",
|
|
||||||
"bootloader": "rw"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"partitions": [
|
|
||||||
{
|
|
||||||
"name": "A",
|
|
||||||
"id": 0,
|
|
||||||
"size": "2044K",
|
|
||||||
"families": ["rp2350-arm-s", "rp2350-riscv"],
|
|
||||||
"permissions": {
|
|
||||||
"secure": "rw",
|
|
||||||
"nonsecure": "rw",
|
|
||||||
"bootloader": "rw"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "B",
|
|
||||||
"id": 1,
|
|
||||||
"size": "2044K",
|
|
||||||
"families": ["rp2350-arm-s", "rp2350-riscv"],
|
|
||||||
"permissions": {
|
|
||||||
"secure": "rw",
|
|
||||||
"nonsecure": "rw",
|
|
||||||
"bootloader": "rw"
|
|
||||||
},
|
|
||||||
"link": ["a", 0]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -150,7 +150,10 @@ int rp_check_elf_header(const elf32_header &eh) {
|
||||||
if (eh.common.machine != EM_ARM && eh.common.machine != EM_RISCV) {
|
if (eh.common.machine != EM_ARM && eh.common.machine != EM_RISCV) {
|
||||||
fail(ERROR_FORMAT, "Not an Arm or RISC-V executable");
|
fail(ERROR_FORMAT, "Not an Arm or RISC-V executable");
|
||||||
}
|
}
|
||||||
if (eh.common.abi != 0) {
|
// Accept either ELFOSABI_NONE or ELFOSABI_GNU for EI_OSABI. Compilers may
|
||||||
|
// set the OS/ABI field to ELFOSABI_GNU when they use GNU features, such as
|
||||||
|
// the SHF_GNU_RETAIN section flag, but the binary is still compatible.
|
||||||
|
if (eh.common.abi != 0 /* NONE */ && eh.common.abi != 3 /* GNU */) {
|
||||||
fail(ERROR_INCOMPATIBLE, "Unrecognized ABI");
|
fail(ERROR_INCOMPATIBLE, "Unrecognized ABI");
|
||||||
}
|
}
|
||||||
// todo amy not sure if this should be expected or not - we have HARD float in clang only for now
|
// todo amy not sure if this should be expected or not - we have HARD float in clang only for now
|
||||||
|
@ -227,6 +230,15 @@ void elf_file::flatten(void) {
|
||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
for (const auto &ph : ph_entries) {
|
||||||
|
if (ph.filez) {
|
||||||
|
elf_bytes.resize(std::max(ph.offset + ph.filez, (uint32_t)elf_bytes.size()));
|
||||||
|
memcpy(&elf_bytes[ph.offset], &ph_data[idx][0], ph.filez);
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
if (verbose) printf("Elf file size %zu\n", elf_bytes.size());
|
if (verbose) printf("Elf file size %zu\n", elf_bytes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +274,18 @@ void elf_file::read_sh_data(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void elf_file::read_ph_data(void) {
|
||||||
|
int ph_idx = 0;
|
||||||
|
ph_data.resize(eh.ph_num);
|
||||||
|
for (const auto &ph: ph_entries) {
|
||||||
|
if (ph.filez) {
|
||||||
|
ph_data[ph_idx].resize(ph.filez);
|
||||||
|
read_bytes(ph.offset, ph.filez, &ph_data[ph_idx][0]);
|
||||||
|
}
|
||||||
|
ph_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::string elf_file::section_name(uint32_t sh_name) const {
|
const std::string elf_file::section_name(uint32_t sh_name) const {
|
||||||
if (!eh.sh_str_index || eh.sh_str_index > eh.sh_num)
|
if (!eh.sh_str_index || eh.sh_str_index > eh.sh_num)
|
||||||
return "";
|
return "";
|
||||||
|
@ -369,6 +393,7 @@ int elf_file::read_file(std::shared_ptr<std::iostream> file) {
|
||||||
read_sh();
|
read_sh();
|
||||||
}
|
}
|
||||||
read_sh_data();
|
read_sh_data();
|
||||||
|
read_ph_data();
|
||||||
}
|
}
|
||||||
catch (const std::ios_base::failure &e) {
|
catch (const std::ios_base::failure &e) {
|
||||||
std::cerr << "Failed to read elf file" << std::endl;
|
std::cerr << "Failed to read elf file" << std::endl;
|
||||||
|
@ -415,6 +440,7 @@ void elf_file::content(const elf32_ph_entry &ph, const std::vector<uint8_t> &con
|
||||||
if (verbose) printf("Update segment content offset %x content size %zx physical size %x\n", ph.offset, content.size(), ph.filez);
|
if (verbose) printf("Update segment content offset %x content size %zx physical size %x\n", ph.offset, content.size(), ph.filez);
|
||||||
memcpy(&elf_bytes[ph.offset], &content[0], std::min(content.size(), (size_t) ph.filez));
|
memcpy(&elf_bytes[ph.offset], &content[0], std::min(content.size(), (size_t) ph.filez));
|
||||||
read_sh_data(); // Extract the sections after modifying the content
|
read_sh_data(); // Extract the sections after modifying the content
|
||||||
|
read_ph_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void elf_file::content(const elf32_sh_entry &sh, const std::vector<uint8_t> &content) {
|
void elf_file::content(const elf32_sh_entry &sh, const std::vector<uint8_t> &content) {
|
||||||
|
@ -423,6 +449,7 @@ void elf_file::content(const elf32_sh_entry &sh, const std::vector<uint8_t> &con
|
||||||
if (verbose) printf("Update section content offset %x content size %zx section size %x\n", sh.offset, content.size(), sh.size);
|
if (verbose) printf("Update section content offset %x content size %zx section size %x\n", sh.offset, content.size(), sh.size);
|
||||||
memcpy(&elf_bytes[sh.offset], &content[0], std::min(content.size(), (size_t) sh.size));
|
memcpy(&elf_bytes[sh.offset], &content[0], std::min(content.size(), (size_t) sh.size));
|
||||||
read_sh_data(); // Extract the sections after modifying the content
|
read_sh_data(); // Extract the sections after modifying the content
|
||||||
|
read_ph_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
const elf32_ph_entry* elf_file::segment_from_physical_address(uint32_t paddr) {
|
const elf32_ph_entry* elf_file::segment_from_physical_address(uint32_t paddr) {
|
||||||
|
@ -500,6 +527,7 @@ const elf32_ph_entry& elf_file::append_segment(uint32_t vaddr, uint32_t paddr, u
|
||||||
sh_entries.push_back(sh);
|
sh_entries.push_back(sh);
|
||||||
sh_data.push_back(std::vector<uint8_t>(size));
|
sh_data.push_back(std::vector<uint8_t>(size));
|
||||||
ph_entries.back().offset = sh.offset;
|
ph_entries.back().offset = sh.offset;
|
||||||
|
ph_data.push_back(std::vector<uint8_t>(size));
|
||||||
|
|
||||||
eh.sh_offset = sh.offset + sh.size;
|
eh.sh_offset = sh.offset + sh.size;
|
||||||
eh.sh_num++;
|
eh.sh_num++;
|
||||||
|
|
|
@ -55,6 +55,7 @@ private:
|
||||||
void read_ph(void);
|
void read_ph(void);
|
||||||
void read_sh(void);
|
void read_sh(void);
|
||||||
void read_sh_data(void);
|
void read_sh_data(void);
|
||||||
|
void read_ph_data(void);
|
||||||
void read_bytes(unsigned offset, unsigned length, void *dest);
|
void read_bytes(unsigned offset, unsigned length, void *dest);
|
||||||
uint32_t append_section_name(const std::string &sh_name_str);
|
uint32_t append_section_name(const std::string &sh_name_str);
|
||||||
void flatten(void);
|
void flatten(void);
|
||||||
|
@ -65,6 +66,7 @@ private:
|
||||||
std::vector<elf32_ph_entry> ph_entries;
|
std::vector<elf32_ph_entry> ph_entries;
|
||||||
std::vector<elf32_sh_entry> sh_entries;
|
std::vector<elf32_sh_entry> sh_entries;
|
||||||
std::vector<std::vector<uint8_t>> sh_data;
|
std::vector<std::vector<uint8_t>> sh_data;
|
||||||
|
std::vector<std::vector<uint8_t>> ph_data;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
};
|
};
|
||||||
int rp_check_elf_header(const elf32_header &eh);
|
int rp_check_elf_header(const elf32_header &eh);
|
||||||
|
|
|
@ -43,27 +43,22 @@
|
||||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||||
# define __PDP_ENDIAN PDP_ENDIAN
|
# define __PDP_ENDIAN PDP_ENDIAN
|
||||||
|
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
|
||||||
# include <endian.h>
|
|
||||||
|
|
||||||
# define __BYTE_ORDER BYTE_ORDER
|
|
||||||
# define __BIG_ENDIAN BIG_ENDIAN
|
|
||||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
|
||||||
# define __PDP_ENDIAN PDP_ENDIAN
|
|
||||||
|
|
||||||
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
|
||||||
|
|
||||||
# include <sys/endian.h>
|
# include <sys/endian.h>
|
||||||
|
|
||||||
|
#ifndef be16toh
|
||||||
# define be16toh(x) betoh16(x)
|
# define be16toh(x) betoh16(x)
|
||||||
|
#endif
|
||||||
|
#ifndef le16toh
|
||||||
# define le16toh(x) letoh16(x)
|
# define le16toh(x) letoh16(x)
|
||||||
|
#endif
|
||||||
|
#ifndef be32toh
|
||||||
# define be32toh(x) betoh32(x)
|
# define be32toh(x) betoh32(x)
|
||||||
|
#endif
|
||||||
|
#ifndef le32toh
|
||||||
# define le32toh(x) letoh32(x)
|
# define le32toh(x) letoh32(x)
|
||||||
|
#endif
|
||||||
# define be64toh(x) betoh64(x)
|
|
||||||
# define le64toh(x) letoh64(x)
|
|
||||||
|
|
||||||
#elif defined(__WINDOWS__)
|
#elif defined(__WINDOWS__)
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ uf2_block gen_abs_block(uint32_t abs_block_loc) {
|
||||||
uf2_block block;
|
uf2_block block;
|
||||||
block.magic_start0 = UF2_MAGIC_START0;
|
block.magic_start0 = UF2_MAGIC_START0;
|
||||||
block.magic_start1 = UF2_MAGIC_START1;
|
block.magic_start1 = UF2_MAGIC_START1;
|
||||||
block.flags = UF2_FLAG_FAMILY_ID_PRESENT;
|
block.flags = UF2_FLAG_FAMILY_ID_PRESENT | UF2_FLAG_EXTENSION_FLAGS_PRESENT;
|
||||||
block.payload_size = UF2_PAGE_SIZE;
|
block.payload_size = UF2_PAGE_SIZE;
|
||||||
block.num_blocks = 2;
|
block.num_blocks = 2;
|
||||||
block.file_size = ABSOLUTE_FAMILY_ID;
|
block.file_size = ABSOLUTE_FAMILY_ID;
|
||||||
|
@ -138,6 +138,7 @@ uf2_block gen_abs_block(uint32_t abs_block_loc) {
|
||||||
block.block_no = 0;
|
block.block_no = 0;
|
||||||
memset(block.data, 0, sizeof(block.data));
|
memset(block.data, 0, sizeof(block.data));
|
||||||
memset(block.data, 0xef, UF2_PAGE_SIZE);
|
memset(block.data, 0xef, UF2_PAGE_SIZE);
|
||||||
|
*(uint32_t*)&(block.data[UF2_PAGE_SIZE]) = UF2_EXTENSION_RP2_IGNORE_BLOCK;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,21 +146,26 @@ bool check_abs_block(uf2_block block) {
|
||||||
return std::all_of(block.data, block.data + UF2_PAGE_SIZE, [](uint8_t i) { return i == 0xef; }) &&
|
return std::all_of(block.data, block.data + UF2_PAGE_SIZE, [](uint8_t i) { return i == 0xef; }) &&
|
||||||
block.magic_start0 == UF2_MAGIC_START0 &&
|
block.magic_start0 == UF2_MAGIC_START0 &&
|
||||||
block.magic_start1 == UF2_MAGIC_START1 &&
|
block.magic_start1 == UF2_MAGIC_START1 &&
|
||||||
block.flags == UF2_FLAG_FAMILY_ID_PRESENT &&
|
(block.flags & ~UF2_FLAG_EXTENSION_FLAGS_PRESENT) == UF2_FLAG_FAMILY_ID_PRESENT &&
|
||||||
block.payload_size == UF2_PAGE_SIZE &&
|
block.payload_size == UF2_PAGE_SIZE &&
|
||||||
block.num_blocks == 2 &&
|
block.num_blocks == 2 &&
|
||||||
block.file_size == ABSOLUTE_FAMILY_ID &&
|
block.file_size == ABSOLUTE_FAMILY_ID &&
|
||||||
block.magic_end == UF2_MAGIC_END &&
|
block.magic_end == UF2_MAGIC_END &&
|
||||||
block.block_no == 0;
|
block.block_no == 0 &&
|
||||||
|
!(block.flags & UF2_FLAG_EXTENSION_FLAGS_PRESENT && *(uint32_t*)&(block.data[UF2_PAGE_SIZE]) != UF2_EXTENSION_RP2_IGNORE_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages2uf2(std::map<uint32_t, std::vector<page_fragment>>& pages, std::shared_ptr<std::iostream> in, std::shared_ptr<std::iostream> out, uint32_t family_id, uint32_t abs_block_loc=0) {
|
int pages2uf2(std::map<uint32_t, std::vector<page_fragment>>& pages, std::shared_ptr<std::iostream> in, std::shared_ptr<std::iostream> out, uint32_t family_id, uint32_t abs_block_loc=0) {
|
||||||
// RP2350-E9: add absolute block to start, targeting end of flash by default
|
// RP2350-E10: add absolute block to start of flash UF2s, targeting end of flash by default
|
||||||
if (family_id != ABSOLUTE_FAMILY_ID && family_id != RP2040_FAMILY_ID && abs_block_loc) {
|
if (family_id != ABSOLUTE_FAMILY_ID && family_id != RP2040_FAMILY_ID && abs_block_loc) {
|
||||||
uf2_block block = gen_abs_block(abs_block_loc);
|
uint32_t base_addr = pages.begin()->first;
|
||||||
out->write((char*)&block, sizeof(uf2_block));
|
address_ranges flash_range = rp2350_address_ranges_flash;
|
||||||
if (out->fail()) {
|
if (is_address_initialized(flash_range, base_addr)) {
|
||||||
fail_write_error();
|
uf2_block block = gen_abs_block(abs_block_loc);
|
||||||
|
out->write((char*)&block, sizeof(uf2_block));
|
||||||
|
if (out->fail()) {
|
||||||
|
fail_write_error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uf2_block block;
|
uf2_block block;
|
||||||
|
|
37
json/default-pt.json
Normal file
37
json/default-pt.json
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/raspberrypi/picotool/develop/json/schemas/partition-table-schema.json",
|
||||||
|
"version": [1, 0],
|
||||||
|
"unpartitioned": {
|
||||||
|
"families": ["absolute"],
|
||||||
|
"permissions": {
|
||||||
|
"secure": "rw",
|
||||||
|
"nonsecure": "rw",
|
||||||
|
"bootloader": "rw"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"partitions": [
|
||||||
|
{
|
||||||
|
"name": "A",
|
||||||
|
"id": 0,
|
||||||
|
"size": "2044K",
|
||||||
|
"families": ["rp2350-arm-s", "rp2350-riscv"],
|
||||||
|
"permissions": {
|
||||||
|
"secure": "rw",
|
||||||
|
"nonsecure": "rw",
|
||||||
|
"bootloader": "rw"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "B",
|
||||||
|
"id": 1,
|
||||||
|
"size": "2044K",
|
||||||
|
"families": ["rp2350-arm-s", "rp2350-riscv"],
|
||||||
|
"permissions": {
|
||||||
|
"secure": "rw",
|
||||||
|
"nonsecure": "rw",
|
||||||
|
"bootloader": "rw"
|
||||||
|
},
|
||||||
|
"link": ["a", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/raspberrypi/picotool/develop/json/schemas/permissions-schema.json",
|
||||||
"10": {
|
"10": {
|
||||||
"no_key_state": 0,
|
"no_key_state": 0,
|
||||||
"key_r": 0,
|
"key_r": 0,
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/raspberrypi/picotool/develop/json/schemas/whitelabel-schema.json",
|
||||||
"device": {
|
"device": {
|
||||||
"vid": "0x2e8b",
|
"vid": "0x2e8b",
|
||||||
"pid": "0x000e",
|
"pid": "0x000e",
|
77
json/schemas/otp-contents-schema.json
Normal file
77
json/schemas/otp-contents-schema.json
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "OTP Contents",
|
||||||
|
"description": "Defined contents of the RP-series device OTP",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"description": "OTP Row",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"crit": {
|
||||||
|
"description": "Critical Row (use three-of-eight vote encoding)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"description": "Row Description",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ecc": {
|
||||||
|
"description": "ECC Row",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"description": "Fields within row",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"description": "Field Description",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"mask": {
|
||||||
|
"description": "Field Bit Mask",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Field Name",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["description", "mask", "name"],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mask": {
|
||||||
|
"description": "Row Bit Mask",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Row Name",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"redundancy": {
|
||||||
|
"description": "Number of redundant rows",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"row": {
|
||||||
|
"description": "OTP Row",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"seq_index": {
|
||||||
|
"description": "Sequence Index",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"seq_length": {
|
||||||
|
"description": "Sequence Length",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"seq_prefix": {
|
||||||
|
"description": "Sequence Prefix",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["crit", "description"],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
50
json/schemas/otp-schema.json
Normal file
50
json/schemas/otp-schema.json
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "OTP Settings",
|
||||||
|
"description": "OTP Settings",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {"$schema": {}},
|
||||||
|
"patternProperties": {
|
||||||
|
"^\\d{1,2}:\\d{1,2}$": {
|
||||||
|
"description": "Generic OTP Row",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"ecc": {
|
||||||
|
"description": "Protect with ECC",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"description": "Value to write",
|
||||||
|
"type": ["array", "string", "integer"],
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{1,6}$",
|
||||||
|
"items": {
|
||||||
|
"description": "Data Byte",
|
||||||
|
"type": ["string", "integer"],
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{1,2}$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["ecc", "value"]
|
||||||
|
},
|
||||||
|
"^[\\d\\w_]+$": {
|
||||||
|
"description": "Defined OTP Row",
|
||||||
|
"type": ["object", "array", "string", "integer"],
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{1,6}$",
|
||||||
|
"items": {
|
||||||
|
"description": "Data Byte",
|
||||||
|
"type": ["string", "integer"],
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{1,2}$"
|
||||||
|
},
|
||||||
|
"patternProperties": {
|
||||||
|
"^[\\d\\w_]+$": {
|
||||||
|
"description": "OTP Field",
|
||||||
|
"type": ["string", "integer"],
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{1,6}$"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
158
json/schemas/partition-table-schema.json
Normal file
158
json/schemas/partition-table-schema.json
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "Partition Table",
|
||||||
|
"description": "Layout of the partition table",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"$schema": {},
|
||||||
|
"version": {
|
||||||
|
"description": "Partition Table Version",
|
||||||
|
"type": "array",
|
||||||
|
"prefixItems": [
|
||||||
|
{
|
||||||
|
"description": "Major Version",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Minor Version",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unpartitioned": {
|
||||||
|
"description": "Unpartitioned space UF2 families and permissions",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"families": {
|
||||||
|
"description": "UF2 families accepted",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"enum": [
|
||||||
|
"data",
|
||||||
|
"absolute",
|
||||||
|
"rp2040",
|
||||||
|
"rp2350-arm-s",
|
||||||
|
"rp2350-arm-ns",
|
||||||
|
"rp2350-riscv"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"permissions": {"$ref": "#/$defs/permissions"}
|
||||||
|
},
|
||||||
|
"required": ["permissions", "families"],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"partitions": {
|
||||||
|
"description": "Partitions",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "Partition Name",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "Partition ID",
|
||||||
|
"type": ["integer", "string"],
|
||||||
|
"minimum": 0,
|
||||||
|
"exclusiveMaximum": 18446744073709551616,
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{1,16}$",
|
||||||
|
"examples": [
|
||||||
|
"0xDED3FFFF01234567",
|
||||||
|
29,
|
||||||
|
"0xdeadbeef"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"description": "Partition Start",
|
||||||
|
"type": ["integer", "string"],
|
||||||
|
"minimum": 0,
|
||||||
|
"pattern": "^\\d+(k|K)$"
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"description": "Partition Size",
|
||||||
|
"type": ["integer", "string"],
|
||||||
|
"minimum": 0,
|
||||||
|
"pattern": "^\\d+(k|K)$"
|
||||||
|
},
|
||||||
|
"families": {
|
||||||
|
"description": "UF2 families accepted",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^data|absolute|rp2040|rp2350-arm-s|rp2350-arm-ns|rp2350-riscv|0x[0-9a-fA-F]{1,8}$",
|
||||||
|
"examples": [
|
||||||
|
"data",
|
||||||
|
"absolute",
|
||||||
|
"rp2040",
|
||||||
|
"rp2350-arm-s",
|
||||||
|
"rp2350-arm-ns",
|
||||||
|
"rp2350-riscv"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"permissions": {"$ref": "#/$defs/permissions"},
|
||||||
|
"link": {
|
||||||
|
"type": "array",
|
||||||
|
"prefixItems": [
|
||||||
|
{
|
||||||
|
"description": "Link Type",
|
||||||
|
"enum": ["a", "owner" , "none"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Link Value",
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"no_reboot_on_uf2_download": {
|
||||||
|
"description": "Don't reboot after UF2 is downloaded",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"ab_non_bootable_owner_affinity": {
|
||||||
|
"description": "Pick the non-bootable owner instead",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"ignored_during_riscv_boot": {
|
||||||
|
"description": "Ignore this partition during Risc-V boot",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"ignored_during_arm_boot": {
|
||||||
|
"description": "Ignore this partition during Arm boot",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["size", "permissions", "families"],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["unpartitioned", "partitions"],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"$defs": {
|
||||||
|
"permissions": {
|
||||||
|
"description": "Permissions",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"secure": {
|
||||||
|
"description": "Secure Permissions",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(r|w){0,2}$"
|
||||||
|
},
|
||||||
|
"nonsecure": {
|
||||||
|
"description": "Non-Secure Permissions",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(r|w){0,2}$"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"description": "Bootloader Permissions",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(r|w){0,2}$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
json/schemas/permissions-schema.json
Normal file
52
json/schemas/permissions-schema.json
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "OTP Permissions",
|
||||||
|
"description": "Setup of OTP page permissions",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {"$schema": {}},
|
||||||
|
"patternProperties": {
|
||||||
|
"^[0-6][0-9]$": {
|
||||||
|
"description": "OTP Page Permissions",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"no_key_state": {
|
||||||
|
"description": "State when at least one key is registered for this page and no matching key has been entered: 0 -> read_only, 1 -> inaccessible",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 1
|
||||||
|
},
|
||||||
|
"key_r": {
|
||||||
|
"description": "Index 1-6 of a hardware key which must be entered to grant read access, or 0 if no such key is required",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 6
|
||||||
|
},
|
||||||
|
"key_w": {
|
||||||
|
"description": "Index 1-6 of a hardware key which must be entered to grant write access, or 0 if no such key is required",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 6
|
||||||
|
},
|
||||||
|
"lock_bl": {
|
||||||
|
"description": "Dummy lock bits reserved for bootloaders (including the RP2350 USB bootloader) to store their own OTP access permissions: 0 -> read_write, 1 -> read_only, 2 -> Do not use (behaves the same as incaccessible), 3 -> inaccessible",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 3
|
||||||
|
},
|
||||||
|
"lock_ns": {
|
||||||
|
"description": "Lock state for Non-secure accesses to this page: 0 -> read_write, 1 -> read_only, 2 -> Do not use (behaves the same as incaccessible), 3 -> inaccessible",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 3
|
||||||
|
},
|
||||||
|
"lock_s": {
|
||||||
|
"description": "Lock state for Secure accesses to this page: 0 -> read_write, 1 -> read_only, 2 -> Do not use (behaves the same as incaccessible), 3 -> inaccessible",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
124
json/schemas/whitelabel-schema.json
Normal file
124
json/schemas/whitelabel-schema.json
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "White Labelling",
|
||||||
|
"description": "White Labelling Configuration, see section 5.7 in the RP2350 datasheet for more details",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"$schema": {},
|
||||||
|
"device": {
|
||||||
|
"description": "Device Properties",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"vid": {
|
||||||
|
"description": "Vendor ID",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{4}$"
|
||||||
|
},
|
||||||
|
"pid": {
|
||||||
|
"description": "Product ID",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{4}$"
|
||||||
|
},
|
||||||
|
"bcd": {
|
||||||
|
"description": "Device Revision",
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 99
|
||||||
|
},
|
||||||
|
"lang_id": {
|
||||||
|
"description": "Language ID",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{4}$"
|
||||||
|
},
|
||||||
|
"manufacturer": {
|
||||||
|
"description": "Manufacturer Name (can contain unicode)",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 30
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"description": "Product Name (can contain unicode)",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 30
|
||||||
|
},
|
||||||
|
"serial_number": {
|
||||||
|
"description": "Serial Number (can contain unicode)",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 30
|
||||||
|
},
|
||||||
|
"max_power": {
|
||||||
|
"description": "Max power consumption, in 2mA units",
|
||||||
|
"type": ["integer", "string"],
|
||||||
|
"maximum": 255,
|
||||||
|
"pattern": "^0x[0-9a-fA-F]{1,2}$"
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"description": "Device attributes: bit 7 must be 1, bit 6 is self-powered, bit 5 is remote wakeup, bits 0-4 must be 0",
|
||||||
|
"type": ["integer", "string"],
|
||||||
|
"minimum": 128,
|
||||||
|
"maximum": 224,
|
||||||
|
"pattern": "^0x[8aceACE]{1}0$"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependentRequired": {
|
||||||
|
"max_power": ["attributes"],
|
||||||
|
"attributes": ["max_power"]
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"scsi": {
|
||||||
|
"description": "SCSI Inquiry Values",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"vendor": {
|
||||||
|
"description": "SCSI Vendor",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 8
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"description": "SCSI Product",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 16
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"description": "SCSI Version",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"description": "MSD Volume Configuration",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"label": {
|
||||||
|
"description": "Volume Label",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 11
|
||||||
|
},
|
||||||
|
"redirect_url": {
|
||||||
|
"description": "INDEX.HTM Redirect URL",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 127
|
||||||
|
},
|
||||||
|
"redirect_name": {
|
||||||
|
"description": "INDEX.HTM Redirect Name",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 127
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"description": "INFO_UF2.TXT Model Name",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 127
|
||||||
|
},
|
||||||
|
"board_id": {
|
||||||
|
"description": "INFO_UF2.TXT Board ID",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 127
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "pre_generated_otp_header",
|
||||||
|
includes = ["."],
|
||||||
|
hdrs = ["rp2350.json.h"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "otp_header_parser",
|
name = "otp_header_parser",
|
||||||
srcs = ["otp_header_parse.cpp"],
|
srcs = ["otp_header_parse.cpp"],
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
// missing __builtins on windows
|
// missing __builtins on windows
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
# include <intrin.h>
|
# include <intrin.h>
|
||||||
# define __builtin_popcount __popcnt
|
# define __builtin_popcount __popcnt
|
||||||
static __forceinline int __builtin_ctz(unsigned x) {
|
static __forceinline int __builtin_ctz(unsigned x) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ cc_library(
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"picoboot_connection.h",
|
"picoboot_connection.h",
|
||||||
"picoboot_connection_cxx.h",
|
"picoboot_connection_cxx.h",
|
||||||
|
"//:flash_id_bin.h",
|
||||||
],
|
],
|
||||||
defines = ["HAS_LIBUSB=1"], # Bazel build always has libusb.
|
defines = ["HAS_LIBUSB=1"], # Bazel build always has libusb.
|
||||||
includes = ["."],
|
includes = ["."],
|
||||||
|
@ -16,6 +17,8 @@ cc_library(
|
||||||
"//elf",
|
"//elf",
|
||||||
"@libusb",
|
"@libusb",
|
||||||
"@pico-sdk//src/common/boot_picoboot_headers",
|
"@pico-sdk//src/common/boot_picoboot_headers",
|
||||||
|
"@pico-sdk//src/rp2_common/boot_bootrom_headers",
|
||||||
"@pico-sdk//src/rp2_common/pico_bootrom:pico_bootrom_headers",
|
"@pico-sdk//src/rp2_common/pico_bootrom:pico_bootrom_headers",
|
||||||
|
"@pico-sdk//src/rp2_common/pico_stdio_usb:reset_interface_headers",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "picoboot_connection.h"
|
#include "picoboot_connection.h"
|
||||||
#include "pico/bootrom_constants.h"
|
#include "boot/bootrom_constants.h"
|
||||||
|
#include "pico/stdio_usb/reset_interface.h"
|
||||||
|
|
||||||
#if ENABLE_DEBUG_LOG
|
#if ENABLE_DEBUG_LOG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -87,7 +88,11 @@ enum picoboot_device_result picoboot_open_device(libusb_device *device, libusb_d
|
||||||
case PRODUCT_ID_PICOPROBE:
|
case PRODUCT_ID_PICOPROBE:
|
||||||
return dr_vidpid_picoprobe;
|
return dr_vidpid_picoprobe;
|
||||||
case PRODUCT_ID_RP2040_STDIO_USB:
|
case PRODUCT_ID_RP2040_STDIO_USB:
|
||||||
|
*model = rp2040;
|
||||||
|
res = dr_vidpid_stdio_usb;
|
||||||
|
break;
|
||||||
case PRODUCT_ID_STDIO_USB:
|
case PRODUCT_ID_STDIO_USB:
|
||||||
|
*model = rp2350;
|
||||||
res = dr_vidpid_stdio_usb;
|
res = dr_vidpid_stdio_usb;
|
||||||
break;
|
break;
|
||||||
case PRODUCT_ID_RP2040_USBBOOT:
|
case PRODUCT_ID_RP2040_USBBOOT:
|
||||||
|
@ -115,15 +120,15 @@ enum picoboot_device_result picoboot_open_device(libusb_device *device, libusb_d
|
||||||
if (vid == 0 || strlen(ser) != 0) {
|
if (vid == 0 || strlen(ser) != 0) {
|
||||||
// didn't check vid or ser, so treat as unknown
|
// didn't check vid or ser, so treat as unknown
|
||||||
return dr_vidpid_unknown;
|
return dr_vidpid_unknown;
|
||||||
} else if (res != dr_vidpid_unknown) {
|
} else if (res == dr_vidpid_stdio_usb) {
|
||||||
return res;
|
return dr_vidpid_stdio_usb_cant_connect;
|
||||||
} else {
|
} else {
|
||||||
return dr_vidpid_bootrom_cant_connect;
|
return dr_vidpid_bootrom_cant_connect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == dr_vidpid_stdio_usb) {
|
if (!ret && res == dr_vidpid_stdio_usb) {
|
||||||
if (strlen(ser) != 0) {
|
if (strlen(ser) != 0) {
|
||||||
// Check USB serial number
|
// Check USB serial number
|
||||||
char ser_str[128];
|
char ser_str[128];
|
||||||
|
@ -138,6 +143,17 @@ enum picoboot_device_result picoboot_open_device(libusb_device *device, libusb_d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Runtime reset interface with thirdparty VID
|
||||||
|
if (!ret) {
|
||||||
|
for (int i = 0; i < config->bNumInterfaces; i++) {
|
||||||
|
if (config->interface[i].altsetting[0].bInterfaceClass == 0xff &&
|
||||||
|
config->interface[i].altsetting[0].bInterfaceSubClass == RESET_INTERFACE_SUBCLASS &&
|
||||||
|
config->interface[i].altsetting[0].bInterfaceProtocol == RESET_INTERFACE_PROTOCOL) {
|
||||||
|
return dr_vidpid_stdio_usb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (config->bNumInterfaces == 1) {
|
if (config->bNumInterfaces == 1) {
|
||||||
interface = 0;
|
interface = 0;
|
||||||
|
@ -579,36 +595,71 @@ static const uint8_t picoboot_peek_cmd[] = {
|
||||||
};
|
};
|
||||||
#define PICOBOOT_PEEK_CMD_PROG_SIZE (size_t)(12 + 4)
|
#define PICOBOOT_PEEK_CMD_PROG_SIZE (size_t)(12 + 4)
|
||||||
|
|
||||||
// todo - compile this - currently taken from github PR #86
|
// 00000000 <flash_get_unique_id_raw>:
|
||||||
static const size_t picoboot_flash_id_cmd_len = 152;
|
// 0: a002 add r0, pc, #8 @ (adr r0, c <FLASH_RUID_DATA_BYTES+0x4>)
|
||||||
static const uint8_t picoboot_flash_id_cmd[] = {
|
// 2: a106 add r1, pc, #24 @ (adr r1, 1c <FLASH_RUID_TOTAL_BYTES+0xf>)
|
||||||
// void flash_get_unique_id(void)
|
// 4: 4a00 ldr r2, [pc, #0] @ (8 <FLASH_RUID_DATA_BYTES>)
|
||||||
0x02, 0xa0, 0x06, 0xa1, 0x00, 0x4a, 0x11, 0xe0,
|
// 6: e011 b.n 2c <flash_do_cmd>
|
||||||
// int buflen
|
// 8: 0000000d .word 0x0000000d
|
||||||
0x0d, 0x00, 0x00, 0x00,
|
// c: 0000004b .word 0x0000004b
|
||||||
// char txbuf[13]
|
// ...
|
||||||
0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
//
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
// 0000002c <flash_do_cmd>:
|
||||||
// char rxbuf[13]
|
// 2c: 2380 movs r3, #128 @ 0x80
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
// 2e: b5f0 push {r4, r5, r6, r7, lr}
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
// 30: 4e17 ldr r6, [pc, #92] @ (90 <FLASH_RUID_CMD+0x45>)
|
||||||
// void flash_do_cmd(txbuf, rxbuf, buflen)
|
// 32: 009b lsls r3, r3, #2
|
||||||
0x80, 0x23, 0xf0, 0xb5, 0x17, 0x4e, 0x9b, 0x00,
|
// 34: 6834 ldr r4, [r6, #0]
|
||||||
0x34, 0x68, 0x63, 0x40, 0xc0, 0x24, 0xa4, 0x00,
|
// 36: 4063 eors r3, r4
|
||||||
0x23, 0x40, 0x15, 0x4c, 0x23, 0x60, 0xc0, 0x24,
|
// 38: 24c0 movs r4, #192 @ 0xc0
|
||||||
0x13, 0x00, 0x64, 0x05, 0x17, 0x00, 0x1f, 0x43,
|
// 3a: 00a4 lsls r4, r4, #2
|
||||||
0x06, 0xd1, 0xc0, 0x23, 0x32, 0x68, 0x9b, 0x00,
|
// 3c: 4023 ands r3, r4
|
||||||
0x93, 0x43, 0x0f, 0x4a, 0x13, 0x60, 0xf0, 0xbd,
|
// 3e: 4c15 ldr r4, [pc, #84] @ (94 <FLASH_RUID_CMD+0x49>)
|
||||||
0x08, 0x25, 0xa7, 0x6a, 0x3d, 0x40, 0xac, 0x46,
|
// 40: 6023 str r3, [r4, #0]
|
||||||
0x02, 0x25, 0x2f, 0x42, 0x08, 0xd0, 0x00, 0x2a,
|
// 42: 24c0 movs r4, #192 @ 0xc0
|
||||||
0x06, 0xd0, 0x9f, 0x1a, 0x0d, 0x2f, 0x03, 0xd8,
|
// 44: 0013 movs r3, r2
|
||||||
0x07, 0x78, 0x01, 0x3a, 0x27, 0x66, 0x01, 0x30,
|
// 46: 0564 lsls r4, r4, #21
|
||||||
0x65, 0x46, 0x00, 0x2d, 0xe2, 0xd0, 0x00, 0x2b,
|
// 48: 0017 movs r7, r2
|
||||||
0xe0, 0xd0, 0x27, 0x6e, 0x01, 0x3b, 0x0f, 0x70,
|
// 4a: 431f orrs r7, r3
|
||||||
0x01, 0x31, 0xdb, 0xe7, 0x0c, 0x80, 0x01, 0x40,
|
// 4c: d106 bne.n 5c <FLASH_RUID_CMD+0x11>
|
||||||
0x0c, 0x90, 0x01, 0x40,
|
// 4e: 23c0 movs r3, #192 @ 0xc0
|
||||||
};
|
// 50: 6832 ldr r2, [r6, #0]
|
||||||
#define PICOBOOT_FLASH_ID_CMD_PROG_SIZE (size_t)(152)
|
// 52: 009b lsls r3, r3, #2
|
||||||
|
// 54: 4393 bics r3, r2
|
||||||
|
// 56: 4a0f ldr r2, [pc, #60] @ (94 <FLASH_RUID_CMD+0x49>)
|
||||||
|
// 58: 6013 str r3, [r2, #0]
|
||||||
|
// 5a: bdf0 pop {r4, r5, r6, r7, pc}
|
||||||
|
// 5c: 2508 movs r5, #8
|
||||||
|
// 5e: 6aa7 ldr r7, [r4, #40] @ 0x28
|
||||||
|
// 60: 403d ands r5, r7
|
||||||
|
// 62: 46ac mov ip, r5
|
||||||
|
// 64: 2502 movs r5, #2
|
||||||
|
// 66: 422f tst r7, r5
|
||||||
|
// 68: d008 beq.n 7c <FLASH_RUID_CMD+0x31>
|
||||||
|
// 6a: 2a00 cmp r2, #0
|
||||||
|
// 6c: d006 beq.n 7c <FLASH_RUID_CMD+0x31>
|
||||||
|
// 6e: 1a9f subs r7, r3, r2
|
||||||
|
// 70: 2f0d cmp r7, #13
|
||||||
|
// 72: d803 bhi.n 7c <FLASH_RUID_CMD+0x31>
|
||||||
|
// 74: 7807 ldrb r7, [r0, #0]
|
||||||
|
// 76: 3a01 subs r2, #1
|
||||||
|
// 78: 6627 str r7, [r4, #96] @ 0x60
|
||||||
|
// 7a: 3001 adds r0, #1
|
||||||
|
// 7c: 4665 mov r5, ip
|
||||||
|
// 7e: 2d00 cmp r5, #0
|
||||||
|
// 80: d0e2 beq.n 48 <flash_do_cmd+0x1c>
|
||||||
|
// 82: 2b00 cmp r3, #0
|
||||||
|
// 84: d0e0 beq.n 48 <flash_do_cmd+0x1c>
|
||||||
|
// 86: 6e27 ldr r7, [r4, #96] @ 0x60
|
||||||
|
// 88: 3b01 subs r3, #1
|
||||||
|
// 8a: 700f strb r7, [r1, #0]
|
||||||
|
// 8c: 3101 adds r1, #1
|
||||||
|
// 8e: e7db b.n 48 <flash_do_cmd+0x1c>
|
||||||
|
// 90: 4001800c .word 0x4001800c
|
||||||
|
// 94: 4001900c .word 0x4001900c
|
||||||
|
|
||||||
|
#include "flash_id_bin.h"
|
||||||
|
#define PICOBOOT_FLASH_ID_CMD_PROG_SIZE (const size_t)(152)
|
||||||
|
|
||||||
// TODO better place for this e.g. the USB DPRAM location the controller has already put it in
|
// TODO better place for this e.g. the USB DPRAM location the controller has already put it in
|
||||||
#define PEEK_POKE_CODE_LOC 0x20000000u
|
#define PEEK_POKE_CODE_LOC 0x20000000u
|
||||||
|
@ -647,10 +698,11 @@ int picoboot_peek(libusb_device_handle *usb_device, uint32_t addr, uint32_t *dat
|
||||||
|
|
||||||
int picoboot_flash_id(libusb_device_handle *usb_device, uint64_t *data) {
|
int picoboot_flash_id(libusb_device_handle *usb_device, uint64_t *data) {
|
||||||
picoboot_exclusive_access(usb_device, 1);
|
picoboot_exclusive_access(usb_device, 1);
|
||||||
|
assert(PICOBOOT_FLASH_ID_CMD_PROG_SIZE == flash_id_bin_SIZE);
|
||||||
uint8_t prog[PICOBOOT_FLASH_ID_CMD_PROG_SIZE];
|
uint8_t prog[PICOBOOT_FLASH_ID_CMD_PROG_SIZE];
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
output("GET FLASH ID\n");
|
output("GET FLASH ID\n");
|
||||||
memcpy(prog, picoboot_flash_id_cmd, picoboot_flash_id_cmd_len);
|
memcpy(prog, flash_id_bin, flash_id_bin_SIZE);
|
||||||
|
|
||||||
// ensure XIP is exited before executing
|
// ensure XIP is exited before executing
|
||||||
int ret = picoboot_exit_xip(usb_device);
|
int ret = picoboot_exit_xip(usb_device);
|
||||||
|
|
|
@ -38,6 +38,7 @@ enum picoboot_device_result {
|
||||||
dr_vidpid_unknown,
|
dr_vidpid_unknown,
|
||||||
dr_error,
|
dr_error,
|
||||||
dr_vidpid_stdio_usb,
|
dr_vidpid_stdio_usb,
|
||||||
|
dr_vidpid_stdio_usb_cant_connect,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -80,6 +81,9 @@ int picoboot_flash_id(libusb_device_handle *usb_device, uint64_t *data);
|
||||||
|
|
||||||
// we require 256 (as this is the page size supported by the device)
|
// we require 256 (as this is the page size supported by the device)
|
||||||
#define LOG2_PAGE_SIZE 8u
|
#define LOG2_PAGE_SIZE 8u
|
||||||
|
#ifdef PAGE_SIZE
|
||||||
|
#undef PAGE_SIZE
|
||||||
|
#endif
|
||||||
#define PAGE_SIZE (1u << LOG2_PAGE_SIZE)
|
#define PAGE_SIZE (1u << LOG2_PAGE_SIZE)
|
||||||
#define FLASH_SECTOR_ERASE_SIZE 4096u
|
#define FLASH_SECTOR_ERASE_SIZE 4096u
|
||||||
|
|
||||||
|
|
8
picoboot_flash_id/BUILD.bazel
Normal file
8
picoboot_flash_id/BUILD.bazel
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "picoboot_flash_id_prebuilt",
|
||||||
|
srcs = ["flash_id.bin"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO: Make it possible to build flash_id.bin from source.
|
36
picoboot_flash_id/CMakeLists.txt
Normal file
36
picoboot_flash_id/CMakeLists.txt
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
|
if (NOT USE_PRECOMPILED)
|
||||||
|
set(PICO_NO_PICOTOOL 1)
|
||||||
|
|
||||||
|
# default build type
|
||||||
|
set(CMAKE_BUILD_TYPE "MinSizeRel" CACHE STRING "build type")
|
||||||
|
|
||||||
|
# If the user set these environment variables to influence the picotool
|
||||||
|
# build, unset them here so that they do not influence the pico-sdk
|
||||||
|
# build. This is especially required for flags that are not supported
|
||||||
|
# by arm-none-eabi compilers.
|
||||||
|
unset(ENV{CFLAGS})
|
||||||
|
unset(ENV{CXXFLAGS})
|
||||||
|
unset(ENV{LDFLAGS})
|
||||||
|
|
||||||
|
include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
|
||||||
|
project(flash_id C CXX ASM)
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
|
add_executable(flash_id flash_id.c)
|
||||||
|
target_link_libraries(flash_id PRIVATE
|
||||||
|
hardware_regs hardware_structs hardware_flash_headers
|
||||||
|
)
|
||||||
|
target_link_options(flash_id PRIVATE -nostartfiles -nodefaultlibs -Ttext=0)
|
||||||
|
pico_add_bin_output(flash_id)
|
||||||
|
pico_add_dis_output(flash_id)
|
||||||
|
else()
|
||||||
|
project(flash_id C CXX ASM)
|
||||||
|
message("Using precompiled flash_id.bin")
|
||||||
|
configure_file(${CMAKE_CURRENT_LIST_DIR}/flash_id.bin ${CMAKE_CURRENT_BINARY_DIR}/flash_id.bin COPYONLY)
|
||||||
|
# Use manually specified variables
|
||||||
|
set(NULL ${CMAKE_MAKE_PROGRAM})
|
||||||
|
set(NULL ${PICO_SDK_PATH})
|
||||||
|
set(NULL ${PICO_DEBUG_INFO_IN_RELEASE})
|
||||||
|
endif()
|
BIN
picoboot_flash_id/flash_id.bin
Executable file
BIN
picoboot_flash_id/flash_id.bin
Executable file
Binary file not shown.
70
picoboot_flash_id/flash_id.c
Normal file
70
picoboot_flash_id/flash_id.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "hardware/regs/io_qspi.h"
|
||||||
|
#include "hardware/structs/ioqspi.h"
|
||||||
|
#include "hardware/structs/ssi.h"
|
||||||
|
#include "hardware/flash.h"
|
||||||
|
|
||||||
|
asm(
|
||||||
|
".macro static_assert value, msg\n"
|
||||||
|
".if !(\\value)\n"
|
||||||
|
".err \\msg\n"
|
||||||
|
".endif\n"
|
||||||
|
".endm\n"
|
||||||
|
|
||||||
|
".set FLASH_RUID_CMD, 0x4b\n"
|
||||||
|
".set FLASH_RUID_DUMMY_BYTES, 4\n"
|
||||||
|
".set FLASH_RUID_DATA_BYTES, 8\n"
|
||||||
|
".set FLASH_RUID_TOTAL_BYTES, (1 + FLASH_RUID_DUMMY_BYTES + FLASH_RUID_DATA_BYTES)\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
void flash_do_cmd(const uint8_t * txbuf, uint8_t *rxbuf, size_t count);
|
||||||
|
void __attribute__((naked)) flash_get_unique_id_raw(void) {
|
||||||
|
asm(
|
||||||
|
".Lflash_get_unique_id_raw:\n"
|
||||||
|
"adr r0, .Ltxbuf\n"
|
||||||
|
"adr r1, .Lrxbuf\n"
|
||||||
|
"ldr r2, .Lbuflen\n"
|
||||||
|
"b flash_do_cmd\n"
|
||||||
|
".Lbuflen:\n"
|
||||||
|
".word FLASH_RUID_TOTAL_BYTES\n"
|
||||||
|
".Ltxbuf:\n"
|
||||||
|
".byte FLASH_RUID_CMD\n"
|
||||||
|
".zero (FLASH_RUID_TOTAL_BYTES - 1)\n"
|
||||||
|
".zero (16 - FLASH_RUID_TOTAL_BYTES)\n"
|
||||||
|
".Lrxbuf:\n"
|
||||||
|
".zero FLASH_RUID_TOTAL_BYTES\n"
|
||||||
|
".zero (16 - FLASH_RUID_TOTAL_BYTES)\n"
|
||||||
|
"static_assert ((.Lrxbuf - flash_get_unique_id_raw) == 28), \"rxbuf offset incorrect\"\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __attribute__((always_inline)) flash_cs_force(_Bool high) {
|
||||||
|
uint32_t field_val = high ?
|
||||||
|
IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH :
|
||||||
|
IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW;
|
||||||
|
hw_write_masked(&ioqspi_hw->io[1].ctrl,
|
||||||
|
field_val << IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB,
|
||||||
|
IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_do_cmd(const uint8_t * txbuf, uint8_t *rxbuf, size_t count) {
|
||||||
|
flash_cs_force(0);
|
||||||
|
size_t tx_remaining = count;
|
||||||
|
size_t rx_remaining = count;
|
||||||
|
// We may be interrupted -- don't want FIFO to overflow if we're distracted.
|
||||||
|
const size_t max_in_flight = 16 - 2;
|
||||||
|
while (tx_remaining || rx_remaining) {
|
||||||
|
uint32_t flags = ssi_hw->sr;
|
||||||
|
bool can_put = !!(flags & SSI_SR_TFNF_BITS);
|
||||||
|
bool can_get = !!(flags & SSI_SR_RFNE_BITS);
|
||||||
|
if (can_put && tx_remaining && rx_remaining - tx_remaining < max_in_flight) {
|
||||||
|
ssi_hw->dr0 = *txbuf++;
|
||||||
|
--tx_remaining;
|
||||||
|
}
|
||||||
|
if (can_get && rx_remaining) {
|
||||||
|
*rxbuf++ = (uint8_t)ssi_hw->dr0;
|
||||||
|
--rx_remaining;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flash_cs_force(1);
|
||||||
|
}
|
|
@ -1,42 +1,53 @@
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
if (NOT USE_PRECOMPILED)
|
if (NOT USE_PRECOMPILED)
|
||||||
set(PICO_PLATFORM rp2350-arm-s)
|
set(PICO_PLATFORM rp2350-arm-s)
|
||||||
|
|
||||||
# Pull in SDK (must be before project)
|
set(PICO_NO_PICOTOOL 1)
|
||||||
include(pico_sdk_import.cmake)
|
|
||||||
|
|
||||||
project(xip_ram_perms C CXX ASM)
|
# If the user set these environment variables to influence the picotool
|
||||||
set(CMAKE_C_STANDARD 11)
|
# build, unset them here so that they do not influence the pico-sdk
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
# build. This is especially required for flags that are not supported
|
||||||
|
# by arm-none-eabi compilers.
|
||||||
|
unset(ENV{CFLAGS})
|
||||||
|
unset(ENV{CXXFLAGS})
|
||||||
|
unset(ENV{LDFLAGS})
|
||||||
|
|
||||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "2.0.0")
|
# Pull in SDK (must be before project)
|
||||||
message(FATAL_ERROR "Raspberry Pi Pico SDK version 2.0.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
|
include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
|
||||||
endif()
|
|
||||||
|
|
||||||
# Initialize the SDK
|
project(xip_ram_perms C CXX ASM)
|
||||||
pico_sdk_init()
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
# XIP Ram OTP Perm Setter
|
if (PICO_SDK_VERSION_STRING VERSION_LESS "2.0.0")
|
||||||
add_executable(xip_ram_perms
|
message(FATAL_ERROR "Raspberry Pi Pico SDK version 2.0.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
|
||||||
set_perms.c
|
endif()
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(xip_ram_perms
|
# Initialize the SDK
|
||||||
pico_stdlib
|
pico_sdk_init()
|
||||||
)
|
|
||||||
|
|
||||||
pico_set_binary_type(xip_ram_perms no_flash)
|
# XIP Ram OTP Perm Setter
|
||||||
# create linker script to run from 0x20070000
|
add_executable(xip_ram_perms
|
||||||
file(READ ${PICO_LINKER_SCRIPT_PATH}/memmap_no_flash.ld LINKER_SCRIPT)
|
set_perms.c
|
||||||
string(REPLACE "RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k" "RAM(rwx) : ORIGIN = 0x13ffc000, LENGTH = 16k" LINKER_SCRIPT "${LINKER_SCRIPT}")
|
)
|
||||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/memmap_xip_ram.ld "${LINKER_SCRIPT}")
|
|
||||||
pico_set_linker_script(xip_ram_perms ${CMAKE_CURRENT_BINARY_DIR}/memmap_xip_ram.ld)
|
target_link_libraries(xip_ram_perms
|
||||||
|
pico_stdlib
|
||||||
|
)
|
||||||
|
|
||||||
|
pico_set_binary_type(xip_ram_perms no_flash)
|
||||||
|
# create linker script to run from 0x20070000
|
||||||
|
file(READ ${PICO_LINKER_SCRIPT_PATH}/memmap_no_flash.ld LINKER_SCRIPT)
|
||||||
|
string(REPLACE "RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k" "RAM(rwx) : ORIGIN = 0x13ffc000, LENGTH = 16k" LINKER_SCRIPT "${LINKER_SCRIPT}")
|
||||||
|
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/memmap_xip_ram.ld "${LINKER_SCRIPT}")
|
||||||
|
pico_set_linker_script(xip_ram_perms ${CMAKE_CURRENT_BINARY_DIR}/memmap_xip_ram.ld)
|
||||||
else()
|
else()
|
||||||
project(xip_ram_perms C CXX ASM)
|
project(xip_ram_perms C CXX ASM)
|
||||||
message("Using precompiled xip_ram_perms.elf")
|
message("Using precompiled xip_ram_perms.elf")
|
||||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/xip_ram_perms.elf ${CMAKE_CURRENT_BINARY_DIR}/xip_ram_perms.elf COPYONLY)
|
configure_file(${CMAKE_CURRENT_LIST_DIR}/xip_ram_perms.elf ${CMAKE_CURRENT_BINARY_DIR}/xip_ram_perms.elf COPYONLY)
|
||||||
# Use manually specified variables
|
# Use manually specified variables
|
||||||
set(NULL ${CMAKE_MAKE_PROGRAM})
|
set(NULL ${CMAKE_MAKE_PROGRAM})
|
||||||
set(NULL ${PICO_SDK_PATH})
|
set(NULL ${PICO_SDK_PATH})
|
||||||
|
set(NULL ${PICO_DEBUG_INFO_IN_RELEASE})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
|
||||||
|
|
||||||
# This can be dropped into an external project to help locate this SDK
|
|
||||||
# It should be include()ed prior to project()
|
|
||||||
|
|
||||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
|
||||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
|
||||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
|
||||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
|
||||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
|
||||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
|
||||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
|
||||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
|
||||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
|
||||||
|
|
||||||
if (NOT PICO_SDK_PATH)
|
|
||||||
if (PICO_SDK_FETCH_FROM_GIT)
|
|
||||||
include(FetchContent)
|
|
||||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
|
||||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
|
||||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
|
||||||
endif ()
|
|
||||||
FetchContent_Declare(
|
|
||||||
pico_sdk
|
|
||||||
GIT_REPOSITORY git@asic-git.pitowers.org:amethyst/pico-sdk.git
|
|
||||||
GIT_TAG use-picotool
|
|
||||||
)
|
|
||||||
if (NOT pico_sdk)
|
|
||||||
message("Downloading Raspberry Pi Pico SDK")
|
|
||||||
FetchContent_Populate(pico_sdk)
|
|
||||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
|
||||||
endif ()
|
|
||||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
|
||||||
else ()
|
|
||||||
message(FATAL_ERROR
|
|
||||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
|
||||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
|
||||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
|
||||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
|
||||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
|
||||||
|
|
||||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue