Browse Source

[prefix] Use 16-bit protected mode for access to high memory

Flat real mode works perfectly on real hardware, but seems to cause
problems for some hypervisors.  Revert to using 16-bit protected mode
(and returning to real mode with 4GB limits, so as not to break PMM
BIOSes).

Allow the code specific to the .mrom format to continue to assume that
flat real mode works, since this format is specific to real hardware.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
a84e15234a
2 changed files with 195 additions and 42 deletions
  1. 189
    41
      src/arch/i386/prefix/libprefix.S
  2. 6
    1
      src/arch/i386/prefix/mromprefix.S

+ 189
- 41
src/arch/i386/prefix/libprefix.S View File

24
 /* Image compression enabled */
24
 /* Image compression enabled */
25
 #define COMPRESS 1
25
 #define COMPRESS 1
26
 
26
 
27
+/* Protected mode flag */
28
+#define CR0_PE 1
29
+
27
 /*****************************************************************************
30
 /*****************************************************************************
28
  * Utility function: print character (with LF -> LF,CR translation)
31
  * Utility function: print character (with LF -> LF,CR translation)
29
  *
32
  *
229
  *   None
232
  *   None
230
  ****************************************************************************
233
  ****************************************************************************
231
  */
234
  */
232
-#if ! COMPRESS
233
 	.section ".prefix.lib", "awx", @progbits
235
 	.section ".prefix.lib", "awx", @progbits
234
 	.code16
236
 	.code16
235
 copy_bytes:
237
 copy_bytes:
236
-	pushl %ecx
238
+	pushl	%ecx
237
 	rep addr32 movsb
239
 	rep addr32 movsb
238
-	popl %ecx
240
+	popl	%ecx
239
 	ret
241
 	ret
240
-	.size copy_bytes, . - copy_bytes
241
-#endif /* COMPRESS */
242
+	.size	copy_bytes, . - copy_bytes
242
 
243
 
243
 /****************************************************************************
244
 /****************************************************************************
244
- * install_block
245
+ * zero_bytes
245
  *
246
  *
246
- * Install block to specified address
247
+ * Zero bytes
247
  *
248
  *
248
  * Parameters:
249
  * Parameters:
249
- *   %esi : source physical address (must be a multiple of 16)
250
- *   %edi : destination physical address (must be a multiple of 16)
251
- *   %ecx : length of (decompressed) data
252
- *   %edx : total length of block (including any uninitialised data portion)
250
+ *   %ds:esi : source address
251
+ *   %es:edi : destination address
252
+ *   %ecx : length
253
  * Returns:
253
  * Returns:
254
- *   %esi : next source physical address (will be a multiple of 16)
255
- *   %edi : next destination physical address (will be a multiple of 16)
254
+ *   %ds:esi : next source address
255
+ *   %es:edi : next destination address
256
  * Corrupts:
256
  * Corrupts:
257
- *   none
257
+ *   None
258
  ****************************************************************************
258
  ****************************************************************************
259
  */
259
  */
260
 	.section ".prefix.lib", "awx", @progbits
260
 	.section ".prefix.lib", "awx", @progbits
261
 	.code16
261
 	.code16
262
-install_block:
262
+zero_bytes:
263
+	pushl	%ecx
264
+	pushw	%ax
265
+	xorw	%ax, %ax
266
+	rep addr32 stosb
267
+	popw	%ax
268
+	popl	%ecx
269
+	ret
270
+	.size	zero_bytes, . - zero_bytes
271
+
272
+/****************************************************************************
273
+ * process_bytes
274
+ *
275
+ * Call memcpy()-like function
276
+ *
277
+ * Parameters:
278
+ *   %esi : source physical address
279
+ *   %edi : destination physical address
280
+ *   %ecx : length
281
+ *   %bx : memcpy()-like function to call, passing parameters:
282
+ *	     %ds:esi : source address
283
+ *	     %es:edi : destination address
284
+ *	     %ecx : length
285
+ *         and returning:
286
+ *	     %ds:esi : next source address
287
+ *	     %es:edi : next destination address
288
+ * Returns:
289
+ *   %esi : next source physical address
290
+ *   %edi : next destination physical address
291
+ * Corrupts:
292
+ *   None
293
+ ****************************************************************************
294
+ */
295
+	.section ".prefix.lib", "awx", @progbits
296
+	.code16
297
+process_bytes:
298
+
299
+#ifndef KEEP_IT_REAL
300
+
263
 	/* Preserve registers */
301
 	/* Preserve registers */
302
+	pushfw
303
+	pushl	%eax
304
+	pushl	%ebp
305
+
306
+	/* Construct GDT on stack (since .prefix may not be writable) */
307
+	.equ	PM_DS, 0x18	/* Flat data segment */
308
+	pushl	$0x008f9300
309
+	pushl	$0x0000ffff
310
+	.equ	PM_SS, 0x10	/* Stack segment based at %ss:0000 */
311
+	pushl	$0x008f0930
312
+	pushw	%ss
313
+	pushw	$0xffff
314
+	.equ	PM_CS, 0x08	/* Code segment based at %cs:0000 */
315
+	pushl	$0x008f09b0
316
+	pushw	%cs
317
+	pushw	$0xffff
318
+	pushl	$0		/* Base and length */
319
+	pushw	%ss
320
+	pushw	$0x1f
321
+	movzwl	%sp, %ebp
322
+	shll	$4, 0x02(%bp)
323
+	addl	%ebp, 0x02(%bp)
324
+	shll	$4, 0x0a(%bp)
325
+	shll	$4, 0x12(%bp)
326
+	subw	$8, %sp
327
+	sgdt	-8(%bp)
328
+
329
+	/* Switch to protected mode */
330
+	pushw	%gs
331
+	pushw	%fs
332
+	pushw	%es
333
+	pushw	%ds
334
+	pushw	%ss
335
+	pushw	%cs
336
+	pushw	$2f
337
+	cli
338
+	data32 lgdt (%bp)
339
+	movl	%cr0, %eax
340
+	orb	$CR0_PE, %al
341
+	movl	%eax, %cr0
342
+	ljmp	$PM_CS, $1f
343
+1:	movw	$PM_SS, %ax
344
+	movw	%ax, %ss
345
+	movw	$PM_DS, %ax
346
+	movw	%ax, %ds
347
+	movw	%ax, %es
348
+	movw	%ax, %fs
349
+	movw	%ax, %gs
350
+
351
+	/* Call memcpy()-like function */
352
+	call	*%bx
353
+
354
+	/* Return to (flat) real mode */
355
+	movl	%cr0, %eax
356
+	andb	$0!CR0_PE, %al
357
+	movl	%eax, %cr0
358
+	lret
359
+2:	/* lret will ljmp to here */
360
+	popw	%ss
361
+	popw	%ds
362
+	popw	%es
363
+	popw	%fs
364
+	popw	%gs
365
+
366
+	/* Restore GDT */
367
+	data32 lgdt -8(%bp)
368
+	addw	$( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
369
+
370
+	/* Restore registers and return */
371
+	popl	%ebp
372
+	popl	%eax
373
+	popfw
374
+	ret
375
+
376
+#else /* KEEP_IT_REAL */
377
+
378
+	/* Preserve registers */
379
+	pushl	%eax
264
 	pushw	%ds
380
 	pushw	%ds
265
 	pushw	%es
381
 	pushw	%es
266
-	pushl	%ecx
267
 	
382
 	
268
 	/* Convert %esi and %edi to %ds:esi and %es:edi */
383
 	/* Convert %esi and %edi to %ds:esi and %es:edi */
269
 	shrl	$4, %esi
384
 	shrl	$4, %esi
275
 	xorw	%di, %di
390
 	xorw	%di, %di
276
 	shll	$4, %edi
391
 	shll	$4, %edi
277
 
392
 
393
+	/* Call memcpy()-like function */
394
+	call	*%bx
395
+
396
+	/* Convert %ds:esi and %es:edi back to physical addresses */
397
+	xorl	%eax, %eax
398
+	movw	%ds, %cx
399
+	shll	$4, %eax
400
+	addl	%eax, %esi
401
+	xorl	%eax, %eax
402
+	movw	%es, %cx
403
+	shll	$4, %eax
404
+	addl	%eax, %edi
405
+
406
+	/* Restore registers and return */
407
+	popw	%es
408
+	popw	%ds
409
+	popl	%eax
410
+	ret
411
+
412
+#endif /* KEEP_IT_REAL */
413
+
414
+	.size	process_bytes, . - process_bytes
415
+
416
+/****************************************************************************
417
+ * install_block
418
+ *
419
+ * Install block to specified address
420
+ *
421
+ * Parameters:
422
+ *   %esi : source physical address (must be a multiple of 16)
423
+ *   %edi : destination physical address (must be a multiple of 16)
424
+ *   %ecx : length of (decompressed) data
425
+ *   %edx : total length of block (including any uninitialised data portion)
426
+ * Returns:
427
+ *   %esi : next source physical address (will be a multiple of 16)
428
+ *   %edi : next destination physical address (will be a multiple of 16)
429
+ * Corrupts:
430
+ *   none
431
+ ****************************************************************************
432
+ */
433
+	.section ".prefix.lib", "awx", @progbits
434
+	.code16
435
+install_block:
436
+	/* Preserve registers */
437
+	pushl	%ecx
438
+	pushw	%bx
439
+
440
+	/* Decompress (or copy) source to destination */
278
 #if COMPRESS
441
 #if COMPRESS
279
-	/* Decompress source to destination */
280
-	call	decompress16
442
+	movw	$decompress16, %bx
281
 #else
443
 #else
282
-	/* Copy source to destination */
283
-	call	copy_bytes
444
+	movw	$copy_bytes, %bx
284
 #endif
445
 #endif
446
+	call	process_bytes
285
 
447
 
286
 	/* Zero .bss portion */
448
 	/* Zero .bss portion */
287
 	negl	%ecx
449
 	negl	%ecx
288
 	addl	%edx, %ecx
450
 	addl	%edx, %ecx
289
-	pushw	%ax
290
-	xorw	%ax, %ax
291
-	rep addr32 stosb
292
-	popw	%ax
451
+	movw	$zero_bytes, %bx
452
+	call	process_bytes
293
 
453
 
294
 	/* Round up %esi and %edi to start of next blocks */
454
 	/* Round up %esi and %edi to start of next blocks */
295
 	addl	$0xf, %esi
455
 	addl	$0xf, %esi
297
 	addl	$0xf, %edi
457
 	addl	$0xf, %edi
298
 	andl	$~0xf, %edi
458
 	andl	$~0xf, %edi
299
 
459
 
300
-	/* Convert %ds:esi and %es:edi back to physical addresses */
301
-	xorl	%ecx, %ecx
302
-	movw	%ds, %cx
303
-	shll	$4, %ecx
304
-	addl	%ecx, %esi
305
-	xorl	%ecx, %ecx
306
-	movw	%es, %cx
307
-	shll	$4, %ecx
308
-	addl	%ecx, %edi
309
-
310
 	/* Restore registers and return */
460
 	/* Restore registers and return */
461
+	popw	%bx
311
 	popl	%ecx
462
 	popl	%ecx
312
-	popw	%es
313
-	popw	%ds
314
 	ret
463
 	ret
315
 	.size install_block, . - install_block
464
 	.size install_block, . - install_block
316
 
465
 
612
 
761
 
613
 	/* Copy code to new location */
762
 	/* Copy code to new location */
614
 	pushl	%edi
763
 	pushl	%edi
615
-	pushw	%ax
616
-	xorw	%ax, %ax
617
-	movw	%ax, %es
618
-	es rep addr32 movsb
619
-	popw	%ax
764
+	pushw	%bx
765
+	movw	$copy_bytes, %bx
766
+	call	process_bytes
767
+	popw	%bx
620
 	popl	%edi
768
 	popl	%edi
621
 
769
 
622
 	/* Initialise librm at new location */
770
 	/* Initialise librm at new location */

+ 6
- 1
src/arch/i386/prefix/mromprefix.S View File

151
 	/* Copy payload to buffer, or set buffer address to BAR address */
151
 	/* Copy payload to buffer, or set buffer address to BAR address */
152
 	testl	%esi, %esi
152
 	testl	%esi, %esi
153
 	jz	1f
153
 	jz	1f
154
-	/* We have a buffer; copy payload to it */
154
+	/* We have a buffer; copy payload to it.  Since .mrom is
155
+	 * designed specifically for real hardware, we assume that
156
+	 * flat real mode is working properly.  (In the unlikely event
157
+	 * that this code is run inside a hypervisor that doesn't
158
+	 * properly support flat real mode, it will die horribly.)
159
+	 */
155
 	pushl	%esi
160
 	pushl	%esi
156
 	pushw	%es
161
 	pushw	%es
157
 	movl	%esi, %edi
162
 	movl	%esi, %edi

Loading…
Cancel
Save