EmulatorPkg: Add D-BUS Listener Thread

Signed-off-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
diff --git a/EmulatorPkg/EmulatorPkg.dec b/EmulatorPkg/EmulatorPkg.dec
index 3a768d6..b055188 100644
--- a/EmulatorPkg/EmulatorPkg.dec
+++ b/EmulatorPkg/EmulatorPkg.dec
@@ -32,14 +32,15 @@
   EmuSignalLib|Include/Library/EmuSignalLib.h

 

 [Protocols]

-  gEmuThunkProtocolGuid          = { 0x5CF32E0B, 0x8EDF, 0x2E44, { 0x9C, 0xDA, 0x93, 0x20, 0x5E, 0x99, 0xEC, 0x1C } }

-  gEmuIoThunkProtocolGuid        = { 0x453368F6, 0x7C85, 0x434A, { 0xA9, 0x8A, 0x72, 0xD1, 0xB7, 0xFF, 0xA9, 0x26 } }

-  gEmuGraphicsWindowProtocolGuid = { 0x30FD316A, 0x6728, 0x2E41, { 0xA6, 0x90, 0x0D, 0x13, 0x33, 0xD8, 0xCA, 0xC1 } }

-  gEmuThreadThunkProtocolGuid    = { 0x3B1E4B7C, 0x09D8, 0x944F, { 0xA4, 0x08, 0x13, 0x09, 0xEB, 0x8B, 0x44, 0x27 } }

-  gEmuBlockIoProtocolGuid        = { 0x6888A4AE, 0xAFCE, 0xE84B, { 0x91, 0x02, 0xF7, 0xB9, 0xDA, 0xE6, 0xA0, 0x30 } }

-  gEmuSnpProtocolGuid            = { 0xFD5FBE54, 0x8C35, 0xB345, { 0x8A, 0x0F, 0x7A, 0xC8, 0xA5, 0xFD, 0x05, 0x21 } }

-  gEmuCacheThunkProtocolGuid     = { 0x8816732A, 0xF6DE, 0x466A, { 0x8E, 0x47, 0x1C, 0xE0, 0xEE, 0x1F, 0xB3, 0x3A } }

-  gEmuSignalThunkProtocolGuid    = { 0x3B5AEFDB, 0x262E, 0x4852, { 0x92, 0x9F, 0xAA, 0x7E, 0x2F, 0x5D, 0xD2, 0x39 } }

+  gEmuThunkProtocolGuid           = { 0x5CF32E0B, 0x8EDF, 0x2E44, { 0x9C, 0xDA, 0x93, 0x20, 0x5E, 0x99, 0xEC, 0x1C } }

+  gEmuIoThunkProtocolGuid         = { 0x453368F6, 0x7C85, 0x434A, { 0xA9, 0x8A, 0x72, 0xD1, 0xB7, 0xFF, 0xA9, 0x26 } }

+  gEmuGraphicsWindowProtocolGuid  = { 0x30FD316A, 0x6728, 0x2E41, { 0xA6, 0x90, 0x0D, 0x13, 0x33, 0xD8, 0xCA, 0xC1 } }

+  gEmuThreadThunkProtocolGuid     = { 0x3B1E4B7C, 0x09D8, 0x944F, { 0xA4, 0x08, 0x13, 0x09, 0xEB, 0x8B, 0x44, 0x27 } }

+  gEmuBlockIoProtocolGuid         = { 0x6888A4AE, 0xAFCE, 0xE84B, { 0x91, 0x02, 0xF7, 0xB9, 0xDA, 0xE6, 0xA0, 0x30 } }

+  gEmuSnpProtocolGuid             = { 0xFD5FBE54, 0x8C35, 0xB345, { 0x8A, 0x0F, 0x7A, 0xC8, 0xA5, 0xFD, 0x05, 0x21 } }

+  gEmuCacheThunkProtocolGuid      = { 0x8816732A, 0xF6DE, 0x466A, { 0x8E, 0x47, 0x1C, 0xE0, 0xEE, 0x1F, 0xB3, 0x3A } }

+  gEmuSignalThunkProtocolGuid     = { 0x3B5AEFDB, 0x262E, 0x4852, { 0x92, 0x9F, 0xAA, 0x7E, 0x2F, 0x5D, 0xD2, 0x39 } }

+  gEmuDbusPrmdServiceProtocolGuid = { 0x9E758CE5, 0x2083, 0x4577, { 0x81, 0x65, 0x18, 0xF2, 0xE2, 0x17, 0x98, 0xFD } }

 

 [Ppis]

   gEmuThunkPpiGuid               = { 0xE113F896, 0x75CF, 0xF640, { 0x81, 0x7F, 0xC8, 0x5A, 0x79, 0xE8, 0xAE, 0x67 } }

@@ -114,6 +115,7 @@
   gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort|L"/dev/ttyS0"|VOID*|0x00001002

   gEmulatorPkgTokenSpaceGuid.PcdEmuCache|L"CacheCtl"|VOID*|0x0000101d

   gEmulatorPkgTokenSpaceGuid.PcdEmuSignal|L"SignalCtl"|VOID*|0x0000101e

+  gEmulatorPkgTokenSpaceGuid.PcdEmuDbusPrmdService|L"DbusPrmdServiceCtl"|VOID*|0x0000101f

 

   #

   # On Unix host, this is the network interface name on host system that will

diff --git a/EmulatorPkg/Include/Protocol/EmuDbusPrmdService.h b/EmulatorPkg/Include/Protocol/EmuDbusPrmdService.h
new file mode 100644
index 0000000..bf3531e
--- /dev/null
+++ b/EmulatorPkg/Include/Protocol/EmuDbusPrmdService.h
@@ -0,0 +1,121 @@
+/** @file
+  Provides the mailbox for invoking the PRM Dispatch API from dbus
+
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __EMU_DBUS_PRMD_SERVICE__
+#define __EMU_DBUS_PRMD_SERVICE__
+
+typedef struct {
+  UINTN         Function;
+  EFI_STATUS    Status;
+  UINT8         Data[1];
+} EMU_DBUS_PRMD_SERVICE_COMMUNICATE_HEADER;
+
+//
+// The payload for this function is EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INSTALL_PACKAGE.
+//
+#define EMU_DBUS_PRMD_SERVICE_FUNCTION_INSTALL_PACKAGE  1
+//
+// The payload for this function is .
+//
+#define EMU_DBUS_PRMD_SERVICE_FUNCTION_ENUMERATE_HANDLERS  2
+//
+// The payload for this function is EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INVOKE_HANDLER.
+//
+#define EMU_DBUS_PRMD_SERVICE_FUNCTION_INVOKE_HANDLER  3
+//
+// The payload for this function is .
+//
+#define EMU_DBUS_PRMD_SERVICE_FUNCTION_UNINSTALL_PRM_MODULE  4
+//
+// The payload for this function is .
+//
+#define EMU_DBUS_PRMD_SERVICE_FUNCTION_GET_HANDLER_DEBUG_INFO  5
+
+typedef struct {
+  VOID          *PrmPackage;
+  UINT32        PrmPackageLength;
+} EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INSTALL_PACKAGE;
+
+typedef struct {
+  EFI_GUID      HandlerGuid;
+  EFI_STATUS    PrmHandlerReturnStatus;
+  VOID          *ParameterBuffer;
+  UINT8         ParameterBufferLength;
+} EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INVOKE_HANDLER;
+
+typedef struct {
+  EFI_GUID      HandlerGuid;
+  VOID          *AcpiParameterBuffer;
+  UINT32        AcpiParameterBufferLength;
+  CHAR8         *HandlerName;
+} EMU_DBUS_PRMD_SERVICE_COMMUNICATE_GET_HANDLER_DEBUG_INFO;
+
+typedef struct _EMU_DBUS_PRMD_SERVICE_THUNK_PROTOCOL EMU_DBUS_PRMD_SERVICE_THUNK_PROTOCOL;
+
+/**
+  Acquire the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was acquired successfully.
+  @retval EFI_TIMEOUT                 Acquiring the mailbox failed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EMU_DBUS_PRMD_SERVICE_ACQUIRE_MAILBOX)(
+  VOID
+  );
+
+/**
+  Release the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was released successfully.
+  @retval EFI_TIMEOUT                 Releasing the mailbox failed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EMU_DBUS_PRMD_SERVICE_RELEASE_MAILBOX)(
+  VOID
+  );
+
+/**
+  Wait for a new message to be stored in the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 A new message is in the mailbox
+  @retval EFI_TIMEOUT                 Waiting for a new message failed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EMU_DBUS_PRMD_SERVICE_WAIT_FOR_MESSAGE)(
+  VOID
+  );
+
+/**
+  Signal that the message has been successfully processed and the results
+  are waiting in the PRM Dispatch Service Mailbox
+
+  @retval None
+
+**/
+typedef
+VOID
+(EFIAPI *EMU_DBUS_PRMD_SERVICE_MESSAGE_RESPONSE_READY)(
+  VOID
+  );
+
+struct _EMU_DBUS_PRMD_SERVICE_THUNK_PROTOCOL {
+  EMU_DBUS_PRMD_SERVICE_ACQUIRE_MAILBOX                   AcquireMailbox;
+  EMU_DBUS_PRMD_SERVICE_RELEASE_MAILBOX                   ReleaseMailbox;
+  EMU_DBUS_PRMD_SERVICE_WAIT_FOR_MESSAGE                  WaitForMessage;
+  EMU_DBUS_PRMD_SERVICE_MESSAGE_RESPONSE_READY            MessageResponseReady;
+
+  EMU_DBUS_PRMD_SERVICE_COMMUNICATE_HEADER                *Mailbox;
+};
+
+#endif
diff --git a/EmulatorPkg/Unix/Host/Arm/Gasket.c b/EmulatorPkg/Unix/Host/Arm/Gasket.c
index 9fcb8bb..8a926ee 100644
--- a/EmulatorPkg/Unix/Host/Arm/Gasket.c
+++ b/EmulatorPkg/Unix/Host/Arm/Gasket.c
@@ -947,24 +947,6 @@
   return SecUnregisterSignalHandler (SignalNumber);
 }
 
-EFI_STATUS
-EFIAPI
-GasketSignalOpen (
-  IN  EMU_IO_THUNK_PROTOCOL  *This
-  )
-{
-  return SignalOpen (This);
-}
-
-EFI_STATUS
-EFIAPI
-GasketSignalClose (
-  IN  EMU_IO_THUNK_PROTOCOL  *This
-  )
-{
-  return SignalClose (This);
-}
-
 UINT32
 EFIAPI
 GasketGetIsSigTermSignaled (
@@ -982,3 +964,99 @@
 {
   return SetIsSigTermSignaled (value);
 }
+
+EFI_STATUS
+EFIAPI
+GasketEmuSignalThunkOpen (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  )
+{
+  return EmuSignalThunkOpen (This);
+}
+
+EFI_STATUS
+EFIAPI
+GasketEmuSignalThunkClose (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  )
+{
+  return EmuSignalThunkClose (This);
+}
+
+/**
+  Acquire the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was acquired successfully.
+  @retval EFI_TIMEOUT                 Acquiring the mailbox failed.
+
+**/
+EFI_STATUS
+GasketEmuDbusAcquireMailbox (
+  VOID
+  )
+{
+  return SecDbusAcquireMailbox ();
+}
+
+/**
+  Release the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was released successfully.
+  @retval EFI_TIMEOUT                 Releasing the mailbox failed.
+
+**/
+EFI_STATUS
+GasketEmuDbusReleaseMailbox (
+  VOID
+  )
+{
+  return SecDbusReleaseMailbox ();
+}
+
+/**
+  Wait for a new message to be stored in the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 A new message is in the mailbox
+  @retval EFI_TIMEOUT                 Waiting for a new message failed.
+
+**/
+EFI_STATUS
+GasketEmuDbusWaitForMessage (
+  VOID
+  )
+{
+  return SecDbusWaitForMessage ();
+}
+
+/**
+  Signal that the message has been successfully processed and the results
+  are waiting in the PRM Dispatch Service Mailbox
+
+  @retval None
+
+**/
+VOID
+GasketEmuDbusMessageResponseReady (
+  VOID
+  )
+{
+  return SecDbusMessageResponseReady ();
+}
+
+EFI_STATUS
+EFIAPI
+GasketEmuDbusThunkOpen (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  )
+{
+  return SecDbusPrmdServiceThunkOpen (This);
+}
+
+EFI_STATUS
+EFIAPI
+GasketEmuDbusThunkClose (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  )
+{
+  return SecDbusPrmdServiceThunkClose (This);
+}
diff --git a/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h b/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h
index 07152e0..f5d43d6 100644
--- a/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h
+++ b/EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h
@@ -1158,16 +1158,6 @@
   IN      UINTN                       SignalNumber
   );
 
-EFI_STATUS
-SignalOpen (
-  IN  EMU_IO_THUNK_PROTOCOL  *This
-  );
-
-EFI_STATUS
-SignalClose (
-  IN  EMU_IO_THUNK_PROTOCOL  *This
-  );
-
 /**
   Get IsSigTermSignaled value.
 
@@ -1192,4 +1182,72 @@
   IN      UINT32   value
   );
 
+EFI_STATUS
+EmuSignalThunkOpen (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  );
+
+EFI_STATUS
+EmuSignalThunkClose (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  );
+
+/**
+  Acquire the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was acquired successfully.
+  @retval EFI_TIMEOUT                 Acquiring the mailbox failed.
+
+**/
+EFI_STATUS
+SecDbusAcquireMailbox (
+  VOID
+  );
+
+/**
+  Release the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was released successfully.
+  @retval EFI_TIMEOUT                 Releasing the mailbox failed.
+
+**/
+EFI_STATUS
+SecDbusReleaseMailbox (
+  VOID
+  );
+
+/**
+  Wait for a new message to be stored in the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 A new message is in the mailbox
+  @retval EFI_TIMEOUT                 Waiting for a new message failed.
+
+**/
+EFI_STATUS
+SecDbusWaitForMessage (
+  VOID
+  );
+
+/**
+  Signal that the message has been successfully processed and the results
+  are waiting in the PRM Dispatch Service Mailbox
+
+  @retval None
+
+**/
+VOID
+SecDbusMessageResponseReady (
+  VOID
+  );
+
+EFI_STATUS
+SecDbusPrmdServiceThunkOpen (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  );
+
+EFI_STATUS
+SecDbusPrmdServiceThunkClose (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  );
+
 #endif
diff --git a/EmulatorPkg/Unix/Host/DbusPrmdService.c b/EmulatorPkg/Unix/Host/DbusPrmdService.c
new file mode 100644
index 0000000..be57463
--- /dev/null
+++ b/EmulatorPkg/Unix/Host/DbusPrmdService.c
@@ -0,0 +1,1216 @@
+/** @file
+  Provides the PRM Dispatch API as a dbus callable service
+
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//#include <stdbool.h>
+//#include <string.h>
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <unistd.h>
+#include "Host.h"
+#include <pthread.h>
+#include <systemd/sd-bus.h>
+
+#include <Protocol/EmuDbusPrmdService.h>
+//#include <dbus/dbus.h>
+//#include <dbus/dbus-glib-lowlevel.h> /* for glib main loop */
+
+/**
+  Get IsSigTermSignaled value.
+
+  @retval        Value             current IsSigTermSignaled value.
+
+**/
+UINT32
+EFIAPI
+GetIsSigTermSignaled (
+  VOID
+  );
+
+#define PRMD_DBUS_OBJECT_NAME       "/com/intel/PrmDispatch"
+#define PRMD_DBUS_INTERFACE_NAME    "com.intel.PrmDispatch"
+#define PRMD_DBUS_SERVICE_NAME      "com.intel.PrmDispatch" // Note: This is called a D-Bus "bus name"
+
+#define PRMD_DBUS_MAILBOX_SIZE      SIZE_4KB
+
+const char *PrmDispatchApiVersion = "0.1";
+
+EMU_DBUS_PRMD_SERVICE_COMMUNICATE_HEADER   *gPrmDispatchMailbox = NULL;
+
+STATIC pthread_mutex_t mPrmDispatchMailbox = PTHREAD_MUTEX_INITIALIZER;
+
+STATIC int mMessageIsReadyFlag = 0;
+STATIC pthread_mutex_t mMessageIsReadyMutex = PTHREAD_MUTEX_INITIALIZER;
+STATIC pthread_cond_t mMessageIsReadyCond = PTHREAD_COND_INITIALIZER;
+
+STATIC int mResponseIsReadyFlag = 0;
+STATIC pthread_mutex_t mResponseIsReadyMutex = PTHREAD_MUTEX_INITIALIZER;
+STATIC pthread_cond_t mResponseIsReadyCond = PTHREAD_COND_INITIALIZER;
+
+STATIC sd_bus              *mBus = NULL;
+
+UINT32
+ConvertEfiStatus (
+  EFI_STATUS    Status
+  )
+{
+  UINT32    Status32 = 0;
+
+  if ((Status & MAX_BIT) != 0) {
+    Status32 |= 0x80000000;   // Error Bit
+  }
+  if ((Status & (MAX_BIT >> 1)) != 0) {
+    Status32 |= 0x40000000;   // OEM Namespace Bit
+  }
+  if ((Status & (MAX_BIT >> 2)) != 0) {
+    Status32 |= 0x20000000;   // PI Spec Namespace Bit
+  }
+  Status32 |= (UINT32) (((UINTN) Status) & 0x1FFFFFFF);   // Mantissa
+  return Status32;
+}
+
+EFI_STATUS
+ConvertStatus (
+  int Status
+  )
+{
+  if (Status == EINVAL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Status == ETIMEDOUT) {
+    return EFI_TIMEOUT;
+  }
+  if (Status == EBUSY) {        // The mutex could not be acquired because it was already locked.
+    return EFI_ALREADY_STARTED;
+  }
+  if (Status == EOPNOTSUPP) {   // The byte order in the message is different than native byte order.
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Status == EPERM) {        // The current thread does not own the mutex.
+                                // The message is not sealed.
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Status == EBADMSG) {      // The message cannot be parsed.
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Status == ENXIO) {        // The message does not contain the specified type at current position.
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Status == EAGAIN) {       // The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
+    return EFI_ABORTED;
+  }
+  if (Status == EDEADLK) {      // The current thread already owns the mutex.
+    return EFI_ABORTED;
+  }
+  if (Status == EAGAIN) {       // The system lacked the necessary resources to create another thread
+    return EFI_OUT_OF_RESOURCES;
+  }
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Wait for DXE to process the message in the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 A new message is in the mailbox
+  @retval EFI_TIMEOUT                 Waiting for a new message failed.
+
+**/
+EFI_STATUS
+DbusWaitForDxeResponse (
+  VOID
+  )
+{
+  int Status;
+
+  Status = pthread_mutex_lock (&mResponseIsReadyMutex);
+  if (Status != 0) {
+    return ConvertStatus (Status);
+  }
+  while (!mResponseIsReadyFlag) {
+    Status = pthread_cond_wait (&mResponseIsReadyCond, &mResponseIsReadyMutex);
+    if (Status != 0) {
+      pthread_mutex_unlock (&mResponseIsReadyMutex);
+      return ConvertStatus (Status);
+    }
+  }
+  mResponseIsReadyFlag = 0;
+  Status = pthread_mutex_unlock (&mResponseIsReadyMutex);
+  if (Status != 0) {
+    return ConvertStatus (Status);
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Signal DXE that a new message is waiting in the PRM Dispatch Service Mailbox
+
+  @retval None
+
+**/
+VOID
+DbusSignalDxeMessageIsReady (
+  VOID
+  )
+{
+  int Status;
+
+  Status = pthread_mutex_lock (&mMessageIsReadyMutex);
+  if (Status != 0) {
+    return;
+  }
+  mMessageIsReadyFlag = 1;
+  Status = pthread_cond_signal (&mMessageIsReadyCond);
+  if (Status != 0) {
+    pthread_mutex_unlock (&mMessageIsReadyMutex);
+    return;
+  }
+  Status = pthread_mutex_unlock (&mMessageIsReadyMutex);
+  if (Status != 0) {
+    return;
+  }
+}
+
+static int
+DbusInstallPrmPackage (
+  sd_bus_message  *Message,
+  void            *UserData,
+  sd_bus_error    *ReturnStatus
+  )
+{
+  EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INSTALL_PACKAGE   *InstallPackageData;
+  EFI_STATUS                                          EfiStatus;
+  EFI_STATUS                                          ReturnedStatus;
+  int                                                 Status;
+  char                                                *PrmPackage;
+  size_t                                              PrmPackageLength;
+
+  //
+  // Get the PRM package from the D-BUS message
+  //
+  Status = sd_bus_message_read_array (Message, 'y', (const void **)&PrmPackage, &PrmPackageLength);
+  if (Status == 0) {
+    fprintf (stderr, "Failed to read PRM package, array is empty\n");
+    return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (EFI_INVALID_PARAMETER));
+  }
+  if (Status < 0) {
+    fprintf (stderr, "Failed to read PRM package: %s\n", strerror (-Status));
+    return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (ConvertStatus (-Status)));
+  }
+
+  //
+  // Populate the mailbox message
+  //
+  EfiStatus = SecDbusAcquireMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusAcquireMailbox() Failed: %x\n", (int) EfiStatus);
+    return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (EfiStatus));
+  }
+  ZeroMem ((VOID *) gPrmDispatchMailbox, PRMD_DBUS_MAILBOX_SIZE);
+  gPrmDispatchMailbox->Function = EMU_DBUS_PRMD_SERVICE_FUNCTION_INSTALL_PACKAGE;
+  InstallPackageData = (EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INSTALL_PACKAGE *) &(gPrmDispatchMailbox->Data[0]);
+  InstallPackageData->PrmPackage = (VOID *) PrmPackage;
+  InstallPackageData->PrmPackageLength = (UINT32) PrmPackageLength;
+  EfiStatus = SecDbusReleaseMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusReleaseMailbox() Failed: %x\n", (int) EfiStatus);
+    return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (EfiStatus));
+  }
+
+  //
+  // Inform the DaemonBds DXE driver that a new message is waiting
+  //
+  DbusSignalDxeMessageIsReady ();
+
+  //
+  // Wait for DaemonBds to process the message
+  //
+  EfiStatus = DbusWaitForDxeResponse ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "DbusWaitForDxeResponse() Failed: %x\n", (int) EfiStatus);
+    return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (EfiStatus));
+  }
+
+  //
+  // Read the returned status code from DaemonBds
+  //
+  EfiStatus = SecDbusAcquireMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusAcquireMailbox() Failed: %x\n", (int) EfiStatus);
+    return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (EfiStatus));
+  }
+  ReturnedStatus = gPrmDispatchMailbox->Status;
+  EfiStatus = SecDbusReleaseMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusReleaseMailbox() Failed: %x\n", (int) EfiStatus);
+    return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (EfiStatus));
+  }
+
+  //
+  // Send the status code back to the D-BUS client
+  //
+  return sd_bus_reply_method_return (Message, "u", ConvertEfiStatus (ReturnedStatus));
+}
+
+static int
+DbusEnumerateHandlers (
+  sd_bus_message  *Message,
+  void            *UserData,
+  sd_bus_error    *ReturnStatus
+  )
+{
+  //@todo
+  return -1;
+}
+
+static int
+DbusInvokeHandler (
+  sd_bus_message  *Message,
+  void            *UserData,
+  sd_bus_error    *ReturnStatus
+  )
+{
+  EFI_GUID                                            HandlerGuid;
+  EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INVOKE_HANDLER    *InvokeHandlerData;
+  EFI_STATUS                                          EfiStatus;
+  EFI_STATUS                                          ReturnedStatus;
+  EFI_STATUS                                          PrmHandlerStatus;
+  int                                                 Status;
+  char                                                *HandlerGuidStr;
+  char                                                *ParameterBufferSrc;
+  size_t                                              ParameterBufferLength;
+  char                                                *ParameterBufferDest = NULL;
+  sd_bus_message                                      *Reply = NULL;
+  char                                                EmptyArray[] = "\0";
+
+  //
+  // Get the HandlerGuid and ParameterBuffer from the D-BUS message
+  //
+  Status = sd_bus_message_read (Message, "s", &HandlerGuidStr);
+  if (Status < 0) {
+    fprintf (stderr, "Failed to read PRM package: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    goto Error;
+  }
+  EfiStatus = AsciiStrToGuid (HandlerGuidStr, &HandlerGuid);
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "AsciiStrToGuid() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+  Status = sd_bus_message_read_array (Message, 'y', (const void **)&ParameterBufferSrc, &ParameterBufferLength);
+  if (Status == 0) {
+    fprintf (stderr, "Failed to read PRM package, array is empty\n");
+    EfiStatus = EFI_INVALID_PARAMETER;
+    goto Error;
+  }
+  if (Status < 0) {
+    fprintf (stderr, "Failed to read PRM package: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    goto Error;
+  }
+  ParameterBufferDest = malloc (ParameterBufferLength);
+  if (ParameterBufferDest == NULL) {
+    fprintf (stderr, "DbusInvokeHandler() Failed: Out of Memory\n");
+    EfiStatus = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+  CopyMem (ParameterBufferDest, ParameterBufferSrc, (UINTN) ParameterBufferLength);
+
+  //
+  // Populate the mailbox message
+  //
+  EfiStatus = SecDbusAcquireMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusAcquireMailbox() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+  ZeroMem ((VOID *) gPrmDispatchMailbox, PRMD_DBUS_MAILBOX_SIZE);
+  gPrmDispatchMailbox->Function = EMU_DBUS_PRMD_SERVICE_FUNCTION_INVOKE_HANDLER;
+  InvokeHandlerData = (EMU_DBUS_PRMD_SERVICE_COMMUNICATE_INVOKE_HANDLER *) &(gPrmDispatchMailbox->Data[0]);
+  CopyGuid (&InvokeHandlerData->HandlerGuid, &HandlerGuid);
+  InvokeHandlerData->ParameterBuffer = ParameterBufferDest;
+  InvokeHandlerData->ParameterBufferLength = ParameterBufferLength;
+  EfiStatus = SecDbusReleaseMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusReleaseMailbox() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+
+  //
+  // Inform the DaemonBds DXE driver that a new message is waiting
+  //
+  DbusSignalDxeMessageIsReady ();
+
+  //
+  // Wait for DaemonBds to process the message
+  //
+  EfiStatus = DbusWaitForDxeResponse ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "DbusWaitForDxeResponse() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+
+  //
+  // Create a message for the reply
+  //
+  Status = sd_bus_message_new_method_return (Message, &Reply);
+  if (Status < 0) {
+    fprintf (stderr, "sd_bus_message_new_method_return() Failed: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    goto Error;
+  }
+
+  //
+  // Populate the reply with the returned data from DaemonBds
+  //
+  EfiStatus = SecDbusAcquireMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusAcquireMailbox() Failed: %x\n", (int) EfiStatus);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+    goto Error;
+  }
+  ReturnedStatus = gPrmDispatchMailbox->Status;
+  PrmHandlerStatus = InvokeHandlerData->PrmHandlerReturnStatus;
+  Status = sd_bus_message_append_array (Reply, 'y', ParameterBufferDest, ParameterBufferLength);
+  if (Status < 0) {
+    fprintf (stderr, "sd_bus_message_append_array() Failed: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+    SecDbusReleaseMailbox ();
+    goto Error;
+  }
+  EfiStatus = SecDbusReleaseMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusReleaseMailbox() Failed: %x\n", (int) EfiStatus);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+    goto Error;
+  }
+
+  free (ParameterBufferDest);
+  ParameterBufferDest = NULL;
+  Status = sd_bus_message_append (Reply, "uu", ConvertEfiStatus (PrmHandlerStatus), ConvertEfiStatus (ReturnedStatus));
+  if (Status < 0) {
+    fprintf (stderr, "sd_bus_message_append() Failed: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+  }
+
+  //
+  // Send the reply to the D-BUS client
+  //
+  Status = sd_bus_send (mBus, Reply, NULL);
+  sd_bus_message_unref (Reply);
+
+  return Status;
+
+Error:
+  if (ParameterBufferDest != NULL) {
+    free (ParameterBufferDest);
+  }
+  Status = sd_bus_message_new_method_return (Message, &Reply);
+  if (Status < 0) {
+    return Status;
+  }
+  Status = sd_bus_message_append_array (Reply, 'y', EmptyArray, 0);
+  if (Status < 0) {
+    sd_bus_message_unref (Reply);
+    return Status;
+  }
+  Status = sd_bus_message_append (Reply, "uu", 0, ConvertEfiStatus (EfiStatus));
+  if (Status < 0) {
+    sd_bus_message_unref (Reply);
+    return Status;
+  }
+  Status = sd_bus_send (mBus, Reply, NULL);
+  sd_bus_message_unref (Reply);
+
+  return Status;
+}
+
+static int
+DbusUninstallPrmModule (
+  sd_bus_message  *Message,
+  void            *UserData,
+  sd_bus_error    *ReturnStatus
+  )
+{
+  //@todo
+  return EFI_UNSUPPORTED;
+}
+
+  // SD_BUS_METHOD_WITH_ARGS (
+  //   "GetHandlerDebugInfo",
+  //   SD_BUS_ARGS ("s", HandlerGuid),
+  //   SD_BUS_RESULT ("ay", AcpiParameterBuffer, "s", HandlerName, "u", EfiStatus),
+  //   DbusGetHandlerDebugInfo,
+  //   SD_BUS_VTABLE_UNPRIVILEGED
+  //   ),
+
+static int
+DbusGetHandlerDebugInfo (
+  sd_bus_message  *Message,
+  void            *UserData,
+  sd_bus_error    *ReturnStatus
+  )
+{
+  EFI_GUID                                                    HandlerGuid;
+  EMU_DBUS_PRMD_SERVICE_COMMUNICATE_GET_HANDLER_DEBUG_INFO    *GetHandlerDebugInfoData;
+  EFI_STATUS                                                  EfiStatus;
+  EFI_STATUS                                                  ReturnedStatus;
+  int                                                         Status;
+  char                                                        *HandlerGuidStr;
+  sd_bus_message                                              *Reply = NULL;
+  char                                                        EmptyArray[] = "\0";
+
+  //
+  // Get the HandlerGuid and ParameterBuffer from the D-BUS message
+  //
+  Status = sd_bus_message_read (Message, "s", &HandlerGuidStr);
+  if (Status < 0) {
+    fprintf (stderr, "Failed to read PRM package: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    goto Error;
+  }
+  EfiStatus = AsciiStrToGuid (HandlerGuidStr, &HandlerGuid);
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "AsciiStrToGuid() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+
+  //
+  // Populate the mailbox message
+  //
+  EfiStatus = SecDbusAcquireMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusAcquireMailbox() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+  ZeroMem ((VOID *) gPrmDispatchMailbox, PRMD_DBUS_MAILBOX_SIZE);
+  gPrmDispatchMailbox->Function = EMU_DBUS_PRMD_SERVICE_FUNCTION_GET_HANDLER_DEBUG_INFO;
+  GetHandlerDebugInfoData = (EMU_DBUS_PRMD_SERVICE_COMMUNICATE_GET_HANDLER_DEBUG_INFO *) &(gPrmDispatchMailbox->Data[0]);
+  CopyGuid (&GetHandlerDebugInfoData->HandlerGuid, &HandlerGuid);
+  EfiStatus = SecDbusReleaseMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusReleaseMailbox() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+
+  //
+  // Inform the DaemonBds DXE driver that a new message is waiting
+  //
+  DbusSignalDxeMessageIsReady ();
+
+  //
+  // Wait for DaemonBds to process the message
+  //
+  EfiStatus = DbusWaitForDxeResponse ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "DbusWaitForDxeResponse() Failed: %x\n", (int) EfiStatus);
+    goto Error;
+  }
+
+  //
+  // Create a message for the reply
+  //
+  Status = sd_bus_message_new_method_return (Message, &Reply);
+  if (Status < 0) {
+    fprintf (stderr, "sd_bus_message_new_method_return() Failed: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    goto Error;
+  }
+
+  //
+  // Populate the reply with the returned data from DaemonBds
+  //
+  EfiStatus = SecDbusAcquireMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusAcquireMailbox() Failed: %x\n", (int) EfiStatus);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+    goto Error;
+  }
+  ReturnedStatus = gPrmDispatchMailbox->Status;
+  //@todo There is an obscure race condition here. The AcpiParameterBuffer and
+  //      HandlerName are contained in PrmDispatcher's internal data structures.
+  //      Therefore, if someone implements a EFI_TIMER event handler that
+  //      installs/uninstall PRM modules these structures could be modified by
+  //      the main thread while we are reading them. This is very unlikely but
+  //      DaemonBds should be modified to handle this corner case.
+  Status  = sd_bus_message_append_array (
+              Reply,
+              'y',
+              GetHandlerDebugInfoData->AcpiParameterBuffer,
+              GetHandlerDebugInfoData->AcpiParameterBufferLength
+              );
+  if (Status < 0) {
+    fprintf (stderr, "sd_bus_message_append_array() Failed: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+    SecDbusReleaseMailbox ();
+    goto Error;
+  }
+  Status = sd_bus_message_append (Reply, "s", GetHandlerDebugInfoData->HandlerName);
+  if (Status < 0) {
+    fprintf (stderr, "sd_bus_message_append() Failed: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+    SecDbusReleaseMailbox ();
+    goto Error;
+  }
+  EfiStatus = SecDbusReleaseMailbox ();
+  if (EFI_ERROR (EfiStatus)) {
+    fprintf (stderr, "SecDbusReleaseMailbox() Failed: %x\n", (int) EfiStatus);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+    goto Error;
+  }
+
+  Status = sd_bus_message_append (Reply, "u", ConvertEfiStatus (ReturnedStatus));
+  if (Status < 0) {
+    fprintf (stderr, "sd_bus_message_append() Failed: %s\n", strerror (-Status));
+    EfiStatus = ConvertStatus (-Status);
+    sd_bus_message_unref (Reply);
+    Reply = NULL;
+  }
+
+  //
+  // Send the reply to the D-BUS client
+  //
+  Status = sd_bus_send (mBus, Reply, NULL);
+  sd_bus_message_unref (Reply);
+
+  return Status;
+
+Error:
+  Status = sd_bus_message_new_method_return (Message, &Reply);
+  if (Status < 0) {
+    return Status;
+  }
+  Status = sd_bus_message_append_array (Reply, 'y', EmptyArray, 0);
+  if (Status < 0) {
+    sd_bus_message_unref (Reply);
+    return Status;
+  }
+  Status = sd_bus_message_append (Reply, "su", EmptyArray, ConvertEfiStatus (EfiStatus));
+  if (Status < 0) {
+    sd_bus_message_unref (Reply);
+    return Status;
+  }
+  Status = sd_bus_send (mBus, Reply, NULL);
+  sd_bus_message_unref (Reply);
+
+  return Status;
+}
+
+//
+// D-Bus Interface Definition
+//
+static const sd_bus_vtable PrmDispatchVtable[] = {
+  SD_BUS_VTABLE_START (0),
+  SD_BUS_METHOD_WITH_ARGS (
+    "InstallPrmPackage",
+    SD_BUS_ARGS ("ay", PrmPackage),
+    SD_BUS_RESULT ("u", EfiStatus),
+    DbusInstallPrmPackage,
+    SD_BUS_VTABLE_UNPRIVILEGED
+    ),
+  SD_BUS_METHOD_WITH_ARGS (
+    "EnumerateHandlers",
+    SD_BUS_NO_ARGS,
+    SD_BUS_RESULT ("u", EfiStatus, "a{ss}", PrmHandlerInfo),
+    DbusEnumerateHandlers,
+    SD_BUS_VTABLE_UNPRIVILEGED
+    ),
+  SD_BUS_METHOD_WITH_ARGS (
+    "InvokeHandler",
+    SD_BUS_ARGS ("s", HandlerGuid, "ay", ParameterBuffer),
+    SD_BUS_RESULT ("ay", ModifiedParameterBuffer, "u", PrmHandlerReturnStatus, "u", EfiStatus),
+    DbusInvokeHandler,
+    SD_BUS_VTABLE_UNPRIVILEGED
+    ),
+  SD_BUS_METHOD_WITH_ARGS (
+    "UninstallPrmModule",
+    SD_BUS_ARGS ("s", ModuleGuid),
+    SD_BUS_RESULT ("u", EfiStatus),
+    DbusUninstallPrmModule,
+    SD_BUS_VTABLE_UNPRIVILEGED
+    ),
+  SD_BUS_METHOD_WITH_ARGS (
+    "GetHandlerDebugInfo",
+    SD_BUS_ARGS ("s", HandlerGuid),
+    SD_BUS_RESULT ("ay", AcpiParameterBuffer, "s", HandlerName, "u", EfiStatus),
+    DbusGetHandlerDebugInfo,
+    SD_BUS_VTABLE_UNPRIVILEGED
+    ),
+  SD_BUS_VTABLE_END
+};
+
+void*
+DBusWorkerThread (
+  void *Arg
+  )
+{
+//  struct sigaction    act;
+  int                 Status;
+  sd_bus_slot         *Slot = NULL;
+
+
+  // // @todo DELETE
+  // // Register a signal handler for SIGTERM so that if the daemon is requested
+  // // to exit this thread will shut itself down cleanly.
+  // //
+  // sigemptyset (&act.sa_mask);
+  // act.sa_flags = SA_SIGINFO;
+  // act.sa_sigaction = SignalHandler;
+  // sigaction (SIGTERM, &act, NULL);
+
+  //
+  // Open a connection to the system level D-BUS
+  //
+  Status = sd_bus_open_system (&mBus);
+  if (Status < 0) {
+    fprintf (stderr, "Failed to connect to system D-BUS: %s\n", strerror (-Status));
+    goto Done;
+  }
+
+  //
+  // Register the PrmDispatch service on to the message bus
+  //
+  Status  = sd_bus_add_object_vtable (
+              mBus,
+              &Slot,
+              PRMD_DBUS_OBJECT_NAME,
+              PRMD_DBUS_INTERFACE_NAME,
+              PrmDispatchVtable,
+              NULL
+              );
+  if (Status < 0) {
+    fprintf (stderr, "Failed to add D-Bus object: %s\n", strerror (-Status));
+    goto Done;
+  }
+
+  Status = sd_bus_request_name (mBus, PRMD_DBUS_SERVICE_NAME, 0);
+  if (Status < 0) {
+    fprintf (stderr, "Failed to acquire D-Bus service name: %s\n", strerror (-Status));
+    goto Done;
+  }
+
+  //
+  // Message Processing Loop
+  //
+  while (1) {
+    Status = sd_bus_process (mBus, NULL);
+    if (Status < 0) {
+      fprintf (stderr, "Failed to process bus: %s\n", strerror (-Status));
+      goto Done;
+    }
+    if (Status > 0) {
+      //
+      // If a dbus request was processed, immediately try to process another
+      // request because it is possible that multiple requests are currently
+      // sitting in the queue
+      //
+      continue;
+    }
+
+check_sigterm:
+    //
+    // If we have received SIGTERM, exit the loop and allow the thread to quit
+    //
+    if (GetIsSigTermSignaled ()) {
+      printf ("Exiting D-BUS loop.\n");
+      goto Done;
+    }
+
+    //
+    // Wait for the next message to come in
+    //
+    Status = sd_bus_wait (mBus, 1000000 /* 1 sec */);
+    if (Status < 0) {
+      fprintf (stderr, "Failed to wait for bus traffic: %s\n", strerror (-Status));
+      goto Done;
+    }
+    if (Status == 0) {
+      //
+      // sd_bus_wait() timed out, check for SIGTERM and then start waiting again
+      //
+      goto check_sigterm;
+    }
+  }
+
+Done:
+  sd_bus_slot_unref (Slot);
+  sd_bus_unref (mBus);
+  free (gPrmDispatchMailbox);
+  gPrmDispatchMailbox = NULL;
+  return NULL;
+}
+
+/**
+  Acquire the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was acquired successfully.
+  @retval EFI_TIMEOUT                 Acquiring the mailbox failed.
+
+**/
+EFI_STATUS
+SecDbusAcquireMailbox (
+  VOID
+  )
+{
+  int Status;
+
+  Status = pthread_mutex_lock (&mPrmDispatchMailbox);
+  if (Status != 0) {
+    return ConvertStatus (Status);
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Release the lock semaphore for the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 The mailbox was released successfully.
+  @retval EFI_TIMEOUT                 Releasing the mailbox failed.
+
+**/
+EFI_STATUS
+SecDbusReleaseMailbox (
+  VOID
+  )
+{
+  int Status;
+
+  Status = pthread_mutex_unlock (&mPrmDispatchMailbox);
+  if (Status != 0) {
+    return ConvertStatus (Status);
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Wait for a new message to be stored in the PRM Dispatch Service Mailbox
+
+  @retval EFI_SUCCESS                 A new message is in the mailbox
+  @retval EFI_TIMEOUT                 Waiting for a new message failed.
+
+**/
+EFI_STATUS
+SecDbusWaitForMessage (
+  VOID
+  )
+{
+  int Status;
+
+  Status = pthread_mutex_lock (&mMessageIsReadyMutex);
+  if (Status != 0) {
+    return ConvertStatus (Status);
+  }
+  while (!mMessageIsReadyFlag) {
+    Status = pthread_cond_wait (&mMessageIsReadyCond, &mMessageIsReadyMutex);
+    if (Status != 0) {
+      pthread_mutex_unlock (&mMessageIsReadyMutex);
+      return ConvertStatus (Status);
+    }
+  }
+  mMessageIsReadyFlag = 0;
+  Status = pthread_mutex_unlock (&mMessageIsReadyMutex);
+  if (Status != 0) {
+    return ConvertStatus (Status);
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Signal that the message has been successfully processed and the results
+  are waiting in the PRM Dispatch Service Mailbox
+
+  @retval None
+
+**/
+VOID
+SecDbusMessageResponseReady (
+  VOID
+  )
+{
+  int Status;
+
+  Status = pthread_mutex_lock (&mResponseIsReadyMutex);
+  if (Status != 0) {
+    return;
+  }
+  mResponseIsReadyFlag = 1;
+  Status = pthread_cond_signal (&mResponseIsReadyCond);
+  if (Status != 0) {
+    pthread_mutex_unlock (&mResponseIsReadyMutex);
+    return;
+  }
+  Status = pthread_mutex_unlock (&mResponseIsReadyMutex);
+  if (Status != 0) {
+    return;
+  }
+}
+
+EMU_DBUS_PRMD_SERVICE_THUNK_PROTOCOL  gEmuDbusPrmdServiceThunk = {
+  GasketEmuDbusAcquireMailbox,
+  GasketEmuDbusReleaseMailbox,
+  GasketEmuDbusWaitForMessage,
+  GasketEmuDbusMessageResponseReady,
+  NULL  // Mailbox is initialized in SecDbusInitializeListener()
+};
+
+/**
+  Initialize the background worker thread for D-BUS communication
+
+  @retval EFI_SUCCESS                 The D-BUS listener was activated successfully.
+
+**/
+EFI_STATUS
+SecDbusInitializeListener (
+  VOID
+  )
+{
+  pthread_t Thread;
+  int Status;
+
+  gPrmDispatchMailbox = (EMU_DBUS_PRMD_SERVICE_COMMUNICATE_HEADER *) malloc (PRMD_DBUS_MAILBOX_SIZE);
+  if (gPrmDispatchMailbox == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  gEmuDbusPrmdServiceThunk.Mailbox = gPrmDispatchMailbox;
+
+  Status = pthread_create (&Thread, NULL, DBusWorkerThread, NULL);
+  if (Status != 0) {
+    return ConvertStatus (Status);
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SecDbusPrmdServiceThunkOpen (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  )
+{
+  if (This->Instance != 0) {
+    // Only single instance is supported
+    return EFI_NOT_FOUND;
+  }
+
+  This->Interface = &gEmuDbusPrmdServiceThunk;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SecDbusPrmdServiceThunkClose (
+  IN  EMU_IO_THUNK_PROTOCOL  *This
+  )
+{
+  return EFI_SUCCESS;
+}
+
+EMU_IO_THUNK_PROTOCOL  gDbusPrmdServiceThunkIo = {
+  &gEmuDbusPrmdServiceProtocolGuid,
+  NULL,
+  NULL,
+  0,
+  GasketEmuDbusThunkOpen,
+  GasketEmuDbusThunkClose,
+  NULL
+};
+
+// GMainLoop *mainloop;
+
+// /*
+//  * This is the XML string describing the interfaces, methods and
+//  * signals implemented by our 'Server' object. It's used by the
+//  * 'Introspect' method of 'org.freedesktop.DBus.Introspectable'
+//  * interface.
+//  */
+// const char *server_introspection_xml =
+//     DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
+//     "<node>\n"
+
+//     "  <interface name='org.freedesktop.DBus.Introspectable'>\n"
+//     "    <method name='Introspect'>\n"
+//     "      <arg name='data' type='s' direction='out' />\n"
+//     "    </method>\n"
+//     "  </interface>\n"
+
+//     "  <interface name='org.freedesktop.DBus.Properties'>\n"
+//     "    <method name='Get'>\n"
+//     "      <arg name='interface' type='s' direction='in' />\n"
+//     "      <arg name='property'  type='s' direction='in' />\n"
+//     "      <arg name='value'     type='s' direction='out' />\n"
+//     "    </method>\n"
+//     "    <method name='GetAll'>\n"
+//     "      <arg name='interface'  type='s'     direction='in'/>\n"
+//     "      <arg name='properties' type='a{sv}' direction='out'/>\n"
+//     "    </method>\n"
+//     "  </interface>\n"
+
+//     "  <interface name='com.Intel.PrmDispatch'>\n"
+//     "    <property name='Version' type='s' access='read' />\n"
+//     "    <method name='InstallPrmPackage'>\n"
+//     "       <arg type='ay' direction='in' name='PrmPackage' />\n"
+//     "       <arg type='u' direction='out' name='EfiStatus' />\n"
+//     "    </method>\n"
+//     "    <method name='EnumerateHandlers'>\n"
+//     "       <arg type='u' direction='out' name='EfiStatus'>\n"
+//     "       <arg type='a{ss} direction='out' name='PrmHandlerInfo' />\n"
+//     "         <entry key='PlatformGuid' value='s'/>\n"
+//     "         <entry key='ModuleGuid' value='s'/>\n"
+//     "         <entry key='HandlerGuid' value='s'/>\n"
+//     "       </arg>\n"
+//     "    </method>\n"
+//     "    <method name='InvokeHandler'>\n"
+//     "       <arg type='s' direction='in' name='HandlerGuid'/>\n"
+//     "       <arg type='ay' direction='in' name='ParameterBuffer' optional='true'/>\n"
+//     "       <arg type='u' direction='out' name='PrmHandlerReturnStatus'/>\n"
+//     "       <arg type='u' direction='out' name='EfiStatus'  "
+//     "    </method>\n"
+//     "    <method name='UninstallPrmModule'>\n"
+//     "       <arg type='s' direction='in' name='ModuleGuid'/>\n"
+//     "       <arg type='u' direction='out' name='EfiStatus'/>\n"
+//     "     </method>\n"
+//     "     <method name='GetHandlerDebugInfo'>\n"
+//     "       <arg type='s' direction='in' name='HandlerGuid'/>\n"
+//     "       <arg type='ay' direction='out' name='AcpiParameterBuffer'/>\n"
+//     "       <arg type='s' direction='out' name='HandlerName' />\n"
+//     "       <arg type='u' durection='out' name='EfiStatus'/>\n"
+//     "     </method>\n"
+//     "    <method name='Quit'>\n"
+// 	  "    </method>\n"
+//     "  </interface>\n"
+
+//     "</node>\n";
+
+// /*
+//  * This implements 'Get' method of DBUS_INTERFACE_PROPERTIES so a
+//  * client can inspect the properties/attributes of 'TestInterface'.
+//  */
+// DBusHandlerResult server_get_properties_handler(const char *property, DBusConnection *conn, DBusMessage *reply)
+// {
+//   if (!strcmp(property, "Version"))
+//   {
+//     dbus_message_append_args(reply,
+//                              DBUS_TYPE_STRING, &version,
+//                              DBUS_TYPE_INVALID);
+//   }
+//   else
+//     /* Unknown property */
+//     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+//   if (!dbus_connection_send(conn, reply, NULL))
+//     return DBUS_HANDLER_RESULT_NEED_MEMORY;
+//   return DBUS_HANDLER_RESULT_HANDLED;
+// }
+
+// /*
+//  * This implements 'GetAll' method of DBUS_INTERFACE_PROPERTIES. This
+//  * one seems required by g_dbus_proxy_get_cached_property().
+//  */
+// DBusHandlerResult server_get_all_properties_handler(DBusConnection *conn, DBusMessage *reply)
+// {
+//   DBusHandlerResult result;
+//   DBusMessageIter array, dict, iter, variant;
+//   const char *property = "Version";
+
+//   /*
+//    * All dbus functions used below might fail due to out of
+//    * memory error. If one of them fails, we assume that all
+//    * following functions will fail too, including
+//    * dbus_connection_send().
+//    */
+//   result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+//   dbus_message_iter_init_append(reply, &iter);
+//   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
+
+//   /* Append all properties name/value pairs */
+//   property = "Version";
+//   dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
+//   dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &property);
+//   dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, "s", &variant);
+//   dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &version);
+//   dbus_message_iter_close_container(&dict, &variant);
+//   dbus_message_iter_close_container(&array, &dict);
+//   dbus_message_iter_close_container(&iter, &array);
+
+//   if (dbus_connection_send(conn, reply, NULL))
+//     result = DBUS_HANDLER_RESULT_HANDLED;
+//   return result;
+// }
+
+// /*
+//  * This function implements the 'TestInterface' interface for the
+//  * 'Server' DBus object.
+//  *
+//  * It also implements 'Introspect' method of
+//  * 'org.freedesktop.DBus.Introspectable' interface which returns the
+//  * XML string describing the interfaces, methods, and signals
+//  * implemented by 'Server' object. This also can be used by tools such
+//  * as d-feet(1) and can be queried by:
+//  *
+//  * $ gdbus introspect --session --dest org.example.TestServer --object-path /org/example/TestObject
+//  */
+// DBusHandlerResult server_message_handler(DBusConnection *conn, DBusMessage *message, void *data)
+// {
+//   DBusHandlerResult result;
+//   DBusMessage *reply = NULL;
+//   DBusError err;
+//   bool quit = false;
+
+//   fprintf(stderr, "Got D-Bus request: %s.%s on %s\n",
+//           dbus_message_get_interface(message),
+//           dbus_message_get_member(message),
+//           dbus_message_get_path(message));
+
+//   /*
+//    * Does not allocate any memory; the error only needs to be
+//    * freed if it is set at some point.
+//    */
+//   dbus_error_init(&err);
+
+//   if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
+//   {
+
+//     if (!(reply = dbus_message_new_method_return(message)))
+//       goto fail;
+
+//     dbus_message_append_args(reply,
+//                              DBUS_TYPE_STRING, &server_introspection_xml,
+//                              DBUS_TYPE_INVALID);
+//   }
+//   else if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "Get"))
+//   {
+//     const char *interface, *property;
+
+//     if (!dbus_message_get_args(message, &err,
+//                                DBUS_TYPE_STRING, &interface,
+//                                DBUS_TYPE_STRING, &property,
+//                                DBUS_TYPE_INVALID))
+//       goto fail;
+
+//     if (!(reply = dbus_message_new_method_return(message)))
+//       goto fail;
+
+//     result = server_get_properties_handler(property, conn, reply);
+//     dbus_message_unref(reply);
+//     return result;
+//   }
+//   else if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "GetAll"))
+//   {
+
+//     if (!(reply = dbus_message_new_method_return(message)))
+//       goto fail;
+
+//     result = server_get_all_properties_handler(conn, reply);
+//     dbus_message_unref(reply);
+//     return result;
+//   }
+//   else if (dbus_message_is_method_call(message, "com.Intel.PrmDispatch", "Quit"))
+//   {
+//     /*
+//      * Quit() has no return values but a METHOD_RETURN
+//      * reply is required, so the caller will know the
+//      * method was successfully processed.
+//      */
+//     reply = dbus_message_new_method_return(message);
+//     quit = true;
+//   }
+//   else
+//     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+// fail:
+//   if (dbus_error_is_set(&err))
+//   {
+//     if (reply)
+//       dbus_message_unref(reply);
+//     reply = dbus_message_new_error(message, err.name, err.message);
+//     dbus_error_free(&err);
+//   }
+
+//   /*
+//    * In any cases we should have allocated a reply otherwise it
+//    * means that we failed to allocate one.
+//    */
+//   if (!reply)
+//     return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+//   /* Send the reply which might be an error one too. */
+//   result = DBUS_HANDLER_RESULT_HANDLED;
+//   if (!dbus_connection_send(conn, reply, NULL))
+//     result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+//   dbus_message_unref(reply);
+
+//   if (quit)
+//   {
+//     fprintf(stderr, "Server exiting...\n");
+// 		g_main_loop_quit(mainloop);
+// 	}
+// 	return result;
+// }
+
+
+// const DBusObjectPathVTable server_vtable = {
+// 	.message_function = server_message_handler
+// };
+
+
+// int run_server(void)
+// {
+// 	DBusConnection *conn;
+// 	DBusError err;
+// 	int rv;
+
+//   dbus_error_init(&err);
+
+// 	/* connect to the daemon bus */
+// 	conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
+// 	if (!conn) {
+// 		fprintf(stderr, "Failed to get a session DBus connection: %s\n", err.message);
+// 		goto fail;
+// 	}
+
+// 	rv = dbus_bus_request_name(conn, "com.intel.PrmDispatch", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
+// 	if (rv != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+// 		fprintf(stderr, "Failed to request name on bus: %s\n", err.message);
+// 		goto fail;
+// 	}
+
+// 	if (!dbus_connection_register_object_path(conn, "/com/intel/PrmDispatch", &server_vtable, NULL)) {
+// 		fprintf(stderr, "Failed to register a object path for 'PrmDispatch'\n");
+// 		goto fail;
+// 	}
+
+// 	/*
+// 	 * For the sake of simplicity we're using glib event loop to
+// 	 * handle DBus messages. This is the only place where glib is
+// 	 * used.
+// 	 */
+// 	printf("Starting demo dbus server v%s\n", version);
+// 	mainloop = g_main_loop_new(NULL, false);
+// 	/* Set up the DBus connection to work in a GLib event loop */
+// 	dbus_connection_setup_with_g_main(conn, NULL);
+// 	/* Start the glib event loop */
+// 	g_main_loop_run(mainloop);
+
+// 	return EXIT_SUCCESS;
+// fail:
+// 	dbus_error_free(&err);
+// 	return EXIT_FAILURE;
+// }
+
+// int main(void){
+//   run_server();
+// }
diff --git a/EmulatorPkg/Unix/Host/DbusServer.c b/EmulatorPkg/Unix/Host/DbusServer.c
deleted file mode 100644
index ea7a2a6..0000000
--- a/EmulatorPkg/Unix/Host/DbusServer.c
+++ /dev/null
@@ -1,295 +0,0 @@
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h> /* for glib main loop */
-
-const char *version = "0.1";
-GMainLoop *mainloop;
-
-/*
- * This is the XML string describing the interfaces, methods and
- * signals implemented by our 'Server' object. It's used by the
- * 'Introspect' method of 'org.freedesktop.DBus.Introspectable'
- * interface.
- */
-const char *server_introspection_xml =
-    DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
-    "<node>\n"
-
-    "  <interface name='org.freedesktop.DBus.Introspectable'>\n"
-    "    <method name='Introspect'>\n"
-    "      <arg name='data' type='s' direction='out' />\n"
-    "    </method>\n"
-    "  </interface>\n"
-
-    "  <interface name='org.freedesktop.DBus.Properties'>\n"
-    "    <method name='Get'>\n"
-    "      <arg name='interface' type='s' direction='in' />\n"
-    "      <arg name='property'  type='s' direction='in' />\n"
-    "      <arg name='value'     type='s' direction='out' />\n"
-    "    </method>\n"
-    "    <method name='GetAll'>\n"
-    "      <arg name='interface'  type='s'     direction='in'/>\n"
-    "      <arg name='properties' type='a{sv}' direction='out'/>\n"
-    "    </method>\n"
-    "  </interface>\n"
-
-    "  <interface name='com.Intel.PrmDispatch'>\n"
-    "    <property name='Version' type='s' access='read' />\n"
-    "    <method name='InstallPrmPackage'>\n"
-    "       <arg type='ay' direction='in' name='PrmPackage' />\n"
-    "       <arg type='u' direction='out' name='EfiStatus' />\n"
-    "    </method>\n"
-    "    <method name='EnumerateHandlers'>\n"
-    "       <arg type='u' direction='out' name='EfiStatus'>\n"
-    "       <arg type='a{ss} direction='out' name='PrmHandlerInfo' />\n"
-    "         <entry key='PlatformGuid' value='s'/>\n"
-    "         <entry key='ModuleGuid' value='s'/>\n"
-    "         <entry key='HandlerGuid' value='s'/>\n"
-    "       </arg>\n"
-    "    </method>\n"
-    "    <method name='InvokeHandler'>\n"
-    "       <arg type='s' direction='in' name='HandlerGuid'/>\n"
-    "       <arg type='ay' direction='in' name='ParameterBuffer' optional='true'/>\n"
-    "       <arg type='u' direction='out' name='PrmHandlerReturnStatus'/>\n"
-    "       <arg type='u' direction='out' name='EfiStatus'  "
-    "    </method>\n"
-    "    <method name='UninstallPrmModule'>\n"
-    "       <arg type='s' direction='in' name='ModuleGuid'/>\n"
-    "       <arg type='u' direction='out' name='EfiStatus'/>\n"
-    "     </method>\n"
-    "     <method name='GetHandlerDebugInfo'>\n"
-    "       <arg type='s' direction='in' name='HandlerGuid'/>\n"
-    "       <arg type='ay' direction='out' name='AcpiParameterBuffer'/>\n"
-    "       <arg type='s' direction='out' name='HandlerName' />\n"
-    "       <arg type='u' durection='out' name='EfiStatus'/>\n"
-    "     </method>\n"
-    "    <method name='Quit'>\n"
-	  "    </method>\n"
-    "  </interface>\n"
-
-    "</node>\n";
-
-/*
- * This implements 'Get' method of DBUS_INTERFACE_PROPERTIES so a
- * client can inspect the properties/attributes of 'TestInterface'.
- */
-DBusHandlerResult server_get_properties_handler(const char *property, DBusConnection *conn, DBusMessage *reply)
-{
-  if (!strcmp(property, "Version"))
-  {
-    dbus_message_append_args(reply,
-                             DBUS_TYPE_STRING, &version,
-                             DBUS_TYPE_INVALID);
-  }
-  else
-    /* Unknown property */
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-  if (!dbus_connection_send(conn, reply, NULL))
-    return DBUS_HANDLER_RESULT_NEED_MEMORY;
-  return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-/*
- * This implements 'GetAll' method of DBUS_INTERFACE_PROPERTIES. This
- * one seems required by g_dbus_proxy_get_cached_property().
- */
-DBusHandlerResult server_get_all_properties_handler(DBusConnection *conn, DBusMessage *reply)
-{
-  DBusHandlerResult result;
-  DBusMessageIter array, dict, iter, variant;
-  const char *property = "Version";
-
-  /*
-   * All dbus functions used below might fail due to out of
-   * memory error. If one of them fails, we assume that all
-   * following functions will fail too, including
-   * dbus_connection_send().
-   */
-  result = DBUS_HANDLER_RESULT_NEED_MEMORY;
-
-  dbus_message_iter_init_append(reply, &iter);
-  dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
-
-  /* Append all properties name/value pairs */
-  property = "Version";
-  dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
-  dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &property);
-  dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, "s", &variant);
-  dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &version);
-  dbus_message_iter_close_container(&dict, &variant);
-  dbus_message_iter_close_container(&array, &dict);
-  dbus_message_iter_close_container(&iter, &array);
-
-  if (dbus_connection_send(conn, reply, NULL))
-    result = DBUS_HANDLER_RESULT_HANDLED;
-  return result;
-}
-
-/*
- * This function implements the 'TestInterface' interface for the
- * 'Server' DBus object.
- *
- * It also implements 'Introspect' method of
- * 'org.freedesktop.DBus.Introspectable' interface which returns the
- * XML string describing the interfaces, methods, and signals
- * implemented by 'Server' object. This also can be used by tools such
- * as d-feet(1) and can be queried by:
- *
- * $ gdbus introspect --session --dest org.example.TestServer --object-path /org/example/TestObject
- */
-DBusHandlerResult server_message_handler(DBusConnection *conn, DBusMessage *message, void *data)
-{
-  DBusHandlerResult result;
-  DBusMessage *reply = NULL;
-  DBusError err;
-  bool quit = false;
-
-  fprintf(stderr, "Got D-Bus request: %s.%s on %s\n",
-          dbus_message_get_interface(message),
-          dbus_message_get_member(message),
-          dbus_message_get_path(message));
-
-  /*
-   * Does not allocate any memory; the error only needs to be
-   * freed if it is set at some point.
-   */
-  dbus_error_init(&err);
-
-  if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
-  {
-
-    if (!(reply = dbus_message_new_method_return(message)))
-      goto fail;
-
-    dbus_message_append_args(reply,
-                             DBUS_TYPE_STRING, &server_introspection_xml,
-                             DBUS_TYPE_INVALID);
-  }
-  else if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "Get"))
-  {
-    const char *interface, *property;
-
-    if (!dbus_message_get_args(message, &err,
-                               DBUS_TYPE_STRING, &interface,
-                               DBUS_TYPE_STRING, &property,
-                               DBUS_TYPE_INVALID))
-      goto fail;
-
-    if (!(reply = dbus_message_new_method_return(message)))
-      goto fail;
-
-    result = server_get_properties_handler(property, conn, reply);
-    dbus_message_unref(reply);
-    return result;
-  }
-  else if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "GetAll"))
-  {
-
-    if (!(reply = dbus_message_new_method_return(message)))
-      goto fail;
-
-    result = server_get_all_properties_handler(conn, reply);
-    dbus_message_unref(reply);
-    return result;
-  }
-  else if (dbus_message_is_method_call(message, "com.Intel.PrmDispatch", "Quit"))
-  {
-    /*
-     * Quit() has no return values but a METHOD_RETURN
-     * reply is required, so the caller will know the
-     * method was successfully processed.
-     */
-    reply = dbus_message_new_method_return(message);
-    quit = true;
-  }
-  else
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-fail:
-  if (dbus_error_is_set(&err))
-  {
-    if (reply)
-      dbus_message_unref(reply);
-    reply = dbus_message_new_error(message, err.name, err.message);
-    dbus_error_free(&err);
-  }
-
-  /*
-   * In any cases we should have allocated a reply otherwise it
-   * means that we failed to allocate one.
-   */
-  if (!reply)
-    return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
-  /* Send the reply which might be an error one too. */
-  result = DBUS_HANDLER_RESULT_HANDLED;
-  if (!dbus_connection_send(conn, reply, NULL))
-    result = DBUS_HANDLER_RESULT_NEED_MEMORY;
-  dbus_message_unref(reply);
-
-  if (quit)
-  {
-    fprintf(stderr, "Server exiting...\n");
-		g_main_loop_quit(mainloop);
-	}
-	return result;
-}
-
-
-const DBusObjectPathVTable server_vtable = {
-	.message_function = server_message_handler
-};
-
-
-int run_server(void)
-{
-	DBusConnection *conn;
-	DBusError err;
-	int rv;
-
-  dbus_error_init(&err);
-
-	/* connect to the daemon bus */
-	conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
-	if (!conn) {
-		fprintf(stderr, "Failed to get a session DBus connection: %s\n", err.message);
-		goto fail;
-	}
-
-	rv = dbus_bus_request_name(conn, "com.Intel.PrmDispatchServer", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
-	if (rv != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-		fprintf(stderr, "Failed to request name on bus: %s\n", err.message);
-		goto fail;
-	}
-
-	if (!dbus_connection_register_object_path(conn, "/org/Intel/PrmDispatchAPIObject", &server_vtable, NULL)) {
-		fprintf(stderr, "Failed to register a object path for 'PrmDispatchAPIObject'\n");
-		goto fail;
-	}
-
-	/*
-	 * For the sake of simplicity we're using glib event loop to
-	 * handle DBus messages. This is the only place where glib is
-	 * used.
-	 */
-	printf("Starting demo dbus server v%s\n", version);
-	mainloop = g_main_loop_new(NULL, false);
-	/* Set up the DBus connection to work in a GLib event loop */
-	dbus_connection_setup_with_g_main(conn, NULL);
-	/* Start the glib event loop */
-	g_main_loop_run(mainloop);
-
-	return EXIT_SUCCESS;
-fail:
-	dbus_error_free(&err);
-	return EXIT_FAILURE;
-}
-
-int main(void){
-  run_server();
-}
\ No newline at end of file
diff --git a/EmulatorPkg/Unix/Host/Gasket.h b/EmulatorPkg/Unix/Host/Gasket.h
index 50f40fc..73b627a 100644
--- a/EmulatorPkg/Unix/Host/Gasket.h
+++ b/EmulatorPkg/Unix/Host/Gasket.h
@@ -690,13 +690,13 @@
 

 EFI_STATUS

 EFIAPI

-GasketSignalOpen (

+GasketEmuSignalThunkOpen (

   IN  EMU_IO_THUNK_PROTOCOL  *This

   );

 

 EFI_STATUS

 EFIAPI

-GasketSignalClose (

+GasketEmuSignalThunkClose (

   IN  EMU_IO_THUNK_PROTOCOL  *This

   );

 

@@ -724,4 +724,64 @@
   IN      UINT32    value

   );

 

+/**

+  Acquire the lock semaphore for the PRM Dispatch Service Mailbox

+

+  @retval EFI_SUCCESS                 The mailbox was acquired successfully.

+  @retval EFI_TIMEOUT                 Acquiring the mailbox failed.

+

+**/

+EFI_STATUS

+GasketEmuDbusAcquireMailbox (

+  VOID

+  );

+

+/**

+  Release the lock semaphore for the PRM Dispatch Service Mailbox

+

+  @retval EFI_SUCCESS                 The mailbox was released successfully.

+  @retval EFI_TIMEOUT                 Releasing the mailbox failed.

+

+**/

+EFI_STATUS

+GasketEmuDbusReleaseMailbox (

+  VOID

+  );

+

+/**

+  Wait for a new message to be stored in the PRM Dispatch Service Mailbox

+

+  @retval EFI_SUCCESS                 A new message is in the mailbox

+  @retval EFI_TIMEOUT                 Waiting for a new message failed.

+

+**/

+EFI_STATUS

+GasketEmuDbusWaitForMessage (

+  VOID

+  );

+

+/**

+  Signal that the message has been successfully processed and the results

+  are waiting in the PRM Dispatch Service Mailbox

+

+  @retval None

+

+**/

+VOID

+GasketEmuDbusMessageResponseReady (

+  VOID

+  );

+

+EFI_STATUS

+EFIAPI

+GasketEmuDbusThunkOpen (

+  IN  EMU_IO_THUNK_PROTOCOL  *This

+  );

+

+EFI_STATUS

+EFIAPI

+GasketEmuDbusThunkClose (

+  IN  EMU_IO_THUNK_PROTOCOL  *This

+  );

+

 #endif

diff --git a/EmulatorPkg/Unix/Host/Host.c b/EmulatorPkg/Unix/Host/Host.c
index bb84279..17ed51d 100644
--- a/EmulatorPkg/Unix/Host/Host.c
+++ b/EmulatorPkg/Unix/Host/Host.c
@@ -166,10 +166,20 @@
   //

   AddThunkProtocol (&gPthreadThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuApCount), FALSE);

   AddThunkProtocol (&gSignalThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuSignal), FALSE);

+  AddThunkProtocol (&gDbusPrmdServiceThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuDbusPrmdService), FALSE);

 #if defined (MDE_CPU_ARM)

   AddThunkProtocol (&gCacheThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuCache), FALSE);

 #endif

 

+  //

+  // Initialize D-BUS background listener thread

+  //

+  Status = SecDbusInitializeListener ();

+  if (EFI_ERROR (Status)) {

+    printf ("ERROR : Can not start D-BUS listener thread.  Exiting.\n");

+    exit (1);

+  }

+

   // EmuSecLibConstructor ();

 

   gPpiList = GetThunkPpiList ();

diff --git a/EmulatorPkg/Unix/Host/Host.h b/EmulatorPkg/Unix/Host/Host.h
index f7d0d97..890305d 100644
--- a/EmulatorPkg/Unix/Host/Host.h
+++ b/EmulatorPkg/Unix/Host/Host.h
@@ -373,6 +373,65 @@
   IN OUT  void                      *ucontext

   );

 

+/**

+  Acquire the lock semaphore for the PRM Dispatch Service Mailbox

+

+  @retval EFI_SUCCESS                 The mailbox was acquired successfully.

+  @retval EFI_TIMEOUT                 Acquiring the mailbox failed.

+

+**/

+EFI_STATUS

+SecDbusAcquireMailbox (

+  VOID

+  );

+

+/**

+  Release the lock semaphore for the PRM Dispatch Service Mailbox

+

+  @retval EFI_SUCCESS                 The mailbox was released successfully.

+  @retval EFI_TIMEOUT                 Releasing the mailbox failed.

+

+**/

+EFI_STATUS

+SecDbusReleaseMailbox (

+  VOID

+  );

+

+/**

+  Wait for a new message to be stored in the PRM Dispatch Service Mailbox

+

+  @retval EFI_SUCCESS                 A new message is in the mailbox

+  @retval EFI_TIMEOUT                 Waiting for a new message failed.

+

+**/

+EFI_STATUS

+SecDbusWaitForMessage (

+  VOID

+  );

+

+/**

+  Signal that the message has been successfully processed and the results

+  are waiting in the PRM Dispatch Service Mailbox

+

+  @retval None

+

+**/

+VOID

+SecDbusMessageResponseReady (

+  VOID

+  );

+

+/**

+  Initialize the background worker thread for D-BUS communication

+

+  @retval EFI_SUCCESS                 The D-BUS listener was activated successfully.

+

+**/

+EFI_STATUS

+SecDbusInitializeListener (

+  VOID

+  );

+

 extern EMU_THUNK_PROTOCOL     gEmuThunkProtocol;

 //extern EMU_IO_THUNK_PROTOCOL  gX11ThunkIo;

 extern EMU_IO_THUNK_PROTOCOL  gPosixFileSystemThunkIo;

@@ -381,5 +440,6 @@
 extern EMU_IO_THUNK_PROTOCOL  gSnpThunkIo;

 extern EMU_IO_THUNK_PROTOCOL  gCacheThunkIo;

 extern EMU_IO_THUNK_PROTOCOL  gSignalThunkIo;

+extern EMU_IO_THUNK_PROTOCOL  gDbusPrmdServiceThunkIo;

 

 #endif

diff --git a/EmulatorPkg/Unix/Host/Host.inf b/EmulatorPkg/Unix/Host/Host.inf
index 057190d..aad16a5 100644
--- a/EmulatorPkg/Unix/Host/Host.inf
+++ b/EmulatorPkg/Unix/Host/Host.inf
@@ -34,6 +34,7 @@
   BerkeleyPacketFilter.c

   MemoryAllocationLib.c

   Signal.c

+  DbusPrmdService.c

 

 [Sources.X64]

   X64/Gasket.S        # convert between Emu x86_64 ABI and EFI X64 ABI

@@ -85,6 +86,7 @@
   gEmuSnpProtocolGuid

   gEmuCacheThunkProtocolGuid

   gEmuSignalThunkProtocolGuid

+  gEmuDbusPrmdServiceProtocolGuid

   gEfiSimpleFileSystemProtocolGuid

 

 [Guids]

@@ -106,6 +108,7 @@
   gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort

   gEmulatorPkgTokenSpaceGuid.PcdEmuCache

   gEmulatorPkgTokenSpaceGuid.PcdEmuSignal

+  gEmulatorPkgTokenSpaceGuid.PcdEmuDbusPrmdService

   gEmulatorPkgTokenSpaceGuid.PcdEmuNetworkInterface

   gEmulatorPkgTokenSpaceGuid.PcdNetworkPacketFilterSize

 

@@ -144,7 +147,7 @@
    GCC:*_*_ARM_DLINK_FLAGS == -o $(BIN_DIR)/Host -mthumb -march=armv7-a -mlittle-endian -mabi=aapcs

    GCC:*_*_ARM_CC_FLAGS == -g -Os -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -fno-common -march=armv7-a -mlittle-endian -mabi=aapcs -fno-short-enums -funsigned-char -fstack-protector -Wno-unused-but-set-variable -Wno-unused-const-variable -mword-relocations -flto -ffunction-sections -fdata-sections -fomit-frame-pointer -Wno-address -mthumb -mfloat-abi=hard -fno-pic -fno-pie -c -include $(DEST_DIR_DEBUG)/AutoGen.h

 

-   GCC:*_*_*_DLINK2_FLAGS == -lpthread -ldl

+   GCC:*_*_*_DLINK2_FLAGS == -lpthread -ldl -lsystemd

 

 #

 # Need to do this link via gcc and not ld as the pathing to libraries changes from OS version to OS version

diff --git a/EmulatorPkg/Unix/Host/Ia32/Gasket.S b/EmulatorPkg/Unix/Host/Ia32/Gasket.S
index dd850c1..db196e7 100644
--- a/EmulatorPkg/Unix/Host/Ia32/Gasket.S
+++ b/EmulatorPkg/Unix/Host/Ia32/Gasket.S
@@ -1539,8 +1539,8 @@
   leave

   ret

 

-ASM_GLOBAL ASM_PFX(GasketSignalOpen)

-ASM_PFX(GasketSignalOpen):

+ASM_GLOBAL ASM_PFX(GasketEmuSignalThunkOpen)

+ASM_PFX(GasketEmuSignalThunkOpen):

   pushl %ebp

   movl  %esp, %ebp

   subl  $24, %esp      // sub extra 16 from the stack for alignment

@@ -1548,13 +1548,13 @@
   movl  8(%ebp), %eax

   movl  %eax, (%esp)

 

-  call    ASM_PFX(SignalOpen)

+  call    ASM_PFX(EmuSignalThunkOpen)

 

   leave

   ret

 

-ASM_GLOBAL ASM_PFX(GasketSignalClose)

-ASM_PFX(GasketSignalClose):

+ASM_GLOBAL ASM_PFX(GasketEmuSignalThunkClose)

+ASM_PFX(GasketEmuSignalThunkClose):

   pushl %ebp

   movl  %esp, %ebp

   subl  $24, %esp      // sub extra 16 from the stack for alignment

@@ -1562,7 +1562,7 @@
   movl  8(%ebp), %eax

   movl  %eax, (%esp)

 

-  call    ASM_PFX(SignalClose)

+  call    ASM_PFX(EmuSignalThunkClose)

 

   leave

   ret

@@ -1592,3 +1592,5 @@
 

   leave

   ret

+

+//@todo Add gaskets

diff --git a/EmulatorPkg/Unix/Host/Signal.c b/EmulatorPkg/Unix/Host/Signal.c
index 7cd7160..99258c1 100644
--- a/EmulatorPkg/Unix/Host/Signal.c
+++ b/EmulatorPkg/Unix/Host/Signal.c
@@ -335,7 +335,7 @@
 };
 
 EFI_STATUS
-SignalOpen (
+EmuSignalThunkOpen (
   IN  EMU_IO_THUNK_PROTOCOL  *This
   )
 {
@@ -350,7 +350,7 @@
 }
 
 EFI_STATUS
-SignalClose (
+EmuSignalThunkClose (
   IN  EMU_IO_THUNK_PROTOCOL  *This
   )
 {
@@ -362,7 +362,7 @@
   NULL,
   NULL,
   0,
-  GasketSignalOpen,
-  GasketSignalClose,
+  GasketEmuSignalThunkOpen,
+  GasketEmuSignalThunkClose,
   NULL
 };
diff --git a/EmulatorPkg/Unix/Host/X64/Gasket.S b/EmulatorPkg/Unix/Host/X64/Gasket.S
index e0d23e3..3d0bec7 100644
--- a/EmulatorPkg/Unix/Host/X64/Gasket.S
+++ b/EmulatorPkg/Unix/Host/X64/Gasket.S
@@ -1678,8 +1678,8 @@
   popq    %rbp

   ret

 

-ASM_GLOBAL ASM_PFX(GasketSignalOpen)

-ASM_PFX(GasketSignalOpen):

+ASM_GLOBAL ASM_PFX(GasketEmuSignalThunkOpen)

+ASM_PFX(GasketEmuSignalThunkOpen):

   pushq   %rbp            // stack frame is for the debugger

   movq    %rsp, %rbp

 

@@ -1688,15 +1688,15 @@
 

   movq    %rcx, %rdi    // Swizzle args

 

-  call    ASM_PFX(SignalOpen)

+  call    ASM_PFX(EmuSignalThunkOpen)

 

   popq    %rdi          // restore state

   popq    %rsi

   popq    %rbp

   ret

 

-ASM_GLOBAL ASM_PFX(GasketSignalClose)

-ASM_PFX(GasketSignalClose):

+ASM_GLOBAL ASM_PFX(GasketEmuSignalThunkClose)

+ASM_PFX(GasketEmuSignalThunkClose):

   pushq   %rbp            // stack frame is for the debugger

   movq    %rsp, %rbp

 

@@ -1705,7 +1705,7 @@
 

   movq    %rcx, %rdi    // Swizzle args

 

-  call    ASM_PFX(SignalClose)

+  call    ASM_PFX(EmuSignalThunkClose)

 

   popq    %rdi          // restore state

   popq    %rsi

@@ -1744,3 +1744,5 @@
   popq    %rsi

   popq    %rbp

   ret

+

+//@todo Add gaskets