From 682976c8dad3e678b4f17dae03223ba0e42e770d Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Thu, 18 Apr 2019 12:55:35 +0800 Subject: [PATCH 01/27] linux-loader: Create linux-loader crate This crate is derived from upstream project: firecracker project commit 223bdb64d3eb445f55872e63d9ed2518d2235759 The following changes are made after code ported from firecracker: - Return the offset in memory where kernel image loading is finished, add the related logic in load function also, according to upstream project crosvm commit 4133b0120d1e16cafbb373b2ae17a214b594038b - Ported to vm-memory, remove dependency on firecrakcer memory-model - Remove dependency on sys_util, use read_util instead Signed-off-by: Cathy Zhang --- Cargo.toml | 10 ++ DESIGN.md | 38 ++++ README.md | 27 +++ src/cmdline/mod.rs | 234 +++++++++++++++++++++++++ src/lib.rs | 13 ++ src/loader/elf.rs | 339 ++++++++++++++++++++++++++++++++++++ src/loader/mod.rs | 357 ++++++++++++++++++++++++++++++++++++++ src/loader/struct_util.rs | 151 ++++++++++++++++ src/loader/test_elf.bin | Bin 0 -> 4424 bytes 9 files changed, 1169 insertions(+) create mode 100644 Cargo.toml create mode 100644 DESIGN.md create mode 100644 README.md create mode 100644 src/cmdline/mod.rs create mode 100644 src/lib.rs create mode 100644 src/loader/elf.rs create mode 100644 src/loader/mod.rs create mode 100644 src/loader/struct_util.rs create mode 100644 src/loader/test_elf.bin diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..b731b04e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "linux-loader" +version = "0.1.0" +authors = ["Cathy Zhang "] +edition = "2018" +license = "Apache-2.0" + +[dependencies.vm-memory] +git = "https://github.com/rust-vmm/vm-memory" +features = ["backend-mmap"] diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 00000000..b448900c --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,38 @@ +# ELF Image parsing and loading + +The boot process is explained from the following two sides. + +## Loader side + +It follows ELF standard which is specified in elf.rs. +The entry header and program headers will be inerpreted, and PT_LOAD segments +will be loaded into guest memory. + +### Where kernel is loaded + +There are two ways on deciding where the program segments will be loaded. + +- One way is to provide an option and allow vmm to specify where to load the + image, considering its memory layout. + +- The other way is to load image into phdr.p_paddr by default. + +## VMM side + +### Construct zero page + +According to the 64-bit boot protocol, the boot parameters (traditionally known +as "zero page") should be setup, including setup_header, e820 table and other +stuff. However, ELF has no setup_header, nothing returned from ELF loader could +be used to fill boot parameters, vmm is totally responsible for the construction. + +### Configure vCPU + +- RIP, the start offset of guest memory where kernel is loaded, which is + returned from loader + +- 64 bit mode with paging enabled + +- GDT must be configured and loaded + + diff --git a/README.md b/README.md new file mode 100644 index 00000000..28174678 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Linux-loader + +## Short-description + +* Parsing and loading vmlinux (raw ELF image) and bzImage images +* Linux command line parsing and generation +* Definitions and helpers for the Linux boot protocol + +## How to build + +``` +cd linux-loader +cargo build +``` + +## How to run test + +``` +cd linux-loader +cargo test +cargo test -- --nocapture +``` + +## Platform Support +- Arch: x86 +- OS: Linux/Unix + diff --git a/src/cmdline/mod.rs b/src/cmdline/mod.rs new file mode 100644 index 00000000..3dd3c8bc --- /dev/null +++ b/src/cmdline/mod.rs @@ -0,0 +1,234 @@ +// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the THIRD-PARTY file. + +//! Helper for creating valid kernel command line strings. + +use std::fmt; +use std::result; + +/// The error type for command line building operations. +#[derive(PartialEq, Debug)] +pub enum Error { + /// Operation would have resulted in a non-printable ASCII character. + InvalidAscii, + /// Key/Value Operation would have had a space in it. + HasSpace, + /// Key/Value Operation would have had an equals sign in it. + HasEquals, + /// Operation would have made the command line too large. + TooLarge, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}", + match *self { + Error::InvalidAscii => "string contains non-printable ASCII character", + Error::HasSpace => "string contains a space", + Error::HasEquals => "string contains an equals sign", + Error::TooLarge => "inserting string would make command line too long", + } + ) + } +} + +/// Specialized Result type for command line operations. +pub type Result = result::Result; + +fn valid_char(c: char) -> bool { + match c { + ' '...'~' => true, + _ => false, + } +} + +fn valid_str(s: &str) -> Result<()> { + if s.chars().all(valid_char) { + Ok(()) + } else { + Err(Error::InvalidAscii) + } +} + +fn valid_element(s: &str) -> Result<()> { + if !s.chars().all(valid_char) { + Err(Error::InvalidAscii) + } else if s.contains(' ') { + Err(Error::HasSpace) + } else if s.contains('=') { + Err(Error::HasEquals) + } else { + Ok(()) + } +} + +/// A builder for a kernel command line string that validates the string as its being built. A +/// `CString` can be constructed from this directly using `CString::new`. +#[derive(Clone)] +pub struct Cmdline { + line: String, + capacity: usize, +} + +impl Cmdline { + /// Constructs an empty Cmdline with the given capacity, which includes the nul terminator. + /// Capacity must be greater than 0. + pub fn new(capacity: usize) -> Cmdline { + assert_ne!(capacity, 0); + Cmdline { + line: String::with_capacity(capacity), + capacity: capacity, + } + } + + fn has_capacity(&self, more: usize) -> Result<()> { + let needs_space = if self.line.is_empty() { 0 } else { 1 }; + if self.line.len() + more + needs_space < self.capacity { + Ok(()) + } else { + Err(Error::TooLarge) + } + } + + fn start_push(&mut self) { + if !self.line.is_empty() { + self.line.push(' '); + } + } + + fn end_push(&mut self) { + // This assert is always true because of the `has_capacity` check that each insert method + // uses. + assert!(self.line.len() < self.capacity); + } + + /// Validates and inserts a key value pair into this command line + pub fn insert>(&mut self, key: T, val: T) -> Result<()> { + let k = key.as_ref(); + let v = val.as_ref(); + + valid_element(k)?; + valid_element(v)?; + self.has_capacity(k.len() + v.len() + 1)?; + + self.start_push(); + self.line.push_str(k); + self.line.push('='); + self.line.push_str(v); + self.end_push(); + + Ok(()) + } + + /// Validates and inserts a string to the end of the current command line + pub fn insert_str>(&mut self, slug: T) -> Result<()> { + let s = slug.as_ref(); + valid_str(s)?; + + self.has_capacity(s.len())?; + + self.start_push(); + self.line.push_str(s); + self.end_push(); + + Ok(()) + } + + /// Returns the cmdline in progress without nul termination + pub fn as_str(&self) -> &str { + self.line.as_str() + } +} + +impl Into> for Cmdline { + fn into(self) -> Vec { + self.line.into_bytes() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::ffi::CString; + + #[test] + fn insert_hello_world() { + let mut cl = Cmdline::new(100); + assert_eq!(cl.as_str(), ""); + assert!(cl.insert("hello", "world").is_ok()); + assert_eq!(cl.as_str(), "hello=world"); + + let s = CString::new(cl).expect("failed to create CString from Cmdline"); + assert_eq!(s, CString::new("hello=world").unwrap()); + } + + #[test] + fn insert_multi() { + let mut cl = Cmdline::new(100); + assert!(cl.insert("hello", "world").is_ok()); + assert!(cl.insert("foo", "bar").is_ok()); + assert_eq!(cl.as_str(), "hello=world foo=bar"); + } + + #[test] + fn insert_space() { + let mut cl = Cmdline::new(100); + assert_eq!(cl.insert("a ", "b"), Err(Error::HasSpace)); + assert_eq!(cl.insert("a", "b "), Err(Error::HasSpace)); + assert_eq!(cl.insert("a ", "b "), Err(Error::HasSpace)); + assert_eq!(cl.insert(" a", "b"), Err(Error::HasSpace)); + assert_eq!(cl.as_str(), ""); + } + + #[test] + fn insert_equals() { + let mut cl = Cmdline::new(100); + assert_eq!(cl.insert("a=", "b"), Err(Error::HasEquals)); + assert_eq!(cl.insert("a", "b="), Err(Error::HasEquals)); + assert_eq!(cl.insert("a=", "b "), Err(Error::HasEquals)); + assert_eq!(cl.insert("=a", "b"), Err(Error::HasEquals)); + assert_eq!(cl.insert("a", "=b"), Err(Error::HasEquals)); + assert_eq!(cl.as_str(), ""); + } + + #[test] + fn insert_emoji() { + let mut cl = Cmdline::new(100); + assert_eq!(cl.insert("heart", "💖"), Err(Error::InvalidAscii)); + assert_eq!(cl.insert("💖", "love"), Err(Error::InvalidAscii)); + assert_eq!(cl.as_str(), ""); + } + + #[test] + fn insert_string() { + let mut cl = Cmdline::new(13); + assert_eq!(cl.as_str(), ""); + assert!(cl.insert_str("noapic").is_ok()); + assert_eq!(cl.as_str(), "noapic"); + assert!(cl.insert_str("nopci").is_ok()); + assert_eq!(cl.as_str(), "noapic nopci"); + } + + #[test] + fn insert_too_large() { + let mut cl = Cmdline::new(4); + assert_eq!(cl.insert("hello", "world"), Err(Error::TooLarge)); + assert_eq!(cl.insert("a", "world"), Err(Error::TooLarge)); + assert_eq!(cl.insert("hello", "b"), Err(Error::TooLarge)); + assert!(cl.insert("a", "b").is_ok()); + assert_eq!(cl.insert("a", "b"), Err(Error::TooLarge)); + assert_eq!(cl.insert_str("a"), Err(Error::TooLarge)); + assert_eq!(cl.as_str(), "a=b"); + + let mut cl = Cmdline::new(10); + assert!(cl.insert("ab", "ba").is_ok()); // adds 5 length + assert_eq!(cl.insert("c", "da"), Err(Error::TooLarge)); // adds 5 (including space) length + assert!(cl.insert("c", "d").is_ok()); // adds 4 (including space) length + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..f8aa7d49 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,13 @@ +// Copyright (c) 2019 Intel Corporation. All rights reserved. +// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +pub mod cmdline; +pub mod loader; + +extern crate vm_memory; + diff --git a/src/loader/elf.rs b/src/loader/elf.rs new file mode 100644 index 00000000..d0664b69 --- /dev/null +++ b/src/loader/elf.rs @@ -0,0 +1,339 @@ +// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the THIRD-PARTY file. + +/* + * automatically generated by rust-bindgen + * From upstream linux include/uapi/linux/elf.h at commit: + * 806276b7f07a39a1cc3f38bb1ef5c573d4594a38 + */ +pub const EI_MAG0: ::std::os::raw::c_uint = 0; +pub const EI_MAG1: ::std::os::raw::c_uint = 1; +pub const EI_MAG2: ::std::os::raw::c_uint = 2; +pub const EI_MAG3: ::std::os::raw::c_uint = 3; +pub const EI_DATA: ::std::os::raw::c_uint = 5; + +pub const ELFMAG0: ::std::os::raw::c_uint = 127; + +pub const ELFDATA2LSB: ::std::os::raw::c_uint = 1; +pub const PT_LOAD: ::std::os::raw::c_uint = 1; + +pub const ELFMAG1: u8 = b'E'; +pub const ELFMAG2: u8 = b'L'; +pub const ELFMAG3: u8 = b'F'; + +type Elf64_Addr = __u64; +type Elf64_Half = __u16; +type Elf64_Off = __u64; +type Elf64_Word = __u32; +type Elf64_Xword = __u64; + +type __s8 = ::std::os::raw::c_schar; +type __u8 = ::std::os::raw::c_uchar; +type __s16 = ::std::os::raw::c_short; +type __u16 = ::std::os::raw::c_ushort; +type __s32 = ::std::os::raw::c_int; +type __u32 = ::std::os::raw::c_uint; +type __s64 = ::std::os::raw::c_longlong; +type __u64 = ::std::os::raw::c_ulonglong; + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct elf64_hdr { + pub e_ident: [::std::os::raw::c_uchar; 16usize], + pub e_type: Elf64_Half, + pub e_machine: Elf64_Half, + pub e_version: Elf64_Word, + pub e_entry: Elf64_Addr, + pub e_phoff: Elf64_Off, + pub e_shoff: Elf64_Off, + pub e_flags: Elf64_Word, + pub e_ehsize: Elf64_Half, + pub e_phentsize: Elf64_Half, + pub e_phnum: Elf64_Half, + pub e_shentsize: Elf64_Half, + pub e_shnum: Elf64_Half, + pub e_shstrndx: Elf64_Half, +} +impl Clone for elf64_hdr { + fn clone(&self) -> Self { + *self + } +} +pub type Elf64_Ehdr = elf64_hdr; + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct elf64_phdr { + pub p_type: Elf64_Word, + pub p_flags: Elf64_Word, + pub p_offset: Elf64_Off, + pub p_vaddr: Elf64_Addr, + pub p_paddr: Elf64_Addr, + pub p_filesz: Elf64_Xword, + pub p_memsz: Elf64_Xword, + pub p_align: Elf64_Xword, +} + +impl Clone for elf64_phdr { + fn clone(&self) -> Self { + *self + } +} +pub type Elf64_Phdr = elf64_phdr; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bindgen_test_layout_elf64_phdr() { + assert_eq!( + ::std::mem::size_of::(), + 56usize, + concat!("Size of: ", stringify!(elf64_phdr)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(elf64_phdr)) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_type as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_type) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_flags as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_flags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_offset as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_offset) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_vaddr as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_vaddr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_paddr as *const _ as usize }, + 24usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_paddr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_filesz as *const _ as usize }, + 32usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_filesz) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_memsz as *const _ as usize }, + 40usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_memsz) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_phdr)).p_align as *const _ as usize }, + 48usize, + concat!( + "Alignment of field: ", + stringify!(elf64_phdr), + "::", + stringify!(p_align) + ) + ); + } + + #[test] + fn bindgen_test_layout_elf64_hdr() { + assert_eq!( + ::std::mem::size_of::(), + 64usize, + concat!("Size of: ", stringify!(elf64_hdr)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(elf64_hdr)) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_ident as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_ident) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_type as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_type) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_machine as *const _ as usize }, + 18usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_machine) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_version as *const _ as usize }, + 20usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_version) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_entry as *const _ as usize }, + 24usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_entry) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_phoff as *const _ as usize }, + 32usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_phoff) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_shoff as *const _ as usize }, + 40usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_shoff) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_flags as *const _ as usize }, + 48usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_flags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_ehsize as *const _ as usize }, + 52usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_ehsize) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_phentsize as *const _ as usize }, + 54usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_phentsize) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_phnum as *const _ as usize }, + 56usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_phnum) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_shentsize as *const _ as usize }, + 58usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_shentsize) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_shnum as *const _ as usize }, + 60usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_shnum) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const elf64_hdr)).e_shstrndx as *const _ as usize }, + 62usize, + concat!( + "Alignment of field: ", + stringify!(elf64_hdr), + "::", + stringify!(e_shstrndx) + ) + ); + } +} diff --git a/src/loader/mod.rs b/src/loader/mod.rs new file mode 100644 index 00000000..5f904279 --- /dev/null +++ b/src/loader/mod.rs @@ -0,0 +1,357 @@ +// Copyright (c) 2019 Intel Corporation. All rights reserved. +// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern crate vm_memory; + +use std::error::{self, Error as KernelLoaderError}; +use std::ffi::CStr; +use std::fmt::{self, Display}; +use std::io::{Read, Seek, SeekFrom}; +use std::mem; + +use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestUsize}; + +#[allow(dead_code)] +#[allow(non_camel_case_types)] +#[allow(non_snake_case)] +#[allow(non_upper_case_globals)] +#[cfg_attr(feature = "cargo-clippy", allow(clippy))] +mod elf; +mod struct_util; + +#[derive(Debug, PartialEq)] +pub enum Error { + BigEndianElfOnLittle, + CommandLineCopy, + CommandLineOverflow, + InvalidElfMagicNumber, + InvalidProgramHeaderSize, + InvalidProgramHeaderOffset, + InvalidProgramHeaderAddress, + InvalidEntryAddress, + InvalidKernelStartAddress, + InitrdImageSizeTooLarge, + ReadElfHeader, + ReadKernelImage, + ReadProgramHeader, + ReadInitrdImage, + SeekKernelStart, + SeekElfStart, + SeekProgramHeader, + SeekInitrdImage, +} +pub type Result = std::result::Result; + +impl error::Error for Error { + fn description(&self) -> &str { + match self { + Error::BigEndianElfOnLittle => { + "Trying to load big-endian binary on little-endian machine" + } + Error::CommandLineCopy => "Failed writing command line to guest memory", + Error::CommandLineOverflow => "Command line overflowed guest memory", + Error::InvalidElfMagicNumber => "Invalid Elf magic number", + Error::InvalidProgramHeaderSize => "Invalid program header size", + Error::InvalidProgramHeaderOffset => "Invalid program header offset", + Error::InvalidProgramHeaderAddress => "Invalid Program Header Address", + Error::InvalidEntryAddress => "Invalid entry address", + Error::InvalidKernelStartAddress => "Invalid kernel start address", + Error::InitrdImageSizeTooLarge => "Initrd image size too large", + Error::ReadElfHeader => "Unable to read elf header", + Error::ReadKernelImage => "Unable to read kernel image", + Error::ReadProgramHeader => "Unable to read program header", + Error::ReadInitrdImage => "Unable to read initrd image", + Error::SeekKernelStart => "Unable to seek to kernel start", + Error::SeekElfStart => "Unable to seek to elf start", + Error::SeekProgramHeader => "Unable to seek to program header", + Error::SeekInitrdImage => "Unable to seek initrd image", + } + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Kernel Loader Error: {}", Error::description(self)) + } +} + +pub struct ElfLoader; + +impl ElfLoader { + /// Loads a kernel from a vmlinux elf image to a slice + /// + /// kernel is loaded into guest memory at offset phdr.p_paddr specified by elf image. + /// + /// # Arguments + /// + /// * `guest_mem` - The guest memory region the kernel is written to. + /// * `kernel_start` - The offset into 'guest _mem' at which to load the kernel. + /// * `kernel_image` - Input vmlinux image. + /// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it. + /// + /// # Returns + /// * GuestAddress - GuestAddress where kernel is loaded. + /// * usize - the length of kernel image. Return this in case of other part + /// like initrd will be loaded adjacent to the kernel part. + pub fn load_kernel( + guest_mem: &GuestMemoryMmap, + kernel_start: Option, + kernel_image: &mut F, + lowest_kernel_start: Option, + ) -> Result<(GuestAddress, GuestUsize)> + where + F: Read + Seek, + { + let mut ehdr: elf::Elf64_Ehdr = Default::default(); + kernel_image + .seek(SeekFrom::Start(0)) + .map_err(|_| Error::SeekElfStart)?; + unsafe { + // read_struct is safe when reading a POD struct. It can be used and dropped without issue. + struct_util::read_struct(kernel_image, &mut ehdr).map_err(|_| Error::ReadElfHeader)?; + } + + // Sanity checks + if ehdr.e_ident[elf::EI_MAG0 as usize] != elf::ELFMAG0 as u8 + || ehdr.e_ident[elf::EI_MAG1 as usize] != elf::ELFMAG1 + || ehdr.e_ident[elf::EI_MAG2 as usize] != elf::ELFMAG2 + || ehdr.e_ident[elf::EI_MAG3 as usize] != elf::ELFMAG3 + { + return Err(Error::InvalidElfMagicNumber); + } + if ehdr.e_ident[elf::EI_DATA as usize] != elf::ELFDATA2LSB as u8 { + return Err(Error::BigEndianElfOnLittle); + } + if ehdr.e_phentsize as usize != mem::size_of::() { + return Err(Error::InvalidProgramHeaderSize); + } + if (ehdr.e_phoff as usize) < mem::size_of::() { + // If the program header is backwards, bail. + return Err(Error::InvalidProgramHeaderOffset); + } + if lowest_kernel_start.is_some() { + if (ehdr.e_entry as u64) < lowest_kernel_start.unwrap().raw_value() { + return Err(Error::InvalidEntryAddress); + } + } + // where the kernel will be start loaded. + let kernel_loaded_addr = match kernel_start { + Some(start) => GuestAddress(start.raw_value() + (ehdr.e_entry as u64)), + None => GuestAddress(ehdr.e_entry as u64), + }; + + kernel_image + .seek(SeekFrom::Start(ehdr.e_phoff)) + .map_err(|_| Error::SeekProgramHeader)?; + let phdrs: Vec = unsafe { + // Reading the structs is safe for a slice of POD structs. + struct_util::read_struct_slice(kernel_image, ehdr.e_phnum as usize) + .map_err(|_| Error::ReadProgramHeader)? + }; + + let mut kernel_end: GuestUsize = 0; + + // Read in each section pointed to by the program headers. + for phdr in &phdrs { + if phdr.p_type != elf::PT_LOAD || phdr.p_filesz == 0 { + continue; + } + + kernel_image + .seek(SeekFrom::Start(phdr.p_offset)) + .map_err(|_| Error::SeekKernelStart)?; + + // vmm does not specify where the kernel should be loaded, just + // load it to the physical address p_paddr for each segment. + let mem_offset = match kernel_start { + Some(start) => start + .checked_add(phdr.p_paddr as u64) + .ok_or(Error::InvalidProgramHeaderAddress)?, + None => GuestAddress(phdr.p_paddr as u64), + }; + + guest_mem + .read_exact_from(mem_offset, kernel_image, phdr.p_filesz as usize) + .map_err(|_| Error::ReadKernelImage)?; + + kernel_end = mem_offset.raw_value() as GuestUsize + phdr.p_memsz as GuestUsize; + } + + Ok((kernel_loaded_addr, kernel_end)) + } +} + +/// Writes the command line string to the given memory slice. +/// +/// # Arguments +/// +/// * `guest_mem` - A u8 slice that will be partially overwritten by the command line. +/// * `guest_addr` - The address in `guest_mem` at which to load the command line. +/// * `cmdline` - The kernel command line. +pub fn load_cmdline( + guest_mem: &GuestMemoryMmap, + guest_addr: GuestAddress, + cmdline: &CStr, +) -> Result<()> { + let len = cmdline.to_bytes().len(); + if len == 0 { + return Ok(()); + } + + let end = guest_addr + .checked_add(len as u64 + 1) + .ok_or(Error::CommandLineOverflow)?; // Extra for null termination. + if end > guest_mem.end_addr() { + return Err(Error::CommandLineOverflow)?; + } + + guest_mem + .write_slice(cmdline.to_bytes_with_nul(), guest_addr) + .map_err(|_| Error::CommandLineCopy)?; + + Ok(()) +} + +#[cfg(test)] +mod test { + use super::*; + use vm_memory::{Address, GuestAddress, GuestMemoryMmap}; + use std::io::Cursor; + + const MEM_SIZE: u64 = 0x1000000; + + fn create_guest_mem() -> GuestMemoryMmap { + GuestMemoryMmap::new(&[(GuestAddress(0x0), (MEM_SIZE as usize))]).unwrap() + } + + // Elf64 image that prints hello world on x86_64. + fn make_elf_bin() -> Vec { + let mut v = Vec::new(); + v.extend_from_slice(include_bytes!("test_elf.bin")); + v + } + + #[test] + fn load_elf() { + let gm = create_guest_mem(); + let image = make_elf_bin(); + let kernel_addr = GuestAddress(0x200000); + let mut lowest_kernel_start = GuestAddress(0x0); + + let mut x = ElfLoader::load_kernel( + &gm, + Some(kernel_addr), + &mut Cursor::new(&image), + Some(lowest_kernel_start), + ); + assert_eq!(x.is_ok(), true); + let mut entry_addr = x.unwrap().0; + println!("load elf at address {:8x} \n", entry_addr.raw_value()); + + x = ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&image), None); + assert_eq!(x.is_ok(), true); + entry_addr = x.unwrap().0; + println!("load elf at address {:8x} \n", entry_addr.raw_value()); + + x = ElfLoader::load_kernel( + &gm, + None, + &mut Cursor::new(&image), + Some(lowest_kernel_start), + ); + assert_eq!(x.is_ok(), true); + entry_addr = x.unwrap().0; + println!("load elf at address {:8x} \n", entry_addr.raw_value()); + + lowest_kernel_start = GuestAddress(0xa00000); + assert_eq!( + Err(Error::InvalidEntryAddress), + ElfLoader::load_kernel(&gm, None, &mut Cursor::new(&image), Some(lowest_kernel_start)) + ); + } + + #[test] + fn cmdline_overflow() { + let gm = create_guest_mem(); + let cmdline_address = GuestAddress(MEM_SIZE - 5); + assert_eq!( + Err(Error::CommandLineOverflow), + load_cmdline( + &gm, + cmdline_address, + CStr::from_bytes_with_nul(b"12345\0").unwrap() + ) + ); + } + + #[test] + fn cmdline_write_end() { + let gm = create_guest_mem(); + let mut cmdline_address = GuestAddress(45); + assert_eq!( + Ok(()), + load_cmdline( + &gm, + cmdline_address, + CStr::from_bytes_with_nul(b"1234\0").unwrap() + ) + ); + let val: u8 = gm.read_obj(cmdline_address).unwrap(); + assert_eq!(val, '1' as u8); + cmdline_address = cmdline_address.unchecked_add(1); + let val: u8 = gm.read_obj(cmdline_address).unwrap(); + assert_eq!(val, '2' as u8); + cmdline_address = cmdline_address.unchecked_add(1); + let val: u8 = gm.read_obj(cmdline_address).unwrap(); + assert_eq!(val, '3' as u8); + cmdline_address = cmdline_address.unchecked_add(1); + let val: u8 = gm.read_obj(cmdline_address).unwrap(); + assert_eq!(val, '4' as u8); + cmdline_address = cmdline_address.unchecked_add(1); + let val: u8 = gm.read_obj(cmdline_address).unwrap(); + assert_eq!(val, '\0' as u8); + } + + #[test] + fn bad_magic() { + let gm = create_guest_mem(); + let kernel_addr = GuestAddress(0x0); + let mut bad_image = make_elf_bin(); + bad_image[0x1] = 0x33; + assert_eq!( + Err(Error::InvalidElfMagicNumber), + ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) + ); + } + + #[test] + fn bad_endian() { + // Only little endian is supported + let gm = create_guest_mem(); + let kernel_addr = GuestAddress(0x0); + let mut bad_image = make_elf_bin(); + bad_image[0x5] = 2; + assert_eq!( + Err(Error::BigEndianElfOnLittle), + ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) + ); + } + + #[test] + fn bad_phoff() { + // program header has to be past the end of the elf header + let gm = create_guest_mem(); + let kernel_addr = GuestAddress(0x0); + let mut bad_image = make_elf_bin(); + bad_image[0x20] = 0x10; + assert_eq!( + Err(Error::InvalidProgramHeaderOffset), + ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) + ); + } +} diff --git a/src/loader/struct_util.rs b/src/loader/struct_util.rs new file mode 100644 index 00000000..08f7fe6e --- /dev/null +++ b/src/loader/struct_util.rs @@ -0,0 +1,151 @@ +// Copyright (c) 2019 Intel Corporation. All rights reserved. +// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the THIRD-PARTY file. + +use std; +use std::io::Read; +use std::mem; + +#[derive(Debug)] +pub enum Error { + ReadStruct, +} +pub type Result = std::result::Result; + +/// Reads a struct from an input buffer. +/// This is unsafe because the struct is initialized to unverified data read from the input. +/// `read_struct` should only be called to fill plain old data structs. It is not endian safe. +/// +/// # Arguments +/// +/// * `f` - The input to read from. Often this is a file. +/// * `out` - The struct to fill with data read from `f`. +pub unsafe fn read_struct(f: &mut F, out: &mut T) -> Result<()> { + let out_slice = std::slice::from_raw_parts_mut(out as *mut T as *mut u8, mem::size_of::()); + f.read_exact(out_slice).map_err(|_| Error::ReadStruct)?; + Ok(()) +} + +/// Reads an array of structs from an input buffer. Returns a Vec of structs initialized with data +/// from the specified input. +/// This is unsafe because the structs are initialized to unverified data read from the input. +/// `read_struct_slice` should only be called for plain old data structs. It is not endian safe. +/// +/// # Arguments +/// +/// * `f` - The input to read from. Often this is a file. +/// * `len` - The number of structs to fill with data read from `f`. +pub unsafe fn read_struct_slice(f: &mut F, len: usize) -> Result> { + let mut out: Vec = Vec::with_capacity(len); + out.set_len(len); + let out_slice = std::slice::from_raw_parts_mut( + out.as_ptr() as *mut T as *mut u8, + mem::size_of::() * len, + ); + f.read_exact(out_slice).map_err(|_| Error::ReadStruct)?; + Ok(out) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::io::Cursor; + use std::mem; + + #[derive(Clone, Copy, Debug, Default, PartialEq)] + struct TestRead { + a: u64, + b: u8, + c: u8, + d: u8, + e: u8, + } + + #[test] + fn struct_basic_read() { + let orig = TestRead { + a: 0x7766554433221100, + b: 0x88, + c: 0x99, + d: 0xaa, + e: 0xbb, + }; + let source = unsafe { + // Don't worry it's a test + std::slice::from_raw_parts( + &orig as *const _ as *const u8, + std::mem::size_of::(), + ) + }; + assert_eq!(mem::size_of::(), mem::size_of_val(&source)); + let mut tr: TestRead = Default::default(); + unsafe { + read_struct(&mut Cursor::new(source), &mut tr).unwrap(); + } + assert_eq!(orig, tr); + } + + #[test] + fn struct_read_past_end() { + let orig = TestRead { + a: 0x7766554433221100, + b: 0x88, + c: 0x99, + d: 0xaa, + e: 0xbb, + }; + let source = unsafe { + // Don't worry it's a test + std::slice::from_raw_parts( + &orig as *const _ as *const u8, + std::mem::size_of::() - 1, + ) + }; + let mut tr: TestRead = Default::default(); + unsafe { + assert!(read_struct(&mut Cursor::new(source), &mut tr).is_err()); + format!("{:?}", read_struct(&mut Cursor::new(source), &mut tr)); + } + } + + #[test] + fn struct_slice_read() { + let orig = vec![ + TestRead { + a: 0x7766554433221100, + b: 0x88, + c: 0x99, + d: 0xaa, + e: 0xbb, + }, + TestRead { + a: 0x7867564534231201, + b: 0x02, + c: 0x13, + d: 0x24, + e: 0x35, + }, + TestRead { + a: 0x7a69584736251403, + b: 0x04, + c: 0x15, + d: 0x26, + e: 0x37, + }, + ]; + let source = unsafe { + // Don't worry it's a test + std::slice::from_raw_parts( + orig.as_ptr() as *const u8, + std::mem::size_of::() * 3, + ) + }; + + let tr: Vec = unsafe { read_struct_slice(&mut Cursor::new(source), 3).unwrap() }; + assert_eq!(orig, tr); + } +} diff --git a/src/loader/test_elf.bin b/src/loader/test_elf.bin new file mode 100644 index 0000000000000000000000000000000000000000..2e75f639f132360c251cf9d5a4d9df3ac0eefbe1 GIT binary patch literal 4424 zcmb<-^>JfjWMqH=CI&kO2u}bk|%wV;wAW^tHi~*tLq55Go zOdZG$HXv4jDpwGIFkm!4R3D6n>4OT7QllX-8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OB!ocPt{==Ey}Y8p-gg({ivJ~S?>zn=eEns^zh^1GzP$d!;E|e>ldq#t zo?n!cqR7R-pjVtxTvAk$n8cu0l3G#1pqG+Zl1PGmxRi1OC17I$5H-+&0Vo9@KY$v* rf@Y8)R6jFR95#*s8()BrBjC^vvKyusssv2wL+uww76h_E>X88eCQBm? literal 0 HcmV?d00001 From 49da615922ff5d569620b03d62400586954c389f Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Mon, 6 May 2019 20:06:29 +0800 Subject: [PATCH 02/27] Relicensing files according to the upstream discussion https://github.com/rust-vmm/community/issues/14 Add the license files meanwhile. Signed-off-by: Cathy Zhang --- Cargo.toml | 2 +- LICENSE-APACHE | 201 ++++++++++++++++++++++++++++++++++++++ LICENSE-BSD-3-Clause | 27 +++++ src/cmdline/mod.rs | 7 +- src/lib.rs | 5 +- src/loader/elf.rs | 5 +- src/loader/mod.rs | 5 +- src/loader/struct_util.rs | 5 +- 8 files changed, 245 insertions(+), 12 deletions(-) create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-BSD-3-Clause diff --git a/Cargo.toml b/Cargo.toml index b731b04e..3bde4e1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "linux-loader" version = "0.1.0" authors = ["Cathy Zhang "] edition = "2018" -license = "Apache-2.0" +license = "Apache-2.0 AND BSD-3-Clause" [dependencies.vm-memory] git = "https://github.com/rust-vmm/vm-memory" diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 00000000..6f756351 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE-BSD-3-Clause b/LICENSE-BSD-3-Clause new file mode 100644 index 00000000..8bafca30 --- /dev/null +++ b/LICENSE-BSD-3-Clause @@ -0,0 +1,27 @@ +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/cmdline/mod.rs b/src/cmdline/mod.rs index 3dd3c8bc..ed8dedb7 100644 --- a/src/cmdline/mod.rs +++ b/src/cmdline/mod.rs @@ -1,10 +1,11 @@ // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 // // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be -// found in the THIRD-PARTY file. - +// found in the LICENSE-BSD-3-Clause file. +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause +// //! Helper for creating valid kernel command line strings. use std::fmt; diff --git a/src/lib.rs b/src/lib.rs index f8aa7d49..01004ac8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,11 @@ // Copyright (c) 2019 Intel Corporation. All rights reserved. // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 // // Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// found in the LICENSE-BSD-3-Clause file. +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause pub mod cmdline; pub mod loader; diff --git a/src/loader/elf.rs b/src/loader/elf.rs index d0664b69..4d2769f7 100644 --- a/src/loader/elf.rs +++ b/src/loader/elf.rs @@ -1,9 +1,10 @@ // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 // // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be -// found in the THIRD-PARTY file. +// found in the LICENSE-BSD-3-Clause file. +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause /* * automatically generated by rust-bindgen diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 5f904279..066c0edb 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -1,10 +1,11 @@ // Copyright (c) 2019 Intel Corporation. All rights reserved. // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 // // Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// found in the LICENSE-BSD-3-Clause file. +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause extern crate vm_memory; diff --git a/src/loader/struct_util.rs b/src/loader/struct_util.rs index 08f7fe6e..8454b4de 100644 --- a/src/loader/struct_util.rs +++ b/src/loader/struct_util.rs @@ -1,10 +1,11 @@ // Copyright (c) 2019 Intel Corporation. All rights reserved. // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 // // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be -// found in the THIRD-PARTY file. +// found in the LICENSE-BSD-3-Clause file. +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause use std; use std::io::Read; From e983c6ad8ec7484a8cbe0bc8022d7a4dde540e9b Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Thu, 18 Apr 2019 13:03:18 +0800 Subject: [PATCH 03/27] loader: Define a kernel loader trait Convert the ELF loader to it, the bzImage support will also implement that trait. Having a trait allows us to support further kernel image formats in a common way. Signed-off-by: Cathy Zhang --- src/loader/mod.rs | 88 +++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 066c0edb..57a36f3c 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -81,9 +81,29 @@ impl Display for Error { } } -pub struct ElfLoader; +/// * `kernel_load` - The actual `guest_mem` address where kernel image is loaded start. +/// * `kernel_end` - The offset of `guest_mem` where kernel image load is loaded finish, return +/// in case of loading initrd adjacent to kernel image. +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct KernelLoaderResult { + pub kernel_load: GuestAddress, + pub kernel_end: GuestUsize, +} + +pub trait KernelLoader { + fn load( + guest_mem: &GuestMemoryMmap, + kernel_start: Option, + kernel_image: &mut F, + lowest_kernel_start: Option, + ) -> Result<(KernelLoaderResult)> + where + F: Read + Seek; +} + +pub struct Elf; -impl ElfLoader { +impl KernelLoader for Elf { /// Loads a kernel from a vmlinux elf image to a slice /// /// kernel is loaded into guest memory at offset phdr.p_paddr specified by elf image. @@ -96,15 +116,13 @@ impl ElfLoader { /// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it. /// /// # Returns - /// * GuestAddress - GuestAddress where kernel is loaded. - /// * usize - the length of kernel image. Return this in case of other part - /// like initrd will be loaded adjacent to the kernel part. - pub fn load_kernel( + /// * KernelLoaderResult + fn load( guest_mem: &GuestMemoryMmap, kernel_start: Option, kernel_image: &mut F, lowest_kernel_start: Option, - ) -> Result<(GuestAddress, GuestUsize)> + ) -> Result<(KernelLoaderResult)> where F: Read + Seek, { @@ -140,8 +158,10 @@ impl ElfLoader { return Err(Error::InvalidEntryAddress); } } + + let mut loader_result: KernelLoaderResult = Default::default(); // where the kernel will be start loaded. - let kernel_loaded_addr = match kernel_start { + loader_result.kernel_load = match kernel_start { Some(start) => GuestAddress(start.raw_value() + (ehdr.e_entry as u64)), None => GuestAddress(ehdr.e_entry as u64), }; @@ -155,8 +175,6 @@ impl ElfLoader { .map_err(|_| Error::ReadProgramHeader)? }; - let mut kernel_end: GuestUsize = 0; - // Read in each section pointed to by the program headers. for phdr in &phdrs { if phdr.p_type != elf::PT_LOAD || phdr.p_filesz == 0 { @@ -180,10 +198,11 @@ impl ElfLoader { .read_exact_from(mem_offset, kernel_image, phdr.p_filesz as usize) .map_err(|_| Error::ReadKernelImage)?; - kernel_end = mem_offset.raw_value() as GuestUsize + phdr.p_memsz as GuestUsize; + loader_result.kernel_end = + mem_offset.raw_value() as GuestUsize + phdr.p_memsz as GuestUsize; } - Ok((kernel_loaded_addr, kernel_end)) + Ok(loader_result) } } @@ -221,8 +240,8 @@ pub fn load_cmdline( #[cfg(test)] mod test { use super::*; - use vm_memory::{Address, GuestAddress, GuestMemoryMmap}; use std::io::Cursor; + use vm_memory::{Address, GuestAddress, GuestMemoryMmap}; const MEM_SIZE: u64 = 0x1000000; @@ -243,36 +262,45 @@ mod test { let image = make_elf_bin(); let kernel_addr = GuestAddress(0x200000); let mut lowest_kernel_start = GuestAddress(0x0); - - let mut x = ElfLoader::load_kernel( + let mut loader_result = Elf::load( &gm, Some(kernel_addr), &mut Cursor::new(&image), Some(lowest_kernel_start), + ) + .unwrap(); + println!( + "load elf at address {:8x} \n", + loader_result.kernel_load.raw_value() ); - assert_eq!(x.is_ok(), true); - let mut entry_addr = x.unwrap().0; - println!("load elf at address {:8x} \n", entry_addr.raw_value()); - x = ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&image), None); - assert_eq!(x.is_ok(), true); - entry_addr = x.unwrap().0; - println!("load elf at address {:8x} \n", entry_addr.raw_value()); + loader_result = Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&image), None).unwrap(); + println!( + "load elf at address {:8x} \n", + loader_result.kernel_load.raw_value() + ); - x = ElfLoader::load_kernel( + loader_result = Elf::load( &gm, None, &mut Cursor::new(&image), Some(lowest_kernel_start), + ) + .unwrap(); + println!( + "load elf at address {:8x} \n", + loader_result.kernel_load.raw_value() ); - assert_eq!(x.is_ok(), true); - entry_addr = x.unwrap().0; - println!("load elf at address {:8x} \n", entry_addr.raw_value()); lowest_kernel_start = GuestAddress(0xa00000); assert_eq!( Err(Error::InvalidEntryAddress), - ElfLoader::load_kernel(&gm, None, &mut Cursor::new(&image), Some(lowest_kernel_start)) + Elf::load( + &gm, + None, + &mut Cursor::new(&image), + Some(lowest_kernel_start) + ) ); } @@ -326,7 +354,7 @@ mod test { bad_image[0x1] = 0x33; assert_eq!( Err(Error::InvalidElfMagicNumber), - ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) + Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) ); } @@ -339,7 +367,7 @@ mod test { bad_image[0x5] = 2; assert_eq!( Err(Error::BigEndianElfOnLittle), - ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) + Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) ); } @@ -352,7 +380,7 @@ mod test { bad_image[0x20] = 0x10; assert_eq!( Err(Error::InvalidProgramHeaderOffset), - ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) + Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None) ); } } From 02a04c087f2d8ab6c5263cad3bf064f147541bf4 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Thu, 18 Apr 2019 23:37:27 +0800 Subject: [PATCH 04/27] loader: Add bzImage support Reimplement KernelLoader trait against structure BzImage to add bzImage loader support. Signed-off-by: Cathy Zhang --- DESIGN.md | 54 + README.md | 25 +- src/loader/bootparam.rs | 3870 +++++++++++++++++++++++++++++++++++++++ src/loader/mod.rs | 192 ++ 4 files changed, 4137 insertions(+), 4 deletions(-) create mode 100644 src/loader/bootparam.rs diff --git a/DESIGN.md b/DESIGN.md index b448900c..c6203ae2 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -35,4 +35,58 @@ be used to fill boot parameters, vmm is totally responsible for the construction - GDT must be configured and loaded +# bzImage + +The boot process is also explained from the following two sides. + +## Loader side + +### What will be returned from loader + +bzImage includes two parts, the setup and the compressed kernel. The compressed +kernel part will be loaded into guest memory, and the following three parts +will be returned to the VMM by the loader. + +- The start address of loaded kernel + +- The offset of memory where kernel is end of loading + +- The setup header begin at the offset 0x01f1 of bzImage, this one is an extra + compared to the return of ELF loader. + +### Where kernel is loaded + +The same as ELF image loader, there are two ways for deciding where the +compressed kernel will be loaded. + +- VMM specify where to load kernel image. + +- Load into code32_start (Boot load address) by default. + +### Additional checking + +As what the boot protocol said, the kernel is a bzImage kernel if the +protocol >= 2.00 and the 0x01 bit(LOAD_HIGH) is the loadflags field is set. Add +this checking to validate the bzImage. + +## VMM side + +### Construct zero page + +While vmm build "zero page" with e820 table and other stuff, bzImage loader will +return the setup header to fill the boot parameters. Meanwhile, +setup_header.init_size is a must to be filled into zero page, which will be used +during head_64.S boot process. + +### Configure vCPU + +- RIP, the start address of loaded 64-bit kernel returned from loader + 0x200. + Regarding to the 64-bit boot protocol, kernel is started by jumping to the + 64-bit kernel entry point, which is the start address of loaded 64-bit kernel + plus 0x200. + +- 64 bit mode with paging enabled + +- GDT must be configured and loaded + diff --git a/README.md b/README.md index 28174678..4972ae5e 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,29 @@ cd linux-loader cargo build ``` -## How to run test +## How to run test for Elf loader +```shell +# Assuming your linux-loader is under $HOME +$ cd linux-loader +$ cargo test +$ cargo test -- --nocapture ``` -cd linux-loader -cargo test -cargo test -- --nocapture + +## How to run test for bzImage loader + +As we don't want to distribute an entire kernel bzImage, the `load_bzImage` test is ignored by +default. In order to test the bzImage support, one needs to locally build a bzImage, copy it +to the `src/loader` directory and run the ignored test: + +```shell +# Assuming your linux-loader and linux-stable are both under $LINUX_LOADER +$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $LINUX_LOADER/linux-stable +$ cd linux-stable +$ make bzImage +$ cp linux-stable/arch/x86/boot/bzImage $LINUX_LOADER/linux-loader/src/loader/ +$ cd $LINUX_LOADER/linux-loader +$ cargo test -- --ignored ``` ## Platform Support diff --git a/src/loader/bootparam.rs b/src/loader/bootparam.rs new file mode 100644 index 00000000..f19663ff --- /dev/null +++ b/src/loader/bootparam.rs @@ -0,0 +1,3870 @@ +// Copyright (c) 2019 Intel Corporation. All rights reserved. +// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// +// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE-BSD-3-Clause file. +// +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause + +/* + * automatically generated by rust-bindgen + * From upstream linux bootparam.h at commit: + * 806276b7f07a39a1cc3f38bb1ef5c573d4594a38 + */ + +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData); +impl __IncompleteArrayField { + #[inline] + pub fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ptr(&self) -> *const T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut_ptr(&mut self) -> *mut T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +impl ::std::clone::Clone for __IncompleteArrayField { + #[inline] + fn clone(&self) -> Self { + Self::new() + } +} +impl ::std::marker::Copy for __IncompleteArrayField {} +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[inline] + pub fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + Self::new() + } +} +impl ::std::marker::Copy for __BindgenUnionField {} +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +pub const SETUP_NONE: ::std::os::raw::c_uint = 0; +pub const SETUP_E820_EXT: ::std::os::raw::c_uint = 1; +pub const SETUP_DTB: ::std::os::raw::c_uint = 2; +pub const SETUP_PCI: ::std::os::raw::c_uint = 3; +pub const SETUP_EFI: ::std::os::raw::c_uint = 4; +pub const RAMDISK_IMAGE_START_MASK: ::std::os::raw::c_uint = 2047; +pub const RAMDISK_PROMPT_FLAG: ::std::os::raw::c_uint = 32768; +pub const RAMDISK_LOAD_FLAG: ::std::os::raw::c_uint = 16384; +pub const LOADED_HIGH: ::std::os::raw::c_uint = 1; +pub const QUIET_FLAG: ::std::os::raw::c_uint = 32; +pub const KEEP_SEGMENTS: ::std::os::raw::c_uint = 64; +pub const CAN_USE_HEAP: ::std::os::raw::c_uint = 128; +pub const XLF_KERNEL_64: ::std::os::raw::c_uint = 1; +pub const XLF_CAN_BE_LOADED_ABOVE_4G: ::std::os::raw::c_uint = 2; +pub const XLF_EFI_HANDOVER_32: ::std::os::raw::c_uint = 4; +pub const XLF_EFI_HANDOVER_64: ::std::os::raw::c_uint = 8; +pub const XLF_EFI_KEXEC: ::std::os::raw::c_uint = 16; +pub const __BITS_PER_LONG: ::std::os::raw::c_uint = 64; +pub const __FD_SETSIZE: ::std::os::raw::c_uint = 1024; +pub const VIDEO_TYPE_MDA: ::std::os::raw::c_uint = 16; +pub const VIDEO_TYPE_CGA: ::std::os::raw::c_uint = 17; +pub const VIDEO_TYPE_EGAM: ::std::os::raw::c_uint = 32; +pub const VIDEO_TYPE_EGAC: ::std::os::raw::c_uint = 33; +pub const VIDEO_TYPE_VGAC: ::std::os::raw::c_uint = 34; +pub const VIDEO_TYPE_VLFB: ::std::os::raw::c_uint = 35; +pub const VIDEO_TYPE_PICA_S3: ::std::os::raw::c_uint = 48; +pub const VIDEO_TYPE_MIPS_G364: ::std::os::raw::c_uint = 49; +pub const VIDEO_TYPE_SGI: ::std::os::raw::c_uint = 51; +pub const VIDEO_TYPE_TGAC: ::std::os::raw::c_uint = 64; +pub const VIDEO_TYPE_SUN: ::std::os::raw::c_uint = 80; +pub const VIDEO_TYPE_SUNPCI: ::std::os::raw::c_uint = 81; +pub const VIDEO_TYPE_PMAC: ::std::os::raw::c_uint = 96; +pub const VIDEO_TYPE_EFI: ::std::os::raw::c_uint = 112; +pub const VIDEO_FLAGS_NOCURSOR: ::std::os::raw::c_uint = 1; +pub const VIDEO_CAPABILITY_SKIP_QUIRKS: ::std::os::raw::c_uint = 1; +pub const APM_STATE_READY: ::std::os::raw::c_uint = 0; +pub const APM_STATE_STANDBY: ::std::os::raw::c_uint = 1; +pub const APM_STATE_SUSPEND: ::std::os::raw::c_uint = 2; +pub const APM_STATE_OFF: ::std::os::raw::c_uint = 3; +pub const APM_STATE_BUSY: ::std::os::raw::c_uint = 4; +pub const APM_STATE_REJECT: ::std::os::raw::c_uint = 5; +pub const APM_STATE_OEM_SYS: ::std::os::raw::c_uint = 32; +pub const APM_STATE_OEM_DEV: ::std::os::raw::c_uint = 64; +pub const APM_STATE_DISABLE: ::std::os::raw::c_uint = 0; +pub const APM_STATE_ENABLE: ::std::os::raw::c_uint = 1; +pub const APM_STATE_DISENGAGE: ::std::os::raw::c_uint = 0; +pub const APM_STATE_ENGAGE: ::std::os::raw::c_uint = 1; +pub const APM_SYS_STANDBY: ::std::os::raw::c_uint = 1; +pub const APM_SYS_SUSPEND: ::std::os::raw::c_uint = 2; +pub const APM_NORMAL_RESUME: ::std::os::raw::c_uint = 3; +pub const APM_CRITICAL_RESUME: ::std::os::raw::c_uint = 4; +pub const APM_LOW_BATTERY: ::std::os::raw::c_uint = 5; +pub const APM_POWER_STATUS_CHANGE: ::std::os::raw::c_uint = 6; +pub const APM_UPDATE_TIME: ::std::os::raw::c_uint = 7; +pub const APM_CRITICAL_SUSPEND: ::std::os::raw::c_uint = 8; +pub const APM_USER_STANDBY: ::std::os::raw::c_uint = 9; +pub const APM_USER_SUSPEND: ::std::os::raw::c_uint = 10; +pub const APM_STANDBY_RESUME: ::std::os::raw::c_uint = 11; +pub const APM_CAPABILITY_CHANGE: ::std::os::raw::c_uint = 12; +pub const APM_USER_HIBERNATION: ::std::os::raw::c_uint = 13; +pub const APM_HIBERNATION_RESUME: ::std::os::raw::c_uint = 14; +pub const APM_SUCCESS: ::std::os::raw::c_uint = 0; +pub const APM_DISABLED: ::std::os::raw::c_uint = 1; +pub const APM_CONNECTED: ::std::os::raw::c_uint = 2; +pub const APM_NOT_CONNECTED: ::std::os::raw::c_uint = 3; +pub const APM_16_CONNECTED: ::std::os::raw::c_uint = 5; +pub const APM_16_UNSUPPORTED: ::std::os::raw::c_uint = 6; +pub const APM_32_CONNECTED: ::std::os::raw::c_uint = 7; +pub const APM_32_UNSUPPORTED: ::std::os::raw::c_uint = 8; +pub const APM_BAD_DEVICE: ::std::os::raw::c_uint = 9; +pub const APM_BAD_PARAM: ::std::os::raw::c_uint = 10; +pub const APM_NOT_ENGAGED: ::std::os::raw::c_uint = 11; +pub const APM_BAD_FUNCTION: ::std::os::raw::c_uint = 12; +pub const APM_RESUME_DISABLED: ::std::os::raw::c_uint = 13; +pub const APM_NO_ERROR: ::std::os::raw::c_uint = 83; +pub const APM_BAD_STATE: ::std::os::raw::c_uint = 96; +pub const APM_NO_EVENTS: ::std::os::raw::c_uint = 128; +pub const APM_NOT_PRESENT: ::std::os::raw::c_uint = 134; +pub const APM_DEVICE_BIOS: ::std::os::raw::c_uint = 0; +pub const APM_DEVICE_ALL: ::std::os::raw::c_uint = 1; +pub const APM_DEVICE_DISPLAY: ::std::os::raw::c_uint = 256; +pub const APM_DEVICE_STORAGE: ::std::os::raw::c_uint = 512; +pub const APM_DEVICE_PARALLEL: ::std::os::raw::c_uint = 768; +pub const APM_DEVICE_SERIAL: ::std::os::raw::c_uint = 1024; +pub const APM_DEVICE_NETWORK: ::std::os::raw::c_uint = 1280; +pub const APM_DEVICE_PCMCIA: ::std::os::raw::c_uint = 1536; +pub const APM_DEVICE_BATTERY: ::std::os::raw::c_uint = 32768; +pub const APM_DEVICE_OEM: ::std::os::raw::c_uint = 57344; +pub const APM_DEVICE_OLD_ALL: ::std::os::raw::c_uint = 65535; +pub const APM_DEVICE_CLASS: ::std::os::raw::c_uint = 255; +pub const APM_DEVICE_MASK: ::std::os::raw::c_uint = 65280; +pub const APM_MAX_BATTERIES: ::std::os::raw::c_uint = 2; +pub const APM_CAP_GLOBAL_STANDBY: ::std::os::raw::c_uint = 1; +pub const APM_CAP_GLOBAL_SUSPEND: ::std::os::raw::c_uint = 2; +pub const APM_CAP_RESUME_STANDBY_TIMER: ::std::os::raw::c_uint = 4; +pub const APM_CAP_RESUME_SUSPEND_TIMER: ::std::os::raw::c_uint = 8; +pub const APM_CAP_RESUME_STANDBY_RING: ::std::os::raw::c_uint = 16; +pub const APM_CAP_RESUME_SUSPEND_RING: ::std::os::raw::c_uint = 32; +pub const APM_CAP_RESUME_STANDBY_PCMCIA: ::std::os::raw::c_uint = 64; +pub const APM_CAP_RESUME_SUSPEND_PCMCIA: ::std::os::raw::c_uint = 128; +pub const _IOC_NRBITS: ::std::os::raw::c_uint = 8; +pub const _IOC_TYPEBITS: ::std::os::raw::c_uint = 8; +pub const _IOC_SIZEBITS: ::std::os::raw::c_uint = 14; +pub const _IOC_DIRBITS: ::std::os::raw::c_uint = 2; +pub const _IOC_NRMASK: ::std::os::raw::c_uint = 255; +pub const _IOC_TYPEMASK: ::std::os::raw::c_uint = 255; +pub const _IOC_SIZEMASK: ::std::os::raw::c_uint = 16383; +pub const _IOC_DIRMASK: ::std::os::raw::c_uint = 3; +pub const _IOC_NRSHIFT: ::std::os::raw::c_uint = 0; +pub const _IOC_TYPESHIFT: ::std::os::raw::c_uint = 8; +pub const _IOC_SIZESHIFT: ::std::os::raw::c_uint = 16; +pub const _IOC_DIRSHIFT: ::std::os::raw::c_uint = 30; +pub const _IOC_NONE: ::std::os::raw::c_uint = 0; +pub const _IOC_WRITE: ::std::os::raw::c_uint = 1; +pub const _IOC_READ: ::std::os::raw::c_uint = 2; +pub const IOC_IN: ::std::os::raw::c_uint = 1073741824; +pub const IOC_OUT: ::std::os::raw::c_uint = 2147483648; +pub const IOC_INOUT: ::std::os::raw::c_uint = 3221225472; +pub const IOCSIZE_MASK: ::std::os::raw::c_uint = 1073676288; +pub const IOCSIZE_SHIFT: ::std::os::raw::c_uint = 16; +pub const EDDNR: ::std::os::raw::c_uint = 489; +pub const EDDBUF: ::std::os::raw::c_uint = 3328; +pub const EDDMAXNR: ::std::os::raw::c_uint = 6; +pub const EDDEXTSIZE: ::std::os::raw::c_uint = 8; +pub const EDDPARMSIZE: ::std::os::raw::c_uint = 74; +pub const CHECKEXTENSIONSPRESENT: ::std::os::raw::c_uint = 65; +pub const GETDEVICEPARAMETERS: ::std::os::raw::c_uint = 72; +pub const LEGACYGETDEVICEPARAMETERS: ::std::os::raw::c_uint = 8; +pub const EDDMAGIC1: ::std::os::raw::c_uint = 21930; +pub const EDDMAGIC2: ::std::os::raw::c_uint = 43605; +pub const READ_SECTORS: ::std::os::raw::c_uint = 2; +pub const EDD_MBR_SIG_OFFSET: ::std::os::raw::c_uint = 440; +pub const EDD_MBR_SIG_BUF: ::std::os::raw::c_uint = 656; +pub const EDD_MBR_SIG_MAX: ::std::os::raw::c_uint = 16; +pub const EDD_MBR_SIG_NR_BUF: ::std::os::raw::c_uint = 490; +pub const EDD_EXT_FIXED_DISK_ACCESS: ::std::os::raw::c_uint = 1; +pub const EDD_EXT_DEVICE_LOCKING_AND_EJECTING: ::std::os::raw::c_uint = 2; +pub const EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT: ::std::os::raw::c_uint = 4; +pub const EDD_EXT_64BIT_EXTENSIONS: ::std::os::raw::c_uint = 8; +pub const EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT: ::std::os::raw::c_uint = 1; +pub const EDD_INFO_GEOMETRY_VALID: ::std::os::raw::c_uint = 2; +pub const EDD_INFO_REMOVABLE: ::std::os::raw::c_uint = 4; +pub const EDD_INFO_WRITE_VERIFY: ::std::os::raw::c_uint = 8; +pub const EDD_INFO_MEDIA_CHANGE_NOTIFICATION: ::std::os::raw::c_uint = 16; +pub const EDD_INFO_LOCKABLE: ::std::os::raw::c_uint = 32; +pub const EDD_INFO_NO_MEDIA_PRESENT: ::std::os::raw::c_uint = 64; +pub const EDD_INFO_USE_INT13_FN50: ::std::os::raw::c_uint = 128; +pub const E820MAP: ::std::os::raw::c_uint = 720; +pub const E820MAX: ::std::os::raw::c_uint = 128; +pub const E820_X_MAX: ::std::os::raw::c_uint = 128; +pub const E820NR: ::std::os::raw::c_uint = 488; +pub const E820_RAM: ::std::os::raw::c_uint = 1; +pub const E820_RESERVED: ::std::os::raw::c_uint = 2; +pub const E820_ACPI: ::std::os::raw::c_uint = 3; +pub const E820_NVS: ::std::os::raw::c_uint = 4; +pub const E820_UNUSABLE: ::std::os::raw::c_uint = 5; +pub const E820_RESERVED_KERN: ::std::os::raw::c_uint = 128; +pub const ISA_START_ADDRESS: ::std::os::raw::c_uint = 655360; +pub const ISA_END_ADDRESS: ::std::os::raw::c_uint = 1048576; +pub const BIOS_BEGIN: ::std::os::raw::c_uint = 655360; +pub const BIOS_END: ::std::os::raw::c_uint = 1048576; +pub const BIOS_ROM_BASE: ::std::os::raw::c_uint = 4292870144; +pub const BIOS_ROM_END: ::std::os::raw::c_uint = 4294967295; +pub type __s8 = ::std::os::raw::c_schar; +pub type __u8 = ::std::os::raw::c_uchar; +pub type __s16 = ::std::os::raw::c_short; +pub type __u16 = ::std::os::raw::c_ushort; +pub type __s32 = ::std::os::raw::c_int; +pub type __u32 = ::std::os::raw::c_uint; +pub type __s64 = ::std::os::raw::c_longlong; +pub type __u64 = ::std::os::raw::c_ulonglong; +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct __kernel_fd_set { + pub fds_bits: [::std::os::raw::c_ulong; 16usize], +} +#[test] +fn bindgen_test_layout___kernel_fd_set() { + assert_eq!( + ::std::mem::size_of::<__kernel_fd_set>(), + 128usize, + concat!("Size of: ", stringify!(__kernel_fd_set)) + ); + assert_eq!( + ::std::mem::align_of::<__kernel_fd_set>(), + 8usize, + concat!("Alignment of ", stringify!(__kernel_fd_set)) + ); + assert_eq!( + unsafe { &(*(0 as *const __kernel_fd_set)).fds_bits as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(__kernel_fd_set), + "::", + stringify!(fds_bits) + ) + ); +} +impl Clone for __kernel_fd_set { + fn clone(&self) -> Self { + *self + } +} +pub type __kernel_sighandler_t = + ::std::option::Option; +pub type __kernel_key_t = ::std::os::raw::c_int; +pub type __kernel_mqd_t = ::std::os::raw::c_int; +pub type __kernel_old_uid_t = ::std::os::raw::c_ushort; +pub type __kernel_old_gid_t = ::std::os::raw::c_ushort; +pub type __kernel_old_dev_t = ::std::os::raw::c_ulong; +pub type __kernel_long_t = ::std::os::raw::c_long; +pub type __kernel_ulong_t = ::std::os::raw::c_ulong; +pub type __kernel_ino_t = __kernel_ulong_t; +pub type __kernel_mode_t = ::std::os::raw::c_uint; +pub type __kernel_pid_t = ::std::os::raw::c_int; +pub type __kernel_ipc_pid_t = ::std::os::raw::c_int; +pub type __kernel_uid_t = ::std::os::raw::c_uint; +pub type __kernel_gid_t = ::std::os::raw::c_uint; +pub type __kernel_suseconds_t = __kernel_long_t; +pub type __kernel_daddr_t = ::std::os::raw::c_int; +pub type __kernel_uid32_t = ::std::os::raw::c_uint; +pub type __kernel_gid32_t = ::std::os::raw::c_uint; +pub type __kernel_size_t = __kernel_ulong_t; +pub type __kernel_ssize_t = __kernel_long_t; +pub type __kernel_ptrdiff_t = __kernel_long_t; +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct __kernel_fsid_t { + pub val: [::std::os::raw::c_int; 2usize], +} +#[test] +fn bindgen_test_layout___kernel_fsid_t() { + assert_eq!( + ::std::mem::size_of::<__kernel_fsid_t>(), + 8usize, + concat!("Size of: ", stringify!(__kernel_fsid_t)) + ); + assert_eq!( + ::std::mem::align_of::<__kernel_fsid_t>(), + 4usize, + concat!("Alignment of ", stringify!(__kernel_fsid_t)) + ); + assert_eq!( + unsafe { &(*(0 as *const __kernel_fsid_t)).val as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(__kernel_fsid_t), + "::", + stringify!(val) + ) + ); +} +impl Clone for __kernel_fsid_t { + fn clone(&self) -> Self { + *self + } +} +pub type __kernel_off_t = __kernel_long_t; +pub type __kernel_loff_t = ::std::os::raw::c_longlong; +pub type __kernel_time_t = __kernel_long_t; +pub type __kernel_clock_t = __kernel_long_t; +pub type __kernel_timer_t = ::std::os::raw::c_int; +pub type __kernel_clockid_t = ::std::os::raw::c_int; +pub type __kernel_caddr_t = *mut ::std::os::raw::c_char; +pub type __kernel_uid16_t = ::std::os::raw::c_ushort; +pub type __kernel_gid16_t = ::std::os::raw::c_ushort; +pub type __le16 = __u16; +pub type __be16 = __u16; +pub type __le32 = __u32; +pub type __be32 = __u32; +pub type __le64 = __u64; +pub type __be64 = __u64; +pub type __sum16 = __u16; +pub type __wsum = __u32; +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct screen_info { + pub orig_x: __u8, + pub orig_y: __u8, + pub ext_mem_k: __u16, + pub orig_video_page: __u16, + pub orig_video_mode: __u8, + pub orig_video_cols: __u8, + pub flags: __u8, + pub unused2: __u8, + pub orig_video_ega_bx: __u16, + pub unused3: __u16, + pub orig_video_lines: __u8, + pub orig_video_isVGA: __u8, + pub orig_video_points: __u16, + pub lfb_width: __u16, + pub lfb_height: __u16, + pub lfb_depth: __u16, + pub lfb_base: __u32, + pub lfb_size: __u32, + pub cl_magic: __u16, + pub cl_offset: __u16, + pub lfb_linelength: __u16, + pub red_size: __u8, + pub red_pos: __u8, + pub green_size: __u8, + pub green_pos: __u8, + pub blue_size: __u8, + pub blue_pos: __u8, + pub rsvd_size: __u8, + pub rsvd_pos: __u8, + pub vesapm_seg: __u16, + pub vesapm_off: __u16, + pub pages: __u16, + pub vesa_attributes: __u16, + pub capabilities: __u32, + pub _reserved: [__u8; 6usize], +} +#[test] +fn bindgen_test_layout_screen_info() { + assert_eq!( + ::std::mem::size_of::(), + 64usize, + concat!("Size of: ", stringify!(screen_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(screen_info)) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_x as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_x) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_y as *const _ as usize }, + 1usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_y) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).ext_mem_k as *const _ as usize }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(ext_mem_k) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_video_page as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_video_page) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_video_mode as *const _ as usize }, + 6usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_video_mode) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_video_cols as *const _ as usize }, + 7usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_video_cols) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).flags as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).unused2 as *const _ as usize }, + 9usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(unused2) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_video_ega_bx as *const _ as usize }, + 10usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_video_ega_bx) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).unused3 as *const _ as usize }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(unused3) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_video_lines as *const _ as usize }, + 14usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_video_lines) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_video_isVGA as *const _ as usize }, + 15usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_video_isVGA) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).orig_video_points as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(orig_video_points) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).lfb_width as *const _ as usize }, + 18usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(lfb_width) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).lfb_height as *const _ as usize }, + 20usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(lfb_height) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).lfb_depth as *const _ as usize }, + 22usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(lfb_depth) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).lfb_base as *const _ as usize }, + 24usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(lfb_base) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).lfb_size as *const _ as usize }, + 28usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(lfb_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).cl_magic as *const _ as usize }, + 32usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(cl_magic) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).cl_offset as *const _ as usize }, + 34usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(cl_offset) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).lfb_linelength as *const _ as usize }, + 36usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(lfb_linelength) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).red_size as *const _ as usize }, + 38usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(red_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).red_pos as *const _ as usize }, + 39usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(red_pos) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).green_size as *const _ as usize }, + 40usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(green_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).green_pos as *const _ as usize }, + 41usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(green_pos) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).blue_size as *const _ as usize }, + 42usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(blue_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).blue_pos as *const _ as usize }, + 43usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(blue_pos) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).rsvd_size as *const _ as usize }, + 44usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(rsvd_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).rsvd_pos as *const _ as usize }, + 45usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(rsvd_pos) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).vesapm_seg as *const _ as usize }, + 46usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(vesapm_seg) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).vesapm_off as *const _ as usize }, + 48usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(vesapm_off) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).pages as *const _ as usize }, + 50usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(pages) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).vesa_attributes as *const _ as usize }, + 52usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(vesa_attributes) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info)).capabilities as *const _ as usize }, + 54usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(capabilities) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const screen_info))._reserved as *const _ as usize }, + 58usize, + concat!( + "Alignment of field: ", + stringify!(screen_info), + "::", + stringify!(_reserved) + ) + ); +} +impl Clone for screen_info { + fn clone(&self) -> Self { + *self + } +} +pub type apm_event_t = ::std::os::raw::c_ushort; +pub type apm_eventinfo_t = ::std::os::raw::c_ushort; +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct apm_bios_info { + pub version: __u16, + pub cseg: __u16, + pub offset: __u32, + pub cseg_16: __u16, + pub dseg: __u16, + pub flags: __u16, + pub cseg_len: __u16, + pub cseg_16_len: __u16, + pub dseg_len: __u16, +} +#[test] +fn bindgen_test_layout_apm_bios_info() { + assert_eq!( + ::std::mem::size_of::(), + 20usize, + concat!("Size of: ", stringify!(apm_bios_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(apm_bios_info)) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).version as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(version) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).cseg as *const _ as usize }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(cseg) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).offset as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(offset) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).cseg_16 as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(cseg_16) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).dseg as *const _ as usize }, + 10usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(dseg) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).flags as *const _ as usize }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).cseg_len as *const _ as usize }, + 14usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(cseg_len) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).cseg_16_len as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(cseg_16_len) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const apm_bios_info)).dseg_len as *const _ as usize }, + 18usize, + concat!( + "Alignment of field: ", + stringify!(apm_bios_info), + "::", + stringify!(dseg_len) + ) + ); +} +impl Clone for apm_bios_info { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params { + pub length: __u16, + pub info_flags: __u16, + pub num_default_cylinders: __u32, + pub num_default_heads: __u32, + pub sectors_per_track: __u32, + pub number_of_sectors: __u64, + pub bytes_per_sector: __u16, + pub dpte_ptr: __u32, + pub key: __u16, + pub device_path_info_length: __u8, + pub reserved2: __u8, + pub reserved3: __u16, + pub host_bus_type: [__u8; 4usize], + pub interface_type: [__u8; 8usize], + pub interface_path: edd_device_params__bindgen_ty_1, + pub device_path: edd_device_params__bindgen_ty_2, + pub reserved4: __u8, + pub checksum: __u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_1 { + pub isa: __BindgenUnionField, + pub pci: __BindgenUnionField, + pub ibnd: __BindgenUnionField, + pub xprs: __BindgenUnionField, + pub htpt: __BindgenUnionField, + pub unknown: __BindgenUnionField, + pub bindgen_union_field: [u8; 8usize], +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_1__bindgen_ty_1 { + pub base_address: __u16, + pub reserved1: __u16, + pub reserved2: __u32, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_1__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_1) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_1)).base_address as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_1), + "::", + stringify!(base_address) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_1)).reserved1 as *const _ + as usize + }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_1), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_1)).reserved2 as *const _ + as usize + }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_1), + "::", + stringify!(reserved2) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_1__bindgen_ty_1 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_1__bindgen_ty_2 { + pub bus: __u8, + pub slot: __u8, + pub function: __u8, + pub channel: __u8, + pub reserved: __u32, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_1__bindgen_ty_2() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_2) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_2) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_2)).bus as *const _ as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_2), + "::", + stringify!(bus) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_2)).slot as *const _ + as usize + }, + 1usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_2), + "::", + stringify!(slot) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_2)).function as *const _ + as usize + }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_2), + "::", + stringify!(function) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_2)).channel as *const _ + as usize + }, + 3usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_2), + "::", + stringify!(channel) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_2)).reserved as *const _ + as usize + }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_2), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_1__bindgen_ty_2 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_1__bindgen_ty_3 { + pub reserved: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_1__bindgen_ty_3() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_3) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_3) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_3)).reserved as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_3), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_1__bindgen_ty_3 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_1__bindgen_ty_4 { + pub reserved: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_1__bindgen_ty_4() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_4) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_4) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_4)).reserved as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_4), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_1__bindgen_ty_4 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_1__bindgen_ty_5 { + pub reserved: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_1__bindgen_ty_5() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_5) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_5) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_5)).reserved as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_5), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_1__bindgen_ty_5 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_1__bindgen_ty_6 { + pub reserved: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_1__bindgen_ty_6() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_6) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_6) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_1__bindgen_ty_6)).reserved as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1__bindgen_ty_6), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_1__bindgen_ty_6 { + fn clone(&self) -> Self { + *self + } +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(edd_device_params__bindgen_ty_1)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(edd_device_params__bindgen_ty_1)) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_1)).isa as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1), + "::", + stringify!(isa) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_1)).pci as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1), + "::", + stringify!(pci) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_1)).ibnd as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1), + "::", + stringify!(ibnd) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_1)).xprs as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1), + "::", + stringify!(xprs) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_1)).htpt as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1), + "::", + stringify!(htpt) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_1)).unknown as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_1), + "::", + stringify!(unknown) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_1 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2 { + pub ata: __BindgenUnionField, + pub atapi: __BindgenUnionField, + pub scsi: __BindgenUnionField, + pub usb: __BindgenUnionField, + pub i1394: __BindgenUnionField, + pub fibre: __BindgenUnionField, + pub i2o: __BindgenUnionField, + pub raid: __BindgenUnionField, + pub sata: __BindgenUnionField, + pub unknown: __BindgenUnionField, + pub bindgen_union_field: [u8; 16usize], +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_1 { + pub device: __u8, + pub reserved1: __u8, + pub reserved2: __u16, + pub reserved3: __u32, + pub reserved4: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_1) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_1)).device as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_1), + "::", + stringify!(device) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_1)).reserved1 as *const _ + as usize + }, + 1usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_1), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_1)).reserved2 as *const _ + as usize + }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_1), + "::", + stringify!(reserved2) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_1)).reserved3 as *const _ + as usize + }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_1), + "::", + stringify!(reserved3) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_1)).reserved4 as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_1), + "::", + stringify!(reserved4) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_1 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_2 { + pub device: __u8, + pub lun: __u8, + pub reserved1: __u8, + pub reserved2: __u8, + pub reserved3: __u32, + pub reserved4: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_2() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_2)).device as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2), + "::", + stringify!(device) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_2)).lun as *const _ as usize + }, + 1usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2), + "::", + stringify!(lun) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_2)).reserved1 as *const _ + as usize + }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_2)).reserved2 as *const _ + as usize + }, + 3usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2), + "::", + stringify!(reserved2) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_2)).reserved3 as *const _ + as usize + }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2), + "::", + stringify!(reserved3) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_2)).reserved4 as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_2), + "::", + stringify!(reserved4) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_2 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_3 { + pub id: __u16, + pub lun: __u64, + pub reserved1: __u16, + pub reserved2: __u32, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_3() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_3) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_3) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_3)).id as *const _ as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_3), + "::", + stringify!(id) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_3)).lun as *const _ as usize + }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_3), + "::", + stringify!(lun) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_3)).reserved1 as *const _ + as usize + }, + 10usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_3), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_3)).reserved2 as *const _ + as usize + }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_3), + "::", + stringify!(reserved2) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_3 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_4 { + pub serial_number: __u64, + pub reserved: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_4() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_4) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_4) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_4)).serial_number + as *const _ as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_4), + "::", + stringify!(serial_number) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_4)).reserved as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_4), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_4 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_5 { + pub eui: __u64, + pub reserved: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_5() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_5) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_5) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_5)).eui as *const _ as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_5), + "::", + stringify!(eui) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_5)).reserved as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_5), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_5 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_6 { + pub wwid: __u64, + pub lun: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_6() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_6) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_6) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_6)).wwid as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_6), + "::", + stringify!(wwid) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_6)).lun as *const _ as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_6), + "::", + stringify!(lun) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_6 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_7 { + pub identity_tag: __u64, + pub reserved: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_7() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_7) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_7) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_7)).identity_tag as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_7), + "::", + stringify!(identity_tag) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_7)).reserved as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_7), + "::", + stringify!(reserved) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_7 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_8 { + pub array_number: __u32, + pub reserved1: __u32, + pub reserved2: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_8() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_8) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_8) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_8)).array_number as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_8), + "::", + stringify!(array_number) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_8)).reserved1 as *const _ + as usize + }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_8), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_8)).reserved2 as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_8), + "::", + stringify!(reserved2) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_8 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_9 { + pub device: __u8, + pub reserved1: __u8, + pub reserved2: __u16, + pub reserved3: __u32, + pub reserved4: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_9() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_9) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_9) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_9)).device as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_9), + "::", + stringify!(device) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_9)).reserved1 as *const _ + as usize + }, + 1usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_9), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_9)).reserved2 as *const _ + as usize + }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_9), + "::", + stringify!(reserved2) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_9)).reserved3 as *const _ + as usize + }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_9), + "::", + stringify!(reserved3) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_9)).reserved4 as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_9), + "::", + stringify!(reserved4) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_9 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_device_params__bindgen_ty_2__bindgen_ty_10 { + pub reserved1: __u64, + pub reserved2: __u64, +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2__bindgen_ty_10() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!( + "Size of: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_10) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_10) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_10)).reserved1 as *const _ + as usize + }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_10), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { + &(*(0 as *const edd_device_params__bindgen_ty_2__bindgen_ty_10)).reserved2 as *const _ + as usize + }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2__bindgen_ty_10), + "::", + stringify!(reserved2) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2__bindgen_ty_10 { + fn clone(&self) -> Self { + *self + } +} +#[test] +fn bindgen_test_layout_edd_device_params__bindgen_ty_2() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(edd_device_params__bindgen_ty_2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(edd_device_params__bindgen_ty_2)) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).ata as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(ata) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).atapi as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(atapi) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).scsi as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(scsi) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).usb as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(usb) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).i1394 as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(i1394) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).fibre as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(fibre) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).i2o as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(i2o) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).raid as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(raid) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).sata as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(sata) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params__bindgen_ty_2)).unknown as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params__bindgen_ty_2), + "::", + stringify!(unknown) + ) + ); +} +impl Clone for edd_device_params__bindgen_ty_2 { + fn clone(&self) -> Self { + *self + } +} +#[test] +fn bindgen_test_layout_edd_device_params() { + assert_eq!( + ::std::mem::size_of::(), + 74usize, + concat!("Size of: ", stringify!(edd_device_params)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(edd_device_params)) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).length as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(length) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).info_flags as *const _ as usize }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(info_flags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).num_default_cylinders as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(num_default_cylinders) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).num_default_heads as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(num_default_heads) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).sectors_per_track as *const _ as usize }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(sectors_per_track) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).number_of_sectors as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(number_of_sectors) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).bytes_per_sector as *const _ as usize }, + 24usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(bytes_per_sector) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).dpte_ptr as *const _ as usize }, + 26usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(dpte_ptr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).key as *const _ as usize }, + 30usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(key) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).device_path_info_length as *const _ as usize }, + 32usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(device_path_info_length) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).reserved2 as *const _ as usize }, + 33usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(reserved2) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).reserved3 as *const _ as usize }, + 34usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(reserved3) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).host_bus_type as *const _ as usize }, + 36usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(host_bus_type) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).interface_type as *const _ as usize }, + 40usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(interface_type) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).interface_path as *const _ as usize }, + 48usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(interface_path) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).device_path as *const _ as usize }, + 56usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(device_path) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).reserved4 as *const _ as usize }, + 72usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(reserved4) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_device_params)).checksum as *const _ as usize }, + 73usize, + concat!( + "Alignment of field: ", + stringify!(edd_device_params), + "::", + stringify!(checksum) + ) + ); +} +impl Clone for edd_device_params { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct edd_info { + pub device: __u8, + pub version: __u8, + pub interface_support: __u16, + pub legacy_max_cylinder: __u16, + pub legacy_max_head: __u8, + pub legacy_sectors_per_track: __u8, + pub params: edd_device_params, +} +#[test] +fn bindgen_test_layout_edd_info() { + assert_eq!( + ::std::mem::size_of::(), + 82usize, + concat!("Size of: ", stringify!(edd_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(edd_info)) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_info)).device as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd_info), + "::", + stringify!(device) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_info)).version as *const _ as usize }, + 1usize, + concat!( + "Alignment of field: ", + stringify!(edd_info), + "::", + stringify!(version) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_info)).interface_support as *const _ as usize }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(edd_info), + "::", + stringify!(interface_support) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_info)).legacy_max_cylinder as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(edd_info), + "::", + stringify!(legacy_max_cylinder) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_info)).legacy_max_head as *const _ as usize }, + 6usize, + concat!( + "Alignment of field: ", + stringify!(edd_info), + "::", + stringify!(legacy_max_head) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_info)).legacy_sectors_per_track as *const _ as usize }, + 7usize, + concat!( + "Alignment of field: ", + stringify!(edd_info), + "::", + stringify!(legacy_sectors_per_track) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd_info)).params as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(edd_info), + "::", + stringify!(params) + ) + ); +} +impl Clone for edd_info { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct edd { + pub mbr_signature: [::std::os::raw::c_uint; 16usize], + pub edd_info: [edd_info; 6usize], + pub mbr_signature_nr: ::std::os::raw::c_uchar, + pub edd_info_nr: ::std::os::raw::c_uchar, +} +#[test] +fn bindgen_test_layout_edd() { + assert_eq!( + ::std::mem::size_of::(), + 560usize, + concat!("Size of: ", stringify!(edd)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(edd)) + ); + assert_eq!( + unsafe { &(*(0 as *const edd)).mbr_signature as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edd), + "::", + stringify!(mbr_signature) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd)).edd_info as *const _ as usize }, + 64usize, + concat!( + "Alignment of field: ", + stringify!(edd), + "::", + stringify!(edd_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd)).mbr_signature_nr as *const _ as usize }, + 556usize, + concat!( + "Alignment of field: ", + stringify!(edd), + "::", + stringify!(mbr_signature_nr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const edd)).edd_info_nr as *const _ as usize }, + 557usize, + concat!( + "Alignment of field: ", + stringify!(edd), + "::", + stringify!(edd_info_nr) + ) + ); +} +impl Clone for edd { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct e820entry { + pub addr: __u64, + pub size: __u64, + pub type_: __u32, +} +#[test] +fn bindgen_test_layout_e820entry() { + assert_eq!( + ::std::mem::size_of::(), + 20usize, + concat!("Size of: ", stringify!(e820entry)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(e820entry)) + ); + assert_eq!( + unsafe { &(*(0 as *const e820entry)).addr as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(e820entry), + "::", + stringify!(addr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const e820entry)).size as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(e820entry), + "::", + stringify!(size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const e820entry)).type_ as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(e820entry), + "::", + stringify!(type_) + ) + ); +} +impl Clone for e820entry { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct e820map { + pub nr_map: __u32, + pub map: [e820entry; 128usize], +} +#[test] +fn bindgen_test_layout_e820map() { + assert_eq!( + ::std::mem::size_of::(), + 2564usize, + concat!("Size of: ", stringify!(e820map)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(e820map)) + ); + assert_eq!( + unsafe { &(*(0 as *const e820map)).nr_map as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(e820map), + "::", + stringify!(nr_map) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const e820map)).map as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(e820map), + "::", + stringify!(map) + ) + ); +} +impl Default for e820map { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct ist_info { + pub signature: __u32, + pub command: __u32, + pub event: __u32, + pub perf_level: __u32, +} +#[test] +fn bindgen_test_layout_ist_info() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(ist_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(ist_info)) + ); + assert_eq!( + unsafe { &(*(0 as *const ist_info)).signature as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(ist_info), + "::", + stringify!(signature) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const ist_info)).command as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(ist_info), + "::", + stringify!(command) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const ist_info)).event as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(ist_info), + "::", + stringify!(event) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const ist_info)).perf_level as *const _ as usize }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(ist_info), + "::", + stringify!(perf_level) + ) + ); +} +impl Clone for ist_info { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct edid_info { + pub dummy: [::std::os::raw::c_uchar; 128usize], +} +#[test] +fn bindgen_test_layout_edid_info() { + assert_eq!( + ::std::mem::size_of::(), + 128usize, + concat!("Size of: ", stringify!(edid_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(edid_info)) + ); + assert_eq!( + unsafe { &(*(0 as *const edid_info)).dummy as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(edid_info), + "::", + stringify!(dummy) + ) + ); +} +impl Default for edid_info { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct setup_data { + pub next: __u64, + pub type_: __u32, + pub len: __u32, + pub data: __IncompleteArrayField<__u8>, +} +#[test] +fn bindgen_test_layout_setup_data() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(setup_data)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(setup_data)) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_data)).next as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(setup_data), + "::", + stringify!(next) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_data)).type_ as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(setup_data), + "::", + stringify!(type_) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_data)).len as *const _ as usize }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(setup_data), + "::", + stringify!(len) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_data)).data as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(setup_data), + "::", + stringify!(data) + ) + ); +} +impl Clone for setup_data { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct setup_header { + pub setup_sects: __u8, + pub root_flags: __u16, + pub syssize: __u32, + pub ram_size: __u16, + pub vid_mode: __u16, + pub root_dev: __u16, + pub boot_flag: __u16, + pub jump: __u16, + pub header: __u32, + pub version: __u16, + pub realmode_swtch: __u32, + pub start_sys: __u16, + pub kernel_version: __u16, + pub type_of_loader: __u8, + pub loadflags: __u8, + pub setup_move_size: __u16, + pub code32_start: __u32, + pub ramdisk_image: __u32, + pub ramdisk_size: __u32, + pub bootsect_kludge: __u32, + pub heap_end_ptr: __u16, + pub ext_loader_ver: __u8, + pub ext_loader_type: __u8, + pub cmd_line_ptr: __u32, + pub initrd_addr_max: __u32, + pub kernel_alignment: __u32, + pub relocatable_kernel: __u8, + pub min_alignment: __u8, + pub xloadflags: __u16, + pub cmdline_size: __u32, + pub hardware_subarch: __u32, + pub hardware_subarch_data: __u64, + pub payload_offset: __u32, + pub payload_length: __u32, + pub setup_data: __u64, + pub pref_address: __u64, + pub init_size: __u32, + pub handover_offset: __u32, +} +#[test] +fn bindgen_test_layout_setup_header() { + assert_eq!( + ::std::mem::size_of::(), + 119usize, + concat!("Size of: ", stringify!(setup_header)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(setup_header)) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).setup_sects as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(setup_sects) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).root_flags as *const _ as usize }, + 1usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(root_flags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).syssize as *const _ as usize }, + 3usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(syssize) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).ram_size as *const _ as usize }, + 7usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(ram_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).vid_mode as *const _ as usize }, + 9usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(vid_mode) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).root_dev as *const _ as usize }, + 11usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(root_dev) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).boot_flag as *const _ as usize }, + 13usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(boot_flag) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).jump as *const _ as usize }, + 15usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(jump) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).header as *const _ as usize }, + 17usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(header) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).version as *const _ as usize }, + 21usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(version) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).realmode_swtch as *const _ as usize }, + 23usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(realmode_swtch) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).start_sys as *const _ as usize }, + 27usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(start_sys) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).kernel_version as *const _ as usize }, + 29usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(kernel_version) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).type_of_loader as *const _ as usize }, + 31usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(type_of_loader) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).loadflags as *const _ as usize }, + 32usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(loadflags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).setup_move_size as *const _ as usize }, + 33usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(setup_move_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).code32_start as *const _ as usize }, + 35usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(code32_start) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).ramdisk_image as *const _ as usize }, + 39usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(ramdisk_image) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).ramdisk_size as *const _ as usize }, + 43usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(ramdisk_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).bootsect_kludge as *const _ as usize }, + 47usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(bootsect_kludge) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).heap_end_ptr as *const _ as usize }, + 51usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(heap_end_ptr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).ext_loader_ver as *const _ as usize }, + 53usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(ext_loader_ver) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).ext_loader_type as *const _ as usize }, + 54usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(ext_loader_type) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).cmd_line_ptr as *const _ as usize }, + 55usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(cmd_line_ptr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).initrd_addr_max as *const _ as usize }, + 59usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(initrd_addr_max) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).kernel_alignment as *const _ as usize }, + 63usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(kernel_alignment) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).relocatable_kernel as *const _ as usize }, + 67usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(relocatable_kernel) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).min_alignment as *const _ as usize }, + 68usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(min_alignment) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).xloadflags as *const _ as usize }, + 69usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(xloadflags) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).cmdline_size as *const _ as usize }, + 71usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(cmdline_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).hardware_subarch as *const _ as usize }, + 75usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(hardware_subarch) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).hardware_subarch_data as *const _ as usize }, + 79usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(hardware_subarch_data) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).payload_offset as *const _ as usize }, + 87usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(payload_offset) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).payload_length as *const _ as usize }, + 91usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(payload_length) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).setup_data as *const _ as usize }, + 95usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(setup_data) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).pref_address as *const _ as usize }, + 103usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(pref_address) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).init_size as *const _ as usize }, + 111usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(init_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const setup_header)).handover_offset as *const _ as usize }, + 115usize, + concat!( + "Alignment of field: ", + stringify!(setup_header), + "::", + stringify!(handover_offset) + ) + ); +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct sys_desc_table { + pub length: __u16, + pub table: [__u8; 14usize], +} +#[test] +fn bindgen_test_layout_sys_desc_table() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(sys_desc_table)) + ); + assert_eq!( + ::std::mem::align_of::(), + 2usize, + concat!("Alignment of ", stringify!(sys_desc_table)) + ); + assert_eq!( + unsafe { &(*(0 as *const sys_desc_table)).length as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(sys_desc_table), + "::", + stringify!(length) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const sys_desc_table)).table as *const _ as usize }, + 2usize, + concat!( + "Alignment of field: ", + stringify!(sys_desc_table), + "::", + stringify!(table) + ) + ); +} +impl Clone for sys_desc_table { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Debug, Default, Copy)] +pub struct olpc_ofw_header { + pub ofw_magic: __u32, + pub ofw_version: __u32, + pub cif_handler: __u32, + pub irq_desc_table: __u32, +} +#[test] +fn bindgen_test_layout_olpc_ofw_header() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(olpc_ofw_header)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(olpc_ofw_header)) + ); + assert_eq!( + unsafe { &(*(0 as *const olpc_ofw_header)).ofw_magic as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(olpc_ofw_header), + "::", + stringify!(ofw_magic) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const olpc_ofw_header)).ofw_version as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(olpc_ofw_header), + "::", + stringify!(ofw_version) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const olpc_ofw_header)).cif_handler as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(olpc_ofw_header), + "::", + stringify!(cif_handler) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const olpc_ofw_header)).irq_desc_table as *const _ as usize }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(olpc_ofw_header), + "::", + stringify!(irq_desc_table) + ) + ); +} +impl Clone for olpc_ofw_header { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct efi_info { + pub efi_loader_signature: __u32, + pub efi_systab: __u32, + pub efi_memdesc_size: __u32, + pub efi_memdesc_version: __u32, + pub efi_memmap: __u32, + pub efi_memmap_size: __u32, + pub efi_systab_hi: __u32, + pub efi_memmap_hi: __u32, +} +#[test] +fn bindgen_test_layout_efi_info() { + assert_eq!( + ::std::mem::size_of::(), + 32usize, + concat!("Size of: ", stringify!(efi_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(efi_info)) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_loader_signature as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_loader_signature) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_systab as *const _ as usize }, + 4usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_systab) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_memdesc_size as *const _ as usize }, + 8usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_memdesc_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_memdesc_version as *const _ as usize }, + 12usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_memdesc_version) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_memmap as *const _ as usize }, + 16usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_memmap) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_memmap_size as *const _ as usize }, + 20usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_memmap_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_systab_hi as *const _ as usize }, + 24usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_systab_hi) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const efi_info)).efi_memmap_hi as *const _ as usize }, + 28usize, + concat!( + "Alignment of field: ", + stringify!(efi_info), + "::", + stringify!(efi_memmap_hi) + ) + ); +} +impl Clone for efi_info { + fn clone(&self) -> Self { + *self + } +} +#[repr(C, packed)] +#[derive(Copy, Clone)] +pub struct boot_params { + pub screen_info: screen_info, + pub apm_bios_info: apm_bios_info, + pub _pad2: [__u8; 4usize], + pub tboot_addr: __u64, + pub ist_info: ist_info, + pub _pad3: [__u8; 16usize], + pub hd0_info: [__u8; 16usize], + pub hd1_info: [__u8; 16usize], + pub sys_desc_table: sys_desc_table, + pub olpc_ofw_header: olpc_ofw_header, + pub ext_ramdisk_image: __u32, + pub ext_ramdisk_size: __u32, + pub ext_cmd_line_ptr: __u32, + pub _pad4: [__u8; 116usize], + pub edid_info: edid_info, + pub efi_info: efi_info, + pub alt_mem_k: __u32, + pub scratch: __u32, + pub e820_entries: __u8, + pub eddbuf_entries: __u8, + pub edd_mbr_sig_buf_entries: __u8, + pub kbd_status: __u8, + pub _pad5: [__u8; 3usize], + pub sentinel: __u8, + pub _pad6: [__u8; 1usize], + pub hdr: setup_header, + pub _pad7: [__u8; 40usize], + pub edd_mbr_sig_buffer: [__u32; 16usize], + pub e820_map: [e820entry; 128usize], + pub _pad8: [__u8; 48usize], + pub eddbuf: [edd_info; 6usize], + pub _pad9: [__u8; 276usize], +} +#[test] +fn bindgen_test_layout_boot_params() { + assert_eq!( + ::std::mem::size_of::(), + 4096usize, + concat!("Size of: ", stringify!(boot_params)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(boot_params)) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).screen_info as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(screen_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).apm_bios_info as *const _ as usize }, + 64usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(apm_bios_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad2 as *const _ as usize }, + 84usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad2) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).tboot_addr as *const _ as usize }, + 88usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(tboot_addr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).ist_info as *const _ as usize }, + 96usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(ist_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad3 as *const _ as usize }, + 112usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad3) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).hd0_info as *const _ as usize }, + 128usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(hd0_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).hd1_info as *const _ as usize }, + 144usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(hd1_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).sys_desc_table as *const _ as usize }, + 160usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(sys_desc_table) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).olpc_ofw_header as *const _ as usize }, + 176usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(olpc_ofw_header) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).ext_ramdisk_image as *const _ as usize }, + 192usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(ext_ramdisk_image) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).ext_ramdisk_size as *const _ as usize }, + 196usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(ext_ramdisk_size) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).ext_cmd_line_ptr as *const _ as usize }, + 200usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(ext_cmd_line_ptr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad4 as *const _ as usize }, + 204usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad4) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).edid_info as *const _ as usize }, + 320usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(edid_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).efi_info as *const _ as usize }, + 448usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(efi_info) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).alt_mem_k as *const _ as usize }, + 480usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(alt_mem_k) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).scratch as *const _ as usize }, + 484usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(scratch) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).e820_entries as *const _ as usize }, + 488usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(e820_entries) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).eddbuf_entries as *const _ as usize }, + 489usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(eddbuf_entries) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).edd_mbr_sig_buf_entries as *const _ as usize }, + 490usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(edd_mbr_sig_buf_entries) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).kbd_status as *const _ as usize }, + 491usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(kbd_status) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad5 as *const _ as usize }, + 492usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad5) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).sentinel as *const _ as usize }, + 495usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(sentinel) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad6 as *const _ as usize }, + 496usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad6) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).hdr as *const _ as usize }, + 497usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(hdr) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad7 as *const _ as usize }, + 616usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad7) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).edd_mbr_sig_buffer as *const _ as usize }, + 656usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(edd_mbr_sig_buffer) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).e820_map as *const _ as usize }, + 720usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(e820_map) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad8 as *const _ as usize }, + 3280usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad8) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params)).eddbuf as *const _ as usize }, + 3328usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(eddbuf) + ) + ); + assert_eq!( + unsafe { &(*(0 as *const boot_params))._pad9 as *const _ as usize }, + 3820usize, + concat!( + "Alignment of field: ", + stringify!(boot_params), + "::", + stringify!(_pad9) + ) + ); +} +impl Default for boot_params { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +pub const X86_SUBARCH_PC: _bindgen_ty_1 = 0; +pub const X86_SUBARCH_LGUEST: _bindgen_ty_1 = 1; +pub const X86_SUBARCH_XEN: _bindgen_ty_1 = 2; +pub const X86_SUBARCH_INTEL_MID: _bindgen_ty_1 = 3; +pub const X86_SUBARCH_CE4100: _bindgen_ty_1 = 4; +pub const X86_NR_SUBARCHS: _bindgen_ty_1 = 5; +pub type _bindgen_ty_1 = ::std::os::raw::c_uint; diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 57a36f3c..17f218bd 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -17,6 +17,12 @@ use std::mem; use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestUsize}; +#[allow(dead_code)] +#[allow(non_camel_case_types)] +#[allow(non_snake_case)] +#[allow(non_upper_case_globals)] +#[cfg_attr(feature = "cargo-clippy", allow(clippy))] +pub mod bootparam; #[allow(dead_code)] #[allow(non_camel_case_types)] #[allow(non_snake_case)] @@ -35,15 +41,21 @@ pub enum Error { InvalidProgramHeaderOffset, InvalidProgramHeaderAddress, InvalidEntryAddress, + InvalidBzImage, InvalidKernelStartAddress, InitrdImageSizeTooLarge, ReadElfHeader, ReadKernelImage, ReadProgramHeader, + ReadBzImageHeader, + ReadBzImageCompressedKernel, ReadInitrdImage, SeekKernelStart, SeekElfStart, SeekProgramHeader, + SeekBzImageEnd, + SeekBzImageHeader, + SeekBzImageCompressedKernel, SeekInitrdImage, } pub type Result = std::result::Result; @@ -61,15 +73,21 @@ impl error::Error for Error { Error::InvalidProgramHeaderOffset => "Invalid program header offset", Error::InvalidProgramHeaderAddress => "Invalid Program Header Address", Error::InvalidEntryAddress => "Invalid entry address", + Error::InvalidBzImage => "Invalid bzImage", Error::InvalidKernelStartAddress => "Invalid kernel start address", Error::InitrdImageSizeTooLarge => "Initrd image size too large", Error::ReadElfHeader => "Unable to read elf header", Error::ReadKernelImage => "Unable to read kernel image", Error::ReadProgramHeader => "Unable to read program header", + Error::ReadBzImageHeader => "Unable to read bzImage header", + Error::ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel", Error::ReadInitrdImage => "Unable to read initrd image", Error::SeekKernelStart => "Unable to seek to kernel start", Error::SeekElfStart => "Unable to seek to elf start", Error::SeekProgramHeader => "Unable to seek to program header", + Error::SeekBzImageEnd => "Unable to seek bzImage end", + Error::SeekBzImageHeader => "Unable to seek bzImage header", + Error::SeekBzImageCompressedKernel => "Unable to seek bzImage compressed kernel", Error::SeekInitrdImage => "Unable to seek initrd image", } } @@ -84,10 +102,14 @@ impl Display for Error { /// * `kernel_load` - The actual `guest_mem` address where kernel image is loaded start. /// * `kernel_end` - The offset of `guest_mem` where kernel image load is loaded finish, return /// in case of loading initrd adjacent to kernel image. +/// * `setup_header` - The setup_header belongs to linux boot protocol, only for bzImage, vmm +/// will use it to setup setup_header.init_size, which is a must for bzImage +/// direct boot. #[derive(Debug, Default, Copy, Clone, PartialEq)] pub struct KernelLoaderResult { pub kernel_load: GuestAddress, pub kernel_end: GuestUsize, + pub setup_header: Option, } pub trait KernelLoader { @@ -202,6 +224,98 @@ impl KernelLoader for Elf { mem_offset.raw_value() as GuestUsize + phdr.p_memsz as GuestUsize; } + loader_result.setup_header = None; + + Ok(loader_result) + } +} + +pub struct BzImage; + +impl KernelLoader for BzImage { + /// Loads a bzImage + /// + /// kernel is loaded into guest memory at code32_start the default load address + /// stored in bzImage setup header. + /// + /// # Arguments + /// + /// * `guest_mem` - The guest memory region the kernel is written to. + /// * `kernel_start` - The offset into 'guest _mem' at which to load the kernel. + /// * `kernel_image` - Input bzImage image. + /// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it. + /// + /// # Returns + /// * KernelLoaderResult + fn load( + guest_mem: &GuestMemoryMmap, + kernel_start: Option, + kernel_image: &mut F, + lowest_kernel_start: Option, + ) -> Result<(KernelLoaderResult)> + where + F: Read + Seek, + { + let mut kernel_size = kernel_image + .seek(SeekFrom::End(0)) + .map_err(|_| Error::SeekBzImageEnd)? as usize; + let mut boot_header: bootparam::setup_header = Default::default(); + kernel_image + .seek(SeekFrom::Start(0x1F1)) + .map_err(|_| Error::SeekBzImageHeader)?; + unsafe { + // read_struct is safe when reading a POD struct. It can be used and dropped without issue. + struct_util::read_struct(kernel_image, &mut boot_header) + .map_err(|_| Error::ReadBzImageHeader)?; + } + + // if the HdrS magic number is not found at offset 0x202, the boot protocol version is "old", + // the image type is assumed as zImage, not bzImage. + if boot_header.header != 0x53726448 { + return Err(Error::InvalidBzImage); + } + + // follow section of loading the rest of the kernel in linux boot protocol + if (boot_header.version < 0x0200) || ((boot_header.loadflags & 0x1) == 0x0) { + return Err(Error::InvalidBzImage); + } + + let mut setup_size = boot_header.setup_sects as usize; + if setup_size == 0 { + setup_size = 4; + } + setup_size = (setup_size + 1) * 512; + kernel_size -= setup_size; + + // verify bzImage validation by checking if code32_start, the defaults to the address of + // the kernel is not lower than high memory. + if lowest_kernel_start.is_some() { + if (boot_header.code32_start as u64) < lowest_kernel_start.unwrap().raw_value() { + return Err(Error::InvalidKernelStartAddress); + } + } + + let mem_offset = match kernel_start { + Some(start) => start, + None => GuestAddress(boot_header.code32_start as u64), + }; + + boot_header.code32_start = mem_offset.raw_value() as u32; + + let mut loader_result: KernelLoaderResult = Default::default(); + loader_result.setup_header = Some(boot_header); + loader_result.kernel_load = mem_offset; + + //seek the compressed vmlinux.bin and read to memory + kernel_image + .seek(SeekFrom::Start(setup_size as u64)) + .map_err(|_| Error::SeekBzImageCompressedKernel)?; + guest_mem + .read_exact_from(mem_offset, kernel_image, kernel_size) + .map_err(|_| Error::ReadBzImageCompressedKernel)?; + + loader_result.kernel_end = mem_offset.raw_value() as GuestUsize + kernel_size as GuestUsize; + Ok(loader_result) } } @@ -249,6 +363,13 @@ mod test { GuestMemoryMmap::new(&[(GuestAddress(0x0), (MEM_SIZE as usize))]).unwrap() } + #[allow(non_snake_case)] + fn make_bzImage() -> Vec { + let mut v = Vec::new(); + v.extend_from_slice(include_bytes!("bzImage")); + v + } + // Elf64 image that prints hello world on x86_64. fn make_elf_bin() -> Vec { let mut v = Vec::new(); @@ -256,6 +377,77 @@ mod test { v } + #[allow(safe_packed_borrows)] + #[allow(non_snake_case)] + #[test] + #[ignore] + fn load_bzImage() { + let gm = create_guest_mem(); + let image = make_bzImage(); + let mut kernel_start = GuestAddress(0x200000); + let mut lowest_kernel_start = GuestAddress(0x0); + + // load bzImage with good kernel_start and himem_start setting + let mut loader_result = BzImage::load( + &gm, + Some(kernel_start), + &mut Cursor::new(&image), + Some(lowest_kernel_start), + ) + .unwrap(); + assert_eq!(0x53726448, loader_result.setup_header.unwrap().header); + println!( + "bzImage is loaded at {:8x} \n", + loader_result.kernel_load.raw_value() + ); + println!( + "bzImage version is {:2x} \n", + loader_result.setup_header.unwrap().version + ); + println!( + "bzImage loadflags is {:x} \n", + loader_result.setup_header.unwrap().loadflags + ); + println!( + "bzImage kernel size is {:4x} \n", + (loader_result.kernel_end as u32) + ); + + // load bzImage without kernel_start + loader_result = BzImage::load( + &gm, + None, + &mut Cursor::new(&image), + Some(lowest_kernel_start), + ) + .unwrap(); + assert_eq!(0x53726448, loader_result.setup_header.unwrap().header); + println!( + "bzImage is loaded at {:8x} \n", + loader_result.kernel_load.raw_value() + ); + + // load bzImage withouth himem_start + loader_result = BzImage::load(&gm, None, &mut Cursor::new(&image), None).unwrap(); + assert_eq!(0x53726448, loader_result.setup_header.unwrap().header); + println!( + "bzImage is loaded at {:8x} \n", + loader_result.kernel_load.raw_value() + ); + + // load bzImage with a bad himem setting + kernel_start = GuestAddress(0x1000); + lowest_kernel_start = GuestAddress(0x200000); + let x = BzImage::load( + &gm, + Some(kernel_start), + &mut Cursor::new(&image), + Some(lowest_kernel_start), + ); + assert_eq!(x.is_ok(), false); + println!("load bzImage with bad himem setting \n"); + } + #[test] fn load_elf() { let gm = create_guest_mem(); From eef5535037f55b3c8bb63abf7d0a8af38b465454 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 19 Apr 2019 14:59:01 +0800 Subject: [PATCH 05/27] lint: Fix clippy lint warnings Signed-off-by: Cathy Zhang --- src/cmdline/mod.rs | 2 +- src/loader/mod.rs | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cmdline/mod.rs b/src/cmdline/mod.rs index ed8dedb7..d9991f69 100644 --- a/src/cmdline/mod.rs +++ b/src/cmdline/mod.rs @@ -84,7 +84,7 @@ impl Cmdline { assert_ne!(capacity, 0); Cmdline { line: String::with_capacity(capacity), - capacity: capacity, + capacity, } } diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 17f218bd..88b68732 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -21,13 +21,13 @@ use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, Gues #[allow(non_camel_case_types)] #[allow(non_snake_case)] #[allow(non_upper_case_globals)] -#[cfg_attr(feature = "cargo-clippy", allow(clippy))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::all))] pub mod bootparam; #[allow(dead_code)] #[allow(non_camel_case_types)] #[allow(non_snake_case)] #[allow(non_upper_case_globals)] -#[cfg_attr(feature = "cargo-clippy", allow(clippy))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::all))] mod elf; mod struct_util; @@ -175,10 +175,10 @@ impl KernelLoader for Elf { // If the program header is backwards, bail. return Err(Error::InvalidProgramHeaderOffset); } - if lowest_kernel_start.is_some() { - if (ehdr.e_entry as u64) < lowest_kernel_start.unwrap().raw_value() { - return Err(Error::InvalidEntryAddress); - } + if (lowest_kernel_start.is_some()) + && ((ehdr.e_entry as u64) < lowest_kernel_start.unwrap().raw_value()) + { + return Err(Error::InvalidEntryAddress); } let mut loader_result: KernelLoaderResult = Default::default(); @@ -271,7 +271,7 @@ impl KernelLoader for BzImage { // if the HdrS magic number is not found at offset 0x202, the boot protocol version is "old", // the image type is assumed as zImage, not bzImage. - if boot_header.header != 0x53726448 { + if boot_header.header != 0x5372_6448 { return Err(Error::InvalidBzImage); } @@ -289,15 +289,15 @@ impl KernelLoader for BzImage { // verify bzImage validation by checking if code32_start, the defaults to the address of // the kernel is not lower than high memory. - if lowest_kernel_start.is_some() { - if (boot_header.code32_start as u64) < lowest_kernel_start.unwrap().raw_value() { - return Err(Error::InvalidKernelStartAddress); - } + if (lowest_kernel_start.is_some()) + && (u64::from(boot_header.code32_start) < lowest_kernel_start.unwrap().raw_value()) + { + return Err(Error::InvalidKernelStartAddress); } let mem_offset = match kernel_start { Some(start) => start, - None => GuestAddress(boot_header.code32_start as u64), + None => GuestAddress(u64::from(boot_header.code32_start)), }; boot_header.code32_start = mem_offset.raw_value() as u32; From 79bd1d59757c77afad197bc459177087c1ec5178 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 6 May 2019 15:35:46 +0200 Subject: [PATCH 06/27] tests: Add kcov based coverage generation scripts And update/add the corresponding README sections. Signed-off-by: Samuel Ortiz --- README.md | 85 +++++++++++++++++++++++++++----- tests/conftest.py | 28 +++++++++++ tests/coverage | 1 + tests/test_coverage.py | 108 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+), 12 deletions(-) create mode 100644 tests/conftest.py create mode 100644 tests/coverage create mode 100644 tests/test_coverage.py diff --git a/README.md b/README.md index 4972ae5e..0c8920db 100644 --- a/README.md +++ b/README.md @@ -13,16 +13,77 @@ cd linux-loader cargo build ``` -## How to run test for Elf loader +## Tests -```shell -# Assuming your linux-loader is under $HOME -$ cd linux-loader -$ cargo test -$ cargo test -- --nocapture +Our Continuous Integration (CI) pipeline is implemented on top of +[Buildkite](https://buildkite.com/). +For the complete list of tests, check our +[CI pipeline](https://buildkite.com/rust-vmm/vm-virtio-ci). + +Each individual test runs in a container. To reproduce a test locally, you can +use the dev-container on both x86 and arm64. + +```bash +docker run -it \ + --security-opt seccomp=unconfined \ + --volume $(pwd):/linux-loader \ + fandree/rust-vmm-dev +cd linux-loader/ +cargo test ``` -## How to run test for bzImage loader +### Test Profiles + +The integration tests support two test profiles: +- **devel**: this is the recommended profile for running the integration tests + on a local development machine. +- **ci** (default option): this is the profile used when running the + integration tests as part of the the Continuous Integration (CI). + +The test profiles are applicable to tests that run using pytest. Currently only +the [coverage test](tests/test_coverage.py) follows this model as all the other +integration tests are run using the +[Buildkite pipeline](https://buildkite.com/rust-vmm/vm-virtio-ci). + +The difference between is declaring tests as passed or failed: +- with the **devel** profile the coverage test passes if the current coverage + is equal or higher than the upstream coverage value. In case the current + coverage is higher, the coverage file is updated to the new coverage value. +- with the **ci** profile the coverage test passes only if the current coverage + is equal to the upstream coverage value. + +Further details about the coverage test can be found in the +[Adaptive Coverage](#adaptive-coverage) section. + +### Adaptive Coverage + +The line coverage is saved in [tests/coverage](tests/coverage). To update the +coverage before submitting a PR, run the coverage test: + +```bash +docker run -it \ + --security-opt seccomp=unconfined \ + --volume $(pwd):/linux-loader \ + fandree/rust-vmm-dev +cd linux-loader/ +pytest --profile=devel tests/test_coverage.py +``` + +If the PR coverage is higher than the upstream coverage, the coverage file +needs to be manually added to the commit before submitting the PR: + +```bash +git add tests/coverage +``` + +Failing to do so will generate a fail on the CI pipeline when publishing the +PR. + +**NOTE:** The coverage file is only updated in the `devel` test profile. In +the `ci` profile the coverage test will fail if the current coverage is higher +than the coverage reported in [tests/coverage](tests/coverage). + +### bzImage test As we don't want to distribute an entire kernel bzImage, the `load_bzImage` test is ignored by default. In order to test the bzImage support, one needs to locally build a bzImage, copy it @@ -35,10 +96,10 @@ $ cd linux-stable $ make bzImage $ cp linux-stable/arch/x86/boot/bzImage $LINUX_LOADER/linux-loader/src/loader/ $ cd $LINUX_LOADER/linux-loader +$ docker run -it \ + --security-opt seccomp=unconfined \ + --volume $(pwd):/linux-loader \ + fandree/rust-vmm-dev +$ cd linux-loader/ $ cargo test -- --ignored ``` - -## Platform Support -- Arch: x86 -- OS: Linux/Unix - diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..58aef2d7 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,28 @@ +import pytest + + +PROFILE_CI="ci" +PROFILE_DEVEL="devel" + + +def pytest_addoption(parser): + parser.addoption( + "--profile", + default=PROFILE_CI, + choices=[PROFILE_CI, PROFILE_DEVEL], + help="Profile for running the test: {} or {}".format( + PROFILE_CI, + PROFILE_DEVEL + ) + ) + + +@pytest.fixture +def profile(request): + return request.config.getoption("--profile") + + +# This is used for defining global variables in pytest. +def pytest_configure(): + pytest.profile_ci = PROFILE_CI + pytest.profile_devel = PROFILE_DEVEL diff --git a/tests/coverage b/tests/coverage new file mode 100644 index 00000000..aca6ad82 --- /dev/null +++ b/tests/coverage @@ -0,0 +1 @@ +63.0 \ No newline at end of file diff --git a/tests/test_coverage.py b/tests/test_coverage.py new file mode 100644 index 00000000..c009f8e0 --- /dev/null +++ b/tests/test_coverage.py @@ -0,0 +1,108 @@ +# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause +"""Test the coverage and update the threshold when coverage is increased.""" + +import os, re, shutil, subprocess +import pytest + +def _get_current_coverage(): + """Helper function that returns the coverage computed with kcov.""" + kcov_ouput_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "kcov_output" + ) + + # By default the build output for kcov and unit tests are both in the debug + # directory. This causes some linker errors that I haven't investigated. + # Error: error: linking with `cc` failed: exit code: 1 + # An easy fix is to have separate build directories for kcov & unit tests. + kcov_build_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "kcov_build" + ) + + # Remove kcov output and build directory to be sure we are always working + # on a clean environment. + shutil.rmtree(kcov_ouput_dir, ignore_errors=True) + shutil.rmtree(kcov_build_dir, ignore_errors=True) + + exclude_pattern = ( + '${CARGO_HOME:-$HOME/.cargo/},' + 'usr/lib/,' + 'lib/' + ) + exclude_region = "'mod tests {'" + + kcov_cmd = "CARGO_TARGET_DIR={} cargo kcov --all " \ + "--output {} -- " \ + "--exclude-region={} " \ + "--exclude-pattern={} " \ + "--verify".format( + kcov_build_dir, + kcov_ouput_dir, + exclude_region, + exclude_pattern + ) + + subprocess.run(kcov_cmd, shell=True, check=True) + + # Read the coverage reported by kcov. + coverage_file = os.path.join(kcov_ouput_dir, 'index.js') + with open(coverage_file) as cov_output: + coverage = float(re.findall( + r'"covered":"(\d+\.\d)"', + cov_output.read() + )[0]) + + # Remove coverage related directories. + shutil.rmtree(kcov_ouput_dir, ignore_errors=True) + shutil.rmtree(kcov_build_dir, ignore_errors=True) + + return coverage + + +def _get_previous_coverage(): + """Helper function that returns the last reported coverage.""" + coverage_path = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'coverage' + ) + + # The first and only line of the file contains the coverage. + with open(coverage_path) as f: + coverage = f.readline() + return float(coverage.strip()) + +def _update_coverage(cov_value): + """Updates the coverage in the coverage file.""" + coverage_path = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'coverage' + ) + + with open(coverage_path, "w") as f: + f.write(str(cov_value)) + +def test_coverage(profile): + current_coverage = _get_current_coverage() + previous_coverage = _get_previous_coverage() + if previous_coverage < current_coverage: + if profile == pytest.profile_ci: + # In the CI Profile we expect the coverage to be manually updated. + assert False, "Coverage is increased from {} to {}. " \ + "Please update the coverage in " \ + "tests/coverage.".format( + previous_coverage, + current_coverage + ) + elif profile == pytest.profile_devel: + _update_coverage(current_coverage) + else: + # This should never happen because pytest should only accept + # the valid test profiles specified with `choices` in + # `pytest_addoption`. + assert False, "Invalid test profile." + elif previous_coverage > current_coverage: + diff = float(previous_coverage - current_coverage) + assert False, "Coverage drops by {:.2f}%. Please add unit tests for" \ + "the uncovered lines.".format(diff) From c39f0f8051d4dc3787ef8748418f3a1e0ef3c176 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 6 May 2019 15:43:33 +0200 Subject: [PATCH 07/27] buildkite: Initial pipeline Handled and consumed by https://buildkite.com/rust-vmm/linux-loader-ci/ Signed-off-by: Samuel Ortiz --- .buildkite/pipeline.yml | 61 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .buildkite/pipeline.yml diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml new file mode 100644 index 00000000..8a072660 --- /dev/null +++ b/.buildkite/pipeline.yml @@ -0,0 +1,61 @@ +steps: + - label: "build-gnu-x86" + commands: + - cargo build --release + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "fandree/rust-vmm-dev" + always-pull: true + + - label: "style" + command: cargo fmt --all -- --check + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "fandree/rust-vmm-dev" + always-pull: true + + - label: "unittests-gnu-x86" + commands: + - cargo test + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "fandree/rust-vmm-dev" + always-pull: true + + - label: "clippy-x86" + commands: + - cargo clippy --all -- -D warnings + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "fandree/rust-vmm-dev" + always-pull: true + + - label: "coverage-x86" + commands: + - pytest tests/test_coverage.py + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "fandree/rust-vmm-dev" + always-pull: true From 62cb1523767504f73a684c66df09cd266e68ce7f Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Sat, 1 Jun 2019 08:01:14 +0800 Subject: [PATCH 08/27] loader: Add inline links for loader trait and structs As suggested by rust, it's good practice to add documentation to public items of a crate. Thus, add inline links for public traits and structs. Signed-off-by: Cathy Zhang --- src/loader/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 88b68732..369c82c9 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -7,6 +7,13 @@ // // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause +//! Traits and Structs +//! - [KernelLoader](trait.KernelLoader.html): load kernel image into guest memory +//! - [KernelLoaderResult](struct.KernelLoaderResult.html): the structure which loader +//! returns to VMM to assist zero page construction and boot environment setup +//! - [Elf](struct.Elf.html): elf image loader +//! - [BzImage](struct.BzImage.html): bzImage loader + extern crate vm_memory; use std::error::{self, Error as KernelLoaderError}; From be2e8b018308a68b6ba95e9b6e733f7ed2b8e303 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Sat, 1 Jun 2019 08:03:45 +0800 Subject: [PATCH 09/27] loader: Remove dependency on GuestMemoryMmap Update Loader with GuestMemory, instead of GuestMemoryMmap backend, which may not be generally used by VMMs. Signed-off-by: Cathy Zhang --- src/loader/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 369c82c9..dd10db62 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -22,7 +22,7 @@ use std::fmt::{self, Display}; use std::io::{Read, Seek, SeekFrom}; use std::mem; -use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestUsize}; +use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestUsize}; #[allow(dead_code)] #[allow(non_camel_case_types)] @@ -120,8 +120,8 @@ pub struct KernelLoaderResult { } pub trait KernelLoader { - fn load( - guest_mem: &GuestMemoryMmap, + fn load( + guest_mem: &M, kernel_start: Option, kernel_image: &mut F, lowest_kernel_start: Option, @@ -146,8 +146,8 @@ impl KernelLoader for Elf { /// /// # Returns /// * KernelLoaderResult - fn load( - guest_mem: &GuestMemoryMmap, + fn load( + guest_mem: &M, kernel_start: Option, kernel_image: &mut F, lowest_kernel_start: Option, @@ -254,8 +254,8 @@ impl KernelLoader for BzImage { /// /// # Returns /// * KernelLoaderResult - fn load( - guest_mem: &GuestMemoryMmap, + fn load( + guest_mem: &M, kernel_start: Option, kernel_image: &mut F, lowest_kernel_start: Option, @@ -334,8 +334,8 @@ impl KernelLoader for BzImage { /// * `guest_mem` - A u8 slice that will be partially overwritten by the command line. /// * `guest_addr` - The address in `guest_mem` at which to load the command line. /// * `cmdline` - The kernel command line. -pub fn load_cmdline( - guest_mem: &GuestMemoryMmap, +pub fn load_cmdline( + guest_mem: &M, guest_addr: GuestAddress, cmdline: &CStr, ) -> Result<()> { From f6da4fed7cf4261544ff05143b5e038bb3275e7d Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Sat, 1 Jun 2019 08:12:08 +0800 Subject: [PATCH 10/27] loader: Add memory overflow checking for kernel end There is no checking in loader to see if the memory is large enough to store the kernel image, so add this checking to avoid memory overflow. Signed-off-by: Cathy Zhang --- src/loader/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index dd10db62..28c0bd53 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -51,6 +51,7 @@ pub enum Error { InvalidBzImage, InvalidKernelStartAddress, InitrdImageSizeTooLarge, + MemoryOverflow, ReadElfHeader, ReadKernelImage, ReadProgramHeader, @@ -83,6 +84,7 @@ impl error::Error for Error { Error::InvalidBzImage => "Invalid bzImage", Error::InvalidKernelStartAddress => "Invalid kernel start address", Error::InitrdImageSizeTooLarge => "Initrd image size too large", + Error::MemoryOverflow => "Memory to load kernel image is not enough", Error::ReadElfHeader => "Unable to read elf header", Error::ReadKernelImage => "Unable to read kernel image", Error::ReadProgramHeader => "Unable to read program header", @@ -227,8 +229,9 @@ impl KernelLoader for Elf { .read_exact_from(mem_offset, kernel_image, phdr.p_filesz as usize) .map_err(|_| Error::ReadKernelImage)?; - loader_result.kernel_end = - mem_offset.raw_value() as GuestUsize + phdr.p_memsz as GuestUsize; + loader_result.kernel_end = mem_offset.raw_value() + .checked_add(phdr.p_memsz as GuestUsize) + .ok_or(Error::MemoryOverflow)?; } loader_result.setup_header = None; @@ -321,7 +324,9 @@ impl KernelLoader for BzImage { .read_exact_from(mem_offset, kernel_image, kernel_size) .map_err(|_| Error::ReadBzImageCompressedKernel)?; - loader_result.kernel_end = mem_offset.raw_value() as GuestUsize + kernel_size as GuestUsize; + loader_result.kernel_end = mem_offset.raw_value() + .checked_add(kernel_size as GuestUsize) + .ok_or(Error::MemoryOverflow)?; Ok(loader_result) } From b71ddaa15560df0ffe4d0c8244dcd4063f4873b9 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Sat, 1 Jun 2019 08:20:33 +0800 Subject: [PATCH 11/27] loader: Refactor comments There are some comments not in a good format, or not presented clearly, correct them. Signed-off-by: Cathy Zhang --- src/loader/mod.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 28c0bd53..9bb4110a 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -108,16 +108,15 @@ impl Display for Error { } } -/// * `kernel_load` - The actual `guest_mem` address where kernel image is loaded start. -/// * `kernel_end` - The offset of `guest_mem` where kernel image load is loaded finish, return -/// in case of loading initrd adjacent to kernel image. -/// * `setup_header` - The setup_header belongs to linux boot protocol, only for bzImage, vmm -/// will use it to setup setup_header.init_size, which is a must for bzImage -/// direct boot. #[derive(Debug, Default, Copy, Clone, PartialEq)] pub struct KernelLoaderResult { + // Address in the guest memory where the kernel image starts to be loaded pub kernel_load: GuestAddress, + // Offset in guest memory corresponding to the end of kernel image, in case that + // device tree blob and initrd will be loaded adjacent to kernel image. pub kernel_end: GuestUsize, + // This field is only for bzImage following https://www.kernel.org/doc/Documentation/x86/boot.txt + // VMM should make use of it to fill zero page for bzImage direct boot. pub setup_header: Option, } @@ -142,7 +141,7 @@ impl KernelLoader for Elf { /// # Arguments /// /// * `guest_mem` - The guest memory region the kernel is written to. - /// * `kernel_start` - The offset into 'guest _mem' at which to load the kernel. + /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel. /// * `kernel_image` - Input vmlinux image. /// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it. /// @@ -181,7 +180,6 @@ impl KernelLoader for Elf { return Err(Error::InvalidProgramHeaderSize); } if (ehdr.e_phoff as usize) < mem::size_of::() { - // If the program header is backwards, bail. return Err(Error::InvalidProgramHeaderOffset); } if (lowest_kernel_start.is_some()) @@ -216,7 +214,7 @@ impl KernelLoader for Elf { .seek(SeekFrom::Start(phdr.p_offset)) .map_err(|_| Error::SeekKernelStart)?; - // vmm does not specify where the kernel should be loaded, just + // if the vmm does not specify where the kernel should be loaded, just // load it to the physical address p_paddr for each segment. let mem_offset = match kernel_start { Some(start) => start @@ -234,6 +232,7 @@ impl KernelLoader for Elf { .ok_or(Error::MemoryOverflow)?; } + // elf image has no setup_header which is defined for bzImage loader_result.setup_header = None; Ok(loader_result) @@ -250,8 +249,8 @@ impl KernelLoader for BzImage { /// /// # Arguments /// - /// * `guest_mem` - The guest memory region the kernel is written to. - /// * `kernel_start` - The offset into 'guest _mem' at which to load the kernel. + /// * `guest_mem` - The guest memory where the kernel image is loaded. + /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel. /// * `kernel_image` - Input bzImage image. /// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it. /// From 97e3c54e376ec74709d2a0a1efd6d191324e4b51 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Sat, 1 Jun 2019 08:22:50 +0800 Subject: [PATCH 12/27] loader: Rename high memory field for loader trait and functions High memory is defined in linux boot protocol where the protected-mode kernel was relocated. It could be passed by VMM to loader to specify where is the bottom line of kernel image to be loaded. Rename it here to follow the linux boot protocol definition. Signed-off-by: Cathy Zhang --- src/loader/mod.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 9bb4110a..802f4933 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -125,8 +125,8 @@ pub trait KernelLoader { guest_mem: &M, kernel_start: Option, kernel_image: &mut F, - lowest_kernel_start: Option, - ) -> Result<(KernelLoaderResult)> + highmem_start_address: Option, + ) -> Result where F: Read + Seek; } @@ -143,7 +143,7 @@ impl KernelLoader for Elf { /// * `guest_mem` - The guest memory region the kernel is written to. /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel. /// * `kernel_image` - Input vmlinux image. - /// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it. + /// * `highmem_start_address` - This is the start of the high memory, kernel should above it. /// /// # Returns /// * KernelLoaderResult @@ -151,8 +151,8 @@ impl KernelLoader for Elf { guest_mem: &M, kernel_start: Option, kernel_image: &mut F, - lowest_kernel_start: Option, - ) -> Result<(KernelLoaderResult)> + highmem_start_address: Option, + ) -> Result where F: Read + Seek, { @@ -182,8 +182,8 @@ impl KernelLoader for Elf { if (ehdr.e_phoff as usize) < mem::size_of::() { return Err(Error::InvalidProgramHeaderOffset); } - if (lowest_kernel_start.is_some()) - && ((ehdr.e_entry as u64) < lowest_kernel_start.unwrap().raw_value()) + if (highmem_start_address.is_some()) + && ((ehdr.e_entry as u64) < highmem_start_address.unwrap().raw_value()) { return Err(Error::InvalidEntryAddress); } @@ -252,7 +252,7 @@ impl KernelLoader for BzImage { /// * `guest_mem` - The guest memory where the kernel image is loaded. /// * `kernel_start` - The offset into 'guest_mem' at which to load the kernel. /// * `kernel_image` - Input bzImage image. - /// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it. + /// * `highmem_start_address` - This is the start of the high memory, kernel should above it. /// /// # Returns /// * KernelLoaderResult @@ -260,8 +260,8 @@ impl KernelLoader for BzImage { guest_mem: &M, kernel_start: Option, kernel_image: &mut F, - lowest_kernel_start: Option, - ) -> Result<(KernelLoaderResult)> + highmem_start_address: Option, + ) -> Result where F: Read + Seek, { @@ -298,8 +298,8 @@ impl KernelLoader for BzImage { // verify bzImage validation by checking if code32_start, the defaults to the address of // the kernel is not lower than high memory. - if (lowest_kernel_start.is_some()) - && (u64::from(boot_header.code32_start) < lowest_kernel_start.unwrap().raw_value()) + if (highmem_start_address.is_some()) + && (u64::from(boot_header.code32_start) < highmem_start_address.unwrap().raw_value()) { return Err(Error::InvalidKernelStartAddress); } @@ -396,14 +396,14 @@ mod test { let gm = create_guest_mem(); let image = make_bzImage(); let mut kernel_start = GuestAddress(0x200000); - let mut lowest_kernel_start = GuestAddress(0x0); + let mut highmem_start_address = GuestAddress(0x0); // load bzImage with good kernel_start and himem_start setting let mut loader_result = BzImage::load( &gm, Some(kernel_start), &mut Cursor::new(&image), - Some(lowest_kernel_start), + Some(highmem_start_address), ) .unwrap(); assert_eq!(0x53726448, loader_result.setup_header.unwrap().header); @@ -429,7 +429,7 @@ mod test { &gm, None, &mut Cursor::new(&image), - Some(lowest_kernel_start), + Some(highmem_start_address), ) .unwrap(); assert_eq!(0x53726448, loader_result.setup_header.unwrap().header); @@ -448,12 +448,12 @@ mod test { // load bzImage with a bad himem setting kernel_start = GuestAddress(0x1000); - lowest_kernel_start = GuestAddress(0x200000); + highmem_start_address = GuestAddress(0x200000); let x = BzImage::load( &gm, Some(kernel_start), &mut Cursor::new(&image), - Some(lowest_kernel_start), + Some(highmem_start_address), ); assert_eq!(x.is_ok(), false); println!("load bzImage with bad himem setting \n"); @@ -464,12 +464,12 @@ mod test { let gm = create_guest_mem(); let image = make_elf_bin(); let kernel_addr = GuestAddress(0x200000); - let mut lowest_kernel_start = GuestAddress(0x0); + let mut highmem_start_address = GuestAddress(0x0); let mut loader_result = Elf::load( &gm, Some(kernel_addr), &mut Cursor::new(&image), - Some(lowest_kernel_start), + Some(highmem_start_address), ) .unwrap(); println!( @@ -487,7 +487,7 @@ mod test { &gm, None, &mut Cursor::new(&image), - Some(lowest_kernel_start), + Some(highmem_start_address), ) .unwrap(); println!( @@ -495,14 +495,14 @@ mod test { loader_result.kernel_load.raw_value() ); - lowest_kernel_start = GuestAddress(0xa00000); + highmem_start_address = GuestAddress(0xa00000); assert_eq!( Err(Error::InvalidEntryAddress), Elf::load( &gm, None, &mut Cursor::new(&image), - Some(lowest_kernel_start) + Some(highmem_start_address) ) ); } From d758d9efe5b49e9b76787494908686fc750f5b5f Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Sat, 1 Jun 2019 14:33:57 +0800 Subject: [PATCH 13/27] buildkite: Add repository post-checkout hook to upload bzImage A pre-compiled bzImage is needed for bzImage loader unit test, add this hook to prepare it in CI environment by downloading and extracting it in specified path for later test. Signed-off-by: Cathy Zhang --- .buildkite/hooks/post-checkout | 19 +++++++++++++++++++ src/loader/mod.rs | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 .buildkite/hooks/post-checkout diff --git a/.buildkite/hooks/post-checkout b/.buildkite/hooks/post-checkout new file mode 100644 index 00000000..38a88420 --- /dev/null +++ b/.buildkite/hooks/post-checkout @@ -0,0 +1,19 @@ +#!/bin/bash + +DEB_NAME="linux-image-4.9.0-9-amd64_4.9.168-1_amd64.deb" +DEB_URL="http://ftp.debian.org/debian/pool/main/l/linux/${DEB_NAME}" + +REPO_PATH="${BUILDKITE_BUILD_CHECKOUT_PATH}/linux-loader" +DEB_PATH="${REPO_PATH}/${DEB_NAME}" +EXTRACT_PATH="${REPO_PATH}/src/bzimage-archive" +BZIMAGE_PATH="${EXTRACT_PATH}/boot/vmlinuz-4.9.0-9-amd64" + +mkdir -p ${EXTRACT_PATH} + +wget $DEB_URL -P ${REPO_PATH} +dpkg-deb -x ${DEB_PATH} ${EXTRACT_PATH} + +mv ${BZIMAGE_PATH} ${REPO_PATH}/src/loader/bzimage +rm -r ${EXTRACT_PATH} +rm -f ${DEB_PATH} + diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 802f4933..bd5518cf 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -377,7 +377,7 @@ mod test { #[allow(non_snake_case)] fn make_bzImage() -> Vec { let mut v = Vec::new(); - v.extend_from_slice(include_bytes!("bzImage")); + v.extend_from_slice(include_bytes!("bzimage")); v } From 9cde9f275f331330f93823aa74395d4d705db6f2 Mon Sep 17 00:00:00 2001 From: Andreea Florescu Date: Thu, 6 Jun 2019 11:29:32 +0300 Subject: [PATCH 14/27] buildkite: Fix path in post-checkout hook The buildkite-agent actually clones the code in ${BUILDKITE_BUILD_CHECKOUT_PATH}. There is no need to add the repository name. Signed-off-by: Andreea Florescu --- .buildkite/hooks/post-checkout | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.buildkite/hooks/post-checkout b/.buildkite/hooks/post-checkout index 38a88420..d6806995 100644 --- a/.buildkite/hooks/post-checkout +++ b/.buildkite/hooks/post-checkout @@ -3,7 +3,7 @@ DEB_NAME="linux-image-4.9.0-9-amd64_4.9.168-1_amd64.deb" DEB_URL="http://ftp.debian.org/debian/pool/main/l/linux/${DEB_NAME}" -REPO_PATH="${BUILDKITE_BUILD_CHECKOUT_PATH}/linux-loader" +REPO_PATH="${BUILDKITE_BUILD_CHECKOUT_PATH}" DEB_PATH="${REPO_PATH}/${DEB_NAME}" EXTRACT_PATH="${REPO_PATH}/src/bzimage-archive" BZIMAGE_PATH="${EXTRACT_PATH}/boot/vmlinuz-4.9.0-9-amd64" @@ -13,6 +13,7 @@ mkdir -p ${EXTRACT_PATH} wget $DEB_URL -P ${REPO_PATH} dpkg-deb -x ${DEB_PATH} ${EXTRACT_PATH} + mv ${BZIMAGE_PATH} ${REPO_PATH}/src/loader/bzimage rm -r ${EXTRACT_PATH} rm -f ${DEB_PATH} From eb49f577b6f65aee20d729cc533a814150768b1e Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 7 Jun 2019 00:30:05 +0800 Subject: [PATCH 15/27] loader: Remove ignore config to run bzImage loader unit test ignore has not taken effect to avoid run bzImage loader unit test, remove it. It's required to follow steps on README.md to do the test. Signed-off-by: Cathy Zhang --- README.md | 4 ++-- src/loader/mod.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0c8920db..2126c8da 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ than the coverage reported in [tests/coverage](tests/coverage). As we don't want to distribute an entire kernel bzImage, the `load_bzImage` test is ignored by default. In order to test the bzImage support, one needs to locally build a bzImage, copy it -to the `src/loader` directory and run the ignored test: +to the `src/loader` directory and run cargo test: ```shell # Assuming your linux-loader and linux-stable are both under $LINUX_LOADER @@ -101,5 +101,5 @@ $ docker run -it \ --volume $(pwd):/linux-loader \ fandree/rust-vmm-dev $ cd linux-loader/ -$ cargo test -- --ignored +$ cargo test ``` diff --git a/src/loader/mod.rs b/src/loader/mod.rs index bd5518cf..d37f5e2b 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -391,7 +391,6 @@ mod test { #[allow(safe_packed_borrows)] #[allow(non_snake_case)] #[test] - #[ignore] fn load_bzImage() { let gm = create_guest_mem(); let image = make_bzImage(); From 81487dc3e3bf568517bb72dafe85183c2b7f3760 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 7 Jun 2019 00:56:12 +0800 Subject: [PATCH 16/27] linux-loader: Fix rustfmt errors Reformat code as cargo fmt messages indicate. Signed-off-by: Cathy Zhang --- src/lib.rs | 3 +-- src/loader/elf.rs | 2 +- src/loader/mod.rs | 8 +++++--- src/loader/struct_util.rs | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 01004ac8..4cb50e9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,10 +5,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-BSD-3-Clause file. // -// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause pub mod cmdline; pub mod loader; extern crate vm_memory; - diff --git a/src/loader/elf.rs b/src/loader/elf.rs index 4d2769f7..b7d71d7a 100644 --- a/src/loader/elf.rs +++ b/src/loader/elf.rs @@ -4,7 +4,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-BSD-3-Clause file. // -// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause /* * automatically generated by rust-bindgen diff --git a/src/loader/mod.rs b/src/loader/mod.rs index d37f5e2b..923f826d 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -112,7 +112,7 @@ impl Display for Error { pub struct KernelLoaderResult { // Address in the guest memory where the kernel image starts to be loaded pub kernel_load: GuestAddress, - // Offset in guest memory corresponding to the end of kernel image, in case that + // Offset in guest memory corresponding to the end of kernel image, in case that // device tree blob and initrd will be loaded adjacent to kernel image. pub kernel_end: GuestUsize, // This field is only for bzImage following https://www.kernel.org/doc/Documentation/x86/boot.txt @@ -227,7 +227,8 @@ impl KernelLoader for Elf { .read_exact_from(mem_offset, kernel_image, phdr.p_filesz as usize) .map_err(|_| Error::ReadKernelImage)?; - loader_result.kernel_end = mem_offset.raw_value() + loader_result.kernel_end = mem_offset + .raw_value() .checked_add(phdr.p_memsz as GuestUsize) .ok_or(Error::MemoryOverflow)?; } @@ -323,7 +324,8 @@ impl KernelLoader for BzImage { .read_exact_from(mem_offset, kernel_image, kernel_size) .map_err(|_| Error::ReadBzImageCompressedKernel)?; - loader_result.kernel_end = mem_offset.raw_value() + loader_result.kernel_end = mem_offset + .raw_value() .checked_add(kernel_size as GuestUsize) .ok_or(Error::MemoryOverflow)?; diff --git a/src/loader/struct_util.rs b/src/loader/struct_util.rs index 8454b4de..a2ef60bf 100644 --- a/src/loader/struct_util.rs +++ b/src/loader/struct_util.rs @@ -5,7 +5,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-BSD-3-Clause file. // -// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause use std; use std::io::Read; From 5be96c6fc13dc2216c5464bbdb197c25882bf631 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 7 Jun 2019 01:26:03 +0800 Subject: [PATCH 17/27] Update README and pipeline to point to rustvmm/dev container This change is made according to the following commit https://github.com/rust-vmm/rust-vmm-container/commit/f5c16fb68599ba9239215ef598d8d574d252e001 Signed-off-by: Cathy Zhang --- .buildkite/pipeline.yml | 10 +++++----- README.md | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 8a072660..f86d3037 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -8,7 +8,7 @@ steps: platform: x86_64.metal plugins: - docker#v3.0.1: - image: "fandree/rust-vmm-dev" + image: "rustvmm/dev:v2" always-pull: true - label: "style" @@ -19,7 +19,7 @@ steps: platform: x86_64.metal plugins: - docker#v3.0.1: - image: "fandree/rust-vmm-dev" + image: "rustvmm/dev:v2" always-pull: true - label: "unittests-gnu-x86" @@ -32,7 +32,7 @@ steps: plugins: - docker#v3.0.1: privileged: true - image: "fandree/rust-vmm-dev" + image: "rustvmm/dev:v2" always-pull: true - label: "clippy-x86" @@ -44,7 +44,7 @@ steps: platform: x86_64.metal plugins: - docker#v3.0.1: - image: "fandree/rust-vmm-dev" + image: "rustvmm/dev:v2" always-pull: true - label: "coverage-x86" @@ -57,5 +57,5 @@ steps: plugins: - docker#v3.0.1: privileged: true - image: "fandree/rust-vmm-dev" + image: "rustvmm/dev:v2" always-pull: true diff --git a/README.md b/README.md index 2126c8da..0fae1780 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ use the dev-container on both x86 and arm64. docker run -it \ --security-opt seccomp=unconfined \ --volume $(pwd):/linux-loader \ - fandree/rust-vmm-dev + rustvmm/dev:v2 cd linux-loader/ cargo test ``` @@ -64,7 +64,7 @@ coverage before submitting a PR, run the coverage test: docker run -it \ --security-opt seccomp=unconfined \ --volume $(pwd):/linux-loader \ - fandree/rust-vmm-dev + rustvmm/dev:v2 cd linux-loader/ pytest --profile=devel tests/test_coverage.py ``` @@ -99,7 +99,7 @@ $ cd $LINUX_LOADER/linux-loader $ docker run -it \ --security-opt seccomp=unconfined \ --volume $(pwd):/linux-loader \ - fandree/rust-vmm-dev + rustvmm/dev:v2 $ cd linux-loader/ $ cargo test ``` From a2d63ed342ae55af9572d0ddc67dc1ecf023b88b Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 7 Jun 2019 03:23:44 +0800 Subject: [PATCH 18/27] loader: Add elf and bzimage features Add feature setting to separate elf and bzImage support, which will make convenience for VMM to select loader type based on its needs. Signed-off-by: Cathy Zhang --- .buildkite/pipeline.yml | 50 ++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 5 +++++ src/loader/mod.rs | 11 +++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index f86d3037..287c0366 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -34,7 +34,55 @@ steps: privileged: true image: "rustvmm/dev:v2" always-pull: true - + + - label: "build-gnu-x86-elf" + commands: + - cargo build --release --features elf + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "unittests-gnu-x86-elf" + commands: + - cargo test --features elf + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + + - label: "build-gnu-x86-bzimage" + commands: + - cargo build --release --features bzimage + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "unittests-gnu-x86-bzimage" + commands: + - cargo test --features bzimage + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + - label: "clippy-x86" commands: - cargo clippy --all -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index 3bde4e1f..1994eb90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,11 @@ authors = ["Cathy Zhang "] edition = "2018" license = "Apache-2.0 AND BSD-3-Clause" +[features] +default = ["elf"] +elf = [] +bzimage = [] + [dependencies.vm-memory] git = "https://github.com/rust-vmm/vm-memory" features = ["backend-mmap"] diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 923f826d..dd21a164 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -131,8 +131,10 @@ pub trait KernelLoader { F: Read + Seek; } +#[cfg(feature = "elf")] pub struct Elf; +#[cfg(feature = "elf")] impl KernelLoader for Elf { /// Loads a kernel from a vmlinux elf image to a slice /// @@ -240,8 +242,10 @@ impl KernelLoader for Elf { } } +#[cfg(feature = "bzimage")] pub struct BzImage; +#[cfg(feature = "bzimage")] impl KernelLoader for BzImage { /// Loads a bzImage /// @@ -377,6 +381,7 @@ mod test { } #[allow(non_snake_case)] + #[cfg(feature = "bzimage")] fn make_bzImage() -> Vec { let mut v = Vec::new(); v.extend_from_slice(include_bytes!("bzimage")); @@ -384,6 +389,7 @@ mod test { } // Elf64 image that prints hello world on x86_64. + #[cfg(feature = "elf")] fn make_elf_bin() -> Vec { let mut v = Vec::new(); v.extend_from_slice(include_bytes!("test_elf.bin")); @@ -393,6 +399,7 @@ mod test { #[allow(safe_packed_borrows)] #[allow(non_snake_case)] #[test] + #[cfg(feature = "bzimage")] fn load_bzImage() { let gm = create_guest_mem(); let image = make_bzImage(); @@ -461,6 +468,7 @@ mod test { } #[test] + #[cfg(feature = "elf")] fn load_elf() { let gm = create_guest_mem(); let image = make_elf_bin(); @@ -550,6 +558,7 @@ mod test { assert_eq!(val, '\0' as u8); } + #[cfg(feature = "elf")] #[test] fn bad_magic() { let gm = create_guest_mem(); @@ -562,6 +571,7 @@ mod test { ); } + #[cfg(feature = "elf")] #[test] fn bad_endian() { // Only little endian is supported @@ -575,6 +585,7 @@ mod test { ); } + #[cfg(feature = "elf")] #[test] fn bad_phoff() { // program header has to be past the end of the elf header From 5b6f29eb699c7c099e27ffd9cb4585207224e807 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 7 Jun 2019 03:26:51 +0800 Subject: [PATCH 19/27] loader: Condition crates import and usage by feature We only need SeekFrom, Cursor, struct_util and mem when either ELF or bzImage are selected. We only need read_struct_slice for ELF. Signed-off-by: Samuel Ortiz --- src/loader/mod.rs | 7 ++++++- src/loader/struct_util.rs | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index dd21a164..ee7c03ad 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -19,7 +19,10 @@ extern crate vm_memory; use std::error::{self, Error as KernelLoaderError}; use std::ffi::CStr; use std::fmt::{self, Display}; -use std::io::{Read, Seek, SeekFrom}; +#[cfg(any(feature = "elf", feature = "bzimage"))] +use std::io::SeekFrom; +use std::io::{Read, Seek}; +#[cfg(feature = "elf")] use std::mem; use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestUsize}; @@ -36,6 +39,7 @@ pub mod bootparam; #[allow(non_upper_case_globals)] #[cfg_attr(feature = "cargo-clippy", allow(clippy::all))] mod elf; +#[cfg(any(feature = "elf", feature = "bzimage"))] mod struct_util; #[derive(Debug, PartialEq)] @@ -371,6 +375,7 @@ pub fn load_cmdline( #[cfg(test)] mod test { use super::*; + #[cfg(any(feature = "elf", feature = "bzimage"))] use std::io::Cursor; use vm_memory::{Address, GuestAddress, GuestMemoryMmap}; diff --git a/src/loader/struct_util.rs b/src/loader/struct_util.rs index a2ef60bf..716282c4 100644 --- a/src/loader/struct_util.rs +++ b/src/loader/struct_util.rs @@ -40,6 +40,7 @@ pub unsafe fn read_struct(f: &mut F, out: &mut T) -> Result<() /// /// * `f` - The input to read from. Often this is a file. /// * `len` - The number of structs to fill with data read from `f`. +#[cfg(feature = "elf")] pub unsafe fn read_struct_slice(f: &mut F, len: usize) -> Result> { let mut out: Vec = Vec::with_capacity(len); out.set_len(len); @@ -114,6 +115,7 @@ mod tests { } #[test] + #[cfg(feature = "elf")] fn struct_slice_read() { let orig = vec![ TestRead { From f74075eb883eb74f5be235a0f57560242777080d Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 7 Jun 2019 03:27:26 +0800 Subject: [PATCH 20/27] tests: Update coverage coverage-x86 pytest in buildkite failed with message indicating that coverage number is changed. Update this to have test passed. Signed-off-by: Cathy Zhang --- tests/coverage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/coverage b/tests/coverage index aca6ad82..82645f51 100644 --- a/tests/coverage +++ b/tests/coverage @@ -1 +1 @@ -63.0 \ No newline at end of file +83.6 From 983b4af6fb1302c2c15d981e2082c76042d869a2 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Fri, 7 Jun 2019 04:11:05 +0800 Subject: [PATCH 21/27] tests: Update test_coverage.py Update cargo kcov with features setting, and exclude coverage test for autogenerated files: elf.rs and bootparam.rs Signed-off-by: Cathy Zhang --- tests/test_coverage.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_coverage.py b/tests/test_coverage.py index c009f8e0..f94d74fa 100644 --- a/tests/test_coverage.py +++ b/tests/test_coverage.py @@ -29,11 +29,13 @@ def _get_current_coverage(): exclude_pattern = ( '${CARGO_HOME:-$HOME/.cargo/},' 'usr/lib/,' - 'lib/' + 'lib/,' + 'bootparam.rs,' + 'elf.rs' ) exclude_region = "'mod tests {'" - kcov_cmd = "CARGO_TARGET_DIR={} cargo kcov --all " \ + kcov_cmd = "CARGO_TARGET_DIR={} cargo kcov --all --features=elf,bzimage " \ "--output {} -- " \ "--exclude-region={} " \ "--exclude-pattern={} " \ From 7e51de8994397ae6dff4da0f762ab66b16250bb3 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 7 Jun 2019 11:03:47 +0200 Subject: [PATCH 22/27] buildkite: Switch to the rust-vmm-ci pipeline We now have 2 pipelines: One coming from rust-vmm-ci and another one specific to linux-loader. The latter builds with all features enabled. Next step: Include rust-vmm-ci as a git submodule. Signed-off-by: Samuel Ortiz --- .buildkite/pipeline.yml | 91 +------------- .buildkite/rust-vmm-ci-pipeline.yml | 176 ++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 87 deletions(-) create mode 100644 .buildkite/rust-vmm-ci-pipeline.yml diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 287c0366..74264c5a 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,64 +1,6 @@ +# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 steps: - - label: "build-gnu-x86" - commands: - - cargo build --release - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - image: "rustvmm/dev:v2" - always-pull: true - - - label: "style" - command: cargo fmt --all -- --check - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - image: "rustvmm/dev:v2" - always-pull: true - - - label: "unittests-gnu-x86" - commands: - - cargo test - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - privileged: true - image: "rustvmm/dev:v2" - always-pull: true - - - label: "build-gnu-x86-elf" - commands: - - cargo build --release --features elf - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - image: "rustvmm/dev:v2" - always-pull: true - - - label: "unittests-gnu-x86-elf" - commands: - - cargo test --features elf - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - privileged: true - image: "rustvmm/dev:v2" - - label: "build-gnu-x86-bzimage" commands: - cargo build --release --features bzimage @@ -71,39 +13,14 @@ steps: image: "rustvmm/dev:v2" always-pull: true - - label: "unittests-gnu-x86-bzimage" - commands: - - cargo test --features bzimage - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - privileged: true - image: "rustvmm/dev:v2" - - - label: "clippy-x86" - commands: - - cargo clippy --all -- -D warnings - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - image: "rustvmm/dev:v2" - always-pull: true - - - label: "coverage-x86" + - label: "build-musl-x86-bzimage" commands: - - pytest tests/test_coverage.py + - cargo build --release --features bzimage --target x86_64-unknown-linux-musl retry: automatic: false agents: platform: x86_64.metal plugins: - docker#v3.0.1: - privileged: true image: "rustvmm/dev:v2" always-pull: true diff --git a/.buildkite/rust-vmm-ci-pipeline.yml b/.buildkite/rust-vmm-ci-pipeline.yml new file mode 100644 index 00000000..39d19757 --- /dev/null +++ b/.buildkite/rust-vmm-ci-pipeline.yml @@ -0,0 +1,176 @@ +# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +steps: + - label: "build-gnu-x86" + commands: + - cargo build --release + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "build-gnu-arm" + commands: + - cargo build --release + retry: + automatic: false + agents: + platform: arm.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "build-musl-x86" + commands: + - cargo build --release --target x86_64-unknown-linux-musl + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "build-musl-arm" + commands: + - cargo build --release --target aarch64-unknown-linux-musl + retry: + automatic: false + agents: + platform: arm.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "style" + command: cargo fmt --all -- --check + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "unittests-gnu-x86" + commands: + - cargo test --all-features + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + always-pull: true + + - label: "unittests-gnu-arm" + commands: + - cargo test --all-features + retry: + automatic: false + agents: + platform: arm.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + always-pull: true + + - label: "unittests-musl-x86" + command: + - cargo test --all-features --target x86_64-unknown-linux-musl + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + always-pull: true + + - label: "unittests-musl-arm" + command: + - cargo test --all-features --target aarch64-unknown-linux-musl + retry: + automatic: false + agents: + platform: arm.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + always-pull: true + + - label: "clippy-x86" + commands: + - cargo clippy --all -- -D warnings + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "clippy-arm" + commands: + - cargo clippy --all -- -D warnings + retry: + automatic: false + agents: + platform: arm.metal + plugins: + - docker#v3.0.1: + image: "rustvmm/dev:v2" + always-pull: true + + - label: "check-warnings-x86" + commands: + - RUSTFLAGS="-D warnings" cargo check --all-targets + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + always-pull: true + + - label: "check-warnings-arm" + command: + - RUSTFLAGS="-D warnings" cargo check --all-targets + retry: + automatic: false + agents: + platform: arm.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + always-pull: true + + - label: "coverage-x86" + commands: + - pytest tests/test_coverage.py + retry: + automatic: false + agents: + platform: x86_64.metal + plugins: + - docker#v3.0.1: + privileged: true + image: "rustvmm/dev:v2" + always-pull: true From d67f657570f8e9fdf1573c036296466ab7d9c1ca Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 7 Jun 2019 11:32:07 +0200 Subject: [PATCH 23/27] build: Fix the musl unit tests Signed-off-by: Samuel Ortiz --- .cargo/config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .cargo/config diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 00000000..ba63e46b --- /dev/null +++ b/.cargo/config @@ -0,0 +1,3 @@ +[target.aarch64-unknown-linux-musl] +rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lgcc" ] + From 7d7e03de68d8f52599601d8a2bc1a4e38f7b8c7d Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 7 Jun 2019 12:25:03 +0200 Subject: [PATCH 24/27] lib: Force public interfaces documentation ...and actually document them. Signed-off-by: Samuel Ortiz --- src/lib.rs | 19 +++++++++++++++++ src/loader/mod.rs | 52 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4cb50e9e..fadbd490 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,25 @@ // // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause +#![deny(missing_docs)] + +//! A Linux kernel image loading crate. +//! +//! This crate offers support for loading raw ELF (vmlinux) and compressed +//! big zImage (bzImage) kernel images. +//! Support for any other kernel image format can be added by implementing +//! the KernelLoader. +//! +//! # Platform support +//! +//! - x86_64 +//! +//! This crates only supports x86_64 platforms because it implements support +//! for kernel image formats (vmlinux and bzImage) that are x86 specific. +//! +//! Extending it to support other kernel image formats (e.g. ARM's Image) +//! will make it consumable by other platforms. + pub mod cmdline; pub mod loader; diff --git a/src/loader/mod.rs b/src/loader/mod.rs index ee7c03ad..303977e5 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -31,6 +31,7 @@ use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestUsize}; #[allow(non_camel_case_types)] #[allow(non_snake_case)] #[allow(non_upper_case_globals)] +#[allow(missing_docs)] #[cfg_attr(feature = "cargo-clippy", allow(clippy::all))] pub mod bootparam; #[allow(dead_code)] @@ -43,33 +44,55 @@ mod elf; mod struct_util; #[derive(Debug, PartialEq)] +/// Kernel loader errors. pub enum Error { + /// Loaded big endian binary on a little endian platform. BigEndianElfOnLittle, + /// Failed writing command line to guest memory. CommandLineCopy, + /// Command line overflowed guest memory. CommandLineOverflow, + /// Invalid ELF magic number InvalidElfMagicNumber, + /// Invalid program header size. InvalidProgramHeaderSize, + /// Invalid program header offset. InvalidProgramHeaderOffset, + /// Invalid program header address. InvalidProgramHeaderAddress, + /// Invalid entry address. InvalidEntryAddress, + /// Invalid bzImage binary. InvalidBzImage, + /// Invalid kernel start address. InvalidKernelStartAddress, - InitrdImageSizeTooLarge, + /// Memory to load kernel image is too small. MemoryOverflow, + /// Unable to read ELF header. ReadElfHeader, + /// Unable to read kernel image. ReadKernelImage, + /// Unable to read program header. ReadProgramHeader, + /// Unable to read bzImage header. ReadBzImageHeader, + /// Unable to read bzImage compressed image. ReadBzImageCompressedKernel, - ReadInitrdImage, + /// Unable to seek to kernel start. SeekKernelStart, + /// Unable to seek to ELF start. SeekElfStart, + /// Unable to seek to program header. SeekProgramHeader, + /// Unable to seek to bzImage end. SeekBzImageEnd, + /// Unable to seek to bzImage header. SeekBzImageHeader, + /// Unable to seek to bzImage compressed kernel. SeekBzImageCompressedKernel, - SeekInitrdImage, } + +/// A specialized `Result` type for the kernel loader. pub type Result = std::result::Result; impl error::Error for Error { @@ -87,21 +110,18 @@ impl error::Error for Error { Error::InvalidEntryAddress => "Invalid entry address", Error::InvalidBzImage => "Invalid bzImage", Error::InvalidKernelStartAddress => "Invalid kernel start address", - Error::InitrdImageSizeTooLarge => "Initrd image size too large", Error::MemoryOverflow => "Memory to load kernel image is not enough", Error::ReadElfHeader => "Unable to read elf header", Error::ReadKernelImage => "Unable to read kernel image", Error::ReadProgramHeader => "Unable to read program header", Error::ReadBzImageHeader => "Unable to read bzImage header", Error::ReadBzImageCompressedKernel => "Unable to read bzImage compressed kernel", - Error::ReadInitrdImage => "Unable to read initrd image", Error::SeekKernelStart => "Unable to seek to kernel start", Error::SeekElfStart => "Unable to seek to elf start", Error::SeekProgramHeader => "Unable to seek to program header", Error::SeekBzImageEnd => "Unable to seek bzImage end", Error::SeekBzImageHeader => "Unable to seek bzImage header", Error::SeekBzImageCompressedKernel => "Unable to seek bzImage compressed kernel", - Error::SeekInitrdImage => "Unable to seek initrd image", } } } @@ -113,18 +133,26 @@ impl Display for Error { } #[derive(Debug, Default, Copy, Clone, PartialEq)] +/// Result of the KernelLoader load() call. +/// +/// This specifies where the kernel is loading and passes additional +/// information for the rest of the boot process to be completed by +/// the VMM. pub struct KernelLoaderResult { - // Address in the guest memory where the kernel image starts to be loaded + /// Address in the guest memory where the kernel image starts to be loaded pub kernel_load: GuestAddress, - // Offset in guest memory corresponding to the end of kernel image, in case that - // device tree blob and initrd will be loaded adjacent to kernel image. + /// Offset in guest memory corresponding to the end of kernel image, in case that + /// device tree blob and initrd will be loaded adjacent to kernel image. pub kernel_end: GuestUsize, - // This field is only for bzImage following https://www.kernel.org/doc/Documentation/x86/boot.txt - // VMM should make use of it to fill zero page for bzImage direct boot. + /// This field is only for bzImage following https://www.kernel.org/doc/Documentation/x86/boot.txt + /// VMM should make use of it to fill zero page for bzImage direct boot. pub setup_header: Option, } +/// A kernel image loading support must implement the KernelLoader trait. +/// The only method to be implemented is the load one, returning a KernelLoaderResult structure. pub trait KernelLoader { + /// How to load a specific kernel image format into the guest memory. fn load( guest_mem: &M, kernel_start: Option, @@ -136,6 +164,7 @@ pub trait KernelLoader { } #[cfg(feature = "elf")] +/// Raw ELF (a.k.a. vmlinux) kernel image support. pub struct Elf; #[cfg(feature = "elf")] @@ -247,6 +276,7 @@ impl KernelLoader for Elf { } #[cfg(feature = "bzimage")] +/// Big zImage (bzImage) kernel image support. pub struct BzImage; #[cfg(feature = "bzimage")] From eeb3c5e0bf4ea1cee5f5ebcf07a88aec11a92dec Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 7 Jun 2019 12:32:06 +0200 Subject: [PATCH 25/27] loader: Mark both ELF and bzImage supports x86 specific bzImage is x86 specific and although ARM supports loading uncompressed kernel images, it follows the Image format (raw ELF + some headers). Signed-off-by: Samuel Ortiz --- src/loader/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 303977e5..8ef8f8f3 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -20,9 +20,11 @@ use std::error::{self, Error as KernelLoaderError}; use std::ffi::CStr; use std::fmt::{self, Display}; #[cfg(any(feature = "elf", feature = "bzimage"))] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use std::io::SeekFrom; use std::io::{Read, Seek}; #[cfg(feature = "elf")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use std::mem; use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestUsize}; @@ -41,6 +43,7 @@ pub mod bootparam; #[cfg_attr(feature = "cargo-clippy", allow(clippy::all))] mod elf; #[cfg(any(feature = "elf", feature = "bzimage"))] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod struct_util; #[derive(Debug, PartialEq)] @@ -164,10 +167,12 @@ pub trait KernelLoader { } #[cfg(feature = "elf")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] /// Raw ELF (a.k.a. vmlinux) kernel image support. pub struct Elf; #[cfg(feature = "elf")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] impl KernelLoader for Elf { /// Loads a kernel from a vmlinux elf image to a slice /// @@ -276,10 +281,12 @@ impl KernelLoader for Elf { } #[cfg(feature = "bzimage")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] /// Big zImage (bzImage) kernel image support. pub struct BzImage; #[cfg(feature = "bzimage")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] impl KernelLoader for BzImage { /// Loads a bzImage /// @@ -406,6 +413,7 @@ pub fn load_cmdline( mod test { use super::*; #[cfg(any(feature = "elf", feature = "bzimage"))] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use std::io::Cursor; use vm_memory::{Address, GuestAddress, GuestMemoryMmap}; @@ -417,6 +425,7 @@ mod test { #[allow(non_snake_case)] #[cfg(feature = "bzimage")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn make_bzImage() -> Vec { let mut v = Vec::new(); v.extend_from_slice(include_bytes!("bzimage")); @@ -425,6 +434,7 @@ mod test { // Elf64 image that prints hello world on x86_64. #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn make_elf_bin() -> Vec { let mut v = Vec::new(); v.extend_from_slice(include_bytes!("test_elf.bin")); @@ -435,6 +445,7 @@ mod test { #[allow(non_snake_case)] #[test] #[cfg(feature = "bzimage")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn load_bzImage() { let gm = create_guest_mem(); let image = make_bzImage(); @@ -504,6 +515,7 @@ mod test { #[test] #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn load_elf() { let gm = create_guest_mem(); let image = make_elf_bin(); @@ -594,6 +606,7 @@ mod test { } #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[test] fn bad_magic() { let gm = create_guest_mem(); @@ -607,6 +620,7 @@ mod test { } #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[test] fn bad_endian() { // Only little endian is supported @@ -621,6 +635,7 @@ mod test { } #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[test] fn bad_phoff() { // program header has to be past the end of the elf header From 891ea4f0af62b2f80f5a3ddbbb6be588b19a78da Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 7 Jun 2019 16:30:38 +0200 Subject: [PATCH 26/27] loader: Fix unit test camel casing Signed-off-by: Samuel Ortiz --- src/loader/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 8ef8f8f3..b130113e 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -423,10 +423,9 @@ mod test { GuestMemoryMmap::new(&[(GuestAddress(0x0), (MEM_SIZE as usize))]).unwrap() } - #[allow(non_snake_case)] #[cfg(feature = "bzimage")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn make_bzImage() -> Vec { + fn make_bzimage() -> Vec { let mut v = Vec::new(); v.extend_from_slice(include_bytes!("bzimage")); v @@ -448,7 +447,7 @@ mod test { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn load_bzImage() { let gm = create_guest_mem(); - let image = make_bzImage(); + let image = make_bzimage(); let mut kernel_start = GuestAddress(0x200000); let mut highmem_start_address = GuestAddress(0x0); From 43f5c6bcc6fdb18dbd715a1e528bb0ec270d4fae Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Fri, 14 Jun 2019 11:42:08 -0700 Subject: [PATCH 27/27] Rely on right branch of vm-memory for virtio-fs Signed-off-by: Sebastien Boeuf --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1994eb90..19df3f5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,5 +11,6 @@ elf = [] bzimage = [] [dependencies.vm-memory] -git = "https://github.com/rust-vmm/vm-memory" +git = "https://github.com/alexandruag/vm-memory" +branch = "file_backed_regions" features = ["backend-mmap"]