浏览代码

feat(spec): add an example for custom SBI error code (#108)

This commit enhances SBI error handling by introducing a custom error type system. It enables clear
error differentiation, extends error code support, and seamlessly integrates standard SBI errors with
project-specific conditions. This solution is also applicable to TEE SBI implementations like Penglai,
Keystone, and CoVE SBI.

The implementation provides automatic conversion via the `From` trait, explicitly handles custom error
codes (1001 and 1002), and demonstrates practical error matching patterns. It improves diagnostics,
ensures compatibility with SBI specifications, and offers a structured error management template for
Rust-based SBI projects.

Future improvements could simplify `From` implementations using derive macros from error handling crates.

Reported-by: ttzay <[email protected]>
Signed-off-by: Zhouqi Jiang <[email protected]>
Luo Jia / Zhouqi Jiang 1 月之前
父节点
当前提交
18154a8e76
共有 2 个文件被更改,包括 72 次插入0 次删除
  1. 1 0
      library/sbi-spec/CHANGELOG.md
  2. 71 0
      library/sbi-spec/examples/custom-sbi-error.rs

+ 1 - 0
library/sbi-spec/CHANGELOG.md

@@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 - examples: an SBI version example for usage of the Version structure
 - base: add special constant `V1_0` and `V2_0` for structure `Version`
 - examples: add an example on non-usize `HartMask` structure
+- examples: add an example for custom SBI error code
 
 ### Modified
 

+ 71 - 0
library/sbi-spec/examples/custom-sbi-error.rs

@@ -0,0 +1,71 @@
+/// This example demonstrates how to define custom error types and map SBI error codes.
+///
+/// The code shows:
+/// - How to create a custom error enum that wraps standard SBI errors and adds custom error codes
+/// - Conversion logic between standard SBI errors and custom error types
+/// - Error handling patterns using Rust's Result type and error matching
+use sbi_spec::binary::{Error, SbiRet};
+
+/// Custom error type for SBI-related operations
+///
+/// Contains three possible variants:
+/// - Standard: Wraps standard SBI errors from the sbi_spec crate
+/// - MyErrorCode1/MyErrorCode2: Custom error codes specific to this implementation
+pub enum MyError {
+    /// Wrapper for standard SBI errors defined in sbi_spec
+    Standard(sbi_spec::binary::Error),
+    /// First custom error code (maps to value 1001)
+    MyErrorCode1,
+    /// Second custom error code (maps to value 1002)
+    MyErrorCode2,
+}
+
+/// Numeric value for first custom error code
+const MY_ERROR_CODE_1: usize = 1001;
+/// Numeric value for second custom error code
+const MY_ERROR_CODE_2: usize = 1002;
+
+/// Conversion implementation from standard SBI errors to our custom error type
+///
+/// This allows automatic conversion when using the ? operator in functions returning MyError.
+/// The conversion logic:
+/// - Maps specific custom error codes to their corresponding MyError variants
+/// - Wraps all other standard errors in the Standard variant
+impl From<sbi_spec::binary::Error> for MyError {
+    fn from(value: Error) -> Self {
+        match value {
+            // Handle custom error code mappings
+            Error::Custom(MY_ERROR_CODE_1) => MyError::MyErrorCode1,
+            Error::Custom(MY_ERROR_CODE_2) => MyError::MyErrorCode2,
+            // Wrap all other standard errors
+            _ => MyError::Standard(value),
+        }
+    }
+}
+
+/// Main function demonstrating error handling workflow
+///
+/// The execution flow:
+/// 1. Creates an SbiRet structure with success status
+/// 2. Manually sets an error code for demonstration
+/// 3. Converts the SbiRet to Result type with custom error mapping
+/// 4. Pattern matches on the result to handle different error cases
+fn main() {
+    // Create a base SbiRet with success status (value = 0)
+    let mut ret = SbiRet::success(0);
+    // Override the error code for demonstration purposes
+    ret.error = 1001;
+
+    // Convert SbiRet to Result, mapping error codes to MyError variants
+    let ans = ret.map_err(MyError::from);
+
+    // Handle different error cases through pattern matching
+    match ans {
+        Ok(_) => println!("Okay"),
+        // Match specific custom error codes
+        Err(MyError::MyErrorCode1) => println!("Custom error code 1"),
+        Err(MyError::MyErrorCode2) => println!("Custom error code 2"),
+        // Handle wrapped standard SBI errors
+        Err(MyError::Standard(err)) => println!("Standard error: {:?}", err),
+    }
+}