Skip to content

Commit 75d8485

Browse files
committed
Implement filesystem-based partition state management
- Add new logic to `libwolfboot.c` for reading and updating partition states using a filesystem, enabled via `WOLFBOOT_PARTITION_FILENAME`. - Implement functions to set and get partition states (`wolfBoot_update_trigger`, `wolfBoot_success`, `wolfBoot_get_partition_state`) - Add `boot_status.py` and `hal/library_fs.c` for CLI and library access. - Update `.gitignore` and build rules for new artifacts.
1 parent 2a89172 commit 75d8485

File tree

8 files changed

+437
-3
lines changed

8 files changed

+437
-3
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ tools/tpm/policy_create
118118
tools/tpm/policy_sign
119119
config/*.ld
120120
test-lib
121+
lib-fs
121122

122123
# Elf preprocessing tools
123124
tools/squashelf/**
@@ -255,3 +256,8 @@ lib/r_tsip_rx
255256
Debug/
256257
Release/
257258
language.settings.xml
259+
260+
# Eclipse
261+
.cproject
262+
.project
263+
.settings/

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ test-lib: libwolfboot.a hal/library.o
202202
@echo "\t[BIN] $@"
203203
$(Q)$(CC) $(CFLAGS) -o $@ hal/library.o libwolfboot.a
204204

205+
lib-fs: libwolfboot.a hal/library.o
206+
@echo "\t[BIN] $@"
207+
$(Q)$(CC) $(CFLAGS) -o hal/library.o libwolfboot.a
208+
205209
wolfboot.efi: wolfboot.elf
206210
@echo "\t[BIN] $@"
207211
$(Q)$(OBJCOPY) -j .rodata -j .text -j .sdata -j .data \

hal/library_fs.c

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/* library_fs.c
2+
*
3+
* Copyright (C) 2025 wolfSSL Inc.
4+
*
5+
* This file is part of wolfBoot.
6+
*
7+
* wolfBoot is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfBoot is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
#include <stdio.h>
23+
#include <string.h>
24+
#include <stdlib.h>
25+
26+
#include "image.h"
27+
#include "printf.h"
28+
#include "wolfboot/wolfboot.h"
29+
30+
/* Helper function to convert partition ID to string */
31+
static const char* partition_name(uint8_t part)
32+
{
33+
switch (part) {
34+
case PART_BOOT:
35+
return "BOOT";
36+
case PART_UPDATE:
37+
return "UPDATE";
38+
default:
39+
return "UNKNOWN";
40+
}
41+
}
42+
43+
/* Helper function to convert state value to string */
44+
static const char* state_name(uint8_t state)
45+
{
46+
switch (state) {
47+
case IMG_STATE_NEW:
48+
return "NEW";
49+
case IMG_STATE_UPDATING:
50+
return "UPDATING";
51+
case IMG_STATE_SUCCESS:
52+
return "SUCCESS";
53+
default:
54+
return "UNKNOWN";
55+
}
56+
}
57+
58+
/* Print partition state */
59+
static int cmd_get_state(uint8_t part)
60+
{
61+
uint8_t state;
62+
int ret;
63+
64+
ret = wolfBoot_get_partition_state(part, &state);
65+
if (ret != 0) {
66+
wolfBoot_printf("Error: Failed to get state for %s partition (error: %d)\n",
67+
partition_name(part), ret);
68+
return -1;
69+
}
70+
71+
wolfBoot_printf("%s partition state: %s (0x%02X)\n",
72+
partition_name(part), state_name(state), state);
73+
return 0;
74+
}
75+
76+
/* Print all partition states */
77+
static int cmd_get_all_states(void)
78+
{
79+
int ret = 0;
80+
81+
wolfBoot_printf("=== Partition States ===\n");
82+
83+
if (cmd_get_state(PART_BOOT) != 0)
84+
ret = -1;
85+
86+
if (cmd_get_state(PART_UPDATE) != 0)
87+
ret = -1;
88+
89+
return ret;
90+
}
91+
92+
/* Trigger an update */
93+
static int cmd_update_trigger(void)
94+
{
95+
wolfBoot_printf("Triggering update...\n");
96+
wolfBoot_update_trigger();
97+
wolfBoot_printf("Update triggered successfully. UPDATE partition set to UPDATING state.\n");
98+
return 0;
99+
}
100+
101+
/* Mark current boot as successful */
102+
static int cmd_success(void)
103+
{
104+
wolfBoot_printf("Marking BOOT partition as SUCCESS...\n");
105+
wolfBoot_success();
106+
wolfBoot_printf("BOOT partition marked as SUCCESS.\n");
107+
return 0;
108+
}
109+
110+
/* Print usage information */
111+
static void print_usage(const char* prog_name)
112+
{
113+
wolfBoot_printf("wolfBoot Partition Manager CLI\n");
114+
wolfBoot_printf("\nUsage: %s <command> [options]\n\n", prog_name);
115+
wolfBoot_printf("Commands:\n");
116+
wolfBoot_printf(" status - Show state of all partitions\n");
117+
wolfBoot_printf(" get-boot - Get BOOT partition state\n");
118+
wolfBoot_printf(" get-update - Get UPDATE partition state\n");
119+
wolfBoot_printf(" update-trigger - Trigger an update (sets UPDATE partition to UPDATING)\n");
120+
wolfBoot_printf(" success - Mark BOOT partition as SUCCESS\n");
121+
wolfBoot_printf(" help - Show this help message\n");
122+
wolfBoot_printf("\nPartitions:\n");
123+
wolfBoot_printf(" BOOT - Currently running firmware partition\n");
124+
wolfBoot_printf(" UPDATE - Staging partition for new firmware\n");
125+
wolfBoot_printf("\nExamples:\n");
126+
wolfBoot_printf(" %s status - Display all partition states\n", prog_name);
127+
wolfBoot_printf(" %s update-trigger - Stage an update for next boot\n", prog_name);
128+
wolfBoot_printf(" %s success - Confirm current firmware is working\n", prog_name);
129+
wolfBoot_printf("\n");
130+
}
131+
132+
int main(int argc, const char* argv[])
133+
{
134+
int ret = 0;
135+
136+
/* Check for argument count */
137+
if (argc != 2) {
138+
print_usage(argv[0]);
139+
return 1;
140+
}
141+
142+
const char* command = argv[1];
143+
144+
/* Process commands */
145+
if (strcmp(command, "status") == 0) {
146+
ret = cmd_get_all_states();
147+
}
148+
else if (strcmp(command, "get-boot") == 0) {
149+
ret = cmd_get_state(PART_BOOT);
150+
}
151+
else if (strcmp(command, "get-update") == 0) {
152+
ret = cmd_get_state(PART_UPDATE);
153+
}
154+
else if (strcmp(command, "update-trigger") == 0) {
155+
ret = cmd_update_trigger();
156+
}
157+
else if (strcmp(command, "success") == 0) {
158+
ret = cmd_success();
159+
}
160+
else if (strcmp(command, "help") == 0 || strcmp(command, "--help") == 0 ||
161+
strcmp(command, "-h") == 0) {
162+
print_usage(argv[0]);
163+
ret = 0;
164+
}
165+
else {
166+
wolfBoot_printf("Error: Unknown command '%s'\n\n", command);
167+
print_usage(argv[0]);
168+
ret = 1;
169+
}
170+
171+
return ret;
172+
}

include/target.h.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
#ifdef WOLFBOOT_FIXED_PARTITIONS
3838

39-
#ifdef ARCH_SIM
39+
#if defined(ARCH_SIM) && !defined(WOLFBOOT_PARTITION_FILENAME)
4040
#include <stdint.h>
4141
/* use runtime ram base for simulator */
4242
extern uint8_t *sim_ram_base;

include/user_settings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,9 @@ extern int tolower(int c);
464464
#define NO_HC128
465465
#define NO_DES3
466466
#define NO_WRITEV
467+
#ifndef WOLFBOOT_PARTITION_FILENAME
467468
#define NO_FILESYSTEM
469+
#endif
468470
#define NO_MAIN_DRIVER
469471
#define NO_OLD_RNGNAME
470472
#define NO_WOLFSSL_DIR

options.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,3 +1035,7 @@ endif
10351035
ifeq ($(USE_UART3),1)
10361036
CFLAGS += -DUSE_UART3=1
10371037
endif
1038+
1039+
ifneq ($(WOLFBOOT_PARTITION_FILENAME),)
1040+
CFLAGS += -DWOLFBOOT_PARTITION_FILENAME=$(WOLFBOOT_PARTITION_FILENAME)
1041+
endif

src/libwolfboot.c

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ static void RAMFUNCTION set_partition_magic(uint8_t part)
403403
return;
404404
}
405405

406-
#else
406+
#elif !defined(WOLFBOOT_PARTITION_FILENAME)
407407

408408
/**
409409
* @brief Get the trailer at a specific address
@@ -543,8 +543,114 @@ static void RAMFUNCTION set_partition_magic(uint8_t part)
543543
#endif /* !MOCK_PARTITION_TRAILER */
544544

545545

546+
#ifdef WOLFBOOT_PARTITION_FILENAME
546547

547-
#ifdef WOLFBOOT_FIXED_PARTITIONS
548+
#ifndef WOLFBOOT_FIXED_PARTITIONS
549+
#error Using WOLFBOOT_PARTITION_FILENAME requires WOLFBOOT_FIXED_PARTITIONS
550+
#endif
551+
552+
static void set_partition_state_fs(uint8_t st, uint8_t part)
553+
{
554+
const char* fileName = WOLFBOOT_PARTITION_FILENAME;
555+
XFILE partFile = XBADFILE;
556+
union {
557+
uint32_t num;
558+
byte buf[sizeof(uint32_t)];
559+
} magic;
560+
long offset;
561+
562+
if (part == PART_BOOT)
563+
offset = PART_BOOT_ENDFLAGS;
564+
else if (part == PART_UPDATE)
565+
offset = PART_UPDATE_ENDFLAGS;
566+
else
567+
return;
568+
569+
partFile = XFOPEN(fileName, "r+b");
570+
if (partFile == XBADFILE)
571+
goto cleanup;
572+
573+
if (XFSEEK(partFile, offset - sizeof(uint32_t), XSEEK_SET) != 0)
574+
goto cleanup;
575+
576+
if (XFREAD(magic.buf, 1, sizeof(magic.buf), partFile) != sizeof(magic.buf))
577+
goto cleanup;
578+
579+
if (magic.num != WOLFBOOT_MAGIC_TRAIL) {
580+
magic.num = WOLFBOOT_MAGIC_TRAIL;
581+
if (XFSEEK(partFile, offset - sizeof(uint32_t), XSEEK_SET) != 0)
582+
goto cleanup;
583+
if (XFWRITE(magic.buf, 1, sizeof(magic.buf), partFile) !=
584+
sizeof(magic.buf))
585+
goto cleanup;
586+
}
587+
588+
if (XFSEEK(partFile, offset - sizeof(uint32_t) - 1, XSEEK_SET) != 0)
589+
goto cleanup;
590+
591+
if (XFWRITE(&st, 1, sizeof(st), partFile) != sizeof(st))
592+
goto cleanup;
593+
594+
cleanup:
595+
if (partFile != XBADFILE)
596+
XFCLOSE(partFile);
597+
}
598+
599+
void RAMFUNCTION wolfBoot_update_trigger(void)
600+
{
601+
set_partition_state_fs(IMG_STATE_UPDATING, PART_UPDATE);
602+
}
603+
604+
void RAMFUNCTION wolfBoot_success(void)
605+
{
606+
set_partition_state_fs(IMG_STATE_SUCCESS, PART_BOOT);
607+
}
608+
609+
int RAMFUNCTION wolfBoot_get_partition_state(uint8_t part, uint8_t *st)
610+
{
611+
const char* fileName = WOLFBOOT_PARTITION_FILENAME;
612+
XFILE partFile = XBADFILE;
613+
union {
614+
uint32_t num;
615+
byte buf[sizeof(uint32_t)];
616+
} magic;
617+
long offset;
618+
int ret = -1;
619+
620+
if (part == PART_BOOT)
621+
offset = PART_BOOT_ENDFLAGS;
622+
else if (part == PART_UPDATE)
623+
offset = PART_UPDATE_ENDFLAGS;
624+
else
625+
return -1;
626+
627+
partFile = XFOPEN(fileName, "rb");
628+
if (partFile == XBADFILE)
629+
goto cleanup;
630+
631+
if (XFSEEK(partFile, offset - sizeof(uint32_t), XSEEK_SET) != 0)
632+
goto cleanup;
633+
634+
if (XFREAD(magic.buf, 1, sizeof(magic.buf), partFile) != sizeof(magic.buf))
635+
goto cleanup;
636+
637+
if (magic.num != WOLFBOOT_MAGIC_TRAIL)
638+
goto cleanup;
639+
640+
if (XFSEEK(partFile, offset - sizeof(uint32_t) - 1, XSEEK_SET) != 0)
641+
goto cleanup;
642+
643+
if (XFREAD(st, 1, sizeof(*st), partFile) != sizeof(*st))
644+
goto cleanup;
645+
646+
ret = 0;
647+
cleanup:
648+
if (partFile != XBADFILE)
649+
XFCLOSE(partFile);
650+
return ret;
651+
}
652+
653+
#elif defined(WOLFBOOT_FIXED_PARTITIONS) /* WOLFBOOT_PARTITION_FILENAME */
548654
/**
549655
* @brief Get the magic trailer of a partition.
550656
*

0 commit comments

Comments
 (0)