RE: [PATCH] Kvm: Qemu: save nvram

"Zhang, Yang" <[email protected]>
Newsgroups org.kernel.vger.kvm-ia64,org.kernel.vger.kvm
Message-ID <10C63FAD690C13458F0B32BCED571F1403BD3282@pdsmsx502.ccr.corp.intel.com>
>Charles Duffy wrote:
>>An unlinked temporary file as default behavior makes good sense -- it
>>doesn't leave anything sitting around the user didn't ask for or doesn't
>>expect, so it wouldn't be surprising behavior to me as an end-user, but
>>provides a method for persisting nvram contents during a single session.
>
>Ok, seems you are right. I will modify the patch.
The patch is modified. Without the arg of nvram, the patch will do nothing

From 2fd0c2746a2d07813ad16700ee31c7f6ae78c40a Mon Sep 17 00:00:00 2001
From: Yang Zhang <[email protected]>
Date: Tue, 2 Dec 2008 13:05:55 +0800
Subject: [PATCH] KVM: Qemu: save nvram

support to save nvram to the file

Signed-off-by: Yang Zhang <[email protected]>
---
 qemu/hw/ipf.c               |   19 ++++++++-
 qemu/target-ia64/firmware.c |   94 ++++++++++++++++++++++++++++++++++++++++--
 qemu/target-ia64/firmware.h |   22 +++++++++-
 3 files changed, 126 insertions(+), 9 deletions(-)

diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c
index 337c854..2300ba9 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,13 @@ 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 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 +477,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);
+        if (qemu_name) {
+            nvram_addr = NVRAM_START;
+            nvram_fd = kvm_ia64_nvram_init();
+            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..6729cb5 100644
--- a/qemu/target-ia64/firmware.c
+++ b/qemu/target-ia64/firmware.c
@@ -31,6 +31,9 @@
 
 #include "firmware.h"
 
+#include "qemu-common.h"
+#include "sysemu.h"
+
 typedef struct {
     unsigned long signature;
     unsigned int  type;
@@ -85,14 +88,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 +107,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 +211,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 +235,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 +296,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 +598,73 @@ out_1:
     return NULL;
 }
 
+int kvm_ia64_nvram_init()
+{
+    unsigned long nvram_fd;
+    char nvram_path[PATH_MAX] = NVRAM_DIR;
+
+    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, ".dat");
+    nvram_fd = open(nvram_path, O_CREAT|O_RDWR, 0644);
+    if (nvram_fd < 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);
+    nvram_fd = kvm_ia64_nvram_init();
+    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..d632599 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
0001-KVM-Qemu-save-nvram.patch (application/octet-stream, 8.3 KB)
From 2fd0c2746a2d07813ad16700ee31c7f6ae78c40a Mon Sep 17 00:00:00 2001
From: Yang Zhang <[email protected]>
Date: Tue, 2 Dec 2008 13:05:55 +0800
Subject: [PATCH] KVM: Qemu: save nvram

support to save nvram to the file

Signed-off-by: Yang Zhang <[email protected]>
---
 qemu/hw/ipf.c               |   19 ++++++++-
 qemu/target-ia64/firmware.c |   94 ++++++++++++++++++++++++++++++++++++++++--
 qemu/target-ia64/firmware.h |   22 +++++++++-
 3 files changed, 126 insertions(+), 9 deletions(-)

diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c
index 337c854..2300ba9 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,13 @@ 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 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 +477,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);
+        if (qemu_name) {
+            nvram_addr = NVRAM_START;
+            nvram_fd = kvm_ia64_nvram_init();
+            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..6729cb5 100644
--- a/qemu/target-ia64/firmware.c
+++ b/qemu/target-ia64/firmware.c
@@ -31,6 +31,9 @@
 
 #include "firmware.h"
 
+#include "qemu-common.h"
+#include "sysemu.h"
+
 typedef struct {
     unsigned long signature;
     unsigned int  type;
@@ -85,14 +88,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 +107,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 +211,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 +235,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 +296,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 +598,73 @@ out_1:
     return NULL;
 }
 
+int kvm_ia64_nvram_init()
+{
+    unsigned long nvram_fd;
+    char nvram_path[PATH_MAX] = NVRAM_DIR;
+
+    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, ".dat");
+    nvram_fd = open(nvram_path, O_CREAT|O_RDWR, 0644);
+    if (nvram_fd < 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);
+    nvram_fd = kvm_ia64_nvram_init();
+    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..d632599 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.