]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c
MdePkg UefiPciSegmentLibPciRootBridgeIo: Remove redundant dependency
[mirror_edk2.git] / MdePkg / Library / UefiDevicePathLib / UefiDevicePathLibOptionalDevicePathProtocol.c
1 /** @file
2 Device Path services. The thing to remember is device paths are built out of
3 nodes. The device path is terminated by an end node that is length
4 sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
5 all over this file.
6
7 The only place where multi-instance device paths are supported is in
8 environment varibles. Multi-instance device paths should never be placed
9 on a Handle.
10
11 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
12 This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution. The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php.
16
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19
20 **/
21
22
23 #include "UefiDevicePathLib.h"
24
25 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathLibDevicePathUtilities = NULL;
26 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevicePathLibDevicePathToText = NULL;
27 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mDevicePathLibDevicePathFromText = NULL;
28
29 /**
30 The constructor function caches the pointer to DevicePathUtilites protocol,
31 DevicePathToText protocol and DevicePathFromText protocol.
32
33 The constructor function locates these three protocols from protocol database.
34 It will caches the pointer to local protocol instance if that operation fails
35 and it will always return EFI_SUCCESS.
36
37 @param ImageHandle The firmware allocated handle for the EFI image.
38 @param SystemTable A pointer to the EFI System Table.
39
40 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
41
42 **/
43 EFI_STATUS
44 EFIAPI
45 UefiDevicePathLibOptionalDevicePathProtocolConstructor (
46 IN EFI_HANDLE ImageHandle,
47 IN EFI_SYSTEM_TABLE *SystemTable
48 )
49 {
50 EFI_STATUS Status;
51
52 Status = gBS->LocateProtocol (
53 &gEfiDevicePathUtilitiesProtocolGuid,
54 NULL,
55 (VOID**) &mDevicePathLibDevicePathUtilities
56 );
57 ASSERT_EFI_ERROR (Status);
58 ASSERT (mDevicePathLibDevicePathUtilities != NULL);
59 return Status;
60 }
61
62 /**
63 Returns the size of a device path in bytes.
64
65 This function returns the size, in bytes, of the device path data structure
66 specified by DevicePath including the end of device path node.
67 If DevicePath is NULL or invalid, then 0 is returned.
68
69 @param DevicePath A pointer to a device path data structure.
70
71 @retval 0 If DevicePath is NULL or invalid.
72 @retval Others The size of a device path in bytes.
73
74 **/
75 UINTN
76 EFIAPI
77 GetDevicePathSize (
78 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
79 )
80 {
81 if (mDevicePathLibDevicePathUtilities != NULL) {
82 return mDevicePathLibDevicePathUtilities->GetDevicePathSize (DevicePath);
83 } else {
84 return UefiDevicePathLibGetDevicePathSize (DevicePath);
85 }
86 }
87
88 /**
89 Creates a new copy of an existing device path.
90
91 This function allocates space for a new copy of the device path specified by DevicePath.
92 If DevicePath is NULL, then NULL is returned. If the memory is successfully
93 allocated, then the contents of DevicePath are copied to the newly allocated
94 buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned.
95 The memory for the new device path is allocated from EFI boot services memory.
96 It is the responsibility of the caller to free the memory allocated.
97
98 @param DevicePath A pointer to a device path data structure.
99
100 @retval NULL DevicePath is NULL or invalid.
101 @retval Others A pointer to the duplicated device path.
102
103 **/
104 EFI_DEVICE_PATH_PROTOCOL *
105 EFIAPI
106 DuplicateDevicePath (
107 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
108 )
109 {
110 if (mDevicePathLibDevicePathUtilities != NULL) {
111 return mDevicePathLibDevicePathUtilities->DuplicateDevicePath (DevicePath);
112 } else {
113 return UefiDevicePathLibDuplicateDevicePath (DevicePath);
114 }
115 }
116
117 /**
118 Creates a new device path by appending a second device path to a first device path.
119
120 This function creates a new device path by appending a copy of SecondDevicePath
121 to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path
122 device node from SecondDevicePath is retained. The newly created device path is
123 returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of
124 SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored,
125 and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and
126 SecondDevicePath are NULL, then a copy of an end-of-device-path is returned.
127
128 If there is not enough memory for the newly allocated buffer, then NULL is returned.
129 The memory for the new device path is allocated from EFI boot services memory.
130 It is the responsibility of the caller to free the memory allocated.
131
132 @param FirstDevicePath A pointer to a device path data structure.
133 @param SecondDevicePath A pointer to a device path data structure.
134
135 @retval NULL If there is not enough memory for the newly allocated buffer.
136 @retval NULL If FirstDevicePath or SecondDevicePath is invalid.
137 @retval Others A pointer to the new device path if success.
138 Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL.
139
140 **/
141 EFI_DEVICE_PATH_PROTOCOL *
142 EFIAPI
143 AppendDevicePath (
144 IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL
145 IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL
146 )
147 {
148 if (mDevicePathLibDevicePathUtilities != NULL) {
149 return mDevicePathLibDevicePathUtilities->AppendDevicePath (FirstDevicePath, SecondDevicePath);
150 } else {
151 return UefiDevicePathLibAppendDevicePath (FirstDevicePath, SecondDevicePath);
152 }
153 }
154
155 /**
156 Creates a new path by appending the device node to the device path.
157
158 This function creates a new device path by appending a copy of the device node
159 specified by DevicePathNode to a copy of the device path specified by DevicePath
160 in an allocated buffer. The end-of-device-path device node is moved after the
161 end of the appended device node.
162 If DevicePathNode is NULL then a copy of DevicePath is returned.
163 If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device
164 path device node is returned.
165 If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path
166 device node is returned.
167 If there is not enough memory to allocate space for the new device path, then
168 NULL is returned.
169 The memory is allocated from EFI boot services memory. It is the responsibility
170 of the caller to free the memory allocated.
171
172 @param DevicePath A pointer to a device path data structure.
173 @param DevicePathNode A pointer to a single device path node.
174
175 @retval NULL If there is not enough memory for the new device path.
176 @retval Others A pointer to the new device path if success.
177 A copy of DevicePathNode followed by an end-of-device-path node
178 if both FirstDevicePath and SecondDevicePath are NULL.
179 A copy of an end-of-device-path node if both FirstDevicePath
180 and SecondDevicePath are NULL.
181
182 **/
183 EFI_DEVICE_PATH_PROTOCOL *
184 EFIAPI
185 AppendDevicePathNode (
186 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL
187 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL
188 )
189 {
190 if (mDevicePathLibDevicePathUtilities != NULL) {
191 return mDevicePathLibDevicePathUtilities->AppendDeviceNode (DevicePath, DevicePathNode);
192 } else {
193 return UefiDevicePathLibAppendDevicePathNode (DevicePath, DevicePathNode);
194 }
195 }
196
197 /**
198 Creates a new device path by appending the specified device path instance to the specified device
199 path.
200
201 This function creates a new device path by appending a copy of the device path
202 instance specified by DevicePathInstance to a copy of the device path specified
203 by DevicePath in a allocated buffer.
204 The end-of-device-path device node is moved after the end of the appended device
205 path instance and a new end-of-device-path-instance node is inserted between.
206 If DevicePath is NULL, then a copy if DevicePathInstance is returned.
207 If DevicePathInstance is NULL, then NULL is returned.
208 If DevicePath or DevicePathInstance is invalid, then NULL is returned.
209 If there is not enough memory to allocate space for the new device path, then
210 NULL is returned.
211 The memory is allocated from EFI boot services memory. It is the responsibility
212 of the caller to free the memory allocated.
213
214 @param DevicePath A pointer to a device path data structure.
215 @param DevicePathInstance A pointer to a device path instance.
216
217 @return A pointer to the new device path.
218
219 **/
220 EFI_DEVICE_PATH_PROTOCOL *
221 EFIAPI
222 AppendDevicePathInstance (
223 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL
224 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL
225 )
226 {
227 if (mDevicePathLibDevicePathUtilities != NULL) {
228 return mDevicePathLibDevicePathUtilities->AppendDevicePathInstance (DevicePath, DevicePathInstance);
229 } else {
230 return UefiDevicePathLibAppendDevicePathInstance (DevicePath, DevicePathInstance);
231 }
232 }
233
234 /**
235 Creates a copy of the current device path instance and returns a pointer to the next device path
236 instance.
237
238 This function creates a copy of the current device path instance. It also updates
239 DevicePath to point to the next device path instance in the device path (or NULL
240 if no more) and updates Size to hold the size of the device path instance copy.
241 If DevicePath is NULL, then NULL is returned.
242 If DevicePath points to a invalid device path, then NULL is returned.
243 If there is not enough memory to allocate space for the new device path, then
244 NULL is returned.
245 The memory is allocated from EFI boot services memory. It is the responsibility
246 of the caller to free the memory allocated.
247 If Size is NULL, then ASSERT().
248
249 @param DevicePath On input, this holds the pointer to the current
250 device path instance. On output, this holds
251 the pointer to the next device path instance
252 or NULL if there are no more device path
253 instances in the device path pointer to a
254 device path data structure.
255 @param Size On output, this holds the size of the device
256 path instance, in bytes or zero, if DevicePath
257 is NULL.
258
259 @return A pointer to the current device path instance.
260
261 **/
262 EFI_DEVICE_PATH_PROTOCOL *
263 EFIAPI
264 GetNextDevicePathInstance (
265 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
266 OUT UINTN *Size
267 )
268 {
269 if (mDevicePathLibDevicePathUtilities != NULL) {
270 return mDevicePathLibDevicePathUtilities->GetNextDevicePathInstance (DevicePath, Size);
271 } else {
272 return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, Size);
273 }
274 }
275
276 /**
277 Creates a device node.
278
279 This function creates a new device node in a newly allocated buffer of size
280 NodeLength and initializes the device path node header with NodeType and NodeSubType.
281 The new device path node is returned.
282 If NodeLength is smaller than a device path header, then NULL is returned.
283 If there is not enough memory to allocate space for the new device path, then
284 NULL is returned.
285 The memory is allocated from EFI boot services memory. It is the responsibility
286 of the caller to free the memory allocated.
287
288 @param NodeType The device node type for the new device node.
289 @param NodeSubType The device node sub-type for the new device node.
290 @param NodeLength The length of the new device node.
291
292 @return The new device path.
293
294 **/
295 EFI_DEVICE_PATH_PROTOCOL *
296 EFIAPI
297 CreateDeviceNode (
298 IN UINT8 NodeType,
299 IN UINT8 NodeSubType,
300 IN UINT16 NodeLength
301 )
302 {
303 if (mDevicePathLibDevicePathUtilities != NULL) {
304 return mDevicePathLibDevicePathUtilities->CreateDeviceNode (NodeType, NodeSubType, NodeLength);
305 } else {
306 return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType, NodeLength);
307 }
308 }
309
310 /**
311 Determines if a device path is single or multi-instance.
312
313 This function returns TRUE if the device path specified by DevicePath is
314 multi-instance.
315 Otherwise, FALSE is returned.
316 If DevicePath is NULL or invalid, then FALSE is returned.
317
318 @param DevicePath A pointer to a device path data structure.
319
320 @retval TRUE DevicePath is multi-instance.
321 @retval FALSE DevicePath is not multi-instance, or DevicePath
322 is NULL or invalid.
323
324 **/
325 BOOLEAN
326 EFIAPI
327 IsDevicePathMultiInstance (
328 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
329 )
330 {
331 if (mDevicePathLibDevicePathUtilities != NULL) {
332 return mDevicePathLibDevicePathUtilities->IsDevicePathMultiInstance (DevicePath);
333 } else {
334 return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath);
335 }
336 }
337
338 /**
339 Locate and return the protocol instance identified by the ProtocolGuid.
340
341 @param ProtocolGuid The GUID of the protocol.
342
343 @return A pointer to the protocol instance or NULL when absent.
344 **/
345 VOID *
346 UefiDevicePathLibLocateProtocol (
347 EFI_GUID *ProtocolGuid
348 )
349 {
350 EFI_STATUS Status;
351 VOID *Protocol;
352 Status = gBS->LocateProtocol (
353 ProtocolGuid,
354 NULL,
355 (VOID**) &Protocol
356 );
357 if (EFI_ERROR (Status)) {
358 return NULL;
359 } else {
360 return Protocol;
361 }
362 }
363
364 /**
365 Converts a device node to its string representation.
366
367 @param DeviceNode A Pointer to the device node to be converted.
368 @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
369 of the display node is used, where applicable. If DisplayOnly
370 is FALSE, then the longer text representation of the display node
371 is used.
372 @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
373 representation for a device node can be used, where applicable.
374
375 @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
376 is NULL or there was insufficient memory.
377
378 **/
379 CHAR16 *
380 EFIAPI
381 ConvertDeviceNodeToText (
382 IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
383 IN BOOLEAN DisplayOnly,
384 IN BOOLEAN AllowShortcuts
385 )
386 {
387 if (mDevicePathLibDevicePathToText == NULL) {
388 mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid);
389 }
390 if (mDevicePathLibDevicePathToText != NULL) {
391 return mDevicePathLibDevicePathToText->ConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts);
392 }
393
394 return UefiDevicePathLibConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts);
395 }
396
397 /**
398 Converts a device path to its text representation.
399
400 @param DevicePath A Pointer to the device to be converted.
401 @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
402 of the display node is used, where applicable. If DisplayOnly
403 is FALSE, then the longer text representation of the display node
404 is used.
405 @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
406 representation for a device node can be used, where applicable.
407
408 @return A pointer to the allocated text representation of the device path or
409 NULL if DeviceNode is NULL or there was insufficient memory.
410
411 **/
412 CHAR16 *
413 EFIAPI
414 ConvertDevicePathToText (
415 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
416 IN BOOLEAN DisplayOnly,
417 IN BOOLEAN AllowShortcuts
418 )
419 {
420 if (mDevicePathLibDevicePathToText == NULL) {
421 mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid);
422 }
423 if (mDevicePathLibDevicePathToText != NULL) {
424 return mDevicePathLibDevicePathToText->ConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts);
425 }
426
427 return UefiDevicePathLibConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts);
428 }
429
430 /**
431 Convert text to the binary representation of a device node.
432
433 @param TextDeviceNode TextDeviceNode points to the text representation of a device
434 node. Conversion starts with the first character and continues
435 until the first non-device node character.
436
437 @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
438 insufficient memory or text unsupported.
439
440 **/
441 EFI_DEVICE_PATH_PROTOCOL *
442 EFIAPI
443 ConvertTextToDeviceNode (
444 IN CONST CHAR16 *TextDeviceNode
445 )
446 {
447 if (mDevicePathLibDevicePathFromText == NULL) {
448 mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid);
449 }
450 if (mDevicePathLibDevicePathFromText != NULL) {
451 return mDevicePathLibDevicePathFromText->ConvertTextToDeviceNode (TextDeviceNode);
452 }
453
454 return UefiDevicePathLibConvertTextToDeviceNode (TextDeviceNode);
455 }
456
457 /**
458 Convert text to the binary representation of a device path.
459
460
461 @param TextDevicePath TextDevicePath points to the text representation of a device
462 path. Conversion starts with the first character and continues
463 until the first non-device node character.
464
465 @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
466 there was insufficient memory.
467
468 **/
469 EFI_DEVICE_PATH_PROTOCOL *
470 EFIAPI
471 ConvertTextToDevicePath (
472 IN CONST CHAR16 *TextDevicePath
473 )
474 {
475 if (mDevicePathLibDevicePathFromText == NULL) {
476 mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid);
477 }
478 if (mDevicePathLibDevicePathFromText != NULL) {
479 return mDevicePathLibDevicePathFromText->ConvertTextToDevicePath (TextDevicePath);
480 }
481
482 return UefiDevicePathLibConvertTextToDevicePath (TextDevicePath);
483 }
484