From: hpa Date: Wed, 26 Nov 2003 05:42:33 +0000 (+0000) Subject: Add a bootstrap chainloading API, and include a sample program for it. X-Git-Tag: syslinux-3.11~492 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=df2322b51c6ffd9e4a05b225c5c4ba44b09d3e75;p=platform%2Fupstream%2Fsyslinux.git Add a bootstrap chainloading API, and include a sample program for it. --- diff --git a/NEWS b/NEWS index 236ba35..d4e31a3 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 24ebab6..f0dc260 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 5d1a954..768bf3c 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 c8dbff1..e421d67 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 ad1c324..57488cb 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 9bbaab9..13b9b36 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 7b16811..d53924b 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 0bd4512..900acbd 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 0000000..03e13d1 --- /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 +#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; +} + + +