3.07: Fix chainloading
authorhpa <hpa>
Wed, 12 Jan 2005 00:34:54 +0000 (00:34 +0000)
committerhpa <hpa>
Wed, 12 Jan 2005 00:34:54 +0000 (00:34 +0000)
NEWS
bootsect.inc
com32/modules/chain.c
comboot.inc
pxelinux.asm
tracers.inc
version

diff --git a/NEWS b/NEWS
index c0c820d..f9ce8f5 100644 (file)
--- 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.
 
index 67ce676..f22e845 100644 (file)
@@ -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
index eea48f1..0a52f13 100644 (file)
@@ -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;
index 83b57f4..d8a55a8 100644 (file)
@@ -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
 ;
index 2b3a811..e8c3806 100644 (file)
@@ -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
index 300523a..2f6ddac 100644 (file)
@@ -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 1a5b403..e449dd2 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-3.06
+3.07