All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gleb Natapov <gleb@qumranet.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v4 1/8] Key/value based qemu<->guest firmware communication mechanism.
Date: Mon, 1 Sep 2008 10:44:53 +0300	[thread overview]
Message-ID: <20080901074453.GJ6192@minantech.com> (raw)
In-Reply-To: <20080901072536.17854.65821.stgit@gleb-debian.qumranet.com.qumranet.com>

Sorry, use this one instead.

---
    Generic way to pass configuration info between qemu process and guest firmware.
    
    Signed-off-by: Gleb Natapov <gleb@qumranet.com>

diff --git a/Makefile.target b/Makefile.target
index 2464484..02bb553 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -473,6 +473,7 @@ endif #CONFIG_DARWIN_USER
 ifndef CONFIG_USER_ONLY
 
 OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o
+OBJS+=fw_cfg.o
 ifdef CONFIG_WIN32
 OBJS+=block-raw-win32.o
 else
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
new file mode 100644
index 0000000..ee06905
--- /dev/null
+++ b/hw/fw_cfg.c
@@ -0,0 +1,220 @@
+/*
+ * QEMU Firmware configuration device emulation
+ *
+ * Copyright (c) 2008 Gleb Natapov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "isa.h"
+#include "fw_cfg.h"
+
+/* debug firmware config */
+//#define DEBUG_FW_CFG
+
+#ifdef DEBUG_FW_CFG
+#define FW_CFG_DPRINTF(fmt, args...)                     \
+    do { printf("FW_CFG: " fmt , ##args); } while (0)
+#else
+#define FW_CFG_DPRINTF(fmt, args...)
+#endif
+
+#define FW_CFG_SIZE 2
+
+typedef struct _FWCfgEntry {
+    uint16_t len;
+    const uint8_t *data;
+} FWCfgEntry;
+
+typedef struct _FWCfgState {
+    FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
+    uint16_t cur_entry;
+    uint16_t cur_offset;
+} FWCfgState;
+
+static int fw_cfg_select(FWCfgState *s, uint16_t key)
+{
+    int ret;
+
+    s->cur_offset = 0;
+    if ((key & ~FW_CFG_ARCH_LOCAL) >= FW_CFG_MAX_ENTRY) {
+        s->cur_entry = FW_CFG_INVALID;
+        ret = 0;
+    } else {
+        s->cur_entry = key;
+        ret = 1;
+    }
+
+    FW_CFG_DPRINTF("select key %d (%sfound)\n", key, ret ? "" : "not ");
+
+    return ret;
+}
+
+static uint8_t fw_cfg_read(FWCfgState *s)
+{
+    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
+    FWCfgEntry *e = &s->entries[arch][s->cur_entry & ~FW_CFG_ARCH_LOCAL];
+    uint8_t ret;
+
+    if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)
+        ret = 0;
+    else
+        ret = e->data[s->cur_offset++];
+
+    FW_CFG_DPRINTF("read %d\n", ret);
+
+    return ret;
+}
+
+static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
+{
+    return fw_cfg_read(opaque);
+}
+
+static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
+{
+    fw_cfg_select(opaque, (uint16_t)value);
+}
+
+static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+    return fw_cfg_read(opaque);
+}
+
+static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    fw_cfg_select(opaque, (uint16_t)value);
+}
+
+static CPUReadMemoryFunc *fw_cfg_mem_read[3] = {
+    fw_cfg_mem_readb,
+    NULL,
+    NULL,
+};
+
+static CPUWriteMemoryFunc *fw_cfg_mem_write[3] = {
+    NULL,
+    fw_cfg_mem_writew,
+    NULL,
+};
+
+static void fw_cfg_reset(void *opaque)
+{
+    FWCfgState *s = opaque;
+
+    fw_cfg_select(s, 0);
+}
+
+static void fw_cfg_save(QEMUFile *f, void *opaque)
+{
+    FWCfgState *s = opaque;
+
+    qemu_put_be16s(f, &s->cur_entry);
+    qemu_put_be16s(f, &s->cur_offset);
+}
+
+static int fw_cfg_load(QEMUFile *f, void *opaque, int version_id)
+{
+    FWCfgState *s = opaque;
+
+    if (version_id > 1)
+        return -EINVAL;
+
+    qemu_get_be16s(f, &s->cur_entry);
+    qemu_get_be16s(f, &s->cur_offset);
+
+    return 0;
+}
+
+int fw_cfg_add_bytes(void *opaque, uint16_t key, const uint8_t *data, uint16_t len)
+{
+    FWCfgState *s = opaque;
+    int arch = !!(key & FW_CFG_ARCH_LOCAL);
+
+    key &= (~FW_CFG_ARCH_LOCAL);
+
+    if (key >= FW_CFG_MAX_ENTRY)
+        return 0;
+
+    s->entries[arch][key].data = data;
+    s->entries[arch][key].len = len;
+
+    return 1;
+}
+
+int fw_cfg_add_i16(void *opaque, uint16_t key, uint16_t value)
+{
+    uint16_t *copy;
+
+    copy = qemu_malloc(sizeof(value));
+    if (!copy)
+        return 0;
+    *copy = cpu_to_le16(value);
+    return fw_cfg_add_bytes(opaque, key, (uint8_t *)copy, sizeof(value));
+}
+
+int fw_cfg_add_i32(void *opaque, uint16_t key, uint32_t value)
+{
+    uint32_t *copy;
+
+    copy = qemu_malloc(sizeof(value));
+    if (!copy)
+        return 0;
+    *copy = cpu_to_le32(value);
+    return fw_cfg_add_bytes(opaque, key, (uint8_t *)copy, sizeof(value));
+}
+
+int fw_cfg_add_i64(void *opaque, uint16_t key, uint64_t value)
+{
+    uint64_t *copy;
+
+    copy = qemu_malloc(sizeof(value));
+    if (!copy)
+        return 0;
+    *copy = cpu_to_le64(value);
+    return fw_cfg_add_bytes(opaque, key, (uint8_t *)copy, sizeof(value));
+}
+
+void *fw_cfg_init(uint32_t port, target_phys_addr_t addr)
+{
+    FWCfgState *s;
+    int io_memory;
+
+    s = qemu_mallocz(sizeof(FWCfgState));
+    if (!s)
+        return NULL;
+
+    if (port) {
+        register_ioport_read(port, 1, 1, fw_cfg_io_readb, s);
+        register_ioport_write(port, 2, 2, fw_cfg_io_writew, s);
+    }
+    if (addr) {
+        io_memory = cpu_register_io_memory(0, fw_cfg_mem_read,
+                                           fw_cfg_mem_write, s);
+        cpu_register_physical_memory(addr, FW_CFG_SIZE, io_memory);
+
+    }
+    fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (uint8_t *)"QEMU", 4);
+    register_savevm("fw_cfg", -1, 1, fw_cfg_save, fw_cfg_load, s);
+    qemu_register_reset(fw_cfg_reset, s);
+    fw_cfg_reset(s);
+
+    return s;
+}
diff --git a/hw/fw_cfg.h b/hw/fw_cfg.h
new file mode 100644
index 0000000..e0b88a3
--- /dev/null
+++ b/hw/fw_cfg.h
@@ -0,0 +1,21 @@
+#ifndef FW_CFG_H
+#define FW_CFG_H
+
+#define FW_CFG_SIGNATURE        0x00
+#define FW_CFG_ID               0x01
+#define FW_CFG_MAX_ENTRY        0x10
+
+#define FW_CFG_ARCH_LOCAL       0x8000
+
+#define FW_CFG_INVALID          0xffff
+
+#ifndef NO_QEMU_PROTOS
+int fw_cfg_add_bytes(void *opaque, uint16_t key, const uint8_t *data,
+                     uint16_t len);
+int fw_cfg_add_i16(void *opaque, uint16_t key, uint16_t value);
+int fw_cfg_add_i32(void *opaque, uint16_t key, uint32_t value);
+int fw_cfg_add_i64(void *opaque, uint16_t key, uint64_t value);
+void *fw_cfg_init(uint32_t port, target_phys_addr_t addr);
+#endif /* NO_QEMU_PROTOS */
+
+#endif
diff --git a/hw/pc.c b/hw/pc.c
index 213ead8..933e936 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -32,6 +32,7 @@
 #include "smbus.h"
 #include "boards.h"
 #include "console.h"
+#include "fw_cfg.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -44,6 +45,7 @@
 
 /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
 #define ACPI_DATA_SIZE       0x10000
+#define BIOS_CFG_IOPORT 0x510
 
 #define MAX_IDE_BUS 2
 
@@ -416,6 +418,8 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
 
 static void bochs_bios_init(void)
 {
+    void *fw_cfg;
+
     register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL);
     register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL);
     register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL);
@@ -426,6 +430,9 @@ static void bochs_bios_init(void)
     register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL);
     register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL);
     register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL);
+
+    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, 0);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
 }
 
 /* Generate an initial boot sector which sets state and jump to
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 21f8899..6f3108b 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -34,6 +34,7 @@
 #include "scsi.h"
 #include "pc.h"
 #include "isa.h"
+#include "fw_cfg.h"
 
 //#define DEBUG_IRQ
 
@@ -78,6 +79,7 @@
 #define PROM_SIZE_MAX        (512 * 1024)
 #define PROM_VADDR           0xffd00000
 #define PROM_FILENAME        "openbios-sparc32"
+#define CFG_ADDR             0xd00000510ULL
 
 // Control plane, 8-bit and 24-bit planes
 #define TCX_SIZE             (9 * 1024 * 1024)
@@ -410,6 +412,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size,
     char buf[1024];
     BlockDriverState *fd[MAX_FD];
     int drive_index;
+    void *fw_cfg;
 
     /* init CPUs */
     if (!cpu_model)
@@ -570,6 +573,9 @@ static void sun4m_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size,
     if (hwdef->ecc_base != (target_phys_addr_t)-1)
         ecc_init(hwdef->ecc_base, slavio_irq[hwdef->ecc_irq],
                  hwdef->ecc_version);
+
+    fw_cfg = fw_cfg_init(0, CFG_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
 }
 
 static void sun4c_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size,
@@ -589,6 +595,7 @@ static void sun4c_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size,
     char buf[1024];
     BlockDriverState *fd[MAX_FD];
     int drive_index;
+    void *fw_cfg;
 
     /* init CPU */
     if (!cpu_model)
@@ -715,6 +722,9 @@ static void sun4c_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size,
     nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
                boot_device, RAM_size, kernel_size, graphic_width,
                graphic_height, graphic_depth, hwdef->machine_id, "Sun4c");
+
+    fw_cfg = fw_cfg_init(0, CFG_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
 }
 
 static const struct hwdef hwdefs[] = {
@@ -1405,6 +1415,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
     int ret;
     char buf[1024];
     int drive_index;
+    void *fw_cfg;
 
     /* init CPUs */
     if (!cpu_model)
@@ -1528,6 +1539,9 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
     nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
                boot_device, RAM_size, kernel_size, graphic_width,
                graphic_height, graphic_depth, hwdef->machine_id, "Sun4d");
+
+    fw_cfg = fw_cfg_init(0, CFG_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
 }
 
 /* SPARCserver 1000 hardware initialisation */
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 42a765d..4bac0d6 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -31,6 +31,7 @@
 #include "sysemu.h"
 #include "boards.h"
 #include "firmware_abi.h"
+#include "fw_cfg.h"
 
 #define KERNEL_LOAD_ADDR     0x00404000
 #define CMDLINE_ADDR         0x003ff000
@@ -44,6 +45,7 @@
 #define PROM_FILENAME        "openbios-sparc64"
 #define NVRAM_SIZE           0x2000
 #define MAX_IDE_BUS          2
+#define BIOS_CFG_IOPORT      0x510
 
 struct hwdef {
     const char * const default_cpu_model;
@@ -270,6 +272,7 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size,
     int drive_index;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BlockDriverState *fd[MAX_FD];
+    void *fw_cfg;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -415,6 +418,8 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size,
                            graphic_width, graphic_height, graphic_depth,
                            (uint8_t *)&nd_table[0].macaddr);
 
+    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, 0);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
 }
 
 static const struct hwdef hwdefs[] = {
--
			Gleb.

  reply	other threads:[~2008-09-01  7:45 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-01  7:25 [Qemu-devel] [PATCH v4 0/8] Add new firmware configuration mechanism Gleb Natapov
2008-09-01  7:25 ` [Qemu-devel] [PATCH v4 1/8] Key/value based qemu<->guest firmware communication mechanism Gleb Natapov
2008-09-01  7:44   ` Gleb Natapov [this message]
2008-09-01  7:25 ` [Qemu-devel] [PATCH v4 2/8] Add -uuid command line option Gleb Natapov
2008-09-01  7:25 ` [Qemu-devel] [PATCH v4 3/8] Add "info uuid" command to monitor Gleb Natapov
2008-09-01  7:25 ` [Qemu-devel] [PATCH v4 4/8] Use libuuid if available Gleb Natapov
2008-09-01 14:25   ` Blue Swirl
2008-09-01 14:49   ` Andreas Färber
2008-09-01 15:15     ` Tomas Carnecky
2008-09-01 16:29       ` M. Warner Losh
2008-09-01 15:30     ` Jamie Lokier
2008-09-01 16:32       ` Andreas Färber
2008-09-01 15:50     ` Andreas Schwab
2008-09-01 16:29     ` M. Warner Losh
2008-09-01  7:25 ` [Qemu-devel] [PATCH v4 5/8] Add UUID to firmware configuration info Gleb Natapov
2008-09-01  7:26 ` [Qemu-devel] [PATCH v4 6/8] Pass cpu speed into SM BIOS Gleb Natapov
2008-09-01  7:46   ` Gleb Natapov
2008-09-01  7:26 ` [Qemu-devel] [PATCH v4 7/8] Add common keys to firmware configuration Gleb Natapov
2008-09-01  7:26 ` [Qemu-devel] [PATCH v4 8/8] Add sparc " Gleb Natapov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080901074453.GJ6192@minantech.com \
    --to=gleb@qumranet.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.