Skip to content

Commit ae8be03

Browse files
committed
loader: add support for ARM64 PE format
Signed-off-by: Qiu Wenbo <qiuwenbo@phytium.com.cn>
1 parent 0c754f3 commit ae8be03

File tree

2 files changed

+104
-4
lines changed

2 files changed

+104
-4
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ license = "Apache-2.0 AND BSD-3-Clause"
99
default = ["elf"]
1010
elf = []
1111
bzimage = []
12+
image = []
1213

1314
[dependencies]
1415
vm-memory = {version = "0.1.0", features = ["backend-mmap"]}

src/loader/mod.rs

Lines changed: 103 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ extern crate vm_memory;
1919
use std::error::{self, Error as KernelLoaderError};
2020
use std::ffi::CStr;
2121
use std::fmt::{self, Display};
22-
#[cfg(any(feature = "elf", feature = "bzimage"))]
23-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
2422
use std::io::SeekFrom;
2523
use std::io::{Read, Seek};
2624
#[cfg(feature = "elf")]
@@ -42,8 +40,6 @@ pub mod bootparam;
4240
#[allow(non_upper_case_globals)]
4341
#[cfg_attr(feature = "cargo-clippy", allow(clippy::all))]
4442
mod elf;
45-
#[cfg(any(feature = "elf", feature = "bzimage"))]
46-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
4743
mod struct_util;
4844

4945
#[derive(Debug, PartialEq)]
@@ -67,6 +63,10 @@ pub enum Error {
6763
InvalidEntryAddress,
6864
/// Invalid bzImage binary.
6965
InvalidBzImage,
66+
/// Invalid Image binary.
67+
InvalidImage,
68+
/// Invalid Image magic number.
69+
InvalidImageMagicNumber,
7070
/// Invalid kernel start address.
7171
InvalidKernelStartAddress,
7272
/// Memory to load kernel image is too small.
@@ -81,6 +81,8 @@ pub enum Error {
8181
ReadBzImageHeader,
8282
/// Unable to read bzImage compressed image.
8383
ReadBzImageCompressedKernel,
84+
/// Unable to read Image header
85+
ReadImageHeader,
8486
/// Unable to seek to kernel start.
8587
SeekKernelStart,
8688
/// Unable to seek to ELF start.
@@ -93,6 +95,10 @@ pub enum Error {
9395
SeekBzImageHeader,
9496
/// Unable to seek to bzImage compressed kernel.
9597
SeekBzImageCompressedKernel,
98+
/// Unable to seek to Image end.
99+
SeekImageEnd,
100+
/// Unable to seek to Image header.
101+
SeekImageHeader,
96102
}
97103

98104
/// A specialized `Result` type for the kernel loader.
@@ -113,18 +119,23 @@ impl error::Error for Error {
113119
Error::InvalidEntryAddress => "Invalid entry address",
114120
Error::InvalidBzImage => "Invalid bzImage",
115121
Error::InvalidKernelStartAddress => "Invalid kernel start address",
122+
Error::InvalidImage => "Invalid Image",
123+
Error::InvalidImageMagicNumber => "Invalid Image magic number",
116124
Error::MemoryOverflow => "Memory to load kernel image is not enough",
117125
Error::ReadElfHeader => "Unable to read elf header",
118126
Error::ReadKernelImage => "Unable to read kernel image",
119127
Error::ReadProgramHeader => "Unable to read program header",
120128
Error::ReadBzImageHeader => "Unable to read bzImage header",
129+
Error::ReadImageHeader => "Unable to read Image header",
121130
Error::ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel",
122131
Error::SeekKernelStart => "Unable to seek to kernel start",
123132
Error::SeekElfStart => "Unable to seek to elf start",
124133
Error::SeekProgramHeader => "Unable to seek to program header",
125134
Error::SeekBzImageEnd => "Unable to seek bzImage end",
126135
Error::SeekBzImageHeader => "Unable to seek bzImage header",
127136
Error::SeekBzImageCompressedKernel => "Unable to seek bzImage compressed kernel",
137+
Error::SeekImageEnd => "Unable to seek Image end",
138+
Error::SeekImageHeader => "Unable to seek image header",
128139
}
129140
}
130141
}
@@ -409,6 +420,94 @@ pub fn load_cmdline<M: GuestMemory>(
409420
Ok(())
410421
}
411422

423+
#[cfg(feature = "image")]
424+
#[cfg(target_arch = "aarch64")]
425+
/// ARM64 Image (PE) format support
426+
pub struct Image;
427+
428+
#[cfg(feature = "image")]
429+
#[cfg(target_arch = "aarch64")]
430+
#[allow(missing_docs)]
431+
#[repr(C)]
432+
#[derive(Debug, Copy, Clone, Default)]
433+
pub struct arm64_image_header {
434+
pub code0: u32,
435+
pub code1: u32,
436+
pub text_offset: u64,
437+
pub image_size: u64,
438+
pub flags: u64,
439+
pub res2: u64,
440+
pub res3: u64,
441+
pub res4: u64,
442+
pub magic: u32,
443+
pub res5: u32,
444+
}
445+
446+
#[cfg(feature = "image")]
447+
#[cfg(target_arch = "aarch64")]
448+
impl KernelLoader for Image {
449+
/// Loads a Image
450+
///
451+
/// # Arguments
452+
///
453+
/// * `guest_mem` - The guest memory where the kernel image is loaded.
454+
/// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel.
455+
/// * `kernel_image` - Input Image image.
456+
/// * `highmem_start_address` - ignored on ARM64
457+
///
458+
/// # Returns
459+
/// * KernelLoaderResult
460+
fn load<F, M: GuestMemory>(
461+
guest_mem: &M,
462+
kernel_start: Option<GuestAddress>,
463+
kernel_image: &mut F,
464+
_highmem_start_address: Option<GuestAddress>,
465+
) -> Result<KernelLoaderResult>
466+
where
467+
F: Read + Seek,
468+
{
469+
let kernel_size = kernel_image
470+
.seek(SeekFrom::End(0))
471+
.map_err(|_| Error::SeekImageEnd)? as usize;
472+
let mut arm64_header: arm64_image_header = Default::default();
473+
kernel_image
474+
.seek(SeekFrom::Start(0))
475+
.map_err(|_| Error::SeekImageHeader)?;
476+
unsafe {
477+
// read_struct is safe when reading a POD struct. It can be used and dropped without issue.
478+
struct_util::read_struct(kernel_image, &mut arm64_header)
479+
.map_err(|_| Error::ReadImageHeader)?;
480+
}
481+
482+
if u32::from_le(arm64_header.magic) != 0x644d_5241 {
483+
return Err(Error::InvalidImageMagicNumber);
484+
}
485+
486+
let text_offset = u64::from_le(arm64_header.text_offset);
487+
let mem_offset = kernel_start
488+
.unwrap_or(GuestAddress(0))
489+
.checked_add(text_offset)
490+
.ok_or(Error::InvalidImage)?;
491+
492+
let mut loader_result: KernelLoaderResult = Default::default();
493+
loader_result.kernel_load = mem_offset;
494+
495+
kernel_image
496+
.seek(SeekFrom::Start(0))
497+
.map_err(|_| Error::SeekImageHeader)?;
498+
guest_mem
499+
.read_exact_from(mem_offset, kernel_image, kernel_size)
500+
.map_err(|_| Error::ReadKernelImage)?;
501+
502+
loader_result.kernel_end = mem_offset
503+
.raw_value()
504+
.checked_add(kernel_size as GuestUsize)
505+
.ok_or(Error::MemoryOverflow)?;
506+
507+
Ok(loader_result)
508+
}
509+
}
510+
412511
#[cfg(test)]
413512
mod test {
414513
use super::*;

0 commit comments

Comments
 (0)