From 695a0628ffa6a9d6e351baa66f101c91901734f4 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Sun, 4 May 2025 20:06:07 +0000 Subject: [PATCH 01/38] Build and compile inside build/ directory --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33e9484..3159f27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty OUTPUT_STRIP_TRAILING_WHITESPACE) string(REGEX REPLACE "v([0-9]+\\.[0-9]+).*" "\\1" CMAKE_GIT_REPO_VERSION ${GIT_REPO_VERSION}) string(REGEX REPLACE "^(.......-.*)|(.......)$" "0.0.0" CMAKE_GIT_REPO_VERSION ${CMAKE_GIT_REPO_VERSION}) -configure_file("src/version.h.in" "src/version.h") +configure_file("src/version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/version.h") message("GIT_REPO_VERSION is ${GIT_REPO_VERSION}") message("CMAKE_GIT_REPO_VERSION is ${CMAKE_GIT_REPO_VERSION}") @@ -22,6 +22,8 @@ project(picoboot LANGUAGES C CXX ASM VERSION ${CMAKE_GIT_REPO_VERSION}) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/dist) + add_executable(picoboot src/picoboot.c src/pio.c @@ -59,5 +61,3 @@ function(merge_uf2 NAME BASE_TARGET INPUTS) DEPENDS ${BASE_TARGET} ${INPUTS} COMMAND_EXPAND_LISTS) endfunction() - -merge_uf2(picoboot_full picoboot "${CMAKE_CURRENT_LIST_DIR}/payload.uf2") From e3d29473fe92bf16b9c68047cf20a372e8f07d0d Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Sun, 4 May 2025 20:06:42 +0000 Subject: [PATCH 02/38] Add family ID argument to process_ipl.py script --- process_ipl.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/process_ipl.py b/process_ipl.py index b9ead81..55730e3 100755 --- a/process_ipl.py +++ b/process_ipl.py @@ -69,7 +69,14 @@ def flatten_dol(data): # Entry point, load address, memory image return entry, dol_min, img -def pack_uf2(data, base_address): +def pack_uf2(data, base_address, family): + if family == "rp2040": + family_id = 0xE48BFF56 # RP2040 + elif family == "rp2350": + family_id = 0xE48BFF58 # DATA family ID compatible with RP2350 + else: + raise ValueError(f"Unknown family: {family}") + ret = bytearray() seq = 0 @@ -89,7 +96,7 @@ def pack_uf2(data, base_address): chunk_size, seq, total_chunks, - 0xE48BFF56, # Board family: Raspberry Pi RP2040 + family_id, # Board family: Raspberry Pi RP2040 *chunk.ljust(476, b"\x00"), 0x0AB16F30, # Final magic ) @@ -101,11 +108,12 @@ def pack_uf2(data, base_address): def main(): if len(sys.argv) not in range(3, 4 + 1): - print(f"Usage: {sys.argv[0]} ") + print(f"Usage: {sys.argv[0]} []") return 1 output = sys.argv[1] executable = sys.argv[2] + family = sys.argv[3] with open(executable, "rb") as f: exe = bytearray(f.read()) @@ -151,7 +159,7 @@ def main(): out = header + img elif output.endswith(".uf2"): - out = pack_uf2(header + img, 0x10080000) + out = pack_uf2(header + img, 0x10080000, family) else: print("Unknown output format") From be9e4881e55e69ae159599ce8f43246d139ad4ca Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Sun, 4 May 2025 20:07:14 +0000 Subject: [PATCH 03/38] Update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f7d8346..62e908e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ _deps # Build environment build/ +dist/ CMakeFiles/ elf2uf2/ generated/ @@ -20,3 +21,5 @@ picoboot.elf.map picoboot.hex *.uf2 picoboot.pio.h +gekkoboot.dol +src/version.h \ No newline at end of file From 4e816609d83c370419b7bae4bc60a8a050771724 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Sun, 4 May 2025 20:08:28 +0000 Subject: [PATCH 04/38] Add main build script --- tools/build.sh | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 tools/build.sh diff --git a/tools/build.sh b/tools/build.sh new file mode 100755 index 0000000..1caa392 --- /dev/null +++ b/tools/build.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +set -e + +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' + +platforms=("rp2040" "rp2350") +boards=("pico_w" "pico2_w") +boards_arch=("pico" "pico2") +families=("pico_w" "pico2_w") +output_files=("picoboot_full_pico.uf2" "picoboot_full_pico2.uf2") +build_type="RelWithDebInfo" + +num_configs=${#platforms[@]} + +if [ ! -f "gekkoboot.dol" ]; then + echo -e "${RED}Error: gekkoboot.dol file not found${NC}" + exit 1 +fi + +echo -e "${BLUE}##########################################################${NC}" +echo -e "🚀 ${YELLOW}Generating payload uf2 files:${NC}" +echo -e "📂 ${YELLOW}Build directory:${NC} ${GREEN}build/gekkoboot${NC}" +echo -e "${BLUE}##########################################################${NC}" + +if [ ! -d "dist" ]; then + mkdir dist +fi + +echo -e "\n🔨 ${YELLOW}Building payload uf2 file for Pico...${NC}" +./process_ipl.py dist/payload_pico.uf2 gekkoboot.dol rp2040 + +echo -e "\n🔨 ${YELLOW}Building payload uf2 file for Pico 2...${NC}" +./process_ipl.py dist/payload_pico2.uf2 gekkoboot.dol rp2350 + +echo -e "\n🔨 ${YELLOW}Building universal payload uf2 file...${NC}" +cat dist/payload_pico.uf2 dist/payload_pico2.uf2 > dist/payload_universal.uf2 + +for (( i=0; i Date: Sun, 4 May 2025 20:08:54 +0000 Subject: [PATCH 05/38] Update build workflow --- .github/build_summary.md | 9 +++++++++ .github/workflows/10-build.yml | 23 ++++++++++------------- 2 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 .github/build_summary.md diff --git a/.github/build_summary.md b/.github/build_summary.md new file mode 100644 index 0000000..f84e0f7 --- /dev/null +++ b/.github/build_summary.md @@ -0,0 +1,9 @@ +### Files included in the build artifact + +* **`picoboot_pico.uf2`**: PicoBoot firmware only for Raspberry Pi Pico / Pico W +* **`picoboot_pico2.uf2`**: PicoBoot firmware only for Raspberry Pi Pico 2 / Pico 2 W +* **`picoboot_full_pico.uf2`**: PicoBoot firmware for Raspberry Pi Pico. Includes the embedded payload (gekkoboot) +* **`picoboot_full_pico2.uf2`**: PicoBoot firmware for Raspberry Pi Pico W / Pico 2. Includes the embedded payload (gekkoboot) +* **`payload_pico.uf2`**: The payload (gekkoboot) packaged as a UF2 file for Raspberry Pi Pico / Pico W. This can be used to update the payload without reflashing the main PicoBoot firmware. +* **`payload_pico2.uf2`**: The payload (gekkoboot) packaged as a UF2 file for Raspberry Pi Pico 2 / Pico 2 W. This can be used to update the payload without reflashing the main PicoBoot firmware. +* **`payload_universal.uf2`**: The payload (gekkoboot) packaged as a universal UF2 file compatible with both Pico and Pico 2. This can be used to update the payload without reflashing the main PicoBoot firmware. diff --git a/.github/workflows/10-build.yml b/.github/workflows/10-build.yml index f290242..3591bad 100644 --- a/.github/workflows/10-build.yml +++ b/.github/workflows/10-build.yml @@ -40,21 +40,19 @@ jobs: - uses: robinraju/release-downloader@v1 id: gekkoboot-download with: - repository: 'webhdx/iplboot' + repository: 'webhdx/gekkoboot' latest: true fileName: '*.zip' out-file-path: gekkoboot extract: true - - name: Copy gekkoboot uf2 payload + - name: Copy gekkoboot.dol run: | cd gekkoboot - if [ -f "gekkoboot_pico.uf2" ]; then - cp gekkoboot_pico.uf2 ${{ github.workspace }}/payload.uf2 - elif [ -f "iplboot_pico.uf2" ]; then - cp iplboot_pico.uf2 ${{ github.workspace }}/payload.uf2 + if [ -f "gekkoboot.dol" ]; then + cp gekkoboot.dol ${{ github.workspace }}/gekkoboot.dol else - echo "Neither gekkoboot_pico.uf2 nor iplboot_pico.uf2 found." + echo "gekkoboot.dol not found" exit 1 fi @@ -64,14 +62,13 @@ jobs: imageName: ghcr.io/webhdx/picoboot cacheFrom: ghcr.io/webhdx/picoboot runCmd: | - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . - make + tools/build.sh - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: picoboot-${{ steps.vars.outputs.sha_short }} - path: | - picoboot_full.uf2 - picoboot.uf2 - payload.uf2 + path: dist/ + + - name: Add build summary + run: echo "$(cat .github/build_summary.md)" >> $GITHUB_STEP_SUMMARY From f57ab4a4acc666c2b2661f8e30a940eabff8512b Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:37:04 +0000 Subject: [PATCH 06/38] Add GPIO status LED driver --- src/status_led/gpio.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/status_led/gpio.h | 20 ++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/status_led/gpio.c create mode 100644 src/status_led/gpio.h diff --git a/src/status_led/gpio.c b/src/status_led/gpio.c new file mode 100644 index 0000000..1687cf6 --- /dev/null +++ b/src/status_led/gpio.c @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include "gpio.h" +#ifdef PICO_RP2040 +#include "boards/pico.h" +#else +#include "boards/pico2.h" +#endif + +static bool led_state_gpio = false; + +int status_led_gpio_init(void) { + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + + led_state_gpio = false; + + return 0; +} + +void status_led_gpio_on(void) { + gpio_put(PICO_DEFAULT_LED_PIN, true); + + led_state_gpio = true; +} + +void status_led_gpio_off(void) { + gpio_put(PICO_DEFAULT_LED_PIN, false); + + led_state_gpio = false; +} + +void status_led_gpio_toggle(void) { + if (led_state_gpio) { + status_led_gpio_off(); + } else { + status_led_gpio_on(); + } +} diff --git a/src/status_led/gpio.h b/src/status_led/gpio.h new file mode 100644 index 0000000..8cf34c0 --- /dev/null +++ b/src/status_led/gpio.h @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef STATUS_LED_GPIO_DRIVER_H +#define STATUS_LED_GPIO_DRIVER_H + +#include "pico/stdlib.h" + +int status_led_gpio_init(void); + +void status_led_gpio_on(void); + +void status_led_gpio_off(void); + +void status_led_gpio_toggle(void); + +#endif \ No newline at end of file From b5eaabaa81a2af89d7911a13950f9f1faea56537 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:37:14 +0000 Subject: [PATCH 07/38] Add CYW43 status LED driver --- src/status_led/cyw43.c | 48 ++++++++++++++++++++++++++++++++++++++++++ src/status_led/cyw43.h | 18 ++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/status_led/cyw43.c create mode 100644 src/status_led/cyw43.h diff --git a/src/status_led/cyw43.c b/src/status_led/cyw43.c new file mode 100644 index 0000000..4b21b6e --- /dev/null +++ b/src/status_led/cyw43.c @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include + +#include "pico/cyw43_arch.h" +#ifdef PICO_RP2040 +#include "boards/pico_w.h" +#else +#include "boards/pico2_w.h" +#endif + +#include "cyw43.h" + +static bool led_state_cyw43 = false; + +int status_led_cyw43_init(void) { + if (cyw43_arch_init()) { + return 1; + } + + led_state_cyw43 = false; + + return 0; +} + +void status_led_cyw43_on(void) { + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, true); + + led_state_cyw43 = true; +} + +void status_led_cyw43_off(void) { + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, false); + + led_state_cyw43 = false; +} + +void status_led_cyw43_toggle(void) { + if (led_state_cyw43) { + status_led_cyw43_off(); + } else { + status_led_cyw43_on(); + } +} \ No newline at end of file diff --git a/src/status_led/cyw43.h b/src/status_led/cyw43.h new file mode 100644 index 0000000..3d380af --- /dev/null +++ b/src/status_led/cyw43.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef STATUS_LED_CYW43_DRIVER_H +#define STATUS_LED_CYW43_DRIVER_H + +int status_led_cyw43_init(void); + +void status_led_cyw43_on(void); + +void status_led_cyw43_off(void); + +void status_led_cyw43_toggle(void); + +#endif \ No newline at end of file From 330c575f935f21dd803a294f211f39ced96dfda4 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:37:36 +0000 Subject: [PATCH 08/38] Abstract Status LED from hardware platform --- src/status_led.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ src/status_led.h | 20 ++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/status_led.c create mode 100644 src/status_led.h diff --git a/src/status_led.c b/src/status_led.c new file mode 100644 index 0000000..861a960 --- /dev/null +++ b/src/status_led.c @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include +#include + +#include "hw.h" +#include "status_led.h" +#include "status_led/cyw43.h" +#include "status_led/gpio.h" + +typedef int (*led_init_func_p)(void); +typedef void (*led_op_func_p)(void); + +typedef struct { + led_init_func_p init; + led_op_func_p on; + led_op_func_p off; + led_op_func_p toggle; +} status_led_driver_t; + +static int led_init_noop(void) { + return 0; +} + +static void led_op_noop(void) { + // Do nothing +} + +static status_led_driver_t s_led_driver = { + .init = led_init_noop, + .on = led_op_noop, + .off = led_op_noop, + .toggle = led_op_noop, +}; + +void status_led_init(hw_board_type_t board_type) { + if (board_type == HW_BOARD_TYPE_PICO_W || board_type == HW_BOARD_TYPE_PICO_2_W) { + s_led_driver.init = status_led_cyw43_init; + s_led_driver.on = status_led_cyw43_on; + s_led_driver.off = status_led_cyw43_off; + s_led_driver.toggle = status_led_cyw43_toggle; + } else { + s_led_driver.init = status_led_gpio_init; + s_led_driver.on = status_led_gpio_on; + s_led_driver.off = status_led_gpio_off; + s_led_driver.toggle = status_led_gpio_toggle; + } + + if (s_led_driver.init() != 0) { + s_led_driver.init = led_init_noop; + s_led_driver.on = led_op_noop; + s_led_driver.off = led_op_noop; + s_led_driver.toggle = led_op_noop; + } +} + +void status_led_on(void) { + s_led_driver.on(); +} + +void status_led_off(void) { + s_led_driver.off(); +} + +void status_led_toggle(void) { + s_led_driver.toggle(); +} diff --git a/src/status_led.h b/src/status_led.h new file mode 100644 index 0000000..c097ce4 --- /dev/null +++ b/src/status_led.h @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef STATUS_LED_H +#define STATUS_LED_H + +#include "hw.h" + +void status_led_init(hw_board_type_t board_type); + +void status_led_on(void); + +void status_led_off(void); + +void status_led_toggle(void); + +#endif // STATUS_LED_H From 08d59ffce434c459cd966c809c1a8092dc071801 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:38:01 +0000 Subject: [PATCH 09/38] Detect HW at runtime --- src/hw.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hw.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/hw.c create mode 100644 src/hw.h diff --git a/src/hw.c b/src/hw.c new file mode 100644 index 0000000..31c1c2c --- /dev/null +++ b/src/hw.c @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include "hardware/adc.h" +#include "pico/stdlib.h" +#include "pico/platform.h" + +#include "hw.h" + +#define ADC_PIN_VSYS 29 +#define ADC_INPUT_VSYS 3 + +// Threshold for differentiating Pico from Pico W based on raw ADC reading. +// Pico W typically has a much lower reading on VSYS ADC (e.g., ~0x01c). +// Pico typically has a higher reading (e.g., ~0x2cd). +// A value around 0x100 should be a safe threshold. +#define PICO_W_ADC_THRESHOLD 0x100 + +hw_board_type_t hw_detect_board_type(void) { + adc_gpio_init(ADC_PIN_VSYS); + adc_select_input(ADC_INPUT_VSYS); + + uint16_t adc_result = adc_read(); + + if (adc_result < PICO_W_ADC_THRESHOLD) { + #if defined(PICO_RP2350) + return HW_BOARD_TYPE_PICO_2_W; + #else + return HW_BOARD_TYPE_PICO_W; + #endif + } else { + #if defined(PICO_RP2350) + return HW_BOARD_TYPE_PICO_2; + #else + return HW_BOARD_TYPE_PICO; + #endif + } +} + +const char* hw_board_type_to_string(hw_board_type_t board_type) { + switch (board_type) { + case HW_BOARD_TYPE_PICO: + return "Raspberry Pi Pico"; + case HW_BOARD_TYPE_PICO_W: + return "Raspberry Pi Pico W"; + case HW_BOARD_TYPE_PICO_2: + return "Raspberry Pi Pico 2"; + case HW_BOARD_TYPE_PICO_2_W: + return "Raspberry Pi Pico 2 W"; + default: + return "Unknown"; + } +} diff --git a/src/hw.h b/src/hw.h new file mode 100644 index 0000000..2c54ff5 --- /dev/null +++ b/src/hw.h @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef HW_H +#define HW_H + +// Defines the possible board types +typedef enum { + HW_BOARD_TYPE_PICO, + HW_BOARD_TYPE_PICO_W, + HW_BOARD_TYPE_PICO_2, + HW_BOARD_TYPE_PICO_2_W, + HW_BOARD_TYPE_UNKNOWN +} hw_board_type_t; + +/** + * @brief Detects the type of Raspberry Pi Pico board. + * + * This function reads the ADC on GPIO29 (ADC3) to differentiate + * between a Pico and a Pico W. Pico W typically shows a much lower + * voltage on VSYS (connected to ADC3) when the wireless circuitry is present. + * + * @note The ADC system must be initialized by calling adc_init() before this function. + * + * @return hw_board_type_t The detected board type (HW_BOARD_TYPE_PICO or HW_BOARD_TYPE_PICO_W). + */ +hw_board_type_t hw_detect_board_type(void); + +/** + * @brief Converts a hw_board_type_t enum to its string representation. + * + * @param board_type The board type enum. + * + * @return const char* The string representation of the board type. + */ +const char* hw_board_type_to_string(hw_board_type_t board_type); + +#endif // HW_H \ No newline at end of file From 50d948eb2f4eb2f9c9ea5ae8272056d8c849425b Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:38:33 +0000 Subject: [PATCH 10/38] Move version injection code to separate cmake file --- CMakeLists.txt | 40 +++++++++++++---------------------- cmake/extract_version.cmake | 42 +++++++++++++++++++++++++++++++++++++ src/version.h.in | 23 ++++++++++++++++++-- 3 files changed, 77 insertions(+), 28 deletions(-) create mode 100644 cmake/extract_version.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 3159f27..e997a02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,21 +3,12 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) -find_package(Git) -execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE GIT_REPO_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) -string(REGEX REPLACE "v([0-9]+\\.[0-9]+).*" "\\1" CMAKE_GIT_REPO_VERSION ${GIT_REPO_VERSION}) -string(REGEX REPLACE "^(.......-.*)|(.......)$" "0.0.0" CMAKE_GIT_REPO_VERSION ${CMAKE_GIT_REPO_VERSION}) -configure_file("src/version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/version.h") -message("GIT_REPO_VERSION is ${GIT_REPO_VERSION}") -message("CMAKE_GIT_REPO_VERSION is ${CMAKE_GIT_REPO_VERSION}") +include(cmake/extract_version.cmake) # Pull in Raspberry Pi Pico SDK (must be before project) include(pico_sdk_import.cmake) -project(picoboot LANGUAGES C CXX ASM VERSION ${CMAKE_GIT_REPO_VERSION}) +project(picoboot LANGUAGES C CXX ASM VERSION ${PROJECT_VERSION_STRING}) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() @@ -26,7 +17,11 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/dist) add_executable(picoboot src/picoboot.c + src/hw.c src/pio.c + src/status_led.c + src/status_led/gpio.c + src/status_led/cyw43.c ) pico_generate_pio_header(picoboot @@ -35,10 +30,9 @@ pico_generate_pio_header(picoboot pico_set_program_name(picoboot "PicoBoot") pico_set_program_description(picoboot "RP2040 based modchip for Nintendo GameCube") -pico_set_program_version(picoboot ${GIT_REPO_VERSION}) +pico_set_program_version(picoboot ${FW_VER_STRING}) pico_set_program_url(picoboot "https://github.com/webhdx/PicoBoot") -pico_set_binary_type(picoboot copy_to_ram) target_link_options(pico_standard_link INTERFACE "LINKER:--script=${CMAKE_CURRENT_LIST_DIR}/memmap_picoboot.ld") pico_enable_stdio_uart(picoboot 0) @@ -46,18 +40,12 @@ pico_enable_stdio_usb(picoboot 1) target_include_directories(picoboot PRIVATE src) -target_link_libraries(picoboot PRIVATE pico_stdlib hardware_pio hardware_dma) +target_link_libraries(picoboot PRIVATE + hardware_adc + hardware_dma + hardware_pio + pico_cyw43_arch_none + pico_stdlib +) pico_add_extra_outputs(picoboot) - -function(merge_uf2 NAME BASE_TARGET INPUTS) - get_target_property(BASE_TARGET_NAME ${BASE_TARGET} OUTPUT_NAME) - if(BASE_TARGET_NAME STREQUAL "BASE_TARGET_NAME-NOTFOUND") - get_target_property(BASE_TARGET_NAME ${BASE_TARGET} NAME) - endif() - - add_custom_target(${NAME} ALL - COMMAND ${CMAKE_CURRENT_LIST_DIR}/merge_uf2.py ${NAME}.uf2 ${BASE_TARGET_NAME}.uf2 ${INPUTS} - DEPENDS ${BASE_TARGET} ${INPUTS} - COMMAND_EXPAND_LISTS) -endfunction() diff --git a/cmake/extract_version.cmake b/cmake/extract_version.cmake new file mode 100644 index 0000000..b616007 --- /dev/null +++ b/cmake/extract_version.cmake @@ -0,0 +1,42 @@ +# CMake script to extract version information from Git and configure version.h + +find_package(Git REQUIRED) + +execute_process( + COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_DESCRIBE_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE GIT_DESCRIBE_RESULT +) + +set(FW_VER_STRING "0.0.0-unknown") +set(FW_VER_MAJOR 0) +set(FW_VER_MINOR 0) +set(FW_VER_PATCH 0) + +if(GIT_DESCRIBE_RESULT EQUAL 0 AND GIT_DESCRIBE_OUTPUT) + set(FW_VER_STRING ${GIT_DESCRIBE_OUTPUT}) + if(FW_VER_STRING MATCHES "^v([0-9]+)\.([0-9]+)\.([0-9]+)") + set(FW_VER_MAJOR ${CMAKE_MATCH_1}) + set(FW_VER_MINOR ${CMAKE_MATCH_2}) + set(FW_VER_PATCH ${CMAKE_MATCH_3}) + else() + message(STATUS "Git version string '${FW_VER_STRING}' does not match vX.Y.Z format for MAJOR/MINOR/PATCH. Using 0.0.0 for these.") + endif() +else() + message(WARNING "git describe failed or returned empty. Using default version: ${FW_VER_STRING}, MAJOR: ${FW_VER_MAJOR}, MINOR: ${FW_VER_MINOR}, PATCH: ${FW_VER_PATCH}") +endif() + +set(PROJECT_VERSION_STRING "${FW_VER_MAJOR}.${FW_VER_MINOR}.${FW_VER_PATCH}") + +configure_file( + "${CMAKE_SOURCE_DIR}/src/version.h.in" + "${CMAKE_SOURCE_DIR}/src/version.h" +) + +message(STATUS "FW_VER_STRING: ${FW_VER_STRING}") +message(STATUS "FW_VER_MAJOR: ${FW_VER_MAJOR}") +message(STATUS "FW_VER_MINOR: ${FW_VER_MINOR}") +message(STATUS "FW_VER_PATCH: ${FW_VER_PATCH}") +message(STATUS "PROJECT_VERSION_STRING: ${PROJECT_VERSION_STRING}") \ No newline at end of file diff --git a/src/version.h.in b/src/version.h.in index c4e94c9..1a6ea1b 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,3 +1,22 @@ -#pragma once +/** + * Copyright (c) 2025 Maciej Kobus + * + * SPDX-License-Identifier: GPL-2.0-only + */ -#define PICOBOOT_VERSION "${GIT_REPO_VERSION}" \ No newline at end of file +#ifndef VERSION_H +#define VERSION_H + +#include + +#define FW_VER_STRING "${FW_VER_STRING}" + +static const uint8_t FW_VER_MAJOR = ${FW_VER_MAJOR}; +static const uint8_t FW_VER_MINOR = ${FW_VER_MINOR}; +static const uint8_t FW_VER_PATCH = ${FW_VER_PATCH}; + +static const uint32_t FW_VER_FULL = ((uint32_t)FW_VER_MAJOR << 24) | + ((uint32_t)FW_VER_MINOR << 16) | + ((uint32_t)FW_VER_PATCH << 8); + +#endif // VERSION_H From 3a034eaa31958794b4ff33260e80f3ac70932b0b Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:39:03 +0000 Subject: [PATCH 11/38] Support rp2350-arm-s family ID in uf2 payload file --- process_ipl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/process_ipl.py b/process_ipl.py index 55730e3..07c5b66 100755 --- a/process_ipl.py +++ b/process_ipl.py @@ -73,6 +73,8 @@ def pack_uf2(data, base_address, family): if family == "rp2040": family_id = 0xE48BFF56 # RP2040 elif family == "rp2350": + family_id = 0xE48BFF59 # RP2350-ARM-S + elif family == "data": family_id = 0xE48BFF58 # DATA family ID compatible with RP2350 else: raise ValueError(f"Unknown family: {family}") From 8958978a2db5598dc429d639c899af86503a08fa Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:39:33 +0000 Subject: [PATCH 12/38] Adjust main program file to recent changes --- src/picoboot.c | 52 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/picoboot.c b/src/picoboot.c index a11b75d..d7bdc45 100644 --- a/src/picoboot.c +++ b/src/picoboot.c @@ -1,27 +1,34 @@ /** - * Copyright (c) 2024 Maciej Kobus + * Copyright (c) 2025 Maciej Kobus * * SPDX-License-Identifier: GPL-2.0-only */ #include -#include "pico/stdlib.h" -#include "hardware/pio.h" +#include + +#include "hardware/adc.h" #include "hardware/clocks.h" #include "hardware/dma.h" +#include "hardware/pio.h" #include "hardware/structs/bus_ctrl.h" -#include "pio.h" -#include "picoboot.pio.h" -#include "endian.h" +#include "pico/stdlib.h" -const uint PIN_LED = 25; // Status LED +#include "endian.h" +#include "hw.h" +#include "picoboot.pio.h" +#include "pio.h" +#include "status_led.h" +#include "version.h" extern const uint32_t __payload[]; extern const uint32_t __payload_end[]; -const uint32_t payload_magic0 = 0x49504C42; // "IPLB" -const uint32_t payload_magic1 = 0x4F4F5420; // "OOT " -const uint32_t payload_magic2 = 0x5049434F; // "PICO" +static const uint32_t payload_magic0 = 0x49504C42; // "IPLB" +static const uint32_t payload_magic1 = 0x4F4F5420; // "OOT " +static const uint32_t payload_magic2 = 0x5049434F; // "PICO" + +static hw_board_type_t s_board_type; size_t validate_payload() { if (BigEndian32(__payload[0]) != payload_magic0) { @@ -51,18 +58,27 @@ size_t validate_payload() { void main() { - // Initialize and light up builtin LED, it will basically - // act as a power LED. - // TODO: Use the LED to signalize system faults? - gpio_init(PIN_LED); - gpio_set_dir(PIN_LED, GPIO_OUT); - gpio_put(PIN_LED, true); + stdio_init_all(); + + while (!tud_cdc_connected()) { + sleep_ms(100); + } + + adc_init(); + s_board_type = hw_detect_board_type(); + + printf("PicoBoot (%s) by webhdx (c) 2025\n", FW_VER_STRING); + printf("Board Type: %s\n", hw_board_type_to_string(s_board_type)); + + status_led_init(s_board_type); + status_led_on(); size_t payload_size = validate_payload(); if (payload_size == SIZE_MAX) { + printf("PicoBoot: Invalid payload. Entering infinite loop.\n"); while (true) { sleep_ms(500); - gpio_xor_mask(1 << PIN_LED); + status_led_toggle(); } } @@ -136,6 +152,8 @@ void main() pio_sm_set_enabled(pio, transfer_start_sm, true); pio_sm_set_enabled(pio, clocked_output_sm, true); + printf("PicoBoot: Finished injecting payload. Entering infinite loop.\n"); + while (true) { tight_loop_contents(); } From ce4aab87b942dcbed5110cc4a798e93c57352bec Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:39:59 +0000 Subject: [PATCH 13/38] Update year in file headers --- src/picoboot.pio | 2 +- src/pio.c | 2 +- src/pio.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/picoboot.pio b/src/picoboot.pio index 28b6018..1bb30fb 100644 --- a/src/picoboot.pio +++ b/src/picoboot.pio @@ -1,4 +1,4 @@ - ; Copyright (c) 2024 Maciej Kobus + ; Copyright (c) 2025 Maciej Kobus ; ; SPDX-License-Identifier: GPL-2.0-only diff --git a/src/pio.c b/src/pio.c index db65be8..fecb2bc 100644 --- a/src/pio.c +++ b/src/pio.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022 Maciej Kobus + * Copyright (c) 2025 Maciej Kobus * * SPDX-License-Identifier: GPL-2.0-only */ diff --git a/src/pio.h b/src/pio.h index 0d8eec8..375d6f5 100644 --- a/src/pio.h +++ b/src/pio.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022 Maciej Kobus + * Copyright (c) 2025 Maciej Kobus * * SPDX-License-Identifier: GPL-2.0-only */ From 0fd35e2fffa8e13f2e85c14a8a0863f6cdbbd2c1 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 22:40:24 +0000 Subject: [PATCH 14/38] Fix build script with platform workarounds --- tools/build.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/build.sh b/tools/build.sh index 1caa392..99404a9 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -11,8 +11,7 @@ NC='\033[0m' platforms=("rp2040" "rp2350") boards=("pico_w" "pico2_w") boards_arch=("pico" "pico2") -families=("pico_w" "pico2_w") -output_files=("picoboot_full_pico.uf2" "picoboot_full_pico2.uf2") +families=("rp2040" "rp2350-arm-s") build_type="RelWithDebInfo" num_configs=${#platforms[@]} @@ -44,8 +43,9 @@ for (( i=0; i Date: Wed, 7 May 2025 23:00:10 +0000 Subject: [PATCH 15/38] Update release workflow for new dist structure --- .github/workflows/00-release.yml | 41 ++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/.github/workflows/00-release.yml b/.github/workflows/00-release.yml index 45e3550..5b3418b 100644 --- a/.github/workflows/00-release.yml +++ b/.github/workflows/00-release.yml @@ -6,7 +6,7 @@ on: version: description: 'Version to tag' required: true - default: 'v0.4' + default: 'v0.5.0' type: string is_draft: description: 'Is draft release?' @@ -88,7 +88,9 @@ jobs: run: | echo '```' >> release-description.md cd dist/ - sha256sum picoboot_full.uf2 >> ../release-description.md + sha256sum picoboot_full_pico.uf2 >> ../release-description.md + sha256sum picoboot_full_pico2.uf2 >> ../release-description.md + sha256sum payload_universal.uf2 >> ../release-description.md cd ../ echo '```' >> release-description.md @@ -97,24 +99,27 @@ jobs: git config --global user.name "GitHub Actions" git config --global user.email "actions@github.com" + - name: Create tag + uses: actions/github-script@v7 + with: + script: | + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'refs/tags/${{ github.event.inputs.version }}', + sha: context.sha + }) + - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: softprops/action-gh-release@v2 + if: github.ref_type == 'tag' with: + name: ${{ steps.determine_name.outputs.name }} tag_name: ${{ github.event.inputs.version }} - release_name: ${{ steps.determine_name.outputs.name }} - body_path: ${{ github.workspace }}/release-description.md draft: ${{ github.event.inputs.is_draft }} prerelease: ${{ github.event.inputs.is_prerelease }} - - - name: Upload Release Asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ${{ github.workspace }}/dist/picoboot_full.uf2 - asset_name: picoboot_full.uf2 - asset_content_type: application/octet-stream + body_path: ${{ github.workspace }}/release-description.md + files: | + dist/picoboot_full_pico.uf2 + dist/picoboot_full_pico2.uf2 + dist/payload_universal.uf2 From 43c74690be0f69386eba3c7d0d859edd3de819e0 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 23:11:07 +0000 Subject: [PATCH 16/38] Remove redundant tagging --- .github/workflows/00-release.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/00-release.yml b/.github/workflows/00-release.yml index 5b3418b..bd1d39b 100644 --- a/.github/workflows/00-release.yml +++ b/.github/workflows/00-release.yml @@ -99,20 +99,8 @@ jobs: git config --global user.name "GitHub Actions" git config --global user.email "actions@github.com" - - name: Create tag - uses: actions/github-script@v7 - with: - script: | - github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: 'refs/tags/${{ github.event.inputs.version }}', - sha: context.sha - }) - - name: Create Release uses: softprops/action-gh-release@v2 - if: github.ref_type == 'tag' with: name: ${{ steps.determine_name.outputs.name }} tag_name: ${{ github.event.inputs.version }} From b4c5717226dc9fe8f2a63e46d64bb89d5c1df40a Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 23:17:17 +0000 Subject: [PATCH 17/38] Trigger build workflow after devcontainer --- .github/workflows/10-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/10-build.yml b/.github/workflows/10-build.yml index 3591bad..d5069c7 100644 --- a/.github/workflows/10-build.yml +++ b/.github/workflows/10-build.yml @@ -1,13 +1,12 @@ name: Build on: - push: - branches: - - '**' - pull_request: + workflow_run: + workflows: ["Dev Container Build and Push Image"] + types: + - completed branches: - main - - workflow_call: + pull_request: {} env: # Customize the CMake build @@ -16,6 +15,7 @@ env: jobs: build: runs-on: ubuntu-latest + if: (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') || github.event_name == 'pull_request' steps: - name: Clean workspace run: | From bd7164e97a3d65eb426efdb7d42bcf89d46ff03d Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 23:18:14 +0000 Subject: [PATCH 18/38] Update workflow names --- .github/workflows/{10-build.yml => build.yml} | 2 +- .github/workflows/{20-devcontainer.yml => devcontainer.yml} | 0 .github/workflows/{00-release.yml => release.yml} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{10-build.yml => build.yml} (98%) rename .github/workflows/{20-devcontainer.yml => devcontainer.yml} (100%) rename .github/workflows/{00-release.yml => release.yml} (100%) diff --git a/.github/workflows/10-build.yml b/.github/workflows/build.yml similarity index 98% rename from .github/workflows/10-build.yml rename to .github/workflows/build.yml index d5069c7..e927e2a 100644 --- a/.github/workflows/10-build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build +name: Build PicoBoot on: workflow_run: workflows: ["Dev Container Build and Push Image"] diff --git a/.github/workflows/20-devcontainer.yml b/.github/workflows/devcontainer.yml similarity index 100% rename from .github/workflows/20-devcontainer.yml rename to .github/workflows/devcontainer.yml diff --git a/.github/workflows/00-release.yml b/.github/workflows/release.yml similarity index 100% rename from .github/workflows/00-release.yml rename to .github/workflows/release.yml From e4b8bac6c20a5109036887a73014f61fc835a41e Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 23:52:44 +0000 Subject: [PATCH 19/38] Revert "Trigger build workflow after devcontainer" This reverts commit b4c5717226dc9fe8f2a63e46d64bb89d5c1df40a. --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e927e2a..2fd61f9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,12 +1,13 @@ name: Build PicoBoot on: - workflow_run: - workflows: ["Dev Container Build and Push Image"] - types: - - completed + push: + branches: + - '**' + pull_request: branches: - main - pull_request: {} + + workflow_call: env: # Customize the CMake build @@ -15,7 +16,6 @@ env: jobs: build: runs-on: ubuntu-latest - if: (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') || github.event_name == 'pull_request' steps: - name: Clean workspace run: | From 392653055b6ec982dba120d0f35921b6276d14dc Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 7 May 2025 23:57:55 +0000 Subject: [PATCH 20/38] Never push devcontainer image in build workflow --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2fd61f9..4b315c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,6 +61,7 @@ jobs: with: imageName: ghcr.io/webhdx/picoboot cacheFrom: ghcr.io/webhdx/picoboot + push: never runCmd: | tools/build.sh From 5dc3c5a2135b4d9e427d9ee8681b5c7e35b17878 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 00:02:36 +0000 Subject: [PATCH 21/38] Fix build workflow name --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd1d39b..e82c1eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,7 +47,7 @@ jobs: build: needs: tag - uses: ./.github/workflows/10-build.yml + uses: ./.github/workflows/build.yml release: runs-on: ubuntu-latest From 23fa01282e0b6706cad0a1f919c26f166e905c77 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 06:36:33 +0000 Subject: [PATCH 22/38] Fetch full history before build --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4b315c2..8068fd9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,8 @@ jobs: - name: Checkout PicoBoot code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set outputs id: vars From 447e51bff17682da85117a894a9be31616a7f140 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 06:48:35 +0000 Subject: [PATCH 23/38] Update build summary --- .github/build_summary.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/build_summary.md b/.github/build_summary.md index f84e0f7..ce113f7 100644 --- a/.github/build_summary.md +++ b/.github/build_summary.md @@ -1,9 +1,13 @@ ### Files included in the build artifact -* **`picoboot_pico.uf2`**: PicoBoot firmware only for Raspberry Pi Pico / Pico W -* **`picoboot_pico2.uf2`**: PicoBoot firmware only for Raspberry Pi Pico 2 / Pico 2 W -* **`picoboot_full_pico.uf2`**: PicoBoot firmware for Raspberry Pi Pico. Includes the embedded payload (gekkoboot) -* **`picoboot_full_pico2.uf2`**: PicoBoot firmware for Raspberry Pi Pico W / Pico 2. Includes the embedded payload (gekkoboot) -* **`payload_pico.uf2`**: The payload (gekkoboot) packaged as a UF2 file for Raspberry Pi Pico / Pico W. This can be used to update the payload without reflashing the main PicoBoot firmware. -* **`payload_pico2.uf2`**: The payload (gekkoboot) packaged as a UF2 file for Raspberry Pi Pico 2 / Pico 2 W. This can be used to update the payload without reflashing the main PicoBoot firmware. -* **`payload_universal.uf2`**: The payload (gekkoboot) packaged as a universal UF2 file compatible with both Pico and Pico 2. This can be used to update the payload without reflashing the main PicoBoot firmware. +Most users should use one of the **`picoboot_full_*.uf2`** files (full package). Other files are intended for advanced users to update only specific parts of the firmware or payload. + +| File Name | Platform | Description | +| ------------------------- | ------------------------------------ | --------------------------------- | +| `picoboot_full_pico.uf2` | Pico
Pico W | firmware + payload (full package) | +| `picoboot_full_pico2.uf2` | Pico 2
Pico 2 W | firmware + payload (full package) | +| `picoboot_pico.uf2` | Pico
Pico W | firmware only | +| `picoboot_pico2.uf2` | Pico 2
Pico 2 W | firmware only | +| `payload_pico.uf2` | Pico
Pico W | payload | +| `payload_pico2.uf2` | Pico 2
Pico 2 W | payload | +| `payload_universal.uf2` | Pico
Pico W
Pico 2
Pico 2 W | payload | From 4d8d61189664bf43275c96946a8d0119314a21ed Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 07:56:55 +0000 Subject: [PATCH 24/38] Automatically generate release notes --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e82c1eb..3506e42 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,6 @@ jobs: cd dist/ sha256sum picoboot_full_pico.uf2 >> ../release-description.md sha256sum picoboot_full_pico2.uf2 >> ../release-description.md - sha256sum payload_universal.uf2 >> ../release-description.md cd ../ echo '```' >> release-description.md @@ -107,7 +106,7 @@ jobs: draft: ${{ github.event.inputs.is_draft }} prerelease: ${{ github.event.inputs.is_prerelease }} body_path: ${{ github.workspace }}/release-description.md + generate_release_notes: true files: | dist/picoboot_full_pico.uf2 dist/picoboot_full_pico2.uf2 - dist/payload_universal.uf2 From 5db9b61c1fb7ea8f5c2914e0519cef2d1384be8b Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 09:19:27 +0000 Subject: [PATCH 25/38] Add changelog to release --- .github/release_description.md | 14 ++++++++++++++ .github/workflows/release.yml | 31 ++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 .github/release_description.md diff --git a/.github/release_description.md b/.github/release_description.md new file mode 100644 index 0000000..cbf4ed3 --- /dev/null +++ b/.github/release_description.md @@ -0,0 +1,14 @@ +@DESCRIPTION@ + +## Changes in this release + +@CHANGELOG@ + +## Available files + +* `picoboot_full_pico.uf2`: Compatible with Raspberry Pi Pico and Raspberry Pi Pico W. +* `picoboot_full_pico2.uf2`: Compatible with Raspberry Pi Pico 2 and Raspberry Pi Pico 2 W. + +## Useful Links + +✨ [Software features](https://github.com/redolution/gekkoboot/) | 🚀 [Installation Guide](https://support.webhdx.dev/gc/picoboot/installation-guide) | ⬆️ [Update Guide](https://support.webhdx.dev/gc/picoboot/update-picoboot) | 🛠️ [Troubleshooting](https://support.webhdx.dev/gc/picoboot/troubleshooting) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3506e42..1387866 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,11 +78,33 @@ jobs: with: name: picoboot-${{ steps.vars.outputs.sha_short }} path: dist/ + + - name: Build Changelog + id: build_changelog + uses: mikepenz/release-changelog-builder-action@v5 + with: + mode: "COMMIT" + toTag: ${{ github.event.inputs.version }} # Explicitly set the current tag + configurationJson: | + { + "template": "#{{CHANGELOG}}", + "commit_template": "* {{SUBJECT}} (`{{SHORT_HASH}}`)", + "empty_template": "_No notable changes in this version._", + "categories": [] + } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Prepare release description - run: | - touch release-description.md - echo "${{ github.event.inputs.release_description }}" >> release-description.md + - name: Prepare release description + env: + DESCRIPTION: ${{ github.event.inputs.release_description }} + RELEASE_NAME: ${{ steps.determine_name.outputs.name }} + CHANGELOG: ${{ steps.build_changelog.outputs.changelog }} + run: | + content=$(cat .github/release_description.md) + content=${content//@DESCRIPTION@/$DESCRIPTION} + content=${content//@CHANGELOG@/$CHANGELOG} + echo "$content" > release-description.md - name: Calculate artifact checksum run: | @@ -106,7 +128,6 @@ jobs: draft: ${{ github.event.inputs.is_draft }} prerelease: ${{ github.event.inputs.is_prerelease }} body_path: ${{ github.workspace }}/release-description.md - generate_release_notes: true files: | dist/picoboot_full_pico.uf2 dist/picoboot_full_pico2.uf2 From e5d1c12f8534b3a11a4ac99c2392443e0da79380 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 09:30:45 +0000 Subject: [PATCH 26/38] Fix changelog in releases --- .github/release_description.md | 8 ++++---- .github/workflows/release.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/release_description.md b/.github/release_description.md index cbf4ed3..4197668 100644 --- a/.github/release_description.md +++ b/.github/release_description.md @@ -4,11 +4,11 @@ @CHANGELOG@ +## Useful Links + +✨ [Software features](https://github.com/redolution/gekkoboot/) | 🚀 [Installation Guide](https://support.webhdx.dev/gc/picoboot/installation-guide) | ⬆️ [Update Guide](https://support.webhdx.dev/gc/picoboot/update-picoboot) | 🛠️ [Troubleshooting](https://support.webhdx.dev/gc/picoboot/troubleshooting) + ## Available files * `picoboot_full_pico.uf2`: Compatible with Raspberry Pi Pico and Raspberry Pi Pico W. * `picoboot_full_pico2.uf2`: Compatible with Raspberry Pi Pico 2 and Raspberry Pi Pico 2 W. - -## Useful Links - -✨ [Software features](https://github.com/redolution/gekkoboot/) | 🚀 [Installation Guide](https://support.webhdx.dev/gc/picoboot/installation-guide) | ⬆️ [Update Guide](https://support.webhdx.dev/gc/picoboot/update-picoboot) | 🛠️ [Troubleshooting](https://support.webhdx.dev/gc/picoboot/troubleshooting) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1387866..d10ff0c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -87,7 +87,7 @@ jobs: toTag: ${{ github.event.inputs.version }} # Explicitly set the current tag configurationJson: | { - "template": "#{{CHANGELOG}}", + "template": "#{{UNCATEGORIZED}}", "commit_template": "* {{SUBJECT}} (`{{SHORT_HASH}}`)", "empty_template": "_No notable changes in this version._", "categories": [] From 6f6673b986f3ae029480197175b99744e6d32fec Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 11:17:18 +0000 Subject: [PATCH 27/38] Use default commit template in release notes --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d10ff0c..260422c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,7 +88,6 @@ jobs: configurationJson: | { "template": "#{{UNCATEGORIZED}}", - "commit_template": "* {{SUBJECT}} (`{{SHORT_HASH}}`)", "empty_template": "_No notable changes in this version._", "categories": [] } From f7f7cfbb4fcee6edecd0b7326d66aee2eb9cf974 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 12:30:53 +0000 Subject: [PATCH 28/38] Update changelog template --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 260422c..4553361 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,6 +88,7 @@ jobs: configurationJson: | { "template": "#{{UNCATEGORIZED}}", + "commit_template": "* #{{TITLE}} (`#{{MERGE_SHA}} by #{{AUTHOR}}`)", "empty_template": "_No notable changes in this version._", "categories": [] } From 2da2defefe15d731eaea08894fb4c21f48c2c5ca Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 12:38:12 +0000 Subject: [PATCH 29/38] Fix author and commit link in changelogs --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4553361..532cd46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,7 +88,7 @@ jobs: configurationJson: | { "template": "#{{UNCATEGORIZED}}", - "commit_template": "* #{{TITLE}} (`#{{MERGE_SHA}} by #{{AUTHOR}}`)", + "commit_template": "* #{{TITLE}} by @#{{AUTHOR}} (#{{MERGE_SHA}})", "empty_template": "_No notable changes in this version._", "categories": [] } From e986208c876675eb4d7840bb5cea794078a1c9b3 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 20:10:21 +0000 Subject: [PATCH 30/38] Use payload.dol for making builds --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- tools/build.sh | 28 +++++++++++++++++++++------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8068fd9..a03f7e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,7 +52,7 @@ jobs: run: | cd gekkoboot if [ -f "gekkoboot.dol" ]; then - cp gekkoboot.dol ${{ github.workspace }}/gekkoboot.dol + cp gekkoboot.dol ${{ github.workspace }}/payload.dol else echo "gekkoboot.dol not found" exit 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 532cd46..828342b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -84,7 +84,7 @@ jobs: uses: mikepenz/release-changelog-builder-action@v5 with: mode: "COMMIT" - toTag: ${{ github.event.inputs.version }} # Explicitly set the current tag + toTag: ${{ github.event.inputs.version }} configurationJson: | { "template": "#{{UNCATEGORIZED}}", diff --git a/tools/build.sh b/tools/build.sh index 99404a9..345d3d3 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -1,4 +1,16 @@ #!/bin/bash +# ----------------------------------------------------------------------- +# build.sh - Builds PicoBoot firmware files for different platforms +# ----------------------------------------------------------------------- +# Purpose: +# Builds PicoBoot firmware files for both Raspberry Pi Pico and Pico 2 +# platforms. Processes gekkoboot.dol into payload files and creates +# universal payload that works on both boards. +# Outputs uf2 files into dist/ directory. +# +# Usage: +# ./build.sh +# ----------------------------------------------------------------------- set -e @@ -16,14 +28,14 @@ build_type="RelWithDebInfo" num_configs=${#platforms[@]} -if [ ! -f "gekkoboot.dol" ]; then - echo -e "${RED}Error: gekkoboot.dol file not found${NC}" +if [ ! -f "payload.dol" ]; then + echo -e "${RED}Error: payload.dol file not found${NC}" exit 1 fi echo -e "${BLUE}##########################################################${NC}" echo -e "🚀 ${YELLOW}Generating payload uf2 files:${NC}" -echo -e "📂 ${YELLOW}Build directory:${NC} ${GREEN}build/gekkoboot${NC}" +echo -e "📂 ${YELLOW}Input file:${NC} ${GREEN}payload.dol${NC}" echo -e "${BLUE}##########################################################${NC}" if [ ! -d "dist" ]; then @@ -31,10 +43,10 @@ if [ ! -d "dist" ]; then fi echo -e "\n🔨 ${YELLOW}Building payload uf2 file for Pico...${NC}" -./process_ipl.py dist/payload_pico.uf2 gekkoboot.dol rp2040 +./process_ipl.py dist/payload_pico.uf2 payload.dol rp2040 echo -e "\n🔨 ${YELLOW}Building payload uf2 file for Pico 2...${NC}" -./process_ipl.py dist/payload_pico2.uf2 gekkoboot.dol rp2350 +./process_ipl.py dist/payload_pico2.uf2 payload.dol rp2350 echo -e "\n🔨 ${YELLOW}Building universal payload uf2 file...${NC}" cat dist/payload_pico.uf2 dist/payload_pico2.uf2 > dist/payload_universal.uf2 @@ -63,13 +75,15 @@ for (( i=0; i Date: Thu, 8 May 2025 20:10:38 +0000 Subject: [PATCH 31/38] Add script for aligning RP2040 binaries --- tools/rp2040_4k_align.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100755 tools/rp2040_4k_align.sh diff --git a/tools/rp2040_4k_align.sh b/tools/rp2040_4k_align.sh new file mode 100755 index 0000000..102654a --- /dev/null +++ b/tools/rp2040_4k_align.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# ----------------------------------------------------------------------- +# rp2040_4k_align.sh - Aligns binary file size to 4KB multiples +# ----------------------------------------------------------------------- +# Purpose: +# Pads binary files to 4KB block size to work around an issue with +# the RP2040 bootrom as described in the RP2040 datasheet errata section. +# +# Usage: +# ./rp2040_4k_align.sh input_file output_file +# +# Arguments: +# $1 - Input file path +# $2 - Output file path +# +# Example: +# ./rp2040_4k_align.sh picoboot.bin picoboot_padded.bin +# ----------------------------------------------------------------------- + +dd if=/dev/zero of="$2" bs=1 count=$(( ($(stat -c%s "$1") + 4096 - 1) / 4096 * 4096 )) 2>/dev/null +dd if="$1" of="$2" bs=1 count=$(stat -c%s "$1") conv=notrunc 2>/dev/null \ No newline at end of file From 76282d18a7cb2f6d083d3e502e5d2e55c0991275 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 20:10:56 +0000 Subject: [PATCH 32/38] Move python scripts to tools/ --- merge_uf2.py => tools/merge_uf2.py | 0 process_ipl.py => tools/process_ipl.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename merge_uf2.py => tools/merge_uf2.py (100%) rename process_ipl.py => tools/process_ipl.py (100%) diff --git a/merge_uf2.py b/tools/merge_uf2.py similarity index 100% rename from merge_uf2.py rename to tools/merge_uf2.py diff --git a/process_ipl.py b/tools/process_ipl.py similarity index 100% rename from process_ipl.py rename to tools/process_ipl.py From a68b234091962a56117d0e822f18c3001e6c5ba9 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 20:19:22 +0000 Subject: [PATCH 33/38] Fix process_ipl.py path --- tools/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/build.sh b/tools/build.sh index 345d3d3..80214cc 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -43,10 +43,10 @@ if [ ! -d "dist" ]; then fi echo -e "\n🔨 ${YELLOW}Building payload uf2 file for Pico...${NC}" -./process_ipl.py dist/payload_pico.uf2 payload.dol rp2040 +tools/process_ipl.py dist/payload_pico.uf2 payload.dol rp2040 echo -e "\n🔨 ${YELLOW}Building payload uf2 file for Pico 2...${NC}" -./process_ipl.py dist/payload_pico2.uf2 payload.dol rp2350 +tools/process_ipl.py dist/payload_pico2.uf2 payload.dol rp2350 echo -e "\n🔨 ${YELLOW}Building universal payload uf2 file...${NC}" cat dist/payload_pico.uf2 dist/payload_pico2.uf2 > dist/payload_universal.uf2 From e62f9476260580132eb5440929483c3ab3435705 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 20:46:42 +0000 Subject: [PATCH 34/38] Remove delay when waiting for USB --- src/picoboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/picoboot.c b/src/picoboot.c index d7bdc45..26c320e 100644 --- a/src/picoboot.c +++ b/src/picoboot.c @@ -61,7 +61,7 @@ void main() stdio_init_all(); while (!tud_cdc_connected()) { - sleep_ms(100); + // wait for USB } adc_init(); From 305ff1431b62b1f1343090a4cefae2c96344df8f Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 20:46:59 +0000 Subject: [PATCH 35/38] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 62e908e..384ba27 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ picoboot.hex *.uf2 picoboot.pio.h gekkoboot.dol +payload.dol src/version.h \ No newline at end of file From 1d6876fdf2331949a900d51ef228c795394b35de Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 20:47:26 +0000 Subject: [PATCH 36/38] Remove debugging info --- src/picoboot.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/picoboot.c b/src/picoboot.c index 26c320e..a970beb 100644 --- a/src/picoboot.c +++ b/src/picoboot.c @@ -58,24 +58,14 @@ size_t validate_payload() { void main() { - stdio_init_all(); - - while (!tud_cdc_connected()) { - // wait for USB - } - adc_init(); s_board_type = hw_detect_board_type(); - printf("PicoBoot (%s) by webhdx (c) 2025\n", FW_VER_STRING); - printf("Board Type: %s\n", hw_board_type_to_string(s_board_type)); - status_led_init(s_board_type); status_led_on(); size_t payload_size = validate_payload(); if (payload_size == SIZE_MAX) { - printf("PicoBoot: Invalid payload. Entering infinite loop.\n"); while (true) { sleep_ms(500); status_led_toggle(); @@ -152,8 +142,6 @@ void main() pio_sm_set_enabled(pio, transfer_start_sm, true); pio_sm_set_enabled(pio, clocked_output_sm, true); - printf("PicoBoot: Finished injecting payload. Entering infinite loop.\n"); - while (true) { tight_loop_contents(); } From b70b6dd9b04c15396c193f6e62aa6934e55a69f2 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 8 May 2025 22:04:23 +0000 Subject: [PATCH 37/38] Revert "Remove debugging info" This reverts commit 1d6876fdf2331949a900d51ef228c795394b35de. --- src/picoboot.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/picoboot.c b/src/picoboot.c index a970beb..26c320e 100644 --- a/src/picoboot.c +++ b/src/picoboot.c @@ -58,14 +58,24 @@ size_t validate_payload() { void main() { + stdio_init_all(); + + while (!tud_cdc_connected()) { + // wait for USB + } + adc_init(); s_board_type = hw_detect_board_type(); + printf("PicoBoot (%s) by webhdx (c) 2025\n", FW_VER_STRING); + printf("Board Type: %s\n", hw_board_type_to_string(s_board_type)); + status_led_init(s_board_type); status_led_on(); size_t payload_size = validate_payload(); if (payload_size == SIZE_MAX) { + printf("PicoBoot: Invalid payload. Entering infinite loop.\n"); while (true) { sleep_ms(500); status_led_toggle(); @@ -142,6 +152,8 @@ void main() pio_sm_set_enabled(pio, transfer_start_sm, true); pio_sm_set_enabled(pio, clocked_output_sm, true); + printf("PicoBoot: Finished injecting payload. Entering infinite loop.\n"); + while (true) { tight_loop_contents(); } From 4b746236fbdb76a432b879e4a1adf487aef7f29e Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 14 May 2025 22:59:29 +0000 Subject: [PATCH 38/38] [Workaround] Delay LED initialization --- src/picoboot.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/picoboot.c b/src/picoboot.c index 26c320e..273dcb5 100644 --- a/src/picoboot.c +++ b/src/picoboot.c @@ -59,23 +59,17 @@ size_t validate_payload() { void main() { stdio_init_all(); - - while (!tud_cdc_connected()) { - // wait for USB - } - adc_init(); s_board_type = hw_detect_board_type(); printf("PicoBoot (%s) by webhdx (c) 2025\n", FW_VER_STRING); printf("Board Type: %s\n", hw_board_type_to_string(s_board_type)); - status_led_init(s_board_type); - status_led_on(); - size_t payload_size = validate_payload(); if (payload_size == SIZE_MAX) { printf("PicoBoot: Invalid payload. Entering infinite loop.\n"); + status_led_init(s_board_type); + while (true) { sleep_ms(500); status_led_toggle(); @@ -154,6 +148,9 @@ void main() printf("PicoBoot: Finished injecting payload. Entering infinite loop.\n"); + status_led_init(s_board_type); + status_led_on(); + while (true) { tight_loop_contents(); }