EmulatorPkg: formalize line endings
The patch is the result of running "BaseTools/Scripts/FormatDosFiles.py EmulatorPkg/" No functionality impact. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com> Cc: Liming Gao <liming.gao@intel.com>
This commit is contained in:
@@ -47,8 +47,8 @@ typedef struct {
|
||||
VOID *CurrentReadPointer;
|
||||
VOID *EndReadPointer;
|
||||
|
||||
UINT32 ReceivedPackets;
|
||||
UINT32 DroppedPackets;
|
||||
UINT32 ReceivedPackets;
|
||||
UINT32 DroppedPackets;
|
||||
|
||||
} EMU_SNP_PRIVATE;
|
||||
|
||||
@@ -200,8 +200,8 @@ EmuSnpStart (
|
||||
struct ifreq BoundIf;
|
||||
struct bpf_program BpfProgram;
|
||||
struct bpf_insn *FilterProgram;
|
||||
u_int Value;
|
||||
u_int ReadBufferSize;
|
||||
u_int Value;
|
||||
u_int ReadBufferSize;
|
||||
UINT16 Temp16;
|
||||
UINT32 Temp32;
|
||||
|
||||
@@ -229,23 +229,23 @@ EmuSnpStart (
|
||||
}
|
||||
|
||||
//
|
||||
// Get the read buffer size.
|
||||
//
|
||||
if (ioctl (Private->BpfFd, BIOCGBLEN, &ReadBufferSize) < 0) {
|
||||
goto DeviceErrorExit;
|
||||
}
|
||||
// Get the read buffer size.
|
||||
//
|
||||
if (ioctl (Private->BpfFd, BIOCGBLEN, &ReadBufferSize) < 0) {
|
||||
goto DeviceErrorExit;
|
||||
}
|
||||
|
||||
//
|
||||
// Default value from BIOCGBLEN is usually too small, so use a much larger size, if necessary.
|
||||
//
|
||||
if (ReadBufferSize < FixedPcdGet32 (PcdNetworkPacketFilterSize)) {
|
||||
ReadBufferSize = FixedPcdGet32 (PcdNetworkPacketFilterSize);
|
||||
if (ioctl (Private->BpfFd, BIOCSBLEN, &ReadBufferSize) < 0) {
|
||||
goto DeviceErrorExit;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Default value from BIOCGBLEN is usually too small, so use a much larger size, if necessary.
|
||||
//
|
||||
if (ReadBufferSize < FixedPcdGet32 (PcdNetworkPacketFilterSize)) {
|
||||
ReadBufferSize = FixedPcdGet32 (PcdNetworkPacketFilterSize);
|
||||
if (ioctl (Private->BpfFd, BIOCSBLEN, &ReadBufferSize) < 0) {
|
||||
goto DeviceErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Associate our interface with this BPF file descriptor.
|
||||
//
|
||||
AsciiStrCpy (BoundIf.ifr_name, Private->InterfaceName);
|
||||
@@ -254,7 +254,7 @@ EmuSnpStart (
|
||||
}
|
||||
|
||||
//
|
||||
// Enable immediate mode.
|
||||
// Enable immediate mode.
|
||||
//
|
||||
Value = 1;
|
||||
if (ioctl (Private->BpfFd, BIOCIMMEDIATE, &Value) < 0) {
|
||||
@@ -286,8 +286,8 @@ EmuSnpStart (
|
||||
//
|
||||
// Allocate read buffer.
|
||||
//
|
||||
Private->ReadBufferSize = ReadBufferSize;
|
||||
Private->ReadBuffer = malloc (Private->ReadBufferSize);
|
||||
Private->ReadBufferSize = ReadBufferSize;
|
||||
Private->ReadBuffer = malloc (Private->ReadBufferSize);
|
||||
if (Private->ReadBuffer == NULL) {
|
||||
goto ErrorExit;
|
||||
}
|
||||
@@ -295,7 +295,7 @@ EmuSnpStart (
|
||||
Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer;
|
||||
|
||||
//
|
||||
// Install our packet filter: successful reads should only produce broadcast or unicast
|
||||
// Install our packet filter: successful reads should only produce broadcast or unicast
|
||||
// packets directed to our fake MAC address.
|
||||
//
|
||||
FilterProgram = malloc (sizeof (mFilterInstructionTemplate)) ;
|
||||
@@ -906,7 +906,7 @@ EmuSnpReceive (
|
||||
{
|
||||
EMU_SNP_PRIVATE *Private;
|
||||
struct bpf_hdr *BpfHeader;
|
||||
struct bpf_stat BpfStats;
|
||||
struct bpf_stat BpfStats;
|
||||
ETHERNET_HEADER *EnetHeader;
|
||||
ssize_t Result;
|
||||
|
||||
@@ -916,19 +916,19 @@ EmuSnpReceive (
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
ZeroMem (&BpfStats, sizeof( BpfStats));
|
||||
ZeroMem (&BpfStats, sizeof( BpfStats));
|
||||
|
||||
if (ioctl (Private->BpfFd, BIOCGSTATS, &BpfStats) == 0) {
|
||||
Private->ReceivedPackets += BpfStats.bs_recv;
|
||||
if (BpfStats.bs_drop > Private->DroppedPackets) {
|
||||
printf (
|
||||
"SNP: STATS: RCVD = %d DROPPED = %d. Probably need to increase BPF PcdNetworkPacketFilterSize?\n",
|
||||
BpfStats.bs_recv,
|
||||
BpfStats.bs_drop - Private->DroppedPackets
|
||||
);
|
||||
Private->DroppedPackets = BpfStats.bs_drop;
|
||||
}
|
||||
}
|
||||
if (ioctl (Private->BpfFd, BIOCGSTATS, &BpfStats) == 0) {
|
||||
Private->ReceivedPackets += BpfStats.bs_recv;
|
||||
if (BpfStats.bs_drop > Private->DroppedPackets) {
|
||||
printf (
|
||||
"SNP: STATS: RCVD = %d DROPPED = %d. Probably need to increase BPF PcdNetworkPacketFilterSize?\n",
|
||||
BpfStats.bs_recv,
|
||||
BpfStats.bs_drop - Private->DroppedPackets
|
||||
);
|
||||
Private->DroppedPackets = BpfStats.bs_drop;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Do we have any remaining packets from the previous read?
|
||||
@@ -1004,7 +1004,7 @@ GetInterfaceMacAddr (
|
||||
EMU_SNP_PRIVATE *Private
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS Status;
|
||||
struct ifaddrs *IfAddrs;
|
||||
struct ifaddrs *If;
|
||||
struct sockaddr_dl *IfSdl;
|
||||
|
@@ -347,7 +347,7 @@ EmuBlockIoReadWriteCommon (
|
||||
@param[in] MediaId Id of the media, changes every time the media is
|
||||
replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data. The
|
||||
caller is responsible for either having implicit or
|
||||
|
@@ -1,440 +1,440 @@
|
||||
/*++ @file
|
||||
Since the SEC is the only program in our emulation we
|
||||
must use a UEFI/PI mechanism to export APIs to other modules.
|
||||
This is the role of the EFI_EMU_THUNK_PROTOCOL.
|
||||
|
||||
The mUnixThunkTable exists so that a change to EFI_EMU_THUNK_PROTOCOL
|
||||
will cause an error in initializing the array if all the member functions
|
||||
are not added. It looks like adding a element to end and not initializing
|
||||
it may cause the table to be initaliized with the members at the end being
|
||||
set to zero. This is bad as jumping to zero will crash.
|
||||
|
||||
Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
|
||||
Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Host.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define DebugAssert _Mangle__DebugAssert
|
||||
|
||||
#include <assert.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
#undef DebugAssert
|
||||
#endif
|
||||
|
||||
int settimer_initialized;
|
||||
struct timeval settimer_timeval;
|
||||
void (*settimer_callback)(UINT64 delta);
|
||||
|
||||
BOOLEAN gEmulatorInterruptEnabled = FALSE;
|
||||
|
||||
|
||||
UINTN
|
||||
SecWriteStdErr (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
ssize_t Return;
|
||||
|
||||
Return = write (STDERR_FILENO, (const void *)Buffer, (size_t)NumberOfBytes);
|
||||
|
||||
return (Return == -1) ? 0 : Return;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
SecConfigStdIn (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
struct termios tty;
|
||||
|
||||
//
|
||||
// Need to turn off line buffering, ECHO, and make it unbuffered.
|
||||
//
|
||||
tcgetattr (STDIN_FILENO, &tty);
|
||||
tty.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr (STDIN_FILENO, TCSANOW, &tty);
|
||||
|
||||
// setvbuf (STDIN_FILENO, NULL, _IONBF, 0);
|
||||
|
||||
// now ioctl FIONREAD will do what we need
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINTN
|
||||
SecWriteStdOut (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
ssize_t Return;
|
||||
|
||||
Return = write (STDOUT_FILENO, (const void *)Buffer, (size_t)NumberOfBytes);
|
||||
|
||||
return (Return == -1) ? 0 : Return;
|
||||
}
|
||||
|
||||
UINTN
|
||||
SecReadStdIn (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
ssize_t Return;
|
||||
|
||||
Return = read (STDIN_FILENO, Buffer, (size_t)NumberOfBytes);
|
||||
|
||||
return (Return == -1) ? 0 : Return;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SecPollStdIn (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
int Result;
|
||||
int Bytes;
|
||||
|
||||
Result = ioctl (STDIN_FILENO, FIONREAD, &Bytes);
|
||||
if (Result == -1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (BOOLEAN)(Bytes > 0);
|
||||
}
|
||||
|
||||
|
||||
VOID *
|
||||
SecMalloc (
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
return malloc ((size_t)Size);
|
||||
}
|
||||
|
||||
VOID *
|
||||
SecValloc (
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
return valloc ((size_t)Size);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SecFree (
|
||||
IN VOID *Ptr
|
||||
)
|
||||
{
|
||||
if (EfiSystemMemoryRange (Ptr)) {
|
||||
// If an address range is in the EFI memory map it was alloced via EFI.
|
||||
// So don't free those ranges and let the caller know.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free (Ptr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
settimer_handler (int sig)
|
||||
{
|
||||
struct timeval timeval;
|
||||
UINT64 delta;
|
||||
|
||||
gettimeofday (&timeval, NULL);
|
||||
delta = ((UINT64)timeval.tv_sec * 1000) + (timeval.tv_usec / 1000)
|
||||
- ((UINT64)settimer_timeval.tv_sec * 1000)
|
||||
- (settimer_timeval.tv_usec / 1000);
|
||||
settimer_timeval = timeval;
|
||||
|
||||
if (settimer_callback) {
|
||||
ReverseGasketUint64 (settimer_callback, delta);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
SecSetTimer (
|
||||
IN UINT64 PeriodMs,
|
||||
IN EMU_SET_TIMER_CALLBACK CallBack
|
||||
)
|
||||
{
|
||||
struct itimerval timerval;
|
||||
UINT32 remainder;
|
||||
|
||||
if (!settimer_initialized) {
|
||||
struct sigaction act;
|
||||
|
||||
settimer_initialized = 1;
|
||||
act.sa_handler = settimer_handler;
|
||||
act.sa_flags = 0;
|
||||
sigemptyset (&act.sa_mask);
|
||||
gEmulatorInterruptEnabled = TRUE;
|
||||
if (sigaction (SIGALRM, &act, NULL) != 0) {
|
||||
printf ("SetTimer: sigaction error %s\n", strerror (errno));
|
||||
}
|
||||
if (gettimeofday (&settimer_timeval, NULL) != 0) {
|
||||
printf ("SetTimer: gettimeofday error %s\n", strerror (errno));
|
||||
}
|
||||
}
|
||||
timerval.it_value.tv_sec = DivU64x32(PeriodMs, 1000);
|
||||
DivU64x32Remainder(PeriodMs, 1000, &remainder);
|
||||
timerval.it_value.tv_usec = remainder * 1000;
|
||||
timerval.it_value.tv_sec = DivU64x32(PeriodMs, 1000);
|
||||
timerval.it_interval = timerval.it_value;
|
||||
|
||||
if (setitimer (ITIMER_REAL, &timerval, NULL) != 0) {
|
||||
printf ("SetTimer: setitimer error %s\n", strerror (errno));
|
||||
}
|
||||
settimer_callback = CallBack;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecEnableInterrupt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
gEmulatorInterruptEnabled = TRUE;
|
||||
// Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
|
||||
// by enabling/disabling SIGALRM.
|
||||
sigemptyset (&sigset);
|
||||
sigaddset (&sigset, SIGALRM);
|
||||
pthread_sigmask (SIG_UNBLOCK, &sigset, NULL);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecDisableInterrupt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
// Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
|
||||
// by enabling/disabling SIGALRM.
|
||||
sigemptyset (&sigset);
|
||||
sigaddset (&sigset, SIGALRM);
|
||||
pthread_sigmask (SIG_BLOCK, &sigset, NULL);
|
||||
gEmulatorInterruptEnabled = FALSE;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
SecInterruptEanbled (void)
|
||||
{
|
||||
return gEmulatorInterruptEnabled;
|
||||
}
|
||||
|
||||
|
||||
UINT64
|
||||
QueryPerformanceFrequency (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Hard code to nanoseconds
|
||||
return 1000000000ULL;
|
||||
}
|
||||
|
||||
UINT64
|
||||
QueryPerformanceCounter (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
#if __APPLE__
|
||||
UINT64 Start;
|
||||
static mach_timebase_info_data_t sTimebaseInfo;
|
||||
|
||||
|
||||
Start = mach_absolute_time ();
|
||||
|
||||
// Convert to nanoseconds.
|
||||
|
||||
// If this is the first time we've run, get the timebase.
|
||||
// We can use denom == 0 to indicate that sTimebaseInfo is
|
||||
// uninitialised because it makes no sense to have a zero
|
||||
// denominator is a fraction.
|
||||
|
||||
if ( sTimebaseInfo.denom == 0 ) {
|
||||
(void) mach_timebase_info(&sTimebaseInfo);
|
||||
}
|
||||
|
||||
// Do the maths. We hope that the multiplication doesn't
|
||||
// overflow; the price you pay for working in fixed point.
|
||||
|
||||
return (Start * sTimebaseInfo.numer) / sTimebaseInfo.denom;
|
||||
#else
|
||||
// Need to figure out what to do for Linux?
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
SecSleep (
|
||||
IN UINT64 Nanoseconds
|
||||
)
|
||||
{
|
||||
struct timespec rq, rm;
|
||||
struct timeval start, end;
|
||||
unsigned long MicroSec;
|
||||
|
||||
rq.tv_sec = DivU64x32 (Nanoseconds, 1000000000);
|
||||
rq.tv_nsec = ModU64x32 (Nanoseconds, 1000000000);
|
||||
|
||||
//
|
||||
// nanosleep gets interrupted by our timer tic.
|
||||
// we need to track wall clock time or we will stall for way too long
|
||||
//
|
||||
gettimeofday (&start, NULL);
|
||||
end.tv_sec = start.tv_sec + rq.tv_sec;
|
||||
MicroSec = (start.tv_usec + rq.tv_nsec/1000);
|
||||
end.tv_usec = MicroSec % 1000000;
|
||||
if (MicroSec > 1000000) {
|
||||
end.tv_sec++;
|
||||
}
|
||||
|
||||
while (nanosleep (&rq, &rm) == -1) {
|
||||
if (errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
gettimeofday (&start, NULL);
|
||||
if (start.tv_sec > end.tv_sec) {
|
||||
break;
|
||||
} if ((start.tv_sec == end.tv_sec) && (start.tv_usec > end.tv_usec)) {
|
||||
break;
|
||||
}
|
||||
rq = rm;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecCpuSleep (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
struct timespec rq, rm;
|
||||
|
||||
// nanosleep gets interrupted by the timer tic
|
||||
rq.tv_sec = 1;
|
||||
rq.tv_nsec = 0;
|
||||
|
||||
nanosleep (&rq, &rm);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecExit (
|
||||
UINTN Status
|
||||
)
|
||||
{
|
||||
exit (Status);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecGetTime (
|
||||
OUT EFI_TIME *Time,
|
||||
OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
|
||||
)
|
||||
{
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
|
||||
t = time (NULL);
|
||||
tm = localtime (&t);
|
||||
|
||||
Time->Year = 1900 + tm->tm_year;
|
||||
Time->Month = tm->tm_mon + 1;
|
||||
Time->Day = tm->tm_mday;
|
||||
Time->Hour = tm->tm_hour;
|
||||
Time->Minute = tm->tm_min;
|
||||
Time->Second = tm->tm_sec;
|
||||
Time->Nanosecond = 0;
|
||||
Time->TimeZone = timezone;
|
||||
Time->Daylight = (daylight ? EFI_TIME_ADJUST_DAYLIGHT : 0)
|
||||
| (tm->tm_isdst > 0 ? EFI_TIME_IN_DAYLIGHT : 0);
|
||||
|
||||
if (Capabilities != NULL) {
|
||||
Capabilities->Resolution = 1;
|
||||
Capabilities->Accuracy = 50000000;
|
||||
Capabilities->SetsToZero = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
SecSetTime (
|
||||
IN EFI_TIME *Time
|
||||
)
|
||||
{
|
||||
// Don't change the time on the system
|
||||
// We could save delta to localtime() and have SecGetTime adjust return values?
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
SecGetNextProtocol (
|
||||
IN BOOLEAN EmuBusDriver,
|
||||
OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL
|
||||
)
|
||||
{
|
||||
return GetNextThunkProtocol (EmuBusDriver, Instance);
|
||||
}
|
||||
|
||||
|
||||
EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
|
||||
GasketSecWriteStdErr,
|
||||
GasketSecConfigStdIn,
|
||||
GasketSecWriteStdOut,
|
||||
GasketSecReadStdIn,
|
||||
GasketSecPollStdIn,
|
||||
GasketSecMalloc,
|
||||
GasketSecValloc,
|
||||
GasketSecFree,
|
||||
GasketSecPeCoffGetEntryPoint,
|
||||
GasketSecPeCoffRelocateImageExtraAction,
|
||||
GasketSecPeCoffUnloadImageExtraAction,
|
||||
GasketSecEnableInterrupt,
|
||||
GasketSecDisableInterrupt,
|
||||
GasketQueryPerformanceFrequency,
|
||||
GasketQueryPerformanceCounter,
|
||||
GasketSecSleep,
|
||||
GasketSecCpuSleep,
|
||||
GasketSecExit,
|
||||
GasketSecGetTime,
|
||||
GasketSecSetTime,
|
||||
GasketSecSetTimer,
|
||||
GasketSecGetNextProtocol
|
||||
};
|
||||
|
||||
|
||||
VOID
|
||||
SecInitThunkProtocol (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// timezone and daylight lib globals depend on tzset be called 1st.
|
||||
tzset ();
|
||||
}
|
||||
|
||||
/*++ @file
|
||||
Since the SEC is the only program in our emulation we
|
||||
must use a UEFI/PI mechanism to export APIs to other modules.
|
||||
This is the role of the EFI_EMU_THUNK_PROTOCOL.
|
||||
|
||||
The mUnixThunkTable exists so that a change to EFI_EMU_THUNK_PROTOCOL
|
||||
will cause an error in initializing the array if all the member functions
|
||||
are not added. It looks like adding a element to end and not initializing
|
||||
it may cause the table to be initaliized with the members at the end being
|
||||
set to zero. This is bad as jumping to zero will crash.
|
||||
|
||||
Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
|
||||
Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Host.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define DebugAssert _Mangle__DebugAssert
|
||||
|
||||
#include <assert.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
#undef DebugAssert
|
||||
#endif
|
||||
|
||||
int settimer_initialized;
|
||||
struct timeval settimer_timeval;
|
||||
void (*settimer_callback)(UINT64 delta);
|
||||
|
||||
BOOLEAN gEmulatorInterruptEnabled = FALSE;
|
||||
|
||||
|
||||
UINTN
|
||||
SecWriteStdErr (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
ssize_t Return;
|
||||
|
||||
Return = write (STDERR_FILENO, (const void *)Buffer, (size_t)NumberOfBytes);
|
||||
|
||||
return (Return == -1) ? 0 : Return;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
SecConfigStdIn (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
struct termios tty;
|
||||
|
||||
//
|
||||
// Need to turn off line buffering, ECHO, and make it unbuffered.
|
||||
//
|
||||
tcgetattr (STDIN_FILENO, &tty);
|
||||
tty.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr (STDIN_FILENO, TCSANOW, &tty);
|
||||
|
||||
// setvbuf (STDIN_FILENO, NULL, _IONBF, 0);
|
||||
|
||||
// now ioctl FIONREAD will do what we need
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINTN
|
||||
SecWriteStdOut (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
ssize_t Return;
|
||||
|
||||
Return = write (STDOUT_FILENO, (const void *)Buffer, (size_t)NumberOfBytes);
|
||||
|
||||
return (Return == -1) ? 0 : Return;
|
||||
}
|
||||
|
||||
UINTN
|
||||
SecReadStdIn (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
ssize_t Return;
|
||||
|
||||
Return = read (STDIN_FILENO, Buffer, (size_t)NumberOfBytes);
|
||||
|
||||
return (Return == -1) ? 0 : Return;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SecPollStdIn (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
int Result;
|
||||
int Bytes;
|
||||
|
||||
Result = ioctl (STDIN_FILENO, FIONREAD, &Bytes);
|
||||
if (Result == -1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (BOOLEAN)(Bytes > 0);
|
||||
}
|
||||
|
||||
|
||||
VOID *
|
||||
SecMalloc (
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
return malloc ((size_t)Size);
|
||||
}
|
||||
|
||||
VOID *
|
||||
SecValloc (
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
return valloc ((size_t)Size);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SecFree (
|
||||
IN VOID *Ptr
|
||||
)
|
||||
{
|
||||
if (EfiSystemMemoryRange (Ptr)) {
|
||||
// If an address range is in the EFI memory map it was alloced via EFI.
|
||||
// So don't free those ranges and let the caller know.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free (Ptr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
settimer_handler (int sig)
|
||||
{
|
||||
struct timeval timeval;
|
||||
UINT64 delta;
|
||||
|
||||
gettimeofday (&timeval, NULL);
|
||||
delta = ((UINT64)timeval.tv_sec * 1000) + (timeval.tv_usec / 1000)
|
||||
- ((UINT64)settimer_timeval.tv_sec * 1000)
|
||||
- (settimer_timeval.tv_usec / 1000);
|
||||
settimer_timeval = timeval;
|
||||
|
||||
if (settimer_callback) {
|
||||
ReverseGasketUint64 (settimer_callback, delta);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
SecSetTimer (
|
||||
IN UINT64 PeriodMs,
|
||||
IN EMU_SET_TIMER_CALLBACK CallBack
|
||||
)
|
||||
{
|
||||
struct itimerval timerval;
|
||||
UINT32 remainder;
|
||||
|
||||
if (!settimer_initialized) {
|
||||
struct sigaction act;
|
||||
|
||||
settimer_initialized = 1;
|
||||
act.sa_handler = settimer_handler;
|
||||
act.sa_flags = 0;
|
||||
sigemptyset (&act.sa_mask);
|
||||
gEmulatorInterruptEnabled = TRUE;
|
||||
if (sigaction (SIGALRM, &act, NULL) != 0) {
|
||||
printf ("SetTimer: sigaction error %s\n", strerror (errno));
|
||||
}
|
||||
if (gettimeofday (&settimer_timeval, NULL) != 0) {
|
||||
printf ("SetTimer: gettimeofday error %s\n", strerror (errno));
|
||||
}
|
||||
}
|
||||
timerval.it_value.tv_sec = DivU64x32(PeriodMs, 1000);
|
||||
DivU64x32Remainder(PeriodMs, 1000, &remainder);
|
||||
timerval.it_value.tv_usec = remainder * 1000;
|
||||
timerval.it_value.tv_sec = DivU64x32(PeriodMs, 1000);
|
||||
timerval.it_interval = timerval.it_value;
|
||||
|
||||
if (setitimer (ITIMER_REAL, &timerval, NULL) != 0) {
|
||||
printf ("SetTimer: setitimer error %s\n", strerror (errno));
|
||||
}
|
||||
settimer_callback = CallBack;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecEnableInterrupt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
gEmulatorInterruptEnabled = TRUE;
|
||||
// Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
|
||||
// by enabling/disabling SIGALRM.
|
||||
sigemptyset (&sigset);
|
||||
sigaddset (&sigset, SIGALRM);
|
||||
pthread_sigmask (SIG_UNBLOCK, &sigset, NULL);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecDisableInterrupt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
// Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
|
||||
// by enabling/disabling SIGALRM.
|
||||
sigemptyset (&sigset);
|
||||
sigaddset (&sigset, SIGALRM);
|
||||
pthread_sigmask (SIG_BLOCK, &sigset, NULL);
|
||||
gEmulatorInterruptEnabled = FALSE;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
SecInterruptEanbled (void)
|
||||
{
|
||||
return gEmulatorInterruptEnabled;
|
||||
}
|
||||
|
||||
|
||||
UINT64
|
||||
QueryPerformanceFrequency (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Hard code to nanoseconds
|
||||
return 1000000000ULL;
|
||||
}
|
||||
|
||||
UINT64
|
||||
QueryPerformanceCounter (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
#if __APPLE__
|
||||
UINT64 Start;
|
||||
static mach_timebase_info_data_t sTimebaseInfo;
|
||||
|
||||
|
||||
Start = mach_absolute_time ();
|
||||
|
||||
// Convert to nanoseconds.
|
||||
|
||||
// If this is the first time we've run, get the timebase.
|
||||
// We can use denom == 0 to indicate that sTimebaseInfo is
|
||||
// uninitialised because it makes no sense to have a zero
|
||||
// denominator is a fraction.
|
||||
|
||||
if ( sTimebaseInfo.denom == 0 ) {
|
||||
(void) mach_timebase_info(&sTimebaseInfo);
|
||||
}
|
||||
|
||||
// Do the maths. We hope that the multiplication doesn't
|
||||
// overflow; the price you pay for working in fixed point.
|
||||
|
||||
return (Start * sTimebaseInfo.numer) / sTimebaseInfo.denom;
|
||||
#else
|
||||
// Need to figure out what to do for Linux?
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
SecSleep (
|
||||
IN UINT64 Nanoseconds
|
||||
)
|
||||
{
|
||||
struct timespec rq, rm;
|
||||
struct timeval start, end;
|
||||
unsigned long MicroSec;
|
||||
|
||||
rq.tv_sec = DivU64x32 (Nanoseconds, 1000000000);
|
||||
rq.tv_nsec = ModU64x32 (Nanoseconds, 1000000000);
|
||||
|
||||
//
|
||||
// nanosleep gets interrupted by our timer tic.
|
||||
// we need to track wall clock time or we will stall for way too long
|
||||
//
|
||||
gettimeofday (&start, NULL);
|
||||
end.tv_sec = start.tv_sec + rq.tv_sec;
|
||||
MicroSec = (start.tv_usec + rq.tv_nsec/1000);
|
||||
end.tv_usec = MicroSec % 1000000;
|
||||
if (MicroSec > 1000000) {
|
||||
end.tv_sec++;
|
||||
}
|
||||
|
||||
while (nanosleep (&rq, &rm) == -1) {
|
||||
if (errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
gettimeofday (&start, NULL);
|
||||
if (start.tv_sec > end.tv_sec) {
|
||||
break;
|
||||
} if ((start.tv_sec == end.tv_sec) && (start.tv_usec > end.tv_usec)) {
|
||||
break;
|
||||
}
|
||||
rq = rm;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecCpuSleep (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
struct timespec rq, rm;
|
||||
|
||||
// nanosleep gets interrupted by the timer tic
|
||||
rq.tv_sec = 1;
|
||||
rq.tv_nsec = 0;
|
||||
|
||||
nanosleep (&rq, &rm);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecExit (
|
||||
UINTN Status
|
||||
)
|
||||
{
|
||||
exit (Status);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
SecGetTime (
|
||||
OUT EFI_TIME *Time,
|
||||
OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
|
||||
)
|
||||
{
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
|
||||
t = time (NULL);
|
||||
tm = localtime (&t);
|
||||
|
||||
Time->Year = 1900 + tm->tm_year;
|
||||
Time->Month = tm->tm_mon + 1;
|
||||
Time->Day = tm->tm_mday;
|
||||
Time->Hour = tm->tm_hour;
|
||||
Time->Minute = tm->tm_min;
|
||||
Time->Second = tm->tm_sec;
|
||||
Time->Nanosecond = 0;
|
||||
Time->TimeZone = timezone;
|
||||
Time->Daylight = (daylight ? EFI_TIME_ADJUST_DAYLIGHT : 0)
|
||||
| (tm->tm_isdst > 0 ? EFI_TIME_IN_DAYLIGHT : 0);
|
||||
|
||||
if (Capabilities != NULL) {
|
||||
Capabilities->Resolution = 1;
|
||||
Capabilities->Accuracy = 50000000;
|
||||
Capabilities->SetsToZero = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
SecSetTime (
|
||||
IN EFI_TIME *Time
|
||||
)
|
||||
{
|
||||
// Don't change the time on the system
|
||||
// We could save delta to localtime() and have SecGetTime adjust return values?
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
SecGetNextProtocol (
|
||||
IN BOOLEAN EmuBusDriver,
|
||||
OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL
|
||||
)
|
||||
{
|
||||
return GetNextThunkProtocol (EmuBusDriver, Instance);
|
||||
}
|
||||
|
||||
|
||||
EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
|
||||
GasketSecWriteStdErr,
|
||||
GasketSecConfigStdIn,
|
||||
GasketSecWriteStdOut,
|
||||
GasketSecReadStdIn,
|
||||
GasketSecPollStdIn,
|
||||
GasketSecMalloc,
|
||||
GasketSecValloc,
|
||||
GasketSecFree,
|
||||
GasketSecPeCoffGetEntryPoint,
|
||||
GasketSecPeCoffRelocateImageExtraAction,
|
||||
GasketSecPeCoffUnloadImageExtraAction,
|
||||
GasketSecEnableInterrupt,
|
||||
GasketSecDisableInterrupt,
|
||||
GasketQueryPerformanceFrequency,
|
||||
GasketQueryPerformanceCounter,
|
||||
GasketSecSleep,
|
||||
GasketSecCpuSleep,
|
||||
GasketSecExit,
|
||||
GasketSecGetTime,
|
||||
GasketSecSetTime,
|
||||
GasketSecSetTimer,
|
||||
GasketSecGetNextProtocol
|
||||
};
|
||||
|
||||
|
||||
VOID
|
||||
SecInitThunkProtocol (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// timezone and daylight lib globals depend on tzset be called 1st.
|
||||
tzset ();
|
||||
}
|
||||
|
||||
|
@@ -1148,7 +1148,7 @@ GdbScriptAddImage (
|
||||
|
||||
if (ImageContext->PdbPointer != NULL && !IsPdbFile (ImageContext->PdbPointer)) {
|
||||
FILE *GdbTempFile;
|
||||
if (FeaturePcdGet (PcdEmulatorLazyLoadSymbols)) {
|
||||
if (FeaturePcdGet (PcdEmulatorLazyLoadSymbols)) {
|
||||
GdbTempFile = fopen (gGdbWorkingFileName, "a");
|
||||
if (GdbTempFile != NULL) {
|
||||
long unsigned int SymbolsAddr = (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders);
|
||||
@@ -1170,13 +1170,13 @@ GdbScriptAddImage (
|
||||
GdbTempFile = fopen (gGdbWorkingFileName, "w");
|
||||
if (GdbTempFile != NULL) {
|
||||
fprintf (
|
||||
GdbTempFile,
|
||||
"add-symbol-file %s 0x%08lx\n",
|
||||
ImageContext->PdbPointer,
|
||||
GdbTempFile,
|
||||
"add-symbol-file %s 0x%08lx\n",
|
||||
ImageContext->PdbPointer,
|
||||
(long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)
|
||||
);
|
||||
fclose (GdbTempFile);
|
||||
|
||||
|
||||
//
|
||||
// Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
|
||||
// Hey what can you say scripting in gdb is not that great....
|
||||
@@ -1225,7 +1225,7 @@ GdbScriptRemoveImage (
|
||||
return;
|
||||
}
|
||||
|
||||
if (FeaturePcdGet (PcdEmulatorLazyLoadSymbols)) {
|
||||
if (FeaturePcdGet (PcdEmulatorLazyLoadSymbols)) {
|
||||
//
|
||||
// Write the file we need for the gdb script
|
||||
//
|
||||
@@ -1256,7 +1256,7 @@ GdbScriptRemoveImage (
|
||||
SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, 0, 0);
|
||||
} else {
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -82,7 +82,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#undef NTOHS
|
||||
#undef HTONS
|
||||
#undef B0
|
||||
#undef CR3
|
||||
#undef CR3
|
||||
|
||||
#include <PiPei.h>
|
||||
#include <Uefi.h>
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,74 +1,74 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "Host.h"
|
||||
|
||||
|
||||
/**
|
||||
Transfers control to a function starting with a new stack.
|
||||
|
||||
Transfers control to the function specified by EntryPoint using the new stack
|
||||
specified by NewStack and passing in the parameters specified by Context1 and
|
||||
Context2. Context1 and Context2 are optional and may be NULL. The function
|
||||
EntryPoint must never return.
|
||||
|
||||
If EntryPoint is NULL, then ASSERT().
|
||||
If NewStack is NULL, then ASSERT().
|
||||
|
||||
@param EntryPoint A pointer to function to call with the new stack.
|
||||
@param Context1 A pointer to the context to pass into the EntryPoint
|
||||
function.
|
||||
@param Context2 A pointer to the context to pass into the EntryPoint
|
||||
function.
|
||||
@param NewStack A pointer to the new stack to use for the EntryPoint
|
||||
function.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
PeiSwitchStacks (
|
||||
IN SWITCH_STACK_ENTRY_POINT EntryPoint,
|
||||
IN VOID *Context1, OPTIONAL
|
||||
IN VOID *Context2, OPTIONAL
|
||||
IN VOID *NewStack
|
||||
)
|
||||
{
|
||||
BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
|
||||
|
||||
ASSERT (EntryPoint != NULL);
|
||||
ASSERT (NewStack != NULL);
|
||||
|
||||
//
|
||||
// Stack should be aligned with CPU_STACK_ALIGNMENT
|
||||
//
|
||||
ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0);
|
||||
|
||||
JumpBuffer.Eip = (UINTN)EntryPoint;
|
||||
JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*);
|
||||
JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2);
|
||||
((VOID**)JumpBuffer.Esp)[1] = Context1;
|
||||
((VOID**)JumpBuffer.Esp)[2] = Context2;
|
||||
|
||||
LongJump (&JumpBuffer, (UINTN)-1);
|
||||
|
||||
|
||||
//
|
||||
// PeiSwitchStacks () will never return
|
||||
//
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "Host.h"
|
||||
|
||||
|
||||
/**
|
||||
Transfers control to a function starting with a new stack.
|
||||
|
||||
Transfers control to the function specified by EntryPoint using the new stack
|
||||
specified by NewStack and passing in the parameters specified by Context1 and
|
||||
Context2. Context1 and Context2 are optional and may be NULL. The function
|
||||
EntryPoint must never return.
|
||||
|
||||
If EntryPoint is NULL, then ASSERT().
|
||||
If NewStack is NULL, then ASSERT().
|
||||
|
||||
@param EntryPoint A pointer to function to call with the new stack.
|
||||
@param Context1 A pointer to the context to pass into the EntryPoint
|
||||
function.
|
||||
@param Context2 A pointer to the context to pass into the EntryPoint
|
||||
function.
|
||||
@param NewStack A pointer to the new stack to use for the EntryPoint
|
||||
function.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
PeiSwitchStacks (
|
||||
IN SWITCH_STACK_ENTRY_POINT EntryPoint,
|
||||
IN VOID *Context1, OPTIONAL
|
||||
IN VOID *Context2, OPTIONAL
|
||||
IN VOID *NewStack
|
||||
)
|
||||
{
|
||||
BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
|
||||
|
||||
ASSERT (EntryPoint != NULL);
|
||||
ASSERT (NewStack != NULL);
|
||||
|
||||
//
|
||||
// Stack should be aligned with CPU_STACK_ALIGNMENT
|
||||
//
|
||||
ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0);
|
||||
|
||||
JumpBuffer.Eip = (UINTN)EntryPoint;
|
||||
JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*);
|
||||
JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2);
|
||||
((VOID**)JumpBuffer.Esp)[1] = Context1;
|
||||
((VOID**)JumpBuffer.Esp)[2] = Context2;
|
||||
|
||||
LongJump (&JumpBuffer, (UINTN)-1);
|
||||
|
||||
|
||||
//
|
||||
// PeiSwitchStacks () will never return
|
||||
//
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -1,145 +1,145 @@
|
||||
/*++ @file
|
||||
|
||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Base.h"
|
||||
#include "Library/BaseMemoryLib.h"
|
||||
#include "Library/MemoryAllocationLib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
Allocates a buffer of type EfiBootServicesData.
|
||||
|
||||
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
|
||||
pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
|
||||
returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
|
||||
|
||||
@param AllocationSize The number of bytes to allocate.
|
||||
|
||||
@return A pointer to the allocated buffer or NULL if allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
AllocatePool (
|
||||
IN UINTN AllocationSize
|
||||
)
|
||||
{
|
||||
return (VOID*) malloc (AllocationSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocates and zeros a buffer of type EfiBootServicesData.
|
||||
|
||||
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
|
||||
buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
|
||||
valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
|
||||
request, then NULL is returned.
|
||||
|
||||
@param AllocationSize The number of bytes to allocate and zero.
|
||||
|
||||
@return A pointer to the allocated buffer or NULL if allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
AllocateZeroPool (
|
||||
IN UINTN AllocationSize
|
||||
)
|
||||
{
|
||||
VOID *Buffer;
|
||||
|
||||
Buffer = AllocatePool (AllocationSize);
|
||||
if (Buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem (Buffer, AllocationSize);
|
||||
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reallocates a buffer of type EfiBootServicesData.
|
||||
|
||||
Allocates and zeros the number bytes specified by NewSize from memory of type
|
||||
EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
|
||||
NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
|
||||
OldBuffer is freed. A pointer to the newly allocated buffer is returned.
|
||||
If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
|
||||
enough memory remaining to satisfy the request, then NULL is returned.
|
||||
|
||||
If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
|
||||
is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
|
||||
|
||||
@param OldSize The size, in bytes, of OldBuffer.
|
||||
@param NewSize The size, in bytes, of the buffer to reallocate.
|
||||
@param OldBuffer The buffer to copy to the allocated buffer. This is an optional
|
||||
parameter that may be NULL.
|
||||
|
||||
@return A pointer to the allocated buffer or NULL if allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
ReallocatePool (
|
||||
IN UINTN OldSize,
|
||||
IN UINTN NewSize,
|
||||
IN VOID *OldBuffer OPTIONAL
|
||||
)
|
||||
{
|
||||
VOID *NewBuffer;
|
||||
|
||||
NewBuffer = AllocatePool (NewSize);
|
||||
if (NewBuffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (OldBuffer != NULL) {
|
||||
if (OldSize > 0) {
|
||||
CopyMem (NewBuffer, OldBuffer, OldSize);
|
||||
}
|
||||
|
||||
FreePool (OldBuffer);
|
||||
}
|
||||
|
||||
return NewBuffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Frees a buffer that was previously allocated with one of the pool allocation functions in the
|
||||
Memory Allocation Library.
|
||||
|
||||
Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
|
||||
pool allocation services of the Memory Allocation Library. If it is not possible to free pool
|
||||
resources, then this function will perform no actions.
|
||||
|
||||
If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
|
||||
then ASSERT().
|
||||
|
||||
@param Buffer Pointer to the buffer to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
FreePool (
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
free ((void *) Buffer);
|
||||
}
|
||||
|
||||
/*++ @file
|
||||
|
||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Base.h"
|
||||
#include "Library/BaseMemoryLib.h"
|
||||
#include "Library/MemoryAllocationLib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
Allocates a buffer of type EfiBootServicesData.
|
||||
|
||||
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
|
||||
pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
|
||||
returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
|
||||
|
||||
@param AllocationSize The number of bytes to allocate.
|
||||
|
||||
@return A pointer to the allocated buffer or NULL if allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
AllocatePool (
|
||||
IN UINTN AllocationSize
|
||||
)
|
||||
{
|
||||
return (VOID*) malloc (AllocationSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allocates and zeros a buffer of type EfiBootServicesData.
|
||||
|
||||
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
|
||||
buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
|
||||
valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
|
||||
request, then NULL is returned.
|
||||
|
||||
@param AllocationSize The number of bytes to allocate and zero.
|
||||
|
||||
@return A pointer to the allocated buffer or NULL if allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
AllocateZeroPool (
|
||||
IN UINTN AllocationSize
|
||||
)
|
||||
{
|
||||
VOID *Buffer;
|
||||
|
||||
Buffer = AllocatePool (AllocationSize);
|
||||
if (Buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem (Buffer, AllocationSize);
|
||||
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reallocates a buffer of type EfiBootServicesData.
|
||||
|
||||
Allocates and zeros the number bytes specified by NewSize from memory of type
|
||||
EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
|
||||
NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
|
||||
OldBuffer is freed. A pointer to the newly allocated buffer is returned.
|
||||
If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
|
||||
enough memory remaining to satisfy the request, then NULL is returned.
|
||||
|
||||
If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
|
||||
is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
|
||||
|
||||
@param OldSize The size, in bytes, of OldBuffer.
|
||||
@param NewSize The size, in bytes, of the buffer to reallocate.
|
||||
@param OldBuffer The buffer to copy to the allocated buffer. This is an optional
|
||||
parameter that may be NULL.
|
||||
|
||||
@return A pointer to the allocated buffer or NULL if allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
ReallocatePool (
|
||||
IN UINTN OldSize,
|
||||
IN UINTN NewSize,
|
||||
IN VOID *OldBuffer OPTIONAL
|
||||
)
|
||||
{
|
||||
VOID *NewBuffer;
|
||||
|
||||
NewBuffer = AllocatePool (NewSize);
|
||||
if (NewBuffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (OldBuffer != NULL) {
|
||||
if (OldSize > 0) {
|
||||
CopyMem (NewBuffer, OldBuffer, OldSize);
|
||||
}
|
||||
|
||||
FreePool (OldBuffer);
|
||||
}
|
||||
|
||||
return NewBuffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Frees a buffer that was previously allocated with one of the pool allocation functions in the
|
||||
Memory Allocation Library.
|
||||
|
||||
Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
|
||||
pool allocation services of the Memory Allocation Library. If it is not possible to free pool
|
||||
resources, then this function will perform no actions.
|
||||
|
||||
If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
|
||||
then ASSERT().
|
||||
|
||||
@param Buffer Pointer to the buffer to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
FreePool (
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
free ((void *) Buffer);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,235 +1,235 @@
|
||||
/*++ @file
|
||||
POSIX Pthreads to emulate APs and implement threads
|
||||
|
||||
Copyright (c) 2011, Apple Inc. All rights reserved.
|
||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Host.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
PthreadMutexLock (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
return (UINTN)pthread_mutex_lock ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
PthreadMutexUnLock (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
return (UINTN)pthread_mutex_unlock ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
PthreadMutexTryLock (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
return (UINTN)pthread_mutex_trylock ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
|
||||
VOID *
|
||||
PthreadMutexInit (
|
||||
IN VOID
|
||||
)
|
||||
{
|
||||
pthread_mutex_t *Mutex;
|
||||
int err;
|
||||
|
||||
Mutex = malloc (sizeof (pthread_mutex_t));
|
||||
err = pthread_mutex_init (Mutex, NULL);
|
||||
if (err == 0) {
|
||||
return Mutex;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
UINTN
|
||||
PthreadMutexDestroy (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
if (Mutex != NULL) {
|
||||
return pthread_mutex_destroy ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Can't store this data on PthreadCreate stack so we need a global
|
||||
typedef struct {
|
||||
pthread_mutex_t Mutex;
|
||||
THREAD_THUNK_THREAD_ENTRY Start;
|
||||
} THREAD_MANGLE;
|
||||
|
||||
THREAD_MANGLE mThreadMangle = {
|
||||
PTHREAD_MUTEX_INITIALIZER,
|
||||
NULL
|
||||
};
|
||||
|
||||
VOID *
|
||||
SecFakePthreadStart (
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
THREAD_THUNK_THREAD_ENTRY Start;
|
||||
sigset_t SigMask;
|
||||
|
||||
// Save global on the stack before we unlock
|
||||
Start = mThreadMangle.Start;
|
||||
pthread_mutex_unlock (&mThreadMangle.Mutex);
|
||||
|
||||
// Mask all signals to the APs
|
||||
sigfillset (&SigMask);
|
||||
pthread_sigmask (SIG_BLOCK, &SigMask, NULL);
|
||||
|
||||
//
|
||||
// We have to start the thread in SEC as we need to follow
|
||||
// OS X calling conventions. We can then call back into
|
||||
// to the callers Start.
|
||||
//
|
||||
// This is a great example of how all problems in computer
|
||||
// science can be solved by adding another level of indirection
|
||||
//
|
||||
return (VOID *)ReverseGasketUint64 ((CALL_BACK)Start, (UINTN)Context);
|
||||
}
|
||||
|
||||
UINTN
|
||||
PthreadCreate (
|
||||
IN VOID *Thread,
|
||||
IN VOID *Attribute,
|
||||
IN THREAD_THUNK_THREAD_ENTRY Start,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
int err;
|
||||
BOOLEAN EnabledOnEntry;
|
||||
|
||||
//
|
||||
// Threads inherit interrupt state so disable interrupts before we start thread
|
||||
//
|
||||
if (SecInterruptEanbled ()) {
|
||||
SecDisableInterrupt ();
|
||||
EnabledOnEntry = TRUE;
|
||||
} else {
|
||||
EnabledOnEntry = FALSE;
|
||||
}
|
||||
|
||||
// Aquire lock for global, SecFakePthreadStart runs in a different thread.
|
||||
pthread_mutex_lock (&mThreadMangle.Mutex);
|
||||
mThreadMangle.Start = Start;
|
||||
|
||||
err = pthread_create (Thread, Attribute, SecFakePthreadStart, Context);
|
||||
if (err != 0) {
|
||||
// Thread failed to launch so release the lock;
|
||||
pthread_mutex_unlock (&mThreadMangle.Mutex);
|
||||
}
|
||||
|
||||
if (EnabledOnEntry) {
|
||||
// Restore interrupt state
|
||||
SecEnableInterrupt ();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
PthreadExit (
|
||||
IN VOID *ValuePtr
|
||||
)
|
||||
{
|
||||
pthread_exit (ValuePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
UINTN
|
||||
PthreadSelf (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// POSIX currently allows pthread_t to be a structure or arithmetic type.
|
||||
// Check out sys/types.h to make sure this will work if you are porting.
|
||||
// On OS X (Darwin) pthread_t is a pointer to a structure so this code works.
|
||||
return (UINTN)pthread_self ();
|
||||
}
|
||||
|
||||
|
||||
EMU_THREAD_THUNK_PROTOCOL gPthreadThunk = {
|
||||
GasketPthreadMutexLock,
|
||||
GasketPthreadMutexUnLock,
|
||||
GasketPthreadMutexTryLock,
|
||||
GasketPthreadMutexInit,
|
||||
GasketPthreadMutexDestroy,
|
||||
GasketPthreadCreate,
|
||||
GasketPthreadExit,
|
||||
GasketPthreadSelf
|
||||
};
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
PthreadOpen (
|
||||
IN EMU_IO_THUNK_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
if (This->Instance != 0) {
|
||||
// Only single instance is supported
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (This->ConfigString[0] == L'0') {
|
||||
// If AP count is zero no need for threads
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
This->Interface = &gPthreadThunk;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
PthreadClose (
|
||||
IN EMU_IO_THUNK_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EMU_IO_THUNK_PROTOCOL gPthreadThunkIo = {
|
||||
&gEmuThreadThunkProtocolGuid,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
GasketPthreadOpen,
|
||||
GasketPthreadClose,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/*++ @file
|
||||
POSIX Pthreads to emulate APs and implement threads
|
||||
|
||||
Copyright (c) 2011, Apple Inc. All rights reserved.
|
||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Host.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
PthreadMutexLock (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
return (UINTN)pthread_mutex_lock ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
PthreadMutexUnLock (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
return (UINTN)pthread_mutex_unlock ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
PthreadMutexTryLock (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
return (UINTN)pthread_mutex_trylock ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
|
||||
VOID *
|
||||
PthreadMutexInit (
|
||||
IN VOID
|
||||
)
|
||||
{
|
||||
pthread_mutex_t *Mutex;
|
||||
int err;
|
||||
|
||||
Mutex = malloc (sizeof (pthread_mutex_t));
|
||||
err = pthread_mutex_init (Mutex, NULL);
|
||||
if (err == 0) {
|
||||
return Mutex;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
UINTN
|
||||
PthreadMutexDestroy (
|
||||
IN VOID *Mutex
|
||||
)
|
||||
{
|
||||
if (Mutex != NULL) {
|
||||
return pthread_mutex_destroy ((pthread_mutex_t *)Mutex);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Can't store this data on PthreadCreate stack so we need a global
|
||||
typedef struct {
|
||||
pthread_mutex_t Mutex;
|
||||
THREAD_THUNK_THREAD_ENTRY Start;
|
||||
} THREAD_MANGLE;
|
||||
|
||||
THREAD_MANGLE mThreadMangle = {
|
||||
PTHREAD_MUTEX_INITIALIZER,
|
||||
NULL
|
||||
};
|
||||
|
||||
VOID *
|
||||
SecFakePthreadStart (
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
THREAD_THUNK_THREAD_ENTRY Start;
|
||||
sigset_t SigMask;
|
||||
|
||||
// Save global on the stack before we unlock
|
||||
Start = mThreadMangle.Start;
|
||||
pthread_mutex_unlock (&mThreadMangle.Mutex);
|
||||
|
||||
// Mask all signals to the APs
|
||||
sigfillset (&SigMask);
|
||||
pthread_sigmask (SIG_BLOCK, &SigMask, NULL);
|
||||
|
||||
//
|
||||
// We have to start the thread in SEC as we need to follow
|
||||
// OS X calling conventions. We can then call back into
|
||||
// to the callers Start.
|
||||
//
|
||||
// This is a great example of how all problems in computer
|
||||
// science can be solved by adding another level of indirection
|
||||
//
|
||||
return (VOID *)ReverseGasketUint64 ((CALL_BACK)Start, (UINTN)Context);
|
||||
}
|
||||
|
||||
UINTN
|
||||
PthreadCreate (
|
||||
IN VOID *Thread,
|
||||
IN VOID *Attribute,
|
||||
IN THREAD_THUNK_THREAD_ENTRY Start,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
int err;
|
||||
BOOLEAN EnabledOnEntry;
|
||||
|
||||
//
|
||||
// Threads inherit interrupt state so disable interrupts before we start thread
|
||||
//
|
||||
if (SecInterruptEanbled ()) {
|
||||
SecDisableInterrupt ();
|
||||
EnabledOnEntry = TRUE;
|
||||
} else {
|
||||
EnabledOnEntry = FALSE;
|
||||
}
|
||||
|
||||
// Aquire lock for global, SecFakePthreadStart runs in a different thread.
|
||||
pthread_mutex_lock (&mThreadMangle.Mutex);
|
||||
mThreadMangle.Start = Start;
|
||||
|
||||
err = pthread_create (Thread, Attribute, SecFakePthreadStart, Context);
|
||||
if (err != 0) {
|
||||
// Thread failed to launch so release the lock;
|
||||
pthread_mutex_unlock (&mThreadMangle.Mutex);
|
||||
}
|
||||
|
||||
if (EnabledOnEntry) {
|
||||
// Restore interrupt state
|
||||
SecEnableInterrupt ();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
PthreadExit (
|
||||
IN VOID *ValuePtr
|
||||
)
|
||||
{
|
||||
pthread_exit (ValuePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
UINTN
|
||||
PthreadSelf (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// POSIX currently allows pthread_t to be a structure or arithmetic type.
|
||||
// Check out sys/types.h to make sure this will work if you are porting.
|
||||
// On OS X (Darwin) pthread_t is a pointer to a structure so this code works.
|
||||
return (UINTN)pthread_self ();
|
||||
}
|
||||
|
||||
|
||||
EMU_THREAD_THUNK_PROTOCOL gPthreadThunk = {
|
||||
GasketPthreadMutexLock,
|
||||
GasketPthreadMutexUnLock,
|
||||
GasketPthreadMutexTryLock,
|
||||
GasketPthreadMutexInit,
|
||||
GasketPthreadMutexDestroy,
|
||||
GasketPthreadCreate,
|
||||
GasketPthreadExit,
|
||||
GasketPthreadSelf
|
||||
};
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
PthreadOpen (
|
||||
IN EMU_IO_THUNK_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
if (This->Instance != 0) {
|
||||
// Only single instance is supported
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (This->ConfigString[0] == L'0') {
|
||||
// If AP count is zero no need for threads
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
This->Interface = &gPthreadThunk;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
PthreadClose (
|
||||
IN EMU_IO_THUNK_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EMU_IO_THUNK_PROTOCOL gPthreadThunkIo = {
|
||||
&gEmuThreadThunkProtocolGuid,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
GasketPthreadOpen,
|
||||
GasketPthreadClose,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user