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