summary refs log tree commit diff
path: root/aarch64/src
diff options
context:
space:
mode:
authorTristan Muntsinger <muntsinger@google.com>2018-12-21 16:01:56 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-01-28 14:17:10 -0800
commit4133b0120d1e16cafbb373b2ae17a214b594038b (patch)
tree177506988846e4b86e639cdb963bbaba0c4e6ca9 /aarch64/src
parentf052cfefc8d6d27fa068c34190615db1819b8fef (diff)
downloadcrosvm-4133b0120d1e16cafbb373b2ae17a214b594038b.tar
crosvm-4133b0120d1e16cafbb373b2ae17a214b594038b.tar.gz
crosvm-4133b0120d1e16cafbb373b2ae17a214b594038b.tar.bz2
crosvm-4133b0120d1e16cafbb373b2ae17a214b594038b.tar.lz
crosvm-4133b0120d1e16cafbb373b2ae17a214b594038b.tar.xz
crosvm-4133b0120d1e16cafbb373b2ae17a214b594038b.tar.zst
crosvm-4133b0120d1e16cafbb373b2ae17a214b594038b.zip
crosvm: x86_64 guest support for android device-tree
This device tree is derived from the Android fstab file which is
provided via command line flag.

BUG=chromium:922737
TEST=None
CQ-DEPEND=CL:1415390
CQ-DEPEND=CL:1415270

Change-Id: Idd007c844f84cab3ff37be16a718f14e5f630312
Reviewed-on: https://chromium-review.googlesource.com/1370058
Commit-Ready: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'aarch64/src')
-rw-r--r--aarch64/src/fdt.rs239
-rw-r--r--aarch64/src/lib.rs1
2 files changed, 7 insertions, 233 deletions
diff --git a/aarch64/src/fdt.rs b/aarch64/src/fdt.rs
index e6cfa0d..0780a55 100644
--- a/aarch64/src/fdt.rs
+++ b/aarch64/src/fdt.rs
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use byteorder::{BigEndian, ByteOrder};
-use libc::{c_char, c_int, c_void};
-use std::error::{self, Error as FdtError};
-use std::ffi::{CStr, CString};
-use std::fmt;
-use std::ptr::null;
+use std::ffi::CStr;
 
+use arch::fdt::{
+    begin_node, end_node, finish_fdt, generate_prop32, generate_prop64, property, property_cstring,
+    property_null, property_string, property_u32, property_u64, start_fdt, Error,
+};
 use devices::PciInterruptPin;
 use sys_util::{GuestAddress, GuestMemory};
 
@@ -55,197 +54,6 @@ const IRQ_TYPE_EDGE_RISING: u32 = 0x00000001;
 const IRQ_TYPE_LEVEL_HIGH: u32 = 0x00000004;
 const IRQ_TYPE_LEVEL_LOW: u32 = 0x00000008;
 
-// This links to libfdt which handles the creation of the binary blob
-// flattened device tree (fdt) that is passed to the kernel and indicates
-// the hardware configuration of the machine.
-#[link(name = "fdt")]
-extern "C" {
-    fn fdt_create(buf: *mut c_void, bufsize: c_int) -> c_int;
-    fn fdt_finish_reservemap(fdt: *mut c_void) -> c_int;
-    fn fdt_begin_node(fdt: *mut c_void, name: *const c_char) -> c_int;
-    fn fdt_property(fdt: *mut c_void, name: *const c_char, val: *const c_void, len: c_int)
-        -> c_int;
-    fn fdt_end_node(fdt: *mut c_void) -> c_int;
-    fn fdt_open_into(fdt: *const c_void, buf: *mut c_void, bufsize: c_int) -> c_int;
-    fn fdt_finish(fdt: *const c_void) -> c_int;
-    fn fdt_pack(fdt: *mut c_void) -> c_int;
-}
-
-#[derive(Debug)]
-pub enum Error {
-    FdtCreateError(c_int),
-    FdtFinishReservemapError(c_int),
-    FdtBeginNodeError(c_int),
-    FdtPropertyError(c_int),
-    FdtEndNodeError(c_int),
-    FdtOpenIntoError(c_int),
-    FdtFinishError(c_int),
-    FdtPackError(c_int),
-    FdtGuestMemoryWriteError,
-}
-
-impl error::Error for Error {
-    fn description(&self) -> &str {
-        match self {
-            &Error::FdtCreateError(_) => "Error creating FDT",
-            &Error::FdtFinishReservemapError(_) => "Error finishing reserve map",
-            &Error::FdtBeginNodeError(_) => "Error beginning FDT node",
-            &Error::FdtPropertyError(_) => "Error adding FDT property",
-            &Error::FdtEndNodeError(_) => "Error ending FDT node",
-            &Error::FdtOpenIntoError(_) => "Error copying FDT to Guest",
-            &Error::FdtFinishError(_) => "Error performing FDT finish",
-            &Error::FdtPackError(_) => "Error packing FDT",
-            &Error::FdtGuestMemoryWriteError => "Error writing FDT to Guest Memory",
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let prefix = "Libfdt Error: ";
-        match self {
-            &Error::FdtCreateError(fdt_ret)
-            | &Error::FdtFinishReservemapError(fdt_ret)
-            | &Error::FdtBeginNodeError(fdt_ret)
-            | &Error::FdtPropertyError(fdt_ret)
-            | &Error::FdtEndNodeError(fdt_ret)
-            | &Error::FdtOpenIntoError(fdt_ret)
-            | &Error::FdtFinishError(fdt_ret)
-            | &Error::FdtPackError(fdt_ret) => write!(
-                f,
-                "{} {} code: {}",
-                prefix,
-                Error::description(self),
-                fdt_ret
-            ),
-            &Error::FdtGuestMemoryWriteError => {
-                write!(f, "{} {}", prefix, Error::description(self))
-            }
-        }
-    }
-}
-
-// Our ARM systems are little-endian whereas fdts are big-endian, so we need
-// to convert integers
-fn cpu_to_fdt32(input: u32) -> [u8; 4] {
-    let mut buf = [0; 4];
-    BigEndian::write_u32(&mut buf, input);
-    buf
-}
-
-fn cpu_to_fdt64(input: u64) -> [u8; 8] {
-    let mut buf = [0; 8];
-    BigEndian::write_u64(&mut buf, input);
-    buf
-}
-
-fn begin_node(fdt: &mut Vec<u8>, name: &str) -> Result<(), Box<Error>> {
-    let cstr_name = CString::new(name).unwrap();
-
-    // Safe because we allocated fdt and converted name to a CString
-    let fdt_ret = unsafe { fdt_begin_node(fdt.as_mut_ptr() as *mut c_void, cstr_name.as_ptr()) };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtBeginNodeError(fdt_ret)));
-    }
-    Ok(())
-}
-
-fn end_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
-    // Safe because we allocated fdt
-    let fdt_ret = unsafe { fdt_end_node(fdt.as_mut_ptr() as *mut c_void) };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtEndNodeError(fdt_ret)));
-    }
-    Ok(())
-}
-
-fn property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<(), Box<Error>> {
-    let cstr_name = CString::new(name).unwrap();
-    let val_ptr = val.as_ptr() as *const c_void;
-
-    // Safe because we allocated fdt and converted name to a CString
-    let fdt_ret = unsafe {
-        fdt_property(
-            fdt.as_mut_ptr() as *mut c_void,
-            cstr_name.as_ptr(),
-            val_ptr,
-            val.len() as i32,
-        )
-    };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPropertyError(fdt_ret)));
-    }
-    Ok(())
-}
-
-fn property_cstring(fdt: &mut Vec<u8>, name: &str, cstr_value: &CStr) -> Result<(), Box<Error>> {
-    let value_bytes = cstr_value.to_bytes_with_nul();
-    let cstr_name = CString::new(name).unwrap();
-
-    // Safe because we allocated fdt, converted name and value to CStrings
-    let fdt_ret = unsafe {
-        fdt_property(
-            fdt.as_mut_ptr() as *mut c_void,
-            cstr_name.as_ptr(),
-            value_bytes.as_ptr() as *mut c_void,
-            value_bytes.len() as i32,
-        )
-    };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPropertyError(fdt_ret)));
-    }
-    Ok(())
-}
-
-fn property_null(fdt: &mut Vec<u8>, name: &str) -> Result<(), Box<Error>> {
-    let cstr_name = CString::new(name).unwrap();
-
-    // Safe because we allocated fdt, converted name to a CString
-    let fdt_ret = unsafe {
-        fdt_property(
-            fdt.as_mut_ptr() as *mut c_void,
-            cstr_name.as_ptr(),
-            null(),
-            0,
-        )
-    };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPropertyError(fdt_ret)));
-    }
-    Ok(())
-}
-
-fn property_string(fdt: &mut Vec<u8>, name: &str, value: &str) -> Result<(), Box<Error>> {
-    let cstr_value = CString::new(value).unwrap();
-    property_cstring(fdt, name, &cstr_value)
-}
-
-fn property_u32(fdt: &mut Vec<u8>, name: &str, val: u32) -> Result<(), Box<Error>> {
-    property(fdt, name, &cpu_to_fdt32(val))
-}
-
-fn property_u64(fdt: &mut Vec<u8>, name: &str, val: u64) -> Result<(), Box<Error>> {
-    property(fdt, name, &cpu_to_fdt64(val))
-}
-
-// Helper to generate a properly formatted byte vector using 32-bit cells
-fn generate_prop32(cells: &[u32]) -> Vec<u8> {
-    let mut ret: Vec<u8> = Vec::new();
-    for &e in cells {
-        ret.extend(cpu_to_fdt32(e).into_iter());
-    }
-    ret
-}
-
-// Helper to generate a properly formatted byte vector using 64-bit cells
-fn generate_prop64(cells: &[u64]) -> Vec<u8> {
-    let mut ret: Vec<u8> = Vec::new();
-    for &e in cells {
-        ret.extend(cpu_to_fdt64(e).into_iter());
-    }
-    ret
-}
-
 fn create_memory_node(fdt: &mut Vec<u8>, guest_mem: &GuestMemory) -> Result<(), Box<Error>> {
     let mem_size = guest_mem.memory_size();
     let mem_reg_prop = generate_prop64(&[AARCH64_PHYS_MEM_START, mem_size]);
@@ -487,18 +295,7 @@ pub fn create_fdt(
     cmdline: &CStr,
 ) -> Result<(), Box<Error>> {
     let mut fdt = vec![0; fdt_max_size];
-
-    // Safe since we allocated this array with fdt_max_size
-    let mut fdt_ret = unsafe { fdt_create(fdt.as_mut_ptr() as *mut c_void, fdt_max_size as c_int) };
-
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtCreateError(fdt_ret)));
-    }
-    // Safe since we allocated this array
-    fdt_ret = unsafe { fdt_finish_reservemap(fdt.as_mut_ptr() as *mut c_void) };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtFinishReservemapError(fdt_ret)));
-    }
+    start_fdt(&mut fdt, fdt_max_size)?;
 
     // The whole thing is put into one giant node with some top level properties
     begin_node(&mut fdt, "")?;
@@ -519,32 +316,10 @@ pub fn create_fdt(
     // End giant node
     end_node(&mut fdt)?;
 
-    // Safe since we allocated fdt_final and previously passed in it's size
-    fdt_ret = unsafe { fdt_finish(fdt.as_mut_ptr() as *mut c_void) };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtFinishError(fdt_ret)));
-    }
-
     // Allocate another buffer so we can format and then write fdt to guest
     let mut fdt_final = vec![0; fdt_max_size];
+    finish_fdt(&mut fdt, &mut fdt_final, fdt_max_size)?;
 
-    // Safe because we allocated both arrays with the correct size
-    fdt_ret = unsafe {
-        fdt_open_into(
-            fdt.as_mut_ptr() as *mut c_void,
-            fdt_final.as_mut_ptr() as *mut c_void,
-            fdt_max_size as i32,
-        )
-    };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtOpenIntoError(fdt_ret)));
-    }
-
-    // Safe since we allocated fdt_final
-    fdt_ret = unsafe { fdt_pack(fdt_final.as_mut_ptr() as *mut c_void) };
-    if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPackError(fdt_ret)));
-    }
     let fdt_address = GuestAddress(AARCH64_PHYS_MEM_START + fdt_load_offset);
     let written = guest_mem
         .write_at_addr(fdt_final.as_slice(), fdt_address)
diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs
index d579a17..48effe5 100644
--- a/aarch64/src/lib.rs
+++ b/aarch64/src/lib.rs
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 extern crate arch;
-extern crate byteorder;
 extern crate data_model;
 extern crate devices;
 extern crate io_jail;