]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
MdeModulePkg/NvmExpressPei: Use PCI_DEVICE_PPI to manage Nvme device
[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
1436aea4
MK
20 (UINT8)(sizeof (NVME_NAMESPACE_DEVICE_PATH)),\r
21 (UINT8)((sizeof (NVME_NAMESPACE_DEVICE_PATH)) >> 8)\r
2e15b750
HW
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
1436aea4
MK
35 (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)),\r
36 (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)\r
2e15b750
HW
37 }\r
38};\r
39\r
05fd2a92
HW
40/**\r
41 Get the size of the current device path instance.\r
42\r
43 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL\r
44 structure.\r
45 @param[out] InstanceSize The size of the current device path instance.\r
46 @param[out] EntireDevicePathEnd Indicate whether the instance is the last\r
47 one in the device path strucure.\r
48\r
49 @retval EFI_SUCCESS The size of the current device path instance is fetched.\r
50 @retval Others Fails to get the size of the current device path instance.\r
51\r
52**/\r
53EFI_STATUS\r
54GetDevicePathInstanceSize (\r
1436aea4
MK
55 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
56 OUT UINTN *InstanceSize,\r
57 OUT BOOLEAN *EntireDevicePathEnd\r
05fd2a92
HW
58 )\r
59{\r
1436aea4 60 EFI_DEVICE_PATH_PROTOCOL *Walker;\r
05fd2a92 61\r
1436aea4 62 if ((DevicePath == NULL) || (InstanceSize == NULL) || (EntireDevicePathEnd == NULL)) {\r
05fd2a92
HW
63 return EFI_INVALID_PARAMETER;\r
64 }\r
65\r
66 //\r
67 // Find the end of the device path instance\r
68 //\r
69 Walker = DevicePath;\r
70 while (Walker->Type != END_DEVICE_PATH_TYPE) {\r
71 Walker = NextDevicePathNode (Walker);\r
72 }\r
73\r
74 //\r
75 // Check if 'Walker' points to the end of an entire device path\r
76 //\r
77 if (Walker->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) {\r
78 *EntireDevicePathEnd = TRUE;\r
79 } else if (Walker->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE) {\r
80 *EntireDevicePathEnd = FALSE;\r
81 } else {\r
82 return EFI_INVALID_PARAMETER;\r
83 }\r
84\r
85 //\r
86 // Compute the size of the device path instance\r
87 //\r
1436aea4 88 *InstanceSize = ((UINTN)Walker - (UINTN)(DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
05fd2a92
HW
89\r
90 return EFI_SUCCESS;\r
91}\r
92\r
2e15b750
HW
93/**\r
94 Check the validity of the device path of a NVM Express host controller.\r
95\r
96 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL\r
97 structure.\r
98 @param[in] DevicePathLength The length of the device path.\r
99\r
100 @retval EFI_SUCCESS The device path is valid.\r
101 @retval EFI_INVALID_PARAMETER The device path is invalid.\r
102\r
103**/\r
104EFI_STATUS\r
105NvmeIsHcDevicePathValid (\r
1436aea4
MK
106 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
107 IN UINTN DevicePathLength\r
2e15b750
HW
108 )\r
109{\r
1436aea4
MK
110 EFI_DEVICE_PATH_PROTOCOL *Start;\r
111 UINTN Size;\r
2e15b750
HW
112\r
113 if (DevicePath == NULL) {\r
114 return EFI_INVALID_PARAMETER;\r
115 }\r
116\r
117 //\r
118 // Validate the DevicePathLength is big enough to touch the first node.\r
119 //\r
120 if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
121 return EFI_INVALID_PARAMETER;\r
122 }\r
123\r
124 Start = DevicePath;\r
125 while (!(DevicePath->Type == END_DEVICE_PATH_TYPE &&\r
1436aea4
MK
126 DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE))\r
127 {\r
2e15b750
HW
128 DevicePath = NextDevicePathNode (DevicePath);\r
129\r
130 //\r
131 // Prevent overflow and invalid zero in the 'Length' field of a device path\r
132 // node.\r
133 //\r
1436aea4 134 if ((UINTN)DevicePath <= (UINTN)Start) {\r
2e15b750
HW
135 return EFI_INVALID_PARAMETER;\r
136 }\r
137\r
138 //\r
139 // Prevent touching memory beyond given DevicePathLength.\r
140 //\r
1436aea4
MK
141 if ((UINTN)DevicePath - (UINTN)Start >\r
142 DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL))\r
143 {\r
2e15b750
HW
144 return EFI_INVALID_PARAMETER;\r
145 }\r
146 }\r
147\r
148 //\r
149 // Check if the device path and its size match exactly with each other.\r
150 //\r
1436aea4 151 Size = ((UINTN)DevicePath - (UINTN)Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
2e15b750
HW
152 if (Size != DevicePathLength) {\r
153 return EFI_INVALID_PARAMETER;\r
154 }\r
155\r
156 return EFI_SUCCESS;\r
157}\r
158\r
159/**\r
160 Build the device path for an Nvm Express device with given namespace identifier\r
161 and namespace extended unique identifier.\r
162\r
163 @param[in] Private A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA\r
164 data structure.\r
165 @param[in] NamespaceId The given namespace identifier.\r
166 @param[in] NamespaceUuid The given namespace extended unique identifier.\r
167 @param[out] DevicePathLength The length of the device path in bytes specified\r
168 by DevicePath.\r
169 @param[out] DevicePath The device path of Nvm Express device.\r
170\r
171 @retval EFI_SUCCESS The operation succeeds.\r
172 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
173 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.\r
174\r
175**/\r
176EFI_STATUS\r
177NvmeBuildDevicePath (\r
1436aea4
MK
178 IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private,\r
179 IN UINT32 NamespaceId,\r
180 IN UINT64 NamespaceUuid,\r
181 OUT UINTN *DevicePathLength,\r
182 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
2e15b750
HW
183 )\r
184{\r
1436aea4
MK
185 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;\r
186 NVME_NAMESPACE_DEVICE_PATH *NvmeDeviceNode;\r
2e15b750 187\r
1436aea4 188 if ((DevicePathLength == NULL) || (DevicePath == NULL)) {\r
2e15b750
HW
189 return EFI_INVALID_PARAMETER;\r
190 }\r
191\r
192 *DevicePathLength = Private->DevicePathLength + sizeof (NVME_NAMESPACE_DEVICE_PATH);\r
193 *DevicePath = AllocatePool (*DevicePathLength);\r
194 if (*DevicePath == NULL) {\r
195 *DevicePathLength = 0;\r
196 return EFI_OUT_OF_RESOURCES;\r
197 }\r
198\r
199 //\r
200 // Construct the host controller part device nodes\r
201 //\r
202 DevicePathWalker = *DevicePath;\r
203 CopyMem (\r
204 DevicePathWalker,\r
205 Private->DevicePath,\r
206 Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)\r
207 );\r
208\r
209 //\r
210 // Construct the Nvm Express device node\r
211 //\r
1436aea4
MK
212 DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePathWalker +\r
213 (Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)));\r
2e15b750
HW
214 CopyMem (\r
215 DevicePathWalker,\r
216 &mNvmeDevicePathNodeTemplate,\r
217 sizeof (mNvmeDevicePathNodeTemplate)\r
218 );\r
219 NvmeDeviceNode = (NVME_NAMESPACE_DEVICE_PATH *)DevicePathWalker;\r
220 NvmeDeviceNode->NamespaceId = NamespaceId;\r
221 NvmeDeviceNode->NamespaceUuid = NamespaceUuid;\r
222\r
223 //\r
224 // Construct the end device node\r
225 //\r
1436aea4
MK
226 DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePathWalker +\r
227 sizeof (NVME_NAMESPACE_DEVICE_PATH));\r
2e15b750
HW
228 CopyMem (\r
229 DevicePathWalker,\r
230 &mNvmeEndDevicePathNodeTemplate,\r
231 sizeof (mNvmeEndDevicePathNodeTemplate)\r
232 );\r
233\r
234 return EFI_SUCCESS;\r
235}\r