1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-17 19:00:58 +00:00

norcow: introduce NORCOW_MAGIC

This commit is contained in:
Pavol Rusnak 2017-12-08 11:42:18 +01:00
parent 38e3088325
commit 44a11fa3ef
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
2 changed files with 67 additions and 90 deletions

View File

@ -2,26 +2,20 @@
#include "norcow.h" #include "norcow.h"
#include "common.h"
#include "../../trezorhal/flash.h" #include "../../trezorhal/flash.h"
#ifndef NORCOW_SECTORS #ifndef NORCOW_SECTORS
#define NORCOW_SECTORS {4, 16} #define NORCOW_SECTORS {FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_2}
#endif #endif
// NRCW = 4e524357
#define NORCOW_MAGIC ((uint32_t)0x5743524e)
#define NORCOW_MAGIC_LEN (sizeof(uint32_t))
static uint8_t norcow_sectors[NORCOW_SECTOR_COUNT] = NORCOW_SECTORS; static uint8_t norcow_sectors[NORCOW_SECTOR_COUNT] = NORCOW_SECTORS;
static uint8_t norcow_active_sector = 0; static uint8_t norcow_active_sector = 0;
static uint32_t norcow_active_offset = 0; static uint32_t norcow_active_offset = NORCOW_MAGIC_LEN;
/*
* Erases sector
*/
static secbool norcow_erase(uint8_t sector)
{
if (sector >= NORCOW_SECTOR_COUNT) {
return secfalse;
}
return flash_erase_sectors(&norcow_sectors[sector], 1, NULL);
}
/* /*
* Returns pointer to sector, starting with offset * Returns pointer to sector, starting with offset
@ -29,9 +23,7 @@ static secbool norcow_erase(uint8_t sector)
*/ */
static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size) static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size)
{ {
if (sector >= NORCOW_SECTOR_COUNT) { ensure(sectrue * (sector <= NORCOW_SECTOR_COUNT), "invalid sector");
return NULL;
}
return flash_get_address(norcow_sectors[sector], offset, size); return flash_get_address(norcow_sectors[sector], offset, size);
} }
@ -51,25 +43,39 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix, co
flash_lock(); flash_lock();
return secfalse; return secfalse;
} }
offset += sizeof(uint32_t); if (len > 0) {
// write data offset += sizeof(uint32_t);
for (uint16_t i = 0; i < len; i++, offset++) { // write data
if (sectrue != flash_write_byte_rel(norcow_sectors[sector], offset, data[i])) { for (uint16_t i = 0; i < len; i++, offset++) {
flash_lock(); if (sectrue != flash_write_byte_rel(norcow_sectors[sector], offset, data[i])) {
return secfalse; flash_lock();
return secfalse;
}
} }
} // pad with zeroes
// pad with zeroes for (; offset % 4; offset++) {
for (; offset % 4; offset++) { if (sectrue != flash_write_byte_rel(norcow_sectors[sector], offset, 0x00)) {
if (sectrue != flash_write_byte_rel(norcow_sectors[sector], offset, 0x00)) { flash_lock();
flash_lock(); return secfalse;
return secfalse; }
} }
} }
flash_lock(); flash_lock();
return sectrue; return sectrue;
} }
/*
* Erases sector (and sets a magic)
*/
static void norcow_erase(uint8_t sector, secbool set_magic)
{
ensure(sectrue * (sector <= NORCOW_SECTOR_COUNT), "invalid sector");
ensure(flash_erase_sectors(&norcow_sectors[sector], 1, NULL), "erase failed");
if (sectrue == set_magic) {
ensure(norcow_write(norcow_active_sector, 0, NORCOW_MAGIC, NULL, 0), "set magic failed");
}
}
#define ALIGN4(X) (X) = ((X) + 3) & ~3 #define ALIGN4(X) (X) = ((X) + 3) & ~3
/* /*
@ -117,7 +123,7 @@ static secbool find_item(uint8_t sector, uint16_t key, const void **val, uint16_
{ {
*val = 0; *val = 0;
*len = 0; *len = 0;
uint32_t offset = 0; uint32_t offset = NORCOW_MAGIC_LEN;
for (;;) { for (;;) {
uint16_t k, l; uint16_t k, l;
const void *v; const void *v;
@ -139,7 +145,7 @@ static secbool find_item(uint8_t sector, uint16_t key, const void **val, uint16_
*/ */
static uint32_t find_free_offset(uint8_t sector) static uint32_t find_free_offset(uint8_t sector)
{ {
uint32_t offset = 0; uint32_t offset = NORCOW_MAGIC_LEN;
for (;;) { for (;;) {
uint16_t key, len; uint16_t key, len;
const void *val; const void *val;
@ -158,8 +164,9 @@ static uint32_t find_free_offset(uint8_t sector)
static void compact() static void compact()
{ {
uint8_t norcow_next_sector = (norcow_active_sector + 1) % NORCOW_SECTOR_COUNT; uint8_t norcow_next_sector = (norcow_active_sector + 1) % NORCOW_SECTOR_COUNT;
norcow_erase(norcow_next_sector, sectrue);
uint32_t offset = 0, offsetw = 0; uint32_t offset = NORCOW_MAGIC_LEN, offsetw = NORCOW_MAGIC_LEN;
for (;;) { for (;;) {
// read item // read item
@ -167,14 +174,18 @@ static void compact()
const void *v; const void *v;
uint32_t pos; uint32_t pos;
secbool r = read_item(norcow_active_sector, offset, &k, &v, &l, &pos); secbool r = read_item(norcow_active_sector, offset, &k, &v, &l, &pos);
if (sectrue != r) break; if (sectrue != r) {
break;
}
offset = pos; offset = pos;
// check if not already saved // check if not already saved
const void *v2; const void *v2;
uint16_t l2; uint16_t l2;
r = find_item(norcow_next_sector, k, &v2, &l2); r = find_item(norcow_next_sector, k, &v2, &l2);
if (sectrue == r) continue; if (sectrue == r) {
continue;
}
// scan for latest instance // scan for latest instance
uint32_t offsetr = offset; uint32_t offsetr = offset;
@ -182,7 +193,9 @@ static void compact()
uint16_t k2; uint16_t k2;
uint32_t posr; uint32_t posr;
r = read_item(norcow_active_sector, offsetr, &k2, &v2, &l2, &posr); r = read_item(norcow_active_sector, offsetr, &k2, &v2, &l2, &posr);
if (sectrue != r) break; if (sectrue != r) {
break;
}
if (k == k2) { if (k == k2) {
v = v2; v = v2;
l = l2; l = l2;
@ -197,7 +210,7 @@ static void compact()
offsetw = posw; offsetw = posw;
} }
norcow_erase(norcow_active_sector); norcow_erase(norcow_active_sector, secfalse);
norcow_active_sector = norcow_next_sector; norcow_active_sector = norcow_next_sector;
norcow_active_offset = find_free_offset(norcow_active_sector); norcow_active_offset = find_free_offset(norcow_active_sector);
} }
@ -207,14 +220,26 @@ static void compact()
*/ */
secbool norcow_init(void) secbool norcow_init(void)
{ {
// detect active sector (inactive sectors are empty = start with 0xFF) secbool found = secfalse;
// detect active sector - starts with magic
for (uint8_t i = 0; i < NORCOW_SECTOR_COUNT; i++) { for (uint8_t i = 0; i < NORCOW_SECTOR_COUNT; i++) {
const uint8_t *b = norcow_ptr(i, 0, 1); const uint32_t *magic = norcow_ptr(i, 0, NORCOW_MAGIC_LEN);
if (b != NULL && *b != 0xFF) { if (magic != NULL && *magic == NORCOW_MAGIC) {
found = sectrue;
norcow_active_sector = i; norcow_active_sector = i;
break; break;
} }
} }
// no active sectors found - let's erase
if (sectrue != found) {
norcow_active_sector = 0;
if (sectrue != norcow_wipe()) {
return secfalse;
}
if (sectrue != norcow_write(norcow_active_sector, 0, NORCOW_MAGIC, NULL, 0)) {
return secfalse;
}
}
norcow_active_offset = find_free_offset(norcow_active_sector); norcow_active_offset = find_free_offset(norcow_active_sector);
return sectrue; return sectrue;
} }
@ -224,13 +249,12 @@ secbool norcow_init(void)
*/ */
secbool norcow_wipe(void) secbool norcow_wipe(void)
{ {
for (uint8_t i = 0; i < NORCOW_SECTOR_COUNT; i++) { norcow_erase(0, sectrue);
if (sectrue != norcow_erase(i)) { for (uint8_t i = 1; i < NORCOW_SECTOR_COUNT; i++) {
return secfalse; norcow_erase(i, secfalse);
}
} }
norcow_active_sector = 0; norcow_active_sector = 0;
norcow_active_offset = 0; norcow_active_offset = NORCOW_MAGIC_LEN;
return sectrue; return sectrue;
} }

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) Pavol Rusnak, SatoshiLabs
*
* Licensed under TREZOR License
* see LICENSE file for details
*/
#include "../../trezorhal/flash.h"
void flash_set_option_bytes(void)
{
}
secbool flash_unlock(void)
{
return secfalse;
}
secbool flash_lock(void)
{
return secfalse;
}
secbool flash_erase_sectors(const uint8_t *sectors, int len, void (*progress)(int pos, int len))
{
return secfalse;
}
secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen)
{
return secfalse;
}
secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen)
{
return secfalse;
}
secbool flash_otp_lock(uint8_t block)
{
return secfalse;
}
secbool flash_otp_is_locked(uint8_t block)
{
return secfalse;
}