@@ -29,7 +29,9 @@ use std::io::{Read, Seek};
2929#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
3030use std:: mem;
3131
32- use vm_memory:: { Address , Bytes , GuestAddress , GuestMemory , GuestUsize } ;
32+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
33+ use vm_memory:: VolatileMemory ;
34+ use vm_memory:: { Address , ByteValued , Bytes , GuestAddress , GuestMemory , GuestUsize } ;
3335
3436#[ allow( dead_code) ]
3537#[ allow( non_camel_case_types) ]
@@ -51,9 +53,6 @@ pub mod start_info;
5153#[ allow( non_upper_case_globals) ]
5254#[ cfg_attr( feature = "cargo-clippy" , allow( clippy:: all) ) ]
5355mod elf;
54- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
55- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
56- mod struct_util;
5756
5857#[ derive( Debug , PartialEq ) ]
5958/// Kernel loader errors.
@@ -193,6 +192,18 @@ pub trait KernelLoader {
193192/// Raw ELF (a.k.a. vmlinux) kernel image support.
194193pub struct Elf ;
195194
195+ #[ cfg( feature = "elf" ) ]
196+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
197+ unsafe impl ByteValued for elf:: Elf64_Ehdr { }
198+ #[ cfg( feature = "elf" ) ]
199+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
200+ unsafe impl ByteValued for elf:: Elf64_Nhdr { }
201+ #[ cfg( feature = "elf" ) ]
202+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
203+ unsafe impl ByteValued for elf:: Elf64_Phdr { }
204+
205+ unsafe impl ByteValued for bootparam:: setup_header { }
206+
196207#[ cfg( feature = "elf" ) ]
197208#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
198209impl KernelLoader for Elf {
@@ -218,14 +229,17 @@ impl KernelLoader for Elf {
218229 where
219230 F : Read + Seek ,
220231 {
221- let mut ehdr: elf:: Elf64_Ehdr = Default :: default ( ) ;
222232 kernel_image
223233 . seek ( SeekFrom :: Start ( 0 ) )
224234 . map_err ( |_| Error :: SeekElfStart ) ?;
225- unsafe {
226- // read_struct is safe when reading a POD struct. It can be used and dropped without issue.
227- struct_util:: read_struct ( kernel_image, & mut ehdr) . map_err ( |_| Error :: ReadElfHeader ) ?;
228- }
235+
236+ // TODO: use `Bytes` trait methods when rust-vmm/vm-memory#83 is merged.
237+ let ehdr_bytes = & mut [ 0u8 ; mem:: size_of :: < elf:: Elf64_Ehdr > ( ) ] [ ..] ;
238+ ehdr_bytes
239+ . as_volatile_slice ( )
240+ . read_from ( 0 , kernel_image, ehdr_bytes. len ( ) )
241+ . map_err ( |_| Error :: ReadElfHeader ) ?;
242+ let ehdr = elf:: Elf64_Ehdr :: from_mut_slice ( ehdr_bytes) . ok_or ( Error :: ReadElfHeader ) ?;
229243
230244 // Sanity checks
231245 if ehdr. e_ident [ elf:: EI_MAG0 as usize ] != elf:: ELFMAG0 as u8
@@ -260,14 +274,24 @@ impl KernelLoader for Elf {
260274 kernel_image
261275 . seek ( SeekFrom :: Start ( ehdr. e_phoff ) )
262276 . map_err ( |_| Error :: SeekProgramHeader ) ?;
263- let phdrs: Vec < elf:: Elf64_Phdr > = unsafe {
264- // Reading the structs is safe for a slice of POD structs.
265- struct_util:: read_struct_slice ( kernel_image, ehdr. e_phnum as usize )
266- . map_err ( |_| Error :: ReadProgramHeader ) ?
267- } ;
277+
278+ // TODO: use `Bytes` trait methods when rust-vmm/vm-memory#83 is merged.
279+ let phdr_sz = mem:: size_of :: < elf:: Elf64_Phdr > ( ) ;
280+ let phdrs_bytes = & mut vec ! [ 0u8 ; ehdr. e_phnum as usize * phdr_sz] [ ..] ;
281+ phdrs_bytes
282+ . as_volatile_slice ( )
283+ . read_from ( 0 , kernel_image, phdrs_bytes. len ( ) )
284+ . map_err ( |_| Error :: ReadProgramHeader ) ?;
285+ let mut phdrs: Vec < & elf:: Elf64_Phdr > = vec ! [ ] ;
286+ for i in 0usize ..ehdr. e_phnum as usize {
287+ phdrs. push (
288+ elf:: Elf64_Phdr :: from_slice ( & phdrs_bytes[ i * phdr_sz..( i + 1 ) * phdr_sz] )
289+ . ok_or ( Error :: ReadElfHeader ) ?,
290+ ) ;
291+ }
268292
269293 // Read in each section pointed to by the program headers.
270- for phdr in & phdrs {
294+ for phdr in phdrs {
271295 if phdr. p_type != elf:: PT_LOAD || phdr. p_filesz == 0 {
272296 if phdr. p_type == elf:: PT_NOTE {
273297 // This segment describes a Note, check if PVH entry point is encoded.
@@ -329,11 +353,13 @@ where
329353 let mut read_size: usize = 0 ;
330354
331355 while read_size < phdr. p_filesz as usize {
332- unsafe {
333- // read_struct is safe when reading a POD struct.
334- // It can be used and dropped without issue.
335- struct_util:: read_struct ( kernel_image, & mut nhdr) . map_err ( |_| Error :: ReadNoteHeader ) ?;
336- }
356+ let nhdr_bytes = & mut [ 0u8 ; mem:: size_of :: < elf:: Elf64_Nhdr > ( ) ] [ ..] ;
357+ nhdr_bytes
358+ . as_volatile_slice ( )
359+ . read_from ( 0 , kernel_image, nhdr_bytes. len ( ) )
360+ . map_err ( |_| Error :: ReadBzImageHeader ) ?;
361+ nhdr = * elf:: Elf64_Nhdr :: from_mut_slice ( nhdr_bytes) . ok_or ( Error :: ReadNoteHeader ) ?;
362+
337363 // If the note header found is not the desired one, keep reading until
338364 // the end of the segment
339365 if nhdr. n_type == XEN_ELFNOTE_PHYS32_ENTRY {
@@ -413,15 +439,18 @@ impl KernelLoader for BzImage {
413439 let mut kernel_size = kernel_image
414440 . seek ( SeekFrom :: End ( 0 ) )
415441 . map_err ( |_| Error :: SeekBzImageEnd ) ? as usize ;
416- let mut boot_header: bootparam:: setup_header = Default :: default ( ) ;
417442 kernel_image
418443 . seek ( SeekFrom :: Start ( 0x1F1 ) )
419444 . map_err ( |_| Error :: SeekBzImageHeader ) ?;
420- unsafe {
421- // read_struct is safe when reading a POD struct. It can be used and dropped without issue.
422- struct_util:: read_struct ( kernel_image, & mut boot_header)
423- . map_err ( |_| Error :: ReadBzImageHeader ) ?;
424- }
445+
446+ // TODO: use `Bytes` trait methods when rust-vmm/vm-memory#83 is merged.
447+ let boothdr_bytes = & mut [ 0u8 ; mem:: size_of :: < bootparam:: setup_header > ( ) ] [ ..] ;
448+ boothdr_bytes
449+ . as_volatile_slice ( )
450+ . read_from ( 0 , kernel_image, boothdr_bytes. len ( ) )
451+ . map_err ( |_| Error :: ReadBzImageHeader ) ?;
452+ let boot_header = bootparam:: setup_header:: from_mut_slice ( boothdr_bytes)
453+ . ok_or ( Error :: ReadBzImageHeader ) ?;
425454
426455 // if the HdrS magic number is not found at offset 0x202, the boot protocol version is "old",
427456 // the image type is assumed as zImage, not bzImage.
@@ -457,7 +486,7 @@ impl KernelLoader for BzImage {
457486 boot_header. code32_start = mem_offset. raw_value ( ) as u32 ;
458487
459488 let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
460- loader_result. setup_header = Some ( boot_header) ;
489+ loader_result. setup_header = Some ( * boot_header) ;
461490 loader_result. kernel_load = mem_offset;
462491
463492 //seek the compressed vmlinux.bin and read to memory
0 commit comments