]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressPei / DevicePath.c
1 /** @file
2 The device path help function.
3
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "NvmExpressPei.h"
11
12 //
13 // Template for an Nvm Express Device Path node
14 //
15 NVME_NAMESPACE_DEVICE_PATH mNvmeDevicePathNodeTemplate = {
16 { // Header
17 MESSAGING_DEVICE_PATH,
18 MSG_NVME_NAMESPACE_DP,
19 {
20 (UINT8)(sizeof (NVME_NAMESPACE_DEVICE_PATH)),
21 (UINT8)((sizeof (NVME_NAMESPACE_DEVICE_PATH)) >> 8)
22 }
23 },
24 0x0, // NamespaceId
25 0x0 // NamespaceUuid
26 };
27
28 //
29 // Template for an End of entire Device Path node
30 //
31 EFI_DEVICE_PATH_PROTOCOL mNvmeEndDevicePathNodeTemplate = {
32 END_DEVICE_PATH_TYPE,
33 END_ENTIRE_DEVICE_PATH_SUBTYPE,
34 {
35 (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)),
36 (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8)
37 }
38 };
39
40 /**
41 Get the size of the current device path instance.
42
43 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
44 structure.
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.
48
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.
51
52 **/
53 EFI_STATUS
54 GetDevicePathInstanceSize (
55 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
56 OUT UINTN *InstanceSize,
57 OUT BOOLEAN *EntireDevicePathEnd
58 )
59 {
60 EFI_DEVICE_PATH_PROTOCOL *Walker;
61
62 if ((DevicePath == NULL) || (InstanceSize == NULL) || (EntireDevicePathEnd == NULL)) {
63 return EFI_INVALID_PARAMETER;
64 }
65
66 //
67 // Find the end of the device path instance
68 //
69 Walker = DevicePath;
70 while (Walker->Type != END_DEVICE_PATH_TYPE) {
71 Walker = NextDevicePathNode (Walker);
72 }
73
74 //
75 // Check if 'Walker' points to the end of an entire device path
76 //
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;
81 } else {
82 return EFI_INVALID_PARAMETER;
83 }
84
85 //
86 // Compute the size of the device path instance
87 //
88 *InstanceSize = ((UINTN)Walker - (UINTN)(DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
89
90 return EFI_SUCCESS;
91 }
92
93 /**
94 Check the validity of the device path of a NVM Express host controller.
95
96 @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
97 structure.
98 @param[in] DevicePathLength The length of the device path.
99
100 @retval EFI_SUCCESS The device path is valid.
101 @retval EFI_INVALID_PARAMETER The device path is invalid.
102
103 **/
104 EFI_STATUS
105 NvmeIsHcDevicePathValid (
106 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
107 IN UINTN DevicePathLength
108 )
109 {
110 EFI_DEVICE_PATH_PROTOCOL *Start;
111 UINTN Size;
112
113 if (DevicePath == NULL) {
114 return EFI_INVALID_PARAMETER;
115 }
116
117 //
118 // Validate the DevicePathLength is big enough to touch the first node.
119 //
120 if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
121 return EFI_INVALID_PARAMETER;
122 }
123
124 Start = DevicePath;
125 while (!(DevicePath->Type == END_DEVICE_PATH_TYPE &&
126 DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE))
127 {
128 DevicePath = NextDevicePathNode (DevicePath);
129
130 //
131 // Prevent overflow and invalid zero in the 'Length' field of a device path
132 // node.
133 //
134 if ((UINTN)DevicePath <= (UINTN)Start) {
135 return EFI_INVALID_PARAMETER;
136 }
137
138 //
139 // Prevent touching memory beyond given DevicePathLength.
140 //
141 if ((UINTN)DevicePath - (UINTN)Start >
142 DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL))
143 {
144 return EFI_INVALID_PARAMETER;
145 }
146 }
147
148 //
149 // Check if the device path and its size match exactly with each other.
150 //
151 Size = ((UINTN)DevicePath - (UINTN)Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
152 if (Size != DevicePathLength) {
153 return EFI_INVALID_PARAMETER;
154 }
155
156 return EFI_SUCCESS;
157 }
158
159 /**
160 Build the device path for an Nvm Express device with given namespace identifier
161 and namespace extended unique identifier.
162
163 @param[in] Private A pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA
164 data structure.
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
168 by DevicePath.
169 @param[out] DevicePath The device path of Nvm Express device.
170
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.
174
175 **/
176 EFI_STATUS
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
183 )
184 {
185 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
186 NVME_NAMESPACE_DEVICE_PATH *NvmeDeviceNode;
187
188 if ((DevicePathLength == NULL) || (DevicePath == NULL)) {
189 return EFI_INVALID_PARAMETER;
190 }
191
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;
197 }
198
199 //
200 // Construct the host controller part device nodes
201 //
202 DevicePathWalker = *DevicePath;
203 CopyMem (
204 DevicePathWalker,
205 Private->DevicePath,
206 Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)
207 );
208
209 //
210 // Construct the Nvm Express device node
211 //
212 DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePathWalker +
213 (Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
214 CopyMem (
215 DevicePathWalker,
216 &mNvmeDevicePathNodeTemplate,
217 sizeof (mNvmeDevicePathNodeTemplate)
218 );
219 NvmeDeviceNode = (NVME_NAMESPACE_DEVICE_PATH *)DevicePathWalker;
220 NvmeDeviceNode->NamespaceId = NamespaceId;
221 NvmeDeviceNode->NamespaceUuid = NamespaceUuid;
222
223 //
224 // Construct the end device node
225 //
226 DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePathWalker +
227 sizeof (NVME_NAMESPACE_DEVICE_PATH));
228 CopyMem (
229 DevicePathWalker,
230 &mNvmeEndDevicePathNodeTemplate,
231 sizeof (mNvmeEndDevicePathNodeTemplate)
232 );
233
234 return EFI_SUCCESS;
235 }