blob: 021daa4a055dcd710b6d19bfbc3f918c78d5155b [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,
Andrew Walbranb88eb012023-07-05 13:58:26 +000028 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};
Andrew Walbran730375d2022-12-21 14:04:34 +000033use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010034use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000035use log::{debug, error, info, trace, warn, LevelFilter};
Andrew Walbranb88eb012023-07-05 13:58:26 +000036use vmbase::{configure_heap, cstr, layout::stack_chk_guard, logger, main, memory::SIZE_64KB};
Andrew Walbraneef98202022-04-27 16:23:06 +000037
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000038static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
39static mut ZEROED_DATA: [u32; 10] = [0; 10];
40static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
41
Andrew Walbran13564542022-04-20 16:29:45 +000042const ASID: usize = 1;
43const ROOT_LEVEL: usize = 1;
44
Andrew Walbraneef98202022-04-27 16:23:06 +000045main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000046configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000047
48/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000049pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010050 logger::init(LevelFilter::Debug).unwrap();
51
Jakob Vukalovicef996292023-04-13 14:28:34 +000052 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010053 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000054 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000055 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000056 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000057 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000058
59 info!("Checking FDT...");
60 let fdt = dtb_range();
61 let fdt =
62 unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt.end.0 - fdt.start.0) };
63 let fdt = Fdt::from_mut_slice(fdt).unwrap();
64 info!("FDT passed verification.");
65 check_fdt(fdt);
66
Andrew Walbran730375d2022-12-21 14:04:34 +000067 let pci_info = PciInfo::from_fdt(fdt).unwrap();
68 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000069
70 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000071
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000072 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000073
74 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
Jakob Vukalovic50559df2023-04-19 19:24:13 +010075 idmap
76 .map_range(
77 &DEVICE_REGION,
78 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
79 )
80 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000081 idmap
82 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000083 &text_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010084 Attributes::VALID | Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
Andrew Walbran13564542022-04-20 16:29:45 +000085 )
86 .unwrap();
87 idmap
88 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000089 &rodata_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010090 Attributes::VALID
91 | Attributes::NORMAL
Andrew Walbran13564542022-04-20 16:29:45 +000092 | Attributes::NON_GLOBAL
93 | Attributes::READ_ONLY
94 | Attributes::EXECUTE_NEVER,
95 )
96 .unwrap();
97 idmap
98 .map_range(
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +010099 &scratch_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100100 Attributes::VALID
101 | Attributes::NORMAL
102 | Attributes::NON_GLOBAL
103 | Attributes::EXECUTE_NEVER,
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100104 )
105 .unwrap();
106 idmap
107 .map_range(
108 &boot_stack_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100109 Attributes::VALID
110 | Attributes::NORMAL
111 | Attributes::NON_GLOBAL
112 | Attributes::EXECUTE_NEVER,
Andrew Walbran13564542022-04-20 16:29:45 +0000113 )
114 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000115 idmap
116 .map_range(
117 &dtb_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100118 Attributes::VALID
119 | Attributes::NORMAL
Andrew Walbran8217d062022-11-22 16:56:18 +0000120 | Attributes::NON_GLOBAL
121 | Attributes::READ_ONLY
122 | Attributes::EXECUTE_NEVER,
123 )
124 .unwrap();
125 idmap
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100126 .map_range(
127 &get_bar_region(&pci_info),
128 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
129 )
Andrew Walbran8217d062022-11-22 16:56:18 +0000130 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000131
David Brazdilb41aa8f2022-07-05 12:41:00 +0100132 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000133 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000134 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100135 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000136
137 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000138 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000139
Andrew Walbran730375d2022-12-21 14:04:34 +0000140 let mut pci_root = unsafe { pci_info.make_pci_root() };
141 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000142
143 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000144}
145
David Brazdila51c6f02022-10-12 09:51:48 +0000146fn check_stack_guard() {
147 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
148
149 info!("Testing stack guard");
150 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
151}
152
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000153fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100154 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000155 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100156 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
157 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000158 }
159
160 assert_eq!(INITIALISED_DATA[0], 1);
161 assert_eq!(INITIALISED_DATA[1], 2);
162 assert_eq!(INITIALISED_DATA[2], 3);
163 assert_eq!(INITIALISED_DATA[3], 4);
164
165 unsafe {
166 for element in ZEROED_DATA.iter() {
167 assert_eq!(*element, 0);
168 }
169 ZEROED_DATA[0] = 13;
170 assert_eq!(ZEROED_DATA[0], 13);
171 ZEROED_DATA[0] = 0;
172 assert_eq!(ZEROED_DATA[0], 0);
173
174 assert_eq!(MUTABLE_DATA[0], 1);
175 assert_eq!(MUTABLE_DATA[1], 2);
176 assert_eq!(MUTABLE_DATA[2], 3);
177 assert_eq!(MUTABLE_DATA[3], 4);
178 MUTABLE_DATA[0] += 41;
179 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000180 MUTABLE_DATA[0] -= 41;
181 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000182 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100183 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000184}
185
Andrew Walbran8217d062022-11-22 16:56:18 +0000186fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000187 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100188 info!("memory @ {reg:#x?}");
189 }
190
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000191 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000192
193 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000194 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000195 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
196 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000197}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000198
Andrew Walbran8217d062022-11-22 16:56:18 +0000199fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000200 writer.unpack().unwrap();
201 info!("FDT successfully unpacked.");
202
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000203 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000204 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000205 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000206 let mut child = node.add_subnode(name).unwrap();
207 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
208
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000209 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000210 child.appendprop(name, b"property-value\0").unwrap();
211 info!("Appended property '{}'.", name.to_str().unwrap());
212
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000213 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000214 let addr = 0x0123_4567u64;
215 let size = 0x89ab_cdefu64;
216 child.appendprop_addrrange(name, addr, size).unwrap();
217 info!("Appended property '{}'.", name.to_str().unwrap());
218
219 let writer = child.fdt();
220 writer.pack().unwrap();
221 info!("FDT successfully packed.");
222
David Brazdil1baa9a92022-06-28 14:47:50 +0100223 info!("FDT checks done.");
224}
225
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000226fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100227 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000228 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
229 assert_eq!(vector[0], 1);
230 assert_eq!(vector[1], 2);
231 assert_eq!(vector[2], 3);
232 assert_eq!(vector[3], 4);
233 vector[2] = 42;
234 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100235 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000236}
David Brazdil9a83e612022-09-27 17:38:10 +0000237
238fn check_dice() {
239 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000240 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000241 assert_eq!(
242 hash,
243 [
244 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
245 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
246 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
247 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
248 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
249 ]
250 );
251}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000252
253macro_rules! log_all_levels {
254 ($msg:literal) => {{
255 error!($msg);
256 warn!($msg);
257 info!($msg);
258 debug!($msg);
259 trace!($msg);
260 }};
261}
262
263fn emit_suppressed_log() {
264 {
265 let _guard = logger::suppress();
266 log_all_levels!("Suppressed message");
267 }
268 log_all_levels!("Unsuppressed message");
269}