@@ -21,8 +21,6 @@ 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
26
#[ cfg( feature = "elf" ) ]
@@ -51,8 +49,6 @@ pub mod start_info;
51
49
#[ allow( non_upper_case_globals) ]
52
50
#[ cfg_attr( feature = "cargo-clippy" , allow( clippy:: all) ) ]
53
51
mod elf;
54
- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
55
- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
56
52
mod struct_util;
57
53
58
54
#[ derive( Debug , PartialEq ) ]
@@ -76,6 +72,10 @@ pub enum Error {
76
72
InvalidEntryAddress ,
77
73
/// Invalid bzImage binary.
78
74
InvalidBzImage ,
75
+ /// Invalid Image binary.
76
+ InvalidImage ,
77
+ /// Invalid Image magic number.
78
+ InvalidImageMagicNumber ,
79
79
/// Invalid kernel start address.
80
80
InvalidKernelStartAddress ,
81
81
/// Memory to load kernel image is too small.
@@ -90,6 +90,8 @@ pub enum Error {
90
90
ReadBzImageHeader ,
91
91
/// Unable to read bzImage compressed image.
92
92
ReadBzImageCompressedKernel ,
93
+ /// Unable to read Image header
94
+ ReadImageHeader ,
93
95
/// Unable to seek to kernel start.
94
96
SeekKernelStart ,
95
97
/// Unable to seek to ELF start.
@@ -102,6 +104,10 @@ pub enum Error {
102
104
SeekBzImageHeader ,
103
105
/// Unable to seek to bzImage compressed kernel.
104
106
SeekBzImageCompressedKernel ,
107
+ /// Unable to seek to Image end.
108
+ SeekImageEnd ,
109
+ /// Unable to seek to Image header.
110
+ SeekImageHeader ,
105
111
/// Unable to seek to note header.
106
112
SeekNoteHeader ,
107
113
/// Unable to read note header.
@@ -128,11 +134,14 @@ impl error::Error for Error {
128
134
Error :: InvalidEntryAddress => "Invalid entry address" ,
129
135
Error :: InvalidBzImage => "Invalid bzImage" ,
130
136
Error :: InvalidKernelStartAddress => "Invalid kernel start address" ,
137
+ Error :: InvalidImage => "Invalid Image" ,
138
+ Error :: InvalidImageMagicNumber => "Invalid Image magic number" ,
131
139
Error :: MemoryOverflow => "Memory to load kernel image is not enough" ,
132
140
Error :: ReadElfHeader => "Unable to read elf header" ,
133
141
Error :: ReadKernelImage => "Unable to read kernel image" ,
134
142
Error :: ReadProgramHeader => "Unable to read program header" ,
135
143
Error :: ReadBzImageHeader => "Unable to read bzImage header" ,
144
+ Error :: ReadImageHeader => "Unable to read Image header" ,
136
145
Error :: ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel" ,
137
146
Error :: SeekKernelStart => "Unable to seek to kernel start" ,
138
147
Error :: SeekElfStart => "Unable to seek to elf start" ,
@@ -143,6 +152,8 @@ impl error::Error for Error {
143
152
Error :: SeekNoteHeader => "Unable to seek to note header" ,
144
153
Error :: ReadNoteHeader => "Unable to read note header" ,
145
154
Error :: InvalidPvhNote => "Invalid PVH note header" ,
155
+ Error :: SeekImageEnd => "Unable to seek Image end" ,
156
+ Error :: SeekImageHeader => "Unable to seek image header" ,
146
157
}
147
158
}
148
159
}
@@ -525,6 +536,101 @@ fn align_up(addr: u64, align: u64) -> usize {
525
536
}
526
537
}
527
538
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
+
528
634
#[ cfg( test) ]
529
635
mod test {
530
636
use super :: * ;
0 commit comments