]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/BaseLib/String.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdePkg / Library / BaseLib / String.c
... / ...
CommitLineData
1/** @file\r
2 Unicode and ASCII string primitives.\r
3\r
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "BaseLibInternals.h"\r
10\r
11/**\r
12 Returns the length of a Null-terminated Unicode string.\r
13\r
14 This function returns the number of Unicode characters in the Null-terminated\r
15 Unicode string specified by String.\r
16\r
17 If String is NULL, then ASSERT().\r
18 If String is not aligned on a 16-bit boundary, then ASSERT().\r
19 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
20 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
21 Null-terminator, then ASSERT().\r
22\r
23 @param String A pointer to a Null-terminated Unicode string.\r
24\r
25 @return The length of String.\r
26\r
27**/\r
28UINTN\r
29EFIAPI\r
30StrLen (\r
31 IN CONST CHAR16 *String\r
32 )\r
33{\r
34 UINTN Length;\r
35\r
36 ASSERT (String != NULL);\r
37 ASSERT (((UINTN)String & BIT0) == 0);\r
38\r
39 for (Length = 0; *String != L'\0'; String++, Length++) {\r
40 //\r
41 // If PcdMaximumUnicodeStringLength is not zero,\r
42 // length should not more than PcdMaximumUnicodeStringLength\r
43 //\r
44 if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {\r
45 ASSERT (Length < PcdGet32 (PcdMaximumUnicodeStringLength));\r
46 }\r
47 }\r
48\r
49 return Length;\r
50}\r
51\r
52/**\r
53 Returns the size of a Null-terminated Unicode string in bytes, including the\r
54 Null terminator.\r
55\r
56 This function returns the size, in bytes, of the Null-terminated Unicode string\r
57 specified by String.\r
58\r
59 If String is NULL, then ASSERT().\r
60 If String is not aligned on a 16-bit boundary, then ASSERT().\r
61 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
62 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
63 Null-terminator, then ASSERT().\r
64\r
65 @param String A pointer to a Null-terminated Unicode string.\r
66\r
67 @return The size of String.\r
68\r
69**/\r
70UINTN\r
71EFIAPI\r
72StrSize (\r
73 IN CONST CHAR16 *String\r
74 )\r
75{\r
76 return (StrLen (String) + 1) * sizeof (*String);\r
77}\r
78\r
79/**\r
80 Compares two Null-terminated Unicode strings, and returns the difference\r
81 between the first mismatched Unicode characters.\r
82\r
83 This function compares the Null-terminated Unicode string FirstString to the\r
84 Null-terminated Unicode string SecondString. If FirstString is identical to\r
85 SecondString, then 0 is returned. Otherwise, the value returned is the first\r
86 mismatched Unicode character in SecondString subtracted from the first\r
87 mismatched Unicode character in FirstString.\r
88\r
89 If FirstString is NULL, then ASSERT().\r
90 If FirstString is not aligned on a 16-bit boundary, then ASSERT().\r
91 If SecondString is NULL, then ASSERT().\r
92 If SecondString is not aligned on a 16-bit boundary, then ASSERT().\r
93 If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more\r
94 than PcdMaximumUnicodeStringLength Unicode characters, not including the\r
95 Null-terminator, then ASSERT().\r
96 If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more\r
97 than PcdMaximumUnicodeStringLength Unicode characters, not including the\r
98 Null-terminator, then ASSERT().\r
99\r
100 @param FirstString A pointer to a Null-terminated Unicode string.\r
101 @param SecondString A pointer to a Null-terminated Unicode string.\r
102\r
103 @retval 0 FirstString is identical to SecondString.\r
104 @return others FirstString is not identical to SecondString.\r
105\r
106**/\r
107INTN\r
108EFIAPI\r
109StrCmp (\r
110 IN CONST CHAR16 *FirstString,\r
111 IN CONST CHAR16 *SecondString\r
112 )\r
113{\r
114 //\r
115 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength\r
116 //\r
117 ASSERT (StrSize (FirstString) != 0);\r
118 ASSERT (StrSize (SecondString) != 0);\r
119\r
120 while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {\r
121 FirstString++;\r
122 SecondString++;\r
123 }\r
124\r
125 return *FirstString - *SecondString;\r
126}\r
127\r
128/**\r
129 Compares up to a specified length the contents of two Null-terminated Unicode strings,\r
130 and returns the difference between the first mismatched Unicode characters.\r
131\r
132 This function compares the Null-terminated Unicode string FirstString to the\r
133 Null-terminated Unicode string SecondString. At most, Length Unicode\r
134 characters will be compared. If Length is 0, then 0 is returned. If\r
135 FirstString is identical to SecondString, then 0 is returned. Otherwise, the\r
136 value returned is the first mismatched Unicode character in SecondString\r
137 subtracted from the first mismatched Unicode character in FirstString.\r
138\r
139 If Length > 0 and FirstString is NULL, then ASSERT().\r
140 If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().\r
141 If Length > 0 and SecondString is NULL, then ASSERT().\r
142 If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().\r
143 If PcdMaximumUnicodeStringLength is not zero, and Length is greater than\r
144 PcdMaximumUnicodeStringLength, then ASSERT().\r
145 If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than\r
146 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
147 then ASSERT().\r
148 If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than\r
149 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
150 then ASSERT().\r
151\r
152 @param FirstString A pointer to a Null-terminated Unicode string.\r
153 @param SecondString A pointer to a Null-terminated Unicode string.\r
154 @param Length The maximum number of Unicode characters to compare.\r
155\r
156 @retval 0 FirstString is identical to SecondString.\r
157 @return others FirstString is not identical to SecondString.\r
158\r
159**/\r
160INTN\r
161EFIAPI\r
162StrnCmp (\r
163 IN CONST CHAR16 *FirstString,\r
164 IN CONST CHAR16 *SecondString,\r
165 IN UINTN Length\r
166 )\r
167{\r
168 if (Length == 0) {\r
169 return 0;\r
170 }\r
171\r
172 //\r
173 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.\r
174 // Length tests are performed inside StrLen().\r
175 //\r
176 ASSERT (StrSize (FirstString) != 0);\r
177 ASSERT (StrSize (SecondString) != 0);\r
178\r
179 if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {\r
180 ASSERT (Length <= PcdGet32 (PcdMaximumUnicodeStringLength));\r
181 }\r
182\r
183 while ((*FirstString != L'\0') &&\r
184 (*SecondString != L'\0') &&\r
185 (*FirstString == *SecondString) &&\r
186 (Length > 1))\r
187 {\r
188 FirstString++;\r
189 SecondString++;\r
190 Length--;\r
191 }\r
192\r
193 return *FirstString - *SecondString;\r
194}\r
195\r
196/**\r
197 Returns the first occurrence of a Null-terminated Unicode sub-string\r
198 in a Null-terminated Unicode string.\r
199\r
200 This function scans the contents of the Null-terminated Unicode string\r
201 specified by String and returns the first occurrence of SearchString.\r
202 If SearchString is not found in String, then NULL is returned. If\r
203 the length of SearchString is zero, then String is\r
204 returned.\r
205\r
206 If String is NULL, then ASSERT().\r
207 If String is not aligned on a 16-bit boundary, then ASSERT().\r
208 If SearchString is NULL, then ASSERT().\r
209 If SearchString is not aligned on a 16-bit boundary, then ASSERT().\r
210\r
211 If PcdMaximumUnicodeStringLength is not zero, and SearchString\r
212 or String contains more than PcdMaximumUnicodeStringLength Unicode\r
213 characters, not including the Null-terminator, then ASSERT().\r
214\r
215 @param String A pointer to a Null-terminated Unicode string.\r
216 @param SearchString A pointer to a Null-terminated Unicode string to search for.\r
217\r
218 @retval NULL If the SearchString does not appear in String.\r
219 @return others If there is a match.\r
220\r
221**/\r
222CHAR16 *\r
223EFIAPI\r
224StrStr (\r
225 IN CONST CHAR16 *String,\r
226 IN CONST CHAR16 *SearchString\r
227 )\r
228{\r
229 CONST CHAR16 *FirstMatch;\r
230 CONST CHAR16 *SearchStringTmp;\r
231\r
232 //\r
233 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.\r
234 // Length tests are performed inside StrLen().\r
235 //\r
236 ASSERT (StrSize (String) != 0);\r
237 ASSERT (StrSize (SearchString) != 0);\r
238\r
239 if (*SearchString == L'\0') {\r
240 return (CHAR16 *)String;\r
241 }\r
242\r
243 while (*String != L'\0') {\r
244 SearchStringTmp = SearchString;\r
245 FirstMatch = String;\r
246\r
247 while ( (*String == *SearchStringTmp)\r
248 && (*String != L'\0'))\r
249 {\r
250 String++;\r
251 SearchStringTmp++;\r
252 }\r
253\r
254 if (*SearchStringTmp == L'\0') {\r
255 return (CHAR16 *)FirstMatch;\r
256 }\r
257\r
258 if (*String == L'\0') {\r
259 return NULL;\r
260 }\r
261\r
262 String = FirstMatch + 1;\r
263 }\r
264\r
265 return NULL;\r
266}\r
267\r
268/**\r
269 Check if a Unicode character is a decimal character.\r
270\r
271 This internal function checks if a Unicode character is a\r
272 decimal character. The valid decimal character is from\r
273 L'0' to L'9'.\r
274\r
275 @param Char The character to check against.\r
276\r
277 @retval TRUE If the Char is a decmial character.\r
278 @retval FALSE If the Char is not a decmial character.\r
279\r
280**/\r
281BOOLEAN\r
282EFIAPI\r
283InternalIsDecimalDigitCharacter (\r
284 IN CHAR16 Char\r
285 )\r
286{\r
287 return (BOOLEAN)(Char >= L'0' && Char <= L'9');\r
288}\r
289\r
290/**\r
291 Convert a Unicode character to upper case only if\r
292 it maps to a valid small-case ASCII character.\r
293\r
294 This internal function only deal with Unicode character\r
295 which maps to a valid small-case ASCII character, i.e.\r
296 L'a' to L'z'. For other Unicode character, the input character\r
297 is returned directly.\r
298\r
299 @param Char The character to convert.\r
300\r
301 @retval LowerCharacter If the Char is with range L'a' to L'z'.\r
302 @retval Unchanged Otherwise.\r
303\r
304**/\r
305CHAR16\r
306EFIAPI\r
307CharToUpper (\r
308 IN CHAR16 Char\r
309 )\r
310{\r
311 if ((Char >= L'a') && (Char <= L'z')) {\r
312 return (CHAR16)(Char - (L'a' - L'A'));\r
313 }\r
314\r
315 return Char;\r
316}\r
317\r
318/**\r
319 Convert a Unicode character to numerical value.\r
320\r
321 This internal function only deal with Unicode character\r
322 which maps to a valid hexadecimal ASII character, i.e.\r
323 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other\r
324 Unicode character, the value returned does not make sense.\r
325\r
326 @param Char The character to convert.\r
327\r
328 @return The numerical value converted.\r
329\r
330**/\r
331UINTN\r
332EFIAPI\r
333InternalHexCharToUintn (\r
334 IN CHAR16 Char\r
335 )\r
336{\r
337 if (InternalIsDecimalDigitCharacter (Char)) {\r
338 return Char - L'0';\r
339 }\r
340\r
341 return (10 + CharToUpper (Char) - L'A');\r
342}\r
343\r
344/**\r
345 Check if a Unicode character is a hexadecimal character.\r
346\r
347 This internal function checks if a Unicode character is a\r
348 decimal character. The valid hexadecimal character is\r
349 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
350\r
351\r
352 @param Char The character to check against.\r
353\r
354 @retval TRUE If the Char is a hexadecmial character.\r
355 @retval FALSE If the Char is not a hexadecmial character.\r
356\r
357**/\r
358BOOLEAN\r
359EFIAPI\r
360InternalIsHexaDecimalDigitCharacter (\r
361 IN CHAR16 Char\r
362 )\r
363{\r
364 return (BOOLEAN)(InternalIsDecimalDigitCharacter (Char) ||\r
365 (Char >= L'A' && Char <= L'F') ||\r
366 (Char >= L'a' && Char <= L'f'));\r
367}\r
368\r
369/**\r
370 Convert a Null-terminated Unicode decimal string to a value of\r
371 type UINTN.\r
372\r
373 This function returns a value of type UINTN by interpreting the contents\r
374 of the Unicode string specified by String as a decimal number. The format\r
375 of the input Unicode string String is:\r
376\r
377 [spaces] [decimal digits].\r
378\r
379 The valid decimal digit character is in the range [0-9]. The\r
380 function will ignore the pad space, which includes spaces or\r
381 tab characters, before [decimal digits]. The running zero in the\r
382 beginning of [decimal digits] will be ignored. Then, the function\r
383 stops at the first character that is a not a valid decimal character\r
384 or a Null-terminator, whichever one comes first.\r
385\r
386 If String is NULL, then ASSERT().\r
387 If String is not aligned in a 16-bit boundary, then ASSERT().\r
388 If String has only pad spaces, then 0 is returned.\r
389 If String has no pad spaces or valid decimal digits,\r
390 then 0 is returned.\r
391 If the number represented by String overflows according\r
392 to the range defined by UINTN, then MAX_UINTN is returned.\r
393\r
394 If PcdMaximumUnicodeStringLength is not zero, and String contains\r
395 more than PcdMaximumUnicodeStringLength Unicode characters, not including\r
396 the Null-terminator, then ASSERT().\r
397\r
398 @param String A pointer to a Null-terminated Unicode string.\r
399\r
400 @retval Value translated from String.\r
401\r
402**/\r
403UINTN\r
404EFIAPI\r
405StrDecimalToUintn (\r
406 IN CONST CHAR16 *String\r
407 )\r
408{\r
409 UINTN Result;\r
410\r
411 StrDecimalToUintnS (String, (CHAR16 **)NULL, &Result);\r
412 return Result;\r
413}\r
414\r
415/**\r
416 Convert a Null-terminated Unicode decimal string to a value of\r
417 type UINT64.\r
418\r
419 This function returns a value of type UINT64 by interpreting the contents\r
420 of the Unicode string specified by String as a decimal number. The format\r
421 of the input Unicode string String is:\r
422\r
423 [spaces] [decimal digits].\r
424\r
425 The valid decimal digit character is in the range [0-9]. The\r
426 function will ignore the pad space, which includes spaces or\r
427 tab characters, before [decimal digits]. The running zero in the\r
428 beginning of [decimal digits] will be ignored. Then, the function\r
429 stops at the first character that is a not a valid decimal character\r
430 or a Null-terminator, whichever one comes first.\r
431\r
432 If String is NULL, then ASSERT().\r
433 If String is not aligned in a 16-bit boundary, then ASSERT().\r
434 If String has only pad spaces, then 0 is returned.\r
435 If String has no pad spaces or valid decimal digits,\r
436 then 0 is returned.\r
437 If the number represented by String overflows according\r
438 to the range defined by UINT64, then MAX_UINT64 is returned.\r
439\r
440 If PcdMaximumUnicodeStringLength is not zero, and String contains\r
441 more than PcdMaximumUnicodeStringLength Unicode characters, not including\r
442 the Null-terminator, then ASSERT().\r
443\r
444 @param String A pointer to a Null-terminated Unicode string.\r
445\r
446 @retval Value translated from String.\r
447\r
448**/\r
449UINT64\r
450EFIAPI\r
451StrDecimalToUint64 (\r
452 IN CONST CHAR16 *String\r
453 )\r
454{\r
455 UINT64 Result;\r
456\r
457 StrDecimalToUint64S (String, (CHAR16 **)NULL, &Result);\r
458 return Result;\r
459}\r
460\r
461/**\r
462 Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN.\r
463\r
464 This function returns a value of type UINTN by interpreting the contents\r
465 of the Unicode string specified by String as a hexadecimal number.\r
466 The format of the input Unicode string String is:\r
467\r
468 [spaces][zeros][x][hexadecimal digits].\r
469\r
470 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
471 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
472 If "x" appears in the input string, it must be prefixed with at least one 0.\r
473 The function will ignore the pad space, which includes spaces or tab characters,\r
474 before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
475 [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
476 first valid hexadecimal digit. Then, the function stops at the first character that is\r
477 a not a valid hexadecimal character or NULL, whichever one comes first.\r
478\r
479 If String is NULL, then ASSERT().\r
480 If String is not aligned in a 16-bit boundary, then ASSERT().\r
481 If String has only pad spaces, then zero is returned.\r
482 If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
483 then zero is returned.\r
484 If the number represented by String overflows according to the range defined by\r
485 UINTN, then MAX_UINTN is returned.\r
486\r
487 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
488 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
489 then ASSERT().\r
490\r
491 @param String A pointer to a Null-terminated Unicode string.\r
492\r
493 @retval Value translated from String.\r
494\r
495**/\r
496UINTN\r
497EFIAPI\r
498StrHexToUintn (\r
499 IN CONST CHAR16 *String\r
500 )\r
501{\r
502 UINTN Result;\r
503\r
504 StrHexToUintnS (String, (CHAR16 **)NULL, &Result);\r
505 return Result;\r
506}\r
507\r
508/**\r
509 Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
510\r
511 This function returns a value of type UINT64 by interpreting the contents\r
512 of the Unicode string specified by String as a hexadecimal number.\r
513 The format of the input Unicode string String is\r
514\r
515 [spaces][zeros][x][hexadecimal digits].\r
516\r
517 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
518 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
519 If "x" appears in the input string, it must be prefixed with at least one 0.\r
520 The function will ignore the pad space, which includes spaces or tab characters,\r
521 before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
522 [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
523 first valid hexadecimal digit. Then, the function stops at the first character that is\r
524 a not a valid hexadecimal character or NULL, whichever one comes first.\r
525\r
526 If String is NULL, then ASSERT().\r
527 If String is not aligned in a 16-bit boundary, then ASSERT().\r
528 If String has only pad spaces, then zero is returned.\r
529 If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
530 then zero is returned.\r
531 If the number represented by String overflows according to the range defined by\r
532 UINT64, then MAX_UINT64 is returned.\r
533\r
534 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
535 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
536 then ASSERT().\r
537\r
538 @param String A pointer to a Null-terminated Unicode string.\r
539\r
540 @retval Value translated from String.\r
541\r
542**/\r
543UINT64\r
544EFIAPI\r
545StrHexToUint64 (\r
546 IN CONST CHAR16 *String\r
547 )\r
548{\r
549 UINT64 Result;\r
550\r
551 StrHexToUint64S (String, (CHAR16 **)NULL, &Result);\r
552 return Result;\r
553}\r
554\r
555/**\r
556 Check if a ASCII character is a decimal character.\r
557\r
558 This internal function checks if a Unicode character is a\r
559 decimal character. The valid decimal character is from\r
560 '0' to '9'.\r
561\r
562 @param Char The character to check against.\r
563\r
564 @retval TRUE If the Char is a decmial character.\r
565 @retval FALSE If the Char is not a decmial character.\r
566\r
567**/\r
568BOOLEAN\r
569EFIAPI\r
570InternalAsciiIsDecimalDigitCharacter (\r
571 IN CHAR8 Char\r
572 )\r
573{\r
574 return (BOOLEAN)(Char >= '0' && Char <= '9');\r
575}\r
576\r
577/**\r
578 Check if a ASCII character is a hexadecimal character.\r
579\r
580 This internal function checks if a ASCII character is a\r
581 decimal character. The valid hexadecimal character is\r
582 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
583\r
584\r
585 @param Char The character to check against.\r
586\r
587 @retval TRUE If the Char is a hexadecmial character.\r
588 @retval FALSE If the Char is not a hexadecmial character.\r
589\r
590**/\r
591BOOLEAN\r
592EFIAPI\r
593InternalAsciiIsHexaDecimalDigitCharacter (\r
594 IN CHAR8 Char\r
595 )\r
596{\r
597 return (BOOLEAN)(InternalAsciiIsDecimalDigitCharacter (Char) ||\r
598 (Char >= 'A' && Char <= 'F') ||\r
599 (Char >= 'a' && Char <= 'f'));\r
600}\r
601\r
602/**\r
603 Returns the length of a Null-terminated ASCII string.\r
604\r
605 This function returns the number of ASCII characters in the Null-terminated\r
606 ASCII string specified by String.\r
607\r
608 If Length > 0 and Destination is NULL, then ASSERT().\r
609 If Length > 0 and Source is NULL, then ASSERT().\r
610 If PcdMaximumAsciiStringLength is not zero and String contains more than\r
611 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
612 then ASSERT().\r
613\r
614 @param String A pointer to a Null-terminated ASCII string.\r
615\r
616 @return The length of String.\r
617\r
618**/\r
619UINTN\r
620EFIAPI\r
621AsciiStrLen (\r
622 IN CONST CHAR8 *String\r
623 )\r
624{\r
625 UINTN Length;\r
626\r
627 ASSERT (String != NULL);\r
628\r
629 for (Length = 0; *String != '\0'; String++, Length++) {\r
630 //\r
631 // If PcdMaximumUnicodeStringLength is not zero,\r
632 // length should not more than PcdMaximumUnicodeStringLength\r
633 //\r
634 if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) {\r
635 ASSERT (Length < PcdGet32 (PcdMaximumAsciiStringLength));\r
636 }\r
637 }\r
638\r
639 return Length;\r
640}\r
641\r
642/**\r
643 Returns the size of a Null-terminated ASCII string in bytes, including the\r
644 Null terminator.\r
645\r
646 This function returns the size, in bytes, of the Null-terminated ASCII string\r
647 specified by String.\r
648\r
649 If String is NULL, then ASSERT().\r
650 If PcdMaximumAsciiStringLength is not zero and String contains more than\r
651 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
652 then ASSERT().\r
653\r
654 @param String A pointer to a Null-terminated ASCII string.\r
655\r
656 @return The size of String.\r
657\r
658**/\r
659UINTN\r
660EFIAPI\r
661AsciiStrSize (\r
662 IN CONST CHAR8 *String\r
663 )\r
664{\r
665 return (AsciiStrLen (String) + 1) * sizeof (*String);\r
666}\r
667\r
668/**\r
669 Compares two Null-terminated ASCII strings, and returns the difference\r
670 between the first mismatched ASCII characters.\r
671\r
672 This function compares the Null-terminated ASCII string FirstString to the\r
673 Null-terminated ASCII string SecondString. If FirstString is identical to\r
674 SecondString, then 0 is returned. Otherwise, the value returned is the first\r
675 mismatched ASCII character in SecondString subtracted from the first\r
676 mismatched ASCII character in FirstString.\r
677\r
678 If FirstString is NULL, then ASSERT().\r
679 If SecondString is NULL, then ASSERT().\r
680 If PcdMaximumAsciiStringLength is not zero and FirstString contains more than\r
681 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
682 then ASSERT().\r
683 If PcdMaximumAsciiStringLength is not zero and SecondString contains more\r
684 than PcdMaximumAsciiStringLength ASCII characters, not including the\r
685 Null-terminator, then ASSERT().\r
686\r
687 @param FirstString A pointer to a Null-terminated ASCII string.\r
688 @param SecondString A pointer to a Null-terminated ASCII string.\r
689\r
690 @retval ==0 FirstString is identical to SecondString.\r
691 @retval !=0 FirstString is not identical to SecondString.\r
692\r
693**/\r
694INTN\r
695EFIAPI\r
696AsciiStrCmp (\r
697 IN CONST CHAR8 *FirstString,\r
698 IN CONST CHAR8 *SecondString\r
699 )\r
700{\r
701 //\r
702 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
703 //\r
704 ASSERT (AsciiStrSize (FirstString));\r
705 ASSERT (AsciiStrSize (SecondString));\r
706\r
707 while ((*FirstString != '\0') && (*FirstString == *SecondString)) {\r
708 FirstString++;\r
709 SecondString++;\r
710 }\r
711\r
712 return *FirstString - *SecondString;\r
713}\r
714\r
715/**\r
716 Converts a lowercase Ascii character to upper one.\r
717\r
718 If Chr is lowercase Ascii character, then converts it to upper one.\r
719\r
720 If Value >= 0xA0, then ASSERT().\r
721 If (Value & 0x0F) >= 0x0A, then ASSERT().\r
722\r
723 @param Chr one Ascii character\r
724\r
725 @return The uppercase value of Ascii character\r
726\r
727**/\r
728CHAR8\r
729EFIAPI\r
730AsciiCharToUpper (\r
731 IN CHAR8 Chr\r
732 )\r
733{\r
734 return (UINT8)((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr);\r
735}\r
736\r
737/**\r
738 Convert a ASCII character to numerical value.\r
739\r
740 This internal function only deal with Unicode character\r
741 which maps to a valid hexadecimal ASII character, i.e.\r
742 '0' to '9', 'a' to 'f' or 'A' to 'F'. For other\r
743 ASCII character, the value returned does not make sense.\r
744\r
745 @param Char The character to convert.\r
746\r
747 @return The numerical value converted.\r
748\r
749**/\r
750UINTN\r
751EFIAPI\r
752InternalAsciiHexCharToUintn (\r
753 IN CHAR8 Char\r
754 )\r
755{\r
756 if (InternalIsDecimalDigitCharacter (Char)) {\r
757 return Char - '0';\r
758 }\r
759\r
760 return (10 + AsciiCharToUpper (Char) - 'A');\r
761}\r
762\r
763/**\r
764 Performs a case insensitive comparison of two Null-terminated ASCII strings,\r
765 and returns the difference between the first mismatched ASCII characters.\r
766\r
767 This function performs a case insensitive comparison of the Null-terminated\r
768 ASCII string FirstString to the Null-terminated ASCII string SecondString. If\r
769 FirstString is identical to SecondString, then 0 is returned. Otherwise, the\r
770 value returned is the first mismatched lower case ASCII character in\r
771 SecondString subtracted from the first mismatched lower case ASCII character\r
772 in FirstString.\r
773\r
774 If FirstString is NULL, then ASSERT().\r
775 If SecondString is NULL, then ASSERT().\r
776 If PcdMaximumAsciiStringLength is not zero and FirstString contains more than\r
777 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
778 then ASSERT().\r
779 If PcdMaximumAsciiStringLength is not zero and SecondString contains more\r
780 than PcdMaximumAsciiStringLength ASCII characters, not including the\r
781 Null-terminator, then ASSERT().\r
782\r
783 @param FirstString A pointer to a Null-terminated ASCII string.\r
784 @param SecondString A pointer to a Null-terminated ASCII string.\r
785\r
786 @retval ==0 FirstString is identical to SecondString using case insensitive\r
787 comparisons.\r
788 @retval !=0 FirstString is not identical to SecondString using case\r
789 insensitive comparisons.\r
790\r
791**/\r
792INTN\r
793EFIAPI\r
794AsciiStriCmp (\r
795 IN CONST CHAR8 *FirstString,\r
796 IN CONST CHAR8 *SecondString\r
797 )\r
798{\r
799 CHAR8 UpperFirstString;\r
800 CHAR8 UpperSecondString;\r
801\r
802 //\r
803 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
804 //\r
805 ASSERT (AsciiStrSize (FirstString));\r
806 ASSERT (AsciiStrSize (SecondString));\r
807\r
808 UpperFirstString = AsciiCharToUpper (*FirstString);\r
809 UpperSecondString = AsciiCharToUpper (*SecondString);\r
810 while ((*FirstString != '\0') && (*SecondString != '\0') && (UpperFirstString == UpperSecondString)) {\r
811 FirstString++;\r
812 SecondString++;\r
813 UpperFirstString = AsciiCharToUpper (*FirstString);\r
814 UpperSecondString = AsciiCharToUpper (*SecondString);\r
815 }\r
816\r
817 return UpperFirstString - UpperSecondString;\r
818}\r
819\r
820/**\r
821 Compares two Null-terminated ASCII strings with maximum lengths, and returns\r
822 the difference between the first mismatched ASCII characters.\r
823\r
824 This function compares the Null-terminated ASCII string FirstString to the\r
825 Null-terminated ASCII string SecondString. At most, Length ASCII characters\r
826 will be compared. If Length is 0, then 0 is returned. If FirstString is\r
827 identical to SecondString, then 0 is returned. Otherwise, the value returned\r
828 is the first mismatched ASCII character in SecondString subtracted from the\r
829 first mismatched ASCII character in FirstString.\r
830\r
831 If Length > 0 and FirstString is NULL, then ASSERT().\r
832 If Length > 0 and SecondString is NULL, then ASSERT().\r
833 If PcdMaximumAsciiStringLength is not zero, and Length is greater than\r
834 PcdMaximumAsciiStringLength, then ASSERT().\r
835 If PcdMaximumAsciiStringLength is not zero, and FirstString contains more than\r
836 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
837 then ASSERT().\r
838 If PcdMaximumAsciiStringLength is not zero, and SecondString contains more than\r
839 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
840 then ASSERT().\r
841\r
842 @param FirstString A pointer to a Null-terminated ASCII string.\r
843 @param SecondString A pointer to a Null-terminated ASCII string.\r
844 @param Length The maximum number of ASCII characters for compare.\r
845\r
846 @retval ==0 FirstString is identical to SecondString.\r
847 @retval !=0 FirstString is not identical to SecondString.\r
848\r
849**/\r
850INTN\r
851EFIAPI\r
852AsciiStrnCmp (\r
853 IN CONST CHAR8 *FirstString,\r
854 IN CONST CHAR8 *SecondString,\r
855 IN UINTN Length\r
856 )\r
857{\r
858 if (Length == 0) {\r
859 return 0;\r
860 }\r
861\r
862 //\r
863 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
864 //\r
865 ASSERT (AsciiStrSize (FirstString));\r
866 ASSERT (AsciiStrSize (SecondString));\r
867\r
868 if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) {\r
869 ASSERT (Length <= PcdGet32 (PcdMaximumAsciiStringLength));\r
870 }\r
871\r
872 while ((*FirstString != '\0') &&\r
873 (*SecondString != '\0') &&\r
874 (*FirstString == *SecondString) &&\r
875 (Length > 1))\r
876 {\r
877 FirstString++;\r
878 SecondString++;\r
879 Length--;\r
880 }\r
881\r
882 return *FirstString - *SecondString;\r
883}\r
884\r
885/**\r
886 Returns the first occurrence of a Null-terminated ASCII sub-string\r
887 in a Null-terminated ASCII string.\r
888\r
889 This function scans the contents of the ASCII string specified by String\r
890 and returns the first occurrence of SearchString. If SearchString is not\r
891 found in String, then NULL is returned. If the length of SearchString is zero,\r
892 then String is returned.\r
893\r
894 If String is NULL, then ASSERT().\r
895 If SearchString is NULL, then ASSERT().\r
896\r
897 If PcdMaximumAsciiStringLength is not zero, and SearchString or\r
898 String contains more than PcdMaximumAsciiStringLength Unicode characters\r
899 not including the Null-terminator, then ASSERT().\r
900\r
901 @param String A pointer to a Null-terminated ASCII string.\r
902 @param SearchString A pointer to a Null-terminated ASCII string to search for.\r
903\r
904 @retval NULL If the SearchString does not appear in String.\r
905 @retval others If there is a match return the first occurrence of SearchingString.\r
906 If the length of SearchString is zero,return String.\r
907\r
908**/\r
909CHAR8 *\r
910EFIAPI\r
911AsciiStrStr (\r
912 IN CONST CHAR8 *String,\r
913 IN CONST CHAR8 *SearchString\r
914 )\r
915{\r
916 CONST CHAR8 *FirstMatch;\r
917 CONST CHAR8 *SearchStringTmp;\r
918\r
919 //\r
920 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
921 //\r
922 ASSERT (AsciiStrSize (String) != 0);\r
923 ASSERT (AsciiStrSize (SearchString) != 0);\r
924\r
925 if (*SearchString == '\0') {\r
926 return (CHAR8 *)String;\r
927 }\r
928\r
929 while (*String != '\0') {\r
930 SearchStringTmp = SearchString;\r
931 FirstMatch = String;\r
932\r
933 while ( (*String == *SearchStringTmp)\r
934 && (*String != '\0'))\r
935 {\r
936 String++;\r
937 SearchStringTmp++;\r
938 }\r
939\r
940 if (*SearchStringTmp == '\0') {\r
941 return (CHAR8 *)FirstMatch;\r
942 }\r
943\r
944 if (*String == '\0') {\r
945 return NULL;\r
946 }\r
947\r
948 String = FirstMatch + 1;\r
949 }\r
950\r
951 return NULL;\r
952}\r
953\r
954/**\r
955 Convert a Null-terminated ASCII decimal string to a value of type\r
956 UINTN.\r
957\r
958 This function returns a value of type UINTN by interpreting the contents\r
959 of the ASCII string String as a decimal number. The format of the input\r
960 ASCII string String is:\r
961\r
962 [spaces] [decimal digits].\r
963\r
964 The valid decimal digit character is in the range [0-9]. The function will\r
965 ignore the pad space, which includes spaces or tab characters, before the digits.\r
966 The running zero in the beginning of [decimal digits] will be ignored. Then, the\r
967 function stops at the first character that is a not a valid decimal character or\r
968 Null-terminator, whichever on comes first.\r
969\r
970 If String has only pad spaces, then 0 is returned.\r
971 If String has no pad spaces or valid decimal digits, then 0 is returned.\r
972 If the number represented by String overflows according to the range defined by\r
973 UINTN, then MAX_UINTN is returned.\r
974 If String is NULL, then ASSERT().\r
975 If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
976 PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,\r
977 then ASSERT().\r
978\r
979 @param String A pointer to a Null-terminated ASCII string.\r
980\r
981 @retval Value translated from String.\r
982\r
983**/\r
984UINTN\r
985EFIAPI\r
986AsciiStrDecimalToUintn (\r
987 IN CONST CHAR8 *String\r
988 )\r
989{\r
990 UINTN Result;\r
991\r
992 AsciiStrDecimalToUintnS (String, (CHAR8 **)NULL, &Result);\r
993 return Result;\r
994}\r
995\r
996/**\r
997 Convert a Null-terminated ASCII decimal string to a value of type\r
998 UINT64.\r
999\r
1000 This function returns a value of type UINT64 by interpreting the contents\r
1001 of the ASCII string String as a decimal number. The format of the input\r
1002 ASCII string String is:\r
1003\r
1004 [spaces] [decimal digits].\r
1005\r
1006 The valid decimal digit character is in the range [0-9]. The function will\r
1007 ignore the pad space, which includes spaces or tab characters, before the digits.\r
1008 The running zero in the beginning of [decimal digits] will be ignored. Then, the\r
1009 function stops at the first character that is a not a valid decimal character or\r
1010 Null-terminator, whichever on comes first.\r
1011\r
1012 If String has only pad spaces, then 0 is returned.\r
1013 If String has no pad spaces or valid decimal digits, then 0 is returned.\r
1014 If the number represented by String overflows according to the range defined by\r
1015 UINT64, then MAX_UINT64 is returned.\r
1016 If String is NULL, then ASSERT().\r
1017 If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
1018 PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,\r
1019 then ASSERT().\r
1020\r
1021 @param String A pointer to a Null-terminated ASCII string.\r
1022\r
1023 @retval Value translated from String.\r
1024\r
1025**/\r
1026UINT64\r
1027EFIAPI\r
1028AsciiStrDecimalToUint64 (\r
1029 IN CONST CHAR8 *String\r
1030 )\r
1031{\r
1032 UINT64 Result;\r
1033\r
1034 AsciiStrDecimalToUint64S (String, (CHAR8 **)NULL, &Result);\r
1035 return Result;\r
1036}\r
1037\r
1038/**\r
1039 Convert a Null-terminated ASCII hexadecimal string to a value of type UINTN.\r
1040\r
1041 This function returns a value of type UINTN by interpreting the contents of\r
1042 the ASCII string String as a hexadecimal number. The format of the input ASCII\r
1043 string String is:\r
1044\r
1045 [spaces][zeros][x][hexadecimal digits].\r
1046\r
1047 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
1048 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x"\r
1049 appears in the input string, it must be prefixed with at least one 0. The function\r
1050 will ignore the pad space, which includes spaces or tab characters, before [zeros],\r
1051 [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits]\r
1052 will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal\r
1053 digit. Then, the function stops at the first character that is a not a valid\r
1054 hexadecimal character or Null-terminator, whichever on comes first.\r
1055\r
1056 If String has only pad spaces, then 0 is returned.\r
1057 If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then\r
1058 0 is returned.\r
1059\r
1060 If the number represented by String overflows according to the range defined by UINTN,\r
1061 then MAX_UINTN is returned.\r
1062 If String is NULL, then ASSERT().\r
1063 If PcdMaximumAsciiStringLength is not zero,\r
1064 and String contains more than PcdMaximumAsciiStringLength ASCII characters not including\r
1065 the Null-terminator, then ASSERT().\r
1066\r
1067 @param String A pointer to a Null-terminated ASCII string.\r
1068\r
1069 @retval Value translated from String.\r
1070\r
1071**/\r
1072UINTN\r
1073EFIAPI\r
1074AsciiStrHexToUintn (\r
1075 IN CONST CHAR8 *String\r
1076 )\r
1077{\r
1078 UINTN Result;\r
1079\r
1080 AsciiStrHexToUintnS (String, (CHAR8 **)NULL, &Result);\r
1081 return Result;\r
1082}\r
1083\r
1084/**\r
1085 Convert a Null-terminated ASCII hexadecimal string to a value of type UINT64.\r
1086\r
1087 This function returns a value of type UINT64 by interpreting the contents of\r
1088 the ASCII string String as a hexadecimal number. The format of the input ASCII\r
1089 string String is:\r
1090\r
1091 [spaces][zeros][x][hexadecimal digits].\r
1092\r
1093 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
1094 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x"\r
1095 appears in the input string, it must be prefixed with at least one 0. The function\r
1096 will ignore the pad space, which includes spaces or tab characters, before [zeros],\r
1097 [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits]\r
1098 will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal\r
1099 digit. Then, the function stops at the first character that is a not a valid\r
1100 hexadecimal character or Null-terminator, whichever on comes first.\r
1101\r
1102 If String has only pad spaces, then 0 is returned.\r
1103 If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then\r
1104 0 is returned.\r
1105\r
1106 If the number represented by String overflows according to the range defined by UINT64,\r
1107 then MAX_UINT64 is returned.\r
1108 If String is NULL, then ASSERT().\r
1109 If PcdMaximumAsciiStringLength is not zero,\r
1110 and String contains more than PcdMaximumAsciiStringLength ASCII characters not including\r
1111 the Null-terminator, then ASSERT().\r
1112\r
1113 @param String A pointer to a Null-terminated ASCII string.\r
1114\r
1115 @retval Value translated from String.\r
1116\r
1117**/\r
1118UINT64\r
1119EFIAPI\r
1120AsciiStrHexToUint64 (\r
1121 IN CONST CHAR8 *String\r
1122 )\r
1123{\r
1124 UINT64 Result;\r
1125\r
1126 AsciiStrHexToUint64S (String, (CHAR8 **)NULL, &Result);\r
1127 return Result;\r
1128}\r
1129\r
1130STATIC CHAR8 EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\r
1131 "abcdefghijklmnopqrstuvwxyz"\r
1132 "0123456789+/";\r
1133\r
1134/**\r
1135 Convert binary data to a Base64 encoded ascii string based on RFC4648.\r
1136\r
1137 Produce a Null-terminated Ascii string in the output buffer specified by Destination and DestinationSize.\r
1138 The Ascii string is produced by converting the data string specified by Source and SourceLength.\r
1139\r
1140 @param Source Input UINT8 data\r
1141 @param SourceLength Number of UINT8 bytes of data\r
1142 @param Destination Pointer to output string buffer\r
1143 @param DestinationSize Size of ascii buffer. Set to 0 to get the size needed.\r
1144 Caller is responsible for passing in buffer of DestinationSize\r
1145\r
1146 @retval RETURN_SUCCESS When ascii buffer is filled in.\r
1147 @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize is NULL.\r
1148 @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is bigger than (MAX_ADDRESS - (UINTN)Destination).\r
1149 @retval RETURN_BUFFER_TOO_SMALL If SourceLength is 0 and DestinationSize is <1.\r
1150 @retval RETURN_BUFFER_TOO_SMALL If Destination is NULL or DestinationSize is smaller than required buffersize.\r
1151\r
1152**/\r
1153RETURN_STATUS\r
1154EFIAPI\r
1155Base64Encode (\r
1156 IN CONST UINT8 *Source,\r
1157 IN UINTN SourceLength,\r
1158 OUT CHAR8 *Destination OPTIONAL,\r
1159 IN OUT UINTN *DestinationSize\r
1160 )\r
1161{\r
1162 UINTN RequiredSize;\r
1163 UINTN Left;\r
1164\r
1165 //\r
1166 // Check pointers, and SourceLength is valid\r
1167 //\r
1168 if ((Source == NULL) || (DestinationSize == NULL)) {\r
1169 return RETURN_INVALID_PARAMETER;\r
1170 }\r
1171\r
1172 //\r
1173 // Allow for RFC 4648 test vector 1\r
1174 //\r
1175 if (SourceLength == 0) {\r
1176 if (*DestinationSize < 1) {\r
1177 *DestinationSize = 1;\r
1178 return RETURN_BUFFER_TOO_SMALL;\r
1179 }\r
1180\r
1181 *DestinationSize = 1;\r
1182 *Destination = '\0';\r
1183 return RETURN_SUCCESS;\r
1184 }\r
1185\r
1186 //\r
1187 // Check if SourceLength or DestinationSize is valid\r
1188 //\r
1189 if ((SourceLength >= (MAX_ADDRESS - (UINTN)Source)) || (*DestinationSize >= (MAX_ADDRESS - (UINTN)Destination))) {\r
1190 return RETURN_INVALID_PARAMETER;\r
1191 }\r
1192\r
1193 //\r
1194 // 4 ascii per 3 bytes + NULL\r
1195 //\r
1196 RequiredSize = ((SourceLength + 2) / 3) * 4 + 1;\r
1197 if ((Destination == NULL) || (*DestinationSize < RequiredSize)) {\r
1198 *DestinationSize = RequiredSize;\r
1199 return RETURN_BUFFER_TOO_SMALL;\r
1200 }\r
1201\r
1202 Left = SourceLength;\r
1203\r
1204 //\r
1205 // Encode 24 bits (three bytes) into 4 ascii characters\r
1206 //\r
1207 while (Left >= 3) {\r
1208 *Destination++ = EncodingTable[(Source[0] & 0xfc) >> 2];\r
1209 *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)];\r
1210 *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2) + ((Source[2] & 0xc0) >> 6)];\r
1211 *Destination++ = EncodingTable[(Source[2] & 0x3f)];\r
1212 Left -= 3;\r
1213 Source += 3;\r
1214 }\r
1215\r
1216 //\r
1217 // Handle the remainder, and add padding '=' characters as necessary.\r
1218 //\r
1219 switch (Left) {\r
1220 case 0:\r
1221\r
1222 //\r
1223 // No bytes Left, done.\r
1224 //\r
1225 break;\r
1226 case 1:\r
1227\r
1228 //\r
1229 // One more data byte, two pad characters\r
1230 //\r
1231 *Destination++ = EncodingTable[(Source[0] & 0xfc) >> 2];\r
1232 *Destination++ = EncodingTable[((Source[0] & 0x03) << 4)];\r
1233 *Destination++ = '=';\r
1234 *Destination++ = '=';\r
1235 break;\r
1236 case 2:\r
1237\r
1238 //\r
1239 // Two more data bytes, and one pad character\r
1240 //\r
1241 *Destination++ = EncodingTable[(Source[0] & 0xfc) >> 2];\r
1242 *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)];\r
1243 *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2)];\r
1244 *Destination++ = '=';\r
1245 break;\r
1246 }\r
1247\r
1248 //\r
1249 // Add terminating NULL\r
1250 //\r
1251 *Destination = '\0';\r
1252 return RETURN_SUCCESS;\r
1253}\r
1254\r
1255/**\r
1256 Decode Base64 ASCII encoded data to 8-bit binary representation, based on\r
1257 RFC4648.\r
1258\r
1259 Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648.\r
1260\r
1261 Whitespace is ignored at all positions:\r
1262 - 0x09 ('\t') horizontal tab\r
1263 - 0x0A ('\n') new line\r
1264 - 0x0B ('\v') vertical tab\r
1265 - 0x0C ('\f') form feed\r
1266 - 0x0D ('\r') carriage return\r
1267 - 0x20 (' ') space\r
1268\r
1269 The minimum amount of required padding (with ASCII 0x3D, '=') is tolerated\r
1270 and enforced at the end of the Base64 ASCII encoded data, and only there.\r
1271\r
1272 Other characters outside of the encoding alphabet cause the function to\r
1273 reject the Base64 ASCII encoded data.\r
1274\r
1275 @param[in] Source Array of CHAR8 elements containing the Base64\r
1276 ASCII encoding. May be NULL if SourceSize is\r
1277 zero.\r
1278\r
1279 @param[in] SourceSize Number of CHAR8 elements in Source.\r
1280\r
1281 @param[out] Destination Array of UINT8 elements receiving the decoded\r
1282 8-bit binary representation. Allocated by the\r
1283 caller. May be NULL if DestinationSize is\r
1284 zero on input. If NULL, decoding is\r
1285 performed, but the 8-bit binary\r
1286 representation is not stored. If non-NULL and\r
1287 the function returns an error, the contents\r
1288 of Destination are indeterminate.\r
1289\r
1290 @param[in,out] DestinationSize On input, the number of UINT8 elements that\r
1291 the caller allocated for Destination. On\r
1292 output, if the function returns\r
1293 RETURN_SUCCESS or RETURN_BUFFER_TOO_SMALL,\r
1294 the number of UINT8 elements that are\r
1295 required for decoding the Base64 ASCII\r
1296 representation. If the function returns a\r
1297 value different from both RETURN_SUCCESS and\r
1298 RETURN_BUFFER_TOO_SMALL, then DestinationSize\r
1299 is indeterminate on output.\r
1300\r
1301 @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source have\r
1302 been decoded to on-output DestinationSize\r
1303 UINT8 elements at Destination. Note that\r
1304 RETURN_SUCCESS covers the case when\r
1305 DestinationSize is zero on input, and\r
1306 Source decodes to zero bytes (due to\r
1307 containing at most ignored whitespace).\r
1308\r
1309 @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is not\r
1310 large enough for decoding SourceSize CHAR8\r
1311 elements at Source. The required number of\r
1312 UINT8 elements has been stored to\r
1313 DestinationSize.\r
1314\r
1315 @retval RETURN_INVALID_PARAMETER DestinationSize is NULL.\r
1316\r
1317 @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not zero.\r
1318\r
1319 @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSize is\r
1320 not zero on input.\r
1321\r
1322 @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source +\r
1323 SourceSize) would wrap around MAX_ADDRESS.\r
1324\r
1325 @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destination +\r
1326 DestinationSize) would wrap around\r
1327 MAX_ADDRESS, as specified on input.\r
1328\r
1329 @retval RETURN_INVALID_PARAMETER None of Source and Destination are NULL,\r
1330 and CHAR8[SourceSize] at Source overlaps\r
1331 UINT8[DestinationSize] at Destination, as\r
1332 specified on input.\r
1333\r
1334 @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in\r
1335 Source.\r
1336**/\r
1337RETURN_STATUS\r
1338EFIAPI\r
1339Base64Decode (\r
1340 IN CONST CHAR8 *Source OPTIONAL,\r
1341 IN UINTN SourceSize,\r
1342 OUT UINT8 *Destination OPTIONAL,\r
1343 IN OUT UINTN *DestinationSize\r
1344 )\r
1345{\r
1346 BOOLEAN PaddingMode;\r
1347 UINTN SixBitGroupsConsumed;\r
1348 UINT32 Accumulator;\r
1349 UINTN OriginalDestinationSize;\r
1350 UINTN SourceIndex;\r
1351 CHAR8 SourceChar;\r
1352 UINT32 Base64Value;\r
1353 UINT8 DestinationOctet;\r
1354\r
1355 if (DestinationSize == NULL) {\r
1356 return RETURN_INVALID_PARAMETER;\r
1357 }\r
1358\r
1359 //\r
1360 // Check Source array validity.\r
1361 //\r
1362 if (Source == NULL) {\r
1363 if (SourceSize > 0) {\r
1364 //\r
1365 // At least one CHAR8 element at NULL Source.\r
1366 //\r
1367 return RETURN_INVALID_PARAMETER;\r
1368 }\r
1369 } else if (SourceSize > MAX_ADDRESS - (UINTN)Source) {\r
1370 //\r
1371 // Non-NULL Source, but it wraps around.\r
1372 //\r
1373 return RETURN_INVALID_PARAMETER;\r
1374 }\r
1375\r
1376 //\r
1377 // Check Destination array validity.\r
1378 //\r
1379 if (Destination == NULL) {\r
1380 if (*DestinationSize > 0) {\r
1381 //\r
1382 // At least one UINT8 element at NULL Destination.\r
1383 //\r
1384 return RETURN_INVALID_PARAMETER;\r
1385 }\r
1386 } else if (*DestinationSize > MAX_ADDRESS - (UINTN)Destination) {\r
1387 //\r
1388 // Non-NULL Destination, but it wraps around.\r
1389 //\r
1390 return RETURN_INVALID_PARAMETER;\r
1391 }\r
1392\r
1393 //\r
1394 // Check for overlap.\r
1395 //\r
1396 if ((Source != NULL) && (Destination != NULL)) {\r
1397 //\r
1398 // Both arrays have been provided, and we know from earlier that each array\r
1399 // is valid in itself.\r
1400 //\r
1401 if ((UINTN)Source + SourceSize <= (UINTN)Destination) {\r
1402 //\r
1403 // Source array precedes Destination array, OK.\r
1404 //\r
1405 } else if ((UINTN)Destination + *DestinationSize <= (UINTN)Source) {\r
1406 //\r
1407 // Destination array precedes Source array, OK.\r
1408 //\r
1409 } else {\r
1410 //\r
1411 // Overlap.\r
1412 //\r
1413 return RETURN_INVALID_PARAMETER;\r
1414 }\r
1415 }\r
1416\r
1417 //\r
1418 // Decoding loop setup.\r
1419 //\r
1420 PaddingMode = FALSE;\r
1421 SixBitGroupsConsumed = 0;\r
1422 Accumulator = 0;\r
1423 OriginalDestinationSize = *DestinationSize;\r
1424 *DestinationSize = 0;\r
1425\r
1426 //\r
1427 // Decoding loop.\r
1428 //\r
1429 for (SourceIndex = 0; SourceIndex < SourceSize; SourceIndex++) {\r
1430 SourceChar = Source[SourceIndex];\r
1431\r
1432 //\r
1433 // Whitespace is ignored at all positions (regardless of padding mode).\r
1434 //\r
1435 if ((SourceChar == '\t') || (SourceChar == '\n') || (SourceChar == '\v') ||\r
1436 (SourceChar == '\f') || (SourceChar == '\r') || (SourceChar == ' '))\r
1437 {\r
1438 continue;\r
1439 }\r
1440\r
1441 //\r
1442 // If we're in padding mode, accept another padding character, as long as\r
1443 // that padding character completes the quantum. This completes case (2)\r
1444 // from RFC4648, Chapter 4. "Base 64 Encoding":\r
1445 //\r
1446 // (2) The final quantum of encoding input is exactly 8 bits; here, the\r
1447 // final unit of encoded output will be two characters followed by two\r
1448 // "=" padding characters.\r
1449 //\r
1450 if (PaddingMode) {\r
1451 if ((SourceChar == '=') && (SixBitGroupsConsumed == 3)) {\r
1452 SixBitGroupsConsumed = 0;\r
1453 continue;\r
1454 }\r
1455\r
1456 return RETURN_INVALID_PARAMETER;\r
1457 }\r
1458\r
1459 //\r
1460 // When not in padding mode, decode Base64Value based on RFC4648, "Table 1:\r
1461 // The Base 64 Alphabet".\r
1462 //\r
1463 if (('A' <= SourceChar) && (SourceChar <= 'Z')) {\r
1464 Base64Value = SourceChar - 'A';\r
1465 } else if (('a' <= SourceChar) && (SourceChar <= 'z')) {\r
1466 Base64Value = 26 + (SourceChar - 'a');\r
1467 } else if (('0' <= SourceChar) && (SourceChar <= '9')) {\r
1468 Base64Value = 52 + (SourceChar - '0');\r
1469 } else if (SourceChar == '+') {\r
1470 Base64Value = 62;\r
1471 } else if (SourceChar == '/') {\r
1472 Base64Value = 63;\r
1473 } else if (SourceChar == '=') {\r
1474 //\r
1475 // Enter padding mode.\r
1476 //\r
1477 PaddingMode = TRUE;\r
1478\r
1479 if (SixBitGroupsConsumed == 2) {\r
1480 //\r
1481 // If we have consumed two 6-bit groups from the current quantum before\r
1482 // encountering the first padding character, then this is case (2) from\r
1483 // RFC4648, Chapter 4. "Base 64 Encoding". Bump SixBitGroupsConsumed,\r
1484 // and we'll enforce another padding character.\r
1485 //\r
1486 SixBitGroupsConsumed = 3;\r
1487 } else if (SixBitGroupsConsumed == 3) {\r
1488 //\r
1489 // If we have consumed three 6-bit groups from the current quantum\r
1490 // before encountering the first padding character, then this is case\r
1491 // (3) from RFC4648, Chapter 4. "Base 64 Encoding". The quantum is now\r
1492 // complete.\r
1493 //\r
1494 SixBitGroupsConsumed = 0;\r
1495 } else {\r
1496 //\r
1497 // Padding characters are not allowed at the first two positions of a\r
1498 // quantum.\r
1499 //\r
1500 return RETURN_INVALID_PARAMETER;\r
1501 }\r
1502\r
1503 //\r
1504 // Wherever in a quantum we enter padding mode, we enforce the padding\r
1505 // bits pending in the accumulator -- from the last 6-bit group just\r
1506 // preceding the padding character -- to be zero. Refer to RFC4648,\r
1507 // Chapter 3.5. "Canonical Encoding".\r
1508 //\r
1509 if (Accumulator != 0) {\r
1510 return RETURN_INVALID_PARAMETER;\r
1511 }\r
1512\r
1513 //\r
1514 // Advance to the next source character.\r
1515 //\r
1516 continue;\r
1517 } else {\r
1518 //\r
1519 // Other characters outside of the encoding alphabet are rejected.\r
1520 //\r
1521 return RETURN_INVALID_PARAMETER;\r
1522 }\r
1523\r
1524 //\r
1525 // Feed the bits of the current 6-bit group of the quantum to the\r
1526 // accumulator.\r
1527 //\r
1528 Accumulator = (Accumulator << 6) | Base64Value;\r
1529 SixBitGroupsConsumed++;\r
1530 switch (SixBitGroupsConsumed) {\r
1531 case 1:\r
1532 //\r
1533 // No octet to spill after consuming the first 6-bit group of the\r
1534 // quantum; advance to the next source character.\r
1535 //\r
1536 continue;\r
1537 case 2:\r
1538 //\r
1539 // 12 bits accumulated (6 pending + 6 new); prepare for spilling an\r
1540 // octet. 4 bits remain pending.\r
1541 //\r
1542 DestinationOctet = (UINT8)(Accumulator >> 4);\r
1543 Accumulator &= 0xF;\r
1544 break;\r
1545 case 3:\r
1546 //\r
1547 // 10 bits accumulated (4 pending + 6 new); prepare for spilling an\r
1548 // octet. 2 bits remain pending.\r
1549 //\r
1550 DestinationOctet = (UINT8)(Accumulator >> 2);\r
1551 Accumulator &= 0x3;\r
1552 break;\r
1553 default:\r
1554 ASSERT (SixBitGroupsConsumed == 4);\r
1555 //\r
1556 // 8 bits accumulated (2 pending + 6 new); prepare for spilling an octet.\r
1557 // The quantum is complete, 0 bits remain pending.\r
1558 //\r
1559 DestinationOctet = (UINT8)Accumulator;\r
1560 Accumulator = 0;\r
1561 SixBitGroupsConsumed = 0;\r
1562 break;\r
1563 }\r
1564\r
1565 //\r
1566 // Store the decoded octet if there's room left. Increment\r
1567 // (*DestinationSize) unconditionally.\r
1568 //\r
1569 if (*DestinationSize < OriginalDestinationSize) {\r
1570 ASSERT (Destination != NULL);\r
1571 Destination[*DestinationSize] = DestinationOctet;\r
1572 }\r
1573\r
1574 (*DestinationSize)++;\r
1575\r
1576 //\r
1577 // Advance to the next source character.\r
1578 //\r
1579 }\r
1580\r
1581 //\r
1582 // If Source terminates mid-quantum, then Source is invalid.\r
1583 //\r
1584 if (SixBitGroupsConsumed != 0) {\r
1585 return RETURN_INVALID_PARAMETER;\r
1586 }\r
1587\r
1588 //\r
1589 // Done.\r
1590 //\r
1591 if (*DestinationSize <= OriginalDestinationSize) {\r
1592 return RETURN_SUCCESS;\r
1593 }\r
1594\r
1595 return RETURN_BUFFER_TOO_SMALL;\r
1596}\r
1597\r
1598/**\r
1599 Converts an 8-bit value to an 8-bit BCD value.\r
1600\r
1601 Converts the 8-bit value specified by Value to BCD. The BCD value is\r
1602 returned.\r
1603\r
1604 If Value >= 100, then ASSERT().\r
1605\r
1606 @param Value The 8-bit value to convert to BCD. Range 0..99.\r
1607\r
1608 @return The BCD value.\r
1609\r
1610**/\r
1611UINT8\r
1612EFIAPI\r
1613DecimalToBcd8 (\r
1614 IN UINT8 Value\r
1615 )\r
1616{\r
1617 ASSERT (Value < 100);\r
1618 return (UINT8)(((Value / 10) << 4) | (Value % 10));\r
1619}\r
1620\r
1621/**\r
1622 Converts an 8-bit BCD value to an 8-bit value.\r
1623\r
1624 Converts the 8-bit BCD value specified by Value to an 8-bit value. The 8-bit\r
1625 value is returned.\r
1626\r
1627 If Value >= 0xA0, then ASSERT().\r
1628 If (Value & 0x0F) >= 0x0A, then ASSERT().\r
1629\r
1630 @param Value The 8-bit BCD value to convert to an 8-bit value.\r
1631\r
1632 @return The 8-bit value is returned.\r
1633\r
1634**/\r
1635UINT8\r
1636EFIAPI\r
1637BcdToDecimal8 (\r
1638 IN UINT8 Value\r
1639 )\r
1640{\r
1641 ASSERT (Value < 0xa0);\r
1642 ASSERT ((Value & 0xf) < 0xa);\r
1643 return (UINT8)((Value >> 4) * 10 + (Value & 0xf));\r
1644}\r