blob: c056203724c6b17999aa347c17090253894159f4 [file] [log] [blame]
// Copyright 2021 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 <lib/efi/testing/stub_boot_services.h>
#include <stdio.h>
#include <stdlib.h>
namespace efi {
namespace {
using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::SetArgPointee;
// We need to stash the global StubBootServices object here since there's
// no "self" parameter to any of these functions.
StubBootServices* active_stub = nullptr;
// Wrapper to bounce the EFI C function pointer into our global StubBootServices
// object.
template <auto func, typename... Args>
EFIAPI efi_status Wrap(Args... args) {
if (!active_stub) {
// Someone held onto the underlying function table after deleting
// the parent StubBootServices.
return EFI_NOT_READY;
}
return (active_stub->*func)(args...);
}
} // namespace
StubBootServices::StubBootServices()
: services_{
.AllocatePool = Wrap<&StubBootServices::AllocatePool>,
.FreePool = Wrap<&StubBootServices::FreePool>,
.CreateEvent = Wrap<&StubBootServices::CreateEvent>,
.SetTimer = Wrap<&StubBootServices::SetTimer>,
.CloseEvent = Wrap<&StubBootServices::CloseEvent>,
.CheckEvent = Wrap<&StubBootServices::CheckEvent>,
.OpenProtocol = Wrap<&StubBootServices::OpenProtocol>,
.CloseProtocol = Wrap<&StubBootServices::CloseProtocol>,
.LocateHandleBuffer = Wrap<&StubBootServices::LocateHandleBuffer>,
.LocateProtocol = Wrap<&StubBootServices::LocateProtocol>,
} {
if (active_stub) {
// We cannot support multiple StubBootServices due to the global singleton
// nature. Rather than causing hard-to-debug test behavior here, just fail
// loudly and immediately.
fprintf(stderr, "ERROR: cannot create multiple StubBootService objects - exiting\n");
exit(1);
}
active_stub = this;
}
StubBootServices::~StubBootServices() { active_stub = nullptr; }
efi_status StubBootServices::AllocatePool(efi_memory_type /*pool_type*/, size_t size, void** buf) {
*buf = malloc(size);
return EFI_SUCCESS;
}
efi_status StubBootServices::FreePool(void* buf) {
free(buf);
return EFI_SUCCESS;
}
void MockBootServices::ExpectOpenProtocol(efi_handle handle, efi_guid guid, void* protocol) {
EXPECT_CALL(*this, OpenProtocol(handle, MatchGuid(guid), _, _, _, _))
.WillOnce(DoAll(SetArgPointee<2>(protocol), Return(EFI_SUCCESS)));
}
void MockBootServices::ExpectCloseProtocol(efi_handle handle, efi_guid guid) {
EXPECT_CALL(*this, CloseProtocol(handle, MatchGuid(guid), _, _)).WillOnce(Return(EFI_SUCCESS));
}
} // namespace efi