RE: [PATCH] Kvm: Qemu: save nvram

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

 



>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 <yang.zhang@xxxxxxxxx>
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 <yang.zhang@xxxxxxxxx>
---
 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


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