defunct: playing around with bootloaders
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Flash partition layout for STM32G431 (128KB total flash)
|
||||
* MCUboot + single application slot configuration
|
||||
*/
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0x0000A000>; /* 40 KB for MCUboot */
|
||||
read-only;
|
||||
};
|
||||
|
||||
slot0_partition: partition@A000 {
|
||||
label = "image-0";
|
||||
reg = <0x0000A000 0x00016000>; /* 88 KB for application */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,code-partition = &slot0_partition;
|
||||
};
|
||||
};
|
||||
@@ -4,27 +4,4 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0x00008000>; /* 32 KB */
|
||||
read-only;
|
||||
};
|
||||
|
||||
slot0_partition: partition@8000 {
|
||||
label = "image-0";
|
||||
reg = <0x00008000 0x00018000>; /* 96 KB */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,code-partition = &slot0_partition;
|
||||
};
|
||||
};
|
||||
#include "flash_partitions_128kb.dtsi"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Enable Console and printk for logging
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_PROCESS_THREAD=y
|
||||
|
||||
# Enable Shell
|
||||
CONFIG_SHELL=y
|
||||
@@ -13,3 +14,8 @@ CONFIG_KERNEL_SHELL=y
|
||||
CONFIG_SETTINGS=y
|
||||
CONFIG_SETTINGS_NVS=y
|
||||
CONFIG_NVS=y
|
||||
|
||||
# Enable Flash and Flash Map for image trailer manipulation
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
|
||||
@@ -2,9 +2,83 @@
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/shell/shell.h>
|
||||
#include <zephyr/sys/reboot.h>
|
||||
#include <zephyr/drivers/flash.h>
|
||||
#include <zephyr/storage/flash_map.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
|
||||
LOG_MODULE_REGISTER(firmware_node, LOG_LEVEL_INF);
|
||||
|
||||
// Image header magic number (from MCUboot)
|
||||
#define IMAGE_MAGIC 0x96f3b83d
|
||||
#define IMAGE_HEADER_SIZE 32
|
||||
|
||||
// Function to invalidate current image and trigger serial recovery
|
||||
static int invalidate_current_image(void)
|
||||
{
|
||||
const struct flash_area *fa;
|
||||
int rc;
|
||||
|
||||
// Get the flash area for the current image slot (slot0_partition)
|
||||
rc = flash_area_open(FIXED_PARTITION_ID(slot0_partition), &fa);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to open flash area: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Ensure the flash area is valid
|
||||
if (fa->fa_id != FIXED_PARTITION_ID(slot0_partition)) {
|
||||
LOG_ERR("Invalid flash area ID: %d", fa->fa_id);
|
||||
flash_area_close(fa);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Get the flash device associated with this area
|
||||
// This is necessary to perform erase operations
|
||||
|
||||
const struct device *flash_dev = flash_area_get_device(fa);
|
||||
if (flash_dev == NULL) {
|
||||
LOG_ERR("Failed to get flash device for area");
|
||||
flash_area_close(fa);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
struct flash_pages_info page_info;
|
||||
off_t last_block_offset;
|
||||
|
||||
// Find the last block of the flash area
|
||||
rc = flash_get_page_info_by_offs(flash_dev, fa->fa_off + fa->fa_size - 1, &page_info);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to get page info: %d", rc);
|
||||
flash_area_close(fa);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Calculate the last block offset
|
||||
rc = flash_get_page_info_by_offs(flash_dev, fa->fa_off + fa->fa_size - 1, &page_info);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to get page info: %d", rc);
|
||||
flash_area_close(fa);
|
||||
return rc;
|
||||
}
|
||||
last_block_offset = page_info.start_offset;
|
||||
|
||||
// Convert absolute flash offset to relative offset within the flash area
|
||||
off_t relative_offset = last_block_offset - fa->fa_off;
|
||||
|
||||
// Erase the image trailer/metadata at the end of the partition
|
||||
LOG_INF("Erasing image trailer at absolute offset: %ld, relative offset: %ld, size: %d bytes",
|
||||
last_block_offset, relative_offset, page_info.size);
|
||||
rc = flash_area_erase(fa, relative_offset, page_info.size);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to erase image trailer: %d", rc);
|
||||
|
||||
} else {
|
||||
LOG_INF("Image trailer erased successfully");
|
||||
}
|
||||
|
||||
flash_area_close(fa);
|
||||
return rc;
|
||||
}
|
||||
// Custom reset command handler
|
||||
static int cmd_reset(const struct shell *shell, size_t argc, char **argv)
|
||||
{
|
||||
@@ -19,30 +93,75 @@ static int cmd_reset(const struct shell *shell, size_t argc, char **argv)
|
||||
}
|
||||
|
||||
// MCUboot serial recovery command handler
|
||||
static int cmd_mcuboot_recovery(const struct shell *shell, size_t argc, char **argv)
|
||||
static int cmd_recovery(const struct shell *shell, size_t argc, char **argv)
|
||||
{
|
||||
ARG_UNUSED(argc);
|
||||
ARG_UNUSED(argv);
|
||||
|
||||
shell_print(shell, "Entering MCUboot serial recovery mode...");
|
||||
shell_print(shell, "System will reset and MCUboot will wait for image upload via mcumgr");
|
||||
shell_print(shell, "Corrupting current image magic to trigger recovery...");
|
||||
|
||||
// Invalidate the current image by corrupting its header
|
||||
int rc = invalidate_current_image();
|
||||
if (rc != 0) {
|
||||
shell_error(shell, "Failed to invalidate image: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
shell_print(shell, "Image magic corrupted. System will reset and MCUboot will detect bad image.");
|
||||
shell_print(shell, "MCUboot should show error and wait for recovery.");
|
||||
k_msleep(100); // Give time for the message to be sent
|
||||
|
||||
// TODO: Set a flag or trigger MCUboot serial recovery mode
|
||||
// For now, just reset - MCUboot serial recovery needs to be enabled
|
||||
sys_reboot(SYS_REBOOT_COLD);
|
||||
// Reset the system - MCUboot will detect invalid image and enter serial recovery
|
||||
// log_process(true);
|
||||
// sys_reboot(SYS_REBOOT_COLD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Command to show firmware info
|
||||
static int cmd_info(const struct shell *shell, size_t argc, char **argv)
|
||||
{
|
||||
ARG_UNUSED(argc);
|
||||
ARG_UNUSED(argv);
|
||||
|
||||
const struct flash_area *fa;
|
||||
int rc = flash_area_open(FIXED_PARTITION_ID(slot0_partition), &fa);
|
||||
|
||||
if (rc != 0) {
|
||||
shell_error(shell, "Failed to open flash area: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Read the first few bytes to check the image header
|
||||
uint32_t magic;
|
||||
rc = flash_area_read(fa, 0, &magic, sizeof(magic));
|
||||
if (rc == 0) {
|
||||
shell_print(shell, "Image magic: 0x%08x", magic);
|
||||
if (magic == IMAGE_MAGIC) {
|
||||
shell_print(shell, "Image header is valid");
|
||||
shell_print(shell, "Image starts at flash offset: 0x%lx", (unsigned long)fa->fa_off);
|
||||
shell_print(shell, "Image partition size: %d bytes", fa->fa_size);
|
||||
} else {
|
||||
shell_print(shell, "Image header is INVALID (expected 0x%08x)", IMAGE_MAGIC);
|
||||
}
|
||||
} else {
|
||||
shell_error(shell, "Failed to read image header: %d", rc);
|
||||
}
|
||||
|
||||
flash_area_close(fa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHELL_CMD_REGISTER(reset, NULL, "Reset the system", cmd_reset);
|
||||
SHELL_CMD_REGISTER(mcuboot_recovery, NULL, "Enter MCUboot serial recovery mode", cmd_mcuboot_recovery);
|
||||
SHELL_CMD_REGISTER(recovery, NULL, "Enter MCUboot serial recovery mode", cmd_recovery);
|
||||
SHELL_CMD_REGISTER(info, NULL, "Show firmware info", cmd_info);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
LOG_INF("Firmware Node starting up");
|
||||
LOG_INF("Shell with reset command available");
|
||||
LOG_INF("MCUboot serial recovery command available");
|
||||
LOG_INF("Serial recovery command available");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
4
software/apps/firmware_node/sysbuild.cmake
Normal file
4
software/apps/firmware_node/sysbuild.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
# Sysbuild configuration for firmware_node with MCUboot
|
||||
|
||||
# Enable MCUboot as bootloader
|
||||
set(SB_CONFIG_BOOTLOADER_MCUBOOT TRUE)
|
||||
@@ -4,24 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0x00008000>; /* 32 KB */
|
||||
read-only;
|
||||
};
|
||||
|
||||
slot0_partition: partition@8000 {
|
||||
label = "image-0";
|
||||
reg = <0x00008000 0x00018000>; /* 96 KB */
|
||||
};
|
||||
};
|
||||
};
|
||||
#include "../boards/flash_partitions_128kb.dtsi"
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
# MCUboot configuration for firmware_node
|
||||
# Enable basic console and logging for debugging
|
||||
CONFIG_LOG=y
|
||||
CONFIG_BOOT_BANNER=y
|
||||
CONFIG_MCUBOOT_LOG_LEVEL_DBG=y
|
||||
# Disable console in MCUboot to allow serial recovery
|
||||
CONFIG_CONSOLE=n
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_PRINTK=y
|
||||
|
||||
# Single slot configuration (no upgrades)
|
||||
CONFIG_SINGLE_APPLICATION_SLOT=y
|
||||
|
||||
# Enable MCUboot serial recovery for firmware updates
|
||||
CONFIG_MCUBOOT_SERIAL=y
|
||||
CONFIG_BOOT_SERIAL_CDC_ACM=y
|
||||
# Enable serial recovery mode (temporarily commented out for debugging)
|
||||
# CONFIG_MCUBOOT_SERIAL=y
|
||||
# CONFIG_BOOT_SERIAL_UART=y
|
||||
# CONFIG_BOOT_SERIAL_DETECT_PORT=y
|
||||
|
||||
# Disable signature validation for testing
|
||||
# Disable signature validation for testing to save space
|
||||
CONFIG_BOOT_SIGNATURE_TYPE_NONE=y
|
||||
|
||||
# Size optimizations to fit in 40KB flash
|
||||
CONFIG_SIZE_OPTIMIZATIONS=y
|
||||
CONFIG_CBPRINTF_NANO=y
|
||||
CONFIG_MINIMAL_LIBC=y
|
||||
CONFIG_ASSERT=n
|
||||
|
||||
# Disable debug features for size
|
||||
CONFIG_DEBUG_INFO=n
|
||||
CONFIG_DEBUG_OPTIMIZATIONS=n
|
||||
|
||||
# Minimal heap for size optimization
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=0
|
||||
|
||||
@@ -1,27 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* MCUboot device tree overlay for firmware_node
|
||||
* Uses shared flash partition layout
|
||||
*/
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0x00008000>; /* 32 KB */
|
||||
read-only;
|
||||
};
|
||||
|
||||
slot0_partition: partition@8000 {
|
||||
label = "image-0";
|
||||
reg = <0x00008000 0x00018000>; /* 96 KB */
|
||||
};
|
||||
};
|
||||
};
|
||||
#include "../boards/flash_partitions_128kb.dtsi"
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* MCUboot specific overlay for weact_stm32g431_core
|
||||
* This overlay defines flash partitions for MCUboot
|
||||
*/
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0x00008000>;
|
||||
};
|
||||
slot0_partition: partition@8000 {
|
||||
label = "image-0";
|
||||
reg = <0x00008000 0x0000E000>;
|
||||
};
|
||||
slot1_partition: partition@16000 {
|
||||
label = "image-1";
|
||||
reg = <0x00016000 0x0000E000>;
|
||||
};
|
||||
storage_partition: partition@24000 {
|
||||
label = "storage";
|
||||
reg = <0x00024000 0x00004000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&chosen {
|
||||
zephyr,boot-partition = &boot_partition;
|
||||
};
|
||||
Reference in New Issue
Block a user