Pārlūkot izejas kodu

relocate the DragonBoot (#3)

LoGin 5 mēneši atpakaļ
vecāks
revīzija
1971aeeee1

+ 1 - 0
Cargo.toml

@@ -11,6 +11,7 @@ build = "build.rs"
 log = "0.4.20"
 uefi = { version = "0.26.0", features = ["alloc"] }
 uefi-services = "0.23.0"
+elf = { version = "0.7.2", default-features = false }
 
 [build-dependencies]
 dragon_boot_build = { path = "build-scripts/dragon_boot_build" }

+ 7 - 4
src/arch/riscv64/crt0-efi-riscv64.S

@@ -152,10 +152,10 @@ _start:
 	sd			ra, 16(sp)
 
 	/* Run relocation */
-	// lla			a0, ImageBase
-	// lla			a1, _DYNAMIC
-	// call		_relocate
-	// bne			a0, zero, 0f
+	lla			a0, ImageBase
+	lla			a1, _DYNAMIC
+	call		efi_relocate
+	bne			a0, zero, 0f
 
 	/* Call EFI code */
 	ld			a1, 8(sp)
@@ -166,3 +166,6 @@ _start:
 
 0:	addi		sp, sp, 24
 	ret
+
+_DYNAMIC:
+    .long 0

+ 1 - 1
src/arch/riscv64/mod.rs

@@ -1 +1 @@
-
+mod relocate;

+ 76 - 0
src/arch/riscv64/relocate.rs

@@ -0,0 +1,76 @@
+use core::{ffi::c_void, hint::spin_loop, ptr};
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+struct Dyn {
+    pub d_tag: i64,
+    pub(super) d_un: u64,
+}
+
+impl Dyn {
+    pub fn d_val(&self) -> u64 {
+        self.d_un
+    }
+
+    pub fn d_ptr(&self) -> u64 {
+        self.d_un
+    }
+}
+
+#[no_mangle]
+unsafe extern "C" fn efi_relocate(ldbase: u64, elf_dyn: *mut c_void) -> usize {
+    let elf_dyn = elf_dyn as *mut Dyn;
+    return do_relocate(ldbase, elf_dyn).0 as usize;
+}
+
+unsafe fn do_relocate(ldbase: u64, elf_dyn: *mut Dyn) -> uefi::Status {
+    let mut relsz = 0;
+    let mut relent = 0;
+    let mut rel: *mut elf::relocation::Elf64_Rela = ptr::null_mut();
+
+    let mut item = elf_dyn;
+
+    while (*item).d_tag != elf::abi::DT_NULL {
+        match (*item).d_tag {
+            elf::abi::DT_RELA => {
+                rel = (*item).d_ptr() as *mut elf::relocation::Elf64_Rela;
+            }
+            elf::abi::DT_RELASZ => {
+                relsz = (*item).d_val();
+            }
+            elf::abi::DT_RELAENT => {
+                relent = (*item).d_val();
+            }
+            _ => {}
+        }
+        item = (item as usize + core::mem::size_of::<Dyn>()) as *mut Dyn;
+    }
+
+    if rel.is_null() && (relent == 0) {
+        return uefi::Status::SUCCESS;
+    }
+
+    if rel.is_null() || relent == 0 {
+        return uefi::Status::LOAD_ERROR;
+    }
+
+    while relsz > 0 {
+        match ((*rel).r_info & 0xFF) as u32 {
+            elf::abi::R_RISCV_RELATIVE => {
+                let addr = ldbase + (*rel).r_offset as u64;
+                let sym_addr = ldbase + (*rel).r_addend as u64;
+                let addr_ptr = addr as *mut u64;
+                *addr_ptr = sym_addr;
+            }
+            _ => {
+                /* Panic */
+                loop {
+                    spin_loop();
+                }
+            }
+        }
+        rel = (rel as usize + relent as usize) as *mut elf::relocation::Elf64_Rela;
+        relsz -= relent;
+    }
+
+    return uefi::Status::SUCCESS;
+}

+ 1 - 0
src/lib.rs

@@ -7,6 +7,7 @@ use core::{
     fmt::{Formatter, Write},
 };
 extern crate alloc;
+extern crate elf;
 
 use alloc::string::String;
 use log::info;