2 The device path help function.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "NvmExpressPei.h"
13 // Template for an Nvm Express Device Path node
15 NVME_NAMESPACE_DEVICE_PATH mNvmeDevicePathNodeTemplate
= {
17 MESSAGING_DEVICE_PATH
,
18 MSG_NVME_NAMESPACE_DP
,
20 (UINT8
) (sizeof (NVME_NAMESPACE_DEVICE_PATH
)),
21 (UINT8
) ((sizeof (NVME_NAMESPACE_DEVICE_PATH
)) >> 8)
29 // Template for an End of entire Device Path node
31 EFI_DEVICE_PATH_PROTOCOL mNvmeEndDevicePathNodeTemplate
= {
33 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
35 (UINT8
) (sizeof (EFI_DEVICE_PATH_PROTOCOL
)),
36 (UINT8
) ((sizeof (EFI_DEVICE_PATH_PROTOCOL
)) >> 8)
41 Returns the 16-bit Length field of a device path node.
43 Returns the 16-bit Length field of the device path node specified by Node.
44 Node is not required to be aligned on a 16-bit boundary, so it is recommended
45 that a function such as ReadUnaligned16() be used to extract the contents of
48 If Node is NULL, then ASSERT().
50 @param Node A pointer to a device path node data structure.
52 @return The 16-bit Length field of the device path node specified by Node.
56 DevicePathNodeLength (
60 ASSERT (Node
!= NULL
);
61 return ReadUnaligned16 ((UINT16
*)&((EFI_DEVICE_PATH_PROTOCOL
*)(Node
))->Length
[0]);
65 Returns a pointer to the next node in a device path.
67 If Node is NULL, then ASSERT().
69 @param Node A pointer to a device path node data structure.
71 @return a pointer to the device path node that follows the device path node
75 EFI_DEVICE_PATH_PROTOCOL
*
80 ASSERT (Node
!= NULL
);
81 return (EFI_DEVICE_PATH_PROTOCOL
*)((UINT8
*)(Node
) + DevicePathNodeLength(Node
));
85 Get the size of the current device path instance.
87 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
89 @param[out] InstanceSize The size of the current device path instance.
90 @param[out] EntireDevicePathEnd Indicate whether the instance is the last
91 one in the device path strucure.
93 @retval EFI_SUCCESS The size of the current device path instance is fetched.
94 @retval Others Fails to get the size of the current device path instance.
98 GetDevicePathInstanceSize (
99 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
100 OUT UINTN
*InstanceSize
,
101 OUT BOOLEAN
*EntireDevicePathEnd
104 EFI_DEVICE_PATH_PROTOCOL
*Walker
;
106 if (DevicePath
== NULL
|| InstanceSize
== NULL
|| EntireDevicePathEnd
== NULL
) {
107 return EFI_INVALID_PARAMETER
;
111 // Find the end of the device path instance
114 while (Walker
->Type
!= END_DEVICE_PATH_TYPE
) {
115 Walker
= NextDevicePathNode (Walker
);
119 // Check if 'Walker' points to the end of an entire device path
121 if (Walker
->SubType
== END_ENTIRE_DEVICE_PATH_SUBTYPE
) {
122 *EntireDevicePathEnd
= TRUE
;
123 } else if (Walker
->SubType
== END_INSTANCE_DEVICE_PATH_SUBTYPE
) {
124 *EntireDevicePathEnd
= FALSE
;
126 return EFI_INVALID_PARAMETER
;
130 // Compute the size of the device path instance
132 *InstanceSize
= ((UINTN
) Walker
- (UINTN
) (DevicePath
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
138 Check the validity of the device path of a NVM Express host controller.
140 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
142 @param[in] DevicePathLength The length of the device path.
144 @retval EFI_SUCCESS The device path is valid.
145 @retval EFI_INVALID_PARAMETER The device path is invalid.
149 NvmeIsHcDevicePathValid (
150 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
151 IN UINTN DevicePathLength
154 EFI_DEVICE_PATH_PROTOCOL
*Start
;
157 if (DevicePath
== NULL
) {
158 return EFI_INVALID_PARAMETER
;
162 // Validate the DevicePathLength is big enough to touch the first node.
164 if (DevicePathLength
< sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
165 return EFI_INVALID_PARAMETER
;
169 while (!(DevicePath
->Type
== END_DEVICE_PATH_TYPE
&&
170 DevicePath
->SubType
== END_ENTIRE_DEVICE_PATH_SUBTYPE
)) {
171 DevicePath
= NextDevicePathNode (DevicePath
);
174 // Prevent overflow and invalid zero in the 'Length' field of a device path
177 if ((UINTN
) DevicePath
<= (UINTN
) Start
) {
178 return EFI_INVALID_PARAMETER
;
182 // Prevent touching memory beyond given DevicePathLength.
184 if ((UINTN
) DevicePath
- (UINTN
) Start
>
185 DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
186 return EFI_INVALID_PARAMETER
;
191 // Check if the device path and its size match exactly with each other.
193 Size
= ((UINTN
) DevicePath
- (UINTN
) Start
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
194 if (Size
!= DevicePathLength
) {
195 return EFI_INVALID_PARAMETER
;
202 Build the device path for an Nvm Express device with given namespace identifier
203 and namespace extended unique identifier.
205 @param[in] Private A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA
207 @param[in] NamespaceId The given namespace identifier.
208 @param[in] NamespaceUuid The given namespace extended unique identifier.
209 @param[out] DevicePathLength The length of the device path in bytes specified
211 @param[out] DevicePath The device path of Nvm Express device.
213 @retval EFI_SUCCESS The operation succeeds.
214 @retval EFI_INVALID_PARAMETER The parameters are invalid.
215 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
219 NvmeBuildDevicePath (
220 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
,
221 IN UINT32 NamespaceId
,
222 IN UINT64 NamespaceUuid
,
223 OUT UINTN
*DevicePathLength
,
224 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
227 EFI_DEVICE_PATH_PROTOCOL
*DevicePathWalker
;
228 NVME_NAMESPACE_DEVICE_PATH
*NvmeDeviceNode
;
230 if (DevicePathLength
== NULL
|| DevicePath
== NULL
) {
231 return EFI_INVALID_PARAMETER
;
234 *DevicePathLength
= Private
->DevicePathLength
+ sizeof (NVME_NAMESPACE_DEVICE_PATH
);
235 *DevicePath
= AllocatePool (*DevicePathLength
);
236 if (*DevicePath
== NULL
) {
237 *DevicePathLength
= 0;
238 return EFI_OUT_OF_RESOURCES
;
242 // Construct the host controller part device nodes
244 DevicePathWalker
= *DevicePath
;
248 Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)
252 // Construct the Nvm Express device node
254 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*) ((UINT8
*)DevicePathWalker
+
255 (Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
258 &mNvmeDevicePathNodeTemplate
,
259 sizeof (mNvmeDevicePathNodeTemplate
)
261 NvmeDeviceNode
= (NVME_NAMESPACE_DEVICE_PATH
*)DevicePathWalker
;
262 NvmeDeviceNode
->NamespaceId
= NamespaceId
;
263 NvmeDeviceNode
->NamespaceUuid
= NamespaceUuid
;
266 // Construct the end device node
268 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*) ((UINT8
*)DevicePathWalker
+
269 sizeof (NVME_NAMESPACE_DEVICE_PATH
));
272 &mNvmeEndDevicePathNodeTemplate
,
273 sizeof (mNvmeEndDevicePathNodeTemplate
)