]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AhciPei/AhciPeiS3.c
MdeModulePkg/AhciPei: Add AHCI mode ATA device support in PEI
[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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution. The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "AhciPei.h"
19
20 #include <Guid/S3StorageDeviceInitList.h>
21
22 #include <Library/LockBoxLib.h>
23
24 /**
25 Collect the ports that need to be enumerated on a controller for S3 phase.
26
27 @param[in] HcDevicePath Device path of the controller.
28 @param[in] HcDevicePathLength Length of the device path specified by
29 HcDevicePath.
30 @param[out] PortBitMap Bitmap that indicates the ports that need
31 to be enumerated on the controller.
32
33 @retval The number of ports that need to be enumerated.
34
35 **/
36 UINT8
37 AhciS3GetEumeratePorts (
38 IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath,
39 IN UINTN HcDevicePathLength,
40 OUT UINT32 *PortBitMap
41 )
42 {
43 EFI_STATUS Status;
44 UINT8 DummyData;
45 UINTN S3InitDevicesLength;
46 EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;
47 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
48 UINTN DevicePathInstLength;
49 BOOLEAN EntireEnd;
50 SATA_DEVICE_PATH *SataDeviceNode;
51
52 *PortBitMap = 0;
53
54 //
55 // From the LockBox, get the list of device paths for devices need to be
56 // initialized in S3.
57 //
58 S3InitDevices = NULL;
59 S3InitDevicesLength = sizeof (DummyData);
60 EntireEnd = FALSE;
61 Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, &DummyData, &S3InitDevicesLength);
62 if (Status != EFI_BUFFER_TOO_SMALL) {
63 return 0;
64 } else {
65 S3InitDevices = AllocatePool (S3InitDevicesLength);
66 if (S3InitDevices == NULL) {
67 return 0;
68 }
69
70 Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, S3InitDevices, &S3InitDevicesLength);
71 if (EFI_ERROR (Status)) {
72 return 0;
73 }
74 }
75
76 if (S3InitDevices == NULL) {
77 return 0;
78 }
79
80 //
81 // Only enumerate the ports that exist in the device list.
82 //
83 do {
84 //
85 // Fetch the size of current device path instance.
86 //
87 Status = GetDevicePathInstanceSize (
88 S3InitDevices,
89 &DevicePathInstLength,
90 &EntireEnd
91 );
92 if (EFI_ERROR (Status)) {
93 break;
94 }
95
96 DevicePathInst = S3InitDevices;
97 S3InitDevices = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN) S3InitDevices + DevicePathInstLength);
98
99 if (HcDevicePathLength >= DevicePathInstLength) {
100 continue;
101 }
102
103 //
104 // Compare the device paths to determine if the device is managed by this
105 // controller.
106 //
107 if (CompareMem (
108 DevicePathInst,
109 HcDevicePath,
110 HcDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)
111 ) == 0) {
112 //
113 // Get the port number.
114 //
115 while (DevicePathInst->Type != END_DEVICE_PATH_TYPE) {
116 if ((DevicePathInst->Type == MESSAGING_DEVICE_PATH) &&
117 (DevicePathInst->SubType == MSG_SATA_DP)) {
118 SataDeviceNode = (SATA_DEVICE_PATH *) DevicePathInst;
119 //
120 // For now, the driver only support upto AHCI_MAX_PORTS ports and
121 // devices directly connected to a HBA.
122 //
123 if ((SataDeviceNode->HBAPortNumber >= AHCI_MAX_PORTS) ||
124 (SataDeviceNode->PortMultiplierPortNumber != 0xFFFF)) {
125 break;
126 }
127 *PortBitMap |= (UINT32)BIT0 << SataDeviceNode->HBAPortNumber;
128 break;
129 }
130 DevicePathInst = NextDevicePathNode (DevicePathInst);
131 }
132 }
133 } while (!EntireEnd);
134
135 //
136 // Return the number of ports need to be enumerated on this controller.
137 //
138 return AhciGetNumberOfPortsFromMap (*PortBitMap);
139 }