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
 	.size	print_kill_line, . - print_kill_line
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
  * Parameters:
240
  * Parameters:
241
- *   %ax : address of routine to call in 16-bit protected mode
241
+ *   none
242
  * Returns:
242
  * Returns:
243
  *   none
243
  *   none
244
  * Corrupts:
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
 #ifndef KEEP_IT_REAL
248
 #ifndef KEEP_IT_REAL
257
 
249
 
258
 	/* GDT for protected-mode calls */
250
 	/* GDT for protected-mode calls */
259
 	.section ".prefix.lib", "awx", @progbits
251
 	.section ".prefix.lib", "awx", @progbits
260
 	.align 16
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
 			.word 0 /* padding */
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
 	.word   0xffff, 0
260
 	.word   0xffff, 0
269
 	.byte   0, 0x9b, 0x8f, 0
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
 	.word   0xffff, 0
264
 	.word   0xffff, 0
273
 	.byte   0, 0x93, 0x8f, 0
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
 	.section ".prefix.lib", "awx", @progbits
270
 	.section ".prefix.lib", "awx", @progbits
283
 	.align 16
271
 	.align 16
284
-pm_saved_gdt:	
272
+flatten_saved_gdt:
285
 	.long	0, 0
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
 	.section ".prefix.lib", "awx", @progbits
279
 	.section ".prefix.lib", "awx", @progbits
292
 	.code16
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
 	pushw	%bp
283
 	pushw	%bp
296
 	movw	%sp, %bp
284
 	movw	%sp, %bp
297
-	subw	$pm_call_vars_size, %sp
285
+	subw	$flatten_vars_size, %sp
298
 	andw	$0xfff0, %sp
286
 	andw	$0xfff0, %sp
299
 	pushfl
287
 	pushfl
288
+	pushl	%eax
289
+	pushl	%edi
290
+	pushw	%si
291
+	pushw	%cx
300
 	pushw	%gs
292
 	pushw	%gs
301
 	pushw	%fs
293
 	pushw	%fs
302
 	pushw	%es
294
 	pushw	%es
303
 	pushw	%ds
295
 	pushw	%ds
304
 	pushw	%ss
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
 	pushw	%ss
299
 	pushw	%ss
313
 	popw	%es
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
 	cs rep movsb
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
 	/* Set up GDT bases */
307
 	/* Set up GDT bases */
324
-	pushl	%eax
325
-	pushl	%edi
326
 	xorl	%eax, %eax
308
 	xorl	%eax, %eax
327
 	movw	%ss, %ax
309
 	movw	%ss, %ax
328
 	shll	$4, %eax
310
 	shll	$4, %eax
329
 	movzwl	%bp, %edi
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
 	movw	%cs, %ax
314
 	movw	%cs, %ax
333
-	movw	$PM_CALL_VAR(pm_cs), %di
315
+	movw	$FLATTEN_VAR(flatten_cs), %di
334
 	call	set_seg_base
316
 	call	set_seg_base
335
 	movw	%ss, %ax
317
 	movw	%ss, %ax
336
-	movw	$PM_CALL_VAR(pm_ss), %di
318
+	movw	$FLATTEN_VAR(flatten_ss), %di
337
 	call	set_seg_base
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
 	cli
324
 	cli
344
-	data32 lgdt PM_CALL_VAR(gdt)(%bp)
325
+	data32 lgdt FLATTEN_VAR(flatten_gdt)(%bp)
345
 	movl	%cr0, %eax
326
 	movl	%cr0, %eax
346
 	orb	$CR0_PE, %al
327
 	orb	$CR0_PE, %al
347
 	movl	%eax, %cr0
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
 	movw	%ax, %ss
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
 	movw	%ax, %ds
332
 	movw	%ax, %ds
364
 	movw	%ax, %es
333
 	movw	%ax, %es
365
 	movw	%ax, %fs
334
 	movw	%ax, %fs
366
 	movw	%ax, %gs
335
 	movw	%ax, %gs
367
-
368
-	/* Return CPU to real mode */
369
 	movl	%cr0, %eax
336
 	movl	%cr0, %eax
370
 	andb	$0!CR0_PE, %al
337
 	andb	$0!CR0_PE, %al
371
 	movl	%eax, %cr0
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
 	popw	%ds
345
 	popw	%ds
377
 	popw	%es
346
 	popw	%es
378
 	popw	%fs
347
 	popw	%fs
379
 	popw	%gs
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
 	popfl
353
 	popfl
382
 	movw	%bp, %sp
354
 	movw	%bp, %sp
383
 	popw	%bp
355
 	popw	%bp
384
 	ret
356
 	ret
385
-	.size pm_call, . - pm_call
357
+	.size flatten_real_mode, . - flatten_real_mode
386
 
358
 
387
 set_seg_base:
359
 set_seg_base:
388
 	rolw	$4, %ax
360
 	rolw	$4, %ax
396
 #endif /* KEEP_IT_REAL */
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
  * Copy bytes
373
  * Copy bytes
402
  *
374
  *
411
  *   None
383
  *   None
412
  ****************************************************************************
384
  ****************************************************************************
413
  */
385
  */
386
+#if ! COMPRESS
414
 	.section ".prefix.lib", "awx", @progbits
387
 	.section ".prefix.lib", "awx", @progbits
415
 	.code16
388
 	.code16
416
 copy_bytes:
389
 copy_bytes:
419
 	popl %ecx
392
 	popl %ecx
420
 	ret
393
 	ret
421
 	.size copy_bytes, . - copy_bytes
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
  * Install block to specified address
400
  * Install block to specified address
427
  *
401
  *
439
 	.section ".prefix.lib", "awx", @progbits
413
 	.section ".prefix.lib", "awx", @progbits
440
 	.code16
414
 	.code16
441
 install_block:
415
 install_block:
442
-	
443
-#ifdef KEEP_IT_REAL
444
-
445
 	/* Preserve registers */
416
 	/* Preserve registers */
446
 	pushw	%ds
417
 	pushw	%ds
447
 	pushw	%es
418
 	pushw	%es
448
 	pushl	%ecx
419
 	pushl	%ecx
449
 	pushl	%edi
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
 	shrl	$4, %esi
423
 	shrl	$4, %esi
453
 	movw	%si, %ds
424
 	movw	%si, %ds
454
 	xorw	%si, %si
425
 	xorw	%si, %si
426
+	shll	$4, %esi
455
 	shrl	$4, %edi
427
 	shrl	$4, %edi
456
 	movw	%di, %es
428
 	movw	%di, %es
457
 	xorw	%di, %di
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
 #if COMPRESS
432
 #if COMPRESS
476
 	/* Decompress source to destination */
433
 	/* Decompress source to destination */
477
 	call	decompress16
434
 	call	decompress16
492
 	addl	$0xf, %esi
449
 	addl	$0xf, %esi
493
 	andl	$~0xf, %esi
450
 	andl	$~0xf, %esi
494
 
451
 
495
-
496
-#ifdef KEEP_IT_REAL
497
-
498
 	/* Convert %ds:esi back to a physical address */
452
 	/* Convert %ds:esi back to a physical address */
499
-	movzwl	%ds, %cx
453
+	xorl	%ecx, %ecx
454
+	movw	%ds, %cx
500
 	shll	$4, %ecx
455
 	shll	$4, %ecx
501
 	addl	%ecx, %esi
456
 	addl	%ecx, %esi
502
 
457
 
503
-	/* Restore registers */
458
+	/* Restore registers and return */
504
 	popl	%edi
459
 	popl	%edi
505
 	popl	%ecx
460
 	popl	%ecx
506
 	popw	%es
461
 	popw	%es
507
 	popw	%ds
462
 	popw	%ds
508
-
509
-#else /* KEEP_IT_REAL */
510
-
511
-	/* Restore registers */
512
-	popl	%edi
513
-	popl	%ecx
514
-
515
-#endif
516
-
517
 	ret
463
 	ret
518
 	.size install_block, . - install_block
464
 	.size install_block, . - install_block
519
-	
465
+
520
 /****************************************************************************
466
 /****************************************************************************
521
- * alloc_basemem (real-mode near call)
467
+ * alloc_basemem
522
  *
468
  *
523
  * Allocate space for .text16 and .data16 from top of base memory.
469
  * Allocate space for .text16 and .data16 from top of base memory.
524
  * Memory is allocated using the BIOS free base memory counter at
470
  * Memory is allocated using the BIOS free base memory counter at
568
 	.size alloc_basemem, . - alloc_basemem
514
 	.size alloc_basemem, . - alloc_basemem
569
 
515
 
570
 /****************************************************************************
516
 /****************************************************************************
571
- * free_basemem (real-mode near call)
517
+ * free_basemem
572
  *
518
  *
573
  * Free space allocated with alloc_basemem.
519
  * Free space allocated with alloc_basemem.
574
  *
520
  *
620
 	.size	hooked_bios_interrupts, . - hooked_bios_interrupts
566
 	.size	hooked_bios_interrupts, . - hooked_bios_interrupts
621
 
567
 
622
 /****************************************************************************
568
 /****************************************************************************
623
- * install (real-mode near call)
569
+ * install
624
  *
570
  *
625
  * Install all text and data segments.
571
  * Install all text and data segments.
626
  *
572
  *
655
 	.size install, . - install
601
 	.size install, . - install
656
 
602
 
657
 /****************************************************************************
603
 /****************************************************************************
658
- * install_prealloc (real-mode near call)
604
+ * install_prealloc
659
  *
605
  *
660
  * Install all text and data segments.
606
  * Install all text and data segments.
661
  *
607
  *
680
 	/* Sanity: clear the direction flag asap */
626
 	/* Sanity: clear the direction flag asap */
681
 	cld
627
 	cld
682
 
628
 
629
+#ifndef KEEP_IT_REAL
630
+	/* Flatten real mode */
631
+	call	flatten_real_mode
632
+#endif
633
+
683
 	/* Calculate physical address of payload (i.e. first source) */
634
 	/* Calculate physical address of payload (i.e. first source) */
684
 	testl	%esi, %esi
635
 	testl	%esi, %esi
685
 	jnz	1f
636
 	jnz	1f
732
 
683
 
733
 	/* Copy code to new location */
684
 	/* Copy code to new location */
734
 	pushl	%edi
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
 	popl	%edi
689
 	popl	%edi
740
 
690
 
741
 	/* Initialise librm at new location */
691
 	/* Initialise librm at new location */
742
 	lcall	*init_librm_vector
692
 	lcall	*init_librm_vector
743
-
744
 #endif
693
 #endif
694
+
745
 	/* Restore registers */
695
 	/* Restore registers */
746
 	popw	%es
696
 	popw	%es
747
 	popw	%ds
697
 	popw	%ds
749
 	ret
699
 	ret
750
 	.size install_prealloc, . - install_prealloc
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
 	.section ".data16", "aw", @progbits
705
 	.section ".data16", "aw", @progbits
754
 #ifdef KEEP_IT_REAL
706
 #ifdef KEEP_IT_REAL
755
 init_libkir_vector:
707
 init_libkir_vector:
768
 #endif
720
 #endif
769
 
721
 
770
 /****************************************************************************
722
 /****************************************************************************
771
- * uninstall (real-mode near call)
723
+ * uninstall
772
  *
724
  *
773
  * Uninstall all text and data segments.
725
  * Uninstall all text and data segments.
774
  *
726
  *

Loading…
Cancel
Save