From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Mkwpo-00062B-Q5 for qemu-devel@nongnu.org; Tue, 08 Sep 2009 05:17:57 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Mkwpj-0005yK-J6 for qemu-devel@nongnu.org; Tue, 08 Sep 2009 05:17:55 -0400 Received: from [199.232.76.173] (port=60414 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Mkwpi-0005xp-Dg for qemu-devel@nongnu.org; Tue, 08 Sep 2009 05:17:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51227) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Mkwph-0000hn-Q3 for qemu-devel@nongnu.org; Tue, 08 Sep 2009 05:17:50 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n889HnZG032704 for ; Tue, 8 Sep 2009 05:17:49 -0400 From: Gerd Hoffmann Date: Tue, 8 Sep 2009 11:17:43 +0200 Message-Id: <1252401463-3249-3-git-send-email-kraxel@redhat.com> In-Reply-To: <1252401463-3249-1-git-send-email-kraxel@redhat.com> References: <1252401463-3249-1-git-send-email-kraxel@redhat.com> Subject: [Qemu-devel] [PATCH 2/2] extboot: qemu code. List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Gerd Hoffmann booting from scsi + virtio works now. Signed-off-by: Gerd Hoffmann --- Makefile.target | 1 + hw/extboot.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pc.c | 15 +++++- hw/pc.h | 4 ++ qemu-config.c | 4 ++ qemu-options.hx | 2 +- sysemu.h | 1 + vl.c | 12 +++++ 8 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 hw/extboot.c diff --git a/Makefile.target b/Makefile.target index 67bd4d7..2314812 100644 --- a/Makefile.target +++ b/Makefile.target @@ -188,6 +188,7 @@ obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o +obj-i386-y += extboot.o # shared objects obj-ppc-y = ppc.o ide/core.o ide/isa.o ide/pci.o ide/macio.o diff --git a/hw/extboot.c b/hw/extboot.c new file mode 100644 index 0000000..b91d54f --- /dev/null +++ b/hw/extboot.c @@ -0,0 +1,135 @@ +/* + * Extended boot option ROM support. + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw.h" +#include "pc.h" +#include "isa.h" +#include "block.h" + +/* Extended Boot ROM suport */ + +union extboot_cmd +{ + uint16_t type; + struct { + uint16_t type; + uint16_t cylinders; + uint16_t heads; + uint16_t sectors; + uint64_t nb_sectors; + } query_geometry; + struct { + uint16_t type; + uint16_t nb_sectors; + uint16_t segment; + uint16_t offset; + uint64_t sector; + } xfer; +}; + +static void get_translated_chs(BlockDriverState *bs, int *c, int *h, int *s) +{ + bdrv_get_geometry_hint(bs, c, h, s); + + if (*c <= 1024) { + *c >>= 0; + *h <<= 0; + } else if (*c <= 2048) { + *c >>= 1; + *h <<= 1; + } else if (*c <= 4096) { + *c >>= 2; + *h <<= 2; + } else if (*c <= 8192) { + *c >>= 3; + *h <<= 3; + } else { + *c >>= 4; + *h <<= 4; + } + + /* what is the correct algorithm for this?? */ + if (*h == 256) { + *h = 255; + *c = *c + 1; + } +} + +static uint32_t extboot_read(void *opaque, uint32_t addr) +{ + int *pcmd = opaque; + return *pcmd; +} + +static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value) +{ + union extboot_cmd cmd; + BlockDriverState *bs = opaque; + int cylinders, heads, sectors, err; + uint64_t nb_sectors; + target_phys_addr_t pa = 0; + int blen = 0; + void *buf = NULL; + + cpu_physical_memory_read((value & 0xFFFF) << 4, (uint8_t *)&cmd, + sizeof(cmd)); + + if (cmd.type == 0x01 || cmd.type == 0x02) { + pa = cmd.xfer.segment * 16 + cmd.xfer.offset; + blen = cmd.xfer.nb_sectors * 512; + buf = qemu_memalign(512, blen); + } + + switch (cmd.type) { + case 0x00: + get_translated_chs(bs, &cylinders, &heads, §ors); + bdrv_get_geometry(bs, &nb_sectors); + cmd.query_geometry.cylinders = cylinders; + cmd.query_geometry.heads = heads; + cmd.query_geometry.sectors = sectors; + cmd.query_geometry.nb_sectors = nb_sectors; + break; + case 0x01: + err = bdrv_read(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors); + if (err) + printf("Read failed\n"); + + cpu_physical_memory_write(pa, buf, blen); + + break; + case 0x02: + cpu_physical_memory_read(pa, buf, blen); + + err = bdrv_write(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors); + if (err) + printf("Write failed\n"); + + break; + } + + cpu_physical_memory_write((value & 0xFFFF) << 4, (uint8_t *)&cmd, + sizeof(cmd)); + if (buf) + qemu_free(buf); +} + +void extboot_init(BlockDriverState *bs, int cmd) +{ + int *pcmd; + + pcmd = qemu_mallocz(sizeof(int)); + + *pcmd = cmd; + register_ioport_read(0x404, 1, 1, extboot_read, pcmd); + register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs); +} diff --git a/hw/pc.c b/hw/pc.c index 6292001..a17dbd0 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -47,6 +47,7 @@ #define BIOS_FILENAME "bios.bin" #define VGABIOS_FILENAME "vgabios.bin" #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" +#define EXTBOOT_FILENAME "extboot.bin" #define PC_MAX_BIOS_SIZE (4 * 1024 * 1024) @@ -1130,7 +1131,7 @@ static void pc_init1(ram_addr_t ram_size, qemu_irq *isa_irq; qemu_irq *i8259; IsaIrqState *isa_irq_state; - DriveInfo *dinfo; + DriveInfo *dinfo, *boot_drive; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BlockDriverState *fd[MAX_FD]; int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled; @@ -1218,7 +1219,10 @@ static void pc_init1(ram_addr_t ram_size, isa_bios_size, (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); - + boot_drive = drive_get_boot(); + if (boot_drive) { + option_rom[nb_option_roms++] = qemu_strdup(EXTBOOT_FILENAME); + } option_rom_offset = qemu_ram_alloc(0x20000); oprom_area_size = 0; @@ -1428,6 +1432,13 @@ static void pc_init1(ram_addr_t ram_size, } } } + + if (boot_drive) { + int cyls, heads, secs; + bdrv_guess_geometry(boot_drive->bdrv, &cyls, &heads, &secs); + bdrv_set_geometry_hint(boot_drive->bdrv, cyls, heads, secs); + extboot_init(boot_drive->bdrv, 1); + } } static void pc_init_pci(ram_addr_t ram_size, diff --git a/hw/pc.h b/hw/pc.h index ec5735b..bd3c20a 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -151,4 +151,8 @@ void isa_cirrus_vga_init(void); void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd); int cpu_is_bsp(CPUState *env); + +/* extboot.c */ +void extboot_init(BlockDriverState *bs, int cmd); + #endif diff --git a/qemu-config.c b/qemu-config.c index 4808db0..efea7f4 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -70,6 +70,10 @@ QemuOptsList qemu_drive_opts = { .name = "addr", .type = QEMU_OPT_STRING, .help = "pci address (virtio only)", + },{ + .name = "boot", + .type = QEMU_OPT_BOOL, + .help = "make this a boot drive", }, { /* end if list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index ce38a3b..df751ca 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -103,7 +103,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n" " [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n" " [,cache=writethrough|writeback|none][,format=f][,serial=s]\n" - " [,addr=A][,id=name][,aio=threads|native]\n" + " [,addr=A][,id=name][,aio=threads|native][,boot=on]\n" " use 'file' as a drive image\n") DEF("set", HAS_ARG, QEMU_OPTION_set, "-set group.id.arg=value\n" diff --git a/sysemu.h b/sysemu.h index ac16c21..dd24444 100644 --- a/sysemu.h +++ b/sysemu.h @@ -186,6 +186,7 @@ extern TAILQ_HEAD(driveoptlist, DriveOpt) driveopts; extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); extern DriveInfo *drive_get_by_id(const char *id); +extern DriveInfo *drive_get_boot(void); extern int drive_get_max_bus(BlockInterfaceType type); extern void drive_uninit(BlockDriverState *bdrv); extern const char *drive_get_serial(BlockDriverState *bdrv); diff --git a/vl.c b/vl.c index 098daaa..982b418 100644 --- a/vl.c +++ b/vl.c @@ -1843,6 +1843,18 @@ DriveInfo *drive_get_by_id(const char *id) return NULL; } +DriveInfo *drive_get_boot(void) +{ + DriveInfo *dinfo; + + TAILQ_FOREACH(dinfo, &drives, next) { + if (qemu_opt_get_bool(dinfo->opts, "boot", 0) == 0) + continue; + return dinfo; + } + return NULL; +} + int drive_get_max_bus(BlockInterfaceType type) { int max_bus; -- 1.6.2.5