RE: [PATCH] Kvm: Qemu: save nvram

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

 



Zhang, Yang wrote:
>The patch is modified. Without the arg of nvram, the patch will do nothing

Sorry, I has upload the wrong patch. Please drop it.
This is the right one.
Please review it.


>From 3cce00ce9ac25c723dec34226991c61d89f79e70 Mon Sep 17 00:00:00 2001
From: Zhang Yang <yang.zhang@xxxxxxxxx>
Date: Wed, 24 Dec 2008 11:54:38 +0800
Subject: [PATCH] KVM : Qemu: Save nvram

Save nvram to the file

Signed-off-by: Zhang Yang <yang.zhang@xxxxxxxxx>
---
 qemu/hw/ipf.c               |   21 ++++++++-
 qemu/target-ia64/firmware.c |  110 ++++++++++++++++++++++++++++++++++++++++--
 qemu/target-ia64/firmware.h |   24 +++++++++-
 qemu/vl.c                   |    9 ++++
 4 files changed, 155 insertions(+), 9 deletions(-)

diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c
index 3e24c98..4e9b052 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,20 @@ 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;
+        if (nvram) {
+            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

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