[Top][All Lists]
[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;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH 4/5] Block Memory boot devices,
Jason Wessel <=