blob: ec28a112134754ddada58715384084c53104d8df [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]
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000019#![feature(default_alloc_error_handler)]
Andrew Walbraneef98202022-04-27 16:23:06 +000020
21mod exceptions;
Andrew Walbran153aad92022-06-28 15:51:13 +000022mod layout;
Andrew Walbran8217d062022-11-22 16:56:18 +000023mod pci;
Andrew Walbraneef98202022-04-27 16:23:06 +000024
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000025extern crate alloc;
26
Andrew Walbran153aad92022-06-28 15:51:13 +000027use crate::layout::{
David Brazdila51c6f02022-10-12 09:51:48 +000028 bionic_tls, dtb_range, print_addresses, rodata_range, stack_chk_guard, text_range,
29 writable_region, DEVICE_REGION,
Andrew Walbran13564542022-04-20 16:29:45 +000030};
Andrew Walbran730375d2022-12-21 14:04:34 +000031use crate::pci::{check_pci, get_bar_region};
Andrew Walbran8217d062022-11-22 16:56:18 +000032use aarch64_paging::{idmap::IdMap, paging::Attributes};
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000033use alloc::{vec, vec::Vec};
34use buddy_system_allocator::LockedHeap;
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +000035use core::ffi::CStr;
Andrew Walbran730375d2022-12-21 14:04:34 +000036use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010037use libfdt::Fdt;
Andrew Walbran4a59a172022-11-22 17:35:27 +000038use log::{debug, info, trace, LevelFilter};
David Brazdilb41aa8f2022-07-05 12:41:00 +010039use vmbase::{logger, main, println};
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 Walbran13564542022-04-20 16:29:45 +000045const ASID: usize = 1;
46const ROOT_LEVEL: usize = 1;
47
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000048#[global_allocator]
49static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
50
51static mut HEAP: [u8; 65536] = [0; 65536];
52
Andrew Walbraneef98202022-04-27 16:23:06 +000053main!(main);
54
55/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000056pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010057 logger::init(LevelFilter::Debug).unwrap();
58
Andrew Walbraneef98202022-04-27 16:23:06 +000059 println!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010060 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000061 print_addresses();
Andrew Walbran153aad92022-06-28 15:51:13 +000062 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000063 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000064 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000065
66 info!("Checking FDT...");
67 let fdt = dtb_range();
68 let fdt =
69 unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt.end.0 - fdt.start.0) };
70 let fdt = Fdt::from_mut_slice(fdt).unwrap();
71 info!("FDT passed verification.");
72 check_fdt(fdt);
73
Andrew Walbran730375d2022-12-21 14:04:34 +000074 let pci_info = PciInfo::from_fdt(fdt).unwrap();
75 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000076
77 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000078
79 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +010080 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000081 }
82
83 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000084
85 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
86 idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
87 idmap
88 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000089 &text_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000090 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
91 )
92 .unwrap();
93 idmap
94 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000095 &rodata_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000096 Attributes::NORMAL
97 | Attributes::NON_GLOBAL
98 | Attributes::READ_ONLY
99 | Attributes::EXECUTE_NEVER,
100 )
101 .unwrap();
102 idmap
103 .map_range(
104 &writable_region(),
105 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
106 )
107 .unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +0000108 idmap
109 .map_range(
110 &dtb_range().into(),
111 Attributes::NORMAL
112 | Attributes::NON_GLOBAL
113 | Attributes::READ_ONLY
114 | Attributes::EXECUTE_NEVER,
115 )
116 .unwrap();
117 idmap
Andrew Walbran730375d2022-12-21 14:04:34 +0000118 .map_range(&get_bar_region(&pci_info), Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER)
Andrew Walbran8217d062022-11-22 16:56:18 +0000119 .unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000120
David Brazdilb41aa8f2022-07-05 12:41:00 +0100121 info!("Activating IdMap...");
Andrew Walbran4a59a172022-11-22 17:35:27 +0000122 trace!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +0000123 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100124 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000125
126 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000127 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000128
Andrew Walbran730375d2022-12-21 14:04:34 +0000129 let mut pci_root = unsafe { pci_info.make_pci_root() };
130 check_pci(&mut pci_root);
Andrew Walbran13564542022-04-20 16:29:45 +0000131}
132
David Brazdila51c6f02022-10-12 09:51:48 +0000133fn check_stack_guard() {
134 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
135
136 info!("Testing stack guard");
137 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
138}
139
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000140fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100141 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000142 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100143 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
144 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
145 info!("HEAP: {:?}", HEAP.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000146 }
147
148 assert_eq!(INITIALISED_DATA[0], 1);
149 assert_eq!(INITIALISED_DATA[1], 2);
150 assert_eq!(INITIALISED_DATA[2], 3);
151 assert_eq!(INITIALISED_DATA[3], 4);
152
153 unsafe {
154 for element in ZEROED_DATA.iter() {
155 assert_eq!(*element, 0);
156 }
157 ZEROED_DATA[0] = 13;
158 assert_eq!(ZEROED_DATA[0], 13);
159 ZEROED_DATA[0] = 0;
160 assert_eq!(ZEROED_DATA[0], 0);
161
162 assert_eq!(MUTABLE_DATA[0], 1);
163 assert_eq!(MUTABLE_DATA[1], 2);
164 assert_eq!(MUTABLE_DATA[2], 3);
165 assert_eq!(MUTABLE_DATA[3], 4);
166 MUTABLE_DATA[0] += 41;
167 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000168 MUTABLE_DATA[0] -= 41;
169 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000170 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100171 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000172}
173
Andrew Walbran8217d062022-11-22 16:56:18 +0000174fn check_fdt(reader: &Fdt) {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000175 for reg in reader.memory().unwrap().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100176 info!("memory @ {reg:#x?}");
177 }
178
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000179 let compatible = CStr::from_bytes_with_nul(b"ns16550a\0").unwrap();
180
181 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000182 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000183 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
184 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000185}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000186
Andrew Walbran8217d062022-11-22 16:56:18 +0000187fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000188 writer.unpack().unwrap();
189 info!("FDT successfully unpacked.");
190
191 let path = CStr::from_bytes_with_nul(b"/memory\0").unwrap();
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000192 let mut node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000193 let name = CStr::from_bytes_with_nul(b"child\0").unwrap();
194 let mut child = node.add_subnode(name).unwrap();
195 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
196
197 let name = CStr::from_bytes_with_nul(b"str-property\0").unwrap();
198 child.appendprop(name, b"property-value\0").unwrap();
199 info!("Appended property '{}'.", name.to_str().unwrap());
200
201 let name = CStr::from_bytes_with_nul(b"pair-property\0").unwrap();
202 let addr = 0x0123_4567u64;
203 let size = 0x89ab_cdefu64;
204 child.appendprop_addrrange(name, addr, size).unwrap();
205 info!("Appended property '{}'.", name.to_str().unwrap());
206
207 let writer = child.fdt();
208 writer.pack().unwrap();
209 info!("FDT successfully packed.");
210
David Brazdil1baa9a92022-06-28 14:47:50 +0100211 info!("FDT checks done.");
212}
213
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000214fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100215 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000216 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
217 assert_eq!(vector[0], 1);
218 assert_eq!(vector[1], 2);
219 assert_eq!(vector[2], 3);
220 assert_eq!(vector[3], 4);
221 vector[2] = 42;
222 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100223 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000224}
David Brazdil9a83e612022-09-27 17:38:10 +0000225
226fn check_dice() {
227 info!("Testing DICE integration...");
228 let hash = dice::hash("hello world".as_bytes()).expect("DiceHash failed");
229 assert_eq!(
230 hash,
231 [
232 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
233 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
234 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
235 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
236 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
237 ]
238 );
239}