blob: ed0275bd2944ece16dabad95f3d0885050ac3093 [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
Andrew Walbran153aad92022-06-28 15:51:13 +000026use crate::layout::{
David Brazdila51c6f02022-10-12 09:51:48 +000027 bionic_tls, dtb_range, print_addresses, rodata_range, stack_chk_guard, text_range,
28 writable_region, DEVICE_REGION,
Andrew Walbran13564542022-04-20 16:29:45 +000029};
Andrew Walbran730375d2022-12-21 14:04:34 +000030use crate::pci::{check_pci, get_bar_region};
Andrew Walbran8217d062022-11-22 16:56:18 +000031use aarch64_paging::{idmap::IdMap, paging::Attributes};
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000032use alloc::{vec, vec::Vec};
33use buddy_system_allocator::LockedHeap;
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +000034use core::ffi::CStr;
Andrew Walbran730375d2022-12-21 14:04:34 +000035use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010036use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000037use log::{debug, error, info, trace, warn, LevelFilter};
38use vmbase::{logger, main};
Andrew Walbraneef98202022-04-27 16:23:06 +000039
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000040static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
41static mut ZEROED_DATA: [u32; 10] = [0; 10];
42static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
43
Andrew Walbran13564542022-04-20 16:29:45 +000044const ASID: usize = 1;
45const ROOT_LEVEL: usize = 1;
46
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000047#[global_allocator]
48static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
49
50static mut HEAP: [u8; 65536] = [0; 65536];
51
Andrew Walbraneef98202022-04-27 16:23:06 +000052main!(main);
53
54/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000055pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010056 logger::init(LevelFilter::Debug).unwrap();
57
Jakob Vukalovicef996292023-04-13 14:28:34 +000058 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010059 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000060 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000061 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000062 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000063 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000064
65 info!("Checking FDT...");
66 let fdt = dtb_range();
67 let fdt =
68 unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt.end.0 - fdt.start.0) };
69 let fdt = Fdt::from_mut_slice(fdt).unwrap();
70 info!("FDT passed verification.");
71 check_fdt(fdt);
72
Andrew Walbran730375d2022-12-21 14:04:34 +000073 let pci_info = PciInfo::from_fdt(fdt).unwrap();
74 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000075
76 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000077
78 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +010079 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000080 }
81
82 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000083
84 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
85 idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
86 idmap
87 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000088 &text_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000089 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
90 )
91 .unwrap();
92 idmap
93 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000094 &rodata_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000095 Attributes::NORMAL
96 | Attributes::NON_GLOBAL
97 | Attributes::READ_ONLY
98 | Attributes::EXECUTE_NEVER,
99 )
100 .unwrap();
101 idmap
102 .map_range(
103 &writable_region(),
104 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
105 )
106 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000107 idmap
108 .map_range(
109 &dtb_range().into(),
110 Attributes::NORMAL
111 | Attributes::NON_GLOBAL
112 | Attributes::READ_ONLY
113 | Attributes::EXECUTE_NEVER,
114 )
115 .unwrap();
116 idmap
Andrew Walbran730375d2022-12-21 14:04:34 +0000117 .map_range(&get_bar_region(&pci_info), Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER)
Andrew Walbran8217d062022-11-22 16:56:18 +0000118 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000119
David Brazdilb41aa8f2022-07-05 12:41:00 +0100120 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000121 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000122 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100123 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000124
125 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000126 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000127
Andrew Walbran730375d2022-12-21 14:04:34 +0000128 let mut pci_root = unsafe { pci_info.make_pci_root() };
129 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000130
131 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000132}
133
David Brazdila51c6f02022-10-12 09:51:48 +0000134fn check_stack_guard() {
135 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
136
137 info!("Testing stack guard");
138 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
139}
140
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000141fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100142 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000143 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100144 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
145 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
146 info!("HEAP: {:?}", HEAP.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000147 }
148
149 assert_eq!(INITIALISED_DATA[0], 1);
150 assert_eq!(INITIALISED_DATA[1], 2);
151 assert_eq!(INITIALISED_DATA[2], 3);
152 assert_eq!(INITIALISED_DATA[3], 4);
153
154 unsafe {
155 for element in ZEROED_DATA.iter() {
156 assert_eq!(*element, 0);
157 }
158 ZEROED_DATA[0] = 13;
159 assert_eq!(ZEROED_DATA[0], 13);
160 ZEROED_DATA[0] = 0;
161 assert_eq!(ZEROED_DATA[0], 0);
162
163 assert_eq!(MUTABLE_DATA[0], 1);
164 assert_eq!(MUTABLE_DATA[1], 2);
165 assert_eq!(MUTABLE_DATA[2], 3);
166 assert_eq!(MUTABLE_DATA[3], 4);
167 MUTABLE_DATA[0] += 41;
168 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000169 MUTABLE_DATA[0] -= 41;
170 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000171 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100172 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000173}
174
Andrew Walbran8217d062022-11-22 16:56:18 +0000175fn check_fdt(reader: &Fdt) {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000176 for reg in reader.memory().unwrap().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100177 info!("memory @ {reg:#x?}");
178 }
179
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000180 let compatible = CStr::from_bytes_with_nul(b"ns16550a\0").unwrap();
181
182 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000183 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000184 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
185 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000186}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000187
Andrew Walbran8217d062022-11-22 16:56:18 +0000188fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000189 writer.unpack().unwrap();
190 info!("FDT successfully unpacked.");
191
192 let path = CStr::from_bytes_with_nul(b"/memory\0").unwrap();
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000193 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000194 let name = CStr::from_bytes_with_nul(b"child\0").unwrap();
195 let mut child = node.add_subnode(name).unwrap();
196 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
197
198 let name = CStr::from_bytes_with_nul(b"str-property\0").unwrap();
199 child.appendprop(name, b"property-value\0").unwrap();
200 info!("Appended property '{}'.", name.to_str().unwrap());
201
202 let name = CStr::from_bytes_with_nul(b"pair-property\0").unwrap();
203 let addr = 0x0123_4567u64;
204 let size = 0x89ab_cdefu64;
205 child.appendprop_addrrange(name, addr, size).unwrap();
206 info!("Appended property '{}'.", name.to_str().unwrap());
207
208 let writer = child.fdt();
209 writer.pack().unwrap();
210 info!("FDT successfully packed.");
211
David Brazdil1baa9a92022-06-28 14:47:50 +0100212 info!("FDT checks done.");
213}
214
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000215fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100216 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000217 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
218 assert_eq!(vector[0], 1);
219 assert_eq!(vector[1], 2);
220 assert_eq!(vector[2], 3);
221 assert_eq!(vector[3], 4);
222 vector[2] = 42;
223 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100224 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000225}
David Brazdil9a83e612022-09-27 17:38:10 +0000226
227fn check_dice() {
228 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000229 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000230 assert_eq!(
231 hash,
232 [
233 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
234 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
235 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
236 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
237 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
238 ]
239 );
240}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000241
242macro_rules! log_all_levels {
243 ($msg:literal) => {{
244 error!($msg);
245 warn!($msg);
246 info!($msg);
247 debug!($msg);
248 trace!($msg);
249 }};
250}
251
252fn emit_suppressed_log() {
253 {
254 let _guard = logger::suppress();
255 log_all_levels!("Suppressed message");
256 }
257 log_all_levels!("Unsuppressed message");
258}