blob: 9e47e1a515258288b78f71c1ebdf7558830a9223 [file] [log] [blame]
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
;; Copyright 2009-2012 Intel Corporation; author: 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
;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
;; Boston 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
push word 0
jmp short load_bootsec
is_bss_sector:
; Transfer the superblock
SuperSize equ $+1
push word superblock_len_fat16
%endif
load_bootsec:
mov edi,free_high_memory
mov [trackbuf+4],edi ; Copy from this address
mov eax,0xA0000 ; Maximum load
xor dx,dx ; No padding
mov bx,abort_check ; Don't print dots, but allow abort
call load_high
sub edi,free_high_memory
mov [trackbuf+8],edi ; Save length
cmp edi,0xA0000-7C00h
ja bs_too_big
mov eax,7C00h ; Entry point
mov [trackbuf],eax ; Copy to this address
%if IS_SYSLINUX
xor ecx,ecx
pop cx
; For a BSS boot sector we have to patch.
mov esi,superblock
mov edi,free_high_memory+(superblock-bootsec)
call bcopy
%endif
push eax ; Save entry point
xor edx,edx
xor esi,esi
%if IS_SYSLINUX || IS_EXTLINUX
; Restore original FDC table
mov eax,[OrigFDCTabPtr]
mov [fdctab],eax
mov dl,[DriveNumber]
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
xor bx,bx
%elif IS_ISOLINUX
mov dl,[DriveNumber]
xor bx,bx
%elif IS_PXELINUX
mov byte [KeepPXE],03h ; Chainloading + keep PXE
pm_call reset_pxe
lfs si,[InitStack]
; Put restore DS, EDX and ESI to the true initial values
mov bx,[fs:si+6]
mov edx,[fs:si+28]
mov esi,[fs:si+12]
%endif
;
; replace_bootstrap for the special case where we have exactly one
; descriptor, based in low memory. We will generate a second descriptor
; to clear remaining FBM.
;
replace_bootstrap_one:
mov eax,[trackbuf] ; Base address
add eax,[trackbuf+8] ; Length
movzx ecx,word [BIOS_fbm]
shl ecx,10 ; Free Base Memory
sub ecx,eax
mov [trackbuf+12],eax
or dword [trackbuf+16],-1 ; Zero memory
mov [trackbuf+20],ecx
push word 2 ; Length of descriptor list
; Fall through
;
; Entrypoint for "shut down and replace bootstrap" -- also invoked by
; the COMBOOT API. This routine expects the entry point (CS, IP) and the
; count of the descriptor sequence on the stack; the shuffle
; descriptors start at the first byte of the trackbuf.
;
; The registers EDX and ESI are passed on to the called program,
; and BX is passed on as DS.
;
replace_bootstrap:
;
; Prepare for shutting down
;
call vgaclearmode
;
; We jump here when loading a kernel image, so that we don't reset
; the screen mode in "quiet" mode
;
replace_bootstrap_noclearmode:
call cleanup_hardware
;
; Set up initial stack frame (not used by PXE if keeppxe is
; set - we use the PXE stack then.)
;
xor ax,ax
mov ds,ax
mov es,ax
%if IS_PXELINUX
cmp byte [KeepPXE],0
je .stdstack
les di,[InitStack] ; Reset stack to PXE original
jmp .stackok
%endif
.stdstack:
; StackBuf is guaranteed to have 44 bytes free immediately
; above it, and it will not interfere with our existing stack.
mov di,StackBuf
push di
mov cx,22 ; 44 bytes
rep stosw
pop di
.stackok:
mov [es:di+28],edx ; New EDX
mov [es:di+12],esi ; New ESI
mov [es:di+6],bx ; New DS
%if IS_PXELINUX == 0
; DON'T DO THIS FOR PXELINUX...
; For PXE, ES:BX -> PXENV+, and this would corrupt
; that use.
; Restore ES:DI -> $PnP (if we were ourselves called
; that way...)
mov ax,[OrigESDI]
mov bx,[OrigESDI+2]
mov [es:di+8],ax ; New DI
mov [es:di+4],bx ; New ES
%endif
pop ax ; descriptor list entries count
push di
push es
push ds
pop es
mov ebx,trackbuf
imul di,ax,12
push di ; length of list
add di,bx ; DI <- end of list
; Terminating entry...
lea eax,[replace_stub] ; Entrypoint
push ax
stosd
xor ax,ax ; EAX[31:16] == 0 already
stosd ; 16-bit mode
stosd ; End of list
; Copy the stub
pop di
mov si,__replacestub_lma
mov cx,__replacestub_dwords
rep movsd
; ECX <- final list length
xor ecx,ecx
pop cx ; original length in bytes
add cx, 12 ; + termination entry size
pop word [replace_stub.ss]
pop word [replace_stub.esp]
pop dword [replace_stub.csip]
cli
mov ss,[replace_stub.ss]
mov esp,[replace_stub.esp]
mov edi,trackbuf
mov esi,edi
jmp shuffle_and_boot_raw
; This stub gets run after the shuffle. It is copied
; below 0x7c00 in order to properly handle the case
; of bootstrap replacement.
section .replacestub
replace_stub:
mov cr0,eax
jmp 0:.next
.next:
mov ax,strict word 0
.ss equ $-2
mov ss,ax
mov esp,strict dword 0
.esp equ $-4
pop gs
pop fs
pop es
pop ds
popad
popfd
jmp 0:0
.csip equ $-4
section .text16
bs_too_big:
call close
mov si,err_bs_too_big
jmp abort_load
section .data16
err_bs_too_big db "Too large for a bootstrap (need LINUX instead of KERNEL?)"
db CR, LF, 0
section .text16