OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
BootEntryInfo.c
Go to the documentation of this file.
1
16
17#include <Guid/AppleBless.h>
20
21#include <Library/BaseLib.h>
22#include <Library/BaseMemoryLib.h>
24#include <Library/DevicePathLib.h>
25#include <Library/MemoryAllocationLib.h>
27#include <Library/OcFileLib.h>
28#include <Library/OcStringLib.h>
29#include <Library/OcXmlLib.h>
30#include <Library/PrintLib.h>
31#include <Library/UefiBootServicesTableLib.h>
32
33EFI_STATUS
35 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
36 IN CONST CHAR16 *DirectoryName,
37 IN CONST CHAR16 *Filename,
38 IN UINT32 MaxFileSize,
39 IN UINT32 MinFileSize,
40 OUT VOID **FileData,
41 OUT UINT32 *DataSize OPTIONAL
42 )
43{
44 CHAR16 *FilePath;
45 UINTN FilePathSize;
46 UINT32 FileReadSize;
47 BOOLEAN Result;
48
49 Result = BaseOverflowAddUN (
50 StrSize (DirectoryName),
51 StrSize (Filename) - sizeof (CHAR16),
52 &FilePathSize
53 );
54 if (Result) {
55 return EFI_OUT_OF_RESOURCES;
56 }
57
58 FilePath = AllocatePool (FilePathSize);
59
60 if (FilePath == NULL) {
61 return EFI_OUT_OF_RESOURCES;
62 }
63
64 UnicodeSPrint (FilePath, FilePathSize, L"%s%s", DirectoryName, Filename);
65 *FileData = OcReadFile (FileSystem, FilePath, &FileReadSize, MaxFileSize);
66
67 FreePool (FilePath);
68
69 if (*FileData == NULL) {
70 return EFI_NOT_FOUND;
71 }
72
73 if (FileReadSize < MinFileSize) {
74 FreePool (*FileData);
75 return EFI_UNSUPPORTED;
76 }
77
78 if (DataSize != NULL) {
79 *DataSize = FileReadSize;
80 }
81
82 return EFI_SUCCESS;
83}
84
85CHAR16 *
87 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
88 IN CONST CHAR16 *BootDirectoryName,
89 IN CONST CHAR16 *LabelFilename
90 )
91{
92 EFI_STATUS Status;
93 CHAR8 *AsciiDiskLabel;
94 CHAR16 *UnicodeDiskLabel;
95 UINT32 DiskLabelLength;
96
98 FileSystem,
99 BootDirectoryName,
100 LabelFilename,
102 0,
103 (VOID **)&AsciiDiskLabel,
104 &DiskLabelLength
105 );
106
107 if (EFI_ERROR (Status)) {
108 return NULL;
109 }
110
111 UnicodeDiskLabel = AsciiStrCopyToUnicode (AsciiDiskLabel, DiskLabelLength);
112 if (UnicodeDiskLabel != NULL) {
113 UnicodeFilterString (UnicodeDiskLabel, TRUE);
114 }
115
116 FreePool (AsciiDiskLabel);
117
118 return UnicodeDiskLabel;
119}
120
121CHAR8 *
123 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
124 IN CONST CHAR16 *BootDirectoryName
125 )
126{
127 EFI_STATUS Status;
128 CHAR8 *AsciiContentFlavour;
129
131 FileSystem,
132 BootDirectoryName,
133 L".contentFlavour",
135 0,
136 (VOID **)&AsciiContentFlavour,
137 NULL
138 );
139
140 if (EFI_ERROR (Status)) {
141 return NULL;
142 }
143
144 AsciiFilterString (AsciiContentFlavour, TRUE);
145
146 return AsciiContentFlavour;
147}
148
149STATIC
150EFI_STATUS
152 IN CHAR8 *SystemVersionData,
153 IN UINT32 SystemVersionDataSize,
154 OUT CHAR8 *AppleVersion
155 )
156{
157 EFI_STATUS Status;
158 XML_DOCUMENT *Document;
159 XML_NODE *RootDict;
160 UINT32 DictSize;
161 UINT32 Index;
162 CONST CHAR8 *CurrentKey;
163 XML_NODE *CurrentValue;
164 CONST CHAR8 *Version;
165
166 Document = XmlDocumentParse (SystemVersionData, SystemVersionDataSize, FALSE);
167
168 if (Document == NULL) {
169 return EFI_NOT_FOUND;
170 }
171
173
174 if (RootDict == NULL) {
175 XmlDocumentFree (Document);
176 return EFI_NOT_FOUND;
177 }
178
179 Status = EFI_NOT_FOUND;
180
181 DictSize = PlistDictChildren (RootDict);
182 for (Index = 0; Index < DictSize; Index++) {
183 CurrentKey = PlistKeyValue (PlistDictChild (RootDict, Index, &CurrentValue));
184
185 if ((CurrentKey == NULL) || (AsciiStrCmp (CurrentKey, "ProductUserVisibleVersion") != 0)) {
186 continue;
187 }
188
189 if (PlistNodeCast (CurrentValue, PLIST_NODE_TYPE_STRING) != NULL) {
190 Version = XmlNodeContent (CurrentValue);
191 if (Version != NULL) {
192 if (AsciiStrCpyS (AppleVersion, OC_APPLE_VERSION_MAX_SIZE, Version) != RETURN_SUCCESS) {
193 Status = EFI_UNSUPPORTED;
194 } else {
195 Status = EFI_SUCCESS;
196 }
197 }
198 }
199
200 break;
201 }
202
203 XmlDocumentFree (Document);
204 return Status;
205}
206
207STATIC
208CHAR16 *
210 IN CHAR8 *Version
211 )
212{
213 CHAR16 *RecoveryName;
214 UINTN RecoveryNameSize;
215
216 RecoveryName = NULL;
217
218 if (Version[0] != '\0') {
219 RecoveryNameSize = L_STR_SIZE (L"Recovery ") + AsciiStrLen (Version) * sizeof (CHAR16);
220 RecoveryName = AllocatePool (RecoveryNameSize);
221 if (RecoveryName != NULL) {
222 UnicodeSPrint (RecoveryName, RecoveryNameSize, L"Recovery %a", Version);
223 UnicodeFilterString (RecoveryName, TRUE);
224 }
225 }
226
227 return RecoveryName;
228}
229
230STATIC
231EFI_STATUS
233 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
234 IN CONST CHAR16 *DirectoryName,
235 OUT CHAR8 *AppleVersion
236 )
237{
238 EFI_STATUS Status;
239 CHAR8 *SystemVersionData;
240 UINT32 SystemVersionDataSize;
241
243 FileSystem,
244 DirectoryName,
245 L"SystemVersion.plist",
246 BASE_1MB,
247 0,
248 (VOID **)&SystemVersionData,
249 &SystemVersionDataSize
250 );
251
252 if (EFI_ERROR (Status)) {
253 return EFI_NOT_FOUND;
254 }
255
256 Status = GetAppleVersionFromPlist (SystemVersionData, SystemVersionDataSize, AppleVersion);
257 FreePool (SystemVersionData);
258
259 return Status;
260}
261
262EFI_STATUS
264 IN EFI_HANDLE Device,
265 OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
266 IN BOOLEAN Basic
267 )
268{
269 EFI_STATUS Status;
270 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
271 EFI_FILE_PROTOCOL *Root;
272 EFI_FILE_PROTOCOL *Recovery;
273 UINTN FilePathSize;
274 EFI_DEVICE_PATH_PROTOCOL *TmpPath;
275 UINTN TmpPathSize;
276 CHAR16 *DevicePathText;
277
278 Status = gBS->HandleProtocol (
279 Device,
281 (VOID **)&FileSystem
282 );
283 if (EFI_ERROR (Status)) {
284 return Status;
285 }
286
287 Status = FileSystem->OpenVolume (FileSystem, &Root);
288 if (EFI_ERROR (Status)) {
289 return Status;
290 }
291
292 FilePathSize = 0;
293
294 if (!Basic) {
295 *FilePath = (EFI_DEVICE_PATH_PROTOCOL *)OcGetFileInfo (
296 Root,
298 sizeof (EFI_DEVICE_PATH_PROTOCOL),
299 &FilePathSize
300 );
301 } else {
302 //
303 // Requested basic recovery support, i.e. only com.apple.recovery.boot folder check.
304 // This is useful for locating empty USB sticks with just a dmg in them.
305 //
306 *FilePath = NULL;
307 }
308
309 if (*FilePath != NULL) {
310 if (IsDevicePathValid (*FilePath, FilePathSize)) {
311 //
312 // We skip alternate entry when current one is the same.
313 // This is to prevent recovery and volume duplicates on HFS+ systems.
314 //
315
316 TmpPath = (EFI_DEVICE_PATH_PROTOCOL *)OcGetFileInfo (
317 Root,
319 sizeof (EFI_DEVICE_PATH_PROTOCOL),
320 &TmpPathSize
321 );
322
323 if (TmpPath != NULL) {
324 if ( IsDevicePathValid (TmpPath, TmpPathSize)
325 && IsDevicePathEqual (TmpPath, *FilePath))
326 {
327 DEBUG ((DEBUG_INFO, "Skipping equal alternate device path %p\n", Device));
328 Status = EFI_ALREADY_STARTED;
329 FreePool (*FilePath);
330 *FilePath = NULL;
331 }
332
333 FreePool (TmpPath);
334 }
335
336 if (!EFI_ERROR (Status)) {
337 //
338 // This entry should point to a folder with recovery.
339 // Apple never adds trailing slashes to blessed folder paths.
340 // However, we do rely on trailing slashes in folder paths and add them here.
341 //
343 if (TmpPath != NULL) {
344 FreePool (*FilePath);
345 *FilePath = TmpPath;
346 }
347 }
348 } else {
349 FreePool (*FilePath);
350 *FilePath = NULL;
351 Status = EFI_NOT_FOUND;
352 }
353 } else {
354 //
355 // Ok, this one can still be FileVault 2 HFS+ recovery or just a hardcoded basic recovery.
356 // Apple does add its path to so called "Alternate OS blessed file/folder", but this
357 // path is not accessible from HFSPlus.efi driver. Just why???
358 // Their SlingShot.efi app just bruteforces com.apple.recovery.boot directory existence,
359 // and we have to copy.
360 //
361 Status = OcSafeFileOpen (Root, &Recovery, L"\\com.apple.recovery.boot", EFI_FILE_MODE_READ, 0);
362 if (!EFI_ERROR (Status)) {
363 //
364 // Do not do any extra checks for simplicity, as they will be done later either way.
365 //
366 Root->Close (Recovery);
367 Status = EFI_NOT_FOUND;
368 TmpPath = DevicePathFromHandle (Device);
369
370 if (TmpPath != NULL) {
371 *FilePath = AppendFileNameDevicePath (TmpPath, L"\\com.apple.recovery.boot\\");
372 if (*FilePath != NULL) {
373 DEBUG_CODE_BEGIN ();
374 DevicePathText = ConvertDevicePathToText (*FilePath, FALSE, FALSE);
375 if (DevicePathText != NULL) {
376 DEBUG ((DEBUG_INFO, "OCB: Got recovery dp %s\n", DevicePathText));
377 FreePool (DevicePathText);
378 }
379
380 DEBUG_CODE_END ();
381 Status = EFI_SUCCESS;
382 }
383 }
384 } else {
385 Status = EFI_NOT_FOUND;
386 }
387 }
388
389 Root->Close (Root);
390
391 return Status;
392}
393
394EFI_STATUS
395EFIAPI
397 IN OC_PICKER_CONTEXT *Context,
398 IN OC_BOOT_ENTRY *BootEntry,
399 IN UINT8 Scale,
400 OUT VOID **ImageData,
401 OUT UINT32 *DataLength
402 )
403{
404 ASSERT (DataLength != NULL);
405 return OcGetBootEntryFile (
406 BootEntry,
407 Scale == 2 ? L".disk_label_2x" : L".disk_label",
408 "label",
409 BASE_16MB,
410 sizeof (APPLE_DISK_LABEL),
411 ImageData,
412 DataLength,
413 TRUE,
414 FALSE
415 );
416}
417
418EFI_STATUS
419EFIAPI
421 IN OC_PICKER_CONTEXT *Context,
422 IN OC_BOOT_ENTRY *BootEntry,
423 OUT VOID **ImageData,
424 OUT UINT32 *DataLength
425 )
426{
427 ASSERT (DataLength != NULL);
428 return OcGetBootEntryFile (
429 BootEntry,
430 L".VolumeIcon.icns",
431 "volume icon",
432 BASE_16MB,
433 sizeof (APPLE_ICNS_RECORD) * 2,
434 ImageData,
435 DataLength,
436 FALSE,
437 TRUE
438 );
439}
440
441EFI_STATUS
442EFIAPI
444 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
445 IN CONST CHAR16 *FileName,
446 IN CONST CHAR16 *DebugBootEntryName,
447 IN CONST CHAR8 *DebugFileType,
448 IN UINT32 MaxFileSize,
449 IN UINT32 MinFileSize,
450 OUT VOID **FileData,
451 OUT UINT32 *DataLength OPTIONAL,
452 IN BOOLEAN SearchAtLeaf,
453 IN BOOLEAN SearchAtRoot
454 )
455{
456 EFI_STATUS Status;
457 CHAR16 *BootDirectoryName;
458 CHAR16 *GuidPrefix;
459 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
460
461 ASSERT (SearchAtLeaf || SearchAtRoot);
462 ASSERT (DevicePath != NULL);
463 ASSERT (FileData != NULL);
464
465 *FileData = NULL;
466 if (DataLength != NULL) {
467 *DataLength = 0;
468 }
469
471 DevicePath,
472 &BootDirectoryName,
473 &FileSystem
474 );
475
476 if (EFI_ERROR (Status)) {
477 return Status;
478 }
479
480 Status = EFI_NOT_FOUND;
481
482 if (SearchAtLeaf) {
484 FileSystem,
485 BootDirectoryName,
486 FileName,
487 MaxFileSize,
488 MinFileSize,
489 FileData,
490 DataLength
491 );
492 }
493
494 if (!EFI_ERROR (Status) || !SearchAtRoot) {
495 DEBUG ((
496 DEBUG_INFO,
497 "OCB: Get %a for %s - %r\n",
498 DebugFileType,
499 DebugBootEntryName,
500 Status
501 ));
502
503 FreePool (BootDirectoryName);
504
505 return Status;
506 }
507
508 GuidPrefix = BootDirectoryName[0] == '\\' ? &BootDirectoryName[1] : &BootDirectoryName[0];
509 if (HasValidGuidStringPrefix (GuidPrefix) && (GuidPrefix[GUID_STRING_LENGTH] == '\\')) {
510 GuidPrefix[GUID_STRING_LENGTH+1] = '\0';
511 } else {
512 GuidPrefix = NULL;
513 }
514
515 //
516 // OC-specific location, per-GUID and hence per-OS, below Preboot volume root.
517 // Not recognised by Apple bootpicker.
518 //
519 if (GuidPrefix != NULL) {
521 FileSystem,
522 GuidPrefix,
523 FileName,
524 MaxFileSize,
525 MinFileSize,
526 FileData,
527 DataLength
528 );
529 } else {
530 Status = EFI_UNSUPPORTED;
531 }
532
533 //
534 // Apple default location at Preboot volume root (typically mounted within OS
535 // at /System/Volumes/Preboot/), shared by all OSes on a volume.
536 //
537 if (EFI_ERROR (Status)) {
539 FileSystem,
540 L"",
541 FileName,
542 MaxFileSize,
543 MinFileSize,
544 FileData,
545 DataLength
546 );
547 }
548
549 DEBUG ((
550 DEBUG_INFO,
551 "OCB: Get %a for %s %s - %r\n",
552 DebugFileType,
553 DebugBootEntryName,
554 GuidPrefix,
555 Status
556 ));
557
558 FreePool (BootDirectoryName);
559
560 return Status;
561}
562
563EFI_STATUS
564EFIAPI
566 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
567 IN CONST CHAR16 *FileName,
568 IN CONST CHAR8 *DebugFileType,
569 IN UINT32 MaxFileSize,
570 IN UINT32 MinFileSize,
571 OUT VOID **FileData,
572 OUT UINT32 *DataLength OPTIONAL,
573 IN BOOLEAN SearchAtLeaf,
574 IN BOOLEAN SearchAtRoot
575 )
576{
578 DevicePath,
579 FileName,
580 L"boot entry",
581 DebugFileType,
582 MaxFileSize,
583 MinFileSize,
584 FileData,
585 DataLength,
586 SearchAtLeaf,
587 SearchAtRoot
588 );
589}
590
591EFI_STATUS
592EFIAPI
594 IN OC_BOOT_ENTRY *BootEntry,
595 IN CONST CHAR16 *FileName,
596 IN CONST CHAR8 *DebugFileType,
597 IN UINT32 MaxFileSize,
598 IN UINT32 MinFileSize,
599 OUT VOID **FileData,
600 OUT UINT32 *DataLength OPTIONAL,
601 IN BOOLEAN SearchAtLeaf,
602 IN BOOLEAN SearchAtRoot
603 )
604{
605 if ((BootEntry->Type & (OC_BOOT_EXTERNAL_TOOL | OC_BOOT_SYSTEM)) != 0) {
606 return EFI_NOT_FOUND;
607 }
608
610 BootEntry->DevicePath,
611 FileName,
612 BootEntry->Name,
613 DebugFileType,
614 MaxFileSize,
615 MinFileSize,
616 FileData,
617 DataLength,
618 SearchAtLeaf,
619 SearchAtRoot
620 );
621}
622
623//
624// Duplicate each flavour in list, w/ apple version added to first of each duplicate
625//
626STATIC
627CHAR8 *
629 IN CHAR8 *Flavour,
630 IN CHAR8 *Version
631 )
632{
633 UINTN VersionLength;
634 UINTN FlavourLength;
635 UINTN SepCount;
636 UINTN Size;
637 UINTN Index;
638 CHAR8 *NewFlavour;
639 CHAR8 *Start;
640 CHAR8 *End;
641 CHAR8 *Pos;
642
643 ASSERT (Flavour != NULL);
644 ASSERT (Version != NULL);
645
646 VersionLength = AsciiStrLen (Version);
647 FlavourLength = AsciiStrLen (Flavour);
648 SepCount = 0;
649 for (Index = 0; Index < FlavourLength; Index++) {
650 if (Flavour[Index] == ':') {
651 ++SepCount;
652 }
653 }
654
655 Size = 2 * (FlavourLength + 1) + VersionLength * (SepCount + 1);
656
658 return Flavour;
659 }
660
661 NewFlavour = AllocatePool (Size);
662 if (NewFlavour == NULL) {
663 return Flavour;
664 }
665
666 Pos = NewFlavour;
667 End = Flavour - 1;
668 do {
669 for (Start = ++End; *End != '\0' && *End != ':'; ++End) {
670 }
671
672 AsciiStrnCpyS (Pos, Size - (Pos - NewFlavour), Start, End - Start);
673 Pos += End - Start;
674 AsciiStrnCpyS (Pos, Size - (Pos - NewFlavour), Version, VersionLength);
675 Pos += VersionLength;
676 *Pos++ = ':';
677 AsciiStrnCpyS (Pos, Size - (Pos - NewFlavour), Start, End - Start);
678 Pos += End - Start;
679 *Pos++ = ':';
680 } while (*End != '\0');
681
682 *(Pos - 1) = '\0';
683
684 ASSERT ((UINTN)(Pos - NewFlavour) == Size);
685
686 FreePool (Flavour);
687
688 return NewFlavour;
689}
690
691EFI_STATUS
693 IN OC_BOOT_CONTEXT *BootContext,
694 IN OUT OC_BOOT_ENTRY *BootEntry
695 )
696{
697 EFI_STATUS Status;
698 CHAR16 *BootDirectoryName;
699 CHAR16 *TmpBootName;
700 UINT32 BcdSize;
701 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
702 CHAR8 *ContentFlavour;
703 CHAR8 AppleVersion[OC_APPLE_VERSION_MAX_SIZE];
704 CHAR8 *Dot;
705
706 AppleVersion[0] = '\0';
707
708 //
709 // Custom entries need no special description.
710 //
711 if ((BootEntry->Type == OC_BOOT_EXTERNAL_OS) || (BootEntry->Type == OC_BOOT_EXTERNAL_TOOL)) {
712 return EFI_SUCCESS;
713 }
714
716 BootEntry->DevicePath,
717 &BootDirectoryName,
718 &FileSystem
719 );
720
721 if (EFI_ERROR (Status)) {
722 return Status;
723 }
724
725 //
726 // Try to use APFS-style label or legacy HFS one.
727 //
728 BootEntry->Name = InternalGetAppleDiskLabel (FileSystem, BootDirectoryName, L".contentDetails");
729 if (BootEntry->Name == NULL) {
730 BootEntry->Name = InternalGetAppleDiskLabel (FileSystem, BootDirectoryName, L".disk_label.contentDetails");
731 }
732
733 //
734 // With FV2 encryption on HFS+ the actual boot happens from "Recovery HD/S/L/CoreServices".
735 // For some reason "Recovery HD/S/L/CoreServices/.disk_label" may not get updated immediately,
736 // and will contain "Recovery HD" despite actually pointing to "Macintosh HD".
737 // This also spontaneously happens with renamed APFS volumes. The workaround is to manually
738 // edit the file or sometimes choose the boot volume once more in preferences.
739 //
740 // TODO: Bugreport this to Apple, as this is clearly their bug, which should be reproducible
741 // on original hardware.
742 //
743 // There exists .root_uuid, which contains real partition UUID in ASCII, however, Apple
744 // BootPicker only uses it for entry deduplication, and we cannot figure out the name
745 // on an encrypted volume anyway.
746 //
747
748 //
749 // Windows boot entry may have a custom name, so ensure OC_BOOT_WINDOWS is set correctly.
750 //
751 if ((BootEntry->Type == OC_BOOT_UNKNOWN) && BootEntry->IsGeneric) {
752 DEBUG ((DEBUG_INFO, "OCB: Trying to detect Microsoft BCD\n"));
753 Status = OcReadFileSize (FileSystem, L"\\EFI\\Microsoft\\Boot\\BCD", &BcdSize);
754 if (!EFI_ERROR (Status)) {
755 BootEntry->Type = OC_BOOT_WINDOWS;
756 }
757 }
758
759 if ((BootEntry->Type == OC_BOOT_WINDOWS) && (BootEntry->Name == NULL)) {
760 BootEntry->Name = AllocateCopyPool (sizeof (L"Windows"), L"Windows");
761 }
762
763 // TODO: Should macOS installer have own OC_BOOT_ENTRY_TYPE (plus own voiceover file?)?
764 BootEntry->IsAppleInstaller = (StrStr (BootDirectoryName, L"com.apple.installer") != NULL);
765 if (BootEntry->Name == NULL) {
766 //
767 // Special case - installer should be clearly identified to end users but does not normally
768 // contain text label, only pre-rendered graphical label which is not usable in builtin
769 // picker, or in Canopy with disk labels disabled.
770 //
771 if (BootEntry->IsAppleInstaller) {
772 BootEntry->Name = AllocateCopyPool (L_STR_SIZE (L"macOS Installer"), L"macOS Installer");
773 } else {
774 BootEntry->Name = OcGetVolumeLabel (FileSystem);
775 if (BootEntry->Name != NULL) {
776 if ( (StrCmp (BootEntry->Name, L"Recovery HD") == 0)
777 || (StrCmp (BootEntry->Name, L"Recovery") == 0))
778 {
779 if ((BootEntry->Type == OC_BOOT_UNKNOWN) || (BootEntry->Type == OC_BOOT_APPLE_OS)) {
780 BootEntry->Type = OC_BOOT_APPLE_RECOVERY;
781 }
782
783 Status = InternalGetAppleVersion (FileSystem, BootDirectoryName, AppleVersion);
784 if (EFI_ERROR (Status)) {
785 TmpBootName = NULL;
786 } else {
787 TmpBootName = InternalGetAppleRecoveryName (AppleVersion);
788 }
789 } else if (StrCmp (BootEntry->Name, L"Preboot") == 0) {
790 //
791 // Common Big Sur beta bug failing to create .contentDetails files.
792 // Workaround it by using the standard installed macOS system volume name.
793 // Applies to anything on the system volume without text labels (and not already
794 // handled above, such as installer).
795 //
796 TmpBootName = AllocateCopyPool (sizeof (L"Macintosh HD"), L"Macintosh HD");
797 } else {
798 TmpBootName = NULL;
799 }
800
801 if (TmpBootName != NULL) {
802 FreePool (BootEntry->Name);
803 BootEntry->Name = TmpBootName;
804 }
805 }
806 }
807 }
808
809 if (BootEntry->Name == NULL) {
810 FreePool (BootDirectoryName);
811 return EFI_NOT_FOUND;
812 }
813
814 BootEntry->PathName = BootDirectoryName;
815
816 //
817 // Get user-specified or builtin content flavour.
818 //
819 if ((BootContext->PickerContext->PickerAttributes & OC_ATTR_USE_FLAVOUR_ICON) != 0) {
820 BootEntry->Flavour = InternalGetContentFlavour (FileSystem, BootDirectoryName);
821 }
822
823 if ((BootEntry->Flavour == NULL) || (AsciiStrCmp (BootEntry->Flavour, OC_FLAVOUR_AUTO) == 0)) {
824 switch (BootEntry->Type) {
825 case OC_BOOT_APPLE_OS:
826 ContentFlavour = AllocateCopyPool (sizeof (OC_FLAVOUR_APPLE_OS), OC_FLAVOUR_APPLE_OS);
827 if ((BootContext->PickerContext->PickerAttributes & OC_ATTR_USE_FLAVOUR_ICON) != 0) {
828 InternalGetAppleVersion (FileSystem, BootDirectoryName, AppleVersion);
829 }
830
831 break;
833 ContentFlavour = AllocateCopyPool (sizeof (OC_FLAVOUR_APPLE_FW), OC_FLAVOUR_APPLE_FW);
834 break;
836 ContentFlavour = AllocateCopyPool (sizeof (OC_FLAVOUR_APPLE_RECOVERY), OC_FLAVOUR_APPLE_RECOVERY);
837 break;
839 ContentFlavour = AllocateCopyPool (sizeof (OC_FLAVOUR_APPLE_TIME_MACHINE), OC_FLAVOUR_APPLE_TIME_MACHINE);
840 break;
841 case OC_BOOT_WINDOWS:
842 ContentFlavour = AllocateCopyPool (sizeof (OC_FLAVOUR_WINDOWS), OC_FLAVOUR_WINDOWS);
843 break;
844 case OC_BOOT_UNKNOWN:
845 ContentFlavour = NULL;
846 break;
847 default:
848 DEBUG ((DEBUG_ERROR, "OCB: Entry kind %d unsupported for flavour\n", BootEntry->Type));
849 ContentFlavour = NULL;
850 break;
851 }
852
853 if ((BootEntry->Type & OC_BOOT_APPLE_ANY) != 0) {
854 if (ContentFlavour == NULL) {
855 ASSERT (FALSE);
856 } else if ( (AppleVersion[0] != '\0')
857 && ((BootContext->PickerContext->PickerAttributes & OC_ATTR_USE_FLAVOUR_ICON) != 0)
858 )
859 {
860 //
861 // If 10.x(.y) remove .y and replace first . with _, otherwise remove from first .
862 //
863 Dot = AsciiStrStr (AppleVersion, ".");
864 if (Dot != NULL) {
865 if ( (Dot - AppleVersion == sizeof ("10") - 1)
866 && OcAsciiStartsWith (AppleVersion, "10", FALSE)
867 )
868 {
869 *Dot++ = '_';
870 Dot = AsciiStrStr (Dot, ".");
871 if (Dot != NULL) {
872 *Dot = '\0';
873 }
874 } else {
875 *Dot = '\0';
876 }
877 }
878
879 ContentFlavour = InternalAddAppleVersion (ContentFlavour, AppleVersion);
880 }
881 }
882
883 if ((ContentFlavour == NULL) && (BootEntry->Flavour == NULL)) {
884 ContentFlavour = AllocateCopyPool (sizeof (OC_FLAVOUR_AUTO), OC_FLAVOUR_AUTO);
885 }
886
887 if (ContentFlavour != NULL) {
888 if (BootEntry->Flavour != NULL) {
889 FreePool (BootEntry->Flavour);
890 }
891
892 BootEntry->Flavour = ContentFlavour;
893 }
894 }
895
896 return EFI_SUCCESS;
897}
EFI_GUID gAppleBlessedOsxFolderInfoGuid
A global variable storing the GUID of the APPLE_BLESSED_OSX_FOLDER_INFO_GUID.
EFI_GUID gAppleBlessedSystemFolderInfoGuid
A global variable storing the GUID of the APPLE_BLESSED_SYSTEM_FOLDER_INFO_GUID.
UINT32 Version
UINT64 Start
EFI_DEVICE_PATH_PROTOCOL End
EFI_STATUS EFIAPI InternalGetBootEntryFile(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 *FileName, IN CONST CHAR16 *DebugBootEntryName, IN CONST CHAR8 *DebugFileType, IN UINT32 MaxFileSize, IN UINT32 MinFileSize, OUT VOID **FileData, OUT UINT32 *DataLength OPTIONAL, IN BOOLEAN SearchAtLeaf, IN BOOLEAN SearchAtRoot)
EFI_STATUS EFIAPI OcGetBootEntryIcon(IN OC_PICKER_CONTEXT *Context, IN OC_BOOT_ENTRY *BootEntry, OUT VOID **ImageData, OUT UINT32 *DataLength)
EFI_STATUS InternalGetRecoveryOsBooter(IN EFI_HANDLE Device, OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, IN BOOLEAN Basic)
EFI_STATUS InternalReadBootEntryFile(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *DirectoryName, IN CONST CHAR16 *Filename, IN UINT32 MaxFileSize, IN UINT32 MinFileSize, OUT VOID **FileData, OUT UINT32 *DataSize OPTIONAL)
CHAR16 * InternalGetAppleDiskLabel(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *BootDirectoryName, IN CONST CHAR16 *LabelFilename)
EFI_STATUS InternalDescribeBootEntry(IN OC_BOOT_CONTEXT *BootContext, IN OUT OC_BOOT_ENTRY *BootEntry)
EFI_STATUS EFIAPI OcGetBootEntryFileFromDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 *FileName, IN CONST CHAR8 *DebugFileType, IN UINT32 MaxFileSize, IN UINT32 MinFileSize, OUT VOID **FileData, OUT UINT32 *DataLength OPTIONAL, IN BOOLEAN SearchAtLeaf, IN BOOLEAN SearchAtRoot)
EFI_STATUS EFIAPI OcGetBootEntryLabelImage(IN OC_PICKER_CONTEXT *Context, IN OC_BOOT_ENTRY *BootEntry, IN UINT8 Scale, OUT VOID **ImageData, OUT UINT32 *DataLength)
STATIC CHAR16 * InternalGetAppleRecoveryName(IN CHAR8 *Version)
EFI_STATUS EFIAPI OcGetBootEntryFile(IN OC_BOOT_ENTRY *BootEntry, IN CONST CHAR16 *FileName, IN CONST CHAR8 *DebugFileType, IN UINT32 MaxFileSize, IN UINT32 MinFileSize, OUT VOID **FileData, OUT UINT32 *DataLength OPTIONAL, IN BOOLEAN SearchAtLeaf, IN BOOLEAN SearchAtRoot)
STATIC EFI_STATUS GetAppleVersionFromPlist(IN CHAR8 *SystemVersionData, IN UINT32 SystemVersionDataSize, OUT CHAR8 *AppleVersion)
STATIC CHAR8 * InternalAddAppleVersion(IN CHAR8 *Flavour, IN CHAR8 *Version)
CHAR8 * InternalGetContentFlavour(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *BootDirectoryName)
STATIC EFI_STATUS InternalGetAppleVersion(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *DirectoryName, OUT CHAR8 *AppleVersion)
#define OC_APPLE_VERSION_MAX_SIZE
EFI_STATUS OcBootPolicyDevicePathToDirPath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT CHAR16 **BootPathName, OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **FileSystem)
DMG_FILEPATH_DEVICE_PATH FilePath
DMG_SIZE_DEVICE_PATH Size
#define OC_FLAVOUR_WINDOWS
#define OC_FLAVOUR_APPLE_RECOVERY
#define OC_BOOT_APPLE_TIME_MACHINE
#define OC_BOOT_APPLE_ANY
#define OC_BOOT_EXTERNAL_TOOL
#define OC_FLAVOUR_APPLE_TIME_MACHINE
#define OC_FLAVOUR_APPLE_OS
#define OC_BOOT_EXTERNAL_OS
#define OC_ATTR_USE_FLAVOUR_ICON
#define OC_BOOT_APPLE_RECOVERY
#define OC_FLAVOUR_AUTO
#define OC_BOOT_WINDOWS
#define OC_FLAVOUR_APPLE_FW
#define OC_BOOT_APPLE_OS
#define OC_BOOT_UNKNOWN
#define OC_BOOT_APPLE_FW_UPDATE
#define OC_BOOT_SYSTEM
EFI_BOOT_SERVICES * gBS
EFI_DEVICE_PATH_PROTOCOL * TrailedBooterDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
EFI_DEVICE_PATH_PROTOCOL * AppendFileNameDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName)
BOOLEAN EFIAPI IsDevicePathEqual(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2)
CHAR16 * OcGetVolumeLabel(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem)
EFI_STATUS OcReadFileSize(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *FilePath, OUT UINT32 *Size)
Definition ReadFile.c:110
VOID * OcGetFileInfo(IN EFI_FILE_PROTOCOL *File, IN EFI_GUID *InformationType, IN UINTN MinFileInfoSize, OUT UINTN *RealFileInfoSize OPTIONAL)
Definition GetFileInfo.c:33
#define OC_MAX_VOLUME_LABEL_SIZE
Definition OcFileLib.h:32
VOID * OcReadFile(IN CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *FilePath, OUT UINT32 *FileSize OPTIONAL, IN CONST UINT32 MaxFileSize OPTIONAL)
Definition ReadFile.c:33
#define OC_MAX_CONTENT_FLAVOUR_SIZE
Definition OcFileLib.h:37
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
VOID AsciiFilterString(IN OUT CHAR8 *String, IN BOOLEAN SingleLine)
Definition OcAsciiLib.c:480
BOOLEAN HasValidGuidStringPrefix(IN CONST CHAR16 *String)
#define L_STR_SIZE(String)
Definition OcStringLib.h:35
CHAR16 * AsciiStrCopyToUnicode(IN CONST CHAR8 *String, IN UINTN Length)
Definition OcAsciiLib.c:119
VOID UnicodeFilterString(IN OUT CHAR16 *String, IN BOOLEAN SingleLine)
BOOLEAN EFIAPI OcAsciiStartsWith(IN CONST CHAR8 *String, IN CONST CHAR8 *SearchString, IN BOOLEAN CaseInsensitiveMatch)
Definition OcAsciiLib.c:291
@ PLIST_NODE_TYPE_DICT
Definition OcXmlLib.h:91
@ PLIST_NODE_TYPE_STRING
Definition OcXmlLib.h:93
XML_DOCUMENT * XmlDocumentParse(IN OUT CHAR8 *Buffer, IN UINT32 Length, IN BOOLEAN WithRefs)
Definition OcXmlLib.c:1308
CONST CHAR8 * PlistKeyValue(IN XML_NODE *Node OPTIONAL)
Definition OcXmlLib.c:1841
CONST CHAR8 * XmlNodeContent(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1467
UINT32 PlistDictChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1813
XML_NODE * PlistNodeCast(IN XML_NODE *Node OPTIONAL, IN PLIST_NODE_TYPE Type)
Definition OcXmlLib.c:1760
XML_NODE * PlistDocumentRoot(IN CONST XML_DOCUMENT *Document)
Definition OcXmlLib.c:1736
VOID XmlDocumentFree(IN OUT XML_DOCUMENT *Document)
Definition OcXmlLib.c:1435
XML_NODE * PlistDictChild(IN CONST XML_NODE *Node, IN UINT32 Child, OUT XML_NODE **Value OPTIONAL)
Definition OcXmlLib.c:1823
EFI_GUID gEfiSimpleFileSystemProtocolGuid
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
Definition UserMisc.c:680
#define ASSERT(x)
Definition coder.h:55
ush Pos
Definition deflate.h:92