]>
Commit | Line | Data |
---|---|---|
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 | |
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 | |
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\r | |
28 | isalnum (\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 | |
45 | int\r | |
46 | isdchar (\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 | |
64 | int\r | |
65 | isspace (\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 | |
78 | void *\r | |
79 | malloc (\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 | |
89 | void\r | |
90 | free (\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 | |
108 | char *\r | |
109 | strdup (\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 | |
137 | int\r | |
138 | toupper (\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 | |
154 | int\r | |
155 | Digit2Val (\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 | |
178 | long long\r | |
179 | strtoll (\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 | |
330 | long\r | |
331 | strtol (\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 | |
438 | unsigned long long\r | |
439 | strtoull (\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 | |
545 | double\r | |
546 | strtod (\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 | |
556 | static 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 | |
564 | static\r | |
565 | void\r | |
566 | BuildBitmap (\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 | |
594 | char *\r | |
595 | strpbrk (\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 | |
629 | char *\r | |
630 | strerror (\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 | |
640 | void *\r | |
641 | calloc (\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 | |
668 | UINTN 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 | |
711 | time_t\r | |
712 | time (\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 | |
754 | void\r | |
755 | qsort (\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 | |
775 | int\r | |
776 | fgetc (\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 | |
789 | FILE *\r | |
790 | fopen (\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 | |
804 | size_t\r | |
805 | fread (\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 | |
821 | size_t\r | |
822 | fwrite (\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 | |
838 | int\r | |
839 | fclose (\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 | |
852 | int\r | |
853 | fprintf (\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 | |
876 | BOOLEAN\r | |
877 | CheckFormatingString (\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 | |
921 | CHAR8 *\r | |
922 | ReplaceUnicodeToAsciiStrFormat (\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 | |
1001 | ContinueCheck:\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 | |
1029 | UINTN\r | |
1030 | EFIAPI\r | |
1031 | RedfishAsciiVSPrint (\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 | |
1073 | UINTN\r | |
1074 | EFIAPI\r | |
1075 | RedfishAsciiSPrint (\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 |