Add more functions which were missed in the first time commit, that causes the build error with EDK2 Redfish feature driver. strerror - We don't support this on edk2 environment. strpbrk - Cloned this function from edk2-LibC File operation functions - Not supported on edk2 environment. Signed-off-by: Abner Chang <abner.chang@hpe.com> Cc: Nickle Wang <nickle.wang@hpe.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Nickle Wang <nickle.wang@hpe.com> Acked-by: Leif Lindholm <leif@nuviainc.com>
		
			
				
	
	
		
			930 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			930 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  CRT wrapper functions for system call,the string operation functions
 | 
						|
  are remodeled after edk2-libc.
 | 
						|
 | 
						|
  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 | 
						|
  (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
 | 
						|
 | 
						|
    SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
#include <Uefi.h>
 | 
						|
#include <Library/RedfishCrtLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/SortLib.h>
 | 
						|
#include <Library/UefiRuntimeServicesTableLib.h>
 | 
						|
 | 
						|
int  errno = 0;
 | 
						|
char errnum_message [] = "We don't support to map errnum to the error message on edk2 Redfish\n";
 | 
						|
 | 
						|
// This is required to keep VC++ happy if you use floating-point
 | 
						|
int _fltused  = 1;
 | 
						|
 | 
						|
/**
 | 
						|
  Determine if a particular character is an alphanumeric character
 | 
						|
  @return  Returns 1 if c is an alphanumeric character, otherwise returns 0.
 | 
						|
**/
 | 
						|
int isalnum (int c)
 | 
						|
{
 | 
						|
  //
 | 
						|
  // <alnum> ::= [0-9] | [a-z] | [A-Z]
 | 
						|
  //
 | 
						|
  return ((('0' <= (c)) && ((c) <= '9')) ||
 | 
						|
          (('a' <= (c)) && ((c) <= 'z')) ||
 | 
						|
          (('A' <= (c)) && ((c) <= 'Z')));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Determine if a particular character is a digital character
 | 
						|
 | 
						|
  @return  Returns 1 if c is an digital character, otherwise returns 0.
 | 
						|
**/
 | 
						|
int isdchar (int c)
 | 
						|
{
 | 
						|
  //
 | 
						|
  // [0-9] | [e +-.]
 | 
						|
  //
 | 
						|
  return ((('0' <= (c)) && ((c) <= '9')) ||
 | 
						|
          (c == 'e') || (c == 'E') ||
 | 
						|
          (c == '+') || (c == '-') ||
 | 
						|
          (c == '.'));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Determine if a particular character is a space character
 | 
						|
 | 
						|
  @return  Returns 1 if c is a space character
 | 
						|
**/
 | 
						|
int isspace (int c)
 | 
						|
{
 | 
						|
  //
 | 
						|
  // <space> ::= [ ]
 | 
						|
  //
 | 
						|
  return ((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n') || ((c) == '\v')  || ((c) == '\f');
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocates memory blocks
 | 
						|
*/
 | 
						|
void *malloc (size_t size)
 | 
						|
{
 | 
						|
  return AllocatePool ((UINTN) size);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  De-allocates or frees a memory block
 | 
						|
*/
 | 
						|
void free (void *ptr)
 | 
						|
{
 | 
						|
  //
 | 
						|
  // In Standard C, free() handles a null pointer argument transparently. This
 | 
						|
  // is not true of FreePool() below, so protect it.
 | 
						|
  //
 | 
						|
  if (ptr != NULL) {
 | 
						|
    FreePool (ptr);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  NetBSD Compatibility Function strdup creates a duplicate copy of a string.
 | 
						|
 | 
						|
  @return  Returns the pointer to duplicated string.
 | 
						|
**/
 | 
						|
char * strdup(const char *str)
 | 
						|
{
 | 
						|
  size_t len;
 | 
						|
  char *copy;
 | 
						|
 | 
						|
  len = strlen(str) + 1;
 | 
						|
  if ((copy = malloc(len)) == NULL)
 | 
						|
    return (NULL);
 | 
						|
  memcpy(copy, str, len);
 | 
						|
  return (copy);
 | 
						|
}
 | 
						|
 | 
						|
/** The toupper function converts a lowercase letter to a corresponding
 | 
						|
    uppercase letter.
 | 
						|
 | 
						|
    @param[in]    c   The character to be converted.
 | 
						|
 | 
						|
    @return   If the argument is a character for which islower is true and
 | 
						|
              there are one or more corresponding characters, as specified by
 | 
						|
              the current locale, for which isupper is true, the toupper
 | 
						|
              function returns one of the corresponding characters (always the
 | 
						|
              same one for any given locale); otherwise, the argument is
 | 
						|
              returned unchanged.
 | 
						|
**/
 | 
						|
int
 | 
						|
toupper(
 | 
						|
  IN  int c
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ( (c >= 'a') && (c <= 'z') ) {
 | 
						|
    c = c - ('a' - 'A');
 | 
						|
  }
 | 
						|
  return c;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Digit to a value.
 | 
						|
 | 
						|
  @return  Returns the value of digit.
 | 
						|
**/
 | 
						|
int
 | 
						|
Digit2Val( int c)
 | 
						|
{
 | 
						|
  if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {  /* If c is one of [A-Za-z]... */
 | 
						|
    c = toupper(c) - 7;   // Adjust so 'A' is ('9' + 1)
 | 
						|
  }
 | 
						|
  return c - '0';   // Value returned is between 0 and 35, inclusive.
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/** The strtoll function converts the initial portion of the string pointed to
 | 
						|
    by nptr to long long int representation.
 | 
						|
 | 
						|
    See the description for strtol for more information.
 | 
						|
 | 
						|
  @return   The strtoll function returns the converted value, if any. If no
 | 
						|
            conversion could be performed, zero is returned. If the correct
 | 
						|
            value is outside the range of representable values, LLONG_MIN or
 | 
						|
            LLONG_MAX is returned (according to the sign of the value, if any),
 | 
						|
            and the value of the macro ERANGE is stored in errno.
 | 
						|
**/
 | 
						|
long long
 | 
						|
strtoll(const char * nptr, char ** endptr, int base)
 | 
						|
{
 | 
						|
  const char *pEnd;
 | 
						|
  long long   Result = 0;
 | 
						|
  long long   Previous;
 | 
						|
  int         temp;
 | 
						|
  BOOLEAN     Negative = FALSE;
 | 
						|
 | 
						|
  pEnd = nptr;
 | 
						|
 | 
						|
  if((base < 0) || (base == 1) || (base > 36)) {
 | 
						|
    if(endptr != NULL) {
 | 
						|
    *endptr = NULL;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  // Skip leading spaces.
 | 
						|
  while(isspace(*nptr))   ++nptr;
 | 
						|
 | 
						|
  // Process Subject sequence: optional sign followed by digits.
 | 
						|
  if(*nptr == '+') {
 | 
						|
    Negative = FALSE;
 | 
						|
    ++nptr;
 | 
						|
  }
 | 
						|
  else if(*nptr == '-') {
 | 
						|
    Negative = TRUE;
 | 
						|
    ++nptr;
 | 
						|
  }
 | 
						|
 | 
						|
  if(*nptr == '0') {  /* Might be Octal or Hex */
 | 
						|
    if(toupper(nptr[1]) == 'X') {   /* Looks like Hex */
 | 
						|
      if((base == 0) || (base == 16)) {
 | 
						|
        nptr += 2;  /* Skip the "0X"      */
 | 
						|
        base = 16;  /* In case base was 0 */
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {    /* Looks like Octal */
 | 
						|
      if((base == 0) || (base == 8)) {
 | 
						|
        ++nptr;     /* Skip the leading "0" */
 | 
						|
        base = 8;   /* In case base was 0   */
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if(base == 0) {   /* If still zero then must be decimal */
 | 
						|
    base = 10;
 | 
						|
  }
 | 
						|
  if(*nptr  == '0') {
 | 
						|
    for( ; *nptr == '0'; ++nptr);  /* Skip any remaining leading zeros */
 | 
						|
    pEnd = nptr;
 | 
						|
  }
 | 
						|
 | 
						|
  while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
 | 
						|
    Previous = Result;
 | 
						|
    Result = MultS64x64 (Result, base) + (long long int)temp;
 | 
						|
    if( Result <= Previous) {   // Detect Overflow
 | 
						|
      if(Negative) {
 | 
						|
        Result = LLONG_MIN;
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        Result = LLONG_MAX;
 | 
						|
      }
 | 
						|
      Negative = FALSE;
 | 
						|
      errno = ERANGE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    pEnd = ++nptr;
 | 
						|
  }
 | 
						|
  if(Negative) {
 | 
						|
    Result = -Result;
 | 
						|
  }
 | 
						|
 | 
						|
  // Save pointer to final sequence
 | 
						|
  if(endptr != NULL) {
 | 
						|
    *endptr = (char *)pEnd;
 | 
						|
  }
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
/** The strtol, strtoll, strtoul, and strtoull functions convert the initial
 | 
						|
    portion of the string pointed to by nptr to long int, long long int,
 | 
						|
    unsigned long int, and unsigned long long int representation, respectively.
 | 
						|
    First, they decompose the input string into three parts: an initial,
 | 
						|
    possibly empty, sequence of white-space characters (as specified by the
 | 
						|
    isspace function), a subject sequence resembling an integer represented in
 | 
						|
    some radix determined by the value of base, and a final string of one or
 | 
						|
    more unrecognized characters, including the terminating null character of
 | 
						|
    the input string. Then, they attempt to convert the subject sequence to an
 | 
						|
    integer, and return the result.
 | 
						|
 | 
						|
    If the value of base is zero, the expected form of the subject sequence is
 | 
						|
    that of an integer constant, optionally preceded
 | 
						|
    by a plus or minus sign, but not including an integer suffix. If the value
 | 
						|
    of base is between 2 and 36 (inclusive), the expected form of the subject
 | 
						|
    sequence is a sequence of letters and digits representing an integer with
 | 
						|
    the radix specified by base, optionally preceded by a plus or minus sign,
 | 
						|
    but not including an integer suffix. The letters from a (or A) through z
 | 
						|
    (or Z) are ascribed the values 10 through 35; only letters and digits whose
 | 
						|
    ascribed values are less than that of base are permitted. If the value of
 | 
						|
    base is 16, the characters 0x or 0X may optionally precede the sequence of
 | 
						|
    letters and digits, following the sign if present.
 | 
						|
 | 
						|
    The subject sequence is defined as the longest initial subsequence of the
 | 
						|
    input string, starting with the first non-white-space character, that is of
 | 
						|
    the expected form. The subject sequence contains no characters if the input
 | 
						|
    string is empty or consists entirely of white space, or if the first
 | 
						|
    non-white-space character is other than a sign or a permissible letter or digit.
 | 
						|
 | 
						|
    If the subject sequence has the expected form and the value of base is
 | 
						|
    zero, the sequence of characters starting with the first digit is
 | 
						|
    interpreted as an integer constant. If the subject sequence has the
 | 
						|
    expected form and the value of base is between 2 and 36, it is used as the
 | 
						|
    base for conversion, ascribing to each letter its value as given above. If
 | 
						|
    the subject sequence begins with a minus sign, the value resulting from the
 | 
						|
    conversion is negated (in the return type). A pointer to the final string
 | 
						|
    is stored in the object pointed to by endptr, provided that endptr is
 | 
						|
    not a null pointer.
 | 
						|
 | 
						|
    In other than the "C" locale, additional locale-specific subject sequence
 | 
						|
    forms may be accepted.
 | 
						|
 | 
						|
    If the subject sequence is empty or does not have the expected form, no
 | 
						|
    conversion is performed; the value of nptr is stored in the object pointed
 | 
						|
    to by endptr, provided that endptr is not a null pointer.
 | 
						|
 | 
						|
  @return   The strtol, strtoll, strtoul, and strtoull functions return the
 | 
						|
            converted value, if any. If no conversion could be performed, zero
 | 
						|
            is returned. If the correct value is outside the range of
 | 
						|
            representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
 | 
						|
            ULONG_MAX, or ULLONG_MAX is returned (according to the return type
 | 
						|
            and sign of the value, if any), and the value of the macro ERANGE
 | 
						|
            is stored in errno.
 | 
						|
**/
 | 
						|
long
 | 
						|
strtol(const char * nptr, char ** endptr, int base)
 | 
						|
{
 | 
						|
  const char *pEnd;
 | 
						|
  long        Result = 0;
 | 
						|
  long        Previous;
 | 
						|
  int         temp;
 | 
						|
  BOOLEAN     Negative = FALSE;
 | 
						|
 | 
						|
  pEnd = nptr;
 | 
						|
 | 
						|
  if((base < 0) || (base == 1) || (base > 36)) {
 | 
						|
    if(endptr != NULL) {
 | 
						|
    *endptr = NULL;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  // Skip leading spaces.
 | 
						|
  while(isspace(*nptr))   ++nptr;
 | 
						|
 | 
						|
  // Process Subject sequence: optional sign followed by digits.
 | 
						|
  if(*nptr == '+') {
 | 
						|
    Negative = FALSE;
 | 
						|
    ++nptr;
 | 
						|
  }
 | 
						|
  else if(*nptr == '-') {
 | 
						|
    Negative = TRUE;
 | 
						|
    ++nptr;
 | 
						|
  }
 | 
						|
 | 
						|
  if(*nptr == '0') {  /* Might be Octal or Hex */
 | 
						|
    if(toupper(nptr[1]) == 'X') {   /* Looks like Hex */
 | 
						|
      if((base == 0) || (base == 16)) {
 | 
						|
        nptr += 2;  /* Skip the "0X"      */
 | 
						|
        base = 16;  /* In case base was 0 */
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {    /* Looks like Octal */
 | 
						|
      if((base == 0) || (base == 8)) {
 | 
						|
        ++nptr;     /* Skip the leading "0" */
 | 
						|
        base = 8;   /* In case base was 0   */
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if(base == 0) {   /* If still zero then must be decimal */
 | 
						|
    base = 10;
 | 
						|
  }
 | 
						|
  if(*nptr  == '0') {
 | 
						|
    for( ; *nptr == '0'; ++nptr);  /* Skip any remaining leading zeros */
 | 
						|
    pEnd = nptr;
 | 
						|
  }
 | 
						|
 | 
						|
  while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
 | 
						|
    Previous = Result;
 | 
						|
    Result = (Result * base) + (long int)temp;
 | 
						|
    if( Result <= Previous) {   // Detect Overflow
 | 
						|
      if(Negative) {
 | 
						|
        Result = LONG_MIN;
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        Result = LONG_MAX;
 | 
						|
      }
 | 
						|
      Negative = FALSE;
 | 
						|
      errno = ERANGE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    pEnd = ++nptr;
 | 
						|
  }
 | 
						|
  if(Negative) {
 | 
						|
    Result = -Result;
 | 
						|
  }
 | 
						|
 | 
						|
  // Save pointer to final sequence
 | 
						|
  if(endptr != NULL) {
 | 
						|
    *endptr = (char *)pEnd;
 | 
						|
  }
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
/** The strtoull function converts the initial portion of the string pointed to
 | 
						|
    by nptr to unsigned long long int representation.
 | 
						|
 | 
						|
    See the description for strtol for more information.
 | 
						|
 | 
						|
  @return   The strtoull function returns the converted value, if any. If no
 | 
						|
            conversion could be performed, zero is returned. If the correct
 | 
						|
            value is outside the range of representable values, ULLONG_MAX is
 | 
						|
            returned and the value of the macro ERANGE is stored in errno.
 | 
						|
**/
 | 
						|
unsigned long long
 | 
						|
strtoull(const char * nptr, char ** endptr, int base)
 | 
						|
{
 | 
						|
  const char           *pEnd;
 | 
						|
  unsigned long long    Result = 0;
 | 
						|
  unsigned long long    Previous;
 | 
						|
  int                   temp;
 | 
						|
 | 
						|
  pEnd = nptr;
 | 
						|
 | 
						|
  if((base < 0) || (base == 1) || (base > 36)) {
 | 
						|
    if(endptr != NULL) {
 | 
						|
    *endptr = NULL;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  // Skip leading spaces.
 | 
						|
  while(isspace(*nptr))   ++nptr;
 | 
						|
 | 
						|
  // Process Subject sequence: optional + sign followed by digits.
 | 
						|
  if(*nptr == '+') {
 | 
						|
    ++nptr;
 | 
						|
  }
 | 
						|
 | 
						|
  if(*nptr == '0') {  /* Might be Octal or Hex */
 | 
						|
    if(toupper(nptr[1]) == 'X') {   /* Looks like Hex */
 | 
						|
      if((base == 0) || (base == 16)) {
 | 
						|
        nptr += 2;  /* Skip the "0X"      */
 | 
						|
        base = 16;  /* In case base was 0 */
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {    /* Looks like Octal */
 | 
						|
      if((base == 0) || (base == 8)) {
 | 
						|
        ++nptr;     /* Skip the leading "0" */
 | 
						|
        base = 8;   /* In case base was 0   */
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if(base == 0) {   /* If still zero then must be decimal */
 | 
						|
    base = 10;
 | 
						|
  }
 | 
						|
  if(*nptr  == '0') {
 | 
						|
    for( ; *nptr == '0'; ++nptr);  /* Skip any remaining leading zeros */
 | 
						|
    pEnd = nptr;
 | 
						|
  }
 | 
						|
 | 
						|
  while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
 | 
						|
    Previous = Result;
 | 
						|
    Result = DivU64x32 (Result, base) + (unsigned long long)temp;
 | 
						|
    if( Result < Previous)  {   // If we overflowed
 | 
						|
      Result = ULLONG_MAX;
 | 
						|
      errno = ERANGE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    pEnd = ++nptr;
 | 
						|
  }
 | 
						|
 | 
						|
  // Save pointer to final sequence
 | 
						|
  if(endptr != NULL) {
 | 
						|
    *endptr = (char *)pEnd;
 | 
						|
  }
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  edk2 Jansson port does not support doubles, simply return 0.
 | 
						|
 | 
						|
  These conversion functions convert the initial portion of the string
 | 
						|
  pointed to by nptr to double, float, and long double representation,
 | 
						|
  respectively.
 | 
						|
 | 
						|
  The strtod(), strtof(), and strtold() functions return the converted
 | 
						|
  value, if any.
 | 
						|
 | 
						|
  If endptr is not NULL, a pointer to the character after the last charac-
 | 
						|
  ter used in the conversion is stored in the location referenced by
 | 
						|
  endptr.
 | 
						|
 | 
						|
  If no conversion is performed, zero is returned and the value of nptr is
 | 
						|
  stored in the location referenced by endptr.
 | 
						|
 | 
						|
  If the correct value would cause overflow, plus or minus HUGE_VAL,
 | 
						|
  HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of
 | 
						|
  the return value), and ERANGE is stored in errno.  If the correct value
 | 
						|
  would cause underflow, zero is returned and ERANGE is stored in errno.
 | 
						|
 | 
						|
  @return  Return 0.
 | 
						|
**/
 | 
						|
double
 | 
						|
strtod (const char * __restrict nptr, char ** __restrict endptr) {
 | 
						|
 | 
						|
    DEBUG((DEBUG_INFO, "We don't supprot double type on edk2 yet!"));
 | 
						|
    ASSERT(FALSE);
 | 
						|
    return (double)0;
 | 
						|
}
 | 
						|
 | 
						|
static UINT8  BitMask[] = {
 | 
						|
  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
 | 
						|
  };
 | 
						|
 | 
						|
#define WHICH8(c)     ((unsigned char)(c) >> 3)
 | 
						|
#define WHICH_BIT(c)  (BitMask[((c) & 0x7)])
 | 
						|
#define BITMAP64      ((UINT64 *)bitmap)
 | 
						|
 | 
						|
static
 | 
						|
void
 | 
						|
BuildBitmap(unsigned char * bitmap, const char *s2, int n)
 | 
						|
{
 | 
						|
  unsigned char bit;
 | 
						|
  int           index;
 | 
						|
 | 
						|
  // Initialize bitmap.  Bit 0 is always 1 which corresponds to '\0'
 | 
						|
  for (BITMAP64[0] = index = 1; index < n; index++) {
 | 
						|
    BITMAP64[index] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  // Set bits in bitmap corresponding to the characters in s2
 | 
						|
  for (; *s2 != '\0'; s2++) {
 | 
						|
    index = WHICH8(*s2);
 | 
						|
    bit = WHICH_BIT(*s2);
 | 
						|
    bitmap[index] = bitmap[index] | bit;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/** The strpbrk function locates the first occurrence in the string pointed to
 | 
						|
    by s1 of any character from the string pointed to by s2.
 | 
						|
 | 
						|
    @return   The strpbrk function returns a pointer to the character, or a
 | 
						|
              null pointer if no character from s2 occurs in s1.
 | 
						|
**/
 | 
						|
char *
 | 
						|
strpbrk(const char *s1, const char *s2)
 | 
						|
{
 | 
						|
  UINT8 bitmap[ (((UCHAR_MAX + 1) / CHAR_BIT) + (CHAR_BIT - 1)) & ~7U];
 | 
						|
  UINT8 bit;
 | 
						|
  int index;
 | 
						|
 | 
						|
  BuildBitmap( bitmap, s2, sizeof(bitmap) / sizeof(UINT64));
 | 
						|
 | 
						|
  for( ; *s1 != '\0'; ++s1) {
 | 
						|
    index = WHICH8(*s1);
 | 
						|
    bit = WHICH_BIT(*s1);
 | 
						|
    if( (bitmap[index] & bit) != 0) {
 | 
						|
      return (char *)s1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/** The strerror function maps the number in errnum to a message string.
 | 
						|
    Typically, the values for errnum come from errno, but strerror shall map
 | 
						|
    any value of type int to a message.
 | 
						|
 | 
						|
    The implementation shall behave as if no library function calls the
 | 
						|
    strerror function.
 | 
						|
 | 
						|
    @return   The strerror function returns a pointer to the string, the
 | 
						|
              contents of which are locale specific.  The array pointed to
 | 
						|
              shall not be modified by the program, but may be overwritten by
 | 
						|
              a subsequent call to the strerror function.
 | 
						|
**/
 | 
						|
char *
 | 
						|
strerror(int errnum)
 | 
						|
{
 | 
						|
  return errnum_message;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocate and zero-initialize array.
 | 
						|
**/
 | 
						|
void *
 | 
						|
calloc(size_t Num, size_t Size)
 | 
						|
{
 | 
						|
  void       *RetVal;
 | 
						|
  size_t      NumSize;
 | 
						|
 | 
						|
  NumSize = Num * Size;
 | 
						|
  RetVal  = NULL;
 | 
						|
  if (NumSize != 0) {
 | 
						|
  RetVal = malloc(NumSize);
 | 
						|
  if( RetVal != NULL) {
 | 
						|
    (VOID)ZeroMem( RetVal, NumSize);
 | 
						|
  }
 | 
						|
  }
 | 
						|
  DEBUG((DEBUG_POOL, "0x%p = calloc(%d, %d)\n", RetVal, Num, Size));
 | 
						|
 | 
						|
  return RetVal;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
//  The arrays give the cumulative number of days up to the first of the
 | 
						|
//  month number used as the index (1 -> 12) for regular and leap years.
 | 
						|
//  The value at index 13 is for the whole year.
 | 
						|
//
 | 
						|
UINTN CumulativeDays[2][14] = {
 | 
						|
  {
 | 
						|
    0,
 | 
						|
    0,
 | 
						|
    31,
 | 
						|
    31 + 28,
 | 
						|
    31 + 28 + 31,
 | 
						|
    31 + 28 + 31 + 30,
 | 
						|
    31 + 28 + 31 + 30 + 31,
 | 
						|
    31 + 28 + 31 + 30 + 31 + 30,
 | 
						|
    31 + 28 + 31 + 30 + 31 + 30 + 31,
 | 
						|
    31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
 | 
						|
    31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
 | 
						|
    31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
 | 
						|
    31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
 | 
						|
    31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0,
 | 
						|
    0,
 | 
						|
    31,
 | 
						|
    31 + 29,
 | 
						|
    31 + 29 + 31,
 | 
						|
    31 + 29 + 31 + 30,
 | 
						|
    31 + 29 + 31 + 30 + 31,
 | 
						|
    31 + 29 + 31 + 30 + 31 + 30,
 | 
						|
    31 + 29 + 31 + 30 + 31 + 30 + 31,
 | 
						|
    31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
 | 
						|
    31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
 | 
						|
    31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
 | 
						|
    31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
 | 
						|
    31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
#define IsLeap(y)   (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
 | 
						|
#define SECSPERMIN  (60)
 | 
						|
#define SECSPERHOUR (60 * 60)
 | 
						|
#define SECSPERDAY  (24 * SECSPERHOUR)
 | 
						|
 | 
						|
/**
 | 
						|
  Get the system time as seconds elapsed since midnight, January 1, 1970.
 | 
						|
**/
 | 
						|
time_t time (time_t *timer)
 | 
						|
{
 | 
						|
  EFI_TIME  Time;
 | 
						|
  time_t    CalTime;
 | 
						|
  UINTN     Year;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the current time and date information
 | 
						|
  //
 | 
						|
  gRT->GetTime (&Time, NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Years Handling
 | 
						|
  // UTime should now be set to 00:00:00 on Jan 1 of the current year.
 | 
						|
  //
 | 
						|
  for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {
 | 
						|
    CalTime = CalTime + (time_t)(CumulativeDays[IsLeap(Year)][13] * SECSPERDAY);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
 | 
						|
  //
 | 
						|
  CalTime = CalTime +
 | 
						|
            (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +
 | 
						|
            (time_t)(CumulativeDays[IsLeap(Time.Year)][Time.Month] * SECSPERDAY) +
 | 
						|
            (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +
 | 
						|
            (time_t)(Time.Hour * SECSPERHOUR) +
 | 
						|
            (time_t)(Time.Minute * 60) +
 | 
						|
            (time_t)Time.Second;
 | 
						|
 | 
						|
  if (timer != NULL) {
 | 
						|
    *timer = CalTime;
 | 
						|
  }
 | 
						|
 | 
						|
  return CalTime;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Performs a quick sort
 | 
						|
**/
 | 
						|
void qsort (void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
 | 
						|
{
 | 
						|
 | 
						|
  ASSERT (base    != NULL);
 | 
						|
  ASSERT (compare != NULL);
 | 
						|
 | 
						|
  PerformQuickSort (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get character from stream, we don't support file operastion on edk2 JSON library.
 | 
						|
 | 
						|
  @return Returns the character currently pointed by the internal file position indicator of the specified stream
 | 
						|
 | 
						|
**/
 | 
						|
int fgetc(FILE * _File){
 | 
						|
   return EOF;
 | 
						|
}
 | 
						|
/**
 | 
						|
  Open stream file, we don't support file operastion on edk2 JSON library.
 | 
						|
 | 
						|
  @return 0 Unsupported
 | 
						|
 | 
						|
**/
 | 
						|
FILE *fopen (const char *filename, const char *mode) {
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
/**
 | 
						|
  Read stream from file, we don't support file operastion on edk2 JSON library.
 | 
						|
 | 
						|
  @return 0 Unsupported
 | 
						|
 | 
						|
**/
 | 
						|
size_t fread (void * ptr, size_t size, size_t count, FILE * stream) {
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
/**
 | 
						|
  Write stream from file, we don't support file operastion on edk2 JSON library.
 | 
						|
 | 
						|
  @return 0 Unsupported
 | 
						|
 | 
						|
**/
 | 
						|
size_t fwrite (const void * ptr, size_t size, size_t count, FILE * stream) {
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
/**
 | 
						|
  Close file, we don't support file operastion on edk2 JSON library.
 | 
						|
 | 
						|
  @return 0 Unsupported
 | 
						|
 | 
						|
**/
 | 
						|
int fclose (FILE * stream) {
 | 
						|
  return EOF;
 | 
						|
}
 | 
						|
/**
 | 
						|
  Write the formatted string to file, we don't support file operastion on edk2 JSON library.
 | 
						|
 | 
						|
  @return 0 Unsupported
 | 
						|
 | 
						|
**/
 | 
						|
int fprintf (FILE * stream, const char * format, ...) {
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
/**
 | 
						|
  This function check if this is the formating string specifier.
 | 
						|
 | 
						|
  @param[in]      FormatString     A Null-terminated ASCII format string.
 | 
						|
  @param[in,out]  CurrentPosition  The starting position at the given string to check for
 | 
						|
                                   "[flags][width][.precision][length]s" string specifier.
 | 
						|
  @param[in]      StrLength        Maximum string length.
 | 
						|
 | 
						|
  @return BOOLEAN   TRUE means this is the formating string specifier. CurrentPosition is
 | 
						|
                    returned at the position of "s".
 | 
						|
                    FALSE means this is not the formating string specifier.. CurrentPosition is
 | 
						|
                    returned at the position of failed character.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
CheckFormatingString (
 | 
						|
  IN     CONST CHAR8 *FormatString,
 | 
						|
  IN OUT UINTN       *CurrentPosition,
 | 
						|
  IN     UINTN       StrLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8 FormatStringParamater;
 | 
						|
 | 
						|
  while (*(FormatString + *CurrentPosition) != 's') {
 | 
						|
    //
 | 
						|
    // Loop until reach character 's' if the formating string is
 | 
						|
    // compliant with "[flags][width][.precision][length]" format for
 | 
						|
    // the string specifier.
 | 
						|
    //
 | 
						|
    FormatStringParamater = *(FormatString + *CurrentPosition);
 | 
						|
    if ((FormatStringParamater != '-') &&
 | 
						|
        (FormatStringParamater != '+') &&
 | 
						|
        (FormatStringParamater != '*') &&
 | 
						|
        (FormatStringParamater != '.') &&
 | 
						|
        !(((UINTN)FormatStringParamater >= (UINTN)'0') && ((UINTN)FormatStringParamater <= (UINTN)'9'))
 | 
						|
        ) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
    (*CurrentPosition)++;
 | 
						|
    if (*CurrentPosition >= StrLength) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function clones *FormatString however replaces "%s" with "%a" in the
 | 
						|
  returned string.
 | 
						|
 | 
						|
  @param[in] A Null-terminated ASCII format string.
 | 
						|
 | 
						|
  @return The new format string. Caller has to free the memory of this string
 | 
						|
          using FreePool().
 | 
						|
 | 
						|
**/
 | 
						|
CHAR8 *
 | 
						|
ReplaceUnicodeToAsciiStrFormat (
 | 
						|
  IN CONST CHAR8 *FormatString
 | 
						|
)
 | 
						|
{
 | 
						|
  UINTN FormatStrSize;
 | 
						|
  UINTN FormatStrIndex;
 | 
						|
  UINTN FormatStrSpecifier;
 | 
						|
  BOOLEAN PercentageMark;
 | 
						|
  CHAR8 *TempFormatBuffer;
 | 
						|
  BOOLEAN IsFormatString;
 | 
						|
 | 
						|
  //
 | 
						|
  // Error checking.
 | 
						|
  //
 | 
						|
  if (FormatString == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  FormatStrSize = AsciiStrSize(FormatString);
 | 
						|
  if (FormatStrSize == 0) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  TempFormatBuffer = AllocatePool(FormatStrSize); // Allocate memory for the
 | 
						|
                                                  // new string.
 | 
						|
  if (TempFormatBuffer== NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Clone *FormatString but replace "%s" wih "%a".
 | 
						|
  // "%%" is not considered as the format tag.
 | 
						|
  //
 | 
						|
  PercentageMark = FALSE;
 | 
						|
  FormatStrIndex = 0;
 | 
						|
  while (FormatStrIndex < FormatStrSize) {
 | 
						|
    if (PercentageMark == TRUE) {
 | 
						|
      //
 | 
						|
      // Previous character is "%".
 | 
						|
      //
 | 
						|
      PercentageMark = FALSE;
 | 
						|
      if (*(FormatString + FormatStrIndex) != '%') { // Check if this is double "%".
 | 
						|
        FormatStrSpecifier = FormatStrIndex;
 | 
						|
        //
 | 
						|
        // Check if this is the formating string specifier.
 | 
						|
        //
 | 
						|
        IsFormatString = CheckFormatingString (FormatString, &FormatStrSpecifier, FormatStrSize);
 | 
						|
        if ((FormatStrSpecifier - FormatStrIndex) != 0) {
 | 
						|
          CopyMem((VOID *)(TempFormatBuffer + FormatStrIndex),
 | 
						|
                  (VOID *)(FormatString + FormatStrIndex),
 | 
						|
                  FormatStrSpecifier - FormatStrIndex
 | 
						|
                  );
 | 
						|
        }
 | 
						|
        FormatStrIndex = FormatStrSpecifier;
 | 
						|
        if (IsFormatString == TRUE) {
 | 
						|
          //
 | 
						|
          // Replace 's' with 'a' which is printed in ASCII
 | 
						|
          // format on edk2 environment.
 | 
						|
          //
 | 
						|
          *(TempFormatBuffer + FormatStrSpecifier) = 'a';
 | 
						|
          FormatStrIndex ++;
 | 
						|
        }
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      goto ContinueCheck;
 | 
						|
    }
 | 
						|
    if (*(FormatString + FormatStrIndex) == '%') {
 | 
						|
      //
 | 
						|
      // This character is "%", set the flag.
 | 
						|
      //
 | 
						|
      PercentageMark = TRUE;
 | 
						|
    }
 | 
						|
ContinueCheck:
 | 
						|
    //
 | 
						|
    // Clone character to the new string and advance FormatStrIndex
 | 
						|
    // to process next character.
 | 
						|
    //
 | 
						|
    *(TempFormatBuffer + FormatStrIndex) = *(FormatString + FormatStrIndex);
 | 
						|
    FormatStrIndex++;
 | 
						|
  };
 | 
						|
  return TempFormatBuffer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
 | 
						|
  "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
 | 
						|
  environment however "%s" is ascii code base on vsnprintf().
 | 
						|
  See definitions of AsciiVSPrint() for the details.
 | 
						|
 | 
						|
  @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
 | 
						|
                          ASCII string.
 | 
						|
  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
 | 
						|
  @param  FormatString    A Null-terminated ASCII format string.
 | 
						|
  @param  Marker          VA_LIST marker for the variable argument list.
 | 
						|
 | 
						|
  @return The number of ASCII characters in the produced output buffer not including the
 | 
						|
          Null-terminator.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EFIAPI
 | 
						|
RedfishAsciiVSPrint (
 | 
						|
  OUT CHAR8         *StartOfBuffer,
 | 
						|
  IN  UINTN         BufferSize,
 | 
						|
  IN  CONST CHAR8   *FormatString,
 | 
						|
  IN  VA_LIST       Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8 *TempFormatBuffer;
 | 
						|
  UINTN LenStrProduced;
 | 
						|
 | 
						|
  //
 | 
						|
  // Looking for "%s" in the format string and replace it
 | 
						|
  // with "%a" for printing ASCII code characters on edk2
 | 
						|
  // environment.
 | 
						|
  //
 | 
						|
  TempFormatBuffer = ReplaceUnicodeToAsciiStrFormat (FormatString);
 | 
						|
  if (TempFormatBuffer == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  LenStrProduced = AsciiVSPrint (StartOfBuffer, BufferSize, (CONST CHAR8 *)TempFormatBuffer, Marker);
 | 
						|
  FreePool (TempFormatBuffer);
 | 
						|
  return LenStrProduced;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This is the Redfish version of CRT snprintf function, this function replaces "%s" to
 | 
						|
  "%a" before invoking AsciiSPrint(). That is because "%s" is unicode base on edk2
 | 
						|
  environment however "%s" is ascii code base on snprintf().
 | 
						|
  See definitions of AsciiSPrint() for the details.
 | 
						|
 | 
						|
  @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
 | 
						|
                          ASCII string.
 | 
						|
  @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
 | 
						|
  @param  FormatString    A Null-terminated ASCII format string.
 | 
						|
  @param  ...             Variable argument list whose contents are accessed based on the
 | 
						|
                          format string specified by FormatString.
 | 
						|
 | 
						|
  @return The number of ASCII characters in the produced output buffer not including the
 | 
						|
          Null-terminator.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EFIAPI
 | 
						|
RedfishAsciiSPrint (
 | 
						|
  OUT CHAR8        *StartOfBuffer,
 | 
						|
  IN  UINTN        BufferSize,
 | 
						|
  IN  CONST CHAR8  *FormatString,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  VA_LIST Marker;
 | 
						|
  UINTN LenStrProduced;
 | 
						|
 | 
						|
  VA_START(Marker, FormatString);
 | 
						|
  LenStrProduced = RedfishAsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
 | 
						|
  return LenStrProduced;
 | 
						|
}
 | 
						|
 |