• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use arch::android::create_android_fdt;
6 use arch::fdt::{Error, FdtWriter};
7 use data_model::DataInit;
8 use std::fs::File;
9 use std::mem;
10 use vm_memory::{GuestAddress, GuestMemory};
11 
12 use crate::bootparam::setup_data;
13 use crate::{SETUP_DTB, X86_64_FDT_MAX_SIZE};
14 
15 // Like `setup_data` without the incomplete array field at the end, which allows us to safely
16 // implement Copy, Clone, and DataInit.
17 #[repr(C)]
18 #[derive(Copy, Clone, Default)]
19 struct setup_data_hdr {
20     pub next: u64,
21     pub type_: u32,
22     pub len: u32,
23 }
24 
25 unsafe impl DataInit for setup_data_hdr {}
26 
27 /// Creates a flattened device tree containing all of the parameters for the
28 /// kernel and loads it into the guest memory at the specified offset.
29 ///
30 /// # Arguments
31 ///
32 /// * `fdt_max_size` - The amount of space reserved for the device tree
33 /// * `guest_mem` - The guest memory object
34 /// * `fdt_load_offset` - The offset into physical memory for the device tree
35 /// * `android_fstab` - the File object for the android fstab
create_fdt( fdt_max_size: usize, guest_mem: &GuestMemory, fdt_load_offset: u64, android_fstab: File, ) -> Result<usize, Error>36 pub fn create_fdt(
37     fdt_max_size: usize,
38     guest_mem: &GuestMemory,
39     fdt_load_offset: u64,
40     android_fstab: File,
41 ) -> Result<usize, Error> {
42     // Reserve space for the setup_data
43     let fdt_data_size = fdt_max_size - mem::size_of::<setup_data>();
44 
45     let mut fdt = FdtWriter::new(&[]);
46 
47     // The whole thing is put into one giant node with some top level properties
48     let root_node = fdt.begin_node("")?;
49     create_android_fdt(&mut fdt, android_fstab)?;
50     fdt.end_node(root_node)?;
51 
52     let fdt_final = fdt.finish(fdt_data_size)?;
53 
54     assert_eq!(
55         mem::size_of::<setup_data>(),
56         mem::size_of::<setup_data_hdr>()
57     );
58     let hdr = setup_data_hdr {
59         next: 0,
60         type_: SETUP_DTB,
61         len: fdt_data_size as u32,
62     };
63 
64     assert!(fdt_data_size as u64 <= X86_64_FDT_MAX_SIZE);
65 
66     let fdt_address = GuestAddress(fdt_load_offset);
67     guest_mem
68         .checked_offset(fdt_address, fdt_data_size as u64)
69         .ok_or(Error::FdtGuestMemoryWriteError)?;
70     guest_mem
71         .write_obj_at_addr(hdr, fdt_address)
72         .map_err(|_| Error::FdtGuestMemoryWriteError)?;
73 
74     let fdt_data_address = GuestAddress(fdt_load_offset + mem::size_of::<setup_data>() as u64);
75     let written = guest_mem
76         .write_at_addr(fdt_final.as_slice(), fdt_data_address)
77         .map_err(|_| Error::FdtGuestMemoryWriteError)?;
78     if written < fdt_data_size {
79         return Err(Error::FdtGuestMemoryWriteError);
80     }
81     Ok(fdt_data_size)
82 }
83