11use alloc:: boxed:: Box ;
2+ use alloc:: vec:: Vec ;
23use elf_rs:: { ElfFile , ProgramHeaderEntry , ProgramType } ;
4+ use log:: { debug, info} ;
35use multiboot2:: {
4- BootLoaderNameTag , CommandLineTag , MaybeDynSized , MemoryArea , MemoryAreaType , MemoryMapTag ,
5- ModuleTag , SmbiosTag ,
6+ BootLoaderNameTag , CommandLineTag , EFIMemoryAreaType , MaybeDynSized , MemoryArea ,
7+ MemoryAreaType , MemoryMapTag , ModuleTag , SmbiosTag ,
68} ;
79
10+ fn get_free_mmap_areas (
11+ mbi : & multiboot2:: BootInformation ,
12+ ) -> Vec < ( u64 /* start */ , u64 /* size */ ) > {
13+ match ( mbi. memory_map_tag ( ) , mbi. efi_memory_map_tag ( ) ) {
14+ ( Some ( mmt) , None ) => mmt
15+ . memory_areas ( )
16+ . iter ( )
17+ . filter ( |ma| ma. typ ( ) == MemoryAreaType :: Available )
18+ . map ( |ma| ( ma. start_address ( ) , ma. size ( ) ) )
19+ . collect :: < alloc:: vec:: Vec < _ > > ( ) ,
20+ ( _, Some ( mmt) ) => mmt
21+ . memory_areas ( )
22+ . filter ( |ma| ma. ty == EFIMemoryAreaType :: CONVENTIONAL )
23+ . map ( |ma| ( ma. phys_start , ma. page_count * 4096 ) )
24+ . collect :: < alloc:: vec:: Vec < _ > > ( ) ,
25+ _ => panic ! ( "No usable memory map" ) ,
26+ }
27+ }
28+
29+ fn assert_load_segment_fits_into_memory (
30+ start : u64 ,
31+ size : u64 ,
32+ free_areas : & [ ( u64 /* start */ , u64 /* size */ ) ] ,
33+ ) {
34+ let end = start + size;
35+ let range = free_areas
36+ . iter ( )
37+ . find ( |( a_start, a_size) | start >= * a_start && end <= a_start + a_size) ;
38+ if let Some ( range) = range {
39+ debug ! ( "Can load load segment (0x{start:x?}, {size:x?}) into free memory area {range:#x?}" ) ;
40+ } else {
41+ panic ! ( "Can't load load segment (0x{start:x?}, {size:x?}) into any area!" ) ;
42+ }
43+ }
44+
845/// Loads the first module into memory. Assumes that the module is a ELF file.
946/// The handoff is performed according to the Multiboot2 spec.
10- pub fn load_module ( mut modules : multiboot:: information:: ModuleIter ) -> ! {
47+ pub fn load_module ( mbi : & multiboot2:: BootInformation ) -> ! {
48+ let mut modules = mbi. module_tags ( ) ;
49+
1150 // Load the ELF from the Multiboot1 boot module.
1251 let elf_mod = modules. next ( ) . expect ( "Should have payload" ) ;
1352 let elf_bytes = unsafe {
1453 core:: slice:: from_raw_parts (
15- elf_mod. start as * const u64 as * const u8 ,
16- ( elf_mod. end - elf_mod . start ) as usize ,
54+ elf_mod. start_address ( ) as * const u64 as * const u8 ,
55+ elf_mod. module_size ( ) as usize ,
1756 )
1857 } ;
1958 let elf = elf_rs:: Elf32 :: from_bytes ( elf_bytes) . expect ( "Should be valid ELF" ) ;
@@ -28,10 +67,11 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
2867 log:: info!( "Multiboot2 header:\n {hdr:#?}" ) ;
2968 }
3069
31- // Map the load segments into memory (at their corresponding link).
70+ // Load the load segments into memory (at their corresponding link address ).
3271 {
33- let elf = elf_rs :: Elf32 :: from_bytes ( elf_bytes ) . expect ( "Should be valid ELF" ) ;
72+ let free_areas = get_free_mmap_areas ( mbi ) ;
3473 elf. program_header_iter ( )
74+ . inspect ( |ph| assert_load_segment_fits_into_memory ( ph. vaddr ( ) , ph. memsz ( ) , & free_areas) )
3575 . filter ( |ph| ph. ph_type ( ) == ProgramType :: LOAD )
3676 . for_each ( |ph| {
3777 map_memory ( ph) ;
@@ -53,9 +93,9 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
5393 MemoryAreaType :: Reserved ,
5494 ) ] ) )
5595 . add_module ( ModuleTag :: new (
56- elf_mod. start as u32 ,
57- elf_mod. end as u32 ,
58- elf_mod. string . unwrap ( ) ,
96+ elf_mod. start_address ( ) ,
97+ elf_mod. end_address ( ) ,
98+ elf_mod. cmdline ( ) . unwrap ( ) ,
5999 ) )
60100 // Test that we can add SmbiosTag multiple times.
61101 . add_smbios ( SmbiosTag :: new ( 1 , 1 , & [ 1 , 2 , 3 ] ) )
@@ -66,7 +106,7 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
66106
67107 log:: info!(
68108 "Handing over to ELF: {}" ,
69- elf_mod. string . unwrap_or( "<unknown>" )
109+ elf_mod. cmdline ( ) . unwrap_or( "<unknown>" )
70110 ) ;
71111
72112 // handoff
@@ -84,7 +124,7 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
84124/// address space. The loader assumes that the addresses to not clash with the
85125/// loader (or anything else).
86126fn map_memory ( ph : ProgramHeaderEntry ) {
87- log :: debug!( "Mapping LOAD segment {ph:#?}" ) ;
127+ debug ! ( "Mapping LOAD segment {ph:#?}" ) ;
88128 let dest_ptr = ph. vaddr ( ) as * mut u8 ;
89129 let content = ph. content ( ) . expect ( "Should have content" ) ;
90130 unsafe { core:: ptr:: copy ( content. as_ptr ( ) , dest_ptr, content. len ( ) ) } ;
0 commit comments