blob: 8aa9f0478e20c31379c8ef40c73f630fad26de64 [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);
112 // Check that the TLS and guard are properly accessible from the dedicated register.
113 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
114 // Check that the LLVM __stack_chk_guard alias is also properly set up.
115 assert_eq!(
116 stack_guard,
117 // SAFETY: No concurrency issue should occur when running these tests.
118 unsafe { linker::__stack_chk_guard },
119 );
David Brazdila51c6f02022-10-12 09:51:48 +0000120}
121
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000122fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100123 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000124 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100125 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
126 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000127 }
128
129 assert_eq!(INITIALISED_DATA[0], 1);
130 assert_eq!(INITIALISED_DATA[1], 2);
131 assert_eq!(INITIALISED_DATA[2], 3);
132 assert_eq!(INITIALISED_DATA[3], 4);
133
134 unsafe {
135 for element in ZEROED_DATA.iter() {
136 assert_eq!(*element, 0);
137 }
138 ZEROED_DATA[0] = 13;
139 assert_eq!(ZEROED_DATA[0], 13);
140 ZEROED_DATA[0] = 0;
141 assert_eq!(ZEROED_DATA[0], 0);
142
143 assert_eq!(MUTABLE_DATA[0], 1);
144 assert_eq!(MUTABLE_DATA[1], 2);
145 assert_eq!(MUTABLE_DATA[2], 3);
146 assert_eq!(MUTABLE_DATA[3], 4);
147 MUTABLE_DATA[0] += 41;
148 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000149 MUTABLE_DATA[0] -= 41;
150 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000151 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100152 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000153}
154
Andrew Walbran8217d062022-11-22 16:56:18 +0000155fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000156 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100157 info!("memory @ {reg:#x?}");
158 }
159
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000160 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000161
162 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000163 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000164 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
165 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000166}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000167
Andrew Walbran8217d062022-11-22 16:56:18 +0000168fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000169 writer.unpack().unwrap();
170 info!("FDT successfully unpacked.");
171
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000172 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000173 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000174 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000175 let mut child = node.add_subnode(name).unwrap();
176 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
177
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000178 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000179 child.appendprop(name, b"property-value\0").unwrap();
180 info!("Appended property '{}'.", name.to_str().unwrap());
181
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000182 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000183 let addr = 0x0123_4567u64;
184 let size = 0x89ab_cdefu64;
185 child.appendprop_addrrange(name, addr, size).unwrap();
186 info!("Appended property '{}'.", name.to_str().unwrap());
187
188 let writer = child.fdt();
189 writer.pack().unwrap();
190 info!("FDT successfully packed.");
191
David Brazdil1baa9a92022-06-28 14:47:50 +0100192 info!("FDT checks done.");
193}
194
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000195fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100196 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000197 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
198 assert_eq!(vector[0], 1);
199 assert_eq!(vector[1], 2);
200 assert_eq!(vector[2], 3);
201 assert_eq!(vector[3], 4);
202 vector[2] = 42;
203 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100204 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000205}
David Brazdil9a83e612022-09-27 17:38:10 +0000206
207fn check_dice() {
208 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000209 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000210 assert_eq!(
211 hash,
212 [
213 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
214 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
215 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
216 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
217 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
218 ]
219 );
220}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000221
222macro_rules! log_all_levels {
223 ($msg:literal) => {{
224 error!($msg);
225 warn!($msg);
226 info!($msg);
227 debug!($msg);
228 trace!($msg);
229 }};
230}
231
232fn emit_suppressed_log() {
233 {
234 let _guard = logger::suppress();
235 log_all_levels!("Suppressed message");
236 }
237 log_all_levels!("Unsuppressed message");
238}