Untitled diff

Created Diff never expires
11 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
621 lines
41 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
651 lines
/**
/**
UEFI driver for enabling loading of OSX without memory relocation.
UEFI driver for enabling loading of OSX without memory relocation.
by dmazar
by dmazar
**/
**/


#include <Library/UefiLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/DebugLib.h>
#include <Library/CpuLib.h>
#include <Library/CpuLib.h>


#include <Guid/GlobalVariable.h>
#include <Guid/GlobalVariable.h>


#include <Protocol/LoadedImage.h>
#include <Protocol/LoadedImage.h>


#include "BootFixes.h"
#include "BootFixes3.h"
#include "DecodedKernelCheck.h"
#include "DecodedKernelCheck.h"
#include "BootArgs.h"
#include "BootArgs.h"
#include "AsmFuncs.h"
#include "AsmFuncs.h"
#include "VMem.h"
#include "VMem.h"
#include "Lib.h"
#include "Lib.h"
#include "Hibernate.h"
#include "Hibernate.h"
#include "NVRAMDebug.h"
#include "NVRAMDebug.h"


#include "RTShims.h"


// DBG_TO: 0=no debug, 1=serial, 2=console
// DBG_TO: 0=no debug, 1=serial, 2=console
// serial requires
// serial requires
// [PcdsFixedAtBuild]
// [PcdsFixedAtBuild]
// gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07
// gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07
// gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xFFFFFFFF
// gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xFFFFFFFF
// in package DSC file
// in package DSC file
#define DBG_TO 0
#define DBG_TO 0


#if DBG_TO == 2
#if DBG_TO == 2
#define DBG(...) AsciiPrint(__VA_ARGS__);
#define DBG(...) AsciiPrint(__VA_ARGS__);
#elif DBG_TO == 1
#elif DBG_TO == 1
#define DBG(...) DebugPrint(1, __VA_ARGS__);
#define DBG(...) DebugPrint(1, __VA_ARGS__);
#else
#else
#define DBG(...)
#define DBG(...)
#endif
#endif


#include "../Version.h"
#include "../Version.h"
CONST CHAR8* CloverRevision = REVISION_STR;
CONST CHAR8* CloverRevision = REVISION_STR;
STATIC UINTN Counter = 0;
STATIC UINTN Counter = 0;




// TRUE if we are doing hibernate wake
// TRUE if we are doing hibernate wake
BOOLEAN gHibernateWake = FALSE;
BOOLEAN gHibernateWake = FALSE;




// placeholders for storing original Boot and RT Services functions
// placeholders for storing original Boot and RT Services functions
EFI_ALLOCATE_PAGES gStoredAllocatePages = NULL;
EFI_ALLOCATE_PAGES gStoredAllocatePages = NULL;
EFI_GET_MEMORY_MAP gStoredGetMemoryMap = NULL;
EFI_GET_MEMORY_MAP gStoredGetMemoryMap = NULL;
EFI_EXIT_BOOT_SERVICES gStoredExitBootServices = NULL;
EFI_EXIT_BOOT_SERVICES gStoredExitBootServices = NULL;
EFI_IMAGE_START gStartImage = NULL;
EFI_IMAGE_START gStartImage = NULL;
EFI_HANDLE_PROTOCOL gHandleProtocol = NULL;
EFI_HANDLE_PROTOCOL gHandleProtocol = NULL;
EFI_SET_VIRTUAL_ADDRESS_MAP gStoredSetVirtualAddressMap = NULL;
EFI_SET_VIRTUAL_ADDRESS_MAP gStoredSetVirtualAddressMap = NULL;
UINT32 OrgRTCRC32 = 0;
UINT32 OrgRTCRC32 = 0;




// monitoring AlocatePages
// monitoring AlocatePages
EFI_PHYSICAL_ADDRESS gMinAllocatedAddr = 0;
EFI_PHYSICAL_ADDRESS gMinAllocatedAddr = 0;
EFI_PHYSICAL_ADDRESS gMaxAllocatedAddr = 0;
EFI_PHYSICAL_ADDRESS gMaxAllocatedAddr = 0;


// relocation base address
// relocation base address
EFI_PHYSICAL_ADDRESS gRelocBase = 0;
EFI_PHYSICAL_ADDRESS gRelocBase = 0;
// relocation block size in pages
// relocation block size in pages
UINTN gRelocSizePages = 0;
UINTN gRelocSizePages = 0;


// location of memory allocated by boot.efi for hibernate image
// location of memory allocated by boot.efi for hibernate image
EFI_PHYSICAL_ADDRESS gHibernateImageAddress = 0;
EFI_PHYSICAL_ADDRESS gHibernateImageAddress = 0;


// last memory map obtained by boot.efi
// last memory map obtained by boot.efi
UINTN gLastMemoryMapSize = 0;
UINTN gLastMemoryMapSize = 0;
EFI_MEMORY_DESCRIPTOR *gLastMemoryMap = NULL;
EFI_MEMORY_DESCRIPTOR *gLastMemoryMap = NULL;
UINTN gLastDescriptorSize = 0;
UINTN gLastDescriptorSize = 0;
UINT32 gLastDescriptorVersion = 0;
UINT32 gLastDescriptorVersion = 0;


/** Helper function that calls GetMemoryMap() and returns new MapKey.
/** Helper function that calls GetMemoryMap() and returns new MapKey.
* Uses gStoredGetMemoryMap, so can be called only after gStoredGetMemoryMap is set.
* Uses gStoredGetMemoryMap, so can be called only after gStoredGetMemoryMap is set.
*/
*/
EFI_STATUS
EFI_STATUS
GetMemoryMapKey(OUT UINTN *MapKey)
GetMemoryMapKey(OUT UINTN *MapKey)
{
{
EFI_STATUS Status;
EFI_STATUS Status;
UINTN MemoryMapSize;
UINTN MemoryMapSize;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
UINTN DescriptorSize;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
UINT32 DescriptorVersion;
Status = GetMemoryMapAlloc(gStoredGetMemoryMap, &MemoryMapSize, &MemoryMap, MapKey, &DescriptorSize, &DescriptorVersion);
Status = GetMemoryMapAlloc(gStoredGetMemoryMap, &MemoryMapSize, &MemoryMap, MapKey, &DescriptorSize, &DescriptorVersion);
return Status;
return Status;
}
}


/** Helper function that calculates number of RT and MMIO pages from mem map. */
/** Helper function that calculates number of RT and MMIO pages from mem map. */
EFI_STATUS
EFI_STATUS
GetNumberOfRTPages(OUT UINTN *NumPages)
GetNumberOfRTPages(OUT UINTN *NumPages)
{
{
EFI_STATUS Status;
EFI_STATUS Status;
UINTN MemoryMapSize;
UINTN MemoryMapSize;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
UINTN MapKey;
UINTN MapKey;
UINTN DescriptorSize;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
UINT32 DescriptorVersion;
UINTN NumEntries;
UINTN NumEntries;
UINTN Index;
UINTN Index;
EFI_MEMORY_DESCRIPTOR *Desc;
EFI_MEMORY_DESCRIPTOR *Desc;
Status = GetMemoryMapAlloc(gBS->GetMemoryMap, &MemoryMapSize, &MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);
Status = GetMemoryMapAlloc(gBS->GetMemoryMap, &MemoryMapSize, &MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);
if (EFI_ERROR(Status)) {
if (EFI_ERROR(Status)) {
return Status;
return Status;
}
}
//
//
// Apply some fixes
// Apply some fixes
//
//
FixMemMap(MemoryMapSize, MemoryMap, DescriptorSize, DescriptorVersion);
FixMemMap(MemoryMapSize, MemoryMap, DescriptorSize, DescriptorVersion);
//
//
// Sum RT and MMIO areas - all that have runtime attribute
// Sum RT and MMIO areas - all that have runtime attribute
//
//
*NumPages = 0;
*NumPages = 0;
Desc = MemoryMap;
Desc = MemoryMap;
NumEntries = MemoryMapSize / DescriptorSize;
NumEntries = MemoryMapSize / DescriptorSize;
for (Index = 0; Index < NumEntries; Index++) {
for (Index = 0; Index < NumEntries; Index++) {
if ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0) {
if ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0) {
*NumPages += Desc->NumberOfPages;
*NumPages += Desc->NumberOfPages;
}
}
Desc = NEXT_MEMORY_DESCRIPTOR(Desc, DescriptorSize);
Desc = NEXT_MEMORY_DESCRIPTOR(Desc, DescriptorSize);
}
}
return Status;
return Status;
}
}




/** gBS->HandleProtocol override:
/** gBS->HandleProtocol override:
* Boot.efi requires EfiGraphicsOutputProtocol on ConOutHandle, but it is not present
* Boot.efi requires EfiGraphicsOutputProtocol on ConOutHandle, but it is not present
* there on Aptio 2.0. EfiGraphicsOutputProtocol exists on some other handle.
* there on Aptio 2.0. EfiGraphicsOutputProtocol exists on some other handle.
* If this is the case, we'll intercept that call and return EfiGraphicsOutputProtocol
* If this is the case, we'll intercept that call and return EfiGraphicsOutputProtocol
* from that other handle.
* from that other handle.
*/
*/
EFI_STATUS EFIAPI
EFI_STATUS EFIAPI
MOHandleProtocol(
MOHandleProtocol(
IN EFI_HANDLE Handle,
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN EFI_GUID *Protocol,
OUT VOID **Interface
OUT VOID **Interface
)
)
{
{
EFI_STATUS res;
EFI_STATUS res;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
// special handling if gEfiGraphicsOutputProtocolGuid is requested by boot.efi
// special handling if gEfiGraphicsOutputProtocolGuid is requested by boot.efi
if (CompareGuid(Protocol, &gEfiGraphicsOutputProtocolGuid)) {
if (CompareGuid(Protocol, &gEfiGraphicsOutputProtocolGuid)) {
res = gHandleProtocol(Handle, Protocol, Interface);
res = gHandleProtocol(Handle, Protocol, Interface);
if (res != EFI_SUCCESS) {
if (res != EFI_SUCCESS) {
// let's find it on some other handle
// let's find it on some other handle
res = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID**)&GraphicsOutput);
res = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID**)&GraphicsOutput);
if (res == EFI_SUCCESS) {
if (res == EFI_SUCCESS) {
// return it
// return it
*Interface = GraphicsOutput;
*Interface = GraphicsOutput;
// DBG("->HandleProtocol(%p, %s, %p) = %r (returning from other handle)\n", Handle, GuidStr(Protocol), *Interface, res);
// DBG("->HandleProtocol(%p, %s, %p) = %r (returning from other handle)\n", Handle, GuidStr(Protocol), *Interface, res);
DBGnvr("->HandleProtocol(%p, %s, %p) = %r (from other handle)\n", Handle, GuidStr(Protocol), *Interface, res);
DBGnvr("->HandleProtocol(%p, %s, %p) = %r (from other handle)\n", Handle, GuidStr(Protocol), *Interface, res);
return res;
return res;
}
}
}
}
DBGnvr("->HandleProtocol(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), *Interface, res);
DBGnvr("->HandleProtocol(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), *Interface, res);
} else {
} else {
res = gHandleProtocol(Handle, Protocol, Interface);
res = gHandleProtocol(Handle, Protocol, Interface);
}
}
// DBG("->HandleProtocol(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), *Interface, res);
// DBG("->HandleProtocol(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), *Interface, res);
return res;
return res;
}
}


/** gBS->AllocatePages override:
/** gBS->AllocatePages override:
* Returns pages from free memory block to boot.efi for kernel boot image.
* Returns pages from free memory block to boot.efi for kernel boot image.
*/
*/
EFI_STATUS
EFI_STATUS
EFIAPI
EFIAPI
MOAllocatePages (
MOAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
IN UINTN NumberOfPages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
IN OUT EFI_PHYSICAL_ADDRESS *Memory
)
)
{
{
EFI_STATUS Status;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS UpperAddr;
EFI_PHYSICAL_ADDRESS UpperAddr;
// EFI_PHYSICAL_ADDRESS MemoryIn;
// EFI_PHYSICAL_ADDRESS MemoryIn;
// BOOLEAN FromRelocBlock = FALSE;
// BOOLEAN FromRelocBlock = FALSE;
// MemoryIn = *Memory;
// MemoryIn = *Memory;
if (Type == AllocateAddress && MemoryType == EfiLoaderData) {
if (Type == AllocateAddress && MemoryType == EfiLoaderData) {
// called from boot.efi
// called from boot.efi
UpperAddr = *Memory + EFI_PAGES_TO_SIZE(NumberOfPages);
UpperAddr = *Memory + EFI_PAGES_TO_SIZE(NumberOfPages);
// store min and max mem - can be used later to determine start and end of kernel boot image
// store min and max mem - can be used later to determine start and end of kernel boot image
if (gMinAllocatedAddr == 0 || *Memory < gMinAllocatedAddr) gMinAllocatedAddr = *Memory;
if (gMinAllocatedAddr == 0 || *Memory < gMinAllocatedAddr) gMinAllocatedAddr = *Memory;
if (UpperAddr > gMaxAllocatedAddr) gMaxAllocatedAddr = UpperAddr;
if (UpperAddr > gMaxAllocatedAddr) gMaxAllocatedAddr = UpperAddr;
Status = gStoredAllocatePages(Type, MemoryType, NumberOfPages, Memory);
Status = gStoredAllocatePages(Type, MemoryType, NumberOfPages, Memory);
// FromRelocBlock = FALSE;
// FromRelocBlock = FALSE;
} else if (gHibernateWake && Type == AllocateAnyPages && MemoryType == EfiLoaderData) {
} else if (gHibernateWake && Type == AllocateAnyPages && MemoryType == EfiLoaderData) {
// called from boot.efi during hibernate wake
// called from boot.efi during hibernate wake
// first such allocation is for hibernate image
// first such allocation is for hibernate image
Status = gStoredAllocatePages(Type, MemoryType, NumberOfPages, Memory);
Status = gStoredAllocatePages(Type, MemoryType, NumberOfPages, Memory);
if (gHibernateImageAddress == 0 && Status == EFI_SUCCESS) {
if (gHibernateImageAddress == 0 && Status == EFI_SUCCESS) {
gHibernateImageAddress = *Memory;
gHibernateImageAddress = *Memory;
}
}
} else {
} else {
// default page allocation
// default page allocation
Status = gStoredAllocatePages(Type, MemoryType, NumberOfPages, Memory);
Status = gStoredAllocatePages(Type, MemoryType, NumberOfPages, Memory);
}
}
//DBG("AllocatePages(%s, %s, %x, %lx/%lx) = %r %c\n",
//DBG("AllocatePages(%s, %s, %x, %lx/%lx) = %r %c\n",
// EfiAllocateTypeDesc[Type], EfiMemoryTypeDesc[MemoryType], NumberOfPages, MemoryIn, *Memory, Status, FromRelocBlock ? L'+' : L' ');
// EfiAllocateTypeDesc[Type], EfiMemoryTypeDesc[MemoryType], NumberOfPages, MemoryIn, *Memory, Status, FromRelocBlock ? L'+' : L' ');
return Status;
return Status;
}
}




/** gBS->GetMemoryMap override:
/** gBS->GetMemoryMap override:
* Returns shrinked memory map. I think kernel can handle up to 128 entries.
* Returns shrinked memory map. I think kernel can handle up to 128 entries.
*/
*/
EFI_STATUS
EFI_STATUS
EFIAPI
EFIAPI
MOGetMemoryMap (
MOGetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
OUT UINTN *MapKey,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
OUT UINT32 *DescriptorVersion
)
)
{
{
EFI_STATUS Status;
EFI_STATUS Status;
Status = gStoredGetMemoryMap(MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
Status = gStoredGetMemoryMap(MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
//PrintMemMap(*MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
//PrintMemMap(*MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
DBGnvr("GetMemoryMap: %p = %r\n", MemoryMap, Status);
DBGnvr("GetMemoryMap: %p = %r\n", MemoryMap, Status);
if (Status == EFI_SUCCESS) {
if (Status == EFI_SUCCESS) {
FixMemMap(*MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
FixMemMap(*MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
ShrinkMemMap(MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
ShrinkMemMap(MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
//PrintMemMap(*MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
//PrintMemMap(*MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
// remember last/final memmap
// remember last/final memmap
gLastMemoryMapSize = *MemoryMapSize;
gLastMemoryMapSize = *MemoryMapSize;
gLastMemoryMap = MemoryMap;
gLastMemoryMap = MemoryMap;
gLastDescriptorSize = *DescriptorSize;
gLastDescriptorSize = *DescriptorSize;
gLastDescriptorVersion = *DescriptorVersion;
gLastDescriptorVersion = *DescriptorVersion;
}
}
return Status;
return Status;
}
}


/** gBS->ExitBootServices override:
/** gBS->ExitBootServices override:
* Patches kernel entry point with jump to our KernelEntryPatchJumpBack().
* Patches kernel entry point with jump to our KernelEntryPatchJumpBack().
*/
*/
EFI_STATUS
EFI_STATUS
EFIAPI
EFIAPI
MOExitBootServices (
MOExitBootServices (
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ImageHandle,
IN UINTN MapKey
IN UINTN MapKey
)
)
{
{
EFI_STATUS Status;
EFI_STATUS Status;
UINTN NewMapKey;
UINTN NewMapKey;
//UINTN SlideAddr = 0;
UINTN SlideAddr = 0;
//VOID *MachOImage = NULL;
VOID *MachOImage = NULL;
IOHibernateImageHeader *ImageHeader = NULL;
IOHibernateImageHeader *ImageHeader = NULL;
// we need hibernate image address for wake
// we need hibernate image address for wake
if (gHibernateWake && gHibernateImageAddress == 0) {
if (gHibernateWake && gHibernateImageAddress == 0) {
Print(L"OsxAptioFix2 error: Doing hibernate wake, but did not find hibernate image address.");
Print(L"OsxAptioFix3 error: Doing hibernate wake, but did not find hibernate image address.");
Print(L"... waiting 5 secs ...\n");
Print(L"... waiting 5 secs ...\n");
gBS->Stall(5000000);
gBS->Stall(5000000);
return EFI_INVALID_PARAMETER;
return EFI_INVALID_PARAMETER;
}
}
// for tests: we can just return EFI_SUCCESS and continue using Print for debug.
// for tests: we can just return EFI_SUCCESS and continue using Print for debug.
// Status = EFI_SUCCESS;
// Status = EFI_SUCCESS;
//Print(L"ExitBootServices()\n");
//Print(L"ExitBootServices()\n");
Status = gStoredExitBootServices(ImageHandle, MapKey);
Status = gStoredExitBootServices(ImageHandle, MapKey);
DBGnvr("ExitBootServices: = %r\n", Status);
DBGnvr("ExitBootServices: = %r\n", Status);
if (EFI_ERROR (Status)) {
if (EFI_ERROR (Status)) {
// just report error as var in nvram to be visible from OSX with "nvram -p"
// just report error as var in nvram to be visible from OSX with "nvram -p"
gRT->SetVariable(L"OsxAptioFixDrv-ErrorExitingBootServices",
gRT->SetVariable(L"OsxAptioFixDrv-ErrorExitingBootServices",
&gEfiAppleBootGuid,
&gEfiAppleBootGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
3,
3,
"Yes"
"Yes"
);
);
Status = GetMemoryMapKey(&NewMapKey);
Status = GetMemoryMapKey(&NewMapKey);
DBGnvr("ExitBootServices: GetMemoryMapKey = %r\n", Status);
DBGnvr("ExitBootServices: GetMemoryMapKey = %r\n", Status);
if (Status == EFI_SUCCESS) {
if (Status == EFI_SUCCESS) {
// we have latest mem map and NewMapKey
// we have latest mem map and NewMapKey
// we'll try again ExitBootServices with NewMapKey
// we'll try again ExitBootServices with NewMapKey
Status = gStoredExitBootServices(ImageHandle, NewMapKey);
Status = gStoredExitBootServices(ImageHandle, NewMapKey);
DBGnvr("ExitBootServices: 2nd try = %r\n", Status);
DBGnvr("ExitBootServices: 2nd try = %r\n", Status);
if (EFI_ERROR (Status)) {
if (EFI_ERROR (Status)) {
// Error!
// Error!
Print(L"OsxAptioFixDrv: Error ExitBootServices() 2nd try = Status: %r\n", Status);
Print(L"OsxAptioFixDrv: Error ExitBootServices() 2nd try = Status: %r\n", Status);
}
}
} else {
} else {
Print(L"OsxAptioFixDrv: Error ExitBootServices(), GetMemoryMapKey() = Status: %r\n", Status);
Print(L"OsxAptioFixDrv: Error ExitBootServices(), GetMemoryMapKey() = Status: %r\n", Status);
Status = EFI_INVALID_PARAMETER;
Status = EFI_INVALID_PARAMETER;
}
}
}
}
if (EFI_ERROR(Status)) {
if (EFI_ERROR(Status)) {
Print(L"... waiting 10 secs ...\n");
Print(L"... waiting 10 secs ...\n");
gBS->Stall(10*1000000);
gBS->Stall(10*1000000);
return Status;
return Status;
}
}
if (!gHibernateWake) {
if (!gHibernateWake) {
// normal boot
// normal boot
DBG("ExitBootServices: gMinAllocatedAddr: %lx, gMaxAllocatedAddr: %lx\n", gMinAllocatedAddr, gMaxAllocatedAddr);
DBG("ExitBootServices: gMinAllocatedAddr: %lx, gMaxAllocatedAddr: %lx\n", gMinAllocatedAddr, gMaxAllocatedAddr);
//SlideAddr = gMinAllocatedAddr - 0x100000;
SlideAddr = gMinAllocatedAddr - 0x100000;
//MachOImage = (VOID*)(UINTN)(SlideAddr + 0x200000);
MachOImage = (VOID*)(UINTN)(SlideAddr + 0x200000);
//KernelEntryFromMachOPatchJump(MachOImage, SlideAddr);
KernelEntryFromMachOPatchJump(MachOImage, SlideAddr);
} else {
} else {
// hibernate wake
// hibernate wake
// at this stage HIB section is not yet copied from sleep image to it's
// at this stage HIB section is not yet copied from sleep image to it's
// proper memory destination. so we'll patch entry point in sleep image.
// proper memory destination. so we'll patch entry point in sleep image.
ImageHeader = (IOHibernateImageHeader *)(UINTN)gHibernateImageAddress;
ImageHeader = (IOHibernateImageHeader *)(UINTN)gHibernateImageAddress;
KernelEntryPatchJump( ((UINT32)(UINTN)&(ImageHeader->fileExtentMap[0])) + ImageHeader->fileExtentMapSize + ImageHeader->restore1CodeOffset );
KernelEntryPatchJump( ((UINT32)(UINTN)&(ImageHeader->fileExtentMap[0])) + ImageHeader->fileExtentMapSize + ImageHeader->restore1CodeOffset );
}
}
return Status;
return Status;
}
}




/** gRT->SetVirtualAddressMap override:
/** gRT->SetVirtualAddressMap override:
* Fixes virtualizing of RT services.
* Fixes virtualizing of RT services.
*/
*/
EFI_STATUS EFIAPI
EFI_STATUS EFIAPI
OvrSetVirtualAddressMap(
OvrSetVirtualAddressMap(
IN UINTN MemoryMapSize,
IN UINTN MemoryMapSize,
IN UINTN DescriptorSize,
IN UINTN DescriptorSize,
IN UINT32 DescriptorVersion,
IN UINT32 DescriptorVersion,
IN EFI_MEMORY_DESCRIPTOR *VirtualMap
IN EFI_MEMORY_DESCRIPTOR *VirtualMap
)
)
{
{
EFI_STATUS Status;
EFI_STATUS Status;
UINT32 EfiSystemTable;
UINT32 EfiSystemTable;
DBG("->SetVirtualAddressMap(%d, %d, 0x%x, %p) START ...\n", MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
DBG("->SetVirtualAddressMap(%d, %d, 0x%x, %p) START ...\n", MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
DBGnvr("->SetVirtualAddressMap(%d, %d, 0x%x, %p) START ...\n", MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
DBGnvr("->SetVirtualAddressMap(%d, %d, 0x%x, %p) START ...\n", MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
// restore origs
// restore origs
gRT->Hdr.CRC32 = OrgRTCRC32;
gRT->Hdr.CRC32 = OrgRTCRC32;
gRT->SetVirtualAddressMap = gStoredSetVirtualAddressMap;
gRT->SetVirtualAddressMap = gStoredSetVirtualAddressMap;
// Protect RT data areas from relocation by marking then MemMapIO
// Protect RT data areas from relocation by marking then MemMapIO
ProtectRtDataFromRelocation(MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
ProtectRtDataFromRelocation(MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
// Remember physical sys table addr
// Remember physical sys table addr
EfiSystemTable = (UINT32)(UINTN)gST;
EfiSystemTable = (UINT32)(UINTN)gST;
// virtualize RT services with all needed fixes
// virtualize RT services with all needed fixes
Status = ExecSetVirtualAddressesToMemMap(MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
Status = ExecSetVirtualAddressesToMemMap(MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);

CopyEfiSysTableToSeparateRtDataArea(&EfiSystemTable);
CopyEfiSysTableToSeparateRtDataArea(&EfiSystemTable);
// we will defragment RT data and code that is left unprotected.
// we will defragment RT data and code that is left unprotected.
// this will also mark those as AcpiNVS and by this protect it
// this will also mark those as AcpiNVS and by this protect it
// from boot.efi relocation and zeroing
// from boot.efi relocation and zeroing
DefragmentRuntimeServices(MemoryMapSize,
DefragmentRuntimeServices(MemoryMapSize,
DescriptorSize,
DescriptorSize,
DescriptorVersion,
DescriptorVersion,
VirtualMap,
VirtualMap,
NULL,
NULL,
gHibernateWake ? FALSE : TRUE
gHibernateWake ? FALSE : TRUE
);
);

// For AptioFix V2 we can correct the pointers earlier
VirtualizeRTShimPointers(MemoryMapSize, DescriptorSize, VirtualMap);
return Status;
return Status;
}
}




/** Callback called when boot.efi jumps to kernel. */
/** Callback called when boot.efi jumps to kernel. */
UINTN
UINTN
EFIAPI
EFIAPI
KernelEntryPatchJumpBack(UINTN bootArgs, BOOLEAN ModeX64)
KernelEntryPatchJumpBack(UINTN bootArgs, BOOLEAN ModeX64)
{
{
DBGnvr("\nBACK FROM KERNEL: BootArgs = %x, KernelEntry: %x, Kernel called in %s bit mode\n", bootArgs, AsmKernelEntry, (ModeX64 ? L"64" : L"32"));
DBGnvr("\nBACK FROM KERNEL: BootArgs = %x, KernelEntry: %x, Kernel called in %s bit mode\n", bootArgs, AsmKernelEntry, (ModeX64 ? L"64" : L"32"));
if (!gHibernateWake) {
if (!gHibernateWake) {
bootArgs = FixBootingWithoutRelocBlock(bootArgs, ModeX64);
bootArgs = FixBootingWithoutRelocBlock(bootArgs, ModeX64);
} else {
} else {
bootArgs = FixHibernateWakeWithoutRelocBlock(bootArgs, ModeX64);
bootArgs = FixHibernateWakeWithoutRelocBlock(bootArgs, ModeX64);
}
}
DBGnvr("BACK TO KERNEL: BootArgs = %x, KImgStartReloc = %x, KImgStart = %x, KImgSize = %x\n",
DBGnvr("BACK TO KERNEL: BootArgs = %x, KImgStartReloc = %x, KImgStart = %x, KImgSize = %x\n",
bootArgs, AsmKernelImageStartReloc, AsmKernelImageStart, AsmKernelImageSize);
bootArgs, AsmKernelImageStartReloc, AsmKernelImageStart, AsmKernelImageSize);
return bootArgs;
return bootArgs;
}
}





/** SWITCH_STACK_ENTRY_POINT implementation:
/** SWITCH_STACK_ENTRY_POINT implementation:
* Allocates kernel image reloc block, installs UEFI overrides and starts given image.
* Allocates kernel image reloc block, installs UEFI overrides and starts given image.
* If image returns, then deinstalls overrides and releases kernel image reloc block.
* If image returns, then deinstalls overrides and releases kernel image reloc block.
*
*
* If started with ImgContext->JumpBuffer, then it will return with LongJump().
* If started with ImgContext->JumpBuffer, then it will return with LongJump().
*/
*/
EFI_STATUS
EFI_STATUS
RunImageWithOverrides(
RunImageWithOverrides(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ImageHandle,
IN EFI_LOADED_IMAGE_PROTOCOL *Image,
IN EFI_LOADED_IMAGE_PROTOCOL *Image,
OUT UINTN *ExitDataSize,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
OUT CHAR16 **ExitData OPTIONAL
)
)
{
{
EFI_STATUS Status;
EFI_STATUS Status;

// save current 64bit state - will be restored later in callback from kernel jump
// save current 64bit state - will be restored later in callback from kernel jump
// and relocate MyAsmCopyAndJumpToKernel32 code to higher mem (for copying kernel back to
// and relocate MyAsmCopyAndJumpToKernel32 code to higher mem (for copying kernel back to
// proper place and jumping back to it)
// proper place and jumping back to it)
Status = PrepareJumpFromKernel();
Status = PrepareJumpFromKernel();
if (EFI_ERROR(Status)) {
if (EFI_ERROR(Status)) {
return Status;
return Status;
}
}
// init VMem memory pool - will be used after ExitBootServices
// init VMem memory pool - will be used after ExitBootServices
Status = VmAllocateMemoryPool();
Status = VmAllocateMemoryPool();
if (EFI_ERROR(Status)) {
if (EFI_ERROR(Status)) {
return Status;
return Status;
}
}

Status = gBS->AllocatePool (
EfiRuntimeServicesCode,
((UINTN)&gRTShimsDataEnd - (UINTN)&gRTShimsDataStart),
&RTShims
);

if (!EFI_ERROR (Status)) {
gGetVariable = (UINTN)gRT->GetVariable;
gGetNextVariableName = (UINTN)gRT->GetNextVariableName;
gSetVariable = (UINTN)gRT->SetVariable;

CopyMem (
RTShims,
(VOID *)&gRTShimsDataStart,
((UINTN)&gRTShimsDataEnd - (UINTN)&gRTShimsDataStart)
);

gRT->GetVariable = (EFI_GET_VARIABLE)((UINTN)RTShims + ((UINTN)&RTShimGetVariable - (UINTN)&gRTShimsDataStart));
gRT->GetNextVariableName = (EFI_GET_NEXT_VARIABLE_NAME)((UINTN)RTShims + ((UINTN)&RTShimGetNextVariableName - (UINTN)&gRTShimsDataStart));
gRT->SetVariable = (EFI_SET_VARIABLE)((UINTN)RTShims + ((UINTN)&RTShimSetVariable - (UINTN)&gRTShimsDataStart));

gRT->Hdr.CRC32 = 0;
gBS->CalculateCrc32 (gRT, gRT->Hdr.HeaderSize, &gRT->Hdr.CRC32);
} else {
RTShims = NULL;
}
// clear monitoring vars
// clear monitoring vars
gMinAllocatedAddr = 0;
gMinAllocatedAddr = 0;
gMaxAllocatedAddr = 0;
gMaxAllocatedAddr = 0;
// save original BS functions
// save original BS functions
gStoredAllocatePages = gBS->AllocatePages;
gStoredAllocatePages = gBS->AllocatePages;
gStoredGetMemoryMap = gBS->GetMemoryMap;
gStoredGetMemoryMap = gBS->GetMemoryMap;
gStoredExitBootServices = gBS->ExitBootServices;
gStoredExitBootServices = gBS->ExitBootServices;
gHandleProtocol = gBS->HandleProtocol;
gHandleProtocol = gBS->HandleProtocol;
// install our overrides
// install our overrides
gBS->AllocatePages = MOAllocatePages;
gBS->AllocatePages = MOAllocatePages;
gBS->GetMemoryMap = MOGetMemoryMap;
gBS->GetMemoryMap = MOGetMemoryMap;
gBS->ExitBootServices = MOExitBootServices;
gBS->ExitBootServices = MOExitBootServices;
gBS->HandleProtocol = MOHandleProtocol;
gBS->HandleProtocol = MOHandleProtocol;
gBS->Hdr.CRC32 = 0;
gBS->Hdr.CRC32 = 0;
gBS->CalculateCrc32(gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
gBS->CalculateCrc32(gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
OrgRTCRC32 = gRT->Hdr.CRC32;
OrgRTCRC32 = gRT->Hdr.CRC32;
gStoredSetVirtualAddressMap = gRT->SetVirtualAddressMap;
gStoredSetVirtualAddressMap = gRT->SetVirtualAddressMap;
gRT->SetVirtualAddressMap = OvrSetVirtualAddressMap;
gRT->SetVirtualAddressMap = OvrSetVirtualAddressMap;
gRT->Hdr.CRC32 = 0;
gRT->Hdr.CRC32 = 0;
gBS->CalculateCrc32(gRT, gRT->Hdr.HeaderSize, &gRT->Hdr.CRC32);
gBS->CalculateCrc32(gRT, gRT->Hdr.HeaderSize, &gRT->Hdr.CRC32);
// force boot.efi to use our copy od system table
// force boot.efi to use our copy od system table
DBG("StartImage: orig sys table: %p\n", Image->SystemTable);
DBG("StartImage: orig sys table: %p\n", Image->SystemTable);
Image->SystemTable = (EFI_SYSTEM_TABLE *)(UINTN)gSysTableRtArea;
Image->SystemTable = (EFI_SYSTEM_TABLE *)(UINTN)gSysTableRtArea;
DBG("StartImage: new sys table: %p\n", Image->SystemTable);
DBG("StartImage: new sys table: %p\n", Image->SystemTable);
// run image
// run image
Status = gStartImage(ImageHandle, ExitDataSize, ExitData);
Status = gStartImage(ImageHandle, ExitDataSize, ExitData);
// if we get here then boot.efi did not start kernel
// if we get here then boot.efi did not start kernel
// and we'll try to do some cleanup ...
// and we'll try to do some cleanup ...
// return back originals
// return back originals
gBS->AllocatePages = gStoredAllocatePages;
gBS->AllocatePages = gStoredAllocatePages;
gBS->GetMemoryMap = gStoredGetMemoryMap;
gBS->GetMemoryMap = gStoredGetMemoryMap;
gBS->ExitBootServices = gStoredExitBootServices;
gBS->ExitBootServices = gStoredExitBootServices;
gBS->HandleProtocol = gHandleProtocol;
gBS->HandleProtocol = gHandleProtocol;
gBS->Hdr.CRC32 = 0;
gBS->Hdr.CRC32 = 0;
gBS->CalculateCrc32(gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
gBS->CalculateCrc32(gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
gRT->SetVirtualAddressMap = gStoredSetVirtualAddressMap;
gRT->SetVirtualAddressMap = gStoredSetVirtualAddressMap;
gBS->CalculateCrc32(gRT, gRT->Hdr.HeaderSize, &gRT->Hdr.CRC32);
gBS->CalculateCrc32(gRT, gRT->Hdr.HeaderSize, &gRT->Hdr.CRC32);
return Status;
return Status;
}
}


/** gBS->StartImage override:
/** gBS->StartImage override:
* Called to start an efi image.
* Called to start an efi image.
*
*
* If this is boot.efi, then run it with our overrides.
* If this is boot.efi, then run it with our overrides.
*/
*/
EFI_STATUS
EFI_STATUS
EFIAPI
EFIAPI
MOStartImage (
MOStartImage (
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ImageHandle,
OUT UINTN *ExitDataSize,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
OUT CHAR16 **ExitData OPTIONAL
)
)
{
{
EFI_STATUS Status;
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *Image;
EFI_LOADED_IMAGE_PROTOCOL *Image;
CHAR16 *FilePathText = NULL;
CHAR16 *FilePathText = NULL;
UINTN Size = 0;
UINTN Size = 0;
VOID *Value = NULL;
VOID *Value = NULL;
UINTN Size2 = 0;
UINTN Size2 = 0;
CHAR16 *StartFlag = NULL;
CHAR16 *StartFlag = NULL;


DBG("StartImage(%lx)\n", ImageHandle);
DBG("StartImage(%lx)\n", ImageHandle);
// find out image name from EfiLoadedImageProtocol
// find out image name from EfiLoadedImageProtocol
Status = gBS->OpenProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &Image, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
Status = gBS->OpenProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &Image, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (Status != EFI_SUCCESS) {
if (Status != EFI_SUCCESS) {
DBG("ERROR: MOStartImage: OpenProtocol(gEfiLoadedImageProtocolGuid) = %r\n", Status);
DBG("ERROR: MOStartImage: OpenProtocol(gEfiLoadedImageProtocolGuid) = %r\n", Status);
return EFI_INVALID_PARAMETER;
return EFI_INVALID_PARAMETER;
}
}
FilePathText = FileDevicePathToText(Image->FilePath);
FilePathText = FileDevicePathToText(Image->FilePath);
if (FilePathText != NULL) {
if (FilePathText != NULL) {
DBG("FilePath: %s\n", FilePathText);
DBG("FilePath: %s\n", FilePathText);
}
}
DBG("ImageBase: %p - %lx (%lx)\n", Image->ImageBase, (UINT64)Image->ImageBase + Image->ImageSize, Image->ImageSize);
DBG("ImageBase: %p - %lx (%lx)\n", Image->ImageBase, (UINT64)Image->ImageBase + Image->ImageSize, Image->ImageSize);
Status = gBS->CloseProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, gImageHandle, NULL);
Status = gBS->CloseProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, gImageHandle, NULL);
if (EFI_ERROR(Status)) {
if (EFI_ERROR(Status)) {
DBG("CloseProtocol error: %r\n", Status);
DBG("CloseProtocol error: %r\n", Status);
}
}
if (StrStriBasic(FilePathText,L"boot.efi")){
if (StrStriBasic(FilePathText,L"boot.efi")){
Status = GetVariable2 (L"aptiofixflag", &gEfiAppleBootGuid, &Value, &Size2);
Status = GetVariable2 (L"aptiofixflag", &gEfiAppleBootGuid, &Value, &Size2);
if (!EFI_ERROR(Status)) {
if (!EFI_ERROR(Status)) {
Status = gRT->SetVariable(L"recovery-boot-mode", &gEfiAppleBootGuid,
Status = gRT->SetVariable(L"recovery-boot-mode", &gEfiAppleBootGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
Size2, Value);
Size2, Value);
if (EFI_ERROR(Status)) {
if (EFI_ERROR(Status)) {
DBG(" Something goes wrong while setting recovery-boot-mode\n");
DBG(" Something goes wrong while setting recovery-boot-mode\n");
}
}
Status = gRT->SetVariable (L"aptiofixflag", &gEfiAppleBootGuid, 0, 0, NULL);
Status = gRT->SetVariable (L"aptiofixflag", &gEfiAppleBootGuid, 0, 0, NULL);
FreePool(Value);
FreePool(Value);
}
}
Size2 =0;
Size2 =0;
//Check recovery-boot-mode present for nested boot.efi
//Check recovery-boot-mode present for nested boot.efi
Status = GetVariable2 (L"recovery-boot-mode", &gEfiAppleBootGuid, &Value, &Size2);
Status = GetVariable2 (L"recovery-boot-mode", &gEfiAppleBootGuid, &Value, &Size2);
if (!EFI_ERROR(Status)) {
if (!EFI_ERROR(Status)) {
//If it presents, then wait for \com.apple.recovery.boot\boot.efi boot
//If it presents, then wait for \com.apple.recovery.boot\boot.efi boot
DBG(" recovery-boot-mode present\n");
DBG(" recovery-boot-mode present\n");
StartFlag = StrStriBasic(FilePathText,L"\\com.apple.recovery.boot\\boot.efi");
StartFlag = StrStriBasic(FilePathText,L"\\com.apple.recovery.boot\\boot.efi");
if (Counter > 0x00){
if (Counter > 0x00){
Status = gRT->SetVariable(L"aptiofixflag", &gEfiAppleBootGuid,
Status = gRT->SetVariable(L"aptiofixflag", &gEfiAppleBootGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
Size2, Value);
Size2, Value);
if (EFI_ERROR(Status)) {
if (EFI_ERROR(Status)) {
DBG("Something goes wrong! \n");
DBG("Something goes wrong! \n");
}
}
gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
}
}
} else {
} else {
StartFlag = StrStriBasic(FilePathText,L"boot.efi");
StartFlag = StrStriBasic(FilePathText,L"boot.efi");
}
}
FreePool(Value);
FreePool(Value);
}
}


// check if this is boot.efi
// check if this is boot.efi
// if (StrStriBasic(FilePathText, L"boot.efi")) {
// if (StrStriBasic(FilePathText, L"boot.efi")) {
if (StartFlag) {
if (StartFlag) {
Counter++;
Counter++;
//the presence of the variable means HibernateWake
//the presence of the variable means HibernateWake
//if the wake is canceled then the variable must be deleted
//if the wake is canceled then the variable must be deleted
Status = gRT->GetVariable(L"boot-switch-vars", &gEfiAppleBootGuid, NULL, &Size, NULL);
Status = gRT->GetVariable(L"boot-switch-vars", &gEfiAppleBootGuid, NULL, &Size, NULL);
gHibernateWake = (Status == EFI_BUFFER_TOO_SMALL);
gHibernateWake = (Status == EFI_BUFFER_TOO_SMALL);
Print(L"OsxAptioFix2Drv: Starting overrides for %s\nUsing reloc block: no, hibernate wake: %s \n",
Print(L"OsxAptioFix3Drv: Starting overrides for %s\nUsing reloc block: no, hibernate wake: %s \n",
FilePathText, gHibernateWake ? L"yes" : L"no");
FilePathText, gHibernateWake ? L"yes" : L"no");
//gBS->Stall(2000000);
//gBS->Stall(2000000);
// run with our overrides
// run with our overrides
Status = RunImageWithOverrides(ImageHandle, Image, ExitDataSize, ExitData);
Status = RunImageWithOverrides(ImageHandle, Image, ExitDataSize, ExitData);
} else {
} else {
// call original function to do the job
// call original function to do the job
Status = gStartImage(ImageHandle, ExitDataSize, ExitData);
Status = gStartImage(ImageHandle, ExitDataSize, ExitData);
}
}
if (FilePathText != NULL) {
if (FilePathText != NULL) {
gBS->FreePool(FilePathText);
gBS->FreePool(FilePathText);
}
}
return Status;
return Status;
}
}




/** Entry point. Installs our StartImage override.
/** Entry point. Installs our StartImage override.
* All other stuff will be installed from there when boot.efi is started.
* All other stuff will be installed from there when boot.efi is started.
*/
*/
EFI_STATUS
EFI_STATUS
EFIAPI
EFIAPI
OsxAptioFixDrvEntrypoint (
OsxAptioFixDrvEntrypoint (
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
IN EFI_SYSTEM_TABLE *SystemTable
)
)
{
{
// install StartImage override
// install StartImage override
// all other overrides will be started when boot.efi is started
// all other overrides will be started when boot.efi is started
gStartImage = gBS->StartImage;
gStartImage = gBS->StartImage;
gBS->StartImage = MOStartImage;
gBS->StartImage = MOStartImage;
gBS->Hdr.CRC32 = 0;
gBS->Hdr.CRC32 = 0;
gBS->CalculateCrc32(gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
gBS->CalculateCrc32(gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
return EFI_SUCCESS;
return EFI_SUCCESS;
}
}