@@ -21,12 +21,9 @@ extern crate vm_memory;
21
21
use std:: error:: { self , Error as KernelLoaderError } ;
22
22
use std:: ffi:: CStr ;
23
23
use std:: fmt:: { self , Display } ;
24
- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
25
- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
26
24
use std:: io:: SeekFrom ;
27
25
use 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" ) ) ]
30
27
use std:: mem;
31
28
32
29
use vm_memory:: { Address , ByteValued , Bytes , GuestAddress , GuestMemory , GuestUsize } ;
@@ -73,6 +70,10 @@ pub enum Error {
73
70
InvalidEntryAddress ,
74
71
/// Invalid bzImage binary.
75
72
InvalidBzImage ,
73
+ /// Invalid Image binary.
74
+ InvalidImage ,
75
+ /// Invalid Image magic number.
76
+ InvalidImageMagicNumber ,
76
77
/// Invalid kernel start address.
77
78
InvalidKernelStartAddress ,
78
79
/// Memory to load kernel image is too small.
@@ -87,6 +88,8 @@ pub enum Error {
87
88
ReadBzImageHeader ,
88
89
/// Unable to read bzImage compressed image.
89
90
ReadBzImageCompressedKernel ,
91
+ /// Unable to read Image header
92
+ ReadImageHeader ,
90
93
/// Unable to seek to kernel start.
91
94
SeekKernelStart ,
92
95
/// Unable to seek to ELF start.
@@ -99,6 +102,10 @@ pub enum Error {
99
102
SeekBzImageHeader ,
100
103
/// Unable to seek to bzImage compressed kernel.
101
104
SeekBzImageCompressedKernel ,
105
+ /// Unable to seek to Image end.
106
+ SeekImageEnd ,
107
+ /// Unable to seek to Image header.
108
+ SeekImageHeader ,
102
109
/// Unable to seek to note header.
103
110
SeekNoteHeader ,
104
111
/// Unable to read note header.
@@ -125,11 +132,14 @@ impl error::Error for Error {
125
132
Error :: InvalidEntryAddress => "Invalid entry address" ,
126
133
Error :: InvalidBzImage => "Invalid bzImage" ,
127
134
Error :: InvalidKernelStartAddress => "Invalid kernel start address" ,
135
+ Error :: InvalidImage => "Invalid Image" ,
136
+ Error :: InvalidImageMagicNumber => "Invalid Image magic number" ,
128
137
Error :: MemoryOverflow => "Memory to load kernel image is not enough" ,
129
138
Error :: ReadElfHeader => "Unable to read elf header" ,
130
139
Error :: ReadKernelImage => "Unable to read kernel image" ,
131
140
Error :: ReadProgramHeader => "Unable to read program header" ,
132
141
Error :: ReadBzImageHeader => "Unable to read bzImage header" ,
142
+ Error :: ReadImageHeader => "Unable to read Image header" ,
133
143
Error :: ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel" ,
134
144
Error :: SeekKernelStart => "Unable to seek to kernel start" ,
135
145
Error :: SeekElfStart => "Unable to seek to elf start" ,
@@ -140,6 +150,8 @@ impl error::Error for Error {
140
150
Error :: SeekNoteHeader => "Unable to seek to note header" ,
141
151
Error :: ReadNoteHeader => "Unable to read note header" ,
142
152
Error :: InvalidPvhNote => "Invalid PVH note header" ,
153
+ Error :: SeekImageEnd => "Unable to seek Image end" ,
154
+ Error :: SeekImageHeader => "Unable to seek image header" ,
143
155
}
144
156
}
145
157
}
@@ -539,6 +551,104 @@ fn align_up(addr: u64, align: u64) -> usize {
539
551
}
540
552
}
541
553
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
+
542
652
#[ cfg( test) ]
543
653
mod test {
544
654
use super :: * ;
0 commit comments