Files
OpenCellular/common/vboot_stub.c
Bill Richardson 8101b71316 Enable verified boot for EC firmware
BUG=chrome-os-partner:7459
TEST=manual

In the chroot:

  cd src/platform/ec
  make BOARD=link

The firmware image (build/link/ec.bin) is signed with dev-keys. Reflash the
EC and try it, and it should verify and reboot into RW A.

Additional tests (setting USE_RO_NORMAL, poking random values into VBLOCK_A
or FW_MAIN_A to force RW B to run, etc.) are left as an exercise for the
reader. I've done them and they work, though.

Change-Id: I29a23ea69aef02a11aebd4af3b043f6864723523
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
2012-05-10 17:27:36 -07:00

169 lines
4.0 KiB
C

/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Functions needed by vboot library */
#define _STUB_IMPLEMENTATION_
#include "console.h"
#include "shared_mem.h"
#include "util.h"
#include "utility.h"
/* Console output macros */
#define CPUTS(outstr) cputs(CC_VBOOT, outstr)
#define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args)
#if 0 /* change this to debug memory usage */
#define DPRINTF CPRINTF
#else
#define DPRINTF(...)
#endif
/****************************************************************************/
void *Memcpy(void *dest, const void *src, uint64_t n)
{
return memcpy(dest, src, (size_t)n);
}
void *Memset(void *d, const uint8_t c, uint64_t n)
{
return memset(d, c, n);
}
int Memcmp(const void *src1, const void *src2, size_t n)
{
size_t i;
const uint8_t *a = src1;
const uint8_t *b = src2;
for (i = 0; i < n; i++) {
if (*a != *b)
return (*a < *b) ? -1 : 1;
a++;
b++;
}
return 0;
}
/****************************************************************************/
/* The vboot_api library requires some dynamic memory, but we don't have
* malloc/free. Instead we have one chunk of shared RAM that we can gain
* exclusive access to for a time. We'll have to experiment with various
* algorithms to see what works best. This algorithm allocates and
* reuses blocks, but never actually frees anything until all memory has been
* reclaimed. */
/* Since we only need this stuff to boot, don't waste run-time .bss */
static struct {
int bucket_size; /* total RAM available */
uint8_t *out_base; /* malloc from here */
int out_count; /* number of active mallocs */
int out_size; /* high-water mark */
/* We have a limited number of active mallocs. We never free, but we
* do reuse slots. */
#define MAX_SLOTS 8
struct {
int in_use; /* is this slot active? */
void *ptr; /* starts here */
size_t size; /* how big */
} slots[MAX_SLOTS];
} *bucket;
void *VbExMalloc(size_t size)
{
int i, j;
void *ptr = 0;
if (!bucket) {
i = shared_mem_size();
if (EC_SUCCESS != shared_mem_acquire(i, 1, (char **)&bucket)) {
CPRINTF("FAILED at %s:%d\n", __FILE__, __LINE__);
ASSERT(0);
}
Memset(bucket, 0, sizeof(*bucket));
bucket->bucket_size = i;
bucket->out_base = (uint8_t *)(bucket + 1);
bucket->out_size = sizeof(*bucket);
DPRINTF("grab the bucket: at 0x%x, size 0x%x\n",
bucket, bucket->bucket_size);
}
if (size % 8) {
int tmp = (size + 8) & ~0x7ULL;
DPRINTF(" %d -> %d\n", size, tmp);
size = tmp;
}
for (i = 0; i < MAX_SLOTS; i++) {
if (!bucket->slots[i].in_use) {
/* Found an empty one, but reuse the same size if one
* already exists. */
for (j = i; j < MAX_SLOTS; j++) {
if (!bucket->slots[j].in_use &&
size == bucket->slots[j].size) {
/* empty AND same size */
bucket->slots[j].in_use = 1;
ptr = bucket->slots[j].ptr;
DPRINTF(" = %d (%d)\n", j, size);
goto out;
}
}
/* no exact matches, must allocate a new chunk */
ptr = bucket->out_base + bucket->out_size;
bucket->out_size += size;
bucket->slots[i].in_use = 1;
bucket->slots[i].ptr = ptr;
bucket->slots[i].size = size;
DPRINTF(" + %d (%d)\n", i, size);
goto out;
}
}
CPRINTF("FAILED: no empty slots (%d/%d)\n", i, MAX_SLOTS);
ASSERT(0);
out:
bucket->out_count++;
if (bucket->out_size >= bucket->bucket_size) {
CPRINTF("FAILED: out of memory (%d/%d)\n",
bucket->out_size, bucket->bucket_size);
ASSERT(0);
}
return ptr;
}
void VbExFree(void *ptr)
{
int i;
for (i = 0; i < MAX_SLOTS; i++) {
if (ptr == bucket->slots[i].ptr) {
bucket->slots[i].in_use = 0;
DPRINTF(" - %d (%d)\n", i, bucket->slots[i].size);
break;
}
}
if (MAX_SLOTS == i) {
CPRINTF("FAILED: can't find ptr %x!\n", ptr);
ASSERT(0);
}
bucket->out_count--;
if (!bucket->out_count) {
DPRINTF("dump the bucket: max used = %d\n", bucket->out_size);
shared_mem_release(bucket);
bucket = 0;
}
}