575 lines
17 KiB
C
575 lines
17 KiB
C
/** @file
|
|
Initialize ATA AHCI host controller.
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2020 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains a 'Sample Driver' and is licensed as such under the terms
|
|
of your license agreement with Intel or your vendor. This file may be modified
|
|
by the user, subject to the additional terms of the license agreement.
|
|
|
|
@par Specification
|
|
**/
|
|
|
|
#include "AhciPciHcPei.h"
|
|
|
|
EDKII_ATA_AHCI_HOST_CONTROLLER_PPI mAhciHostControllerPpi = {
|
|
GetAhciHcMmioBar,
|
|
GetAhciHcDevicePath
|
|
};
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR mPpiList = {
|
|
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEdkiiPeiAtaAhciHostControllerPpiGuid,
|
|
&mAhciHostControllerPpi
|
|
};
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR mRstPpiList = {
|
|
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gRstRaidControllerPpiGuid,
|
|
&mAhciHostControllerPpi
|
|
};
|
|
|
|
EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiNotifyList = {
|
|
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEfiEndOfPeiSignalPpiGuid,
|
|
AhciHcEndOfPei
|
|
};
|
|
|
|
//
|
|
// The PCI information of the ATA AHCI controller
|
|
//
|
|
PCI_NODE_INFO mAhciHcPciInfo[MAX_ATA_AHCI_HCS] = {
|
|
{ATA_AHCI_HC_PCI_BUS_NUM, 23, 0x0},
|
|
};
|
|
|
|
UINT32 MmioBarBase;
|
|
UINT32 MmioBarLimit;
|
|
|
|
//
|
|
// Template for an ATA AHCI host controller
|
|
//
|
|
ATA_AHCI_DEVICE_PATH mAtaAhciDevicePathTemplate = {
|
|
{ // PciRoot
|
|
{
|
|
ACPI_DEVICE_PATH,
|
|
ACPI_DP,
|
|
{
|
|
(UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
|
|
(UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
|
|
}
|
|
},
|
|
0x0A0341D0,
|
|
0
|
|
},
|
|
{ // AhciEp
|
|
{
|
|
HARDWARE_DEVICE_PATH,
|
|
HW_PCI_DP,
|
|
{
|
|
(UINT8) (sizeof (PCI_DEVICE_PATH)),
|
|
(UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8)
|
|
}
|
|
},
|
|
0,
|
|
0
|
|
},
|
|
{ // End
|
|
END_DEVICE_PATH_TYPE,
|
|
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
|
{
|
|
(UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),
|
|
(UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
Get the MMIO base address of ATA AHCI host controller.
|
|
|
|
@param[in] This The PPI instance pointer.
|
|
@param[in] ControllerId The ID of the ATA AHCI host controller.
|
|
@param[out] MmioBar The MMIO base address of the controller.
|
|
|
|
@retval EFI_SUCCESS The operation succeeds.
|
|
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
|
@retval EFI_NOT_FOUND The specified ATA AHCI host controller not found.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GetAhciHcMmioBar (
|
|
IN EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *This,
|
|
IN UINT8 ControllerId,
|
|
OUT UINTN *MmioBar
|
|
)
|
|
{
|
|
AHCI_HC_PEI_PRIVATE_DATA *Private;
|
|
|
|
if ((This == NULL) || (MmioBar == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Private = AHCI_HC_PEI_PRIVATE_DATA_FROM_THIS (This);
|
|
|
|
if (ControllerId >= Private->TotalAhciHcs) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
*MmioBar = Private->HcInfo[ControllerId].Bar;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the device path of ATA AHCI host controller.
|
|
|
|
@param[in] This The PPI instance pointer.
|
|
@param[in] ControllerId The ID of the ATA AHCI host controller.
|
|
@param[out] DevicePathLength The length of the device path in bytes specified
|
|
by DevicePath.
|
|
@param[out] DevicePath The device path of ATA AHCI host controller.
|
|
This field re-uses EFI Device Path Protocol as
|
|
defined by Section 10.2 EFI Device Path Protocol
|
|
of UEFI 2.7 Specification.
|
|
|
|
@retval EFI_SUCCESS The operation succeeds.
|
|
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
|
@retval EFI_NOT_FOUND The specified ATA AHCI host controller not found.
|
|
@retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GetAhciHcDevicePath (
|
|
IN EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *This,
|
|
IN UINT8 ControllerId,
|
|
OUT UINTN *DevicePathLength,
|
|
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
|
|
)
|
|
{
|
|
AHCI_HC_PEI_PRIVATE_DATA *Private;
|
|
|
|
if ((This == NULL) || (DevicePathLength == NULL) || (DevicePath == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Private = AHCI_HC_PEI_PRIVATE_DATA_FROM_THIS (This);
|
|
|
|
if (ControllerId >= Private->TotalAhciHcs) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
*DevicePathLength = Private->HcInfo[ControllerId].DevicePathLength;
|
|
*DevicePath = AllocateCopyPool (*DevicePathLength, Private->HcInfo[ControllerId].DevicePath);
|
|
if (*DevicePath == NULL) {
|
|
*DevicePathLength = 0;
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Restore the PCI configuration space of the ATA AHCI host controller.
|
|
|
|
@param[in] HcInfo A pointer to the AHCI_HC_INFO structure.
|
|
|
|
**/
|
|
VOID
|
|
AhciHcConfigSpaceRestore (
|
|
IN AHCI_HC_INFO *HcInfo
|
|
)
|
|
{
|
|
UINTN PciHcBase;
|
|
|
|
PciHcBase = PCI_LIB_ADDRESS (
|
|
HcInfo->PciInfo.Bus,
|
|
HcInfo->PciInfo.Device,
|
|
HcInfo->PciInfo.Function,
|
|
0
|
|
);
|
|
|
|
PciWrite8 (PciHcBase + PCI_COMMAND_OFFSET, HcInfo->OriCmdRegLow);
|
|
PciWrite32 (PciHcBase + PCI_AHCI_BASE_ADDRESSREG_OFFSET, HcInfo->OriABarReg);
|
|
|
|
}
|
|
|
|
/**
|
|
Get the assigned MMIO resource range for the ATA AHCI controllers.
|
|
|
|
@param[out] Base Base of the memory-mapped I/O region.
|
|
@param[out] Limit Range limit of the memory-mapped I/O region.
|
|
|
|
@retval EFI_SUCCESS Successfully get the memory-mapped I/O region.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AhciGetMmio (
|
|
OUT UINT32 *Base,
|
|
OUT UINT32 *Limit
|
|
)
|
|
{
|
|
*Base = PcdGet32 (PcdAhciPeiMmioBase);
|
|
*Limit = PcdGet32 (PcdAhciPeiMmioLimit);
|
|
|
|
DEBUG ((
|
|
DEBUG_INFO, "%a: BarBase = 0x%x, BarLimit = 0x%x.\n",
|
|
__FUNCTION__, *Base, *Limit
|
|
));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Enable the ATA AHCI host controller specified by the PCI information.
|
|
|
|
@param[in,out] Private A pointer to the AHCI_HC_PEI_PRIVATE_DATA structure.
|
|
@param[in] PciNodeInfo Data structure that holds the PCI information of
|
|
the ATA AHCI host controller.
|
|
|
|
@retval EFI_SUCCESS Controller enabled successfully.
|
|
@retval others Error occurs during the enabling process.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AhciEnableThisHc (
|
|
IN OUT AHCI_HC_PEI_PRIVATE_DATA *Private,
|
|
IN PCI_NODE_INFO PciNodeInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN HcIndex;
|
|
AHCI_HC_INFO *HcInfo;
|
|
UINTN PciHcBase;
|
|
UINT32 Size;
|
|
UINT32 MmioSize;
|
|
ATA_AHCI_DEVICE_PATH *HcDevicePath;
|
|
PCI_CLASSC PciClass;
|
|
UINT16 VidDid;
|
|
|
|
ASSERT (Private->TotalAhciHcs <= MAX_ATA_AHCI_HCS);
|
|
|
|
//
|
|
// Check if the PCI AHCI host controller has already been enabled.
|
|
//
|
|
for (HcIndex = 0; HcIndex < Private->TotalAhciHcs; HcIndex++) {
|
|
HcInfo = &(Private->HcInfo[HcIndex]);
|
|
if (PciNodeInfo.Device == HcInfo->PciInfo.Device &&
|
|
PciNodeInfo.Function == HcInfo->PciInfo.Function) {
|
|
//
|
|
// Already started, return EFI_SUCCESS directly.
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable this PCI AHCI host controller by setting BME and MSE bits of PCI_CMD register.
|
|
//
|
|
HcIndex = Private->TotalAhciHcs;
|
|
HcInfo = &(Private->HcInfo[HcIndex]);
|
|
|
|
PciHcBase = PCI_LIB_ADDRESS (
|
|
PciNodeInfo.Bus,
|
|
PciNodeInfo.Device,
|
|
PciNodeInfo.Function,
|
|
0
|
|
);
|
|
|
|
//
|
|
// check if device conntected behind SATA controller
|
|
//
|
|
VidDid = PciSegmentRead16 (PciHcBase + PCI_VENDOR_ID_OFFSET);
|
|
|
|
if (VidDid == 0xFFFF) {
|
|
DEBUG ((DEBUG_ERROR, "Vendor id is invalid.\n"));
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
PciClass.BaseCode = PciSegmentRead8 (PciHcBase + PCI_CLASSCODE_OFFSET + 2);
|
|
PciClass.SubClassCode = PciSegmentRead8 (PciHcBase + PCI_CLASSCODE_OFFSET + 1);
|
|
|
|
if ((PciClass.BaseCode != PCI_CLASS_MASS_STORAGE) ||
|
|
((PciClass.SubClassCode != PCI_CLASS_MASS_STORAGE_SATADPA) && (PciClass.SubClassCode != PCI_CLASS_MASS_STORAGE_RAID))
|
|
) {
|
|
DEBUG ((DEBUG_ERROR, "SataHostDriver : BaseCode(0x%x) or ClassCode(0x%x) is not supported\n", PciClass.BaseCode, PciClass.SubClassCode));
|
|
Status = EFI_UNSUPPORTED;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if (!(( Private->IsRaid && (PciClass.SubClassCode == PCI_CLASS_MASS_STORAGE_RAID)) ||
|
|
(!Private->IsRaid && (PciClass.SubClassCode == PCI_CLASS_MASS_STORAGE_SATADPA)) )
|
|
) {
|
|
Status = EFI_UNSUPPORTED;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
HcInfo->PciInfo.Bus = PciNodeInfo.Bus;
|
|
HcInfo->PciInfo.Device = PciNodeInfo.Device;
|
|
HcInfo->PciInfo.Function = PciNodeInfo.Function;
|
|
HcInfo->OriCmdRegLow = PciRead8 (PciHcBase + PCI_COMMAND_OFFSET);
|
|
HcInfo->OriABarReg = PciRead32 (PciHcBase + PCI_AHCI_BASE_ADDRESSREG_OFFSET);
|
|
|
|
HcInfo->Bar = MmioBarBase;
|
|
PciAnd8 (PciHcBase + PCI_COMMAND_OFFSET, 0);
|
|
PciWrite32 (PciHcBase + PCI_AHCI_BASE_ADDRESSREG_OFFSET, 0xFFFFFFFF);
|
|
Size = PciRead32 (PciHcBase + PCI_AHCI_BASE_ADDRESSREG_OFFSET);
|
|
if ((Size & 0x07) == 0x0) {
|
|
//
|
|
// According to Serial ATA Advanced Host Controller Interface (AHCI) 1.3.1
|
|
// spec Section 2.1.11, the register is 32-bits wide.
|
|
//
|
|
MmioSize = (~(Size & 0xFFFFFFF0)) + 1;
|
|
} else {
|
|
DEBUG ((DEBUG_ERROR, "%a: Unknown BAR type for an AHCI controller!\n", __FUNCTION__));
|
|
Status = EFI_UNSUPPORTED;
|
|
goto ErrorExit;
|
|
}
|
|
//
|
|
// Roundup the MMIO size to 8KB according to Serial ATA Advanced Host Controller
|
|
// Interface (AHCI) 1.3.1 spec Section 2.1.11.
|
|
//
|
|
MmioSize = ALIGN_VALUE (MmioSize, SIZE_8KB);
|
|
//
|
|
// Check the BAR range upon the limit
|
|
//
|
|
if ((MmioSize > MmioBarLimit) ||
|
|
(MmioBarBase > MmioBarLimit - MmioSize)) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ErrorExit;
|
|
}
|
|
MmioBarBase += MmioSize;
|
|
|
|
//
|
|
// Construct the device path of the AHCI controller.
|
|
//
|
|
HcInfo->DevicePathLength = sizeof (ATA_AHCI_DEVICE_PATH);
|
|
HcInfo->DevicePath = AllocatePool (HcInfo->DevicePathLength);
|
|
if (HcInfo->DevicePath == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
HcDevicePath = (ATA_AHCI_DEVICE_PATH *)HcInfo->DevicePath;
|
|
CopyMem (
|
|
HcDevicePath,
|
|
&mAtaAhciDevicePathTemplate,
|
|
sizeof (ATA_AHCI_DEVICE_PATH)
|
|
);
|
|
HcDevicePath->AhciEp.Device = PciNodeInfo.Device;
|
|
HcDevicePath->AhciEp.Function = PciNodeInfo.Function;
|
|
|
|
PciWrite32 (PciHcBase + PCI_AHCI_BASE_ADDRESSREG_OFFSET, (UINT32) HcInfo->Bar);
|
|
PciWrite8 (PciHcBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE);
|
|
Private->TotalAhciHcs++;
|
|
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"%a: ATA AHCI host controller found at - Bus(0x0), Dev(0x%x), Func(0x%x)!\n",
|
|
__FUNCTION__, HcInfo->PciInfo.Device, HcInfo->PciInfo.Function
|
|
));
|
|
DEBUG ((
|
|
DEBUG_INFO, "%a: Bar = 0x%x, MmioSize = 0x%x.\n",
|
|
__FUNCTION__, HcInfo->Bar, MmioSize
|
|
));
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
ErrorExit:
|
|
AhciHcConfigSpaceRestore (HcInfo);
|
|
ZeroMem (HcInfo, sizeof (HcInfo));
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Enable the ATA AHCI host controllers by programing the PCI configuration space.
|
|
|
|
@param[in,out] Private A pointer to the AHCI_HC_PEI_PRIVATE_DATA structure.
|
|
@param[in] IsRaid Indicate if private structure is for RAID device.
|
|
|
|
@retval EFI_SUCCESS The function completes successfully.
|
|
@retval others The function fails.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AhciEnableHcs (
|
|
IN OUT AHCI_HC_PEI_PRIVATE_DATA *Private,
|
|
IN BOOLEAN IsRaid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
|
|
Private->IsRaid = IsRaid;
|
|
|
|
for (Index = 0; Index < MAX_ATA_AHCI_HCS; Index++) {
|
|
Status = AhciEnableThisHc (Private, mAhciHcPciInfo[Index]);
|
|
if (Status == EFI_OUT_OF_RESOURCES) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
DEBUG ((
|
|
DEBUG_INFO, "%a: A total of %d AHCI host controller found, IsRaid = %d\n",
|
|
__FUNCTION__, Private->TotalAhciHcs, IsRaid
|
|
));
|
|
|
|
if (Private->TotalAhciHcs == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Private->Signature = AHCI_HC_PEI_SIGNATURE;
|
|
CopyMem (&Private->AhciControllerPpi, &mAhciHostControllerPpi, sizeof (EDKII_ATA_AHCI_HOST_CONTROLLER_PPI));
|
|
|
|
if(IsRaid) {
|
|
CopyMem (&Private->PpiList, &mRstPpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
|
|
} else {
|
|
CopyMem (&Private->PpiList, &mPpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
|
|
}
|
|
|
|
CopyMem (&Private->EndOfPeiNotifyList, &mEndOfPeiNotifyList, sizeof (EFI_PEI_NOTIFY_DESCRIPTOR));
|
|
Private->PpiList.Ppi = &Private->AhciControllerPpi;
|
|
|
|
PeiServicesInstallPpi (&Private->PpiList);
|
|
PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Initialize ATA AHCI host controller.
|
|
|
|
@retval EFI_SUCCESS The function completes successfully.
|
|
@retval others The function fails.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AhciPciConfigSpaceProgram (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AHCI_HC_PEI_PRIVATE_DATA *Private;
|
|
|
|
Status = AhciGetMmio (&MmioBarBase, &MmioBarLimit);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Initialize AHCI controllers for AHCI mode
|
|
//
|
|
Private = (AHCI_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (AHCI_HC_PEI_PRIVATE_DATA));
|
|
if (Private == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory for AHCI_HC_PEI_PRIVATE_DATA.\n", __FUNCTION__));
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
AhciEnableHcs (Private, FALSE);
|
|
|
|
//
|
|
// Initialize AHCI controllers for RAID mode
|
|
//
|
|
Private = (AHCI_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (AHCI_HC_PEI_PRIVATE_DATA));
|
|
if (Private == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory for AHCI_HC_PEI_PRIVATE_DATA (RAID mode).\n", __FUNCTION__));
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
AhciEnableHcs (Private, TRUE);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
One notified function to restore the controller PCI configuration space at
|
|
EndOfPei.
|
|
|
|
@param[in] PeiServices Pointer to PEI Services Table.
|
|
@param[in] NotifyDescriptor Pointer to the descriptor for the Notification
|
|
event that caused this function to execute.
|
|
@param[in] Ppi Pointer to the PPI data associated with this function.
|
|
|
|
@retval EFI_SUCCESS The function completes successfully.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AhciHcEndOfPei (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
|
IN VOID *Ppi
|
|
)
|
|
{
|
|
AHCI_HC_PEI_PRIVATE_DATA *Private;
|
|
UINTN HcIndex;
|
|
|
|
Private = AHCI_HC_PEI_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);
|
|
ASSERT (Private->TotalAhciHcs <= MAX_ATA_AHCI_HCS);
|
|
|
|
for (HcIndex = 0; HcIndex < Private->TotalAhciHcs; HcIndex++) {
|
|
AhciHcConfigSpaceRestore (&(Private->HcInfo[HcIndex]));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Entry point of the PEIM.
|
|
|
|
@param[in] FileHandle Handle of the file being invoked.
|
|
@param[in] PeiServices Describes the list of possible PEI Services.
|
|
|
|
@retval EFI_SUCCESS Operation performed successfully.
|
|
@retval EFI_OUT_OF_RESOURCES Not enough memory to allocate.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AhciPciHcPeimEntry (
|
|
IN EFI_PEI_FILE_HANDLE FileHandle,
|
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_BOOT_MODE BootMode;
|
|
|
|
Status = PeiServicesGetBootMode (&BootMode);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "%a: Fail to get the current boot mode.\n", __FUNCTION__));
|
|
return Status;
|
|
}
|
|
|
|
if ((BootMode == BOOT_ON_S3_RESUME) ||
|
|
(BootMode == BOOT_IN_RECOVERY_MODE) ||
|
|
(BootMode == BOOT_ON_FLASH_UPDATE)) {
|
|
Status = AhciPciConfigSpaceProgram ();
|
|
}
|
|
|
|
return Status;
|
|
}
|