blob: 90a0ec267f9030a8e0d4c4964d1fc1a6524029fc [file] [log] [blame]
Andrew Walbraneef98202022-04-27 16:23:06 +00001// 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
20mod exceptions;
Andrew Walbran153aad92022-06-28 15:51:13 +000021mod layout;
Andrew Walbran8217d062022-11-22 16:56:18 +000022mod pci;
Andrew Walbraneef98202022-04-27 16:23:06 +000023
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000024extern crate alloc;
25
Andrew Walbran153aad92022-06-28 15:51:13 +000026use crate::layout::{
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +010027 bionic_tls, boot_stack_range, dtb_range, print_addresses, rodata_range, scratch_range,
28 stack_chk_guard, text_range, DEVICE_REGION,
Andrew Walbran13564542022-04-20 16:29:45 +000029};
Andrew Walbran730375d2022-12-21 14:04:34 +000030use crate::pci::{check_pci, get_bar_region};
Andrew Walbran8217d062022-11-22 16:56:18 +000031use aarch64_paging::{idmap::IdMap, paging::Attributes};
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000032use alloc::{vec, vec::Vec};
33use buddy_system_allocator::LockedHeap;
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +000034use core::ffi::CStr;
Andrew Walbran730375d2022-12-21 14:04:34 +000035use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010036use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000037use log::{debug, error, info, trace, warn, LevelFilter};
38use vmbase::{logger, main};
Andrew Walbraneef98202022-04-27 16:23:06 +000039
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000040static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
41static mut ZEROED_DATA: [u32; 10] = [0; 10];
42static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
43
Andrew Walbran13564542022-04-20 16:29:45 +000044const ASID: usize = 1;
45const ROOT_LEVEL: usize = 1;
46
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000047#[global_allocator]
48static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
49
50static mut HEAP: [u8; 65536] = [0; 65536];
51
Andrew Walbraneef98202022-04-27 16:23:06 +000052main!(main);
53
54/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000055pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010056 logger::init(LevelFilter::Debug).unwrap();
57
Jakob Vukalovicef996292023-04-13 14:28:34 +000058 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010059 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000060 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000061 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000062 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000063 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000064
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
Andrew Walbran730375d2022-12-21 14:04:34 +000073 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);
Andrew Walbran8217d062022-11-22 16:56:18 +000075
76 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000077
78 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +010079 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000080 }
81
82 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000083
84 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
Jakob Vukalovic50559df2023-04-19 19:24:13 +010085 idmap
86 .map_range(
87 &DEVICE_REGION,
88 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
89 )
90 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000091 idmap
92 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000093 &text_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010094 Attributes::VALID | Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
Andrew Walbran13564542022-04-20 16:29:45 +000095 )
96 .unwrap();
97 idmap
98 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000099 &rodata_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100100 Attributes::VALID
101 | Attributes::NORMAL
Andrew Walbran13564542022-04-20 16:29:45 +0000102 | Attributes::NON_GLOBAL
103 | Attributes::READ_ONLY
104 | Attributes::EXECUTE_NEVER,
105 )
106 .unwrap();
107 idmap
108 .map_range(
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100109 &scratch_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100110 Attributes::VALID
111 | Attributes::NORMAL
112 | Attributes::NON_GLOBAL
113 | Attributes::EXECUTE_NEVER,
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100114 )
115 .unwrap();
116 idmap
117 .map_range(
118 &boot_stack_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100119 Attributes::VALID
120 | Attributes::NORMAL
121 | Attributes::NON_GLOBAL
122 | Attributes::EXECUTE_NEVER,
Andrew Walbran13564542022-04-20 16:29:45 +0000123 )
124 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000125 idmap
126 .map_range(
127 &dtb_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100128 Attributes::VALID
129 | Attributes::NORMAL
Andrew Walbran8217d062022-11-22 16:56:18 +0000130 | Attributes::NON_GLOBAL
131 | Attributes::READ_ONLY
132 | Attributes::EXECUTE_NEVER,
133 )
134 .unwrap();
135 idmap
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100136 .map_range(
137 &get_bar_region(&pci_info),
138 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
139 )
Andrew Walbran8217d062022-11-22 16:56:18 +0000140 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000141
David Brazdilb41aa8f2022-07-05 12:41:00 +0100142 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000143 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000144 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100145 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000146
147 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000148 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000149
Andrew Walbran730375d2022-12-21 14:04:34 +0000150 let mut pci_root = unsafe { pci_info.make_pci_root() };
151 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000152
153 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000154}
155
David Brazdila51c6f02022-10-12 09:51:48 +0000156fn check_stack_guard() {
157 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
158
159 info!("Testing stack guard");
160 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
161}
162
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000163fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100164 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000165 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100166 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
167 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
168 info!("HEAP: {:?}", HEAP.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000169 }
170
171 assert_eq!(INITIALISED_DATA[0], 1);
172 assert_eq!(INITIALISED_DATA[1], 2);
173 assert_eq!(INITIALISED_DATA[2], 3);
174 assert_eq!(INITIALISED_DATA[3], 4);
175
176 unsafe {
177 for element in ZEROED_DATA.iter() {
178 assert_eq!(*element, 0);
179 }
180 ZEROED_DATA[0] = 13;
181 assert_eq!(ZEROED_DATA[0], 13);
182 ZEROED_DATA[0] = 0;
183 assert_eq!(ZEROED_DATA[0], 0);
184
185 assert_eq!(MUTABLE_DATA[0], 1);
186 assert_eq!(MUTABLE_DATA[1], 2);
187 assert_eq!(MUTABLE_DATA[2], 3);
188 assert_eq!(MUTABLE_DATA[3], 4);
189 MUTABLE_DATA[0] += 41;
190 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000191 MUTABLE_DATA[0] -= 41;
192 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000193 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100194 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000195}
196
Andrew Walbran8217d062022-11-22 16:56:18 +0000197fn check_fdt(reader: &Fdt) {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000198 for reg in reader.memory().unwrap().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100199 info!("memory @ {reg:#x?}");
200 }
201
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000202 let compatible = CStr::from_bytes_with_nul(b"ns16550a\0").unwrap();
203
204 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000205 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000206 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
207 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000208}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000209
Andrew Walbran8217d062022-11-22 16:56:18 +0000210fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000211 writer.unpack().unwrap();
212 info!("FDT successfully unpacked.");
213
214 let path = CStr::from_bytes_with_nul(b"/memory\0").unwrap();
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000215 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000216 let name = CStr::from_bytes_with_nul(b"child\0").unwrap();
217 let mut child = node.add_subnode(name).unwrap();
218 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
219
220 let name = CStr::from_bytes_with_nul(b"str-property\0").unwrap();
221 child.appendprop(name, b"property-value\0").unwrap();
222 info!("Appended property '{}'.", name.to_str().unwrap());
223
224 let name = CStr::from_bytes_with_nul(b"pair-property\0").unwrap();
225 let addr = 0x0123_4567u64;
226 let size = 0x89ab_cdefu64;
227 child.appendprop_addrrange(name, addr, size).unwrap();
228 info!("Appended property '{}'.", name.to_str().unwrap());
229
230 let writer = child.fdt();
231 writer.pack().unwrap();
232 info!("FDT successfully packed.");
233
David Brazdil1baa9a92022-06-28 14:47:50 +0100234 info!("FDT checks done.");
235}
236
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000237fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100238 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000239 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
240 assert_eq!(vector[0], 1);
241 assert_eq!(vector[1], 2);
242 assert_eq!(vector[2], 3);
243 assert_eq!(vector[3], 4);
244 vector[2] = 42;
245 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100246 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000247}
David Brazdil9a83e612022-09-27 17:38:10 +0000248
249fn check_dice() {
250 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000251 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000252 assert_eq!(
253 hash,
254 [
255 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
256 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
257 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
258 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
259 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
260 ]
261 );
262}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000263
264macro_rules! log_all_levels {
265 ($msg:literal) => {{
266 error!($msg);
267 warn!($msg);
268 info!($msg);
269 debug!($msg);
270 trace!($msg);
271 }};
272}
273
274fn emit_suppressed_log() {
275 {
276 let _guard = logger::suppress();
277 log_all_levels!("Suppressed message");
278 }
279 log_all_levels!("Unsuppressed message");
280}