blob: 3bf850c206ba3f323dd6fe0e4929306a0dc1337e [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);
85 idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
86 idmap
87 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000088 &text_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000089 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
90 )
91 .unwrap();
92 idmap
93 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000094 &rodata_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000095 Attributes::NORMAL
96 | Attributes::NON_GLOBAL
97 | Attributes::READ_ONLY
98 | Attributes::EXECUTE_NEVER,
99 )
100 .unwrap();
101 idmap
102 .map_range(
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100103 &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(),
Andrew Walbran13564542022-04-20 16:29:45 +0000110 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
111 )
112 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000113 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
Andrew Walbran730375d2022-12-21 14:04:34 +0000123 .map_range(&get_bar_region(&pci_info), Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER)
Andrew Walbran8217d062022-11-22 16:56:18 +0000124 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000125
David Brazdilb41aa8f2022-07-05 12:41:00 +0100126 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000127 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000128 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100129 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000130
131 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000132 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000133
Andrew Walbran730375d2022-12-21 14:04:34 +0000134 let mut pci_root = unsafe { pci_info.make_pci_root() };
135 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000136
137 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000138}
139
David Brazdila51c6f02022-10-12 09:51:48 +0000140fn 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
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000147fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100148 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000149 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100150 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
151 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
152 info!("HEAP: {:?}", HEAP.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000153 }
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);
Andrew Walbran13564542022-04-20 16:29:45 +0000175 MUTABLE_DATA[0] -= 41;
176 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000177 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100178 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000179}
180
Andrew Walbran8217d062022-11-22 16:56:18 +0000181fn check_fdt(reader: &Fdt) {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000182 for reg in reader.memory().unwrap().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100183 info!("memory @ {reg:#x?}");
184 }
185
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000186 let compatible = CStr::from_bytes_with_nul(b"ns16550a\0").unwrap();
187
188 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000189 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000190 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
191 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000192}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000193
Andrew Walbran8217d062022-11-22 16:56:18 +0000194fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000195 writer.unpack().unwrap();
196 info!("FDT successfully unpacked.");
197
198 let path = CStr::from_bytes_with_nul(b"/memory\0").unwrap();
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000199 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000200 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
David Brazdil1baa9a92022-06-28 14:47:50 +0100218 info!("FDT checks done.");
219}
220
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000221fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100222 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000223 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);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100230 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000231}
David Brazdil9a83e612022-09-27 17:38:10 +0000232
233fn check_dice() {
234 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000235 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000236 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}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000247
248macro_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
258fn emit_suppressed_log() {
259 {
260 let _guard = logger::suppress();
261 log_all_levels!("Suppressed message");
262 }
263 log_all_levels!("Unsuppressed message");
264}