summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2023-06-14 15:51:09 -0400
committerRusty Wagner <rusty.wagner@gmail.com>2023-06-14 15:53:36 -0400
commit7b4d183be90a2570c13abc5a0d3655c542854f35 (patch)
treea52367e1366d09e282080a5e6855ff339e0e3bd7 /platform
parent49b90e2334a5532ed1c98ae99a07b0438c407be4 (diff)
Support IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION PE subsystem with EFI types
Diffstat (limited to 'platform')
-rw-r--r--platform/efi/platform_efi.cpp119
1 files changed, 119 insertions, 0 deletions
diff --git a/platform/efi/platform_efi.cpp b/platform/efi/platform_efi.cpp
index bc5dc208..4a1763ef 100644
--- a/platform/efi/platform_efi.cpp
+++ b/platform/efi/platform_efi.cpp
@@ -6,6 +6,7 @@ using namespace std;
Ref<Platform> g_efiX86, g_efiX64, g_efiArm, g_efiThumb, g_efiArm64;
+Ref<Platform> g_efiX86Windows, g_efiX64Windows, g_efiArm64Windows;
class EFIX86Platform : public Platform
@@ -52,6 +53,50 @@ public:
};
+class EFIX86WindowsPlatform : public Platform
+{
+public:
+ EFIX86WindowsPlatform(Architecture* arch) : Platform(arch, "efi-windows-x86")
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("cdecl");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("fastcall");
+ if (cc)
+ RegisterFastcallCallingConvention(cc);
+
+ cc = arch->GetCallingConventionByName("stdcall");
+ if (cc)
+ RegisterStdcallCallingConvention(cc);
+
+ cc = arch->GetCallingConventionByName("thiscall");
+ if (cc)
+ RegisterCallingConvention(cc);
+
+ // Linux-style register convention is commonly used by Borland compilers
+ cc = arch->GetCallingConventionByName("regparm");
+ if (cc)
+ RegisterCallingConvention(cc);
+ }
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ Ref<Metadata> subsystem = metadata->Get("Subsystem");
+ if (!subsystem || !subsystem->IsUnsignedInteger())
+ return nullptr;
+ if (subsystem->GetUnsignedInteger() == 0x10) // IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
+ return g_efiX86Windows;
+ return nullptr;
+ }
+};
+
+
class EFIX64Platform : public Platform
{
public:
@@ -85,6 +130,39 @@ public:
};
+class EFIX64WindowsPlatform : public Platform
+{
+public:
+ EFIX64WindowsPlatform(Architecture* arch) : Platform(arch, "efi-windows-x86_64")
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("win64");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+
+ // Linux-style calling convention is sometimes used internally by EFI applications
+ cc = arch->GetCallingConventionByName("sysv");
+ RegisterCallingConvention(cc);
+ }
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ Ref<Metadata> subsystem = metadata->Get("Subsystem");
+ if (!subsystem || !subsystem->IsUnsignedInteger())
+ return nullptr;
+ if (subsystem->GetUnsignedInteger() == 0x10) // IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
+ return g_efiX64Windows;
+ return nullptr;
+ }
+};
+
+
class EFIArmv7Platform : public Platform
{
public:
@@ -143,6 +221,35 @@ public:
};
+class EFIArm64WindowsPlatform : public Platform
+{
+public:
+ EFIArm64WindowsPlatform(Architecture* arch) : Platform(arch, "efi-windows-aarch64")
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("cdecl");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+ }
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ Ref<Metadata> subsystem = metadata->Get("Subsystem");
+ if (!subsystem || !subsystem->IsUnsignedInteger())
+ return nullptr;
+ if (subsystem->GetUnsignedInteger() == 0x10) // IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
+ return g_efiArm64Windows;
+ return nullptr;
+ }
+};
+
+
extern "C"
{
BN_DECLARE_CORE_ABI_VERSION
@@ -172,6 +279,10 @@ extern "C"
g_efiX86 = new EFIX86Platform(x86);
Platform::Register("efi", g_efiX86);
pe->RegisterPlatformRecognizer(0x14c, LittleEndian, EFIX86Platform::Recognize);
+
+ g_efiX86Windows = new EFIX86WindowsPlatform(x86);
+ Platform::Register("efi", g_efiX86Windows);
+ pe->RegisterPlatformRecognizer(0x14c, LittleEndian, EFIX86WindowsPlatform::Recognize);
}
Ref<Architecture> x64 = Architecture::GetByName("x86_64");
@@ -180,6 +291,10 @@ extern "C"
g_efiX64 = new EFIX64Platform(x64);
Platform::Register("efi", g_efiX64);
pe->RegisterPlatformRecognizer(0x8664, LittleEndian, EFIX64Platform::Recognize);
+
+ g_efiX64Windows = new EFIX64WindowsPlatform(x64);
+ Platform::Register("efi", g_efiX64Windows);
+ pe->RegisterPlatformRecognizer(0x8664, LittleEndian, EFIX64WindowsPlatform::Recognize);
}
Ref<Architecture> armv7 = Architecture::GetByName("armv7");
@@ -203,6 +318,10 @@ extern "C"
g_efiArm64 = new EFIArm64Platform(arm64);
Platform::Register("efi", g_efiArm64);
pe->RegisterPlatformRecognizer(0xaa64, LittleEndian, EFIArm64Platform::Recognize);
+
+ g_efiArm64Windows = new EFIArm64WindowsPlatform(arm64);
+ Platform::Register("efi", g_efiArm64Windows);
+ pe->RegisterPlatformRecognizer(0xaa64, LittleEndian, EFIArm64WindowsPlatform::Recognize);
}
}