blob: 3d74168fcabc3f389af5d742ae9e00614337dd02 [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;
David Brazdil1baa9a92022-06-28 14:47:50 +010036use libfdt::Fdt;
David Brazdilb41aa8f2022-07-05 12:41:00 +010037use log::{info, LevelFilter};
38use 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();
David Brazdil1baa9a92022-06-28 14:47:50 +010064 check_fdt();
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000065
66 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +010067 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000068 }
69
70 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000071
72 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
73 idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
74 idmap
75 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000076 &text_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000077 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
78 )
79 .unwrap();
80 idmap
81 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000082 &rodata_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000083 Attributes::NORMAL
84 | Attributes::NON_GLOBAL
85 | Attributes::READ_ONLY
86 | Attributes::EXECUTE_NEVER,
87 )
88 .unwrap();
89 idmap
90 .map_range(
91 &writable_region(),
92 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
93 )
94 .unwrap();
95
David Brazdilb41aa8f2022-07-05 12:41:00 +010096 info!("Activating IdMap...");
97 info!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +000098 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +010099 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000100
101 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000102 check_dice();
Andrew Walbran13564542022-04-20 16:29:45 +0000103}
104
David Brazdila51c6f02022-10-12 09:51:48 +0000105fn check_stack_guard() {
106 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
107
108 info!("Testing stack guard");
109 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
110}
111
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000112fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100113 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000114 unsafe {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100115 info!("ZEROED_DATA: {:?}", ZEROED_DATA.as_ptr());
116 info!("MUTABLE_DATA: {:?}", MUTABLE_DATA.as_ptr());
117 info!("HEAP: {:?}", HEAP.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000118 }
119
120 assert_eq!(INITIALISED_DATA[0], 1);
121 assert_eq!(INITIALISED_DATA[1], 2);
122 assert_eq!(INITIALISED_DATA[2], 3);
123 assert_eq!(INITIALISED_DATA[3], 4);
124
125 unsafe {
126 for element in ZEROED_DATA.iter() {
127 assert_eq!(*element, 0);
128 }
129 ZEROED_DATA[0] = 13;
130 assert_eq!(ZEROED_DATA[0], 13);
131 ZEROED_DATA[0] = 0;
132 assert_eq!(ZEROED_DATA[0], 0);
133
134 assert_eq!(MUTABLE_DATA[0], 1);
135 assert_eq!(MUTABLE_DATA[1], 2);
136 assert_eq!(MUTABLE_DATA[2], 3);
137 assert_eq!(MUTABLE_DATA[3], 4);
138 MUTABLE_DATA[0] += 41;
139 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000140 MUTABLE_DATA[0] -= 41;
141 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000142 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100143 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000144}
145
David Brazdil1baa9a92022-06-28 14:47:50 +0100146fn check_fdt() {
147 info!("Checking FDT...");
148 let fdt = MemoryRegion::from(layout::dtb_range());
149 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt.start().0 as *mut u8, fdt.len()) };
150
151 let reader = Fdt::from_slice(fdt).unwrap();
152 info!("FDT passed verification.");
153 for reg in reader.memory().unwrap() {
154 info!("memory @ {reg:#x?}");
155 }
156
157 info!("FDT checks done.");
158}
159
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000160fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100161 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000162 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
163 assert_eq!(vector[0], 1);
164 assert_eq!(vector[1], 2);
165 assert_eq!(vector[2], 3);
166 assert_eq!(vector[3], 4);
167 vector[2] = 42;
168 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100169 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000170}
David Brazdil9a83e612022-09-27 17:38:10 +0000171
172fn check_dice() {
173 info!("Testing DICE integration...");
174 let hash = dice::hash("hello world".as_bytes()).expect("DiceHash failed");
175 assert_eq!(
176 hash,
177 [
178 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
179 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
180 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
181 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
182 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
183 ]
184 );
185}