@@ -485,20 +485,64 @@ impl<'a> Loader<'a> {
485485 let ( boot_lvl0_upper_addr, boot_lvl0_upper_size) = elf
486486 . find_symbol ( "boot_lvl0_upper" )
487487 . expect ( "Could not find 'boot_lvl0_upper' symbol" ) ;
488+ let ( boot_lvl2_lower_addr, boot_lvl2_lower_size) = elf
489+ . find_symbol ( "boot_lvl2_lower" )
490+ . expect ( "Could not find 'boot_lvl2_lower' symbol" ) ;
491+ let ( start_addr, _) = elf
492+ . find_symbol ( "_loader_start" )
493+ . expect ( "Could not find 'loader_start' symbol" ) ;
494+ let ( end_addr, _) = elf
495+ . find_symbol ( "_loader_end" )
496+ . expect ( "Could not find 'loader_end' symbol" ) ;
497+
498+ if Aarch64 :: lvl1_index ( start_addr) != Aarch64 :: lvl1_index ( end_addr) {
499+ panic ! ( "We only map 1GiB, but elfloader paddr range covers multiple GiB" ) ;
500+ }
488501
489502 let mut boot_lvl0_lower: [ u8 ; PAGE_TABLE_SIZE ] = [ 0 ; PAGE_TABLE_SIZE ] ;
490503 boot_lvl0_lower[ ..8 ] . copy_from_slice ( & ( boot_lvl1_lower_addr | 3 ) . to_le_bytes ( ) ) ;
491504
492505 let mut boot_lvl1_lower: [ u8 ; PAGE_TABLE_SIZE ] = [ 0 ; PAGE_TABLE_SIZE ] ;
493- for i in 0 ..512 {
506+
507+ // map optional UART MMIO in l1 1GB page, only available if CONFIG_PRINTING
508+ if let Ok ( ( uart_addr, _) ) = elf. find_symbol ( "uart_addr" ) {
509+ let data = elf
510+ . get_data ( uart_addr, 8 )
511+ . expect ( "uart_addr not initialized" ) ;
512+ let uart_base = u64:: from_le_bytes ( data[ 0 ..8 ] . try_into ( ) . unwrap ( ) ) ;
513+
514+ let lvl1_idx = Aarch64 :: lvl1_index ( uart_base) ;
494515 #[ allow( clippy:: identity_op) ] // keep the (0 << 2) for clarity
495- let pt_entry: u64 = ( ( i as u64 ) << AARCH64_1GB_BLOCK_BITS ) |
516+ let pt_entry: u64 = ( ( lvl1_idx as u64 ) << AARCH64_1GB_BLOCK_BITS ) |
496517 ( 1 << 10 ) | // access flag
497518 ( 0 << 2 ) | // strongly ordered memory
498- ( 1 ) ; // 1G block
519+ ( 1 << 0 ) ; // 1G block
520+ let start = 8 * lvl1_idx;
521+ let end = 8 * ( lvl1_idx + 1 ) ;
522+ boot_lvl1_lower[ start..end] . copy_from_slice ( & pt_entry. to_le_bytes ( ) ) ;
523+ }
524+
525+ let mut boot_lvl2_lower: [ u8 ; PAGE_TABLE_SIZE ] = [ 0 ; PAGE_TABLE_SIZE ] ;
526+
527+ // 1GB lvl1 Table entry
528+ let pt_entry = ( boot_lvl2_lower_addr | 3 ) . to_le_bytes ( ) ;
529+ let lvl1_idx = Aarch64 :: lvl1_index ( start_addr) ;
530+ let start = 8 * lvl1_idx;
531+ let end = 8 * ( lvl1_idx + 1 ) ;
532+ boot_lvl1_lower[ start..end] . copy_from_slice ( & pt_entry) ;
533+
534+ // map the loader 1:1 access into 2MB lvl2 Block entries for a 4KB granule
535+ let lvl2_idx = Aarch64 :: lvl2_index ( start_addr) ;
536+ for i in lvl2_idx ..= Aarch64 :: lvl2_index ( end_addr) {
537+ let entry_idx = ( i - Aarch64 :: lvl2_index ( start_addr) ) << AARCH64_2MB_BLOCK_BITS ;
538+ let pt_entry: u64 = ( entry_idx as u64 + start_addr) |
539+ ( 1 << 10 ) | // Access flag
540+ ( 3 << 8 ) | // Sharable
541+ ( 4 << 2 ) | // MT_NORMAL memory
542+ ( 1 << 0 ) ; // 2M block
499543 let start = 8 * i;
500544 let end = 8 * ( i + 1 ) ;
501- boot_lvl1_lower [ start..end] . copy_from_slice ( & pt_entry. to_le_bytes ( ) ) ;
545+ boot_lvl2_lower [ start..end] . copy_from_slice ( & pt_entry. to_le_bytes ( ) ) ;
502546 }
503547
504548 let boot_lvl0_upper: [ u8 ; PAGE_TABLE_SIZE ] = [ 0 ; PAGE_TABLE_SIZE ] ;
@@ -536,6 +580,7 @@ impl<'a> Loader<'a> {
536580 ( boot_lvl0_upper_addr, boot_lvl0_upper_size, boot_lvl0_upper) ,
537581 ( boot_lvl1_upper_addr, boot_lvl1_upper_size, boot_lvl1_upper) ,
538582 ( boot_lvl2_upper_addr, boot_lvl2_upper_size, boot_lvl2_upper) ,
583+ ( boot_lvl2_lower_addr, boot_lvl2_lower_size, boot_lvl2_lower) ,
539584 ]
540585 }
541586}
0 commit comments