mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-20 20:53:46 +00:00
DM: ovmf NV storage writeback support
To support modification of OVMF NV storage, add an option "w" for --ovmf to write the changed OVMF NV data section back to the OVMF image from guest memory before deinit operations. This will enable persistent EFI variables. Only option "w" is supported, dm will exit if passing invalid option. It expects OVMF NV storage writeback with option "w" when power off or reboot the UOS, poweroff, cold and warm reboot in EFI shell and when dm recieves SIGINT and SIGHUP. Tracked-On: #3413 Signed-off-by: Yang, Yu-chu <yu-chu.yang@intel.com> Reviewed-by:Eddie Dong <eddie.dong@intel.com> Acked-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
parent
c787aaa328
commit
16a7d2522c
@ -516,6 +516,12 @@ vrtc_fail:
|
||||
static void
|
||||
vm_deinit_vdevs(struct vmctx *ctx)
|
||||
{
|
||||
/*
|
||||
* Write ovmf NV storage back to the original file from guest
|
||||
* memory before deinit operations.
|
||||
*/
|
||||
acrn_writeback_ovmf_nvstorage(ctx);
|
||||
|
||||
deinit_pci(ctx);
|
||||
monitor_close();
|
||||
|
||||
@ -535,6 +541,12 @@ vm_deinit_vdevs(struct vmctx *ctx)
|
||||
static void
|
||||
vm_reset_vdevs(struct vmctx *ctx)
|
||||
{
|
||||
/*
|
||||
* Write ovmf NV storage back to the original file from guest
|
||||
* memory before deinit operations.
|
||||
*/
|
||||
acrn_writeback_ovmf_nvstorage(ctx);
|
||||
|
||||
/*
|
||||
* The current virtual devices doesn't define virtual
|
||||
* device reset function. So we call vdev deinit/init
|
||||
|
@ -48,17 +48,27 @@
|
||||
* | |
|
||||
* + NV data storage +
|
||||
* | |
|
||||
* +--------------------------------------------------+
|
||||
* +--------------------------------------------------+ <--OVMF offset 0
|
||||
*/
|
||||
|
||||
/* ovmf real entry is reset vector, which is (OVMF_TOP - 16) */
|
||||
#define OVMF_TOP(ctx) (4*GB)
|
||||
|
||||
/* ovmf NV storage begins at offset 0 */
|
||||
#define OVMF_NVSTORAGE_OFFSET (OVMF_TOP(ctx) - ovmf_size)
|
||||
|
||||
/* ovmf image size limit */
|
||||
#define OVMF_SZ_LIMIT (2*MB)
|
||||
|
||||
/* ovmf NV storage size */
|
||||
#define OVMF_NVSTORAGE_SZ (128*KB)
|
||||
|
||||
/* located in the ROM area */
|
||||
#define OVMF_E820_BASE 0x000EF000UL
|
||||
|
||||
static char ovmf_path[STR_LEN];
|
||||
static size_t ovmf_size;
|
||||
bool writeback_nv_storage;
|
||||
|
||||
extern int init_cmos_vrpmb(struct vmctx *ctx);
|
||||
|
||||
@ -72,17 +82,30 @@ int
|
||||
acrn_parse_ovmf(char *arg)
|
||||
{
|
||||
int error = -1;
|
||||
char *str, *cp, *token = NULL;
|
||||
size_t len = strnlen(arg, STR_LEN);
|
||||
|
||||
str = strdup(arg);
|
||||
if (len < STR_LEN) {
|
||||
strncpy(ovmf_path, arg, len + 1);
|
||||
if (check_image(ovmf_path, 2 * MB, &ovmf_size) == 0) {
|
||||
ovmf_file_name = ovmf_path;
|
||||
printf("SW_LOAD: get ovmf path %s, size 0x%lx\n",
|
||||
ovmf_path, ovmf_size);
|
||||
error = 0;
|
||||
cp = str;
|
||||
token = strsep(&cp, ",");
|
||||
while (token != NULL) {
|
||||
if (strcmp(token, "w") == 0) {
|
||||
writeback_nv_storage = true;
|
||||
} else {
|
||||
len = strnlen(token, STR_LEN);
|
||||
strncpy(ovmf_path, token, len + 1);
|
||||
if (check_image(ovmf_path, OVMF_SZ_LIMIT, &ovmf_size) != 0)
|
||||
break;
|
||||
ovmf_file_name = ovmf_path;
|
||||
printf("SW_LOAD: get ovmf path %s, size 0x%lx\n",
|
||||
ovmf_path, ovmf_size);
|
||||
error = 0;
|
||||
}
|
||||
token = strsep(&cp, ",");
|
||||
}
|
||||
}
|
||||
free(str);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -123,7 +146,6 @@ acrn_prepare_ovmf(struct vmctx *ctx)
|
||||
fclose(fp);
|
||||
printf("SW_LOAD: partition blob %s size %lu copy to guest 0x%lx\n",
|
||||
ovmf_path, ovmf_size, OVMF_TOP(ctx) - ovmf_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -171,3 +193,55 @@ acrn_sw_load_ovmf(struct vmctx *ctx)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The NV data section is the first 128KB in the OVMF image. At runtime,
|
||||
* it's copied into guest memory and behave as RAM to OVMF. It can be
|
||||
* accessed and updated by OVMF. To preserve NV section (referred to
|
||||
* as Non-Volatile Data Store section in the OVMF spec), we're flushing
|
||||
* in-memory data back to the NV data section of the OVMF image file
|
||||
* at designated points.
|
||||
*/
|
||||
int
|
||||
acrn_writeback_ovmf_nvstorage(struct vmctx *ctx)
|
||||
{
|
||||
FILE *fp;
|
||||
size_t write;
|
||||
|
||||
if (!writeback_nv_storage)
|
||||
return 0;
|
||||
|
||||
fp = fopen(ovmf_path, "r+");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr,
|
||||
"OVMF_WRITEBACK ERR: could not open ovmf file: %s\n",
|
||||
ovmf_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
if (ftell(fp) != ovmf_size) {
|
||||
fprintf(stderr,
|
||||
"SW_LOAD ERR: ovmf file changed\n");
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
write = fwrite(ctx->baseaddr + OVMF_NVSTORAGE_OFFSET,
|
||||
sizeof(char), OVMF_NVSTORAGE_SZ, fp);
|
||||
|
||||
if (write < OVMF_NVSTORAGE_SZ) {
|
||||
fprintf(stderr,
|
||||
"OVMF_WRITEBACK ERR: could not write back OVMF\n");
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
printf("OVMF_WRITEBACK: OVMF has been written back \
|
||||
to partition blob %s size %lu from guest 0x%lx\n",
|
||||
ovmf_path, OVMF_NVSTORAGE_SZ, OVMF_NVSTORAGE_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ struct e820_entry {
|
||||
|
||||
extern const struct e820_entry e820_default_entries[NUM_E820_ENTRIES];
|
||||
extern int with_bootargs;
|
||||
extern bool writeback_nv_storage;
|
||||
|
||||
size_t ovmf_image_size(void);
|
||||
|
||||
@ -78,6 +79,7 @@ int acrn_sw_load_bzimage(struct vmctx *ctx);
|
||||
int acrn_sw_load_elf(struct vmctx *ctx);
|
||||
int acrn_sw_load_vsbl(struct vmctx *ctx);
|
||||
int acrn_sw_load_ovmf(struct vmctx *ctx);
|
||||
int acrn_writeback_ovmf_nvstorage(struct vmctx *ctx);
|
||||
int acrn_sw_load(struct vmctx *ctx);
|
||||
#endif
|
||||
|
||||
|
@ -33,15 +33,13 @@
|
||||
#include <uuid/uuid.h>
|
||||
#include "types.h"
|
||||
#include "vmm.h"
|
||||
#include "macros.h"
|
||||
|
||||
/*
|
||||
* API version for out-of-tree consumers for making compile time decisions.
|
||||
*/
|
||||
#define VMMAPI_VERSION 0103 /* 2 digit major followed by 2 digit minor */
|
||||
|
||||
#define MB (1024 * 1024UL)
|
||||
#define GB (1024 * 1024 * 1024UL)
|
||||
|
||||
#define ALIGN_UP(x, align) (((x) + ((align)-1)) & ~((align)-1))
|
||||
#define ALIGN_DOWN(x, align) ((x) & ~((align)-1))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user