qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 4/5] Block Memory boot devices


From: Jason Wessel
Subject: [Qemu-devel] [PATCH 4/5] Block Memory boot devices
Date: Sat, 20 May 2006 16:02:03 -0500
User-agent: Thunderbird 1.5.0.2 (Windows/20060308)


This patch adds memory block devices to QEMU. It was mainly for the purpose of booting a pentium qemu without a disk, but it is also very useful for testing and debugging different types of file systems from the OS using only memory.
signed-off-by: address@hidden

Jason.

Index: qemu/Makefile
===================================================================
--- qemu.orig/Makefile
+++ qemu/Makefile
@@ -29,7 +29,7 @@ subdir-%: dyngen$(EXESUF)
 
 recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
         
-qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c 
block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
+qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c 
block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c 
block-mem.c
        $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
 
 dyngen$(EXESUF): dyngen.c
Index: qemu/Makefile.target
===================================================================
--- qemu.orig/Makefile.target
+++ qemu/Makefile.target
@@ -273,7 +273,7 @@ endif
 
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o
-VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o 
block-bochs.o block-vpc.o block-vvfat.o
+VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o 
block-bochs.o block-vpc.o block-vvfat.o block-mem.o
 ifdef CONFIG_WIN32
 VL_OBJS+=tap-win32.o
 endif
Index: qemu/block-mem.c
===================================================================
--- /dev/null
+++ qemu/block-mem.c
@@ -0,0 +1,216 @@
+/*
+ * Block driver for volatile memory-based devices
+ *
+ * Copyright (c) 2006 Wind River Systems, Inc.
+ * Written by Alex deVries and Jason Wessel
+ *
+ * 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 "vl.h"
+#include "block_int.h"
+
+/**************************************************************/
+/* Memory scratch disk driver using host memory */
+
+/* mem_segment is a linked list of segments */
+
+struct mem_segment {
+    char name[256];
+    char * data;
+    unsigned int size;
+    struct mem_segment * next;
+} ;
+
+static struct mem_segment * segment_head = NULL;
+
+
+struct BDRVMemState {
+    struct mem_segment * segment;
+};
+
+
+/* Given a segment name, find the mem_segment (if it exists) */
+
+static struct mem_segment * find_segment(char * segment_name) {
+
+    struct mem_segment * p;
+
+    if (!segment_name) return NULL;
+
+    for (p = segment_head; p ; p=p->next) {
+        if (strcmp(p->name,segment_name)==0) return p;
+    }
+    return NULL;
+}
+
+/* Read the block device */
+
+static int mem_read(BlockDriverState *bs, int64_t sector_num,
+                    uint8_t *buf, int nb_sectors)
+{
+    struct BDRVMemState *s;
+    struct mem_segment * p ;
+
+    uint64_t len = nb_sectors * 512;
+    uint64_t offset = sector_num * 512;
+
+    if (!bs) return -1;
+    s = bs->opaque;
+
+    if (s && s->segment) return -1;
+    p = s->segment;
+
+    /* Check if it is out of bounds */
+    if (offset > p->size) return -1;
+
+    /* Make sure we don't read off the end */
+    if (len + offset > p->size) len = p->size - offset;
+
+    memcpy(buf,p->data,len);
+    return len;
+}
+
+/* Write to the block device */
+
+static int mem_write(BlockDriverState *bs, int64_t sector_num,
+                     const uint8_t *buf, int nb_sectors)
+{
+    struct BDRVMemState *s;
+    struct mem_segment * p ;
+
+    uint64_t len = nb_sectors * 512;
+    uint64_t offset = sector_num * 512;
+
+    if (!bs) return -1;
+    s = bs->opaque;
+
+    if (s && s->segment) return -1;
+    p = s->segment;
+
+    /* Check if it is out of bounds */
+    if (offset > p->size) return -1;
+
+    /* Make sure we don't read off the end */
+    if (len + offset > p->size) len = p->size - offset;
+
+    memcpy(p->data,buf,len);
+    return len;
+}
+
+/* Close the device */
+
+static void mem_close(BlockDriverState *bs)
+{
+    return;
+}
+
+static int mem_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+    if (!strncmp(filename, "mem:",4))
+        return 100;
+
+    return 0;
+}
+
+/* Create the segment.  Create a segment with the segment name of
+ * filename, and size of image_sectors * 512
+ */
+static int mem_create(const char *filename, int64_t image_sectors,
+                      const char *image_filename, int flags)
+{
+    struct mem_segment* p;
+
+    /* When image_sectors is zero, parse the sector size from
+     * the file name.
+     */
+    if (!filename || filename[0] == 0)
+    {
+        return -1;
+    }
+
+    if (image_sectors == 0) {
+        const char *s = filename;
+        if (strncmp(s,"mem:",4) != 0)
+            return -1;
+        s += 4;
+        s = strchr(s,':');
+        if (!s)
+            return -1;
+        s++;
+        image_sectors = atoi(s);
+        if (image_sectors == 0)
+            return -1;
+    }
+
+    /* Make sure the segment isn't already being used */
+
+    if (find_segment((char *) filename)) return -1;
+
+    /* Create memory for the segment */
+    p = qemu_malloc(sizeof(struct mem_segment));
+    if (!p) return -1;
+
+    /* Allocate the data area */
+    p->data = qemu_malloc(image_sectors * 512);
+    if (!p->data) return -1;
+
+    /* Setup the name */
+    snprintf(p->name,256,filename);
+    p->size=image_sectors * 512;
+
+    /* Tack it to the head */
+    p->next = segment_head;
+    segment_head=p;
+
+    return 0;
+
+}
+
+/* Open the block device */
+
+static int mem_open(BlockDriverState *bs, const char *filename)
+{
+
+    struct mem_segment * p = find_segment((char *) filename);
+
+
+    if (!p  || !p->data) {
+        /* If the segment did not exist, try to create it on the fly */
+        mem_create(filename, 0, 0, 0);
+        p = find_segment((char *) filename);
+        if (!p  || !p->data)
+            return -1;
+    }
+
+    bs->opaque = (void * ) p;
+
+    return 0;
+}
+
+BlockDriver bdrv_mem = {
+    "mem",
+    sizeof(struct BDRVMemState),
+    mem_probe,
+    mem_open,
+    mem_read,
+    mem_write,
+    mem_close,
+    mem_create,
+    0,
+};
Index: qemu/block.c
===================================================================
--- qemu.orig/block.c
+++ qemu/block.c
@@ -784,6 +784,7 @@ BlockDriver bdrv_raw = {
 void bdrv_init(void)
 {
     bdrv_register(&bdrv_raw);
+    bdrv_register(&bdrv_mem);
 #ifndef _WIN32
     bdrv_register(&bdrv_cow);
 #endif
Index: qemu/qemu-doc.texi
===================================================================
--- qemu.orig/qemu-doc.texi
+++ qemu/qemu-doc.texi
@@ -814,6 +814,7 @@ written), compressed and encrypted disk 
 * disk_images_snapshot_mode:: Snapshot mode
 * qemu_img_invocation::       qemu-img Invocation
 * disk_images_fat_images::    Virtual FAT disk images
+* disk_images_mem_images::    Memory only scratch disk
 @end menu
 
 @node disk_images_quickstart
@@ -878,6 +879,21 @@ What you should @emph{never} do:
 @item write to the FAT directory on the host system while accessing it with 
the guest system.
 @end itemize
 
address@hidden disk_images_mem_images
address@hidden Memory only scratch disk
+
+QEMU can create an in memory scratch disk device instead of using a disk 
image.  This is the default on a pentium system to satisfy the BIOS if you do 
not provide a disk image.  In the default case you only have a single 512byte 
sector which is the MBR of the scratch disk, but you can create a large scratch 
disk.  You can also choose to use memory scratch devices with any other target. 
 The syntax is as follows:
+
address@hidden
+qemu -kernel bzImage -hda mem:0:1
address@hidden example
+
+The scratch disks use the keyword "mem" followed by ":" then the memory device 
number "0", and finally the number of 512 byte sectors to allocate.  The above 
invocation is equivalent to when the -hda and its parameter are omitted for the 
pentium qemu.  Below is an example of creating a 1 megabyte scratch disk as the 
second IDE drive.
+
address@hidden
+qemu -kernel bzImage -hda hdisk.img -hdb mem:1:524288
address@hidden example
+
 @node pcsys_network
 @section Network emulation
 
Index: qemu/vl.c
===================================================================
--- qemu.orig/vl.c
+++ qemu/vl.c
@@ -5556,6 +5556,14 @@ int main(int argc, char **argv)
         bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM);
     }
 
+#ifdef TARGET_I386
+    /* Allow a i386 target to boot with no "-hda" argument */
+    if (!hd_filename[0]) {
+        hd_filename[0] = strdup("mem:0:1");
+        boot_device = 'c';
+    }
+#endif /* TARGET_I386 */
+
     /* open the virtual block devices */
     for(i = 0; i < MAX_DISKS; i++) {
         if (hd_filename[i]) {
Index: qemu/vl.h
===================================================================
--- qemu.orig/vl.h
+++ qemu/vl.h
@@ -468,6 +468,7 @@ int cpu_load(QEMUFile *f, void *opaque, 
 typedef struct BlockDriverState BlockDriverState;
 typedef struct BlockDriver BlockDriver;
 
+extern BlockDriver bdrv_mem;
 extern BlockDriver bdrv_raw;
 extern BlockDriver bdrv_cow;
 extern BlockDriver bdrv_qcow;

reply via email to

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