/** @file
The driver entry point for RamDiskDxe driver.
Copyright (c) 2016, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "RamDiskImpl.h"
//
// Handle for the EFI_RAM_DISK_PROTOCOL instance
//
EFI_HANDLE mRamDiskHandle = NULL;
//
// The EFI_RAM_DISK_PROTOCOL instances that is installed onto the driver
// handle
//
EFI_RAM_DISK_PROTOCOL mRamDiskProtocol = {
RamDiskRegister,
RamDiskUnregister
};
//
// RamDiskDxe driver maintains a list of registered RAM disks.
//
LIST_ENTRY RegisteredRamDisks;
//
// Pointers to the EFI_ACPI_TABLE_PROTOCOL and EFI_ACPI_SDT_PROTOCOL.
//
EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol = NULL;
EFI_ACPI_SDT_PROTOCOL *mAcpiSdtProtocol = NULL;
/**
Check whether EFI_ACPI_TABLE_PROTOCOL and EFI_ACPI_SDT_PROTOCOL are produced.
If both protocols are produced, publish all the reserved memory type RAM
disks to the NVDIMM Firmware Interface Table (NFIT).
@param[in] Event Event whose notification function is being invoked.
@param[in] Context The pointer to the notification function's context,
which is implementation-dependent.
**/
VOID
EFIAPI
RamDiskAcpiCheck (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
LIST_ENTRY *Entry;
RAM_DISK_PRIVATE_DATA *PrivateData;
gBS->CloseEvent (Event);
//
// Locate the EFI_ACPI_TABLE_PROTOCOL.
//
Status = gBS->LocateProtocol (
&gEfiAcpiTableProtocolGuid,
NULL,
(VOID **)&mAcpiTableProtocol
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"RamDiskAcpiCheck: Cannot locate the EFI ACPI Table Protocol, "
"unable to publish RAM disks to NFIT.\n"
));
return;
}
//
// Locate the EFI_ACPI_SDT_PROTOCOL.
//
Status = gBS->LocateProtocol (
&gEfiAcpiSdtProtocolGuid,
NULL,
(VOID **)&mAcpiSdtProtocol
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"RamDiskAcpiCheck: Cannot locate the EFI ACPI Sdt Protocol, "
"unable to publish RAM disks to NFIT.\n"
));
mAcpiTableProtocol = NULL;
return;
}
BASE_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
RamDiskPublishNfit (PrivateData);
}
}
/**
The entry point for RamDiskDxe driver.
@param[in] ImageHandle The image handle of the driver.
@param[in] SystemTable The system table.
@retval EFI_ALREADY_STARTED The driver already exists in system.
@retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of
resources.
@retval EFI_SUCCES All the related protocols are installed on
the driver.
**/
EFI_STATUS
EFIAPI
RamDiskDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate;
VOID *DummyInterface;
EFI_EVENT Event;
//
// If already started, return.
//
Status = gBS->LocateProtocol (
&gEfiRamDiskProtocolGuid,
NULL,
&DummyInterface
);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Driver already started!\n"));
return EFI_ALREADY_STARTED;
}
//
// Create a private data structure.
//
ConfigPrivate = AllocateCopyPool (sizeof (RAM_DISK_CONFIG_PRIVATE_DATA), &mRamDiskConfigPrivateDataTemplate);
if (ConfigPrivate == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Install RAM disk configuration form
//
Status = InstallRamDiskConfigForm (ConfigPrivate);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Initialize the list of registered RAM disks maintained by the driver
// before installing the protocol
//
InitializeListHead (&RegisteredRamDisks);
//
// Install the EFI_RAM_DISK_PROTOCOL and RAM disk private data onto a
// new handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&mRamDiskHandle,
&gEfiRamDiskProtocolGuid,
&mRamDiskProtocol,
&gEfiCallerIdGuid,
ConfigPrivate,
NULL
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
Status = EfiCreateEventReadyToBootEx (
TPL_CALLBACK,
RamDiskAcpiCheck,
NULL,
&Event
);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
ErrorExit:
if (ConfigPrivate != NULL) {
UninstallRamDiskConfigForm (ConfigPrivate);
}
return Status;
}
/**
Unload the RamDiskDxe driver and its configuration form.
@param[in] ImageHandle The driver's image handle.
@retval EFI_SUCCESS The RamDiskDxe driver and its configuration
form is unloaded.
@retval Others Failed to unload the form.
**/
EFI_STATUS
EFIAPI
RamDiskDxeUnload (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate;
Status = gBS->HandleProtocol (
mRamDiskHandle,
&gEfiCallerIdGuid,
(VOID **)&ConfigPrivate
);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (ConfigPrivate->Signature == RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE);
//
// Unregister all registered RAM disks
//
UnregisterAllRamDisks ();
gBS->UninstallMultipleProtocolInterfaces (
mRamDiskHandle,
&gEfiRamDiskProtocolGuid,
&mRamDiskProtocol,
&gEfiCallerIdGuid,
ConfigPrivate,
NULL
);
UninstallRamDiskConfigForm (ConfigPrivate);
return EFI_SUCCESS;
}