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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user