blob: d8fd15a00aeca5402ddbc58f121b1b2b342486f0 [file] [log] [blame]
// Copyright 2017 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.
#include "efi.h"
static const uint16_t kMzSignature = 0x5a4d; // MZ
static const uint32_t kMzMagic = 0x644d5241; // ARM\x64
// MZ header used to boot ARM64 kernels.
//
// See: https://www.kernel.org/doc/Documentation/arm64/booting.txt.
struct MzHeader {
uint32_t code0;
uint32_t code1;
uint64_t kernel_off;
uint64_t kernel_len;
uint64_t flags;
uint64_t reserved0;
uint64_t reserved1;
uint64_t reserved2;
uint32_t magic;
uint32_t pe_off;
} __PACKED;
static_assert(sizeof(MzHeader) == 64, "");
static bool is_mz(const MzHeader* header) {
return (header->code0 & UINT16_MAX) == kMzSignature &&
header->kernel_len > sizeof(MzHeader) && header->magic == kMzMagic &&
header->pe_off >= sizeof(MzHeader);
}
zx_status_t read_efi(const uintptr_t first_page,
uintptr_t* guest_ip,
uintptr_t* kernel_off,
size_t* kernel_len) {
MzHeader* mz_header = reinterpret_cast<MzHeader*>(first_page);
if (!is_mz(mz_header))
return ZX_ERR_NOT_SUPPORTED;
*guest_ip = mz_header->kernel_off;
*kernel_off = mz_header->kernel_off;
*kernel_len = mz_header->kernel_len;
return ZX_OK;
}