OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
ExpandDevicePath.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11
12#include <IndustryStandard/Pci.h>
13
15#include <Guid/Gpt.h>
16
17#include <Protocol/BlockIo.h>
18#include <Protocol/LoadFile.h>
19#include <Protocol/PciIo.h>
20#include <Protocol/SimpleFileSystem.h>
21#include <Protocol/UsbIo.h>
22
23#include <Library/BaseLib.h>
24#include <Library/BaseMemoryLib.h>
26#include <Library/DevicePathLib.h>
28#include <Library/MemoryAllocationLib.h>
29#include <Library/OcFileLib.h>
30#include <Library/UefiBootServicesTableLib.h>
31
32#define ACPI_VMD0001_HID 0x000159A4 // EisaId ("VMD0001")
33#define ACPI_VBS0001_HID 0x00015853 // EisaId ("VBS0001")
34
35// CHANGE: Track InternalConnectAll() execution status.
36STATIC BOOLEAN mConnectAllExecuted = FALSE;
37
38// CHANGE: Added from UefiBootManagerLib
39
47VOID
49 VOID
50 )
51{
52 EFI_STATUS Status;
53 UINTN HandleCount;
54 EFI_HANDLE *HandleBuffer;
55 UINTN Index;
56
57 // CHANGE: Report execution status.
59
60 //
61 // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
62 // CHANGE: Only connect device handles. Do not call gDS->Dispatch().
63 //
64 Status = gBS->LocateHandleBuffer (
65 ByProtocol,
67 NULL,
68 &HandleCount,
69 &HandleBuffer
70 );
71 if (!EFI_ERROR (Status)) {
72 for (Index = 0; Index < HandleCount; Index++) {
73 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
74 }
75
76 FreePool (HandleBuffer);
77 }
78}
79
91STATIC
92BOOLEAN
94 IN EFI_USB_IO_PROTOCOL *UsbIo,
95 IN USB_CLASS_DEVICE_PATH *UsbClass
96 )
97{
98 EFI_STATUS Status;
99 EFI_USB_DEVICE_DESCRIPTOR DevDesc;
100 EFI_USB_INTERFACE_DESCRIPTOR IfDesc;
101 UINT8 DeviceClass;
102 UINT8 DeviceSubClass;
103 UINT8 DeviceProtocol;
104
105 if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||
106 (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP))
107 {
108 return FALSE;
109 }
110
111 //
112 // Check Vendor Id and Product Id.
113 //
114 Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
115 if (EFI_ERROR (Status)) {
116 return FALSE;
117 }
118
119 if ((UsbClass->VendorId != 0xffff) &&
120 (UsbClass->VendorId != DevDesc.IdVendor))
121 {
122 return FALSE;
123 }
124
125 if ((UsbClass->ProductId != 0xffff) &&
126 (UsbClass->ProductId != DevDesc.IdProduct))
127 {
128 return FALSE;
129 }
130
131 DeviceClass = DevDesc.DeviceClass;
132 DeviceSubClass = DevDesc.DeviceSubClass;
133 DeviceProtocol = DevDesc.DeviceProtocol;
134 if (DeviceClass == 0) {
135 //
136 // If Class in Device Descriptor is set to 0, use the Class, SubClass and
137 // Protocol in Interface Descriptor instead.
138 //
139 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);
140 if (EFI_ERROR (Status)) {
141 return FALSE;
142 }
143
144 DeviceClass = IfDesc.InterfaceClass;
145 DeviceSubClass = IfDesc.InterfaceSubClass;
146 DeviceProtocol = IfDesc.InterfaceProtocol;
147 }
148
149 //
150 // Check Class, SubClass and Protocol.
151 //
152 if ((UsbClass->DeviceClass != 0xff) &&
153 (UsbClass->DeviceClass != DeviceClass))
154 {
155 return FALSE;
156 }
157
158 if ((UsbClass->DeviceSubClass != 0xff) &&
159 (UsbClass->DeviceSubClass != DeviceSubClass))
160 {
161 return FALSE;
162 }
163
164 if ((UsbClass->DeviceProtocol != 0xff) &&
165 (UsbClass->DeviceProtocol != DeviceProtocol))
166 {
167 return FALSE;
168 }
169
170 return TRUE;
171}
172
184STATIC
185BOOLEAN
187 IN EFI_USB_IO_PROTOCOL *UsbIo,
188 IN USB_WWID_DEVICE_PATH *UsbWwid
189 )
190{
191 EFI_STATUS Status;
192 EFI_USB_DEVICE_DESCRIPTOR DevDesc;
193 EFI_USB_INTERFACE_DESCRIPTOR IfDesc;
194 UINT16 *LangIdTable;
195 UINT16 TableSize;
196 UINT16 Index;
197 CHAR16 *CompareStr;
198 UINTN CompareLen;
199 CHAR16 *SerialNumberStr;
200 UINTN Length;
201
202 if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||
203 (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP))
204 {
205 return FALSE;
206 }
207
208 //
209 // Check Vendor Id and Product Id.
210 //
211 Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
212 if (EFI_ERROR (Status)) {
213 return FALSE;
214 }
215
216 if ((DevDesc.IdVendor != UsbWwid->VendorId) ||
217 (DevDesc.IdProduct != UsbWwid->ProductId))
218 {
219 return FALSE;
220 }
221
222 //
223 // Check Interface Number.
224 //
225 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);
226 if (EFI_ERROR (Status)) {
227 return FALSE;
228 }
229
230 if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {
231 return FALSE;
232 }
233
234 //
235 // Check Serial Number.
236 //
237 if (DevDesc.StrSerialNumber == 0) {
238 return FALSE;
239 }
240
241 //
242 // Get all supported languages.
243 //
244 TableSize = 0;
245 LangIdTable = NULL;
246 Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);
247 if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {
248 return FALSE;
249 }
250
251 //
252 // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.
253 //
254 CompareStr = (CHAR16 *)(UINTN)(UsbWwid + 1);
255 CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);
256 if (CompareStr[CompareLen - 1] == L'\0') {
257 CompareLen--;
258 }
259
260 //
261 // Compare serial number in each supported language.
262 //
263 for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {
264 SerialNumberStr = NULL;
265 Status = UsbIo->UsbGetStringDescriptor (
266 UsbIo,
267 LangIdTable[Index],
268 DevDesc.StrSerialNumber,
269 &SerialNumberStr
270 );
271 if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {
272 continue;
273 }
274
275 Length = StrLen (SerialNumberStr);
276 if ((Length >= CompareLen) &&
277 (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0))
278 {
279 FreePool (SerialNumberStr);
280 return TRUE;
281 }
282
283 FreePool (SerialNumberStr);
284 }
285
286 return FALSE;
287}
288
304STATIC
305EFI_HANDLE *
307 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
308 IN UINTN ParentDevicePathSize,
309 OUT UINTN *UsbIoHandleCount
310 )
311{
312 EFI_STATUS Status;
313 EFI_HANDLE *UsbIoHandles;
314 EFI_DEVICE_PATH_PROTOCOL *UsbIoDevicePath;
315 EFI_USB_IO_PROTOCOL *UsbIo;
316 UINTN Index;
317 BOOLEAN Matched;
318
319 ASSERT (UsbIoHandleCount != NULL);
320
321 //
322 // Get all UsbIo Handles.
323 //
324 Status = gBS->LocateHandleBuffer (
325 ByProtocol,
326 &gEfiUsbIoProtocolGuid,
327 NULL,
328 UsbIoHandleCount,
329 &UsbIoHandles
330 );
331 if (EFI_ERROR (Status)) {
332 *UsbIoHandleCount = 0;
333 UsbIoHandles = NULL;
334 }
335
336 for (Index = 0; Index < *UsbIoHandleCount; ) {
337 //
338 // Get the Usb IO interface.
339 //
340 Status = gBS->HandleProtocol (
341 UsbIoHandles[Index],
342 &gEfiUsbIoProtocolGuid,
343 (VOID **)&UsbIo
344 );
345 UsbIoDevicePath = DevicePathFromHandle (UsbIoHandles[Index]);
346 Matched = FALSE;
347 if (!EFI_ERROR (Status) && (UsbIoDevicePath != NULL)) {
348 //
349 // Compare starting part of UsbIoHandle's device path with ParentDevicePath.
350 //
351 if (CompareMem (UsbIoDevicePath, DevicePath, ParentDevicePathSize) == 0) {
352 if (BmMatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *)((UINTN)DevicePath + ParentDevicePathSize)) ||
353 BmMatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *)((UINTN)DevicePath + ParentDevicePathSize)))
354 {
355 Matched = TRUE;
356 }
357 }
358 }
359
360 if (!Matched) {
361 (*UsbIoHandleCount)--;
362 CopyMem (&UsbIoHandles[Index], &UsbIoHandles[Index + 1], (*UsbIoHandleCount - Index) * sizeof (EFI_HANDLE));
363 } else {
364 Index++;
365 }
366 }
367
368 return UsbIoHandles;
369}
370
397STATIC
398EFI_DEVICE_PATH_PROTOCOL *
400 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
401 IN EFI_DEVICE_PATH_PROTOCOL *FullPath,
402 IN EFI_DEVICE_PATH_PROTOCOL *ShortformNode
403 )
404{
405 UINTN ParentDevicePathSize;
406 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
407 EFI_DEVICE_PATH_PROTOCOL *NextFullPath;
408 EFI_HANDLE *Handles;
409 UINTN HandleCount;
410 UINTN Index;
411 BOOLEAN GetNext;
412
413 NextFullPath = NULL;
414 GetNext = (BOOLEAN)(FullPath == NULL);
415 ParentDevicePathSize = (UINTN)ShortformNode - (UINTN)FilePath;
416 RemainingDevicePath = NextDevicePathNode (ShortformNode);
417 Handles = BmFindUsbDevice (FilePath, ParentDevicePathSize, &HandleCount);
418
419 for (Index = 0; Index < HandleCount; Index++) {
420 FilePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);
421 if (FilePath == NULL) {
422 //
423 // Out of memory.
424 //
425 continue;
426 }
427
428 NextFullPath = OcGetNextLoadOptionDevicePath (FilePath, NULL);
429 FreePool (FilePath);
430 if (NextFullPath == NULL) {
431 //
432 // No BlockIo or SimpleFileSystem under FilePath.
433 //
434 continue;
435 }
436
437 if (GetNext) {
438 break;
439 } else {
440 GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
441 FreePool (NextFullPath);
442 NextFullPath = NULL;
443 }
444 }
445
446 if (Handles != NULL) {
447 FreePool (Handles);
448 }
449
450 return NextFullPath;
451}
452
463STATIC
464EFI_DEVICE_PATH_PROTOCOL *
466 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
467 IN EFI_DEVICE_PATH_PROTOCOL *FullPath,
468 IN EFI_HANDLE Handle
469 )
470{
471 EFI_STATUS Status;
472 EFI_BLOCK_IO_PROTOCOL *BlockIo;
473 VOID *Buffer;
474 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
475 EFI_DEVICE_PATH_PROTOCOL *NextFullPath;
476 UINTN Size;
477 UINTN TempSize;
478 EFI_HANDLE *SimpleFileSystemHandles;
479 UINTN NumberSimpleFileSystemHandles;
480 UINTN Index;
481 BOOLEAN GetNext;
482
483 GetNext = (BOOLEAN)(FullPath == NULL);
484 //
485 // Check whether the device is connected
486 // CHANGE: This branch has been removed as it has been covered by a caller change
487 //
488
489 // CHANGE: Get Handle via parameter as the function is called by the caller too
490
491 //
492 // For device boot option only pointing to the removable device handle,
493 // should make sure all its children handles (its child partion or media handles)
494 // are created and connected.
495 //
496 gBS->ConnectController (Handle, NULL, NULL, TRUE);
497
498 //
499 // Issue a dummy read to the device to check for media change.
500 // When the removable media is changed, any Block IO read/write will
501 // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is
502 // returned. After the Block IO protocol is reinstalled, subsequent
503 // Block IO read/write will success.
504 //
505 Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
506 // CHANGE: Do not ASSERT.
507 if (EFI_ERROR (Status)) {
508 return NULL;
509 }
510
511 Buffer = AllocatePool (BlockIo->Media->BlockSize);
512 if (Buffer != NULL) {
513 BlockIo->ReadBlocks (
514 BlockIo,
515 BlockIo->Media->MediaId,
516 0,
517 BlockIo->Media->BlockSize,
518 Buffer
519 );
520 FreePool (Buffer);
521 }
522
523 //
524 // Detect the the default boot file from removable Media
525 //
526 NextFullPath = NULL;
527 Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;
528 gBS->LocateHandleBuffer (
529 ByProtocol,
531 NULL,
532 &NumberSimpleFileSystemHandles,
533 &SimpleFileSystemHandles
534 );
535 for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
536 //
537 // Get the device path size of SimpleFileSystem handle
538 //
539 TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
540 TempSize = GetDevicePathSize (TempDevicePath) - END_DEVICE_PATH_LENGTH;
541 //
542 // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path
543 //
544 if ((Size <= TempSize) && (CompareMem (TempDevicePath, DevicePath, Size) == 0)) {
545 // CHANGE: Do not append EFI boot file.
546 NextFullPath = DuplicateDevicePath (TempDevicePath);
547 if (GetNext) {
548 break;
549 } else {
550 GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
551 FreePool (NextFullPath);
552 NextFullPath = NULL;
553 }
554 }
555 }
556
557 if (SimpleFileSystemHandles != NULL) {
558 FreePool (SimpleFileSystemHandles);
559 }
560
561 return NextFullPath;
562}
563
578STATIC
579BOOLEAN
581 IN EFI_HANDLE Handle,
582 IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
583 IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath,
584 IN BOOLEAN LocateEsp
585 )
586{
587 HARDDRIVE_DEVICE_PATH *Node;
588 CONST EFI_PARTITION_ENTRY *PartEntry;
589
590 if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {
591 return FALSE;
592 }
593
594 // CHANGE: Abort early if partition cannot be an ESP while it was requested.
595 if ( LocateEsp
596 && ( (HardDriveDevicePath->MBRType != MBR_TYPE_EFI_PARTITION_TABLE_HEADER)
597 || (HardDriveDevicePath->SignatureType != SIGNATURE_TYPE_GUID)))
598 {
599 return FALSE;
600 }
601
602 //
603 // Match all the partition device path nodes including the nested partition nodes
604 //
605 while (!IsDevicePathEnd (BlockIoDevicePath)) {
606 if ((DevicePathType (BlockIoDevicePath) == MEDIA_DEVICE_PATH) &&
607 (DevicePathSubType (BlockIoDevicePath) == MEDIA_HARDDRIVE_DP)
608 )
609 {
610 //
611 // See if the harddrive device path in blockio matches the orig Hard Drive Node
612 //
613 Node = (HARDDRIVE_DEVICE_PATH *)BlockIoDevicePath;
614
615 //
616 // Match Signature and PartitionNumber.
617 // Unused bytes in Signature are initiaized with zeros.
618 //
619 if ((Node->MBRType == HardDriveDevicePath->MBRType) &&
620 (Node->SignatureType == HardDriveDevicePath->SignatureType) &&
621 (CompareMem (Node->Signature, HardDriveDevicePath->Signature, sizeof (Node->Signature)) == 0))
622 {
623 // CHANGE: Allow ESP location when PartitionNumber mismatches.
624 if (!LocateEsp) {
625 if (Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) {
626 return TRUE;
627 }
628 } else {
629 PartEntry = OcGetGptPartitionEntry (Handle);
630 if ( (PartEntry != NULL)
631 && CompareGuid (&PartEntry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid))
632 {
633 return TRUE;
634 }
635 }
636 }
637 }
638
639 BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);
640 }
641
642 return FALSE;
643}
644
658STATIC
659EFI_DEVICE_PATH_PROTOCOL *
661 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
662 )
663{
664 EFI_STATUS Status;
665 UINTN BlockIoHandleCount;
666 EFI_HANDLE *BlockIoBuffer;
667 EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
668 UINTN Index;
669 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
670 EFI_DEVICE_PATH_PROTOCOL *FullPath;
671 BOOLEAN LocateEsp;
672
673 // CHANGE: Remove HDDP variable code.
674
675 FullPath = NULL;
676 //
677 // If we get here we fail to find or 'HDDP' not exist, and now we need
678 // to search all devices in the system for a matched partition
679 //
680 // CHANGE: Only connect all on failure.
681 //
682 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
683 if (EFI_ERROR (Status)) {
684 BlockIoHandleCount = 0;
685 BlockIoBuffer = NULL;
686 }
687
688 //
689 // Loop through all the device handles that support the BLOCK_IO Protocol
690 // CHANGE: Locate ESP when failing to find an exact match
691 //
692 LocateEsp = FALSE;
693 do {
694 for (Index = 0; Index < BlockIoHandleCount; Index++) {
695 BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[Index]);
696 if (BlockIoDevicePath == NULL) {
697 continue;
698 }
699
700 if (BmMatchPartitionDevicePathNode (BlockIoBuffer[Index], BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *)FilePath, LocateEsp)) {
701 //
702 // Find the matched partition device path
703 //
704 TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));
705 FullPath = OcGetNextLoadOptionDevicePath (TempDevicePath, NULL);
706 FreePool (TempDevicePath);
707
708 if (FullPath != NULL) {
709 break;
710 }
711 }
712 }
713
714 if (FullPath != NULL) {
715 break;
716 }
717
718 if (!mConnectAllExecuted) {
721 break;
722 }
723
724 if (LocateEsp) {
725 break;
726 }
727
728 LocateEsp = TRUE;
729 } while (TRUE);
730
731 if (BlockIoBuffer != NULL) {
732 FreePool (BlockIoBuffer);
733 }
734
735 return FullPath;
736}
737
753STATIC
754EFI_STATUS
756 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
757 )
758{
759 EFI_STATUS Status;
760 EFI_HANDLE *Handles;
761 UINTN HandleCount;
762 UINTN Index;
763 EFI_PCI_IO_PROTOCOL *PciIo;
764 UINT8 Class[3];
765 BOOLEAN AtLeastOneConnected;
766
767 //
768 // Check the passed in parameters
769 //
770 if (DevicePath == NULL) {
771 return EFI_INVALID_PARAMETER;
772 }
773
774 if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
775 ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))
776 )
777 {
778 return EFI_INVALID_PARAMETER;
779 }
780
781 //
782 // Find the usb host controller firstly, then connect with the remaining device path
783 //
784 AtLeastOneConnected = FALSE;
785 Status = gBS->LocateHandleBuffer (
786 ByProtocol,
787 &gEfiPciIoProtocolGuid,
788 NULL,
789 &HandleCount,
790 &Handles
791 );
792 if (!EFI_ERROR (Status)) {
793 for (Index = 0; Index < HandleCount; Index++) {
794 Status = gBS->HandleProtocol (
795 Handles[Index],
796 &gEfiPciIoProtocolGuid,
797 (VOID **)&PciIo
798 );
799 if (!EFI_ERROR (Status)) {
800 //
801 // Check whether the Pci device is the wanted usb host controller
802 //
803 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
804 if (!EFI_ERROR (Status) &&
805 ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
806 )
807 {
808 Status = gBS->ConnectController (
809 Handles[Index],
810 NULL,
811 DevicePath,
812 FALSE
813 );
814 if (!EFI_ERROR (Status)) {
815 AtLeastOneConnected = TRUE;
816 }
817 }
818 }
819 }
820
821 if (Handles != NULL) {
822 FreePool (Handles);
823 }
824 }
825
826 return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
827}
828
849STATIC
850EFI_DEVICE_PATH_PROTOCOL *
852 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
853 )
854{
855 EFI_STATUS Status;
856 UINTN HandleCount;
857 UINTN Index;
858 EFI_HANDLE *HandleBuffer;
859 EFI_DEVICE_PATH_PROTOCOL *HvDevicePath;
860 EFI_DEVICE_PATH_PROTOCOL *Node;
861 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
862 UINTN FilePathSize;
863 UINTN HvSuffixSize;
864 SCSI_DEVICE_PATH *FileScsiPath;
865 SCSI_DEVICE_PATH *HvScsiPath;
866
867 DebugPrintDevicePath (DEBUG_INFO, "OCDP: Expanding Hyper-V DP", FilePath);
868
869 FilePathSize = GetDevicePathSize (FilePath);
870
871 //
872 // Get SCSI device node from file path, if any.
873 //
874 FileScsiPath = NULL;
875 if ( (DevicePathType (FilePath) == MESSAGING_DEVICE_PATH)
876 && (DevicePathSubType (FilePath) == MSG_SCSI_DP))
877 {
878 FileScsiPath = (SCSI_DEVICE_PATH *)FilePath;
879 FilePath = NextDevicePathNode (FilePath);
880 }
881
882 Status = gBS->LocateHandleBuffer (
883 ByProtocol,
885 NULL,
886 &HandleCount,
887 &HandleBuffer
888 );
889
890 if (EFI_ERROR (Status)) {
891 return NULL;
892 }
893
894 for (Index = 0; Index < HandleCount; ++Index) {
895 Status = gBS->HandleProtocol (
896 HandleBuffer[Index],
898 (VOID **)&HvDevicePath
899 );
900 if (EFI_ERROR (Status)) {
901 continue;
902 }
903
904 DebugPrintDevicePath (DEBUG_INFO, "OCDP: Matching Hyper-V DP", HvDevicePath);
905
906 for (Node = HvDevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
907 //
908 // Skip over SCSI paths if the target of the file path matches the LUN of this one.
909 //
910 if ( (FileScsiPath != NULL)
911 && (DevicePathType (Node) == MESSAGING_DEVICE_PATH)
912 && (DevicePathSubType (Node) == MSG_SCSI_DP))
913 {
914 HvScsiPath = (SCSI_DEVICE_PATH *)Node;
915 if ((HvScsiPath->Pun == FileScsiPath->Lun) && (HvScsiPath->Lun == FileScsiPath->Pun)) {
916 continue;
917 } else {
918 break;
919 }
920 }
921
922 //
923 // Skip till we find the matching node in the middle of macOS-made DP.
924 //
925 if ( (DevicePathType (Node) == DevicePathType (FilePath))
926 && (DevicePathSubType (Node) == DevicePathSubType (FilePath)))
927 {
928 //
929 // Match the macOS-made DP till the filename.
930 //
931 HvSuffixSize = GetDevicePathSize (Node) - END_DEVICE_PATH_LENGTH;
932 if (FilePathSize < HvSuffixSize) {
933 break;
934 }
935
936 if (CompareMem (Node, FilePath, HvSuffixSize) == 0) {
937 NewDevicePath = AppendDevicePath (
938 HvDevicePath,
939 (VOID *)((UINTN)FilePath + HvSuffixSize)
940 );
941 if (NewDevicePath != NULL) {
942 DebugPrintDevicePath (DEBUG_INFO, "OCDP: Matched Hyper-V DP", NewDevicePath);
943 }
944
945 FreePool (HandleBuffer);
946 return NewDevicePath;
947 }
948 }
949 }
950 }
951
952 FreePool (HandleBuffer);
953 return NULL;
954}
955
975STATIC
976EFI_DEVICE_PATH_PROTOCOL *
978 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
979 )
980{
981 EFI_STATUS Status;
982 UINTN HandleCount;
983 UINTN Index;
984 EFI_HANDLE *HandleBuffer;
985 EFI_DEVICE_PATH_PROTOCOL *SdDevicePath;
986 EFI_DEVICE_PATH_PROTOCOL *Node;
987 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
988 UINTN FilePathSize;
989 UINTN SdSuffixSize;
990
991 DebugPrintDevicePath (DEBUG_INFO, "OCDP: Expanding SD card DP", FilePath);
992
993 FilePathSize = GetDevicePathSize (FilePath);
994
995 Status = gBS->LocateHandleBuffer (
996 ByProtocol,
998 NULL,
999 &HandleCount,
1000 &HandleBuffer
1001 );
1002
1003 if (EFI_ERROR (Status)) {
1004 return NULL;
1005 }
1006
1007 for (Index = 0; Index < HandleCount; ++Index) {
1008 Status = gBS->HandleProtocol (
1009 HandleBuffer[Index],
1011 (VOID **)&SdDevicePath
1012 );
1013 if (EFI_ERROR (Status)) {
1014 continue;
1015 }
1016
1017 DebugPrintDevicePath (DEBUG_INFO, "OCDP: Matching SD card DP", SdDevicePath);
1018
1019 for (Node = SdDevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
1020 //
1021 // Skip till we find the matching node in the middle of macOS-made DP.
1022 //
1023 if ( (DevicePathType (Node) == DevicePathType (FilePath))
1024 && (DevicePathSubType (Node) == DevicePathSubType (FilePath)))
1025 {
1026 //
1027 // Match the macOS-made DP till the filename.
1028 //
1029 SdSuffixSize = GetDevicePathSize (Node) - END_DEVICE_PATH_LENGTH;
1030 if (FilePathSize < SdSuffixSize) {
1031 break;
1032 }
1033
1034 if (CompareMem (Node, FilePath, SdSuffixSize) == 0) {
1035 NewDevicePath = AppendDevicePath (
1036 SdDevicePath,
1037 (VOID *)((UINTN)FilePath + SdSuffixSize)
1038 );
1039 if (NewDevicePath != NULL) {
1040 DebugPrintDevicePath (DEBUG_INFO, "OCDP: Matched SD card DP", NewDevicePath);
1041 }
1042
1043 FreePool (HandleBuffer);
1044 return NewDevicePath;
1045 }
1046 }
1047 }
1048 }
1049
1050 FreePool (HandleBuffer);
1051 return NULL;
1052}
1053
1054EFI_DEVICE_PATH_PROTOCOL *
1056 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1057 IN EFI_DEVICE_PATH_PROTOCOL *FullPath
1058 )
1059{
1060 EFI_HANDLE Handle;
1061 EFI_DEVICE_PATH_PROTOCOL *Node;
1062 EFI_DEVICE_PATH_PROTOCOL *DeviceNode;
1063 ACPI_HID_DEVICE_PATH *AcpiNode;
1064 VENDOR_DEFINED_DEVICE_PATH *VendorNode;
1065 EFI_STATUS Status;
1066
1067 ASSERT (FilePath != NULL);
1068
1069 //
1070 // CHANGE: If SimpleFileSystem is located, the device path is already expanded.
1071 //
1072 Node = FilePath;
1073 Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &Node, &Handle);
1074 if (!EFI_ERROR (Status)) {
1075 if (FullPath != NULL) {
1076 return NULL;
1077 }
1078
1079 return DuplicateDevicePath (FilePath);
1080 }
1081
1082 // CHANGE: Hyper-V support start.
1083
1084 //
1085 // Match ACPI_VMD0001_HID during the first call only.
1086 //
1087 if ( (FullPath == NULL)
1088 && (DevicePathType (Node) == ACPI_DEVICE_PATH)
1089 && (DevicePathSubType (Node) == ACPI_DP)
1090 && (DevicePathNodeLength (Node) == sizeof (ACPI_HID_DEVICE_PATH)))
1091 {
1092 AcpiNode = (ACPI_HID_DEVICE_PATH *)Node;
1093 if ((AcpiNode->HID == ACPI_VMD0001_HID) && (AcpiNode->UID == 0)) {
1094 //
1095 // Match ACPI_VBS0001_HID.
1096 //
1097 Node = NextDevicePathNode (Node);
1098 if ( (DevicePathType (Node) == ACPI_DEVICE_PATH)
1099 && (DevicePathSubType (Node) == ACPI_DP)
1100 && (DevicePathNodeLength (Node) == sizeof (ACPI_HID_DEVICE_PATH)))
1101 {
1102 AcpiNode = (ACPI_HID_DEVICE_PATH *)Node;
1103 if ((AcpiNode->HID == ACPI_VBS0001_HID) && (AcpiNode->UID == 0)) {
1104 Node = NextDevicePathNode (Node);
1105 return BmExpandHyperVDevicePath (Node);
1106 }
1107 }
1108 }
1109 }
1110
1111 // CHANGE: Hyper-V support end.
1112
1113 //
1114 // Locate and match Apple SD card device path during the first call only.
1115 //
1116 if (FullPath == NULL) {
1117 for (DeviceNode = Node; !IsDevicePathEnd (DeviceNode); DeviceNode = NextDevicePathNode (DeviceNode)) {
1118 if ((DevicePathType (DeviceNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DeviceNode) == MSG_VENDOR_DP)) {
1119 VendorNode = (VENDOR_DEFINED_DEVICE_PATH *)DeviceNode;
1120 if (CompareGuid (&gAppleSdCardVendorDevicePathGuid, &VendorNode->Guid)) {
1121 Node = NextDevicePathNode (DeviceNode);
1122 return BmExpandAppleSDCardDevicePath (Node);
1123 }
1124 }
1125 }
1126 }
1127
1128 Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &Node, &Handle);
1129 if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {
1130 return BmExpandMediaDevicePath (FilePath, FullPath, Handle);
1131 }
1132
1133 // CHANGE: File Path node support removed.
1134
1135 //
1136 // Expand the short-form device path to full device path
1137 //
1138 if ((DevicePathType (FilePath) == MEDIA_DEVICE_PATH) &&
1139 (DevicePathSubType (FilePath) == MEDIA_HARDDRIVE_DP))
1140 {
1141 //
1142 // Expand the Harddrive device path
1143 //
1144 if (FullPath == NULL) {
1146 } else {
1147 return NULL;
1148 }
1149 } else if ((DevicePathType (FilePath) == MESSAGING_DEVICE_PATH) &&
1150 (DevicePathSubType (FilePath) == MSG_URI_DP))
1151 {
1152 //
1153 // CHANGE: Removed expansion of the URI device path
1154 //
1155 return NULL;
1156 } else {
1157 Node = FilePath;
1158 Status = gBS->LocateDevicePath (&gEfiUsbIoProtocolGuid, &Node, &Handle);
1159 if (EFI_ERROR (Status)) {
1160 //
1161 // Only expand the USB WWID/Class device path
1162 // when FilePath doesn't point to a physical UsbIo controller.
1163 // Otherwise, infinite recursion will happen.
1164 //
1165 for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
1166 if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&
1167 ((DevicePathSubType (Node) == MSG_USB_CLASS_DP) || (DevicePathSubType (Node) == MSG_USB_WWID_DP)))
1168 {
1169 break;
1170 }
1171 }
1172
1173 //
1174 // Expand the USB WWID/Class device path
1175 //
1176 if (!IsDevicePathEnd (Node)) {
1177 if (FilePath == Node) {
1178 //
1179 // Boot Option device path starts with USB Class or USB WWID device path.
1180 // For Boot Option device path which doesn't begin with the USB Class or
1181 // USB WWID device path, it's not needed to connect again here.
1182 //
1184 }
1185
1186 return BmExpandUsbDevicePath (FilePath, FullPath, Node);
1187 }
1188 }
1189 }
1190
1191 //
1192 // For the below cases, FilePath only expands to one Full path.
1193 // So just handle the case when FullPath == NULL.
1194 //
1195 if (FullPath != NULL) {
1196 return NULL;
1197 }
1198
1199 // CHANGE: SimleFileSystem case has been covered at the beginning of the function
1200
1201 // CHANGE: Removed FV support.
1202
1203 //
1204 // CHANGE: Remove LoadFile support (e.g. PXE network boot).
1205 //
1206 return NULL;
1207}
EFI_GUID gAppleSdCardVendorDevicePathGuid
UINT64 Length
STATIC BOOLEAN mConnectAllExecuted
EFI_DEVICE_PATH_PROTOCOL * OcGetNextLoadOptionDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN EFI_DEVICE_PATH_PROTOCOL *FullPath)
#define ACPI_VBS0001_HID
STATIC EFI_STATUS BmConnectUsbShortFormDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID InternalConnectAll(VOID)
STATIC EFI_DEVICE_PATH_PROTOCOL * BmExpandUsbDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN EFI_DEVICE_PATH_PROTOCOL *FullPath, IN EFI_DEVICE_PATH_PROTOCOL *ShortformNode)
STATIC EFI_DEVICE_PATH_PROTOCOL * BmExpandHyperVDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *FilePath)
STATIC EFI_DEVICE_PATH_PROTOCOL * BmExpandMediaDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN EFI_DEVICE_PATH_PROTOCOL *FullPath, IN EFI_HANDLE Handle)
STATIC BOOLEAN BmMatchPartitionDevicePathNode(IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath, IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath, IN BOOLEAN LocateEsp)
STATIC EFI_DEVICE_PATH_PROTOCOL * BmExpandPartitionDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *FilePath)
STATIC BOOLEAN BmMatchUsbClass(IN EFI_USB_IO_PROTOCOL *UsbIo, IN USB_CLASS_DEVICE_PATH *UsbClass)
STATIC EFI_HANDLE * BmFindUsbDevice(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN ParentDevicePathSize, OUT UINTN *UsbIoHandleCount)
STATIC BOOLEAN BmMatchUsbWwid(IN EFI_USB_IO_PROTOCOL *UsbIo, IN USB_WWID_DEVICE_PATH *UsbWwid)
#define ACPI_VMD0001_HID
STATIC EFI_DEVICE_PATH_PROTOCOL * BmExpandAppleSDCardDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *FilePath)
DMG_FILEPATH_DEVICE_PATH FilePath
DMG_SIZE_DEVICE_PATH Size
EFI_BOOT_SERVICES * gBS
VOID DebugPrintDevicePath(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL)
CONST EFI_PARTITION_ENTRY * OcGetGptPartitionEntry(IN EFI_HANDLE FsHandle)
Definition DiskMisc.c:732
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
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)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
EFI_GUID gEfiSimpleFileSystemProtocolGuid
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