blob: da82b1721c2e1c3108147bbd0ac524674199b8df [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};
Chariseee5b78342024-04-08 17:59:31 +000031use core::ptr::addr_of_mut;
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000032use cstr::cstr;
Andrew Walbran730375d2022-12-21 14:04:34 +000033use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010034use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000035use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000036use vmbase::{
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000037 bionic, configure_heap,
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000038 layout::{dtb_range, rodata_range, scratch_range, text_range},
39 linker, logger, main,
Alice Wangcee2c652023-07-05 09:16:52 +000040 memory::{PageTable, SIZE_64KB},
Alice Wanga3931aa2023-07-05 12:52:09 +000041};
Andrew Walbraneef98202022-04-27 16:23:06 +000042
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000043static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
44static mut ZEROED_DATA: [u32; 10] = [0; 10];
45static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
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
Alice Wangcee2c652023-07-05 09:16:52 +000050fn init_page_table(pci_bar_range: &MemoryRegion) -> Result<(), MapError> {
51 let mut page_table = PageTable::default();
52
53 page_table.map_device(&DEVICE_REGION)?;
54 page_table.map_code(&text_range().into())?;
55 page_table.map_rodata(&rodata_range().into())?;
56 page_table.map_data(&scratch_range().into())?;
57 page_table.map_data(&boot_stack_range().into())?;
58 page_table.map_rodata(&dtb_range().into())?;
59 page_table.map_device(pci_bar_range)?;
60
61 info!("Activating IdMap...");
62 // SAFETY: page_table duplicates the static mappings for everything that the Rust code is
63 // aware of so activating it shouldn't have any visible effect.
64 unsafe {
65 page_table.activate();
66 }
67 info!("Activated.");
68
69 Ok(())
70}
71
Andrew Walbraneef98202022-04-27 16:23:06 +000072/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000073pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000074 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010075
Jakob Vukalovicef996292023-04-13 14:28:34 +000076 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010077 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000078 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000079 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000080 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000081 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000082
83 info!("Checking FDT...");
84 let fdt = dtb_range();
Andrew Walbran47842802023-07-05 16:56:08 +000085 let fdt_size = fdt.end.0 - fdt.start.0;
86 // SAFETY: The DTB range is valid, writable memory, and we don't construct any aliases to it.
87 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt_size) };
Andrew Walbran8217d062022-11-22 16:56:18 +000088 let fdt = Fdt::from_mut_slice(fdt).unwrap();
89 info!("FDT passed verification.");
90 check_fdt(fdt);
91
Andrew Walbran730375d2022-12-21 14:04:34 +000092 let pci_info = PciInfo::from_fdt(fdt).unwrap();
93 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000094
95 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000096
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000097 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000098
Alice Wangcee2c652023-07-05 09:16:52 +000099 init_page_table(&get_bar_region(&pci_info)).unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000100
101 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000102 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000103
Andrew Walbran47842802023-07-05 16:56:08 +0000104 // SAFETY: This is the only place where `make_pci_root` is called.
Andrew Walbran730375d2022-12-21 14:04:34 +0000105 let mut pci_root = unsafe { pci_info.make_pci_root() };
106 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000107
108 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000109}
110
David Brazdila51c6f02022-10-12 09:51:48 +0000111fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000112 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000113 // SAFETY: No concurrency issue should occur when running these tests.
114 let stack_guard = unsafe { bionic::TLS.stack_guard };
115 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000116 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
117 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000118 // Check that the TLS and guard are properly accessible from the dedicated register.
119 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
120 // Check that the LLVM __stack_chk_guard alias is also properly set up.
121 assert_eq!(
122 stack_guard,
123 // SAFETY: No concurrency issue should occur when running these tests.
124 unsafe { linker::__stack_chk_guard },
125 );
David Brazdila51c6f02022-10-12 09:51:48 +0000126}
127
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000128fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100129 info!("INITIALISED_DATA: {:?}", INITIALISED_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!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000132 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000133 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000134
135 assert_eq!(INITIALISED_DATA[0], 1);
136 assert_eq!(INITIALISED_DATA[1], 2);
137 assert_eq!(INITIALISED_DATA[2], 3);
138 assert_eq!(INITIALISED_DATA[3], 4);
139
Andrew Walbran47842802023-07-05 16:56:08 +0000140 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
141 // chance of concurrent access.
Chariseee5b78342024-04-08 17:59:31 +0000142 let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) };
Andrew Walbran47842802023-07-05 16:56:08 +0000143 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
144 // chance of concurrent access.
Chariseeb59cda42024-04-12 19:13:36 +0000145 let mutable_data = unsafe { &mut *addr_of_mut!(MUTABLE_DATA) };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000146
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000147 for element in zeroed_data.iter() {
148 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000149 }
Chariseee5b78342024-04-08 17:59:31 +0000150
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000151 zeroed_data[0] = 13;
152 assert_eq!(zeroed_data[0], 13);
153 zeroed_data[0] = 0;
154 assert_eq!(zeroed_data[0], 0);
155
156 assert_eq!(mutable_data[0], 1);
157 assert_eq!(mutable_data[1], 2);
158 assert_eq!(mutable_data[2], 3);
159 assert_eq!(mutable_data[3], 4);
160 mutable_data[0] += 41;
161 assert_eq!(mutable_data[0], 42);
162 mutable_data[0] -= 41;
163 assert_eq!(mutable_data[0], 1);
164
David Brazdilb41aa8f2022-07-05 12:41:00 +0100165 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000166}
167
Andrew Walbran8217d062022-11-22 16:56:18 +0000168fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000169 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100170 info!("memory @ {reg:#x?}");
171 }
172
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000173 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000174
175 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000176 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000177 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
178 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000179}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000180
Andrew Walbran8217d062022-11-22 16:56:18 +0000181fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000182 writer.unpack().unwrap();
183 info!("FDT successfully unpacked.");
184
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000185 let path = cstr!("/memory");
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000186 let node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000187 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000188 let mut child = node.add_subnode(name).unwrap();
189 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
190
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000191 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000192 child.appendprop(name, b"property-value\0").unwrap();
193 info!("Appended property '{}'.", name.to_str().unwrap());
194
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000195 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000196 let addr = 0x0123_4567u64;
197 let size = 0x89ab_cdefu64;
198 child.appendprop_addrrange(name, addr, size).unwrap();
199 info!("Appended property '{}'.", name.to_str().unwrap());
200
201 let writer = child.fdt();
202 writer.pack().unwrap();
203 info!("FDT successfully packed.");
204
David Brazdil1baa9a92022-06-28 14:47:50 +0100205 info!("FDT checks done.");
206}
207
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000208fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100209 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000210 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
211 assert_eq!(vector[0], 1);
212 assert_eq!(vector[1], 2);
213 assert_eq!(vector[2], 3);
214 assert_eq!(vector[3], 4);
215 vector[2] = 42;
216 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100217 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000218}
David Brazdil9a83e612022-09-27 17:38:10 +0000219
220fn check_dice() {
221 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000222 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000223 assert_eq!(
224 hash,
225 [
226 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
227 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
228 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
229 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
230 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
231 ]
232 );
233}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000234
235macro_rules! log_all_levels {
236 ($msg:literal) => {{
237 error!($msg);
238 warn!($msg);
239 info!($msg);
240 debug!($msg);
241 trace!($msg);
242 }};
243}
244
245fn emit_suppressed_log() {
246 {
247 let _guard = logger::suppress();
248 log_all_levels!("Suppressed message");
249 }
250 log_all_levels!("Unsuppressed message");
251}