@@ -485,20 +485,63 @@ 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+ let pt_entry = ( boot_lvl2_lower_addr | 3 ) . to_le_bytes ( ) ;
528+ let lvl1_idx = Aarch64 :: lvl1_index ( start_addr) ;
529+ let start = 8 * lvl1_idx;
530+ let end = 8 * ( lvl1_idx + 1 ) ;
531+ boot_lvl1_lower[ start..end] . copy_from_slice ( & pt_entry) ;
532+
533+ // map the loader 1:1 access into 2MB blocks
534+ let lvl2_idx = Aarch64 :: lvl2_index ( start_addr) ;
535+ for i in lvl2_idx ..= Aarch64 :: lvl2_index ( end_addr) {
536+ let entry_idx = ( i - Aarch64 :: lvl2_index ( start_addr) ) << AARCH64_2MB_BLOCK_BITS ;
537+ let pt_entry: u64 = ( entry_idx as u64 + start_addr) |
538+ ( 1 << 10 ) | // Access flag
539+ ( 3 << 8 ) | // Sharable
540+ ( 3 << 2 ) | // MT_NORMAL memory
541+ ( 1 << 0 ) ; // 2M block
499542 let start = 8 * i;
500543 let end = 8 * ( i + 1 ) ;
501- boot_lvl1_lower [ start..end] . copy_from_slice ( & pt_entry. to_le_bytes ( ) ) ;
544+ boot_lvl2_lower [ start..end] . copy_from_slice ( & pt_entry. to_le_bytes ( ) ) ;
502545 }
503546
504547 let boot_lvl0_upper: [ u8 ; PAGE_TABLE_SIZE ] = [ 0 ; PAGE_TABLE_SIZE ] ;
@@ -536,6 +579,7 @@ impl<'a> Loader<'a> {
536579 ( boot_lvl0_upper_addr, boot_lvl0_upper_size, boot_lvl0_upper) ,
537580 ( boot_lvl1_upper_addr, boot_lvl1_upper_size, boot_lvl1_upper) ,
538581 ( boot_lvl2_upper_addr, boot_lvl2_upper_size, boot_lvl2_upper) ,
582+ ( boot_lvl2_lower_addr, boot_lvl2_lower_size, boot_lvl2_lower) ,
539583 ]
540584 }
541585}
0 commit comments