Files
acrn-hypervisor/devicemodel/core/sw_load_vsbl.c
Geoffroy Van Cutsem 8b16be9185 Remove "All rights reserved" string headers
Many of the license and Intel copyright headers include the "All rights
reserved" string. It is not relevant in the context of the BSD-3-Clause
license that the code is released under. This patch removes those strings
throughout the code (hypervisor, devicemodel and misc).

Tracked-On: #7254
Signed-off-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
2022-04-06 13:21:02 +08:00

313 lines
9.0 KiB
C

/*-
* Copyright (c) 2018 Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "dm.h"
#include "vmmapi.h"
#include "sw_load.h"
#include "acpi.h"
#include "log.h"
/* If the vsbl is loaded by DM, the User VM memory layout will be like:
*
* | ... |
* +--------------------------------------------------+
* | offset: 0xf2400 (ACPI table) |
* +--------------------------------------------------+
* | ... |
* +--------------------------------------------------+
* | offset: 16MB (vsbl image) |
* +--------------------------------------------------+
* | ... |
* +--------------------------------------------------+
* | offset: lowmem - 16K (partition blob) |
* +--------------------------------------------------+
* | offset: lowmem - 12K (e820 table) |
* +--------------------------------------------------+
* | offset: lowmem - 8K (boot_args_address) |
* +--------------------------------------------------+
* | offset: lowmem - 6K (vsbl entry address) |
* +--------------------------------------------------+
* | offset: lowmem - 4K (config_page with e820 table)|
* +--------------------------------------------------+
*/
/* vsbl binary layout:
*
* +--------------------------------------------------+ <--vSBL Top
* | |offset: Top - 0x10 (reset vector) |
* + STAGEINIT |------------------------------------+
* | (0x10000) |other |
* +--------------------------------------------------+
* | |
* + PAYLOAD +
* |(0x100000) |
* +--------------------------------------------------+
* | |
* + vFastboot +
* |(0x200000) |
* +--------------------------------------------------+
*/
/* Check default e820 table in sw_load_common.c for info about ctx->lowmem */
#define CONFIGPAGE_OFF(ctx) ((ctx)->lowmem - 4*KB)
#define VSBL_ENTRY_OFF(ctx) ((ctx)->lowmem - 6*KB)
#define BOOTARGS_OFF(ctx) ((ctx)->lowmem - 8*KB)
#define E820_TABLE_OFF(ctx) ((ctx)->lowmem - 12*KB)
#define GUEST_PART_INFO_OFF(ctx) ((ctx)->lowmem - 16*KB)
/* vsbl real entry is reset vector, which is (VSBL_TOP - 16) */
#define VSBL_TOP(ctx) (64*MB)
struct vsbl_para {
uint64_t e820_table_address;
uint64_t e820_entries;
uint64_t acpi_table_address;
uint64_t acpi_table_size;
uint64_t guest_part_info_address;
uint64_t guest_part_info_size;
uint64_t vsbl_address;
uint64_t vsbl_size;
uint64_t bootargs_address;
uint32_t trusty_enabled;
uint32_t key_info_lock;
uint32_t reserved;
uint32_t boot_device_address;
};
static char guest_part_info_path[STR_LEN];
static size_t guest_part_info_size;
static bool with_guest_part_info;
static char vsbl_path[STR_LEN];
static size_t vsbl_size;
static int boot_blk_bdf;
extern int init_cmos_vrpmb(struct vmctx *ctx);
#define LOW_8BIT(x) ((x) & 0xFF)
void
vsbl_set_bdf(int bnum, int snum, int fnum)
{
boot_blk_bdf = (LOW_8BIT(bnum) << 16) | (LOW_8BIT(snum) << 8) |
LOW_8BIT(fnum);
}
int
acrn_parse_guest_part_info(char *arg)
{
int error = -1;
size_t len = strnlen(arg, STR_LEN);
if (len < STR_LEN) {
strncpy(guest_part_info_path, arg, len + 1);
if (check_image(guest_part_info_path, 0, &guest_part_info_size) == 0) {
with_guest_part_info = true;
pr_info("SW_LOAD: get partition blob path %s\n",
guest_part_info_path);
error = 0;
}
}
return error;
}
static int
acrn_prepare_guest_part_info(struct vmctx *ctx)
{
FILE *fp;
long len;
size_t read;
fp = fopen(guest_part_info_path, "r");
if (fp == NULL) {
pr_err("SW_LOAD ERR: could not open partition blob %s\n",
guest_part_info_path);
return -1;
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
if (len != guest_part_info_size) {
pr_err("SW_LOAD ERR: partition blob changed\n");
fclose(fp);
return -1;
}
if ((len + GUEST_PART_INFO_OFF(ctx)) > BOOTARGS_OFF(ctx)) {
pr_err("SW_LOAD ERR: too large partition blob\n");
fclose(fp);
return -1;
}
fseek(fp, 0, SEEK_SET);
read = fread(ctx->baseaddr + GUEST_PART_INFO_OFF(ctx),
sizeof(char), len, fp);
if (read < len) {
pr_err("SW_LOAD ERR: could not read whole partition blob\n");
fclose(fp);
return -1;
}
fclose(fp);
pr_info("SW_LOAD: partition blob %s size %lu copy to guest 0x%lx\n",
guest_part_info_path, guest_part_info_size,
GUEST_PART_INFO_OFF(ctx));
return 0;
}
int
acrn_parse_vsbl(char *arg)
{
int error = -1;
size_t len = strnlen(arg, STR_LEN);
if (len < STR_LEN) {
strncpy(vsbl_path, arg, len + 1);
if (check_image(vsbl_path, 8 * MB, &vsbl_size) == 0) {
vsbl_file_name = vsbl_path;
pr_notice("SW_LOAD: get vsbl path %s\n", vsbl_path);
error = 0;
}
}
return error;
}
static int
acrn_prepare_vsbl(struct vmctx *ctx)
{
FILE *fp;
size_t read;
fp = fopen(vsbl_path, "r");
if (fp == NULL) {
pr_err("SW_LOAD ERR: could not open vsbl file: %s\n",
vsbl_path);
return -1;
}
fseek(fp, 0, SEEK_END);
if (ftell(fp) != vsbl_size) {
pr_err("SW_LOAD ERR: vsbl file changed\n");
fclose(fp);
return -1;
}
fseek(fp, 0, SEEK_SET);
read = fread(ctx->baseaddr + VSBL_TOP(ctx) - vsbl_size,
sizeof(char), vsbl_size, fp);
if (read < vsbl_size) {
pr_err("SW_LOAD ERR: could not read whole partition blob\n");
fclose(fp);
return -1;
}
fclose(fp);
pr_info("SW_LOAD: partition blob %s size %lu copy to guest 0x%lx\n",
vsbl_path, vsbl_size, VSBL_TOP(ctx) - vsbl_size);
return 0;
}
int
acrn_sw_load_vsbl(struct vmctx *ctx)
{
int ret;
struct e820_entry *e820;
struct vsbl_para *vsbl_para;
init_cmos_vrpmb(ctx);
vsbl_para = (struct vsbl_para *)
(ctx->baseaddr + CONFIGPAGE_OFF(ctx));
memset(vsbl_para, 0x0, sizeof(struct vsbl_para));
e820 = (struct e820_entry *)
(ctx->baseaddr + E820_TABLE_OFF(ctx));
vsbl_para->e820_entries = acrn_create_e820_table(ctx, e820);
vsbl_para->e820_table_address = E820_TABLE_OFF(ctx);
vsbl_para->acpi_table_address = get_acpi_base();
vsbl_para->acpi_table_size = get_acpi_table_length();
if (with_bootargs) {
strncpy(ctx->baseaddr + BOOTARGS_OFF(ctx), get_bootargs(), STR_LEN);
vsbl_para->bootargs_address = BOOTARGS_OFF(ctx);
} else {
vsbl_para->bootargs_address = 0;
}
if (with_guest_part_info) {
ret = acrn_prepare_guest_part_info(ctx);
if (ret)
return ret;
vsbl_para->guest_part_info_address = GUEST_PART_INFO_OFF(ctx);
vsbl_para->guest_part_info_size = guest_part_info_size;
} else {
vsbl_para->guest_part_info_address = 0;
vsbl_para->guest_part_info_size = 0;
}
ret = acrn_prepare_vsbl(ctx);
if (ret)
return ret;
vsbl_para->vsbl_address = VSBL_TOP(ctx) - vsbl_size;
vsbl_para->vsbl_size = vsbl_size;
vsbl_para->e820_entries = add_e820_entry(e820, vsbl_para->e820_entries,
vsbl_para->vsbl_address, vsbl_size, E820_TYPE_RESERVED);
pr_info("SW_LOAD: vsbl_entry 0x%lx\n", VSBL_TOP(ctx) - 16);
vsbl_para->boot_device_address = boot_blk_bdf;
vsbl_para->trusty_enabled = trusty_enabled;
/* set guest bsp state. Will call hypercall set bsp state
* after bsp is created.
*/
memset(&ctx->bsp_regs, 0, sizeof( struct acrn_vcpu_regs));
ctx->bsp_regs.vcpu_id = 0;
/* CR0_ET | CR0_NE */
ctx->bsp_regs.vcpu_regs.cr0 = 0x30U;
ctx->bsp_regs.vcpu_regs.cs_ar = 0x009FU;
ctx->bsp_regs.vcpu_regs.cs_sel = 0xF000U;
ctx->bsp_regs.vcpu_regs.cs_limit = 0xFFFFU;
ctx->bsp_regs.vcpu_regs.cs_base = (VSBL_TOP(ctx) - 16) &0xFFFF0000UL;
ctx->bsp_regs.vcpu_regs.rip = (VSBL_TOP(ctx) - 16) & 0xFFFFUL;
ctx->bsp_regs.vcpu_regs.gprs.rsi = CONFIGPAGE_OFF(ctx);
return 0;
}