/** @file Copyright (C) 2019, vit9696. All rights reserved. All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include STATIC CHAR16 * GetAppleDiskLabel ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *BootDirectoryName ) { CHAR16 *DiskLabelPath; UINTN DiskLabelPathSize; CHAR8 *AsciiDiskLabel; CHAR16 *UnicodeDiskLabel; UINTN DiskLabelLength; DiskLabelPathSize = StrSize (BootDirectoryName) + L_STR_SIZE_NT (L".disk_label.contentDetails"); DiskLabelPath = AllocatePool (DiskLabelPathSize); if (DiskLabelPath == NULL) { return NULL; } UnicodeSPrint (DiskLabelPath, DiskLabelPathSize, L"%s.disk_label.contentDetails", BootDirectoryName); AsciiDiskLabel = (CHAR8 *) ReadFile (FileSystem, DiskLabelPath, &DiskLabelLength); FreePool (DiskLabelPath); if (AsciiDiskLabel != NULL) { UnicodeDiskLabel = OcAsciiStrToUnicode (AsciiDiskLabel, DiskLabelLength); FreePool (AsciiDiskLabel); } else { UnicodeDiskLabel = NULL; } return UnicodeDiskLabel; } STATIC CHAR16 * GetAppleRecoveryNameFromPlsit ( IN CHAR8 *SystemVersionData, IN UINTN SystemVersionDataSize ) { XML_DOCUMENT *Document; XML_NODE *RootDict; UINT32 DictSize; UINT32 Index; CONST CHAR8 *CurrentKey; XML_NODE *CurrentValue; CONST CHAR8 *Version; CHAR16 *RecoveryName; UINTN RecoveryNameSize; Document = XmlParseDocument (SystemVersionData, SystemVersionDataSize); if (Document == NULL) { return NULL; } RootDict = PlistNodeCast (PlistDocumentRoot (Document), PLIST_NODE_TYPE_DICT); if (RootDict == NULL) { XmlDocumentFree (Document); return NULL; } RecoveryName = NULL; DictSize = PlistDictChildren (RootDict); for (Index = 0; Index < DictSize; Index++) { CurrentKey = PlistKeyValue (PlistDictChild (RootDict, Index, &CurrentValue)); if (CurrentKey == NULL || AsciiStrCmp (CurrentKey, "ProductUserVisibleVersion") != 0) { continue; } if (PlistNodeCast (CurrentValue, PLIST_NODE_TYPE_STRING) != NULL) { Version = XmlNodeContent (CurrentValue); if (Version != NULL) { RecoveryNameSize = L_STR_SIZE(L"Recovery ") + AsciiStrLen (Version) * sizeof (CHAR16); RecoveryName = AllocatePool (RecoveryNameSize); if (RecoveryName != NULL) { UnicodeSPrint(RecoveryName, RecoveryNameSize, L"Recovery %a", Version); } } } break; } XmlDocumentFree (Document); return RecoveryName; } STATIC CHAR16 * GetAppleRecoveryName ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem, IN CONST CHAR16 *BootDirectoryName ) { CHAR16 *SystemVersionPath; UINTN SystemVersionPathSize; CHAR8 *SystemVersionData; CHAR16 *UnicodeDiskLabel; UINTN SystemVersionDataSize; SystemVersionPathSize = StrSize (BootDirectoryName) + L_STR_SIZE_NT (L"SystemVersion.plist"); SystemVersionPath = AllocatePool (SystemVersionPathSize); if (SystemVersionPath == NULL) { return NULL; } UnicodeSPrint (SystemVersionPath, SystemVersionPathSize, L"%sSystemVersion.plist", BootDirectoryName); SystemVersionData = (CHAR8 *) ReadFile (FileSystem, SystemVersionPath, &SystemVersionDataSize); FreePool (SystemVersionPath); if (SystemVersionData != NULL) { UnicodeDiskLabel = GetAppleRecoveryNameFromPlsit (SystemVersionData, SystemVersionDataSize); FreePool (SystemVersionData); } else { UnicodeDiskLabel = NULL; } return UnicodeDiskLabel; } EFI_STATUS OcDescribeBootEntry ( IN APPLE_BOOT_POLICY_PROTOCOL *BootPolicy, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN OUT CHAR16 **BootEntryName OPTIONAL, IN OUT CHAR16 **BootPathName OPTIONAL ) { EFI_STATUS Status; CHAR16 *BootDirectoryName; CHAR16 *RecoveryBootName; EFI_HANDLE Device; EFI_HANDLE ApfsVolumeHandle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem; Status = BootPolicy->GetBootInfo ( DevicePath, &BootDirectoryName, &Device, &ApfsVolumeHandle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->HandleProtocol ( Device, &gEfiSimpleFileSystemProtocolGuid, (VOID **) &FileSystem ); if (EFI_ERROR (Status)) { FreePool (BootDirectoryName); return Status; } if (BootEntryName != NULL) { *BootEntryName = GetAppleDiskLabel (FileSystem, BootDirectoryName); if (*BootEntryName == NULL) { *BootEntryName = GetVolumeLabel (FileSystem); if (*BootEntryName != NULL && !StrCmp (*BootEntryName, L"Recovery HD")) { RecoveryBootName = GetAppleRecoveryName (FileSystem, BootDirectoryName); if (RecoveryBootName != NULL) { FreePool (*BootEntryName); *BootEntryName = RecoveryBootName; } } } if (*BootEntryName == NULL) { FreePool (BootDirectoryName); return EFI_NOT_FOUND; } } if (BootPathName != NULL) { *BootPathName = BootDirectoryName; } else { FreePool (BootDirectoryName); } return EFI_SUCCESS; }