summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2003-11-26 05:42:33 +0000
committerhpa <hpa>2003-11-26 05:42:33 +0000
commitdf2322b51c6ffd9e4a05b225c5c4ba44b09d3e75 (patch)
tree2e837e97013969748192fddd5bac9515e6b2596d
parent0fab936237d1b5fb713f291dfe6aa7c342c7d246 (diff)
downloadsyslinux-df2322b51c6ffd9e4a05b225c5c4ba44b09d3e75.tar.gz
Add a bootstrap chainloading API, and include a sample program for it.syslinux-2.08-pre5
-rw-r--r--NEWS3
-rw-r--r--bootsect.inc91
-rw-r--r--comboot.doc27
-rw-r--r--comboot.inc16
-rw-r--r--isolinux.asm6
-rw-r--r--ldlinux.asm4
-rw-r--r--pxelinux.asm3
-rw-r--r--sample/Makefile2
-rw-r--r--sample/fd.c63
9 files changed, 177 insertions, 38 deletions
diff --git a/NEWS b/NEWS
index 236ba35d..d4e31a3a 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,9 @@ Changes in 2.08:
(including file not found.) This bug would cause us to run
out of sockets and thus "go deaf" after a while.
* MEMDISK: Add an API to query for the existence of MEMDISK.
+ * SYSLINUX: Fix loading boot sectors (.bs/.bss) from floppy
+ disk.
+ * .c32 is now one of the extensions searched for automatically.
Changes in 2.07:
* MEMDISK: Workaround for BIOSes which go into a snit when
diff --git a/bootsect.inc b/bootsect.inc
index 24ebab6e..f0dc260f 100644
--- a/bootsect.inc
+++ b/bootsect.inc
@@ -27,81 +27,106 @@
is_bootsector:
%if IS_SYSLINUX || IS_MDSLINUX
; Transfer zero bytes
- xor cx,cx
+ mov byte [CopySuper],0
jmp short load_bootsec
+
is_bss_sector:
; Transfer the superblock
- mov cx,superblock_len
-load_bootsec:
- push cx
+ mov byte [CopySuper],superblock_len
%endif
+load_bootsec:
xchg dx,ax
shl eax,16
xchg dx,ax ; Now EAX = file length
mov edi, 100000h
+ push edi ; Save load address
call load_high
call crlf
-%if IS_SYSLINUX || IS_MDSLINUX
- pop cx
-%endif
-
sub edi,100000h
push edi ; Save length
%if IS_SYSLINUX || IS_MDSLINUX
+ movzx ecx,byte [CopySuper]
jcxz .not_bss
; For a BSS boot sector we have to patch.
mov esi,superblock
mov edi,100000h+(superblock-bootsec)
- movzx ecx,cx
call bcopy
.not_bss:
%endif
-;
-; Prepare for shutting down
-;
- call vgaclearmode
+
xor edx,edx
- xor eax,eax
+ xor esi,esi
%if IS_SYSLINUX || IS_MDSLINUX
- mov dl,[bsDriveNumber]
+ ; Restore original FDC table
+ mov eax,[OrigFDCTabPtr]
+ mov [fdctab],eax
- mov si,PartInfo
+ mov dl,[bsDriveNumber]
+ mov si,PartInfo ; Partition info buffer
mov di,800h-18 ; Put partition info here
push di
mov cx,8 ; 16 bytes
+ xor ax,ax
rep movsw
pop si ; DS:SI points to partition info
%elif IS_ISOLINUX
mov dl,[DriveNo]
%elif IS_PXELINUX
- ; Close the UDP stack so the PXE stack is in a known state for
- ; the new NBP
+ mov byte [KeepPXE],1 ; Chainloading another NBP
call reset_pxe
%endif
+ xor bx,bx
- pop ecx ; Byte count to copy
+;
+; Entrypoint for "shut down and replace bootstrap" -- also invoked by
+; the COMBOOT API. This routine expects two dword on the stack:
+; linear address and length. Additionally, the values of ESI and EDX
+; are passed on to the new bootstrap; the value of BX becomes the new
+; DS.
+;
+replace_bootstrap:
+
+ ;
+ ; Prepare for shutting down
+ ;
+ call vgaclearmode
+
+ ;
+ ; Set up initial stack frame (not used by PXE if keeppxe is set)
+ ;
+ xor ax,ax
+ mov ds,ax
+ mov es,ax
- cli
- xor ebx,ebx
- mov ds,bx
- mov es,bx
%if IS_PXELINUX
- lss sp,[InitStack] ; Reset stack to PXE original
-%else
- mov esp,7C00h
- pushfd
- pushad
- push bx ; ds
- push bx ; es
- push bx ; fs
- push bx ; gs
+ test byte [KeepPXE],01h
+ jz .stdstack
+ les di,[InitStack] ; Reset stack to PXE original
+ jmp .stackok
%endif
+.stdstack:
+ mov di,7C00h-44
+ push di
+ mov cx,22 ; 44 bytes
+ rep stosw
+ pop di
+.stackok:
+
+ mov [es:di+28],edx
+ mov [es:di+12],esi
+ mov [es:di+6],bx
- mov esi,100000h ; Copy from...
+ pop ecx ; Byte count to copy
+ pop esi ; Copy from...
+
+ cli
+ mov ax,es
+ mov ss,ax
+ movzx esp,di
mov edi,7C00h ; Copy to...
jmp bcopy_over_self
diff --git a/comboot.doc b/comboot.doc
index 5d1a9547..768bf3c3 100644
--- a/comboot.doc
+++ b/comboot.doc
@@ -439,7 +439,7 @@ AX=000Ch Perform final cleanup
MAKE SURE TO DISABLE INTERRUPTS, AND INSTALL NEW GDT AND IDTS
BEFORE OVERWRITING THESE MEMORY AREAS.
- The permissible values for DX are as follows:
+ The permissible values for DX is an OR of these values:
SYSLINUX: 0000h Normal cleanup
@@ -450,3 +450,28 @@ AX=000Ch Perform final cleanup
All other values are undefined, and may have different
meanings in future versions of SYSLINUX.
+
+
+AX=000Dh Cleanup and replace bootstrap code
+ Input: AX 000Ch
+ DX derivative-specific flags (see previous function)
+ EDI bootstrap code (linear address, can be in high memory)
+ ECX bootstrap code length in bytes (max
+ EBX(!) initial value of EDX after bootstrap
+ ESI initial value of ESI after bootstrap
+ DS initial value of DS after bootstrap
+ Output: None
+
+ This routine performs final cleanup, then takes a piece of
+ code, copies it over the primary bootstrap at address 7C00h,
+ and jumps to it. This can be used to chainload boot sectors,
+ MBRs, bootstraps, etc.
+
+ Normal boot sectors expect DL to contain the drive number,
+ and, for hard drives (DL >= 80h) DS:SI to contain a pointer to
+ the 16-byte partition table entry. The memory between
+ 600h-7FFh is available to put the partition table entry in.
+
+ For PXELINUX, if the PXE stack is not unloaded, all registers
+ (except DS, ESI and EDX) and the stack will be set up as they
+ were set up by the PXE ROM.
diff --git a/comboot.inc b/comboot.inc
index c8dbff11..e421d67f 100644
--- a/comboot.inc
+++ b/comboot.inc
@@ -518,7 +518,9 @@ comapi_cleanup:
; Unload PXE if requested
test dl,3
setnz [KeepPXE]
+ sub bp,sp ; unload_pxe may move the stack around
call unload_pxe
+ add bp,sp ; restore frame pointer...
%elif IS_SYSLINUX || IS_MDSLINUX
; Restore original FDC table
mov eax,[OrigFDCTabPtr]
@@ -531,6 +533,19 @@ comapi_cleanup:
clc
ret
+
+;
+; INT 22h AX=000Dh Clean up then replace bootstrap
+;
+comapi_chainboot:
+ call comapi_cleanup
+ mov esi,P_ESI
+ mov edx,P_EBX
+ mov bx,P_DS
+ push P_EDI
+ push P_ECX
+ jmp replace_bootstrap
+
;
; This stuff should really be in the data section...
;
@@ -567,6 +582,7 @@ int22_table:
dw comapi_derinfo ; 000A derivative-specific info
dw comapi_serialcfg ; 000B get serial port config
dw comapi_cleanup ; 000C perform final cleanup
+ dw comapi_chainboot ; 000D clean up then bootstrap
int22_count equ ($-int22_table)/2
APIKeyWait db 0
diff --git a/isolinux.asm b/isolinux.asm
index ad1c3240..57488cb7 100644
--- a/isolinux.asm
+++ b/isolinux.asm
@@ -224,6 +224,9 @@ Files resb MAX_OPEN*open_file_t_size
;; loading the rest.
;;
bootsec equ $
+
+StackBuf equ $-44
+
_start: ; Far jump makes sure we canonicalize the address
cli
jmp 0:_start1
@@ -241,7 +244,7 @@ _start1: mov [cs:InitStack],sp ; Save initial stack pointer
mov [cs:InitStack+2],ss
xor ax,ax
mov ss,ax
- mov sp,_start ; Set up stack
+ mov sp,StackBuf ; Set up stack
mov ds,ax
mov es,ax
mov fs,ax
@@ -1578,6 +1581,7 @@ exten_table: db '.cbt' ; COMBOOT (specific)
db '.img' ; Disk image
db '.bin' ; CD boot sector
db '.com' ; COMBOOT (same as DOS)
+ db '.c32' ; COM32
exten_table_end:
dd 0, 0 ; Need 8 null bytes here
diff --git a/ldlinux.asm b/ldlinux.asm
index 9bbaab9f..13b9b36d 100644
--- a/ldlinux.asm
+++ b/ldlinux.asm
@@ -201,6 +201,7 @@ LoadFlags resb 1 ; Loadflags from kernel
A20Tries resb 1 ; Times until giving up on A20
FuncFlag resb 1 ; Escape sequences received from keyboard
DisplayMask resb 1 ; Display modes mask
+CopySuper resb 1 ; Distinguish .bs versus .bss
MNameBuf resb 11 ; Generic mangled file name buffer
InitRD resb 11 ; initrd= mangled name
KernelCName resb 13 ; Unmangled kernel name
@@ -217,7 +218,7 @@ VGAFileMBuf resb 11 ; Mangled VGA image name
; "close" to the initial stack pointer offset, in order to
; reduce the code size...
;
-StackBuf equ $-32 ; Start the stack here (grow down - 4K)
+StackBuf equ $-44-32 ; Start the stack here (grow down - 4K)
PartInfo equ StackBuf ; Saved partition table entry
FloppyTable equ PartInfo+16 ; Floppy info table (must follow PartInfo)
OrigFDCTabPtr equ StackBuf-4 ; The high dword on the stack
@@ -1421,6 +1422,7 @@ exten_table: db 'CBT',0 ; COMBOOT (specific)
db 'BSS',0 ; Boot Sector (add superblock)
db 'BS ',0 ; Boot Sector
db 'COM',0 ; COMBOOT (same as DOS)
+ db 'C32',0 ; COM32
exten_table_end:
dd 0, 0 ; Need 8 null bytes here
diff --git a/pxelinux.asm b/pxelinux.asm
index 7b168119..d53924bb 100644
--- a/pxelinux.asm
+++ b/pxelinux.asm
@@ -310,7 +310,7 @@ packet_buf_size equ $-packet_buf
section .text
org 7C00h
-StackBuf equ $ ; Base of stack if we use our own
+StackBuf equ $-44 ; Base of stack if we use our own
;
; Primary entry point.
@@ -2432,6 +2432,7 @@ bootif_str_len equ $-bootif_str
exten_table: db '.cbt' ; COMBOOT (specific)
db '.0', 0, 0 ; PXE bootstrap program
db '.com' ; COMBOOT (same as DOS)
+ db '.c32' ; COM32
exten_table_end:
dd 0, 0 ; Need 8 null bytes here
diff --git a/sample/Makefile b/sample/Makefile
index 0bd4512f..900acbd6 100644
--- a/sample/Makefile
+++ b/sample/Makefile
@@ -31,7 +31,7 @@ LIBOBJS = conio.o
.SUFFIXES: .lss .c .o .elf .c32
-all: syslogo.lss comecho.com hello.c32 hello2.c32 filetest.c32 c32echo.c32
+all: syslogo.lss comecho.com hello.c32 hello2.c32 filetest.c32 c32echo.c32 fd.c32
%.o: %.S
$(CC) $(SFLAGS) -c -o $@ $<
diff --git a/sample/fd.c b/sample/fd.c
new file mode 100644
index 00000000..03e13d1a
--- /dev/null
+++ b/sample/fd.c
@@ -0,0 +1,63 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003 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
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * fd.c
+ *
+ * Chainload a floppy disk (currently rather braindead.)
+ */
+
+#include <com32.h>
+#define NULL ((void *)0)
+
+int printf(const char *, ...);
+unsigned int atou(const char *);
+
+int __start(void)
+{
+ int whichfd = atou(__com32.cs_cmdline);
+ static com32sys_t inreg, outreg; /* In bss, so zeroed automatically */
+ int retry;
+
+ for ( retry = 0 ; retry < 6 ; retry++ ) {
+ printf(">");
+ inreg.eax.w[0] = 0x0201; /* Read one sector */
+ inreg.ecx.w[0] = 0x0001; /* Cyl 0 sector 1 */
+ inreg.edx.b[1] = 0; /* Head 0 */
+ inreg.edx.b[0] = whichfd; /* Drive number */
+ inreg.es = SEG(__com32.cs_bounce); /* Read into the bounce buffer */
+ inreg.ebx.w[0] = OFFS(__com32.cs_bounce);
+ __com32.cs_intcall(0x13, &inreg, &outreg);
+
+ if ( (outreg.eflags.l & 1) == 0 )
+ break;
+ }
+
+ if ( (outreg.eflags.l & 1) == 0 ) {
+ printf("!\n");
+ inreg.eax.w[0] = 0x000d;
+ inreg.edx.w[0] = 0;
+ inreg.edi.l = (uint32_t) __com32.cs_bounce;
+ inreg.ecx.l = 512;
+ inreg.ebx.l = whichfd & 0xff;
+ inreg.esi.l = 0; /* No partitions */
+ inreg.ds = 0; /* No partitions */
+ __com32.cs_intcall(0x22, &inreg, NULL);
+ }
+
+ /* If we get here, badness happened */
+ return 255;
+}
+
+
+