blob: 7a47ddd173a02b002e5250064de9f627212d7881 [file] [log] [blame]
// Copyright 2024 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 "gbl_efi_fastboot_protocol.h"
#include <zircon/assert.h>
#include <functional>
#include <span>
#include <string_view>
#include <phys/efi/main.h>
#include "utils.h"
#define GBL_EFI_FASTBOOT_PROTOCOL_GUID \
{0xc67e48a0, 0x5eb8, 0x4127, {0xbe, 0x89, 0xdf, 0x2e, 0xd9, 0x3d, 0x8a, 0x9a}}
// Set within `LaunchGbl()`;
bool g_should_stop_in_fastboot = false;
namespace {
struct GblEfiFastbootProtocol {
struct gbl_efi_fastboot_protocol protocol;
};
// Contains information such as variable name and value.
constexpr struct Variable {
const char* var_name;
// For now we only consider constant variable.
const char* var_impl;
/// Gets the name as a string_view.
std::string_view name() const { return std::string_view(var_name); }
/// Gets the value as a string_view.
std::string_view impl() const { return std::string_view(var_impl); }
} kVariables[] = {
{"hw-revision", BOARD_NAME},
};
/// Gets the list of variables
std::span<const Variable> variables() { return std::span<const Variable>(kVariables); }
EFIAPI efi_status GetVar(struct gbl_efi_fastboot_protocol* self, const char* const* args,
size_t num_args, uint8_t* buf, size_t* bufsize) {
const std::span<const char* const> args_span{args, num_args};
if (args_span.empty() || !bufsize) {
return EFI_INVALID_PARAMETER;
}
std::span<uint8_t> out{buf, *bufsize};
for (size_t i = 0; i < variables().size(); i++) {
const Variable& var = variables()[i];
if (std::string_view(args_span[0]) != var.name()) {
continue;
}
if (out.size() < var.impl().size() + 1) {
return EFI_BUFFER_TOO_SMALL;
}
memcpy(out.data(), var.impl().data(), var.impl().size());
*bufsize = var.impl().size();
out.data()[*bufsize] = 0;
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
EFIAPI efi_status GetVarAll(struct gbl_efi_fastboot_protocol* self, void* ctx,
get_var_callback cb) {
for (size_t i = 0; i < variables().size(); i++) {
std::array args{variables()[i].name().data()};
cb(ctx, args.data(), args.size(), variables()[i].impl().data());
}
return EFI_SUCCESS;
}
EFIAPI efi_status RunOemFunction(struct gbl_efi_fastboot_protocol* self, const char* cmd,
size_t len, uint8_t* download_buffer, size_t download_data_size,
fastboot_message_sender sender, void* ctx) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status GetStaged(struct gbl_efi_fastboot_protocol* self, uint8_t* out, size_t* out_size,
size_t* out_remain) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status GetPolicy(struct gbl_efi_fastboot_protocol* self,
gbl_efi_fastboot_policy* policy) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status SetLock(struct gbl_efi_fastboot_protocol* self, uint64_t lock_state) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status ClearLock(struct gbl_efi_fastboot_protocol* self, uint64_t lock_state) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status StartLocal(struct gbl_efi_fastboot_protocol* self, void** ctx) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status UpdateLocal(struct gbl_efi_fastboot_protocol* self, void* ctx, uint8_t* buf,
size_t* size) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status CloseLocal(struct gbl_efi_fastboot_protocol* self, void* ctx) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status GetPartitionPermissions(struct gbl_efi_fastboot_protocol* self,
const uint8_t* part_name, size_t part_name_len,
uint64_t* permissions) {
return EFI_UNSUPPORTED;
}
EFIAPI efi_status WipeUserData(struct gbl_efi_fastboot_protocol* self) { return EFI_UNSUPPORTED; }
EFIAPI bool ShouldStopInFastboot(struct gbl_efi_fastboot_protocol* self) {
return g_should_stop_in_fastboot;
}
GblEfiFastbootProtocol protocol = {.protocol = {
.version = 0x01,
.get_var = GetVar,
.get_var_all = GetVarAll,
.run_oem_function = RunOemFunction,
.get_staged = GetStaged,
.get_policy = GetPolicy,
.set_lock = SetLock,
.clear_lock = ClearLock,
.start_local_session = StartLocal,
.update_local_session = UpdateLocal,
.close_local_session = CloseLocal,
.get_partition_permissions = GetPartitionPermissions,
.wipe_user_data = WipeUserData,
.should_stop_in_fastboot = ShouldStopInFastboot,
}};
efi_guid guid = GBL_EFI_FASTBOOT_PROTOCOL_GUID;
} // namespace
namespace gigaboot {
efi_status InstallGblEfiFastbootProtocol() {
efi_handle out_handle = NULL;
return gEfiSystemTable->BootServices->InstallMultipleProtocolInterfaces(&out_handle, &guid,
&protocol.protocol, NULL);
}
} // namespace gigaboot