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