2 The device path help function.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "NvmExpressPei.h"
20 // Template for an Nvm Express Device Path node
22 NVME_NAMESPACE_DEVICE_PATH mNvmeDevicePathNodeTemplate
= {
24 MESSAGING_DEVICE_PATH
,
25 MSG_NVME_NAMESPACE_DP
,
27 (UINT8
) (sizeof (NVME_NAMESPACE_DEVICE_PATH
)),
28 (UINT8
) ((sizeof (NVME_NAMESPACE_DEVICE_PATH
)) >> 8)
36 // Template for an End of entire Device Path node
38 EFI_DEVICE_PATH_PROTOCOL mNvmeEndDevicePathNodeTemplate
= {
40 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
42 (UINT8
) (sizeof (EFI_DEVICE_PATH_PROTOCOL
)),
43 (UINT8
) ((sizeof (EFI_DEVICE_PATH_PROTOCOL
)) >> 8)
48 Returns the 16-bit Length field of a device path node.
50 Returns the 16-bit Length field of the device path node specified by Node.
51 Node is not required to be aligned on a 16-bit boundary, so it is recommended
52 that a function such as ReadUnaligned16() be used to extract the contents of
55 If Node is NULL, then ASSERT().
57 @param Node A pointer to a device path node data structure.
59 @return The 16-bit Length field of the device path node specified by Node.
63 DevicePathNodeLength (
67 ASSERT (Node
!= NULL
);
68 return ReadUnaligned16 ((UINT16
*)&((EFI_DEVICE_PATH_PROTOCOL
*)(Node
))->Length
[0]);
72 Returns a pointer to the next node in a device path.
74 If Node is NULL, then ASSERT().
76 @param Node A pointer to a device path node data structure.
78 @return a pointer to the device path node that follows the device path node
82 EFI_DEVICE_PATH_PROTOCOL
*
87 ASSERT (Node
!= NULL
);
88 return (EFI_DEVICE_PATH_PROTOCOL
*)((UINT8
*)(Node
) + DevicePathNodeLength(Node
));
92 Get the size of the current device path instance.
94 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
96 @param[out] InstanceSize The size of the current device path instance.
97 @param[out] EntireDevicePathEnd Indicate whether the instance is the last
98 one in the device path strucure.
100 @retval EFI_SUCCESS The size of the current device path instance is fetched.
101 @retval Others Fails to get the size of the current device path instance.
105 GetDevicePathInstanceSize (
106 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
107 OUT UINTN
*InstanceSize
,
108 OUT BOOLEAN
*EntireDevicePathEnd
111 EFI_DEVICE_PATH_PROTOCOL
*Walker
;
113 if (DevicePath
== NULL
|| InstanceSize
== NULL
|| EntireDevicePathEnd
== NULL
) {
114 return EFI_INVALID_PARAMETER
;
118 // Find the end of the device path instance
121 while (Walker
->Type
!= END_DEVICE_PATH_TYPE
) {
122 Walker
= NextDevicePathNode (Walker
);
126 // Check if 'Walker' points to the end of an entire device path
128 if (Walker
->SubType
== END_ENTIRE_DEVICE_PATH_SUBTYPE
) {
129 *EntireDevicePathEnd
= TRUE
;
130 } else if (Walker
->SubType
== END_INSTANCE_DEVICE_PATH_SUBTYPE
) {
131 *EntireDevicePathEnd
= FALSE
;
133 return EFI_INVALID_PARAMETER
;
137 // Compute the size of the device path instance
139 *InstanceSize
= ((UINTN
) Walker
- (UINTN
) (DevicePath
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
145 Check the validity of the device path of a NVM Express host controller.
147 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
149 @param[in] DevicePathLength The length of the device path.
151 @retval EFI_SUCCESS The device path is valid.
152 @retval EFI_INVALID_PARAMETER The device path is invalid.
156 NvmeIsHcDevicePathValid (
157 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
158 IN UINTN DevicePathLength
161 EFI_DEVICE_PATH_PROTOCOL
*Start
;
164 if (DevicePath
== NULL
) {
165 return EFI_INVALID_PARAMETER
;
169 // Validate the DevicePathLength is big enough to touch the first node.
171 if (DevicePathLength
< sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
172 return EFI_INVALID_PARAMETER
;
176 while (!(DevicePath
->Type
== END_DEVICE_PATH_TYPE
&&
177 DevicePath
->SubType
== END_ENTIRE_DEVICE_PATH_SUBTYPE
)) {
178 DevicePath
= NextDevicePathNode (DevicePath
);
181 // Prevent overflow and invalid zero in the 'Length' field of a device path
184 if ((UINTN
) DevicePath
<= (UINTN
) Start
) {
185 return EFI_INVALID_PARAMETER
;
189 // Prevent touching memory beyond given DevicePathLength.
191 if ((UINTN
) DevicePath
- (UINTN
) Start
>
192 DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
193 return EFI_INVALID_PARAMETER
;
198 // Check if the device path and its size match exactly with each other.
200 Size
= ((UINTN
) DevicePath
- (UINTN
) Start
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
201 if (Size
!= DevicePathLength
) {
202 return EFI_INVALID_PARAMETER
;
209 Build the device path for an Nvm Express device with given namespace identifier
210 and namespace extended unique identifier.
212 @param[in] Private A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA
214 @param[in] NamespaceId The given namespace identifier.
215 @param[in] NamespaceUuid The given namespace extended unique identifier.
216 @param[out] DevicePathLength The length of the device path in bytes specified
218 @param[out] DevicePath The device path of Nvm Express device.
220 @retval EFI_SUCCESS The operation succeeds.
221 @retval EFI_INVALID_PARAMETER The parameters are invalid.
222 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
226 NvmeBuildDevicePath (
227 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
,
228 IN UINT32 NamespaceId
,
229 IN UINT64 NamespaceUuid
,
230 OUT UINTN
*DevicePathLength
,
231 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
234 EFI_DEVICE_PATH_PROTOCOL
*DevicePathWalker
;
235 NVME_NAMESPACE_DEVICE_PATH
*NvmeDeviceNode
;
237 if (DevicePathLength
== NULL
|| DevicePath
== NULL
) {
238 return EFI_INVALID_PARAMETER
;
241 *DevicePathLength
= Private
->DevicePathLength
+ sizeof (NVME_NAMESPACE_DEVICE_PATH
);
242 *DevicePath
= AllocatePool (*DevicePathLength
);
243 if (*DevicePath
== NULL
) {
244 *DevicePathLength
= 0;
245 return EFI_OUT_OF_RESOURCES
;
249 // Construct the host controller part device nodes
251 DevicePathWalker
= *DevicePath
;
255 Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)
259 // Construct the Nvm Express device node
261 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*) ((UINT8
*)DevicePathWalker
+
262 (Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
265 &mNvmeDevicePathNodeTemplate
,
266 sizeof (mNvmeDevicePathNodeTemplate
)
268 NvmeDeviceNode
= (NVME_NAMESPACE_DEVICE_PATH
*)DevicePathWalker
;
269 NvmeDeviceNode
->NamespaceId
= NamespaceId
;
270 NvmeDeviceNode
->NamespaceUuid
= NamespaceUuid
;
273 // Construct the end device node
275 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*) ((UINT8
*)DevicePathWalker
+
276 sizeof (NVME_NAMESPACE_DEVICE_PATH
));
279 &mNvmeEndDevicePathNodeTemplate
,
280 sizeof (mNvmeEndDevicePathNodeTemplate
)