All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: Xen-devel <xen-devel@lists.xensource.com>,
	Keir Fraser <Keir.Fraser@cl.cam.ac.uk>
Subject: [PATCH] Extboot support for Xen
Date: Tue, 15 Jan 2008 14:02:24 -0600	[thread overview]
Message-ID: <478D1150.8030403@us.ibm.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1105 bytes --]

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.

The version of QEMU in Xen is a bit old so I couldn't complete the plumbing.
The main problem is that Xen provides no way of exposing SCSI disks 
right now
and PV disks aren't actually accessible within QEMU.  I'm hoping someone 
else
can pick that up though as I'm pretty overcommitted at the moment.  The
extboot infrastructure is there though so it's just a matter of 
initializing it
with the appropriate BlockDriverState.

Another thing to look at is the choice of physical address.  extboot 
occupies
1.5k of memory but option roms have to fall on a 2k boundary.  I stole 
2k from
the space used by etherboot.  That should be fine since etherboot and 
extboot
should never be loaded at the same time.  Of course, someone with more 
insight
into hvmloader may know of a better place.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

[-- Attachment #2: extboot.diff --]
[-- Type: text/x-patch, Size: 23067 bytes --]

Subject: [PATCH] Extboot support for Xen
Cc: Keir Fraser <Keir.Fraser@cl.cam.ac.uk>

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.

The version of QEMU in Xen is a bit old so I couldn't complete the plumbing.
The main problem is that Xen provides no way of exposing SCSI disks right now
and PV disks aren't actually accessible within QEMU.  I'm hoping someone else
can pick that up though as I'm pretty overcommitted at the moment.  The
extboot infrastructure is there though so it's just a matter of initializing it
with the appropriate BlockDriverState.

Another thing to look at is the choice of physical address.  extboot occupies
1.5k of memory but option roms have to fall on a 2k boundary.  I stole 2k from
the space used by etherboot.  That should be fine since etherboot and extboot
should never be loaded at the same time.  Of course, someone with more insight
into hvmloader may know of a better place.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

diff -r 533a8e6cebd0 tools/firmware/Makefile
--- a/tools/firmware/Makefile	Sat Jan 12 11:26:04 2008 +0000
+++ b/tools/firmware/Makefile	Tue Jan 15 13:55:22 2008 -0600
@@ -10,6 +10,7 @@ SUBDIRS += rombios rombios/32bit
 SUBDIRS += rombios rombios/32bit
 SUBDIRS += vgabios
 SUBDIRS += vmxassist
+SUBDIRS += extboot
 SUBDIRS += hvmloader
 
 .PHONY: all
diff -r 533a8e6cebd0 tools/firmware/extboot/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/Makefile	Tue Jan 15 13:55:22 2008 -0600
@@ -0,0 +1,41 @@
+OBJCOPY=objcopy
+
+# from kernel sources - scripts/Kbuild.include
+# try-run
+# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
+# Exit code chooses option. "$$TMP" is can be used as temporary file and
+# is automatically cleaned up.
+try-run = $(shell set -e;		\
+	TMP="$(TMPOUT).$$$$.tmp";	\
+	if ($(1)) >/dev/null 2>&1;	\
+	then echo "$(2)";		\
+	else echo "$(3)";		\
+	fi;				\
+	rm -f "$$TMP")
+
+# cc-option-yn
+# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
+cc-option-yn = $(call try-run,\
+	$(CC) $(KBUILD_CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",y,n)
+
+CFLAGS = -Wall -Wstrict-prototypes -Werror -fomit-frame-pointer -fno-builtin
+ifeq ($(call cc-option-yn,-fno-stack-protector),y)
+CFLAGS += -fno-stack-protector
+endif
+
+all: extboot.bin
+
+%.o: %.S
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+extboot.img: extboot.o
+	$(LD) --oformat binary -Ttext 0 -o $@ $<
+
+extboot.bin: extboot.img signrom
+	./signrom extboot.img extboot.bin
+
+signrom: signrom.c
+	$(CC) -o $@ -g -Wall $^
+
+clean:
+	$(RM) *.o *.img *.bin signrom *~
diff -r 533a8e6cebd0 tools/firmware/extboot/STATUS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/STATUS	Tue Jan 15 13:55:22 2008 -0600
@@ -0,0 +1,6 @@
+Working
+-------
+
+Ubuntu Server 7.04 (i386)
+Windows 2000 Professional (i386)
+Windows XP SP2 (i386)
diff -r 533a8e6cebd0 tools/firmware/extboot/extboot.S
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/extboot.S	Tue Jan 15 13:55:22 2008 -0600
@@ -0,0 +1,742 @@
+/*
+ * 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@us.ibm.com>
+ */
+
+.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 out 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
+	je 1f
+	cmp $2, %al
+	je 2f
+	jmp 3f
+
+1: /* hook int13: intb(0x404) == 1 */
+	/* 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)
+	jmp 3f
+
+2: /* linux boot: intb(0x404) == 2 */
+	cli
+	cld
+	mov $0x9000, %ax
+	mov %ax, %ds
+	mov %ax, %es
+	mov %ax, %fs
+	mov %ax, %gs
+	mov %ax, %ss
+	mov $0x8ffe, %sp
+	ljmp $0x9000 + 0x20, $0
+
+3: /* fall through: inb(0x404) == 0 */
+	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
+#if 0
+	/* this function is seriously borked */
+1:
+	push %ax
+	push %bp
+	push %cx
+	push %dx
+
+	allocbpa $8
+
+	movw $0, 0(%bp) /* read c,h,s */
+	push %bp
+	call send_command
+	add $2, %sp
+
+	/* check the size of the passed in data */
+	cmpw $26, 0(%si)
+	mov 0(%si), %ax
+	dump %ax
+	jle 0b
+
+	/* set flags to 2 */
+	movw $2, 2(%si)
+
+	/* cylinders */
+	mov 2(%bp), %ax
+	mov %ax, 4(%si)
+	xor %ax, %ax
+	mov %ax, 6(%si)
+
+	/* heads */
+	mov 4(%bp), %ax
+	mov %ax, 8(%si)
+	xor %ax, %ax
+	mov %ax, 10(%si)
+
+	/* sectors */
+	mov 6(%bp), %ax
+	mov %ax, 12(%si)
+	xor %ax, %ax
+	mov %ax, 14(%si)
+
+	/* calculate total sectors */
+
+	/* cx:dx = cylinders */
+	mov 2(%bp), %dx
+	xor %cx, %cx
+
+	/* *= heads */
+	push 4(%bp)
+	push $0
+	push %dx
+	push %cx
+	call mul32
+	add $8, %sp
+
+	/* *= sectors */
+	push 6(%bp)
+	push $0
+	push %dx
+	push %cx
+	call mul32
+	add $8, %sp
+
+	/* total number of sectors */
+	mov %dx, 16(%si)
+	mov %cx, 18(%si)
+	xor %ax, %ax
+	mov %ax, 20(%si)
+	mov %ax, 22(%si)
+
+	/* number of bytes per sector */
+	movw $512, 24(%si)
+
+	/* optional segmention:offset to EDD config */
+	cmpw $30, 0(%si)
+	jl 1f
+
+	movw $0xFFFF, 26(%si)
+	movw $0xFFFF, 28(%si)
+
+1:
+	freebpa
+
+	pop %dx
+	pop %cx
+	pop %bp
+	pop %ax
+
+	mov $0, %ah
+	clc
+	ret
+#endif
+
+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 533a8e6cebd0 tools/firmware/extboot/signrom.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/extboot/signrom.c	Tue Jan 15 13:55:22 2008 -0600
@@ -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@us.ibm.com>
+ */
+
+#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 533a8e6cebd0 tools/firmware/hvmloader/Makefile
--- a/tools/firmware/hvmloader/Makefile	Sat Jan 12 11:26:04 2008 +0000
+++ b/tools/firmware/hvmloader/Makefile	Tue Jan 15 13:55:22 2008 -0600
@@ -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 533a8e6cebd0 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h	Sat Jan 12 11:26:04 2008 +0000
+++ b/tools/firmware/hvmloader/config.h	Tue Jan 15 13:55:22 2008 -0600
@@ -21,6 +21,9 @@
 #define HYPERCALL_PHYSICAL_ADDRESS    0x00080000
 #define VGABIOS_PHYSICAL_ADDRESS      0x000C0000
 #define ETHERBOOT_PHYSICAL_ADDRESS    0x000C8000
+/* extboot only needs 1.5k but option roms must be on a 2k boundary */
+/* FIXME: I think etherboot takes up this full space */
+#define EXTBOOT_PHYSICAL_ADDRESS      0x000CF800
 #define VMXASSIST_PHYSICAL_ADDRESS    0x000D0000
 #define SMBIOS_PHYSICAL_ADDRESS       0x000E9000
 #define SMBIOS_MAXIMUM_SIZE           0x00001000
diff -r 533a8e6cebd0 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c	Sat Jan 12 11:26:04 2008 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c	Tue Jan 15 13:55:22 2008 -0600
@@ -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 533a8e6cebd0 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target	Sat Jan 12 11:26:04 2008 +0000
+++ b/tools/ioemu/Makefile.target	Tue Jan 15 13:55:22 2008 -0600
@@ -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 533a8e6cebd0 tools/ioemu/hw/extboot.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/extboot.c	Tue Jan 15 13:55:22 2008 -0600
@@ -0,0 +1,125 @@
+/*
+ * Extended boot option ROM support.
+ *
+ * Copyright IBM, Corp. 2007
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * 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, &sectors);
+
+    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 533a8e6cebd0 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h	Sat Jan 12 11:26:04 2008 +0000
+++ b/tools/ioemu/vl.h	Tue Jan 15 13:55:22 2008 -0600
@@ -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);

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

             reply	other threads:[~2008-01-15 20:02 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-15 20:02 Anthony Liguori [this message]
2008-01-15 21:35 ` [PATCH] Extboot support for Xen Keir Fraser
2008-01-15 21:45   ` Anthony Liguori
2008-01-15 21:44 ` Daniel P. Berrange

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=478D1150.8030403@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --cc=Keir.Fraser@cl.cam.ac.uk \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.