@@ -27,7 +27,9 @@ use std::io::{Read, Seek};
2727#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
2828use std:: mem;
2929
30- use vm_memory:: { Address , Bytes , GuestAddress , GuestMemory , GuestUsize } ;
30+ use vm_memory:: {
31+ Address , ByteValued , Bytes , GuestAddress , GuestMemory , GuestUsize , VolatileMemory ,
32+ } ;
3133
3234#[ allow( dead_code) ]
3335#[ allow( non_camel_case_types) ]
@@ -42,9 +44,6 @@ pub mod bootparam;
4244#[ allow( non_upper_case_globals) ]
4345#[ cfg_attr( feature = "cargo-clippy" , allow( clippy:: all) ) ]
4446mod elf;
45- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
46- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
47- mod struct_util;
4847
4948#[ derive( Debug , PartialEq ) ]
5049/// Kernel loader errors.
@@ -171,6 +170,15 @@ pub trait KernelLoader {
171170/// Raw ELF (a.k.a. vmlinux) kernel image support.
172171pub struct Elf ;
173172
173+ #[ cfg( feature = "elf" ) ]
174+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
175+ unsafe impl ByteValued for elf:: Elf64_Ehdr { }
176+ #[ cfg( feature = "elf" ) ]
177+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
178+ unsafe impl ByteValued for elf:: Elf64_Phdr { }
179+
180+ unsafe impl ByteValued for bootparam:: setup_header { }
181+
174182#[ cfg( feature = "elf" ) ]
175183#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
176184impl KernelLoader for Elf {
@@ -196,14 +204,17 @@ impl KernelLoader for Elf {
196204 where
197205 F : Read + Seek ,
198206 {
199- let mut ehdr: elf:: Elf64_Ehdr = Default :: default ( ) ;
200207 kernel_image
201208 . seek ( SeekFrom :: Start ( 0 ) )
202209 . map_err ( |_| Error :: SeekElfStart ) ?;
203- unsafe {
204- // read_struct is safe when reading a POD struct. It can be used and dropped without issue.
205- struct_util:: read_struct ( kernel_image, & mut ehdr) . map_err ( |_| Error :: ReadElfHeader ) ?;
206- }
210+
211+ // TODO: use `Bytes` trait methods when rust-vmm/vm-memory#83 is merged.
212+ let ehdr_bytes = & mut [ 0u8 ; mem:: size_of :: < elf:: Elf64_Ehdr > ( ) ] [ ..] ;
213+ ehdr_bytes
214+ . as_volatile_slice ( )
215+ . read_from ( 0 , kernel_image, ehdr_bytes. len ( ) )
216+ . map_err ( |_| Error :: ReadElfHeader ) ?;
217+ let ehdr = elf:: Elf64_Ehdr :: from_mut_slice ( ehdr_bytes) . ok_or ( Error :: ReadElfHeader ) ?;
207218
208219 // Sanity checks
209220 if ehdr. e_ident [ elf:: EI_MAG0 as usize ] != elf:: ELFMAG0 as u8
@@ -238,14 +249,24 @@ impl KernelLoader for Elf {
238249 kernel_image
239250 . seek ( SeekFrom :: Start ( ehdr. e_phoff ) )
240251 . map_err ( |_| Error :: SeekProgramHeader ) ?;
241- let phdrs: Vec < elf:: Elf64_Phdr > = unsafe {
242- // Reading the structs is safe for a slice of POD structs.
243- struct_util:: read_struct_slice ( kernel_image, ehdr. e_phnum as usize )
244- . map_err ( |_| Error :: ReadProgramHeader ) ?
245- } ;
252+
253+ // TODO: use `Bytes` trait methods when rust-vmm/vm-memory#83 is merged.
254+ let phdr_sz = mem:: size_of :: < elf:: Elf64_Phdr > ( ) ;
255+ let phdrs_bytes = & mut vec ! [ 0u8 ; ehdr. e_phnum as usize * phdr_sz] [ ..] ;
256+ phdrs_bytes
257+ . as_volatile_slice ( )
258+ . read_from ( 0 , kernel_image, phdrs_bytes. len ( ) )
259+ . map_err ( |_| Error :: ReadProgramHeader ) ?;
260+ let mut phdrs: Vec < & elf:: Elf64_Phdr > = vec ! [ ] ;
261+ for i in 0usize ..ehdr. e_phnum as usize {
262+ phdrs. push (
263+ elf:: Elf64_Phdr :: from_slice ( & phdrs_bytes[ i * phdr_sz..( i + 1 ) * phdr_sz] )
264+ . ok_or ( Error :: ReadElfHeader ) ?,
265+ ) ;
266+ }
246267
247268 // Read in each section pointed to by the program headers.
248- for phdr in & phdrs {
269+ for phdr in phdrs {
249270 if phdr. p_type != elf:: PT_LOAD || phdr. p_filesz == 0 {
250271 continue ;
251272 }
@@ -314,15 +335,18 @@ impl KernelLoader for BzImage {
314335 let mut kernel_size = kernel_image
315336 . seek ( SeekFrom :: End ( 0 ) )
316337 . map_err ( |_| Error :: SeekBzImageEnd ) ? as usize ;
317- let mut boot_header: bootparam:: setup_header = Default :: default ( ) ;
318338 kernel_image
319339 . seek ( SeekFrom :: Start ( 0x1F1 ) )
320340 . map_err ( |_| Error :: SeekBzImageHeader ) ?;
321- unsafe {
322- // read_struct is safe when reading a POD struct. It can be used and dropped without issue.
323- struct_util:: read_struct ( kernel_image, & mut boot_header)
324- . map_err ( |_| Error :: ReadBzImageHeader ) ?;
325- }
341+
342+ // TODO: use `Bytes` trait methods when rust-vmm/vm-memory#83 is merged.
343+ let boothdr_bytes = & mut [ 0u8 ; mem:: size_of :: < bootparam:: setup_header > ( ) ] [ ..] ;
344+ boothdr_bytes
345+ . as_volatile_slice ( )
346+ . read_from ( 0 , kernel_image, boothdr_bytes. len ( ) )
347+ . map_err ( |_| Error :: ReadBzImageHeader ) ?;
348+ let boot_header = bootparam:: setup_header:: from_mut_slice ( boothdr_bytes)
349+ . ok_or ( Error :: ReadBzImageHeader ) ?;
326350
327351 // if the HdrS magic number is not found at offset 0x202, the boot protocol version is "old",
328352 // the image type is assumed as zImage, not bzImage.
@@ -358,7 +382,7 @@ impl KernelLoader for BzImage {
358382 boot_header. code32_start = mem_offset. raw_value ( ) as u32 ;
359383
360384 let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
361- loader_result. setup_header = Some ( boot_header) ;
385+ loader_result. setup_header = Some ( * boot_header) ;
362386 loader_result. kernel_load = mem_offset;
363387
364388 //seek the compressed vmlinux.bin and read to memory
0 commit comments