@@ -21,8 +21,6 @@ extern crate vm_memory;
2121use std:: error:: { self , Error as KernelLoaderError } ;
2222use std:: ffi:: CStr ;
2323use std:: fmt:: { self , Display } ;
24- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
25- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
2624use std:: io:: SeekFrom ;
2725use std:: io:: { Read , Seek } ;
2826#[ cfg( feature = "elf" ) ]
@@ -51,8 +49,6 @@ pub mod start_info;
5149#[ allow( non_upper_case_globals) ]
5250#[ cfg_attr( feature = "cargo-clippy" , allow( clippy:: all) ) ]
5351mod elf;
54- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
55- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
5652mod struct_util;
5753
5854#[ derive( Debug , PartialEq ) ]
@@ -76,6 +72,10 @@ pub enum Error {
7672 InvalidEntryAddress ,
7773 /// Invalid bzImage binary.
7874 InvalidBzImage ,
75+ /// Invalid Image binary.
76+ InvalidImage ,
77+ /// Invalid Image magic number.
78+ InvalidImageMagicNumber ,
7979 /// Invalid kernel start address.
8080 InvalidKernelStartAddress ,
8181 /// Memory to load kernel image is too small.
@@ -90,6 +90,8 @@ pub enum Error {
9090 ReadBzImageHeader ,
9191 /// Unable to read bzImage compressed image.
9292 ReadBzImageCompressedKernel ,
93+ /// Unable to read Image header
94+ ReadImageHeader ,
9395 /// Unable to seek to kernel start.
9496 SeekKernelStart ,
9597 /// Unable to seek to ELF start.
@@ -102,6 +104,10 @@ pub enum Error {
102104 SeekBzImageHeader ,
103105 /// Unable to seek to bzImage compressed kernel.
104106 SeekBzImageCompressedKernel ,
107+ /// Unable to seek to Image end.
108+ SeekImageEnd ,
109+ /// Unable to seek to Image header.
110+ SeekImageHeader ,
105111 /// Unable to seek to note header.
106112 SeekNoteHeader ,
107113 /// Unable to read note header.
@@ -128,11 +134,14 @@ impl error::Error for Error {
128134 Error :: InvalidEntryAddress => "Invalid entry address" ,
129135 Error :: InvalidBzImage => "Invalid bzImage" ,
130136 Error :: InvalidKernelStartAddress => "Invalid kernel start address" ,
137+ Error :: InvalidImage => "Invalid Image" ,
138+ Error :: InvalidImageMagicNumber => "Invalid Image magic number" ,
131139 Error :: MemoryOverflow => "Memory to load kernel image is not enough" ,
132140 Error :: ReadElfHeader => "Unable to read elf header" ,
133141 Error :: ReadKernelImage => "Unable to read kernel image" ,
134142 Error :: ReadProgramHeader => "Unable to read program header" ,
135143 Error :: ReadBzImageHeader => "Unable to read bzImage header" ,
144+ Error :: ReadImageHeader => "Unable to read Image header" ,
136145 Error :: ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel" ,
137146 Error :: SeekKernelStart => "Unable to seek to kernel start" ,
138147 Error :: SeekElfStart => "Unable to seek to elf start" ,
@@ -143,6 +152,8 @@ impl error::Error for Error {
143152 Error :: SeekNoteHeader => "Unable to seek to note header" ,
144153 Error :: ReadNoteHeader => "Unable to read note header" ,
145154 Error :: InvalidPvhNote => "Invalid PVH note header" ,
155+ Error :: SeekImageEnd => "Unable to seek Image end" ,
156+ Error :: SeekImageHeader => "Unable to seek image header" ,
146157 }
147158 }
148159}
@@ -525,6 +536,101 @@ fn align_up(addr: u64, align: u64) -> usize {
525536 }
526537}
527538
539+ #[ cfg( feature = "pe" ) ]
540+ #[ cfg( target_arch = "aarch64" ) ]
541+ /// ARM64 Image (PE) format support
542+ pub struct PE ;
543+
544+ #[ cfg( feature = "pe" ) ]
545+ #[ cfg( target_arch = "aarch64" ) ]
546+ #[ repr( C ) ]
547+ #[ derive( Debug , Copy , Clone , Default ) ]
548+ // See kernel doc Documentation/arm64/booting.txt for more information.
549+ // All these fields should be little endian.
550+ struct arm64_image_header {
551+ code0 : u32 ,
552+ code1 : u32 ,
553+ text_offset : u64 ,
554+ image_size : u64 ,
555+ flags : u64 ,
556+ res2 : u64 ,
557+ res3 : u64 ,
558+ res4 : u64 ,
559+ magic : u32 ,
560+ res5 : u32 ,
561+ }
562+
563+ #[ cfg( feature = "pe" ) ]
564+ #[ cfg( target_arch = "aarch64" ) ]
565+ impl KernelLoader for PE {
566+ /// Loads a PE Image into guest memory.
567+ ///
568+ /// # Arguments
569+ ///
570+ /// * `guest_mem` - The guest memory where the kernel image is loaded.
571+ /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel.
572+ /// * `kernel_image` - Input Image image.
573+ /// * `highmem_start_address` - ignored on ARM64
574+ ///
575+ /// # Returns
576+ /// * KernelLoaderResult
577+ fn load < F , M : GuestMemory > (
578+ guest_mem : & M ,
579+ kernel_start : Option < GuestAddress > ,
580+ kernel_image : & mut F ,
581+ _highmem_start_address : Option < GuestAddress > ,
582+ ) -> Result < KernelLoaderResult >
583+ where
584+ F : Read + Seek ,
585+ {
586+ let kernel_size = kernel_image
587+ . seek ( SeekFrom :: End ( 0 ) )
588+ . map_err ( |_| Error :: SeekImageEnd ) ? as usize ;
589+ let mut arm64_header: arm64_image_header = Default :: default ( ) ;
590+ kernel_image
591+ . seek ( SeekFrom :: Start ( 0 ) )
592+ . map_err ( |_| Error :: SeekImageHeader ) ?;
593+ unsafe {
594+ // read_struct is safe when reading a POD struct. It can be used and dropped without issue.
595+ struct_util:: read_struct ( kernel_image, & mut arm64_header)
596+ . map_err ( |_| Error :: ReadImageHeader ) ?;
597+ }
598+
599+ if u32:: from_le ( arm64_header. magic ) != 0x644d_5241 {
600+ return Err ( Error :: InvalidImageMagicNumber ) ;
601+ }
602+
603+ let image_size = u64:: from_le ( arm64_header. image_size ) ;
604+ let mut text_offset = u64:: from_le ( arm64_header. text_offset ) ;
605+
606+ if image_size == 0 {
607+ text_offset = 0x80000 ;
608+ }
609+
610+ let mem_offset = kernel_start
611+ . unwrap_or ( GuestAddress ( 0 ) )
612+ . checked_add ( text_offset)
613+ . ok_or ( Error :: InvalidImage ) ?;
614+
615+ let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
616+ loader_result. kernel_load = mem_offset;
617+
618+ kernel_image
619+ . seek ( SeekFrom :: Start ( 0 ) )
620+ . map_err ( |_| Error :: SeekImageHeader ) ?;
621+ guest_mem
622+ . read_exact_from ( mem_offset, kernel_image, kernel_size)
623+ . map_err ( |_| Error :: ReadKernelImage ) ?;
624+
625+ loader_result. kernel_end = mem_offset
626+ . raw_value ( )
627+ . checked_add ( kernel_size as GuestUsize )
628+ . ok_or ( Error :: MemoryOverflow ) ?;
629+
630+ Ok ( loader_result)
631+ }
632+ }
633+
528634#[ cfg( test) ]
529635mod test {
530636 use super :: * ;
0 commit comments