[PATCH] Kvm: Qemu: save nvram

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux KVM Devel]     [Linux Virtualization]     [Big List of Linux Books]     [Linux SCSI]     [Yosemite Forum]

  Powered by Linux