mirror of https://github.com/wolfSSL/wolfBoot.git
260 lines
8.2 KiB
C
260 lines
8.2 KiB
C
/* library_fs.c
|
|
*
|
|
* Copyright (C) 2025 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfBoot.
|
|
*
|
|
* wolfBoot is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfBoot is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "image.h"
|
|
#include "printf.h"
|
|
#include "wolfboot/wolfboot.h"
|
|
|
|
|
|
/* Helper function to convert partition ID to string */
|
|
static const char* partition_name(uint8_t part)
|
|
{
|
|
switch (part) {
|
|
case PART_BOOT:
|
|
return "BOOT";
|
|
case PART_UPDATE:
|
|
return "UPDATE";
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
/* Helper function to convert state value to string */
|
|
static const char* partition_state_name(uint8_t state)
|
|
{
|
|
switch (state) {
|
|
case IMG_STATE_NEW:
|
|
return "NEW";
|
|
case IMG_STATE_UPDATING:
|
|
return "UPDATING";
|
|
case IMG_STATE_FINAL_FLAGS:
|
|
return "FFLAGS";
|
|
case IMG_STATE_TESTING:
|
|
return "TESTING";
|
|
case IMG_STATE_SUCCESS:
|
|
return "SUCCESS";
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
/* Print all partition states */
|
|
static int cmd_get_all_states(void)
|
|
{
|
|
uint32_t cur_fw_version, update_fw_version;
|
|
uint16_t hdrSz;
|
|
uint8_t boot_part_state = IMG_STATE_NEW, update_part_state = IMG_STATE_NEW;
|
|
|
|
cur_fw_version = wolfBoot_current_firmware_version();
|
|
update_fw_version = wolfBoot_update_firmware_version();
|
|
|
|
wolfBoot_get_partition_state(PART_BOOT, &boot_part_state);
|
|
wolfBoot_get_partition_state(PART_UPDATE, &update_part_state);
|
|
|
|
wolfBoot_printf("\n");
|
|
wolfBoot_printf("System information\n");
|
|
wolfBoot_printf("====================================\n");
|
|
wolfBoot_printf("Firmware version : 0x%lx\n",
|
|
(unsigned long)wolfBoot_current_firmware_version());
|
|
wolfBoot_printf("Current firmware state: %s\n",
|
|
partition_state_name(boot_part_state));
|
|
if (update_fw_version != 0) {
|
|
if (update_part_state == IMG_STATE_UPDATING) {
|
|
wolfBoot_printf("Candidate firmware version : 0x%lx\n",
|
|
(unsigned long)update_fw_version);
|
|
} else {
|
|
wolfBoot_printf("Backup firmware version : 0x%lx\n",
|
|
(unsigned long)update_fw_version);
|
|
}
|
|
wolfBoot_printf("Update state: %s\n",
|
|
partition_state_name(update_part_state));
|
|
if (update_fw_version > cur_fw_version) {
|
|
wolfBoot_printf("'reboot' to initiate update.\n");
|
|
} else {
|
|
wolfBoot_printf("Update image older than current.\n");
|
|
}
|
|
} else {
|
|
wolfBoot_printf("No image in update partition.\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_get_keystore(void)
|
|
{
|
|
int i, j;
|
|
uint32_t n_keys;
|
|
|
|
wolfBoot_printf("\n");
|
|
wolfBoot_printf("Bootloader keystore information\n");
|
|
wolfBoot_printf("====================================\n");
|
|
n_keys = keystore_num_pubkeys();
|
|
wolfBoot_printf("Number of public keys: %lu\n", (unsigned long)n_keys);
|
|
for (i = 0; i < (int)n_keys; i++) {
|
|
uint32_t size = keystore_get_size(i);
|
|
uint32_t type = keystore_get_key_type(i);
|
|
uint32_t mask = keystore_get_mask(i);
|
|
uint8_t *keybuf = keystore_get_buffer(i);
|
|
|
|
wolfBoot_printf("\n");
|
|
wolfBoot_printf(" Public Key #%d: size %lu, type %lx, mask %08lx\n", i,
|
|
(unsigned long)size, (unsigned long)type, (unsigned long)mask);
|
|
wolfBoot_printf(" ====================================\n ");
|
|
for (j = 0; j < (int)size; j++) {
|
|
wolfBoot_printf("%02X ", keybuf[j]);
|
|
if (j % 16 == 15) {
|
|
wolfBoot_printf("\n ");
|
|
}
|
|
}
|
|
wolfBoot_printf("\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Trigger an update */
|
|
static int cmd_update_trigger(void)
|
|
{
|
|
wolfBoot_printf("Triggering update...\n");
|
|
wolfBoot_update_trigger();
|
|
wolfBoot_printf("Update triggered successfully. UPDATE partition set to UPDATING state.\n");
|
|
return 0;
|
|
}
|
|
|
|
/* Mark current boot as successful */
|
|
static int cmd_success(void)
|
|
{
|
|
wolfBoot_printf("Marking BOOT partition as SUCCESS...\n");
|
|
wolfBoot_success();
|
|
wolfBoot_printf("BOOT partition marked as SUCCESS.\n");
|
|
return 0;
|
|
}
|
|
|
|
/* Print usage information */
|
|
static void print_usage(const char* prog_name)
|
|
{
|
|
wolfBoot_printf("wolfBoot Partition Manager CLI\n");
|
|
wolfBoot_printf("\nUsage: %s <command> [options]\n\n", prog_name);
|
|
wolfBoot_printf("Commands:\n");
|
|
wolfBoot_printf(" status - Show state of all partitions\n");
|
|
wolfBoot_printf(" keystore - Show keystore information\n");
|
|
wolfBoot_printf(" update-trigger - Trigger an update (sets UPDATE partition to UPDATING)\n");
|
|
wolfBoot_printf(" success - Mark BOOT partition as SUCCESS\n");
|
|
wolfBoot_printf(" verify-boot - Verify integrity and authenticity of BOOT partition\n");
|
|
wolfBoot_printf(" verify-update - Verify integrity and authenticity of UPDATE partition\n");
|
|
wolfBoot_printf(" help - Show this help message\n");
|
|
wolfBoot_printf("\nPartitions:\n");
|
|
wolfBoot_printf(" BOOT - Currently running firmware partition\n");
|
|
wolfBoot_printf(" UPDATE - Staging partition for new firmware\n");
|
|
wolfBoot_printf("\nExamples:\n");
|
|
wolfBoot_printf(" %s status - Display all partition states\n", prog_name);
|
|
wolfBoot_printf(" %s update-trigger - Stage an update for next boot\n", prog_name);
|
|
wolfBoot_printf(" %s success - Confirm current firmware is working\n", prog_name);
|
|
wolfBoot_printf("\n");
|
|
}
|
|
|
|
/* Verify integrity and authenticity of a partition */
|
|
static int cmd_verify(uint8_t part)
|
|
{
|
|
struct wolfBoot_image img;
|
|
int ret;
|
|
size_t img_size = 0;
|
|
|
|
ret = wolfBoot_open_image(&img, part);
|
|
if (ret < 0) {
|
|
wolfBoot_printf("Failed to open image header for %s partition (error: %d)\n",
|
|
partition_name(part), ret);
|
|
return -1;
|
|
}
|
|
|
|
ret = wolfBoot_verify_integrity(&img);
|
|
if (ret < 0) {
|
|
wolfBoot_printf("Integrity check failed for %s partition\n",
|
|
partition_name(part));
|
|
return -1;
|
|
}
|
|
|
|
ret = wolfBoot_verify_authenticity(&img);
|
|
if (ret < 0) {
|
|
wolfBoot_printf("Authenticity check failed for %s partition\n",
|
|
partition_name(part));
|
|
return -1;
|
|
}
|
|
|
|
wolfBoot_printf("%s partition: Integrity and authenticity verified.\n",
|
|
partition_name(part));
|
|
return ret;
|
|
}
|
|
|
|
int main(int argc, const char* argv[])
|
|
{
|
|
int ret = 0;
|
|
const char* prog_name = "lib-fs";
|
|
const char* command;
|
|
|
|
if (argc >= 1) {
|
|
prog_name = argv[0];
|
|
}
|
|
|
|
/* Check for argument count */
|
|
if (argc != 2) {
|
|
print_usage(prog_name);
|
|
return 1;
|
|
}
|
|
|
|
command = argv[1];
|
|
|
|
/* Process commands */
|
|
if (strcmp(command, "status") == 0) {
|
|
ret = cmd_get_all_states();
|
|
}
|
|
else if (strcmp(command, "keystore") == 0) {
|
|
ret = cmd_get_keystore();
|
|
}
|
|
else if (strcmp(command, "update-trigger") == 0) {
|
|
ret = cmd_update_trigger();
|
|
}
|
|
else if (strcmp(command, "success") == 0) {
|
|
ret = cmd_success();
|
|
}
|
|
else if (strcmp(command, "verify-boot") == 0) {
|
|
ret = cmd_verify(PART_BOOT);
|
|
}
|
|
else if (strcmp(command, "verify-update") == 0) {
|
|
ret = cmd_verify(PART_UPDATE);
|
|
}
|
|
else if (strcmp(command, "help") == 0 || strcmp(command, "--help") == 0 ||
|
|
strcmp(command, "-h") == 0) {
|
|
print_usage(argv[0]);
|
|
ret = 0;
|
|
}
|
|
else {
|
|
wolfBoot_printf("Error: Unknown command '%s'\n\n", command);
|
|
print_usage(argv[0]);
|
|
ret = 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|