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