aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhpa <hpa>2005-01-12 00:34:54 +0000
committerhpa <hpa>2005-01-12 00:34:54 +0000
commit25ac97ff571bf6b5891921f6e5f1b6f45806314a (patch)
treebd4dc3873d43dfd03e0312d229c61a5256f12c12
parenta740cb88107937fe0758aa6e520fb4cc552157fc (diff)
downloadsyslinux-25ac97ff571bf6b5891921f6e5f1b6f45806314a.tar.gz
syslinux-25ac97ff571bf6b5891921f6e5f1b6f45806314a.tar.xz
syslinux-25ac97ff571bf6b5891921f6e5f1b6f45806314a.zip
3.07: Fix chainloading
-rw-r--r--NEWS3
-rw-r--r--bootsect.inc12
-rw-r--r--com32/modules/chain.c136
-rw-r--r--comboot.inc5
-rw-r--r--pxelinux.asm20
-rw-r--r--tracers.inc2
-rw-r--r--version2
7 files changed, 104 insertions, 76 deletions
diff --git a/NEWS b/NEWS
index c0c820d6..f9ce8f52 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@ Starting with 1.47, changes marked with SYSLINUX/PXELINUX/ISOLINUX
apply to that specific program only; other changes apply to all of
them.
+Changes in 3.07:
+ * Fix chainloading (chain.c32).
+
Changes in 3.06:
* Fix typo that caused the ramdisk to load in the wrong place.
diff --git a/bootsect.inc b/bootsect.inc
index 67ce6762..f22e845a 100644
--- a/bootsect.inc
+++ b/bootsect.inc
@@ -66,7 +66,7 @@ load_bootsec:
xor edx,edx
xor esi,esi
-%if IS_SYSLINUX || IS_MDSLINUX
+%if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
; Restore original FDC table
mov eax,[OrigFDCTabPtr]
mov [fdctab],eax
@@ -111,7 +111,9 @@ replace_bootstrap:
call vgaclearmode
;
- ; Set up initial stack frame (not used by PXE if keeppxe is set)
+ ; Set up initial stack frame (not used by PXE if keeppxe is
+ ; set - we use the PXE stack then.)
+ ; AFTER THIS POINT ONLY .earlybss IS AVAILABLE, NOT .bss
;
xor ax,ax
mov ds,ax
@@ -135,12 +137,12 @@ replace_bootstrap:
mov [es:di+12],esi
mov [es:di+6],bx
- pop cx ; Copy list count
+ pop ax ; Copy list count
pop bx ; Copy from...
cli
- mov ax,es
- mov ss,ax
+ mov cx,es
+ mov ss,cx
movzx esp,di
jmp shuffle_and_boot
diff --git a/com32/modules/chain.c b/com32/modules/chain.c
index eea48f18..0a52f138 100644
--- a/com32/modules/chain.c
+++ b/com32/modules/chain.c
@@ -1,7 +1,7 @@
#ident "$Id$"
/* ----------------------------------------------------------------------- *
*
- * Copyright 2003-2004 H. Peter Anvin - All Rights Reserved
+ * Copyright 2003-2005 H. Peter Anvin - All Rights Reserved
*
* 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
@@ -21,7 +21,7 @@
*
* ... e.g. "chain hd0 1" will boot the first partition on the first hard disk.
*
- * Only partitions 1-4 supported at this time; 0 = boot MBR (default.)
+ * Partitions 1-4 are primary, 5+ logical, 0 = boot MBR (default.)
*/
#include <com32.h>
@@ -35,7 +35,7 @@
static inline void error(const char *msg)
{
- puts(msg);
+ fputs(msg, stderr);
}
/*
@@ -48,9 +48,9 @@ int int13_retry(const com32sys_t *inreg, com32sys_t *outreg)
if ( !outreg ) outreg = &tmpregs;
- while ( retry ) {
+ while ( retry-- ) {
__intcall(0x13, inreg, outreg);
- if ( (outreg->eflags.l & 1) == 0 )
+ if ( !(outreg->eflags.l & EFLAGS_CF) )
return 0; /* CF=0, OK */
}
@@ -62,43 +62,49 @@ int int13_retry(const com32sys_t *inreg, com32sys_t *outreg)
*/
struct diskinfo {
int disk;
+ int ebios; /* EBIOS supported on this disk */
+ int cbios; /* CHS geometry is valid */
int head;
int sect;
- int ebios;
} disk_info;
int get_disk_params(int disk)
{
- com32sys_t getparm, parm, getebios, ebios;
-
- memset(&getparm, 0, sizeof getparm);
- memset(&getebios, 0, sizeof getebios);
- memset(&disk_info, 0, sizeof disk_info);
+ static com32sys_t getparm, parm, getebios, ebios;
disk_info.disk = disk;
- if ( disk & 0x80 ) {
- /* Get disk parameters -- hard drives only */
-
- getparm.eax.b[1] = 0x08;
- getparm.edx.b[0] = disk;
- if ( int13_retry(&getparm, &parm) )
- return -1;
-
- disk_info.head = parm.edx.b[1]+1;
- disk_info.sect = parm.ecx.b[0] & 0x3f;
-
- /* Get EBIOS support */
-
- getebios.eax.w[0] = 0x4100;
- getebios.edx.b[0] = disk;
- getebios.ebx.w[0] = 0x55aa;
- getebios.eflags.b[0] = 0x3; /* CF set */
- if ( !int13_retry(&getebios, &ebios) ) {
- if ( ebios.ebx.w[0] == 0xaa55 &&
- (ebios.ecx.b[0] & 1) )
- disk_info.ebios = 1;
- }
+ /* Get EBIOS support */
+ getebios.eax.w[0] = 0x4100;
+ getebios.ebx.w[0] = 0x55aa;
+ getebios.edx.b[0] = disk;
+ getebios.eflags.b[0] = 0x3; /* CF set */
+
+ __intcall(0x13, &getebios, &ebios);
+
+ if ( !(ebios.eflags.l & EFLAGS_CF) &&
+ ebios.ebx.w[0] == 0xaa55 &&
+ (ebios.ecx.b[0] & 1) ) {
+ disk_info.ebios = 1;
+ }
+
+ /* Get disk parameters -- really only useful for
+ hard disks, but if we have a partitioned floppy
+ it's actually our best chance... */
+ getparm.eax.b[1] = 0x08;
+ getparm.edx.b[0] = disk;
+
+ __intcall(0x13, &getparm, &parm);
+
+ if ( parm.eflags.l & EFLAGS_CF )
+ return disk_info.ebios ? 0 : -1;
+
+ disk_info.head = parm.edx.b[1]+1;
+ disk_info.sect = parm.ecx.b[0] & 0x3f;
+ if ( disk_info.sect == 0 ) {
+ disk_info.sect = 1;
+ } else {
+ disk_info.cbios = 1; /* Valid geometry */
}
return 0;
@@ -135,10 +141,19 @@ int read_sector(void *buf, unsigned int lba)
} else {
unsigned int c, h, s, t;
- s = (lba % disk_info.sect) + 1;
- t = lba / disk_info.sect; /* Track = head*cyl */
- h = t % disk_info.head;
- c = t / disk_info.head;
+ if ( !disk_info.cbios ) {
+ /* We failed to get the geometry */
+
+ if ( lba )
+ return -1; /* Can only read MBR */
+
+ s = 1; h = 0; c = 0;
+ } else {
+ s = (lba % disk_info.sect) + 1;
+ t = lba / disk_info.sect; /* Track = head*cyl */
+ h = t % disk_info.head;
+ c = t / disk_info.head;
+ }
if ( s > 63 || h > 256 || c > 1023 )
return -1;
@@ -253,39 +268,38 @@ struct part_entry *find_logical_partition(int whichpart, char *table, struct par
}
-int main(void)
+int main(int argc, char *argv[])
{
char *mbr, *boot_sector = NULL;
struct part_entry *partinfo;
- char *cmdline = __com32.cs_cmdline;
+ char *drivename, *partition;
int hd, drive, whichpart;
static com32sys_t inreg; /* In bss, so zeroed automatically */
openconsole(&dev_null_r, &dev_stdcon_w);
- /* Parse command line */
- while ( isspace(*cmdline) )
- cmdline++;
+ if ( argc < 2 ) {
+ error("Usage: chain.c32 (hd|fd)# [partition]\n");
+ goto bail;
+ }
+
+ drivename = argv[1];
+ partition = argv[2]; /* Possibly null */
hd = 0;
- if ( (cmdline[0] == 'h' || cmdline[0] == 'f') &&
- cmdline[1] == 'd' ) {
- hd = cmdline[0] == 'h';
- cmdline += 2;
+ if ( (drivename[0] == 'h' || drivename[0] == 'f') &&
+ drivename[1] == 'd' ) {
+ hd = drivename[0] == 'h';
+ drivename += 2;
}
- drive = (hd ? 0x80 : 0) | strtoul(cmdline, &cmdline, 0);
+ drive = (hd ? 0x80 : 0) | strtoul(drivename, NULL, 0);
whichpart = 0; /* Default */
- if ( isspace(*cmdline) ) {
- while ( isspace(*cmdline) )
- cmdline++;
-
- whichpart = strtoul(cmdline, NULL, 0);
- }
+ if ( partition )
+ whichpart = strtoul(partition, NULL, 0);
- if ( !(drive & 0x80) && whichpart != 0 ) {
- error("Partitions not supported on floppy drives\n");
- goto bail;
+ if ( !(drive & 0x80) && whichpart ) {
+ error("Warning: Partitions of floppy devices may not work\n");
}
/* Divvy up the bounce buffer. To keep things sector-
@@ -295,14 +309,15 @@ int main(void)
dapa = (struct ebios_dapa *)__com32.cs_bounce;
mbr = (char *)__com32.cs_bounce + SECTOR;
- /* Get the MBR */
- if ( get_disk_params(drive) ) {
+ /* Get the disk geometry (not needed for MBR) */
+ if ( get_disk_params(drive) && whichpart ) {
error("Cannot get disk parameters\n");
goto bail;
}
+ /* Get MBR */
if ( read_sector(mbr, 0) ) {
- error("Cannot read MBR\n");
+ error("Cannot read Master Boot Record\n");
goto bail;
}
@@ -343,6 +358,9 @@ int main(void)
inreg.esi.w[0] = 0x7be;
memcpy((char *)0x7be, partinfo, sizeof(*partinfo));
}
+
+ fputs("Booting...\n", stdout);
+
inreg.eax.w[0] = 0x000d; /* Clean up and chain boot */
inreg.edx.w[0] = 0; /* Should be 3 for "keeppxe" */
inreg.edi.l = (uint32_t)boot_sector;
diff --git a/comboot.inc b/comboot.inc
index 83b57f46..d8a55a8a 100644
--- a/comboot.inc
+++ b/comboot.inc
@@ -1,7 +1,7 @@
;; $Id$
;; -----------------------------------------------------------------------
;;
-;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
+;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved
;;
;; 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
@@ -527,7 +527,7 @@ comapi_cleanup:
sub bp,sp ; unload_pxe may move the stack around
call unload_pxe
add bp,sp ; restore frame pointer...
-%elif IS_SYSLINUX || IS_MDSLINUX
+%elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
; Restore original FDC table
mov eax,[OrigFDCTabPtr]
mov [fdctab],eax
@@ -539,7 +539,6 @@ comapi_cleanup:
clc
ret
-
;
; INT 22h AX=000Dh Clean up then replace bootstrap
;
diff --git a/pxelinux.asm b/pxelinux.asm
index 2b3a8115..e8c38062 100644
--- a/pxelinux.asm
+++ b/pxelinux.asm
@@ -8,7 +8,7 @@
; network booting API. It is based on the SYSLINUX boot loader for
; MS-DOS floppies.
;
-; Copyright (C) 1994-2004 H. Peter Anvin
+; Copyright (C) 1994-2005 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
@@ -196,6 +196,7 @@ ConfigName resb 256-4 ; Configuration file from DHCP option
PathPrefix resb 256 ; Path prefix derived from boot file
DotQuadBuf resb 16 ; Buffer for dotted-quad IP address
IPOption resb 80 ; ip= option buffer
+InitStack resd 1 ; Pointer to reset stack
; Warning here: RBFG build 22 randomly overwrites memory location
; [0x5680,0x576c), possibly more. It seems that it gets confused and
@@ -205,7 +206,6 @@ RBFG_brainfuck resb 0E00h
section .bss
alignb 4
-InitStack resd 1 ; Pointer to reset stack
RebootTime resd 1 ; Reboot timeout, if set by option
StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure
APIVer resw 1 ; PXE API version found
@@ -253,9 +253,9 @@ xbs_vgatmpbuf equ 2*trackbufsize
section .text
;
; PXELINUX needs more BSS than the other derivatives;
- ; therefore we relocate it from 7C00h on startup
+ ; therefore we relocate it from 7C00h on startup.
;
-StackBuf equ $-44 ; Base of stack if we use our own
+StackBuf equ $ ; Base of stack if we use our own
;
; Primary entry point.
@@ -411,7 +411,7 @@ old_api: ; Need to use a PXENV+ structure
mov eax,[es:bx+0Ah] ; PXE RM API
mov [PXENVEntry],eax
- mov si,undi_data_msg ; ***
+ mov si,undi_data_msg
call writestr
mov ax,[es:bx+20h]
call writehex4
@@ -466,7 +466,7 @@ have_pxe:
mov eax,[es:bx+10h]
mov [PXEEntry],eax
- mov si,undi_data_msg ; ***
+ mov si,undi_data_msg
call writestr
mov eax,[es:bx+2Ah]
call writehex8
@@ -1905,7 +1905,13 @@ unload_pxe:
jmp .call_loop
.call_done:
-%if USE_PXE_PROVIDED_STACK
+;
+; This isn't necessary anymore; we can use the memory area previously
+; used by the PXE stack indefinitely, and the chainload code sets up
+; a new stack independently. Leave the source code in here for now,
+; but expect to rip it out soonish.
+;
+%if 0 ; USE_PXE_PROVIDED_STACK
; We need to switch to our local stack here...
pusha
pushf
diff --git a/tracers.inc b/tracers.inc
index 300523a9..2f6ddace 100644
--- a/tracers.inc
+++ b/tracers.inc
@@ -21,7 +21,7 @@
%define _TRACERS_INC
; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
-; %define DEBUG_TRACERS 1 ; Uncomment to get debugging tracers
+%define DEBUG_TRACERS 1 ; Uncomment to get debugging tracers
; %define DEBUG_MESSAGES ; Uncomment to get debugging messages
%ifdef DEBUG_TRACERS
diff --git a/version b/version
index 1a5b4037..e449dd2a 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-3.06
+3.07