diff options
-rw-r--r-- | core/diskboot.inc | 37 | ||||
-rw-r--r-- | core/diskfs.inc | 5 | ||||
-rw-r--r-- | core/diskstart.inc | 23 | ||||
-rw-r--r-- | libinstaller/syslxint.h | 8 | ||||
-rw-r--r-- | memdisk/dskprobe.c | 125 |
5 files changed, 141 insertions, 57 deletions
diff --git a/core/diskboot.inc b/core/diskboot.inc index 8f04f376..574db456 100644 --- a/core/diskboot.inc +++ b/core/diskboot.inc @@ -262,6 +262,7 @@ eddcheck: ; with parsing the superblock and root directory; it doesn't fit ; together with EBIOS support, unfortunately. ; +Sect1Load: mov eax,strict dword Sect1Ptr0_VAL ; 0xdeadbeef Sect1Ptr0 equ $-4 mov edx,strict dword Sect1Ptr1_VAL ; 0xfeedface @@ -273,9 +274,8 @@ Sect1Ptr1 equ $-4 cmp dword [ldlinux_magic+4],LDLINUX_MAGIC^HEXDATE jne kaboom - ; Go for it... - jmp 0:ldlinux_ent - + ; Go for it! This also normalizes CS:IP. + jmp ldlinux_ent ; ; getonesec: load a single disk linear sector EDX:EAX into the buffer @@ -390,8 +390,15 @@ kaboom: pop dword [fdctab] ; Restore FDC table .patch: ; When we have full code, intercept here mov si,bailmsg - call writestr_early +.loop: lodsb + and al,al + jz .done + mov ah,0Eh ; Write to screen as TTY + mov bx,0007h ; Attribute + int 10h + jmp short .loop +.done: xor ax,ax .again: int 16h ; Wait for keypress ; NB: replaced by int 18h if @@ -401,24 +408,6 @@ kaboom: jmp short .norge ; -; -; writestr_early: write a null-terminated string to the console -; This assumes we're on page 0. This is only used for early -; messages, so it should be OK. -; -writestr_early: - pushad -.loop: lodsb - and al,al - jz .return - mov ah,0Eh ; Write to screen as TTY - mov bx,0007h ; Attribute - int 10h - jmp short .loop -.return: popad - ret - -; ; INT 13h wrapper function ; xint13: @@ -434,8 +423,10 @@ xint13: bailmsg: db 'Boot error', 0Dh, 0Ah, 0 ; This fails if the boot sector overflowsg - zb 1FEh-($-$$) + zb 1F8h-($-$$) +bs_magic dd LDLINUX_MAGIC +bs_link dw (Sect1Load - bootsec) | BS_MAGIC_VER bootsignature dw 0xAA55 ; diff --git a/core/diskfs.inc b/core/diskfs.inc index a04a4f0d..fc80a153 100644 --- a/core/diskfs.inc +++ b/core/diskfs.inc @@ -2,7 +2,7 @@ ; ----------------------------------------------------------------------- ; ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved -; Copyright 2009 Intel Corporation; author: H. Peter Anvin +; Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin ; ; 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 @@ -27,6 +27,9 @@ retry_count equ 16 ; How patient are we with the disk? %assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with +; This indicates the general format of the last few bytes in the boot sector +BS_MAGIC_VER equ 0x1b << 9 + SECTOR_SHIFT equ 9 SECTOR_SIZE equ (1 << SECTOR_SHIFT) diff --git a/core/diskstart.inc b/core/diskstart.inc index 9280f7da..b3c09286 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -1,7 +1,7 @@ ; ----------------------------------------------------------------------- ; ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved -; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin +; Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin ; ; 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 @@ -92,7 +92,8 @@ ldlinux_ent: ; value in CS, but we don't want to deal with that anymore from now ; on. ; - sti ; In case of broken INT 13h BIOSes + jmp 0:.next ; Normalize CS:IP +.next: sti ; In case of broken INT 13h BIOSes ; ; Tell the user we got this far @@ -370,6 +371,24 @@ maxtrans: .ok: ret ; +; +; writestr_early: write a null-terminated string to the console +; This assumes we're on page 0. This is only used for early +; messages, so it should be OK. +; +writestr_early: + pushad +.loop: lodsb + and al,al + jz .return + mov ah,0Eh ; Write to screen as TTY + mov bx,0007h ; Attribute + int 10h + jmp short .loop +.return: popad + ret + +; ; Checksum error message ; checksumerr_msg db ' Load error - ', 0 ; Boot failed appended diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h index 14a7fc2b..80c40f76 100644 --- a/libinstaller/syslxint.h +++ b/libinstaller/syslxint.h @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin * * 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 @@ -156,6 +157,7 @@ void memcpy_from_sl(void *dst, const void *src, size_t len); #endif #define LDLINUX_MAGIC 0x3eb202fe +#define BS_MAGIC_VER (0x1b << 9) /* Patch area for disk-based installers */ struct patch_area { @@ -214,7 +216,7 @@ struct boot_sector { uint32_t VolumeID; char VolumeLabel[11]; char FileSysType[8]; - uint8_t Code[448]; + uint8_t Code[442]; } __attribute__ ((packed)) bs16; struct { uint32_t FATSz32; @@ -230,10 +232,12 @@ struct boot_sector { uint32_t VolumeID; char VolumeLabel[11]; char FileSysType[8]; - uint8_t Code[420]; + uint8_t Code[414]; } __attribute__ ((packed)) bs32; } __attribute__ ((packed)); + uint32_t bsMagic; + uint16_t bsForwardPtr; uint16_t bsSignature; } __attribute__ ((packed)); diff --git a/memdisk/dskprobe.c b/memdisk/dskprobe.c index de858bb9..84400a83 100644 --- a/memdisk/dskprobe.c +++ b/memdisk/dskprobe.c @@ -16,37 +16,82 @@ * Routines for probing BIOS disk drives */ -/* - * Uncomment for debugging - * - * #define DBG_DSKPROBE 1 - */ +/* Change to 1 for debugging */ +#define DBG_DSKPROBE 0 #include <stdint.h> #include "memdisk.h" #include "bda.h" #include "conio.h" -/* - * We will probe a BIOS drive numer using INT 13h, AH=probe - * and will pass along that call's success or failure +/* Function type for printf() */ +typedef int (f_printf) (const char *, ...); + +/* Dummy printf() that does nothing */ +static f_printf no_printf; +static f_printf *dskprobe_printfs[] = { no_printf, printf }; + +#define dskprobe_printf (dskprobe_printfs[DBG_DSKPROBE]) + +static void dskprobe_pause(com32sys_t *); + +/* Probe routine function type */ +typedef int (f_probe) (uint8_t, com32sys_t *); +static f_probe probe_int13h_08h, probe_int13h_15h, probe_int13h_41h; + +/* We will probe a BIOS drive number using INT 0x13, AH == func */ +static void probe_any(uint8_t func, uint8_t drive, com32sys_t * regs) +{ + regs->eax.b[1] = func; /* AH == sub-function for probe */ + regs->edx.b[0] = drive; /* DL == drive number to probe */ + intcall(0x13, regs, regs); + return; +} + +/** + * INT 0x13, AH == 0x08: Get drive parameters. */ -int probe_int13_ah(uint8_t drive, uint8_t probe) +static int probe_int13h_08h(uint8_t drive, com32sys_t * regs) { - int err; - com32sys_t regs; + int present; + + memset(regs, 0, sizeof *regs); + probe_any(0x08, drive, regs); + present = !(regs->eflags.l & 1); + dskprobe_printf(" AH08: CF%d BL%02x DL%02x\n", regs->eflags.l & 1, + regs->ebx.b[0], regs->edx.b[0]); + return present; +} - memset(®s, 0, sizeof regs); +/** + * INT 0x13, AH == 0x15: Get disk type. + */ +static int probe_int13h_15h(uint8_t drive, com32sys_t * regs) +{ + int present; - regs.eax.b[1] = probe; /* AH = probe */ - regs.edx.b[0] = drive; /* DL = drive number to probe */ - intcall(0x13, ®s, ®s); + memset(regs, 0, sizeof *regs); + probe_any(0x15, drive, regs); + present = !(regs->eflags.l & 1) && regs->eax.b[1]; + dskprobe_printf(" AH15: CF%d AH%02x\n", regs->eflags.l & 1, + regs->eax.b[1]); + return present; +} - err = !(regs.eflags.l & 1); -#ifdef DBG_DSKPROBE - printf("probe_int13_ah(0x%02x, 0x%02x) == %d\n", drive, probe, err); -#endif - return err; +/** + * INT 0x13, AH == 0x41: INT 0x13 extensions installation check. + */ +static int probe_int13h_41h(uint8_t drive, com32sys_t * regs) +{ + int present; + + memset(regs, 0, sizeof *regs); + regs->ebx.w[0] = 0x55AA; /* BX == 0x55AA */ + probe_any(0x41, drive, regs); + present = !(regs->eflags.l & 1); + dskprobe_printf(" AH41: CF%d BX%04x AH%02x DH%02x\n", regs->eflags.l & 1, + regs->ebx.w[0], regs->eax.b[1], regs->edx.b[1]); + return present; } /* @@ -72,10 +117,8 @@ int probe_bda_drive(uint8_t drive) bios_drives = 0; } err = (drive - (drive & 0x80)) >= bios_drives ? 0 : 1; -#ifdef DBG_DSKPROBE - printf("probe_bda_drive(0x%02x) == %d, count: %d\n", - drive, err, bios_drives); -#endif + dskprobe_printf("BDA drive %02x? %d, total count: %d\n", drive, err, + bios_drives); return err; } @@ -83,16 +126,21 @@ int probe_bda_drive(uint8_t drive) * We will probe a drive with a few different methods, returning * the count of succesful probes */ -int probe_drive(uint8_t drive) +int multi_probe_drive(uint8_t drive) { int c = 0; + com32sys_t regs; + + dskprobe_printf("INT 13 DL%02x:\n", drive); /* Only probe the BDA for floppies */ if (drive & 0x80) { - c += probe_int13_ah(drive, 0x08); - c += probe_int13_ah(drive, 0x15); - c += probe_int13_ah(drive, 0x41); + + c += probe_int13h_08h(drive, ®s); + c += probe_int13h_15h(drive, ®s); + c += probe_int13h_41h(drive, ®s); } c += probe_bda_drive(drive); + dskprobe_pause(®s); return c; } @@ -104,7 +152,7 @@ int probe_drive(uint8_t drive) uint8_t probe_drive_range(uint8_t start) { uint8_t drive = start; - while (probe_drive(drive)) { + while (multi_probe_drive(drive)) { drive++; /* Check for passing the floppy/HDD boundary */ if ((drive & 0x7F) == 0) @@ -112,3 +160,22 @@ uint8_t probe_drive_range(uint8_t start) } return drive; } + +/* Dummy printf() that does nothing */ +static int no_printf(const char *ignored, ...) +{ + (void)ignored; + return 0; +} + +/* Pause if we are in debug-mode */ +static void dskprobe_pause(com32sys_t * regs) +{ + if (!DBG_DSKPROBE) + return; + dskprobe_printf("Press a key to continue...\n"); + memset(regs, 0, sizeof *regs); + regs->eax.w[0] = 0; + intcall(0x16, regs, NULL); + return; +} |