@@ -27,7 +27,9 @@ use std::io::{Read, Seek};
27
27
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
28
28
use std:: mem;
29
29
30
- use vm_memory:: { Address , Bytes , GuestAddress , GuestMemory , GuestUsize } ;
30
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
31
+ use vm_memory:: VolatileMemory ;
32
+ use vm_memory:: { Address , ByteValued , Bytes , GuestAddress , GuestMemory , GuestUsize } ;
31
33
32
34
#[ allow( dead_code) ]
33
35
#[ allow( non_camel_case_types) ]
@@ -42,9 +44,6 @@ pub mod bootparam;
42
44
#[ allow( non_upper_case_globals) ]
43
45
#[ cfg_attr( feature = "cargo-clippy" , allow( clippy:: all) ) ]
44
46
mod elf;
45
- #[ cfg( any( feature = "elf" , feature = "bzimage" ) ) ]
46
- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
47
- mod struct_util;
48
47
49
48
#[ derive( Debug , PartialEq ) ]
50
49
/// Kernel loader errors.
@@ -171,6 +170,15 @@ pub trait KernelLoader {
171
170
/// Raw ELF (a.k.a. vmlinux) kernel image support.
172
171
pub struct Elf ;
173
172
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
+
174
182
#[ cfg( feature = "elf" ) ]
175
183
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
176
184
impl KernelLoader for Elf {
@@ -196,14 +204,17 @@ impl KernelLoader for Elf {
196
204
where
197
205
F : Read + Seek ,
198
206
{
199
- let mut ehdr: elf:: Elf64_Ehdr = Default :: default ( ) ;
200
207
kernel_image
201
208
. seek ( SeekFrom :: Start ( 0 ) )
202
209
. 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 ) ?;
207
218
208
219
// Sanity checks
209
220
if ehdr. e_ident [ elf:: EI_MAG0 as usize ] != elf:: ELFMAG0 as u8
@@ -238,14 +249,24 @@ impl KernelLoader for Elf {
238
249
kernel_image
239
250
. seek ( SeekFrom :: Start ( ehdr. e_phoff ) )
240
251
. 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
+ }
246
267
247
268
// Read in each section pointed to by the program headers.
248
- for phdr in & phdrs {
269
+ for phdr in phdrs {
249
270
if phdr. p_type != elf:: PT_LOAD || phdr. p_filesz == 0 {
250
271
continue ;
251
272
}
@@ -314,15 +335,18 @@ impl KernelLoader for BzImage {
314
335
let mut kernel_size = kernel_image
315
336
. seek ( SeekFrom :: End ( 0 ) )
316
337
. map_err ( |_| Error :: SeekBzImageEnd ) ? as usize ;
317
- let mut boot_header: bootparam:: setup_header = Default :: default ( ) ;
318
338
kernel_image
319
339
. seek ( SeekFrom :: Start ( 0x1F1 ) )
320
340
. 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 ) ?;
326
350
327
351
// if the HdrS magic number is not found at offset 0x202, the boot protocol version is "old",
328
352
// the image type is assumed as zImage, not bzImage.
@@ -358,7 +382,7 @@ impl KernelLoader for BzImage {
358
382
boot_header. code32_start = mem_offset. raw_value ( ) as u32 ;
359
383
360
384
let mut loader_result: KernelLoaderResult = Default :: default ( ) ;
361
- loader_result. setup_header = Some ( boot_header) ;
385
+ loader_result. setup_header = Some ( * boot_header) ;
362
386
loader_result. kernel_load = mem_offset;
363
387
364
388
//seek the compressed vmlinux.bin and read to memory
0 commit comments