Hi Please drop former. This is the modify patch for save nvram. I add the new command line arg of "-nvram file" to specify the location Of the file. Without the arg ,it will save the nvram in the current dir and named as "nvram.dat". Also, it will read the saved file "nvram.dat" from current dir without the arg.
>From 902ac71c035a641ac0c9e0a0859d8198dfbe3319 Mon Sep 17 00:00:00 2001 From: Zhang Yang <yang.zh...@intel.com> Date: Mon, 15 Dec 2008 23:56:12 +0800 Subject: [PATCH] KVM : Qemu: Save nvram Save nvram to the file Signed-off-by: Zhang Yang <yang.zh...@intel.com> --- qemu/hw/ipf.c | 20 +++++++- qemu/target-ia64/firmware.c | 110 ++++++++++++++++++++++++++++++++++++++++-- qemu/target-ia64/firmware.h | 24 +++++++++- qemu/vl.c | 9 ++++ 4 files changed, 154 insertions(+), 9 deletions(-) diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c index 3e24c98..ba3f0b4 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,19 @@ 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; + 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
0001-KVM-Qemu-Save-nvram.patch
Description: 0001-KVM-Qemu-Save-nvram.patch