1use console::{Emoji, Style};
2use raw_cpuid::{CpuId, SgxSectionInfo};
3use std::fmt;
4
5pub struct SgxCpuInfo(CpuId);
6
7impl SgxCpuInfo {
8 pub fn new() -> Self {
9 Self { 0: CpuId::new() }
10 }
11}
12
13impl Default for SgxCpuInfo {
14 fn default() -> Self {
15 SgxCpuInfo::new()
16 }
17}
18
19impl From<SgxCpuInfo> for CpuId {
20 fn from(sgx_cpu_info: SgxCpuInfo) -> CpuId {
21 sgx_cpu_info.0
22 }
23}
24
25impl fmt::Display for SgxCpuInfo {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 writeln!(f, "# CPU features")?;
28 let feature_info = self
29 .0
30 .get_feature_info()
31 .expect("Cannot get feature information");
32 writeln!(f, "stepping {}", feature_info.stepping_id())?;
33 writeln!(
34 f,
35 "model {} (extended {})",
36 feature_info.model_id(),
37 feature_info.extended_model_id()
38 )?;
39 writeln!(
40 f,
41 "family {} (extended {})",
42 feature_info.family_id(),
43 feature_info.extended_family_id()
44 )?;
45 writeln!(
46 f,
47 "{} SMX support",
48 Emoji(&emoji(feature_info.has_smx()), "")
49 )?;
50
51 writeln!(f, "\n# Intel SGX capabilities")?;
52 let extended_features = self
53 .0
54 .get_extended_feature_info()
55 .expect("Cannot get extended features information");
56 writeln!(
57 f,
58 "{} SGX availability",
59 Emoji(&emoji(extended_features.has_sgx()), "")
60 )?;
61 writeln!(
62 f,
63 "{} SGX FLC (Flexible Launch Control)",
64 Emoji(&emoji(extended_features.has_sgx_lc()), "")
65 )?;
66 let sgx_info = self.0.get_sgx_info().expect("Cannot get SGX information");
67 writeln!(
68 f,
69 "{} SGX 1 support",
70 Emoji(&emoji(sgx_info.has_sgx1()), "")
71 )?;
72 write!(
73 f,
74 "{} SGX 2 support",
75 Emoji(&emoji(sgx_info.has_sgx2()), "")
76 )?;
77
78 if !extended_features.has_sgx_lc() {
80 let yellow = Style::new().yellow();
81 writeln!(
82 f,
83 "\n\n{} {}",
84 Emoji("⚠️", ""),
85 yellow.apply_to("Warning !")
86 )?;
87 writeln!(
88 f,
89 "This CPU does not have FLC feature, so it does not support DCAP."
90 )?;
91 writeln!(
92 f,
93 "This CPU will not be able to run SGX using in-kernel SGX driver from Linux (starting from kernel 5.11)."
94 )?;
95 write!(f, "You must use the regular SGX driver")?;
96 }
97 Ok(())
98 }
99}
100
101fn emoji(b: bool) -> String {
102 if b {
103 "✅".to_owned()
104 } else {
105 "❌".to_owned()
106 }
107}
108
109impl fmt::Debug for SgxCpuInfo {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 writeln!(f, "# CPU features")?;
112 let feature_info = self
113 .0
114 .get_feature_info()
115 .expect("Cannot get feature information");
116 writeln!(f, "{:#02x?}", feature_info)?;
117 writeln!(f, "stepping {}", feature_info.stepping_id())?;
118 writeln!(f, "model {}", feature_info.model_id())?;
119 writeln!(f, "extended model {}", feature_info.extended_model_id())?;
120 writeln!(f, "family {}", feature_info.family_id())?;
121 writeln!(f, "extended family {}", feature_info.extended_family_id())?;
122 writeln!(f, "SMX support {}", feature_info.has_smx())?;
125
126 writeln!(f, "\n# Extended feature bits")?;
127 let extended_features = self
128 .0
129 .get_extended_feature_info()
130 .expect("Cannot get extended features information");
131 writeln!(f, "{:#02x?}", extended_features)?;
132 writeln!(f, "SGX available: {}", extended_features.has_sgx())?;
133 writeln!(
134 f,
135 "SGX FLC (Flexible Launch Control): {}",
136 extended_features.has_sgx_lc()
137 )?;
138
139 writeln!(f, "\n# Intel SGX capabilities")?;
140 writeln!(f, "\n## Sub-leaf 0 (ECX=0)")?;
141 let sgx_info = self.0.get_sgx_info().expect("Cannot get SGX information");
142 writeln!(f, "{:#02x?}", sgx_info)?;
143 writeln!(f, "SGX 1 supported: {}", sgx_info.has_sgx1())?;
144 writeln!(f, "SGX 2 supported: {}", sgx_info.has_sgx2())?;
145 writeln!(
146 f,
147 "MaxEnclaveSize_Not64: {:#02x}",
148 sgx_info.max_enclave_size_non_64bit()
149 )?;
150 writeln!(
151 f,
152 "MaxEnclaveSize_64: {:#02x}",
153 sgx_info.max_enclave_size_64bit()
154 )?;
155
156 writeln!(f, "\n## Sub-leaf 1 (ECX=1)")?;
157 let (eax, ecx) = sgx_info.secs_attributes();
158 write!(f, "eax: {:#02x?}, ebx: 0, ecx: {:#02x?}, edx: 0", eax, ecx)?;
159
160 for (idx, SgxSectionInfo::Epc(epc_section)) in sgx_info.iter().enumerate() {
161 writeln!(f, "\nSub-leaf {} (ECX={})", idx + 2, idx + 2)?;
162 writeln!(
163 f,
164 "EPC (Enclave Page Cache) section:\n{:#02x?}",
165 epc_section
166 )?;
167 writeln!(
168 f,
169 "physical base address: {:#02x?}",
170 epc_section.physical_base()
171 )?;
172 write!(
173 f,
174 "size of EPC section in Processor Reserved Memory: {} MB",
175 epc_section.size() / 1_048_576
176 )?;
177 }
178 Ok(())
179 }
180}