blob: 5772589573dc2183cef4b2dedb5845540e261875 [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.
#ifdef ZIRCON_BOOT_CUSTOM_SYSDEPS_HEADER
#include <zircon_boot_sysdeps.h>
#else
#include <string.h>
#endif
#include <lib/zircon_boot/android_boot_image.h>
#include "utils.h"
bool zircon_boot_get_android_image_kernel_position(const zircon_boot_android_image_headers* header,
size_t* kernel_offset, size_t* kernel_size) {
if (memcmp(header, ZIRCON_BOOT_ANDROID_IMAGE_MAGIC, ZIRCON_BOOT_ANDROID_IMAGE_MAGIC_SIZE)) {
return false;
}
// Extract the kernel offset and size from the header.
switch (header->v0.header_version) {
case 0:
*kernel_offset = header->v0.page_size;
*kernel_size = header->v0.kernel_size;
break;
case 1:
*kernel_offset = header->v1.page_size;
*kernel_size = header->v1.kernel_size;
break;
case 2:
*kernel_offset = header->v2.page_size;
*kernel_size = header->v2.kernel_size;
break;
case 3:
*kernel_offset = 4096; // Version 3 hardcodes the page size at 4096.
*kernel_size = header->v3.kernel_size;
break;
case 4:
*kernel_offset = 4096; // Version 4 hardcodes the page size at 4096.
*kernel_size = header->v4.kernel_size;
break;
default:
zircon_boot_dlog("Unsupported Android boot image version (%u)\n", header->v0.header_version);
return false;
}
return true;
}
bool zircon_boot_get_android_image_kernel(const void* image, size_t size, const void** kernel,
size_t* kernel_size) {
if (size < sizeof(zircon_boot_android_image_headers) ||
((uintptr_t)image % ANDROID_IMAGE_HEADER_ALIGNMENT != 0)) {
return false;
}
size_t kernel_offset = 0;
if (!zircon_boot_get_android_image_kernel_position(
(const zircon_boot_android_image_headers*)image, &kernel_offset, kernel_size)) {
return false;
}
// Finally check that the provided image is actually big enough to hold the
// header and the kernel.
size_t required_size = kernel_offset + *kernel_size;
if (required_size < *kernel_size) {
zircon_boot_dlog("Kernel size overflow\n");
return false;
}
if (size < required_size) {
zircon_boot_dlog("Image is too small to contain the reported kernel\n");
return false;
}
*kernel = (const uint8_t*)image + kernel_offset;
return true;
}