Implement the clock() function using the EFI time-of-day clock instead of a TimerLib instance. Signed-off-by: darylm503 Reviewed-by: jljusten Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12683 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			766 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			766 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**
 | 
						|
  Definitions and Implementation for <time.h>.
 | 
						|
 | 
						|
  Copyright (c) 2010 - 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 that 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.
 | 
						|
 | 
						|
  Portions derived from the NIH time zone package file, localtime.c,
 | 
						|
  which contains the following notice:
 | 
						|
 | 
						|
    This file is in the public domain, so clarified as of
 | 
						|
    1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
 | 
						|
 | 
						|
  NetBSD: localtime.c,v 1.39 2006/03/22 14:01:30 christos Exp
 | 
						|
**/
 | 
						|
#include  <Uefi.h>
 | 
						|
#include  <Library/UefiLib.h>
 | 
						|
#include  <Library/TimerLib.h>
 | 
						|
#include  <Library/BaseLib.h>
 | 
						|
#include  <Library/UefiRuntimeServicesTableLib.h>
 | 
						|
//#include  <Library/UefiRuntimeLib.h>
 | 
						|
 | 
						|
#include  <LibConfig.h>
 | 
						|
 | 
						|
#include  <errno.h>
 | 
						|
#include  <limits.h>
 | 
						|
#include  <time.h>
 | 
						|
#include  <reentrant.h>
 | 
						|
#include  "tzfile.h"
 | 
						|
#include  "TimeVals.h"
 | 
						|
#include  <MainData.h>
 | 
						|
#include  <extern.h>      // Library/include/extern.h: Private to implementation
 | 
						|
 | 
						|
#if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler specifics. */
 | 
						|
// Keep compiler quiet about casting from function to data pointers
 | 
						|
#pragma warning ( disable : 4054 )
 | 
						|
#endif  /* defined(_MSC_VER) */
 | 
						|
 | 
						|
/* #######################  Private Data  ################################# */
 | 
						|
 | 
						|
#if 0
 | 
						|
static EFI_TIME TimeBuffer;
 | 
						|
 | 
						|
  static  UINT16   MonthOffs[12] = {
 | 
						|
     00,
 | 
						|
     31,   59,   90,  120,
 | 
						|
    151,  181,  212,  243,
 | 
						|
    273,  304,  334
 | 
						|
  };
 | 
						|
  static  clock_t   y2kOffs = 730485;
 | 
						|
#endif
 | 
						|
 | 
						|
const int  mon_lengths[2][MONSPERYEAR] = {
 | 
						|
  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
 | 
						|
  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
 | 
						|
};
 | 
						|
 | 
						|
const int  year_lengths[2] = {
 | 
						|
  DAYSPERNYEAR, DAYSPERLYEAR
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static const char *wday_name[7] = {
 | 
						|
  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 | 
						|
};
 | 
						|
 | 
						|
static const char *mon_name[12] = {
 | 
						|
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 | 
						|
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 | 
						|
};
 | 
						|
 | 
						|
static int    gmt_is_set;
 | 
						|
 | 
						|
/* ###############  Implementation Functions  ############################ */
 | 
						|
// Forward reference
 | 
						|
static void
 | 
						|
localsub(const time_t * const timep, const long   offset, struct tm * const tmp);
 | 
						|
 | 
						|
clock_t
 | 
						|
__getCPS(void)
 | 
						|
{
 | 
						|
  return gMD->ClocksPerSecond;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
timesub(
 | 
						|
  const time_t        * const timep,
 | 
						|
  const long                  offset,
 | 
						|
  const struct state  * const sp,
 | 
						|
        struct tm     * const tmp
 | 
						|
  )
 | 
						|
{
 | 
						|
  const struct lsinfo *  lp;
 | 
						|
  time_t /*INTN*/     days;
 | 
						|
  time_t /*INTN*/     rem;
 | 
						|
  time_t /*INTN*/      y;
 | 
						|
  int      yleap;
 | 
						|
  const int *    ip;
 | 
						|
  time_t /*INTN*/     corr;
 | 
						|
  int      hit;
 | 
						|
  int      i;
 | 
						|
 | 
						|
  corr = 0;
 | 
						|
  hit = 0;
 | 
						|
#ifdef ALL_STATE
 | 
						|
  i = (sp == NULL) ? 0 : sp->leapcnt;
 | 
						|
#endif /* defined ALL_STATE */
 | 
						|
#ifndef ALL_STATE
 | 
						|
  i = sp->leapcnt;
 | 
						|
#endif /* State Farm */
 | 
						|
  while (--i >= 0) {
 | 
						|
    lp = &sp->lsis[i];
 | 
						|
    if (*timep >= lp->ls_trans) {
 | 
						|
      if (*timep == lp->ls_trans) {
 | 
						|
        hit = ((i == 0 && lp->ls_corr > 0) ||
 | 
						|
               lp->ls_corr > sp->lsis[i - 1].ls_corr);
 | 
						|
        if (hit)
 | 
						|
          while (i > 0                                                &&
 | 
						|
                 sp->lsis[i].ls_trans == sp->lsis[i - 1].ls_trans + 1 &&
 | 
						|
                 sp->lsis[i].ls_corr  == sp->lsis[i - 1].ls_corr  + 1 )
 | 
						|
          {
 | 
						|
            ++hit;
 | 
						|
            --i;
 | 
						|
          }
 | 
						|
      }
 | 
						|
      corr = lp->ls_corr;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  days = *timep / SECSPERDAY;
 | 
						|
  rem = *timep % SECSPERDAY;
 | 
						|
  rem += (offset - corr);
 | 
						|
  while (rem < 0) {
 | 
						|
    rem += SECSPERDAY;
 | 
						|
    --days;
 | 
						|
  }
 | 
						|
  while (rem >= SECSPERDAY) {
 | 
						|
    rem -= SECSPERDAY;
 | 
						|
    ++days;
 | 
						|
  }
 | 
						|
  tmp->tm_hour = (int) (rem / SECSPERHOUR);
 | 
						|
  rem = rem % SECSPERHOUR;
 | 
						|
  tmp->tm_min = (int) (rem / SECSPERMIN);
 | 
						|
  /*
 | 
						|
  ** A positive leap second requires a special
 | 
						|
  ** representation.  This uses "... ??:59:60" et seq.
 | 
						|
  */
 | 
						|
  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
 | 
						|
  tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
 | 
						|
  if (tmp->tm_wday < 0)
 | 
						|
    tmp->tm_wday += DAYSPERWEEK;
 | 
						|
  y = EPOCH_YEAR;
 | 
						|
  while (days < 0 || days >= (LONG32) year_lengths[yleap = isleap(y)]) {
 | 
						|
    time_t /*INTN*/  newy;
 | 
						|
 | 
						|
    newy = (y + days / DAYSPERNYEAR);
 | 
						|
    if (days < 0)
 | 
						|
      --newy;
 | 
						|
    days -= (newy - y) * DAYSPERNYEAR +
 | 
						|
      LEAPS_THRU_END_OF(newy - 1) -
 | 
						|
      LEAPS_THRU_END_OF(y - 1);
 | 
						|
    y = newy;
 | 
						|
  }
 | 
						|
  tmp->tm_year = (int)(y - TM_YEAR_BASE);
 | 
						|
  tmp->tm_yday = (int) days;
 | 
						|
  ip = mon_lengths[yleap];
 | 
						|
  for (tmp->tm_mon = 0; days >= (LONG32) ip[tmp->tm_mon]; ++(tmp->tm_mon))
 | 
						|
    days = days - (LONG32) ip[tmp->tm_mon];
 | 
						|
  tmp->tm_mday = (int) (days + 1);
 | 
						|
  tmp->tm_isdst = 0;
 | 
						|
#ifdef TM_GMTOFF
 | 
						|
  tmp->TM_GMTOFF = offset;
 | 
						|
#endif /* defined TM_GMTOFF */
 | 
						|
}
 | 
						|
 | 
						|
/* ###############  Time Manipulation Functions  ########################## */
 | 
						|
 | 
						|
/**
 | 
						|
**/
 | 
						|
double
 | 
						|
difftime(time_t time1, time_t time0)
 | 
						|
{
 | 
						|
  return (double)(time1 - time0);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Adapted from code provided by Robert Elz, who writes:
 | 
						|
**  The "best" way to do mktime I think is based on an idea of Bob
 | 
						|
**  Kridle's (so its said...) from a long time ago.
 | 
						|
**  [kridle@xinet.com as of 1996-01-16.]
 | 
						|
**  It does a binary search of the time_t space.  Since time_t's are
 | 
						|
**  just 32 bits, its a max of 32 iterations (even at 64 bits it
 | 
						|
**  would still be very reasonable).
 | 
						|
*/
 | 
						|
 | 
						|
#ifndef WRONG
 | 
						|
#define WRONG (-1)
 | 
						|
#endif /* !defined WRONG */
 | 
						|
 | 
						|
/*
 | 
						|
** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
 | 
						|
*/
 | 
						|
 | 
						|
static int
 | 
						|
increment_overflow(int * number, int delta)
 | 
						|
{
 | 
						|
  int number0;
 | 
						|
 | 
						|
  number0 = *number;
 | 
						|
  *number += delta;
 | 
						|
  return (*number < number0) != (delta < 0);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
normalize_overflow(int * const tensptr, int * const unitsptr, const int base)
 | 
						|
{
 | 
						|
  register int  tensdelta;
 | 
						|
 | 
						|
  tensdelta = (*unitsptr >= 0)  ?
 | 
						|
              (*unitsptr / base) : (-1 - (-1 - *unitsptr) / base);
 | 
						|
  *unitsptr -= tensdelta * base;
 | 
						|
  return increment_overflow(tensptr, tensdelta);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
tmcomp(const struct tm * const atmp, const struct tm * const btmp)
 | 
						|
{
 | 
						|
  register int  result;
 | 
						|
 | 
						|
  if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
 | 
						|
      (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
 | 
						|
      (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
 | 
						|
      (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
 | 
						|
      (result = (atmp->tm_min - btmp->tm_min)) == 0)
 | 
						|
    result = atmp->tm_sec - btmp->tm_sec;
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
static time_t
 | 
						|
time2sub(
 | 
						|
  struct tm * const tmp,
 | 
						|
  void (* const funcp)(const time_t*, long, struct tm*),
 | 
						|
  const long offset,
 | 
						|
  int * const okayp,
 | 
						|
  const int do_norm_secs
 | 
						|
  )
 | 
						|
{
 | 
						|
  register const struct state * sp;
 | 
						|
  register int                  dir;
 | 
						|
  register int                  bits;
 | 
						|
  register int                  i, j ;
 | 
						|
  register int                  saved_seconds;
 | 
						|
  time_t                        newt;
 | 
						|
  time_t                        t;
 | 
						|
  struct tm                     yourtm, mytm;
 | 
						|
 | 
						|
  *okayp = FALSE;
 | 
						|
  yourtm = *tmp;    // Create a copy of tmp
 | 
						|
  if (do_norm_secs) {
 | 
						|
    if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
 | 
						|
                           SECSPERMIN))
 | 
						|
      return WRONG;
 | 
						|
  }
 | 
						|
  if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
 | 
						|
    return WRONG;
 | 
						|
  if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
 | 
						|
    return WRONG;
 | 
						|
  if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
 | 
						|
    return WRONG;
 | 
						|
  /*
 | 
						|
  ** Turn yourtm.tm_year into an actual year number for now.
 | 
						|
  ** It is converted back to an offset from TM_YEAR_BASE later.
 | 
						|
  */
 | 
						|
  if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
 | 
						|
    return WRONG;
 | 
						|
  while (yourtm.tm_mday <= 0) {
 | 
						|
    if (increment_overflow(&yourtm.tm_year, -1))
 | 
						|
      return WRONG;
 | 
						|
    i = yourtm.tm_year + (1 < yourtm.tm_mon);
 | 
						|
    yourtm.tm_mday += year_lengths[isleap(i)];
 | 
						|
  }
 | 
						|
  while (yourtm.tm_mday > DAYSPERLYEAR) {
 | 
						|
    i = yourtm.tm_year + (1 < yourtm.tm_mon);
 | 
						|
    yourtm.tm_mday -= year_lengths[isleap(i)];
 | 
						|
    if (increment_overflow(&yourtm.tm_year, 1))
 | 
						|
      return WRONG;
 | 
						|
  }
 | 
						|
  for ( ; ; ) {
 | 
						|
    i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
 | 
						|
    if (yourtm.tm_mday <= i)
 | 
						|
      break;
 | 
						|
    yourtm.tm_mday -= i;
 | 
						|
    if (++yourtm.tm_mon >= MONSPERYEAR) {
 | 
						|
      yourtm.tm_mon = 0;
 | 
						|
      if (increment_overflow(&yourtm.tm_year, 1))
 | 
						|
        return WRONG;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
 | 
						|
    return WRONG;
 | 
						|
  if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
 | 
						|
    saved_seconds = 0;
 | 
						|
  else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
 | 
						|
    /*
 | 
						|
    ** We can't set tm_sec to 0, because that might push the
 | 
						|
    ** time below the minimum representable time.
 | 
						|
    ** Set tm_sec to 59 instead.
 | 
						|
    ** This assumes that the minimum representable time is
 | 
						|
    ** not in the same minute that a leap second was deleted from,
 | 
						|
    ** which is a safer assumption than using 58 would be.
 | 
						|
    */
 | 
						|
    if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
 | 
						|
      return WRONG;
 | 
						|
    saved_seconds = yourtm.tm_sec;
 | 
						|
    yourtm.tm_sec = SECSPERMIN - 1;
 | 
						|
  } else {
 | 
						|
    saved_seconds = yourtm.tm_sec;
 | 
						|
    yourtm.tm_sec = 0;
 | 
						|
  }
 | 
						|
  /*
 | 
						|
  ** Divide the search space in half
 | 
						|
  ** (this works whether time_t is signed or unsigned).
 | 
						|
  */
 | 
						|
  bits = TYPE_BIT(time_t) - 1;
 | 
						|
  /*
 | 
						|
  ** Set t to the midpoint of our binary search.
 | 
						|
  **
 | 
						|
  ** If time_t is signed, then 0 is just above the median,
 | 
						|
  ** assuming two's complement arithmetic.
 | 
						|
  ** If time_t is unsigned, then (1 << bits) is just above the median.
 | 
						|
  */
 | 
						|
  t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
 | 
						|
  for ( ; ; ) {
 | 
						|
    (*funcp)(&t, offset, &mytm);    // Convert t to broken-down time in mytm
 | 
						|
    dir = tmcomp(&mytm, &yourtm);   // Is mytm larger, equal, or less than yourtm?
 | 
						|
    if (dir != 0) {                 // If mytm != yourtm...
 | 
						|
      if (bits-- < 0)                   // If we have exhausted all the bits..
 | 
						|
        return WRONG;                       // Return that we failed
 | 
						|
      if (bits < 0)                     // If on the last bit...
 | 
						|
        --t; /* may be needed if new t is minimal */
 | 
						|
      else if (dir > 0)                 // else if mytm > yourtm...
 | 
						|
        t -= ((time_t) 1) << bits;          // subtract half the remaining time-space
 | 
						|
      else  t += ((time_t) 1) << bits;      // otherwise add half the remaining time-space
 | 
						|
      continue;                     // Repeat for the next half
 | 
						|
    }
 | 
						|
    if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
 | 
						|
      break;
 | 
						|
    /*
 | 
						|
    ** Right time, wrong type.
 | 
						|
    ** Hunt for right time, right type.
 | 
						|
    ** It's okay to guess wrong since the guess
 | 
						|
    ** gets checked.
 | 
						|
    */
 | 
						|
    /*
 | 
						|
    ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
 | 
						|
    */
 | 
						|
    sp = (const struct state *)
 | 
						|
      (((void *) funcp == (void *) localsub) ?
 | 
						|
       lclptr : gmtptr);
 | 
						|
#ifdef ALL_STATE
 | 
						|
    if (sp == NULL)
 | 
						|
      return WRONG;
 | 
						|
#endif /* defined ALL_STATE */
 | 
						|
    for (i = sp->typecnt - 1; i >= 0; --i) {
 | 
						|
      if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
 | 
						|
        continue;
 | 
						|
      for (j = sp->typecnt - 1; j >= 0; --j) {
 | 
						|
        if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
 | 
						|
          continue;
 | 
						|
        newt = t + sp->ttis[j].tt_gmtoff -
 | 
						|
          sp->ttis[i].tt_gmtoff;
 | 
						|
        (*funcp)(&newt, offset, &mytm);
 | 
						|
        if (tmcomp(&mytm, &yourtm) != 0)
 | 
						|
          continue;
 | 
						|
        if (mytm.tm_isdst != yourtm.tm_isdst)
 | 
						|
          continue;
 | 
						|
        /*
 | 
						|
        ** We have a match.
 | 
						|
        */
 | 
						|
        t = newt;
 | 
						|
        goto label;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return WRONG;
 | 
						|
  }
 | 
						|
  label:
 | 
						|
  newt = t + saved_seconds;
 | 
						|
  if ((newt < t) != (saved_seconds < 0))
 | 
						|
    return WRONG;
 | 
						|
  t = newt;
 | 
						|
  (*funcp)(&t, offset, tmp);
 | 
						|
  *okayp = TRUE;
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
time_t
 | 
						|
time2(struct tm * const tmp, void (* const funcp)(const time_t*, long, struct tm*),
 | 
						|
      const long offset, int * const okayp)
 | 
						|
{
 | 
						|
  time_t  t;
 | 
						|
 | 
						|
  /*
 | 
						|
  ** First try without normalization of seconds
 | 
						|
  ** (in case tm_sec contains a value associated with a leap second).
 | 
						|
  ** If that fails, try with normalization of seconds.
 | 
						|
  */
 | 
						|
  t = time2sub(tmp, funcp, offset, okayp, FALSE);
 | 
						|
  return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
static time_t
 | 
						|
time1(
 | 
						|
  struct tm * const tmp,
 | 
						|
  void (* const funcp)(const time_t *, long, struct tm *),
 | 
						|
  const long offset
 | 
						|
  )
 | 
						|
{
 | 
						|
  register time_t               t;
 | 
						|
  register const struct state * sp;
 | 
						|
  register int                  samei, otheri;
 | 
						|
  register int                  sameind, otherind;
 | 
						|
  register int                  i;
 | 
						|
  register int                  nseen;
 | 
						|
  int                           seen[TZ_MAX_TYPES];
 | 
						|
  int                           types[TZ_MAX_TYPES];
 | 
						|
  int                           okay;
 | 
						|
 | 
						|
  if (tmp->tm_isdst > 1)
 | 
						|
    tmp->tm_isdst = 1;
 | 
						|
  t = time2(tmp, funcp, offset, &okay);
 | 
						|
#ifdef PCTS
 | 
						|
  /*
 | 
						|
  ** PCTS code courtesy Grant Sullivan (grant@osf.org).
 | 
						|
  */
 | 
						|
  if (okay)
 | 
						|
    return t;
 | 
						|
  if (tmp->tm_isdst < 0)
 | 
						|
    tmp->tm_isdst = 0;  /* reset to std and try again */
 | 
						|
#endif /* defined PCTS */
 | 
						|
#ifndef PCTS
 | 
						|
  if (okay || tmp->tm_isdst < 0)
 | 
						|
    return t;
 | 
						|
#endif /* !defined PCTS */
 | 
						|
  /*
 | 
						|
  ** We're supposed to assume that somebody took a time of one type
 | 
						|
  ** and did some math on it that yielded a "struct tm" that's bad.
 | 
						|
  ** We try to divine the type they started from and adjust to the
 | 
						|
  ** type they need.
 | 
						|
  */
 | 
						|
  /*
 | 
						|
  ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
 | 
						|
  */
 | 
						|
  sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
 | 
						|
                               lclptr : gmtptr);
 | 
						|
#ifdef ALL_STATE
 | 
						|
  if (sp == NULL)
 | 
						|
    return WRONG;
 | 
						|
#endif /* defined ALL_STATE */
 | 
						|
  for (i = 0; i < sp->typecnt; ++i)
 | 
						|
    seen[i] = FALSE;
 | 
						|
  nseen = 0;
 | 
						|
  for (i = sp->timecnt - 1; i >= 0; --i)
 | 
						|
    if (!seen[sp->types[i]]) {
 | 
						|
    seen[sp->types[i]] = TRUE;
 | 
						|
    types[nseen++] = sp->types[i];
 | 
						|
    }
 | 
						|
    for (sameind = 0; sameind < nseen; ++sameind) {
 | 
						|
      samei = types[sameind];
 | 
						|
      if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
 | 
						|
        continue;
 | 
						|
      for (otherind = 0; otherind < nseen; ++otherind) {
 | 
						|
        otheri = types[otherind];
 | 
						|
        if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
 | 
						|
          continue;
 | 
						|
        tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
 | 
						|
                             sp->ttis[samei].tt_gmtoff);
 | 
						|
        tmp->tm_isdst = !tmp->tm_isdst;
 | 
						|
        t = time2(tmp, funcp, offset, &okay);
 | 
						|
        if (okay)
 | 
						|
          return t;
 | 
						|
        tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
 | 
						|
                             sp->ttis[samei].tt_gmtoff);
 | 
						|
        tmp->tm_isdst = !tmp->tm_isdst;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return WRONG;
 | 
						|
}
 | 
						|
 | 
						|
/** The mktime function converts the broken-down time, expressed as local time,
 | 
						|
    in the structure pointed to by timeptr into a calendar time value with the
 | 
						|
    same encoding as that of the values returned by the time function.  The
 | 
						|
    original values of the tm_wday and tm_yday components of the structure are
 | 
						|
    ignored, and the original values of the other components are not restricted
 | 
						|
    to the ranges indicated above.  Thus, a positive or zero value for tm_isdst
 | 
						|
    causes the mktime function to presume initially that Daylight Saving Time,
 | 
						|
    respectively, is or is not in effect for the specified time. A negative
 | 
						|
    value causes it to attempt to determine whether Daylight Saving Time is in
 | 
						|
    effect for the specified time.  On successful completion, the values of the
 | 
						|
    tm_wday and tm_yday components of the structure are set appropriately, and
 | 
						|
    the other components are set to represent the specified calendar time, but
 | 
						|
    with their values forced to the ranges indicated above; the final value of
 | 
						|
    tm_mday is not set until tm_mon and tm_year are determined.
 | 
						|
 | 
						|
    @return   The mktime function returns the specified calendar time encoded
 | 
						|
              as a value of type time_t.  If the calendar time cannot be
 | 
						|
              represented, the function returns the value (time_t)(-1).
 | 
						|
**/
 | 
						|
time_t
 | 
						|
mktime(struct tm *timeptr)
 | 
						|
{
 | 
						|
  /* From NetBSD */
 | 
						|
  time_t result;
 | 
						|
 | 
						|
  rwlock_wrlock(&lcl_lock);
 | 
						|
  tzset();
 | 
						|
  result = time1(timeptr, &localsub, 0L);
 | 
						|
  rwlock_unlock(&lcl_lock);
 | 
						|
  return (result);
 | 
						|
}
 | 
						|
 | 
						|
/** The time function determines the current calendar time.  The encoding of
 | 
						|
    the value is unspecified.
 | 
						|
 | 
						|
    @return   The time function returns the implementation's best approximation
 | 
						|
              to the current calendar time.  The value (time_t)(-1) is returned
 | 
						|
              if the calendar time is not available.  If timer is not a null
 | 
						|
              pointer, the return value is also assigned to the object it
 | 
						|
              points to.
 | 
						|
**/
 | 
						|
time_t
 | 
						|
time(time_t *timer)
 | 
						|
{
 | 
						|
  time_t      CalTime;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_TIME   *ET;
 | 
						|
  struct tm  *BT;
 | 
						|
 | 
						|
  ET = &gMD->TimeBuffer;
 | 
						|
  BT = &gMD->BDTime;
 | 
						|
 | 
						|
  // Get EFI Time
 | 
						|
  Status = gRT->GetTime( ET, NULL);
 | 
						|
//  Status = EfiGetTime( ET, NULL);
 | 
						|
  EFIerrno = Status;
 | 
						|
  if( Status != RETURN_SUCCESS) {
 | 
						|
    return (time_t)-1;
 | 
						|
  }
 | 
						|
 | 
						|
  // Convert EFI time to broken-down time.
 | 
						|
  Efi2Tm( ET, BT);
 | 
						|
 | 
						|
  // Convert to time_t
 | 
						|
  CalTime  =  mktime(&gMD->BDTime);
 | 
						|
 | 
						|
  if( timer != NULL) {
 | 
						|
    *timer = CalTime;
 | 
						|
  }
 | 
						|
  return CalTime;   // Return calendar time in microseconds
 | 
						|
}
 | 
						|
 | 
						|
/** The clock function determines the processor time used.
 | 
						|
 | 
						|
    @return   The clock function returns the implementation's best
 | 
						|
              approximation to the processor time used by the program since the
 | 
						|
              beginning of an implementation-defined era related only to the
 | 
						|
              program invocation.  To determine the time in seconds, the value
 | 
						|
              returned by the clock function should be divided by the value of
 | 
						|
              the macro CLOCKS_PER_SEC.  If the processor time used is not
 | 
						|
              available or its value cannot be represented, the function
 | 
						|
              returns the value (clock_t)(-1).
 | 
						|
**/
 | 
						|
clock_t
 | 
						|
clock(void)
 | 
						|
{
 | 
						|
  clock_t   retval;
 | 
						|
  time_t    temp;
 | 
						|
 | 
						|
  temp = time(NULL);
 | 
						|
  retval = ((clock_t)((UINT32)temp)) - gMD->AppStartTime;
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/* #################  Time Conversion Functions  ########################## */
 | 
						|
/*
 | 
						|
    Except for the strftime function, these functions each return a pointer to
 | 
						|
    one of two types of static objects: a broken-down time structure or an
 | 
						|
    array of char.  Execution of any of the functions that return a pointer to
 | 
						|
    one of these object types may overwrite the information in any object of
 | 
						|
    the same type pointed to by the value returned from any previous call to
 | 
						|
    any of them.  The implementation shall behave as if no other library
 | 
						|
    functions call these functions.
 | 
						|
*/
 | 
						|
 | 
						|
/** The asctime function converts the broken-down time in the structure pointed
 | 
						|
    to by timeptr into a string in the form
 | 
						|
      Sun Sep 16 01:03:52 1973\n\0
 | 
						|
    using the equivalent of the following algorithm.
 | 
						|
 | 
						|
      char *asctime(const struct tm *timeptr)
 | 
						|
      {
 | 
						|
        static const char wday_name[7][3] = {
 | 
						|
          "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 | 
						|
        };
 | 
						|
        static const char mon_name[12][3] = {
 | 
						|
          "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 | 
						|
          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 | 
						|
        };
 | 
						|
        static char result[26];
 | 
						|
        sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
 | 
						|
                wday_name[timeptr->tm_wday],
 | 
						|
                mon_name[timeptr->tm_mon],
 | 
						|
                timeptr->tm_mday, timeptr->tm_hour,
 | 
						|
                timeptr->tm_min, timeptr->tm_sec,
 | 
						|
                1900 + timeptr->tm_year);
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
    @return   The asctime function returns a pointer to the string.
 | 
						|
**/
 | 
						|
char *
 | 
						|
asctime(const struct tm *timeptr)
 | 
						|
{
 | 
						|
  register const char * wn;
 | 
						|
  register const char * mn;
 | 
						|
 | 
						|
  if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
 | 
						|
    wn = "???";
 | 
						|
  else  wn = wday_name[timeptr->tm_wday];
 | 
						|
  if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
 | 
						|
    mn = "???";
 | 
						|
  else  mn = mon_name[timeptr->tm_mon];
 | 
						|
  /*
 | 
						|
  ** The X3J11-suggested format is
 | 
						|
  **  "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
 | 
						|
  ** Since the .2 in 02.2d is ignored, we drop it.
 | 
						|
  */
 | 
						|
  (void)snprintf(gMD->ASasctime,
 | 
						|
                 sizeof (char[ASCTIME_BUFLEN]),
 | 
						|
                 "%.3s %.3s%3d %02d:%02d:%02d %d\r\n",    // explicit CRLF for EFI
 | 
						|
                 wn, mn,
 | 
						|
                 timeptr->tm_mday, timeptr->tm_hour,
 | 
						|
                 timeptr->tm_min, timeptr->tm_sec,
 | 
						|
                 TM_YEAR_BASE + timeptr->tm_year);
 | 
						|
  return gMD->ASasctime;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
**/
 | 
						|
char *
 | 
						|
ctime(const time_t *timer)
 | 
						|
{
 | 
						|
  return asctime(localtime(timer));
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** gmtsub is to gmtime as localsub is to localtime.
 | 
						|
*/
 | 
						|
void
 | 
						|
gmtsub(
 | 
						|
  const time_t * const  timep,
 | 
						|
  const long            offset,
 | 
						|
  struct tm    * const  tmp
 | 
						|
  )
 | 
						|
{
 | 
						|
#ifdef _REENTRANT
 | 
						|
  static mutex_t gmt_mutex = MUTEX_INITIALIZER;
 | 
						|
#endif
 | 
						|
 | 
						|
  mutex_lock(&gmt_mutex);
 | 
						|
  if (!gmt_is_set) {
 | 
						|
    gmt_is_set = TRUE;
 | 
						|
#ifdef ALL_STATE
 | 
						|
    gmtptr = (struct state *) malloc(sizeof *gmtptr);
 | 
						|
    if (gmtptr != NULL)
 | 
						|
#endif /* defined ALL_STATE */
 | 
						|
      gmtload(gmtptr);
 | 
						|
  }
 | 
						|
  mutex_unlock(&gmt_mutex);
 | 
						|
  timesub(timep, offset, gmtptr, tmp);
 | 
						|
#ifdef TM_ZONE
 | 
						|
  /*
 | 
						|
  ** Could get fancy here and deliver something such as
 | 
						|
  ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
 | 
						|
  ** but this is no time for a treasure hunt.
 | 
						|
  */
 | 
						|
  if (offset != 0)
 | 
						|
    tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr);
 | 
						|
  else {
 | 
						|
#ifdef ALL_STATE
 | 
						|
    if (gmtptr == NULL)
 | 
						|
      tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt);
 | 
						|
    else  tmp->TM_ZONE = gmtptr->chars;
 | 
						|
#endif /* defined ALL_STATE */
 | 
						|
#ifndef ALL_STATE
 | 
						|
    tmp->TM_ZONE = gmtptr->chars;
 | 
						|
#endif /* State Farm */
 | 
						|
  }
 | 
						|
#endif /* defined TM_ZONE */
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
**/
 | 
						|
struct tm *
 | 
						|
gmtime(const time_t *timer)
 | 
						|
{
 | 
						|
  gmtsub(timer, 0L, &gMD->BDTime);
 | 
						|
  return &gMD->BDTime;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
localsub(const time_t * const timep, const long   offset, struct tm * const tmp)
 | 
						|
{
 | 
						|
  register struct state *   sp;
 | 
						|
  register const struct ttinfo *  ttisp;
 | 
						|
  register int      i;
 | 
						|
  const time_t      t = *timep;
 | 
						|
 | 
						|
  sp = lclptr;
 | 
						|
#ifdef ALL_STATE
 | 
						|
  if (sp == NULL) {
 | 
						|
    gmtsub(timep, offset, tmp);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
#endif /* defined ALL_STATE */
 | 
						|
  if (sp->timecnt == 0 || t < sp->ats[0]) {
 | 
						|
    i = 0;
 | 
						|
    while (sp->ttis[i].tt_isdst)
 | 
						|
      if (++i >= sp->typecnt) {
 | 
						|
        i = 0;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
  } else {
 | 
						|
    for (i = 1; i < sp->timecnt; ++i)
 | 
						|
      if (t < sp->ats[i])
 | 
						|
      break;
 | 
						|
    i = sp->types[i - 1];
 | 
						|
  }
 | 
						|
  ttisp = &sp->ttis[i];
 | 
						|
  /*
 | 
						|
  ** To get (wrong) behavior that's compatible with System V Release 2.0
 | 
						|
  ** you'd replace the statement below with
 | 
						|
  **  t += ttisp->tt_gmtoff;
 | 
						|
  **  timesub(&t, 0L, sp, tmp);
 | 
						|
  */
 | 
						|
  timesub(&t, ttisp->tt_gmtoff, sp, tmp);
 | 
						|
  tmp->tm_isdst = ttisp->tt_isdst;
 | 
						|
  tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
 | 
						|
#ifdef TM_ZONE
 | 
						|
  tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
 | 
						|
#endif /* defined TM_ZONE */
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
**/
 | 
						|
struct tm *
 | 
						|
localtime(const time_t *timer)
 | 
						|
{
 | 
						|
  tzset();
 | 
						|
  localsub(timer, 0L, &gMD->BDTime);
 | 
						|
  return &gMD->BDTime;
 | 
						|
}
 |