|
@@ -6,6 +6,10 @@
|
6
|
6
|
* table so using a noticeable amount of stack space is a no-no.
|
7
|
7
|
*/
|
8
|
8
|
|
|
9
|
+#define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
|
|
10
|
+#define PMM_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'M' << 16 ) + ( 'M' << 24 ) )
|
|
11
|
+#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
|
|
12
|
+
|
9
|
13
|
.text
|
10
|
14
|
.code16
|
11
|
15
|
.arch i386
|
|
@@ -15,7 +19,9 @@
|
15
|
19
|
romheader:
|
16
|
20
|
.word 0xAA55 /* BIOS extension signature */
|
17
|
21
|
romheader_size: .byte _load_size_sect /* Size in 512-byte blocks */
|
18
|
|
- jmp init_vector /* Initialisation vector */
|
|
22
|
+ jmp init /* Initialisation vector */
|
|
23
|
+checksum:
|
|
24
|
+ .byte 0
|
19
|
25
|
.org 0x16
|
20
|
26
|
.word undiheader
|
21
|
27
|
.org 0x18
|
|
@@ -72,7 +78,7 @@ pnpheader:
|
72
|
78
|
.byte 0x54 /* Device indicator */
|
73
|
79
|
.word 0x0000 /* Boot connection vector */
|
74
|
80
|
.word 0x0000 /* Disconnect vector */
|
75
|
|
- .word exec_vector /* Boot execution vector */
|
|
81
|
+ .word bev_entry /* Boot execution vector */
|
76
|
82
|
.word 0x0000 /* Reserved */
|
77
|
83
|
.word 0x0000 /* Static resource information vector*/
|
78
|
84
|
.equ pnpheader_len, . - pnpheader
|
|
@@ -98,60 +104,180 @@ undiheader:
|
98
|
104
|
.equ undiheader_len, . - undiheader
|
99
|
105
|
.size undiheader, . - undiheader
|
100
|
106
|
|
101
|
|
-/* Initialisation vector
|
|
107
|
+/* Initialisation (called once during POST)
|
102
|
108
|
*
|
103
|
109
|
* Determine whether or not this is a PnP system via a signature
|
104
|
110
|
* check. If it is PnP, return to the PnP BIOS indicating that we are
|
105
|
111
|
* a boot-capable device; the BIOS will call our boot execution vector
|
106
|
112
|
* if it wants to boot us. If it is not PnP, hook INT 19.
|
107
|
113
|
*/
|
108
|
|
-init_vector:
|
109
|
|
- pushw %si
|
110
|
|
- cmpw $'$'+'P'*256, %es:0(%di)
|
111
|
|
- jne notpnp
|
112
|
|
- cmpw $'n'+'P'*256, %es:2(%di)
|
113
|
|
- jne notpnp
|
114
|
|
-ispnp:
|
115
|
|
- movw $ispnp_message, %si
|
116
|
|
- jmp 99f
|
117
|
|
-notpnp:
|
|
114
|
+init:
|
|
115
|
+ /* Preserve registers, clear direction flag, set %ds=%cs */
|
|
116
|
+ pushaw
|
118
|
117
|
pushw %ds
|
119
|
|
- pushw $0
|
120
|
|
- popw %ds
|
|
118
|
+ pushw %es
|
|
119
|
+ cld
|
121
|
120
|
pushw %cs
|
122
|
|
- pushw $exec_vector
|
123
|
|
- popl ( 0x19 * 4 )
|
124
|
121
|
popw %ds
|
125
|
|
- movw $notpnp_message, %si
|
|
122
|
+ /* Print message as early as possible */
|
|
123
|
+ movw $init_message, %si
|
|
124
|
+ call print_message
|
|
125
|
+ /* Check for PnP BIOS */
|
|
126
|
+ cmpl $PNP_SIGNATURE, %es:0(%di)
|
|
127
|
+ je ispnp
|
|
128
|
+notpnp: /* Not PnP: hook INT19 */
|
|
129
|
+ xorw %ax, %ax
|
|
130
|
+ movw %ax, %es
|
|
131
|
+ pushw %cs
|
|
132
|
+ pushw $int19_entry
|
|
133
|
+ popl %es:( 0x19 * 4 )
|
|
134
|
+ jmp 99f
|
|
135
|
+ispnp: /* Is PnP: print PnP message */
|
|
136
|
+ movw $init_message_pnp, %si
|
|
137
|
+ call print_message
|
|
138
|
+ /* Check for PMM */
|
|
139
|
+ movw $( 0xe000 - 1 ), %di
|
|
140
|
+pmm_scan:
|
|
141
|
+ incw %di
|
|
142
|
+ jz 99f
|
|
143
|
+ movw %di, %es
|
|
144
|
+ cmpl $PMM_SIGNATURE, %es:0
|
|
145
|
+ jne pmm_scan
|
|
146
|
+ xorw %bx, %bx
|
|
147
|
+ xorw %si, %si
|
|
148
|
+ movzbw %es:5, %cx
|
|
149
|
+1: es lodsb
|
|
150
|
+ addb %al, %bl
|
|
151
|
+ loop 1b
|
|
152
|
+ jnz pmm_scan
|
|
153
|
+ /* PMM found: print PMM message */
|
|
154
|
+ movw $init_message_pmm, %si
|
|
155
|
+ call print_message
|
|
156
|
+ /* Try to allocate 2MB block via PMM */
|
|
157
|
+ pushw $0x0006 /* Aligned, extended memory */
|
|
158
|
+ pushl $0xffffffff /* No handle */
|
|
159
|
+ pushl $( 0x00200000 / 16 ) /* 2MB in paragraphs */
|
|
160
|
+ pushw $0x0000 /* pmmAllocate */
|
|
161
|
+ lcall %es:*(7)
|
|
162
|
+ addw $12, %sp
|
|
163
|
+ testw %dx, %dx /* %ax==0 even on success, since align=2MB */
|
|
164
|
+ jnz gotpmm
|
|
165
|
+ movw $init_message_pmm_failed, %si
|
|
166
|
+ call print_message
|
|
167
|
+ jmp 99f
|
|
168
|
+gotpmm: /* PMM allocation succeeded: copy ROM to PMM block */
|
|
169
|
+ pushal /* PMM presence implies 1kB stack */
|
|
170
|
+ movw %ax, %es /* %ax=0 already - see above */
|
|
171
|
+ pushw %dx
|
|
172
|
+ pushw %ax
|
|
173
|
+ popl %edi
|
|
174
|
+ movl %edi, image_source
|
|
175
|
+ xorl %esi, %esi
|
|
176
|
+ movzbl romheader_size, %ecx
|
|
177
|
+ shll $9, %ecx
|
|
178
|
+ addr32 rep movsb /* PMM presence implies flat real mode */
|
|
179
|
+ movl %edi, decompress_to
|
|
180
|
+ /* Shrink ROM and update checksum */
|
|
181
|
+ xorw %bx, %bx
|
|
182
|
+ xorw %si, %si
|
|
183
|
+ movb $_prefix_size_sect, romheader_size
|
|
184
|
+ shlw $9, %cx
|
|
185
|
+1: lodsb
|
|
186
|
+ addb %al, %bl
|
|
187
|
+ loop 1b
|
|
188
|
+ subb %bl, checksum
|
|
189
|
+ popal
|
126
|
190
|
99:
|
|
191
|
+ /* Print CRLF to terminate messages */
|
|
192
|
+ movw $init_message_crlf, %si
|
127
|
193
|
call print_message
|
|
194
|
+ /* Restore registers */
|
|
195
|
+ popw %es
|
|
196
|
+ popw %ds
|
|
197
|
+ popaw
|
|
198
|
+ /* Indicate boot capability to PnP BIOS, if present */
|
128
|
199
|
movw $0x20, %ax
|
129
|
|
- popw %si
|
130
|
200
|
lret
|
131
|
|
- .size init_vector, . - init_vector
|
132
|
|
-
|
133
|
|
-ispnp_message:
|
134
|
|
- .asciz "gPXE detected PnP BIOS\r\n"
|
135
|
|
- .size ispnp_message, . - ispnp_message
|
136
|
|
-notpnp_message:
|
137
|
|
- .asciz "gPXE detected non-PnP BIOS\r\n"
|
138
|
|
- .size notpnp_message, . - notpnp_message
|
139
|
|
-
|
140
|
|
-/* Boot execution vector
|
141
|
|
- *pciheader_size
|
142
|
|
- * Called by the PnP BIOS when it wants to boot us, or via the hooked
|
143
|
|
- * INT 19 if we detected a non-PnP BIOS.
|
144
|
|
- */
|
145
|
|
-exec_vector:
|
146
|
|
- /* Obtain a reasonably-sized stack */
|
|
201
|
+ .size init, . - init
|
|
202
|
+
|
|
203
|
+init_message:
|
|
204
|
+ .asciz "gPXE (http://etherboot.org)"
|
|
205
|
+ .size init_message, . - init_message
|
|
206
|
+init_message_pnp:
|
|
207
|
+ .asciz " - PnP BIOS detected"
|
|
208
|
+ .size init_message_pnp, . - init_message_pnp
|
|
209
|
+init_message_pmm:
|
|
210
|
+ .asciz ", using PMM"
|
|
211
|
+ .size init_message_pmm, . - init_message_pmm
|
|
212
|
+init_message_pmm_failed:
|
|
213
|
+ .asciz " (failed)"
|
|
214
|
+ .size init_message_pmm_failed, . - init_message_pmm_failed
|
|
215
|
+init_message_crlf:
|
|
216
|
+ .asciz "\r\n"
|
|
217
|
+ .size init_message_crlf, . - init_message_crlf
|
|
218
|
+
|
|
219
|
+/* ROM image location
|
|
220
|
+ *
|
|
221
|
+ * May be either within option ROM space, or within PMM-allocated block.
|
|
222
|
+ */
|
|
223
|
+image_source:
|
|
224
|
+ .long 0
|
|
225
|
+ .size image_source, . - image_source
|
|
226
|
+/* Temporary decompression area
|
|
227
|
+ *
|
|
228
|
+ * May be either at HIGHMEM_LOADPOINT, or within PMM-allocated block.
|
|
229
|
+ */
|
|
230
|
+decompress_to:
|
|
231
|
+ .long HIGHMEM_LOADPOINT
|
|
232
|
+ .size decompress_to, . - decompress_to
|
|
233
|
+
|
|
234
|
+/* Boot Execution Vector entry point
|
|
235
|
+ *
|
|
236
|
+ * Called by the PnP BIOS when it wants to boot us.
|
|
237
|
+ */
|
|
238
|
+bev_entry:
|
|
239
|
+ pushw %cs
|
|
240
|
+ call exec
|
|
241
|
+ lret
|
|
242
|
+ .size bev_entry, . - bev_entry
|
|
243
|
+
|
|
244
|
+/* INT19 entry point
|
|
245
|
+ *
|
|
246
|
+ * Called via the hooked INT 19 if we detected a non-PnP BIOS.
|
|
247
|
+ */
|
|
248
|
+int19_entry:
|
|
249
|
+ pushw %cs
|
|
250
|
+ call exec
|
|
251
|
+ /* No real way to return from INT19 */
|
|
252
|
+ int $0x18
|
|
253
|
+ .size int19_entry, . - int19_entry
|
|
254
|
+
|
|
255
|
+/* Execute as a boot device
|
|
256
|
+ *
|
|
257
|
+ */
|
|
258
|
+exec: /* Set %ds = %cs */
|
|
259
|
+ pushw %cs
|
|
260
|
+ popw %ds
|
|
261
|
+
|
|
262
|
+ /* Print message as soon as possible */
|
|
263
|
+ movw $exec_message, %si
|
|
264
|
+ call print_message
|
|
265
|
+
|
|
266
|
+ /* Store magic word on BIOS stack and remember BIOS %ss:sp */
|
|
267
|
+ pushl $STACK_MAGIC
|
|
268
|
+ movw %ss, %dx
|
|
269
|
+ movw %sp, %bp
|
|
270
|
+
|
|
271
|
+ /* Obtain a reasonably-sized temporary stack */
|
147
|
272
|
xorw %ax, %ax
|
148
|
273
|
movw %ax, %ss
|
149
|
274
|
movw $0x7c00, %sp
|
150
|
|
-
|
151
|
|
- movw $exec_message, %si
|
152
|
|
- call print_message
|
153
|
275
|
|
154
|
|
- call install
|
|
276
|
+ /* Install gPXE */
|
|
277
|
+ movl image_source, %esi
|
|
278
|
+ movl decompress_to, %edi
|
|
279
|
+ call alloc_basemem
|
|
280
|
+ call install_prealloc
|
155
|
281
|
|
156
|
282
|
/* Set up real-mode stack */
|
157
|
283
|
movw %bx, %ss
|
|
@@ -162,13 +288,23 @@ exec_vector:
|
162
|
288
|
pushw $1f
|
163
|
289
|
lret
|
164
|
290
|
.section ".text16", "awx", @progbits
|
165
|
|
-1:
|
|
291
|
+1: /* Call main() */
|
166
|
292
|
pushl $main
|
167
|
293
|
pushw %cs
|
168
|
294
|
call prot_call
|
169
|
|
- popl %eax /* discard */
|
|
295
|
+ /* No need to clean up stack; we are about to reload %ss:sp */
|
|
296
|
+
|
|
297
|
+ /* Restore BIOS stack */
|
|
298
|
+ movw %dx, %ss
|
|
299
|
+ movw %bp, %sp
|
170
|
300
|
|
171
|
|
- /* Boot next device */
|
|
301
|
+ /* Check magic word on BIOS stack */
|
|
302
|
+ popl %eax
|
|
303
|
+ cmpl $STACK_MAGIC, %eax
|
|
304
|
+ jne 1f
|
|
305
|
+ /* BIOS stack OK: return to caller */
|
|
306
|
+ lret
|
|
307
|
+1: /* BIOS stack corrupt: use INT 18 */
|
172
|
308
|
int $0x18
|
173
|
309
|
.previous
|
174
|
310
|
|
|
@@ -182,6 +318,7 @@ exec_message:
|
182
|
318
|
*/
|
183
|
319
|
undiloader:
|
184
|
320
|
/* Save registers */
|
|
321
|
+ pushl %esi
|
185
|
322
|
pushl %edi
|
186
|
323
|
pushw %es
|
187
|
324
|
pushw %bx
|
|
@@ -193,6 +330,8 @@ undiloader:
|
193
|
330
|
pushw %di
|
194
|
331
|
movw %es:12(%di), %bx
|
195
|
332
|
movw %es:14(%di), %ax
|
|
333
|
+ movl %cs:image_source, %esi
|
|
334
|
+ movl %cs:decompress_to, %edi
|
196
|
335
|
call install_prealloc
|
197
|
336
|
popw %di
|
198
|
337
|
/* Call UNDI loader C code */
|
|
@@ -208,6 +347,7 @@ undiloader:
|
208
|
347
|
popw %bx
|
209
|
348
|
popw %es
|
210
|
349
|
popl %edi
|
|
350
|
+ popl %esi
|
211
|
351
|
lret
|
212
|
352
|
.size undiloader, . - undiloader
|
213
|
353
|
|
|
@@ -218,7 +358,7 @@ print_message:
|
218
|
358
|
pushw %bx
|
219
|
359
|
pushw %bp
|
220
|
360
|
movw $0x0007, %bx
|
221
|
|
-1: cs lodsb
|
|
361
|
+1: lodsb
|
222
|
362
|
testb %al, %al
|
223
|
363
|
je 2f
|
224
|
364
|
movb $0x0e, %ah /* write char, tty mode */
|