xref: /DragonBoot/src/arch/riscv64/relocate.rs (revision 1971aeeee1b8252821527c319e1327d93b88ffc4)
1*1971aeeeSLoGin use core::{ffi::c_void, hint::spin_loop, ptr};
2*1971aeeeSLoGin 
3*1971aeeeSLoGin #[derive(Debug, Clone, PartialEq, Eq)]
4*1971aeeeSLoGin struct Dyn {
5*1971aeeeSLoGin     pub d_tag: i64,
6*1971aeeeSLoGin     pub(super) d_un: u64,
7*1971aeeeSLoGin }
8*1971aeeeSLoGin 
9*1971aeeeSLoGin impl Dyn {
d_val(&self) -> u6410*1971aeeeSLoGin     pub fn d_val(&self) -> u64 {
11*1971aeeeSLoGin         self.d_un
12*1971aeeeSLoGin     }
13*1971aeeeSLoGin 
d_ptr(&self) -> u6414*1971aeeeSLoGin     pub fn d_ptr(&self) -> u64 {
15*1971aeeeSLoGin         self.d_un
16*1971aeeeSLoGin     }
17*1971aeeeSLoGin }
18*1971aeeeSLoGin 
19*1971aeeeSLoGin #[no_mangle]
efi_relocate(ldbase: u64, elf_dyn: *mut c_void) -> usize20*1971aeeeSLoGin unsafe extern "C" fn efi_relocate(ldbase: u64, elf_dyn: *mut c_void) -> usize {
21*1971aeeeSLoGin     let elf_dyn = elf_dyn as *mut Dyn;
22*1971aeeeSLoGin     return do_relocate(ldbase, elf_dyn).0 as usize;
23*1971aeeeSLoGin }
24*1971aeeeSLoGin 
do_relocate(ldbase: u64, elf_dyn: *mut Dyn) -> uefi::Status25*1971aeeeSLoGin unsafe fn do_relocate(ldbase: u64, elf_dyn: *mut Dyn) -> uefi::Status {
26*1971aeeeSLoGin     let mut relsz = 0;
27*1971aeeeSLoGin     let mut relent = 0;
28*1971aeeeSLoGin     let mut rel: *mut elf::relocation::Elf64_Rela = ptr::null_mut();
29*1971aeeeSLoGin 
30*1971aeeeSLoGin     let mut item = elf_dyn;
31*1971aeeeSLoGin 
32*1971aeeeSLoGin     while (*item).d_tag != elf::abi::DT_NULL {
33*1971aeeeSLoGin         match (*item).d_tag {
34*1971aeeeSLoGin             elf::abi::DT_RELA => {
35*1971aeeeSLoGin                 rel = (*item).d_ptr() as *mut elf::relocation::Elf64_Rela;
36*1971aeeeSLoGin             }
37*1971aeeeSLoGin             elf::abi::DT_RELASZ => {
38*1971aeeeSLoGin                 relsz = (*item).d_val();
39*1971aeeeSLoGin             }
40*1971aeeeSLoGin             elf::abi::DT_RELAENT => {
41*1971aeeeSLoGin                 relent = (*item).d_val();
42*1971aeeeSLoGin             }
43*1971aeeeSLoGin             _ => {}
44*1971aeeeSLoGin         }
45*1971aeeeSLoGin         item = (item as usize + core::mem::size_of::<Dyn>()) as *mut Dyn;
46*1971aeeeSLoGin     }
47*1971aeeeSLoGin 
48*1971aeeeSLoGin     if rel.is_null() && (relent == 0) {
49*1971aeeeSLoGin         return uefi::Status::SUCCESS;
50*1971aeeeSLoGin     }
51*1971aeeeSLoGin 
52*1971aeeeSLoGin     if rel.is_null() || relent == 0 {
53*1971aeeeSLoGin         return uefi::Status::LOAD_ERROR;
54*1971aeeeSLoGin     }
55*1971aeeeSLoGin 
56*1971aeeeSLoGin     while relsz > 0 {
57*1971aeeeSLoGin         match ((*rel).r_info & 0xFF) as u32 {
58*1971aeeeSLoGin             elf::abi::R_RISCV_RELATIVE => {
59*1971aeeeSLoGin                 let addr = ldbase + (*rel).r_offset as u64;
60*1971aeeeSLoGin                 let sym_addr = ldbase + (*rel).r_addend as u64;
61*1971aeeeSLoGin                 let addr_ptr = addr as *mut u64;
62*1971aeeeSLoGin                 *addr_ptr = sym_addr;
63*1971aeeeSLoGin             }
64*1971aeeeSLoGin             _ => {
65*1971aeeeSLoGin                 /* Panic */
66*1971aeeeSLoGin                 loop {
67*1971aeeeSLoGin                     spin_loop();
68*1971aeeeSLoGin                 }
69*1971aeeeSLoGin             }
70*1971aeeeSLoGin         }
71*1971aeeeSLoGin         rel = (rel as usize + relent as usize) as *mut elf::relocation::Elf64_Rela;
72*1971aeeeSLoGin         relsz -= relent;
73*1971aeeeSLoGin     }
74*1971aeeeSLoGin 
75*1971aeeeSLoGin     return uefi::Status::SUCCESS;
76*1971aeeeSLoGin }
77