aboutsummaryrefslogtreecommitdiffstats
path: root/core/bootsect.inc
blob: 515f1f5ec778fd816076eff0b796b6dbfe51e8a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
;; -----------------------------------------------------------------------
;;
;;   Copyright 1994-2009 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,
;;   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 || IS_MDSLINUX
		; 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,100000h
		mov [trackbuf+4],edi	; Copy from this address
		xor dx,dx		; No padding
		mov bx,abort_check	; Don't print dots, but allow abort
		call load_high

		sub edi,100000h
		mov [trackbuf+8],edi	; Save length

		mov eax,7C00h		; Entry point
		mov [trackbuf],eax	; Copy to this address

%if IS_SYSLINUX || IS_MDSLINUX
		xor ecx,ecx
		pop cx

		; For a BSS boot sector we have to patch.
		mov esi,superblock
		mov edi,100000h+(superblock-bootsec)
		call bcopy
%endif
		push eax		; Save entry point

		xor edx,edx
		xor esi,esi
%if IS_SYSLINUX || IS_MDSLINUX || 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
%elif IS_ISOLINUX
		mov dl,[DriveNumber]
%elif IS_PXELINUX
		mov byte [KeepPXE],03h	; Chainloading + keep PXE
		call reset_pxe
%endif
		xor bx,bx

;
; replace_bootstrap for the special case where we have exactly one
; descriptor.
;

replace_bootstrap_one:
		push word 1			; 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
		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
		test byte [KeepPXE],02h	; Bit 1 = chainloading PXE
		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	; 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			; List length

		push di
		push es

		push ds
		pop es

		mov ebx,trackbuf
		imul di,ax,12
		add di,bx		; DI <- end of list

		; Terminating entry...
		lea eax,[di+12]
		stosd
		xor ax,ax		; EAX[31:16] == 0 already
		stosd			; Real mode
		stosd			; End of list

		; Copy the stub	
		mov si,replace_stub
		mov cx,replace_stub.len >> 2
		rep movsd
		
		pop word [di+replace_stub.ss]
		pop word [di+replace_stub.esp]
		pop dword [di+replace_stub.csip]

		movzx edx,di		; "Safe area"

		cli
		mov ss,[di+replace_stub.ss]
		mov esp,[di+replace_stub.esp]

		jmp shuffle_and_boot_raw

		; This stub gets run after the shuffle, but not in-place.
		; THE ALIGNS ARE CRITICAL.
		align 4
replace_stub:
		mov ax,strict word 0
.ss		equ $-2-.end
		mov ss,ax
		mov esp,strict dword 0
.esp:		equ $-4-.end
		pop gs
		pop fs
		pop es
		pop ds
		popad
		popfd
		jmp 0:0
.csip		equ $-4-.end
		align 4
.end:
.len		equ $-replace_stub