]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AhciPei/AhciPeiS3.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AhciPei / AhciPeiS3.c
1 /** @file
2 The AhciPei driver is used to manage ATA hard disk device working under AHCI
3 mode at PEI phase.
4
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "AhciPei.h"
12
13 #include <Guid/S3StorageDeviceInitList.h>
14
15 #include <Library/LockBoxLib.h>
16
17 /**
18 Collect the ports that need to be enumerated on a controller for S3 phase.
19
20 @param[in] HcDevicePath Device path of the controller.
21 @param[in] HcDevicePathLength Length of the device path specified by
22 HcDevicePath.
23 @param[out] PortBitMap Bitmap that indicates the ports that need
24 to be enumerated on the controller.
25
26 @retval The number of ports that need to be enumerated.
27
28 **/
29 UINT8
30 AhciS3GetEumeratePorts (
31 IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath,
32 IN UINTN HcDevicePathLength,
33 OUT UINT32 *PortBitMap
34 )
35 {
36 EFI_STATUS Status;
37 UINT8 DummyData;
38 UINTN S3InitDevicesLength;
39 EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;
40 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
41 UINTN DevicePathInstLength;
42 BOOLEAN EntireEnd;
43 SATA_DEVICE_PATH *SataDeviceNode;
44
45 *PortBitMap = 0;
46
47 //
48 // From the LockBox, get the list of device paths for devices need to be
49 // initialized in S3.
50 //
51 S3InitDevices = NULL;
52 S3InitDevicesLength = sizeof (DummyData);
53 EntireEnd = FALSE;
54 Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, &DummyData, &S3InitDevicesLength);
55 if (Status != EFI_BUFFER_TOO_SMALL) {
56 return 0;
57 } else {
58 S3InitDevices = AllocatePool (S3InitDevicesLength);
59 if (S3InitDevices == NULL) {
60 return 0;
61 }
62
63 Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, S3InitDevices, &S3InitDevicesLength);
64 if (EFI_ERROR (Status)) {
65 return 0;
66 }
67 }
68
69 if (S3InitDevices == NULL) {
70 return 0;
71 }
72
73 //
74 // Only enumerate the ports that exist in the device list.
75 //
76 do {
77 //
78 // Fetch the size of current device path instance.
79 //
80 Status = GetDevicePathInstanceSize (
81 S3InitDevices,
82 &DevicePathInstLength,
83 &EntireEnd
84 );
85 if (EFI_ERROR (Status)) {
86 break;
87 }
88
89 DevicePathInst = S3InitDevices;
90 S3InitDevices = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN) S3InitDevices + DevicePathInstLength);
91
92 if (HcDevicePathLength >= DevicePathInstLength) {
93 continue;
94 }
95
96 //
97 // Compare the device paths to determine if the device is managed by this
98 // controller.
99 //
100 if (CompareMem (
101 DevicePathInst,
102 HcDevicePath,
103 HcDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)
104 ) == 0) {
105 //
106 // Get the port number.
107 //
108 while (DevicePathInst->Type != END_DEVICE_PATH_TYPE) {
109 if ((DevicePathInst->Type == MESSAGING_DEVICE_PATH) &&
110 (DevicePathInst->SubType == MSG_SATA_DP)) {
111 SataDeviceNode = (SATA_DEVICE_PATH *) DevicePathInst;
112 //
113 // For now, the driver only support upto AHCI_MAX_PORTS ports and
114 // devices directly connected to a HBA.
115 //
116 if ((SataDeviceNode->HBAPortNumber >= AHCI_MAX_PORTS) ||
117 (SataDeviceNode->PortMultiplierPortNumber != 0xFFFF)) {
118 break;
119 }
120 *PortBitMap |= (UINT32)BIT0 << SataDeviceNode->HBAPortNumber;
121 break;
122 }
123 DevicePathInst = NextDevicePathNode (DevicePathInst);
124 }
125 }
126 } while (!EntireEnd);
127
128 //
129 // Return the number of ports need to be enumerated on this controller.
130 //
131 return AhciGetNumberOfPortsFromMap (*PortBitMap);
132 }