|
@@ -267,6 +267,322 @@ patch_1m_16m:
|
267
|
267
|
ret
|
268
|
268
|
.size patch_1m_16m, . - patch_1m_16m
|
269
|
269
|
|
|
270
|
+/****************************************************************************
|
|
271
|
+ * Get underlying e820 memory region to underlying_e820 buffer
|
|
272
|
+ *
|
|
273
|
+ * Parameters:
|
|
274
|
+ * As for INT 15,e820
|
|
275
|
+ * Returns:
|
|
276
|
+ * As for INT 15,e820
|
|
277
|
+ *
|
|
278
|
+ * Wraps the underlying INT 15,e820 call so that the continuation
|
|
279
|
+ * value (%ebx) is a 16-bit simple sequence counter (with the high 16
|
|
280
|
+ * bits ignored), and termination is always via CF=1 rather than
|
|
281
|
+ * %ebx=0.
|
|
282
|
+ *
|
|
283
|
+ ****************************************************************************
|
|
284
|
+ */
|
|
285
|
+ .section ".text16"
|
|
286
|
+get_underlying_e820:
|
|
287
|
+
|
|
288
|
+ /* If the requested region is in the cache, return it */
|
|
289
|
+ cmpw %bx, underlying_e820_index
|
|
290
|
+ jne 1f
|
|
291
|
+ pushw %di
|
|
292
|
+ pushw %si
|
|
293
|
+ movw $underlying_e820_cache, %si
|
|
294
|
+ movw $20, %cx
|
|
295
|
+ rep movsb
|
|
296
|
+ popw %si
|
|
297
|
+ popw %di
|
|
298
|
+ movw $20, %cx
|
|
299
|
+ incw %bx
|
|
300
|
+ movl %edx, %eax
|
|
301
|
+ ret
|
|
302
|
+1:
|
|
303
|
+ /* If the requested region is earlier than the cached region,
|
|
304
|
+ * invalidate the cache.
|
|
305
|
+ */
|
|
306
|
+ cmpw %bx, underlying_e820_index
|
|
307
|
+ jbe 1f
|
|
308
|
+ movw $0xffff, underlying_e820_index
|
|
309
|
+1:
|
|
310
|
+ /* If the cache is invalid, reset the underlying %ebx */
|
|
311
|
+ cmpw $0xffff, underlying_e820_index
|
|
312
|
+ jne 1f
|
|
313
|
+ andl $0, underlying_e820_ebx
|
|
314
|
+1:
|
|
315
|
+ /* If the cache is valid but the continuation value is zero,
|
|
316
|
+ * this means that the previous underlying call returned with
|
|
317
|
+ * %ebx=0. Return with CF=1 in this case.
|
|
318
|
+ */
|
|
319
|
+ cmpw $0xffff, underlying_e820_index
|
|
320
|
+ je 1f
|
|
321
|
+ cmpl $0, underlying_e820_ebx
|
|
322
|
+ jne 1f
|
|
323
|
+ stc
|
|
324
|
+ ret
|
|
325
|
+1:
|
|
326
|
+ /* Get the next region into the cache */
|
|
327
|
+ pushl %eax
|
|
328
|
+ pushl %ebx
|
|
329
|
+ pushl %ecx
|
|
330
|
+ pushl %edx
|
|
331
|
+ movl underlying_e820_ebx, %ebx
|
|
332
|
+ stc
|
|
333
|
+ pushfw
|
|
334
|
+ lcall *%cs:int15_vector
|
|
335
|
+ jc 1f /* CF set: error */
|
|
336
|
+ cmpl $SMAP, %eax
|
|
337
|
+ je 2f /* 'SMAP' missing: error */
|
|
338
|
+1: /* An error occurred: return values returned by underlying e820 call */
|
|
339
|
+ stc /* Force CF set if SMAP was missing */
|
|
340
|
+ leal 16(%esp), %esp /* avoid changing other flags */
|
|
341
|
+ ret
|
|
342
|
+2: /* No error occurred */
|
|
343
|
+ movl %ebx, underlying_e820_ebx
|
|
344
|
+ popl %edx
|
|
345
|
+ popl %ecx
|
|
346
|
+ popl %ebx
|
|
347
|
+ popl %eax
|
|
348
|
+ /* Copy result to cache */
|
|
349
|
+ pushw %es
|
|
350
|
+ pushw %fs
|
|
351
|
+ pushw %si
|
|
352
|
+ pushw %di
|
|
353
|
+ pushw %cx
|
|
354
|
+ pushw %es
|
|
355
|
+ popw %fs
|
|
356
|
+ movw %di, %si
|
|
357
|
+ pushw %ds
|
|
358
|
+ popw %es
|
|
359
|
+ movw $underlying_e820_cache, %di
|
|
360
|
+ movw $20, %cx
|
|
361
|
+ fs rep movsb
|
|
362
|
+ popw %cx
|
|
363
|
+ popw %di
|
|
364
|
+ popw %si
|
|
365
|
+ popw %fs
|
|
366
|
+ popw %es
|
|
367
|
+ /* Mark cache as containing this result */
|
|
368
|
+ incw underlying_e820_index
|
|
369
|
+
|
|
370
|
+ /* Loop until found */
|
|
371
|
+ jmp get_underlying_e820
|
|
372
|
+ .size get_underlying_e820, . - get_underlying_e820
|
|
373
|
+
|
|
374
|
+ .section ".data16"
|
|
375
|
+underlying_e820_index:
|
|
376
|
+ .word 0xffff /* Initialise to an invalid value */
|
|
377
|
+ .size underlying_e820_index, . - underlying_e820_index
|
|
378
|
+
|
|
379
|
+ .section ".bss16"
|
|
380
|
+underlying_e820_ebx:
|
|
381
|
+ .long 0
|
|
382
|
+ .size underlying_e820_ebx, . - underlying_e820_ebx
|
|
383
|
+
|
|
384
|
+ .section ".bss16"
|
|
385
|
+underlying_e820_cache:
|
|
386
|
+ .space 20
|
|
387
|
+ .size underlying_e820_cache, . - underlying_e820_cache
|
|
388
|
+
|
|
389
|
+/****************************************************************************
|
|
390
|
+ * Get windowed e820 region, without empty region stripping
|
|
391
|
+ *
|
|
392
|
+ * Parameters:
|
|
393
|
+ * As for INT 15,e820
|
|
394
|
+ * Returns:
|
|
395
|
+ * As for INT 15,e820
|
|
396
|
+ *
|
|
397
|
+ * Wraps the underlying INT 15,e820 call so that each underlying
|
|
398
|
+ * region is returned N times, windowed to fit within N visible-memory
|
|
399
|
+ * windows. Termination is always via CF=1.
|
|
400
|
+ *
|
|
401
|
+ ****************************************************************************
|
|
402
|
+ */
|
|
403
|
+
|
|
404
|
+ .section ".tbl.data16.memory_windows.00"
|
|
405
|
+ .align 16
|
|
406
|
+memory_windows:
|
|
407
|
+
|
|
408
|
+ // Dummy memory window encompassing entire 64-bit address space
|
|
409
|
+ .long 0, 0, 0xffffffff, 0xffffffff
|
|
410
|
+
|
|
411
|
+ .section ".tbl.data16.memory_windows.99"
|
|
412
|
+ .align 16
|
|
413
|
+memory_windows_end:
|
|
414
|
+
|
|
415
|
+ .section ".text16"
|
|
416
|
+get_windowed_e820:
|
|
417
|
+
|
|
418
|
+ /* Preserve registers */
|
|
419
|
+ pushl %esi
|
|
420
|
+ pushw %bp
|
|
421
|
+
|
|
422
|
+ /* Split %ebx into %si:%bx, store original %bx in %bp */
|
|
423
|
+ pushl %ebx
|
|
424
|
+ xorl %esi, %esi
|
|
425
|
+ popw %bp
|
|
426
|
+ popw %si
|
|
427
|
+
|
|
428
|
+ /* %si == 0 => start of memory_windows list */
|
|
429
|
+ testw %si, %si
|
|
430
|
+ jne 1f
|
|
431
|
+ movw $memory_windows, %si
|
|
432
|
+1:
|
|
433
|
+ /* Get (cached) underlying e820 region to buffer */
|
|
434
|
+ call get_underlying_e820
|
|
435
|
+ jc 99f /* Abort on error */
|
|
436
|
+
|
|
437
|
+ /* Preserve registers */
|
|
438
|
+ pushal
|
|
439
|
+ /* start => %edx:%eax, len => %ecx:%ebx */
|
|
440
|
+ movl %es:0(%di), %eax
|
|
441
|
+ movl %es:4(%di), %edx
|
|
442
|
+ movl %es:8(%di), %ebx
|
|
443
|
+ movl %es:12(%di), %ecx
|
|
444
|
+ /* Convert (start,len) to (start, end) */
|
|
445
|
+ addl %eax, %ebx
|
|
446
|
+ adcl %edx, %ecx
|
|
447
|
+ /* Truncate to window start */
|
|
448
|
+ cmpl 4(%esi), %edx
|
|
449
|
+ jne 1f
|
|
450
|
+ cmpl 0(%esi), %eax
|
|
451
|
+1: jae 2f
|
|
452
|
+ movl 4(%esi), %edx
|
|
453
|
+ movl 0(%esi), %eax
|
|
454
|
+2: /* Truncate to window end */
|
|
455
|
+ cmpl 12(%esi), %ecx
|
|
456
|
+ jne 1f
|
|
457
|
+ cmpl 8(%esi), %ebx
|
|
458
|
+1: jbe 2f
|
|
459
|
+ movl 12(%esi), %ecx
|
|
460
|
+ movl 8(%esi), %ebx
|
|
461
|
+2: /* Convert (start, end) back to (start, len) */
|
|
462
|
+ subl %eax, %ebx
|
|
463
|
+ sbbl %edx, %ecx
|
|
464
|
+ /* If length is <0, set length to 0 */
|
|
465
|
+ jae 1f
|
|
466
|
+ xorl %ebx, %ebx
|
|
467
|
+ xorl %ecx, %ecx
|
|
468
|
+1: /* Store modified values in e820 map entry */
|
|
469
|
+ movl %eax, %es:0(%di)
|
|
470
|
+ movl %edx, %es:4(%di)
|
|
471
|
+ movl %ebx, %es:8(%di)
|
|
472
|
+ movl %ecx, %es:12(%di)
|
|
473
|
+ /* Restore registers */
|
|
474
|
+ popal
|
|
475
|
+
|
|
476
|
+ /* Derive continuation value for next call */
|
|
477
|
+ addw $16, %si
|
|
478
|
+ cmpw $memory_windows_end, %si
|
|
479
|
+ jne 1f
|
|
480
|
+ /* End of memory windows: reset %si and allow %bx to continue */
|
|
481
|
+ xorw %si, %si
|
|
482
|
+ jmp 2f
|
|
483
|
+1: /* More memory windows to go: restore original %bx */
|
|
484
|
+ movw %bp, %bx
|
|
485
|
+2: /* Construct %ebx from %si:%bx */
|
|
486
|
+ pushw %si
|
|
487
|
+ pushw %bx
|
|
488
|
+ popl %ebx
|
|
489
|
+
|
|
490
|
+98: /* Clear CF */
|
|
491
|
+ clc
|
|
492
|
+99: /* Restore registers and return */
|
|
493
|
+ popw %bp
|
|
494
|
+ popl %esi
|
|
495
|
+ ret
|
|
496
|
+ .size get_windowed_e820, . - get_windowed_e820
|
|
497
|
+
|
|
498
|
+/****************************************************************************
|
|
499
|
+ * Get windowed e820 region, with empty region stripping
|
|
500
|
+ *
|
|
501
|
+ * Parameters:
|
|
502
|
+ * As for INT 15,e820
|
|
503
|
+ * Returns:
|
|
504
|
+ * As for INT 15,e820
|
|
505
|
+ *
|
|
506
|
+ * Wraps the underlying INT 15,e820 call so that each underlying
|
|
507
|
+ * region is returned up to N times, windowed to fit within N
|
|
508
|
+ * visible-memory windows. Empty windows are never returned.
|
|
509
|
+ * Termination is always via CF=1.
|
|
510
|
+ *
|
|
511
|
+ ****************************************************************************
|
|
512
|
+ */
|
|
513
|
+ .section ".text16"
|
|
514
|
+get_nonempty_e820:
|
|
515
|
+
|
|
516
|
+ /* Record entry parameters */
|
|
517
|
+ pushl %eax
|
|
518
|
+ pushl %ecx
|
|
519
|
+ pushl %edx
|
|
520
|
+
|
|
521
|
+ /* Get next windowed region */
|
|
522
|
+ call get_windowed_e820
|
|
523
|
+ jc 99f /* abort on error */
|
|
524
|
+
|
|
525
|
+ /* If region is non-empty, finish here */
|
|
526
|
+ cmpl $0, %es:8(%di)
|
|
527
|
+ jne 98f
|
|
528
|
+ cmpl $0, %es:12(%di)
|
|
529
|
+ jne 98f
|
|
530
|
+
|
|
531
|
+ /* Region was empty: restore entry parameters and go to next region */
|
|
532
|
+ popl %edx
|
|
533
|
+ popl %ecx
|
|
534
|
+ popl %eax
|
|
535
|
+ jmp get_nonempty_e820
|
|
536
|
+
|
|
537
|
+98: /* Clear CF */
|
|
538
|
+ clc
|
|
539
|
+99: /* Return values from underlying call */
|
|
540
|
+ leal 12(%esp), %esp /* avoid changing flags */
|
|
541
|
+ ret
|
|
542
|
+ .size get_nonempty_e820, . - get_nonempty_e820
|
|
543
|
+
|
|
544
|
+/****************************************************************************
|
|
545
|
+ * Get mangled e820 region, with empty region stripping
|
|
546
|
+ *
|
|
547
|
+ * Parameters:
|
|
548
|
+ * As for INT 15,e820
|
|
549
|
+ * Returns:
|
|
550
|
+ * As for INT 15,e820
|
|
551
|
+ *
|
|
552
|
+ * Wraps the underlying INT 15,e820 call so that underlying regions
|
|
553
|
+ * are windowed to the allowed memory regions. Empty regions are
|
|
554
|
+ * stripped from the map. Termination is always via %ebx=0.
|
|
555
|
+ *
|
|
556
|
+ ****************************************************************************
|
|
557
|
+ */
|
|
558
|
+ .section ".text16"
|
|
559
|
+get_mangled_e820:
|
|
560
|
+
|
|
561
|
+ /* Get a nonempty region */
|
|
562
|
+ call get_nonempty_e820
|
|
563
|
+ jc 99f /* Abort on error */
|
|
564
|
+
|
|
565
|
+ /* Peek ahead to see if there are any further nonempty regions */
|
|
566
|
+ pushal
|
|
567
|
+ subw $20, %sp
|
|
568
|
+ movl $0xe820, %eax
|
|
569
|
+ movl $SMAP, %edx
|
|
570
|
+ movl $20, %ecx
|
|
571
|
+ pushw %ss
|
|
572
|
+ popw %es
|
|
573
|
+ movw %sp, %di
|
|
574
|
+ call get_nonempty_e820
|
|
575
|
+ leal 20(%esp), %esp /* avoid changing flags */
|
|
576
|
+ popal
|
|
577
|
+ jnc 99f /* There are further nonempty regions */
|
|
578
|
+
|
|
579
|
+ /* No futher nonempty regions: zero %ebx and clear CF */
|
|
580
|
+ xorl %ebx, %ebx
|
|
581
|
+
|
|
582
|
+99: /* Return */
|
|
583
|
+ ret
|
|
584
|
+ .size get_mangled_e820, . - get_mangled_e820
|
|
585
|
+
|
270
|
586
|
/****************************************************************************
|
271
|
587
|
* Patch E820 memory map entry
|
272
|
588
|
*
|
|
@@ -298,7 +614,7 @@ patch_e820:
|
298
|
614
|
/****************************************************************************
|
299
|
615
|
* Split E820 memory map entry if necessary
|
300
|
616
|
*
|
301
|
|
- * Parameters:
|
|
617
|
+ * Parameters:
|
302
|
618
|
* As for INT 15,e820
|
303
|
619
|
* Returns:
|
304
|
620
|
* As for INT 15,e820
|
|
@@ -318,7 +634,16 @@ split_e820:
|
318
|
634
|
jnz 1f
|
319
|
635
|
movl %ebx, %cs:real_ebx
|
320
|
636
|
1: movl %cs:real_ebx, %ebx
|
321
|
|
- lcall *%cs:int15_vector
|
|
637
|
+
|
|
638
|
+// lcall *%cs:int15_vector
|
|
639
|
+ /* Hacked in call to get_mangled_e820 in place of underlying INT15 */
|
|
640
|
+ popfw
|
|
641
|
+ pushw %ds
|
|
642
|
+ pushw %cs:rm_ds
|
|
643
|
+ popw %ds
|
|
644
|
+ call get_mangled_e820
|
|
645
|
+ popw %ds
|
|
646
|
+
|
322
|
647
|
pushfw
|
323
|
648
|
/* Edit result */
|
324
|
649
|
pushw %ds
|