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