blob: 51a8193775fc49dedf637e6270dcb8347ed49e52 [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Definitions of the Android boot image layout, to support booting from RAM via
// `fastboot boot` which automatically wraps the provided image in this format.
//
// Upstream definitions are at
// https://android.googlesource.com/platform/system/tools/mkbootimg/+/refs/heads/master/include/bootimg/bootimg.h,
// modified here for C compatibility and renaming to avoid collisions.
#ifndef SRC_FIRMWARE_LIB_ZIRCON_BOOT_INCLUDE_LIB_ZIRCON_BOOT_ANDROID_BOOT_IMAGE_H_
#define SRC_FIRMWARE_LIB_ZIRCON_BOOT_INCLUDE_LIB_ZIRCON_BOOT_ANDROID_BOOT_IMAGE_H_
#ifdef ZIRCON_BOOT_CUSTOM_SYSDEPS_HEADER
#include <zircon_boot_sysdeps.h>
#else
#include <stdbool.h>
#include <stdint.h>
#endif
#define ZIRCON_BOOT_ANDROID_IMAGE_MAGIC "ANDROID!"
#define ZIRCON_BOOT_ANDROID_IMAGE_MAGIC_SIZE 8
#define ZIRCON_BOOT_ANDROID_IMAGE_NAME_SIZE 16
#define ZIRCON_BOOT_ANDROID_IMAGE_ARGS_SIZE 512
#define ZIRCON_BOOT_ANDROID_IMAGE_EXTRA_ARGS_SIZE 1024
typedef struct {
uint8_t magic[ZIRCON_BOOT_ANDROID_IMAGE_MAGIC_SIZE];
uint32_t kernel_size;
uint32_t kernel_addr;
uint32_t ramdisk_size;
uint32_t ramdisk_addr;
uint32_t second_size;
uint32_t second_addr;
uint32_t tags_addr;
uint32_t page_size;
uint32_t header_version;
uint32_t os_version;
uint8_t name[ZIRCON_BOOT_ANDROID_IMAGE_NAME_SIZE];
uint8_t cmdline[ZIRCON_BOOT_ANDROID_IMAGE_ARGS_SIZE];
uint32_t id[8];
uint8_t extra_cmdline[ZIRCON_BOOT_ANDROID_IMAGE_EXTRA_ARGS_SIZE];
} __attribute((packed)) zircon_boot_android_image_hdr_v0;
typedef struct {
uint8_t magic[ZIRCON_BOOT_ANDROID_IMAGE_MAGIC_SIZE];
uint32_t kernel_size;
uint32_t kernel_addr;
uint32_t ramdisk_size;
uint32_t ramdisk_addr;
uint32_t second_size;
uint32_t second_addr;
uint32_t tags_addr;
uint32_t page_size;
uint32_t header_version;
uint32_t os_version;
uint8_t name[ZIRCON_BOOT_ANDROID_IMAGE_NAME_SIZE];
uint8_t cmdline[ZIRCON_BOOT_ANDROID_IMAGE_ARGS_SIZE];
uint32_t id[8];
uint8_t extra_cmdline[ZIRCON_BOOT_ANDROID_IMAGE_EXTRA_ARGS_SIZE];
uint32_t recovery_dtbo_size;
uint64_t recovery_dtbo_offset;
uint32_t header_size;
} __attribute((packed)) zircon_boot_android_image_hdr_v1;
typedef struct {
uint8_t magic[ZIRCON_BOOT_ANDROID_IMAGE_MAGIC_SIZE];
uint32_t kernel_size;
uint32_t kernel_addr;
uint32_t ramdisk_size;
uint32_t ramdisk_addr;
uint32_t second_size;
uint32_t second_addr;
uint32_t tags_addr;
uint32_t page_size;
uint32_t header_version;
uint32_t os_version;
uint8_t name[ZIRCON_BOOT_ANDROID_IMAGE_NAME_SIZE];
uint8_t cmdline[ZIRCON_BOOT_ANDROID_IMAGE_ARGS_SIZE];
uint32_t id[8];
uint8_t extra_cmdline[ZIRCON_BOOT_ANDROID_IMAGE_EXTRA_ARGS_SIZE];
uint32_t recovery_dtbo_size;
uint64_t recovery_dtbo_offset;
uint32_t header_size;
uint32_t dtb_size;
uint64_t dtb_addr;
} __attribute((packed)) zircon_boot_android_image_hdr_v2;
typedef struct {
uint8_t magic[ZIRCON_BOOT_ANDROID_IMAGE_MAGIC_SIZE];
uint32_t kernel_size;
uint32_t ramdisk_size;
uint32_t os_version;
uint32_t header_size;
uint32_t reserved[4];
uint32_t header_version;
uint8_t cmdline[ZIRCON_BOOT_ANDROID_IMAGE_ARGS_SIZE + ZIRCON_BOOT_ANDROID_IMAGE_EXTRA_ARGS_SIZE];
} __attribute((packed)) zircon_boot_android_image_hdr_v3;
typedef struct {
uint8_t magic[ZIRCON_BOOT_ANDROID_IMAGE_MAGIC_SIZE];
uint32_t kernel_size;
uint32_t ramdisk_size;
uint32_t os_version;
uint32_t header_size;
uint32_t reserved[4];
uint32_t header_version;
uint8_t cmdline[ZIRCON_BOOT_ANDROID_IMAGE_ARGS_SIZE + ZIRCON_BOOT_ANDROID_IMAGE_EXTRA_ARGS_SIZE];
uint32_t signature_size;
} __attribute((packed)) zircon_boot_android_image_hdr_v4;
// A union of all known header versions.
//
// Reading this many bytes from disk guarantees you will always get at least the
// entire header for all supported versions. However this is fairly large (>1Kib)
// so be careful when allocating objects of this size;
typedef union {
zircon_boot_android_image_hdr_v0 v0;
zircon_boot_android_image_hdr_v1 v1;
zircon_boot_android_image_hdr_v2 v2;
zircon_boot_android_image_hdr_v3 v3;
zircon_boot_android_image_hdr_v4 v4;
} zircon_boot_android_image_headers;
// C99 doesn't have any standard alignof(), hardcode it.
#define ANDROID_IMAGE_HEADER_ALIGNMENT 8
// Given an Android boot image header, returns the kernel offset and size.
//
// @header: pointer to the Android boot image header.
// @kernel_offset: on success will be filled with the offset in bytes from the
// beginning of the header to the beginning of the kernel.
// @kernel_size: on success will be filled with the kernel size in bytes.
//
// Returns true on success.
bool zircon_boot_get_android_image_kernel_position(const zircon_boot_android_image_headers* header,
size_t* kernel_offset, size_t* kernel_size);
// Locates the kernel in an Android boot image.
//
// Note that for Fuchsia, the "kernel" contained in the Android image may
// be just the ZBI, or a combined ZBI+vbmeta.
//
// @image: pointer to the Android boot image. Must be properly-aligned.
// @size: Android boot image size. Must contain at least the header and kernel
// but may omit any following contents.
// @kernel: on success will point to the kernel image.
// @kernel_size: on success will be filled with the kernel size.
//
// Returns true on success.
bool zircon_boot_get_android_image_kernel(const void* image, size_t size, const void** kernel,
size_t* kernel_size);
#endif // SRC_FIRMWARE_LIB_ZIRCON_BOOT_INCLUDE_LIB_ZIRCON_BOOT_ANDROID_BOOT_IMAGE_H_