blob: 8086885f44c98bb150b8771c05cb36b9e43f7222 [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();
83 let fdt =
84 unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt.end.0 - fdt.start.0) };
85 let fdt = Fdt::from_mut_slice(fdt).unwrap();
86 info!("FDT passed verification.");
87 check_fdt(fdt);
88
Andrew Walbran730375d2022-12-21 14:04:34 +000089 let pci_info = PciInfo::from_fdt(fdt).unwrap();
90 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000091
92 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000093
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000094 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000095
Alice Wangcee2c652023-07-05 09:16:52 +000096 init_page_table(&get_bar_region(&pci_info)).unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000097
98 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +000099 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000100
Andrew Walbran730375d2022-12-21 14:04:34 +0000101 let mut pci_root = unsafe { pci_info.make_pci_root() };
102 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000103
104 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000105}
106
David Brazdila51c6f02022-10-12 09:51:48 +0000107fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000108 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000109 // SAFETY: No concurrency issue should occur when running these tests.
110 let stack_guard = unsafe { bionic::TLS.stack_guard };
111 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000112 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
113 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000114 // Check that the TLS and guard are properly accessible from the dedicated register.
115 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
116 // Check that the LLVM __stack_chk_guard alias is also properly set up.
117 assert_eq!(
118 stack_guard,
119 // SAFETY: No concurrency issue should occur when running these tests.
120 unsafe { linker::__stack_chk_guard },
121 );
David Brazdila51c6f02022-10-12 09:51:48 +0000122}
123
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000124fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100125 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000126 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100127 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
128 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000129 }
130
131 assert_eq!(INITIALISED_DATA[0], 1);
132 assert_eq!(INITIALISED_DATA[1], 2);
133 assert_eq!(INITIALISED_DATA[2], 3);
134 assert_eq!(INITIALISED_DATA[3], 4);
135
136 unsafe {
137 for element in ZEROED_DATA.iter() {
138 assert_eq!(*element, 0);
139 }
140 ZEROED_DATA[0] = 13;
141 assert_eq!(ZEROED_DATA[0], 13);
142 ZEROED_DATA[0] = 0;
143 assert_eq!(ZEROED_DATA[0], 0);
144
145 assert_eq!(MUTABLE_DATA[0], 1);
146 assert_eq!(MUTABLE_DATA[1], 2);
147 assert_eq!(MUTABLE_DATA[2], 3);
148 assert_eq!(MUTABLE_DATA[3], 4);
149 MUTABLE_DATA[0] += 41;
150 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000151 MUTABLE_DATA[0] -= 41;
152 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000153 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100154 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000155}
156
Andrew Walbran8217d062022-11-22 16:56:18 +0000157fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000158 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100159 info!("memory @ {reg:#x?}");
160 }
161
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000162 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000163
164 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000165 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000166 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
167 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000168}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000169
Andrew Walbran8217d062022-11-22 16:56:18 +0000170fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000171 writer.unpack().unwrap();
172 info!("FDT successfully unpacked.");
173
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000174 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000175 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000176 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000177 let mut child = node.add_subnode(name).unwrap();
178 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
179
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000180 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000181 child.appendprop(name, b"property-value\0").unwrap();
182 info!("Appended property '{}'.", name.to_str().unwrap());
183
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000184 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000185 let addr = 0x0123_4567u64;
186 let size = 0x89ab_cdefu64;
187 child.appendprop_addrrange(name, addr, size).unwrap();
188 info!("Appended property '{}'.", name.to_str().unwrap());
189
190 let writer = child.fdt();
191 writer.pack().unwrap();
192 info!("FDT successfully packed.");
193
David Brazdil1baa9a92022-06-28 14:47:50 +0100194 info!("FDT checks done.");
195}
196
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000197fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100198 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000199 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
200 assert_eq!(vector[0], 1);
201 assert_eq!(vector[1], 2);
202 assert_eq!(vector[2], 3);
203 assert_eq!(vector[3], 4);
204 vector[2] = 42;
205 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100206 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000207}
David Brazdil9a83e612022-09-27 17:38:10 +0000208
209fn check_dice() {
210 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000211 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000212 assert_eq!(
213 hash,
214 [
215 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
216 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
217 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
218 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
219 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
220 ]
221 );
222}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000223
224macro_rules! log_all_levels {
225 ($msg:literal) => {{
226 error!($msg);
227 warn!($msg);
228 info!($msg);
229 debug!($msg);
230 trace!($msg);
231 }};
232}
233
234fn emit_suppressed_log() {
235 {
236 let _guard = logger::suppress();
237 log_all_levels!("Suppressed message");
238 }
239 log_all_levels!("Unsuppressed message");
240}