diff options
author | Tristan Muntsinger <muntsinger@google.com> | 2018-12-21 16:01:56 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-01-28 14:17:10 -0800 |
commit | 4133b0120d1e16cafbb373b2ae17a214b594038b (patch) | |
tree | 177506988846e4b86e639cdb963bbaba0c4e6ca9 /aarch64/src | |
parent | f052cfefc8d6d27fa068c34190615db1819b8fef (diff) | |
download | crosvm-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.rs | 239 | ||||
-rw-r--r-- | aarch64/src/lib.rs | 1 |
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; |