• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #[cfg(any(target_os = "android", target_os = "linux"))]
6 use std::collections::BTreeMap;
7 use std::fs::File;
8 use std::fs::OpenOptions;
9 use std::io::Write;
10 use std::path::PathBuf;
11 
12 use arch::android::create_android_fdt;
13 use arch::apply_device_tree_overlays;
14 use arch::DtbOverlay;
15 use base::open_file_or_duplicate;
16 use cros_fdt::Error;
17 use cros_fdt::Fdt;
18 use resources::AddressRange;
19 use vm_memory::GuestAddress;
20 
create_config_node(fdt: &mut Fdt, kernel_region: AddressRange) -> cros_fdt::Result<()>21 fn create_config_node(fdt: &mut Fdt, kernel_region: AddressRange) -> cros_fdt::Result<()> {
22     let addr: u32 = kernel_region
23         .start
24         .try_into()
25         .map_err(|_| Error::PropertyValueTooLarge)?;
26     let size: u32 = kernel_region
27         .len()
28         .expect("invalid kernel_region")
29         .try_into()
30         .map_err(|_| Error::PropertyValueTooLarge)?;
31 
32     let config_node = fdt.root_mut().subnode_mut("config")?;
33     config_node.set_prop("kernel-address", addr)?;
34     config_node.set_prop("kernel-size", size)?;
35     Ok(())
36 }
37 
create_chosen_node( fdt: &mut Fdt, initrd: Option<(GuestAddress, usize)>, ) -> cros_fdt::Result<()>38 fn create_chosen_node(
39     fdt: &mut Fdt,
40     initrd: Option<(GuestAddress, usize)>,
41 ) -> cros_fdt::Result<()> {
42     let chosen_node = fdt.root_mut().subnode_mut("chosen")?;
43 
44     if let Some((initrd_addr, initrd_size)) = initrd {
45         let initrd_start = initrd_addr.offset() as u32;
46         let initrd_end = initrd_start + initrd_size as u32;
47         chosen_node.set_prop("linux,initrd-start", initrd_start)?;
48         chosen_node.set_prop("linux,initrd-end", initrd_end)?;
49     }
50 
51     Ok(())
52 }
53 
54 /// Creates a flattened device tree containing all of the parameters for the
55 /// kernel and returns it as DTB.
56 ///
57 /// # Arguments
58 ///
59 /// * `android_fstab` - the File object for the android fstab
create_fdt( android_fstab: Option<File>, dump_device_tree_blob: Option<PathBuf>, device_tree_overlays: Vec<DtbOverlay>, kernel_region: AddressRange, initrd: Option<(GuestAddress, usize)>, ) -> Result<Vec<u8>, Error>60 pub fn create_fdt(
61     android_fstab: Option<File>,
62     dump_device_tree_blob: Option<PathBuf>,
63     device_tree_overlays: Vec<DtbOverlay>,
64     kernel_region: AddressRange,
65     initrd: Option<(GuestAddress, usize)>,
66 ) -> Result<Vec<u8>, Error> {
67     let mut fdt = Fdt::new(&[]);
68     // The whole thing is put into one giant node with some top level properties
69     if let Some(android_fstab) = android_fstab {
70         create_android_fdt(&mut fdt, android_fstab)?;
71     }
72 
73     create_config_node(&mut fdt, kernel_region)?;
74     create_chosen_node(&mut fdt, initrd)?;
75 
76     // Done writing base FDT, now apply DT overlays
77     apply_device_tree_overlays(
78         &mut fdt,
79         device_tree_overlays,
80         #[cfg(any(target_os = "android", target_os = "linux"))]
81         vec![],
82         #[cfg(any(target_os = "android", target_os = "linux"))]
83         &BTreeMap::new(),
84     )?;
85 
86     let fdt_final = fdt.finish()?;
87 
88     if let Some(file_path) = dump_device_tree_blob {
89         let mut fd = open_file_or_duplicate(
90             &file_path,
91             OpenOptions::new()
92                 .read(true)
93                 .create(true)
94                 .truncate(true)
95                 .write(true),
96         )
97         .map_err(|e| Error::FdtIoError(e.into()))?;
98         fd.write_all(&fdt_final)
99             .map_err(|e| Error::FdtDumpIoError(e, file_path.clone()))?;
100     }
101 
102     Ok(fdt_final)
103 }
104