@@ -21,12 +21,9 @@ 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 } ;
28- #[ cfg( feature = "elf" ) ]
29- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
26+ #[ cfg( any( feature = "elf" , feature = "pe" ) ) ]
3027use std:: mem;
3128
3229use vm_memory:: { Address , ByteValued , Bytes , GuestAddress , GuestMemory , GuestUsize } ;
@@ -73,6 +70,10 @@ pub enum Error {
7370 InvalidEntryAddress ,
7471 /// Invalid bzImage binary.
7572 InvalidBzImage ,
73+ /// Invalid Image binary.
74+ InvalidImage ,
75+ /// Invalid Image magic number.
76+ InvalidImageMagicNumber ,
7677 /// Invalid kernel start address.
7778 InvalidKernelStartAddress ,
7879 /// Memory to load kernel image is too small.
@@ -87,6 +88,8 @@ pub enum Error {
8788 ReadBzImageHeader ,
8889 /// Unable to read bzImage compressed image.
8990 ReadBzImageCompressedKernel ,
91+ /// Unable to read Image header
92+ ReadImageHeader ,
9093 /// Unable to seek to kernel start.
9194 SeekKernelStart ,
9295 /// Unable to seek to ELF start.
@@ -99,6 +102,10 @@ pub enum Error {
99102 SeekBzImageHeader ,
100103 /// Unable to seek to bzImage compressed kernel.
101104 SeekBzImageCompressedKernel ,
105+ /// Unable to seek to Image end.
106+ SeekImageEnd ,
107+ /// Unable to seek to Image header.
108+ SeekImageHeader ,
102109 /// Unable to seek to note header.
103110 SeekNoteHeader ,
104111 /// Unable to read note header.
@@ -125,11 +132,14 @@ impl error::Error for Error {
125132 Error :: InvalidEntryAddress => "Invalid entry address" ,
126133 Error :: InvalidBzImage => "Invalid bzImage" ,
127134 Error :: InvalidKernelStartAddress => "Invalid kernel start address" ,
135+ Error :: InvalidImage => "Invalid Image" ,
136+ Error :: InvalidImageMagicNumber => "Invalid Image magic number" ,
128137 Error :: MemoryOverflow => "Memory to load kernel image is not enough" ,
129138 Error :: ReadElfHeader => "Unable to read elf header" ,
130139 Error :: ReadKernelImage => "Unable to read kernel image" ,
131140 Error :: ReadProgramHeader => "Unable to read program header" ,
132141 Error :: ReadBzImageHeader => "Unable to read bzImage header" ,
142+ Error :: ReadImageHeader => "Unable to read Image header" ,
133143 Error :: ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel" ,
134144 Error :: SeekKernelStart => "Unable to seek to kernel start" ,
135145 Error :: SeekElfStart => "Unable to seek to elf start" ,
@@ -140,6 +150,8 @@ impl error::Error for Error {
140150 Error :: SeekNoteHeader => "Unable to seek to note header" ,
141151 Error :: ReadNoteHeader => "Unable to read note header" ,
142152 Error :: InvalidPvhNote => "Invalid PVH note header" ,
153+ Error :: SeekImageEnd => "Unable to seek Image end" ,
154+ Error :: SeekImageHeader => "Unable to seek image header" ,
143155 }
144156 }
145157}
@@ -539,6 +551,104 @@ fn align_up(addr: u64, align: u64) -> usize {
539551 }
540552}
541553
554+ #[ cfg( feature = "pe" ) ]
555+ #[ cfg( target_arch = "aarch64" ) ]
556+ /// ARM64 Image (PE) format support
557+ pub struct PE ;
558+
559+ #[ cfg( feature = "pe" ) ]
560+ #[ cfg( target_arch = "aarch64" ) ]
561+ #[ repr( C ) ]
562+ #[ derive( Debug , Copy , Clone , Default ) ]
563+ // See kernel doc Documentation/arm64/booting.txt for more information.
564+ // All these fields should be little endian.
565+ struct arm64_image_header {
566+ code0 : u32 ,
567+ code1 : u32 ,
568+ text_offset : u64 ,
569+ image_size : u64 ,
570+ flags : u64 ,
571+ res2 : u64 ,
572+ res3 : u64 ,
573+ res4 : u64 ,
574+ magic : u32 ,
575+ res5 : u32 ,
576+ }
577+
578+ #[ cfg( feature = "pe" ) ]
579+ #[ cfg( target_arch = "aarch64" ) ]
580+ unsafe impl ByteValued for arm64_image_header { }
581+
582+ #[ cfg( feature = "pe" ) ]
583+ #[ cfg( target_arch = "aarch64" ) ]
584+ impl KernelLoader for PE {
585+ /// Loads a PE Image into guest memory.
586+ ///
587+ /// # Arguments
588+ ///
589+ /// * `guest_mem` - The guest memory where the kernel image is loaded.
590+ /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel.
591+ /// * `kernel_image` - Input Image image.
592+ /// * `highmem_start_address` - ignored on ARM64
593+ ///
594+ /// # Returns
595+ /// * KernelLoaderResult
596+ fn load < F , M : GuestMemory > (
597+ guest_mem : & M ,
598+ kernel_start : Option < GuestAddress > ,
599+ kernel_image : & mut F ,
600+ _highmem_start_address : Option < GuestAddress > ,
601+ ) -> Result < KernelLoaderResult >
602+ where
603+ F : Read + Seek ,
604+ {
605+ let kernel_size = kernel_image
606+ . seek ( SeekFrom :: End ( 0 ) )
607+ . map_err ( |_| Error :: SeekImageEnd ) ? as usize ;
608+ let mut arm64_header: arm64_image_header = Default :: default ( ) ;
609+ kernel_image
610+ . seek ( SeekFrom :: Start ( 0 ) )
611+ . map_err ( |_| Error :: SeekImageHeader ) ?;
612+
613+ arm64_header. as_bytes ( )
614+ . read_from ( 0 , kernel_image, mem:: size_of :: < arm64_image_header > ( ) )
615+ . map_err ( |_| Error :: ReadImageHeader ) ?;
616+
617+ if u32:: from_le ( arm64_header. magic ) != 0x644d_5241 {
618+ return Err ( Error :: InvalidImageMagicNumber ) ;
619+ }
620+
621+ let image_size = u64:: from_le ( arm64_header. image_size ) ;
622+ let mut text_offset = u64:: from_le ( arm64_header. text_offset ) ;
623+
624+ if image_size == 0 {
625+ text_offset = 0x80000 ;
626+ }
627+
628+ let mem_offset = kernel_start
629+ . unwrap_or ( GuestAddress ( 0 ) )
630+ . checked_add ( text_offset)
631+ . ok_or ( Error :: InvalidImage ) ?;
632+
633+ let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
634+ loader_result. kernel_load = mem_offset;
635+
636+ kernel_image
637+ . seek ( SeekFrom :: Start ( 0 ) )
638+ . map_err ( |_| Error :: SeekImageHeader ) ?;
639+ guest_mem
640+ . read_exact_from ( mem_offset, kernel_image, kernel_size)
641+ . map_err ( |_| Error :: ReadKernelImage ) ?;
642+
643+ loader_result. kernel_end = mem_offset
644+ . raw_value ( )
645+ . checked_add ( kernel_size as GuestUsize )
646+ . ok_or ( Error :: MemoryOverflow ) ?;
647+
648+ Ok ( loader_result)
649+ }
650+ }
651+
542652#[ cfg( test) ]
543653mod test {
544654 use super :: * ;
0 commit comments