Browse Source

[romprefix] Use smaller PMM allocations if possible

The only way that PMM allows us to request a block in a region with
A20=0 is to ask for a block with an alignment of 2MB.  Due to the PMM
API design, the only way we can do this is to ask for a block with a
size of 2MB.

Unfortunately, some BIOSes will hit problems if we allocate a 2MB
block.  In particular, it may not be possible to enter the BIOS setup
screen; the BIOS setup code attempts a PMM allocation, fails, and
hangs the machine.

We now try allocating only as much as we need via PMM.  If the
allocated block has A20=1, we free the allocated block, double the
allocation size, and try again.  Repeat until either we obtain a block
with A20=0 or allocation fails.  (This is guaranteed to terminate by
the time we reach an allocation size of 2MB.)
tags/v0.9.6
Michael Brown 15 years ago
parent
commit
2ca2607b1b
1 changed files with 41 additions and 7 deletions
  1. 41
    7
      src/arch/i386/prefix/romprefix.S

+ 41
- 7
src/arch/i386/prefix/romprefix.S View File

@@ -14,6 +14,7 @@
14 14
 #define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
15 15
 #define PNP_GET_BBS_VERSION 0x60
16 16
 #define PMM_ALLOCATE 0x0000
17
+#define PMM_DEALLOCATE 0x0002
17 18
 
18 19
 /* ROM banner timeout.  Based on the configurable BANNER_TIMEOUT in
19 20
  * config.h, but converted to a number of (18Hz) timer ticks, and
@@ -290,21 +291,52 @@ pmm_scan:
290 291
 	movw	$init_message_pmm, %si
291 292
 	xorw	%di, %di
292 293
 	call	print_message
293
-	/* Try to allocate 2MB block via PMM */
294
+	/* We have PMM and so a 1kB stack: preserve upper register halves */
295
+	pushal
296
+	/* Calculate required allocation size in %esi */
297
+	movzbl	romheader_size, %eax
298
+	shll	$9, %eax
299
+	addl	$_textdata_memsz, %eax
300
+	orw	$0xffff, %ax	/* Ensure allocation size is at least 64kB */
301
+	bsrl	%eax, %ecx
302
+	subw	$15, %cx	/* Round up and convert to 64kB count */
303
+	movw	$1, %si
304
+	shlw	%cl, %si
305
+pmm_loop:
306
+	/* Try to allocate block via PMM */
294 307
 	pushw	$0x0006		/* Aligned, extended memory */
295 308
 	pushl	$0xffffffff	/* No handle */
296
-	pushl	$( 0x00200000 / 16 ) /* 2MB in paragraphs */
309
+	movzwl	%si, %eax
310
+	shll	$12, %eax
311
+	pushl	%eax		/* Allocation size in paragraphs */
297 312
 	pushw	$PMM_ALLOCATE
298 313
 	lcall	*%es:7
299 314
 	addw	$12, %sp
315
+	/* Abort if allocation fails */
316
+	testw	%dx, %dx	/* %ax==0 even on success, since align>=64kB */
317
+	jz	pmm_fail
318
+	/* If block has A20==1, free block and try again with twice
319
+	 * the allocation size (and hence alignment).
320
+	 */
321
+	testw	$0x0010, %dx
322
+	jz	got_pmm
323
+	pushw	%dx
324
+	pushw	$0
325
+	pushw	$PMM_DEALLOCATE
326
+	lcall	*%es:7
327
+	addw	$6, %sp
328
+	addw	%si, %si
329
+	jmp	pmm_loop
330
+got_pmm: /* PMM allocation succeeded */
331
+	movw	%dx, ( image_source + 2 )
300 332
 	movw	%dx, %ax
301 333
 	xorw	%di, %di
302 334
 	call	print_hex_word
303
-	movw	%dx, ( image_source + 2 )
304
-	testw	%dx, %dx	/* %ax==0 even on success, since align=2MB */
305
-	jz	no_pmm
306
-	/* PMM allocation succeeded: copy ROM to PMM block */
307
-	pushal			/* PMM presence implies 1kB stack */
335
+	movb	$'@', %al
336
+	call	print_character
337
+	movw	%si, %ax
338
+	call	print_hex_byte
339
+	/* Copy ROM to PMM block */
308 340
 	xorw	%ax, %ax
309 341
 	movw	%ax, %es
310 342
 	movl	image_source, %edi
@@ -323,6 +355,8 @@ pmm_scan:
323 355
 	addb	%al, %bl
324 356
 	loop	1b
325 357
 	subb	%bl, checksum
358
+pmm_fail:
359
+	/* Restore upper register halves */
326 360
 	popal
327 361
 no_pmm:
328 362
 

Loading…
Cancel
Save