mirror of https://github.com/wolfSSL/wolfBoot.git
Removed dependency on bootutil. Starting from a new clean-room update design
parent
281b460131
commit
6b3dfe2e69
11
Makefile
11
Makefile
|
|
@ -17,14 +17,11 @@ LSCRIPT:=hal/$(TARGET).ld
|
|||
|
||||
OBJS:= \
|
||||
./hal/$(TARGET).o \
|
||||
./lib/bootutil/src/loader.o \
|
||||
./lib/bootutil/src/image_validate.o \
|
||||
./lib/bootutil/src/bootutil_misc.o \
|
||||
./src/loader.o \
|
||||
./src/mem.o \
|
||||
./src/keys.o \
|
||||
./src/crypto.o \
|
||||
./src/wolfboot.o \
|
||||
./src/main.o \
|
||||
./src/image.o \
|
||||
./lib/wolfssl/wolfcrypt/src/sha256.o \
|
||||
./lib/wolfssl/wolfcrypt/src/hash.o \
|
||||
./lib/wolfssl/wolfcrypt/src/wolfmath.o \
|
||||
|
|
@ -41,12 +38,12 @@ ifeq ($(SIGN),ED25519)
|
|||
./lib/wolfssl/wolfcrypt/src/ed25519.o \
|
||||
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
|
||||
./src/ed25519_pub_key.o
|
||||
CFLAGS+=-DBOOT_SIGN_ED25519
|
||||
CFLAGS+=-DWOLFBOOT_SIGN_ED25519
|
||||
endif
|
||||
|
||||
ifeq ($(SIGN),EC256)
|
||||
OBJS+= ./ext/wolfssl/wolfcrypt/src/ecc.o
|
||||
CFLAGS+=-DBOOT_SIGN_EC256
|
||||
CFLAGS+=-DWOLFBOOT_SIGN_EC256
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
|
|
|
|||
22
NOTICE
22
NOTICE
|
|
@ -1,22 +0,0 @@
|
|||
wolfBoot - copyright (c) wolfSSL Inc.
|
||||
|
||||
wolfBoot is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2, as published by
|
||||
the Free Software Foundation.
|
||||
|
||||
wolfBoot, wolfSSL (formerly known as CyaSSL) and wolfCrypt are either licensed for use
|
||||
under the GPLv2 or a standard commercial license. For our users who cannot use
|
||||
wolfSSL under GPLv2, a commercial license to wolfBoot, wolfSSL and wolfCrypt is available.
|
||||
Please contact wolfSSL Inc. directly at:
|
||||
|
||||
Email: licensing@wolfssl.com
|
||||
Phone: +1 425 245-8247
|
||||
|
||||
More information can be found on the wolfSSL website at www.wolfssl.com.
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/)
|
||||
and previously released under the Apache License, Version 2.0.
|
||||
|
||||
Portions of this software were developed at
|
||||
Runtime Inc, copyright 2015 and previously released under the the Apache License, Version 2.0.
|
||||
|
|
@ -2,8 +2,7 @@
|
|||
wolfSSL Secure Bootloader
|
||||
|
||||
wolfBoot is a portable, OS-agnostic, secure bootloader solution for 32-bit microcontrollers,
|
||||
relying on wolfCrypt for firmware authentication, and a modified version of
|
||||
[mcuboot](https://www.mcuboot.com/)'s *bootutil* library to implement firmware upgrade mechanisms.
|
||||
relying on wolfCrypt for firmware authentication, providing firmware upgrade mechanisms.
|
||||
|
||||
Due to the minimalist design of the bootloader and the tiny HAL API, wolfBoot is completely independent
|
||||
from any OS or bare-metal application, and can be easily ported and integrated in existing embedded software
|
||||
|
|
@ -32,8 +31,9 @@ with no dynamic memory allocation mechanism or linkage to any standard C library
|
|||
|
||||
The core application depends on the following libraries:
|
||||
- wolfCrypt, which is used to verify the Ed25519 signature of the images
|
||||
- A modified version of mcuboot's bootutil, to handle the firmware image slots and the upgrade state-machine
|
||||
- A minimalist Hardware Abstraction Layer, with an implementation provided for the supported target, which is in charge for IAP flash access and clock setting on the specific MCU
|
||||
- The core bootloader
|
||||
- A small application library to interact with the bootloader
|
||||
|
||||
The goal of this application is to perform image verification and/or requested firmware upgrade tasks
|
||||
before chain-loading the actual firmware from a specific location in flash.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ In order to run wolfBoot on a target microcontroller, an implementation of the H
|
|||
must be provided.
|
||||
|
||||
The HAL only purposes are allowing write/erase operations from the bootloader
|
||||
and the application initiating the firmware upgrade through the bootutil library, and
|
||||
and the application initiating the firmware upgrade through the application library, and
|
||||
ensuring that the MCU is running at full speed during boot, to optimize the
|
||||
verification of the signatures.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
#ifndef H_BOOTUTIL_
|
||||
#define H_BOOTUTIL_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/** Attempt to boot the contents of slot 0. */
|
||||
#define BOOT_SWAP_TYPE_NONE 1
|
||||
|
||||
/** Swap to slot 1. Absent a confirm command, revert back on next boot. */
|
||||
#define BOOT_SWAP_TYPE_TEST 2
|
||||
|
||||
/** Swap to slot 1, and permanently switch to booting its contents. */
|
||||
#define BOOT_SWAP_TYPE_PERM 3
|
||||
|
||||
/** Swap back to alternate slot. A confirm changes this state to NONE. */
|
||||
#define BOOT_SWAP_TYPE_REVERT 4
|
||||
|
||||
/** Swap failed because image to be run is not valid */
|
||||
#define BOOT_SWAP_TYPE_FAIL 5
|
||||
|
||||
/** Swapping encountered an unrecoverable error */
|
||||
#define BOOT_SWAP_TYPE_PANIC 0xff
|
||||
|
||||
#define MAX_FLASH_ALIGN 8
|
||||
#define BOOT_MAX_ALIGN MAX_FLASH_ALIGN
|
||||
|
||||
struct image_header;
|
||||
/**
|
||||
* A response object provided by the boot loader code; indicates where to jump
|
||||
* to execute the main image.
|
||||
*/
|
||||
struct boot_rsp {
|
||||
/** A pointer to the header of the image to be executed. */
|
||||
const struct image_header *br_hdr;
|
||||
|
||||
/**
|
||||
* The flash offset of the image to execute. Indicates the position of
|
||||
* the image header within its flash device.
|
||||
*/
|
||||
uint8_t br_flash_dev_id;
|
||||
uint32_t br_image_off;
|
||||
};
|
||||
|
||||
/* This is not actually used by bootloader's code but can be used by apps
|
||||
* when attempting to read/write a trailer.
|
||||
*/
|
||||
struct image_trailer {
|
||||
uint8_t copy_done;
|
||||
uint8_t pad1[MAX_FLASH_ALIGN - 1];
|
||||
uint8_t image_ok;
|
||||
uint8_t pad2[MAX_FLASH_ALIGN - 1];
|
||||
uint8_t magic[16];
|
||||
};
|
||||
|
||||
/* you must have pre-allocated all the entries within this structure */
|
||||
int boot_go(struct boot_rsp *rsp);
|
||||
|
||||
int boot_swap_type(void);
|
||||
|
||||
int boot_set_pending(int permanent);
|
||||
int boot_set_confirmed(void);
|
||||
|
||||
#define SPLIT_GO_OK (0)
|
||||
#define SPLIT_GO_NON_MATCHING (-1)
|
||||
#define SPLIT_GO_ERR (-2)
|
||||
int
|
||||
split_go(int loader_slot, int split_slot, void **entry);
|
||||
|
||||
#endif
|
||||
136
include/flash.h
136
include/flash.h
|
|
@ -1,136 +0,0 @@
|
|||
/* flash_map.h
|
||||
*
|
||||
* Copyright (C) 2018 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 2 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
|
||||
*/
|
||||
|
||||
|
||||
#ifndef H_UTIL_FLASH_MAP_
|
||||
#define H_UTIL_FLASH_MAP_
|
||||
|
||||
/**
|
||||
*
|
||||
* System will contain a map which contains flash areas. Every
|
||||
* region will contain flash identifier, offset within flash and length.
|
||||
*
|
||||
* 1. This system map could be in a file within filesystem (Initializer
|
||||
* must know/figure out where the filesystem is at).
|
||||
* 2. Map could be at fixed location for project (compiled to code)
|
||||
* 3. Map could be at specific place in flash (put in place at mfg time).
|
||||
*
|
||||
* Note that the map you use must be valid for BSP it's for,
|
||||
* match the linker scripts when platform executes from flash,
|
||||
* and match the target offset specified in download script.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
|
||||
/**
|
||||
* @brief Structure describing an area on a flash device.
|
||||
*
|
||||
* Multiple flash devices may be available in the system, each of
|
||||
* which may have its own areas. For this reason, flash areas track
|
||||
* which flash device they are part of.
|
||||
*/
|
||||
struct flash_area {
|
||||
/**
|
||||
* This flash area's ID; unique in the system.
|
||||
*/
|
||||
uint8_t fa_id;
|
||||
|
||||
/**
|
||||
* ID of the flash device this area is a part of.
|
||||
*/
|
||||
uint8_t fa_device_id;
|
||||
|
||||
uint16_t pad16;
|
||||
|
||||
/**
|
||||
* This area's offset, relative to the beginning of its flash
|
||||
* device's storage.
|
||||
*/
|
||||
uint32_t fa_off;
|
||||
|
||||
/**
|
||||
* This area's size, in bytes.
|
||||
*/
|
||||
uint32_t fa_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure describing a sector within a flash area.
|
||||
*
|
||||
* Each sector has an offset relative to the start of its flash area
|
||||
* (NOT relative to the start of its flash device), and a size. A
|
||||
* flash area may contain sectors with different sizes.
|
||||
*/
|
||||
struct flash_sector {
|
||||
/**
|
||||
* Offset of this sector, from the start of its flash area (not device).
|
||||
*/
|
||||
uint32_t fs_off;
|
||||
|
||||
/**
|
||||
* Size of this sector, in bytes.
|
||||
*/
|
||||
uint32_t fs_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Retrieve a memory-mapped flash device's base address.
|
||||
*
|
||||
* On success, the address will be stored in the value pointed to by
|
||||
* ret.
|
||||
*
|
||||
* Returns 0 on success, or an error code on failure.
|
||||
*/
|
||||
int flash_device_base(uint8_t fd_id, uintptr_t *ret);
|
||||
|
||||
/*
|
||||
* Start using flash area.
|
||||
*/
|
||||
int flash_area_open(uint8_t id, const struct flash_area **);
|
||||
|
||||
void flash_area_close(const struct flash_area *);
|
||||
|
||||
/*
|
||||
* Read/write/erase. Offset is relative from beginning of flash area.
|
||||
*/
|
||||
int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
|
||||
uint32_t len);
|
||||
int flash_area_write(const struct flash_area *, uint32_t off, const void *src,
|
||||
uint32_t len);
|
||||
int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
|
||||
|
||||
/*
|
||||
* Alignment restriction for flash writes.
|
||||
*/
|
||||
uint8_t flash_area_align(const struct flash_area *);
|
||||
|
||||
/*
|
||||
* Given flash area ID, return info about sectors within the area.
|
||||
*/
|
||||
int flash_area_get_sectors(int fa_id, uint32_t *count,
|
||||
struct flash_sector *sectors);
|
||||
|
||||
int flash_area_id_from_image_slot(int slot);
|
||||
int flash_area_id_to_image_slot(int area_id);
|
||||
|
||||
/* Get the build number of the image stored at the begining of the given flash area */
|
||||
uint32_t flash_area_get_image_buildnum(const struct flash_area *fap);
|
||||
|
||||
#endif /* H_UTIL_FLASH_MAP_ */
|
||||
|
|
@ -1,30 +1,16 @@
|
|||
#ifndef H_TARGETS_TARGET_
|
||||
#define H_TARGETS_TARGET_
|
||||
|
||||
#define FLASH_DEV_NAME "flash"
|
||||
#define FLASH_ALIGN 4
|
||||
|
||||
/* Example flash partitioning.
|
||||
* Ensure that your firmware entry point is
|
||||
* at FLASH_AREA_IMAGE_0_OFFSET + 0x100
|
||||
*/
|
||||
#define FLASH_AREA_IMAGE_0_OFFSET 0x20000
|
||||
#define FLASH_AREA_IMAGE_0_SIZE 0x20000
|
||||
#define FLASH_AREA_IMAGE_1_OFFSET 0x40000
|
||||
#define FLASH_AREA_IMAGE_1_SIZE 0x20000
|
||||
#define FLASH_AREA_IMAGE_SCRATCH_OFFSET 0x60000
|
||||
#define FLASH_AREA_IMAGE_SCRATCH_SIZE 0x20000
|
||||
#define WOLFBOOT_SECTOR_SIZE 0x20000
|
||||
#define WOLFBOOT_PARTITION_SIZE 0x20000
|
||||
|
||||
/*
|
||||
* Sanity check the target support.
|
||||
*/
|
||||
#if !defined(FLASH_DEV_NAME) || \
|
||||
!defined(FLASH_ALIGN) || \
|
||||
!defined(FLASH_AREA_IMAGE_0_OFFSET) || \
|
||||
!defined(FLASH_AREA_IMAGE_0_SIZE) || \
|
||||
!defined(FLASH_AREA_IMAGE_1_OFFSET) || \
|
||||
!defined(FLASH_AREA_IMAGE_1_SIZE)
|
||||
#error "Target support is incomplete; cannot build wolfboot."
|
||||
#endif
|
||||
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x20000
|
||||
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x40000
|
||||
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x60000
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
#ifndef H_IMAGE_
|
||||
#define H_IMAGE_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
struct flash_area;
|
||||
|
||||
#define IMAGE_MAGIC 0x96f3b83d
|
||||
#define IMAGE_MAGIC_V1 0x96f3b83c
|
||||
#define IMAGE_MAGIC_NONE 0xffffffff
|
||||
#define IMAGE_TLV_INFO_MAGIC 0x6907
|
||||
|
||||
#define IMAGE_HEADER_SIZE 32
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
/*
|
||||
* Image header flags.
|
||||
*/
|
||||
#define IMAGE_F_PIC 0x00000001 /* Not supported. */
|
||||
#define IMAGE_F_NON_BOOTABLE 0x00000010 /* Split image app. */
|
||||
/*
|
||||
* Indicates that this image should be loaded into RAM instead of run
|
||||
* directly from flash. The address to load should be in the
|
||||
* ih_load_addr field of the header.
|
||||
*/
|
||||
#define IMAGE_F_RAM_LOAD 0x00000020
|
||||
|
||||
/*
|
||||
* ECSDA224 is with NIST P-224
|
||||
* ECSDA256 is with NIST P-256
|
||||
*/
|
||||
|
||||
/*
|
||||
* Image trailer TLV types.
|
||||
*
|
||||
* Signature is generated by computing signature over the image hash.
|
||||
* Currently the only image hash type is SHA256.
|
||||
*
|
||||
* Signature comes in the form of 2 TLVs.
|
||||
* 1st on identifies the public key which should be used to verify it.
|
||||
* 2nd one is the actual signature.
|
||||
*/
|
||||
#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
|
||||
#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
|
||||
#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */
|
||||
#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output */
|
||||
#define IMAGE_TLV_ECDSA256 0x22 /* ECDSA of hash output */
|
||||
#define IMAGE_TLV_ED25519 0x23 /* ED25519 of hash output */
|
||||
|
||||
struct PACKED image_version {
|
||||
uint8_t iv_major;
|
||||
uint8_t iv_minor;
|
||||
uint16_t iv_revision;
|
||||
uint32_t iv_build_num;
|
||||
};
|
||||
|
||||
/** Image header. All fields are in little endian byte order. */
|
||||
struct PACKED image_header {
|
||||
uint32_t ih_magic;
|
||||
uint32_t ih_load_addr;
|
||||
uint16_t ih_hdr_size; /* Size of image header (bytes). */
|
||||
uint16_t _pad1;
|
||||
uint32_t ih_img_size; /* Does not include header. */
|
||||
uint32_t ih_flags; /* IMAGE_F_[...]. */
|
||||
struct image_version ih_ver;
|
||||
uint32_t _pad2;
|
||||
};
|
||||
|
||||
/** Image TLV header. All fields in little endian. */
|
||||
struct PACKED image_tlv_info {
|
||||
uint16_t it_magic;
|
||||
uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */
|
||||
};
|
||||
|
||||
/** Image trailer TLV format. All fields in little endian. */
|
||||
struct PACKED image_tlv {
|
||||
uint8_t it_type; /* IMAGE_TLV_[...]. */
|
||||
uint8_t _pad;
|
||||
uint16_t it_len; /* Data length (not including TLV header). */
|
||||
};
|
||||
|
||||
int bootutil_img_validate(struct image_header *hdr,
|
||||
const struct flash_area *fap,
|
||||
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
|
||||
uint8_t *seed, int seed_len, uint8_t *out_hash);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef __BOOTUTIL_SIGN_KEY_H_
|
||||
#define __BOOTUTIL_SIGN_KEY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct bootutil_key {
|
||||
const uint8_t *key;
|
||||
const unsigned int *len;
|
||||
};
|
||||
|
||||
extern const struct bootutil_key bootutil_keys[];
|
||||
extern const int bootutil_key_cnt;
|
||||
|
||||
#endif /* __BOOTUTIL_SIGN_KEY_H_ */
|
||||
|
|
@ -1,801 +0,0 @@
|
|||
/* bootutil_misc.c
|
||||
*
|
||||
* Copyright (C) 2018 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 2 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
|
||||
*
|
||||
* **** This file incorporates work covered by the following copyright and ****
|
||||
* **** permission notice: ****
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "hal.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
#include "bootutil/image.h"
|
||||
#include "bootutil_priv.h"
|
||||
#include "bootutil.h"
|
||||
#include "target.h"
|
||||
|
||||
struct area {
|
||||
struct flash_area whole;
|
||||
struct flash_area *areas;
|
||||
uint32_t num_areas;
|
||||
uint8_t id;
|
||||
};
|
||||
|
||||
|
||||
struct area_desc {
|
||||
struct area slots[3];
|
||||
uint32_t num_slots;
|
||||
};
|
||||
|
||||
static struct area_desc flash_areas[1] = {
|
||||
{
|
||||
.slots = {
|
||||
{
|
||||
.whole = {
|
||||
.fa_id = FLASH_AREA_IMAGE_0,
|
||||
.fa_device_id = 0,
|
||||
.fa_off = FLASH_AREA_IMAGE_0_OFFSET,
|
||||
.fa_size = FLASH_AREA_IMAGE_0_SIZE,
|
||||
},
|
||||
.id = FLASH_AREA_IMAGE_0,
|
||||
.num_areas = 1
|
||||
},
|
||||
{
|
||||
.whole = {
|
||||
.fa_id = FLASH_AREA_IMAGE_1,
|
||||
.fa_device_id = 0,
|
||||
.fa_off = FLASH_AREA_IMAGE_1_OFFSET,
|
||||
.fa_size = FLASH_AREA_IMAGE_1_SIZE,
|
||||
},
|
||||
.id = FLASH_AREA_IMAGE_1,
|
||||
.num_areas = 1
|
||||
},
|
||||
#ifndef WOLFBOOT_OVERWRITE_ONLY
|
||||
{
|
||||
.whole = {
|
||||
.fa_id = FLASH_AREA_IMAGE_SCRATCH,
|
||||
.fa_device_id = 0,
|
||||
.fa_off = FLASH_AREA_IMAGE_SCRATCH_OFFSET,
|
||||
.fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE,
|
||||
},
|
||||
.id = FLASH_AREA_IMAGE_SCRATCH,
|
||||
.num_areas = 1
|
||||
}
|
||||
},
|
||||
.num_slots = 3
|
||||
#else
|
||||
},
|
||||
.num_slots = 2
|
||||
#endif
|
||||
}
|
||||
} ;
|
||||
|
||||
void boot_panic(void)
|
||||
{
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
|
||||
void boot_panic_unless(int x)
|
||||
{
|
||||
if(!x)
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
int boot_current_slot;
|
||||
|
||||
const uint32_t boot_img_magic[] = {
|
||||
0xf395c277,
|
||||
0x7fefd260,
|
||||
0x0f505235,
|
||||
0x8079b62c,
|
||||
};
|
||||
|
||||
#define BOOT_MAGIC_SZ (sizeof(boot_img_magic))
|
||||
#define BOOT_MAGIC_ARR_SZ (sizeof(boot_img_magic) / sizeof (uint32_t))
|
||||
|
||||
struct boot_swap_table {
|
||||
/** * For each field, a value of 0 means "any". */
|
||||
uint8_t magic_slot0;
|
||||
uint8_t magic_slot1;
|
||||
uint8_t image_ok_slot0;
|
||||
uint8_t image_ok_slot1;
|
||||
uint8_t copy_done_slot0;
|
||||
|
||||
uint8_t swap_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* This set of tables maps image trailer contents to swap operation type.
|
||||
* When searching for a match, these tables must be iterated sequentially.
|
||||
*
|
||||
* NOTE: the table order is very important. The settings in Slot 1 always
|
||||
* are priority to Slot 0 and should be located earlier in the table.
|
||||
*
|
||||
* The table lists only states where there is action needs to be taken by
|
||||
* the bootloader, as in starting/finishing a swap operation.
|
||||
*/
|
||||
static const struct boot_swap_table boot_swap_tables[] = {
|
||||
{
|
||||
.magic_slot0 = 0,
|
||||
.magic_slot1 = BOOT_MAGIC_GOOD,
|
||||
.image_ok_slot0 = 0,
|
||||
.image_ok_slot1 = 0xff,
|
||||
.copy_done_slot0 = 0,
|
||||
.swap_type = BOOT_SWAP_TYPE_TEST,
|
||||
},
|
||||
{
|
||||
.magic_slot0 = 0,
|
||||
.magic_slot1 = BOOT_MAGIC_GOOD,
|
||||
.image_ok_slot0 = 0,
|
||||
.image_ok_slot1 = 0x01,
|
||||
.copy_done_slot0 = 0,
|
||||
.swap_type = BOOT_SWAP_TYPE_PERM,
|
||||
},
|
||||
{
|
||||
.magic_slot0 = BOOT_MAGIC_GOOD,
|
||||
.magic_slot1 = BOOT_MAGIC_UNSET,
|
||||
.image_ok_slot0 = 0xff,
|
||||
.image_ok_slot1 = 0,
|
||||
.copy_done_slot0 = 0x01,
|
||||
.swap_type = BOOT_SWAP_TYPE_REVERT,
|
||||
},
|
||||
};
|
||||
|
||||
#define BOOT_SWAP_TABLES_COUNT \
|
||||
(sizeof boot_swap_tables / sizeof boot_swap_tables[0])
|
||||
|
||||
int
|
||||
boot_magic_code(const uint32_t *magic)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
|
||||
return BOOT_MAGIC_GOOD;
|
||||
}
|
||||
|
||||
for (i = 0; i < BOOT_MAGIC_SZ / sizeof *magic; i++) {
|
||||
if (magic[i] != 0xffffffff) {
|
||||
return BOOT_MAGIC_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
return BOOT_MAGIC_UNSET;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
boot_slots_trailer_sz(uint8_t min_write_sz)
|
||||
{
|
||||
return /* state for all sectors */
|
||||
BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
|
||||
BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */ +
|
||||
BOOT_MAGIC_SZ;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
boot_scratch_trailer_sz(uint8_t min_write_sz)
|
||||
{
|
||||
return BOOT_STATUS_STATE_COUNT * min_write_sz + /* state for one sector */
|
||||
BOOT_MAX_ALIGN * 2 + /* image_ok + swap_size */
|
||||
BOOT_MAGIC_SZ;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
boot_magic_off(const struct flash_area *fap)
|
||||
{
|
||||
boot_panic_unless(offsetof(struct image_trailer, magic) == 16);
|
||||
return fap->fa_size - BOOT_MAGIC_SZ;
|
||||
}
|
||||
|
||||
int
|
||||
boot_status_entries(const struct flash_area *fap)
|
||||
{
|
||||
switch (fap->fa_id) {
|
||||
case FLASH_AREA_IMAGE_0:
|
||||
case FLASH_AREA_IMAGE_1:
|
||||
return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
|
||||
case FLASH_AREA_IMAGE_SCRATCH:
|
||||
return BOOT_STATUS_STATE_COUNT;
|
||||
default:
|
||||
return BOOT_EBADARGS;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
boot_status_off(const struct flash_area *fap)
|
||||
{
|
||||
uint32_t off_from_end;
|
||||
uint8_t elem_sz;
|
||||
|
||||
elem_sz = flash_area_align(fap);
|
||||
|
||||
if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
|
||||
off_from_end = boot_scratch_trailer_sz(elem_sz);
|
||||
} else {
|
||||
off_from_end = boot_slots_trailer_sz(elem_sz);
|
||||
}
|
||||
|
||||
boot_panic_unless(off_from_end <= fap->fa_size);
|
||||
return fap->fa_size - off_from_end;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
boot_copy_done_off(const struct flash_area *fap)
|
||||
{
|
||||
boot_panic_unless(fap->fa_id != FLASH_AREA_IMAGE_SCRATCH);
|
||||
boot_panic_unless(offsetof(struct image_trailer, copy_done) == 0);
|
||||
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
boot_image_ok_off(const struct flash_area *fap)
|
||||
{
|
||||
boot_panic_unless(offsetof(struct image_trailer, image_ok) == 8);
|
||||
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
boot_swap_size_off(const struct flash_area *fap)
|
||||
{
|
||||
/*
|
||||
* The "swap_size" field if located just before the trailer.
|
||||
* The scratch slot doesn't store "copy_done"...
|
||||
*/
|
||||
if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
|
||||
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
|
||||
}
|
||||
|
||||
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
|
||||
}
|
||||
|
||||
int
|
||||
boot_read_swap_state(const struct flash_area *fap,
|
||||
struct boot_swap_state *state)
|
||||
{
|
||||
uint32_t magic[BOOT_MAGIC_ARR_SZ];
|
||||
uint32_t off;
|
||||
int rc;
|
||||
|
||||
off = boot_magic_off(fap);
|
||||
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
state->magic = boot_magic_code(magic);
|
||||
|
||||
if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
|
||||
off = boot_copy_done_off(fap);
|
||||
rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
}
|
||||
|
||||
off = boot_image_ok_off(fap);
|
||||
rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the image trailer from the scratch area.
|
||||
*/
|
||||
int
|
||||
boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
|
||||
{
|
||||
const struct flash_area *fap;
|
||||
int rc;
|
||||
|
||||
switch (flash_area_id) {
|
||||
case FLASH_AREA_IMAGE_SCRATCH:
|
||||
case FLASH_AREA_IMAGE_0:
|
||||
case FLASH_AREA_IMAGE_1:
|
||||
rc = flash_area_open(flash_area_id, &fap);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return BOOT_EBADARGS;
|
||||
}
|
||||
|
||||
rc = boot_read_swap_state(fap, state);
|
||||
flash_area_close(fap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
boot_read_swap_size(uint32_t *swap_size)
|
||||
{
|
||||
uint32_t magic[BOOT_MAGIC_ARR_SZ];
|
||||
uint32_t off;
|
||||
const struct flash_area *fap;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* In the middle a swap, tries to locate the saved swap size. Looks
|
||||
* for a valid magic, first on Slot 0, then on scratch. Both "slots"
|
||||
* can end up being temporary storage for a swap and it is assumed
|
||||
* that if magic is valid then swap size is too, because magic is
|
||||
* always written in the last step.
|
||||
*/
|
||||
|
||||
rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
|
||||
off = boot_magic_off(fap);
|
||||
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
|
||||
if (rc != 0) {
|
||||
rc = BOOT_EFLASH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
|
||||
/*
|
||||
* If Slot 0 's magic is not valid, try scratch...
|
||||
*/
|
||||
|
||||
flash_area_close(fap);
|
||||
|
||||
rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
|
||||
off = boot_magic_off(fap);
|
||||
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
|
||||
if (rc != 0) {
|
||||
rc = BOOT_EFLASH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
boot_panic_unless(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
|
||||
}
|
||||
|
||||
off = boot_swap_size_off(fap);
|
||||
rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
|
||||
if (rc != 0) {
|
||||
rc = BOOT_EFLASH;
|
||||
}
|
||||
|
||||
out:
|
||||
flash_area_close(fap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
boot_write_magic(const struct flash_area *fap)
|
||||
{
|
||||
uint32_t off;
|
||||
int rc;
|
||||
|
||||
off = boot_magic_off(fap);
|
||||
|
||||
rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
boot_write_flag(int flag, const struct flash_area *fap)
|
||||
{
|
||||
uint32_t off;
|
||||
int rc;
|
||||
uint8_t buf[BOOT_MAX_ALIGN];
|
||||
uint8_t align;
|
||||
|
||||
switch (flag) {
|
||||
case BOOT_FLAG_COPY_DONE:
|
||||
off = boot_copy_done_off(fap);
|
||||
break;
|
||||
case BOOT_FLAG_IMAGE_OK:
|
||||
off = boot_image_ok_off(fap);
|
||||
break;
|
||||
default:
|
||||
return BOOT_EBADARGS;
|
||||
}
|
||||
|
||||
align = flash_area_align(fap);
|
||||
boot_panic_unless(align <= BOOT_MAX_ALIGN);
|
||||
memset(buf, 0xFF, BOOT_MAX_ALIGN);
|
||||
buf[0] = BOOT_FLAG_SET;
|
||||
|
||||
rc = flash_area_write(fap, off, buf, align);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
boot_write_copy_done(const struct flash_area *fap)
|
||||
{
|
||||
return boot_write_flag(BOOT_FLAG_COPY_DONE, fap);
|
||||
}
|
||||
|
||||
int
|
||||
boot_write_image_ok(const struct flash_area *fap)
|
||||
{
|
||||
return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
|
||||
}
|
||||
|
||||
int
|
||||
boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
|
||||
{
|
||||
uint32_t off;
|
||||
int rc;
|
||||
uint8_t buf[BOOT_MAX_ALIGN];
|
||||
uint8_t align;
|
||||
|
||||
off = boot_swap_size_off(fap);
|
||||
align = flash_area_align(fap);
|
||||
boot_panic_unless(align <= BOOT_MAX_ALIGN);
|
||||
if (align < sizeof swap_size) {
|
||||
align = sizeof swap_size;
|
||||
}
|
||||
memset(buf, 0xFF, BOOT_MAX_ALIGN);
|
||||
memcpy(buf, (uint8_t *)&swap_size, sizeof swap_size);
|
||||
|
||||
rc = flash_area_write(fap, off, buf, align);
|
||||
if (rc != 0) {
|
||||
return BOOT_EFLASH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
boot_swap_type(void)
|
||||
{
|
||||
const struct boot_swap_table *table;
|
||||
struct boot_swap_state slot0;
|
||||
struct boot_swap_state slot1;
|
||||
int rc;
|
||||
size_t i;
|
||||
|
||||
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &slot0);
|
||||
if (rc) {
|
||||
return BOOT_SWAP_TYPE_PANIC;
|
||||
}
|
||||
|
||||
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &slot1);
|
||||
if (rc) {
|
||||
return BOOT_SWAP_TYPE_PANIC;
|
||||
}
|
||||
|
||||
for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
|
||||
table = boot_swap_tables + i;
|
||||
|
||||
if ((!table->magic_slot0 || table->magic_slot0 == slot0.magic ) &&
|
||||
(!table->magic_slot1 || table->magic_slot1 == slot1.magic ) &&
|
||||
(!table->image_ok_slot0 || table->image_ok_slot0 == slot0.image_ok ) &&
|
||||
(!table->image_ok_slot1 || table->image_ok_slot1 == slot1.image_ok ) &&
|
||||
(!table->copy_done_slot0 || table->copy_done_slot0 == slot0.copy_done)) {
|
||||
wolfBoot_printf("Swap type: %s",
|
||||
table->swap_type == BOOT_SWAP_TYPE_TEST ? "test" :
|
||||
table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
|
||||
table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
|
||||
"BUG; can't happen");
|
||||
boot_panic_unless(table->swap_type == BOOT_SWAP_TYPE_TEST ||
|
||||
table->swap_type == BOOT_SWAP_TYPE_PERM ||
|
||||
table->swap_type == BOOT_SWAP_TYPE_REVERT);
|
||||
return table->swap_type;
|
||||
}
|
||||
}
|
||||
|
||||
wolfBoot_printf("Swap type: none");
|
||||
return BOOT_SWAP_TYPE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the image in slot 1 as pending. On the next reboot, the system will
|
||||
* perform a one-time boot of the slot 1 image.
|
||||
*
|
||||
* @param permanent Whether the image should be used permanently or
|
||||
* only tested once:
|
||||
* 0=run image once, then confirm or revert.
|
||||
* 1=run image forever.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int
|
||||
boot_set_pending(int permanent)
|
||||
{
|
||||
const struct flash_area *fap;
|
||||
struct boot_swap_state state_slot1;
|
||||
int rc;
|
||||
|
||||
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &state_slot1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch (state_slot1.magic) {
|
||||
case BOOT_MAGIC_GOOD:
|
||||
/* Swap already scheduled. */
|
||||
return 0;
|
||||
|
||||
case BOOT_MAGIC_UNSET:
|
||||
rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
|
||||
if (rc != 0) {
|
||||
rc = BOOT_EFLASH;
|
||||
} else {
|
||||
rc = boot_write_magic(fap);
|
||||
}
|
||||
|
||||
if (rc == 0 && permanent) {
|
||||
rc = boot_write_image_ok(fap);
|
||||
}
|
||||
|
||||
flash_area_close(fap);
|
||||
return rc;
|
||||
|
||||
default:
|
||||
/* XXX: Temporary boot_panic_unless. */
|
||||
boot_panic_unless(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the image in slot 0 as confirmed. The system will continue booting into the image in slot 0 until told to boot from a different slot.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int
|
||||
boot_set_confirmed(void)
|
||||
{
|
||||
const struct flash_area *fap;
|
||||
struct boot_swap_state state_slot0;
|
||||
int rc;
|
||||
|
||||
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch (state_slot0.magic) {
|
||||
case BOOT_MAGIC_GOOD:
|
||||
/* Confirm needed; proceed. */
|
||||
break;
|
||||
|
||||
case BOOT_MAGIC_UNSET:
|
||||
/* Already confirmed. */
|
||||
return 0;
|
||||
|
||||
case BOOT_MAGIC_BAD:
|
||||
/* Unexpected state. */
|
||||
return BOOT_EBADVECT;
|
||||
}
|
||||
|
||||
if (state_slot0.copy_done == BOOT_FLAG_UNSET) {
|
||||
/* Swap never completed. This is unexpected. */
|
||||
return BOOT_EBADVECT;
|
||||
}
|
||||
|
||||
if (state_slot0.image_ok != BOOT_FLAG_UNSET) {
|
||||
/* Already confirmed. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
|
||||
if (rc) {
|
||||
rc = BOOT_EFLASH;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = boot_write_image_ok(fap);
|
||||
if (rc != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
done:
|
||||
flash_area_close(fap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
uint8_t flash_area_align(const struct flash_area *area)
|
||||
{
|
||||
(void)area;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flash_area_open(uint8_t id, const struct flash_area **area)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (flash_areas->slots[i].id == id)
|
||||
break;
|
||||
}
|
||||
if (i == flash_areas->num_slots) {
|
||||
wolfBoot_printf("Unsupported area\n");
|
||||
boot_panic();
|
||||
}
|
||||
*area = &flash_areas->slots[i].whole;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flash_area_close(const struct flash_area *area)
|
||||
{
|
||||
(void)area;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read/write/erase. Offset is relative from beginning of flash area.
|
||||
*/
|
||||
int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
|
||||
uint32_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t *src8, *dst8;
|
||||
wolfBoot_printf("%s: area=%d, off=%x, len=%x",
|
||||
__func__, area->fa_id, off, len);
|
||||
if (!area)
|
||||
return -1;
|
||||
if ((off + len) > (area->fa_size))
|
||||
return -1;
|
||||
src8 = (uint8_t *)(area->fa_off + off);
|
||||
dst8 = (uint8_t *)dst;
|
||||
for (i = 0; i < len; i++) {
|
||||
dst8[i] = src8[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
|
||||
uint32_t len)
|
||||
{
|
||||
wolfBoot_printf("%s: area=%d, off=%x, len=%x", __func__,
|
||||
area->fa_id, off, len);
|
||||
hal_flash_unlock();
|
||||
hal_flash_write(area->fa_off + off, src, len);
|
||||
hal_flash_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
|
||||
{
|
||||
wolfBoot_printf("%s: area=%d, off=%x, len=%x", __func__,
|
||||
area->fa_id, off, len);
|
||||
hal_flash_unlock();
|
||||
hal_flash_erase(area->fa_off + off, len);
|
||||
hal_flash_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
|
||||
{
|
||||
uint32_t i;
|
||||
struct area *slot;
|
||||
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (flash_areas->slots[i].id == idx)
|
||||
break;
|
||||
}
|
||||
if (i == flash_areas->num_slots) {
|
||||
wolfBoot_printf("Unsupported area\n");
|
||||
boot_panic();
|
||||
}
|
||||
|
||||
slot = &flash_areas->slots[i];
|
||||
|
||||
if (slot->num_areas > (uint32_t)*cnt) {
|
||||
wolfBoot_printf("Too many areas in slot\n");
|
||||
boot_panic();
|
||||
}
|
||||
|
||||
if (slot->num_areas == 1) {
|
||||
slot->areas = &slot->whole;
|
||||
}
|
||||
|
||||
*cnt = slot->num_areas;
|
||||
memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_area_get_sectors(int fa_id, uint32_t *count,
|
||||
struct flash_sector *sectors)
|
||||
{
|
||||
uint32_t i;
|
||||
struct area *slot;
|
||||
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (flash_areas->slots[i].id == fa_id)
|
||||
break;
|
||||
}
|
||||
if (i == flash_areas->num_slots) {
|
||||
wolfBoot_printf("Unsupported area\n");
|
||||
boot_panic();
|
||||
}
|
||||
|
||||
slot = &flash_areas->slots[i];
|
||||
|
||||
if (slot->num_areas > *count) {
|
||||
wolfBoot_printf("Too many areas in slot\n");
|
||||
boot_panic();
|
||||
}
|
||||
|
||||
*count = slot->num_areas;
|
||||
if (slot->num_areas == 1) {
|
||||
sectors[0].fs_off = slot->whole.fa_off;
|
||||
sectors[0].fs_size = slot->whole.fa_size;
|
||||
} else {
|
||||
for (i = 0; i < slot->num_areas; i++) {
|
||||
sectors[i].fs_off = slot->areas[i].fa_off -
|
||||
slot->whole.fa_off;
|
||||
sectors[i].fs_size = slot->areas[i].fa_size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_area_id_from_image_slot(int slot)
|
||||
{
|
||||
return slot + FLASH_AREA_IMAGE_0;
|
||||
}
|
||||
|
||||
uint8_t flash_area_erased_val(const struct flash_area *fap)
|
||||
{
|
||||
(void)fap;
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
uint32_t flash_area_get_image_buildnum(const struct flash_area *fap)
|
||||
{
|
||||
struct image_header *hdr = (struct image_header *)(fap->fa_off);
|
||||
return hdr->ih_ver.iv_build_num;
|
||||
}
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
/* bootutil_priv.h
|
||||
*
|
||||
* Copyright (C) 2018 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 2 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
|
||||
*/
|
||||
|
||||
#ifndef H_BOOTUTIL_PRIV_
|
||||
#define H_BOOTUTIL_PRIV_
|
||||
|
||||
|
||||
#include "flash_map_backend.h"
|
||||
|
||||
#include "bootutil/image.h"
|
||||
|
||||
#ifndef BOOT_MAX_IMG_SECTORS
|
||||
# define BOOT_MAX_IMG_SECTORS (32)
|
||||
#endif
|
||||
|
||||
extern void boot_panic(void);
|
||||
extern void boot_panic_unless(int x);
|
||||
|
||||
#define FLASH_AREA_IMAGE_0 1
|
||||
#define FLASH_AREA_IMAGE_1 2
|
||||
#define FLASH_AREA_IMAGE_SCRATCH 3
|
||||
|
||||
|
||||
struct flash_area;
|
||||
|
||||
#define BOOT_EFLASH 1
|
||||
#define BOOT_EFILE 2
|
||||
#define BOOT_EBADIMAGE 3
|
||||
#define BOOT_EBADVECT 4
|
||||
#define BOOT_EBADSTATUS 5
|
||||
#define BOOT_ENOMEM 6
|
||||
#define BOOT_EBADARGS 7
|
||||
|
||||
#define BOOT_TMPBUF_SZ 256
|
||||
|
||||
/*
|
||||
* Maintain state of copy progress.
|
||||
*/
|
||||
struct boot_status {
|
||||
uint32_t idx; /* Which area we're operating on */
|
||||
uint8_t state; /* Which part of the swapping process are we at */
|
||||
uint8_t use_scratch; /* Are status bytes ever written to scratch? */
|
||||
uint32_t swap_size; /* Total size of swapped image */
|
||||
};
|
||||
|
||||
#define BOOT_MAGIC_GOOD 1
|
||||
#define BOOT_MAGIC_BAD 2
|
||||
#define BOOT_MAGIC_UNSET 3
|
||||
|
||||
/**
|
||||
* End-of-image slot structure.
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* ~ ~
|
||||
* ~ Swap status (variable, aligned) ~
|
||||
* ~ ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Swap size |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* ~ 0xff padding (MAX ALIGN - 4) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Copy done | 0xff padding (MAX ALIGN - 1) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Image OK | 0xff padding (MAX ALIGN - 1) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* ~ MAGIC (16 octets) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
extern const uint32_t boot_img_magic[4];
|
||||
|
||||
struct boot_swap_state {
|
||||
uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */
|
||||
uint8_t copy_done;
|
||||
uint8_t image_ok;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The current flashmap API does not check the amount of space allocated when
|
||||
* loading sector data from the flash device, allowing for smaller counts here
|
||||
* would most surely incur in overruns.
|
||||
*
|
||||
* TODO: make flashmap API receive the current sector array size.
|
||||
*/
|
||||
#if BOOT_MAX_IMG_SECTORS < 32
|
||||
#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
|
||||
#endif
|
||||
|
||||
/** Number of image slots in flash; currently limited to two. */
|
||||
#define BOOT_NUM_SLOTS 2
|
||||
|
||||
/** Maximum number of image sectors supported by the bootloader. */
|
||||
#define BOOT_STATUS_STATE_COUNT 3
|
||||
#define BOOT_STATUS_MAX_ENTRIES BOOT_MAX_IMG_SECTORS
|
||||
|
||||
#define BOOT_STATUS_SOURCE_NONE 0
|
||||
#define BOOT_STATUS_SOURCE_SCRATCH 1
|
||||
#define BOOT_STATUS_SOURCE_SLOT0 2
|
||||
|
||||
#define BOOT_FLAG_IMAGE_OK 0
|
||||
#define BOOT_FLAG_COPY_DONE 1
|
||||
|
||||
#define BOOT_FLAG_SET 0x01
|
||||
#define BOOT_FLAG_UNSET 0xff
|
||||
|
||||
extern const uint32_t BOOT_MAGIC_SZ;
|
||||
|
||||
/**
|
||||
* Compatibility shim for flash sector type.
|
||||
*
|
||||
* This can be deleted when flash_area_to_sectors() is removed.
|
||||
*/
|
||||
typedef struct flash_sector boot_sector_t;
|
||||
|
||||
/** Private state maintained during boot. */
|
||||
struct boot_loader_state {
|
||||
struct {
|
||||
struct image_header hdr;
|
||||
const struct flash_area *area;
|
||||
boot_sector_t *sectors;
|
||||
size_t num_sectors;
|
||||
} imgs[BOOT_NUM_SLOTS];
|
||||
|
||||
const struct flash_area *scratch_area;
|
||||
|
||||
uint8_t write_sz;
|
||||
};
|
||||
|
||||
int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
|
||||
size_t slen, uint8_t key_id);
|
||||
|
||||
uint32_t boot_slots_trailer_sz(uint8_t min_write_sz);
|
||||
int boot_status_entries(const struct flash_area *fap);
|
||||
uint32_t boot_status_off(const struct flash_area *fap);
|
||||
int boot_read_swap_state(const struct flash_area *fap,
|
||||
struct boot_swap_state *state);
|
||||
int boot_read_swap_state_by_id(int flash_area_id,
|
||||
struct boot_swap_state *state);
|
||||
int boot_write_magic(const struct flash_area *fap);
|
||||
int boot_write_status(struct boot_status *bs);
|
||||
int boot_schedule_test_swap(void);
|
||||
int boot_write_copy_done(const struct flash_area *fap);
|
||||
int boot_write_image_ok(const struct flash_area *fap);
|
||||
int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
|
||||
int boot_read_swap_size(uint32_t *swap_size);
|
||||
|
||||
/*
|
||||
* Accessors for the contents of struct boot_loader_state.
|
||||
*/
|
||||
|
||||
/* These are macros so they can be used as lvalues. */
|
||||
#define BOOT_IMG_AREA(state, slot) ((state)->imgs[(slot)].area)
|
||||
#define BOOT_SCRATCH_AREA(state) ((state)->scratch_area)
|
||||
#define BOOT_WRITE_SZ(state) ((state)->write_sz)
|
||||
|
||||
static inline struct image_header*
|
||||
boot_img_hdr(struct boot_loader_state *state, size_t slot)
|
||||
{
|
||||
return &state->imgs[slot].hdr;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
boot_img_num_sectors(struct boot_loader_state *state, size_t slot)
|
||||
{
|
||||
return state->imgs[slot].num_sectors;
|
||||
}
|
||||
|
||||
/*
|
||||
* Offset of the slot from the beginning of the flash device.
|
||||
*/
|
||||
static inline uint32_t
|
||||
boot_img_slot_off(struct boot_loader_state *state, size_t slot)
|
||||
{
|
||||
return state->imgs[slot].area->fa_off;
|
||||
}
|
||||
|
||||
static inline size_t boot_scratch_area_size(struct boot_loader_state *state)
|
||||
{
|
||||
return state->scratch_area->fa_size;
|
||||
}
|
||||
|
||||
|
||||
static inline size_t
|
||||
boot_img_sector_size(struct boot_loader_state *state,
|
||||
size_t slot, size_t sector)
|
||||
{
|
||||
return state->imgs[slot].sectors[sector].fs_size;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
boot_img_sector_off(struct boot_loader_state *state, size_t slot,
|
||||
size_t sector)
|
||||
{
|
||||
return state->imgs[slot].sectors[sector].fs_off -
|
||||
state->imgs[slot].sectors[0].fs_off;
|
||||
}
|
||||
|
||||
static inline int
|
||||
boot_initialize_area(struct boot_loader_state *state, int flash_area)
|
||||
{
|
||||
uint32_t num_sectors;
|
||||
struct flash_sector *out_sectors;
|
||||
size_t *out_num_sectors;
|
||||
int rc;
|
||||
|
||||
switch (flash_area) {
|
||||
case FLASH_AREA_IMAGE_0:
|
||||
num_sectors = BOOT_MAX_IMG_SECTORS;
|
||||
out_sectors = state->imgs[0].sectors;
|
||||
out_num_sectors = &state->imgs[0].num_sectors;
|
||||
break;
|
||||
case FLASH_AREA_IMAGE_1:
|
||||
num_sectors = BOOT_MAX_IMG_SECTORS;
|
||||
out_sectors = state->imgs[1].sectors;
|
||||
out_num_sectors = &state->imgs[1].num_sectors;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
*out_num_sectors = num_sectors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* flash_map_backend.h
|
||||
*
|
||||
* Copyright (C) 2018 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 2 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
|
||||
*/
|
||||
|
||||
#ifndef __FLASH_MAP_BACKEND_H__
|
||||
#define __FLASH_MAP_BACKEND_H__
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides abstraction of flash regions for type of use.
|
||||
* I.e. dude where's my image?
|
||||
*
|
||||
* System will contain a map which contains flash areas. Every
|
||||
* region will contain flash identifier, offset within flash and length.
|
||||
*
|
||||
* 1. This system map could be in a file within filesystem (Initializer
|
||||
* must know/figure out where the filesystem is at).
|
||||
* 2. Map could be at fixed location for project (compiled to code)
|
||||
* 3. Map could be at specific place in flash (put in place at mfg time).
|
||||
*
|
||||
* Note that the map you use must be valid for BSP it's for,
|
||||
* match the linker scripts when platform executes from flash,
|
||||
* and match the target offset specified in download script.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Retrieve the flash device with the given name.
|
||||
*
|
||||
* Returns the flash device on success, or NULL on failure.
|
||||
*/
|
||||
struct device *flash_device_get_binding(char *dev_name);
|
||||
|
||||
/*
|
||||
* Retrieve a memory-mapped flash device's base address.
|
||||
*
|
||||
* On success, the address will be stored in the value pointed to by
|
||||
* ret.
|
||||
*
|
||||
* Returns 0 on success, or an error code on failure.
|
||||
*/
|
||||
int flash_device_base(uint8_t fd_id, uintptr_t *ret);
|
||||
|
||||
int flash_area_id_from_image_slot(int slot);
|
||||
|
||||
/* Retrieve the flash sector a given offset belongs to.
|
||||
*
|
||||
* Returns 0 on success, or an error code on failure.
|
||||
*/
|
||||
int flash_area_sector_from_off(off_t off, struct flash_sector *sector);
|
||||
|
||||
uint8_t flash_area_erased_val(const struct flash_area *fap);
|
||||
|
||||
|
||||
#endif /* __FLASH_MAP_BACKEND_H__ */
|
||||
|
|
@ -1,273 +0,0 @@
|
|||
/* image_validate.c
|
||||
*
|
||||
* Copyright (C) 2018 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 2 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
|
||||
*
|
||||
* **** This file incorporates work covered by the following copyright and ****
|
||||
* **** permission notice: ****
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#include "bootutil/image.h"
|
||||
#include "bootutil/sign_key.h"
|
||||
#include "wolfssl/wolfcrypt/sha256.h"
|
||||
|
||||
#include "wolfssl/ssl.h"
|
||||
|
||||
#include "bootutil_priv.h"
|
||||
|
||||
/*
|
||||
* Compute SHA256 over the image.
|
||||
*/
|
||||
static int
|
||||
bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap,
|
||||
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
|
||||
uint8_t *hash_result, uint8_t *seed, int seed_len)
|
||||
{
|
||||
wc_Sha256 sha256_ctx;
|
||||
uint32_t blk_sz;
|
||||
uint32_t size;
|
||||
uint32_t off;
|
||||
int rc;
|
||||
|
||||
wc_InitSha256(&sha256_ctx);
|
||||
|
||||
/* in some cases (split image) the hash is seeded with data from
|
||||
* the loader image */
|
||||
if (seed && (seed_len > 0)) {
|
||||
wc_Sha256Update(&sha256_ctx, seed, seed_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash is computed over image header and image itself. No TLV is
|
||||
* included ATM.
|
||||
*/
|
||||
size = hdr->ih_img_size + hdr->ih_hdr_size;
|
||||
for (off = 0; off < size; off += blk_sz) {
|
||||
blk_sz = size - off;
|
||||
if (blk_sz > tmp_buf_sz) {
|
||||
blk_sz = tmp_buf_sz;
|
||||
}
|
||||
rc = flash_area_read(fap, off, tmp_buf, blk_sz);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
wc_Sha256Update(&sha256_ctx, tmp_buf, blk_sz);
|
||||
}
|
||||
wc_Sha256Final(&sha256_ctx, hash_result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently, we only support being able to verify one type of
|
||||
* signature, because there is a single verification function that we
|
||||
* call. List the type of TLV we are expecting. If we aren't
|
||||
* configured for any signature, don't define this macro.
|
||||
*/
|
||||
#if defined(BOOT_SIGN_RSA)
|
||||
# define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS
|
||||
# define EXPECTED_SIG_LEN(x) ((x) == 256) /* 2048 bits */
|
||||
# if defined(BOOT_SIGN_EC) || defined(BOOT_SIGN_EC256)
|
||||
# error "Multiple signature types not yet supported"
|
||||
# endif
|
||||
#elif defined(BOOT_SIGN_EC)
|
||||
# define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA224
|
||||
# define EXPECTED_SIG_LEN(x) ((x) >= 64) /* oids + 2 * 28 bytes */
|
||||
# if defined(BOOT_SIGN_EC256)
|
||||
# error "Multiple signature types not yet supported"
|
||||
# endif
|
||||
#elif defined(BOOT_SIGN_EC256)
|
||||
# define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA256
|
||||
# define EXPECTED_SIG_LEN(x) ((x) >= 72) /* oids + 2 * 32 bytes */
|
||||
#elif defined(BOOT_SIGN_ED25519)
|
||||
# define EXPECTED_SIG_TLV IMAGE_TLV_ED25519
|
||||
# define EXPECTED_SIG_LEN(x) ((x) == 64)
|
||||
#endif
|
||||
|
||||
#ifdef EXPECTED_SIG_TLV
|
||||
extern void boot_panic_unless(int);
|
||||
static int
|
||||
bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
|
||||
{
|
||||
wc_Sha256 sha256_ctx;
|
||||
int i;
|
||||
const struct bootutil_key *key;
|
||||
uint8_t hash[32];
|
||||
|
||||
boot_panic_unless(keyhash_len <= 32);
|
||||
|
||||
for (i = 0; i < bootutil_key_cnt; i++) {
|
||||
key = &bootutil_keys[i];
|
||||
wc_InitSha256(&sha256_ctx);
|
||||
wc_Sha256Update(&sha256_ctx, key->key, *key->len);
|
||||
wc_Sha256Final(&sha256_ctx, hash);
|
||||
if (!memcmp(hash, keyhash, keyhash_len)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Verify the integrity of the image.
|
||||
* Return non-zero if image could not be validated/does not validate.
|
||||
*/
|
||||
int
|
||||
bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
|
||||
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
|
||||
uint8_t *seed, int seed_len, uint8_t *out_hash)
|
||||
{
|
||||
uint32_t off;
|
||||
uint32_t end;
|
||||
int sha256_valid = 0;
|
||||
struct image_tlv_info info;
|
||||
#ifdef EXPECTED_SIG_TLV
|
||||
int valid_signature = 0;
|
||||
int key_id = -1;
|
||||
#endif
|
||||
struct image_tlv tlv;
|
||||
uint8_t buf[256];
|
||||
uint8_t hash[32];
|
||||
int rc;
|
||||
|
||||
rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
|
||||
seed, seed_len);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (out_hash) {
|
||||
memcpy(out_hash, hash, 32);
|
||||
}
|
||||
|
||||
/* The TLVs come after the image. */
|
||||
/* After image there are TLVs. */
|
||||
off = hdr->ih_img_size + hdr->ih_hdr_size;
|
||||
|
||||
rc = flash_area_read(fap, off, &info, sizeof(info));
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
|
||||
return -1;
|
||||
}
|
||||
end = off + info.it_tlv_tot;
|
||||
off += sizeof(info);
|
||||
|
||||
/*
|
||||
* Traverse through all of the TLVs, performing any checks we know
|
||||
* and are able to do.
|
||||
*/
|
||||
for (; off < end; off += sizeof(tlv) + tlv.it_len) {
|
||||
rc = flash_area_read(fap, off, &tlv, sizeof tlv);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (tlv.it_type == IMAGE_TLV_SHA256) {
|
||||
/*
|
||||
* Verify the SHA256 image hash. This must always be
|
||||
* present.
|
||||
*/
|
||||
if (tlv.it_len != sizeof(hash)) {
|
||||
return -1;
|
||||
}
|
||||
rc = flash_area_read(fap, off + sizeof(tlv), buf, sizeof hash);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
if (memcmp(hash, buf, sizeof(hash))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sha256_valid = 1;
|
||||
#ifdef EXPECTED_SIG_TLV
|
||||
} else if (tlv.it_type == IMAGE_TLV_KEYHASH) {
|
||||
/*
|
||||
* Determine which key we should be checking.
|
||||
*/
|
||||
if (tlv.it_len > 32) {
|
||||
return -1;
|
||||
}
|
||||
rc = flash_area_read(fap, off + sizeof tlv, buf, tlv.it_len);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
key_id = bootutil_find_key(buf, tlv.it_len);
|
||||
/*
|
||||
* The key may not be found, which is acceptable. There
|
||||
* can be multiple signatures, each preceded by a key.
|
||||
*/
|
||||
} else if (tlv.it_type == EXPECTED_SIG_TLV) {
|
||||
/* Ignore this signature if it is out of bounds. */
|
||||
if (key_id < 0 || key_id >= bootutil_key_cnt) {
|
||||
key_id = -1;
|
||||
continue;
|
||||
}
|
||||
if (!EXPECTED_SIG_LEN(tlv.it_len) || tlv.it_len > sizeof(buf)) {
|
||||
return -1;
|
||||
}
|
||||
rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
|
||||
if (rc) {
|
||||
return -1;
|
||||
}
|
||||
rc = bootutil_verify_sig(hash, sizeof(hash), buf, tlv.it_len, key_id);
|
||||
if (rc == 0) {
|
||||
valid_signature = 1;
|
||||
}
|
||||
key_id = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!sha256_valid) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef EXPECTED_SIG_TLV
|
||||
if (!valid_signature) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -24,9 +24,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <bootutil.h>
|
||||
#include <bootutil/sign_key.h>
|
||||
#include <bootutil/image.h>
|
||||
#include <loader.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
|
||||
#if defined BOOT_SIGN_RSA
|
||||
|
|
|
|||
56
src/keys.c
56
src/keys.c
|
|
@ -1,56 +0,0 @@
|
|||
/* keys.c
|
||||
*
|
||||
* Copyright (C) 2018 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 2 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 <bootutil/sign_key.h>
|
||||
|
||||
#if defined(BOOT_SIGN_RSA)
|
||||
#define HAVE_KEYS
|
||||
extern const unsigned char rsa_pub_key[];
|
||||
extern unsigned int rsa_pub_key_len;
|
||||
#elif defined(BOOT_SIGN_EC256)
|
||||
#define HAVE_KEYS
|
||||
extern const unsigned char ecdsa_pub_key[];
|
||||
extern unsigned int ecdsa_pub_key_len;
|
||||
#elif defined(BOOT_SIGN_ED25519)
|
||||
#define HAVE_KEYS
|
||||
extern const unsigned char ed25519_pub_key[];
|
||||
extern unsigned int ed25519_pub_key_len;
|
||||
#else
|
||||
#error "No public key available for given signing algorithm."
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_KEYS)
|
||||
const struct bootutil_key bootutil_keys[] = {
|
||||
{
|
||||
#if defined(BOOT_SIGN_RSA)
|
||||
.key = rsa_pub_key,
|
||||
.len = &rsa_pub_key_len,
|
||||
#elif defined(BOOT_SIGN_EC256)
|
||||
.key = ecdsa_pub_key,
|
||||
.len = &ecdsa_pub_key_len,
|
||||
#elif defined(BOOT_SIGN_ED25519)
|
||||
.key = ed25519_pub_key,
|
||||
.len = &ed25519_pub_key_len,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
const int bootutil_key_cnt = 1;
|
||||
#endif
|
||||
61
src/main.c
61
src/main.c
|
|
@ -1,61 +0,0 @@
|
|||
/* main.c
|
||||
*
|
||||
* Copyright (C) 2018 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 2 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 "target.h"
|
||||
#include "hal.h"
|
||||
#include "printf.h"
|
||||
|
||||
#include "bootutil/image.h"
|
||||
#include "bootutil.h"
|
||||
|
||||
extern void do_boot(void *);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct boot_rsp rsp;
|
||||
int rc;
|
||||
|
||||
hal_init();
|
||||
#ifdef TEST_PENDING
|
||||
boot_set_pending(1);
|
||||
#endif
|
||||
|
||||
wolfBoot_printf("Starting bootloader");
|
||||
|
||||
rc = boot_go(&rsp);
|
||||
if (rc != 0) {
|
||||
wolfBoot_printf("Unable to find bootable image");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
wolfBoot_printf("Bootloader chainload address offset: 0x%x",
|
||||
rsp.br_image_off);
|
||||
|
||||
|
||||
hal_prepare_boot();
|
||||
wolfBoot_printf("Jumping to the first image slot");
|
||||
do_boot((uint8_t *)0 + rsp.br_hdr->ih_load_addr);
|
||||
|
||||
wolfBoot_printf("something went wrong.");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
|
@ -18,8 +18,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
#include "bootutil/image.h"
|
||||
#include "bootutil.h"
|
||||
#include <loader.h>
|
||||
#include <stdint.h>
|
||||
extern unsigned int _stored_data;
|
||||
extern unsigned int _start_data;
|
||||
|
|
|
|||
Loading…
Reference in New Issue