修改了Web后台的部分界面,增加了HAmqtt中的总电量传感器,后台新增mqtt上报频率设置

This commit is contained in:
OOP
2025-03-03 21:49:41 +08:00
parent e1e00b60ce
commit 9f9d4c7a56
4468 changed files with 1473046 additions and 10728 deletions

View 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 (;;)
;
}

View 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

View 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);
}

View 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_ */

View 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

View 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;
}

View 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

View File

@@ -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;
}

View File

@@ -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;
}