diff options
Diffstat (limited to 'src/boot.c')
-rw-r--r-- | src/boot.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/boot.c b/src/boot.c new file mode 100644 index 00000000..828be145 --- /dev/null +++ b/src/boot.c @@ -0,0 +1,118 @@ +// 16bit code to load disk image and start system boot. +// +// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "types.h" // VISIBLE +#include "util.h" // irq_enable +#include "biosvar.h" // struct bregs +#include "farptr.h" // SET_SEG + +static inline void +__call_irq(u8 nr) +{ + asm volatile("int %0" : : "N" (nr)); +} + +static inline u32 +call_irq(u8 nr, struct bregs *callregs) +{ + u32 flags; + asm volatile( + // Save current registers + "pushal\n" + // Pull in calling registers. + "movl 0x04(%%eax), %%edi\n" + "movl 0x08(%%eax), %%esi\n" + "movl 0x0c(%%eax), %%ebp\n" + "movl 0x14(%%eax), %%ebx\n" + "movl 0x18(%%eax), %%edx\n" + "movl 0x1c(%%eax), %%ecx\n" + "movl 0x20(%%eax), %%eax\n" + // Invoke interrupt + "int %1\n" + // Restore registers + "popal\n" + // Exract flags + "pushfw\n" + "popl %%eax\n" + : "=a" (flags): "N" (nr), "a" (callregs), "m" (*callregs)); + return flags; +} + +static void +print_boot_failure() +{ + bprintf(0, "Boot failed\n"); +} + +static void +try_boot() +{ + // XXX - assume floppy + u16 bootseg = 0x07c0; + u8 bootdrv = 0; + + // Read sector + struct bregs cr; + memset(&cr, 0, sizeof(cr)); + cr.dl = bootdrv; + SET_SEG(ES, bootseg); + cr.bx = 0; + cr.ah = 2; + cr.al = 1; + cr.ch = 0; + cr.cl = 1; + cr.dh = 0; + u32 status = call_irq(0x13, &cr); + + if (status & F_CF) { + print_boot_failure(); + return; + } + + u16 bootip = (bootseg & 0x0fff) << 4; + bootseg &= 0xf000; + + u32 segoff = (bootseg << 16) | bootip; + asm volatile ( + "pushf\n" + "pushl %0\n" + "movb %b1, %%dl\n" + // Set the magic number in ax and the boot drive in dl. + "movw $0xaa55, %%ax\n" + // Zero some of the other registers. + "xorw %%bx, %%bx\n" + "movw %%bx, %%ds\n" + "movw %%bx, %%es\n" + "movw %%bx, %%bp\n" + // Go! + "iretw\n" + : : "r" (segoff), "ri" (bootdrv)); +} + +// Boot Failure recovery: try the next device. +void VISIBLE +handle_18(struct bregs *regs) +{ + debug_enter(regs); + try_boot(); +} + +// INT 19h Boot Load Service Entry Point +void VISIBLE +handle_19(struct bregs *regs) +{ + debug_enter(regs); + try_boot(); +} + +// Callback from 32bit entry - start boot process +void VISIBLE +begin_boot() +{ + irq_enable(); + __call_irq(0x19); +} |