]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ata/AhciPei/DevicePath.c
MdeModulePkg/AhciPei: Use PCI_DEVICE_PPI to manage AHCI device
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AhciPei / DevicePath.c
CommitLineData
87bc3f19
HW
1/** @file\r
2 The device path help function.\r
3\r
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
5\r
9d510e61 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
87bc3f19
HW
7\r
8**/\r
9\r
10#include "AhciPei.h"\r
11\r
12//\r
13// Template for a SATA Device Path node\r
14//\r
15SATA_DEVICE_PATH mAhciSataDevicePathNodeTemplate = {\r
16 { // Header\r
17 MESSAGING_DEVICE_PATH,\r
18 MSG_SATA_DP,\r
19 {\r
1436aea4
MK
20 (UINT8)(sizeof (SATA_DEVICE_PATH)),\r
21 (UINT8)((sizeof (SATA_DEVICE_PATH)) >> 8)\r
87bc3f19
HW
22 }\r
23 },\r
24 0x0, // HBAPortNumber\r
25 0xFFFF, // PortMultiplierPortNumber\r
26 0x0 // Lun\r
27};\r
28\r
29//\r
30// Template for an End of entire Device Path node\r
31//\r
32EFI_DEVICE_PATH_PROTOCOL mAhciEndDevicePathNodeTemplate = {\r
33 END_DEVICE_PATH_TYPE,\r
34 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
35 {\r
1436aea4
MK
36 (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)),\r
37 (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)\r
87bc3f19
HW
38 }\r
39};\r
40\r
87bc3f19
HW
41/**\r
42 Get the size of the current device path instance.\r
43\r
44 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL\r
45 structure.\r
46 @param[out] InstanceSize The size of the current device path instance.\r
47 @param[out] EntireDevicePathEnd Indicate whether the instance is the last\r
48 one in the device path strucure.\r
49\r
50 @retval EFI_SUCCESS The size of the current device path instance is fetched.\r
51 @retval Others Fails to get the size of the current device path instance.\r
52\r
53**/\r
54EFI_STATUS\r
55GetDevicePathInstanceSize (\r
1436aea4
MK
56 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
57 OUT UINTN *InstanceSize,\r
58 OUT BOOLEAN *EntireDevicePathEnd\r
87bc3f19
HW
59 )\r
60{\r
1436aea4 61 EFI_DEVICE_PATH_PROTOCOL *Walker;\r
87bc3f19 62\r
1436aea4 63 if ((DevicePath == NULL) || (InstanceSize == NULL) || (EntireDevicePathEnd == NULL)) {\r
87bc3f19
HW
64 return EFI_INVALID_PARAMETER;\r
65 }\r
66\r
67 //\r
68 // Find the end of the device path instance\r
69 //\r
70 Walker = DevicePath;\r
71 while (Walker->Type != END_DEVICE_PATH_TYPE) {\r
72 Walker = NextDevicePathNode (Walker);\r
73 }\r
74\r
75 //\r
76 // Check if 'Walker' points to the end of an entire device path\r
77 //\r
78 if (Walker->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) {\r
79 *EntireDevicePathEnd = TRUE;\r
80 } else if (Walker->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE) {\r
81 *EntireDevicePathEnd = FALSE;\r
82 } else {\r
83 return EFI_INVALID_PARAMETER;\r
84 }\r
85\r
86 //\r
87 // Compute the size of the device path instance\r
88 //\r
1436aea4 89 *InstanceSize = ((UINTN)Walker - (UINTN)(DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
87bc3f19
HW
90\r
91 return EFI_SUCCESS;\r
92}\r
93\r
94/**\r
95 Check the validity of the device path of a ATA AHCI host controller.\r
96\r
97 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL\r
98 structure.\r
99 @param[in] DevicePathLength The length of the device path.\r
100\r
101 @retval EFI_SUCCESS The device path is valid.\r
102 @retval EFI_INVALID_PARAMETER The device path is invalid.\r
103\r
104**/\r
105EFI_STATUS\r
106AhciIsHcDevicePathValid (\r
1436aea4
MK
107 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
108 IN UINTN DevicePathLength\r
87bc3f19
HW
109 )\r
110{\r
1436aea4
MK
111 EFI_DEVICE_PATH_PROTOCOL *Start;\r
112 UINTN Size;\r
87bc3f19
HW
113\r
114 if (DevicePath == NULL) {\r
115 return EFI_INVALID_PARAMETER;\r
116 }\r
117\r
118 //\r
119 // Validate the DevicePathLength is big enough to touch the first node.\r
120 //\r
121 if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
122 return EFI_INVALID_PARAMETER;\r
123 }\r
124\r
125 Start = DevicePath;\r
126 while (!(DevicePath->Type == END_DEVICE_PATH_TYPE &&\r
1436aea4
MK
127 DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE))\r
128 {\r
87bc3f19
HW
129 DevicePath = NextDevicePathNode (DevicePath);\r
130\r
131 //\r
132 // Prevent overflow and invalid zero in the 'Length' field of a device path\r
133 // node.\r
134 //\r
1436aea4 135 if ((UINTN)DevicePath <= (UINTN)Start) {\r
87bc3f19
HW
136 return EFI_INVALID_PARAMETER;\r
137 }\r
138\r
139 //\r
140 // Prevent touching memory beyond given DevicePathLength.\r
141 //\r
1436aea4
MK
142 if ((UINTN)DevicePath - (UINTN)Start >\r
143 DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL))\r
144 {\r
87bc3f19
HW
145 return EFI_INVALID_PARAMETER;\r
146 }\r
147 }\r
148\r
149 //\r
150 // Check if the device path and its size match each other.\r
151 //\r
1436aea4 152 Size = ((UINTN)DevicePath - (UINTN)Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
87bc3f19
HW
153 if (Size != DevicePathLength) {\r
154 return EFI_INVALID_PARAMETER;\r
155 }\r
156\r
157 return EFI_SUCCESS;\r
158}\r
159\r
160/**\r
161 Build the device path for an ATA device with given port and port multiplier number.\r
162\r
163 @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA\r
164 data structure.\r
165 @param[in] Port The given port number.\r
166 @param[in] PortMultiplierPort The given port multiplier number.\r
167 @param[out] DevicePathLength The length of the device path in bytes specified\r
168 by DevicePath.\r
169 @param[out] DevicePath The device path of ATA device.\r
170\r
171 @retval EFI_SUCCESS The operation succeeds.\r
172 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
173 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.\r
174\r
175**/\r
176EFI_STATUS\r
177AhciBuildDevicePath (\r
1436aea4
MK
178 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,\r
179 IN UINT16 Port,\r
180 IN UINT16 PortMultiplierPort,\r
181 OUT UINTN *DevicePathLength,\r
182 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
87bc3f19
HW
183 )\r
184{\r
1436aea4
MK
185 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;\r
186 SATA_DEVICE_PATH *SataDeviceNode;\r
87bc3f19 187\r
1436aea4 188 if ((DevicePathLength == NULL) || (DevicePath == NULL)) {\r
87bc3f19
HW
189 return EFI_INVALID_PARAMETER;\r
190 }\r
191\r
192 *DevicePathLength = Private->DevicePathLength + sizeof (SATA_DEVICE_PATH);\r
193 *DevicePath = AllocatePool (*DevicePathLength);\r
194 if (*DevicePath == NULL) {\r
195 *DevicePathLength = 0;\r
196 return EFI_OUT_OF_RESOURCES;\r
197 }\r
198\r
199 //\r
200 // Construct the host controller part device nodes\r
201 //\r
202 DevicePathWalker = *DevicePath;\r
203 CopyMem (\r
204 DevicePathWalker,\r
205 Private->DevicePath,\r
206 Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)\r
207 );\r
208\r
209 //\r
210 // Construct the SATA device node\r
211 //\r
1436aea4
MK
212 DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePathWalker +\r
213 (Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)));\r
87bc3f19
HW
214 CopyMem (\r
215 DevicePathWalker,\r
216 &mAhciSataDevicePathNodeTemplate,\r
217 sizeof (mAhciSataDevicePathNodeTemplate)\r
218 );\r
219 SataDeviceNode = (SATA_DEVICE_PATH *)DevicePathWalker;\r
220 SataDeviceNode->HBAPortNumber = Port;\r
221 SataDeviceNode->PortMultiplierPortNumber = PortMultiplierPort;\r
222\r
223 //\r
224 // Construct the end device node\r
225 //\r
1436aea4
MK
226 DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePathWalker +\r
227 sizeof (SATA_DEVICE_PATH));\r
87bc3f19
HW
228 CopyMem (\r
229 DevicePathWalker,\r
230 &mAhciEndDevicePathNodeTemplate,\r
231 sizeof (mAhciEndDevicePathNodeTemplate)\r
232 );\r
233\r
234 return EFI_SUCCESS;\r
235}\r