Explorar o código

lib: amend documents

Zhouqi Jiang hai 1 ano
pai
achega
c2525281ca
Modificáronse 1 ficheiros con 164 adicións e 128 borrados
  1. 164 128
      src/lib.rs

+ 164 - 128
src/lib.rs

@@ -4,65 +4,78 @@
 //! using the [RustSBI Prototyping System](https://github.com/rustsbi/standalone)
 //! which will provide binaries for each platforms.
 //! If you are a vendor or contributor who wants to adapt RustSBI to your new product or board,
-//! you may consider adapting the Prototyping System first to get your board adapted in an afternoon;
-//! you are only advised to build a discrete crate if your team have a lot of time working on this board.*
+//! you may consider adapting the Prototyping System first to get your board adapted in a short period of time;
+//! or build a discrete crate if your team have a plenty of time working on this board.*
 //!
 //! *For more details on binary downloads the the RustSBI Prototyping System,
 //! see section [Prototyping System vs discrete packages](#download-binary-file-the-prototyping-system-vs-discrete-packages).*
 //!
-//! The crate `rustsbi` acts as core trait and instance abstraction of the RustSBI ecosystem.
+//! The crate `rustsbi` acts as core trait, extension abstraction and implementation generator
+//! of the RustSBI ecosystem.
 //!
 //! # What is RISC-V SBI?
 //!
 //! RISC-V SBI is short for RISC-V Supervisor Binary Interface. SBI acts as an interface to environment
-//! for your operating system kernel.
-//! An SBI implementation will allow furtherly bootstrap your kernel, and provide an environment while the kernel is running.
+//! for the operating system kernel.
+//! An SBI implementation will allow furtherly bootstrap the kernel, and provide a supportive environment
+//! while the kernel is running.
 //!
 //! More generally, The SBI allows supervisor-mode (S-mode or VS-mode) software to be portable across
 //! all RISC-V implementations by defining an abstraction for platform (or hypervisor) specific functionality.
 //!
-//! # Use RustSBI services in your supervisor software
+//! # Use RustSBI services in the supervisor software
 //!
-//! SBI environment features include boot sequence and a kernel environment. To bootstrap your kernel,
-//! place kernel into RustSBI implementation defined address, then RustSBI will prepare an
-//! environment and call the entry function on this address.
+//! SBI environment features include boot sequence and an S-mode environment. To bootstrap the
+//! S-mode software, the kernel (or other supervisor-lenel software) would be loaded
+//! into an implementation defined address, then RustSBI will prepare an environment and
+//! enter the S-mode software on the S-mode visible harts. If the firmware environment provides
+//! other bootloading standards upon SBI, following bootstrap process will provide further
+//! information to the supervisor software.
 //!
 //! ## Make SBI environment calls
 //!
-//! To use the kernel environment, you either use SBI calls or emulated instructions.
-//! SBI calls are similar to operating systems' `syscall`s. RISC-V SBI defined many SBI extensions,
-//! and in each extension there are different functions, you should pick a function before calling.
-//! Then, you should prepare some parameters, whose definition are not the same among functions.
+//! To use the underlying environment, the supervisor either use SBI calls or run software
+//! implemented instructions.
+//! SBI calls are similar to the system calls for operating systems. The SBI extensions, whether
+//! defined by the RISC-V SBI Specification or by custom vendors, would either consume parameters
+//! only, or defined a list of functions identified by function IDs, where the S-mode software
+//! would pick and call. Definition of parameters varies between extensions and functions.
 //!
-//! Now you have an extension number, a function number, and a few SBI call parameters.
-//! You invoke a special `ecall` instruction on supervisor level, and it will trap into machine level
-//! SBI implementation. It will handle your `ecall`, similar to your kernel handling system calls
-//! from user level.
+//! At this point, we have picked up an extension ID, a function ID, and a few SBI call parameters.
+//! Now instead of a conventinoal jump instruction, the software would invoke a special `ecall`
+//! instruction on supervisor level to transfer the control flow, resulting into a trap to the SBI
+//! environment. The SBI environment will process the `ecall` and fill in SBI call results,
+//! similar to what an operating system would handle system calls from user level.
 //!
-//! SBI functions return two values other than one. First value will be an error number,
-//! it will tell if SBI call have succeeded, or which error have occurred.
-//! Second value is the real return value, its meaning is different according to which function you calls.
+//! All SBI calls would return two integers: the error number and the return value.
+//! The error number will tell if the SBI call have been successfully proceeded, or which error
+//! have occurred. The return value indicates the result of a successful SBI call, whose
+//! meaning being different among different SBI extensions.
 //!
-//! ## Call SBI in different programming languages
+//! ## Call SBI in Rust or other programming languages
 //!
-//! Making SBI calls are similar to making system calls.
+//! Making SBI calls are similar to making system calls; RISC-V SBI calls pass extension ID,
+//! function ID (if applicable) and parameters in integer registers.
 //!
-//! Extension number is required to put on register `a7`, function number on `a6` if applicable.
+//! The extension ID is required to put on register `a7`, function ID on `a6` if applicable.
 //! Parameters should be placed from `a0` to `a5`, first into `a0`, second into `a1`, etc.
 //! Unused parameters can be set to any value or leave untouched.
 //!
-//! After registers are ready, invoke an instruction called `ecall`.
-//! Then, the return value is placed into `a0` and `a1` registers.
-//! The error value could be read from `a0`, and return value is placed into `a1`.
+//! After registers are ready, the S-mode software would invoke an `ecall` instruction.
+//! The SBI call will return two values placed in `a0` and `a1` registers;
+//! the error value could be read from `a0`, and return value is placed into `a1`.
 //!
-//! In Rust, here is an example to call SBI functions using inline assembly:
+//! In Rust, we would usually use crates like [`sbi-rt`](https://crates.io/crates/sbi-rt)
+//! to hide implementation details and focus on supervisor software development.
+//! However, if in some cases we have to write them in inline assembly, here is an example
+//! to do this:
 //!
 //! ```no_run
 //! # #[repr(C)] struct SbiRet { error: usize, value: usize }
 //! # const EXTENSION_BASE: usize = 0x10;
 //! # const FUNCTION_BASE_GET_SPEC_VERSION: usize = 0x0;
 //! #[inline(always)]
-//! fn sbi_call(extension: usize, function: usize, arg0: usize, arg1: usize) -> SbiRet {
+//! fn sbi_call_2(extension: usize, function: usize, arg0: usize, arg1: usize) -> SbiRet {
 //!     let (error, value);
 //!     match () {
 //!         #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
@@ -83,37 +96,16 @@
 //!
 //! #[inline]
 //! pub fn get_spec_version() -> SbiRet {
-//!     sbi_call(EXTENSION_BASE, FUNCTION_BASE_GET_SPEC_VERSION, 0, 0)
+//!     sbi_call_2(EXTENSION_BASE, FUNCTION_BASE_GET_SPEC_VERSION, 0, 0)
 //! }
 //! ```
 //!
-//! SBI functions would return a result thus some of these may fail.
-//! In this example we only take the value, but in complete designs we should handle the `error`
-//! returned by SbiRet.
-//!
-//! You may use other languages to call SBI environment. In C programming language, we can call like this:
-//!
-//! ```text
-//! #define SBI_CALL(ext, funct, arg0, arg1, arg2, arg3) ({ \
-//!     register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); \
-//!     register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); \
-//!     register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); \
-//!     register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); \
-//!     register uintptr_t a6 asm ("a6") = (uintptr_t)(funct); \
-//!     register uintptr_t a7 asm ("a7") = (uintptr_t)(ext); \
-//!     asm volatile ("ecall" \
-//!         : "+r" (a0), "+r" (a1) \
-//!         : "r" (a1), "r" (a2), "r" (a3), "r" (a6), "r" (a7) \
-//!         : "memory") \
-//!     {a0, a1}; \
-//! })
-//!
-//! #define SBI_CALL_0(ext, funct) SBI_CALL(ext, funct, 0, 0, 0, 0)
-//!
-//! static inline sbiret get_spec_version() {
-//!     SBI_CALL_0(EXTENSION_BASE, FUNCTION_BASE_GET_SPEC_VERSION)
-//! }
-//! ```
+//! SBI calls may fail, returning the corresponding type of error in an error code.
+//! In this example we only take the value, but in complete designs we should handle
+//! the `error` code returned by SbiRet thoroughly.
+//!
+//! In other programming languages, similiar methods may be achieved by inline assembly
+//! or other features; its documentation may suggest which is the best way to achieve this.
 //!
 //! # Implement RustSBI on machine environment
 //!
@@ -125,26 +117,27 @@
 //!
 //! Hypervisor and supervisor environment emulator developers may refer to
 //! [Hypervisor and emulator development with RustSBI](#hypervisor-and-emulator-development-with-rustsbi)
-//! for such purposes as RustSBI provide different set of features dedicated for emulated or virtual
+//! for such purposes, as RustSBI provide different set of features dedicated for emulated or virtual
 //! environments.
 //!
 //! ## Use the Prototyping System
 //!
-//! The RustSBI Prototyping System aims to get your platform working with SBI in an afternoon.
+//! The RustSBI Prototyping System aims to get your platform working with SBI in a short period of time.
 //! It supports most RISC-V platforms available by providing scalable set of drivers and features.
-//! It provides custom features such as Penglai TEE, DramForever's emulated hypervisor extension, and Raven
-//! the firmware debugger framework.
+//! It provides useful custom features such as Penglai TEE, DramForever's emulated hypervisor extension,
+//! and Raven the firmware debugger framework.
 //!
 //! You may find further documents on [RustSBI Prototyping System repository](https://github.com/rustsbi/standalone).
 //!
 //! ## Discrete RustSBI package on bare metal RISC-V hardware
 //!
 //! Discrete packages provide developers with most scalability and complete control of underlying
-//! hardware. It is ideal if advanced low power features, management cores and other features should
-//! be used in this implementation.
+//! hardware. It is ideal if detailed SoC low power features, management cores and other features
+//! would be used in the SBI implementation.
 //!
-//! RustSBI supports discrete package by default. Create a new `#![no_std]` bare-metal package
-//! to get started. Add following lines to `Cargo.toml`:
+//! RustSBI supports discrete package development out-of-box. If we are running on bare-metal, we
+//! can create a new `#![no_std]` bare-metal package, add runtime code or use runtime libraries
+//! to get started. Then, we add following lines to `Cargo.toml`:
 //!
 //! ```toml
 //! [dependencies]
@@ -152,23 +145,15 @@
 //! ```
 //!
 //! The feature `machine` indicates that RustSBI library is run directly on machine mode RISC-V
-//! environment; it will use `riscv` crate to fetch machine mode environment, which fits our demand
-//! of using it on bare metal RISC-V.
+//! environment; it will use the `riscv` crate to fetch machine mode environment information by CSR
+//! instructions, which fits our demand of using it on bare metal RISC-V.
 //!
-//! After hardware initialization process, the part of firmware with RustSBI linked should run on memory
-//! blocks with fast accesses, as it would be called frequently by operating system.
-//! If the supervisor is called by trap generator semantics, insert `rustsbi::RustSBI` structure
-//! in your hart executor structure.
+//! After hardware initialization process, the part of firmware with RustSBI linked should run on
+//! memory blocks with fast accesses, as it would be called frequently by operating system.
+//! If the implementation treats the supervisor as a generator of traps, we insert `rustsbi::RustSBI`
+//! implementation in a hart executor structure.
 //!
 //! ```rust
-//! # struct Clint;
-//! # struct MyPlatRfnc;
-//! # struct MyPlatHsm;
-//! # struct MyBoardPower;
-//! # struct MyPlatPmu;
-//! # struct MyPlatDbcn;
-//! # struct MyPlatSusp;
-//! # struct MyPlatCppc;
 //! use rustsbi::RustSBI;
 //!
 //! # struct SupervisorContext;
@@ -176,8 +161,15 @@
 //! struct Executor {
 //!     ctx: SupervisorContext,
 //!     /* other environment variables ... */
-//!     // sbi: RustSBI<Clint, Clint, MyPlatRfnc, MyPlatHsm, MyBoardPower, MyPlatPmu, MyPlatDbcn, MyPlatSusp, MyPlatCppc>,
-//!     /* custom_1: CustomSBI<...> */
+//!     sbi: MySBI,
+//!     /* custom_1: CustomSBI, ... */
+//! }
+//!
+//! #[derive(RustSBI)]
+//! struct MySBI {
+//!     console: MyConsole,
+//!     // todo: other extensions ...
+//!     info: MyEnvInfo,
 //! }
 //!
 //! # struct Trap;
@@ -192,25 +184,46 @@
 //!         todo!("fill in generic or platform specific trampoline procedure")
 //!     }
 //! }
+//! # use sbi_spec::binary::{SbiRet, Physical};
+//! # struct MyConsole;
+//! # impl rustsbi::Console for MyConsole {
+//! #     fn write(&self, _: Physical<&[u8]>) -> SbiRet { unimplemented!() }
+//! #     fn read(&self, _: Physical<&mut [u8]>) -> SbiRet { unimplemented!() }
+//! #     fn write_byte(&self, _: u8) -> SbiRet { unimplemented!() }
+//! # }
+//! # struct MyEnvInfo;
+//! # impl rustsbi::EnvInfo for MyEnvInfo {
+//! #     fn mvendorid(&self) -> usize { 1 }
+//! #     fn marchid(&self) -> usize { 2 }
+//! #     fn mimpid(&self) -> usize { 3 }
+//! # }
 //! ```
 //!
-//! After each `run()`, process the trap returned with the RustSBI instance in executor.
-//! Call `RustSBI::handle_ecall` and fill in developer provided `SupervisorContext` if necessary.
+//! After each `run()`, the SBI implmenetaion would process the trap returned with the RustSBI
+//! instance in executor. Call the function `handle_ecall` (generated by derive macro `RustSBI`)
+//! and fill in a `SupervisorContext` if necessary.
 //!
 //! ```no_run
+//! # use rustsbi::RustSBI;
 //! # use sbi_spec::binary::SbiRet;
-//! # struct RustSBI {} // Mock, prevent doc test error when feature singleton is enabled
-//! # impl RustSBI { fn handle_ecall(&self, e: (), f: (), p: ()) -> SbiRet { SbiRet::success(0) } }
-//! # struct Executor { sbi: RustSBI }
+//! # struct MyEnvInfo;
+//! # impl rustsbi::EnvInfo for MyEnvInfo {
+//! #     fn mvendorid(&self) -> usize { 1 }
+//! #     fn marchid(&self) -> usize { 2 }
+//! #     fn mimpid(&self) -> usize { 3 }
+//! # }
+//! # #[derive(RustSBI)]
+//! # struct MySBI { info: MyEnvInfo } // extensions ...
+//! # struct Executor { sbi: MySBI }
 //! # #[derive(Copy, Clone)] enum Trap { Exception(Exception) }
 //! # impl Trap { fn cause(&self) -> Self { *self } }
 //! # #[derive(Copy, Clone)] enum Exception { SupervisorEcall }
 //! # impl Executor {
-//! #     fn new(board_params: BoardParams) -> Executor { let _ = board_params; Executor { sbi: RustSBI {} } }
+//! #     fn new(board_params: BoardParams) -> Executor { let _ = board_params; Executor { sbi: MySBI { info: MyEnvInfo } } }
 //! #     fn run(&mut self) -> Trap { Trap::Exception(Exception::SupervisorEcall) }
-//! #     fn sbi_extension(&self) -> () { }
-//! #     fn sbi_function(&self) -> () { }
-//! #     fn sbi_params(&self) -> () { }
+//! #     fn sbi_extension(&self) -> usize { unimplemented!() }
+//! #     fn sbi_function(&self) -> usize { unimplemented!() }
+//! #     fn sbi_params(&self) -> [usize; 6] { unimplemented!() }
 //! #     fn fill_sbi_return(&mut self, ans: SbiRet) { let _ = ans; }
 //! # }
 //! # struct BoardParams;
@@ -246,7 +259,8 @@
 //! ```
 //!
 //! Now, call supervisor execution function in your bare metal package to finish the discrete
-//! package project.
+//! package project. Here is an example of a bare-metal entry; actual projects would either
+//! use a library for runtime, or write assemble code only if necessary.
 //!
 //! ```no_run
 //! # #[cfg(nightly)] // disable checks
@@ -298,7 +312,7 @@
 //! # fn board_init_once() {}
 //! # fn print_information_once() {}
 //! # fn execute_supervisor(_bp: &()) -> Operation { Operation::Shutdown }
-//! /// Power operation after main function
+//! /// Power operation after main function.
 //! enum Operation {
 //!     Reboot,
 //!     Shutdown,
@@ -317,7 +331,7 @@
 //! }
 //!
 //! # fn wfi() {}
-//! /// Perform board specific power operations
+//! /// Perform board specific power operations.
 //! ///
 //! /// The function here provides a stub to example power operations.
 //! /// Actual board developers should provide with more practical communications
@@ -338,7 +352,7 @@
 //! }
 //! ```
 //!
-//! Now RustSBI would run on machine environment, you may start a kernel or use an SBI test suite
+//! Now RustSBI would run on machine environment, a kernel may be started or use an SBI test suite
 //! to check if it is properly implemented.
 //!
 //! Some platforms would provide system memory under different grades in speed and size to reduce product cost.
@@ -346,7 +360,7 @@
 //! but instantly available after chip start, while the second one is larger in size but typically requires
 //! memory training. The former one would include built-in SRAM memory, and the later would include
 //! external SRAM or DDR memory. On those platforms, a first stage bootloader is typically needed to
-//! train memory for later stages. In such situation, RustSBI implementation should be linked or concatenated
+//! train memory for later stages. In such situation, RustSBI implementation should be treated as or concatenated
 //! to the second stage bootloader, and the first stage could be a standalone binary package bundled with it.
 //!
 //! # Hypervisor and emulator development with RustSBI
@@ -362,14 +376,17 @@
 //! or provide another set of information to override the current environment. Notably,
 //! RISC-V hypervisors do not have direct access to machine mode (M-mode) registers.
 //!
-//! RustSBI supports both by providing a `EnvInfo` structure in instance based interface.
-//! If RISC-V hypervisors choose to use existing information on current machine, it may require
-//! to call underlying M-mode environment using SBI calls and fill in information into `EnvInfo`.
+//! RustSBI supports both by accepting an implementation of the `EnvInfo` trait.
+//! If RISC-V hypervisors choose to use existing information on current machine,
+//! it may require to call underlying M-mode environment using SBI calls and fill in information
+//! into the variable implementing trait `EnvInfo`.
 //! If hypervisors use customized information other than taking the same one from the
-//! environment they reside in, they may fill in custom one into `EnvInfo` structures.
-//! When creating RustSBI instance, `EnvInfo` structure is required as an input of constructor.
+//! environment they reside in, they may build custom structures implementing `EnvInfo` to provide
+//! customized machine information.
+//! Deriving a RustSBI instance without bare-metal support would require an `EnvInfo` implementation
+//! as a input of the derive macro.
 //!
-//! To begin with, include RustSBI library in file `Cargo.toml`:
+//! To begin with, include the RustSBI library in file `Cargo.toml`:
 //!
 //! ```toml
 //! [dependencies]
@@ -377,21 +394,37 @@
 //! ```
 //!
 //! This will disable default feature `machine` which will assume that RustSBI runs on M-mode directly,
-//! which is not appropriate in our purpose. After that, a `RustSBI` instance may be placed
-//! in the virtual machine structure to prepare for SBI environment:
+//! which is not appropriate in our purpose. After that, define an SBI structure and derive its `RustSBI`
+//! implementation using `#[derive(RustSBI)]`. The defined SBI structure can be placed in
+//! a virtual machine structure representing a control flow executor to prepare for SBI environment:
 //!
 //! ```rust
-//! # struct RustSBI<>();
+//! use rustsbi::RustSBI;
+//!
+//! #[derive(RustSBI)]
+//! struct MySBI {
+//!     // add other fields later ...
+//!     // An environment information must be provided on
+//!     // non bare-metal RustSBI development.
+//!     info: MyEnvInfo,
+//! }
+//!
 //! struct VmHart {
 //!     // other fields ...
-//!     env: RustSBI</* Types, .. */>,
+//!     sbi: MySBI,
 //! }
+//! # struct MyEnvInfo;
+//! # impl rustsbi::EnvInfo for MyEnvInfo {
+//! #     fn mvendorid(&self) -> usize { 1 }
+//! #     fn marchid(&self) -> usize { 2 }
+//! #     fn mimpid(&self) -> usize { 3 }
+//! # }
 //! ```
 //!
 //! When the virtual machine hart traps into hypervisor, its code should decide whether
-//! this trap is an SBI environment call. If that is true, pass in parameters by `env.handle_ecall`
-//! function. RustSBI will handle with SBI standard constants, call corresponding extension module
-//! and provide parameters according to the extension and function IDs.
+//! this trap is an SBI environment call. If that is true, pass in parameters by `sbi.handle_ecall`
+//! function. RustSBI will handle with SBI standard constants, call corresponding extension field
+//! and provide parameters according to the extension and function IDs (if applicable).
 //!
 //! Crate `rustsbi` adapts to standard RISC-V SBI calls.
 //! If the hypervisor has custom SBI extensions that RustSBI does not recognize, those extension
@@ -399,16 +432,16 @@
 //!
 //! ```no_run
 //! # use sbi_spec::binary::SbiRet;
-//! # struct MyExtensionEnv {}
-//! # impl MyExtensionEnv { fn handle_ecall(&self, params: ()) -> SbiRet { SbiRet::success(0) } }
-//! # struct RustSBI {} // Mock, prevent doc test error when feature singleton is enabled
-//! # impl RustSBI { fn handle_ecall(&self, params: ()) -> SbiRet { SbiRet::success(0) } }
-//! # struct VmHart { my_extension_env: MyExtensionEnv, env: RustSBI }
+//! # struct MyExtensionSBI {}
+//! # impl MyExtensionSBI { fn handle_ecall(&self, params: ()) -> SbiRet { SbiRet::success(0) } }
+//! # struct MySBI {} // Mock, prevent doc test error when feature singleton is enabled
+//! # impl MySBI { fn handle_ecall(&self, params: ()) -> SbiRet { SbiRet::success(0) } }
+//! # struct VmHart { my_extension_sbi: MyExtensionSBI, sbi: MySBI }
 //! # #[derive(Copy, Clone)] enum Trap { Exception(Exception) }
 //! # impl Trap { fn cause(&self) -> Self { *self } }
 //! # #[derive(Copy, Clone)] enum Exception { SupervisorEcall }
 //! # impl VmHart {
-//! #     fn new() -> VmHart { VmHart { my_extension_env: MyExtensionEnv {}, env: RustSBI {} } }
+//! #     fn new() -> VmHart { VmHart { my_extension_sbi: MyExtensionSBI {}, sbi: MySBI {} } }
 //! #     fn run(&mut self) -> Trap { Trap::Exception(Exception::SupervisorEcall) }
 //! #     fn trap_params(&self) -> () { }
 //! #     fn fill_in(&mut self, ans: SbiRet) { let _ = ans; }
@@ -418,7 +451,7 @@
 //!     let trap = hart.run();
 //!     if let Trap::Exception(Exception::SupervisorEcall) = trap.cause() {
 //!         // Firstly, handle custom extensions
-//!         let my_extension_sbiret = hart.my_extension_env.handle_ecall(hart.trap_params());
+//!         let my_extension_sbiret = hart.my_extension_sbi.handle_ecall(hart.trap_params());
 //!         // If custom extension handles correctly, fill in its result and continue to hart.
 //!         // The custom handler may handle `probe_extension` in `base` extension as well
 //!         // to allow detections to whether custom extension exists.
@@ -427,7 +460,7 @@
 //!             continue;
 //!         }
 //!         // Then, if it's not a custom extension, handle it using standard SBI handler.
-//!         let standard_sbiret = hart.env.handle_ecall(hart.trap_params());
+//!         let standard_sbiret = hart.sbi.handle_ecall(hart.trap_params());
 //!         hart.fill_in(standard_sbiret);
 //!     }
 //! }
@@ -478,14 +511,16 @@
 //!
 //! ## RustSBI is a library for interfaces
 //!
-//! This library adapts to individual Rust traits to provide basic SBI features.
-//! When building for your own platform, implement traits in this library and pass them to the functions
-//! begin with `init`. After that, you may call `rustsbi::ecall`, `RustSBI::handle_ecall` or
-//! similiar functions in your own exception handler.
-//! It would dispatch parameters from supervisor to the traits to execute SBI functions.
+//! This library adapts to individual Rust traits and a derive macro to provide basic SBI features.
+//! When building for a specific platform, implement traits in this library and pass the types into
+//! a structure to derive RustSBI macro onto. After that, `handle_ecall`  would be called in the
+//! platform specific exception handler.
+//! The derive macro `RustSBI` would dispatch parameters from supervisor to the trait implementations
+//! to handle the SBI calls.
 //!
-//! The library also implements useful functions which may help with platform specific binaries.
-//! The `LOGO` can be printed if necessary when the binary is initializing.
+//! The library also implements useful constants which may help with platform specific binaries.
+//! The `LOGO` and information on `VERSION` can be printed if necessary on SBI initialization
+//! processes.
 //!
 //! Note that this crate is a library which contains common building blocks in SBI implementation.
 //! The RustSBI ecosystem would provide different level of support for each board, those support
@@ -493,14 +528,15 @@
 //!
 //! ## Hardware discovery and feature detection
 //!
-//! According to the RISC-V SBI specification, SBI itself does not specify any method for hardware discovery.
-//! The supervisor software must rely on the other industry standard hardware
-//! discovery methods (i.e. Device Tree or ACPI) for that purpose.
+//! According to the RISC-V SBI specification, the SBI itself does not specify any method for
+//! hardware discovery. The supervisor software must rely on the other industry standard hardware
+//! discovery methods (i.e. Device Tree, ACPI, vendor specific ones or upcoming `configptr` CSRs)
+//! for that purpose.
 //!
 //! To detect any feature under bare metal or under supervisor level, developers may depend on
 //! any hardware discovery methods, or use try-execute-trap method to detect any instructions or
 //! CSRs. If SBI is implemented in user level emulators, it may require to depend on operating
-//! system calls or use the signal trap method to detect any RISC-V core features.
+//! system calls or use a signal-trap procedure to detect any RISC-V core features.
 
 #![no_std]
 
@@ -527,11 +563,11 @@ pub const LOGO: &str = r".______       __    __      _______.___________.  _____
 |  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
 | _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|";
 
-// RustSBI supports RISC-V SBI specification 2.0-rc1
+// RustSBI supports RISC-V SBI specification 2.0-rc8.
 const SBI_SPEC_MAJOR: usize = 2;
 const SBI_SPEC_MINOR: usize = 0;
 
-/// RustSBI implementation ID: 4
+/// RustSBI implementation ID: 4.
 ///
 /// Ref: https://github.com/riscv-non-isa/riscv-sbi-doc/pull/61
 const IMPL_ID_RUSTSBI: usize = 4;