@@ -19,8 +19,6 @@ extern crate vm_memory;
1919use std:: error:: { self , Error as KernelLoaderError } ;
2020use std:: ffi:: CStr ;
2121use std:: fmt:: { self , Display } ;
22- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
23- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
2422use std:: io:: SeekFrom ;
2523use 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) ) ]
4442mod elf;
45- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
46- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
4743mod 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) ]
413512mod test {
414513 use super :: * ;
0 commit comments