@@ -343,3 +343,249 @@ where
343343 None
344344 }
345345}
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