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