/** @file
  The driver entry point for RamDiskDxe driver.

  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
  Copyright (c) Microsoft Corporation.<BR>
  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;
}
