]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/DevicePath/DevicePathUtilities.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / C / DevicePath / DevicePathUtilities.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 variables. Multi-instance device paths should never be placed
9 on a Handle.
10
11 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
12 SPDX-License-Identifier: BSD-2-Clause-Patent
13
14 **/
15
16 #include "UefiDevicePathLib.h"
17 #include <Protocol/DevicePathUtilities.h>
18
19 //
20 // Template for an end-of-device path node.
21 //
22 CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = {
23 END_DEVICE_PATH_TYPE,
24 END_ENTIRE_DEVICE_PATH_SUBTYPE,
25 {
26 END_DEVICE_PATH_LENGTH,
27 0
28 }
29 };
30
31 /**
32 Determine whether a given device path is valid.
33
34 @param DevicePath A pointer to a device path data structure.
35 @param MaxSize The maximum size of the device path data structure.
36
37 @retval TRUE DevicePath is valid.
38 @retval FALSE DevicePath is NULL.
39 @retval FALSE Maxsize is less than sizeof(EFI_DEVICE_PATH_PROTOCOL).
40 @retval FALSE The length of any node in the DevicePath is less
41 than sizeof (EFI_DEVICE_PATH_PROTOCOL).
42 @retval FALSE If MaxSize is not zero, the size of the DevicePath
43 exceeds MaxSize.
44 @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node
45 count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
46 **/
47 BOOLEAN
48 IsDevicePathValid (
49 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
50 UINTN MaxSize
51 )
52 {
53 UINTN Count;
54 UINTN Size;
55 UINTN NodeLength;
56
57 //
58 // Validate the input whether exists and its size big enough to touch the first node
59 //
60 if (DevicePath == NULL || (MaxSize > 0 && MaxSize < END_DEVICE_PATH_LENGTH)) {
61 return FALSE;
62 }
63
64 if (MaxSize == 0) {
65 MaxSize = MAX_UINT32;
66 }
67
68 for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
69 NodeLength = DevicePathNodeLength (DevicePath);
70 if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
71 return FALSE;
72 }
73
74 if (NodeLength > MAX_UINT32 - Size) {
75 return FALSE;
76 }
77 Size += NodeLength;
78
79 //
80 // Validate next node before touch it.
81 //
82 if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) {
83 return FALSE;
84 }
85
86 Count++;
87 if (Count >= MAX_DEVICE_PATH_NODE_COUNT) {
88 return FALSE;
89 }
90
91 }
92
93 //
94 // Only return TRUE when the End Device Path node is valid.
95 //
96 return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
97 }
98
99
100 /**
101 Returns the Type field of a device path node.
102
103 Returns the Type field of the device path node specified by Node.
104
105 If Node is NULL, then ASSERT().
106
107 @param Node A pointer to a device path node data structure.
108
109 @return The Type field of the device path node specified by Node.
110
111 **/
112 UINT8
113 DevicePathType (
114 CONST VOID *Node
115 )
116 {
117 ASSERT (Node != NULL);
118 return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type;
119 }
120
121 /**
122 Returns the SubType field of a device path node.
123
124 Returns the SubType field of the device path node specified by Node.
125
126 If Node is NULL, then ASSERT().
127
128 @param Node A pointer to a device path node data structure.
129
130 @return The SubType field of the device path node specified by Node.
131
132 **/
133 UINT8
134 DevicePathSubType (
135 CONST VOID *Node
136 )
137 {
138 ASSERT (Node != NULL);
139 return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType;
140 }
141
142 /**
143 Returns the 16-bit Length field of a device path node.
144
145 Returns the 16-bit Length field of the device path node specified by Node.
146 Node is not required to be aligned on a 16-bit boundary, so it is recommended
147 that a function such as ReadUnaligned16() be used to extract the contents of
148 the Length field.
149
150 If Node is NULL, then ASSERT().
151
152 @param Node A pointer to a device path node data structure.
153
154 @return The 16-bit Length field of the device path node specified by Node.
155
156 **/
157 UINTN
158 DevicePathNodeLength (
159 CONST VOID *Node
160 )
161 {
162 ASSERT (Node != NULL);
163 return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);
164 }
165
166 /**
167 Returns a pointer to the next node in a device path.
168
169 Returns a pointer to the device path node that follows the device path node
170 specified by Node.
171
172 If Node is NULL, then ASSERT().
173
174 @param Node A pointer to a device path node data structure.
175
176 @return a pointer to the device path node that follows the device path node
177 specified by Node.
178
179 **/
180 EFI_DEVICE_PATH_PROTOCOL *
181 NextDevicePathNode (
182 CONST VOID *Node
183 )
184 {
185 ASSERT (Node != NULL);
186 return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node));
187 }
188
189 /**
190 Determines if a device path node is an end node of a device path.
191 This includes nodes that are the end of a device path instance and nodes that
192 are the end of an entire device path.
193
194 Determines if the device path node specified by Node is an end node of a device path.
195 This includes nodes that are the end of a device path instance and nodes that are the
196 end of an entire device path. If Node represents an end node of a device path,
197 then TRUE is returned. Otherwise, FALSE is returned.
198
199 If Node is NULL, then ASSERT().
200
201 @param Node A pointer to a device path node data structure.
202
203 @retval TRUE The device path node specified by Node is an end node of a
204 device path.
205 @retval FALSE The device path node specified by Node is not an end node of
206 a device path.
207
208 **/
209 BOOLEAN
210 IsDevicePathEndType (
211 CONST VOID *Node
212 )
213 {
214 ASSERT (Node != NULL);
215 return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE);
216 }
217
218 /**
219 Determines if a device path node is an end node of an entire device path.
220
221 Determines if a device path node specified by Node is an end node of an entire
222 device path. If Node represents the end of an entire device path, then TRUE is
223 returned. Otherwise, FALSE is returned.
224
225 If Node is NULL, then ASSERT().
226
227 @param Node A pointer to a device path node data structure.
228
229 @retval TRUE The device path node specified by Node is the end of an entire
230 device path.
231 @retval FALSE The device path node specified by Node is not the end of an
232 entire device path.
233
234 **/
235 BOOLEAN
236 IsDevicePathEnd (
237 CONST VOID *Node
238 )
239 {
240 ASSERT (Node != NULL);
241 return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
242 }
243
244 /**
245 Determines if a device path node is an end node of a device path instance.
246
247 Determines if a device path node specified by Node is an end node of a device
248 path instance. If Node represents the end of a device path instance, then TRUE
249 is returned. Otherwise, FALSE is returned.
250
251 If Node is NULL, then ASSERT().
252
253 @param Node A pointer to a device path node data structure.
254
255 @retval TRUE The device path node specified by Node is the end of a device
256 path instance.
257 @retval FALSE The device path node specified by Node is not the end of a
258 device path instance.
259
260 **/
261 BOOLEAN
262 IsDevicePathEndInstance (
263 CONST VOID *Node
264 )
265 {
266 ASSERT (Node != NULL);
267 return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
268 }
269
270 /**
271 Sets the length, in bytes, of a device path node.
272
273 Sets the length of the device path node specified by Node to the value specified
274 by NodeLength. NodeLength is returned. Node is not required to be aligned on
275 a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16()
276 be used to set the contents of the Length field.
277
278 If Node is NULL, then ASSERT().
279 If NodeLength >= SIZE_64KB, then ASSERT().
280 If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT().
281
282 @param Node A pointer to a device path node data structure.
283 @param Length The length, in bytes, of the device path node.
284
285 @return Length
286
287 **/
288 UINT16
289 SetDevicePathNodeLength (
290 VOID *Node,
291 UINTN Length
292 )
293 {
294 ASSERT (Node != NULL);
295 ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB));
296 return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));
297 }
298
299 /**
300 Fills in all the fields of a device path node that is the end of an entire device path.
301
302 Fills in all the fields of a device path node specified by Node so Node represents
303 the end of an entire device path. The Type field of Node is set to
304 END_DEVICE_PATH_TYPE, the SubType field of Node is set to
305 END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to
306 END_DEVICE_PATH_LENGTH. Node is not required to be aligned on a 16-bit boundary,
307 so it is recommended that a function such as WriteUnaligned16() be used to set
308 the contents of the Length field.
309
310 If Node is NULL, then ASSERT().
311
312 @param Node A pointer to a device path node data structure.
313
314 **/
315 VOID
316 SetDevicePathEndNode (
317 VOID *Node
318 )
319 {
320 ASSERT (Node != NULL);
321 memcpy (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));
322 }
323
324 /**
325 Returns the size of a device path in bytes.
326
327 This function returns the size, in bytes, of the device path data structure
328 specified by DevicePath including the end of device path node.
329 If DevicePath is NULL or invalid, then 0 is returned.
330
331 @param DevicePath A pointer to a device path data structure.
332
333 @retval 0 If DevicePath is NULL or invalid.
334 @retval Others The size of a device path in bytes.
335
336 **/
337 UINTN
338 UefiDevicePathLibGetDevicePathSize (
339 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
340 )
341 {
342 CONST EFI_DEVICE_PATH_PROTOCOL *Start;
343
344 if (DevicePath == NULL) {
345 return 0;
346 }
347
348 if (!IsDevicePathValid (DevicePath, 0)) {
349 return 0;
350 }
351
352 //
353 // Search for the end of the device path structure
354 //
355 Start = DevicePath;
356 while (!IsDevicePathEnd (DevicePath)) {
357 DevicePath = NextDevicePathNode (DevicePath);
358 }
359
360 //
361 // Compute the size and add back in the size of the end device path structure
362 //
363 return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath);
364 }
365
366 /**
367 Creates a new copy of an existing device path.
368
369 This function allocates space for a new copy of the device path specified by DevicePath.
370 If DevicePath is NULL, then NULL is returned. If the memory is successfully
371 allocated, then the contents of DevicePath are copied to the newly allocated
372 buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned.
373 The memory for the new device path is allocated from EFI boot services memory.
374 It is the responsibility of the caller to free the memory allocated.
375
376 @param DevicePath A pointer to a device path data structure.
377
378 @retval NULL DevicePath is NULL or invalid.
379 @retval Others A pointer to the duplicated device path.
380
381 **/
382 EFI_DEVICE_PATH_PROTOCOL *
383 UefiDevicePathLibDuplicateDevicePath (
384 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
385 )
386 {
387 UINTN Size;
388
389 //
390 // Compute the size
391 //
392 Size = GetDevicePathSize (DevicePath);
393 if (Size == 0) {
394 return NULL;
395 }
396
397 //
398 // Allocate space for duplicate device path
399 //
400
401 return AllocateCopyPool (Size, DevicePath);
402 }
403
404 /**
405 Creates a new device path by appending a second device path to a first device path.
406
407 This function creates a new device path by appending a copy of SecondDevicePath
408 to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path
409 device node from SecondDevicePath is retained. The newly created device path is
410 returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of
411 SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored,
412 and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and
413 SecondDevicePath are NULL, then a copy of an end-of-device-path is returned.
414
415 If there is not enough memory for the newly allocated buffer, then NULL is returned.
416 The memory for the new device path is allocated from EFI boot services memory.
417 It is the responsibility of the caller to free the memory allocated.
418
419 @param FirstDevicePath A pointer to a device path data structure.
420 @param SecondDevicePath A pointer to a device path data structure.
421
422 @retval NULL If there is not enough memory for the newly allocated buffer.
423 @retval NULL If FirstDevicePath or SecondDevicePath is invalid.
424 @retval Others A pointer to the new device path if success.
425 Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL.
426
427 **/
428 EFI_DEVICE_PATH_PROTOCOL *
429 UefiDevicePathLibAppendDevicePath (
430 CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath,
431 CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath
432 )
433 {
434 UINTN Size;
435 UINTN Size1;
436 UINTN Size2;
437 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
438 EFI_DEVICE_PATH_PROTOCOL *DevicePath2;
439
440 //
441 // If there's only 1 path, just duplicate it.
442 //
443 if (FirstDevicePath == NULL) {
444 return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath);
445 }
446
447 if (SecondDevicePath == NULL) {
448 return DuplicateDevicePath (FirstDevicePath);
449 }
450
451 if (!IsDevicePathValid (FirstDevicePath, 0) || !IsDevicePathValid (SecondDevicePath, 0)) {
452 return NULL;
453 }
454
455 //
456 // Allocate space for the combined device path. It only has one end node of
457 // length EFI_DEVICE_PATH_PROTOCOL.
458 //
459 Size1 = GetDevicePathSize (FirstDevicePath);
460 Size2 = GetDevicePathSize (SecondDevicePath);
461 Size = Size1 + Size2 - END_DEVICE_PATH_LENGTH;
462
463 NewDevicePath = AllocatePool (Size);
464
465 if (NewDevicePath != NULL) {
466 NewDevicePath = memcpy (NewDevicePath, FirstDevicePath, Size1);
467 //
468 // Over write FirstDevicePath EndNode and do the copy
469 //
470 DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath +
471 (Size1 - END_DEVICE_PATH_LENGTH));
472 memcpy (DevicePath2, SecondDevicePath, Size2);
473 }
474
475 return NewDevicePath;
476 }
477
478 /**
479 Creates a new path by appending the device node to the device path.
480
481 This function creates a new device path by appending a copy of the device node
482 specified by DevicePathNode to a copy of the device path specified by DevicePath
483 in an allocated buffer. The end-of-device-path device node is moved after the
484 end of the appended device node.
485 If DevicePathNode is NULL then a copy of DevicePath is returned.
486 If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device
487 path device node is returned.
488 If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path
489 device node is returned.
490 If there is not enough memory to allocate space for the new device path, then
491 NULL is returned.
492 The memory is allocated from EFI boot services memory. It is the responsibility
493 of the caller to free the memory allocated.
494
495 @param DevicePath A pointer to a device path data structure.
496 @param DevicePathNode A pointer to a single device path node.
497
498 @retval NULL If there is not enough memory for the new device path.
499 @retval Others A pointer to the new device path if success.
500 A copy of DevicePathNode followed by an end-of-device-path node
501 if both FirstDevicePath and SecondDevicePath are NULL.
502 A copy of an end-of-device-path node if both FirstDevicePath
503 and SecondDevicePath are NULL.
504
505 **/
506 EFI_DEVICE_PATH_PROTOCOL *
507 UefiDevicePathLibAppendDevicePathNode (
508 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
509 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
510 )
511 {
512 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
513 EFI_DEVICE_PATH_PROTOCOL *NextNode;
514 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
515 UINTN NodeLength;
516
517 if (DevicePathNode == NULL) {
518 return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath);
519 }
520 //
521 // Build a Node that has a terminator on it
522 //
523 NodeLength = DevicePathNodeLength (DevicePathNode);
524
525 TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH);
526 if (TempDevicePath == NULL) {
527 return NULL;
528 }
529 TempDevicePath = memcpy (TempDevicePath, DevicePathNode, NodeLength);
530 //
531 // Add and end device path node to convert Node to device path
532 //
533 NextNode = NextDevicePathNode (TempDevicePath);
534 SetDevicePathEndNode (NextNode);
535 //
536 // Append device paths
537 //
538 NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath);
539
540 free (TempDevicePath);
541
542 return NewDevicePath;
543 }
544
545 /**
546 Creates a new device path by appending the specified device path instance to the specified device
547 path.
548
549 This function creates a new device path by appending a copy of the device path
550 instance specified by DevicePathInstance to a copy of the device path specified
551 by DevicePath in a allocated buffer.
552 The end-of-device-path device node is moved after the end of the appended device
553 path instance and a new end-of-device-path-instance node is inserted between.
554 If DevicePath is NULL, then a copy if DevicePathInstance is returned.
555 If DevicePathInstance is NULL, then NULL is returned.
556 If DevicePath or DevicePathInstance is invalid, then NULL is returned.
557 If there is not enough memory to allocate space for the new device path, then
558 NULL is returned.
559 The memory is allocated from EFI boot services memory. It is the responsibility
560 of the caller to free the memory allocated.
561
562 @param DevicePath A pointer to a device path data structure.
563 @param DevicePathInstance A pointer to a device path instance.
564
565 @return A pointer to the new device path.
566
567 **/
568 EFI_DEVICE_PATH_PROTOCOL *
569 UefiDevicePathLibAppendDevicePathInstance (
570 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
571 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
572 )
573 {
574 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
575 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
576 UINTN SrcSize;
577 UINTN InstanceSize;
578
579 if (DevicePath == NULL) {
580 return DuplicateDevicePath (DevicePathInstance);
581 }
582
583 if (DevicePathInstance == NULL) {
584 return NULL;
585 }
586
587 if (!IsDevicePathValid (DevicePath, 0) || !IsDevicePathValid (DevicePathInstance, 0)) {
588 return NULL;
589 }
590
591 SrcSize = GetDevicePathSize (DevicePath);
592 InstanceSize = GetDevicePathSize (DevicePathInstance);
593
594 NewDevicePath = AllocatePool (SrcSize + InstanceSize);
595 if (NewDevicePath != NULL) {
596
597 TempDevicePath = memcpy (NewDevicePath, DevicePath, SrcSize);;
598
599 while (!IsDevicePathEnd (TempDevicePath)) {
600 TempDevicePath = NextDevicePathNode (TempDevicePath);
601 }
602
603 TempDevicePath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
604 TempDevicePath = NextDevicePathNode (TempDevicePath);
605 memcpy (TempDevicePath, DevicePathInstance, InstanceSize);
606 }
607
608 return NewDevicePath;
609 }
610
611 /**
612 Creates a copy of the current device path instance and returns a pointer to the next device path
613 instance.
614
615 This function creates a copy of the current device path instance. It also updates
616 DevicePath to point to the next device path instance in the device path (or NULL
617 if no more) and updates Size to hold the size of the device path instance copy.
618 If DevicePath is NULL, then NULL is returned.
619 If DevicePath points to a invalid device path, then NULL is returned.
620 If there is not enough memory to allocate space for the new device path, then
621 NULL is returned.
622 The memory is allocated from EFI boot services memory. It is the responsibility
623 of the caller to free the memory allocated.
624 If Size is NULL, then ASSERT().
625
626 @param DevicePath On input, this holds the pointer to the current
627 device path instance. On output, this holds
628 the pointer to the next device path instance
629 or NULL if there are no more device path
630 instances in the device path pointer to a
631 device path data structure.
632 @param Size On output, this holds the size of the device
633 path instance, in bytes or zero, if DevicePath
634 is NULL.
635
636 @return A pointer to the current device path instance.
637
638 **/
639 EFI_DEVICE_PATH_PROTOCOL *
640 UefiDevicePathLibGetNextDevicePathInstance (
641 EFI_DEVICE_PATH_PROTOCOL **DevicePath,
642 UINTN *Size
643 )
644 {
645 EFI_DEVICE_PATH_PROTOCOL *DevPath;
646 EFI_DEVICE_PATH_PROTOCOL *ReturnValue;
647 UINT8 Temp;
648
649 ASSERT (Size != NULL);
650
651 if (DevicePath == NULL || *DevicePath == NULL) {
652 *Size = 0;
653 return NULL;
654 }
655
656 if (!IsDevicePathValid (*DevicePath, 0)) {
657 return NULL;
658 }
659
660 //
661 // Find the end of the device path instance
662 //
663 DevPath = *DevicePath;
664 while (!IsDevicePathEndType (DevPath)) {
665 DevPath = NextDevicePathNode (DevPath);
666 }
667
668 //
669 // Compute the size of the device path instance
670 //
671 *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
672
673 //
674 // Make a copy and return the device path instance
675 //
676 Temp = DevPath->SubType;
677 DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
678 ReturnValue = DuplicateDevicePath (*DevicePath);
679 DevPath->SubType = Temp;
680
681 //
682 // If DevPath is the end of an entire device path, then another instance
683 // does not follow, so *DevicePath is set to NULL.
684 //
685 if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
686 *DevicePath = NULL;
687 } else {
688 *DevicePath = NextDevicePathNode (DevPath);
689 }
690
691 return ReturnValue;
692 }
693
694 /**
695 Creates a device node.
696
697 This function creates a new device node in a newly allocated buffer of size
698 NodeLength and initializes the device path node header with NodeType and NodeSubType.
699 The new device path node is returned.
700 If NodeLength is smaller than a device path header, then NULL is returned.
701 If there is not enough memory to allocate space for the new device path, then
702 NULL is returned.
703 The memory is allocated from EFI boot services memory. It is the responsibility
704 of the caller to free the memory allocated.
705
706 @param NodeType The device node type for the new device node.
707 @param NodeSubType The device node sub-type for the new device node.
708 @param NodeLength The length of the new device node.
709
710 @return The new device path.
711
712 **/
713 EFI_DEVICE_PATH_PROTOCOL *
714 UefiDevicePathLibCreateDeviceNode (
715 UINT8 NodeType,
716 UINT8 NodeSubType,
717 UINT16 NodeLength
718 )
719 {
720 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
721
722 if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
723 //
724 // NodeLength is less than the size of the header.
725 //
726 return NULL;
727 }
728
729 DevicePath = AllocateZeroPool (NodeLength);
730 if (DevicePath != NULL) {
731 DevicePath->Type = NodeType;
732 DevicePath->SubType = NodeSubType;
733 SetDevicePathNodeLength (DevicePath, NodeLength);
734 }
735
736 return DevicePath;
737 }
738
739 /**
740 Determines if a device path is single or multi-instance.
741
742 This function returns TRUE if the device path specified by DevicePath is
743 multi-instance.
744 Otherwise, FALSE is returned.
745 If DevicePath is NULL or invalid, then FALSE is returned.
746
747 @param DevicePath A pointer to a device path data structure.
748
749 @retval TRUE DevicePath is multi-instance.
750 @retval FALSE DevicePath is not multi-instance, or DevicePath
751 is NULL or invalid.
752
753 **/
754 BOOLEAN
755 UefiDevicePathLibIsDevicePathMultiInstance (
756 CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
757 )
758 {
759 CONST EFI_DEVICE_PATH_PROTOCOL *Node;
760
761 if (DevicePath == NULL) {
762 return FALSE;
763 }
764
765 if (!IsDevicePathValid (DevicePath, 0)) {
766 return FALSE;
767 }
768
769 Node = DevicePath;
770 while (!IsDevicePathEnd (Node)) {
771 if (IsDevicePathEndInstance (Node)) {
772 return TRUE;
773 }
774
775 Node = NextDevicePathNode (Node);
776 }
777
778 return FALSE;
779 }
780
781
782 /**
783 Retrieves the device path protocol from a handle.
784
785 This function returns the device path protocol from the handle specified by Handle.
786 If Handle is NULL or Handle does not contain a device path protocol, then NULL
787 is returned.
788
789 @param Handle The handle from which to retrieve the device
790 path protocol.
791
792 @return The device path protocol from the handle specified by Handle.
793
794 **/
795 /*
796 EFI_DEVICE_PATH_PROTOCOL *
797 DevicePathFromHandle (
798 EFI_HANDLE Handle
799 )
800 {
801 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
802 EFI_STATUS Status;
803
804 Status = gBS->HandleProtocol (
805 Handle,
806 &gEfiDevicePathProtocolGuid,
807 (VOID *) &DevicePath
808 );
809 if (EFI_ERROR (Status)) {
810 DevicePath = NULL;
811 }
812 return DevicePath;
813 }
814 */
815 /**
816 Allocates a device path for a file and appends it to an existing device path.
817
818 If Device is a valid device handle that contains a device path protocol, then a device path for
819 the file specified by FileName is allocated and appended to the device path associated with the
820 handle Device. The allocated device path is returned. If Device is NULL or Device is a handle
821 that does not support the device path protocol, then a device path containing a single device
822 path node for the file specified by FileName is allocated and returned.
823 The memory for the new device path is allocated from EFI boot services memory. It is the responsibility
824 of the caller to free the memory allocated.
825
826 If FileName is NULL, then ASSERT().
827 If FileName is not aligned on a 16-bit boundary, then ASSERT().
828
829 @param Device A pointer to a device handle. This parameter
830 is optional and may be NULL.
831 @param FileName A pointer to a Null-terminated Unicode string.
832
833 @return The allocated device path.
834
835 **/
836 EFI_DEVICE_PATH_PROTOCOL *
837 FileDevicePath (
838 EFI_HANDLE Device, OPTIONAL
839 CONST CHAR16 *FileName
840 )
841 {
842 UINTN Size;
843 FILEPATH_DEVICE_PATH *FilePath;
844 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
845 EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;
846
847 DevicePath = NULL;
848
849 Size = StrSize (FileName);
850 FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
851 if (FileDevicePath != NULL) {
852 FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;
853 FilePath->Header.Type = MEDIA_DEVICE_PATH;
854 FilePath->Header.SubType = MEDIA_FILEPATH_DP;
855 memcpy (&FilePath->PathName, FileName, Size);
856 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
857 SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));
858
859 //if (Device != NULL) {
860 // DevicePath = DevicePathFromHandle (Device);
861 //}
862
863 DevicePath = AppendDevicePath (DevicePath, FileDevicePath);
864 free (FileDevicePath);
865 }
866
867 return DevicePath;
868 }