blob: b305559c2973c94ba313375e4e7c28e37a47cb06 [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 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};
David Brazdil1baa9a92022-06-28 14:47:50 +010030use aarch64_paging::{
31 idmap::IdMap,
32 paging::{Attributes, MemoryRegion},
33};
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000034use alloc::{vec, vec::Vec};
35use buddy_system_allocator::LockedHeap;
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +000036use core::ffi::CStr;
David Brazdil1baa9a92022-06-28 14:47:50 +010037use libfdt::Fdt;
David Brazdilb41aa8f2022-07-05 12:41:00 +010038use log::{info, LevelFilter};
39use 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();
David Brazdil1baa9a92022-06-28 14:47:50 +010065 check_fdt();
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000066
67 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +010068 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000069 }
70
71 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000072
73 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
74 idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
75 idmap
76 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000077 &text_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000078 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
79 )
80 .unwrap();
81 idmap
82 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000083 &rodata_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000084 Attributes::NORMAL
85 | Attributes::NON_GLOBAL
86 | Attributes::READ_ONLY
87 | Attributes::EXECUTE_NEVER,
88 )
89 .unwrap();
90 idmap
91 .map_range(
92 &writable_region(),
93 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
94 )
95 .unwrap();
96
David Brazdilb41aa8f2022-07-05 12:41:00 +010097 info!("Activating IdMap...");
98 info!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +000099 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +0100100 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000101
102 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000103 check_dice();
Andrew Walbran13564542022-04-20 16:29:45 +0000104}
105
David Brazdila51c6f02022-10-12 09:51:48 +0000106fn check_stack_guard() {
107 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
108
109 info!("Testing stack guard");
110 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
111}
112
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000113fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100114 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000115 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100116 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
117 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
118 info!("HEAP: {:?}", HEAP.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
David Brazdil1baa9a92022-06-28 14:47:50 +0100147fn check_fdt() {
148 info!("Checking FDT...");
149 let fdt = MemoryRegion::from(layout::dtb_range());
150 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt.start().0 as *mut u8, fdt.len()) };
151
152 let reader = Fdt::from_slice(fdt).unwrap();
153 info!("FDT passed verification.");
154 for reg in reader.memory().unwrap() {
155 info!("memory @ {reg:#x?}");
156 }
157
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000158 let compatible = CStr::from_bytes_with_nul(b"ns16550a\0").unwrap();
159
160 for c in reader.compatible_nodes(compatible).unwrap() {
161 let reg = c.reg().unwrap().next().unwrap();
162 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
163 }
164
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000165 let writer = Fdt::from_mut_slice(fdt).unwrap();
166 writer.unpack().unwrap();
167 info!("FDT successfully unpacked.");
168
169 let path = CStr::from_bytes_with_nul(b"/memory\0").unwrap();
170 let mut node = writer.node_mut(path).unwrap();
171 let name = CStr::from_bytes_with_nul(b"child\0").unwrap();
172 let mut child = node.add_subnode(name).unwrap();
173 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
174
175 let name = CStr::from_bytes_with_nul(b"str-property\0").unwrap();
176 child.appendprop(name, b"property-value\0").unwrap();
177 info!("Appended property '{}'.", name.to_str().unwrap());
178
179 let name = CStr::from_bytes_with_nul(b"pair-property\0").unwrap();
180 let addr = 0x0123_4567u64;
181 let size = 0x89ab_cdefu64;
182 child.appendprop_addrrange(name, addr, size).unwrap();
183 info!("Appended property '{}'.", name.to_str().unwrap());
184
185 let writer = child.fdt();
186 writer.pack().unwrap();
187 info!("FDT successfully packed.");
188
David Brazdil1baa9a92022-06-28 14:47:50 +0100189 info!("FDT checks done.");
190}
191
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000192fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100193 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000194 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
195 assert_eq!(vector[0], 1);
196 assert_eq!(vector[1], 2);
197 assert_eq!(vector[2], 3);
198 assert_eq!(vector[3], 4);
199 vector[2] = 42;
200 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100201 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000202}
David Brazdil9a83e612022-09-27 17:38:10 +0000203
204fn check_dice() {
205 info!("Testing DICE integration...");
206 let hash = dice::hash("hello world".as_bytes()).expect("DiceHash failed");
207 assert_eq!(
208 hash,
209 [
210 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
211 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
212 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
213 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
214 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
215 ]
216 );
217}