| /** @file | |
| The NvmExpressPei driver is used to manage non-volatile memory subsystem | |
| which follows NVM Express specification at PEI phase. | |
| Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "NvmExpressPei.h" | |
| #include <Guid/S3StorageDeviceInitList.h> | |
| #include <Library/LockBoxLib.h> | |
| /** | |
| Determine if a specific NVM Express controller can be skipped for S3 phase. | |
| @param[in] HcDevicePath Device path of the controller. | |
| @param[in] HcDevicePathLength Length of the device path specified by | |
| HcDevicePath. | |
| @retval The number of ports that need to be enumerated. | |
| **/ | |
| BOOLEAN | |
| NvmeS3SkipThisController ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath, | |
| IN UINTN HcDevicePathLength | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT8 DummyData; | |
| UINTN S3InitDevicesLength; | |
| EFI_DEVICE_PATH_PROTOCOL *S3InitDevices; | |
| EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; | |
| UINTN DevicePathInstLength; | |
| BOOLEAN EntireEnd; | |
| BOOLEAN Skip; | |
| // | |
| // From the LockBox, get the list of device paths for devices need to be | |
| // initialized in S3. | |
| // | |
| S3InitDevices = NULL; | |
| S3InitDevicesLength = sizeof (DummyData); | |
| EntireEnd = FALSE; | |
| Skip = TRUE; | |
| Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, &DummyData, &S3InitDevicesLength); | |
| if (Status != EFI_BUFFER_TOO_SMALL) { | |
| return Skip; | |
| } else { | |
| S3InitDevices = AllocatePool (S3InitDevicesLength); | |
| if (S3InitDevices == NULL) { | |
| return Skip; | |
| } | |
| Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, S3InitDevices, &S3InitDevicesLength); | |
| if (EFI_ERROR (Status)) { | |
| return Skip; | |
| } | |
| } | |
| // | |
| // Only need to initialize the controllers that exist in the device list. | |
| // | |
| do { | |
| // | |
| // Fetch the size of current device path instance. | |
| // | |
| Status = GetDevicePathInstanceSize ( | |
| S3InitDevices, | |
| &DevicePathInstLength, | |
| &EntireEnd | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| break; | |
| } | |
| DevicePathInst = S3InitDevices; | |
| S3InitDevices = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)S3InitDevices + DevicePathInstLength); | |
| if (HcDevicePathLength >= DevicePathInstLength) { | |
| continue; | |
| } | |
| // | |
| // Compare the device paths to determine if the device is managed by this | |
| // controller. | |
| // | |
| if (CompareMem ( | |
| DevicePathInst, | |
| HcDevicePath, | |
| HcDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL) | |
| ) == 0) | |
| { | |
| Skip = FALSE; | |
| break; | |
| } | |
| } while (!EntireEnd); | |
| return Skip; | |
| } |