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