extboot is an x86 Option ROM that passes through int13 functions to a VMM which
allows a VMM to expose an arbitrary block device as the primary BIOS disk.  It
can be used to boot SCSI or paravirtual devices.

Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]>

diff --git a/extboot/Makefile b/extboot/Makefile
new file mode 100644
index 0000000..1ea71a7
--- /dev/null
+++ b/extboot/Makefile
@@ -0,0 +1,21 @@
+OBJCOPY=objcopy
+
+CFLAGS=-Wall -Wstrict-prototypes -Werror -fomit-frame-pointer -fno-builtin \
+       -fno-stack-protector
+
+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 --git a/extboot/STATUS b/extboot/STATUS
new file mode 100644
index 0000000..687c6d6
--- /dev/null
+++ b/extboot/STATUS
@@ -0,0 +1,6 @@
+Working
+-------
+
+Ubuntu Server 7.04 (i386)
+Windows 2000 Professional (i386)
+Windows XP SP2 (i386)
diff --git a/extboot/extboot.S b/extboot/extboot.S
new file mode 100644
index 0000000..7b6e9b2
--- /dev/null
+++ b/extboot/extboot.S
@@ -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 <[EMAIL PROTECTED]>
+ */
+
+.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 --git a/extboot/signrom.c b/extboot/signrom.c
new file mode 100644
index 0000000..fe8d677
--- /dev/null
+++ b/extboot/signrom.c
@@ -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 <[EMAIL PROTECTED]>
+ */
+
+#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;
+}

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to