• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! VM bootloader example.
16 
17 #![no_main]
18 #![no_std]
19 
20 mod exceptions;
21 mod layout;
22 mod pci;
23 
24 extern crate alloc;
25 
26 use crate::layout::{
27     bionic_tls, boot_stack_range, dtb_range, print_addresses, rodata_range, scratch_range,
28     stack_chk_guard, text_range, DEVICE_REGION,
29 };
30 use crate::pci::{check_pci, get_bar_region};
31 use aarch64_paging::{idmap::IdMap, paging::Attributes};
32 use alloc::{vec, vec::Vec};
33 use buddy_system_allocator::LockedHeap;
34 use core::ffi::CStr;
35 use fdtpci::PciInfo;
36 use libfdt::Fdt;
37 use log::{debug, error, info, trace, warn, LevelFilter};
38 use vmbase::{logger, main};
39 
40 static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
41 static mut ZEROED_DATA: [u32; 10] = [0; 10];
42 static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
43 
44 const ASID: usize = 1;
45 const ROOT_LEVEL: usize = 1;
46 
47 #[global_allocator]
48 static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
49 
50 static mut HEAP: [u8; 65536] = [0; 65536];
51 
52 main!(main);
53 
54 /// Entry point for VM bootloader.
main(arg0: u64, arg1: u64, arg2: u64, arg3: u64)55 pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
56     logger::init(LevelFilter::Debug).unwrap();
57 
58     info!("Hello world");
59     info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
60     print_addresses();
61     assert_eq!(arg0, dtb_range().start.0 as u64);
62     check_data();
63     check_stack_guard();
64 
65     info!("Checking FDT...");
66     let fdt = dtb_range();
67     let fdt =
68         unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt.end.0 - fdt.start.0) };
69     let fdt = Fdt::from_mut_slice(fdt).unwrap();
70     info!("FDT passed verification.");
71     check_fdt(fdt);
72 
73     let pci_info = PciInfo::from_fdt(fdt).unwrap();
74     debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
75 
76     modify_fdt(fdt);
77 
78     unsafe {
79         HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
80     }
81 
82     check_alloc();
83 
84     let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
85     idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
86     idmap
87         .map_range(
88             &text_range().into(),
89             Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
90         )
91         .unwrap();
92     idmap
93         .map_range(
94             &rodata_range().into(),
95             Attributes::NORMAL
96                 | Attributes::NON_GLOBAL
97                 | Attributes::READ_ONLY
98                 | Attributes::EXECUTE_NEVER,
99         )
100         .unwrap();
101     idmap
102         .map_range(
103             &scratch_range().into(),
104             Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
105         )
106         .unwrap();
107     idmap
108         .map_range(
109             &boot_stack_range().into(),
110             Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
111         )
112         .unwrap();
113     idmap
114         .map_range(
115             &dtb_range().into(),
116             Attributes::NORMAL
117                 | Attributes::NON_GLOBAL
118                 | Attributes::READ_ONLY
119                 | Attributes::EXECUTE_NEVER,
120         )
121         .unwrap();
122     idmap
123         .map_range(&get_bar_region(&pci_info), Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER)
124         .unwrap();
125 
126     info!("Activating IdMap...");
127     trace!("{:?}", idmap);
128     idmap.activate();
129     info!("Activated.");
130 
131     check_data();
132     check_dice();
133 
134     let mut pci_root = unsafe { pci_info.make_pci_root() };
135     check_pci(&mut pci_root);
136 
137     emit_suppressed_log();
138 }
139 
check_stack_guard()140 fn check_stack_guard() {
141     const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
142 
143     info!("Testing stack guard");
144     assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
145 }
146 
check_data()147 fn check_data() {
148     info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
149     unsafe {
150         info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
151         info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
152         info!("HEAP: {:?}", HEAP.as_ptr());
153     }
154 
155     assert_eq!(INITIALISED_DATA[0], 1);
156     assert_eq!(INITIALISED_DATA[1], 2);
157     assert_eq!(INITIALISED_DATA[2], 3);
158     assert_eq!(INITIALISED_DATA[3], 4);
159 
160     unsafe {
161         for element in ZEROED_DATA.iter() {
162             assert_eq!(*element, 0);
163         }
164         ZEROED_DATA[0] = 13;
165         assert_eq!(ZEROED_DATA[0], 13);
166         ZEROED_DATA[0] = 0;
167         assert_eq!(ZEROED_DATA[0], 0);
168 
169         assert_eq!(MUTABLE_DATA[0], 1);
170         assert_eq!(MUTABLE_DATA[1], 2);
171         assert_eq!(MUTABLE_DATA[2], 3);
172         assert_eq!(MUTABLE_DATA[3], 4);
173         MUTABLE_DATA[0] += 41;
174         assert_eq!(MUTABLE_DATA[0], 42);
175         MUTABLE_DATA[0] -= 41;
176         assert_eq!(MUTABLE_DATA[0], 1);
177     }
178     info!("Data looks good");
179 }
180 
check_fdt(reader: &Fdt)181 fn check_fdt(reader: &Fdt) {
182     for reg in reader.memory().unwrap().unwrap() {
183         info!("memory @ {reg:#x?}");
184     }
185 
186     let compatible = CStr::from_bytes_with_nul(b"ns16550a\0").unwrap();
187 
188     for c in reader.compatible_nodes(compatible).unwrap() {
189         let reg = c.reg().unwrap().unwrap().next().unwrap();
190         info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
191     }
192 }
193 
modify_fdt(writer: &mut Fdt)194 fn modify_fdt(writer: &mut Fdt) {
195     writer.unpack().unwrap();
196     info!("FDT successfully unpacked.");
197 
198     let path = CStr::from_bytes_with_nul(b"/memory\0").unwrap();
199     let mut node = writer.node_mut(path).unwrap().unwrap();
200     let name = CStr::from_bytes_with_nul(b"child\0").unwrap();
201     let mut child = node.add_subnode(name).unwrap();
202     info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
203 
204     let name = CStr::from_bytes_with_nul(b"str-property\0").unwrap();
205     child.appendprop(name, b"property-value\0").unwrap();
206     info!("Appended property '{}'.", name.to_str().unwrap());
207 
208     let name = CStr::from_bytes_with_nul(b"pair-property\0").unwrap();
209     let addr = 0x0123_4567u64;
210     let size = 0x89ab_cdefu64;
211     child.appendprop_addrrange(name, addr, size).unwrap();
212     info!("Appended property '{}'.", name.to_str().unwrap());
213 
214     let writer = child.fdt();
215     writer.pack().unwrap();
216     info!("FDT successfully packed.");
217 
218     info!("FDT checks done.");
219 }
220 
check_alloc()221 fn check_alloc() {
222     info!("Allocating a Vec...");
223     let mut vector: Vec<u32> = vec![1, 2, 3, 4];
224     assert_eq!(vector[0], 1);
225     assert_eq!(vector[1], 2);
226     assert_eq!(vector[2], 3);
227     assert_eq!(vector[3], 4);
228     vector[2] = 42;
229     assert_eq!(vector[2], 42);
230     info!("Vec seems to work.");
231 }
232 
check_dice()233 fn check_dice() {
234     info!("Testing DICE integration...");
235     let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
236     assert_eq!(
237         hash,
238         [
239             0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
240             0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
241             0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
242             0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
243             0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
244         ]
245     );
246 }
247 
248 macro_rules! log_all_levels {
249     ($msg:literal) => {{
250         error!($msg);
251         warn!($msg);
252         info!($msg);
253         debug!($msg);
254         trace!($msg);
255     }};
256 }
257 
emit_suppressed_log()258 fn emit_suppressed_log() {
259     {
260         let _guard = logger::suppress();
261         log_all_levels!("Suppressed message");
262     }
263     log_all_levels!("Unsuppressed message");
264 }
265