diff options
author | hpa <hpa> | 2005-01-12 00:34:54 +0000 |
---|---|---|
committer | hpa <hpa> | 2005-01-12 00:34:54 +0000 |
commit | 25ac97ff571bf6b5891921f6e5f1b6f45806314a (patch) | |
tree | bd4dc3873d43dfd03e0312d229c61a5256f12c12 | |
parent | a740cb88107937fe0758aa6e520fb4cc552157fc (diff) | |
download | syslinux-25ac97ff571bf6b5891921f6e5f1b6f45806314a.tar.gz |
3.07: Fix chainloading
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | bootsect.inc | 12 | ||||
-rw-r--r-- | com32/modules/chain.c | 136 | ||||
-rw-r--r-- | comboot.inc | 5 | ||||
-rw-r--r-- | pxelinux.asm | 20 | ||||
-rw-r--r-- | tracers.inc | 2 | ||||
-rw-r--r-- | version | 2 |
7 files changed, 104 insertions, 76 deletions
@@ -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 @@ -1 +1 @@ -3.06 +3.07 |