Skip to content

Commit 5f15e83

Browse files
authored
OcPeCoffExtLib: Add support for FixupAppleEfiImages quirk (#498)
1 parent dd5b954 commit 5f15e83

File tree

17 files changed

+1000
-6
lines changed

17 files changed

+1000
-6
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ OpenCore Changelog
55
- Fixed hang while generating boot entries on some systems
66
- Added `efidebug.tool` support for 32-bit on 32-bit using GDB or LLDB
77
- Fixed potential incorrect values in kernel image capabilities calculation
8+
- Added `FixupAppleEfiImages` quirk to allow booting Mac OS X 10.4 and 10.5 boot.efi images on modern secure image loaders
89

910
#### v0.9.5
1011
- Fixed GUID formatting for legacy NVRAM saving

Docs/Configuration.tex

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,34 @@ \subsection{Quirks Properties}\label{booterpropsquirks}
16101610
\texttt{RebuildAppleMemoryMap} if the firmware supports memory attributes table (MAT).
16111611
Refer to the \texttt{OCABC: MAT support is 1/0} log entry to determine whether MAT is supported.
16121612

1613+
\item
1614+
\texttt{FixupAppleEfiImages}\\
1615+
\textbf{Type}: \texttt{plist\ boolean}\\
1616+
\textbf{Failsafe}: \texttt{false}\\
1617+
\textbf{Description}: Fix errors in early Mac OS X boot.efi images.
1618+
1619+
Modern secure PE loaders will refuse to load \texttt{boot.efi} images from
1620+
Mac OS X 10.4 and 10.5 due to these files containing \texttt{W\^{}X} errors
1621+
and illegal overlapping sections.
1622+
1623+
This quirk detects these issues and pre-processes such images in memory,
1624+
so that a modern loader can accept them.
1625+
1626+
Pre-processing in memory is incompatible with secure boot, as the image loaded
1627+
is not the image on disk, so you cannot sign files which are loaded in this way
1628+
based on their original disk image contents.
1629+
Certain firmware will offer to register the hash of new, unknown images - this would
1630+
still work. On the other hand, it is not particularly realistic to want to
1631+
start such early, insecure images with secure boot anyway.
1632+
1633+
\emph{Note 1}: The quirk is only applied to Apple-specific `fat' (both 32-bit and 64-bit
1634+
versions in one image) \texttt{.efi} files, and is never applied during the Apple secure
1635+
boot path for newer macOS.
1636+
1637+
\emph{Note 2}: The quirk is only needed for loading Mac OS X 10.4 and 10.5, and even then
1638+
only if the firmware itself includes a modern, more secure PE COFF image loader. This includes
1639+
current builds of OpenDuet.
1640+
16131641
\item
16141642
\texttt{ForceBooterSignature}\\
16151643
\textbf{Type}: \texttt{plist\ boolean}\\

Docs/Sample.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@
319319
<true/>
320320
<key>EnableWriteUnprotector</key>
321321
<true/>
322+
<key>FixupAppleEfiImages</key>
323+
<false/>
322324
<key>ForceBooterSignature</key>
323325
<false/>
324326
<key>ForceExitBootServices</key>

Docs/SampleCustom.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@
319319
<true/>
320320
<key>EnableWriteUnprotector</key>
321321
<true/>
322+
<key>FixupAppleEfiImages</key>
323+
<false/>
322324
<key>ForceBooterSignature</key>
323325
<false/>
324326
<key>ForceExitBootServices</key>

Include/Acidanthera/Library/OcBootManagementLib.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1814,7 +1814,8 @@ OcRegisterBootstrapBootOption (
18141814
**/
18151815
VOID
18161816
OcImageLoaderInit (
1817-
IN CONST BOOLEAN ProtectUefiServices
1817+
IN CONST BOOLEAN ProtectUefiServices,
1818+
IN CONST BOOLEAN FixupAppleEfiImages
18181819
);
18191820

18201821
/**

Include/Acidanthera/Library/OcConfigurationLib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ OC_DECLARE (OC_BOOTER_PATCH_ARRAY)
142142
_(BOOLEAN , DiscardHibernateMap , , FALSE , ()) \
143143
_(BOOLEAN , EnableSafeModeSlide , , FALSE , ()) \
144144
_(BOOLEAN , EnableWriteUnprotector , , FALSE , ()) \
145+
_(BOOLEAN , FixupAppleEfiImages , , FALSE , ()) \
145146
_(BOOLEAN , ForceBooterSignature , , FALSE , ()) \
146147
_(BOOLEAN , ForceExitBootServices , , FALSE , ()) \
147148
_(BOOLEAN , ProtectMemoryRegions , , FALSE , ()) \

Include/Acidanthera/Library/OcPeCoffExtLib.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,19 @@ PeCoffGetApfsDriverVersion (
4343
OUT APFS_DRIVER_VERSION **DriverVersionPtr
4444
);
4545

46+
/**
47+
Detect and patch W^X and section overlap errors in legacy boot.efi.
48+
Expected to make changes in 10.4 and 10.5 only.
49+
50+
@param[in] DriverBuffer Image buffer.
51+
@param[in] DriverSize Size of the image.
52+
53+
@retval EFI_SUCCESS on success.
54+
**/
55+
EFI_STATUS
56+
OcPatchLegacyEfi (
57+
IN VOID *DriverBuffer,
58+
IN UINT32 DriverSize
59+
);
60+
4661
#endif // OC_PE_COFF_EXT_LIB_H

Library/OcBootManagementLib/ImageLoader.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <Library/OcFileLib.h>
3737
#include <Library/OcMachoLib.h>
3838
#include <Library/OcMiscLib.h>
39+
#include <Library/OcPeCoffExtLib.h>
3940
#include <Library/OcStringLib.h>
4041
#include <Library/UefiImageLib.h>
4142
#include <Library/UefiBootServicesTableLib.h>
@@ -82,6 +83,7 @@ STATIC EFI_HANDLE mImageLoaderCapsHandle;
8283
STATIC BOOLEAN mImageLoaderEnabled;
8384

8485
STATIC BOOLEAN mProtectUefiServices;
86+
STATIC BOOLEAN mFixupAppleEfiImages;
8587

8688
STATIC EFI_IMAGE_LOAD mPreservedLoadImage;
8789
STATIC EFI_IMAGE_START mPreservedStartImage;
@@ -865,6 +867,26 @@ InternalEfiLoadImage (
865867
// Determine its capabilities.
866868
//
867869
if (!EFI_ERROR (Status) && (RealSize != SourceSize) && (RealSize >= EFI_PAGE_SIZE)) {
870+
if (mFixupAppleEfiImages) {
871+
if (SecureBootStatus == EFI_SUCCESS) {
872+
DEBUG ((DEBUG_INFO, "OCB: Secure boot, fixup legacy efi ignored\n"));
873+
} else {
874+
Status = OcPatchLegacyEfi (SourceBuffer, RealSize);
875+
//
876+
// Error can mean incompletely patched image, so we should fail.
877+
// Any error not the result of incomplete patching would in general not load anyway.
878+
//
879+
if (EFI_ERROR (Status)) {
880+
DEBUG ((DEBUG_WARN, "OCB: PatchLegacyEfi - %r\n", Status));
881+
if (AllocatedBuffer != NULL) {
882+
FreePool (AllocatedBuffer);
883+
}
884+
885+
return Status;
886+
}
887+
}
888+
}
889+
868890
mImageLoaderCaps = DetectCapabilities (SourceBuffer, RealSize);
869891
}
870892

@@ -1087,10 +1109,12 @@ InternalEfiExit (
10871109

10881110
VOID
10891111
OcImageLoaderInit (
1090-
IN CONST BOOLEAN ProtectUefiServices
1112+
IN CONST BOOLEAN ProtectUefiServices,
1113+
IN CONST BOOLEAN FixupAppleEfiImages
10911114
)
10921115
{
10931116
mProtectUefiServices = ProtectUefiServices;
1117+
mFixupAppleEfiImages = FixupAppleEfiImages;
10941118

10951119
mOriginalEfiLoadImage = gBS->LoadImage;
10961120
mOriginalEfiStartImage = gBS->StartImage;

Library/OcBootManagementLib/OcBootManagementLib.inf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
OcFlexArrayLib
111111
OcMachoLib
112112
OcMiscLib
113+
OcPeCoffExtLib
113114
OcRtcLib
114115
OcTypingLib
115116
OcVariableLib

Library/OcConfigurationLib/OcConfigurationLib.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ OC_SCHEMA
189189
OC_SCHEMA_BOOLEAN_IN ("DiscardHibernateMap", OC_GLOBAL_CONFIG, Booter.Quirks.DiscardHibernateMap),
190190
OC_SCHEMA_BOOLEAN_IN ("EnableSafeModeSlide", OC_GLOBAL_CONFIG, Booter.Quirks.EnableSafeModeSlide),
191191
OC_SCHEMA_BOOLEAN_IN ("EnableWriteUnprotector", OC_GLOBAL_CONFIG, Booter.Quirks.EnableWriteUnprotector),
192+
OC_SCHEMA_BOOLEAN_IN ("FixupAppleEfiImages", OC_GLOBAL_CONFIG, Booter.Quirks.FixupAppleEfiImages),
192193
OC_SCHEMA_BOOLEAN_IN ("ForceBooterSignature", OC_GLOBAL_CONFIG, Booter.Quirks.ForceBooterSignature),
193194
OC_SCHEMA_BOOLEAN_IN ("ForceExitBootServices", OC_GLOBAL_CONFIG, Booter.Quirks.ForceExitBootServices),
194195
OC_SCHEMA_BOOLEAN_IN ("ProtectMemoryRegions", OC_GLOBAL_CONFIG, Booter.Quirks.ProtectMemoryRegions),

Library/OcMainLib/OpenCoreUefi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,7 @@ OcLoadUefiSupport (
899899

900900
OcReinstallProtocols (Config);
901901

902-
OcImageLoaderInit (Config->Booter.Quirks.ProtectUefiServices);
902+
OcImageLoaderInit (Config->Booter.Quirks.ProtectUefiServices, Config->Booter.Quirks.FixupAppleEfiImages);
903903

904904
OcLoadAppleSecureBoot (Config, CpuInfo);
905905

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/** @file
2+
Provides shared private definitions across this library.
3+
4+
Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
5+
Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
6+
Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
7+
8+
SPDX-License-Identifier: BSD-3-Clause
9+
**/
10+
11+
#ifndef BASE_PE_COFF_LIB2_INTERNALS_H_
12+
#define BASE_PE_COFF_LIB2_INTERNALS_H_
13+
14+
//
15+
// PcdImageLoaderRelocTypePolicy bits.
16+
//
17+
18+
///
19+
/// If set, ARM Thumb Image relocations are supported.
20+
///
21+
#define PCD_RELOC_TYPE_POLICY_ARM BIT0
22+
23+
///
24+
/// Denotes the alignment requirement for Image certificate sizes.
25+
///
26+
#define IMAGE_CERTIFICATE_ALIGN 8U
27+
28+
//
29+
// The PE/COFF specification guarantees an 8 Byte alignment for certificate
30+
// sizes. This is larger than the alignment requirement for WIN_CERTIFICATE
31+
// implied by the UEFI ABI. ASSERT this holds.
32+
//
33+
STATIC_ASSERT (
34+
ALIGNOF (WIN_CERTIFICATE) <= IMAGE_CERTIFICATE_ALIGN,
35+
"The PE/COFF specification guarantee does not suffice."
36+
);
37+
38+
//
39+
// The 4 Byte alignment guaranteed by the PE/COFF specification has been
40+
// replaced with ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK) for proof simplicity.
41+
// This obviously was the original intention of the specification. ASSERT in
42+
// case the equality is not given.
43+
//
44+
STATIC_ASSERT (
45+
sizeof (UINT32) == ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK),
46+
"The current model violates the PE/COFF specification"
47+
);
48+
49+
// FIXME:
50+
RETURN_STATUS
51+
PeCoffLoadImageInplaceNoBase (
52+
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
53+
);
54+
55+
#endif // BASE_PE_COFF_LIB_INTERNALS_H_

Library/OcPeCoffExtLib/OcPeCoffExtInternal.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,31 @@ typedef struct APPLE_SIGNATURE_CONTEXT_ {
2929
UINT8 Signature[256];
3030
} APPLE_SIGNATURE_CONTEXT;
3131

32+
/**
33+
Fix W^X and section overlap issues in loaded TE, PE32, or PE32+ Image in
34+
memory while initialising Context.
35+
36+
Closely based on PeCoffInitializeContext from PeCoffLib2.
37+
38+
The approach of modifying the image in memory is basically incompatible
39+
with secure boot, athough:
40+
a) Certain firmware may allow optionally registering the hash of any
41+
image which does not load, which would still work.
42+
b) It is fairly crazy anyway to want to apply secure boot to the old,
43+
insecure .efi files which need these fixups.
44+
45+
@param[out] Context The context describing the Image.
46+
@param[in] FileBuffer The file data to parse as PE Image.
47+
@param[in] FileSize The size, in Bytes, of FileBuffer.
48+
49+
@retval RETURN_SUCCESS The Image context has been initialised successfully.
50+
@retval other The file data is malformed.
51+
**/
52+
RETURN_STATUS
53+
InternalPeCoffFixup (
54+
OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
55+
IN CONST VOID *FileBuffer,
56+
IN UINT32 FileSize
57+
);
58+
3259
#endif // OC_PE_COFF_EXT_INTERNAL_H

Library/OcPeCoffExtLib/OcPeCoffExtLib.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
3333
#include <Library/UefiLib.h>
3434
#include <Library/OcCryptoLib.h>
3535
#include <Library/OcAppleKeysLib.h>
36+
#include <Library/OcStringLib.h>
3637
#include <Guid/AppleCertificate.h>
3738

3839
#include "OcPeCoffExtInternal.h"
@@ -493,7 +494,7 @@ PeCoffGetApfsDriverVersion (
493494
|| (ImageContext.ImageType != PeCoffLoaderTypePe32Plus)
494495
|| (ImageContext.Subsystem != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER))
495496
{
496-
DEBUG ((DEBUG_INFO, "OCPE: PeCoff unsupported image\n"));
497+
DEBUG ((DEBUG_INFO, "OCPE: PeCoff apfs unsupported image\n"));
497498
return EFI_UNSUPPORTED;
498499
}
499500

@@ -541,3 +542,25 @@ PeCoffGetApfsDriverVersion (
541542
*DriverVersionPtr = DriverVersion;
542543
return EFI_SUCCESS;
543544
}
545+
546+
EFI_STATUS
547+
OcPatchLegacyEfi (
548+
IN VOID *DriverBuffer,
549+
IN UINT32 DriverSize
550+
)
551+
{
552+
EFI_STATUS ImageStatus;
553+
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
554+
555+
ImageStatus = InternalPeCoffFixup (
556+
&ImageContext,
557+
DriverBuffer,
558+
DriverSize
559+
);
560+
if (EFI_ERROR (ImageStatus)) {
561+
DEBUG ((DEBUG_WARN, "OCPE: PeCoff legacy patch failure - %r\n", ImageStatus));
562+
return EFI_UNSUPPORTED;
563+
}
564+
565+
return EFI_SUCCESS;
566+
}

Library/OcPeCoffExtLib/OcPeCoffExtLib.inf

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@
2525

2626

2727
#
28-
# VALID_ARCHITECTURES = X64
28+
# VALID_ARCHITECTURES = IA32 X64
2929
#
3030

3131
[Sources]
3232
OcPeCoffExtInternal.h
3333
OcPeCoffExtLib.c
34+
OcPeCoffFixup.c
3435

3536
[Packages]
3637
MdePkg/MdePkg.dec
@@ -48,7 +49,13 @@
4849
DebugLib
4950
OcAppleKeysLib
5051
OcCryptoLib
52+
OcStringLib
5153

5254
[Guids]
5355
gAppleEfiCertificateGuid
5456
gEfiCertTypeRsa2048Sha256Guid
57+
58+
[FixedPcd]
59+
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAlignmentPolicy
60+
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset
61+
gEfiMdePkgTokenSpaceGuid.PcdDebugRaisePropertyMask

0 commit comments

Comments
 (0)