Port Android boot image structures and parsing to Rust

Initial definitions and support for handling Android boot images in
Rust. Contains parallel, ABI compatible definitions for all structs in
bootimg.h as well as parsing helper functions. All parsing functions
are zero-copy.

Test: add unit tests for parsing boot image headers

Change-Id: I4a3f75089075e11231fe91061f320ed34d28dc93
diff --git a/rust/Android.bp b/rust/Android.bp
new file mode 100644
index 0000000..353070e
--- /dev/null
+++ b/rust/Android.bp
@@ -0,0 +1,50 @@
+// Copyright 2023 The Android Open Source Project
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "libbootimg_private_defaults",
+    srcs: ["bootimg_priv.rs"],
+    rustlibs: ["libzerocopy"],
+    lints: "none",
+}
+
+rust_library {
+    name: "libbootimg_private",
+    crate_name: "bootimg_private",
+    vendor_available: true,
+    defaults: ["libbootimg_private_defaults"],
+    host_supported: true,
+    visibility: [":__subpackages__"],
+}
+
+rust_test_host {
+    name: "libbootimg_tests_priv",
+    auto_gen_config: true,
+    defaults: ["libbootimg_private_defaults"],
+}
+
+rust_defaults {
+    name: "libbootimg_defaults",
+    srcs: ["bootimg.rs"],
+    rustlibs: [
+        "libzerocopy",
+        "libbootimg_private",
+    ],
+}
+
+rust_library {
+    name: "libbootimg",
+    crate_name: "bootimg",
+    vendor_available: true,
+    host_supported: true,
+    defaults: ["libbootimg_defaults"],
+}
+
+rust_test_host {
+    name: "libbootimg_tests",
+    auto_gen_config: true,
+    defaults: ["libbootimg_defaults"],
+}
diff --git a/rust/bindgen.sh b/rust/bindgen.sh
new file mode 100755
index 0000000..b854d10
--- /dev/null
+++ b/rust/bindgen.sh
@@ -0,0 +1,76 @@
+#! /usr/bin/env bash
+# Copyright 2023, The Android Open Source Project
+#
+# 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.
+
+set -e
+
+# Run this script to regenerate bootimg_priv.rs if
+# include/bootimg/bootimg.h ever changes.
+# The rust_bindgen rule is not cooperative, causing custom derive types
+# to not percolate to the generated structures.
+# It's just easier to do all the munging in a script.
+
+SCRATCH_DIR=$(mktemp -d)
+
+cleanup (){
+    rm -rf ${SCRATCH_DIR}
+}
+
+trap cleanup EXIT
+pushd ~/aosp > /dev/null
+
+BOOTIMG_DIR=$(realpath system/tools/mkbootimg/)
+# The stdint include generates a lot of unnecessary types that the
+# generated rust bindings really don't need.
+BLOCKED_TYPES_RE="__.+|.?int.+"
+# The stdint include generates a lot of unnecessary constants that the
+# generated rust bindings really don't need.
+BLOCKED_ITEMS_RE="_.+|.?INT.+|PTR.+|ATOMIC.+|.+SOURCE|.+_H|SIG_.+|SIZE_.+|.?CHAR.+"
+CUSTOM_STRUCT_RE="(vendor_)?(boot_img_hdr|ramdisk_table_entry)_v\d+"
+CUSTOM_STRUCT_DERIVES="AsBytes,FromBytes,PartialEq,Copy,Clone,Debug"
+BINDGEN_FLAGS="--use-core --with-derive-default"
+BOOTIMG_PRIV=${BOOTIMG_DIR}/rust/bootimg_priv.rs
+
+# We need C++ isms, and the only obvious way to convince bindgen
+# that the source is C++ is with a C++ extension.
+cp ${BOOTIMG_DIR}/include/bootimg/bootimg.h ${SCRATCH_DIR}/bootimg.hpp
+
+./out/host/linux-x86/bin/bindgen \
+    --blocklist-type="${BLOCKED_TYPES_RE}" \
+    --blocklist-item="${BLOCKED_ITEMS_RE}" \
+    --with-derive-custom-struct="${CUSTOM_STRUCT_RE}=${CUSTOM_STRUCT_DERIVES}" \
+    ${BINDGEN_FLAGS} \
+    ${SCRATCH_DIR}/bootimg.hpp \
+    -o ${SCRATCH_DIR}/bootimg_gen.rs
+
+cat << EOF | cat - ${SCRATCH_DIR}/bootimg_gen.rs > ${BOOTIMG_PRIV}
+// Copyright $(date +%Y), The Android Open Source Project
+//
+// 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.
+
+use zerocopy::{AsBytes, FromBytes};
+
+EOF
+
+rustfmt ${BOOTIMG_PRIV} --config-path system/tools/aidl/rustfmt.toml
diff --git a/rust/bootimg.rs b/rust/bootimg.rs
new file mode 100644
index 0000000..bc83eb1
--- /dev/null
+++ b/rust/bootimg.rs
@@ -0,0 +1,399 @@
+// Copyright 2023, The Android Open Source Project
+//
+// 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.
+
+//! The public interface for bootimg structs
+use zerocopy::{ByteSlice, LayoutVerified};
+
+use bootimg_private::{
+    boot_img_hdr_v0, boot_img_hdr_v1, boot_img_hdr_v2, boot_img_hdr_v3, boot_img_hdr_v4,
+    vendor_boot_img_hdr_v3, vendor_boot_img_hdr_v4, BOOT_MAGIC, BOOT_MAGIC_SIZE, VENDOR_BOOT_MAGIC,
+    VENDOR_BOOT_MAGIC_SIZE,
+};
+
+/// Generalized boot image from a backing store of bytes.
+#[derive(PartialEq, Debug)]
+pub enum BootImage<B: ByteSlice + PartialEq> {
+    /// Version 0 header
+    V0(LayoutVerified<B, boot_img_hdr_v0>),
+    /// Version 1 header
+    V1(LayoutVerified<B, boot_img_hdr_v1>),
+    /// Version 2 header
+    V2(LayoutVerified<B, boot_img_hdr_v2>),
+    /// Version 3 header
+    V3(LayoutVerified<B, boot_img_hdr_v3>),
+    /// Version 4 header
+    V4(LayoutVerified<B, boot_img_hdr_v4>),
+}
+
+/// Generalized vendor boot header from a backing store of bytes.
+#[derive(PartialEq, Debug)]
+pub enum VendorImageHeader<B: ByteSlice + PartialEq> {
+    /// Version 3 header
+    V3(LayoutVerified<B, vendor_boot_img_hdr_v3>),
+    /// Version 4 header
+    V4(LayoutVerified<B, vendor_boot_img_hdr_v4>),
+}
+
+/// Boot related errors.
+#[derive(PartialEq, Debug)]
+pub enum ImageError {
+    /// The provided buffer was too small to hold a header.
+    BufferTooSmall,
+    /// The magic string was incorrect.
+    BadMagic,
+    /// The header version present is not supported.
+    UnexpectedVersion,
+    /// Catch-all for remaining errors.
+    Unknown,
+}
+
+impl core::fmt::Display for ImageError {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        let str = match self {
+            Self::BufferTooSmall => "The provided buffer is too small",
+            Self::BadMagic => "The magic string is incorrect",
+            Self::UnexpectedVersion => "Header version is not supported",
+            Self::Unknown => "Unknown error",
+        };
+        write!(f, "{str}")
+    }
+}
+
+/// Common result type for use with boot headers
+pub type BootResult<T> = Result<T, ImageError>;
+
+fn parse_header<B: ByteSlice + PartialEq, T>(buffer: B) -> BootResult<LayoutVerified<B, T>> {
+    Ok(LayoutVerified::<B, T>::new_from_prefix(buffer).ok_or(ImageError::BufferTooSmall)?.0)
+}
+
+impl<B: ByteSlice + PartialEq> BootImage<B> {
+    /// Given a byte buffer, attempt to parse the contents and return a zero-copy reference
+    /// to the associated boot image header.
+    ///
+    /// # Arguments
+    /// * `buffer` - buffer to parse
+    ///
+    /// # Returns
+    ///
+    /// * `Ok(BootImage)` - if parsing was successful.
+    /// * `Err(ImageError)` - if `buffer` does not contain a valid boot image header.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use bootimg::BootImage;
+    ///
+    /// let mut buffer = [0; 4096];
+    /// // Not shown: read first 4096 bytes of boot image into buffer
+    /// let header = BootImage::parse(&buffer[..]).unwrap();
+    /// ```
+    pub fn parse(buffer: B) -> BootResult<Self> {
+        let magic_size = BOOT_MAGIC_SIZE as usize;
+        // Note: even though the v3 header is not a prefix for the v0, v1, or v2 header,
+        // the version and the magic string exist at the same offset and have the same types.
+        // Make a v3 temporary because it is the smallest.
+        let (hdr, _) =
+            LayoutVerified::<&[u8], boot_img_hdr_v3>::new_from_prefix(buffer.get(..).unwrap())
+                .ok_or(ImageError::BufferTooSmall)?;
+
+        if hdr.magic.ne(&BOOT_MAGIC[..magic_size]) {
+            return Err(ImageError::BadMagic);
+        }
+
+        match hdr.header_version {
+            0 => Ok(Self::V0(parse_header::<B, boot_img_hdr_v0>(buffer)?)),
+            1 => Ok(Self::V1(parse_header::<B, boot_img_hdr_v1>(buffer)?)),
+            2 => Ok(Self::V2(parse_header::<B, boot_img_hdr_v2>(buffer)?)),
+            3 => Ok(Self::V3(parse_header::<B, boot_img_hdr_v3>(buffer)?)),
+            4 => Ok(Self::V4(parse_header::<B, boot_img_hdr_v4>(buffer)?)),
+            _ => Err(ImageError::UnexpectedVersion),
+        }
+    }
+}
+
+impl<B: ByteSlice + PartialEq> VendorImageHeader<B> {
+    /// Given a byte buffer, attempt to parse the contents and return a zero-copy reference
+    /// to the associated vendor boot image header.
+    ///
+    /// # Arguments
+    /// * `buffer` - buffer to parse
+    ///
+    /// # Returns
+    ///
+    /// * `Ok(VendorImageHeader)` - if parsing was successful.
+    /// * `Err(ImageError)` - If `buffer` does not contain a valid boot image header.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use bootimg::VendorImageHeader;
+    ///
+    /// let mut buffer = [0; 4096];
+    /// // Not shown: read first 4096 bytes of vendor image into buffer
+    /// let header = VendorImageHeader::parse(&buffer[..]).unwrap();
+    /// ```
+    pub fn parse(buffer: B) -> BootResult<Self> {
+        let magic_size = VENDOR_BOOT_MAGIC_SIZE as usize;
+        let (hdr, _) = LayoutVerified::<&[u8], vendor_boot_img_hdr_v3>::new_from_prefix(
+            buffer.get(..).unwrap(),
+        )
+        .ok_or(ImageError::BufferTooSmall)?;
+
+        if hdr.magic.ne(&VENDOR_BOOT_MAGIC[..magic_size]) {
+            return Err(ImageError::BadMagic);
+        }
+
+        match hdr.header_version {
+            3 => Ok(Self::V3(parse_header::<B, vendor_boot_img_hdr_v3>(buffer)?)),
+            4 => Ok(Self::V4(parse_header::<B, vendor_boot_img_hdr_v4>(buffer)?)),
+            _ => Err(ImageError::UnexpectedVersion),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use zerocopy::AsBytes;
+
+    const MAGIC_SIZE: usize = BOOT_MAGIC_SIZE as usize;
+    const VENDOR_MAGIC_SIZE: usize = VENDOR_BOOT_MAGIC_SIZE as usize;
+
+    pub fn add<T: AsBytes>(buffer: &mut [u8], t: T) {
+        t.write_to_prefix(buffer).unwrap();
+    }
+
+    #[test]
+    fn buffer_too_small_for_version() {
+        let buffer = [0; 40];
+        assert_eq!(BootImage::parse(&buffer[..]), Err(ImageError::BufferTooSmall));
+    }
+
+    #[test]
+    fn buffer_too_small_valid_version() {
+        // Note: because the v1 header fully encapsulates the v0 header,
+        // we can trigger a buffer-too-small error by providing
+        // a perfectly valid v0 header and changing the version to 1.
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v0>()];
+        add::<boot_img_hdr_v0>(
+            &mut buffer,
+            boot_img_hdr_v0 {
+                magic: BOOT_MAGIC[0..MAGIC_SIZE].try_into().unwrap(),
+                header_version: 1,
+                ..Default::default()
+            },
+        );
+        assert_eq!(BootImage::parse(&buffer[..]), Err(ImageError::BufferTooSmall));
+    }
+
+    #[test]
+    fn bad_magic() {
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v0>()];
+        add::<boot_img_hdr_v0>(
+            &mut buffer,
+            boot_img_hdr_v0 { magic: *b"ANDROGEN", ..Default::default() },
+        );
+        assert_eq!(BootImage::parse(&buffer[..]), Err(ImageError::BadMagic));
+    }
+
+    #[test]
+    fn bad_version() {
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v0>()];
+        add::<boot_img_hdr_v0>(
+            &mut buffer,
+            boot_img_hdr_v0 {
+                magic: BOOT_MAGIC[0..MAGIC_SIZE].try_into().unwrap(),
+                header_version: 2112,
+                ..Default::default()
+            },
+        );
+        assert_eq!(BootImage::parse(&buffer[..]), Err(ImageError::UnexpectedVersion));
+    }
+
+    #[test]
+    fn parse_v0() {
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v0>()];
+        add::<boot_img_hdr_v0>(
+            &mut buffer,
+            boot_img_hdr_v0 {
+                magic: BOOT_MAGIC[0..MAGIC_SIZE].try_into().unwrap(),
+                header_version: 0,
+                ..Default::default()
+            },
+        );
+        let expected =
+            Ok(BootImage::V0(LayoutVerified::<&[u8], boot_img_hdr_v0>::new(&buffer).unwrap()));
+        assert_eq!(BootImage::parse(&buffer[..]), expected);
+    }
+
+    #[test]
+    fn parse_v1() {
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v1>()];
+        add::<boot_img_hdr_v1>(
+            &mut buffer,
+            boot_img_hdr_v1 {
+                _base: boot_img_hdr_v0 {
+                    magic: BOOT_MAGIC[0..MAGIC_SIZE].try_into().unwrap(),
+                    header_version: 1,
+                    ..Default::default()
+                },
+                ..Default::default()
+            },
+        );
+        let expected =
+            Ok(BootImage::V1(LayoutVerified::<&[u8], boot_img_hdr_v1>::new(&buffer).unwrap()));
+        assert_eq!(BootImage::parse(&buffer[..]), expected);
+    }
+
+    #[test]
+    fn parse_v2() {
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v2>()];
+        add::<boot_img_hdr_v2>(
+            &mut buffer,
+            boot_img_hdr_v2 {
+                _base: boot_img_hdr_v1 {
+                    _base: boot_img_hdr_v0 {
+                        magic: BOOT_MAGIC[0..MAGIC_SIZE].try_into().unwrap(),
+                        header_version: 2,
+                        ..Default::default()
+                    },
+                    ..Default::default()
+                },
+                ..Default::default()
+            },
+        );
+        let expected =
+            Ok(BootImage::V2(LayoutVerified::<&[u8], boot_img_hdr_v2>::new(&buffer).unwrap()));
+        assert_eq!(BootImage::parse(&buffer[..]), expected);
+    }
+
+    #[test]
+    fn parse_v3() {
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v3>()];
+        add::<boot_img_hdr_v3>(
+            &mut buffer,
+            boot_img_hdr_v3 {
+                magic: BOOT_MAGIC[0..MAGIC_SIZE].try_into().unwrap(),
+                header_version: 3,
+                ..Default::default()
+            },
+        );
+        let expected =
+            Ok(BootImage::V3(LayoutVerified::<&[u8], boot_img_hdr_v3>::new(&buffer).unwrap()));
+        assert_eq!(BootImage::parse(&buffer[..]), expected);
+    }
+
+    #[test]
+    fn parse_v4() {
+        let mut buffer = [0; core::mem::size_of::<boot_img_hdr_v4>()];
+        add::<boot_img_hdr_v4>(
+            &mut buffer,
+            boot_img_hdr_v4 {
+                _base: boot_img_hdr_v3 {
+                    magic: BOOT_MAGIC[0..MAGIC_SIZE].try_into().unwrap(),
+                    header_version: 4,
+                    ..Default::default()
+                },
+                ..Default::default()
+            },
+        );
+        let expected =
+            Ok(BootImage::V4(LayoutVerified::<&[u8], boot_img_hdr_v4>::new(&buffer).unwrap()));
+        assert_eq!(BootImage::parse(&buffer[..]), expected);
+    }
+
+    #[test]
+    fn vendor_buffer_too_small_for_version() {
+        let buffer = [0; VENDOR_MAGIC_SIZE + 3];
+        assert_eq!(VendorImageHeader::parse(&buffer[..]), Err(ImageError::BufferTooSmall));
+    }
+
+    #[test]
+    fn vendor_bad_magic() {
+        let mut buffer = [0; core::mem::size_of::<vendor_boot_img_hdr_v3>()];
+        add::<vendor_boot_img_hdr_v3>(
+            &mut buffer,
+            vendor_boot_img_hdr_v3 { magic: *b"VNDRBOOK", header_version: 3, ..Default::default() },
+        );
+        assert_eq!(VendorImageHeader::parse(&buffer[..]), Err(ImageError::BadMagic));
+    }
+
+    #[test]
+    fn vendor_bad_version() {
+        let mut buffer = [0; core::mem::size_of::<vendor_boot_img_hdr_v3>()];
+        add::<vendor_boot_img_hdr_v3>(
+            &mut buffer,
+            vendor_boot_img_hdr_v3 {
+                magic: VENDOR_BOOT_MAGIC[0..VENDOR_MAGIC_SIZE].try_into().unwrap(),
+                header_version: 2112,
+                ..Default::default()
+            },
+        );
+        assert_eq!(VendorImageHeader::parse(&buffer[..]), Err(ImageError::UnexpectedVersion));
+    }
+
+    #[test]
+    fn vendor_buffer_too_small_valid_version() {
+        let mut buffer = [0; core::mem::size_of::<vendor_boot_img_hdr_v3>()];
+        add::<vendor_boot_img_hdr_v3>(
+            &mut buffer,
+            vendor_boot_img_hdr_v3 {
+                magic: VENDOR_BOOT_MAGIC[0..VENDOR_MAGIC_SIZE].try_into().unwrap(),
+                // Note: because the v4 header fully encapsulates the v3 header,
+                // we can trigger a buffer-too-small error by providing
+                // a perfectly valid v3 header and changing the version to 4.
+                header_version: 4,
+                ..Default::default()
+            },
+        );
+        assert_eq!(VendorImageHeader::parse(&buffer[..]), Err(ImageError::BufferTooSmall));
+    }
+
+    #[test]
+    fn vendor_parse_v3() {
+        let mut buffer = [0; core::mem::size_of::<vendor_boot_img_hdr_v3>()];
+        add::<vendor_boot_img_hdr_v3>(
+            &mut buffer,
+            vendor_boot_img_hdr_v3 {
+                magic: VENDOR_BOOT_MAGIC[0..VENDOR_MAGIC_SIZE].try_into().unwrap(),
+                header_version: 3,
+                ..Default::default()
+            },
+        );
+        let expected = Ok(VendorImageHeader::V3(
+            LayoutVerified::<&[u8], vendor_boot_img_hdr_v3>::new(&buffer).unwrap(),
+        ));
+        assert_eq!(VendorImageHeader::parse(&buffer[..]), expected);
+    }
+
+    #[test]
+    fn vendor_parse_v4() {
+        let mut buffer = [0; core::mem::size_of::<vendor_boot_img_hdr_v4>()];
+        add::<vendor_boot_img_hdr_v4>(
+            &mut buffer,
+            vendor_boot_img_hdr_v4 {
+                _base: vendor_boot_img_hdr_v3 {
+                    magic: VENDOR_BOOT_MAGIC[0..VENDOR_MAGIC_SIZE].try_into().unwrap(),
+                    header_version: 4,
+                    ..Default::default()
+                },
+                ..Default::default()
+            },
+        );
+        let expected = Ok(VendorImageHeader::V4(
+            LayoutVerified::<&[u8], vendor_boot_img_hdr_v4>::new(&buffer).unwrap(),
+        ));
+        assert_eq!(VendorImageHeader::parse(&buffer[..]), expected);
+    }
+}
diff --git a/rust/bootimg_priv.rs b/rust/bootimg_priv.rs
new file mode 100644
index 0000000..fbd883c
--- /dev/null
+++ b/rust/bootimg_priv.rs
@@ -0,0 +1,669 @@
+// Copyright 2023, The Android Open Source Project
+//
+// 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.
+
+use zerocopy::{AsBytes, FromBytes};
+
+/* automatically generated by rust-bindgen 0.65.1 */
+
+pub const BOOT_MAGIC: &[u8; 9usize] = b"ANDROID!\0";
+pub const BOOT_MAGIC_SIZE: u32 = 8;
+pub const BOOT_NAME_SIZE: u32 = 16;
+pub const BOOT_ARGS_SIZE: u32 = 512;
+pub const BOOT_EXTRA_ARGS_SIZE: u32 = 1024;
+pub const VENDOR_BOOT_MAGIC: &[u8; 9usize] = b"VNDRBOOT\0";
+pub const VENDOR_BOOT_MAGIC_SIZE: u32 = 8;
+pub const VENDOR_BOOT_ARGS_SIZE: u32 = 2048;
+pub const VENDOR_BOOT_NAME_SIZE: u32 = 16;
+pub const VENDOR_RAMDISK_TYPE_NONE: u32 = 0;
+pub const VENDOR_RAMDISK_TYPE_PLATFORM: u32 = 1;
+pub const VENDOR_RAMDISK_TYPE_RECOVERY: u32 = 2;
+pub const VENDOR_RAMDISK_TYPE_DLKM: u32 = 3;
+pub const VENDOR_RAMDISK_NAME_SIZE: u32 = 32;
+pub const VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE: u32 = 16;
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct boot_img_hdr_v0 {
+    pub magic: [u8; 8usize],
+    pub kernel_size: u32,
+    pub kernel_addr: u32,
+    pub ramdisk_size: u32,
+    pub ramdisk_addr: u32,
+    pub second_size: u32,
+    pub second_addr: u32,
+    pub tags_addr: u32,
+    pub page_size: u32,
+    pub header_version: u32,
+    pub os_version: u32,
+    pub name: [u8; 16usize],
+    pub cmdline: [u8; 512usize],
+    pub id: [u32; 8usize],
+    pub extra_cmdline: [u8; 1024usize],
+}
+#[test]
+fn bindgen_test_layout_boot_img_hdr_v0() {
+    const UNINIT: ::core::mem::MaybeUninit<boot_img_hdr_v0> = ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<boot_img_hdr_v0>(),
+        1632usize,
+        concat!("Size of: ", stringify!(boot_img_hdr_v0))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<boot_img_hdr_v0>(),
+        1usize,
+        concat!("Alignment of ", stringify!(boot_img_hdr_v0))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).magic) as usize - ptr as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(magic))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).kernel_size) as usize - ptr as usize },
+        8usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(kernel_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).kernel_addr) as usize - ptr as usize },
+        12usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(kernel_addr))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_size) as usize - ptr as usize },
+        16usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(ramdisk_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_addr) as usize - ptr as usize },
+        20usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(ramdisk_addr))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).second_size) as usize - ptr as usize },
+        24usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(second_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).second_addr) as usize - ptr as usize },
+        28usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(second_addr))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).tags_addr) as usize - ptr as usize },
+        32usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(tags_addr))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).page_size) as usize - ptr as usize },
+        36usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(page_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).header_version) as usize - ptr as usize },
+        40usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(header_version))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).os_version) as usize - ptr as usize },
+        44usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(os_version))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).name) as usize - ptr as usize },
+        48usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(name))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).cmdline) as usize - ptr as usize },
+        64usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(cmdline))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).id) as usize - ptr as usize },
+        576usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(id))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).extra_cmdline) as usize - ptr as usize },
+        608usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v0), "::", stringify!(extra_cmdline))
+    );
+}
+impl Default for boot_img_hdr_v0 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
+pub type boot_img_hdr = boot_img_hdr_v0;
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct boot_img_hdr_v1 {
+    pub _base: boot_img_hdr_v0,
+    pub recovery_dtbo_size: u32,
+    pub recovery_dtbo_offset: u64,
+    pub header_size: u32,
+}
+#[test]
+fn bindgen_test_layout_boot_img_hdr_v1() {
+    const UNINIT: ::core::mem::MaybeUninit<boot_img_hdr_v1> = ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<boot_img_hdr_v1>(),
+        1648usize,
+        concat!("Size of: ", stringify!(boot_img_hdr_v1))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<boot_img_hdr_v1>(),
+        1usize,
+        concat!("Alignment of ", stringify!(boot_img_hdr_v1))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).recovery_dtbo_size) as usize - ptr as usize },
+        1632usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(boot_img_hdr_v1),
+            "::",
+            stringify!(recovery_dtbo_size)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).recovery_dtbo_offset) as usize - ptr as usize },
+        1636usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(boot_img_hdr_v1),
+            "::",
+            stringify!(recovery_dtbo_offset)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).header_size) as usize - ptr as usize },
+        1644usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v1), "::", stringify!(header_size))
+    );
+}
+impl Default for boot_img_hdr_v1 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct boot_img_hdr_v2 {
+    pub _base: boot_img_hdr_v1,
+    pub dtb_size: u32,
+    pub dtb_addr: u64,
+}
+#[test]
+fn bindgen_test_layout_boot_img_hdr_v2() {
+    const UNINIT: ::core::mem::MaybeUninit<boot_img_hdr_v2> = ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<boot_img_hdr_v2>(),
+        1660usize,
+        concat!("Size of: ", stringify!(boot_img_hdr_v2))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<boot_img_hdr_v2>(),
+        1usize,
+        concat!("Alignment of ", stringify!(boot_img_hdr_v2))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).dtb_size) as usize - ptr as usize },
+        1648usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v2), "::", stringify!(dtb_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).dtb_addr) as usize - ptr as usize },
+        1652usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v2), "::", stringify!(dtb_addr))
+    );
+}
+impl Default for boot_img_hdr_v2 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct boot_img_hdr_v3 {
+    pub magic: [u8; 8usize],
+    pub kernel_size: u32,
+    pub ramdisk_size: u32,
+    pub os_version: u32,
+    pub header_size: u32,
+    pub reserved: [u32; 4usize],
+    pub header_version: u32,
+    pub cmdline: [u8; 1536usize],
+}
+#[test]
+fn bindgen_test_layout_boot_img_hdr_v3() {
+    const UNINIT: ::core::mem::MaybeUninit<boot_img_hdr_v3> = ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<boot_img_hdr_v3>(),
+        1580usize,
+        concat!("Size of: ", stringify!(boot_img_hdr_v3))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<boot_img_hdr_v3>(),
+        1usize,
+        concat!("Alignment of ", stringify!(boot_img_hdr_v3))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).magic) as usize - ptr as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(magic))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).kernel_size) as usize - ptr as usize },
+        8usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(kernel_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_size) as usize - ptr as usize },
+        12usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(ramdisk_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).os_version) as usize - ptr as usize },
+        16usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(os_version))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).header_size) as usize - ptr as usize },
+        20usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(header_size))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).reserved) as usize - ptr as usize },
+        24usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(reserved))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).header_version) as usize - ptr as usize },
+        40usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(header_version))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).cmdline) as usize - ptr as usize },
+        44usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v3), "::", stringify!(cmdline))
+    );
+}
+impl Default for boot_img_hdr_v3 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct vendor_boot_img_hdr_v3 {
+    pub magic: [u8; 8usize],
+    pub header_version: u32,
+    pub page_size: u32,
+    pub kernel_addr: u32,
+    pub ramdisk_addr: u32,
+    pub vendor_ramdisk_size: u32,
+    pub cmdline: [u8; 2048usize],
+    pub tags_addr: u32,
+    pub name: [u8; 16usize],
+    pub header_size: u32,
+    pub dtb_size: u32,
+    pub dtb_addr: u64,
+}
+#[test]
+fn bindgen_test_layout_vendor_boot_img_hdr_v3() {
+    const UNINIT: ::core::mem::MaybeUninit<vendor_boot_img_hdr_v3> =
+        ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<vendor_boot_img_hdr_v3>(),
+        2112usize,
+        concat!("Size of: ", stringify!(vendor_boot_img_hdr_v3))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<vendor_boot_img_hdr_v3>(),
+        1usize,
+        concat!("Alignment of ", stringify!(vendor_boot_img_hdr_v3))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).magic) as usize - ptr as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(vendor_boot_img_hdr_v3), "::", stringify!(magic))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).header_version) as usize - ptr as usize },
+        8usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(header_version)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).page_size) as usize - ptr as usize },
+        12usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(page_size)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).kernel_addr) as usize - ptr as usize },
+        16usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(kernel_addr)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_addr) as usize - ptr as usize },
+        20usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(ramdisk_addr)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).vendor_ramdisk_size) as usize - ptr as usize },
+        24usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(vendor_ramdisk_size)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).cmdline) as usize - ptr as usize },
+        28usize,
+        concat!("Offset of field: ", stringify!(vendor_boot_img_hdr_v3), "::", stringify!(cmdline))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).tags_addr) as usize - ptr as usize },
+        2076usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(tags_addr)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).name) as usize - ptr as usize },
+        2080usize,
+        concat!("Offset of field: ", stringify!(vendor_boot_img_hdr_v3), "::", stringify!(name))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).header_size) as usize - ptr as usize },
+        2096usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(header_size)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).dtb_size) as usize - ptr as usize },
+        2100usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(dtb_size)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).dtb_addr) as usize - ptr as usize },
+        2104usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v3),
+            "::",
+            stringify!(dtb_addr)
+        )
+    );
+}
+impl Default for vendor_boot_img_hdr_v3 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct boot_img_hdr_v4 {
+    pub _base: boot_img_hdr_v3,
+    pub signature_size: u32,
+}
+#[test]
+fn bindgen_test_layout_boot_img_hdr_v4() {
+    const UNINIT: ::core::mem::MaybeUninit<boot_img_hdr_v4> = ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<boot_img_hdr_v4>(),
+        1584usize,
+        concat!("Size of: ", stringify!(boot_img_hdr_v4))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<boot_img_hdr_v4>(),
+        1usize,
+        concat!("Alignment of ", stringify!(boot_img_hdr_v4))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).signature_size) as usize - ptr as usize },
+        1580usize,
+        concat!("Offset of field: ", stringify!(boot_img_hdr_v4), "::", stringify!(signature_size))
+    );
+}
+impl Default for boot_img_hdr_v4 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct vendor_boot_img_hdr_v4 {
+    pub _base: vendor_boot_img_hdr_v3,
+    pub vendor_ramdisk_table_size: u32,
+    pub vendor_ramdisk_table_entry_num: u32,
+    pub vendor_ramdisk_table_entry_size: u32,
+    pub bootconfig_size: u32,
+}
+#[test]
+fn bindgen_test_layout_vendor_boot_img_hdr_v4() {
+    const UNINIT: ::core::mem::MaybeUninit<vendor_boot_img_hdr_v4> =
+        ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<vendor_boot_img_hdr_v4>(),
+        2128usize,
+        concat!("Size of: ", stringify!(vendor_boot_img_hdr_v4))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<vendor_boot_img_hdr_v4>(),
+        1usize,
+        concat!("Alignment of ", stringify!(vendor_boot_img_hdr_v4))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).vendor_ramdisk_table_size) as usize - ptr as usize },
+        2112usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v4),
+            "::",
+            stringify!(vendor_ramdisk_table_size)
+        )
+    );
+    assert_eq!(
+        unsafe {
+            ::core::ptr::addr_of!((*ptr).vendor_ramdisk_table_entry_num) as usize - ptr as usize
+        },
+        2116usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v4),
+            "::",
+            stringify!(vendor_ramdisk_table_entry_num)
+        )
+    );
+    assert_eq!(
+        unsafe {
+            ::core::ptr::addr_of!((*ptr).vendor_ramdisk_table_entry_size) as usize - ptr as usize
+        },
+        2120usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v4),
+            "::",
+            stringify!(vendor_ramdisk_table_entry_size)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).bootconfig_size) as usize - ptr as usize },
+        2124usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_boot_img_hdr_v4),
+            "::",
+            stringify!(bootconfig_size)
+        )
+    );
+}
+impl Default for vendor_boot_img_hdr_v4 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
+#[repr(C, packed)]
+#[derive(AsBytes, FromBytes, PartialEq, Copy, Clone, Debug)]
+pub struct vendor_ramdisk_table_entry_v4 {
+    pub ramdisk_size: u32,
+    pub ramdisk_offset: u32,
+    pub ramdisk_type: u32,
+    pub ramdisk_name: [u8; 32usize],
+    pub board_id: [u32; 16usize],
+}
+#[test]
+fn bindgen_test_layout_vendor_ramdisk_table_entry_v4() {
+    const UNINIT: ::core::mem::MaybeUninit<vendor_ramdisk_table_entry_v4> =
+        ::core::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::core::mem::size_of::<vendor_ramdisk_table_entry_v4>(),
+        108usize,
+        concat!("Size of: ", stringify!(vendor_ramdisk_table_entry_v4))
+    );
+    assert_eq!(
+        ::core::mem::align_of::<vendor_ramdisk_table_entry_v4>(),
+        1usize,
+        concat!("Alignment of ", stringify!(vendor_ramdisk_table_entry_v4))
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_size) as usize - ptr as usize },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_ramdisk_table_entry_v4),
+            "::",
+            stringify!(ramdisk_size)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_offset) as usize - ptr as usize },
+        4usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_ramdisk_table_entry_v4),
+            "::",
+            stringify!(ramdisk_offset)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_type) as usize - ptr as usize },
+        8usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_ramdisk_table_entry_v4),
+            "::",
+            stringify!(ramdisk_type)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).ramdisk_name) as usize - ptr as usize },
+        12usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_ramdisk_table_entry_v4),
+            "::",
+            stringify!(ramdisk_name)
+        )
+    );
+    assert_eq!(
+        unsafe { ::core::ptr::addr_of!((*ptr).board_id) as usize - ptr as usize },
+        44usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(vendor_ramdisk_table_entry_v4),
+            "::",
+            stringify!(board_id)
+        )
+    );
+}
+impl Default for vendor_ramdisk_table_entry_v4 {
+    fn default() -> Self {
+        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}