blob: cc260361919ecfb106a354495f303d31c01f862b [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
Alice Wanga3931aa2023-07-05 12:52:09 +000026use crate::layout::{bionic_tls, boot_stack_range, print_addresses, DEVICE_REGION};
Andrew Walbran730375d2022-12-21 14:04:34 +000027use crate::pci::{check_pci, get_bar_region};
Andrew Walbran8217d062022-11-22 16:56:18 +000028use aarch64_paging::{idmap::IdMap, paging::Attributes};
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000029use alloc::{vec, vec::Vec};
Andrew Walbran730375d2022-12-21 14:04:34 +000030use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010031use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000032use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000033use vmbase::{
34 configure_heap, cstr,
35 layout::{dtb_range, rodata_range, scratch_range, stack_chk_guard, text_range},
36 logger, main,
37 memory::SIZE_64KB,
38};
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 Walbraneef98202022-04-27 16:23:06 +000047main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000048configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000049
50/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000051pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010052 logger::init(LevelFilter::Debug).unwrap();
53
Jakob Vukalovicef996292023-04-13 14:28:34 +000054 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010055 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000056 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000057 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000058 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000059 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000060
61 info!("Checking FDT...");
62 let fdt = dtb_range();
63 let fdt =
64 unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt.end.0 - fdt.start.0) };
65 let fdt = Fdt::from_mut_slice(fdt).unwrap();
66 info!("FDT passed verification.");
67 check_fdt(fdt);
68
Andrew Walbran730375d2022-12-21 14:04:34 +000069 let pci_info = PciInfo::from_fdt(fdt).unwrap();
70 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000071
72 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000073
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000074 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000075
76 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
Jakob Vukalovic50559df2023-04-19 19:24:13 +010077 idmap
78 .map_range(
79 &DEVICE_REGION,
80 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
81 )
82 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000083 idmap
84 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000085 &text_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010086 Attributes::VALID | Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
Andrew Walbran13564542022-04-20 16:29:45 +000087 )
88 .unwrap();
89 idmap
90 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000091 &rodata_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +010092 Attributes::VALID
93 | Attributes::NORMAL
Andrew Walbran13564542022-04-20 16:29:45 +000094 | Attributes::NON_GLOBAL
95 | Attributes::READ_ONLY
96 | Attributes::EXECUTE_NEVER,
97 )
98 .unwrap();
99 idmap
100 .map_range(
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100101 &scratch_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100102 Attributes::VALID
103 | Attributes::NORMAL
104 | Attributes::NON_GLOBAL
105 | Attributes::EXECUTE_NEVER,
Pierre-Clément Tosi8bb3d722023-04-21 16:10:56 +0100106 )
107 .unwrap();
108 idmap
109 .map_range(
110 &boot_stack_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100111 Attributes::VALID
112 | Attributes::NORMAL
113 | Attributes::NON_GLOBAL
114 | Attributes::EXECUTE_NEVER,
Andrew Walbran13564542022-04-20 16:29:45 +0000115 )
116 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000117 idmap
118 .map_range(
119 &dtb_range().into(),
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100120 Attributes::VALID
121 | Attributes::NORMAL
Andrew Walbran8217d062022-11-22 16:56:18 +0000122 | Attributes::NON_GLOBAL
123 | Attributes::READ_ONLY
124 | Attributes::EXECUTE_NEVER,
125 )
126 .unwrap();
127 idmap
Jakob Vukalovic50559df2023-04-19 19:24:13 +0100128 .map_range(
129 &get_bar_region(&pci_info),
130 Attributes::VALID | Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER,
131 )
Andrew Walbran8217d062022-11-22 16:56:18 +0000132 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000133
David Brazdilb41aa8f2022-07-05 12:41:00 +0100134 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000135 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000136 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100137 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000138
139 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000140 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000141
Andrew Walbran730375d2022-12-21 14:04:34 +0000142 let mut pci_root = unsafe { pci_info.make_pci_root() };
143 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000144
145 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000146}
147
David Brazdila51c6f02022-10-12 09:51:48 +0000148fn check_stack_guard() {
149 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
150
151 info!("Testing stack guard");
152 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
153}
154
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000155fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100156 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000157 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100158 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
159 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000160 }
161
162 assert_eq!(INITIALISED_DATA[0], 1);
163 assert_eq!(INITIALISED_DATA[1], 2);
164 assert_eq!(INITIALISED_DATA[2], 3);
165 assert_eq!(INITIALISED_DATA[3], 4);
166
167 unsafe {
168 for element in ZEROED_DATA.iter() {
169 assert_eq!(*element, 0);
170 }
171 ZEROED_DATA[0] = 13;
172 assert_eq!(ZEROED_DATA[0], 13);
173 ZEROED_DATA[0] = 0;
174 assert_eq!(ZEROED_DATA[0], 0);
175
176 assert_eq!(MUTABLE_DATA[0], 1);
177 assert_eq!(MUTABLE_DATA[1], 2);
178 assert_eq!(MUTABLE_DATA[2], 3);
179 assert_eq!(MUTABLE_DATA[3], 4);
180 MUTABLE_DATA[0] += 41;
181 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000182 MUTABLE_DATA[0] -= 41;
183 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000184 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100185 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000186}
187
Andrew Walbran8217d062022-11-22 16:56:18 +0000188fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000189 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100190 info!("memory @ {reg:#x?}");
191 }
192
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000193 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000194
195 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000196 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000197 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
198 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000199}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000200
Andrew Walbran8217d062022-11-22 16:56:18 +0000201fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000202 writer.unpack().unwrap();
203 info!("FDT successfully unpacked.");
204
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000205 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000206 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000207 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000208 let mut child = node.add_subnode(name).unwrap();
209 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
210
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000211 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000212 child.appendprop(name, b"property-value\0").unwrap();
213 info!("Appended property '{}'.", name.to_str().unwrap());
214
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000215 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000216 let addr = 0x0123_4567u64;
217 let size = 0x89ab_cdefu64;
218 child.appendprop_addrrange(name, addr, size).unwrap();
219 info!("Appended property '{}'.", name.to_str().unwrap());
220
221 let writer = child.fdt();
222 writer.pack().unwrap();
223 info!("FDT successfully packed.");
224
David Brazdil1baa9a92022-06-28 14:47:50 +0100225 info!("FDT checks done.");
226}
227
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000228fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100229 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000230 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
231 assert_eq!(vector[0], 1);
232 assert_eq!(vector[1], 2);
233 assert_eq!(vector[2], 3);
234 assert_eq!(vector[3], 4);
235 vector[2] = 42;
236 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100237 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000238}
David Brazdil9a83e612022-09-27 17:38:10 +0000239
240fn check_dice() {
241 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000242 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000243 assert_eq!(
244 hash,
245 [
246 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
247 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
248 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
249 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
250 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
251 ]
252 );
253}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000254
255macro_rules! log_all_levels {
256 ($msg:literal) => {{
257 error!($msg);
258 warn!($msg);
259 info!($msg);
260 debug!($msg);
261 trace!($msg);
262 }};
263}
264
265fn emit_suppressed_log() {
266 {
267 let _guard = logger::suppress();
268 log_all_levels!("Suppressed message");
269 }
270 log_all_levels!("Unsuppressed message");
271}