]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / RedfishPkg / PrivateLibrary / RedfishCrtLib / RedfishCrtLib.c
... / ...
CommitLineData
1/** @file\r
2 CRT wrapper functions for system call,the string operation functions\r
3 are remodeled after edk2-libc.\r
4\r
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
6 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11#include <Uefi.h>\r
12#include <Library/RedfishCrtLib.h>\r
13#include <Library/MemoryAllocationLib.h>\r
14#include <Library/SortLib.h>\r
15#include <Library/UefiRuntimeServicesTableLib.h>\r
16\r
17int errno = 0;\r
18char errnum_message[] = "We don't support to map errnum to the error message on edk2 Redfish\n";\r
19\r
20// This is required to keep VC++ happy if you use floating-point\r
21int _fltused = 1;\r
22\r
23/**\r
24 Determine if a particular character is an alphanumeric character\r
25 @return Returns 1 if c is an alphanumeric character, otherwise returns 0.\r
26**/\r
27int\r
28isalnum (\r
29 int c\r
30 )\r
31{\r
32 //\r
33 // <alnum> ::= [0-9] | [a-z] | [A-Z]\r
34 //\r
35 return ((('0' <= (c)) && ((c) <= '9')) ||\r
36 (('a' <= (c)) && ((c) <= 'z')) ||\r
37 (('A' <= (c)) && ((c) <= 'Z')));\r
38}\r
39\r
40/**\r
41 Determine if a particular character is a digital character\r
42\r
43 @return Returns 1 if c is an digital character, otherwise returns 0.\r
44**/\r
45int\r
46isdchar (\r
47 int c\r
48 )\r
49{\r
50 //\r
51 // [0-9] | [e +-.]\r
52 //\r
53 return ((('0' <= (c)) && ((c) <= '9')) ||\r
54 (c == 'e') || (c == 'E') ||\r
55 (c == '+') || (c == '-') ||\r
56 (c == '.'));\r
57}\r
58\r
59/**\r
60 Determine if a particular character is a space character\r
61\r
62 @return Returns 1 if c is a space character\r
63**/\r
64int\r
65isspace (\r
66 int c\r
67 )\r
68{\r
69 //\r
70 // <space> ::= [ ]\r
71 //\r
72 return ((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n') || ((c) == '\v') || ((c) == '\f');\r
73}\r
74\r
75/**\r
76 Allocates memory blocks\r
77*/\r
78void *\r
79malloc (\r
80 size_t size\r
81 )\r
82{\r
83 return AllocatePool ((UINTN)size);\r
84}\r
85\r
86/**\r
87 De-allocates or frees a memory block\r
88*/\r
89void\r
90free (\r
91 void *ptr\r
92 )\r
93{\r
94 //\r
95 // In Standard C, free() handles a null pointer argument transparently. This\r
96 // is not true of FreePool() below, so protect it.\r
97 //\r
98 if (ptr != NULL) {\r
99 FreePool (ptr);\r
100 }\r
101}\r
102\r
103/**\r
104 NetBSD Compatibility Function strdup creates a duplicate copy of a string.\r
105\r
106 @return Returns the pointer to duplicated string.\r
107**/\r
108char *\r
109strdup (\r
110 const char *str\r
111 )\r
112{\r
113 size_t len;\r
114 char *copy;\r
115\r
116 len = strlen (str) + 1;\r
117 if ((copy = malloc (len)) == NULL) {\r
118 return (NULL);\r
119 }\r
120\r
121 memcpy (copy, str, len);\r
122 return (copy);\r
123}\r
124\r
125/** The toupper function converts a lowercase letter to a corresponding\r
126 uppercase letter.\r
127\r
128 @param[in] c The character to be converted.\r
129\r
130 @return If the argument is a character for which islower is true and\r
131 there are one or more corresponding characters, as specified by\r
132 the current locale, for which isupper is true, the toupper\r
133 function returns one of the corresponding characters (always the\r
134 same one for any given locale); otherwise, the argument is\r
135 returned unchanged.\r
136**/\r
137int\r
138toupper (\r
139 IN int c\r
140 )\r
141{\r
142 if ((c >= 'a') && (c <= 'z')) {\r
143 c = c - ('a' - 'A');\r
144 }\r
145\r
146 return c;\r
147}\r
148\r
149/**\r
150 Digit to a value.\r
151\r
152 @return Returns the value of digit.\r
153**/\r
154int\r
155Digit2Val (\r
156 int c\r
157 )\r
158{\r
159 if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {\r
160 /* If c is one of [A-Za-z]... */\r
161 c = toupper (c) - 7; // Adjust so 'A' is ('9' + 1)\r
162 }\r
163\r
164 return c - '0'; // Value returned is between 0 and 35, inclusive.\r
165}\r
166\r
167/** The strtoll function converts the initial portion of the string pointed to\r
168 by nptr to long long int representation.\r
169\r
170 See the description for strtol for more information.\r
171\r
172 @return The strtoll function returns the converted value, if any. If no\r
173 conversion could be performed, zero is returned. If the correct\r
174 value is outside the range of representable values, LLONG_MIN or\r
175 LLONG_MAX is returned (according to the sign of the value, if any),\r
176 and the value of the macro ERANGE is stored in errno.\r
177**/\r
178long long\r
179strtoll (\r
180 const char *nptr,\r
181 char **endptr,\r
182 int base\r
183 )\r
184{\r
185 const char *pEnd;\r
186 long long Result = 0;\r
187 long long Previous;\r
188 int temp;\r
189 BOOLEAN Negative = FALSE;\r
190\r
191 pEnd = nptr;\r
192\r
193 if ((base < 0) || (base == 1) || (base > 36)) {\r
194 if (endptr != NULL) {\r
195 *endptr = NULL;\r
196 }\r
197\r
198 return 0;\r
199 }\r
200\r
201 // Skip leading spaces.\r
202 while (isspace (*nptr)) {\r
203 ++nptr;\r
204 }\r
205\r
206 // Process Subject sequence: optional sign followed by digits.\r
207 if (*nptr == '+') {\r
208 Negative = FALSE;\r
209 ++nptr;\r
210 } else if (*nptr == '-') {\r
211 Negative = TRUE;\r
212 ++nptr;\r
213 }\r
214\r
215 if (*nptr == '0') {\r
216 /* Might be Octal or Hex */\r
217 if (toupper (nptr[1]) == 'X') {\r
218 /* Looks like Hex */\r
219 if ((base == 0) || (base == 16)) {\r
220 nptr += 2; /* Skip the "0X" */\r
221 base = 16; /* In case base was 0 */\r
222 }\r
223 } else {\r
224 /* Looks like Octal */\r
225 if ((base == 0) || (base == 8)) {\r
226 ++nptr; /* Skip the leading "0" */\r
227 base = 8; /* In case base was 0 */\r
228 }\r
229 }\r
230 }\r
231\r
232 if (base == 0) {\r
233 /* If still zero then must be decimal */\r
234 base = 10;\r
235 }\r
236\r
237 if (*nptr == '0') {\r
238 for ( ; *nptr == '0'; ++nptr) {\r
239 /* Skip any remaining leading zeros */\r
240 }\r
241\r
242 pEnd = nptr;\r
243 }\r
244\r
245 while ( isalnum (*nptr) && ((temp = Digit2Val (*nptr)) < base)) {\r
246 Previous = Result;\r
247 Result = MultS64x64 (Result, base) + (long long int)temp;\r
248 if ( Result <= Previous) {\r
249 // Detect Overflow\r
250 if (Negative) {\r
251 Result = LLONG_MIN;\r
252 } else {\r
253 Result = LLONG_MAX;\r
254 }\r
255\r
256 Negative = FALSE;\r
257 errno = ERANGE;\r
258 break;\r
259 }\r
260\r
261 pEnd = ++nptr;\r
262 }\r
263\r
264 if (Negative) {\r
265 Result = -Result;\r
266 }\r
267\r
268 // Save pointer to final sequence\r
269 if (endptr != NULL) {\r
270 *endptr = (char *)pEnd;\r
271 }\r
272\r
273 return Result;\r
274}\r
275\r
276/** The strtol, strtoll, strtoul, and strtoull functions convert the initial\r
277 portion of the string pointed to by nptr to long int, long long int,\r
278 unsigned long int, and unsigned long long int representation, respectively.\r
279 First, they decompose the input string into three parts: an initial,\r
280 possibly empty, sequence of white-space characters (as specified by the\r
281 isspace function), a subject sequence resembling an integer represented in\r
282 some radix determined by the value of base, and a final string of one or\r
283 more unrecognized characters, including the terminating null character of\r
284 the input string. Then, they attempt to convert the subject sequence to an\r
285 integer, and return the result.\r
286\r
287 If the value of base is zero, the expected form of the subject sequence is\r
288 that of an integer constant, optionally preceded\r
289 by a plus or minus sign, but not including an integer suffix. If the value\r
290 of base is between 2 and 36 (inclusive), the expected form of the subject\r
291 sequence is a sequence of letters and digits representing an integer with\r
292 the radix specified by base, optionally preceded by a plus or minus sign,\r
293 but not including an integer suffix. The letters from a (or A) through z\r
294 (or Z) are ascribed the values 10 through 35; only letters and digits whose\r
295 ascribed values are less than that of base are permitted. If the value of\r
296 base is 16, the characters 0x or 0X may optionally precede the sequence of\r
297 letters and digits, following the sign if present.\r
298\r
299 The subject sequence is defined as the longest initial subsequence of the\r
300 input string, starting with the first non-white-space character, that is of\r
301 the expected form. The subject sequence contains no characters if the input\r
302 string is empty or consists entirely of white space, or if the first\r
303 non-white-space character is other than a sign or a permissible letter or digit.\r
304\r
305 If the subject sequence has the expected form and the value of base is\r
306 zero, the sequence of characters starting with the first digit is\r
307 interpreted as an integer constant. If the subject sequence has the\r
308 expected form and the value of base is between 2 and 36, it is used as the\r
309 base for conversion, ascribing to each letter its value as given above. If\r
310 the subject sequence begins with a minus sign, the value resulting from the\r
311 conversion is negated (in the return type). A pointer to the final string\r
312 is stored in the object pointed to by endptr, provided that endptr is\r
313 not a null pointer.\r
314\r
315 In other than the "C" locale, additional locale-specific subject sequence\r
316 forms may be accepted.\r
317\r
318 If the subject sequence is empty or does not have the expected form, no\r
319 conversion is performed; the value of nptr is stored in the object pointed\r
320 to by endptr, provided that endptr is not a null pointer.\r
321\r
322 @return The strtol, strtoll, strtoul, and strtoull functions return the\r
323 converted value, if any. If no conversion could be performed, zero\r
324 is returned. If the correct value is outside the range of\r
325 representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,\r
326 ULONG_MAX, or ULLONG_MAX is returned (according to the return type\r
327 and sign of the value, if any), and the value of the macro ERANGE\r
328 is stored in errno.\r
329**/\r
330long\r
331strtol (\r
332 const char *nptr,\r
333 char **endptr,\r
334 int base\r
335 )\r
336{\r
337 const char *pEnd;\r
338 long Result = 0;\r
339 long Previous;\r
340 int temp;\r
341 BOOLEAN Negative = FALSE;\r
342\r
343 pEnd = nptr;\r
344\r
345 if ((base < 0) || (base == 1) || (base > 36)) {\r
346 if (endptr != NULL) {\r
347 *endptr = NULL;\r
348 }\r
349\r
350 return 0;\r
351 }\r
352\r
353 // Skip leading spaces.\r
354 while (isspace (*nptr)) {\r
355 ++nptr;\r
356 }\r
357\r
358 // Process Subject sequence: optional sign followed by digits.\r
359 if (*nptr == '+') {\r
360 Negative = FALSE;\r
361 ++nptr;\r
362 } else if (*nptr == '-') {\r
363 Negative = TRUE;\r
364 ++nptr;\r
365 }\r
366\r
367 if (*nptr == '0') {\r
368 /* Might be Octal or Hex */\r
369 if (toupper (nptr[1]) == 'X') {\r
370 /* Looks like Hex */\r
371 if ((base == 0) || (base == 16)) {\r
372 nptr += 2; /* Skip the "0X" */\r
373 base = 16; /* In case base was 0 */\r
374 }\r
375 } else {\r
376 /* Looks like Octal */\r
377 if ((base == 0) || (base == 8)) {\r
378 ++nptr; /* Skip the leading "0" */\r
379 base = 8; /* In case base was 0 */\r
380 }\r
381 }\r
382 }\r
383\r
384 if (base == 0) {\r
385 /* If still zero then must be decimal */\r
386 base = 10;\r
387 }\r
388\r
389 if (*nptr == '0') {\r
390 for ( ; *nptr == '0'; ++nptr) {\r
391 /* Skip any remaining leading zeros */\r
392 }\r
393\r
394 pEnd = nptr;\r
395 }\r
396\r
397 while ( isalnum (*nptr) && ((temp = Digit2Val (*nptr)) < base)) {\r
398 Previous = Result;\r
399 Result = (Result * base) + (long int)temp;\r
400 if ( Result <= Previous) {\r
401 // Detect Overflow\r
402 if (Negative) {\r
403 Result = LONG_MIN;\r
404 } else {\r
405 Result = LONG_MAX;\r
406 }\r
407\r
408 Negative = FALSE;\r
409 errno = ERANGE;\r
410 break;\r
411 }\r
412\r
413 pEnd = ++nptr;\r
414 }\r
415\r
416 if (Negative) {\r
417 Result = -Result;\r
418 }\r
419\r
420 // Save pointer to final sequence\r
421 if (endptr != NULL) {\r
422 *endptr = (char *)pEnd;\r
423 }\r
424\r
425 return Result;\r
426}\r
427\r
428/** The strtoull function converts the initial portion of the string pointed to\r
429 by nptr to unsigned long long int representation.\r
430\r
431 See the description for strtol for more information.\r
432\r
433 @return The strtoull function returns the converted value, if any. If no\r
434 conversion could be performed, zero is returned. If the correct\r
435 value is outside the range of representable values, ULLONG_MAX is\r
436 returned and the value of the macro ERANGE is stored in errno.\r
437**/\r
438unsigned long long\r
439strtoull (\r
440 const char *nptr,\r
441 char **endptr,\r
442 int base\r
443 )\r
444{\r
445 const char *pEnd;\r
446 unsigned long long Result = 0;\r
447 unsigned long long Previous;\r
448 int temp;\r
449\r
450 pEnd = nptr;\r
451\r
452 if ((base < 0) || (base == 1) || (base > 36)) {\r
453 if (endptr != NULL) {\r
454 *endptr = NULL;\r
455 }\r
456\r
457 return 0;\r
458 }\r
459\r
460 // Skip leading spaces.\r
461 while (isspace (*nptr)) {\r
462 ++nptr;\r
463 }\r
464\r
465 // Process Subject sequence: optional + sign followed by digits.\r
466 if (*nptr == '+') {\r
467 ++nptr;\r
468 }\r
469\r
470 if (*nptr == '0') {\r
471 /* Might be Octal or Hex */\r
472 if (toupper (nptr[1]) == 'X') {\r
473 /* Looks like Hex */\r
474 if ((base == 0) || (base == 16)) {\r
475 nptr += 2; /* Skip the "0X" */\r
476 base = 16; /* In case base was 0 */\r
477 }\r
478 } else {\r
479 /* Looks like Octal */\r
480 if ((base == 0) || (base == 8)) {\r
481 ++nptr; /* Skip the leading "0" */\r
482 base = 8; /* In case base was 0 */\r
483 }\r
484 }\r
485 }\r
486\r
487 if (base == 0) {\r
488 /* If still zero then must be decimal */\r
489 base = 10;\r
490 }\r
491\r
492 if (*nptr == '0') {\r
493 for ( ; *nptr == '0'; ++nptr) {\r
494 /* Skip any remaining leading zeros */\r
495 }\r
496\r
497 pEnd = nptr;\r
498 }\r
499\r
500 while ( isalnum (*nptr) && ((temp = Digit2Val (*nptr)) < base)) {\r
501 Previous = Result;\r
502 Result = DivU64x32 (Result, base) + (unsigned long long)temp;\r
503 if ( Result < Previous) {\r
504 // If we overflowed\r
505 Result = ULLONG_MAX;\r
506 errno = ERANGE;\r
507 break;\r
508 }\r
509\r
510 pEnd = ++nptr;\r
511 }\r
512\r
513 // Save pointer to final sequence\r
514 if (endptr != NULL) {\r
515 *endptr = (char *)pEnd;\r
516 }\r
517\r
518 return Result;\r
519}\r
520\r
521/**\r
522 edk2 Jansson port does not support doubles, simply return 0.\r
523\r
524 These conversion functions convert the initial portion of the string\r
525 pointed to by nptr to double, float, and long double representation,\r
526 respectively.\r
527\r
528 The strtod(), strtof(), and strtold() functions return the converted\r
529 value, if any.\r
530\r
531 If endptr is not NULL, a pointer to the character after the last charac-\r
532 ter used in the conversion is stored in the location referenced by\r
533 endptr.\r
534\r
535 If no conversion is performed, zero is returned and the value of nptr is\r
536 stored in the location referenced by endptr.\r
537\r
538 If the correct value would cause overflow, plus or minus HUGE_VAL,\r
539 HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of\r
540 the return value), and ERANGE is stored in errno. If the correct value\r
541 would cause underflow, zero is returned and ERANGE is stored in errno.\r
542\r
543 @return Return 0.\r
544**/\r
545double\r
546strtod (\r
547 const char *__restrict nptr,\r
548 char **__restrict endptr\r
549 )\r
550{\r
551 DEBUG ((DEBUG_INFO, "We don't supprot double type on edk2 yet!"));\r
552 ASSERT (FALSE);\r
553 return (double)0;\r
554}\r
555\r
556static UINT8 BitMask[] = {\r
557 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80\r
558};\r
559\r
560#define WHICH8(c) ((unsigned char)(c) >> 3)\r
561#define WHICH_BIT(c) (BitMask[((c) & 0x7)])\r
562#define BITMAP64 ((UINT64 *)bitmap)\r
563\r
564static\r
565void\r
566BuildBitmap (\r
567 unsigned char *bitmap,\r
568 const char *s2,\r
569 int n\r
570 )\r
571{\r
572 unsigned char bit;\r
573 int index;\r
574\r
575 // Initialize bitmap. Bit 0 is always 1 which corresponds to '\0'\r
576 for (BITMAP64[0] = index = 1; index < n; index++) {\r
577 BITMAP64[index] = 0;\r
578 }\r
579\r
580 // Set bits in bitmap corresponding to the characters in s2\r
581 for ( ; *s2 != '\0'; s2++) {\r
582 index = WHICH8 (*s2);\r
583 bit = WHICH_BIT (*s2);\r
584 bitmap[index] = bitmap[index] | bit;\r
585 }\r
586}\r
587\r
588/** The strpbrk function locates the first occurrence in the string pointed to\r
589 by s1 of any character from the string pointed to by s2.\r
590\r
591 @return The strpbrk function returns a pointer to the character, or a\r
592 null pointer if no character from s2 occurs in s1.\r
593**/\r
594char *\r
595strpbrk (\r
596 const char *s1,\r
597 const char *s2\r
598 )\r
599{\r
600 UINT8 bitmap[(((UCHAR_MAX + 1) / CHAR_BIT) + (CHAR_BIT - 1)) & ~7U];\r
601 UINT8 bit;\r
602 int index;\r
603\r
604 BuildBitmap (bitmap, s2, sizeof (bitmap) / sizeof (UINT64));\r
605\r
606 for ( ; *s1 != '\0'; ++s1) {\r
607 index = WHICH8 (*s1);\r
608 bit = WHICH_BIT (*s1);\r
609 if ((bitmap[index] & bit) != 0) {\r
610 return (char *)s1;\r
611 }\r
612 }\r
613\r
614 return NULL;\r
615}\r
616\r
617/** The strerror function maps the number in errnum to a message string.\r
618 Typically, the values for errnum come from errno, but strerror shall map\r
619 any value of type int to a message.\r
620\r
621 The implementation shall behave as if no library function calls the\r
622 strerror function.\r
623\r
624 @return The strerror function returns a pointer to the string, the\r
625 contents of which are locale specific. The array pointed to\r
626 shall not be modified by the program, but may be overwritten by\r
627 a subsequent call to the strerror function.\r
628**/\r
629char *\r
630strerror (\r
631 int errnum\r
632 )\r
633{\r
634 return errnum_message;\r
635}\r
636\r
637/**\r
638 Allocate and zero-initialize array.\r
639**/\r
640void *\r
641calloc (\r
642 size_t Num,\r
643 size_t Size\r
644 )\r
645{\r
646 void *RetVal;\r
647 size_t NumSize;\r
648\r
649 NumSize = Num * Size;\r
650 RetVal = NULL;\r
651 if (NumSize != 0) {\r
652 RetVal = malloc (NumSize);\r
653 if ( RetVal != NULL) {\r
654 (VOID)ZeroMem (RetVal, NumSize);\r
655 }\r
656 }\r
657\r
658 DEBUG ((DEBUG_POOL, "0x%p = calloc(%d, %d)\n", RetVal, Num, Size));\r
659\r
660 return RetVal;\r
661}\r
662\r
663//\r
664// The arrays give the cumulative number of days up to the first of the\r
665// month number used as the index (1 -> 12) for regular and leap years.\r
666// The value at index 13 is for the whole year.\r
667//\r
668UINTN CumulativeDays[2][14] = {\r
669 {\r
670 0,\r
671 0,\r
672 31,\r
673 31 + 28,\r
674 31 + 28 + 31,\r
675 31 + 28 + 31 + 30,\r
676 31 + 28 + 31 + 30 + 31,\r
677 31 + 28 + 31 + 30 + 31 + 30,\r
678 31 + 28 + 31 + 30 + 31 + 30 + 31,\r
679 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,\r
680 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,\r
681 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,\r
682 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,\r
683 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31\r
684 },\r
685 {\r
686 0,\r
687 0,\r
688 31,\r
689 31 + 29,\r
690 31 + 29 + 31,\r
691 31 + 29 + 31 + 30,\r
692 31 + 29 + 31 + 30 + 31,\r
693 31 + 29 + 31 + 30 + 31 + 30,\r
694 31 + 29 + 31 + 30 + 31 + 30 + 31,\r
695 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,\r
696 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,\r
697 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,\r
698 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,\r
699 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31\r
700 }\r
701};\r
702\r
703#define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))\r
704#define SECSPERMIN (60)\r
705#define SECSPERHOUR (60 * 60)\r
706#define SECSPERDAY (24 * SECSPERHOUR)\r
707\r
708/**\r
709 Get the system time as seconds elapsed since midnight, January 1, 1970.\r
710**/\r
711time_t\r
712time (\r
713 time_t *timer\r
714 )\r
715{\r
716 EFI_TIME Time;\r
717 time_t CalTime;\r
718 UINTN Year;\r
719\r
720 //\r
721 // Get the current time and date information\r
722 //\r
723 gRT->GetTime (&Time, NULL);\r
724\r
725 //\r
726 // Years Handling\r
727 // UTime should now be set to 00:00:00 on Jan 1 of the current year.\r
728 //\r
729 for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {\r
730 CalTime = CalTime + (time_t)(CumulativeDays[IsLeap (Year)][13] * SECSPERDAY);\r
731 }\r
732\r
733 //\r
734 // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment\r
735 //\r
736 CalTime = CalTime +\r
737 (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +\r
738 (time_t)(CumulativeDays[IsLeap (Time.Year)][Time.Month] * SECSPERDAY) +\r
739 (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +\r
740 (time_t)(Time.Hour * SECSPERHOUR) +\r
741 (time_t)(Time.Minute * 60) +\r
742 (time_t)Time.Second;\r
743\r
744 if (timer != NULL) {\r
745 *timer = CalTime;\r
746 }\r
747\r
748 return CalTime;\r
749}\r
750\r
751/**\r
752 Performs a quick sort\r
753**/\r
754void\r
755qsort (\r
756 void *base,\r
757 size_t num,\r
758 size_t width,\r
759 int ( *compare )(const void *, const void *)\r
760 )\r
761{\r
762 ASSERT (base != NULL);\r
763 ASSERT (compare != NULL);\r
764\r
765 PerformQuickSort (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare);\r
766 return;\r
767}\r
768\r
769/**\r
770 Get character from stream, we don't support file operastion on edk2 JSON library.\r
771\r
772 @return Returns the character currently pointed by the internal file position indicator of the specified stream\r
773\r
774**/\r
775int\r
776fgetc (\r
777 FILE *_File\r
778 )\r
779{\r
780 return EOF;\r
781}\r
782\r
783/**\r
784 Open stream file, we don't support file operastion on edk2 JSON library.\r
785\r
786 @return 0 Unsupported\r
787\r
788**/\r
789FILE *\r
790fopen (\r
791 const char *filename,\r
792 const char *mode\r
793 )\r
794{\r
795 return NULL;\r
796}\r
797\r
798/**\r
799 Read stream from file, we don't support file operastion on edk2 JSON library.\r
800\r
801 @return 0 Unsupported\r
802\r
803**/\r
804size_t\r
805fread (\r
806 void *ptr,\r
807 size_t size,\r
808 size_t count,\r
809 FILE *stream\r
810 )\r
811{\r
812 return 0;\r
813}\r
814\r
815/**\r
816 Write stream from file, we don't support file operastion on edk2 JSON library.\r
817\r
818 @return 0 Unsupported\r
819\r
820**/\r
821size_t\r
822fwrite (\r
823 const void *ptr,\r
824 size_t size,\r
825 size_t count,\r
826 FILE *stream\r
827 )\r
828{\r
829 return 0;\r
830}\r
831\r
832/**\r
833 Close file, we don't support file operastion on edk2 JSON library.\r
834\r
835 @return 0 Unsupported\r
836\r
837**/\r
838int\r
839fclose (\r
840 FILE *stream\r
841 )\r
842{\r
843 return EOF;\r
844}\r
845\r
846/**\r
847 Write the formatted string to file, we don't support file operastion on edk2 JSON library.\r
848\r
849 @return 0 Unsupported\r
850\r
851**/\r
852int\r
853fprintf (\r
854 FILE *stream,\r
855 const char *format,\r
856 ...\r
857 )\r
858{\r
859 return -1;\r
860}\r
861\r
862/**\r
863 This function check if this is the formating string specifier.\r
864\r
865 @param[in] FormatString A Null-terminated ASCII format string.\r
866 @param[in,out] CurrentPosition The starting position at the given string to check for\r
867 "[flags][width][.precision][length]s" string specifier.\r
868 @param[in] StrLength Maximum string length.\r
869\r
870 @return BOOLEAN TRUE means this is the formating string specifier. CurrentPosition is\r
871 returned at the position of "s".\r
872 FALSE means this is not the formating string specifier.. CurrentPosition is\r
873 returned at the position of failed character.\r
874\r
875**/\r
876BOOLEAN\r
877CheckFormatingString (\r
878 IN CONST CHAR8 *FormatString,\r
879 IN OUT UINTN *CurrentPosition,\r
880 IN UINTN StrLength\r
881 )\r
882{\r
883 CHAR8 FormatStringParamater;\r
884\r
885 while (*(FormatString + *CurrentPosition) != 's') {\r
886 //\r
887 // Loop until reach character 's' if the formating string is\r
888 // compliant with "[flags][width][.precision][length]" format for\r
889 // the string specifier.\r
890 //\r
891 FormatStringParamater = *(FormatString + *CurrentPosition);\r
892 if ((FormatStringParamater != '-') &&\r
893 (FormatStringParamater != '+') &&\r
894 (FormatStringParamater != '*') &&\r
895 (FormatStringParamater != '.') &&\r
896 !(((UINTN)FormatStringParamater >= (UINTN)'0') && ((UINTN)FormatStringParamater <= (UINTN)'9'))\r
897 )\r
898 {\r
899 return FALSE;\r
900 }\r
901\r
902 (*CurrentPosition)++;\r
903 if (*CurrentPosition >= StrLength) {\r
904 return FALSE;\r
905 }\r
906 }\r
907\r
908 return TRUE;\r
909}\r
910\r
911/**\r
912 This function clones *FormatString however replaces "%s" with "%a" in the\r
913 returned string.\r
914\r
915 @param[in] A Null-terminated ASCII format string.\r
916\r
917 @return The new format string. Caller has to free the memory of this string\r
918 using FreePool().\r
919\r
920**/\r
921CHAR8 *\r
922ReplaceUnicodeToAsciiStrFormat (\r
923 IN CONST CHAR8 *FormatString\r
924 )\r
925{\r
926 UINTN FormatStrSize;\r
927 UINTN FormatStrIndex;\r
928 UINTN FormatStrSpecifier;\r
929 BOOLEAN PercentageMark;\r
930 CHAR8 *TempFormatBuffer;\r
931 BOOLEAN IsFormatString;\r
932\r
933 //\r
934 // Error checking.\r
935 //\r
936 if (FormatString == NULL) {\r
937 return NULL;\r
938 }\r
939\r
940 FormatStrSize = AsciiStrSize (FormatString);\r
941 if (FormatStrSize == 0) {\r
942 return NULL;\r
943 }\r
944\r
945 TempFormatBuffer = AllocatePool (FormatStrSize); // Allocate memory for the\r
946 // new string.\r
947 if (TempFormatBuffer == NULL) {\r
948 return NULL;\r
949 }\r
950\r
951 //\r
952 // Clone *FormatString but replace "%s" wih "%a".\r
953 // "%%" is not considered as the format tag.\r
954 //\r
955 PercentageMark = FALSE;\r
956 FormatStrIndex = 0;\r
957 while (FormatStrIndex < FormatStrSize) {\r
958 if (PercentageMark == TRUE) {\r
959 //\r
960 // Previous character is "%".\r
961 //\r
962 PercentageMark = FALSE;\r
963 if (*(FormatString + FormatStrIndex) != '%') {\r
964 // Check if this is double "%".\r
965 FormatStrSpecifier = FormatStrIndex;\r
966 //\r
967 // Check if this is the formating string specifier.\r
968 //\r
969 IsFormatString = CheckFormatingString (FormatString, &FormatStrSpecifier, FormatStrSize);\r
970 if ((FormatStrSpecifier - FormatStrIndex) != 0) {\r
971 CopyMem (\r
972 (VOID *)(TempFormatBuffer + FormatStrIndex),\r
973 (VOID *)(FormatString + FormatStrIndex),\r
974 FormatStrSpecifier - FormatStrIndex\r
975 );\r
976 }\r
977\r
978 FormatStrIndex = FormatStrSpecifier;\r
979 if (IsFormatString == TRUE) {\r
980 //\r
981 // Replace 's' with 'a' which is printed in ASCII\r
982 // format on edk2 environment.\r
983 //\r
984 *(TempFormatBuffer + FormatStrSpecifier) = 'a';\r
985 FormatStrIndex++;\r
986 }\r
987\r
988 continue;\r
989 }\r
990\r
991 goto ContinueCheck;\r
992 }\r
993\r
994 if (*(FormatString + FormatStrIndex) == '%') {\r
995 //\r
996 // This character is "%", set the flag.\r
997 //\r
998 PercentageMark = TRUE;\r
999 }\r
1000\r
1001ContinueCheck:\r
1002 //\r
1003 // Clone character to the new string and advance FormatStrIndex\r
1004 // to process next character.\r
1005 //\r
1006 *(TempFormatBuffer + FormatStrIndex) = *(FormatString + FormatStrIndex);\r
1007 FormatStrIndex++;\r
1008 }\r
1009\r
1010 return TempFormatBuffer;\r
1011}\r
1012\r
1013/**\r
1014 This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to\r
1015 "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2\r
1016 environment however "%s" is ascii code base on vsnprintf().\r
1017 See definitions of AsciiVSPrint() for the details.\r
1018\r
1019 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated\r
1020 ASCII string.\r
1021 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.\r
1022 @param FormatString A Null-terminated ASCII format string.\r
1023 @param Marker VA_LIST marker for the variable argument list.\r
1024\r
1025 @return The number of ASCII characters in the produced output buffer not including the\r
1026 Null-terminator.\r
1027\r
1028**/\r
1029UINTN\r
1030EFIAPI\r
1031RedfishAsciiVSPrint (\r
1032 OUT CHAR8 *StartOfBuffer,\r
1033 IN UINTN BufferSize,\r
1034 IN CONST CHAR8 *FormatString,\r
1035 IN VA_LIST Marker\r
1036 )\r
1037{\r
1038 CHAR8 *TempFormatBuffer;\r
1039 UINTN LenStrProduced;\r
1040\r
1041 //\r
1042 // Looking for "%s" in the format string and replace it\r
1043 // with "%a" for printing ASCII code characters on edk2\r
1044 // environment.\r
1045 //\r
1046 TempFormatBuffer = ReplaceUnicodeToAsciiStrFormat (FormatString);\r
1047 if (TempFormatBuffer == NULL) {\r
1048 return 0;\r
1049 }\r
1050\r
1051 LenStrProduced = AsciiVSPrint (StartOfBuffer, BufferSize, (CONST CHAR8 *)TempFormatBuffer, Marker);\r
1052 FreePool (TempFormatBuffer);\r
1053 return LenStrProduced;\r
1054}\r
1055\r
1056/**\r
1057 This is the Redfish version of CRT snprintf function, this function replaces "%s" to\r
1058 "%a" before invoking AsciiSPrint(). That is because "%s" is unicode base on edk2\r
1059 environment however "%s" is ascii code base on snprintf().\r
1060 See definitions of AsciiSPrint() for the details.\r
1061\r
1062 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated\r
1063 ASCII string.\r
1064 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.\r
1065 @param FormatString A Null-terminated ASCII format string.\r
1066 @param ... Variable argument list whose contents are accessed based on the\r
1067 format string specified by FormatString.\r
1068\r
1069 @return The number of ASCII characters in the produced output buffer not including the\r
1070 Null-terminator.\r
1071\r
1072**/\r
1073UINTN\r
1074EFIAPI\r
1075RedfishAsciiSPrint (\r
1076 OUT CHAR8 *StartOfBuffer,\r
1077 IN UINTN BufferSize,\r
1078 IN CONST CHAR8 *FormatString,\r
1079 ...\r
1080 )\r
1081{\r
1082 VA_LIST Marker;\r
1083 UINTN LenStrProduced;\r
1084\r
1085 VA_START (Marker, FormatString);\r
1086 LenStrProduced = RedfishAsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);\r
1087 return LenStrProduced;\r
1088}\r