2 The device path help function.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 // Template for a SATA Device Path node
15 SATA_DEVICE_PATH mAhciSataDevicePathNodeTemplate
= {
17 MESSAGING_DEVICE_PATH
,
20 (UINT8
)(sizeof (SATA_DEVICE_PATH
)),
21 (UINT8
)((sizeof (SATA_DEVICE_PATH
)) >> 8)
25 0xFFFF, // PortMultiplierPortNumber
30 // Template for an End of entire Device Path node
32 EFI_DEVICE_PATH_PROTOCOL mAhciEndDevicePathNodeTemplate
= {
34 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
36 (UINT8
)(sizeof (EFI_DEVICE_PATH_PROTOCOL
)),
37 (UINT8
)((sizeof (EFI_DEVICE_PATH_PROTOCOL
)) >> 8)
42 Returns the 16-bit Length field of a device path node.
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
49 If Node is NULL, then ASSERT().
51 @param Node A pointer to a device path node data structure.
53 @return The 16-bit Length field of the device path node specified by Node.
57 DevicePathNodeLength (
61 ASSERT (Node
!= NULL
);
62 return ReadUnaligned16 ((UINT16
*)&((EFI_DEVICE_PATH_PROTOCOL
*)(Node
))->Length
[0]);
66 Returns a pointer to the next node in a device path.
68 If Node is NULL, then ASSERT().
70 @param Node A pointer to a device path node data structure.
72 @return a pointer to the device path node that follows the device path node
76 EFI_DEVICE_PATH_PROTOCOL
*
81 ASSERT (Node
!= NULL
);
82 return (EFI_DEVICE_PATH_PROTOCOL
*)((UINT8
*)(Node
) + DevicePathNodeLength (Node
));
86 Get the size of the current device path instance.
88 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
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.
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.
99 GetDevicePathInstanceSize (
100 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
101 OUT UINTN
*InstanceSize
,
102 OUT BOOLEAN
*EntireDevicePathEnd
105 EFI_DEVICE_PATH_PROTOCOL
*Walker
;
107 if ((DevicePath
== NULL
) || (InstanceSize
== NULL
) || (EntireDevicePathEnd
== NULL
)) {
108 return EFI_INVALID_PARAMETER
;
112 // Find the end of the device path instance
115 while (Walker
->Type
!= END_DEVICE_PATH_TYPE
) {
116 Walker
= NextDevicePathNode (Walker
);
120 // Check if 'Walker' points to the end of an entire device path
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
;
127 return EFI_INVALID_PARAMETER
;
131 // Compute the size of the device path instance
133 *InstanceSize
= ((UINTN
)Walker
- (UINTN
)(DevicePath
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
139 Check the validity of the device path of a ATA AHCI host controller.
141 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
143 @param[in] DevicePathLength The length of the device path.
145 @retval EFI_SUCCESS The device path is valid.
146 @retval EFI_INVALID_PARAMETER The device path is invalid.
150 AhciIsHcDevicePathValid (
151 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
152 IN UINTN DevicePathLength
155 EFI_DEVICE_PATH_PROTOCOL
*Start
;
158 if (DevicePath
== NULL
) {
159 return EFI_INVALID_PARAMETER
;
163 // Validate the DevicePathLength is big enough to touch the first node.
165 if (DevicePathLength
< sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
166 return EFI_INVALID_PARAMETER
;
170 while (!(DevicePath
->Type
== END_DEVICE_PATH_TYPE
&&
171 DevicePath
->SubType
== END_ENTIRE_DEVICE_PATH_SUBTYPE
))
173 DevicePath
= NextDevicePathNode (DevicePath
);
176 // Prevent overflow and invalid zero in the 'Length' field of a device path
179 if ((UINTN
)DevicePath
<= (UINTN
)Start
) {
180 return EFI_INVALID_PARAMETER
;
184 // Prevent touching memory beyond given DevicePathLength.
186 if ((UINTN
)DevicePath
- (UINTN
)Start
>
187 DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
))
189 return EFI_INVALID_PARAMETER
;
194 // Check if the device path and its size match each other.
196 Size
= ((UINTN
)DevicePath
- (UINTN
)Start
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
197 if (Size
!= DevicePathLength
) {
198 return EFI_INVALID_PARAMETER
;
205 Build the device path for an ATA device with given port and port multiplier number.
207 @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
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
213 @param[out] DevicePath The device path of ATA device.
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.
221 AhciBuildDevicePath (
222 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
224 IN UINT16 PortMultiplierPort
,
225 OUT UINTN
*DevicePathLength
,
226 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
229 EFI_DEVICE_PATH_PROTOCOL
*DevicePathWalker
;
230 SATA_DEVICE_PATH
*SataDeviceNode
;
232 if ((DevicePathLength
== NULL
) || (DevicePath
== NULL
)) {
233 return EFI_INVALID_PARAMETER
;
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
;
244 // Construct the host controller part device nodes
246 DevicePathWalker
= *DevicePath
;
250 Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)
254 // Construct the SATA device node
256 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINT8
*)DevicePathWalker
+
257 (Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
260 &mAhciSataDevicePathNodeTemplate
,
261 sizeof (mAhciSataDevicePathNodeTemplate
)
263 SataDeviceNode
= (SATA_DEVICE_PATH
*)DevicePathWalker
;
264 SataDeviceNode
->HBAPortNumber
= Port
;
265 SataDeviceNode
->PortMultiplierPortNumber
= PortMultiplierPort
;
268 // Construct the end device node
270 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINT8
*)DevicePathWalker
+
271 sizeof (SATA_DEVICE_PATH
));
274 &mAhciEndDevicePathNodeTemplate
,
275 sizeof (mAhciEndDevicePathNodeTemplate
)