diff options
author | Nate DeSimone <nathaniel.l.desimone@intel.com> | 2023-07-19 23:02:39 -0700 |
---|---|---|
committer | Nate DeSimone <nathaniel.l.desimone@intel.com> | 2023-07-19 23:02:39 -0700 |
commit | 1c340b760484c38335d3754ee2c33fc485386dd1 (patch) | |
tree | c621195c85f5472e18025293c750fecaf65214ad | |
parent | c1f8a758a7453de1d37d7e5c8a449b17863e1e4b (diff) | |
download | edk2-dev/prmd_poc/nldesimo.zip edk2-dev/prmd_poc/nldesimo.tar.gz edk2-dev/prmd_poc/nldesimo.tar.bz2 |
EmulatorPkg: Add D-BUS Listener Threaddev/prmd_poc/nldesimo
Signed-off-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
-rw-r--r-- | EmulatorPkg/EmulatorPkg.dec | 18 | ||||
-rw-r--r-- | EmulatorPkg/Include/Protocol/EmuDbusPrmdService.h | 121 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Arm/Gasket.c | 100 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Arm/GasketFunctionDefinitions.h | 78 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/DbusPrmdService.c | 1216 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/DbusServer.c | 295 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Gasket.h | 64 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Host.c | 10 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Host.h | 60 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Host.inf | 5 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Ia32/Gasket.S | 14 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/Signal.c | 8 | ||||
-rw-r--r-- | EmulatorPkg/Unix/Host/X64/Gasket.S | 14 |
13 files changed, 1660 insertions, 343 deletions
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,38 +947,116 @@ GasketUnregisterSignalHandler ( return SecUnregisterSignalHandler (SignalNumber); } +UINT32 +EFIAPI +GasketGetIsSigTermSignaled ( + VOID + ) +{ + return GetIsSigTermSignaled (); +} + +VOID +EFIAPI +GasketSetIsSigTermSignaled ( + IN UINT32 value + ) +{ + return SetIsSigTermSignaled (value); +} + EFI_STATUS EFIAPI -GasketSignalOpen ( +GasketEmuSignalThunkOpen ( IN EMU_IO_THUNK_PROTOCOL *This ) { - return SignalOpen (This); + return EmuSignalThunkOpen (This); } EFI_STATUS EFIAPI -GasketSignalClose ( +GasketEmuSignalThunkClose ( IN EMU_IO_THUNK_PROTOCOL *This ) { - return SignalClose (This); + return EmuSignalThunkClose (This); } -UINT32 -EFIAPI -GasketGetIsSigTermSignaled ( +/** + 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 GetIsSigTermSignaled (); + 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 -GasketSetIsSigTermSignaled ( - IN UINT32 value +GasketEmuDbusThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This ) { - return SetIsSigTermSignaled (value); + 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 @@ SecUnregisterSignalHandler ( 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 @@ SetIsSigTermSignaled ( 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 @@ GasketUnregisterSignalHandler ( 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 @@ GasketSetIsSigTermSignaled ( 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 @@ main ( //
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 @@ SecInvokeSignalHandler ( 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 gBlockIoThunkIo; 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 @@ ASM_PFX(GasketUnregisterSignalHandler): 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 @@ ASM_PFX(GasketSignalOpen): 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 @@ ASM_PFX(GasketSignalClose): movl 8(%ebp), %eax
movl %eax, (%esp)
- call ASM_PFX(SignalClose)
+ call ASM_PFX(EmuSignalThunkClose)
leave
ret
@@ -1592,3 +1592,5 @@ ASM_PFX(GasketSetIsSigTermSignaled): 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 @@ EMU_SIGNAL_THUNK_PROTOCOL gEmuSignalThunk = { }; EFI_STATUS -SignalOpen ( +EmuSignalThunkOpen ( IN EMU_IO_THUNK_PROTOCOL *This ) { @@ -350,7 +350,7 @@ SignalOpen ( } EFI_STATUS -SignalClose ( +EmuSignalThunkClose ( IN EMU_IO_THUNK_PROTOCOL *This ) { @@ -362,7 +362,7 @@ EMU_IO_THUNK_PROTOCOL gSignalThunkIo = { 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 @@ ASM_PFX(GasketUnregisterSignalHandler): 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 @@ ASM_PFX(GasketSignalOpen): 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 @@ ASM_PFX(GasketSignalClose): movq %rcx, %rdi // Swizzle args
- call ASM_PFX(SignalClose)
+ call ASM_PFX(EmuSignalThunkClose)
popq %rdi // restore state
popq %rsi
@@ -1744,3 +1744,5 @@ ASM_PFX(GasketSetIsSigTermSignaled): popq %rsi
popq %rbp
ret
+
+//@todo Add gaskets
|