acrn-hypervisor/hypervisor/boot/sbl/sbl_seed_parse.c

185 lines
4.9 KiB
C

/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <hypervisor.h>
#include <sbl_seed_parse.h>
#define SEED_ENTRY_TYPE_SVNSEED 0x1U
/* #define SEED_ENTRY_TYPE_RPMBSEED 0x2U */
/* #define SEED_ENTRY_USAGE_USEED 0x1U */
#define SEED_ENTRY_USAGE_DSEED 0x2U
struct seed_list_hob {
uint8_t revision;
uint8_t reserved0[3];
uint32_t buffer_size;
uint8_t total_seed_count;
uint8_t reserved1[3];
};
struct seed_entry {
/* SVN based seed or RPMB seed or attestation key_box */
uint8_t type;
/* For SVN seed: useed or dseed
* For RPMB seed: serial number based or not
*/
uint8_t usage;
/* index for the same type and usage seed */
uint8_t index;
uint8_t reserved;
/* reserved for future use */
uint16_t flags;
/* Total size of this seed entry */
uint16_t seed_entry_size;
/* SVN seed: struct seed_info
* RPMB seed: uint8_t rpmb_key[key_len]
*/
uint8_t seed[0];
};
struct image_boot_params {
uint32_t size_of_this_struct;
uint32_t version;
uint64_t p_seed_list;
uint64_t p_platform_info;
uint64_t reserved;
};
static const char *boot_params_arg = "ImageBootParamsAddr=";
static void parse_seed_list_sbl(struct seed_list_hob *seed_hob)
{
uint8_t i;
uint8_t dseed_index = 0U;
struct seed_entry *entry;
struct seed_info dseed_list[BOOTLOADER_SEED_MAX_ENTRIES];
bool parse_success = false;
if ((seed_hob != NULL) && (seed_hob->total_seed_count != 0U)) {
parse_success = true;
entry = (struct seed_entry *)((uint8_t *)seed_hob + sizeof(struct seed_list_hob));
for (i = 0U; i < seed_hob->total_seed_count; i++) {
if (entry == NULL) {
break;
}
/* retrieve dseed */
if ((SEED_ENTRY_TYPE_SVNSEED == entry->type) && (SEED_ENTRY_USAGE_DSEED == entry->usage)) {
/* The seed_entry with same type/usage are always
* arranged by index in order of 0~3.
*/
if (entry->index != dseed_index) {
pr_warn("Index mismatch. Use fake seed!");
parse_success = false;
break;
}
if (entry->index >= BOOTLOADER_SEED_MAX_ENTRIES) {
pr_warn("Index exceed max number!");
parse_success = false;
break;
}
(void)memcpy_s((void *)&dseed_list[dseed_index], sizeof(struct seed_info),
(void *)entry->seed, sizeof(struct seed_info));
dseed_index++;
/* erase original seed in seed entry */
(void)memset((void *)entry->seed, 0U, sizeof(struct seed_info));
}
entry = (struct seed_entry *)((uint8_t *)entry + entry->seed_entry_size);
}
}
if (parse_success) {
trusty_set_dseed((void *)dseed_list, dseed_index);
} else {
trusty_set_dseed(NULL, 0U);
}
(void)memset((void *)dseed_list, 0U, sizeof(dseed_list));
}
/*
* sbl_seed_parse
*
* description:
* This function parse image_boot_params from cmdline. Mainly on
* 1. parse structure address from cmdline
* 2. get seed_list address and call parse_seed_list_sbl to parse seed
* 3. convert address in the structure from HPA to SOS's GPA
* 4. clear original image_boot_params argument in cmdline since
* original address is HPA.
*
* input:
* vm pointer to vm structure
* cmdline pointer to cmdline string
* out_len the max len of out_arg
*
* output:
* out_arg the argument with SOS's GPA
*
* return value:
* true if parse successfully, otherwise false.
*/
bool sbl_seed_parse(struct acrn_vm *vm, char *cmdline, char *out_arg, uint32_t out_len)
{
char *arg, *arg_end;
char *param;
void *param_addr;
struct image_boot_params *boot_params;
uint32_t len;
bool parse_success = false;
if (is_sos_vm(vm) && (cmdline != NULL)) {
len = strnlen_s(boot_params_arg, MEM_1K);
arg = strstr_s((const char *)cmdline, MEM_2K, boot_params_arg, len);
if (arg != NULL) {
param = arg + len;
param_addr = (void *)hpa2hva(strtoul_hex(param));
if (param_addr != NULL) {
boot_params = (struct image_boot_params *)param_addr;
parse_seed_list_sbl((struct seed_list_hob *)hpa2hva(boot_params->p_seed_list));
/*
* Convert the addresses to SOS GPA since this structure will
* be used in SOS.
*/
boot_params->p_seed_list = sos_vm_hpa2gpa(boot_params->p_seed_list);
boot_params->p_platform_info = sos_vm_hpa2gpa(boot_params->p_platform_info);
/*
* Replace original arguments with spaces since SOS's GPA is not
* identity mapped to HPA. The argument will be appended later when
* compose cmdline for SOS.
*/
arg_end = strchr(arg, ' ');
len = (arg_end != NULL) ? (uint32_t)(arg_end - arg) : strnlen_s(arg, MEM_2K);
(void)memset((void *)arg, ' ', len);
/* Convert the param_addr to SOS GPA and copy to caller */
if (out_arg != NULL) {
snprintf(out_arg, out_len, "%s0x%X ",
boot_params_arg, hva2gpa(vm, param_addr));
}
parse_success = true;
}
}
}
if (!parse_success) {
parse_seed_list_sbl(NULL);
}
return parse_success;
}