blob: d604509f1a35087c8b5b593b05625efb09ed4282 [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};
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};
Pierre-Clément Tosic332fae2023-06-22 11:37:12 +000036use vmbase::{configure_global_allocator_size, cstr, heap, 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 Tosic332fae2023-06-22 11:37:12 +000046configure_global_allocator_size!(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
Pierre-Clément Tosic332fae2023-06-22 11:37:12 +000072 // SAFETY - Only called once, from here.
73 unsafe { heap::init() };
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000074
75 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000076
77 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
Jakob Vukalovic50559df2023-04-19 19:24:13 +010078 idmap
79 .map_range(
80 &DEVICE_REGION,
81 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
82 )
83 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000084 idmap
85 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000086 &text_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010087 Attributes::VALID | Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
Andrew Walbran13564542022-04-20 16:29:45 +000088 )
89 .unwrap();
90 idmap
91 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000092 &rodata_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010093 Attributes::VALID
94 | Attributes::NORMAL
Andrew Walbran13564542022-04-20 16:29:45 +000095 | Attributes::NON_GLOBAL
96 | Attributes::READ_ONLY
97 | Attributes::EXECUTE_NEVER,
98 )
99 .unwrap();
100 idmap
101 .map_range(
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100102 &scratch_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100103 Attributes::VALID
104 | Attributes::NORMAL
105 | Attributes::NON_GLOBAL
106 | Attributes::EXECUTE_NEVER,
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100107 )
108 .unwrap();
109 idmap
110 .map_range(
111 &boot_stack_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100112 Attributes::VALID
113 | Attributes::NORMAL
114 | Attributes::NON_GLOBAL
115 | Attributes::EXECUTE_NEVER,
Andrew Walbran13564542022-04-20 16:29:45 +0000116 )
117 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000118 idmap
119 .map_range(
120 &dtb_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100121 Attributes::VALID
122 | Attributes::NORMAL
Andrew Walbran8217d062022-11-22 16:56:18 +0000123 | Attributes::NON_GLOBAL
124 | Attributes::READ_ONLY
125 | Attributes::EXECUTE_NEVER,
126 )
127 .unwrap();
128 idmap
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100129 .map_range(
130 &get_bar_region(&pci_info),
131 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
132 )
Andrew Walbran8217d062022-11-22 16:56:18 +0000133 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000134
David Brazdilb41aa8f2022-07-05 12:41:00 +0100135 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000136 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000137 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100138 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000139
140 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000141 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000142
Andrew Walbran730375d2022-12-21 14:04:34 +0000143 let mut pci_root = unsafe { pci_info.make_pci_root() };
144 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000145
146 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000147}
148
David Brazdila51c6f02022-10-12 09:51:48 +0000149fn check_stack_guard() {
150 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
151
152 info!("Testing stack guard");
153 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
154}
155
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000156fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100157 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000158 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100159 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
160 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000161 }
162
163 assert_eq!(INITIALISED_DATA[0], 1);
164 assert_eq!(INITIALISED_DATA[1], 2);
165 assert_eq!(INITIALISED_DATA[2], 3);
166 assert_eq!(INITIALISED_DATA[3], 4);
167
168 unsafe {
169 for element in ZEROED_DATA.iter() {
170 assert_eq!(*element, 0);
171 }
172 ZEROED_DATA[0] = 13;
173 assert_eq!(ZEROED_DATA[0], 13);
174 ZEROED_DATA[0] = 0;
175 assert_eq!(ZEROED_DATA[0], 0);
176
177 assert_eq!(MUTABLE_DATA[0], 1);
178 assert_eq!(MUTABLE_DATA[1], 2);
179 assert_eq!(MUTABLE_DATA[2], 3);
180 assert_eq!(MUTABLE_DATA[3], 4);
181 MUTABLE_DATA[0] += 41;
182 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000183 MUTABLE_DATA[0] -= 41;
184 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000185 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100186 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000187}
188
Andrew Walbran8217d062022-11-22 16:56:18 +0000189fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000190 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100191 info!("memory @ {reg:#x?}");
192 }
193
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000194 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000195
196 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000197 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000198 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
199 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000200}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000201
Andrew Walbran8217d062022-11-22 16:56:18 +0000202fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000203 writer.unpack().unwrap();
204 info!("FDT successfully unpacked.");
205
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000206 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000207 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000208 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000209 let mut child = node.add_subnode(name).unwrap();
210 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
211
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000212 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000213 child.appendprop(name, b"property-value\0").unwrap();
214 info!("Appended property '{}'.", name.to_str().unwrap());
215
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000216 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000217 let addr = 0x0123_4567u64;
218 let size = 0x89ab_cdefu64;
219 child.appendprop_addrrange(name, addr, size).unwrap();
220 info!("Appended property '{}'.", name.to_str().unwrap());
221
222 let writer = child.fdt();
223 writer.pack().unwrap();
224 info!("FDT successfully packed.");
225
David Brazdil1baa9a92022-06-28 14:47:50 +0100226 info!("FDT checks done.");
227}
228
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000229fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100230 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000231 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
232 assert_eq!(vector[0], 1);
233 assert_eq!(vector[1], 2);
234 assert_eq!(vector[2], 3);
235 assert_eq!(vector[3], 4);
236 vector[2] = 42;
237 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100238 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000239}
David Brazdil9a83e612022-09-27 17:38:10 +0000240
241fn check_dice() {
242 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000243 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000244 assert_eq!(
245 hash,
246 [
247 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
248 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
249 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
250 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
251 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
252 ]
253 );
254}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000255
256macro_rules! log_all_levels {
257 ($msg:literal) => {{
258 error!($msg);
259 warn!($msg);
260 info!($msg);
261 debug!($msg);
262 trace!($msg);
263 }};
264}
265
266fn emit_suppressed_log() {
267 {
268 let _guard = logger::suppress();
269 log_all_levels!("Suppressed message");
270 }
271 log_all_levels!("Unsuppressed message");
272}