blob: ebd981c352c6b9d44de9409f68214ddcf8ef2533 [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
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000026use crate::layout::{boot_stack_range, print_addresses, DEVICE_REGION};
Andrew Walbran730375d2022-12-21 14:04:34 +000027use crate::pci::{check_pci, get_bar_region};
Alice Wangcee2c652023-07-05 09:16:52 +000028use aarch64_paging::paging::MemoryRegion;
29use aarch64_paging::MapError;
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000030use alloc::{vec, vec::Vec};
Andrew Walbran730375d2022-12-21 14:04:34 +000031use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010032use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000033use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000034use vmbase::{
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000035 bionic, configure_heap, cstr,
36 layout::{dtb_range, rodata_range, scratch_range, text_range},
37 linker, logger, main,
Alice Wangcee2c652023-07-05 09:16:52 +000038 memory::{PageTable, SIZE_64KB},
Alice Wanga3931aa2023-07-05 12:52:09 +000039};
Andrew Walbraneef98202022-04-27 16:23:06 +000040
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000041static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
42static mut ZEROED_DATA: [u32; 10] = [0; 10];
43static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
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
Alice Wangcee2c652023-07-05 09:16:52 +000048fn init_page_table(pci_bar_range: &MemoryRegion) -> Result<(), MapError> {
49 let mut page_table = PageTable::default();
50
51 page_table.map_device(&DEVICE_REGION)?;
52 page_table.map_code(&text_range().into())?;
53 page_table.map_rodata(&rodata_range().into())?;
54 page_table.map_data(&scratch_range().into())?;
55 page_table.map_data(&boot_stack_range().into())?;
56 page_table.map_rodata(&dtb_range().into())?;
57 page_table.map_device(pci_bar_range)?;
58
59 info!("Activating IdMap...");
60 // SAFETY: page_table duplicates the static mappings for everything that the Rust code is
61 // aware of so activating it shouldn't have any visible effect.
62 unsafe {
63 page_table.activate();
64 }
65 info!("Activated.");
66
67 Ok(())
68}
69
Andrew Walbraneef98202022-04-27 16:23:06 +000070/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000071pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000072 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010073
Jakob Vukalovicef996292023-04-13 14:28:34 +000074 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010075 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000076 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000077 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000078 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000079 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000080
81 info!("Checking FDT...");
82 let fdt = dtb_range();
Andrew Walbran47842802023-07-05 16:56:08 +000083 let fdt_size = fdt.end.0 - fdt.start.0;
84 // SAFETY: The DTB range is valid, writable memory, and we don't construct any aliases to it.
85 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt_size) };
Andrew Walbran8217d062022-11-22 16:56:18 +000086 let fdt = Fdt::from_mut_slice(fdt).unwrap();
87 info!("FDT passed verification.");
88 check_fdt(fdt);
89
Andrew Walbran730375d2022-12-21 14:04:34 +000090 let pci_info = PciInfo::from_fdt(fdt).unwrap();
91 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000092
93 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000094
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000095 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000096
Alice Wangcee2c652023-07-05 09:16:52 +000097 init_page_table(&get_bar_region(&pci_info)).unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000098
99 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000100 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000101
Andrew Walbran47842802023-07-05 16:56:08 +0000102 // SAFETY: This is the only place where `make_pci_root` is called.
Andrew Walbran730375d2022-12-21 14:04:34 +0000103 let mut pci_root = unsafe { pci_info.make_pci_root() };
104 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000105
106 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000107}
108
David Brazdila51c6f02022-10-12 09:51:48 +0000109fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000110 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000111 // SAFETY: No concurrency issue should occur when running these tests.
112 let stack_guard = unsafe { bionic::TLS.stack_guard };
113 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000114 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
115 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000116 // Check that the TLS and guard are properly accessible from the dedicated register.
117 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
118 // Check that the LLVM __stack_chk_guard alias is also properly set up.
119 assert_eq!(
120 stack_guard,
121 // SAFETY: No concurrency issue should occur when running these tests.
122 unsafe { linker::__stack_chk_guard },
123 );
David Brazdila51c6f02022-10-12 09:51:48 +0000124}
125
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000126fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100127 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran47842802023-07-05 16:56:08 +0000128 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000129 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000130 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000131 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000132
133 assert_eq!(INITIALISED_DATA[0], 1);
134 assert_eq!(INITIALISED_DATA[1], 2);
135 assert_eq!(INITIALISED_DATA[2], 3);
136 assert_eq!(INITIALISED_DATA[3], 4);
137
Andrew Walbran47842802023-07-05 16:56:08 +0000138 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
139 // chance of concurrent access.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000140 let zeroed_data = unsafe { &mut ZEROED_DATA };
Andrew Walbran47842802023-07-05 16:56:08 +0000141 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
142 // chance of concurrent access.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000143 let mutable_data = unsafe { &mut MUTABLE_DATA };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000144
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000145 for element in zeroed_data.iter() {
146 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000147 }
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000148 zeroed_data[0] = 13;
149 assert_eq!(zeroed_data[0], 13);
150 zeroed_data[0] = 0;
151 assert_eq!(zeroed_data[0], 0);
152
153 assert_eq!(mutable_data[0], 1);
154 assert_eq!(mutable_data[1], 2);
155 assert_eq!(mutable_data[2], 3);
156 assert_eq!(mutable_data[3], 4);
157 mutable_data[0] += 41;
158 assert_eq!(mutable_data[0], 42);
159 mutable_data[0] -= 41;
160 assert_eq!(mutable_data[0], 1);
161
David Brazdilb41aa8f2022-07-05 12:41:00 +0100162 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000163}
164
Andrew Walbran8217d062022-11-22 16:56:18 +0000165fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000166 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100167 info!("memory @ {reg:#x?}");
168 }
169
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000170 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000171
172 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000173 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000174 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
175 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000176}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000177
Andrew Walbran8217d062022-11-22 16:56:18 +0000178fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000179 writer.unpack().unwrap();
180 info!("FDT successfully unpacked.");
181
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000182 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000183 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000184 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000185 let mut child = node.add_subnode(name).unwrap();
186 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
187
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000188 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000189 child.appendprop(name, b"property-value\0").unwrap();
190 info!("Appended property '{}'.", name.to_str().unwrap());
191
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000192 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000193 let addr = 0x0123_4567u64;
194 let size = 0x89ab_cdefu64;
195 child.appendprop_addrrange(name, addr, size).unwrap();
196 info!("Appended property '{}'.", name.to_str().unwrap());
197
198 let writer = child.fdt();
199 writer.pack().unwrap();
200 info!("FDT successfully packed.");
201
David Brazdil1baa9a92022-06-28 14:47:50 +0100202 info!("FDT checks done.");
203}
204
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000205fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100206 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000207 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
208 assert_eq!(vector[0], 1);
209 assert_eq!(vector[1], 2);
210 assert_eq!(vector[2], 3);
211 assert_eq!(vector[3], 4);
212 vector[2] = 42;
213 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100214 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000215}
David Brazdil9a83e612022-09-27 17:38:10 +0000216
217fn check_dice() {
218 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000219 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000220 assert_eq!(
221 hash,
222 [
223 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
224 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
225 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
226 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
227 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
228 ]
229 );
230}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000231
232macro_rules! log_all_levels {
233 ($msg:literal) => {{
234 error!($msg);
235 warn!($msg);
236 info!($msg);
237 debug!($msg);
238 trace!($msg);
239 }};
240}
241
242fn emit_suppressed_log() {
243 {
244 let _guard = logger::suppress();
245 log_all_levels!("Suppressed message");
246 }
247 log_all_levels!("Unsuppressed message");
248}