[Top][All Lists]

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

Re: [Qemu-devel] [PATCH] CMOS file support

From: Anthony Liguori
Subject: Re: [Qemu-devel] [PATCH] CMOS file support
Date: Thu, 16 Sep 2010 12:20:06 -0500
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv: Gecko/20100826 Lightning/1.0b1 Thunderbird/3.0.7

On 09/16/2010 08:58 AM, Mathias Krause wrote:
In contrast to the BIOS and Option ROMs the CMOS content cannot be
predefined by the user. Also the amount of useable CMOS ARM is pretty
limited, even though the amount of CMOS bytes emulated by qemu is
already twice as much as of the original MC146818. Nevertheless those
limitations are pretty annoying when testing different BIOS replacement
implementations like coreboot in combination with FILO that use CMOS
values above the basic RTC range for its own purpose to, e.g., control
the boot device order using a string containing the boot devices to

This patch adds support to specify a file to read the initial CMOS
content from. It also increases the CMOS size to 256 bytes and
implements access to the extended memory range via I/O ports 0x72 and

Use it like: `qemu -global mc146818rtc.file=cmos.bin ...' where cmos.bin
is a binary file, sized 256 bytes containing the CMOS RAM.

Signed-off-by: Mathias Krause<address@hidden>

Instead of using FILE, I'd suggest using a BlockDriver to read and write the data.

I think it would be very nice to add write support too so that writes to CMOS were persisted across boots.

  hw/mc146818rtc.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++-----
  1 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 2b91fa8..9f215e0 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -78,12 +78,16 @@
  #define REG_C_PF   0x40
  #define REG_C_AF   0x20

+#define BASE_PORT  0x70
+#define CMOS_SIZE  256
  typedef struct RTCState {
      ISADevice dev;
-    uint8_t cmos_data[128];
+    uint8_t cmos_data[CMOS_SIZE];
      uint8_t cmos_index;
      struct tm current_tm;
      int32_t base_year;
+    char *file;
      qemu_irq irq;
      qemu_irq sqw_irq;
      int it_shift;
@@ -206,7 +210,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, 
uint32_t data)
      RTCState *s = opaque;

      if ((addr&  1) == 0) {
-        s->cmos_index = data&  0x7f;
+        s->cmos_index = data&  (addr == BASE_PORT ? 0x7f : 0xff);
      } else {
          CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
                       s->cmos_index, data);
@@ -581,7 +585,6 @@ static void rtc_reset(void *opaque)
  static int rtc_initfn(ISADevice *dev)
      RTCState *s = DO_UPCAST(RTCState, dev, dev);
-    int base = 0x70;

      s->cmos_data[RTC_REG_A] = 0x26;
      s->cmos_data[RTC_REG_B] = 0x02;
@@ -603,14 +606,57 @@ static int rtc_initfn(ISADevice *dev)
          qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
      qemu_mod_timer(s->second_timer2, s->next_second_time);

-    register_ioport_write(base, 2, 1, cmos_ioport_write, s);
-    register_ioport_read(base, 2, 1, cmos_ioport_read, s);
+    register_ioport_write(BASE_PORT, 4, 1, cmos_ioport_write, s);
+    register_ioport_read(BASE_PORT, 4, 1, cmos_ioport_read, s);

-    qdev_set_legacy_instance_id(&dev->qdev, base, 2);
+    qdev_set_legacy_instance_id(&dev->qdev, BASE_PORT, 2);
      qemu_register_reset(rtc_reset, s);
      return 0;

+static long get_file_size(FILE *f)
+    long where, size;
+    /* XXX: on Unix systems, using fstat() probably makes more sense */
+    where = ftell(f);
+    fseek(f, 0, SEEK_END);
+    size = ftell(f);
+    fseek(f, where, SEEK_SET);
+    return size;

BlockDrivers have a getlength() functions.


Anthony Liguori

reply via email to

[Prev in Thread] Current Thread [Next in Thread]