]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AhciPei/AhciPeiS3.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 //
70 // Only enumerate the ports that exist in the device list.
71 //
72 do {
73 //
74 // Fetch the size of current device path instance.
75 //
76 Status = GetDevicePathInstanceSize (
77 S3InitDevices,
78 &DevicePathInstLength,
79 &EntireEnd
80 );
81 if (EFI_ERROR (Status)) {
82 break;
83 }
84
85 DevicePathInst = S3InitDevices;
86 S3InitDevices = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)S3InitDevices + DevicePathInstLength);
87
88 if (HcDevicePathLength >= DevicePathInstLength) {
89 continue;
90 }
91
92 //
93 // Compare the device paths to determine if the device is managed by this
94 // controller.
95 //
96 if (CompareMem (
97 DevicePathInst,
98 HcDevicePath,
99 HcDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)
100 ) == 0)
101 {
102 //
103 // Get the port number.
104 //
105 while (DevicePathInst->Type != END_DEVICE_PATH_TYPE) {
106 if ((DevicePathInst->Type == MESSAGING_DEVICE_PATH) &&
107 (DevicePathInst->SubType == MSG_SATA_DP))
108 {
109 SataDeviceNode = (SATA_DEVICE_PATH *)DevicePathInst;
110 //
111 // For now, the driver only support upto AHCI_MAX_PORTS ports and
112 // devices directly connected to a HBA.
113 //
114 if ((SataDeviceNode->HBAPortNumber >= AHCI_MAX_PORTS) ||
115 (SataDeviceNode->PortMultiplierPortNumber != 0xFFFF))
116 {
117 break;
118 }
119
120 *PortBitMap |= (UINT32)BIT0 << SataDeviceNode->HBAPortNumber;
121 break;
122 }
123
124 DevicePathInst = NextDevicePathNode (DevicePathInst);
125 }
126 }
127 } while (!EntireEnd);
128
129 //
130 // Return the number of ports need to be enumerated on this controller.
131 //
132 return AhciGetNumberOfPortsFromMap (*PortBitMap);
133 }