mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-19 00:13:21 +08:00
修改了Web后台的部分界面,增加了HAmqtt中的总电量传感器,后台新增mqtt上报频率设置
This commit is contained in:
702
mico-os/platform/MCU/MW3xx/peripherals/boot2/boot2.c
Normal file
702
mico-os/platform/MCU/MW3xx/peripherals/boot2/boot2.c
Normal file
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014, Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This is a second stage boot loader for the mc200/mw300
|
||||
* It provides below features-
|
||||
* -- Reading partition table information and execute the
|
||||
* latest programmed firmware
|
||||
* -- Boot from backup firmware
|
||||
* -- Passing boot flags to firmware for appropriate actions
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "boot2.h"
|
||||
|
||||
#include <crc32.h>
|
||||
#include <flash.h>
|
||||
#include <partition.h>
|
||||
#include <flash_layout.h>
|
||||
#include <boot_flags.h>
|
||||
#include <lowlevel_drivers.h>
|
||||
#include <firmware_structure.h>
|
||||
#include <mw300_flash.h>
|
||||
#include <mw300_flashc.h>
|
||||
|
||||
#include <secure_boot.h>
|
||||
#include <secure_boot2.h>
|
||||
#ifdef CONFIG_ENABLE_MXCHIP
|
||||
#include "Common.h"
|
||||
#include "MicoPlatform.h"
|
||||
#endif
|
||||
|
||||
void encrypt_arc4(uint8_t *in, uint8_t *out, int len);
|
||||
|
||||
#define FLASH_OTP_NVRAM_ADDR 0x480C002C
|
||||
#define FLASH_OTP_OFFSET 18
|
||||
#define DISABLE_SECURE_BOOT // yhb added
|
||||
|
||||
#define DEFAULT_FIRMWARE_OFFSET (0x10000)
|
||||
#define DEFAULT_FIRMWARE_SIZE (0x10000*6)
|
||||
|
||||
|
||||
#define crc32 _crc32
|
||||
|
||||
/* Make the "MRVL" string into an endian invariant 32-bit constant */
|
||||
#if defined(__ARMEL__)
|
||||
#define FW_MAGIC_STR (('M' << 0)|('R' << 8)|('V' << 16)|('L' << 24))
|
||||
#elif defined(__ARMEB__)
|
||||
#define FW_MAGIC_STR (('M' << 24)|('R' << 16)|('V' << 8)|('L' << 0))
|
||||
#else
|
||||
#error "unknown endian mode"
|
||||
#endif
|
||||
|
||||
#define FAIL 1 /* non-zero return = failure */
|
||||
|
||||
static secure_boot_struct_t *priv;
|
||||
static secure_boot_init_t sb;
|
||||
static uint8_t sec_fw_image_hdr[SB_SEC_IMG_HDR_SIZE];
|
||||
static struct img_hdr ih;
|
||||
static struct seg_hdr sh[SEG_CNT];
|
||||
static uint16_t keystore_len;
|
||||
/* JEDECID of flash */
|
||||
static uint32_t id;
|
||||
|
||||
static FLASH_Interface_Type FLASH_GetInterface(void)
|
||||
{
|
||||
return FLASHC->FCCR.BF.FLASHC_PAD_EN;
|
||||
}
|
||||
|
||||
static int flash_read(void *buf, uint32_t addr, uint32_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (FLASH_GetInterface() == FLASH_INTERFACE_FLASHC) {
|
||||
memcpy(buf, (uint8_t *)addr + 0x1f000000, size);
|
||||
ret = size;
|
||||
} else {
|
||||
ret = FLASH_Read(FLASH_FAST_READ_QUAD_IO, addr,
|
||||
(unsigned char *)buf, size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
static int secure_boot_feed_data(void *buf, uint32_t size)
|
||||
{
|
||||
if (sb.hash_algo != NO_HASH) {
|
||||
if (!priv->hash_update)
|
||||
return FAIL;
|
||||
priv->hash_update(priv->hash_ctx, buf, size);
|
||||
priv->bytes_to_read -= size;
|
||||
if (priv->bytes_to_read < 0) {
|
||||
dbg("Err...invalid fw image length\r\n");
|
||||
return FAIL;
|
||||
}
|
||||
dbg("hash update, remaining:%d\r\n", priv->bytes_to_read);
|
||||
/* If bytes_to_read=0, it means that the entire firmware
|
||||
* image has been read and decrypted. Get the hash result,
|
||||
* take its signature and verify with the received signature.
|
||||
*/
|
||||
if (priv->bytes_to_read == 0) {
|
||||
if (!priv->hash_finish || !priv->signature_verify)
|
||||
return FAIL;
|
||||
|
||||
priv->hash_finish(priv->hash_ctx, priv->hash);
|
||||
if (priv->signature_verify(priv->hash, priv->hash_len,
|
||||
priv->pk, priv->signature) != 0) {
|
||||
dbg("Err...fw signature match failed\r\n");
|
||||
writel((readel(sb_e) | SB_ERR_SIGN_MISMATCH),
|
||||
sb_e);
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.encrypt_algo != NO_ENCRYPT) {
|
||||
if (!priv->decrypt)
|
||||
return FAIL;
|
||||
else
|
||||
return priv->decrypt(priv->decrypt_ctx, buf,
|
||||
buf, size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static uint32_t secure_read_flash(void *buf, uint32_t addr, uint32_t size,
|
||||
uint32_t crc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dbg("flash read from @0x%08x, len 0x%08x\r\n", addr, size);
|
||||
flash_read(buf, addr, size);
|
||||
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
ret = secure_boot_feed_data(buf, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
crc = crc32(buf, size, crc);
|
||||
if ((uint32_t)buf == 0x20000040) {
|
||||
encrypt_arc4(buf, buf, size);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_flash : Reads flash memory
|
||||
* @buf : pointer to butter in which flash content to be read
|
||||
* @addr: Flash read address
|
||||
* @size : no of bytes to be read
|
||||
* @return value : calculated crc
|
||||
*/
|
||||
static uint32_t read_flash(void *buf, uint32_t addr, uint32_t size,
|
||||
uint32_t crc)
|
||||
{
|
||||
flash_read(buf, addr, size);
|
||||
return crc32(buf, size, crc);
|
||||
}
|
||||
|
||||
static int load_partition_table(struct partition_table *ph,
|
||||
uint32_t addr)
|
||||
{
|
||||
uint32_t crc = read_flash(ph, addr, sizeof(*ph), 0);
|
||||
|
||||
if (crc != 0 || ph->magic != PARTITION_TABLE_MAGIC) {
|
||||
if (crc != 0)
|
||||
writel((readel(nvram_addr) | BAD_PART_TABLE_CRC),
|
||||
nvram_addr);
|
||||
else
|
||||
writel((readel(nvram_addr) | BAD_PART_TABLE_MAGIC),
|
||||
nvram_addr);
|
||||
/* Invalidate number of partition entries */
|
||||
ph->partition_entries_no = 0;
|
||||
/* Invalidate generation level */
|
||||
ph->gen_level = 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int select_active_partition_table(uint32_t *addr)
|
||||
{
|
||||
int ret, status;
|
||||
struct partition_table ph[2];
|
||||
|
||||
status = 0;
|
||||
ret = load_partition_table(&ph[0], FL_PART1_START);
|
||||
if (ret != 0)
|
||||
/* Set partition table 1 status to indicate corruption */
|
||||
status |= PARTITION_TABLE1_STATE_MASK;
|
||||
|
||||
ret = load_partition_table(&ph[1], FL_PART2_START);
|
||||
if (ret != 0)
|
||||
/* Set partition table 2 status to indicate corruption */
|
||||
status |= PARTITION_TABLE2_STATE_MASK;
|
||||
|
||||
if (ph[1].gen_level > ph[0].gen_level) {
|
||||
*addr = FL_PART2_START;
|
||||
status |= BOOT_PARTITION_TABLE_MASK;
|
||||
return status;
|
||||
} else {
|
||||
*addr = FL_PART1_START;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
static void load_partition_entry(struct partition_table *pt,
|
||||
struct partition_entry *ph,
|
||||
uint32_t addr, short *start_index)
|
||||
{
|
||||
int i = 0;
|
||||
if (start_index)
|
||||
i = *start_index;
|
||||
|
||||
for (; i < pt->partition_entries_no; i++) {
|
||||
read_flash(ph, addr, sizeof(*ph), 0);
|
||||
addr += sizeof(*ph);
|
||||
if (ph->type == FC_COMP_FW)
|
||||
break;
|
||||
}
|
||||
*start_index = i + 1;
|
||||
if (ph->type != FC_COMP_FW)
|
||||
/* Invalidate partition generation level */
|
||||
ph->gen_level = 0;
|
||||
}
|
||||
|
||||
static void read_from_seghdr(struct firmware_segment *segment, void *addr,
|
||||
uint32_t size)
|
||||
{
|
||||
while (size) {
|
||||
uint32_t length = segment->length;
|
||||
if (!length)
|
||||
return;
|
||||
if (length > size)
|
||||
length = size;
|
||||
secure_read_flash(addr, segment->offset, length, 0);
|
||||
segment->offset += length;
|
||||
segment->length -= length;
|
||||
addr += length;
|
||||
size -= length;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int load_firmware(uint32_t firm_addr, uint32_t firm_size)
|
||||
{
|
||||
struct firmware_segment segment;
|
||||
uint32_t value;
|
||||
uint32_t *data_ptr;
|
||||
int (*fn_ptr) (uint32_t), ret;
|
||||
|
||||
dbg("%s: firm_addr:0x%x, size: 0x%x\r\n", __func__,
|
||||
firm_addr, firm_size);
|
||||
|
||||
segment.offset = firm_addr;
|
||||
segment.length = firm_size;
|
||||
|
||||
/* load and validate image header */
|
||||
read_from_seghdr(&segment, &ih, sizeof(ih));
|
||||
if (ih.magic_str != FW_MAGIC_STR || ih.magic_sig != FW_MAGIC_SIG) {
|
||||
writel((readel(nvram_addr) | BAD_FIRMWARE_SIG), nvram_addr);
|
||||
dbg("firmware magic not found\r\n");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if ((ih.entry & 0x1f000000) == 0x1f000000) {
|
||||
dbg("XIP image found, enabling flashc\r\n");
|
||||
|
||||
PMU->PERI1_CLK_DIV.BF.FLASH_CLK_DIV = 4;
|
||||
/* Sample data on the falling edge.
|
||||
* Sampling on rising edge does not
|
||||
* meet timing requirements at 50MHz
|
||||
*/
|
||||
FLASHC->FCTR.BF.CLK_CAPT_EDGE = 1;
|
||||
|
||||
/* Set FLASH QUAD mode type (continuous/non-continuous mode)
|
||||
* based on the flash */
|
||||
ret = FLASH_SetCmdType_QuadModeRead(id);
|
||||
if (ret == ERROR) {
|
||||
writel((readel(nvram_addr) | BAD_FLASH_JEDECID),
|
||||
nvram_addr);
|
||||
dbg("invalid flash identifier read\r\n");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/* Enable cache mode and disable SRAM mode */
|
||||
FLASHC->FCCR.BF.CACHE_EN = ENABLE;
|
||||
FLASHC->FCCR.BF.SRAM_MODE_EN = DISABLE;
|
||||
|
||||
/* Enable cache hit/miss counters */
|
||||
FLASHC->FCACR.BF.HIT_CNT_EN = ENABLE;
|
||||
FLASHC->FCACR.BF.MISS_CNT_EN = ENABLE;
|
||||
|
||||
/* Set correct clock prescale value, default is 0x2 */
|
||||
FLASHC->FCCR.BF.CLK_PRESCALE = FLASHC_CLK_DIVIDE_1;
|
||||
|
||||
/* Enable Flash Controller */
|
||||
FLASHC->FCCR.BF.FLASHC_PAD_EN = ENABLE;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < SEG_CNT; i++)
|
||||
read_from_seghdr(&segment, &sh[i], sizeof(struct seg_hdr));
|
||||
|
||||
int index = 0;
|
||||
while (ih.seg_cnt--) {
|
||||
sh[index].offset += firm_addr;
|
||||
|
||||
switch (sh[index].type) {
|
||||
case FW_BLK_LOADABLE_SEGMENT:
|
||||
|
||||
if ((sh[index].laddr & 0x1f000000) == 0x1f000000) {
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
if (secure_boot_feed_data((uint8_t *)
|
||||
sh[index].offset + 0x1f000000,
|
||||
sh[index].len))
|
||||
return FAIL;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
dbg("loading fw segment\r\n");
|
||||
if (secure_read_flash((void *)sh[index].laddr,
|
||||
sh[index].offset, sh[index].len,
|
||||
sh[index].crc))
|
||||
return FAIL;
|
||||
break;
|
||||
|
||||
case FW_BLK_POKE_DATA:
|
||||
data_ptr = (void *)sh[index].laddr;
|
||||
value = sh[index].len;
|
||||
*data_ptr = value;
|
||||
break;
|
||||
|
||||
case FW_BLK_FN_CALL:
|
||||
writel((readel(nvram_addr) | BOOT_SUCCESS),
|
||||
nvram_addr);
|
||||
dbg("fw-boot success\r\n");
|
||||
fn_ptr = (void *)sh[index].laddr;
|
||||
value = sh[index].len;
|
||||
if (fn_ptr(value) != 0)
|
||||
return FAIL;
|
||||
break;
|
||||
|
||||
case FW_BLK_ANCILLARY:
|
||||
/* skip over it */
|
||||
break;
|
||||
|
||||
default:
|
||||
dbg("invalid FW block found\r\n");
|
||||
return FAIL;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if ((ih.entry & 0x1f000000) == 0x1f000000) {
|
||||
if (firm_addr & 0x3) {
|
||||
dbg("Err...offset value should be word aligned\r\n");
|
||||
return FAIL;
|
||||
}
|
||||
/* Set flash controller offset register */
|
||||
FLASHC->FAOFFR.BF.OFFSET_VAL = firm_addr;
|
||||
FLASHC->FCACR.BF.OFFSET_EN = ENABLE;
|
||||
}
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
/* Copy keystorage to NVRAM for further use by firmware */
|
||||
memcpy((void *)SB_KEYSTORE_ADDR, &_keystore_start, keystore_len);
|
||||
#endif
|
||||
/* Hand over execution */
|
||||
writel((readel(nvram_addr) | BOOT_SUCCESS), nvram_addr);
|
||||
dbg("fw-boot success\r\n");
|
||||
fn_ptr = (void *)ih.entry;
|
||||
fn_ptr((uint32_t)NULL);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
int keystore_search(uint8_t *keystore_buf,
|
||||
uint8_t type, uint8_t *value, struct tlv_entry **t)
|
||||
{
|
||||
struct tlv_hdr *hdr = (struct tlv_hdr *) keystore_buf;
|
||||
struct tlv_entry *tentry =
|
||||
(struct tlv_entry *) (keystore_buf + sizeof(struct tlv_hdr));
|
||||
|
||||
while ((uint8_t *)tentry < keystore_buf + hdr->len) {
|
||||
if (tentry->type == type) {
|
||||
if (value && tentry->len == 1)
|
||||
memcpy(value, tentry->value, 1);
|
||||
else if (t)
|
||||
*t = tentry;
|
||||
else
|
||||
return FAIL;
|
||||
return 0;
|
||||
}
|
||||
tentry = (struct tlv_entry *) ((uint8_t *)tentry +
|
||||
sizeof(tentry->type) + sizeof(tentry->len)
|
||||
+ tentry->len);
|
||||
}
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
static int validate_and_parse_keystore(boot2_ks_hdr *hdr_t)
|
||||
{
|
||||
int ret;
|
||||
uint32_t crc;
|
||||
|
||||
crc = crc32((uint8_t *) hdr_t + sizeof(boot2_ks_hdr),
|
||||
hdr_t->len - sizeof(boot2_ks_hdr), 0);
|
||||
if (crc != hdr_t->crc) {
|
||||
dbg("CRC verification failed for keystore\r\n");
|
||||
writel((readel(sb_e) | SB_ERR_BAD_KS), sb_e);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Is firmware image signed? */
|
||||
ret = keystore_search((uint8_t *) hdr_t,
|
||||
KEY_FW_SIGNING_ALGO, &sb.sign_algo, NULL);
|
||||
if (!ret && sb.sign_algo != NO_SIGN) {
|
||||
/* Firmware image is signed, get public key */
|
||||
ret = keystore_search((uint8_t *) hdr_t,
|
||||
KEY_FW_PUBLIC_KEY, NULL, &sb.public_key);
|
||||
if (ret) {
|
||||
writel((readel(sb_e) | SB_ERR_BAD_PUB_KEY), sb_e);
|
||||
return ret;
|
||||
}
|
||||
/* Firmware image is signed, get hash algorithm type */
|
||||
ret = keystore_search((uint8_t *) hdr_t,
|
||||
KEY_FW_HASH_ALGO, &sb.hash_algo, NULL);
|
||||
if (ret) {
|
||||
dbg("Err...fw hash algo not found\r\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
sb.sign_algo = NO_SIGN;
|
||||
writel((readel(sb_e) | SB_ERR_NO_SIGN), sb_e);
|
||||
}
|
||||
|
||||
/* Is firmware image encrypted? */
|
||||
ret = keystore_search((uint8_t *) hdr_t,
|
||||
KEY_FW_ENCRYPT_ALGO, &sb.encrypt_algo, NULL);
|
||||
if (!ret && sb.encrypt_algo != NO_ENCRYPT) {
|
||||
/* Firmware image is encrypted, get decryption key */
|
||||
ret = keystore_search((uint8_t *) hdr_t,
|
||||
KEY_FW_DECRYPT_KEY, NULL, &sb.decrypt_key);
|
||||
if (ret) {
|
||||
writel((readel(sb_e) | SB_ERR_BAD_DECRYPT_KEY),
|
||||
sb_e);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
sb.encrypt_algo = NO_ENCRYPT;
|
||||
writel((readel(sb_e) | SB_ERR_NO_ENCRYPT), sb_e);
|
||||
}
|
||||
|
||||
/* Save keystorage length for future use */
|
||||
keystore_len = hdr_t->len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_and_parse_image_hdr(uint32_t firm_addr, uint32_t *offset)
|
||||
{
|
||||
int ret = -1;
|
||||
img_sec_hdr hdr;
|
||||
|
||||
read_flash((uint8_t *)&hdr, firm_addr, sizeof(img_sec_hdr), 0);
|
||||
if (hdr.magic == SEC_FW_MAGIC_SIG) {
|
||||
dbg("found fw image header @%x\r\n", firm_addr);
|
||||
if (hdr.len > SB_SEC_IMG_HDR_SIZE) {
|
||||
dbg("Err...invalid fw image header size %d\r\n",
|
||||
hdr.len);
|
||||
writel((readel(sb_e) | SB_ERR_BAD_FW_HDR_LEN), sb_e);
|
||||
return -1;
|
||||
}
|
||||
memcpy(sec_fw_image_hdr, &hdr, sizeof(img_sec_hdr));
|
||||
read_flash(sec_fw_image_hdr + sizeof(img_sec_hdr),
|
||||
firm_addr + sizeof(img_sec_hdr),
|
||||
hdr.len - sizeof(img_sec_hdr), 0);
|
||||
|
||||
uint32_t crc = crc32((uint8_t *) sec_fw_image_hdr
|
||||
+ sizeof(img_sec_hdr),
|
||||
hdr.len - sizeof(img_sec_hdr), 0);
|
||||
if (crc != hdr.crc) {
|
||||
dbg("CRC verification failed for image header\r\n");
|
||||
writel((readel(sb_e) | SB_ERR_BAD_FW_HDR), sb_e);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct tlv_entry *entry;
|
||||
ret = keystore_search((uint8_t *) sec_fw_image_hdr,
|
||||
KEY_FW_IMAGE_LEN, NULL, &entry);
|
||||
if (ret) {
|
||||
dbg("Err...firmware image length not found\r\n");
|
||||
writel((readel(sb_e) | SB_ERR_NO_FW_LEN), sb_e);
|
||||
return ret;
|
||||
} else {
|
||||
sb.fw_img_len = (entry->value[3] << 24)
|
||||
| (entry->value[2] << 16)
|
||||
| (entry->value[1] << 8)
|
||||
| (entry->value[0]);
|
||||
}
|
||||
|
||||
if (sb.encrypt_algo != NO_ENCRYPT) {
|
||||
ret = keystore_search((uint8_t *) sec_fw_image_hdr,
|
||||
KEY_FW_NONCE, NULL, &sb.nonce);
|
||||
if (ret) {
|
||||
dbg("Err...firmware nonce not found\r\n");
|
||||
writel((readel(sb_e) | SB_ERR_BAD_NONCE),
|
||||
sb_e);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.sign_algo != NO_SIGN) {
|
||||
ret = keystore_search((uint8_t *) sec_fw_image_hdr,
|
||||
KEY_FW_SIGNATURE, NULL, &sb.digital_sig);
|
||||
if (ret) {
|
||||
dbg("Err...firmware signature not found\r\n");
|
||||
writel((readel(sb_e) | SB_ERR_BAD_SIGN),
|
||||
sb_e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writel((readel(sb_e) | SB_ERR_BAD_FW_HDR), sb_e);
|
||||
}
|
||||
|
||||
if (!ret && offset)
|
||||
*offset = hdr.len;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int boot2_main( uint8_t will_load_firmware )
|
||||
{
|
||||
int ret;
|
||||
short index;
|
||||
bool p_num;
|
||||
bool secure_boot = false;
|
||||
uint32_t boot_flags;
|
||||
struct partition_entry p_entry[2];
|
||||
struct partition_table p_table;
|
||||
uint32_t part_addr;
|
||||
uint32_t img_offset = 0;
|
||||
uint32_t otp[5];
|
||||
unsigned long *otp_nvram_addr = (unsigned long *)FLASH_OTP_NVRAM_ADDR;
|
||||
|
||||
/* Read flash JEDECID and set appropriate configuration first */
|
||||
id = FLASH_GetJEDECID();
|
||||
ret = FLASH_SetConfig(id);
|
||||
dbg("jedecID %08x\r\n", id);
|
||||
if (ret == ERROR) {
|
||||
writel((readel(nvram_addr) | CANNOT_CONFIG_JEDECID),
|
||||
nvram_addr);
|
||||
dbg("Cannot set the flash configuration\r\n");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
#ifdef CONFIG_ENABLE_MXCHIP
|
||||
/* read out flash OTP data, save to nvram */
|
||||
FLASH_ENSO();
|
||||
ret = FLASH_Read(FLASH_FAST_READ_QUAD_IO, FLASH_OTP_OFFSET, otp, 20);
|
||||
FLASH_EXSO();
|
||||
otp_nvram_addr[0] = otp[0];
|
||||
otp_nvram_addr[1] = otp[1];
|
||||
otp_nvram_addr[2] = otp[2];
|
||||
otp_nvram_addr[3] = otp[3];
|
||||
otp_nvram_addr[4] = otp[4];
|
||||
|
||||
if ((MicoGpioInputGet((mico_gpio_t)BOOT_SEL) == false) &&
|
||||
(MicoGpioInputGet((mico_gpio_t)EasyLink_BUTTON) == false) &&
|
||||
(MicoGpioInputGet((mico_gpio_t)MFG_SEL) == true)) {
|
||||
dbg("load ATE firmware\r\n");
|
||||
load_firmware(0x160000, 0x40000);
|
||||
}
|
||||
#endif
|
||||
/* Select active partition table */
|
||||
boot_flags = 0;
|
||||
ret = select_active_partition_table(&part_addr);
|
||||
boot_flags |= ret;
|
||||
|
||||
/* Read out partition table */
|
||||
dbg("reading partition table @0x%x\r\n", part_addr);
|
||||
load_partition_table(&p_table, part_addr);
|
||||
part_addr += sizeof(struct partition_table);
|
||||
|
||||
/* Read out firmware partition entries */
|
||||
if (p_table.partition_entries_no > 0) {
|
||||
index = 0;
|
||||
load_partition_entry(&p_table, &p_entry[0], part_addr, &index);
|
||||
part_addr += sizeof(struct partition_entry) * index;
|
||||
load_partition_entry(&p_table, &p_entry[1], part_addr, &index);
|
||||
|
||||
dbg("gen levno: %d,%d\r\n",
|
||||
p_entry[0].gen_level, p_entry[1].gen_level);
|
||||
|
||||
/* select partition with highest generation number */
|
||||
p_num = (p_entry[1].gen_level > p_entry[0].gen_level);
|
||||
} else {
|
||||
/* No partition entries found, load default */
|
||||
p_num = 0;
|
||||
p_entry[0].start = DEFAULT_FIRMWARE_OFFSET;
|
||||
p_entry[0].size = DEFAULT_FIRMWARE_SIZE;
|
||||
p_entry[0].gen_level = 1;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
/* See, if keystore exists for secure boot scheme */
|
||||
boot2_ks_hdr *hdr_t = (boot2_ks_hdr *)&_keystore_start;
|
||||
if (hdr_t->magic == SEC_KEYSTORE_MAGIC_SIG) {
|
||||
/* Keystore is available, boot only trusted fw image (?) */
|
||||
ret = validate_and_parse_keystore(hdr_t);
|
||||
if (ret) {
|
||||
dbg("Valid keystore not found %d\r\n", ret);
|
||||
/* We're toast... */
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
if (sb.sign_algo != NO_SIGN ||
|
||||
sb.encrypt_algo != NO_ENCRYPT) {
|
||||
secure_boot = true;
|
||||
boot_flags |= BOOT_SECURE_FW_ENABLE;
|
||||
if (sb.sign_algo != NO_SIGN)
|
||||
boot_flags |= BOOT_SECURE_SIGN_FW;
|
||||
if (sb.encrypt_algo != NO_ENCRYPT)
|
||||
boot_flags |= BOOT_SECURE_ENCRYPT_FW;
|
||||
}
|
||||
} else {
|
||||
writel((readel(sb_e) | SB_ERR_NO_KS), sb_e);
|
||||
}
|
||||
#endif
|
||||
|
||||
if( will_load_firmware == 0 )
|
||||
return 0;
|
||||
|
||||
/* Try to boot both primary and secondary fw images */
|
||||
int i;
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* store boot flags in memory for firmware consumption */
|
||||
*BOOT_FLAGS = boot_flags | p_num;
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
/* Parse secure firmware image header and initialize secure
|
||||
* boot context with same */
|
||||
if (secure_boot) {
|
||||
ret = validate_and_parse_image_hdr
|
||||
(p_entry[p_num].start, &img_offset);
|
||||
if (ret) {
|
||||
dbg("Invalid secure fw img hdr %d\r\n", ret);
|
||||
/* Invalidate generation level */
|
||||
p_entry[p_num].gen_level = 0;
|
||||
} else {
|
||||
ret = secure_boot_firmware(&sb, &priv);
|
||||
if (ret) {
|
||||
dbg("Secure boot init failed %d\r\n",
|
||||
ret);
|
||||
writel((readel(sb_e) |
|
||||
SB_ERR_INIT_FAIL), sb_e);
|
||||
/* We're toast */
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (p_entry[p_num].gen_level >= 1)
|
||||
load_firmware(p_entry[p_num].start + img_offset,
|
||||
p_entry[p_num].size);
|
||||
|
||||
/* we get here only if selected partition/firmware is bad */
|
||||
boot_flags |= BOOT_MAIN_FIRMWARE_BAD_CRC;
|
||||
writel((readel(nvram_addr) | BAD_FIRMWARE_IMG), nvram_addr);
|
||||
#ifndef DISABLE_SECURE_BOOT
|
||||
/* cleanup secure boot context */
|
||||
secure_boot_cleanup(priv);
|
||||
#endif
|
||||
/* Backup firmware: partition selection has to be flipped */
|
||||
p_num ^= 1;
|
||||
dbg("Trying backup firmware image boot\r\n");
|
||||
}
|
||||
|
||||
writel((readel(nvram_addr) | BOOT_FAILED), nvram_addr);
|
||||
dbg("fw-boot failed boot_flags(0x%08x), error(0x%08x)\r\n",
|
||||
boot_flags, readel(nvram_addr));
|
||||
if (secure_boot)
|
||||
dbg("secure_boot_error(0x%08x)\r\n", readel(sb_e));
|
||||
#ifdef UART_DEBUG
|
||||
uart_cleanup();
|
||||
#endif
|
||||
/* Nothing succeeded. We're toast... */
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
69
mico-os/platform/MCU/MW3xx/peripherals/boot2/boot2.h
Normal file
69
mico-os/platform/MCU/MW3xx/peripherals/boot2/boot2.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2013 Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT2_H_
|
||||
#define _BOOT2_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Nvram address word to store debugging information */
|
||||
#define NVRAM_ADDR 0x480C0020
|
||||
#define SB_ERR_ADDR 0x480C0028
|
||||
|
||||
/* Boot2 progress status */
|
||||
#define SYS_INIT (1<<0)
|
||||
#define FLASH_INIT (1<<1)
|
||||
#define PRIMARY_FIRMWARE (1<<2)
|
||||
|
||||
/* Boot2 error status */
|
||||
#define BAD_PART_TABLE_CRC (1<<16)
|
||||
#define BAD_PART_ENTRY_CRC (1<<17)
|
||||
#define BAD_FIRMWARE_CRC (1<<18)
|
||||
#define BAD_PART_TABLE_MAGIC (1<<19)
|
||||
#define BAD_FIRMWARE_SIG (1<<20)
|
||||
#define BAD_FIRMWARE_IMG (1<<21)
|
||||
#define BAD_FLASH_JEDECID (1<<22)
|
||||
#define CANNOT_CONFIG_JEDECID (1<<23)
|
||||
|
||||
/* Boot2 success or failure status */
|
||||
#define BOOT_SUCCESS (0x80000000)
|
||||
#define BOOT_FAILED (0x00800000)
|
||||
|
||||
extern unsigned long _bss;
|
||||
extern unsigned long _ebss;
|
||||
extern unsigned long _estack;
|
||||
|
||||
#ifdef UART_DEBUG
|
||||
#define dbg(_fmt_, ...) \
|
||||
uart_dbg("[boot2] "_fmt_, ## __VA_ARGS__)
|
||||
void uart_dbg(const char *format, ...);
|
||||
void uart_cleanup(void);
|
||||
#elif SEMIHOST_DEBUG
|
||||
#define dbg printf
|
||||
#else
|
||||
#define dbg(...)
|
||||
#endif
|
||||
|
||||
extern unsigned long *nvram_addr;
|
||||
extern unsigned long *sb_e;
|
||||
|
||||
static inline void writel(uint32_t data, void *addr)
|
||||
{
|
||||
*((volatile uint32_t *)addr) = data;
|
||||
}
|
||||
|
||||
static inline uint32_t readel(void *addr)
|
||||
{
|
||||
return *((volatile uint32_t *)addr);
|
||||
}
|
||||
|
||||
int boot2_main( uint8_t will_load_firmware );
|
||||
extern unsigned long _heap_end, _heap_start, _keystore_start;
|
||||
void *ROM_pvPortMalloc(size_t xWantedSize);
|
||||
void ROM_vPortFree(void *pv);
|
||||
void *ROM_pvPortReAlloc(void *pv, size_t xWantedSize);
|
||||
void ROM_prvHeapInit(unsigned char *startAddress, unsigned char *endAddress);
|
||||
|
||||
#endif
|
||||
162
mico-os/platform/MCU/MW3xx/peripherals/boot2/secure_boot2.c
Normal file
162
mico-os/platform/MCU/MW3xx/peripherals/boot2/secure_boot2.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014, Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <secure_boot2.h>
|
||||
#include <secure_boot.h>
|
||||
#include <cyassl/ctaocrypt/rsa.h>
|
||||
#include <cyassl/ctaocrypt/aes.h>
|
||||
#include <cyassl/ctaocrypt/sha256.h>
|
||||
#include <boot2.h>
|
||||
#include <aes.h>
|
||||
#include <secure_boot.h>
|
||||
|
||||
#define RSA_SIGN_LEN 256
|
||||
|
||||
static Sha256 sha;
|
||||
static RsaKey key;
|
||||
static aes_t dec;
|
||||
static uint8_t sig[RSA_SIGN_LEN];
|
||||
static uint8_t hash[SHA256_DIGEST_SIZE];
|
||||
static uint8_t nonce[AES_BLOCK_SIZE];
|
||||
|
||||
static secure_boot_struct_t priv_data;
|
||||
|
||||
/* Initialize the AES CTR context */
|
||||
static void aes_ctr_init(void *context, void *key, uint32_t key_len,
|
||||
void *iv)
|
||||
{
|
||||
aes_drv_setkey(NULL, context, key, key_len, iv, AES_DECRYPTION,
|
||||
HW_AES_MODE_CTR);
|
||||
}
|
||||
|
||||
/* This function needs to be defined to match the signature of decrypt_func_t
|
||||
* Use appropriate decryption function in it.
|
||||
*/
|
||||
static int aes_ctr_decrypt(void *context, void *inbuf,
|
||||
void *outbuf, uint32_t len)
|
||||
{
|
||||
return aes_drv_decrypt(NULL, context, inbuf, outbuf, len);
|
||||
}
|
||||
|
||||
/* RSA verification callback */
|
||||
static int rsassl_verify(void *message, int len, void *pk, void *signature)
|
||||
{
|
||||
int ret;
|
||||
uint8_t hashDecrypt[SHA256_DIGEST_SIZE];
|
||||
|
||||
ret = RsaSSL_Verify(signature, RSA_SIGN_LEN, hashDecrypt,
|
||||
sizeof(hashDecrypt), pk);
|
||||
if (ret < 0) {
|
||||
dbg("Err...RSA verification failure: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compare if the hash of the decrypted firmware image matches
|
||||
* with hash derived from Signature */
|
||||
if (memcmp(message, hashDecrypt, sizeof(hashDecrypt)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sha256 hash update callback */
|
||||
static void sha256_update(void *context, void *buf, int len)
|
||||
{
|
||||
Sha256Update(context, buf, len);
|
||||
}
|
||||
|
||||
/* Sha256 has finish callback */
|
||||
static void sha256_finish(void *context, void *result)
|
||||
{
|
||||
Sha256Final(context, result);
|
||||
}
|
||||
|
||||
extern unsigned long _rom_data_start, _rom_data_size;
|
||||
static void secure_boot_init()
|
||||
{
|
||||
memset(&_rom_data_start, 0, (unsigned) &_rom_data_size);
|
||||
ROM_prvHeapInit((unsigned char *)&_heap_start,
|
||||
(unsigned char *)&_heap_end);
|
||||
CyaSSL_SetAllocators((CyaSSL_Malloc_cb)
|
||||
((uint32_t) ROM_pvPortMalloc | 0x1),
|
||||
(CyaSSL_Free_cb)
|
||||
((uint32_t) ROM_vPortFree | 0x1),
|
||||
(CyaSSL_Realloc_cb)
|
||||
((uint32_t) ROM_pvPortReAlloc | 0x1));
|
||||
aes_drv_init();
|
||||
}
|
||||
|
||||
/* This function will initialize the encryption and hashing
|
||||
* context appropriately by fetching the required data.
|
||||
*/
|
||||
int secure_boot_firmware(secure_boot_init_t *sb, secure_boot_struct_t **priv)
|
||||
{
|
||||
int ret = 0;
|
||||
word32 idx = 0;
|
||||
|
||||
/* Initialize ROM libs and AES hardware engine */
|
||||
secure_boot_init();
|
||||
|
||||
if (sb->sign_algo == RSA_SIGN) {
|
||||
priv_data.signature_verify = rsassl_verify;
|
||||
priv_data.signature = sig;
|
||||
priv_data.signature_len = sb->digital_sig->len;
|
||||
priv_data.pk = &key;
|
||||
InitRsaKey(&key, 0);
|
||||
ret = RsaPublicKeyDecode(sb->public_key->value, &idx, &key,
|
||||
sb->public_key->len);
|
||||
if (ret != 0) {
|
||||
dbg("RSA Public key decode error:%d", ret);
|
||||
FreeRsaKey(&key);
|
||||
return -1;
|
||||
}
|
||||
memcpy(priv_data.signature, sb->digital_sig->value,
|
||||
priv_data.signature_len > RSA_SIGN_LEN ?
|
||||
RSA_SIGN_LEN : priv_data.signature_len);
|
||||
if (sb->hash_algo == SHA256_HASH) {
|
||||
priv_data.hash_update = sha256_update;
|
||||
priv_data.hash_finish = sha256_finish;
|
||||
priv_data.hash_ctx = &sha;
|
||||
priv_data.hash = hash;
|
||||
priv_data.hash_len = SHA256_DIGEST_SIZE;
|
||||
InitSha256(&sha);
|
||||
}
|
||||
priv_data.bytes_to_read = sb->fw_img_len;
|
||||
}
|
||||
|
||||
/* AES-CTR algorithm init */
|
||||
if (sb->encrypt_algo == AES_CTR_128_ENCRYPT) {
|
||||
priv_data.decrypt_init = aes_ctr_init;
|
||||
priv_data.decrypt = aes_ctr_decrypt;
|
||||
priv_data.decrypt_ctx = &dec;
|
||||
priv_data.iv = nonce;
|
||||
priv_data.iv_len = sb->nonce->len;
|
||||
priv_data.decrypt_key_len = sb->decrypt_key->len;
|
||||
priv_data.decrypt_key = sb->decrypt_key->value;
|
||||
memcpy(priv_data.iv, sb->nonce->value,
|
||||
priv_data.iv_len > AES_BLOCK_SIZE ?
|
||||
AES_BLOCK_SIZE : priv_data.iv_len);
|
||||
|
||||
/* Initialize decryption hardware engine */
|
||||
priv_data.decrypt_init(priv_data.decrypt_ctx,
|
||||
priv_data.decrypt_key,
|
||||
priv_data.decrypt_key_len,
|
||||
priv_data.iv);
|
||||
}
|
||||
|
||||
if (priv)
|
||||
*priv = &priv_data;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void secure_boot_cleanup(secure_boot_struct_t *priv)
|
||||
{
|
||||
if (priv && priv->pk)
|
||||
FreeRsaKey(priv->pk);
|
||||
}
|
||||
196
mico-os/platform/MCU/MW3xx/peripherals/boot2/secure_boot2.h
Normal file
196
mico-os/platform/MCU/MW3xx/peripherals/boot2/secure_boot2.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/* Copyright (C) 2008-2014, Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SECURE_BOOT2_H_
|
||||
#define _SECURE_BOOT2_H_
|
||||
|
||||
/** Prototype for the decrypt initialization function. Please use a
|
||||
* wrapper for your function if it does not match this signature.
|
||||
*
|
||||
* \param[in,out] context A pointer to the decrypt function's context.
|
||||
* \param[in] key Pointer to key that will be used for decryption.
|
||||
* \param[in] key_len decryption key length.
|
||||
* \param[in] iv Pointer to initialization vector.
|
||||
*
|
||||
* \note Right now only AES-CTR-128 mode is supported.
|
||||
*/
|
||||
typedef void (*decrypt_init_func_t) (void *context, void *key,
|
||||
uint32_t key_len, void *iv);
|
||||
|
||||
/** Prototype for the decrypt function. Please use a wrapper for your
|
||||
* function if it does not match this signature.
|
||||
*
|
||||
* \param[in,out] context A pointer to the decrypt function's context.
|
||||
* \param[in] Pointer to the input buffer which has the ciphertext.
|
||||
* \param[out] outbuf A pointer to the output buffer which will hold
|
||||
* the decrypted data. It can be same as the inbuf if the algorithm
|
||||
* uses in-place decryption.
|
||||
* \param[in] len Length of the input buffer (number of bytes).
|
||||
*
|
||||
* \return WM_SUCCESS on success.
|
||||
* \return -WM_FAIL on error.
|
||||
*/
|
||||
typedef int (*decrypt_func_t) (void *context, void *inbuf,
|
||||
void *outbuf, uint32_t len);
|
||||
|
||||
/** Prototype for the signature verification function. Please use a wrapper
|
||||
* for your function if it does not match this signature.
|
||||
*
|
||||
* \param[in] msg Pointer to a buffer which holds the message whose
|
||||
* signature has to be verified.
|
||||
* \param[in] msglen Length of the message
|
||||
* \param[in] pk Pointer to the public key
|
||||
* \param[in] signature The signature against which the verification is
|
||||
* to be done.
|
||||
*
|
||||
* \return 0 if signature verification successful.
|
||||
* \return <any other value> if signature verification failed.
|
||||
*/
|
||||
typedef int (*signature_verify_func_t) (void *msg, int msglen,
|
||||
void *pk, void *signature);
|
||||
|
||||
/** Prototype for the hash update function. Please use a wrapper for your
|
||||
* function if it does not match this signature.
|
||||
*
|
||||
* \param[in,out] context A pointer to the hashing function's context.
|
||||
* \param[in] buf Pointer to a buffer whose hash (checksum) is to be
|
||||
* calculated.
|
||||
* \param[in] buflen Length of the buffer
|
||||
*/
|
||||
typedef void (*hash_update_func_t) (void *context, void *buf, int buflen);
|
||||
|
||||
/** Prototype for the hash finish function. Please use a wrapper for your
|
||||
* function if it does not match this signature.
|
||||
*
|
||||
* \param[in] context A pointer to the hashing function's context.
|
||||
* \param[out] result Pointer to a buffer where the result of the hash
|
||||
* (checksum) will be stored.
|
||||
*/
|
||||
typedef void (*hash_finish_func_t) (void *context, void *result);
|
||||
|
||||
/** Secure boot structure
|
||||
*
|
||||
* Structure to be populated by the application and passed to
|
||||
* secure_boot_firmware().
|
||||
*/
|
||||
typedef struct {
|
||||
/** Pointer to the decryption context initialization function
|
||||
* of type \ref decrypt_init_func_t
|
||||
*/
|
||||
decrypt_init_func_t decrypt_init;
|
||||
/** Pointer to the decryption function of type
|
||||
* \ref decrypt_func_t
|
||||
*/
|
||||
decrypt_func_t decrypt;
|
||||
/** Pointer to the signature verification function of type
|
||||
* \ref signature_verify_func_t
|
||||
*/
|
||||
signature_verify_func_t signature_verify;
|
||||
/** Pointer to the hash update function of type
|
||||
* \ref hash_update_func_t
|
||||
*/
|
||||
hash_update_func_t hash_update;
|
||||
/** Pointer to a hash finish function of type
|
||||
* \ref hash_finish_func_t
|
||||
*/
|
||||
hash_finish_func_t hash_finish;
|
||||
/** Pointer to the decrypt context initialized by the application
|
||||
* before using secure_boot_firmware().
|
||||
*/
|
||||
void *decrypt_ctx;
|
||||
/** Pointer to the hash context initialized by the application
|
||||
* before using secure_boot_firmware().
|
||||
*/
|
||||
void *hash_ctx;
|
||||
/** Pointer to a buffer which will hold the decryption context
|
||||
* initialization vector. This must point to an allocated buffer of
|
||||
* size equal to the IV required by the decryption algorithm being
|
||||
* used.
|
||||
*/
|
||||
void *iv;
|
||||
/** Length of the IV as per the decryption algorithm being used. This
|
||||
* must be initialized by the application.
|
||||
*/
|
||||
int iv_len;
|
||||
/** Pointer to a buffer which holds the received signature. This
|
||||
* must point to an allocated buffer which holds the actual decrypted
|
||||
* signature.
|
||||
*/
|
||||
void *signature;
|
||||
/** Length of the signature as per the algorithm being used. This
|
||||
* must be initialized by the application.
|
||||
*/
|
||||
int signature_len;
|
||||
/** Pointer to a buffer which holds the hash value. The memory must
|
||||
* be allocated by the application.
|
||||
*/
|
||||
void *hash;
|
||||
/** Length of the hash as per the hashing algorithm being used.
|
||||
*/
|
||||
int hash_len;
|
||||
/** Pointer to the public key for verification.
|
||||
*/
|
||||
void *pk;
|
||||
/** Pointer to the decryption key which will later be passed to the
|
||||
* decrypt_init function.
|
||||
*/
|
||||
void *decrypt_key;
|
||||
/** Length of the decryption key which will later be passed to the
|
||||
* decrypt_init function.
|
||||
*/
|
||||
int decrypt_key_len;
|
||||
/** Number of bytes remaining to read. For internal use only.
|
||||
* Do not modify.
|
||||
*/
|
||||
int bytes_to_read;
|
||||
} secure_boot_struct_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t sign_algo;
|
||||
uint8_t encrypt_algo;
|
||||
uint8_t hash_algo;
|
||||
struct tlv_entry *public_key;
|
||||
struct tlv_entry *digital_sig;
|
||||
struct tlv_entry *decrypt_key;
|
||||
struct tlv_entry *nonce;
|
||||
uint32_t fw_img_len;
|
||||
} secure_boot_init_t;
|
||||
|
||||
typedef enum {
|
||||
/* Success */
|
||||
SB_ERR_NONE = 0x00000000,
|
||||
/* No keystorage found, normal boot */
|
||||
SB_ERR_NO_KS = 0x00000001,
|
||||
/* Bad keystorage, CRC or magic mismatch */
|
||||
SB_ERR_BAD_KS = 0x00000002,
|
||||
/* Bad firmware hdr, CRC or magic mismatch */
|
||||
SB_ERR_BAD_FW_HDR = 0x00000004,
|
||||
/* Un-encrypted image */
|
||||
SB_ERR_NO_ENCRYPT = 0x00000008,
|
||||
/* Un-signed image */
|
||||
SB_ERR_NO_SIGN = 0x00000010,
|
||||
/* Firmware len missing */
|
||||
SB_ERR_NO_FW_LEN = 0x00000020,
|
||||
/* Bad or missing public key */
|
||||
SB_ERR_BAD_PUB_KEY = 0x00000040,
|
||||
/* Bad or missing decrypt key */
|
||||
SB_ERR_BAD_DECRYPT_KEY = 0x00000080,
|
||||
/* Bad or missing signature */
|
||||
SB_ERR_BAD_SIGN = 0x00000100,
|
||||
/* Bad or missing nonce/iv */
|
||||
SB_ERR_BAD_NONCE = 0x00000200,
|
||||
/* Secure boot init failed */
|
||||
SB_ERR_INIT_FAIL = 0x00000400,
|
||||
/* Sign match failed */
|
||||
SB_ERR_SIGN_MISMATCH = 0x00000800,
|
||||
/* Invalid firmware header size */
|
||||
SB_ERR_BAD_FW_HDR_LEN = 0x00001000,
|
||||
/* Unknon err */
|
||||
SB_ERR_UNKNOWN = 0x80000000,
|
||||
} sb_err_e;
|
||||
|
||||
int secure_boot_firmware(secure_boot_init_t *sb, secure_boot_struct_t **priv);
|
||||
void secure_boot_cleanup(secure_boot_struct_t *priv);
|
||||
|
||||
#endif /*_SECUR_BOOT2_H_ */
|
||||
16
mico-os/platform/MCU/MW3xx/peripherals/boot2/utils/crc.h
Normal file
16
mico-os/platform/MCU/MW3xx/peripherals/boot2/utils/crc.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013, Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef __CRC_H__
|
||||
#define __CRC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t soft_crc32(const void *__data, int data_size, uint32_t crc);
|
||||
void soft_crc32_init();
|
||||
uint32_t soft_crc16(const void *__data, uint16_t len);
|
||||
void soft_crc16_init();
|
||||
|
||||
#endif
|
||||
34
mico-os/platform/MCU/MW3xx/peripherals/boot2/utils/crc32.c
Normal file
34
mico-os/platform/MCU/MW3xx/peripherals/boot2/utils/crc32.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2013, Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "crc32.h"
|
||||
#include <lowlevel_drivers.h>
|
||||
|
||||
static int crc_init;
|
||||
|
||||
static void crc_set_mode()
|
||||
{
|
||||
CRC_SetMode(CRC_32_IEEE);
|
||||
}
|
||||
|
||||
uint32_t _crc32(void *__data, int data_size, uint32_t crc)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
if (!crc_init) {
|
||||
crc_set_mode();
|
||||
crc_init = 1;
|
||||
}
|
||||
|
||||
CRC_Disable();
|
||||
CRC_Enable();
|
||||
result = CRC_Calculate(__data, data_size);
|
||||
|
||||
if (crc && result == crc)
|
||||
result = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
13
mico-os/platform/MCU/MW3xx/peripherals/boot2/utils/crc32.h
Normal file
13
mico-os/platform/MCU/MW3xx/peripherals/boot2/utils/crc32.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013, Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef __CRC32_H
|
||||
#define __CRC32_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t crc32(void *__data, int data_size, uint32_t crc);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
#define CRC_16_CCITT 0x8408 /*!< CRC mode: CRC-16-CCITT */
|
||||
#define TABLE_SIZE 16
|
||||
|
||||
static uint32_t crc_table[TABLE_SIZE];
|
||||
|
||||
void soft_crc16_init(void)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint8_t i;
|
||||
uint8_t j;
|
||||
|
||||
for (j = 0; j < TABLE_SIZE; j++) {
|
||||
crc = 0;
|
||||
for (i = 0x01; i != 0x10; i <<= 1) {
|
||||
if ((crc & 0x0001) != 0) {
|
||||
crc >>= 1;
|
||||
crc ^= CRC_16_CCITT;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
if ((j & i) != 0) {
|
||||
crc ^= CRC_16_CCITT;
|
||||
}
|
||||
}
|
||||
crc_table[j] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t soft_crc16(const void *__buf, uint16_t len)
|
||||
{
|
||||
const uint8_t *buf = __buf;
|
||||
uint16_t crc = 0;
|
||||
uint8_t crc_H8;
|
||||
|
||||
while (len--) {
|
||||
crc_H8 = (uint8_t)(crc & 0x000F);
|
||||
crc >>= 4;
|
||||
crc ^= crc_table[crc_H8 ^ (*buf & 0x0F)];
|
||||
crc_H8 = (uint8_t)(crc & 0x000F);
|
||||
crc >>= 4;
|
||||
crc ^= crc_table[crc_H8 ^ (*buf >> 4)];
|
||||
buf++;
|
||||
}
|
||||
|
||||
return (uint32_t)crc;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2013, Marvell International Ltd.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
#define TABLE_SIZE 256
|
||||
|
||||
static uint32_t crc_table[TABLE_SIZE];
|
||||
static const int rcrc32 = 0xEDB88320;
|
||||
|
||||
void soft_crc32_init(void)
|
||||
{
|
||||
unsigned int crc = 0;
|
||||
unsigned char i;
|
||||
unsigned int j;
|
||||
|
||||
for (j = 0; j < TABLE_SIZE; j++) {
|
||||
crc = 0;
|
||||
for (i = 0x01; i != 0x00; i <<= 1) {
|
||||
if ((crc & 0x00000001) != 0) {
|
||||
crc >>= 1;
|
||||
crc ^= rcrc32;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
if ((j & i) != 0)
|
||||
crc ^= rcrc32;
|
||||
}
|
||||
crc_table[j] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t soft_crc32(const void *__data, int data_size, uint32_t crc)
|
||||
{
|
||||
const uint8_t *data = __data;
|
||||
unsigned int result = crc;
|
||||
unsigned char crc_H8;
|
||||
|
||||
while (data_size--) {
|
||||
crc_H8 = (unsigned char)(result & 0x000000FF);
|
||||
result >>= 8;
|
||||
result ^= crc_table[crc_H8 ^ (*data)];
|
||||
data++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user