OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcAppleBootPolicyLib.c
Go to the documentation of this file.
1
15#include <AppleMacEfi.h>
16#include <MicrosoftWindows.h>
17
18#include <Guid/AppleApfsInfo.h>
19#include <Guid/AppleBless.h>
20#include <Guid/FileInfo.h>
21
22#include <Protocol/SimpleFileSystem.h>
24
27#include <Library/OcFileLib.h>
28#include <Library/OcMiscLib.h>
29#include <Library/BaseLib.h>
30#include <Library/BaseMemoryLib.h>
32#include <Library/DevicePathLib.h>
33#include <Library/MemoryAllocationLib.h>
34#include <Library/PrintLib.h>
35#include <Library/UefiBootServicesTableLib.h>
36
43
44typedef struct {
45 EFI_HANDLE Handle;
47 EFI_FILE_PROTOCOL *Root;
49
74GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 *gAppleBootPolicyPredefinedPaths[] = {
77 EFI_REMOVABLE_MEDIA_FILE_NAME
78};
79
80GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN gAppleBootPolicyNumPredefinedPaths =
82
83GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN gAppleBootPolicyCoreNumPredefinedPaths = 2;
84
85EFI_STATUS
86EFIAPI
88 IN EFI_HANDLE Device,
89 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
90 );
91
92EFI_STATUS
93EFIAPI
95 IN EFI_HANDLE Device,
96 IN BOOT_POLICY_ACTION Action,
97 OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
98 );
99
100EFI_STATUS
101EFIAPI
103 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
104 OUT CHAR16 **BootPathName,
105 OUT EFI_HANDLE *Device,
106 OUT EFI_HANDLE *ApfsVolumeHandle
107 );
108
109EFI_STATUS
110EFIAPI
112 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
113 IN CONST CHAR16 *PathName,
114 OUT CHAR16 **FullPathName,
115 OUT VOID **Reserved,
116 OUT EFI_FILE_PROTOCOL **Root,
117 OUT EFI_HANDLE *DeviceHandle
118 );
119
120EFI_STATUS
121EFIAPI
123 IN EFI_HANDLE Handle OPTIONAL,
124 OUT VOID **Volumes,
125 OUT UINTN *NumberOfEntries
126 );
127
139
149STATIC
150EFI_STATUS
152 IN EFI_FILE_HANDLE Root,
153 IN CONST CHAR16 *FileName
154 )
155{
156 EFI_STATUS Status;
157 EFI_FILE_HANDLE FileHandle;
158
159 Status = OcSafeFileOpen (
160 Root,
161 &FileHandle,
162 FileName,
163 EFI_FILE_MODE_READ,
164 0
165 );
166
167 if (!EFI_ERROR (Status)) {
168 FileHandle->Close (FileHandle);
169 return EFI_SUCCESS;
170 }
171
172 return Status;
173}
174
175STATIC
176EFI_STATUS
178 IN EFI_FILE_PROTOCOL *Root,
179 IN OUT APPLE_APFS_VOLUME_INFO **VolumeInfo OPTIONAL,
180 IN OUT APPLE_APFS_CONTAINER_INFO **ContainerInfo OPTIONAL
181 )
182{
183 if ((ContainerInfo == NULL) && (VolumeInfo == NULL)) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 if (VolumeInfo != NULL) {
188 *VolumeInfo = OcGetFileInfo (
189 Root,
191 sizeof (**VolumeInfo),
192 NULL
193 );
194
195 if (*VolumeInfo == NULL) {
196 DEBUG ((DEBUG_VERBOSE, "OCBP: APFS Volume Info is missing\n"));
197 return EFI_NOT_FOUND;
198 }
199
200 DEBUG ((
202 "OCBP: APFS Volume Info - %p (%u, %g, %u)\n",
203 *VolumeInfo,
204 (*VolumeInfo)->Always1,
205 &(*VolumeInfo)->Uuid,
206 (*VolumeInfo)->Role
207 ));
208 }
209
210 if (ContainerInfo != NULL) {
211 *ContainerInfo = OcGetFileInfo (
212 Root,
214 sizeof (**ContainerInfo),
215 NULL
216 );
217
218 if (*ContainerInfo == NULL) {
219 DEBUG ((DEBUG_BULK_INFO, "OCBP: APFS Container Info is missing\n"));
220 if (VolumeInfo != NULL) {
221 FreePool (*VolumeInfo);
222 }
223
224 return EFI_NOT_FOUND;
225 }
226
227 DEBUG ((
229 "OCBP: APFS Container Info - %p (%u, %g)\n",
230 *ContainerInfo,
231 (*ContainerInfo)->Always1,
232 &(*ContainerInfo)->Uuid
233 ));
234 }
235
236 return EFI_SUCCESS;
237}
238
239STATIC
240EFI_STATUS
242 IN EFI_FILE_PROTOCOL *Root,
243 OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
244 )
245{
246 UINTN FilePathSize;
247
248 *FilePath = (EFI_DEVICE_PATH_PROTOCOL *)OcGetFileInfo (
249 Root,
251 sizeof (EFI_DEVICE_PATH_PROTOCOL),
252 &FilePathSize
253 );
254
255 if (*FilePath == NULL) {
256 DEBUG ((DEBUG_BULK_INFO, "OCBP: Blessed file is missing\n"));
257 return EFI_NOT_FOUND;
258 }
259
260 DebugPrintHexDump (DEBUG_BULK_INFO, "OCBP: BlessedFileHEX", (UINT8 *)*FilePath, FilePathSize);
261
262 if (!IsDevicePathValid (*FilePath, FilePathSize)) {
263 DEBUG ((DEBUG_BULK_INFO, "OCBP: Blessed file is invalid\n"));
264 FreePool (*FilePath);
265 *FilePath = NULL;
266 return EFI_NOT_FOUND;
267 }
268
269 DebugPrintDevicePath (DEBUG_BULK_INFO, "OCBP: BlessedFileDP", *FilePath);
270
271 DEBUG ((DEBUG_BULK_INFO, "OCBP: Blessed file is valid\n"));
272
273 return EFI_SUCCESS;
274}
275
276STATIC
277EFI_STATUS
279 IN EFI_HANDLE Device,
280 IN EFI_FILE_PROTOCOL *Root,
281 OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
282 )
283{
284 EFI_STATUS Status;
285
286 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
287 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
288 FILEPATH_DEVICE_PATH *FolderDevicePath;
289 UINTN DevicePathSize;
290 UINTN BooterDirPathSize;
291 UINTN BooterPathSize;
292 CHAR16 *BooterPath;
293
294 Status = EFI_NOT_FOUND;
295
296 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)OcGetFileInfo (
297 Root,
299 sizeof (EFI_DEVICE_PATH_PROTOCOL),
300 &DevicePathSize
301 );
302
303 if (DevicePath == NULL) {
304 DEBUG ((DEBUG_BULK_INFO, "OCBP: Blessed folder is missing\n"));
305 return Status;
306 }
307
308 DebugPrintHexDump (DEBUG_BULK_INFO, "OCBP: BlessedFolderHEX", (UINT8 *)DevicePath, DevicePathSize);
309
310 if (!IsDevicePathValid (DevicePath, DevicePathSize)) {
311 DEBUG ((DEBUG_BULK_INFO, "OCBP: Blessed folder is invalid\n"));
312 FreePool (DevicePath);
313 return EFI_NOT_FOUND;
314 }
315
316 DebugPrintDevicePath (DEBUG_BULK_INFO, "OCBP: BlessedFolderDP", DevicePath);
317
318 DevicePathWalker = DevicePath;
319
320 while (!IsDevicePathEnd (DevicePathWalker)) {
321 if ( (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH)
322 && (DevicePathSubType (DevicePathWalker) == MEDIA_FILEPATH_DP))
323 {
324 FolderDevicePath = (FILEPATH_DEVICE_PATH *)DevicePathWalker;
325 BooterDirPathSize = OcFileDevicePathNameSize (FolderDevicePath);
326 BooterPathSize = BooterDirPathSize + L_STR_SIZE (APPLE_BOOTER_ROOT_FILE_NAME) - sizeof (CHAR16);
327 BooterPath = AllocateZeroPool (BooterPathSize);
328
329 if (BooterPath != NULL) {
330 //
331 // FolderDevicePath->PathName may be unaligned, thus byte copying is needed.
332 //
333 CopyMem (BooterPath, FolderDevicePath->PathName, BooterDirPathSize);
334 StrCatS (BooterPath, BooterPathSize, APPLE_BOOTER_ROOT_FILE_NAME);
335 Status = EFI_SUCCESS;
336 } else {
337 Status = EFI_OUT_OF_RESOURCES;
338 }
339
340 break;
341 }
342
343 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
344 }
345
346 FreePool (DevicePath);
347
348 if (EFI_ERROR (Status)) {
349 DEBUG ((DEBUG_BULK_INFO, "OCBP: Blessed folder append failed - %r\n", Status));
350 return Status;
351 }
352
353 Status = InternalFileExists (Root, BooterPath);
354 if (EFI_ERROR (Status)) {
355 DEBUG ((DEBUG_BULK_INFO, "OCBP: Blessed folder %s is missing - %r\n", BooterPath, Status));
356 return EFI_NOT_FOUND;
357 }
358
359 *FilePath = FileDevicePath (Device, BooterPath);
360 return EFI_SUCCESS;
361}
362
363EFI_STATUS
365 IN EFI_HANDLE Device,
366 IN EFI_FILE_PROTOCOL *Root,
367 IN CONST CHAR16 **PredefinedPaths,
368 IN UINTN NumPredefinedPaths,
369 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL,
370 IN CHAR16 *Prefix OPTIONAL
371 )
372{
373 UINTN Index;
374 UINTN FullPathSize;
375 CHAR16 *FullPath;
376 CONST CHAR16 *PathName;
377 EFI_STATUS Status;
378
379 for (Index = 0; Index < NumPredefinedPaths; ++Index) {
380 PathName = PredefinedPaths[Index];
381
382 //
383 // For relative paths (i.e. when Prefix is a volume GUID) we must
384 // not use leading slash. This is what AppleBootPolicy does.
385 //
386 if (Prefix != NULL) {
387 ASSERT (PathName[0] == L'\\');
388 }
389
390 Status = InternalFileExists (
391 Root,
392 Prefix != NULL ? &PathName[1] : &PathName[0]
393 );
394 if (!EFI_ERROR (Status)) {
395 DEBUG ((
397 "OCBP: Predefined %s %s was found\n",
398 Prefix != NULL ? Prefix : L"<nil>",
400 ));
401 if (DevicePath != NULL) {
402 //
403 // Append volume directory prefix if any.
404 //
405 if (Prefix != NULL) {
406 ASSERT (Prefix[0] != L'\\');
407 FullPathSize = StrSize (Prefix) + StrSize (PathName);
408 FullPath = AllocatePool (FullPathSize);
409 if (FullPath != NULL) {
410 UnicodeSPrint (FullPath, FullPathSize, L"\\%s%s", Prefix, PathName);
411 *DevicePath = FileDevicePath (Device, FullPath);
412 FreePool (FullPath);
413 } else {
414 return EFI_OUT_OF_RESOURCES;
415 }
416 } else {
417 *DevicePath = FileDevicePath (Device, PathName);
418 }
419 }
420
421 ASSERT (DevicePath == NULL || *DevicePath != NULL);
422 return EFI_SUCCESS;
423 } else {
424 DEBUG ((
426 "OCBP: Predefined %s %s is missing - %r\n",
427 Prefix != NULL ? Prefix : L"<nil>",
428 PathName,
429 Status
430 ));
431 }
432 }
433
434 return EFI_NOT_FOUND;
435}
436
437STATIC
438EFI_STATUS
440 IN EFI_HANDLE Device,
441 OUT EFI_GUID *ContainerGuid,
442 OUT EFI_GUID *VolumeGuid,
443 OUT APPLE_APFS_VOLUME_ROLE *VolumeRole
444 )
445{
446 EFI_STATUS Status;
447
448 EFI_FILE_PROTOCOL *Root;
449 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
450 APPLE_APFS_CONTAINER_INFO *ApfsContainerInfo;
451 APPLE_APFS_VOLUME_INFO *ApfsVolumeInfo;
452
453 Root = NULL;
454
455 Status = gBS->HandleProtocol (
456 Device,
458 (VOID **)&FileSystem
459 );
460 if (EFI_ERROR (Status)) {
461 return Status;
462 }
463
464 Status = FileSystem->OpenVolume (FileSystem, &Root);
465 if (EFI_ERROR (Status)) {
466 return Status;
467 }
468
469 Status = InternalGetApfsSpecialFileInfo (Root, &ApfsVolumeInfo, &ApfsContainerInfo);
470
471 Root->Close (Root);
472
473 if (EFI_ERROR (Status)) {
474 return EFI_NOT_FOUND;
475 }
476
477 CopyGuid (
478 VolumeGuid,
479 &ApfsVolumeInfo->Uuid
480 );
481
482 *VolumeRole = ApfsVolumeInfo->Role;
483
484 CopyGuid (
485 ContainerGuid,
486 &ApfsContainerInfo->Uuid
487 );
488
489 FreePool (ApfsVolumeInfo);
490 FreePool (ApfsContainerInfo);
491
492 return EFI_SUCCESS;
493}
494
495STATIC
496EFI_STATUS
498 IN EFI_HANDLE Device,
499 IN EFI_FILE_PROTOCOL *PrebootRoot,
500 IN CHAR16 *VolumeDirectoryName,
501 IN CONST CHAR16 **PredefinedPaths,
502 IN UINTN NumPredefinedPaths,
503 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL
504 )
505{
506 EFI_STATUS Status;
507 EFI_FILE_PROTOCOL *VolumeDirectoryHandle;
508 EFI_FILE_INFO *VolumeDirectoryInfo;
509
510 Status = OcSafeFileOpen (
511 PrebootRoot,
512 &VolumeDirectoryHandle,
513 VolumeDirectoryName,
514 EFI_FILE_MODE_READ,
515 0
516 );
517
518 if (EFI_ERROR (Status)) {
519 DEBUG ((DEBUG_BULK_INFO, "OCBP: Missing partition %s on preboot - %r\n", VolumeDirectoryName, Status));
520 return Status;
521 } else {
522 DEBUG ((DEBUG_BULK_INFO, "OCBP: Found partition %s on preboot\n", VolumeDirectoryName));
523 }
524
525 VolumeDirectoryInfo = OcGetFileInfo (
526 VolumeDirectoryHandle,
528 sizeof (*VolumeDirectoryInfo),
529 NULL
530 );
531
532 if (VolumeDirectoryInfo == NULL) {
533 DEBUG ((DEBUG_BULK_INFO, "OCBP: Missing volume file info %s - %r\n", VolumeDirectoryName, Status));
534 VolumeDirectoryHandle->Close (VolumeDirectoryHandle);
535 return EFI_NOT_FOUND;
536 }
537
538 Status = EFI_NOT_FOUND;
539
540 DEBUG ((
542 "OCBP: Want predefined list for APFS %u at %s\n",
543 VolumeDirectoryInfo->Attribute,
544 VolumeDirectoryName
545 ));
546
547 if ((VolumeDirectoryInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
549 Device,
550 VolumeDirectoryHandle,
551 PredefinedPaths,
552 NumPredefinedPaths,
553 DevicePath,
554 VolumeDirectoryName
555 );
556 }
557
558 FreePool (VolumeDirectoryInfo);
559 VolumeDirectoryHandle->Close (VolumeDirectoryHandle);
560
561 return Status;
562}
563
570STATIC
571EFI_STATUS
573 IN EFI_HANDLE Device,
574 IN EFI_FILE_PROTOCOL *PrebootRoot,
575 IN CONST GUID *ContainerUuid,
576 IN CONST CHAR16 *VolumeUuid OPTIONAL,
577 IN CONST CHAR16 **PredefinedPaths,
578 IN UINTN NumPredefinedPaths,
579 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL,
580 OUT EFI_HANDLE *VolumeHandle OPTIONAL
581 )
582{
583 EFI_STATUS Status;
584 EFI_STATUS TmpStatus;
585
586 UINTN NumberOfHandles;
587 EFI_HANDLE *HandleBuffer;
588 UINTN Index;
589 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
590 EFI_FILE_PROTOCOL *HandleRoot;
591 APPLE_APFS_CONTAINER_INFO *ContainerInfo;
592 APPLE_APFS_VOLUME_INFO *VolumeInfo;
593 CHAR16 VolumeDirectoryName[GUID_STRING_LENGTH+1];
594 EFI_DEVICE_PATH_PROTOCOL *VolumeDevPath;
595 EFI_DEVICE_PATH_PROTOCOL *TempDevPath;
596 BOOLEAN ContainerMatch;
597
598 ASSERT (VolumeUuid == NULL || (VolumeUuid != NULL && VolumeHandle != NULL && *VolumeHandle == NULL));
599
600 NumberOfHandles = 0;
601 Status = gBS->LocateHandleBuffer (
602 ByProtocol,
604 NULL,
605 &NumberOfHandles,
606 &HandleBuffer
607 );
608
609 DEBUG ((DEBUG_BULK_INFO, "OCBP: %u filesystems for APFS - %r\n", (UINT32)NumberOfHandles, Status));
610
611 if (EFI_ERROR (Status)) {
612 return Status;
613 }
614
615 Status = EFI_NOT_FOUND;
616
617 for (Index = 0; Index < NumberOfHandles; ++Index) {
618 TmpStatus = gBS->HandleProtocol (
619 HandleBuffer[Index],
621 (VOID **)&FileSystem
622 );
623 if (EFI_ERROR (TmpStatus)) {
624 DEBUG ((
626 "OCBP: Borked APFS filesystem %u of %u - %r\n",
627 (UINT32)(Index + 1),
628 (UINT32)NumberOfHandles,
629 TmpStatus
630 ));
631 continue;
632 }
633
634 TmpStatus = FileSystem->OpenVolume (FileSystem, &HandleRoot);
635 if (EFI_ERROR (TmpStatus)) {
636 DEBUG ((
638 "OCBP: Borked APFS root volume %u of %u - %r\n",
639 (UINT32)(Index + 1),
640 (UINT32)NumberOfHandles,
641 TmpStatus
642 ));
643 continue;
644 }
645
646 TmpStatus = InternalGetApfsSpecialFileInfo (HandleRoot, &VolumeInfo, &ContainerInfo);
647
648 HandleRoot->Close (HandleRoot);
649
650 if (EFI_ERROR (TmpStatus)) {
651 DEBUG ((
652 DEBUG_VERBOSE,
653 "OCBP: No APFS info %u of %u - %r\n",
654 (UINT32)(Index + 1),
655 (UINT32)NumberOfHandles,
656 TmpStatus
657 ));
658 continue;
659 }
660
661 ContainerMatch = CompareGuid (&ContainerInfo->Uuid, ContainerUuid);
662
663 DEBUG ((
665 "OCBP: APFS match container %g vs %g for %u of %u - %d\n",
666 &ContainerInfo->Uuid,
667 ContainerUuid,
668 (UINT32)(Index + 1),
669 (UINT32)NumberOfHandles,
670 ContainerMatch
671 ));
672
673 if (!ContainerMatch) {
674 FreePool (ContainerInfo);
675 FreePool (VolumeInfo);
676 continue;
677 }
678
679 UnicodeSPrint (
680 VolumeDirectoryName,
681 sizeof (VolumeDirectoryName),
682 L"%g",
683 &VolumeInfo->Uuid
684 );
685
686 FreePool (ContainerInfo);
687 FreePool (VolumeInfo);
688
689 if ((VolumeUuid != NULL) && (StrStr (VolumeUuid, VolumeDirectoryName) != NULL)) {
690 *VolumeHandle = HandleBuffer[Index];
691 }
692
694 Device,
695 PrebootRoot,
696 VolumeDirectoryName,
697 PredefinedPaths,
698 NumPredefinedPaths,
699 DevicePath != NULL ? &VolumeDevPath : NULL
700 );
701
702 if (EFI_ERROR (TmpStatus)) {
703 DEBUG ((
705 "OCBP: No APFS booter %u of %u for %s - %r\n",
706 (UINT32)(Index + 1),
707 (UINT32)NumberOfHandles,
708 VolumeDirectoryName,
709 TmpStatus
710 ));
711 } else {
712 Status = EFI_SUCCESS;
713
714 DEBUG ((
716 "OCBP: Found APFS booter %u of %u for %s (%p)\n",
717 (UINT32)(Index + 1),
718 (UINT32)NumberOfHandles,
719 VolumeDirectoryName,
720 DevicePath
721 ));
722
723 if (DevicePath != NULL) {
724 TempDevPath = *DevicePath;
726 TempDevPath,
727 VolumeDevPath
728 );
729 if (TempDevPath != NULL) {
730 FreePool (TempDevPath);
731 }
732 }
733 }
734 }
735
736 FreePool (HandleBuffer);
737
738 DEBUG ((
740 "OCBP: APFS bless for %g:%s is %r\n",
741 ContainerUuid,
742 VolumeUuid,
743 Status
744 ));
745
746 return Status;
747}
748
749STATIC
750EFI_STATUS
752 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
753 OUT CHAR16 **BootPathName,
754 IN BOOLEAN DirectoryOnly
755 )
756{
757 CHAR16 *PathName;
758 UINTN PathNameSize;
759 CHAR16 *Slash;
760 UINTN Len;
761 CHAR16 *FilePathName;
762
763 if ( (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH)
764 && (DevicePathSubType (DevicePath) == MEDIA_FILEPATH_DP))
765 {
766 PathNameSize = OcFileDevicePathFullNameSize (DevicePath);
767
768 PathName = AllocatePool (PathNameSize);
769 if (PathName == NULL) {
770 return EFI_OUT_OF_RESOURCES;
771 }
772
774 PathName,
775 (FILEPATH_DEVICE_PATH *)DevicePath,
776 PathNameSize
777 );
778
779 if (DirectoryOnly) {
780 Slash = StrStr (PathName, L"\\");
781
782 if (Slash != NULL) {
783 Len = StrLen (PathName);
784
785 FilePathName = &PathName[Len - 1];
786
787 while (*FilePathName != L'\\') {
788 *FilePathName = L'\0';
789 --FilePathName;
790 }
791 } else {
792 StrCpyS (PathName, PathNameSize, L"\\");
793 }
794 }
795 } else {
796 PathName = AllocateZeroPool (sizeof (L"\\"));
797
798 if (PathName == NULL) {
799 return EFI_OUT_OF_RESOURCES;
800 }
801
802 StrCpyS (PathName, sizeof (L"\\"), L"\\");
803 }
804
805 *BootPathName = PathName;
806 return EFI_SUCCESS;
807}
808
809STATIC
810EFI_STATUS
812 IN EFI_HANDLE DeviceHandle,
813 IN CHAR16 *PathName,
814 IN CONST CHAR16 **PredefinedPaths,
815 IN UINTN NumPredefinedPaths,
816 OUT EFI_HANDLE *ApfsVolumeHandle
817 )
818{
819 EFI_STATUS Status;
820
821 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
822 EFI_FILE_PROTOCOL *Root;
823 APPLE_APFS_CONTAINER_INFO *ContainerInfo;
824 CHAR16 *FilePathName;
825
826 FilePathName = &PathName[0];
827
828 if (PathName[0] == L'\\') {
829 FilePathName = &PathName[1];
830 }
831
832 if (!HasValidGuidStringPrefix (FilePathName)) {
833 return EFI_INVALID_PARAMETER;
834 }
835
836 Status = gBS->HandleProtocol (
837 DeviceHandle,
839 (VOID **)&FileSystem
840 );
841
842 if (EFI_ERROR (Status)) {
843 return Status;
844 }
845
846 Status = FileSystem->OpenVolume (FileSystem, &Root);
847 if (EFI_ERROR (Status)) {
848 return Status;
849 }
850
851 Status = InternalGetApfsSpecialFileInfo (Root, NULL, &ContainerInfo);
852 if (!EFI_ERROR (Status)) {
853 //
854 // FIXME: ApfsVolumeHandle is only returned when a predefined path exists
855 //
857 DeviceHandle,
858 Root,
859 &ContainerInfo->Uuid,
860 FilePathName,
861 PredefinedPaths,
862 NumPredefinedPaths,
863 NULL,
864 ApfsVolumeHandle
865 );
866
867 FreePool (ContainerInfo);
868 }
869
870 Root->Close (Root);
871
872 return Status;
873}
874
875EFI_STATUS
877 IN EFI_HANDLE Device,
878 IN CONST CHAR16 **PredefinedPaths,
879 IN UINTN NumPredefinedPaths,
880 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
881 )
882{
883 EFI_STATUS Status;
884
885 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
886 EFI_FILE_PROTOCOL *Root;
887
888 ASSERT (Device != NULL);
889 ASSERT (FilePath != NULL);
890
891 *FilePath = NULL;
892 Root = NULL;
893
894 Status = gBS->HandleProtocol (
895 Device,
897 (VOID **)&FileSystem
898 );
899
900 if (EFI_ERROR (Status)) {
901 return Status;
902 }
903
904 Status = FileSystem->OpenVolume (FileSystem, &Root);
905
906 if (EFI_ERROR (Status)) {
907 return Status;
908 }
909
911 if (EFI_ERROR (Status)) {
913 if (EFI_ERROR (Status)) {
915 Device,
916 Root,
917 PredefinedPaths,
918 NumPredefinedPaths,
919 FilePath,
920 NULL
921 );
922 }
923 }
924
925 Root->Close (Root);
926
927 return Status;
928}
929
930EFI_STATUS
931EFIAPI
933 IN EFI_HANDLE Device,
934 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
935 )
936{
937 if ((Device == NULL) || (FilePath == NULL)) {
938 return EFI_INVALID_PARAMETER;
939 }
940
942 Device,
946 );
947}
948
949EFI_STATUS
951 IN EFI_HANDLE Device,
952 IN CONST CHAR16 **PredefinedPaths,
953 IN UINTN NumPredefinedPaths,
954 OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
955 )
956{
957 EFI_STATUS Status;
958 EFI_STATUS TmpStatus;
959
960 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
961 EFI_FILE_PROTOCOL *Root;
962 APPLE_APFS_CONTAINER_INFO *ContainerInfo;
963 APPLE_APFS_VOLUME_INFO *VolumeInfo;
964
965 ASSERT (Device != NULL);
966 ASSERT (FilePath != NULL);
967
968 *FilePath = NULL;
969 Root = NULL;
970
971 Status = gBS->HandleProtocol (
972 Device,
974 (VOID **)&FileSystem
975 );
976 if (EFI_ERROR (Status)) {
977 DEBUG ((DEBUG_BULK_INFO, "OCBP: Missing filesystem - %r\n", Status));
978 return Status;
979 }
980
981 Status = FileSystem->OpenVolume (FileSystem, &Root);
982 if (EFI_ERROR (Status)) {
983 DEBUG ((DEBUG_BULK_INFO, "OCBP: Invalid root volume - %r\n", Status));
984 return Status;
985 }
986
987 Status = InternalGetApfsSpecialFileInfo (Root, &VolumeInfo, &ContainerInfo);
988 if (!EFI_ERROR (Status)) {
989 Status = EFI_NOT_FOUND;
990 if ((VolumeInfo->Role & APPLE_APFS_VOLUME_ROLE_PREBOOT) != 0) {
992 if (EFI_ERROR (TmpStatus)) {
993 TmpStatus = InternalGetBooterFromBlessedSystemFolderPath (Device, Root, FilePath);
994 }
995
996 //
997 // Blessed entry is always first, and subsequent entries are added with deduplication.
998 //
1000 Device,
1001 Root,
1002 &ContainerInfo->Uuid,
1003 NULL,
1004 PredefinedPaths,
1005 NumPredefinedPaths,
1006 FilePath,
1007 NULL
1008 );
1009 if (!EFI_ERROR (TmpStatus)) {
1010 Status = TmpStatus;
1011 }
1012 }
1013
1014 FreePool (VolumeInfo);
1015 FreePool (ContainerInfo);
1016 } else {
1018 if (EFI_ERROR (Status)) {
1020 if (EFI_ERROR (Status)) {
1022 Device,
1023 Root,
1024 PredefinedPaths,
1025 NumPredefinedPaths,
1026 FilePath,
1027 NULL
1028 );
1029 }
1030 }
1031 }
1032
1033 Root->Close (Root);
1034
1035 return Status;
1036}
1037
1038EFI_STATUS
1039EFIAPI
1041 IN EFI_HANDLE Device,
1042 IN BOOT_POLICY_ACTION Action,
1043 OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
1044 )
1045{
1046 if ((Device == NULL) || (FilePath == NULL)) {
1047 return EFI_INVALID_PARAMETER;
1048 }
1049
1051 Device,
1054 FilePath
1055 );
1056}
1057
1058EFI_STATUS
1060 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1061 OUT CHAR16 **BootPathName,
1062 OUT EFI_HANDLE *Device,
1063 IN BOOLEAN DirectoryOnly
1064 )
1065{
1066 EFI_STATUS Status;
1067
1068 ASSERT (DevicePath != NULL);
1069 ASSERT (BootPathName != NULL);
1070 ASSERT (Device != NULL);
1071
1072 *BootPathName = NULL;
1073 *Device = NULL;
1074
1075 Status = gBS->LocateDevicePath (
1077 &DevicePath,
1078 Device
1079 );
1080 if (EFI_ERROR (Status)) {
1081 return Status;
1082 }
1083
1084 return InternalGetBootPathName (DevicePath, BootPathName, DirectoryOnly);
1085}
1086
1087EFI_STATUS
1089 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1090 OUT CHAR16 **BootPathName,
1091 OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **FileSystem
1092 )
1093{
1094 EFI_STATUS Status;
1095 EFI_HANDLE Device;
1096
1097 ASSERT (DevicePath != NULL);
1098 ASSERT (BootPathName != NULL);
1099 ASSERT (FileSystem != NULL);
1100
1102 DevicePath,
1103 BootPathName,
1104 &Device,
1105 TRUE
1106 );
1107
1108 if (EFI_ERROR (Status)) {
1109 return Status;
1110 }
1111
1112 Status = gBS->HandleProtocol (
1113 Device,
1115 (VOID **)FileSystem
1116 );
1117
1118 if (EFI_ERROR (Status)) {
1119 FreePool (BootPathName);
1120 BootPathName = NULL;
1121 }
1122
1123 return Status;
1124}
1125
1126EFI_STATUS
1128 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1129 OUT CHAR16 **BootPathName
1130 )
1131{
1132 EFI_HANDLE Device;
1133
1134 ASSERT (DevicePath != NULL);
1135 ASSERT (BootPathName != NULL);
1136
1138 DevicePath,
1139 BootPathName,
1140 &Device,
1141 FALSE
1142 );
1143}
1144
1145STATIC
1146EFI_STATUS
1148 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1149 IN CONST CHAR16 **PredefinedPaths,
1150 IN UINTN NumPredefinedPaths,
1151 OUT CHAR16 **BootPathName,
1152 OUT EFI_HANDLE *Device,
1153 OUT EFI_HANDLE *ApfsVolumeHandle
1154 )
1155{
1156 EFI_STATUS Status;
1157
1158 ASSERT (DevicePath != NULL);
1159 ASSERT (BootPathName != NULL);
1160 ASSERT (Device != NULL);
1161 ASSERT (ApfsVolumeHandle != NULL);
1162
1164 DevicePath,
1165 BootPathName,
1166 Device,
1167 TRUE
1168 );
1169 if (EFI_ERROR (Status)) {
1170 return Status;
1171 }
1172
1173 //
1174 // InternalGetApfsVolumeHandle status code is ignored, as ApfsVolumeHandle
1175 // may not exist.
1176 //
1177 *ApfsVolumeHandle = NULL;
1179 *Device,
1180 *BootPathName,
1181 PredefinedPaths,
1182 NumPredefinedPaths,
1183 ApfsVolumeHandle
1184 );
1185
1186 return EFI_SUCCESS;
1187}
1188
1189EFI_STATUS
1190EFIAPI
1192 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1193 OUT CHAR16 **BootPathName,
1194 OUT EFI_HANDLE *Device,
1195 OUT EFI_HANDLE *ApfsVolumeHandle
1196 )
1197{
1198 EFI_STATUS Status;
1199
1200 if ( (DevicePath == NULL)
1201 || (BootPathName == NULL)
1202 || (Device == NULL)
1203 || (ApfsVolumeHandle == NULL))
1204 {
1205 return EFI_INVALID_PARAMETER;
1206 }
1207
1209 DevicePath,
1212 BootPathName,
1213 Device,
1214 ApfsVolumeHandle
1215 );
1216 if (EFI_ERROR (Status)) {
1217 *BootPathName = NULL;
1218 *Device = NULL;
1219 *ApfsVolumeHandle = NULL;
1220 return Status;
1221 }
1222
1223 return EFI_SUCCESS;
1224}
1225
1226EFI_STATUS
1228 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1229 IN CONST CHAR16 *PathName,
1230 IN CONST CHAR16 **PredefinedPaths,
1231 IN UINTN NumPredefinedPaths,
1232 OUT CHAR16 **FullPathName,
1233 OUT EFI_FILE_PROTOCOL **Root,
1234 OUT EFI_HANDLE *DeviceHandle
1235 )
1236{
1237 EFI_STATUS Result;
1238
1239 EFI_STATUS Status;
1240
1241 CHAR16 *BootPathName;
1242 EFI_HANDLE Device;
1243 EFI_HANDLE VolumeHandle;
1244
1245 GUID ContainerGuid;
1246 GUID VolumeGuid;
1247 APPLE_APFS_VOLUME_ROLE VolumeRole;
1248
1249 GUID ContainerGuid2;
1250 GUID VolumeGuid2;
1251 APPLE_APFS_VOLUME_ROLE VolumeRole2;
1252
1253 UINTN NoHandles;
1254 EFI_HANDLE *HandleBuffer;
1255 UINTN Index;
1256
1257 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
1258
1259 CHAR16 *FullPathBuffer;
1260 UINTN FullPathNameSize;
1261
1262 EFI_FILE_PROTOCOL *NewHandle;
1263
1264 EFI_FILE_INFO *FileInfo;
1265
1266 ASSERT (DevicePath != NULL);
1267 ASSERT (PathName != NULL);
1268 ASSERT (FullPathName != NULL);
1269 ASSERT (Root != NULL);
1270 ASSERT (DeviceHandle != NULL);
1271
1272 NewHandle = NULL;
1273 *Root = NULL;
1274 *FullPathName = NULL;
1275
1277 DevicePath,
1278 PredefinedPaths,
1279 NumPredefinedPaths,
1280 &BootPathName,
1281 &Device,
1282 &VolumeHandle
1283 );
1284
1285 if (EFI_ERROR (Status)) {
1286 DEBUG ((DEBUG_BULK_INFO, "OCBP: APFS recovery boot info failed - %r\n", Status));
1287 return EFI_NOT_FOUND;
1288 }
1289
1290 if (VolumeHandle == NULL) {
1291 DEBUG ((DEBUG_BULK_INFO, "OCBP: APFS recovery volume handle missing - %s\n", BootPathName));
1292 FreePool (BootPathName);
1293 return EFI_NOT_FOUND;
1294 }
1295
1296 FreePool (BootPathName);
1297
1298 Status = InternalGetApfsVolumeInfo (
1299 VolumeHandle,
1300 &ContainerGuid,
1301 &VolumeGuid,
1302 &VolumeRole
1303 );
1304
1305 if (EFI_ERROR (Status)) {
1306 DEBUG ((DEBUG_BULK_INFO, "OCBP: APFS recovery volume info missing\n"));
1307 return EFI_NOT_FOUND;
1308 }
1309
1310 Status = gBS->LocateHandleBuffer (
1311 ByProtocol,
1313 NULL,
1314 &NoHandles,
1315 &HandleBuffer
1316 );
1317
1318 if (EFI_ERROR (Status)) {
1319 DEBUG ((DEBUG_BULK_INFO, "OCBP: APFS recovery simple fs missing - %r\n", Status));
1320 return Status;
1321 }
1322
1323 Result = EFI_NOT_FOUND;
1324
1325 for (Index = 0; Index < NoHandles; ++Index) {
1326 ZeroMem (&ContainerGuid2, sizeof (ContainerGuid2));
1327 ZeroMem (&VolumeGuid2, sizeof (VolumeGuid2));
1328 VolumeRole2 = 0;
1329
1330 Status = InternalGetApfsVolumeInfo (
1331 HandleBuffer[Index],
1332 &ContainerGuid2,
1333 &VolumeGuid2,
1334 &VolumeRole2
1335 );
1336
1337 DEBUG ((
1339 "OCBP: APFS recovery info %u/%u due to %g/%g/%X - %r\n",
1340 (UINT32)Index,
1341 (UINT32)NoHandles,
1342 &ContainerGuid2,
1343 &ContainerGuid,
1344 (UINT32)VolumeRole2,
1345 Status
1346 ));
1347
1348 if ( EFI_ERROR (Status)
1349 || (VolumeRole2 != APPLE_APFS_VOLUME_ROLE_RECOVERY)
1350 || !CompareGuid (&ContainerGuid2, &ContainerGuid))
1351 {
1352 continue;
1353 }
1354
1355 Status = gBS->HandleProtocol (
1356 HandleBuffer[Index],
1358 (VOID **)&FileSystem
1359 );
1360 if (EFI_ERROR (Status)) {
1361 continue;
1362 }
1363
1364 Status = FileSystem->OpenVolume (FileSystem, Root);
1365 if (EFI_ERROR (Status)) {
1366 continue;
1367 }
1368
1369 FullPathNameSize = sizeof (CHAR16) + StrSize (PathName);
1370 FullPathNameSize += GUID_STRING_LENGTH * sizeof (CHAR16);
1371 FullPathBuffer = AllocateZeroPool (FullPathNameSize);
1372
1373 if (FullPathBuffer == NULL) {
1374 (*Root)->Close (*Root);
1375 continue;
1376 }
1377
1378 //
1379 // Note, this \\ prefixing does not exist in Apple code, and should not be required,
1380 // but we add it for return path consistency.
1381 //
1382 UnicodeSPrint (
1383 FullPathBuffer,
1384 FullPathNameSize,
1385 L"\\%g%s",
1386 &VolumeGuid,
1387 PathName
1388 );
1389
1390 Status = OcSafeFileOpen (
1391 *Root,
1392 &NewHandle,
1393 FullPathBuffer,
1394 EFI_FILE_MODE_READ,
1395 0
1396 );
1397
1398 if (EFI_ERROR (Status)) {
1399 (*Root)->Close (*Root);
1400 FreePool (FullPathBuffer);
1401 continue;
1402 }
1403
1404 FileInfo = OcGetFileInfo (
1405 NewHandle,
1407 sizeof (*FileInfo),
1408 NULL
1409 );
1410
1411 if (FileInfo != NULL) {
1412 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
1413 *FullPathName = FullPathBuffer;
1414 *DeviceHandle = HandleBuffer[Index];
1415 Result = EFI_SUCCESS;
1416 }
1417
1418 FreePool (FileInfo);
1419 }
1420
1421 NewHandle->Close (NewHandle);
1422
1423 if (!EFI_ERROR (Result)) {
1424 break;
1425 }
1426
1427 (*Root)->Close (*Root);
1428 FreePool (FullPathBuffer);
1429 }
1430
1431 FreePool (HandleBuffer);
1432
1433 return Result;
1434}
1435
1436EFI_STATUS
1437EFIAPI
1439 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1440 IN CONST CHAR16 *PathName,
1441 OUT CHAR16 **FullPathName,
1442 OUT VOID **Reserved,
1443 OUT EFI_FILE_PROTOCOL **Root,
1444 OUT EFI_HANDLE *DeviceHandle
1445 )
1446{
1447 if ( (DevicePath == NULL)
1448 || (PathName == NULL)
1449 || (FullPathName == NULL)
1450 || (Reserved == NULL)
1451 || (Root == NULL)
1452 || (DeviceHandle == NULL))
1453 {
1454 return EFI_INVALID_PARAMETER;
1455 }
1456
1457 *Reserved = NULL;
1458
1460 DevicePath,
1461 PathName,
1464 FullPathName,
1465 Root,
1466 DeviceHandle
1467 );
1468}
1469
1470EFI_STATUS
1472 IN EFI_HANDLE Handle OPTIONAL,
1473 OUT VOID **Volumes,
1474 OUT UINTN *NumberOfEntries
1475 )
1476{
1477 EFI_STATUS Status;
1478
1479 UINTN NumberOfHandles;
1480 EFI_HANDLE *HandleBuffer;
1481 APFS_VOLUME_INFO *VolumeInfo;
1482 GUID *ContainerGuids;
1483 UINTN NumberOfContainers;
1484 UINTN NumberOfVolumeInfos;
1485 UINTN Index;
1486 UINTN Index2;
1487 UINTN Index3;
1488 APFS_VOLUME_ROOT **ApfsVolumes;
1489 BOOLEAN GuidPresent;
1490 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
1491 EFI_FILE_PROTOCOL *Root;
1492 EFI_FILE_PROTOCOL *NewHandle;
1493 CHAR16 VolumePathName[GUID_STRING_LENGTH + 1];
1494 EFI_FILE_INFO *FileInfo;
1495 APFS_VOLUME_ROOT *ApfsRoot;
1496
1497 ASSERT (Volumes != NULL);
1498 ASSERT (NumberOfEntries != NULL);
1499
1500 Status = gBS->LocateHandleBuffer (
1501 ByProtocol,
1503 NULL,
1504 &NumberOfHandles,
1505 &HandleBuffer
1506 );
1507
1508 if (EFI_ERROR (Status)) {
1509 return Status;
1510 }
1511
1512 VolumeInfo = AllocateZeroPool (NumberOfHandles * sizeof (*VolumeInfo));
1513 ContainerGuids = AllocateZeroPool (NumberOfHandles * sizeof (*ContainerGuids));
1514
1515 if ((VolumeInfo == NULL) || (ContainerGuids == NULL)) {
1516 Status = EFI_OUT_OF_RESOURCES;
1517 }
1518
1519 if (EFI_ERROR (Status)) {
1520 FreePool (HandleBuffer);
1521
1522 if (VolumeInfo != NULL) {
1523 FreePool (VolumeInfo);
1524 }
1525
1526 if (ContainerGuids != NULL) {
1527 FreePool (ContainerGuids);
1528 }
1529
1530 return Status;
1531 }
1532
1533 NumberOfVolumeInfos = 0;
1534 NumberOfContainers = 0;
1535
1536 for (Index = 0; Index < NumberOfHandles; ++Index) {
1537 Status = InternalGetApfsVolumeInfo (
1538 HandleBuffer[Index],
1539 &VolumeInfo[NumberOfVolumeInfos].ContainerGuid,
1540 &VolumeInfo[NumberOfVolumeInfos].VolumeGuid,
1541 &VolumeInfo[NumberOfVolumeInfos].VolumeRole
1542 );
1543
1544 if (EFI_ERROR (Status)) {
1545 continue;
1546 }
1547
1548 VolumeInfo[NumberOfVolumeInfos].Handle = HandleBuffer[Index];
1549
1550 GuidPresent = FALSE;
1551 for (Index2 = 0; Index2 < NumberOfContainers; ++Index2) {
1552 if (CompareGuid (&ContainerGuids[Index2], &VolumeInfo[NumberOfVolumeInfos].ContainerGuid)) {
1553 GuidPresent = TRUE;
1554 break;
1555 }
1556 }
1557
1558 if (!GuidPresent) {
1559 CopyGuid (
1560 &ContainerGuids[NumberOfContainers],
1561 &VolumeInfo[NumberOfVolumeInfos].ContainerGuid
1562 );
1563
1564 if ((Index2 != 0) && (HandleBuffer[Index] == Handle)) {
1565 CopyMem (
1566 &ContainerGuids[1],
1567 &ContainerGuids[0],
1568 NumberOfContainers * sizeof (ContainerGuids[0])
1569 );
1570 CopyGuid (
1571 &ContainerGuids[0],
1572 &VolumeInfo[NumberOfVolumeInfos].ContainerGuid
1573 );
1574 }
1575
1576 ++NumberOfContainers;
1577 }
1578
1579 ++NumberOfVolumeInfos;
1580 }
1581
1582 Status = EFI_SUCCESS;
1583
1584 if (NumberOfVolumeInfos > 0) {
1585 ApfsVolumes = AllocateZeroPool (
1586 NumberOfVolumeInfos * sizeof (*ApfsVolumes)
1587 );
1588 if (ApfsVolumes == NULL) {
1589 Status = EFI_OUT_OF_RESOURCES;
1590 }
1591 } else {
1592 Status = EFI_NOT_FOUND;
1593 }
1594
1595 if (EFI_ERROR (Status)) {
1596 FreePool (HandleBuffer);
1597 FreePool (VolumeInfo);
1598 FreePool (ContainerGuids);
1599 return Status;
1600 }
1601
1602 *Volumes = ApfsVolumes;
1603 *NumberOfEntries = 0;
1604
1605 for (Index = 0; Index < NumberOfContainers; ++Index) {
1606 for (Index2 = 0; Index2 < NumberOfVolumeInfos; ++Index2) {
1607 if ( ((VolumeInfo[Index2].VolumeRole & APPLE_APFS_VOLUME_ROLE_RECOVERY) == 0)
1608 || !CompareGuid (&ContainerGuids[Index], &VolumeInfo[Index2].ContainerGuid))
1609 {
1610 continue;
1611 }
1612
1613 Status = gBS->HandleProtocol (
1614 VolumeInfo[Index2].Handle,
1616 (VOID **)&FileSystem
1617 );
1618 if (EFI_ERROR (Status)) {
1619 continue;
1620 }
1621
1622 Status = FileSystem->OpenVolume (FileSystem, &Root);
1623 if (EFI_ERROR (Status)) {
1624 continue;
1625 }
1626
1627 //
1628 // Locate recovery for every volume present.
1629 //
1630 for (Index3 = 0; Index3 < NumberOfVolumeInfos; ++Index3) {
1631 if ( ((VolumeInfo[Index2].VolumeRole &
1633 || !CompareGuid (&ContainerGuids[Index], &VolumeInfo[Index3].ContainerGuid))
1634 {
1635 continue;
1636 }
1637
1638 UnicodeSPrint (
1639 VolumePathName,
1640 sizeof (VolumePathName),
1641 L"%g",
1642 &VolumeInfo[Index3].VolumeGuid
1643 );
1644
1645 Status = OcSafeFileOpen (
1646 Root,
1647 &NewHandle,
1648 VolumePathName,
1649 EFI_FILE_MODE_READ,
1650 0
1651 );
1652
1653 if (EFI_ERROR (Status)) {
1654 continue;
1655 }
1656
1657 FileInfo = OcGetFileInfo (
1658 NewHandle,
1660 sizeof (*FileInfo),
1661 NULL
1662 );
1663
1664 NewHandle->Close (NewHandle);
1665
1666 if (FileInfo != NULL) {
1667 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
1668 ApfsRoot = ApfsVolumes[*NumberOfEntries];
1669 ApfsRoot->Handle = VolumeInfo[Index2].Handle;
1670 ApfsRoot->VolumeDirName = AllocateCopyPool (
1671 StrSize (VolumePathName),
1672 VolumePathName
1673 );
1674 ApfsRoot->Root = Root;
1675
1676 ++(*NumberOfEntries);
1677 }
1678
1679 FreePool (FileInfo);
1680 }
1681 }
1682 }
1683 }
1684
1685 FreePool (VolumeInfo);
1686 FreePool (ContainerGuids);
1687 FreePool (HandleBuffer);
1688
1689 if (!EFI_ERROR (Status) && (*NumberOfEntries == 0)) {
1690 Status = EFI_NOT_FOUND;
1691 }
1692
1693 return Status;
1694}
1695
1696EFI_STATUS
1697EFIAPI
1699 IN EFI_HANDLE Handle OPTIONAL,
1700 OUT VOID **Volumes,
1701 OUT UINTN *NumberOfEntries
1702 )
1703{
1704 if ((Volumes == NULL) || (NumberOfEntries == NULL)) {
1705 return EFI_INVALID_PARAMETER;
1706 }
1707
1709 Handle,
1710 Volumes,
1711 NumberOfEntries
1712 );
1713}
1714
1717 IN BOOLEAN Reinstall
1718 )
1719{
1720 EFI_STATUS Status;
1721
1723 EFI_HANDLE Handle;
1724
1725 if (Reinstall) {
1727 if (EFI_ERROR (Status)) {
1728 DEBUG ((DEBUG_ERROR, "OCBP: Uninstall failed - %r\n", Status));
1729 return NULL;
1730 }
1731 } else {
1732 Status = gBS->LocateProtocol (
1734 NULL,
1735 (VOID *)&Protocol
1736 );
1737
1738 if (!EFI_ERROR (Status)) {
1739 return Protocol;
1740 }
1741 }
1742
1743 Handle = NULL;
1744 Status = gBS->InstallMultipleProtocolInterfaces (
1745 &Handle,
1747 (VOID **)&mAppleBootPolicyProtocol,
1748 NULL
1749 );
1750
1751 if (EFI_ERROR (Status)) {
1752 return NULL;
1753 }
1754
1756}
UINT8 Reserved[430]
Definition Apm.h:39
#define APPLE_APFS_VOLUME_ROLE_RECOVERY
UINT32 APPLE_APFS_VOLUME_ROLE
EFI_GUID gAppleApfsVolumeInfoGuid
EFI_GUID gAppleApfsContainerInfoGuid
#define APPLE_APFS_VOLUME_ROLE_PREBOOT
EFI_GUID gAppleBlessedSystemFileInfoGuid
A global variable storing the GUID of the APPLE_BLESSED_SYSTEM_FILE_INFO_GUID.
EFI_GUID gAppleBlessedSystemFolderInfoGuid
A global variable storing the GUID of the APPLE_BLESSED_SYSTEM_FOLDER_INFO_GUID.
BOOT_POLICY_ACTION
#define APPLE_BOOT_POLICY_PROTOCOL_REVISION
EFI_GUID gAppleBootPolicyProtocolGuid
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
#define APPLE_BOOTER_ROOT_FILE_NAME
#define APPLE_BOOTER_DEFAULT_FILE_NAME
#define MS_BOOTER_DEFAULT_FILE_NAME
EFI_STATUS OcBootPolicyGetAllApfsRecoveryFilePath(IN EFI_HANDLE Handle OPTIONAL, OUT VOID **Volumes, OUT UINTN *NumberOfEntries)
STATIC EFI_STATUS InternalGetBootPathName(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT CHAR16 **BootPathName, IN BOOLEAN DirectoryOnly)
EFI_STATUS EFIAPI BootPolicyGetAllApfsRecoveryFilePath(IN EFI_HANDLE Handle OPTIONAL, OUT VOID **Volumes, OUT UINTN *NumberOfEntries)
GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 * gAppleBootPolicyPredefinedPaths[]
APPLE_BOOT_POLICY_PROTOCOL * OcAppleBootPolicyInstallProtocol(IN BOOLEAN Reinstall)
GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN gAppleBootPolicyNumPredefinedPaths
STATIC EFI_STATUS InternalGetBooterFromBlessedSystemFilePath(IN EFI_FILE_PROTOCOL *Root, OUT EFI_DEVICE_PATH_PROTOCOL **FilePath)
STATIC EFI_STATUS InternalGetApfsVolumeInfo(IN EFI_HANDLE Device, OUT EFI_GUID *ContainerGuid, OUT EFI_GUID *VolumeGuid, OUT APPLE_APFS_VOLUME_ROLE *VolumeRole)
STATIC EFI_STATUS OcBootPolicyDevicePathToDirPathAndApfsHandle(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, OUT CHAR16 **BootPathName, OUT EFI_HANDLE *Device, OUT EFI_HANDLE *ApfsVolumeHandle)
STATIC EFI_STATUS InternalGetBooterFromBlessedSystemFolderPath(IN EFI_HANDLE Device, IN EFI_FILE_PROTOCOL *Root, OUT EFI_DEVICE_PATH_PROTOCOL **FilePath)
EFI_STATUS OcBootPolicyDevicePathToFilePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT CHAR16 **BootPathName)
EFI_STATUS EFIAPI BootPolicyDevicePathToDirPath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT CHAR16 **BootPathName, OUT EFI_HANDLE *Device, OUT EFI_HANDLE *ApfsVolumeHandle)
STATIC EFI_STATUS InternalFileExists(IN EFI_FILE_HANDLE Root, IN CONST CHAR16 *FileName)
EFI_STATUS EFIAPI BootPolicyGetBootFileEx(IN EFI_HANDLE Device, IN BOOT_POLICY_ACTION Action, OUT EFI_DEVICE_PATH_PROTOCOL **FilePath)
EFI_STATUS OcGetBooterFromPredefinedPathList(IN EFI_HANDLE Device, IN EFI_FILE_PROTOCOL *Root, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL, IN CHAR16 *Prefix OPTIONAL)
EFI_STATUS EFIAPI BootPolicyGetBootFile(IN EFI_HANDLE Device, IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath)
STATIC EFI_STATUS InternalGetApfsVolumeHandle(IN EFI_HANDLE DeviceHandle, IN CHAR16 *PathName, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, OUT EFI_HANDLE *ApfsVolumeHandle)
EFI_STATUS OcBootPolicyGetBootFileEx(IN EFI_HANDLE Device, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, OUT EFI_DEVICE_PATH_PROTOCOL **FilePath)
EFI_STATUS OcBootPolicyDevicePathToDirPath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT CHAR16 **BootPathName, OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **FileSystem)
EFI_STATUS EFIAPI BootPolicyGetApfsRecoveryFilePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 *PathName, OUT CHAR16 **FullPathName, OUT VOID **Reserved, OUT EFI_FILE_PROTOCOL **Root, OUT EFI_HANDLE *DeviceHandle)
STATIC APPLE_BOOT_POLICY_PROTOCOL mAppleBootPolicyProtocol
STATIC EFI_STATUS InternalGetApfsSpecialFileInfo(IN EFI_FILE_PROTOCOL *Root, IN OUT APPLE_APFS_VOLUME_INFO **VolumeInfo OPTIONAL, IN OUT APPLE_APFS_CONTAINER_INFO **ContainerInfo OPTIONAL)
EFI_STATUS OcBootPolicyGetApfsRecoveryFilePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 *PathName, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, OUT CHAR16 **FullPathName, OUT EFI_FILE_PROTOCOL **Root, OUT EFI_HANDLE *DeviceHandle)
EFI_STATUS InternalBootPolicyDevicePathToDirPath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT CHAR16 **BootPathName, OUT EFI_HANDLE *Device, IN BOOLEAN DirectoryOnly)
STATIC EFI_STATUS InternalGetBooterFromApfsVolumePredefinedPathList(IN EFI_HANDLE Device, IN EFI_FILE_PROTOCOL *PrebootRoot, IN CHAR16 *VolumeDirectoryName, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL)
EFI_STATUS OcBootPolicyGetBootFile(IN EFI_HANDLE Device, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath)
GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN gAppleBootPolicyCoreNumPredefinedPaths
STATIC EFI_STATUS InternalGetBooterFromApfsPredefinedPathList(IN EFI_HANDLE Device, IN EFI_FILE_PROTOCOL *PrebootRoot, IN CONST GUID *ContainerUuid, IN CONST CHAR16 *VolumeUuid OPTIONAL, IN CONST CHAR16 **PredefinedPaths, IN UINTN NumPredefinedPaths, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL, OUT EFI_HANDLE *VolumeHandle OPTIONAL)
CHAR16 PathName[DMG_FILE_PATH_LEN]
DMG_FILEPATH_DEVICE_PATH FilePath
EFI_BOOT_SERVICES * gBS
#define DEBUG_BULK_INFO
VOID DebugPrintHexDump(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN UINT8 *Bytes, IN UINTN Size)
VOID DebugPrintDevicePath(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL)
UINTN OcFileDevicePathNameSize(IN CONST FILEPATH_DEVICE_PATH *FilePath)
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)
UINTN OcFileDevicePathFullNameSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID * OcGetFileInfo(IN EFI_FILE_PROTOCOL *File, IN EFI_GUID *InformationType, IN UINTN MinFileInfoSize, OUT UINTN *RealFileInfoSize OPTIONAL)
Definition GetFileInfo.c:33
EFI_STATUS OcSafeFileOpen(IN CONST EFI_FILE_PROTOCOL *Directory, OUT EFI_FILE_PROTOCOL **NewHandle, IN CONST CHAR16 *FileName, IN CONST UINT64 OpenMode, IN CONST UINT64 Attributes)
Definition OpenFile.c:29
EFI_STATUS OcUninstallAllProtocolInstances(EFI_GUID *Protocol)
BOOLEAN HasValidGuidStringPrefix(IN CONST CHAR16 *String)
#define L_STR_SIZE(String)
Definition OcStringLib.h:35
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_GUID gEfiFileInfoGuid
EFI_GUID gEfiSimpleFileSystemProtocolGuid
#define ASSERT(x)
Definition coder.h:55
#define Len
Definition deflate.h:82
APPLE_APFS_VOLUME_ROLE VolumeRole
EFI_FILE_PROTOCOL * Root
APPLE_APFS_VOLUME_ROLE Role