@@ -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,100 @@ fn align_up(addr: u64, align: u64) -> usize {
525
536
}
526
537
}
527
538
539
+ #[ cfg( feature = "image" ) ]
540
+ #[ cfg( target_arch = "aarch64" ) ]
541
+ /// ARM64 Image (PE) format support
542
+ pub struct Image ;
543
+
544
+ #[ cfg( feature = "image" ) ]
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
+ struct arm64_image_header {
550
+ code0 : u32 ,
551
+ code1 : u32 ,
552
+ text_offset : u64 ,
553
+ image_size : u64 ,
554
+ flags : u64 ,
555
+ res2 : u64 ,
556
+ res3 : u64 ,
557
+ res4 : u64 ,
558
+ magic : u32 ,
559
+ res5 : u32 ,
560
+ }
561
+
562
+ #[ cfg( feature = "image" ) ]
563
+ #[ cfg( target_arch = "aarch64" ) ]
564
+ impl KernelLoader for Image {
565
+ /// Loads a Image
566
+ ///
567
+ /// # Arguments
568
+ ///
569
+ /// * `guest_mem` - The guest memory where the kernel image is loaded.
570
+ /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel.
571
+ /// * `kernel_image` - Input Image image.
572
+ /// * `highmem_start_address` - ignored on ARM64
573
+ ///
574
+ /// # Returns
575
+ /// * KernelLoaderResult
576
+ fn load < F , M : GuestMemory > (
577
+ guest_mem : & M ,
578
+ kernel_start : Option < GuestAddress > ,
579
+ kernel_image : & mut F ,
580
+ _highmem_start_address : Option < GuestAddress > ,
581
+ ) -> Result < KernelLoaderResult >
582
+ where
583
+ F : Read + Seek ,
584
+ {
585
+ let kernel_size = kernel_image
586
+ . seek ( SeekFrom :: End ( 0 ) )
587
+ . map_err ( |_| Error :: SeekImageEnd ) ? as usize ;
588
+ let mut arm64_header: arm64_image_header = Default :: default ( ) ;
589
+ kernel_image
590
+ . seek ( SeekFrom :: Start ( 0 ) )
591
+ . map_err ( |_| Error :: SeekImageHeader ) ?;
592
+ unsafe {
593
+ // read_struct is safe when reading a POD struct. It can be used and dropped without issue.
594
+ struct_util:: read_struct ( kernel_image, & mut arm64_header)
595
+ . map_err ( |_| Error :: ReadImageHeader ) ?;
596
+ }
597
+
598
+ if u32:: from_le ( arm64_header. magic ) != 0x644d_5241 {
599
+ return Err ( Error :: InvalidImageMagicNumber ) ;
600
+ }
601
+
602
+ let image_size = u64:: from_le ( arm64_header. image_size ) ;
603
+ let mut text_offset = u64:: from_le ( arm64_header. text_offset ) ;
604
+
605
+ if image_size == 0 {
606
+ text_offset = 0x80000 ;
607
+ }
608
+
609
+ let mem_offset = kernel_start
610
+ . unwrap_or ( GuestAddress ( 0 ) )
611
+ . checked_add ( text_offset)
612
+ . ok_or ( Error :: InvalidImage ) ?;
613
+
614
+ let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
615
+ loader_result. kernel_load = mem_offset;
616
+
617
+ kernel_image
618
+ . seek ( SeekFrom :: Start ( 0 ) )
619
+ . map_err ( |_| Error :: SeekImageHeader ) ?;
620
+ guest_mem
621
+ . read_exact_from ( mem_offset, kernel_image, kernel_size)
622
+ . map_err ( |_| Error :: ReadKernelImage ) ?;
623
+
624
+ loader_result. kernel_end = mem_offset
625
+ . raw_value ( )
626
+ . checked_add ( kernel_size as GuestUsize )
627
+ . ok_or ( Error :: MemoryOverflow ) ?;
628
+
629
+ Ok ( loader_result)
630
+ }
631
+ }
632
+
528
633
#[ cfg( test) ]
529
634
mod test {
530
635
use super :: * ;
0 commit comments