blob: 41766261f961eaefeb4b640ae967bf22581cffe0 [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
Alice Wanga3931aa2023-07-05 12:52:09 +000026use crate::layout::{bionic_tls, 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::{
35 configure_heap, cstr,
36 layout::{dtb_range, rodata_range, scratch_range, stack_chk_guard, text_range},
37 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) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010072 logger::init(LevelFilter::Debug).unwrap();
73
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() {
108 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
109
110 info!("Testing stack guard");
111 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
112}
113
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000114fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100115 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000116 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100117 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
118 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000119 }
120
121 assert_eq!(INITIALISED_DATA[0], 1);
122 assert_eq!(INITIALISED_DATA[1], 2);
123 assert_eq!(INITIALISED_DATA[2], 3);
124 assert_eq!(INITIALISED_DATA[3], 4);
125
126 unsafe {
127 for element in ZEROED_DATA.iter() {
128 assert_eq!(*element, 0);
129 }
130 ZEROED_DATA[0] = 13;
131 assert_eq!(ZEROED_DATA[0], 13);
132 ZEROED_DATA[0] = 0;
133 assert_eq!(ZEROED_DATA[0], 0);
134
135 assert_eq!(MUTABLE_DATA[0], 1);
136 assert_eq!(MUTABLE_DATA[1], 2);
137 assert_eq!(MUTABLE_DATA[2], 3);
138 assert_eq!(MUTABLE_DATA[3], 4);
139 MUTABLE_DATA[0] += 41;
140 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000141 MUTABLE_DATA[0] -= 41;
142 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000143 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100144 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000145}
146
Andrew Walbran8217d062022-11-22 16:56:18 +0000147fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000148 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100149 info!("memory @ {reg:#x?}");
150 }
151
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000152 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000153
154 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000155 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000156 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
157 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000158}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000159
Andrew Walbran8217d062022-11-22 16:56:18 +0000160fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000161 writer.unpack().unwrap();
162 info!("FDT successfully unpacked.");
163
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000164 let path = cstr!("/memory");
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000165 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000166 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000167 let mut child = node.add_subnode(name).unwrap();
168 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
169
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000170 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000171 child.appendprop(name, b"property-value\0").unwrap();
172 info!("Appended property '{}'.", name.to_str().unwrap());
173
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000174 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000175 let addr = 0x0123_4567u64;
176 let size = 0x89ab_cdefu64;
177 child.appendprop_addrrange(name, addr, size).unwrap();
178 info!("Appended property '{}'.", name.to_str().unwrap());
179
180 let writer = child.fdt();
181 writer.pack().unwrap();
182 info!("FDT successfully packed.");
183
David Brazdil1baa9a92022-06-28 14:47:50 +0100184 info!("FDT checks done.");
185}
186
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000187fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100188 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000189 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
190 assert_eq!(vector[0], 1);
191 assert_eq!(vector[1], 2);
192 assert_eq!(vector[2], 3);
193 assert_eq!(vector[3], 4);
194 vector[2] = 42;
195 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100196 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000197}
David Brazdil9a83e612022-09-27 17:38:10 +0000198
199fn check_dice() {
200 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000201 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000202 assert_eq!(
203 hash,
204 [
205 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
206 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
207 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
208 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
209 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
210 ]
211 );
212}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000213
214macro_rules! log_all_levels {
215 ($msg:literal) => {{
216 error!($msg);
217 warn!($msg);
218 info!($msg);
219 debug!($msg);
220 trace!($msg);
221 }};
222}
223
224fn emit_suppressed_log() {
225 {
226 let _guard = logger::suppress();
227 log_all_levels!("Suppressed message");
228 }
229 log_all_levels!("Unsuppressed message");
230}