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