REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the EmulatorPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			426 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			426 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++ @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 initialized with the members at the end being
 | |
|   set to zero. This is bad as jumping to zero will crash.
 | |
| 
 | |
| Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
| Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #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;
 | |
| UINTN           settimer_callback = 0;
 | |
| 
 | |
| 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 = (UINTN)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 / 60;
 | |
|   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 ();
 | |
| }
 |