Browse Source

[prefix] Use flat real mode for access to high memory

Use flat real mode rather than 16-bit protected mode for access to
high memory during installation.  This simplifies the code by reducing
the number of CPU modes we need to think about, and also increases the
amount of code in common between the normal and (somewhat
hypothetical) KEEP_IT_REAL methods of operation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 years ago
parent
commit
6c35a525da
1 changed files with 79 additions and 127 deletions
  1. 79
    127
      src/arch/i386/prefix/libprefix.S

+ 79
- 127
src/arch/i386/prefix/libprefix.S View File

@@ -233,156 +233,128 @@ print_kill_line:
233 233
 	.size	print_kill_line, . - print_kill_line
234 234
 
235 235
 /****************************************************************************
236
- * pm_call (real-mode near call)
236
+ * flatten_real_mode
237 237
  *
238
- * Call routine in 16-bit protected mode for access to extended memory
238
+ * Set up 4GB segment limits
239 239
  *
240 240
  * Parameters:
241
- *   %ax : address of routine to call in 16-bit protected mode
241
+ *   none
242 242
  * Returns:
243 243
  *   none
244 244
  * Corrupts:
245
- *   %ax
246
- *
247
- * The specified routine is called in 16-bit protected mode, with:
248
- *
249
- *   %cs : 16-bit code segment with base matching real-mode %cs
250
- *   %ss : 16-bit data segment with base matching real-mode %ss
251
- *   %ds,%es,%fs,%gs : 32-bit data segment with zero base and 4GB limit
252
- *
245
+ *   none
253 246
  ****************************************************************************
254 247
  */
255
-
256 248
 #ifndef KEEP_IT_REAL
257 249
 
258 250
 	/* GDT for protected-mode calls */
259 251
 	.section ".prefix.lib", "awx", @progbits
260 252
 	.align 16
261
-pm_call_vars:
262
-gdt:
263
-gdt_limit:		.word gdt_length - 1
264
-gdt_base:		.long 0
253
+flatten_vars:
254
+flatten_gdt:
255
+flatten_gdt_limit:	.word flatten_gdt_length - 1
256
+flatten_gdt_base:	.long 0
265 257
 			.word 0 /* padding */
266
-pm_cs:		/* 16-bit protected-mode flat code segment */
267
-	.equ    PM_CS, pm_cs - gdt
258
+flatten_cs:	/* 16-bit protected-mode flat code segment */
259
+	.equ    FLAT_CS, flatten_cs - flatten_gdt
268 260
 	.word   0xffff, 0
269 261
 	.byte   0, 0x9b, 0x8f, 0
270
-pm_ss:		/* 16-bit protected-mode flat stack segment */
271
-	.equ    PM_SS, pm_ss - gdt
262
+flatten_ss:	/* 16-bit protected-mode flat stack segment */
263
+	.equ    FLAT_SS, flatten_ss - flatten_gdt
272 264
 	.word   0xffff, 0
273 265
 	.byte   0, 0x93, 0x8f, 0
274
-pm_ds:		/* 32-bit protected-mode flat data segment */
275
-	.equ    PM_DS, pm_ds - gdt
276
-	.word   0xffff, 0
277
-	.byte   0, 0x93, 0xcf, 0
278
-gdt_end:
279
-	.equ	gdt_length, . - gdt
280
-	.size	gdt, . - gdt
266
+flatten_gdt_end:
267
+	.equ	flatten_gdt_length, . - flatten_gdt
268
+	.size	flatten_gdt, . - flatten_gdt
281 269
 
282 270
 	.section ".prefix.lib", "awx", @progbits
283 271
 	.align 16
284
-pm_saved_gdt:	
272
+flatten_saved_gdt:
285 273
 	.long	0, 0
286
-	.size	pm_saved_gdt, . - pm_saved_gdt
274
+	.size	flatten_saved_gdt, . - flatten_saved_gdt
287 275
 
288
-	.equ	pm_call_vars_size, . - pm_call_vars
289
-#define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) )
276
+	.equ	flatten_vars_size, . - flatten_vars
277
+#define FLATTEN_VAR(x) ( -flatten_vars_size + ( (x) - flatten_vars ) )
290 278
 
291 279
 	.section ".prefix.lib", "awx", @progbits
292 280
 	.code16
293
-pm_call:
294
-	/* Preserve registers, flags, and RM return point */
281
+flatten_real_mode:
282
+	/* Preserve registers and flags, allocate local variable block */
295 283
 	pushw	%bp
296 284
 	movw	%sp, %bp
297
-	subw	$pm_call_vars_size, %sp
285
+	subw	$flatten_vars_size, %sp
298 286
 	andw	$0xfff0, %sp
299 287
 	pushfl
288
+	pushl	%eax
289
+	pushl	%edi
290
+	pushw	%si
291
+	pushw	%cx
300 292
 	pushw	%gs
301 293
 	pushw	%fs
302 294
 	pushw	%es
303 295
 	pushw	%ds
304 296
 	pushw	%ss
305
-	pushw	%cs
306
-	pushw	$99f
307 297
 
308
-	/* Set up local variable block, and preserve GDT */
309
-	pushw	%cx
310
-	pushw	%si
311
-	pushw	%di
298
+	/* Fill local variable block and preserve GDT */
312 299
 	pushw	%ss
313 300
 	popw	%es
314
-	movw	$pm_call_vars, %si
315
-	leaw	PM_CALL_VAR(pm_call_vars)(%bp), %di
316
-	movw	$pm_call_vars_size, %cx
301
+	movw	$flatten_vars, %si
302
+	leaw	FLATTEN_VAR(flatten_vars)(%bp), %di
303
+	movw	$flatten_vars_size, %cx
317 304
 	cs rep movsb
318
-	popw	%di
319
-	popw	%si
320
-	popw	%cx
321
-	sgdt	PM_CALL_VAR(pm_saved_gdt)(%bp)
305
+	sgdt	FLATTEN_VAR(flatten_saved_gdt)(%bp)
322 306
 
323 307
 	/* Set up GDT bases */
324
-	pushl	%eax
325
-	pushl	%edi
326 308
 	xorl	%eax, %eax
327 309
 	movw	%ss, %ax
328 310
 	shll	$4, %eax
329 311
 	movzwl	%bp, %edi
330
-	addr32 leal PM_CALL_VAR(gdt)(%eax, %edi), %eax
331
-	movl	%eax, PM_CALL_VAR(gdt_base)(%bp)
312
+	addr32 leal FLATTEN_VAR(flatten_gdt)(%eax, %edi), %eax
313
+	movl	%eax, FLATTEN_VAR(flatten_gdt_base)(%bp)
332 314
 	movw	%cs, %ax
333
-	movw	$PM_CALL_VAR(pm_cs), %di
315
+	movw	$FLATTEN_VAR(flatten_cs), %di
334 316
 	call	set_seg_base
335 317
 	movw	%ss, %ax
336
-	movw	$PM_CALL_VAR(pm_ss), %di
318
+	movw	$FLATTEN_VAR(flatten_ss), %di
337 319
 	call	set_seg_base
338
-	popl	%edi
339
-	popl	%eax
340 320
 
341
-	/* Switch CPU to protected mode and load up segment registers */
342
-	pushl	%eax
321
+	/* Switch temporarily to protected mode and set segment registers */
322
+	pushw	%cs
323
+	pushw	$2f
343 324
 	cli
344
-	data32 lgdt PM_CALL_VAR(gdt)(%bp)
325
+	data32 lgdt FLATTEN_VAR(flatten_gdt)(%bp)
345 326
 	movl	%cr0, %eax
346 327
 	orb	$CR0_PE, %al
347 328
 	movl	%eax, %cr0
348
-	ljmp	$PM_CS, $1f
349
-1:	movw	$PM_SS, %ax
329
+	ljmp	$FLAT_CS, $1f
330
+1:	movw	$FLAT_SS, %ax
350 331
 	movw	%ax, %ss
351
-	movw	$PM_DS, %ax
352
-	movw	%ax, %ds
353
-	movw	%ax, %es
354
-	movw	%ax, %fs
355
-	movw	%ax, %gs
356
-	popl	%eax
357
-
358
-	/* Call PM routine */
359
-	call	*%ax
360
-
361
-	/* Set real-mode segment limits on %ds, %es, %fs and %gs */
362
-	movw	%ss, %ax
363 332
 	movw	%ax, %ds
364 333
 	movw	%ax, %es
365 334
 	movw	%ax, %fs
366 335
 	movw	%ax, %gs
367
-
368
-	/* Return CPU to real mode */
369 336
 	movl	%cr0, %eax
370 337
 	andb	$0!CR0_PE, %al
371 338
 	movl	%eax, %cr0
339
+	lret
340
+2:	/* lret will ljmp to here */
372 341
 
373
-	/* Restore registers and flags */
374
-	lret	/* will ljmp to 99f */
375
-99:	popw	%ss
342
+	/* Restore GDT, registers and flags */
343
+	data32 lgdt FLATTEN_VAR(flatten_saved_gdt)(%bp)
344
+	popw	%ss
376 345
 	popw	%ds
377 346
 	popw	%es
378 347
 	popw	%fs
379 348
 	popw	%gs
380
-	data32 lgdt PM_CALL_VAR(pm_saved_gdt)(%bp)
349
+	popw	%cx
350
+	popw	%si
351
+	popl	%edi
352
+	popl	%eax
381 353
 	popfl
382 354
 	movw	%bp, %sp
383 355
 	popw	%bp
384 356
 	ret
385
-	.size pm_call, . - pm_call
357
+	.size flatten_real_mode, . - flatten_real_mode
386 358
 
387 359
 set_seg_base:
388 360
 	rolw	$4, %ax
@@ -396,7 +368,7 @@ set_seg_base:
396 368
 #endif /* KEEP_IT_REAL */
397 369
 
398 370
 /****************************************************************************
399
- * copy_bytes (real-mode or 16-bit protected-mode near call)
371
+ * copy_bytes
400 372
  *
401 373
  * Copy bytes
402 374
  *
@@ -411,6 +383,7 @@ set_seg_base:
411 383
  *   None
412 384
  ****************************************************************************
413 385
  */
386
+#if ! COMPRESS
414 387
 	.section ".prefix.lib", "awx", @progbits
415 388
 	.code16
416 389
 copy_bytes:
@@ -419,9 +392,10 @@ copy_bytes:
419 392
 	popl %ecx
420 393
 	ret
421 394
 	.size copy_bytes, . - copy_bytes
395
+#endif /* COMPRESS */
422 396
 
423 397
 /****************************************************************************
424
- * install_block (real-mode near call)
398
+ * install_block
425 399
  *
426 400
  * Install block to specified address
427 401
  *
@@ -439,39 +413,22 @@ copy_bytes:
439 413
 	.section ".prefix.lib", "awx", @progbits
440 414
 	.code16
441 415
 install_block:
442
-	
443
-#ifdef KEEP_IT_REAL
444
-
445 416
 	/* Preserve registers */
446 417
 	pushw	%ds
447 418
 	pushw	%es
448 419
 	pushl	%ecx
449 420
 	pushl	%edi
450 421
 	
451
-	/* Convert %esi and %edi to segment registers */
422
+	/* Convert %esi and %edi to %ds:esi and %es:edi */
452 423
 	shrl	$4, %esi
453 424
 	movw	%si, %ds
454 425
 	xorw	%si, %si
426
+	shll	$4, %esi
455 427
 	shrl	$4, %edi
456 428
 	movw	%di, %es
457 429
 	xorw	%di, %di
430
+	shll	$4, %edi
458 431
 
459
-#else /* KEEP_IT_REAL */
460
-
461
-	/* Call self in protected mode */
462
-	pushw	%ax
463
-	movw	$1f, %ax
464
-	call	pm_call
465
-	popw	%ax
466
-	ret
467
-1:
468
-	/* Preserve registers */
469
-	pushl	%ecx
470
-	pushl	%edi
471
-	
472
-#endif /* KEEP_IT_REAL */
473
-
474
-	
475 432
 #if COMPRESS
476 433
 	/* Decompress source to destination */
477 434
 	call	decompress16
@@ -492,33 +449,22 @@ install_block:
492 449
 	addl	$0xf, %esi
493 450
 	andl	$~0xf, %esi
494 451
 
495
-
496
-#ifdef KEEP_IT_REAL
497
-
498 452
 	/* Convert %ds:esi back to a physical address */
499
-	movzwl	%ds, %cx
453
+	xorl	%ecx, %ecx
454
+	movw	%ds, %cx
500 455
 	shll	$4, %ecx
501 456
 	addl	%ecx, %esi
502 457
 
503
-	/* Restore registers */
458
+	/* Restore registers and return */
504 459
 	popl	%edi
505 460
 	popl	%ecx
506 461
 	popw	%es
507 462
 	popw	%ds
508
-
509
-#else /* KEEP_IT_REAL */
510
-
511
-	/* Restore registers */
512
-	popl	%edi
513
-	popl	%ecx
514
-
515
-#endif
516
-
517 463
 	ret
518 464
 	.size install_block, . - install_block
519
-	
465
+
520 466
 /****************************************************************************
521
- * alloc_basemem (real-mode near call)
467
+ * alloc_basemem
522 468
  *
523 469
  * Allocate space for .text16 and .data16 from top of base memory.
524 470
  * Memory is allocated using the BIOS free base memory counter at
@@ -568,7 +514,7 @@ alloc_basemem:
568 514
 	.size alloc_basemem, . - alloc_basemem
569 515
 
570 516
 /****************************************************************************
571
- * free_basemem (real-mode near call)
517
+ * free_basemem
572 518
  *
573 519
  * Free space allocated with alloc_basemem.
574 520
  *
@@ -620,7 +566,7 @@ hooked_bios_interrupts:
620 566
 	.size	hooked_bios_interrupts, . - hooked_bios_interrupts
621 567
 
622 568
 /****************************************************************************
623
- * install (real-mode near call)
569
+ * install
624 570
  *
625 571
  * Install all text and data segments.
626 572
  *
@@ -655,7 +601,7 @@ install:
655 601
 	.size install, . - install
656 602
 
657 603
 /****************************************************************************
658
- * install_prealloc (real-mode near call)
604
+ * install_prealloc
659 605
  *
660 606
  * Install all text and data segments.
661 607
  *
@@ -680,6 +626,11 @@ install_prealloc:
680 626
 	/* Sanity: clear the direction flag asap */
681 627
 	cld
682 628
 
629
+#ifndef KEEP_IT_REAL
630
+	/* Flatten real mode */
631
+	call	flatten_real_mode
632
+#endif
633
+
683 634
 	/* Calculate physical address of payload (i.e. first source) */
684 635
 	testl	%esi, %esi
685 636
 	jnz	1f
@@ -732,16 +683,15 @@ install_prealloc:
732 683
 
733 684
 	/* Copy code to new location */
734 685
 	pushl	%edi
735
-	pushw	%ax
736
-	movw	$copy_bytes, %ax
737
-	call	pm_call
738
-	popw	%ax
686
+	xorw	%ax, %ax
687
+	movw	%ax, %es
688
+	es rep addr32 movsb
739 689
 	popl	%edi
740 690
 
741 691
 	/* Initialise librm at new location */
742 692
 	lcall	*init_librm_vector
743
-
744 693
 #endif
694
+
745 695
 	/* Restore registers */
746 696
 	popw	%es
747 697
 	popw	%ds
@@ -749,7 +699,9 @@ install_prealloc:
749 699
 	ret
750 700
 	.size install_prealloc, . - install_prealloc
751 701
 
752
-	/* Vectors for far calls to .text16 functions */
702
+	/* Vectors for far calls to .text16 functions.  Must be in
703
+	 * .data16, since .prefix may not be writable.
704
+	 */
753 705
 	.section ".data16", "aw", @progbits
754 706
 #ifdef KEEP_IT_REAL
755 707
 init_libkir_vector:
@@ -768,7 +720,7 @@ prot_call_vector:
768 720
 #endif
769 721
 
770 722
 /****************************************************************************
771
- * uninstall (real-mode near call)
723
+ * uninstall
772 724
  *
773 725
  * Uninstall all text and data segments.
774 726
  *

Loading…
Cancel
Save