summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c
blob: d704c62eaab3a19352b1503630207046bbf67420 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/** @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;
    }
  }

  if (S3InitDevices == NULL) {
    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;
}