Zhang, Yang wrote: >The patch is modified. Without the arg of nvram, the patch will do nothing Sorry, I has upload the wrong patch. Please drop it. This is the right one. Please review it. >From 3cce00ce9ac25c723dec34226991c61d89f79e70 Mon Sep 17 00:00:00 2001 From: Zhang Yang <yang.zhang@xxxxxxxxx> Date: Wed, 24 Dec 2008 11:54:38 +0800 Subject: [PATCH] KVM : Qemu: Save nvram Save nvram to the file Signed-off-by: Zhang Yang <yang.zhang@xxxxxxxxx> --- qemu/hw/ipf.c | 21 ++++++++- qemu/target-ia64/firmware.c | 110 ++++++++++++++++++++++++++++++++++++++++-- qemu/target-ia64/firmware.h | 24 +++++++++- qemu/vl.c | 9 ++++ 4 files changed, 155 insertions(+), 9 deletions(-) diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c index 3e24c98..4e9b052 100644 --- a/qemu/hw/ipf.c +++ b/qemu/hw/ipf.c @@ -53,6 +53,7 @@ static fdctrl_t *floppy_controller; static RTCState *rtc_state; static PCIDevice *i440fx_state; +uint8_t *g_fw_start; static uint32_t ipf_to_legacy_io(target_phys_addr_t addr) { return (uint32_t)(((addr&0x3ffffff) >> 12 << 2)|((addr) & 0x3)); @@ -454,9 +455,14 @@ static void ipf_init1(ram_addr_t ram_size, int vga_ram_size, unsigned long image_size; char *image = NULL; uint8_t *fw_image_start; + unsigned long nvram_addr = 0; + unsigned long nvram_fd = 0; + unsigned long type = READ_FROM_NVRAM; + unsigned long i = 0; ram_addr_t fw_offset = qemu_ram_alloc(GFW_SIZE); uint8_t *fw_start = phys_ram_base + fw_offset; + g_fw_start = fw_start; snprintf(buf, sizeof(buf), "%s/%s", bios_dir, FW_FILENAME); image = read_image(buf, &image_size ); if (NULL == image || !image_size) { @@ -472,7 +478,20 @@ static void ipf_init1(ram_addr_t ram_size, int vga_ram_size, free(image); flush_icache_range((unsigned long)fw_image_start, (unsigned long)fw_image_start + image_size); - kvm_ia64_build_hob(ram_size + above_4g_mem_size, smp_cpus, fw_start); + + nvram_addr = NVRAM_START; + if (nvram) { + nvram_fd = kvm_ia64_nvram_init(type); + if (nvram_fd != -1) { + kvm_ia64_copy_from_nvram_to_GFW(nvram_fd, g_fw_start); + close(nvram_fd); + } + i = atexit(kvm_ia64_copy_from_GFW_to_nvram); + if (i != 0) + fprintf(stderr, "cannot set exit function\n"); + } + kvm_ia64_build_hob(ram_size + above_4g_mem_size, smp_cpus, + fw_start, nvram_addr); } /*Register legacy io address space, size:64M*/ diff --git a/qemu/target-ia64/firmware.c b/qemu/target-ia64/firmware.c index bac2721..88fcaa8 100644 --- a/qemu/target-ia64/firmware.c +++ b/qemu/target-ia64/firmware.c @@ -31,6 +31,8 @@ #include "firmware.h" +#include "qemu-common.h" + typedef struct { unsigned long signature; unsigned int type; @@ -85,14 +87,16 @@ static int hob_init(void *buffer ,unsigned long buf_size); static int add_pal_hob(void* hob_buf); static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size); static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu); -static int build_hob(void* hob_buf, unsigned long hob_buf_size, - unsigned long dom_mem_size, unsigned long vcpus); +static int add_nvram_hob(void *hob_buf, unsigned long nvram_addr); +static int build_hob(void *hob_buf, unsigned long hob_buf_size, + unsigned long dom_mem_size, unsigned long vcpus, + unsigned long nvram_addr); static int load_hob(void *hob_buf, unsigned long dom_mem_size, void* hob_start); int -kvm_ia64_build_hob(unsigned long memsize, - unsigned long vcpus, uint8_t* fw_start) +kvm_ia64_build_hob(unsigned long memsize, unsigned long vcpus, + uint8_t *fw_start, unsigned long nvram_addr) { char *hob_buf; @@ -102,7 +106,7 @@ kvm_ia64_build_hob(unsigned long memsize, return -1; } - if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus) < 0) { + if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) { free(hob_buf); Hob_Output("Could not build hob"); return -1; @@ -206,7 +210,8 @@ add_max_hob_entry(void* hob_buf) static int build_hob(void* hob_buf, unsigned long hob_buf_size, - unsigned long dom_mem_size, unsigned long vcpus) + unsigned long dom_mem_size, unsigned long vcpus, + unsigned long nvram_addr) { //Init HOB List if (hob_init(hob_buf, hob_buf_size) < 0) { @@ -229,6 +234,11 @@ build_hob(void* hob_buf, unsigned long hob_buf_size, goto err_out; } + if (add_nvram_hob(hob_buf, nvram_addr) < 0) { + Hob_Output("Add nvram hob failed, buffer too small"); + goto err_out; + } + if (add_max_hob_entry(hob_buf) < 0) { Hob_Output("Add max hob entry failed, buffer too small"); goto err_out; @@ -285,6 +295,13 @@ add_vcpus_hob(void* hob_buf, unsigned long vcpus) return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus)); } +static int +add_nvram_hob(void *hob_buf, unsigned long nvram_addr) +{ + return hob_add(hob_buf, HOB_TYPE_NR_NVRAM, + &nvram_addr, sizeof(nvram_addr)); +} + static const unsigned char config_pal_bus_get_features_data[24] = { 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -581,6 +598,87 @@ out_1: return NULL; } +int kvm_ia64_nvram_init(unsigned long type) +{ + unsigned long nvram_fd; + char nvram_path[PATH_MAX]; + unsigned long i; + + if (nvram) { + if (strlen(nvram) > PATH_MAX) { + goto out; + } + if (type == READ_FROM_NVRAM) { + if (access(nvram, R_OK | W_OK | X_OK) == -1) + goto out; + nvram_fd = open(nvram, O_RDONLY); + return nvram_fd; + } + else { /* write from gfw to nvram file */ + i = access(nvram, R_OK | W_OK | X_OK); + if ((i == -1) && (errno != ENOENT)) + goto out; + nvram_fd = open(nvram, O_CREAT|O_RDWR, 0777); + return nvram_fd; + } + } + else { + strcpy(nvram_path, "nvram.dat"); + if (type == READ_FROM_NVRAM) { + if (access(nvram_path, R_OK | W_OK | X_OK) == -1) + goto out; + nvram_fd = open(nvram_path, O_RDONLY); + return nvram_fd; + } + else { /* write from gfw to nvram file */ + i = access(nvram_path, R_OK | W_OK | X_OK); + if ((i == -1) && (errno != ENOENT)) + goto out; + nvram_fd = open(nvram_path, O_CREAT|O_RDWR, 0777); + return nvram_fd; + } + } +out: + return -1; +} + +int +kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd, + const uint8_t *fw_start) +{ + struct stat file_stat; + if ((fstat(nvram_fd, &file_stat) < 0) || + (NVRAM_SIZE != file_stat.st_size) || + (read(nvram_fd, fw_start + NVRAM_OFFSET, NVRAM_SIZE) != NVRAM_SIZE)) + return -1; + return 0; +} + +int +kvm_ia64_copy_from_GFW_to_nvram() +{ + unsigned long nvram_fd; + unsigned long type = WRITE_TO_NVRAM; + unsigned long *nvram_addr = (unsigned long *)(g_fw_start + NVRAM_OFFSET); + nvram_fd = kvm_ia64_nvram_init(type); + if (nvram_fd == -1) + goto out; + if (((struct nvram_save_addr *)nvram_addr)->signature != NVRAM_VALID_SIG) { + close(nvram_fd); + goto out; + } + lseek(nvram_fd, 0, SEEK_SET); + if (write(nvram_fd, ((void *)(((struct nvram_save_addr *)nvram_addr)->addr + + (char *)phys_ram_base)), NVRAM_SIZE) != NVRAM_SIZE) { + close(nvram_fd); + goto out; + } + close(nvram_fd); + return 0; +out: + return -1; +} + /* * Local variables: * mode: C diff --git a/qemu/target-ia64/firmware.h b/qemu/target-ia64/firmware.h index 553a9f9..47aaa1d 100644 --- a/qemu/target-ia64/firmware.h +++ b/qemu/target-ia64/firmware.h @@ -37,8 +37,28 @@ #define Hob_Output(s) fprintf(stderr, s) -extern int kvm_ia64_build_hob(unsigned long memsize, - unsigned long vcpus, uint8_t* fw_start); +#define NVRAM_START (GFW_START + NVRAM_OFFSET) +#define NVRAM_OFFSET (10 * (1UL << 20)) +#define NVRAM_SIZE (64 * (1UL << 10)) +#define NVRAM_VALID_SIG 0x4650494e45584948 /* "HIXENIPF" */ +#define VALIDATE_NVRAM_FD(x) ((1UL<<(sizeof(x)*8 - 1)) | x) +#define IS_VALID_NVRAM_FD(x) ((uint64_t)x >> (sizeof(x)*8 - 1)) +#define READ_FROM_NVRAM 0 +#define WRITE_TO_NVRAM 1 + +struct nvram_save_addr { + unsigned long addr; + unsigned long signature; +}; + +extern const char *nvram; +extern uint8_t *g_fw_start; +extern int kvm_ia64_build_hob(unsigned long memsize, unsigned long vcpus, + uint8_t *fw_start, unsigned long nvram_addr); extern char *read_image(const char *filename, unsigned long *size); +extern int kvm_ia64_copy_from_GFW_to_nvram(); +extern int kvm_ia64_nvram_init(unsigned long type); +extern int kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd, + const uint8_t *fw_start); #endif //__FIRM_WARE_ diff --git a/qemu/vl.c b/qemu/vl.c index 7b58605..fe29ecd 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -255,6 +255,7 @@ unsigned int nb_prom_envs = 0; const char *prom_envs[MAX_PROM_ENVS]; #endif int nb_drives_opt; +const char *nvram = NULL; struct drive_opt drives_opt[MAX_DRIVES]; static CPUState *cur_cpu; @@ -3991,6 +3992,9 @@ static void help(int exitcode) #if defined(TARGET_PPC) || defined(TARGET_SPARC) "-g WxH[xDEPTH] Set the initial graphical resolution and depth\n" #endif +#ifdef TARGET_IA64 + "-nvram file use 'file' to save or load nvram image\n" +#endif "-name string set the name of the guest\n" "-uuid %%08x-%%04x-%%04x-%%04x-%%012x specify machine UUID\n" "\n" @@ -4215,6 +4219,7 @@ enum { QEMU_OPTION_semihosting, QEMU_OPTION_cpu_vendor, QEMU_OPTION_name, + QEMU_OPTION_nvram, QEMU_OPTION_prom_env, QEMU_OPTION_old_param, QEMU_OPTION_clock, @@ -4345,6 +4350,7 @@ static const QEMUOption qemu_options[] = { { "tdf", 0, QEMU_OPTION_tdf }, /* enable time drift fix */ { "kvm-shadow-memory", HAS_ARG, QEMU_OPTION_kvm_shadow_memory }, { "name", HAS_ARG, QEMU_OPTION_name }, + { "nvram", HAS_ARG, QEMU_OPTION_nvram }, #if defined(TARGET_SPARC) { "prom-env", HAS_ARG, QEMU_OPTION_prom_env }, #endif @@ -5418,6 +5424,9 @@ int main(int argc, char **argv) case QEMU_OPTION_incoming: incoming = optarg; break; + case QEMU_OPTION_nvram: + nvram = optarg; + break; } } } -- 1.6.0.rc1
Attachment:
0001-KVM-Qemu-Save-nvram.patch
Description: 0001-KVM-Qemu-Save-nvram.patch