@@ -343,3 +343,249 @@ where
343
343
None
344
344
}
345
345
}
346
+
347
+ #[ cfg( test) ]
348
+ mod tests {
349
+ use super :: * ;
350
+ use bootloader_api:: info:: MemoryRegionKind ;
351
+
352
+ #[ derive( Copy , Clone , Debug ) ]
353
+ struct TestMemoryRegion {
354
+ start : PhysAddr ,
355
+ len : u64 ,
356
+ kind : MemoryRegionKind ,
357
+ }
358
+
359
+ impl LegacyMemoryRegion for TestMemoryRegion {
360
+ fn start ( & self ) -> PhysAddr {
361
+ self . start
362
+ }
363
+
364
+ fn len ( & self ) -> u64 {
365
+ assert ! ( self . len % 4096 == 0 ) ;
366
+ self . len
367
+ }
368
+
369
+ fn kind ( & self ) -> MemoryRegionKind {
370
+ self . kind
371
+ }
372
+
373
+ fn usable_after_bootloader_exit ( & self ) -> bool {
374
+ match self . kind {
375
+ MemoryRegionKind :: Usable => true ,
376
+ _ => false ,
377
+ }
378
+ }
379
+ }
380
+
381
+ // we need some kind of max phys memory, 4GB seems reasonable
382
+ const MAX_PHYS_ADDR : u64 = 0x4000_0000 ;
383
+
384
+ fn create_single_test_region ( ) -> Vec < TestMemoryRegion > {
385
+ vec ! [ TestMemoryRegion {
386
+ start: PhysAddr :: new( 0 ) ,
387
+ len: MAX_PHYS_ADDR ,
388
+ kind: MemoryRegionKind :: Usable ,
389
+ } ]
390
+ }
391
+
392
+ #[ test]
393
+ fn test_kernel_and_ram_in_same_region ( ) {
394
+ let regions = create_single_test_region ( ) ;
395
+ let mut allocator = LegacyFrameAllocator :: new ( regions. into_iter ( ) ) ;
396
+ // allocate at least 1 frame
397
+ allocator. allocate_frame ( ) ;
398
+
399
+ let mut regions = [ MaybeUninit :: uninit ( ) ; 10 ] ;
400
+ let kernel_slice_start = PhysAddr :: new ( 0x50000 ) ;
401
+ let kernel_slice_len = 0x1000 ;
402
+ let ramdisk_slice_start = Some ( PhysAddr :: new ( 0x60000 ) ) ;
403
+ let ramdisk_slice_len = 0x2000 ;
404
+
405
+ let kernel_regions = allocator. construct_memory_map (
406
+ & mut regions,
407
+ kernel_slice_start,
408
+ kernel_slice_len,
409
+ ramdisk_slice_start,
410
+ ramdisk_slice_len,
411
+ ) ;
412
+ let mut kernel_regions = kernel_regions. iter ( ) ;
413
+ // usable memory before the kernel
414
+ assert_eq ! (
415
+ kernel_regions. next( ) ,
416
+ Some ( & MemoryRegion {
417
+ start: 0x0000 ,
418
+ end: 0x50000 ,
419
+ kind: MemoryRegionKind :: Usable
420
+ } )
421
+ ) ;
422
+ // kernel
423
+ assert_eq ! (
424
+ kernel_regions. next( ) ,
425
+ Some ( & MemoryRegion {
426
+ start: 0x50000 ,
427
+ end: 0x51000 ,
428
+ kind: MemoryRegionKind :: Bootloader
429
+ } )
430
+ ) ;
431
+ // usabel memory between kernel and ramdisk
432
+ assert_eq ! (
433
+ kernel_regions. next( ) ,
434
+ Some ( & MemoryRegion {
435
+ start: 0x51000 ,
436
+ end: 0x60000 ,
437
+ kind: MemoryRegionKind :: Usable
438
+ } )
439
+ ) ;
440
+ // ramdisk
441
+ assert_eq ! (
442
+ kernel_regions. next( ) ,
443
+ Some ( & MemoryRegion {
444
+ start: 0x60000 ,
445
+ end: 0x62000 ,
446
+ kind: MemoryRegionKind :: Bootloader
447
+ } )
448
+ ) ;
449
+ // usabele memory after ramdisk, up until bootloader allocated memory
450
+ assert_eq ! (
451
+ kernel_regions. next( ) ,
452
+ Some ( & MemoryRegion {
453
+ start: 0x62000 ,
454
+ end: 0x10_0000 ,
455
+ kind: MemoryRegionKind :: Usable
456
+ } )
457
+ ) ;
458
+ // bootloader allocated memory
459
+ assert_eq ! (
460
+ kernel_regions. next( ) ,
461
+ Some ( & MemoryRegion {
462
+ start: 0x10_0000 ,
463
+ end: 0x10_1000 ,
464
+ kind: MemoryRegionKind :: Bootloader
465
+ } )
466
+ ) ;
467
+ // rest is free
468
+ assert_eq ! (
469
+ kernel_regions. next( ) ,
470
+ Some ( & MemoryRegion {
471
+ start: 0x10_1000 ,
472
+ end: MAX_PHYS_ADDR ,
473
+ kind: MemoryRegionKind :: Usable
474
+ } )
475
+ ) ;
476
+ assert_eq ! ( kernel_regions. next( ) , None ) ;
477
+ }
478
+
479
+ #[ test]
480
+ fn test_multiple_regions ( ) {
481
+ let regions = vec ! [
482
+ TestMemoryRegion {
483
+ start: PhysAddr :: new( 0 ) ,
484
+ len: 0x10_0000 ,
485
+ kind: MemoryRegionKind :: Usable ,
486
+ } ,
487
+ TestMemoryRegion {
488
+ start: PhysAddr :: new( 0x10_0000 ) ,
489
+ len: 0x5000 ,
490
+ kind: MemoryRegionKind :: UnknownBios ( 0 ) ,
491
+ } ,
492
+ TestMemoryRegion {
493
+ start: PhysAddr :: new( 0x10_5000 ) ,
494
+ len: MAX_PHYS_ADDR - 0x10_5000 ,
495
+ kind: MemoryRegionKind :: Usable ,
496
+ } ,
497
+ ] ;
498
+ let mut allocator = LegacyFrameAllocator :: new ( regions. into_iter ( ) ) ;
499
+ // allocate at least 1 frame
500
+ allocator. allocate_frame ( ) ;
501
+
502
+ let mut regions = [ MaybeUninit :: uninit ( ) ; 10 ] ;
503
+ let kernel_slice_start = PhysAddr :: new ( 0x50000 ) ;
504
+ let kernel_slice_len = 0x1000 ;
505
+ let ramdisk_slice_start = Some ( PhysAddr :: new ( 0x60000 ) ) ;
506
+ let ramdisk_slice_len = 0x2000 ;
507
+
508
+ let kernel_regions = allocator. construct_memory_map (
509
+ & mut regions,
510
+ kernel_slice_start,
511
+ kernel_slice_len,
512
+ ramdisk_slice_start,
513
+ ramdisk_slice_len,
514
+ ) ;
515
+ let mut kernel_regions = kernel_regions. iter ( ) ;
516
+
517
+ // usable memory before the kernel
518
+ assert_eq ! (
519
+ kernel_regions. next( ) ,
520
+ Some ( & MemoryRegion {
521
+ start: 0x0000 ,
522
+ end: 0x50000 ,
523
+ kind: MemoryRegionKind :: Usable
524
+ } )
525
+ ) ;
526
+ // kernel
527
+ assert_eq ! (
528
+ kernel_regions. next( ) ,
529
+ Some ( & MemoryRegion {
530
+ start: 0x50000 ,
531
+ end: 0x51000 ,
532
+ kind: MemoryRegionKind :: Bootloader
533
+ } )
534
+ ) ;
535
+ // usabel memory between kernel and ramdisk
536
+ assert_eq ! (
537
+ kernel_regions. next( ) ,
538
+ Some ( & MemoryRegion {
539
+ start: 0x51000 ,
540
+ end: 0x60000 ,
541
+ kind: MemoryRegionKind :: Usable
542
+ } )
543
+ ) ;
544
+ // ramdisk
545
+ assert_eq ! (
546
+ kernel_regions. next( ) ,
547
+ Some ( & MemoryRegion {
548
+ start: 0x60000 ,
549
+ end: 0x62000 ,
550
+ kind: MemoryRegionKind :: Bootloader
551
+ } )
552
+ ) ;
553
+ // usabele memory after ramdisk, up until bootloader allocated memory
554
+ assert_eq ! (
555
+ kernel_regions. next( ) ,
556
+ Some ( & MemoryRegion {
557
+ start: 0x62000 ,
558
+ end: 0x10_0000 ,
559
+ kind: MemoryRegionKind :: Usable
560
+ } )
561
+ ) ;
562
+ // the unknown bios region
563
+ assert_eq ! (
564
+ kernel_regions. next( ) ,
565
+ Some ( & MemoryRegion {
566
+ start: 0x10_0000 ,
567
+ end: 0x10_5000 ,
568
+ kind: MemoryRegionKind :: UnknownBios ( 0 )
569
+ } )
570
+ ) ;
571
+ // bootloader allocated memory, this gets pushed back by the bios region
572
+ assert_eq ! (
573
+ kernel_regions. next( ) ,
574
+ Some ( & MemoryRegion {
575
+ start: 0x10_5000 ,
576
+ end: 0x10_6000 ,
577
+ kind: MemoryRegionKind :: Bootloader
578
+ } )
579
+ ) ;
580
+ // rest is free
581
+ assert_eq ! (
582
+ kernel_regions. next( ) ,
583
+ Some ( & MemoryRegion {
584
+ start: 0x10_6000 ,
585
+ end: MAX_PHYS_ADDR ,
586
+ kind: MemoryRegionKind :: Usable
587
+ } )
588
+ ) ;
589
+ assert_eq ! ( kernel_regions. next( ) , None ) ;
590
+ }
591
+ }
0 commit comments