blob: 9ec2dc46d9d19a9f5feac18bba8195f763e943c1 [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;
Andrew Walbran4a59a172022-11-22 17:35:27 +000037use log::{debug, info, trace, LevelFilter};
David Brazdilb41aa8f2022-07-05 12:41:00 +010038use vmbase::{logger, main, println};
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
Andrew Walbraneef98202022-04-27 16:23:06 +000058 println!("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);
Andrew Walbran13564542022-04-20 16:29:45 +0000130}
131
David Brazdila51c6f02022-10-12 09:51:48 +0000132fn check_stack_guard() {
133 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
134
135 info!("Testing stack guard");
136 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
137}
138
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000139fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100140 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000141 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100142 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
143 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
144 info!("HEAP: {:?}", HEAP.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000145 }
146
147 assert_eq!(INITIALISED_DATA[0], 1);
148 assert_eq!(INITIALISED_DATA[1], 2);
149 assert_eq!(INITIALISED_DATA[2], 3);
150 assert_eq!(INITIALISED_DATA[3], 4);
151
152 unsafe {
153 for element in ZEROED_DATA.iter() {
154 assert_eq!(*element, 0);
155 }
156 ZEROED_DATA[0] = 13;
157 assert_eq!(ZEROED_DATA[0], 13);
158 ZEROED_DATA[0] = 0;
159 assert_eq!(ZEROED_DATA[0], 0);
160
161 assert_eq!(MUTABLE_DATA[0], 1);
162 assert_eq!(MUTABLE_DATA[1], 2);
163 assert_eq!(MUTABLE_DATA[2], 3);
164 assert_eq!(MUTABLE_DATA[3], 4);
165 MUTABLE_DATA[0] += 41;
166 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000167 MUTABLE_DATA[0] -= 41;
168 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000169 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100170 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000171}
172
Andrew Walbran8217d062022-11-22 16:56:18 +0000173fn check_fdt(reader: &Fdt) {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000174 for reg in reader.memory().unwrap().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100175 info!("memory @ {reg:#x?}");
176 }
177
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000178 let compatible = CStr::from_bytes_with_nul(b"ns16550a\0").unwrap();
179
180 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000181 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000182 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
183 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000184}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000185
Andrew Walbran8217d062022-11-22 16:56:18 +0000186fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000187 writer.unpack().unwrap();
188 info!("FDT successfully unpacked.");
189
190 let path = CStr::from_bytes_with_nul(b"/memory\0").unwrap();
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000191 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000192 let name = CStr::from_bytes_with_nul(b"child\0").unwrap();
193 let mut child = node.add_subnode(name).unwrap();
194 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
195
196 let name = CStr::from_bytes_with_nul(b"str-property\0").unwrap();
197 child.appendprop(name, b"property-value\0").unwrap();
198 info!("Appended property '{}'.", name.to_str().unwrap());
199
200 let name = CStr::from_bytes_with_nul(b"pair-property\0").unwrap();
201 let addr = 0x0123_4567u64;
202 let size = 0x89ab_cdefu64;
203 child.appendprop_addrrange(name, addr, size).unwrap();
204 info!("Appended property '{}'.", name.to_str().unwrap());
205
206 let writer = child.fdt();
207 writer.pack().unwrap();
208 info!("FDT successfully packed.");
209
David Brazdil1baa9a92022-06-28 14:47:50 +0100210 info!("FDT checks done.");
211}
212
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000213fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100214 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000215 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
216 assert_eq!(vector[0], 1);
217 assert_eq!(vector[1], 2);
218 assert_eq!(vector[2], 3);
219 assert_eq!(vector[3], 4);
220 vector[2] = 42;
221 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100222 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000223}
David Brazdil9a83e612022-09-27 17:38:10 +0000224
225fn check_dice() {
226 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000227 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000228 assert_eq!(
229 hash,
230 [
231 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
232 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
233 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
234 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
235 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
236 ]
237 );
238}