summaryrefslogtreecommitdiff
path: root/platform/efi/platform_efi.cpp
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2023-06-13 11:17:45 -0600
committerRusty Wagner <rusty.wagner@gmail.com>2023-06-13 16:27:51 -0400
commitadb7ef55fc4e24f03e6faf353cc9122ee07c714f (patch)
treef92befef21cad25479873bdaddf1e3734818c071 /platform/efi/platform_efi.cpp
parent7118c3ecdcbc9148c82aae824a0036762f3040c7 (diff)
Add EFI platform
Diffstat (limited to 'platform/efi/platform_efi.cpp')
-rw-r--r--platform/efi/platform_efi.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/platform/efi/platform_efi.cpp b/platform/efi/platform_efi.cpp
new file mode 100644
index 00000000..bc5dc208
--- /dev/null
+++ b/platform/efi/platform_efi.cpp
@@ -0,0 +1,211 @@
+#include "binaryninjaapi.h"
+#include "lowlevelilinstruction.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+Ref<Platform> g_efiX86, g_efiX64, g_efiArm, g_efiThumb, g_efiArm64;
+
+
+class EFIX86Platform : public Platform
+{
+public:
+ EFIX86Platform(Architecture* arch) : Platform(arch, "efi-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() >= 10 && subsystem->GetUnsignedInteger() <= 13)
+ return g_efiX86;
+ return nullptr;
+ }
+};
+
+
+class EFIX64Platform : public Platform
+{
+public:
+ EFIX64Platform(Architecture* arch) : Platform(arch, "efi-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() >= 10 && subsystem->GetUnsignedInteger() <= 13)
+ return g_efiX64;
+ return nullptr;
+ }
+};
+
+
+class EFIArmv7Platform : public Platform
+{
+public:
+ EFIArmv7Platform(Architecture* arch, const std::string& name) : Platform(arch, name)
+ {
+ 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() >= 10 && subsystem->GetUnsignedInteger() <= 13)
+ return g_efiArm;
+ return nullptr;
+ }
+};
+
+
+class EFIArm64Platform : public Platform
+{
+public:
+ EFIArm64Platform(Architecture* arch) : Platform(arch, "efi-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() >= 10 && subsystem->GetUnsignedInteger() <= 13)
+ return g_efiArm64;
+ return nullptr;
+ }
+};
+
+
+extern "C"
+{
+ BN_DECLARE_CORE_ABI_VERSION
+
+#ifndef DEMO_VERSION
+ BINARYNINJAPLUGIN void CorePluginDependencies()
+ {
+ AddOptionalPluginDependency("arch_x86");
+ AddOptionalPluginDependency("arch_armv7");
+ AddOptionalPluginDependency("arch_arm64");
+ AddOptionalPluginDependency("view_pe");
+ }
+#endif
+
+#ifdef DEMO_VERSION
+ bool EFIPluginInit()
+#else
+ BINARYNINJAPLUGIN bool CorePluginInit()
+#endif
+ {
+ Ref<BinaryViewType> pe = BinaryViewType::GetByName("PE");
+ if (pe)
+ {
+ Ref<Architecture> x86 = Architecture::GetByName("x86");
+ if (x86)
+ {
+ g_efiX86 = new EFIX86Platform(x86);
+ Platform::Register("efi", g_efiX86);
+ pe->RegisterPlatformRecognizer(0x14c, LittleEndian, EFIX86Platform::Recognize);
+ }
+
+ Ref<Architecture> x64 = Architecture::GetByName("x86_64");
+ if (x64)
+ {
+ g_efiX64 = new EFIX64Platform(x64);
+ Platform::Register("efi", g_efiX64);
+ pe->RegisterPlatformRecognizer(0x8664, LittleEndian, EFIX64Platform::Recognize);
+ }
+
+ Ref<Architecture> armv7 = Architecture::GetByName("armv7");
+ Ref<Architecture> thumb2 = Architecture::GetByName("thumb2");
+ if (armv7 && thumb2)
+ {
+ g_efiArm = new EFIArmv7Platform(armv7, "efi-armv7");
+ g_efiThumb = new EFIArmv7Platform(thumb2, "efi-thumb2");
+ g_efiArm->AddRelatedPlatform(thumb2, g_efiThumb);
+ g_efiThumb->AddRelatedPlatform(armv7, g_efiArm);
+ Platform::Register("efi", g_efiArm);
+ Platform::Register("efi", g_efiThumb);
+ pe->RegisterPlatformRecognizer(0x1c0, LittleEndian, EFIArmv7Platform::Recognize);
+ pe->RegisterPlatformRecognizer(0x1c2, LittleEndian, EFIArmv7Platform::Recognize);
+ pe->RegisterPlatformRecognizer(0x1c4, LittleEndian, EFIArmv7Platform::Recognize);
+ }
+
+ Ref<Architecture> arm64 = Architecture::GetByName("aarch64");
+ if (arm64)
+ {
+ g_efiArm64 = new EFIArm64Platform(arm64);
+ Platform::Register("efi", g_efiArm64);
+ pe->RegisterPlatformRecognizer(0xaa64, LittleEndian, EFIArm64Platform::Recognize);
+ }
+ }
+
+ return true;
+ }
+}