1 use core::ptr::addr_of; 2 3 /// 向控制台打印字符串。 4 /// 5 /// 该函数接受一个字节切片 `s` 作为输入,并迭代切片中的每个字节 `c`。 6 /// 然后调用 `sbi_rt::console_write_byte` 函数,将 `c` 的值作为参数传递给它。 7 /// 8 /// # 安全性 9 /// 10 /// 这个函数是安全的,因为对SBI环境的操作不涉及不安全内存的访问操作。 11 /// 12 /// # 参数 13 /// 14 /// * `s` - 表示要打印的字符串的字节切片。 15 /// 16 /// # 示例 17 /// 18 /// ``` 19 /// let message = b"Hello, World!"; 20 /// console_putstr(message); 21 /// ``` 22 pub fn console_putstr(s: &[u8]) { 23 if SbiDriver::extensions().contains(SBIExtensions::CONSOLE) { 24 for c in s { 25 sbi_rt::console_write_byte(*c); 26 } 27 return; 28 } else { 29 for c in s { 30 #[allow(deprecated)] 31 sbi_rt::legacy::console_putchar(*c as usize); 32 } 33 } 34 } 35 36 bitflags! { 37 pub struct SBIExtensions: u64 { 38 /// RISC-V SBI Base extension. 39 const BASE = 1 << 0; 40 /// Timer programmer extension. 41 const TIME = 1 << 1; 42 /// Inter-processor Interrupt extension. 43 const SPI = 1 << 2; 44 /// Remote Fence extension. 45 const RFENCE = 1 << 3; 46 /// Hart State Monitor extension. 47 const HSM = 1 << 4; 48 /// System Reset extension. 49 const RESET = 1 << 5; 50 /// Performance Monitoring Unit extension. 51 const PMU = 1 << 6; 52 /// Debug Console extension. 53 const CONSOLE = 1 << 7; 54 /// System Suspend extension. 55 const SUSPEND = 1 << 8; 56 /// SBI CPPC extension. 57 const CPPC = 1 << 9; 58 /// Nested Acceleration extension. 59 const NACL = 1 << 10; 60 /// Steal-time Accounting extension. 61 const STA = 1 << 11; 62 } 63 } 64 65 static mut EXTENSIONS: SBIExtensions = SBIExtensions::empty(); 66 67 #[derive(Debug)] 68 pub struct SbiDriver; 69 70 impl SbiDriver { 71 #[inline(never)] 72 pub fn early_init() { 73 unsafe { 74 EXTENSIONS = Self::probe_extensions(); 75 } 76 } 77 78 /// 获取probe得到的SBI扩展信息。 79 pub fn extensions() -> &'static SBIExtensions { 80 unsafe { addr_of!(EXTENSIONS).as_ref().unwrap() } 81 } 82 83 fn probe_extensions() -> SBIExtensions { 84 let mut extensions = SBIExtensions::empty(); 85 if sbi_rt::probe_extension(sbi_rt::Base).is_available() { 86 extensions |= SBIExtensions::BASE; 87 } 88 if sbi_rt::probe_extension(sbi_rt::Timer).is_available() { 89 extensions |= SBIExtensions::TIME; 90 } 91 92 if sbi_rt::probe_extension(sbi_rt::Ipi).is_available() { 93 extensions |= SBIExtensions::SPI; 94 } 95 96 if sbi_rt::probe_extension(sbi_rt::Fence).is_available() { 97 extensions |= SBIExtensions::RFENCE; 98 } 99 100 if sbi_rt::probe_extension(sbi_rt::Hsm).is_available() { 101 extensions |= SBIExtensions::HSM; 102 } 103 104 if sbi_rt::probe_extension(sbi_rt::Reset).is_available() { 105 extensions |= SBIExtensions::RESET; 106 } 107 108 if sbi_rt::probe_extension(sbi_rt::Pmu).is_available() { 109 extensions |= SBIExtensions::PMU; 110 } 111 112 if sbi_rt::probe_extension(sbi_rt::Console).is_available() { 113 extensions |= SBIExtensions::CONSOLE; 114 } 115 116 if sbi_rt::probe_extension(sbi_rt::Suspend).is_available() { 117 extensions |= SBIExtensions::SUSPEND; 118 } 119 120 if sbi_rt::probe_extension(sbi_rt::Cppc).is_available() { 121 extensions |= SBIExtensions::CPPC; 122 } 123 124 if sbi_rt::probe_extension(sbi_rt::Nacl).is_available() { 125 extensions |= SBIExtensions::NACL; 126 } 127 128 if sbi_rt::probe_extension(sbi_rt::Sta).is_available() { 129 extensions |= SBIExtensions::STA; 130 } 131 132 return extensions; 133 } 134 } 135