Browse Source

dynamic: identify magic number and version value

Signed-off-by: Zhouqi Jiang <luojia@hust.edu.cn>
Zhouqi Jiang 10 months ago
parent
commit
0a30557f64
3 changed files with 47 additions and 9 deletions
  1. 21 2
      src/dynamic.rs
  2. 25 6
      src/fail.rs
  3. 1 1
      src/main.rs

+ 21 - 2
src/dynamic.rs

@@ -27,20 +27,39 @@ pub struct DynamicInfo {
 
 const DYNAMIC_INFO_VALID_ADDRESSES: Range<usize> = 0x1000..0xf000;
 const NEXT_ADDR_VALID_ADDRESSES: Range<usize> = 0x80000000..0x90000000;
+const MAGIC: usize = 0x4942534f;
+const SUPPORTED_VERSION: Range<usize> = 2..3;
 
 pub struct DynamicReadError {
-    pub bad_paddr: usize,
+    pub bad_paddr: Option<usize>,
+    pub bad_magic: Option<usize>,
+    pub bad_version: Option<usize>,
 }
 
 // TODO unconstrained lifetime
 pub fn read_paddr(paddr: usize) -> Result<DynamicInfo, DynamicReadError> {
+    let mut error = DynamicReadError {
+        bad_paddr: None,
+        bad_magic: None,
+        bad_version: None,
+    };
     // check pointer before dereference
     if !DYNAMIC_INFO_VALID_ADDRESSES.contains(&paddr)
         || !DYNAMIC_INFO_VALID_ADDRESSES.contains(&(paddr + size_of::<DynamicInfo>()))
     {
-        return Err(DynamicReadError { bad_paddr: paddr });
+        error.bad_paddr = Some(paddr);
+        return Err(error);
     }
     let ans = unsafe { *(paddr as *const DynamicInfo) };
+    if ans.magic != MAGIC {
+        error.bad_magic = Some(ans.magic);
+    }
+    if !SUPPORTED_VERSION.contains(&ans.version) {
+        error.bad_version = Some(ans.version);
+    }
+    if error.bad_magic.is_some() || error.bad_version.is_some() {
+        return Err(error);
+    }
     Ok(ans)
 }
 

+ 25 - 6
src/fail.rs

@@ -2,8 +2,8 @@ use crate::{dynamic, reset};
 use riscv::register::mstatus;
 
 #[cold]
-pub fn invalid_dynamic_info(err: dynamic::DynamicError) -> (mstatus::MPP, usize) {
-    error!("Invalid dynamic information:");
+pub fn invalid_dynamic_data(err: dynamic::DynamicError) -> (mstatus::MPP, usize) {
+    error!("Invalid data in dynamic information:");
     if err.invalid_mpp {
         error!("- dynamic information contains invalid privilege mode");
     }
@@ -25,9 +25,28 @@ pub fn invalid_dynamic_info(err: dynamic::DynamicError) -> (mstatus::MPP, usize)
 
 #[cold]
 pub fn no_dynamic_info_available(err: dynamic::DynamicReadError) -> dynamic::DynamicInfo {
-    error!(
-        "no dynamic information available at address 0x{:x}",
-        err.bad_paddr
-    );
+    if let Some(bad_paddr) = err.bad_paddr {
+        error!(
+            "No dynamic information available at address 0x{:x}",
+            bad_paddr
+        );
+    } else {
+        error!("No valid dynamic information available:");
+        if let Some(bad_magic) = err.bad_magic {
+            error!(
+                "- tried to identify dynamic information, but found invalid magic number 0x{:x}",
+                bad_magic
+            );
+        }
+        if let Some(bad_version) = err.bad_version {
+            error!("- tries to identify version of dynamic information, but the version number {} is not supported", bad_version);
+        }
+        if err.bad_magic.is_none() {
+            error!("help: magic number is valid")
+        }
+        if err.bad_version.is_none() {
+            error!("help: dynamic information version is valid")
+        }
+    }
     reset::fail()
 }

+ 1 - 1
src/main.rs

@@ -27,7 +27,7 @@ extern "C" fn main(hart_id: usize, opaque: usize, nonstandard_a2: usize) -> usiz
 
     let info = dynamic::read_paddr(nonstandard_a2).unwrap_or_else(fail::no_dynamic_info_available);
 
-    let (mpp, next_addr) = dynamic::mpp_next_addr(&info).unwrap_or_else(fail::invalid_dynamic_info);
+    let (mpp, next_addr) = dynamic::mpp_next_addr(&info).unwrap_or_else(fail::invalid_dynamic_data);
 
     info!("Redirecting harts to 0x{:x} in {:?} mode.", next_addr, mpp);