# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1200587954 0
# Node ID bf828db8d0174896d078fcc6dce12427b6b64cc5
# Parent 95558b4a6714c37ebd6db0fccc68f7f1197dd622
hvm: Extboot support for Xen
This patch adds extboot to Xen. It should be pretty harmless as the
moment because it's never enabled. extboot allows arbitrary block
devices to be used to boot guests including SCSI and PV disks. I've
tested it with both Windows and Linux guests in QEMU.
Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>
---
tools/firmware/Makefile | 1
tools/firmware/extboot/Makefile | 30 +
tools/firmware/extboot/STATUS | 6
tools/firmware/extboot/extboot.S | 633 +++++++++++++++++++++++++++++++++++
tools/firmware/extboot/signrom.c | 79 ++++
tools/firmware/hvmloader/Makefile | 1
tools/firmware/hvmloader/config.h | 1
tools/firmware/hvmloader/hvmloader.c | 18
tools/ioemu/Makefile.target | 2
tools/ioemu/hw/extboot.c | 125 ++++++
tools/ioemu/vl.h | 3
firmware/extboot/extboot.img | 0
firmware/extboot/signrom | 0
13 files changed, 898 insertions(+), 1 deletion(-)
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/Makefile
--- a/tools/firmware/Makefile Thu Jan 17 15:50:48 2008 +0000
+++ b/tools/firmware/Makefile Thu Jan 17 16:39:14 2008 +0000
@@ -10,6 +10,7 @@ SUBDIRS += rombios rombios/32bit
SUBDIRS += rombios rombios/32bit
SUBDIRS += vgabios
SUBDIRS += vmxassist
+SUBDIRS += extboot
SUBDIRS += hvmloader
.PHONY: all
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/extboot/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/Makefile Thu Jan 17 16:39:14 2008 +0000
@@ -0,0 +1,30 @@
+
+override XEN_TARGET_ARCH = x86_32
+XEN_ROOT = ../../..
+CFLAGS := -I$(XEN_ROOT)/tools/libxc -I.
+include $(XEN_ROOT)/tools/Rules.mk
+
+# Disable PIE/SSP if GCC supports them. They can break us.
+CFLAGS += $(call cc-option,$(CC),-nopie,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
+
+CFLAGS += -fno-builtin -O2 -msoft-float
+
+.PHONY: all
+all: extboot.bin
+
+%.o: %.S
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
+
+extboot.img: extboot.o
+ $(LD) $(LDFLAGS_DIRECT) --oformat binary -Ttext 0 -o $@ $<
+
+extboot.bin: extboot.img signrom
+ ./signrom extboot.img extboot.bin
+
+signrom: signrom.c
+ $(HOSTCC) $(HOSTCFLAGS) -o $@ $^
+
+clean:
+ $(RM) -f *.o *.img *.bin signrom *~
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/extboot/STATUS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/STATUS Thu Jan 17 16:39:14 2008 +0000
@@ -0,0 +1,6 @@
+Working
+-------
+
+Ubuntu Server 7.04 (i386)
+Windows 2000 Professional (i386)
+Windows XP SP2 (i386)
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/extboot/extboot.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/extboot.S Thu Jan 17 16:39:14 2008 +0000
@@ -0,0 +1,633 @@
+/*
+ * Extended Boot Option ROM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corporation, 2007
+ * Authors: Anthony Liguori <aliguori@xxxxxxxxxx>
+ */
+
+.code16
+.text
+ .global _start
+_start:
+ .short 0xaa55
+ .byte (_end - _start) / 512
+
+ push %ax
+ push %bx
+ push %cx
+ push %dx
+ push %ds
+
+ /* setup ds so we can access the IVT */
+ xor %ax, %ax
+ mov %ax, %ds
+
+ /* save old int 19 at int 2b */
+ mov $(0x19 * 4), %bx
+ mov 0(%bx), %ax
+ mov 2(%bx), %cx
+
+ mov $(0x2b * 4), %bx
+ mov %ax, 0(%bx)
+ mov %cx, 2(%bx)
+
+ /* install our int 19 handler */
+ mov $(0x19 * 4), %bx
+ mov $int19_handler, %ax
+ mov %ax, 0(%bx)
+ mov %cs, 2(%bx)
+
+ pop %ds
+ pop %dx
+ pop %cx
+ pop %bx
+ pop %ax
+ lret
+
+int19_handler:
+ push %ax
+ push %bx
+ push %cx
+ push %dx
+ push %ds
+
+ movw $0x404, %dx
+ inb %dx, %al
+ cmp $1, %al
+ jne 1f
+
+ /* hook int13 */
+ /* setup ds to access IVT */
+ xor %ax, %ax
+ mov %ax, %ds
+
+ /* save old int 13 to int 2c */
+ mov $(0x13 * 4), %bx
+ mov 0(%bx), %ax
+ mov 2(%bx), %cx
+
+ mov $(0x2c * 4), %bx
+ mov %ax, 0(%bx)
+ mov %cx, 2(%bx)
+
+ /* install our int 13 handler */
+ mov $(0x13 * 4), %bx
+ mov $int13_handler, %ax
+
+ mov %ax, 0(%bx)
+ mov %cs, 2(%bx)
+
+1: pop %ds
+ pop %dx
+ pop %cx
+ pop %bx
+ pop %ax
+ int $0x2b
+
+#define FLAGS_CF 0x01
+
+.macro clc
+ push %ax
+ pushf
+ pop %ax
+ and $(~FLAGS_CF), %ax
+ push %ax
+ popf
+ pop %ax
+.endm
+
+.macro stc
+ push %ax
+ pushf
+ pop %ax
+ or $(FLAGS_CF), %ax
+ push %ax
+ popf
+ pop %ax
+.endm
+
+/* we clobber %bx */
+.macro alloca size
+ push %ds
+ push %bp
+ mov %sp, %bp /* remember the current stack position */
+
+ mov %ss, %bx
+ mov %bx, %ds
+
+ sub \size, %sp
+ and $(~0x0F), %sp
+ mov %sp, %bx
+
+ push %bp
+ mov 0(%bp), %bp
+.endm
+
+/* we clobber %bp */
+.macro allocbpa size
+ mov %sp, %bp /* remember the current stack position */
+ sub \size, %sp
+ and $(~0x0F), %sp
+ push %bp
+ mov %sp, %bp
+ add $2, %bp
+.endm
+
+.macro freea
+ pop %sp
+ add $2, %sp
+ pop %ds
+.endm
+
+.macro freebpa
+ pop %sp
+.endm
+
+.macro dump reg
+ push %ax
+ push %dx
+
+ mov \reg, %ax
+ mov $0x406, %dx
+ outw %ax, %dx
+
+ pop %dx
+ pop %ax
+.endm
+
+.macro callout value
+ push %bp
+ push %bx
+ mov %sp, %bp
+ alloca $16
+ push %ax
+ push %dx
+
+ mov %ax, 0(%bx) /* ax */
+ mov 0(%bp), %ax /* bx */
+ mov %ax, 2(%bx)
+ mov %cx, 4(%bx) /* cx */
+ mov %dx, 6(%bx) /* dx */
+ mov %si, 8(%bx) /* si */
+ mov %ds, 10(%bx) /* ds */
+ mov %es, 12(%bx) /* ds */
+ movw \value, 14(%bx) /* value */
+
+ mov %bx, %ax
+ shr $4, %ax
+ mov %ds, %dx
+ add %dx, %ax
+
+ mov $0x407, %dx
+ outw %ax, %dx
+
+ pop %dx
+ pop %ax
+ freea
+ pop %bx
+ pop %bp
+.endm
+
+send_command:
+ push %bp
+ mov %sp, %bp
+ push %ax
+ push %bx
+ push %dx
+
+ mov 4(%bp), %ax
+ shr $4, %ax
+ and $0x0FFF, %ax
+ mov %ss, %bx
+ add %bx, %ax
+
+ mov $0x405, %dx
+ outw %ax, %dx
+
+ pop %dx
+ pop %bx
+ pop %ax
+ pop %bp
+
+ push %ax
+ mov 2(%bx), %ax
+ pop %ax
+
+ ret
+
+add32: /* lo, hi, lo, hi */
+ push %bp
+ mov %sp, %bp
+
+ movw 4(%bp), %cx /* hi */
+ movw 6(%bp), %dx /* lo */
+
+ add 10(%bp), %dx
+ jnc 1f
+ add $1, %cx
+1: add 8(%bp), %cx
+
+ pop %bp
+ ret
+
+mul32: /* lo, hi, lo, hi */
+ /* 10(%bp), 8(%bp), 6(%bp), 4(%bp) */
+ push %bp
+ mov %sp, %bp
+ push %ax
+ push %bx
+
+ xor %cx, %cx
+ xor %dx, %dx
+
+ /* for (i = 0; i < 16;) */
+ xor %bx, %bx
+0:
+ cmp $16, %bx
+ jge 2f
+
+ mov 6(%bp), %ax
+ and $1, %ax
+ cmp $1, %ax
+ jne 1f
+ push 10(%bp)
+ push 8(%bp)
+ push %dx
+ push %cx
+ call add32
+ add $8, %sp
+1:
+ shlw $1, 8(%bp)
+ movw 10(%bp), %ax
+ and $0x8000, %ax
+ cmp $0x8000, %ax
+ jne 1f
+ orw $1, 8(%bp)
+1:
+ shlw $1, 10(%bp)
+ shrw $1, 6(%bp)
+
+ /* i++) { */
+ add $1, %bx
+ jmp 0b
+
+2:
+ pop %bx
+ pop %ax
+ pop %bp
+ ret
+
+disk_reset:
+ movb $0, %ah
+ clc
+ ret
+
+/* this really should be a function, not a macro but i'm lazy */
+.macro read_write_disk_sectors cmd
+ push %ax
+ push %bx
+ push %cx
+ push %dx
+ push %si
+
+ push %bp
+ sub $10, %sp
+ mov %sp, %bp
+
+ /* save nb_sectors */
+ mov %al, 6(%bp)
+ movb $0, 7(%bp)
+
+ /* save buffer */
+ mov %bx, 8(%bp)
+
+ /* cylinders */
+ xor %ax, %ax
+ mov %cl, %al
+ shl $2, %ax
+ and $0x300, %ax
+ mov %ch, %al
+ mov %ax, 0(%bp)
+
+ /* heads */
+ xor %ax, %ax
+ mov %dh, %al
+ mov %ax, 2(%bp)
+
+ /* sectors - 1 */
+ xor %ax, %ax
+ mov %cl, %al
+ and $0x3F, %al
+ sub $1, %ax
+ mov %ax, 4(%bp)
+
+ alloca $8
+
+ movw $0, 0(%bx) /* read c,h,s */
+ push %bx
+ call send_command
+ add $2, %sp
+
+ mov 6(%bx), %ax /* total_sectors */
+ mov 2(%bp), %si /* *= heads */
+ mul %si
+ add 4(%bp), %ax /* += sectors - 1 */
+
+ push 4(%bx) /* total_heads */
+ push $0
+ push 6(%bx) /* total_sectors */
+ push $0
+ call mul32
+ add $8, %sp
+
+ push 0(%bp) /* cylinders */
+ push $0
+ push %dx
+ push %cx
+ call mul32
+ add $8, %sp
+
+ add %ax, %dx
+ jnc 1f
+ add $1, %cx
+1:
+ freea
+
+ alloca $16
+
+ movw \cmd, 0(%bx) /* read */
+ movw 6(%bp), %ax /* nb_sectors */
+ movw %ax, 2(%bx)
+ movw %es, 4(%bx) /* segment */
+ movw 8(%bp), %ax /* offset */
+ mov %ax, 6(%bx)
+ movw %dx, 8(%bx) /* sector */
+ movw %cx, 10(%bx)
+ movw $0, 12(%bx)
+ movw $0, 14(%bx)
+
+ push %bx
+ call send_command
+ add $2, %sp
+
+ freea
+
+ add $10, %sp
+ pop %bp
+
+ pop %si
+ pop %dx
+ pop %cx
+ pop %bx
+ pop %ax
+
+ mov $0, %ah
+ clc
+ ret
+.endm
+
+read_disk_sectors:
+ read_write_disk_sectors $0x01
+
+write_disk_sectors:
+ read_write_disk_sectors $0x02
+
+read_disk_drive_parameters:
+ push %bx
+
+ /* allocate memory for packet, pointer gets returned in bx */
+ alloca $8
+
+ /* issue command */
+ movw $0, 0(%bx) /* cmd = 0, read c,h,s */
+ push %bx
+ call send_command
+ add $2, %sp
+
+ /* normalize sector value */
+ movb 6(%bx), %cl
+ andb $0x3F, %cl
+ movb %cl, 6(%bx)
+
+ /* normalize cylinders */
+ subw $2, 2(%bx)
+
+ /* normalize heads */
+ subw $1, 4(%bx)
+
+ /* return code */
+ mov $0, %ah
+
+ /* cylinders */
+ movb 2(%bx), %ch
+ movb 3(%bx), %cl
+ shlb $6, %cl
+ andb $0xC0, %cl
+
+ /* sectors */
+ orb 6(%bx), %cl
+
+ /* heads */
+ movb 4(%bx), %dh
+
+ /* drives */
+ movb $1, %dl
+
+ /* status */
+ mov $0, %ah
+
+ freea
+
+ pop %bx
+
+ /* do this last since it's the most sensitive */
+ clc
+ ret
+
+alternate_disk_reset:
+ movb $0, %ah
+ clc
+ ret
+
+read_disk_drive_size:
+ push %bx
+ alloca $8
+
+ movw $0, 0(%bx) /* cmd = 0, read c,h,s */
+ push %bx
+ call send_command
+ add $2, %sp
+
+ /* cylinders - 1 to cx:dx */
+ mov 2(%bx), %dx
+ xor %cx, %cx
+ sub $1, %dx
+
+ /* heads */
+ push 4(%bx)
+ push $0
+ push %dx
+ push %cx
+ call mul32
+ add $8, %sp
+
+ /* sectors */
+ push 6(%bx)
+ push $0
+ push %dx
+ push %cx
+ call mul32
+ add $8, %sp
+
+ /* status */
+ mov $3, %ah
+
+ freea
+ pop %bx
+
+ clc
+ ret
+
+check_if_extensions_present:
+ mov $0x30, %ah
+ mov $0xAA55, %bx
+ mov $0x07, %cx
+ clc
+ ret
+
+.macro extended_read_write_sectors cmd
+ cmpb $10, 0(%si)
+ jg 1f
+ mov $1, %ah
+ stc
+ ret
+1:
+ push %ax
+ push %bp
+ allocbpa $16
+
+ movw \cmd, 0(%bp) /* read */
+ movw 2(%si), %ax /* nb_sectors */
+ movw %ax, 2(%bp)
+ movw 4(%si), %ax /* offset */
+ movw %ax, 6(%bp)
+ movw 6(%si), %ax /* segment */
+ movw %ax, 4(%bp)
+ movw 8(%si), %ax /* block */
+ movw %ax, 8(%bp)
+ movw 10(%si), %ax
+ movw %ax, 10(%bp)
+ movw 12(%si), %ax
+ movw %ax, 12(%bp)
+ movw 14(%si), %ax
+ movw %ax, 14(%bp)
+
+ push %bp
+ call send_command
+ add $2, %sp
+
+ freebpa
+ pop %bp
+ pop %ax
+
+ mov $0, %ah
+ clc
+ ret
+.endm
+
+extended_read_sectors:
+ extended_read_write_sectors $0x01
+
+extended_write_sectors:
+ extended_read_write_sectors $0x02
+
+get_extended_drive_parameters:
+ mov $1, %ah
+ stc
+ ret
+
+terminate_disk_emulation:
+ mov $1, %ah
+ stc
+ ret
+
+int13_handler:
+ cmp $0x80, %dl
+ je 1f
+ int $0x2c
+ iret
+1:
+ cmp $0x0, %ah
+ jne 1f
+ call disk_reset
+ iret
+1:
+ cmp $0x2, %ah
+ jne 1f
+ call read_disk_sectors
+ iret
+1:
+ cmp $0x8, %ah
+ jne 1f
+ call read_disk_drive_parameters
+ iret
+1:
+ cmp $0x15, %ah
+ jne 1f
+ call read_disk_drive_size
+ iret
+1:
+ cmp $0x41, %ah
+ jne 1f
+ call check_if_extensions_present
+ iret
+1:
+ cmp $0x42, %ah
+ jne 1f
+ call extended_read_sectors
+ iret
+1:
+ cmp $0x48, %ah
+ jne 1f
+ call get_extended_drive_parameters
+ iret
+1:
+ cmp $0x4b, %ah
+ jne 1f
+ call terminate_disk_emulation
+ iret
+1:
+ cmp $0x0d, %ah
+ jne 1f
+ call alternate_disk_reset
+ iret
+1:
+ cmp $0x03, %ah
+ jne 1f
+ call write_disk_sectors
+ iret
+1:
+ cmp $0x43, %ah
+ jne 1f
+ call extended_write_sectors
+ iret
+1:
+ int $0x18 /* boot failed */
+ iret
+
+.align 512, 0
+_end:
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/extboot/extboot.img
Binary file tools/firmware/extboot/extboot.img has changed
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/extboot/signrom
Binary file tools/firmware/extboot/signrom has changed
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/extboot/signrom.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/signrom.c Thu Jan 17 16:39:14 2008 +0000
@@ -0,0 +1,79 @@
+/*
+ * Extended Boot Option ROM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corporation, 2007
+ * Authors: Anthony Liguori <aliguori@xxxxxxxxxx>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+int main(int argc, char **argv)
+{
+ FILE *fin, *fout;
+ char buffer[512], oldbuffer[512];
+ int i, size, lag = 0;
+ uint8_t sum = 0;
+
+ if (argc != 3) {
+ printf("Usage: %s ROM OUTPUT\n", argv[0]);
+ return 1;
+ }
+
+ fin = fopen(argv[1], "rb");
+ fout = fopen(argv[2], "wb");
+
+ if (fin == NULL || fout == NULL) {
+ fprintf(stderr, "Could not open input/output files\n");
+ return 1;
+ }
+
+ do {
+ size = fread(buffer, 512, 1, fin);
+ if (size == 1) {
+ for (i = 0; i < 512; i++)
+ sum += buffer[i];
+
+ if (lag) {
+ if (fwrite(oldbuffer, 512, 1, fout) != 1) {
+ fprintf(stderr, "Write failed\n");
+ return 1;
+ }
+ }
+ lag = 1;
+ memcpy(oldbuffer, buffer, 512);
+ }
+ } while (size == 1);
+
+ if (size != 0) {
+ fprintf(stderr, "Failed to read from input file\n");
+ return 1;
+ }
+
+ oldbuffer[511] = -sum;
+
+ if (fwrite(oldbuffer, 512, 1, fout) != 1) {
+ fprintf(stderr, "Failed to write to output file\n");
+ return 1;
+ }
+
+ fclose(fin);
+ fclose(fout);
+
+ return 0;
+}
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/hvmloader/Makefile
--- a/tools/firmware/hvmloader/Makefile Thu Jan 17 15:50:48 2008 +0000
+++ b/tools/firmware/hvmloader/Makefile Thu Jan 17 16:39:14 2008 +0000
@@ -55,6 +55,7 @@ roms.h: ../rombios/BIOS-bochs-latest ../
sh ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin
>> roms.h
sh ./mkhex vmxassist ../vmxassist/vmxassist.bin >> roms.h
cat ../etherboot/eb-rtl8139.zrom.h >> roms.h
+ sh ./mkhex extboot ../extboot/extboot.bin >> roms.h
.PHONY: clean
clean:
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Thu Jan 17 15:50:48 2008 +0000
+++ b/tools/firmware/hvmloader/config.h Thu Jan 17 16:39:14 2008 +0000
@@ -22,6 +22,7 @@
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000
#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
+#define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800
#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000
#define SMBIOS_MAXIMUM_SIZE 0x00001000
#define ACPI_PHYSICAL_ADDRESS 0x000EA000
diff -r 95558b4a6714 -r bf828db8d017 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Thu Jan 17 15:50:48 2008 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c Thu Jan 17 16:39:14 2008 +0000
@@ -316,6 +316,11 @@ static int must_load_nic(void)
return ((boot_order & 0xf0) == 0x40);
}
+static int must_load_extboot(void)
+{
+ return (inb(0x404) == 1);
+}
+
/* Replace possibly erroneous memory-size CMOS fields with correct values. */
static void cmos_write_memory_size(void)
{
@@ -354,6 +359,7 @@ int main(void)
int main(void)
{
int acpi_sz = 0, vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz;
+ int extboot_sz = 0;
printf("HVM Loader\n");
@@ -396,6 +402,14 @@ int main(void)
memcpy((void *)ETHERBOOT_PHYSICAL_ADDRESS,
etherboot, sizeof(etherboot));
etherboot_sz = sizeof(etherboot);
+ }
+
+ if ( must_load_extboot() )
+ {
+ printf("Loading EXTBOOT ...\n");
+ memcpy((void *)EXTBOOT_PHYSICAL_ADDRESS,
+ extboot, sizeof(extboot));
+ extboot_sz = sizeof(extboot);
}
if ( get_acpi_enabled() )
@@ -416,6 +430,10 @@ int main(void)
printf(" %05x-%05x: Etherboot ROM\n",
ETHERBOOT_PHYSICAL_ADDRESS,
ETHERBOOT_PHYSICAL_ADDRESS + etherboot_sz - 1);
+ if ( extboot_sz )
+ printf(" %05x-%05x: Extboot ROM\n",
+ EXTBOOT_PHYSICAL_ADDRESS,
+ EXTBOOT_PHYSICAL_ADDRESS + extboot_sz - 1);
if ( use_vmxassist() )
printf(" %05x-%05x: VMXAssist\n",
VMXASSIST_PHYSICAL_ADDRESS,
diff -r 95558b4a6714 -r bf828db8d017 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target Thu Jan 17 15:50:48 2008 +0000
+++ b/tools/ioemu/Makefile.target Thu Jan 17 16:39:14 2008 +0000
@@ -403,7 +403,7 @@ VL_OBJS+= ne2000.o rtl8139.o pcnet.o e10
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
-VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) extboot.o
ifeq ($(ARCH),ia64)
VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
else
diff -r 95558b4a6714 -r bf828db8d017 tools/ioemu/hw/extboot.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/extboot.c Thu Jan 17 16:39:14 2008 +0000
@@ -0,0 +1,125 @@
+/*
+ * Extended boot option ROM support.
+ *
+ * Copyright IBM, Corp. 2007
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "vl.h"
+
+/* Extended Boot ROM suport */
+
+union extboot_cmd
+{
+ uint16_t type;
+ struct {
+ uint16_t type;
+ uint16_t cylinders;
+ uint16_t heads;
+ uint16_t 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 = (void *)(phys_ram_base + ((value & 0xFFFF) << 4));
+ BlockDriverState *bs = opaque;
+ int cylinders, heads, sectors, err;
+
+ get_translated_chs(bs, &cylinders, &heads, §ors);
+
+ if (cmd->type == 0x01 || cmd->type == 0x02) {
+ target_ulong pa = cmd->xfer.segment * 16 + cmd->xfer.segment;
+
+ /* possible buffer overflow */
+ if ((pa + cmd->xfer.nb_sectors * 512) > phys_ram_size)
+ return;
+ }
+
+ switch (cmd->type) {
+ case 0x00:
+ cmd->query_geometry.cylinders = cylinders;
+ cmd->query_geometry.heads = heads;
+ cmd->query_geometry.sectors = sectors;
+ cpu_physical_memory_set_dirty((value & 0xFFFF) << 4);
+ break;
+ case 0x01:
+ err = bdrv_read(bs, cmd->xfer.sector, phys_ram_base +
+ cmd->xfer.segment * 16 + cmd->xfer.offset,
+ cmd->xfer.nb_sectors);
+ if (err)
+ printf("Read failed\n");
+ break;
+ case 0x02:
+ err = bdrv_write(bs, cmd->xfer.sector, phys_ram_base +
+ cmd->xfer.segment * 16 + cmd->xfer.offset,
+ cmd->xfer.nb_sectors);
+ if (err)
+ printf("Write failed\n");
+
+ cpu_physical_memory_set_dirty(cmd->xfer.segment * 16 +
cmd->xfer.offset);
+ break;
+ }
+}
+
+void extboot_init(BlockDriverState *bs, int cmd)
+{
+ int *pcmd;
+
+ pcmd = qemu_mallocz(sizeof(int));
+ if (!pcmd) {
+ fprintf(stderr, "Error allocating memory\n");
+ exit(1);
+ }
+
+ *pcmd = cmd;
+ register_ioport_read(0x404, 1, 1, extboot_read, pcmd);
+ register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs);
+}
diff -r 95558b4a6714 -r bf828db8d017 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Thu Jan 17 15:50:48 2008 +0000
+++ b/tools/ioemu/vl.h Thu Jan 17 16:39:14 2008 +0000
@@ -971,6 +971,9 @@ int pmac_ide_init (BlockDriverState **hd
int pmac_ide_init (BlockDriverState **hd_table,
SetIRQFunc *set_irq, void *irq_opaque, int irq);
+/* extboot.c */
+void extboot_init(BlockDriverState *bs, int cmd);
+
/* cdrom.c */
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|