OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcDevicePathLib.c
Go to the documentation of this file.
1
15#include <Uefi.h>
16
17#include <Protocol/DevicePathToText.h>
18#include <Protocol/SimpleFileSystem.h>
19
20#include <Library/DebugLib.h>
21#include <Library/BaseLib.h>
22#include <Library/BaseMemoryLib.h>
23#include <Library/BaseOverflowLib.h>
24#include <Library/DevicePathLib.h>
25#include <Library/MemoryAllocationLib.h>
26#include <Library/OcStringLib.h>
28#include <Library/UefiBootServicesTableLib.h>
29
31
32EFI_DEVICE_PATH_PROTOCOL *
34 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
35 IN CHAR16 *FileName
36 )
37{
38 EFI_DEVICE_PATH_PROTOCOL *AppendedDevicePath;
39
40 FILEPATH_DEVICE_PATH *FilePathNode;
41 EFI_DEVICE_PATH_PROTOCOL *DevicePathEndNode;
42 UINTN FileNameSize;
43 UINTN FileDevicePathNodeSize;
44
45 AppendedDevicePath = NULL;
46
47 if ((DevicePath != NULL) && (FileName != NULL)) {
48 FileNameSize = StrSize (FileName);
49 FileDevicePathNodeSize = (FileNameSize + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
50 FilePathNode = AllocateZeroPool (FileDevicePathNodeSize);
51
52 if (FilePathNode != NULL) {
53 FilePathNode->Header.Type = MEDIA_DEVICE_PATH;
54 FilePathNode->Header.SubType = MEDIA_FILEPATH_DP;
55
56 SetDevicePathNodeLength (&FilePathNode->Header, FileNameSize + SIZE_OF_FILEPATH_DEVICE_PATH);
57
58 CopyMem (FilePathNode->PathName, FileName, FileNameSize);
59
60 DevicePathEndNode = NextDevicePathNode (&FilePathNode->Header);
61
62 SetDevicePathEndNode (DevicePathEndNode);
63
64 AppendedDevicePath = AppendDevicePath (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)FilePathNode);
65
66 FreePool (FilePathNode);
67 }
68 }
69
70 return AppendedDevicePath;
71}
72
73EFI_DEVICE_PATH_PROTOCOL *
75 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
76 )
77{
78 while (!IsDevicePathEnd (DevicePath)) {
79 DevicePath = NextDevicePathNode (DevicePath);
80 }
81
82 return DevicePath;
83}
84
85EFI_DEVICE_PATH_PROTOCOL *
87 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
88 IN UINT8 Type,
89 IN UINT8 SubType OPTIONAL
90 )
91{
92 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
93
94 DevicePathNode = NULL;
95
96 while (!IsDevicePathEnd (DevicePath)) {
97 if ( (DevicePathType (DevicePath) == Type)
98 && ((SubType == 0) || (DevicePathSubType (DevicePath) == SubType)))
99 {
100 DevicePathNode = DevicePath;
101
102 break;
103 }
104
105 DevicePath = NextDevicePathNode (DevicePath);
106 }
107
108 return DevicePathNode;
109}
110
111EFI_DEVICE_PATH_PROTOCOL *
113 IN EFI_HANDLE Handle,
114 IN EFI_DEVICE_PATH_PROTOCOL *RelativePath OPTIONAL
115 )
116{
117 EFI_DEVICE_PATH_PROTOCOL *HandlePath;
118 EFI_DEVICE_PATH_PROTOCOL *NewPath;
119
120 HandlePath = DevicePathFromHandle (Handle);
121 if (HandlePath == NULL) {
122 return NULL;
123 }
124
125 if (RelativePath == NULL) {
126 return DuplicateDevicePath (HandlePath);
127 }
128
129 NewPath = AppendDevicePath (HandlePath, RelativePath);
130
131 if (NewPath == NULL) {
132 return DuplicateDevicePath (HandlePath);
133 }
134
135 return NewPath;
136}
137
138EFI_DEVICE_PATH_PROTOCOL *
140 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
141 )
142{
143 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
144 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
145 FILEPATH_DEVICE_PATH *FilePath;
146 FILEPATH_DEVICE_PATH *NewFilePath;
147 UINTN Length;
148 UINTN Size;
149
150 DevicePathWalker = DevicePath;
151
152 while (!IsDevicePathEnd (DevicePathWalker)) {
153 if ( (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH)
154 && (DevicePathSubType (DevicePathWalker) == MEDIA_FILEPATH_DP)
155 && IsDevicePathEnd (NextDevicePathNode (DevicePathWalker)))
156 {
157 FilePath = (FILEPATH_DEVICE_PATH *)DevicePathWalker;
159 if (Length > 0) {
160 if (FilePath->PathName[Length - 1] == L'\\') {
161 //
162 // Already appended, good. It should never be true with Apple entries though.
163 //
164 return NULL;
165 }
166
167 if ((Length > 4) && ( (FilePath->PathName[Length - 4] != '.')
168 || ((FilePath->PathName[Length - 3] != 'e') && (FilePath->PathName[Length - 3] != 'E'))
169 || ((FilePath->PathName[Length - 2] != 'f') && (FilePath->PathName[Length - 2] != 'F'))
170 || ((FilePath->PathName[Length - 1] != 'i') && (FilePath->PathName[Length - 1] != 'I'))))
171 {
172 //
173 // Found! We should have gotten something like:
174 // PciRoot(0x0)/Pci(...)/Pci(...)/Sata(...)/HD(...)/\com.apple.recovery.boot
175 //
176
177 Size = GetDevicePathSize (DevicePath);
178 NewDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocatePool (Size + sizeof (CHAR16));
179 if (NewDevicePath == NULL) {
180 //
181 // Allocation failure, just ignore.
182 //
183 return NULL;
184 }
185
186 //
187 // Strip the string termination and DP end node, which will get re-set
188 //
189 CopyMem (NewDevicePath, DevicePath, Size - sizeof (CHAR16) - END_DEVICE_PATH_LENGTH);
190 NewFilePath = (FILEPATH_DEVICE_PATH *)((UINT8 *)DevicePathWalker - (UINT8 *)DevicePath + (UINT8 *)NewDevicePath);
191 Size = DevicePathNodeLength (DevicePathWalker) + sizeof (CHAR16);
192 SetDevicePathNodeLength (NewFilePath, Size);
193 NewFilePath->PathName[Length] = L'\\';
194 NewFilePath->PathName[Length+1] = L'\0';
195 SetDevicePathEndNode ((UINT8 *)NewFilePath + Size);
196 return NewDevicePath;
197 }
198 }
199 }
200
201 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
202 }
203
204 //
205 // Has .efi suffix or unsupported format.
206 //
207 return NULL;
208}
209
210VOID
212 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
213 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,
214 IN CONST APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext
215 )
216{
217 EFI_DEV_PATH_PTR Node;
218 UINT8 NodeType;
219 UINT8 NodeSubType;
220
221 //
222 // ATTENTION: This function must be carefully sync'd with changes to
223 // OcFixAppleBootDevicePathNode().
224 //
225
226 Node.DevPath = *DevicePathNode;
227
228 NodeType = DevicePathType (Node.DevPath);
229 NodeSubType = DevicePathSubType (Node.DevPath);
230
231 if (RestoreContext->OldPath != NULL) {
232 //
233 // Restore the previously stored Device Path prior to patching.
234 //
235 *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL *)(
236 (UINTN)RestoreContext->OldPath +
237 ((UINTN)*DevicePathNode - (UINTN)*DevicePath)
238 );
239 FreePool (*DevicePath);
240 *DevicePath = RestoreContext->OldPath;
241 return;
242 }
243
244 if (NodeType == MESSAGING_DEVICE_PATH) {
245 switch (NodeSubType) {
246 case MSG_SATA_DP:
247 Node.Sata->PortMultiplierPortNumber = RestoreContext->Types.Sata.PortMultiplierPortNumber;
248 break;
249
250 //
251 // The related patches in OcFixAppleBootDevicePathNode() are performed
252 // from MSG_SASEX_DP and MSG_NVME_NAMESPACE_DP but change the SubType.
253 // Please refer to the destination rather than the source SubType when
254 // matching the logic.
255 //
256 case MSG_NVME_NAMESPACE_DP:
257 case 0x22:
258 Node.NvmeNamespace->Header.SubType = RestoreContext->Types.SasExNvme.SubType;
259 break;
260
261 default:
262 break;
263 }
264 } else if (NodeType == ACPI_DEVICE_PATH) {
265 switch (NodeSubType) {
266 case ACPI_DP:
267 Node.Acpi->HID = RestoreContext->Types.Acpi.HID;
268 Node.Acpi->UID = RestoreContext->Types.Acpi.UID;
269 break;
270
271 case ACPI_EXTENDED_DP:
272 Node.ExtendedAcpi->HID = RestoreContext->Types.ExtendedAcpi.HID;
273 Node.ExtendedAcpi->CID = RestoreContext->Types.ExtendedAcpi.CID;
274 break;
275
276 default:
277 break;
278 }
279 }
280}
281
282VOID
284 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
285 IN OUT APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext
286 )
287{
288 //
289 // ATTENTION: This function must be carefully sync'd with changes to
290 // OcFixAppleBootDevicePathNode().
291 //
292
293 //
294 // Free the previously stored original Device Path for expansion patches.
295 //
296 if (RestoreContext->OldPath != NULL) {
297 FreePool (RestoreContext->OldPath);
298 }
299}
300
301/*
302 Constructs a new device path for an unrecognised device path with a hard drive
303 node.
304
305 @param[in,out] DevicePath A pointer to the device path to fix the node
306 of. It must be a pool memory buffer.
307 On success, may be updated with a reallocated
308 pool memory buffer.
309 @param[in,out] DevicePathNode A pointer to the device path node to fix. It
310 must be a node of *DevicePath.
311 On success, may be updated with the
312 corresponding node of *DevicePath.
313 @param[out] RestoreContext A pointer to a context that can be used to
314 restore DevicePathNode's original content in
315 the case of failure.
316 On success, data may need to be freed.
317
318 @retval -1 DevicePathNode could not be fixed.
319 @retval 1 DevicePathNode and is valid.
320
321*/
322STATIC
323INTN
325 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
326 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode
327 )
328{
329 EFI_DEVICE_PATH_PROTOCOL *HdNode;
330 UINTN PrefixSize;
331 EFI_DEVICE_PATH_PROTOCOL *ExpandedPath;
332 EFI_DEVICE_PATH_PROTOCOL *ExpandedNode;
333
334 DebugPrintDevicePath (DEBUG_VERBOSE, "Expanding new DP from", *DevicePath);
335 DebugPrintDevicePath (DEBUG_VERBOSE, "at node", *DevicePathNode);
336 //
337 // Find HD node to locate a valid Device Path of. We require the prefix
338 // till the offending node (e.g. a SATA node, which should be
339 // preceeded by a PCI chain) as well as the suffix match (though latter
340 // may be expanded). For example SATA should be an arbitrary VendorBlockIo
341 // node.
342 //
344 *DevicePath,
345 MEDIA_DEVICE_PATH,
346 MEDIA_HARDDRIVE_DP
347 );
348 if (HdNode == NULL) {
349 DEBUG ((DEBUG_VERBOSE, "Failed to find HD node\n"));
350 //
351 // Expansion makes little sense when we don't have a HD node.
352 //
353 return -1;
354 }
355
356 PrefixSize = (UINTN)*DevicePathNode - (UINTN)*DevicePath;
357 //
358 // Expand the Device Path based of the HD node and sanity-check it
359 // likely describes the intended path.
360 //
361 for (
362 ExpandedPath = OcGetNextLoadOptionDevicePath (HdNode, NULL);
363 ExpandedPath != NULL;
364 ExpandedPath = OcGetNextLoadOptionDevicePath (HdNode, ExpandedPath)
365 )
366 {
367 DebugPrintDevicePath (DEBUG_VERBOSE, "DP candidate", ExpandedPath);
368 //
369 // Skip this expansion if the prefix does not match.
370 //
371 if ( (GetDevicePathSize (ExpandedPath) < PrefixSize)
372 || (CompareMem (ExpandedPath, *DevicePath, PrefixSize) != 0))
373 {
374 DEBUG ((DEBUG_VERBOSE, "Prefix does not match\n"));
375 continue;
376 }
377
378 //
379 // The suffix is handled implicitly (by OcGetNextLoadOptionDevicePath).
380 // Keep in mind that with this logic our broken node may expand to an
381 // arbitrary number of nodes now.
382 //
383 ExpandedNode = (EFI_DEVICE_PATH_PROTOCOL *)(
384 (UINTN)ExpandedPath + PrefixSize
385 );
386
387 DebugPrintDevicePath (DEBUG_VERBOSE, "accepted DP", ExpandedPath);
388 DebugPrintDevicePath (DEBUG_VERBOSE, "fix starting at", ExpandedNode);
389
390 DEBUG_CODE (
391 EFI_DEVICE_PATH_PROTOCOL *RemDevPath = ExpandedPath;
392 EFI_HANDLE Dev;
393 EFI_STATUS Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemDevPath, &Dev);
394 if (EFI_ERROR (Status) || (RemDevPath->Type != END_DEVICE_PATH_TYPE) || (RemDevPath->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE)) {
395 DEBUG ((DEBUG_VERBOSE, "borked piece of crap\n"));
396 }
397
398 );
399
400 *DevicePath = ExpandedPath;
401 *DevicePathNode = ExpandedNode;
402 return 1;
403 }
404
405 //
406 // No adequate expansion could be found.
407 //
408 return -1;
409}
410
433STATIC
434INTN
436 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
437 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,
438 OUT APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext OPTIONAL
439 )
440{
441 EFI_STATUS Status;
442 UINTN HandleCount;
443 EFI_HANDLE Device;
444 EFI_HANDLE *HandleBuffer;
445 UINTN Index;
446 UINTN DevicePathSize;
447 UINTN ValidPrefixSize;
448 EFI_DEVICE_PATH_PROTOCOL *TestedDevicePath;
449 EFI_DEVICE_PATH_PROTOCOL *TestedDeviceNode;
450 EFI_DEVICE_PATH_PROTOCOL *NewDeviceNode;
451 EFI_DEVICE_PATH_PROTOCOL *FixedDevicePath;
452 UINTN TestedSize;
453 UINT8 TestedNodeType;
454 UINT8 TestedNodeSubType;
455
456 //
457 // Apple may skip HD node for VirtIO-BLK devices giving APFS Vendor DP
458 // right away in their device paths. Try to locate and fix them up.
459 //
460
461 //
462 // 1. Get all Block Io protocol handles.
463 //
464 HandleCount = 0;
465 Status = gBS->LocateHandleBuffer (
466 ByProtocol,
468 NULL,
469 &HandleCount,
470 &HandleBuffer
471 );
472
473 if (EFI_ERROR (Status)) {
474 DEBUG ((DEBUG_VERBOSE, "Failed to locate any block i/o to fixup DP\n"));
475 return 0;
476 }
477
478 //
479 // 2. Calculate prefix size.
480 //
481 DevicePathSize = GetDevicePathSize (*DevicePath);
482 ValidPrefixSize = DevicePathSize - GetDevicePathSize (*DevicePathNode);
483
484 for (Index = 0; Index < HandleCount; ++Index) {
485 //
486 // 2. Get Device Path protocol from each handle.
487 //
488 Status = gBS->HandleProtocol (
489 HandleBuffer[Index],
491 (VOID **)&TestedDevicePath
492 );
493
494 if (EFI_ERROR (Status)) {
495 continue;
496 }
497
498 //
499 // 3. Calculate found device path size.
500 //
501 TestedSize = GetDevicePathSize (TestedDevicePath);
502
503 //
504 // 4.1 Skip tested device paths that do not match HD paths.
505 //
506 if (TestedSize != ValidPrefixSize + sizeof (HARDDRIVE_DEVICE_PATH) + END_DEVICE_PATH_LENGTH) {
507 continue;
508 }
509
510 //
511 // 4.2 Skip tested device paths that do not share a common prefix.
512 //
513 if (CompareMem (TestedDevicePath, *DevicePath, ValidPrefixSize) != 0) {
514 continue;
515 }
516
517 //
518 // 4.3 Skip tested device paths that are not adding HD nodes.
519 //
520 TestedDeviceNode = (VOID *)((UINTN)TestedDevicePath + ValidPrefixSize);
521 TestedNodeType = DevicePathType (TestedDeviceNode);
522 TestedNodeSubType = DevicePathSubType (TestedDeviceNode);
523 if ( (TestedNodeType != MEDIA_DEVICE_PATH)
524 || (TestedNodeSubType != MEDIA_HARDDRIVE_DP))
525 {
526 continue;
527 }
528
529 //
530 // 5. Initial checks matched. Build fixed device path.
531 //
532 FixedDevicePath = AllocatePool (DevicePathSize + sizeof (HARDDRIVE_DEVICE_PATH));
533 if (FixedDevicePath == NULL) {
534 FreePool (HandleBuffer);
535 return 0;
536 }
537
538 CopyMem (
539 FixedDevicePath,
540 TestedDevicePath,
541 ValidPrefixSize + sizeof (HARDDRIVE_DEVICE_PATH)
542 );
543
544 TestedDeviceNode = (VOID *)((UINTN)FixedDevicePath + ValidPrefixSize + sizeof (HARDDRIVE_DEVICE_PATH));
545
546 CopyMem (
547 TestedDeviceNode,
548 (VOID *)((UINTN)*DevicePath + ValidPrefixSize),
549 DevicePathSize - ValidPrefixSize
550 );
551
552 //
553 // 6. Check this is the right partition.
554 //
555 NewDeviceNode = FixedDevicePath;
556 Status = gBS->LocateDevicePath (
558 &NewDeviceNode,
559 &Device
560 );
561 if (EFI_ERROR (Status)) {
562 FreePool (FixedDevicePath);
563 continue;
564 }
565
566 //
567 // If the discovered device path is past the HD path, then it is ours.
568 // Otherwise we picked up wrong partition and need to retry.
569 //
570 if ((UINTN)NewDeviceNode > (UINTN)TestedDeviceNode) {
571 RestoreContext->OldPath = *DevicePath;
572 *DevicePath = FixedDevicePath;
573 *DevicePathNode = TestedDeviceNode;
574 FreePool (HandleBuffer);
575 return 1;
576 }
577
578 FreePool (FixedDevicePath);
579 }
580
581 FreePool (HandleBuffer);
582
583 //
584 // We found nothing.
585 //
586 return 0;
587}
588
589INTN
591 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
592 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,
593 OUT APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext OPTIONAL,
594 IN EFI_HANDLE ValidDevice OPTIONAL
595 )
596{
597 INTN Result;
598 EFI_DEVICE_PATH_PROTOCOL *OldPath;
599 EFI_DEV_PATH_PTR Node;
600 UINT8 NodeType;
601 UINT8 NodeSubType;
602 UINTN NodeSize;
603
604 ASSERT (DevicePathNode != NULL);
605
606 //
607 // ATTENTION: Changes to this function must be carefully sync'd with
608 // OcFixAppleBootDevicePathNodeRestore().
609 //
610
611 if (RestoreContext != NULL) {
612 RestoreContext->OldPath = NULL;
613 }
614
615 Node.DevPath = *DevicePathNode;
616
617 NodeType = DevicePathType (Node.DevPath);
618 NodeSubType = DevicePathSubType (Node.DevPath);
619
620 if (NodeType == MESSAGING_DEVICE_PATH) {
621 switch (NodeSubType) {
622 case MSG_SATA_DP:
623 if (Node.Sata->PortMultiplierPortNumber != 0xFFFF) {
624 if (RestoreContext != NULL) {
625 RestoreContext->Types.Sata.PortMultiplierPortNumber = Node.Sata->PortMultiplierPortNumber;
626 }
627
628 //
629 // Must be set to 0xFFFF if the device is directly connected to the
630 // HBA. This rule has been established by UEFI 2.5 via an Erratum
631 // and has not been followed by Apple thus far.
632 // Reference: AppleACPIPlatform.kext,
633 // appendSATADevicePathNodeForIOMedia
634 //
635 Node.Sata->PortMultiplierPortNumber = 0xFFFF;
636 return 1;
637 }
638
639 //
640 // Some vendors use proprietary node types over standardised ones. Find
641 // a new, valid DevicePath that matches in prefix and suffix to the
642 // given one but ignore the data of the node that matches the malformed
643 // one.
644 // REF: https://github.com/acidanthera/bugtracker/issues/991#issue-643248184
645 //
646 OldPath = *DevicePath;
647 Result = InternalExpandNewPath (
648 DevicePath,
649 DevicePathNode
650 );
651 if (Result > 0) {
652 //
653 // On success, handle restoring and resources.
654 //
655 if (RestoreContext != NULL) {
656 RestoreContext->OldPath = OldPath;
657 } else {
658 FreePool (OldPath);
659 }
660 }
661
662 return Result;
663
664 case MSG_SASEX_DP:
665 //
666 // Apple uses SubType 0x16 (SasEx) for NVMe, while the UEFI
667 // Specification defines it as SubType 0x17. The structures are
668 // identical.
669 // Reference: AppleACPIPlatform.kext,
670 // appendNVMeDevicePathNodeForIOMedia
671 //
672 if (RestoreContext != NULL) {
673 RestoreContext->Types.SasExNvme.SubType = Node.DevPath->SubType;
674 }
675
677 sizeof (SASEX_DEVICE_PATH) != sizeof (NVME_NAMESPACE_DEVICE_PATH),
678 "SasEx and NVMe DPs must differ in size for fixing to be accurate."
679 );
680
681 NodeSize = DevicePathNodeLength (Node.DevPath);
682 if (NodeSize == sizeof (NVME_NAMESPACE_DEVICE_PATH)) {
683 Node.SasEx->Header.SubType = MSG_NVME_NAMESPACE_DP;
684 return 1;
685 }
686
687 return -1;
688
689 case MSG_NVME_NAMESPACE_DP:
690 //
691 // Workaround for MacPro5,1 using custom NVMe type.
692 //
693 if (RestoreContext != NULL) {
694 RestoreContext->Types.SasExNvme.SubType = Node.DevPath->SubType;
695 }
696
697 Node.NvmeNamespace->Header.SubType = MSG_APPLE_NVME_NAMESPACE_DP;
698 return 1;
699
700 default:
701 break;
702 }
703 } else if (NodeType == ACPI_DEVICE_PATH) {
704 switch (NodeSubType) {
705 case ACPI_DP:
706 if (RestoreContext != NULL) {
707 RestoreContext->Types.Acpi.HID = Node.Acpi->HID;
708 RestoreContext->Types.Acpi.UID = Node.Acpi->UID;
709 }
710
711 if (EISA_ID_TO_NUM (Node.Acpi->HID) == 0x0A03) {
712 //
713 // In some types of firmware, UIDs for PciRoot do not match between ACPI tables and UEFI
714 // UEFI Device Paths. The former contain 0x00, 0x40, 0x80, 0xC0 values, while
715 // the latter have ascending numbers.
716 // Reference: https://github.com/acidanthera/bugtracker/issues/664.
717 // On other boards it is be even more erratic, refer to:
718 // https://github.com/acidanthera/bugtracker/issues/664#issuecomment-647526506
719 // On older boards there also is a PCI0/_UID1 issue, refer to:
720 // https://github.com/acidanthera/bugtracker/issues/664#issuecomment-663873846
721 //
722 switch (Node.Acpi->UID) {
723 case 0x1:
724 Node.Acpi->UID = 0;
725 return 1;
726
727 case 0x10:
728 case 0x40:
729 Node.Acpi->UID = 1;
730 return 1;
731
732 case 0x20:
733 case 0x80:
734 Node.Acpi->UID = 2;
735 return 1;
736
737 case 0x28:
738 case 0xC0:
739 Node.Acpi->UID = 3;
740 return 1;
741
742 case 0x30:
743 Node.Acpi->UID = 4;
744 return 1;
745
746 case 0x38:
747 Node.Acpi->UID = 5;
748 return 1;
749
750 default:
751 break;
752 }
753
754 //
755 // Apple uses PciRoot (EISA 0x0A03) nodes while some types of firmware might use
756 // PcieRoot (EISA 0x0A08).
757 //
758 Node.Acpi->HID = BitFieldWrite32 (
759 Node.Acpi->HID,
760 16,
761 31,
762 0x0A08
763 );
764 return 1;
765 }
766
767 return -1;
768
769 case ACPI_EXTENDED_DP:
770 if (RestoreContext != NULL) {
771 RestoreContext->Types.ExtendedAcpi.HID = Node.ExtendedAcpi->HID;
772 RestoreContext->Types.ExtendedAcpi.CID = Node.ExtendedAcpi->CID;
773 }
774
775 //
776 // Apple uses PciRoot (EISA 0x0A03) nodes while some types of firmware might use
777 // PcieRoot (EISA 0x0A08).
778 //
779 if (EISA_ID_TO_NUM (Node.ExtendedAcpi->HID) == 0x0A03) {
780 Node.ExtendedAcpi->HID = BitFieldWrite32 (
781 Node.ExtendedAcpi->HID,
782 16,
783 31,
784 0x0A08
785 );
786 return 1;
787 }
788
789 if ( (EISA_ID_TO_NUM (Node.ExtendedAcpi->CID) == 0x0A03)
790 && (EISA_ID_TO_NUM (Node.ExtendedAcpi->HID) != 0x0A08))
791 {
792 Node.ExtendedAcpi->CID = BitFieldWrite32 (
793 Node.ExtendedAcpi->CID,
794 16,
795 31,
796 0x0A08
797 );
798 return 1;
799 }
800
801 return -1;
802
803 default:
804 break;
805 }
806 } else if ((NodeType == MEDIA_DEVICE_PATH) && (NodeSubType == MEDIA_VENDOR_DP)) {
807 if (ValidDevice == NULL) {
808 return 0;
809 }
810
812 DevicePath,
813 DevicePathNode,
814 RestoreContext
815 );
816 }
817
818 return 0;
819}
820
821INTN
823 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
824 OUT EFI_DEVICE_PATH_PROTOCOL **RemainingDevicePath
825 )
826{
827 INTN Result;
828 INTN NodePatched;
829 UINTN DevicePathSize;
830
831 APPLE_BOOT_DP_PATCH_CONTEXT FirstNodeRestoreContext;
832 APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContextPtr;
833
834 EFI_HANDLE Device;
835
836 ASSERT (DevicePath != NULL);
837 ASSERT (*DevicePath != NULL);
838 ASSERT (IsDevicePathValid (*DevicePath, 0));
839 //
840 // Restoring is only required for the first Device Path node. Please refer
841 // to the loop for an explanation.
842 //
843 RestoreContextPtr = &FirstNodeRestoreContext;
844 NodePatched = 0;
845 do {
846 //
847 // Retrieve the first Device Path node that cannot be located.
848 //
849 *RemainingDevicePath = *DevicePath;
850 gBS->LocateDevicePath (
852 RemainingDevicePath,
853 &Device
854 );
855 //
856 // Patch the potentially invalid node.
857 //
859 DevicePath,
860 RemainingDevicePath,
861 RestoreContextPtr,
862 Device
863 );
864 //
865 // Save a restore context only for the first processing of the first node.
866 // The reason for this is when the first node cannot be located with any
867 // patch applied, the Device Path may be of a prefix short-form and may
868 // possibly be expanded successfully unmodified.
869 //
870 RestoreContextPtr = NULL;
871 //
872 // Continue as long as nodes are being patched. Remember patch status.
873 //
874 NodePatched |= Result > 0;
875 } while (Result > 0);
876
877 if (Result < 0) {
878 if (NodePatched != 0) {
879 if (*RemainingDevicePath == *DevicePath) {
880 //
881 // If the path could not be fixed, restore the first node if it's the
882 // one failing to be located. Please refer to the loop for an
883 // explanation.
884 // If advancing by at least one node happened, the Device Path cannot
885 // be of a prefix short-form and hence restoring is not beneficial (and
886 // most especially would require tracking every node individually).
887 //
889 DevicePath,
890 RemainingDevicePath,
891 &FirstNodeRestoreContext
892 );
893 } else {
894 //
895 // If patching was successful, explicitly free the used resources.
896 //
898 *DevicePath,
899 &FirstNodeRestoreContext
900 );
901 }
902 }
903
904 return -1;
905 }
906
907 //
908 // Double-check that *RemainingDevicePath still points into *DevicePath.
909 //
910 DEBUG_CODE_BEGIN ();
911 DevicePathSize = GetDevicePathSize (*DevicePath);
912 ASSERT ((UINTN)*RemainingDevicePath >= (UINTN)*DevicePath);
913 ASSERT ((UINTN)*RemainingDevicePath < ((UINTN)*DevicePath) + DevicePathSize);
914 DEBUG_CODE_END ();
915
916 return NodePatched;
917}
918
919STATIC
920BOOLEAN
922 IN CONST FILEPATH_DEVICE_PATH *FilePath,
923 IN OUT UINTN *FilePathLength,
924 IN OUT UINTN *ClipIndex
925 )
926{
927 UINTN Index;
928
929 ASSERT (FilePathLength != NULL);
930 ASSERT (*FilePathLength != 0);
931 ASSERT (FilePath != NULL);
932 ASSERT (ClipIndex != NULL);
933
934 Index = *ClipIndex;
935 if (FilePath->PathName[Index] == L'\\') {
936 *ClipIndex = Index + 1;
937 --(*FilePathLength);
938 return TRUE;
939 }
940
941 return FALSE;
942}
943
944STATIC
945UINTN
947 IN FILEPATH_DEVICE_PATH **FilePath,
948 OUT UINTN *ClipIndex
949 )
950{
951 EFI_DEV_PATH_PTR DevPath;
952 UINTN Index;
953
954 UINTN Length;
955 EFI_DEVICE_PATH_PROTOCOL *NextNode;
956
957 ASSERT (FilePath != NULL);
958 ASSERT (ClipIndex != NULL);
959 //
960 // It is unlikely to be encountered, but empty nodes are not forbidden.
961 //
962 for (
963 Length = 0, NextNode = &(*FilePath)->Header;
964 Length == 0;
965 NextNode = NextDevicePathNode (DevPath.DevPath)
966 )
967 {
968 DevPath.DevPath = NextNode;
969
970 if ( (DevicePathType (DevPath.DevPath) != MEDIA_DEVICE_PATH)
971 || (DevicePathSubType (DevPath.DevPath) != MEDIA_FILEPATH_DP))
972 {
973 Length = 0;
974 break;
975 }
976
977 Length = OcFileDevicePathNameLen (DevPath.FilePath);
978 if (Length > 0) {
979 Index = 0;
980 InternalFileDevicePathsEqualClipBottom (DevPath.FilePath, &Length, &Index);
981 if ( (Length > 0)
982 && (DevPath.FilePath->PathName[Index + Length - 1] == L'\\'))
983 {
984 --Length;
985 }
986
987 *ClipIndex = Index;
988 }
989 }
990
991 *FilePath = DevPath.FilePath;
992 return Length;
993}
994
995STATIC
996UINTN
998 IN FILEPATH_DEVICE_PATH **FilePath,
999 OUT UINTN *ClipIndex
1000 )
1001{
1002 ASSERT (FilePath != NULL);
1003 ASSERT (ClipIndex != NULL);
1004
1005 *FilePath = (FILEPATH_DEVICE_PATH *)NextDevicePathNode (*FilePath);
1007}
1008
1009BOOLEAN
1011 IN FILEPATH_DEVICE_PATH **FilePath1,
1012 IN FILEPATH_DEVICE_PATH **FilePath2
1013 )
1014{
1015 UINTN Clip1Index;
1016 UINTN Clip2Index;
1017 UINTN Len1;
1018 UINTN Len2;
1019 UINTN CurrentLen;
1020 UINTN Index;
1021 CHAR16 Char1;
1022 CHAR16 Char2;
1023 BOOLEAN Result;
1024
1025 ASSERT (FilePath1 != NULL);
1026 ASSERT (*FilePath1 != NULL);
1027 ASSERT (FilePath2 != NULL);
1028 ASSERT (*FilePath2 != NULL);
1029
1030 ASSERT (IsDevicePathValid (&(*FilePath1)->Header, 0));
1031 ASSERT (IsDevicePathValid (&(*FilePath2)->Header, 0));
1032
1033 Len1 = InternalFileDevicePathsEqualClipNode (FilePath1, &Clip1Index);
1034 Len2 = InternalFileDevicePathsEqualClipNode (FilePath2, &Clip2Index);
1035
1036 do {
1037 if ((Len1 == 0) && (Len2 == 0)) {
1038 return TRUE;
1039 }
1040
1041 CurrentLen = MIN (Len1, Len2);
1042 if (CurrentLen == 0) {
1043 return FALSE;
1044 }
1045
1046 //
1047 // FIXME: Discuss case sensitivity. For UEFI FAT, case insensitivity is
1048 // guaranteed.
1049 //
1050 for (Index = 0; Index < CurrentLen; ++Index) {
1051 Char1 = CharToUpper ((*FilePath1)->PathName[Clip1Index + Index]);
1052 Char2 = CharToUpper ((*FilePath2)->PathName[Clip2Index + Index]);
1053 if (Char1 != Char2) {
1054 return FALSE;
1055 }
1056 }
1057
1058 if (Len1 == Len2) {
1059 Len1 = InternalFileDevicePathsEqualClipNextNode (FilePath1, &Clip1Index);
1060 Len2 = InternalFileDevicePathsEqualClipNextNode (FilePath2, &Clip2Index);
1061 } else if (Len1 < Len2) {
1062 Len1 = InternalFileDevicePathsEqualClipNextNode (FilePath1, &Clip1Index);
1063 if (Len1 == 0) {
1064 return FALSE;
1065 }
1066
1067 Len2 -= CurrentLen;
1068 Clip2Index += CurrentLen;
1069 //
1070 // Switching to the next node for the other Device Path implies a path
1071 // separator. Verify we hit such in the currently walked path too.
1072 //
1073 Result = InternalFileDevicePathsEqualClipBottom (*FilePath2, &Len2, &Clip2Index);
1074 if (!Result) {
1075 return FALSE;
1076 }
1077 } else {
1078 Len2 = InternalFileDevicePathsEqualClipNextNode (FilePath2, &Clip2Index);
1079 if (Len2 == 0) {
1080 return FALSE;
1081 }
1082
1083 Len1 -= CurrentLen;
1084 Clip1Index += CurrentLen;
1085 //
1086 // Switching to the next node for the other Device Path implies a path
1087 // separator. Verify we hit such in the currently walked path too.
1088 //
1089 Result = InternalFileDevicePathsEqualClipBottom (*FilePath1, &Len1, &Clip1Index);
1090 if (!Result) {
1091 return FALSE;
1092 }
1093 }
1094 } while (TRUE);
1095}
1096
1106BOOLEAN
1108 IN FILEPATH_DEVICE_PATH *FilePath1,
1109 IN FILEPATH_DEVICE_PATH *FilePath2
1110 )
1111{
1112 ASSERT (FilePath1 != NULL);
1113 ASSERT (FilePath2 != NULL);
1114
1115 return InternalFileDevicePathsEqualWorker (&FilePath1, &FilePath2);
1116}
1117
1118STATIC
1119BOOLEAN
1121 IN EFI_DEVICE_PATH_PROTOCOL *ParentPath,
1122 IN EFI_DEVICE_PATH_PROTOCOL *ChildPath,
1123 IN BOOLEAN CheckChild
1124 )
1125{
1126 BOOLEAN Result;
1127 INTN CmpResult;
1128
1129 EFI_DEV_PATH_PTR ChildPathPtr;
1130 EFI_DEV_PATH_PTR ParentPathPtr;
1131
1132 UINT8 NodeType;
1133 UINT8 NodeSubType;
1134 UINTN NodeSize;
1135
1136 ASSERT (ParentPath != NULL);
1137 ASSERT (IsDevicePathValid (ParentPath, 0));
1138 ASSERT (ChildPath != NULL);
1139 ASSERT (IsDevicePathValid (ChildPath, 0));
1140
1141 ParentPathPtr.DevPath = ParentPath;
1142 ChildPathPtr.DevPath = ChildPath;
1143
1144 while (TRUE) {
1145 NodeType = DevicePathType (ChildPathPtr.DevPath);
1146 NodeSubType = DevicePathSubType (ChildPathPtr.DevPath);
1147
1148 if (NodeType == END_DEVICE_PATH_TYPE) {
1149 //
1150 // We only support single-instance Device Paths.
1151 //
1152 ASSERT (NodeSubType == END_ENTIRE_DEVICE_PATH_SUBTYPE);
1153 return ( CheckChild
1154 || (DevicePathType (ParentPathPtr.DevPath) == END_DEVICE_PATH_TYPE));
1155 }
1156
1157 if ( (DevicePathType (ParentPathPtr.DevPath) != NodeType)
1158 || (DevicePathSubType (ParentPathPtr.DevPath) != NodeSubType))
1159 {
1160 return FALSE;
1161 }
1162
1163 if ( (NodeType == MEDIA_DEVICE_PATH)
1164 && (NodeSubType == MEDIA_FILEPATH_DP))
1165 {
1166 //
1167 // File Paths need special consideration for prepended and appended
1168 // terminators, as well as multiple nodes.
1169 //
1171 &ParentPathPtr.FilePath,
1172 &ChildPathPtr.FilePath
1173 );
1174 if (!Result) {
1175 return FALSE;
1176 }
1177
1178 //
1179 // InternalFileDevicePathsEqualWorker advances the nodes.
1180 //
1181 } else {
1182 NodeSize = DevicePathNodeLength (ChildPathPtr.DevPath);
1183 if (DevicePathNodeLength (ParentPathPtr.DevPath) != NodeSize) {
1184 return FALSE;
1185 }
1186
1188 (sizeof (*ChildPathPtr.DevPath) == 4),
1189 "The Device Path comparison logic depends on the entire header being checked"
1190 );
1191
1192 CmpResult = CompareMem (
1193 (ChildPathPtr.DevPath + 1),
1194 (ParentPathPtr.DevPath + 1),
1195 (NodeSize - sizeof (*ChildPathPtr.DevPath))
1196 );
1197 if (CmpResult != 0) {
1198 return FALSE;
1199 }
1200
1201 ParentPathPtr.DevPath = NextDevicePathNode (ParentPathPtr.DevPath);
1202 ChildPathPtr.DevPath = NextDevicePathNode (ChildPathPtr.DevPath);
1203 }
1204 }
1205}
1206
1207BOOLEAN
1208EFIAPI
1210 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
1211 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
1212 )
1213{
1214 return InternalDevicePathCmpWorker (DevicePath1, DevicePath2, FALSE);
1215}
1216
1217BOOLEAN
1218EFIAPI
1220 IN EFI_DEVICE_PATH_PROTOCOL *ParentPath,
1221 IN EFI_DEVICE_PATH_PROTOCOL *ChildPath
1222 )
1223{
1224 return InternalDevicePathCmpWorker (ParentPath, ChildPath, TRUE);
1225}
1226
1227UINTN
1229 IN CONST FILEPATH_DEVICE_PATH *FilePath
1230 )
1231{
1232 ASSERT (FilePath != NULL);
1233 ASSERT (IsDevicePathValid (&FilePath->Header, 0));
1234 return (OcFileDevicePathNameLen (FilePath) + 1) * sizeof (*FilePath->PathName);
1235}
1236
1237UINTN
1239 IN CONST FILEPATH_DEVICE_PATH *FilePath
1240 )
1241{
1242 UINTN Size;
1243 UINTN Len;
1244
1245 ASSERT (FilePath != NULL);
1246 ASSERT (IsDevicePathValid (&FilePath->Header, 0));
1247
1248 Size = DevicePathNodeLength (FilePath) - SIZE_OF_FILEPATH_DEVICE_PATH;
1249 //
1250 // Account for more than one termination character.
1251 //
1252 Len = (Size / sizeof (*FilePath->PathName)) - 1;
1253 while (Len > 0 && FilePath->PathName[Len - 1] == L'\0') {
1254 --Len;
1255 }
1256
1257 return Len;
1258}
1259
1270UINTN
1272 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
1273 )
1274{
1275 UINTN PathLength;
1276 CONST FILEPATH_DEVICE_PATH *FilePath;
1277
1278 ASSERT (DevicePath != NULL);
1279 ASSERT (IsDevicePathValid (DevicePath, 0));
1280
1281 PathLength = 0;
1282 do {
1283 //
1284 // On the first iteration, this ensures the path is not immediately
1285 // terminated.
1286 //
1287 if ( (DevicePath->Type != MEDIA_DEVICE_PATH)
1288 || (DevicePath->SubType != MEDIA_FILEPATH_DP))
1289 {
1290 return 0;
1291 }
1292
1293 FilePath = (FILEPATH_DEVICE_PATH *)DevicePath;
1294 //
1295 // Each node requires separator or CHAR_NULL
1296 //
1297 PathLength += OcFileDevicePathNameLen (FilePath) + 1;
1298
1299 DevicePath = NextDevicePathNode (DevicePath);
1300 } while (!IsDevicePathEnd (DevicePath));
1301
1302 return PathLength - 1;
1303}
1304
1315UINTN
1317 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
1318 )
1319{
1320 UINTN Len;
1321
1322 Len = OcFileDevicePathFullNameLen (DevicePath);
1323
1324 if (Len == 0) {
1325 return 0;
1326 }
1327
1328 return (Len + 1) * sizeof (CHAR16);
1329}
1330
1342VOID
1344 OUT CHAR16 *PathName,
1345 IN CONST FILEPATH_DEVICE_PATH *FilePath,
1346 IN UINTN PathNameSize
1347 )
1348{
1349 UINTN PathLen;
1350
1351 ASSERT (PathName != NULL);
1352 ASSERT (FilePath != NULL);
1353 ASSERT (IsDevicePathValid (&FilePath->Header, 0));
1354 ASSERT (PathNameSize == OcFileDevicePathFullNameSize (&FilePath->Header));
1355
1356 //
1357 // Note: The UEFI spec declares that a path separator may optionally be
1358 // present at the beginning or end of any node's PathName. This is not
1359 // currently supported here. Any fix would need to be applied here and
1360 // in OcFileDevicePathNameLen.
1361 //
1362 do {
1364 CopyMem (
1365 PathName,
1366 FilePath->PathName,
1367 PathLen * sizeof (*FilePath->PathName)
1368 );
1369 PathName += PathLen;
1370 *PathName++ = L'\\';
1371
1372 FilePath = (CONST FILEPATH_DEVICE_PATH *)NextDevicePathNode (FilePath);
1373 } while (!IsDevicePathEnd (FilePath));
1374
1375 *(PathName - 1) = CHAR_NULL;
1376}
1377
1378CHAR16 *
1380 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1381 OUT EFI_DEVICE_PATH_PROTOCOL **FileDevicePath OPTIONAL
1382 )
1383{
1384 CHAR16 *Path;
1385 EFI_DEVICE_PATH_PROTOCOL *CurrNode;
1386 UINTN PathSize;
1387
1388 Path = NULL;
1389
1390 if (FileDevicePath != NULL) {
1391 *FileDevicePath = NULL;
1392 }
1393
1394 for (CurrNode = DevicePath; !IsDevicePathEnd (CurrNode); CurrNode = NextDevicePathNode (CurrNode)) {
1395 if ( (DevicePathType (CurrNode) == MEDIA_DEVICE_PATH)
1396 && (DevicePathSubType (CurrNode) == MEDIA_FILEPATH_DP))
1397 {
1398 if (FileDevicePath != NULL) {
1399 *FileDevicePath = CurrNode;
1400 }
1401
1402 //
1403 // Perform copying of all the underlying nodes due to potential unaligned access.
1404 //
1405 PathSize = OcFileDevicePathFullNameSize (CurrNode);
1406 if (PathSize == 0) {
1407 return NULL;
1408 }
1409
1410 Path = AllocatePool (PathSize);
1411 if (Path == NULL) {
1412 return NULL;
1413 }
1414
1415 OcFileDevicePathFullName (Path, (FILEPATH_DEVICE_PATH *)CurrNode, PathSize);
1416 break;
1417 }
1418 }
1419
1420 return Path;
1421}
1422
1423EFI_DEVICE_PATH_PROTOCOL *
1425 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
1426 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
1427 )
1428{
1429 INTN CmpResult;
1430
1431 EFI_DEVICE_PATH_PROTOCOL *DevPathWalker;
1432 EFI_DEVICE_PATH_PROTOCOL *CurrentInstance;
1433
1434 UINTN AppendInstanceSize;
1435 UINTN CurrentInstanceSize;
1436
1437 ASSERT (DevicePathInstance != NULL);
1438
1439 if (DevicePath != NULL) {
1440 AppendInstanceSize = GetDevicePathSize (DevicePathInstance);
1441 DevPathWalker = DevicePath;
1442
1443 while (TRUE) {
1444 CurrentInstance = GetNextDevicePathInstance (
1445 &DevPathWalker,
1446 &CurrentInstanceSize
1447 );
1448 if (CurrentInstance == NULL) {
1449 break;
1450 }
1451
1452 if (CurrentInstanceSize != AppendInstanceSize) {
1453 FreePool (CurrentInstance);
1454 continue;
1455 }
1456
1457 CmpResult = CompareMem (
1458 CurrentInstance,
1459 DevicePathInstance,
1460 CurrentInstanceSize
1461 );
1462
1463 FreePool (CurrentInstance);
1464
1465 if (CmpResult == 0) {
1466 return DuplicateDevicePath (DevicePath);
1467 }
1468 }
1469 }
1470
1471 return AppendDevicePathInstance (DevicePath, DevicePathInstance);
1472}
1473
1474UINTN
1476 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
1477 )
1478{
1479 UINTN NumInstances;
1480
1481 NumInstances = 1;
1482
1483 while (!IsDevicePathEnd (DevicePath)) {
1484 if (IsDevicePathEndInstance (DevicePath)) {
1485 ++NumInstances;
1486 }
1487
1488 DevicePath = NextDevicePathNode (DevicePath);
1489 }
1490
1491 return NumInstances;
1492}
1493
1494BOOLEAN
1496 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1497 IN CONST CHAR16 *Suffix,
1498 IN UINTN SuffixLen
1499 )
1500{
1501 FILEPATH_DEVICE_PATH *FilePath;
1502 UINTN PathNameLen;
1503 UINTN PathNameSize;
1504 CHAR16 *PathName;
1505 INTN Result;
1506
1507 //
1508 // OcStrinCmp will be needed in case of a mismatch.
1509 //
1510 ASSERT (SuffixLen == StrLen (Suffix));
1511
1512 FilePath = (FILEPATH_DEVICE_PATH *)FindDevicePathNodeWithType (
1513 DevicePath,
1514 MEDIA_DEVICE_PATH,
1515 MEDIA_FILEPATH_DP
1516 );
1517 if (FilePath == NULL) {
1518 return FALSE;
1519 }
1520
1521 PathNameLen = OcFileDevicePathFullNameLen (&FilePath->Header);
1522 if (PathNameLen < SuffixLen) {
1523 return FALSE;
1524 }
1525
1526 PathNameSize = (PathNameLen + 1) * sizeof (CHAR16);
1527
1528 PathName = AllocatePool (PathNameSize);
1529 if (PathName == NULL) {
1530 return FALSE;
1531 }
1532
1534
1535 Result = OcStriCmp (
1536 &PathName[PathNameLen - SuffixLen],
1537 Suffix
1538 );
1539
1540 FreePool (PathName);
1541
1542 return Result == 0;
1543}
UINT64 Length
CHAR16 PathName[DMG_FILE_PATH_LEN]
DMG_FILEPATH_DEVICE_PATH FilePath
DMG_SIZE_DEVICE_PATH Size
STATIC_ASSERT(BYTES_PER_PIXEL==sizeof(UINT32), "Non 4-byte pixels are unsupported!")
EFI_BOOT_SERVICES * gBS
VOID DebugPrintDevicePath(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL)
STATIC BOOLEAN InternalDevicePathCmpWorker(IN EFI_DEVICE_PATH_PROTOCOL *ParentPath, IN EFI_DEVICE_PATH_PROTOCOL *ChildPath, IN BOOLEAN CheckChild)
BOOLEAN InternalFileDevicePathsEqualWorker(IN FILEPATH_DEVICE_PATH **FilePath1, IN FILEPATH_DEVICE_PATH **FilePath2)
UINTN OcFileDevicePathFullNameLen(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
UINTN OcFileDevicePathNameLen(IN CONST FILEPATH_DEVICE_PATH *FilePath)
INTN OcFixAppleBootDevicePath(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT EFI_DEVICE_PATH_PROTOCOL **RemainingDevicePath)
EFI_DEVICE_PATH_PROTOCOL * FindDevicePathEndNode(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID OcFixAppleBootDevicePathNodeRestoreFree(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, IN OUT APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext)
UINTN OcFileDevicePathNameSize(IN CONST FILEPATH_DEVICE_PATH *FilePath)
BOOLEAN EFIAPI IsDevicePathChild(IN EFI_DEVICE_PATH_PROTOCOL *ParentPath, IN EFI_DEVICE_PATH_PROTOCOL *ChildPath)
CHAR16 * OcCopyDevicePathFullName(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT EFI_DEVICE_PATH_PROTOCOL **FileDevicePath OPTIONAL)
STATIC UINTN InternalFileDevicePathsEqualClipNextNode(IN FILEPATH_DEVICE_PATH **FilePath, OUT UINTN *ClipIndex)
STATIC BOOLEAN InternalFileDevicePathsEqualClipBottom(IN CONST FILEPATH_DEVICE_PATH *FilePath, IN OUT UINTN *FilePathLength, IN OUT UINTN *ClipIndex)
VOID OcFixAppleBootDevicePathNodeRestore(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, IN CONST APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext)
STATIC INTN InternalFixAppleBootDevicePathVirtioNode(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, OUT APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext OPTIONAL)
BOOLEAN OcDevicePathHasFilePathSuffix(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 *Suffix, IN UINTN SuffixLen)
EFI_DEVICE_PATH_PROTOCOL * AbsoluteDevicePath(IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH_PROTOCOL *RelativePath OPTIONAL)
STATIC UINTN InternalFileDevicePathsEqualClipNode(IN FILEPATH_DEVICE_PATH **FilePath, OUT UINTN *ClipIndex)
STATIC INTN InternalExpandNewPath(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode)
EFI_DEVICE_PATH_PROTOCOL * OcAppendDevicePathInstanceDedupe(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance)
VOID OcFileDevicePathFullName(OUT CHAR16 *PathName, IN CONST FILEPATH_DEVICE_PATH *FilePath, IN UINTN PathNameSize)
INTN OcFixAppleBootDevicePathNode(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, OUT APPLE_BOOT_DP_PATCH_CONTEXT *RestoreContext OPTIONAL, IN EFI_HANDLE ValidDevice OPTIONAL)
EFI_DEVICE_PATH_PROTOCOL * TrailedBooterDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
UINTN OcGetNumDevicePathInstances(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
EFI_DEVICE_PATH_PROTOCOL * FindDevicePathNodeWithType(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINT8 Type, IN UINT8 SubType OPTIONAL)
BOOLEAN FileDevicePathsEqual(IN FILEPATH_DEVICE_PATH *FilePath1, IN FILEPATH_DEVICE_PATH *FilePath2)
EFI_DEVICE_PATH_PROTOCOL * AppendFileNameDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName)
UINTN OcFileDevicePathFullNameSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
BOOLEAN EFIAPI IsDevicePathEqual(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2)
EFI_DEVICE_PATH_PROTOCOL * OcGetNextLoadOptionDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN EFI_DEVICE_PATH_PROTOCOL *FullPath)
#define MSG_APPLE_NVME_NAMESPACE_DP
INTN EFIAPI OcStriCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_GUID gEfiBlockIoProtocolGuid
EFI_GUID gEfiDevicePathProtocolGuid
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
Definition UserMisc.c:680
#define ASSERT(x)
Definition coder.h:55
#define MIN(a, b)
Definition deflate.c:1673
#define Len
Definition deflate.h:82