linux_aarch64.rs0.00%
1
// Copyright 2024 Google LLC2
//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 at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// 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 and13
// limitations under the License.14
15
use std::ffi::CStr;16
use std::fs::File;17
use std::io::{BufReader, Read, Seek, SeekFrom};18
use std::path::Path;19
20
use snafu::ResultExt;21
use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes};22
23
use crate::arch::layout::{DEVICE_TREE_START, KERNEL_IMAGE_START};24
use crate::arch::reg::{Pstate, Reg};25
use crate::loader::{InitState, Result, error, search_initramfs_address};26
use crate::mem::MemRegionEntry;27
use crate::mem::mapped::RamBus;28
29
#[repr(C)]30
#[derive(Debug, FromBytes, Immutable, IntoBytes)]31
struct 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
44
const IMAGE_MAGIC: u32 = 0x644d5241;45
46
pub 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
kernel61
.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 - 180
);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