128 lines
3.5 KiB
C
128 lines
3.5 KiB
C
|
/* Copyright 2015 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.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Temporary secure storage commands for use by the host for verified boot
|
||
|
* related activities such as storing the hash of verified firmware for use
|
||
|
* in suspend/resume.
|
||
|
*
|
||
|
* There are a configurable number of vstore slots, with all slots having
|
||
|
* the same size of EC_VSTORE_SLOT_SIZE (64 bytes).
|
||
|
*
|
||
|
* Slots can be written once per AP power-on and will then be locked and
|
||
|
* cannot be written again until it is cleared in the CHIPSET_SHUTDOWN
|
||
|
* or CHIPSET_RESET hooks.
|
||
|
*/
|
||
|
|
||
|
#include "common.h"
|
||
|
#include "hooks.h"
|
||
|
#include "host_command.h"
|
||
|
#include "system.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
#define VSTORE_SYSJUMP_TAG 0x5653 /* "VS" */
|
||
|
#define VSTORE_HOOK_VERSION 1
|
||
|
|
||
|
struct vstore_slot {
|
||
|
uint8_t locked;
|
||
|
uint8_t data[EC_VSTORE_SLOT_SIZE];
|
||
|
};
|
||
|
|
||
|
static struct vstore_slot vstore_slots[CONFIG_VSTORE_SLOT_COUNT];
|
||
|
static const int vstore_size =
|
||
|
sizeof(struct vstore_slot) * CONFIG_VSTORE_SLOT_COUNT;
|
||
|
BUILD_ASSERT(ARRAY_SIZE(vstore_slots) <= EC_VSTORE_SLOT_MAX);
|
||
|
|
||
|
/*
|
||
|
* vstore_info - Get slot count and mask of locked slots.
|
||
|
*/
|
||
|
static enum ec_status vstore_info(struct host_cmd_handler_args *args)
|
||
|
{
|
||
|
struct ec_response_vstore_info *r = args->response;
|
||
|
int i;
|
||
|
|
||
|
r->slot_count = CONFIG_VSTORE_SLOT_COUNT;
|
||
|
r->slot_locked = 0;
|
||
|
for (i = 0; i < CONFIG_VSTORE_SLOT_COUNT; i++)
|
||
|
if (vstore_slots[i].locked)
|
||
|
r->slot_locked |= 1 << i;
|
||
|
|
||
|
args->response_size = sizeof(*r);
|
||
|
|
||
|
return EC_RES_SUCCESS;
|
||
|
}
|
||
|
DECLARE_HOST_COMMAND(EC_CMD_VSTORE_INFO, vstore_info, EC_VER_MASK(0));
|
||
|
|
||
|
/*
|
||
|
* vstore_read - Read slot from temporary secure storage.
|
||
|
*
|
||
|
* Response is EC_VSTORE_SLOT_SIZE bytes of data.
|
||
|
*/
|
||
|
static enum ec_status vstore_read(struct host_cmd_handler_args *args)
|
||
|
{
|
||
|
const struct ec_params_vstore_read *p = args->params;
|
||
|
struct ec_response_vstore_read *r = args->response;
|
||
|
|
||
|
if (p->slot >= CONFIG_VSTORE_SLOT_COUNT)
|
||
|
return EC_RES_INVALID_PARAM;
|
||
|
|
||
|
memcpy(r->data, vstore_slots[p->slot].data, EC_VSTORE_SLOT_SIZE);
|
||
|
|
||
|
args->response_size = sizeof(*r);
|
||
|
|
||
|
return EC_RES_SUCCESS;
|
||
|
}
|
||
|
DECLARE_HOST_COMMAND(EC_CMD_VSTORE_READ, vstore_read, EC_VER_MASK(0));
|
||
|
|
||
|
/*
|
||
|
* vstore_write - Write temporary secure storage slot and lock it.
|
||
|
*/
|
||
|
static enum ec_status vstore_write(struct host_cmd_handler_args *args)
|
||
|
{
|
||
|
const struct ec_params_vstore_write *p = args->params;
|
||
|
struct vstore_slot *slot;
|
||
|
|
||
|
if (p->slot >= CONFIG_VSTORE_SLOT_COUNT)
|
||
|
return EC_RES_INVALID_PARAM;
|
||
|
slot = &vstore_slots[p->slot];
|
||
|
|
||
|
if (slot->locked)
|
||
|
return EC_RES_ACCESS_DENIED;
|
||
|
slot->locked = 1;
|
||
|
memcpy(slot->data, p->data, EC_VSTORE_SLOT_SIZE);
|
||
|
|
||
|
return EC_RES_SUCCESS;
|
||
|
}
|
||
|
DECLARE_HOST_COMMAND(EC_CMD_VSTORE_WRITE, vstore_write, EC_VER_MASK(0));
|
||
|
|
||
|
static void vstore_clear_lock(void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < CONFIG_VSTORE_SLOT_COUNT; i++)
|
||
|
vstore_slots[i].locked = 0;
|
||
|
}
|
||
|
DECLARE_HOOK(HOOK_CHIPSET_RESET, vstore_clear_lock, HOOK_PRIO_DEFAULT);
|
||
|
|
||
|
static void vstore_preserve_state(void)
|
||
|
{
|
||
|
system_add_jump_tag(VSTORE_SYSJUMP_TAG, VSTORE_HOOK_VERSION,
|
||
|
vstore_size, vstore_slots);
|
||
|
}
|
||
|
DECLARE_HOOK(HOOK_SYSJUMP, vstore_preserve_state, HOOK_PRIO_DEFAULT);
|
||
|
|
||
|
static void vstore_init(void)
|
||
|
{
|
||
|
const struct vstore_slot *prev;
|
||
|
int version, size;
|
||
|
|
||
|
prev = (const struct vstore_slot *)system_get_jump_tag(
|
||
|
VSTORE_SYSJUMP_TAG, &version, &size);
|
||
|
|
||
|
if (prev && version == VSTORE_HOOK_VERSION && size == vstore_size)
|
||
|
memcpy(vstore_slots, prev, vstore_size);
|
||
|
}
|
||
|
DECLARE_HOOK(HOOK_INIT, vstore_init, HOOK_PRIO_DEFAULT);
|