blob: 1dd8517e820a8a0c6223de3d6a8cd00b29f96f2c [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;
Andrew Walbran730375d2022-12-21 14:04:34 +000034use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010035use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000036use log::{debug, error, info, trace, warn, LevelFilter};
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +000037use vmbase::{cstr, logger, main};
Andrew Walbraneef98202022-04-27 16:23:06 +000038
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000039static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
40static mut ZEROED_DATA: [u32; 10] = [0; 10];
41static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
42
Andrew Walbran13564542022-04-20 16:29:45 +000043const ASID: usize = 1;
44const ROOT_LEVEL: usize = 1;
45
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000046#[global_allocator]
47static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
48
49static mut HEAP: [u8; 65536] = [0; 65536];
50
Andrew Walbraneef98202022-04-27 16:23:06 +000051main!(main);
52
53/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000054pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010055 logger::init(LevelFilter::Debug).unwrap();
56
Jakob Vukalovicef996292023-04-13 14:28:34 +000057 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010058 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000059 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000060 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000061 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000062 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000063
64 info!("Checking FDT...");
65 let fdt = dtb_range();
66 let fdt =
67 unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt.end.0 - fdt.start.0) };
68 let fdt = Fdt::from_mut_slice(fdt).unwrap();
69 info!("FDT passed verification.");
70 check_fdt(fdt);
71
Andrew Walbran730375d2022-12-21 14:04:34 +000072 let pci_info = PciInfo::from_fdt(fdt).unwrap();
73 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000074
75 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000076
77 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +010078 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000079 }
80
81 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000082
83 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
Jakob Vukalovic50559df2023-04-19 19:24:13 +010084 idmap
85 .map_range(
86 &DEVICE_REGION,
87 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
88 )
89 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000090 idmap
91 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000092 &text_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010093 Attributes::VALID | Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
Andrew Walbran13564542022-04-20 16:29:45 +000094 )
95 .unwrap();
96 idmap
97 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000098 &rodata_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010099 Attributes::VALID
100 | Attributes::NORMAL
Andrew Walbran13564542022-04-20 16:29:45 +0000101 | Attributes::NON_GLOBAL
102 | Attributes::READ_ONLY
103 | Attributes::EXECUTE_NEVER,
104 )
105 .unwrap();
106 idmap
107 .map_range(
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100108 &scratch_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100109 Attributes::VALID
110 | Attributes::NORMAL
111 | Attributes::NON_GLOBAL
112 | Attributes::EXECUTE_NEVER,
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100113 )
114 .unwrap();
115 idmap
116 .map_range(
117 &boot_stack_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100118 Attributes::VALID
119 | Attributes::NORMAL
120 | Attributes::NON_GLOBAL
121 | Attributes::EXECUTE_NEVER,
Andrew Walbran13564542022-04-20 16:29:45 +0000122 )
123 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000124 idmap
125 .map_range(
126 &dtb_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100127 Attributes::VALID
128 | Attributes::NORMAL
Andrew Walbran8217d062022-11-22 16:56:18 +0000129 | Attributes::NON_GLOBAL
130 | Attributes::READ_ONLY
131 | Attributes::EXECUTE_NEVER,
132 )
133 .unwrap();
134 idmap
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100135 .map_range(
136 &get_bar_region(&pci_info),
137 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
138 )
Andrew Walbran8217d062022-11-22 16:56:18 +0000139 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000140
David Brazdilb41aa8f2022-07-05 12:41:00 +0100141 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000142 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000143 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100144 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000145
146 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000147 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000148
Andrew Walbran730375d2022-12-21 14:04:34 +0000149 let mut pci_root = unsafe { pci_info.make_pci_root() };
150 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000151
152 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000153}
154
David Brazdila51c6f02022-10-12 09:51:48 +0000155fn check_stack_guard() {
156 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
157
158 info!("Testing stack guard");
159 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
160}
161
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000162fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100163 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000164 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100165 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
166 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
167 info!("HEAP: {:?}", HEAP.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000168 }
169
170 assert_eq!(INITIALISED_DATA[0], 1);
171 assert_eq!(INITIALISED_DATA[1], 2);
172 assert_eq!(INITIALISED_DATA[2], 3);
173 assert_eq!(INITIALISED_DATA[3], 4);
174
175 unsafe {
176 for element in ZEROED_DATA.iter() {
177 assert_eq!(*element, 0);
178 }
179 ZEROED_DATA[0] = 13;
180 assert_eq!(ZEROED_DATA[0], 13);
181 ZEROED_DATA[0] = 0;
182 assert_eq!(ZEROED_DATA[0], 0);
183
184 assert_eq!(MUTABLE_DATA[0], 1);
185 assert_eq!(MUTABLE_DATA[1], 2);
186 assert_eq!(MUTABLE_DATA[2], 3);
187 assert_eq!(MUTABLE_DATA[3], 4);
188 MUTABLE_DATA[0] += 41;
189 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000190 MUTABLE_DATA[0] -= 41;
191 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000192 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100193 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000194}
195
Andrew Walbran8217d062022-11-22 16:56:18 +0000196fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000197 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100198 info!("memory @ {reg:#x?}");
199 }
200
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000201 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000202
203 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000204 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000205 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
206 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000207}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000208
Andrew Walbran8217d062022-11-22 16:56:18 +0000209fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000210 writer.unpack().unwrap();
211 info!("FDT successfully unpacked.");
212
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000213 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000214 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000215 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000216 let mut child = node.add_subnode(name).unwrap();
217 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
218
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000219 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000220 child.appendprop(name, b"property-value\0").unwrap();
221 info!("Appended property '{}'.", name.to_str().unwrap());
222
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000223 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000224 let addr = 0x0123_4567u64;
225 let size = 0x89ab_cdefu64;
226 child.appendprop_addrrange(name, addr, size).unwrap();
227 info!("Appended property '{}'.", name.to_str().unwrap());
228
229 let writer = child.fdt();
230 writer.pack().unwrap();
231 info!("FDT successfully packed.");
232
David Brazdil1baa9a92022-06-28 14:47:50 +0100233 info!("FDT checks done.");
234}
235
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000236fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100237 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000238 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
239 assert_eq!(vector[0], 1);
240 assert_eq!(vector[1], 2);
241 assert_eq!(vector[2], 3);
242 assert_eq!(vector[3], 4);
243 vector[2] = 42;
244 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100245 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000246}
David Brazdil9a83e612022-09-27 17:38:10 +0000247
248fn check_dice() {
249 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000250 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000251 assert_eq!(
252 hash,
253 [
254 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
255 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
256 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
257 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
258 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
259 ]
260 );
261}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000262
263macro_rules! log_all_levels {
264 ($msg:literal) => {{
265 error!($msg);
266 warn!($msg);
267 info!($msg);
268 debug!($msg);
269 trace!($msg);
270 }};
271}
272
273fn emit_suppressed_log() {
274 {
275 let _guard = logger::suppress();
276 log_all_levels!("Suppressed message");
277 }
278 log_all_levels!("Unsuppressed message");
279}