Alioth Code Coverage

linux_aarch64.rs0.00%

1// Copyright 2024 Google LLC
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// https://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
15use std::ffi::CStr;
16use std::fs::File;
17use std::io::{BufReader, Read, Seek, SeekFrom};
18use std::path::Path;
19
20use snafu::ResultExt;
21use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes};
22
23use crate::arch::layout::{DEVICE_TREE_START, KERNEL_IMAGE_START};
24use crate::arch::reg::{Pstate, Reg};
25use crate::loader::{InitState, Result, error, search_initramfs_address};
26use crate::mem::MemRegionEntry;
27use crate::mem::mapped::RamBus;
28
29#[repr(C)]
30#[derive(Debug, FromBytes, Immutable, IntoBytes)]
31struct ImageHeader {
32 code0: u32,
33 code1: u32,
34 text_offset: u64,
35 image_size: u64,
36 flags: u64,
37 res2: u64,
38 res3: u64,
39 res4: u64,
40 magic: u32,
41 res5: u32,
42}
43
44const IMAGE_MAGIC: u32 = 0x644d5241;
45
46pub fn load<P: AsRef<Path>>(
47 memory: &RamBus,
48 mem_regions: &[(u64, MemRegionEntry)],
49 kernel: P,
50 _cmdline: Option<&CStr>,
51 initramfs: Option<P>,
52) -> Result<InitState> {
53 let access_kernel = error::AccessFile {
54 path: kernel.as_ref(),
55 };
56 let kernel = File::open(&kernel).context(access_kernel)?;
57 let kernel_meta = kernel.metadata().context(access_kernel)?;
58 let mut kernel = BufReader::new(kernel);
59 let mut header = ImageHeader::new_zeroed();
60 kernel
61 .read_exact(header.as_mut_bytes())
62 .context(access_kernel)?;
63 if header.magic != IMAGE_MAGIC {
64 return error::MissingMagic {
65 magic: IMAGE_MAGIC as u64,
66 found: header.magic as u64,
67 }
68 .fail();
69 }
70 if header.image_size == 0 {
71 header.text_offset = 0x80000;
72 }
73 kernel.seek(SeekFrom::Start(0)).context(access_kernel)?;
74 let kernel_image_start = KERNEL_IMAGE_START + header.text_offset;
75 memory.write_range(kernel_image_start, kernel_meta.len(), kernel)?;
76 let kernel_image_end = KERNEL_IMAGE_START + header.text_offset + kernel_meta.len();
77 log::info!(
78 "kernel loaded at {kernel_image_start:#x} - {:#x}",
79 kernel_image_end - 1
80 );
81
82 let initramfs_range;
83 if let Some(initramfs) = initramfs {
84 let access_initramfs = error::AccessFile {
85 path: initramfs.as_ref(),
86 };
87 let initramfs = File::open(&initramfs).context(access_initramfs)?;
88 let initramfs_size = initramfs.metadata().context(access_initramfs)?.len();
89 let initramfs_gpa =
90 search_initramfs_address(mem_regions, initramfs_size, KERNEL_IMAGE_START + (1 << 30))?;
91 if initramfs_gpa < kernel_image_end {
92 return error::CannotLoadInitramfs.fail();
93 }
94 let initramfs_end = initramfs_gpa + initramfs_size;
95 memory.write_range(initramfs_gpa, initramfs_size, initramfs)?;
96 log::info!(
97 "initramfs loaded at {initramfs_gpa:#x} - {:#x}",
98 initramfs_end - 1,
99 );
100 initramfs_range = Some(initramfs_gpa..initramfs_end);
101 } else {
102 initramfs_range = None;
103 }
104 let init_state = InitState {
105 regs: vec![
106 (Reg::X0, DEVICE_TREE_START),
107 (Reg::X1, 0),
108 (Reg::X2, 0),
109 (Reg::X3, 0),
110 (
111 Reg::Pstate,
112 (Pstate::D | Pstate::A | Pstate::I | Pstate::F | Pstate::EL_H | Pstate::EL_BIT2)
113 .bits() as u64,
114 ),
115 (Reg::Pc, kernel_image_start),
116 ],
117 initramfs: initramfs_range,
118 ..Default::default()
119 };
120 Ok(init_state)
121}
122