From 3e012b34a2eac374cd3db4c74657fb059d357536 Mon Sep 17 00:00:00 2001 From: hpa Date: Sun, 28 Apr 2002 00:32:34 +0000 Subject: [PATCH] Generalize and factor out bootsector-generation code. --- NEWS | 3 ++ bcopy32.inc | 51 +++++++++++++++++++++++------ bootsect.inc | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ comboot.inc | 18 +++++------ isolinux.asm | 21 ++++++------ ldlinux.asm | 74 +++++++----------------------------------- loadhigh.inc | 1 - pxelinux.asm | 25 +++++++++----- runkernel.inc | 5 +-- 9 files changed, 196 insertions(+), 104 deletions(-) create mode 100644 bootsect.inc diff --git a/NEWS b/NEWS index 91ad69d..94a35b7 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ apply to that specific program only; other changes apply to both. Changes in 1.73: * Work on removing gratuitous differences between modules. * Break up the source in common and module-specific files. + * PXELINUX: Allow chaining of other PXE NBPs. + * ISOLINUX: Allow loading "CD-ROM boot sectors". + * ALL: generalize the definition of a boot sector/NBP. Changes in 1.72: * PXELINUX, ISOLINUX: Fix bugs in the new core code. diff --git a/bcopy32.inc b/bcopy32.inc index daa061e..4910fbb 100644 --- a/bcopy32.inc +++ b/bcopy32.inc @@ -45,6 +45,21 @@ bcopy_gdt: dw bcopy_gdt_size-1 ; Null descriptor - contains GDT dd 00009300h ; present, dpl 0, cover 64K bcopy_gdt_size: equ $-bcopy_gdt +; +; bcopy: +; 32-bit copy +; +; Inputs: +; ESI - source pointer +; EDI - target pointer +; ECX - byte count +; DF - zero +; +; Outputs: +; ESI - first byte after source +; EDI - first byte after target +; ECX - zero +; bcopy: push eax pushf ; Saves, among others, the IF flag push gs @@ -72,8 +87,19 @@ bcopy: push eax mov ss,ax mov fs,ax mov gs,ax - + + mov al,cl ; Save low bits + shr ecx,2 ; Convert to dwords a32 rep movsd ; Do our business + + test al,2 + jz .noword + a32 movsw +.noword: + test al,1 + jz .nobyte + a32 movsb +.nobyte: mov es,ax ; Set to "real-mode-like" mov ds,ax @@ -350,10 +376,15 @@ try_wbinvd: ; After performing the copy, this routine resets the stack and ; jumps to 0:7c00. ; +; IMPORTANT: This routine does not canonicalize the stack or the +; SS register. That is the responsibility of the caller. +; ; Inputs: ; ESI, EDI, ECX - same as bcopy ; EDX - edx on invocation ; EAX - esi on invocation +; EBX - ebx on invocation +; ES - es on invocation ; %define ADJUST (__bcopy_start - trackbuf) @@ -366,20 +397,20 @@ adjlist dw bcopy_gdt.adj1 - ADJUST adjlist_cnt equ ($-adjlist)/2 bcopy_over_self: - cli - cld - xor bx,bx - mov ds,bx - mov es,bx - mov ss,bx - mov sp,7c00h - + push es + push ebx push eax push edx push esi push edi push ecx + xor bx,bx + mov es,bx + mov ds,bx + mov fs,bx + mov gs,bx + mov si,__bcopy_start mov di,trackbuf mov cx,(__bcopy_end - __bcopy_start + 3) >> 2 @@ -410,5 +441,7 @@ bcopy_over_self: pop edx pop esi + pop ebx + pop es jmp 0:7c00h __bcopy_end: diff --git a/bootsect.inc b/bootsect.inc new file mode 100644 index 0000000..4546eda --- /dev/null +++ b/bootsect.inc @@ -0,0 +1,102 @@ +;; $Id$ +;; ----------------------------------------------------------------------- +;; +;; Copyright 1994-2002 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. +;; +;; ----------------------------------------------------------------------- + +;; +;; bootsect.inc +;; +;; Load a boot sector (or other bootstrap program.) +;; +;; Unlike previous versions of this software, this doesn't require that +;; the length is 512 bytes. This allows PXE bootstraps and WinNT +;; "CD boot sectors" to be invoked. +;; + +; +; Load a boot sector +; +is_bootsector: +%if IS_SYSLINUX + ; Transfer zero bytes + xor cx,cx + jmp short load_bootsec +is_bss_sector: + ; Transfer the superblock + mov cx,superblock_len +load_bootsec: + push cx +%endif + xchg dx,ax + shr eax,16 + xchg dx,ax ; Now EAX = file length + mov edi, 100000h + call load_high + +%if IS_SYSLINUX + pop cx +%endif + + sub edi,100000h + push edi ; Save length + +%if IS_SYSLINUX + 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 +%if IS_SYSLINUX + mov dl,[bsDriveNumber] + + mov si,PartInfo + mov di,800h-18 ; Put partition info here + push di + mov cx,8 ; 16 bytes + rep movsw + pop ax ; DS:SI points to partition info +%elif IS_ISOLINUX + mov dl,[DriveNo] +%endif + + mov esi,7C00h + mov edi,100000h + pop ecx ; Byte count + + cli + xor ebx,ebx + mov ds,bx +%if IS_PXELINUX + lss sp,[Stack] ; Reset stack to PXE original + les bx,[InitESBX] ; ES:BX -> PXENV+ +%else + mov es,bx + mov esp,esi +%endif + jmp bcopy_over_self + +%if IS_SYSLINUX = 0 +is_bss_image: + mov si,err_bssimage + call cwritestr + jmp enter_command +%endif diff --git a/comboot.inc b/comboot.inc index db19914..fbda097 100644 --- a/comboot.inc +++ b/comboot.inc @@ -17,6 +17,12 @@ ;; Common code for running a COMBOOT image ;; +; Looks like a COMBOOT image but too large +comboot_too_large: + mov si,err_comlarge + call cwritestr +cb_enter: jmp enter_command + ; ; Load a COMBOOT image. A COMBOOT image is basically a DOS .COM file, ; except that it may, of course, not contain any DOS system calls. We @@ -24,7 +30,7 @@ ; is_comboot_image: and dx,dx - jnz near comboot_too_large + jnz comboot_too_large cmp ax,0ff00h ; Max size in bytes jae comboot_too_large @@ -86,12 +92,6 @@ comboot_end_cmd: mov al,0Dh ; CR after last character jmp comboot_seg:100h ; Run it -; Looks like a COMBOOT image but too large -comboot_too_large: - mov si,err_comlarge - call cwritestr -cb_enter: jmp enter_command - ; Proper return vector comboot_return: cli ; Don't trust anyone lss sp,[cs:SavedSSSP] @@ -99,7 +99,7 @@ comboot_return: cli ; Don't trust anyone mov es,ax sti cld - jmp short cb_enter + jmp cb_enter ; Attempted to execute DOS system call comboot_bogus: cli ; Don't trust anyone @@ -112,5 +112,5 @@ comboot_bogus: cli ; Don't trust anyone call cwritestr mov si,err_notdos call cwritestr - jmp short cb_enter + jmp cb_enter diff --git a/isolinux.asm b/isolinux.asm index f560e11..d9e6682 100644 --- a/isolinux.asm +++ b/isolinux.asm @@ -1194,9 +1194,11 @@ kernel_corrupt: mov si,err_notkernel ; ; .com - COMBOOT image ; .cbt - COMBOOT image -; .bs - Boot sector (SYSLINUX only) -; .bss - DOS boot sector (SYSLINUX only) -; .img - Disk image (ISOLINUX only) +; .bs - Boot sector +; .0 - PXE bootstrap program (PXELINUX only) +; .bin - Boot sector +; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only) +; .img - Floppy image (ISOLINUX only) ; ; Anything else is assumed to be a Linux kernel. ; @@ -1234,10 +1236,12 @@ kernel_good: cmp ecx,'.img' je near is_disk_image cmp ecx,'.bss' - je near is_bss_sector + je near is_bss_image and ecx, 00ffffffh cmp ecx,'.bs' je near is_bootsector + cmp cx,'.0' + je near is_bootsector ; Otherwise Linux kernel ; @@ -1251,12 +1255,9 @@ kernel_good: %include "comboot.inc" ; -; Load a boot sector +; Boot sector loading code ; -is_bootsector: -is_bss_sector: - ; Can't load these from the network, dang it! -.badness: jmp short .badness +%include "bootsect.inc" ; ; Enable disk emulation. The kind of disk we emulate is dependent on the size of @@ -1911,7 +1912,7 @@ err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' db CR, LF, 0 err_notdos db ': attempted DOS system call', CR, LF, 0 err_comlarge db 'COMBOOT image too large.', CR, LF, 0 -err_bootsec db 'Invalid or corrupt boot sector image.', CR, LF, 0 +err_bssimage db 'BSS images not supported.', CR, LF, 0 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 notfound_msg db 'not found', CR, LF, 0 localboot_msg db 'Booting from local disk...', CR, LF, 0 diff --git a/ldlinux.asm b/ldlinux.asm index af4243a..ec8157d 100644 --- a/ldlinux.asm +++ b/ldlinux.asm @@ -1345,10 +1345,13 @@ kernel_corrupt: mov si,err_notkernel ; that decision on the file extension. The following extensions are ; recognized: ; -; .COM - COMBOOT image -; .CBT - COMBOOT image -; .BS - Boot sector -; .BSS - Boot sector, but transfer over DOS superblock +; .com - COMBOOT image +; .cbt - COMBOOT image +; .bs - Boot sector +; .0 - PXE bootstrap program (PXELINUX only) +; .bin - Boot sector +; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only) +; .img - Floppy image (ISOLINUX only) ; ; Anything else is assumed to be a Linux kernel. ; @@ -1368,6 +1371,8 @@ kernel_good: je near is_comboot_image cmp ecx,'BS ' je near is_bootsector + cmp ecx,'BIN' + je near is_bootsector cmp ecx,'BSS' je near is_bss_sector ; Otherwise Linux kernel @@ -1383,65 +1388,9 @@ kernel_good: %include "comboot.inc" ; -; Load a boot sector -; -is_bootsector: - ; Transfer zero bytes - push word 0 - jmp short load_bootsec -is_bss_sector: - ; Transfer the superblock - push word superblock_len -load_bootsec: - and dx,dx - jnz bad_bootsec - mov bx,[bsBytesPerSec] - cmp ax,bx - jne bad_bootsec - - ; Make sure we don't test this uninitialized - mov [bx+trackbuf-2],dx ; Note DX == 0 - - mov bx,trackbuf - mov cx,1 ; 1 cluster >= 1 sector - call getfssec - - mov bx,[bsBytesPerSec] - mov ax,[bx+trackbuf-2] - cmp ax,0AA55h ; Boot sector signature - jne bad_bootsec - - mov si,superblock - mov di,trackbuf+(superblock-bootsec) - pop cx ; Transfer count - rep movsb +; Boot sector loading code ; -; Okay, here we go... copy over our own boot sector and run the new one -; - call vgaclearmode ; Reset video - - cli ; Point of no return - - mov dl,[bsDriveNumber] ; May not be in new bootsector! - - mov si,trackbuf - mov di,bootsec - mov cx,[bsBytesPerSec] - rep movsb ; Copy the boot sector! - - mov si,PartInfo - mov di,800h-18 ; Put partition info here - push di - mov cx,8 ; 16 bytes - rep movsw - pop si ; DS:SI points to partition info - - jmp bootsec - -bad_bootsec: - mov si,err_bootsec - call cwritestr - jmp enter_command +%include "bootsect.inc" ; ; abort_check: let the user abort with or @@ -1774,7 +1723,6 @@ err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' db CR, LF, 0 err_notdos db ': attempted DOS system call', CR, LF, 0 err_comlarge db 'COMBOOT image too large.', CR, LF, 0 -err_bootsec db 'Invalid or corrupt boot sector image.', CR, LF, 0 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 err_bootfailed db CR, LF, 'Boot failed: please change disks and press ' db 'a key to continue.', CR, LF, 0 diff --git a/loadhigh.inc b/loadhigh.inc index c952ae8..a7757a7 100644 --- a/loadhigh.inc +++ b/loadhigh.inc @@ -80,7 +80,6 @@ load_high: inc ecx jmp short .fix_slop .noslop: - shr ecx,2 ; Convert to dwords push esi ; File handle/cluster pointer mov esi,(xfer_buf_seg << 4) ; Source address call bcopy ; Copy to high memory diff --git a/pxelinux.asm b/pxelinux.asm index 8c83fac..3d1da26 100644 --- a/pxelinux.asm +++ b/pxelinux.asm @@ -198,6 +198,7 @@ RamdiskMax resd 1 ; Highest address for a ramdisk KernelSize resd 1 ; Size of kernel (bytes) SavedSSSP resd 1 ; Our SS:SP while running a COMBOOT image Stack resd 1 ; Pointer to reset stack +InitESBX resd 1 ; Initial ES:BX pointer PXEEntry resd 1 ; !PXE API entry point RebootTime resd 1 ; Reboot timeout, if set by option KernelClust resd 1 ; Kernel size in clusters @@ -275,6 +276,10 @@ _start1: push fs push gs + mov [cs:InitESBX],bx + mov bx,es + mov [cs:InitESBX+2],bx + mov bp,sp les bx,[bp+48] ; Initial !PXE structure pointer @@ -1111,7 +1116,10 @@ kernel_corrupt: mov si,err_notkernel ; .com - COMBOOT image ; .cbt - COMBOOT image ; .bs - Boot sector -; .bss - Boot sector, but transfer over DOS superblock +; .0 - PXE bootstrap program (PXELINUX only) +; .bin - Boot sector +; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only) +; .img - Floppy image (ISOLINUX only) ; ; Boot sectors are currently not supported by PXELINUX. ; @@ -1145,10 +1153,14 @@ kernel_good: cmp ecx,'.cbt' je near is_comboot_image cmp ecx,'.bss' - je near is_bss_sector + je near is_bss_image + cmp ecx,'.bin' + je near is_bootsector and ecx, 00ffffffh cmp ecx,'.bs' je near is_bootsector + cmp cx,'.0' + je near is_bootsector ; Otherwise Linux kernel ; ; Linux kernel loading code is common. However, we need to define @@ -1187,12 +1199,9 @@ kernel_good: %include "comboot.inc" ; -; Load a boot sector +; Boot sector loading code ; -is_bootsector: -is_bss_sector: - ; Can't load these from the network, dang it! -.badness: jmp short .badness +%include "bootsect.inc" ; ; Boot to the local disk by returning the appropriate PXE magic. @@ -2327,7 +2336,7 @@ err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' db CR, LF, 0 err_notdos db ': attempted DOS system call', CR, LF, 0 err_comlarge db 'COMBOOT image too large.', CR, LF, 0 -err_bootsec db 'Invalid or corrupt boot sector image.', CR, LF, 0 +err_bssimage db 'BSS images not supported.', CR, LF, 0 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 err_bootfailed db CR, LF, 'Boot failed: press a key to retry, or wait for reset...', CR, LF, 0 bailmsg equ err_bootfailed diff --git a/runkernel.inc b/runkernel.inc index cc1dfb1..1240444 100644 --- a/runkernel.inc +++ b/runkernel.inc @@ -44,7 +44,7 @@ ; is_linux_kernel: cmp dx,80h ; 8 megs - ja kernel_corrupt + ja near kernel_corrupt and dx,dx jnz kernel_sane cmp ax,1024 ; Bootsect + 1 setup sect @@ -323,7 +323,6 @@ read_kernel: mov ecx,8000h ; 32K sub ecx,esi ; Number of bytes to copy push ecx - shr ecx,2 ; Convert to dwords add esi,(real_mode_seg << 4) ; Pointer to source mov edi,100000h ; Copy to address 100000h call bcopy ; Transfer to high memory @@ -489,8 +488,6 @@ need_high_cmdline: ; Copy the kernel down to the "low" location ; mov ecx,[KernelSize] - add ecx,3 ; Round upwards - shr ecx,2 ; Bytes -> dwords mov esi,100000h mov edi,10000h call bcopy -- 2.7.4