This patch to save the nvram. It save the nvram by specify the arg of -name.And the saved file named by the arg. If do not specify the arg,it will not save the nvram >From d3e31cda03ef67efc860eaec2f93153e5535d744 Mon Sep 17 00:00:00 2001 From: Yang Zhang <yang.zhang@xxxxxxxxx> Date: Tue, 2 Dec 2008 10:02:00 +0800 Subject: [PATCH] Kvm: Qemu: save nvram support to save nvram to the file Signed-off-by: Yang Zhang <yang.zhang@xxxxxxxxx> --- qemu/hw/ipf.c | 15 ++++++- qemu/target-ia64/firmware.c | 107 +++++++++++++++++++++++++++++++++++++++++-- qemu/target-ia64/firmware.h | 22 ++++++++- 3 files changed, 135 insertions(+), 9 deletions(-) diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c index 337c854..cdbd4e0 100644 --- a/qemu/hw/ipf.c +++ b/qemu/hw/ipf.c @@ -51,6 +51,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) { @@ -454,9 +455,12 @@ 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; 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 +476,16 @@ 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); + if (qemu_name) { + nvram_addr = NVRAM_START; + if((nvram_fd = kvm_ia64_nvram_init()) != -1) { + kvm_ia64_copy_from_nvram_to_GFW(nvram_fd,g_fw_start); + close(nvram_fd); + } + atexit(kvm_ia64_copy_from_GFW_to_nvram); + } + 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..39c8361 100644 --- a/qemu/target-ia64/firmware.c +++ b/qemu/target-ia64/firmware.c @@ -31,6 +31,8 @@ #include "firmware.h" +#include "qemu-common.h" +#include "sysemu.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 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 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,7 @@ 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 +233,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 +294,12 @@ 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 +596,88 @@ out_1: return NULL; } +int kvm_ia64_nvram_init() +{ + unsigned long nvram_fd; + char nvram_path[PATH_MAX] = NVRAM_DIR; + char name[21] ; + + if(access(nvram_path, R_OK|W_OK|X_OK) == -1) + { + if(errno != ENOENT) + { + goto out; + } + if(mkdir(nvram_path, 0755) == -1) + { + goto out; + } + else + { + if(access(nvram_path, R_OK|W_OK|X_OK) == -1) + { + errno = EACCES; + goto out; + } + } + } + if(strlen(qemu_name) > PATH_MAX) + { + goto out; + } + strcat(nvram_path, qemu_name); + strcat(nvram_path, ".data"); + if((nvram_fd = open(nvram_path,O_CREAT|O_RDWR,0644)) < 0) + { + goto out; + } + if(VALIDATE_NVRAM_FD(nvram_fd) == (uint64_t)(-1)) + { + close(nvram_fd); + goto out; + } + 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 * nvram_addr = (unsigned long *)(g_fw_start + NVRAM_OFFSET); + if((nvram_fd = kvm_ia64_nvram_init()) == -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..71aef2a 100644 --- a/qemu/target-ia64/firmware.h +++ b/qemu/target-ia64/firmware.h @@ -34,11 +34,27 @@ #define GFW_HOB_START ((4UL<<30) - (14UL<<20)) // 4G - 14M #define GFW_HOB_SIZE (1UL<<20) // 1M #define HOB_OFFSET (GFW_HOB_START-GFW_START) - #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 NVRAM_DIR "/usr/local/share/qemu/nvram/" +#define VALIDATE_NVRAM_FD(x) ((1UL<<(sizeof(x)*8 - 1)) | x) +#define IS_VALID_NVRAM_FD(x) ((uint64_t)x >> (sizeof(x)*8 - 1)) + +struct nvram_save_addr { + unsigned long addr; + unsigned long signature; +}; + +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_nvram_init(); +extern int kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd,const uint8_t * fw_start); +extern int kvm_ia64_copy_from_GFW_to_nvram(); #endif //__FIRM_WARE_ -- 1.6.0.rc1
Attachment:
0001-Kvm-Qemu-save-nvram.patch
Description: 0001-Kvm-Qemu-save-nvram.patch