|
@@ -16,7 +16,14 @@ FILE_LICENCE ( GPL2_OR_LATER )
|
16
|
16
|
#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
|
17
|
17
|
#define PNP_GET_BBS_VERSION 0x60
|
18
|
18
|
#define PMM_ALLOCATE 0x0000
|
19
|
|
-#define PMM_DEALLOCATE 0x0002
|
|
19
|
+#define PMM_FIND 0x0001
|
|
20
|
+#define PMM_HANDLE_BASE ( ( ( 'F' - 'A' + 1 ) << 26 ) + \
|
|
21
|
+ ( ( 'E' - 'A' + 1 ) << 21 ) + \
|
|
22
|
+ ( ( 'N' - 'A' + 1 ) << 16 ) )
|
|
23
|
+#define PMM_HANDLE_BASE_IMAGE_SOURCE \
|
|
24
|
+ ( PMM_HANDLE_BASE | 0x00001000 )
|
|
25
|
+#define PMM_HANDLE_BASE_DECOMPRESS_TO \
|
|
26
|
+ ( PMM_HANDLE_BASE | 0x00002000 )
|
20
|
27
|
|
21
|
28
|
/* ROM banner timeout. Based on the configurable BANNER_TIMEOUT in
|
22
|
29
|
* config.h, but converted to a number of (18Hz) timer ticks, and
|
|
@@ -310,65 +317,44 @@ pmm_scan:
|
310
|
317
|
movw $init_message_pmm, %si
|
311
|
318
|
xorw %di, %di
|
312
|
319
|
call print_message
|
313
|
|
- /* We have PMM and so a 1kB stack: preserve upper register halves */
|
|
320
|
+ /* We have PMM and so a 1kB stack: preserve whole registers */
|
314
|
321
|
pushal
|
315
|
|
- /* Calculate required allocation size in %esi */
|
316
|
|
- movzbl romheader_size, %eax
|
317
|
|
- shll $9, %eax
|
318
|
|
- addl $_textdata_memsz, %eax
|
319
|
|
- orw $0xffff, %ax /* Ensure allocation size is at least 64kB */
|
320
|
|
- bsrl %eax, %ecx
|
321
|
|
- subw $15, %cx /* Round up and convert to 64kB count */
|
322
|
|
- movw $1, %si
|
323
|
|
- shlw %cl, %si
|
324
|
|
-pmm_loop:
|
325
|
|
- /* Try to allocate block via PMM */
|
326
|
|
- pushw $0x0006 /* Aligned, extended memory */
|
327
|
|
- pushl $0xffffffff /* No handle */
|
328
|
|
- movzwl %si, %eax
|
329
|
|
- shll $12, %eax
|
330
|
|
- pushl %eax /* Allocation size in paragraphs */
|
331
|
|
- pushw $PMM_ALLOCATE
|
332
|
|
- lcall *%es:7
|
333
|
|
- addw $12, %sp
|
334
|
|
- /* Abort if allocation fails */
|
335
|
|
- testw %dx, %dx /* %ax==0 even on success, since align>=64kB */
|
336
|
|
- jz pmm_fail
|
337
|
|
- /* If block has A20==1, free block and try again with twice
|
338
|
|
- * the allocation size (and hence alignment).
|
339
|
|
- */
|
340
|
|
- testw $0x0010, %dx
|
341
|
|
- jz got_pmm
|
342
|
|
- pushw %dx
|
343
|
|
- pushw $0
|
344
|
|
- pushw $PMM_DEALLOCATE
|
345
|
|
- lcall *%es:7
|
346
|
|
- addw $6, %sp
|
347
|
|
- addw %si, %si
|
348
|
|
- jmp pmm_loop
|
349
|
|
-got_pmm: /* PMM allocation succeeded */
|
350
|
|
- movw %dx, ( image_source + 2 )
|
351
|
|
- movw %dx, %ax
|
352
|
|
- xorw %di, %di
|
353
|
|
- call print_hex_word
|
354
|
|
- movb $( '@' ), %al
|
355
|
|
- call print_character
|
356
|
|
- movw %si, %ax
|
357
|
|
- call print_hex_byte
|
358
|
|
- /* Copy ROM to PMM block */
|
|
322
|
+ /* Allocate image source PMM block */
|
|
323
|
+ movzbl romheader_size, %ecx
|
|
324
|
+ shll $5, %ecx
|
|
325
|
+ movl $PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx
|
|
326
|
+ movw $get_pmm_image_source, %bp
|
|
327
|
+ call get_pmm
|
|
328
|
+ movl %esi, image_source
|
|
329
|
+ jc 1f
|
|
330
|
+ /* Copy ROM to image source PMM block */
|
|
331
|
+ pushw %es
|
359
|
332
|
xorw %ax, %ax
|
360
|
333
|
movw %ax, %es
|
361
|
|
- movl image_source, %edi
|
|
334
|
+ movl %esi, %edi
|
362
|
335
|
xorl %esi, %esi
|
363
|
336
|
movzbl romheader_size, %ecx
|
364
|
337
|
shll $9, %ecx
|
365
|
338
|
addr32 rep movsb /* PMM presence implies flat real mode */
|
366
|
|
- movl %edi, decompress_to
|
|
339
|
+ popw %es
|
367
|
340
|
/* Shrink ROM */
|
368
|
341
|
movb shrunk_rom_size, %al
|
369
|
342
|
movb %al, romheader_size
|
370
|
|
-pmm_fail:
|
371
|
|
- /* Restore upper register halves */
|
|
343
|
+1: /* Allocate decompression PMM block. Round up the size to the
|
|
344
|
+ * nearest 128kB and use the size within the PMM handle; this
|
|
345
|
+ * allows the same decompression area to be shared between
|
|
346
|
+ * multiple iPXE ROMs even with differing build IDs
|
|
347
|
+ */
|
|
348
|
+ movl $_textdata_memsz_pgh, %ecx
|
|
349
|
+ addl $0x00001fff, %ecx
|
|
350
|
+ andl $0xffffe000, %ecx
|
|
351
|
+ movl %ecx, %ebx
|
|
352
|
+ shrw $12, %bx
|
|
353
|
+ orl $PMM_HANDLE_BASE_DECOMPRESS_TO, %ebx
|
|
354
|
+ movw $get_pmm_decompress_to, %bp
|
|
355
|
+ call get_pmm
|
|
356
|
+ movl %esi, decompress_to
|
|
357
|
+ /* Restore registers */
|
372
|
358
|
popal
|
373
|
359
|
no_pmm:
|
374
|
360
|
|
|
@@ -436,6 +422,88 @@ no_pmm:
|
436
|
422
|
lret
|
437
|
423
|
.size init, . - init
|
438
|
424
|
|
|
425
|
+/* Attempt to find or allocate PMM block
|
|
426
|
+ *
|
|
427
|
+ * Parameters:
|
|
428
|
+ * %ecx : size of block to allocate, in paragraphs
|
|
429
|
+ * %ebx : PMM handle base
|
|
430
|
+ * %bp : routine to check acceptability of found blocks
|
|
431
|
+ * %es:0000 : PMM structure
|
|
432
|
+ * Returns:
|
|
433
|
+ * %ebx : PMM handle
|
|
434
|
+ * %esi : allocated block address, or zero (with CF set) if allocation failed
|
|
435
|
+ */
|
|
436
|
+get_pmm:
|
|
437
|
+ /* Preserve registers */
|
|
438
|
+ pushl %eax
|
|
439
|
+ pushw %di
|
|
440
|
+ movw $' ', %di
|
|
441
|
+get_pmm_find:
|
|
442
|
+ /* Try to find existing block */
|
|
443
|
+ pushl %ebx /* PMM handle */
|
|
444
|
+ pushw $PMM_FIND
|
|
445
|
+ lcall *%es:7
|
|
446
|
+ addw $6, %sp
|
|
447
|
+ pushw %dx
|
|
448
|
+ pushw %ax
|
|
449
|
+ popl %esi
|
|
450
|
+ testl %esi, %esi
|
|
451
|
+ jz get_pmm_allocate
|
|
452
|
+ /* Block found - check acceptability */
|
|
453
|
+ call *%bp
|
|
454
|
+ jnc get_pmm_done
|
|
455
|
+ /* Block not acceptable - increment handle and retry */
|
|
456
|
+ incl %ebx
|
|
457
|
+ jmp get_pmm_find
|
|
458
|
+get_pmm_allocate:
|
|
459
|
+ /* Block not found - try to allocate new block */
|
|
460
|
+ pushw $0x0002 /* Extended memory */
|
|
461
|
+ pushl %ebx /* PMM handle */
|
|
462
|
+ pushl %ecx /* Length */
|
|
463
|
+ pushw $PMM_ALLOCATE
|
|
464
|
+ lcall *%es:7
|
|
465
|
+ addw $12, %sp
|
|
466
|
+ pushw %dx
|
|
467
|
+ pushw %ax
|
|
468
|
+ popl %esi
|
|
469
|
+ movw $'+', %di /* Indicate allocation attempt */
|
|
470
|
+ testl %esi, %esi
|
|
471
|
+ jnz get_pmm_done
|
|
472
|
+ stc
|
|
473
|
+get_pmm_done:
|
|
474
|
+ /* Print block address */
|
|
475
|
+ pushfw
|
|
476
|
+ movw %di, %ax
|
|
477
|
+ xorw %di, %di
|
|
478
|
+ call print_character
|
|
479
|
+ movl %esi, %eax
|
|
480
|
+ call print_hex_dword
|
|
481
|
+ popfw
|
|
482
|
+ /* Restore registers and return */
|
|
483
|
+ popw %di
|
|
484
|
+ popl %eax
|
|
485
|
+ ret
|
|
486
|
+ .size get_pmm, . - get_pmm
|
|
487
|
+
|
|
488
|
+ /* Check acceptability of image source block */
|
|
489
|
+get_pmm_image_source:
|
|
490
|
+ pushw %es
|
|
491
|
+ xorw %ax, %ax
|
|
492
|
+ movw %ax, %es
|
|
493
|
+ movl build_id, %eax
|
|
494
|
+ cmpl %es:build_id(%esi), %eax
|
|
495
|
+ je 1f
|
|
496
|
+ stc
|
|
497
|
+1: popw %es
|
|
498
|
+ ret
|
|
499
|
+ .size get_pmm_image_source, . - get_pmm_image_source
|
|
500
|
+
|
|
501
|
+ /* Check acceptability of decompression block */
|
|
502
|
+get_pmm_decompress_to:
|
|
503
|
+ clc
|
|
504
|
+ ret
|
|
505
|
+ .size get_pmm_decompress_to, . - get_pmm_decompress_to
|
|
506
|
+
|
439
|
507
|
/*
|
440
|
508
|
* Note to hardware vendors:
|
441
|
509
|
*
|
|
@@ -456,7 +524,7 @@ init_message:
|
456
|
524
|
.ascii "\n"
|
457
|
525
|
.ascii PRODUCT_NAME
|
458
|
526
|
.ascii "\n"
|
459
|
|
- .asciz "iPXE (http://ipxe.org) - "
|
|
527
|
+ .asciz "iPXE (http://ipxe.org) "
|
460
|
528
|
.size init_message, . - init_message
|
461
|
529
|
init_message_pci:
|
462
|
530
|
.asciz " PCI"
|