blob: 6f513eeaf01b597a5ee42a67507253babba62b91 [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};
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000031use cstr::cstr;
Andrew Walbran730375d2022-12-21 14:04:34 +000032use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010033use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000034use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000035use vmbase::{
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000036 bionic, configure_heap,
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000037 layout::{dtb_range, rodata_range, scratch_range, text_range},
38 linker, logger, main,
Alice Wangcee2c652023-07-05 09:16:52 +000039 memory::{PageTable, SIZE_64KB},
Alice Wanga3931aa2023-07-05 12:52:09 +000040};
Andrew Walbraneef98202022-04-27 16:23:06 +000041
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000042static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
43static mut ZEROED_DATA: [u32; 10] = [0; 10];
44static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
45
Andrew Walbraneef98202022-04-27 16:23:06 +000046main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000047configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000048
Alice Wangcee2c652023-07-05 09:16:52 +000049fn init_page_table(pci_bar_range: &MemoryRegion) -> Result<(), MapError> {
50 let mut page_table = PageTable::default();
51
52 page_table.map_device(&DEVICE_REGION)?;
53 page_table.map_code(&text_range().into())?;
54 page_table.map_rodata(&rodata_range().into())?;
55 page_table.map_data(&scratch_range().into())?;
56 page_table.map_data(&boot_stack_range().into())?;
57 page_table.map_rodata(&dtb_range().into())?;
58 page_table.map_device(pci_bar_range)?;
59
60 info!("Activating IdMap...");
61 // SAFETY: page_table duplicates the static mappings for everything that the Rust code is
62 // aware of so activating it shouldn't have any visible effect.
63 unsafe {
64 page_table.activate();
65 }
66 info!("Activated.");
67
68 Ok(())
69}
70
Andrew Walbraneef98202022-04-27 16:23:06 +000071/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000072pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000073 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010074
Jakob Vukalovicef996292023-04-13 14:28:34 +000075 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010076 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000077 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000078 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000079 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000080 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000081
82 info!("Checking FDT...");
83 let fdt = dtb_range();
Andrew Walbran47842802023-07-05 16:56:08 +000084 let fdt_size = fdt.end.0 - fdt.start.0;
85 // SAFETY: The DTB range is valid, writable memory, and we don't construct any aliases to it.
86 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt_size) };
Andrew Walbran8217d062022-11-22 16:56:18 +000087 let fdt = Fdt::from_mut_slice(fdt).unwrap();
88 info!("FDT passed verification.");
89 check_fdt(fdt);
90
Andrew Walbran730375d2022-12-21 14:04:34 +000091 let pci_info = PciInfo::from_fdt(fdt).unwrap();
92 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000093
94 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000095
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000096 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000097
Alice Wangcee2c652023-07-05 09:16:52 +000098 init_page_table(&get_bar_region(&pci_info)).unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +000099
100 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000101 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000102
Andrew Walbran47842802023-07-05 16:56:08 +0000103 // SAFETY: This is the only place where `make_pci_root` is called.
Andrew Walbran730375d2022-12-21 14:04:34 +0000104 let mut pci_root = unsafe { pci_info.make_pci_root() };
105 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000106
107 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000108}
109
David Brazdila51c6f02022-10-12 09:51:48 +0000110fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000111 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000112 // SAFETY: No concurrency issue should occur when running these tests.
113 let stack_guard = unsafe { bionic::TLS.stack_guard };
114 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000115 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
116 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000117 // Check that the TLS and guard are properly accessible from the dedicated register.
118 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
119 // Check that the LLVM __stack_chk_guard alias is also properly set up.
120 assert_eq!(
121 stack_guard,
122 // SAFETY: No concurrency issue should occur when running these tests.
123 unsafe { linker::__stack_chk_guard },
124 );
David Brazdila51c6f02022-10-12 09:51:48 +0000125}
126
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000127fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100128 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran47842802023-07-05 16:56:08 +0000129 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000130 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000131 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000132 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000133
134 assert_eq!(INITIALISED_DATA[0], 1);
135 assert_eq!(INITIALISED_DATA[1], 2);
136 assert_eq!(INITIALISED_DATA[2], 3);
137 assert_eq!(INITIALISED_DATA[3], 4);
138
Andrew Walbran47842802023-07-05 16:56:08 +0000139 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
140 // chance of concurrent access.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000141 let zeroed_data = unsafe { &mut ZEROED_DATA };
Andrew Walbran47842802023-07-05 16:56:08 +0000142 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
143 // chance of concurrent access.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000144 let mutable_data = unsafe { &mut MUTABLE_DATA };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000145
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000146 for element in zeroed_data.iter() {
147 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000148 }
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000149 zeroed_data[0] = 13;
150 assert_eq!(zeroed_data[0], 13);
151 zeroed_data[0] = 0;
152 assert_eq!(zeroed_data[0], 0);
153
154 assert_eq!(mutable_data[0], 1);
155 assert_eq!(mutable_data[1], 2);
156 assert_eq!(mutable_data[2], 3);
157 assert_eq!(mutable_data[3], 4);
158 mutable_data[0] += 41;
159 assert_eq!(mutable_data[0], 42);
160 mutable_data[0] -= 41;
161 assert_eq!(mutable_data[0], 1);
162
David Brazdilb41aa8f2022-07-05 12:41:00 +0100163 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000164}
165
Andrew Walbran8217d062022-11-22 16:56:18 +0000166fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000167 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100168 info!("memory @ {reg:#x?}");
169 }
170
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000171 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000172
173 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000174 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000175 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
176 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000177}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000178
Andrew Walbran8217d062022-11-22 16:56:18 +0000179fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000180 writer.unpack().unwrap();
181 info!("FDT successfully unpacked.");
182
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000183 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000184 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000185 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000186 let mut child = node.add_subnode(name).unwrap();
187 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
188
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000189 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000190 child.appendprop(name, b"property-value\0").unwrap();
191 info!("Appended property '{}'.", name.to_str().unwrap());
192
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000193 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000194 let addr = 0x0123_4567u64;
195 let size = 0x89ab_cdefu64;
196 child.appendprop_addrrange(name, addr, size).unwrap();
197 info!("Appended property '{}'.", name.to_str().unwrap());
198
199 let writer = child.fdt();
200 writer.pack().unwrap();
201 info!("FDT successfully packed.");
202
David Brazdil1baa9a92022-06-28 14:47:50 +0100203 info!("FDT checks done.");
204}
205
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000206fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100207 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000208 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
209 assert_eq!(vector[0], 1);
210 assert_eq!(vector[1], 2);
211 assert_eq!(vector[2], 3);
212 assert_eq!(vector[3], 4);
213 vector[2] = 42;
214 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100215 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000216}
David Brazdil9a83e612022-09-27 17:38:10 +0000217
218fn check_dice() {
219 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000220 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000221 assert_eq!(
222 hash,
223 [
224 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
225 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
226 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
227 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
228 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
229 ]
230 );
231}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000232
233macro_rules! log_all_levels {
234 ($msg:literal) => {{
235 error!($msg);
236 warn!($msg);
237 info!($msg);
238 debug!($msg);
239 trace!($msg);
240 }};
241}
242
243fn emit_suppressed_log() {
244 {
245 let _guard = logger::suppress();
246 log_all_levels!("Suppressed message");
247 }
248 log_all_levels!("Unsuppressed message");
249}