blob: cfd6de6d98a1dc385a4cd39223f0a4c821c28caf [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include "lib/boot-shim/efi.h"
#include <lib/acpi_lite.h>
#include <lib/stdcompat/span.h>
#include <string.h>
#include <string_view>
#include <efi/system-table.h>
#include <efi/types.h>
#include <fbl/no_destructor.h>
namespace boot_shim {
namespace {
struct VendorTableMatch {
efi_guid guid;
std::string_view prefix;
};
const void* GetVendorTable(const efi_system_table* systab,
std::initializer_list<VendorTableMatch> matches) {
cpp20::span config(systab->ConfigurationTable, systab->NumberOfTableEntries);
for (const efi_configuration_table& table : config) {
for (const auto& [guid, prefix] : matches) {
if (!memcmp(&table.VendorGuid, &guid, sizeof(guid)) &&
(prefix.empty() || !memcmp(table.VendorTable, prefix.data(), prefix.size()))) {
return table.VendorTable;
}
}
}
return nullptr;
}
struct DirectPhysMemReader : public acpi_lite::PhysMemReader {
zx::status<const void*> PhysToPtr(uintptr_t paddr, size_t bytes) override {
return zx::success(reinterpret_cast<const void*>(paddr));
}
};
} // namespace
void EfiSystemTableItem::Init(const efi_system_table* systab) {
set_payload(reinterpret_cast<uintptr_t>(systab));
}
const void* EfiGetVendorTable(const efi_system_table* systab, const efi_guid& guid,
std::string_view prefix) {
return GetVendorTable(systab, {{guid, prefix}});
}
void EfiSmbiosItem::Init(const efi_system_table* systab) {
if (const void* table = GetVendorTable(systab, //
{
{SMBIOS_TABLE_GUID, "_SM_"},
{SMBIOS3_TABLE_GUID, "_SM3_"},
})) {
set_payload(reinterpret_cast<uintptr_t>(table));
}
}
zx::status<acpi_lite::AcpiParser> EfiGetAcpi(const efi_system_table* systab) {
constexpr std::string_view kRsdPtr = "RSD PTR ";
if (const void* table = GetVendorTable(systab, //
{
{ACPI_TABLE_GUID, kRsdPtr},
{ACPI_20_TABLE_GUID, kRsdPtr},
})) {
static fbl::NoDestructor<DirectPhysMemReader> phys_mem_reader;
zx_paddr_t paddr = reinterpret_cast<uintptr_t>(table);
return acpi_lite::AcpiParser::Init(*phys_mem_reader, paddr);
}
return zx::error(ZX_ERR_NOT_FOUND);
}
} // namespace boot_shim