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 Get the size of the current device path instance.
43 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
45 @param[out] InstanceSize The size of the current device path instance.
46 @param[out] EntireDevicePathEnd Indicate whether the instance is the last
47 one in the device path strucure.
49 @retval EFI_SUCCESS The size of the current device path instance is fetched.
50 @retval Others Fails to get the size of the current device path instance.
54 GetDevicePathInstanceSize (
55 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
56 OUT UINTN
*InstanceSize
,
57 OUT BOOLEAN
*EntireDevicePathEnd
60 EFI_DEVICE_PATH_PROTOCOL
*Walker
;
62 if ((DevicePath
== NULL
) || (InstanceSize
== NULL
) || (EntireDevicePathEnd
== NULL
)) {
63 return EFI_INVALID_PARAMETER
;
67 // Find the end of the device path instance
70 while (Walker
->Type
!= END_DEVICE_PATH_TYPE
) {
71 Walker
= NextDevicePathNode (Walker
);
75 // Check if 'Walker' points to the end of an entire device path
77 if (Walker
->SubType
== END_ENTIRE_DEVICE_PATH_SUBTYPE
) {
78 *EntireDevicePathEnd
= TRUE
;
79 } else if (Walker
->SubType
== END_INSTANCE_DEVICE_PATH_SUBTYPE
) {
80 *EntireDevicePathEnd
= FALSE
;
82 return EFI_INVALID_PARAMETER
;
86 // Compute the size of the device path instance
88 *InstanceSize
= ((UINTN
)Walker
- (UINTN
)(DevicePath
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
94 Check the validity of the device path of a NVM Express host controller.
96 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
98 @param[in] DevicePathLength The length of the device path.
100 @retval EFI_SUCCESS The device path is valid.
101 @retval EFI_INVALID_PARAMETER The device path is invalid.
105 NvmeIsHcDevicePathValid (
106 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
107 IN UINTN DevicePathLength
110 EFI_DEVICE_PATH_PROTOCOL
*Start
;
113 if (DevicePath
== NULL
) {
114 return EFI_INVALID_PARAMETER
;
118 // Validate the DevicePathLength is big enough to touch the first node.
120 if (DevicePathLength
< sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
121 return EFI_INVALID_PARAMETER
;
125 while (!(DevicePath
->Type
== END_DEVICE_PATH_TYPE
&&
126 DevicePath
->SubType
== END_ENTIRE_DEVICE_PATH_SUBTYPE
))
128 DevicePath
= NextDevicePathNode (DevicePath
);
131 // Prevent overflow and invalid zero in the 'Length' field of a device path
134 if ((UINTN
)DevicePath
<= (UINTN
)Start
) {
135 return EFI_INVALID_PARAMETER
;
139 // Prevent touching memory beyond given DevicePathLength.
141 if ((UINTN
)DevicePath
- (UINTN
)Start
>
142 DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
))
144 return EFI_INVALID_PARAMETER
;
149 // Check if the device path and its size match exactly with each other.
151 Size
= ((UINTN
)DevicePath
- (UINTN
)Start
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
152 if (Size
!= DevicePathLength
) {
153 return EFI_INVALID_PARAMETER
;
160 Build the device path for an Nvm Express device with given namespace identifier
161 and namespace extended unique identifier.
163 @param[in] Private A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA
165 @param[in] NamespaceId The given namespace identifier.
166 @param[in] NamespaceUuid The given namespace extended unique identifier.
167 @param[out] DevicePathLength The length of the device path in bytes specified
169 @param[out] DevicePath The device path of Nvm Express device.
171 @retval EFI_SUCCESS The operation succeeds.
172 @retval EFI_INVALID_PARAMETER The parameters are invalid.
173 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
177 NvmeBuildDevicePath (
178 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
,
179 IN UINT32 NamespaceId
,
180 IN UINT64 NamespaceUuid
,
181 OUT UINTN
*DevicePathLength
,
182 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
185 EFI_DEVICE_PATH_PROTOCOL
*DevicePathWalker
;
186 NVME_NAMESPACE_DEVICE_PATH
*NvmeDeviceNode
;
188 if ((DevicePathLength
== NULL
) || (DevicePath
== NULL
)) {
189 return EFI_INVALID_PARAMETER
;
192 *DevicePathLength
= Private
->DevicePathLength
+ sizeof (NVME_NAMESPACE_DEVICE_PATH
);
193 *DevicePath
= AllocatePool (*DevicePathLength
);
194 if (*DevicePath
== NULL
) {
195 *DevicePathLength
= 0;
196 return EFI_OUT_OF_RESOURCES
;
200 // Construct the host controller part device nodes
202 DevicePathWalker
= *DevicePath
;
206 Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)
210 // Construct the Nvm Express device node
212 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINT8
*)DevicePathWalker
+
213 (Private
->DevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
216 &mNvmeDevicePathNodeTemplate
,
217 sizeof (mNvmeDevicePathNodeTemplate
)
219 NvmeDeviceNode
= (NVME_NAMESPACE_DEVICE_PATH
*)DevicePathWalker
;
220 NvmeDeviceNode
->NamespaceId
= NamespaceId
;
221 NvmeDeviceNode
->NamespaceUuid
= NamespaceUuid
;
224 // Construct the end device node
226 DevicePathWalker
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINT8
*)DevicePathWalker
+
227 sizeof (NVME_NAMESPACE_DEVICE_PATH
));
230 &mNvmeEndDevicePathNodeTemplate
,
231 sizeof (mNvmeEndDevicePathNodeTemplate
)