mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-11 14:28:08 +01:00
119 lines
3.0 KiB
C
119 lines
3.0 KiB
C
|
/**
|
||
|
|
||
|
Basic functions for parsing Mach-O kernel.
|
||
|
|
||
|
by dmazar
|
||
|
|
||
|
**/
|
||
|
|
||
|
#include <Library/UefiBootServicesTableLib.h>
|
||
|
|
||
|
#include <Library/UefiLib.h>
|
||
|
#include <Library/DebugLib.h>
|
||
|
#include <Library/PrintLib.h>
|
||
|
|
||
|
#include "UefiLoader.h"
|
||
|
#include "Mach-O.h"
|
||
|
|
||
|
|
||
|
// DBG_TO: 0=no debug, 1=serial, 2=console
|
||
|
// serial requires
|
||
|
// [PcdsFixedAtBuild]
|
||
|
// gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07
|
||
|
// gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xFFFFFFFF
|
||
|
// in package DSC file
|
||
|
#define DBG_TO 0
|
||
|
|
||
|
#if DBG_TO == 2
|
||
|
#define DBG(...) AsciiPrint(__VA_ARGS__);
|
||
|
#elif DBG_TO == 1
|
||
|
#define DBG(...) DebugPrint(1, __VA_ARGS__);
|
||
|
#else
|
||
|
#define DBG(...)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/** Adds Offset bytes to SourcePtr and returns new pointer as ReturnType. */
|
||
|
#define PTR_OFFSET(SourcePtr, Offset, ReturnType) ((ReturnType)(((UINT8*)SourcePtr) + Offset))
|
||
|
|
||
|
|
||
|
/** Returns Mach-O entry point from LC_UNIXTHREAD loader command. */
|
||
|
UINTN
|
||
|
EFIAPI
|
||
|
MachOGetEntryAddress(IN VOID *MachOImage)
|
||
|
{
|
||
|
struct mach_header *MHdr;
|
||
|
struct mach_header_64 *MHdr64;
|
||
|
BOOLEAN Is64Bit;
|
||
|
UINT32 NCmds;
|
||
|
struct load_command *LCmd;
|
||
|
UINTN Index;
|
||
|
i386_thread_state_t *ThreadState;
|
||
|
x86_thread_state64_t *ThreadState64;
|
||
|
UINTN Address;
|
||
|
|
||
|
|
||
|
Address = 0;
|
||
|
MHdr = (struct mach_header *)MachOImage;
|
||
|
MHdr64 = (struct mach_header_64 *)MachOImage;
|
||
|
DBG("MachOImage: %p, magic: %x", MachOImage, MHdr->magic);
|
||
|
|
||
|
if (MHdr->magic == MH_MAGIC || MHdr->magic == MH_CIGAM) {
|
||
|
// 32 bit header
|
||
|
DBG(" -> 32 bit\n");
|
||
|
Is64Bit = FALSE;
|
||
|
NCmds = MHdr->ncmds;
|
||
|
LCmd = PTR_OFFSET(MachOImage, sizeof(struct mach_header), struct load_command *);
|
||
|
} else if (MHdr64->magic == MH_MAGIC_64 || MHdr64->magic == MH_CIGAM_64) {
|
||
|
// 64 bit header
|
||
|
DBG(" -> 64 bit\n");
|
||
|
Is64Bit = TRUE;
|
||
|
NCmds = MHdr64->ncmds;
|
||
|
LCmd = PTR_OFFSET(MachOImage, sizeof(struct mach_header_64), struct load_command *);
|
||
|
} else {
|
||
|
// invalid MachOImage
|
||
|
return Address;
|
||
|
}
|
||
|
DBG("ncmds: %d\n", NCmds, LCmd);
|
||
|
//gBS->Stall(10 * 1000000);
|
||
|
|
||
|
// iterate over load commands
|
||
|
for (Index = 0; Index < NCmds; Index++) {
|
||
|
|
||
|
DBG("%d. LCmd: %p, cmd: %x, size: %d\n", Index, LCmd, LCmd->cmd, LCmd->cmdsize);
|
||
|
|
||
|
if (LCmd->cmd == LC_UNIXTHREAD) {
|
||
|
|
||
|
DBG("LC_UNIXTHREAD\n");
|
||
|
//
|
||
|
// extract thread state
|
||
|
// LCmd =
|
||
|
// struct load_command {
|
||
|
// uint32_t cmd
|
||
|
// uint32_t cmdsize
|
||
|
// }
|
||
|
// uint32_t flavor flavor of thread state */
|
||
|
// uint32_t count count of longs in thread state */
|
||
|
// struct XXX_thread_state state thread state for this flavor */
|
||
|
//
|
||
|
ThreadState = PTR_OFFSET(LCmd, sizeof(struct load_command) + 2 * sizeof(UINT32), i386_thread_state_t *);
|
||
|
ThreadState64 = (x86_thread_state64_t *)ThreadState;
|
||
|
|
||
|
if (Is64Bit) {
|
||
|
Address = (UINTN)ThreadState64->rip;
|
||
|
} else {
|
||
|
Address = (UINTN)ThreadState->eip;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// next command
|
||
|
LCmd = PTR_OFFSET(LCmd, LCmd->cmdsize, struct load_command *);
|
||
|
|
||
|
}
|
||
|
|
||
|
DBG("Address: %lx\n", Address);
|
||
|
//gBS->Stall(20 * 1000000);
|
||
|
return Address;
|
||
|
}
|