summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/diskboot.inc37
-rw-r--r--core/diskfs.inc5
-rw-r--r--core/diskstart.inc23
-rw-r--r--libinstaller/syslxint.h8
-rw-r--r--memdisk/dskprobe.c125
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(&regs, 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, &regs, &regs);
+ 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, &regs);
+ c += probe_int13h_15h(drive, &regs);
+ c += probe_int13h_41h(drive, &regs);
}
c += probe_bda_drive(drive);
+ dskprobe_pause(&regs);
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;
+}