OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
PolicyManagement.c
Go to the documentation of this file.
1
16
17#include <Guid/AppleApfsInfo.h>
18#include <Guid/AppleBless.h>
19#include <Guid/AppleHfsInfo.h>
20#include <Guid/AppleVariable.h>
21#include <Guid/Gpt.h>
22#include <Guid/FileInfo.h>
23#include <Guid/GlobalVariable.h>
24#include <Guid/OcVariable.h>
25
28#include <Protocol/SimpleFileSystem.h>
29#include <Protocol/SimpleTextOut.h>
30#include <Protocol/LoadedImage.h>
31
32#include <Library/BaseMemoryLib.h>
33#include <Library/DebugLib.h>
34#include <Library/DevicePathLib.h>
35#include <Library/MemoryAllocationLib.h>
38#include <Library/OcFileLib.h>
39#include <Library/OcStringLib.h>
40#include <Library/UefiBootServicesTableLib.h>
41#include <Library/UefiLib.h>
42#include <Library/UefiRuntimeServicesTableLib.h>
43
44UINT32
46 IN EFI_HANDLE Handle,
47 OUT BOOLEAN *External OPTIONAL
48 )
49{
50 EFI_STATUS Status;
51 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
52 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
53 ACPI_HID_DEVICE_PATH *Acpi;
54 HARDDRIVE_DEVICE_PATH *HardDrive;
55 UINT8 SubType;
56
57 if (External != NULL) {
58 *External = FALSE;
59 }
60
61 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
62 if (EFI_ERROR (Status)) {
63 return 0;
64 }
65
66 //
67 // FIXME: This code does not take care of RamDisk exception as specified per
68 // https://github.com/acidanthera/bugtracker/issues/335.
69 // Currently we do not need it, but in future we may.
70 //
71
72 DevicePathWalker = DevicePath;
73 while (!IsDevicePathEnd (DevicePathWalker)) {
74 if (DevicePathType (DevicePathWalker) == MESSAGING_DEVICE_PATH) {
75 SubType = DevicePathSubType (DevicePathWalker);
76 switch (SubType) {
77 case MSG_SATA_DP:
78 //
79 // Check if this SATA Bus has a CD connected.
80 //
81 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
82 if ( !IsDevicePathEnd (DevicePathWalker)
83 && (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH)
84 && (DevicePathSubType (DevicePathWalker) == MEDIA_CDROM_DP))
85 {
86 if (External != NULL) {
87 *External = TRUE;
88 }
89 }
90
92 case MSG_SASEX_DP:
94 case MSG_SCSI_DP:
97 case MSG_NVME_NAMESPACE_DP:
99 case MSG_ATAPI_DP:
100 //
101 // Check if this ATA Bus has HDD connected.
102 // DVD will have NO_DISK_SIGNATURE at least for our DuetPkg.
103 //
104 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
105 HardDrive = (HARDDRIVE_DEVICE_PATH *)DevicePathWalker;
106 if ( !IsDevicePathEnd (DevicePathWalker)
107 && (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH)
108 && (DevicePathSubType (DevicePathWalker) == MEDIA_HARDDRIVE_DP)
109 && ( (HardDrive->SignatureType == SIGNATURE_TYPE_MBR)
110 || (HardDrive->SignatureType == SIGNATURE_TYPE_GUID)))
111 {
113 }
114
115 //
116 // Assume this is DVD/CD.
117 //
118 if (External != NULL) {
119 *External = TRUE;
120 }
121
123 case MSG_USB_DP:
124 if (External != NULL) {
125 *External = TRUE;
126 }
127
129 case MSG_1394_DP:
130 if (External != NULL) {
131 *External = TRUE;
132 }
133
135 case MSG_SD_DP:
136 case MSG_EMMC_DP:
137 if (External != NULL) {
138 *External = TRUE;
139 }
140
142 }
143
144 //
145 // We do not have good protection against device tunneling.
146 // These things must be considered:
147 // - Thunderbolt 2 PCI-e pass-through
148 // - Thunderbolt 3 PCI-e pass-through (Type-C, may be different from 2)
149 // - FireWire devices
150 // For now we hope that first messaging type protects us, and all
151 // subsequent messaging types are tunneled.
152 //
153
154 break;
155 }
156
157 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
158 }
159
160 DevicePathWalker = DevicePath;
161 while (!IsDevicePathEnd (DevicePathWalker)) {
162 if (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH) {
164 }
165
166 if (DevicePathType (DevicePathWalker) == ACPI_DEVICE_PATH) {
167 Acpi = (ACPI_HID_DEVICE_PATH *)DevicePathWalker;
168 if ( ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST)
169 && (EISA_ID_TO_NUM (Acpi->HID) == 0x0A03))
170 {
171 //
172 // Allow PciRoot.
173 //
174 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
175 continue;
176 }
177 } else if ( (DevicePathType (DevicePathWalker) == HARDWARE_DEVICE_PATH)
178 && (DevicePathSubType (DevicePathWalker) == HW_PCI_DP))
179 {
180 //
181 // Allow Pci.
182 //
183 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
184 continue;
185 } else if ( (DevicePathType (DevicePathWalker) == MESSAGING_DEVICE_PATH)
186 && (DevicePathSubType (DevicePathWalker) == MSG_DEVICE_LOGICAL_UNIT_DP))
187 {
188 //
189 // Each device may have multiple units.
190 // E.g. PciRoot(0x0)/Pci(0x1B,0x4)/Pci(0x0,0x0)/Unit(0x1)/HD(...)
191 //
192 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
193 continue;
194 }
195
196 //
197 // Forbid everything else.
198 //
199 break;
200 }
201
202 return 0;
203}
204
210 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }
211};
212
214 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }
215};
216
218 0xDE94BBA4, 0x06D1, 0x4D40, { 0xA1, 0x6A, 0xBF, 0xD5, 0x01, 0x79, 0xD6, 0xAC }
219};
220
227 0x44479540, 0xF297, 0x41B2, { 0x9A, 0xF7, 0xD1, 0x31, 0xD5, 0xF0, 0x45, 0x8A }
228};
229
231 0x4F68BCE3, 0xE8CD, 0x4DB1, { 0x96, 0xE7, 0xFB, 0xCA, 0xF9, 0x84, 0xB7, 0x09 }
232};
233
235 0x0FC63DAF, 0x8483, 0x4772, { 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4 }
236};
237
243 0xBC13C2FF, 0x59E6, 0x4262, { 0xA3, 0x52, 0xB2, 0x75, 0xFD, 0x6F, 0x71, 0x72 }
244};
245
246UINT32
248 IN EFI_HANDLE Handle
249 )
250{
251 CONST EFI_PARTITION_ENTRY *PartitionEntry;
252
253 PartitionEntry = OcGetGptPartitionEntry (Handle);
254
255 if (PartitionEntry == NULL) {
256 DEBUG ((DEBUG_INFO, "OCB: Missing partition info for %p\n", Handle));
257 return 0;
258 }
259
260 if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &gAppleApfsPartitionTypeGuid)) {
262 }
263
264 if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)) {
266 }
267
268 if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &mXBootLdrPartitionTypeGuid)) {
270 }
271
272 //
273 // Unsure whether these two should be separate, likely not.
274 //
275 if ( CompareGuid (&PartitionEntry->PartitionTypeGUID, &gAppleHfsPartitionTypeGuid)
276 || CompareGuid (&PartitionEntry->PartitionTypeGUID, &gAppleHfsBootPartitionTypeGuid))
277 {
279 }
280
281 if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &mMsftBasicDataPartitionTypeGuid)) {
283 }
284
285 if ( CompareGuid (&PartitionEntry->PartitionTypeGUID, &mLinuxRootX86PartitionTypeGuid)
286 || CompareGuid (&PartitionEntry->PartitionTypeGUID, &mLinuxRootX8664PartitionTypeGuid))
287 {
289 }
290
291 if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &mLinuxFileSystemPartitionTypeGuid)) {
293 }
294
295 return 0;
296}
297
298EFI_STATUS
300 IN EFI_HANDLE Handle,
301 IN UINT32 Policy,
302 OUT BOOLEAN *External OPTIONAL
303 )
304{
305 UINT32 DevicePolicy;
306 UINT32 FileSystemPolicy;
307
308 //
309 // Always request policy type due to external checks.
310 //
311 DevicePolicy = OcGetDevicePolicyType (Handle, External);
312 if (((Policy & OC_SCAN_DEVICE_LOCK) != 0) && ((Policy & DevicePolicy) == 0)) {
313 DEBUG ((DEBUG_INFO, "OCB: Invalid device policy (%x/%x) for %p\n", DevicePolicy, Policy, Handle));
314 return EFI_SECURITY_VIOLATION;
315 }
316
317 if ((Policy & OC_SCAN_FILE_SYSTEM_LOCK) != 0) {
318 FileSystemPolicy = OcGetFileSystemPolicyType (Handle);
319
320 if ((Policy & FileSystemPolicy) == 0) {
321 DEBUG ((DEBUG_INFO, "OCB: Invalid file system policy (%x/%x) for %p\n", FileSystemPolicy, Policy, Handle));
322 return EFI_SECURITY_VIOLATION;
323 }
324 }
325
326 return EFI_SUCCESS;
327}
328
331 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
332 OUT BOOLEAN *IsFolder OPTIONAL,
333 OUT BOOLEAN *IsGeneric OPTIONAL
334 )
335{
336 CHAR16 *Path;
337 UINTN PathLen;
338 UINTN RestLen;
339 UINTN Index;
340
341 Path = NULL;
342
343 if (IsGeneric != NULL) {
344 *IsGeneric = FALSE;
345 }
346
347 if (IsFolder != NULL) {
348 *IsFolder = FALSE;
349 }
350
351 //
352 // Detect firmware images such as the Apple legacy loader interface.
353 //
354 // Certain Mac models lock up if any additional probing of the device path
355 // is performed when the Apple legacy loader interface is being started.
356 //
357 if ((DevicePath->Type == MEDIA_DEVICE_PATH) && (DevicePath->SubType == MEDIA_PIWG_FW_FILE_DP)) {
358 return OC_BOOT_UNKNOWN;
359 }
360
361 Path = OcCopyDevicePathFullName (DevicePath, NULL);
362 if (Path == NULL) {
363 return OC_BOOT_UNKNOWN;
364 }
365
366 PathLen = StrLen (Path);
367
368 //
369 // Use the trailing character to determine folder.
370 //
371 if ((IsFolder != NULL) && (Path[PathLen - 1] == L'\\')) {
372 *IsFolder = TRUE;
373 }
374
375 //
376 // Detect macOS recovery by com.apple.recovery.boot in the bootloader path.
377 //
378 if (OcStrStrLength (Path, PathLen, L"com.apple.recovery.boot", L_STR_LEN (L"com.apple.recovery.boot")) != NULL) {
379 FreePool (Path);
381 }
382
383 if (OcStrStrLength (Path, PathLen, L"EFI\\APPLE", L_STR_LEN (L"EFI\\APPLE")) != NULL) {
384 FreePool (Path);
386 }
387
388 //
389 // Detect macOS by boot.efi in the bootloader name.
390 // Detect macOS Time Machine by tmbootpicker.efi in the bootloader name.
391 //
392 STATIC CONST CHAR16 *Bootloaders[] = {
393 L"boot.efi",
394 L"tmbootpicker.efi",
395 L"bootmgfw.efi"
396 };
397
398 STATIC CONST UINTN BootloaderLengths[] = {
399 L_STR_LEN (L"boot.efi"),
400 L_STR_LEN (L"tmbootpicker.efi"),
401 L_STR_LEN (L"bootmgfw.efi")
402 };
403
404 STATIC CONST OC_BOOT_ENTRY_TYPE BootloaderTypes[] = {
408 };
409
410 for (Index = 0; Index < ARRAY_SIZE (Bootloaders); ++Index) {
411 if (PathLen < BootloaderLengths[Index]) {
412 continue;
413 }
414
415 RestLen = PathLen - BootloaderLengths[Index];
416 if ( ((RestLen == 0) || (Path[RestLen - 1] == L'\\'))
417 && (OcStrniCmp (&Path[RestLen], Bootloaders[Index], BootloaderLengths[Index]) == 0))
418 {
419 FreePool (Path);
420 return BootloaderTypes[Index];
421 }
422 }
423
424 CONST CHAR16 *GenericBootloader = &EFI_REMOVABLE_MEDIA_FILE_NAME[L_STR_LEN (L"\\EFI\\BOOT\\")];
425 CONST UINTN GenericBootloaderLength = L_STR_LEN (EFI_REMOVABLE_MEDIA_FILE_NAME) - L_STR_LEN (L"\\EFI\\BOOT\\");
426
427 if ((IsGeneric != NULL) && (PathLen >= GenericBootloaderLength)) {
428 RestLen = PathLen - GenericBootloaderLength;
429 if ( ((RestLen == 0) || (Path[RestLen - 1] == L'\\'))
430 && (OcStrniCmp (&Path[RestLen], GenericBootloader, GenericBootloaderLength) == 0))
431 {
432 *IsGeneric = TRUE;
433 }
434 }
435
436 FreePool (Path);
437 return OC_BOOT_UNKNOWN;
438}
439
440EFI_LOADED_IMAGE_PROTOCOL *
442 IN EFI_HANDLE ImageHandle
443 )
444{
445 EFI_STATUS Status;
446 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
447
448 Status = gBS->HandleProtocol (
449 ImageHandle,
451 (VOID **)&LoadedImage
452 );
453
454 if ( !EFI_ERROR (Status)
455 && (LoadedImage->FilePath != NULL)
456 && ((OcGetBootDevicePathType (LoadedImage->FilePath, NULL, NULL) & OC_BOOT_APPLE_ANY) != 0))
457 {
458 return LoadedImage;
459 }
460
461 return NULL;
462}
EFI_GUID gAppleApfsPartitionTypeGuid
EFI_GUID gAppleHfsBootPartitionTypeGuid
EFI_GUID gAppleHfsPartitionTypeGuid
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
#define OC_SCAN_ALLOW_DEVICE_SASEX
#define OC_SCAN_ALLOW_DEVICE_ATAPI
#define OC_SCAN_ALLOW_DEVICE_FIREWIRE
#define OC_BOOT_APPLE_TIME_MACHINE
#define OC_SCAN_ALLOW_FS_HFS
#define OC_SCAN_ALLOW_FS_LINUX_DATA
#define OC_SCAN_ALLOW_DEVICE_SATA
#define OC_SCAN_DEVICE_LOCK
#define OC_SCAN_ALLOW_DEVICE_NVME
#define OC_BOOT_APPLE_ANY
UINT32 OC_BOOT_ENTRY_TYPE
#define OC_SCAN_ALLOW_DEVICE_USB
#define OC_BOOT_APPLE_RECOVERY
#define OC_SCAN_ALLOW_DEVICE_SDCARD
#define OC_BOOT_WINDOWS
#define OC_BOOT_APPLE_OS
#define OC_BOOT_UNKNOWN
#define OC_SCAN_ALLOW_FS_LINUX_ROOT
#define OC_SCAN_ALLOW_DEVICE_SCSI
#define OC_BOOT_APPLE_FW_UPDATE
#define OC_SCAN_FILE_SYSTEM_LOCK
#define OC_SCAN_ALLOW_FS_ESP
#define OC_SCAN_ALLOW_FS_APFS
#define OC_SCAN_ALLOW_FS_NTFS
#define OC_SCAN_ALLOW_FS_XBOOTLDR
#define OC_SCAN_ALLOW_DEVICE_PCI
EFI_BOOT_SERVICES * gBS
#define MSG_APPLE_NVME_NAMESPACE_DP
CHAR16 * OcCopyDevicePathFullName(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT EFI_DEVICE_PATH_PROTOCOL **FileDevicePath OPTIONAL)
CONST EFI_PARTITION_ENTRY * OcGetGptPartitionEntry(IN EFI_HANDLE FsHandle)
Definition DiskMisc.c:732
#define L_STR_LEN(String)
Definition OcStringLib.h:26
INTN EFIAPI OcStrniCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString, IN UINTN Length)
CONST CHAR16 * OcStrStrLength(IN CONST CHAR16 *String, IN UINTN StringLength, IN CONST CHAR16 *SearchString, IN UINTN SearchStringLength)
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
UINT32 OcGetFileSystemPolicyType(IN EFI_HANDLE Handle)
EFI_LOADED_IMAGE_PROTOCOL * OcGetAppleBootLoadedImage(IN EFI_HANDLE ImageHandle)
EFI_GUID mXBootLdrPartitionTypeGuid
EFI_GUID mLinuxRootX86PartitionTypeGuid
EFI_GUID mMsftRecoveryPartitionTypeGuid
EFI_GUID mLinuxFileSystemPartitionTypeGuid
OC_BOOT_ENTRY_TYPE OcGetBootDevicePathType(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT BOOLEAN *IsFolder OPTIONAL, OUT BOOLEAN *IsGeneric OPTIONAL)
EFI_GUID mLinuxRootX8664PartitionTypeGuid
UINT32 OcGetDevicePolicyType(IN EFI_HANDLE Handle, OUT BOOLEAN *External OPTIONAL)
EFI_GUID mMsftBasicDataPartitionTypeGuid
EFI_GUID mMsftReservedPartitionTypeGuid
EFI_STATUS InternalCheckScanPolicy(IN EFI_HANDLE Handle, IN UINT32 Policy, OUT BOOLEAN *External OPTIONAL)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
EFI_GUID gEfiLoadedImageProtocolGuid
EFI_GUID gEfiDevicePathProtocolGuid