@@ -19,8 +19,6 @@ extern crate vm_memory;
19
19
use std:: error:: { self , Error as KernelLoaderError } ;
20
20
use std:: ffi:: CStr ;
21
21
use std:: fmt:: { self , Display } ;
22
- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
23
- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
24
22
use std:: io:: SeekFrom ;
25
23
use std:: io:: { Read , Seek } ;
26
24
#[ cfg( feature = "elf" ) ]
@@ -42,8 +40,6 @@ pub mod bootparam;
42
40
#[ allow( non_upper_case_globals) ]
43
41
#[ cfg_attr( feature = "cargo-clippy" , allow( clippy:: all) ) ]
44
42
mod elf;
45
- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
46
- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
47
43
mod struct_util;
48
44
49
45
#[ derive( Debug , PartialEq ) ]
@@ -67,6 +63,10 @@ pub enum Error {
67
63
InvalidEntryAddress ,
68
64
/// Invalid bzImage binary.
69
65
InvalidBzImage ,
66
+ /// Invalid Image binary.
67
+ InvalidImage ,
68
+ /// Invalid Image magic number.
69
+ InvalidImageMagicNumber ,
70
70
/// Invalid kernel start address.
71
71
InvalidKernelStartAddress ,
72
72
/// Memory to load kernel image is too small.
@@ -81,6 +81,8 @@ pub enum Error {
81
81
ReadBzImageHeader ,
82
82
/// Unable to read bzImage compressed image.
83
83
ReadBzImageCompressedKernel ,
84
+ /// Unable to read Image header
85
+ ReadImageHeader ,
84
86
/// Unable to seek to kernel start.
85
87
SeekKernelStart ,
86
88
/// Unable to seek to ELF start.
@@ -93,6 +95,10 @@ pub enum Error {
93
95
SeekBzImageHeader ,
94
96
/// Unable to seek to bzImage compressed kernel.
95
97
SeekBzImageCompressedKernel ,
98
+ /// Unable to seek to Image end.
99
+ SeekImageEnd ,
100
+ /// Unable to seek to Image header.
101
+ SeekImageHeader ,
96
102
}
97
103
98
104
/// A specialized `Result` type for the kernel loader.
@@ -113,18 +119,23 @@ impl error::Error for Error {
113
119
Error :: InvalidEntryAddress => "Invalid entry address" ,
114
120
Error :: InvalidBzImage => "Invalid bzImage" ,
115
121
Error :: InvalidKernelStartAddress => "Invalid kernel start address" ,
122
+ Error :: InvalidImage => "Invalid Image" ,
123
+ Error :: InvalidImageMagicNumber => "Invalid Image magic number" ,
116
124
Error :: MemoryOverflow => "Memory to load kernel image is not enough" ,
117
125
Error :: ReadElfHeader => "Unable to read elf header" ,
118
126
Error :: ReadKernelImage => "Unable to read kernel image" ,
119
127
Error :: ReadProgramHeader => "Unable to read program header" ,
120
128
Error :: ReadBzImageHeader => "Unable to read bzImage header" ,
129
+ Error :: ReadImageHeader => "Unable to read Image header" ,
121
130
Error :: ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel" ,
122
131
Error :: SeekKernelStart => "Unable to seek to kernel start" ,
123
132
Error :: SeekElfStart => "Unable to seek to elf start" ,
124
133
Error :: SeekProgramHeader => "Unable to seek to program header" ,
125
134
Error :: SeekBzImageEnd => "Unable to seek bzImage end" ,
126
135
Error :: SeekBzImageHeader => "Unable to seek bzImage header" ,
127
136
Error :: SeekBzImageCompressedKernel => "Unable to seek bzImage compressed kernel" ,
137
+ Error :: SeekImageEnd => "Unable to seek Image end" ,
138
+ Error :: SeekImageHeader => "Unable to seek image header" ,
128
139
}
129
140
}
130
141
}
@@ -409,6 +420,94 @@ pub fn load_cmdline<M: GuestMemory>(
409
420
Ok ( ( ) )
410
421
}
411
422
423
+ #[ cfg( feature = "image" ) ]
424
+ #[ cfg( target_arch = "aarch64" ) ]
425
+ /// ARM64 Image (PE) format support
426
+ pub struct Image ;
427
+
428
+ #[ cfg( feature = "image" ) ]
429
+ #[ cfg( target_arch = "aarch64" ) ]
430
+ #[ allow( missing_docs) ]
431
+ #[ repr( C ) ]
432
+ #[ derive( Debug , Copy , Clone , Default ) ]
433
+ pub struct arm64_image_header {
434
+ pub code0 : u32 ,
435
+ pub code1 : u32 ,
436
+ pub text_offset : u64 ,
437
+ pub image_size : u64 ,
438
+ pub flags : u64 ,
439
+ pub res2 : u64 ,
440
+ pub res3 : u64 ,
441
+ pub res4 : u64 ,
442
+ pub magic : u32 ,
443
+ pub res5 : u32 ,
444
+ }
445
+
446
+ #[ cfg( feature = "image" ) ]
447
+ #[ cfg( target_arch = "aarch64" ) ]
448
+ impl KernelLoader for Image {
449
+ /// Loads a Image
450
+ ///
451
+ /// # Arguments
452
+ ///
453
+ /// * `guest_mem` - The guest memory where the kernel image is loaded.
454
+ /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel.
455
+ /// * `kernel_image` - Input Image image.
456
+ /// * `highmem_start_address` - ignored on ARM64
457
+ ///
458
+ /// # Returns
459
+ /// * KernelLoaderResult
460
+ fn load < F , M : GuestMemory > (
461
+ guest_mem : & M ,
462
+ kernel_start : Option < GuestAddress > ,
463
+ kernel_image : & mut F ,
464
+ _highmem_start_address : Option < GuestAddress > ,
465
+ ) -> Result < KernelLoaderResult >
466
+ where
467
+ F : Read + Seek ,
468
+ {
469
+ let kernel_size = kernel_image
470
+ . seek ( SeekFrom :: End ( 0 ) )
471
+ . map_err ( |_| Error :: SeekImageEnd ) ? as usize ;
472
+ let mut arm64_header: arm64_image_header = Default :: default ( ) ;
473
+ kernel_image
474
+ . seek ( SeekFrom :: Start ( 0 ) )
475
+ . map_err ( |_| Error :: SeekImageHeader ) ?;
476
+ unsafe {
477
+ // read_struct is safe when reading a POD struct. It can be used and dropped without issue.
478
+ struct_util:: read_struct ( kernel_image, & mut arm64_header)
479
+ . map_err ( |_| Error :: ReadImageHeader ) ?;
480
+ }
481
+
482
+ if u32:: from_le ( arm64_header. magic ) != 0x644d_5241 {
483
+ return Err ( Error :: InvalidImageMagicNumber ) ;
484
+ }
485
+
486
+ let text_offset = u64:: from_le ( arm64_header. text_offset ) ;
487
+ let mem_offset = kernel_start
488
+ . unwrap_or ( GuestAddress ( 0 ) )
489
+ . checked_add ( text_offset)
490
+ . ok_or ( Error :: InvalidImage ) ?;
491
+
492
+ let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
493
+ loader_result. kernel_load = mem_offset;
494
+
495
+ kernel_image
496
+ . seek ( SeekFrom :: Start ( 0 ) )
497
+ . map_err ( |_| Error :: SeekImageHeader ) ?;
498
+ guest_mem
499
+ . read_exact_from ( mem_offset, kernel_image, kernel_size)
500
+ . map_err ( |_| Error :: ReadKernelImage ) ?;
501
+
502
+ loader_result. kernel_end = mem_offset
503
+ . raw_value ( )
504
+ . checked_add ( kernel_size as GuestUsize )
505
+ . ok_or ( Error :: MemoryOverflow ) ?;
506
+
507
+ Ok ( loader_result)
508
+ }
509
+ }
510
+
412
511
#[ cfg( test) ]
413
512
mod test {
414
513
use super :: * ;
0 commit comments