@@ -29,7 +29,9 @@ use std::io::{Read, Seek};
29
29
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
30
30
use std:: mem;
31
31
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 } ;
33
35
34
36
#[ allow( dead_code) ]
35
37
#[ allow( non_camel_case_types) ]
@@ -51,9 +53,6 @@ pub mod start_info;
51
53
#[ allow( non_upper_case_globals) ]
52
54
#[ cfg_attr( feature = "cargo-clippy" , allow( clippy:: all) ) ]
53
55
mod elf;
54
- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
55
- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
56
- mod struct_util;
57
56
58
57
#[ derive( Debug , PartialEq ) ]
59
58
/// Kernel loader errors.
@@ -193,6 +192,18 @@ pub trait KernelLoader {
193
192
/// Raw ELF (a.k.a. vmlinux) kernel image support.
194
193
pub struct Elf ;
195
194
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
+
196
207
#[ cfg( feature = "elf" ) ]
197
208
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
198
209
impl KernelLoader for Elf {
@@ -218,14 +229,17 @@ impl KernelLoader for Elf {
218
229
where
219
230
F : Read + Seek ,
220
231
{
221
- let mut ehdr: elf:: Elf64_Ehdr = Default :: default ( ) ;
222
232
kernel_image
223
233
. seek ( SeekFrom :: Start ( 0 ) )
224
234
. 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 ) ?;
229
243
230
244
// Sanity checks
231
245
if ehdr. e_ident [ elf:: EI_MAG0 as usize ] != elf:: ELFMAG0 as u8
@@ -260,14 +274,24 @@ impl KernelLoader for Elf {
260
274
kernel_image
261
275
. seek ( SeekFrom :: Start ( ehdr. e_phoff ) )
262
276
. 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
+ }
268
292
269
293
// Read in each section pointed to by the program headers.
270
- for phdr in & phdrs {
294
+ for phdr in phdrs {
271
295
if phdr. p_type != elf:: PT_LOAD || phdr. p_filesz == 0 {
272
296
if phdr. p_type == elf:: PT_NOTE {
273
297
// This segment describes a Note, check if PVH entry point is encoded.
@@ -329,11 +353,13 @@ where
329
353
let mut read_size: usize = 0 ;
330
354
331
355
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
+
337
363
// If the note header found is not the desired one, keep reading until
338
364
// the end of the segment
339
365
if nhdr. n_type == XEN_ELFNOTE_PHYS32_ENTRY {
@@ -413,15 +439,18 @@ impl KernelLoader for BzImage {
413
439
let mut kernel_size = kernel_image
414
440
. seek ( SeekFrom :: End ( 0 ) )
415
441
. map_err ( |_| Error :: SeekBzImageEnd ) ? as usize ;
416
- let mut boot_header: bootparam:: setup_header = Default :: default ( ) ;
417
442
kernel_image
418
443
. seek ( SeekFrom :: Start ( 0x1F1 ) )
419
444
. 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 ) ?;
425
454
426
455
// if the HdrS magic number is not found at offset 0x202, the boot protocol version is "old",
427
456
// the image type is assumed as zImage, not bzImage.
@@ -457,7 +486,7 @@ impl KernelLoader for BzImage {
457
486
boot_header. code32_start = mem_offset. raw_value ( ) as u32 ;
458
487
459
488
let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
460
- loader_result. setup_header = Some ( boot_header) ;
489
+ loader_result. setup_header = Some ( * boot_header) ;
461
490
loader_result. kernel_load = mem_offset;
462
491
463
492
//seek the compressed vmlinux.bin and read to memory
0 commit comments