]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/FCE/Common.c
Revert "BaseTools/FMMT: Add a tool FMMT"
[mirror_edk2.git] / BaseTools / Source / C / FCE / Common.c
CommitLineData
3c59d946
SZ
1/** @file\r
2\r
3 Common library.\r
4\r
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9#include "Common.h"\r
10\r
11#define WARNING_STATUS_NUMBER 4\r
12#define ERROR_STATUS_NUMBER 24\r
13\r
14CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
15\r
16CONST CHAR8 *mStatusString[] = {\r
17 "Success", // RETURN_SUCCESS = 0\r
18 "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1\r
19 "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2\r
20 "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3\r
21 "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4\r
22 "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT\r
23 "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT\r
24 "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT\r
25 "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT\r
26 "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT\r
27 "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT\r
28 "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT\r
29 "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT\r
30 "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT\r
31 "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT\r
32 "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT\r
33 "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT\r
34 "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT\r
35 "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT\r
36 "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT\r
37 "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT\r
38 "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT\r
39 "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT\r
40 "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT\r
41 "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT\r
42 "Aborted", // RETURN_ABORTED = 21 | MAX_BIT\r
43 "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT\r
44 "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT\r
45 "Protocol Error" // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT\r
46};\r
47\r
48/**\r
49 Copies one Null-terminated Unicode string to another Null-terminated Unicode\r
50 string and returns the new Unicode string.\r
51\r
52 This function copies the contents of the Unicode string Source to the Unicode\r
53 string Destination, and returns Destination. If Source and Destination\r
54 overlap, then the results are undefined.\r
55\r
56 If Destination is NULL, then return NULL.\r
57 If Destination is not aligned on a 16-bit boundary, then return NULL.\r
58\r
59 @param Destination A pointer to a Null-terminated Unicode string.\r
60 @param Source A pointer to a Null-terminated Unicode string.\r
61\r
62 @return Destination.\r
63\r
64**/\r
65CHAR16 *\r
66StrCpy (\r
67 OUT CHAR16 *Destination,\r
68 IN CONST CHAR16 *Source\r
69 )\r
70{\r
71 CHAR16 *ReturnValue;\r
72\r
73 ReturnValue = NULL;\r
74\r
75 if ((Destination == NULL) || ((UINTN) Destination % 2 != 0)) {\r
76 return NULL;\r
77 }\r
78\r
79 ReturnValue = Destination;\r
80 while (*Source != 0) {\r
81 *(Destination++) = *(Source++);\r
82 }\r
83 *Destination = 0;\r
84 return ReturnValue;\r
85}\r
86\r
87/**\r
88 Returns the length of a Null-terminated Unicode string.\r
89\r
90 This function returns the number of Unicode characters in the Null-terminated\r
91 Unicode string specified by String.\r
92\r
93 If String is NULL, then return 0.\r
94\r
95 @param String A pointer to a Null-terminated Unicode string.\r
96\r
97 @return The length of String.\r
98\r
99**/\r
100UINTN\r
101FceStrLen (\r
102 IN CONST CHAR16 *String\r
103 )\r
104{\r
105 UINTN Length;\r
106\r
107 if (String == NULL) {\r
108 return 0;\r
109 }\r
110 for (Length = 0; *String != L'\0'; String++, Length++) {\r
111 ;\r
112 }\r
113 return Length;\r
114}\r
115\r
116/**\r
117 Returns the size of a Null-terminated Unicode string in bytes, including the\r
118 Null terminator.\r
119\r
120 This function returns the size, in bytes, of the Null-terminated Unicode string\r
121 specified by String.\r
122\r
123 If String is NULL, then ASSERT().\r
124 If String is not aligned on a 16-bit boundary, then ASSERT().\r
125 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
126 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
127 Null-terminator, then ASSERT().\r
128\r
129 @param String A pointer to a Null-terminated Unicode string.\r
130\r
131 @return The size of String.\r
132\r
133**/\r
134UINTN\r
135FceStrSize (\r
136 IN CONST CHAR16 *String\r
137 )\r
138{\r
139 return (FceStrLen (String) + 1) * sizeof (*String);\r
140}\r
141\r
142/**\r
143 Compares two Null-terminated Unicode strings, and returns the difference\r
144 between the first mismatched Unicode characters.\r
145\r
146 This function compares the Null-terminated Unicode string FirstString to the\r
147 Null-terminated Unicode string SecondString. If FirstString is identical to\r
148 SecondString, then 0 is returned. Otherwise, the value returned is the first\r
149 mismatched Unicode character in SecondString subtracted from the first\r
150 mismatched Unicode character in FirstString.\r
151\r
152 @param FirstString A pointer to a Null-terminated Unicode string.\r
153 @param SecondString A pointer to a Null-terminated Unicode string.\r
154\r
155 @retval 0 FirstString is identical to SecondString.\r
156 @return others FirstString is not identical to SecondString.\r
157\r
158**/\r
159INTN\r
160FceStrCmp (\r
161 IN CONST CHAR16 *FirstString,\r
162 IN CONST CHAR16 *SecondString\r
163 )\r
164{\r
165 while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {\r
166 FirstString++;\r
167 SecondString++;\r
168 }\r
169 return *FirstString - *SecondString;\r
170}\r
171\r
172/**\r
173 Concatenates one Null-terminated Unicode string to another Null-terminated\r
174 Unicode string, and returns the concatenated Unicode string.\r
175\r
176 This function concatenates two Null-terminated Unicode strings. The contents\r
177 of Null-terminated Unicode string Source are concatenated to the end of\r
178 Null-terminated Unicode string Destination. The Null-terminated concatenated\r
179 Unicode String is returned. If Source and Destination overlap, then the\r
180 results are undefined.\r
181\r
182 If Destination is NULL, then ASSERT().\r
183 If Destination is not aligned on a 16-bit boundary, then ASSERT().\r
184 If Source is NULL, then ASSERT().\r
185 If Source is not aligned on a 16-bit boundary, then ASSERT().\r
186 If Source and Destination overlap, then ASSERT().\r
187 If PcdMaximumUnicodeStringLength is not zero, and Destination contains more\r
188 than PcdMaximumUnicodeStringLength Unicode characters, not including the\r
189 Null-terminator, then ASSERT().\r
190 If PcdMaximumUnicodeStringLength is not zero, and Source contains more than\r
191 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
192 Null-terminator, then ASSERT().\r
193 If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination\r
194 and Source results in a Unicode string with more than\r
195 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
196 Null-terminator, then ASSERT().\r
197\r
198 @param Destination A pointer to a Null-terminated Unicode string.\r
199 @param Source A pointer to a Null-terminated Unicode string.\r
200\r
201 @return Destination.\r
202\r
203**/\r
204CHAR16 *\r
205StrCat (\r
206 IN OUT CHAR16 *Destination,\r
207 IN CONST CHAR16 *Source\r
208 )\r
209{\r
210 StrCpy (Destination + FceStrLen (Destination), Source);\r
211\r
212 //\r
213 // Size of the resulting string should never be zero.\r
214 // PcdMaximumUnicodeStringLength is tested inside FceStrLen().\r
215 //\r
216 ASSERT (FceStrSize (Destination) != 0);\r
217 return Destination;\r
218}\r
219\r
220/**\r
221 Returns the first occurrence of a Null-terminated Unicode sub-string\r
222 in a Null-terminated Unicode string.\r
223\r
224 This function scans the contents of the Null-terminated Unicode string\r
225 specified by String and returns the first occurrence of SearchString.\r
226 If SearchString is not found in String, then NULL is returned. If\r
227 the length of SearchString is zero, then String is\r
228 returned.\r
229\r
230 If String is NULL, then ASSERT().\r
231 If String is not aligned on a 16-bit boundary, then ASSERT().\r
232 If SearchString is NULL, then ASSERT().\r
233 If SearchString is not aligned on a 16-bit boundary, then ASSERT().\r
234\r
235 If PcdMaximumUnicodeStringLength is not zero, and SearchString\r
236 or String contains more than PcdMaximumUnicodeStringLength Unicode\r
237 characters, not including the Null-terminator, then ASSERT().\r
238\r
239 @param String A pointer to a Null-terminated Unicode string.\r
240 @param SearchString A pointer to a Null-terminated Unicode string to search for.\r
241\r
242 @retval NULL If the SearchString does not appear in String.\r
243 @return others If there is a match.\r
244\r
245**/\r
246CHAR16 *\r
247StrStr (\r
248 IN CONST CHAR16 *String,\r
249 IN CONST CHAR16 *SearchString\r
250 )\r
251{\r
252 CONST CHAR16 *FirstMatch;\r
253 CONST CHAR16 *SearchStringTmp;\r
254\r
255 //\r
256 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.\r
257 // Length tests are performed inside FceStrLen().\r
258 //\r
259 ASSERT (FceStrSize (String) != 0);\r
260 ASSERT (FceStrSize (SearchString) != 0);\r
261\r
262 if (*SearchString == L'\0') {\r
263 return (CHAR16 *) String;\r
264 }\r
265\r
266 while (*String != L'\0') {\r
267 SearchStringTmp = SearchString;\r
268 FirstMatch = String;\r
269\r
270 while ((*String == *SearchStringTmp)\r
271 && (*String != L'\0')) {\r
272 String++;\r
273 SearchStringTmp++;\r
274 }\r
275\r
276 if (*SearchStringTmp == L'\0') {\r
277 return (CHAR16 *) FirstMatch;\r
278 }\r
279\r
280 if (*String == L'\0') {\r
281 return NULL;\r
282 }\r
283\r
284 String = FirstMatch + 1;\r
285 }\r
286\r
287 return NULL;\r
288}\r
289\r
290/**\r
291 Convert one Null-terminated ASCII string to a Null-terminated\r
292 Unicode string and returns the Unicode string.\r
293\r
294 This function converts the contents of the ASCII string Source to the Unicode\r
295 string Destination, and returns Destination. The function terminates the\r
296 Unicode string Destination by appending a Null-terminator character at the end.\r
297 The caller is responsible to make sure Destination points to a buffer with size\r
298 equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes.\r
299\r
300 @param Source A pointer to a Null-terminated ASCII string.\r
301 @param Destination A pointer to a Null-terminated Unicode string.\r
302\r
303 @return Destination.\r
304 @return NULL If Destination or Source is NULL, return NULL.\r
305\r
306**/\r
307CHAR16 *\r
308AsciiStrToUnicodeStr (\r
309 IN CONST CHAR8 *Source,\r
310 OUT CHAR16 *Destination\r
311 )\r
312{\r
313 CHAR16 *ReturnValue;\r
314\r
315 ReturnValue = NULL;\r
316\r
317 if ((Destination == NULL) || (Source == NULL) || (strlen (Source) == 0)) {\r
318 return NULL;\r
319 }\r
320 ReturnValue = Destination;\r
321 while (*Source != '\0') {\r
322 *(Destination++) = (CHAR16) *(Source++);\r
323 }\r
324 //\r
325 // End the Destination with a NULL.\r
326 //\r
327 *Destination = '\0';\r
328\r
329 return ReturnValue;\r
330}\r
331\r
332/**\r
333 Internal function that convert a number to a string in Buffer.\r
334\r
335 Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer.\r
336\r
337 @param Buffer Location to place the ASCII string of Value.\r
338 @param Value The value to convert to a Decimal or Hexadecimal string in Buffer.\r
339 @param Radix Radix of the value\r
340\r
341 @return A pointer to the end of buffer filled with ASCII string.\r
342\r
343**/\r
344CHAR8 *\r
345BasePrintLibValueToString (\r
346 IN OUT CHAR8 *Buffer,\r
347 IN INT64 Value,\r
348 IN UINTN Radix\r
349 )\r
350{\r
351 UINT32 Remainder;\r
352\r
353 //\r
354 // Loop to convert one digit at a time in reverse order\r
355 //\r
356 *Buffer = 0;\r
357 do {\r
358 Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);\r
359 *(++Buffer) = mHexStr[Remainder];\r
360 } while (Value != 0);\r
361\r
362 //\r
363 // Return pointer of the end of filled buffer.\r
364 //\r
365 return Buffer;\r
366}\r
367\r
368/**\r
369 Reads a 16-bit value from memory that may be unaligned.\r
370\r
371 This function returns the 16-bit value pointed to by Buffer. The function\r
372 guarantees that the read operation does not produce an alignment fault.\r
373\r
374 If the Buffer is NULL, then ASSERT().\r
375\r
376 @param Buffer A pointer to a 16-bit value that may be unaligned.\r
377\r
378 @return The 16-bit value read from Buffer.\r
379\r
380**/\r
381UINT16\r
382FceReadUnaligned16 (\r
383 IN CONST UINT16 *Buffer\r
384 )\r
385{\r
386 ASSERT (Buffer != NULL);\r
387\r
388 return *Buffer;\r
389}\r
390\r
391/**\r
392 Reads a 32-bit value from memory that may be unaligned.\r
393\r
394 This function returns the 32-bit value pointed to by Buffer. The function\r
395 guarantees that the read operation does not produce an alignment fault.\r
396\r
397 If the Buffer is NULL, then ASSERT().\r
398\r
399 @param Buffer A pointer to a 32-bit value that may be unaligned.\r
400\r
401 @return The 32-bit value read from Buffer.\r
402\r
403**/\r
404UINT32\r
405ReadUnaligned32 (\r
406 IN CONST UINT32 *Buffer\r
407 )\r
408{\r
409 ASSERT (Buffer != NULL);\r
410\r
411 return *Buffer;\r
412}\r
413\r
414/**\r
415 Internal function that places the character into the Buffer.\r
416\r
417 Internal function that places ASCII or Unicode character into the Buffer.\r
418\r
419 @param Buffer The buffer to place the Unicode or ASCII string.\r
420 @param EndBuffer The end of the input Buffer. No characters will be\r
421 placed after that.\r
422 @param Length The count of character to be placed into Buffer.\r
423 (Negative value indicates no buffer fill.)\r
424 @param Character The character to be placed into Buffer.\r
425 @param Increment The character increment in Buffer.\r
426\r
427 @return Buffer.\r
428\r
429**/\r
430CHAR8 *\r
431BasePrintLibFillBuffer (\r
432 OUT CHAR8 *Buffer,\r
433 IN CHAR8 *EndBuffer,\r
434 IN INTN Length,\r
435 IN UINTN Character,\r
436 IN INTN Increment\r
437 )\r
438{\r
439 INTN Index;\r
440\r
441 for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {\r
442 *Buffer = (CHAR8) Character;\r
443 if (Increment != 1) {\r
444 *(Buffer + 1) = (CHAR8)(Character >> 8);\r
445 }\r
446 Buffer += Increment;\r
447 }\r
448\r
449 return Buffer;\r
450}\r
451\r
452/**\r
453 Worker function that produces a Null-terminated string in an output buffer\r
454 based on a Null-terminated format string and a VA_LIST argument list.\r
455\r
456 VSPrint function to process format and place the results in Buffer. Since a\r
457 VA_LIST is used this routine allows the nesting of Vararg routines. Thus\r
458 this is the main print working routine.\r
459\r
460 If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.\r
461\r
462 @param[out] Buffer The character buffer to print the results of the\r
463 parsing of Format into.\r
464 @param[in] BufferSize The maximum number of characters to put into\r
465 buffer.\r
466 @param[in] Flags Initial flags value.\r
467 Can only have FORMAT_UNICODE, OUTPUT_UNICODE,\r
468 and COUNT_ONLY_NO_PRINT set.\r
469 @param[in] Format A Null-terminated format string.\r
470 @param[in] VaListMarker VA_LIST style variable argument list consumed by\r
471 processing Format.\r
472 @param[in] BaseListMarker BASE_LIST style variable argument list consumed\r
473 by processing Format.\r
474\r
475 @return The number of characters printed not including the Null-terminator.\r
476 If COUNT_ONLY_NO_PRINT was set returns the same, but without any\r
477 modification to Buffer.\r
478\r
479**/\r
480UINTN\r
481BasePrintLibSPrintMarker (\r
482 OUT CHAR8 *Buffer,\r
483 IN UINTN BufferSize,\r
484 IN UINTN Flags,\r
485 IN CONST CHAR8 *Format,\r
486 IN VA_LIST VaListMarker, OPTIONAL\r
487 IN BASE_LIST BaseListMarker OPTIONAL\r
488 )\r
489{\r
490 CHAR8 *OriginalBuffer;\r
491 CHAR8 *EndBuffer;\r
492 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
493 UINT32 BytesPerOutputCharacter;\r
494 UINTN BytesPerFormatCharacter;\r
495 UINTN FormatMask;\r
496 UINTN FormatCharacter;\r
497 UINTN Width;\r
498 UINTN Precision;\r
499 INT64 Value;\r
500 CONST CHAR8 *ArgumentString;\r
501 UINTN Character;\r
502 EFI_GUID *TmpGuid;\r
503 TIME *TmpTime;\r
504 UINTN Count;\r
505 UINTN ArgumentMask;\r
506 INTN BytesPerArgumentCharacter;\r
507 UINTN ArgumentCharacter;\r
508 BOOLEAN Done;\r
509 UINTN Index;\r
510 CHAR8 Prefix;\r
511 BOOLEAN ZeroPad;\r
512 BOOLEAN Comma;\r
513 UINTN Digits;\r
514 UINTN Radix;\r
515 RETURN_STATUS Status;\r
516 UINT32 GuidData1;\r
517 UINT16 GuidData2;\r
518 UINT16 GuidData3;\r
519 UINTN LengthToReturn;\r
520\r
521 //\r
522 // If you change this code be sure to match the 2 versions of this function.\r
523 // Nearly identical logic is found in the BasePrintLib and\r
524 // DxePrintLibPrint2Protocol (both PrintLib instances).\r
525 //\r
526\r
527 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
528 if (BufferSize == 0) {\r
529 Buffer = NULL;\r
530 }\r
531 } else {\r
532 //\r
533 // We can run without a Buffer for counting only.\r
534 //\r
535 if (BufferSize == 0) {\r
536 return 0;\r
537 }\r
538 ASSERT (Buffer != NULL);\r
539 }\r
540\r
541 if ((Flags & OUTPUT_UNICODE) != 0) {\r
542 BytesPerOutputCharacter = 2;\r
543 } else {\r
544 BytesPerOutputCharacter = 1;\r
545 }\r
546\r
547 LengthToReturn = 0;\r
548\r
549 //\r
550 // Reserve space for the Null terminator.\r
551 //\r
552 BufferSize--;\r
553 OriginalBuffer = Buffer;\r
554\r
555 //\r
556 // Set the tag for the end of the input Buffer.\r
557 //\r
558 EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;\r
559\r
560 if ((Flags & FORMAT_UNICODE) != 0) {\r
561 //\r
562 // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength\r
563 // Unicode characters if PcdMaximumUnicodeStringLength is not zero.\r
564 //\r
565 ASSERT (FceStrSize ((CHAR16 *) Format) != 0);\r
566 BytesPerFormatCharacter = 2;\r
567 FormatMask = 0xffff;\r
568 } else {\r
569 //\r
570 // Make sure format string cannot contain more than PcdMaximumAsciiStringLength\r
571 // Ascii characters if PcdMaximumAsciiStringLength is not zero.\r
572 //\r
573 ASSERT (strlen (Format) + 1 != 0);\r
574 BytesPerFormatCharacter = 1;\r
575 FormatMask = 0xff;\r
576 }\r
577\r
578 //\r
579 // Get the first character from the format string\r
580 //\r
581 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
582\r
583 //\r
584 // Loop until the end of the format string is reached or the output buffer is full\r
585 //\r
586 while (FormatCharacter != 0 && Buffer < EndBuffer) {\r
587 //\r
588 // Clear all the flag bits except those that may have been passed in\r
589 //\r
590 Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);\r
591\r
592 //\r
593 // Set the default width to zero, and the default precision to 1\r
594 //\r
595 Width = 0;\r
596 Precision = 1;\r
597 Prefix = 0;\r
598 Comma = FALSE;\r
599 ZeroPad = FALSE;\r
600 Count = 0;\r
601 Digits = 0;\r
602\r
603 switch (FormatCharacter) {\r
604 case '%':\r
605 //\r
606 // Parse Flags and Width\r
607 //\r
608 for (Done = FALSE; !Done; ) {\r
609 Format += BytesPerFormatCharacter;\r
610 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
611 switch (FormatCharacter) {\r
612 case '.':\r
613 Flags |= PRECISION;\r
614 break;\r
615 case '-':\r
616 Flags |= LEFT_JUSTIFY;\r
617 break;\r
618 case '+':\r
619 Flags |= PREFIX_SIGN;\r
620 break;\r
621 case ' ':\r
622 Flags |= PREFIX_BLANK;\r
623 break;\r
624 case ',':\r
625 Flags |= COMMA_TYPE;\r
626 break;\r
627 case 'L':\r
628 case 'l':\r
629 Flags |= LONG_TYPE;\r
630 break;\r
631 case '*':\r
632 if ((Flags & PRECISION) == 0) {\r
633 Flags |= PAD_TO_WIDTH;\r
634 if (BaseListMarker == NULL) {\r
635 Width = VA_ARG (VaListMarker, UINTN);\r
636 } else {\r
637 Width = BASE_ARG (BaseListMarker, UINTN);\r
638 }\r
639 } else {\r
640 if (BaseListMarker == NULL) {\r
641 Precision = VA_ARG (VaListMarker, UINTN);\r
642 } else {\r
643 Precision = BASE_ARG (BaseListMarker, UINTN);\r
644 }\r
645 }\r
646 break;\r
647 case '0':\r
648 if ((Flags & PRECISION) == 0) {\r
649 Flags |= PREFIX_ZERO;\r
650 }\r
651 case '1':\r
652 case '2':\r
653 case '3':\r
654 case '4':\r
655 case '5':\r
656 case '6':\r
657 case '7':\r
658 case '8':\r
659 case '9':\r
660 for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){\r
661 Count = (Count * 10) + FormatCharacter - '0';\r
662 Format += BytesPerFormatCharacter;\r
663 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
664 }\r
665 Format -= BytesPerFormatCharacter;\r
666 if ((Flags & PRECISION) == 0) {\r
667 Flags |= PAD_TO_WIDTH;\r
668 Width = Count;\r
669 } else {\r
670 Precision = Count;\r
671 }\r
672 break;\r
673\r
674 case '\0':\r
675 //\r
676 // Make no output if Format string terminates unexpectedly when\r
677 // looking up for flag, width, precision and type.\r
678 //\r
679 Format -= BytesPerFormatCharacter;\r
680 Precision = 0;\r
681 //\r
682 // break skipped on purpose.\r
683 //\r
684 default:\r
685 Done = TRUE;\r
686 break;\r
687 }\r
688 }\r
689\r
690 //\r
691 // Handle each argument type\r
692 //\r
693 switch (FormatCharacter) {\r
694 case 'p':\r
695 //\r
696 // Flag space, +, 0, L & l are invalid for type p.\r
697 //\r
698 Flags &= ~(PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE);\r
699 if (sizeof (VOID *) > 4) {\r
700 Flags |= LONG_TYPE;\r
701 }\r
702 case 'X':\r
703 Flags |= PREFIX_ZERO;\r
704 //\r
705 // break skipped on purpose\r
706 //\r
707 case 'x':\r
708 Flags |= RADIX_HEX;\r
709 //\r
710 // break skipped on purpose\r
711 //\r
712 case 'd':\r
713 if ((Flags & LONG_TYPE) == 0) {\r
714 //\r
715 // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
716 // This assumption is made so the format string definition is compatible with the ANSI C\r
717 // Specification for formatted strings. It is recommended that the Base Types be used\r
718 // everywhere, but in this one case, compliance with ANSI C is more important, and\r
719 // provides an implementation that is compatible with that largest possible set of CPU\r
720 // architectures. This is why the type "int" is used in this one case.\r
721 //\r
722 if (BaseListMarker == NULL) {\r
723 Value = VA_ARG (VaListMarker, int);\r
724 } else {\r
725 Value = BASE_ARG (BaseListMarker, int);\r
726 }\r
727 } else {\r
728 if (BaseListMarker == NULL) {\r
729 Value = VA_ARG (VaListMarker, INT64);\r
730 } else {\r
731 Value = BASE_ARG (BaseListMarker, INT64);\r
732 }\r
733 }\r
734 if ((Flags & PREFIX_BLANK) != 0) {\r
735 Prefix = ' ';\r
736 }\r
737 if ((Flags & PREFIX_SIGN) != 0) {\r
738 Prefix = '+';\r
739 }\r
740 if ((Flags & COMMA_TYPE) != 0) {\r
741 Comma = TRUE;\r
742 }\r
743 if ((Flags & RADIX_HEX) == 0) {\r
744 Radix = 10;\r
745 if (Comma) {\r
746 Flags &= (~PREFIX_ZERO);\r
747 Precision = 1;\r
748 }\r
749 if (Value < 0) {\r
750 Flags |= PREFIX_SIGN;\r
751 Prefix = '-';\r
752 Value = -Value;\r
753 }\r
754 } else {\r
755 Radix = 16;\r
756 Comma = FALSE;\r
757 if ((Flags & LONG_TYPE) == 0 && Value < 0) {\r
758 //\r
759 // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
760 // This assumption is made so the format string definition is compatible with the ANSI C\r
761 // Specification for formatted strings. It is recommended that the Base Types be used\r
762 // everywhere, but in this one case, compliance with ANSI C is more important, and\r
763 // provides an implementation that is compatible with that largest possible set of CPU\r
764 // architectures. This is why the type "unsigned int" is used in this one case.\r
765 //\r
766 Value = (unsigned int)Value;\r
767 }\r
768 }\r
769 //\r
770 // Convert Value to a reversed string\r
771 //\r
772 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer;\r
773 if (Value == 0 && Precision == 0) {\r
774 Count = 0;\r
775 }\r
776 ArgumentString = (CHAR8 *)ValueBuffer + Count;\r
777\r
778 Digits = Count % 3;\r
779 if (Digits != 0) {\r
780 Digits = 3 - Digits;\r
781 }\r
782 if (Comma && Count != 0) {\r
783 Count += ((Count - 1) / 3);\r
784 }\r
785 if (Prefix != 0) {\r
786 Count++;\r
787 Precision++;\r
788 }\r
789 Flags |= ARGUMENT_REVERSED;\r
790 ZeroPad = TRUE;\r
791 if ((Flags & PREFIX_ZERO) != 0) {\r
792 if ((Flags & LEFT_JUSTIFY) == 0) {\r
793 if ((Flags & PAD_TO_WIDTH) != 0) {\r
794 if ((Flags & PRECISION) == 0) {\r
795 Precision = Width;\r
796 }\r
797 }\r
798 }\r
799 }\r
800 break;\r
801\r
802 case 's':\r
803 case 'S':\r
804 Flags |= ARGUMENT_UNICODE;\r
805 //\r
806 // break skipped on purpose\r
807 //\r
808 case 'a':\r
809 if (BaseListMarker == NULL) {\r
810 ArgumentString = VA_ARG (VaListMarker, CHAR8 *);\r
811 } else {\r
812 ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);\r
813 }\r
814 if (ArgumentString == NULL) {\r
815 Flags &= (~ARGUMENT_UNICODE);\r
816 ArgumentString = "<null string>";\r
817 }\r
818 //\r
819 // Set the default precision for string to be zero if not specified.\r
820 //\r
821 if ((Flags & PRECISION) == 0) {\r
822 Precision = 0;\r
823 }\r
824 break;\r
825\r
826 case 'c':\r
827 if (BaseListMarker == NULL) {\r
828 Character = VA_ARG (VaListMarker, UINTN) & 0xffff;\r
829 } else {\r
830 Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff;\r
831 }\r
832 ArgumentString = (CHAR8 *)&Character;\r
833 Flags |= ARGUMENT_UNICODE;\r
834 break;\r
835\r
836 case 'g':\r
837 if (BaseListMarker == NULL) {\r
838 TmpGuid = VA_ARG (VaListMarker, EFI_GUID *);\r
839 } else {\r
840 TmpGuid = BASE_ARG (BaseListMarker, EFI_GUID *);\r
841 }\r
842 if (TmpGuid == NULL) {\r
843 ArgumentString = "<null guid>";\r
844 } else {\r
845 GuidData1 = ReadUnaligned32 (&(TmpGuid->Data1));\r
846 GuidData2 = FceReadUnaligned16 (&(TmpGuid->Data2));\r
847 GuidData3 = FceReadUnaligned16 (&(TmpGuid->Data3));\r
848 BasePrintLibSPrint (\r
849 ValueBuffer,\r
850 MAXIMUM_VALUE_CHARACTERS,\r
851 0,\r
852 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
853 GuidData1,\r
854 GuidData2,\r
855 GuidData3,\r
856 TmpGuid->Data4[0],\r
857 TmpGuid->Data4[1],\r
858 TmpGuid->Data4[2],\r
859 TmpGuid->Data4[3],\r
860 TmpGuid->Data4[4],\r
861 TmpGuid->Data4[5],\r
862 TmpGuid->Data4[6],\r
863 TmpGuid->Data4[7]\r
864 );\r
865 ArgumentString = ValueBuffer;\r
866 }\r
867 break;\r
868\r
869 case 't':\r
870 if (BaseListMarker == NULL) {\r
871 TmpTime = VA_ARG (VaListMarker, TIME *);\r
872 } else {\r
873 TmpTime = BASE_ARG (BaseListMarker, TIME *);\r
874 }\r
875 if (TmpTime == NULL) {\r
876 ArgumentString = "<null time>";\r
877 } else {\r
878 BasePrintLibSPrint (\r
879 ValueBuffer,\r
880 MAXIMUM_VALUE_CHARACTERS,\r
881 0,\r
882 "%02d/%02d/%04d %02d:%02d",\r
883 TmpTime->Month,\r
884 TmpTime->Day,\r
885 TmpTime->Year,\r
886 TmpTime->Hour,\r
887 TmpTime->Minute\r
888 );\r
889 ArgumentString = ValueBuffer;\r
890 }\r
891 break;\r
892\r
893 case 'r':\r
894 if (BaseListMarker == NULL) {\r
895 Status = VA_ARG (VaListMarker, RETURN_STATUS);\r
896 } else {\r
897 Status = BASE_ARG (BaseListMarker, RETURN_STATUS);\r
898 }\r
899 ArgumentString = ValueBuffer;\r
900 if (RETURN_ERROR (Status)) {\r
901 //\r
902 // Clear error bit\r
903 //\r
904 Index = Status & ~MAX_BIT;\r
905 if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {\r
906 ArgumentString = mStatusString [Index + WARNING_STATUS_NUMBER];\r
907 }\r
908 } else {\r
909 Index = Status;\r
910 if (Index <= WARNING_STATUS_NUMBER) {\r
911 ArgumentString = mStatusString [Index];\r
912 }\r
913 }\r
914 if (ArgumentString == ValueBuffer) {\r
915 BasePrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);\r
916 }\r
917 break;\r
918\r
919 case '\r':\r
920 Format += BytesPerFormatCharacter;\r
921 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
922 if (FormatCharacter == '\n') {\r
923 //\r
924 // Translate '\r\n' to '\r\n'\r
925 //\r
926 ArgumentString = "\r\n";\r
927 } else {\r
928 //\r
929 // Translate '\r' to '\r'\r
930 //\r
931 ArgumentString = "\r";\r
932 Format -= BytesPerFormatCharacter;\r
933 }\r
934 break;\r
935\r
936 case '\n':\r
937 //\r
938 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'\r
939 //\r
940 ArgumentString = "\r\n";\r
941 Format += BytesPerFormatCharacter;\r
942 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
943 if (FormatCharacter != '\r') {\r
944 Format -= BytesPerFormatCharacter;\r
945 }\r
946 break;\r
947\r
948 case '%':\r
949 default:\r
950 //\r
951 // if the type is '%' or unknown, then print it to the screen\r
952 //\r
953 ArgumentString = (CHAR8 *)&FormatCharacter;\r
954 Flags |= ARGUMENT_UNICODE;\r
955 break;\r
956 }\r
957 break;\r
958\r
959 case '\r':\r
960 Format += BytesPerFormatCharacter;\r
961 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
962 if (FormatCharacter == '\n') {\r
963 //\r
964 // Translate '\r\n' to '\r\n'\r
965 //\r
966 ArgumentString = "\r\n";\r
967 } else {\r
968 //\r
969 // Translate '\r' to '\r'\r
970 //\r
971 ArgumentString = "\r";\r
972 Format -= BytesPerFormatCharacter;\r
973 }\r
974 break;\r
975\r
976 case '\n':\r
977 //\r
978 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'\r
979 //\r
980 ArgumentString = "\r\n";\r
981 Format += BytesPerFormatCharacter;\r
982 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
983 if (FormatCharacter != '\r') {\r
984 Format -= BytesPerFormatCharacter;\r
985 }\r
986 break;\r
987\r
988 default:\r
989 ArgumentString = (CHAR8 *)&FormatCharacter;\r
990 Flags |= ARGUMENT_UNICODE;\r
991 break;\r
992 }\r
993\r
994 //\r
995 // Retrieve the ArgumentString attriubutes\r
996 //\r
997 if ((Flags & ARGUMENT_UNICODE) != 0) {\r
998 ArgumentMask = 0xffff;\r
999 BytesPerArgumentCharacter = 2;\r
1000 } else {\r
1001 ArgumentMask = 0xff;\r
1002 BytesPerArgumentCharacter = 1;\r
1003 }\r
1004 if ((Flags & ARGUMENT_REVERSED) != 0) {\r
1005 BytesPerArgumentCharacter = -BytesPerArgumentCharacter;\r
1006 } else {\r
1007 //\r
1008 // Compute the number of characters in ArgumentString and store it in Count\r
1009 // ArgumentString is either null-terminated, or it contains Precision characters\r
1010 //\r
1011 for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {\r
1012 ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;\r
1013 if (ArgumentCharacter == 0) {\r
1014 break;\r
1015 }\r
1016 }\r
1017 }\r
1018\r
1019 if (Precision < Count) {\r
1020 Precision = Count;\r
1021 }\r
1022\r
1023 //\r
1024 // Pad before the string\r
1025 //\r
1026 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {\r
1027 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);\r
1028 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1029 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
1030 }\r
1031 }\r
1032\r
1033 if (ZeroPad) {\r
1034 if (Prefix != 0) {\r
1035 LengthToReturn += (1 * BytesPerOutputCharacter);\r
1036 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1037 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
1038 }\r
1039 }\r
1040 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);\r
1041 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1042 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);\r
1043 }\r
1044 } else {\r
1045 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);\r
1046 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1047 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);\r
1048 }\r
1049 if (Prefix != 0) {\r
1050 LengthToReturn += (1 * BytesPerOutputCharacter);\r
1051 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1052 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
1053 }\r
1054 }\r
1055 }\r
1056\r
1057 //\r
1058 // Output the Prefix character if it is present\r
1059 //\r
1060 Index = 0;\r
1061 if (Prefix != 0) {\r
1062 Index++;\r
1063 }\r
1064\r
1065 //\r
1066 // Copy the string into the output buffer performing the required type conversions\r
1067 //\r
1068 while (Index < Count) {\r
1069 ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;\r
1070\r
1071 LengthToReturn += (1 * BytesPerOutputCharacter);\r
1072 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1073 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);\r
1074 }\r
1075 ArgumentString += BytesPerArgumentCharacter;\r
1076 Index++;\r
1077 if (Comma) {\r
1078 Digits++;\r
1079 if (Digits == 3) {\r
1080 Digits = 0;\r
1081 Index++;\r
1082 if (Index < Count) {\r
1083 LengthToReturn += (1 * BytesPerOutputCharacter);\r
1084 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1085 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);\r
1086 }\r
1087 }\r
1088 }\r
1089 }\r
1090 }\r
1091\r
1092 //\r
1093 // Pad after the string\r
1094 //\r
1095 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {\r
1096 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);\r
1097 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
1098 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
1099 }\r
1100 }\r
1101\r
1102 //\r
1103 // Get the next character from the format string\r
1104 //\r
1105 Format += BytesPerFormatCharacter;\r
1106\r
1107 //\r
1108 // Get the next character from the format string\r
1109 //\r
1110 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
1111 }\r
1112\r
1113 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
1114 return (LengthToReturn / BytesPerOutputCharacter);\r
1115 }\r
1116\r
1117 ASSERT (Buffer != NULL);\r
1118 //\r
1119 // Null terminate the Unicode or ASCII string\r
1120 //\r
1121 BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);\r
1122 //\r
1123 // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength\r
1124 // Unicode characters if PcdMaximumUnicodeStringLength is not zero.\r
1125 //\r
1126 ASSERT ((((Flags & OUTPUT_UNICODE) == 0)) || (FceStrSize ((CHAR16 *) OriginalBuffer) != 0));\r
1127 //\r
1128 // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength\r
1129 // ASCII characters if PcdMaximumAsciiStringLength is not zero.\r
1130 //\r
1131 ASSERT ((((Flags & OUTPUT_UNICODE) != 0)) || ((strlen (OriginalBuffer) + 1) != 0));\r
1132\r
1133 return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);\r
1134}\r
1135\r
1136/**\r
1137 Worker function that produces a Null-terminated string in an output buffer\r
1138 based on a Null-terminated format string and variable argument list.\r
1139\r
1140 VSPrint function to process format and place the results in Buffer. Since a\r
1141 VA_LIST is used this routine allows the nesting of Vararg routines. Thus\r
1142 this is the main print working routine\r
1143\r
1144 @param StartOfBuffer The character buffer to print the results of the parsing\r
1145 of Format into.\r
1146 @param BufferSize The maximum number of characters to put into buffer.\r
1147 Zero means no limit.\r
1148 @param Flags Initial flags value.\r
1149 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set\r
1150 @param FormatString A Null-terminated format string.\r
1151 @param ... The variable argument list.\r
1152\r
1153 @return The number of characters printed.\r
1154\r
1155**/\r
1156UINTN\r
1157BasePrintLibSPrint (\r
1158 OUT CHAR8 *StartOfBuffer,\r
1159 IN UINTN BufferSize,\r
1160 IN UINTN Flags,\r
1161 IN CONST CHAR8 *FormatString,\r
1162 ...\r
1163 )\r
1164{\r
1165 VA_LIST Marker;\r
1166\r
1167 VA_START (Marker, FormatString);\r
1168 return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);\r
1169}\r
1170\r
1171/**\r
1172 Produces a Null-terminated Unicode string in an output buffer based on\r
1173 a Null-terminated Unicode format string and a VA_LIST argument list\r
1174\r
1175 Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer\r
1176 and BufferSize.\r
1177 The Unicode string is produced by parsing the format string specified by FormatString.\r
1178 Arguments are pulled from the variable argument list specified by Marker based on the\r
1179 contents of the format string.\r
1180 The number of Unicode characters in the produced output buffer is returned not including\r
1181 the Null-terminator.\r
1182 If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.\r
1183\r
1184 If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().\r
1185 If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().\r
1186 If BufferSize > 1 and FormatString is NULL, then ASSERT().\r
1187 If BufferSize > 1 and FormatString is not aligned on a 16-bit boundary, then ASSERT().\r
1188 If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than\r
1189 PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then\r
1190 ASSERT().\r
1191 If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string\r
1192 contains more than PcdMaximumUnicodeStringLength Unicode characters not including the\r
1193 Null-terminator, then ASSERT().\r
1194\r
1195 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated\r
1196 Unicode string.\r
1197 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.\r
1198 @param FormatString A Null-terminated Unicode format string.\r
1199 @param Marker VA_LIST marker for the variable argument list.\r
1200\r
1201 @return The number of Unicode characters in the produced output buffer not including the\r
1202 Null-terminator.\r
1203\r
1204**/\r
1205UINTN\r
1206UnicodeVSPrint (\r
1207 OUT CHAR16 *StartOfBuffer,\r
1208 IN UINTN BufferSize,\r
1209 IN CONST CHAR16 *FormatString,\r
1210 IN VA_LIST Marker\r
1211 )\r
1212{\r
1213 ASSERT_UNICODE_BUFFER (StartOfBuffer);\r
1214 ASSERT_UNICODE_BUFFER (FormatString);\r
1215 return BasePrintLibSPrintMarker ((CHAR8 *)StartOfBuffer, BufferSize >> 1, FORMAT_UNICODE | OUTPUT_UNICODE, (CHAR8 *)FormatString, Marker, NULL);\r
1216}\r
1217\r
1218/**\r
1219 Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated\r
1220 Unicode format string and variable argument list.\r
1221\r
1222 Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer\r
1223 and BufferSize.\r
1224 The Unicode string is produced by parsing the format string specified by FormatString.\r
1225 Arguments are pulled from the variable argument list based on the contents of the format string.\r
1226 The number of Unicode characters in the produced output buffer is returned not including\r
1227 the Null-terminator.\r
1228 If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.\r
1229\r
1230 If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().\r
1231 If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().\r
1232 If BufferSize > 1 and FormatString is NULL, then ASSERT().\r
1233 If BufferSize > 1 and FormatString is not aligned on a 16-bit boundary, then ASSERT().\r
1234 If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than\r
1235 PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then\r
1236 ASSERT().\r
1237 If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string\r
1238 contains more than PcdMaximumUnicodeStringLength Unicode characters not including the\r
1239 Null-terminator, then ASSERT().\r
1240\r
1241 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated\r
1242 Unicode string.\r
1243 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.\r
1244 @param FormatString A Null-terminated Unicode format string.\r
1245 @param ... Variable argument list whose contents are accessed based on the\r
1246 format string specified by FormatString.\r
1247\r
1248 @return The number of Unicode characters in the produced output buffer not including the\r
1249 Null-terminator.\r
1250\r
1251**/\r
1252UINTN\r
1253UnicodeSPrint (\r
1254 OUT CHAR16 *StartOfBuffer,\r
1255 IN UINTN BufferSize,\r
1256 IN CONST CHAR16 *FormatString,\r
1257 ...\r
1258 )\r
1259{\r
1260 VA_LIST Marker;\r
1261\r
1262 VA_START (Marker, FormatString);\r
1263 return UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);\r
1264}\r
1265\r
1266/**\r
1267 Convert a Null-terminated Unicode string to a Null-terminated\r
1268 ASCII string and returns the ASCII string.\r
1269\r
1270 This function converts the content of the Unicode string Source\r
1271 to the ASCII string Destination by copying the lower 8 bits of\r
1272 each Unicode character. It returns Destination. The function terminates\r
1273 the ASCII string Destination by appending a Null-terminator character\r
1274 at the end. The caller is responsible to make sure Destination points\r
1275 to a buffer with size equal or greater than (FceStrLen (Source) + 1) in bytes.\r
1276\r
1277 If Destination is NULL, then ASSERT().\r
1278 If Source is NULL, then ASSERT().\r
1279 If Source is not aligned on a 16-bit boundary, then ASSERT().\r
1280 If Source and Destination overlap, then ASSERT().\r
1281\r
1282 If any Unicode characters in Source contain non-zero value in\r
1283 the upper 8 bits, then ASSERT().\r
1284\r
1285 @param Source Pointer to a Null-terminated Unicode string.\r
1286 @param Destination Pointer to a Null-terminated ASCII string.\r
1287\r
1288 @reture Destination\r
1289\r
1290**/\r
1291CHAR8 *\r
1292UnicodeStrToAsciiStr (\r
1293 IN CONST CHAR16 *Source,\r
1294 OUT CHAR8 *Destination\r
1295 )\r
1296{\r
1297 CHAR8 *ReturnValue;\r
1298\r
1299 ReturnValue = Destination;\r
1300 assert (Destination != NULL);\r
1301 assert (Source != NULL);\r
1302 assert (((UINTN) Source & 0x01) == 0);\r
1303\r
1304 while (*Source != L'\0') {\r
1305 //\r
1306 // If any Unicode characters in Source contain\r
1307 // non-zero value in the upper 8 bits, then ASSERT().\r
1308 //\r
1309 assert (*Source < 0x100);\r
1310 *(ReturnValue++) = (CHAR8) *(Source++);\r
1311 }\r
1312\r
1313 *ReturnValue = '\0';\r
1314\r
1315 return Destination;\r
1316}\r
1317\r
1318/**\r
1319 Allocate new memory and then copy the Unicode string Source to Destination.\r
1320\r
1321 @param Dest Location to copy string\r
1322 @param Src String to copy\r
1323\r
1324**/\r
1325VOID\r
1326NewStringCpy (\r
1327 IN OUT CHAR16 **Dest,\r
1328 IN CHAR16 *Src\r
1329 )\r
1330{\r
1331 if (*Dest != NULL) {\r
1332 FreePool (*Dest);\r
1333 }\r
1334 *Dest = FceAllocateCopyPool (FceStrSize (Src), Src);\r
1335 ASSERT (*Dest != NULL);\r
1336}\r
1337\r
1338/**\r
1339 Check if a Unicode character is a decimal character.\r
1340\r
1341 This internal function checks if a Unicode character is a\r
1342 decimal character. The valid decimal character is from\r
1343 L'0' to L'9'.\r
1344\r
1345 @param Char The character to check against.\r
1346\r
1347 @retval TRUE If the Char is a decmial character.\r
1348 @retval FALSE If the Char is not a decmial character.\r
1349\r
1350**/\r
1351BOOLEAN\r
1352FceInternalIsDecimalDigitCharacter (\r
1353 IN CHAR16 Char\r
1354 )\r
1355{\r
1356 return (BOOLEAN) ((Char >= L'0') && (Char <= L'9'));\r
1357}\r
1358\r
1359/**\r
1360 Convert a Unicode character to upper case only if\r
1361 it maps to a valid small-case ASCII character.\r
1362\r
1363 This internal function only deal with Unicode character\r
1364 which maps to a valid small-case ASCII character, i.e.\r
1365 L'a' to L'z'. For other Unicode character, the input character\r
1366 is returned directly.\r
1367\r
1368 @param Char The character to convert.\r
1369\r
1370 @retval LowerCharacter If the Char is with range L'a' to L'z'.\r
1371 @retval Unchanged Otherwise.\r
1372\r
1373**/\r
1374CHAR16\r
1375FceInternalCharToUpper (\r
1376 IN CHAR16 Char\r
1377 )\r
1378{\r
1379 if ((Char >= L'a') && (Char <= L'z')) {\r
1380 return (CHAR16) (Char - (L'a' - L'A'));\r
1381 }\r
1382\r
1383 return Char;\r
1384}\r
1385\r
1386/**\r
1387 Convert a Unicode character to numerical value.\r
1388\r
1389 This internal function only deal with Unicode character\r
1390 which maps to a valid hexadecimal ASII character, i.e.\r
1391 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other\r
1392 Unicode character, the value returned does not make sense.\r
1393\r
1394 @param Char The character to convert.\r
1395\r
1396 @return The numerical value converted.\r
1397\r
1398**/\r
1399UINTN\r
1400FceInternalHexCharToUintn (\r
1401 IN CHAR16 Char\r
1402 )\r
1403{\r
1404 if (FceInternalIsDecimalDigitCharacter (Char)) {\r
1405 return Char - L'0';\r
1406 }\r
1407\r
1408 return (UINTN) (10 + FceInternalCharToUpper (Char) - L'A');\r
1409}\r
1410\r
1411/**\r
1412 Check if a Unicode character is a hexadecimal character.\r
1413\r
1414 This internal function checks if a Unicode character is a\r
1415 decimal character. The valid hexadecimal character is\r
1416 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
1417\r
1418\r
1419 @param Char The character to check against.\r
1420\r
1421 @retval TRUE If the Char is a hexadecmial character.\r
1422 @retval FALSE If the Char is not a hexadecmial character.\r
1423\r
1424**/\r
1425BOOLEAN\r
1426FceInternalIsHexaDecimalDigitCharacter (\r
1427 IN CHAR16 Char\r
1428 )\r
1429{\r
1430\r
1431 return (BOOLEAN) (FceInternalIsDecimalDigitCharacter (Char) ||\r
1432 ((Char >= L'A') && (Char <= L'F')) ||\r
1433 ((Char >= L'a') && (Char <= L'f')));\r
1434}\r
1435\r
1436\r
1437/**\r
1438 Convert a Null-terminated Unicode decimal string to a value of\r
1439 type UINT64.\r
1440\r
1441 This function returns a value of type UINT64 by interpreting the contents\r
1442 of the Unicode string specified by String as a decimal number. The format\r
1443 of the input Unicode string String is:\r
1444\r
1445 [spaces] [decimal digits].\r
1446\r
1447 The valid decimal digit character is in the range [0-9]. The\r
1448 function will ignore the pad space, which includes spaces or\r
1449 tab characters, before [decimal digits]. The running zero in the\r
1450 beginning of [decimal digits] will be ignored. Then, the function\r
1451 stops at the first character that is a not a valid decimal character\r
1452 or a Null-terminator, whichever one comes first.\r
1453\r
1454 If String is NULL, then ASSERT().\r
1455 If String is not aligned in a 16-bit boundary, then ASSERT().\r
1456 If String has only pad spaces, then 0 is returned.\r
1457 If String has no pad spaces or valid decimal digits,\r
1458 then 0 is returned.\r
1459 If the number represented by String overflows according\r
1460 to the range defined by UINT64, then ASSERT().\r
1461\r
1462 If PcdMaximumUnicodeStringLength is not zero, and String contains\r
1463 more than PcdMaximumUnicodeStringLength Unicode characters, not including\r
1464 the Null-terminator, then ASSERT().\r
1465\r
1466 @param String A pointer to a Null-terminated Unicode string.\r
1467\r
1468 @retval Value translated from String.\r
1469\r
1470**/\r
1471UINT64\r
1472FceStrDecimalToUint64 (\r
1473 IN CONST CHAR16 *String\r
1474 )\r
1475{\r
1476 UINT64 Result;\r
1477\r
1478 //\r
1479 // ASSERT String is less long than PcdMaximumUnicodeStringLength.\r
1480 // Length tests are performed inside FceStrLen().\r
1481 //\r
1482 ASSERT (FceStrSize (String) != 0);\r
1483\r
1484 //\r
1485 // Ignore the pad spaces (space or tab)\r
1486 //\r
1487 while ((*String == L' ') || (*String == L'\t')) {\r
1488 String++;\r
1489 }\r
1490\r
1491 //\r
1492 // Ignore leading Zeros after the spaces\r
1493 //\r
1494 while (*String == L'0') {\r
1495 String++;\r
1496 }\r
1497\r
1498 Result = 0;\r
1499\r
1500 while (FceInternalIsDecimalDigitCharacter (*String)) {\r
1501 //\r
1502 // If the number represented by String overflows according\r
1503 // to the range defined by UINTN, then ASSERT().\r
1504 //\r
1505 ASSERT (Result <= DivU64x32 (((UINT64) ~0) - (*String - L'0') , 10));\r
1506\r
1507 Result = MultU64x32 (Result, 10) + (*String - L'0');\r
1508 String++;\r
1509 }\r
1510\r
1511 return Result;\r
1512}\r
1513\r
1514\r
1515/**\r
1516 Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
1517\r
1518 This function returns a value of type UINT64 by interpreting the contents\r
1519 of the Unicode string specified by String as a hexadecimal number.\r
1520 The format of the input Unicode string String is\r
1521\r
1522 [spaces][zeros][x][hexadecimal digits].\r
1523\r
1524 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
1525 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
1526 If "x" appears in the input string, it must be prefixed with at least one 0.\r
1527 The function will ignore the pad space, which includes spaces or tab characters,\r
1528 before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
1529 [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
1530 first valid hexadecimal digit. Then, the function stops at the first character that is\r
1531 a not a valid hexadecimal character or NULL, whichever one comes first.\r
1532\r
1533 If String is NULL, then ASSERT().\r
1534 If String is not aligned in a 16-bit boundary, then ASSERT().\r
1535 If String has only pad spaces, then zero is returned.\r
1536 If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
1537 then zero is returned.\r
1538 If the number represented by String overflows according to the range defined by\r
1539 UINT64, then ASSERT().\r
1540\r
1541 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
1542 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
1543 then ASSERT().\r
1544\r
1545 @param String A pointer to a Null-terminated Unicode string.\r
1546\r
1547 @retval Value translated from String.\r
1548\r
1549**/\r
1550UINT64\r
1551FceStrHexToUint64 (\r
1552 IN CONST CHAR16 *String\r
1553 )\r
1554{\r
1555 UINT64 Result;\r
1556\r
1557 //\r
1558 // ASSERT String is less long than PcdMaximumUnicodeStringLength.\r
1559 // Length tests are performed inside FceStrLen().\r
1560 //\r
1561 ASSERT (FceStrSize (String) != 0);\r
1562\r
1563 //\r
1564 // Ignore the pad spaces (space or tab)\r
1565 //\r
1566 while ((*String == L' ') || (*String == L'\t')) {\r
1567 String++;\r
1568 }\r
1569\r
1570 //\r
1571 // Ignore leading Zeros after the spaces\r
1572 //\r
1573 while (*String == L'0') {\r
1574 String++;\r
1575 }\r
1576\r
1577 if (FceInternalCharToUpper (*String) == L'X') {\r
1578 ASSERT (*(String - 1) == L'0');\r
1579 if (*(String - 1) != L'0') {\r
1580 return 0;\r
1581 }\r
1582 //\r
1583 // Skip the 'X'\r
1584 //\r
1585 String++;\r
1586 }\r
1587\r
1588 Result = 0;\r
1589\r
1590 while (FceInternalIsHexaDecimalDigitCharacter (*String)) {\r
1591 //\r
1592 // If the Hex Number represented by String overflows according\r
1593 // to the range defined by UINTN, then ASSERT().\r
1594 //\r
1595 ASSERT (Result <= RShiftU64 (((UINT64) ~0) - FceInternalHexCharToUintn (*String) , 4));\r
1596\r
1597 Result = LShiftU64 (Result, 4);\r
1598 Result = Result + FceInternalHexCharToUintn (*String);\r
1599 String++;\r
1600 }\r
1601\r
1602 return Result;\r
1603}\r
1604\r
1605\r
1606CHAR16\r
1607ToUpper (\r
1608 CHAR16 a\r
1609 )\r
1610{\r
1611 if (('a' <= a) && (a <= 'z')) {\r
1612 return (CHAR16) (a - 0x20);\r
1613 } else {\r
1614 return a;\r
1615 }\r
1616}\r
1617\r
1618CHAR16\r
1619ToLower (\r
1620 CHAR16 a\r
1621 )\r
1622{\r
1623 if (('A' <= a) && (a <= 'Z')) {\r
1624 return (CHAR16) (a + 0x20);\r
1625 } else {\r
1626 return a;\r
1627 }\r
1628}\r
1629\r
1630/**\r
1631 Performs a case-insensitive comparison between a Null-terminated\r
1632 Unicode pattern string and a Null-terminated Unicode string.\r
1633\r
1634 @param String - A pointer to a Null-terminated Unicode string.\r
1635 @param Pattern - A pointer to a Null-terminated Unicode pattern string.\r
1636\r
1637\r
1638 @retval TRUE - Pattern was found in String.\r
1639 @retval FALSE - Pattern was not found in String.\r
1640\r
1641**/\r
1642BOOLEAN\r
1643MetaiMatch (\r
1644 IN CHAR16 *String,\r
1645 IN CHAR16 *Pattern\r
1646 )\r
1647{\r
1648 CHAR16 c;\r
1649 CHAR16 p;\r
1650\r
1651 assert (String != NULL);\r
1652 assert (Pattern != NULL);\r
1653\r
1654 for (;;) {\r
1655 p = *Pattern;\r
1656 Pattern += 1;\r
1657\r
1658 if (p == 0) {\r
1659 //\r
1660 // End of pattern. If end of string, TRUE match\r
1661 //\r
1662 if (*String) {\r
1663 return FALSE;\r
1664 } else {\r
1665 return TRUE;\r
1666 }\r
1667\r
1668 } else {\r
1669\r
1670 c = *String;\r
1671 if (ToUpper (c) != ToUpper (p)) {\r
1672 return FALSE;\r
1673 }\r
1674\r
1675 String += 1;\r
1676\r
1677 }\r
1678\r
1679 }\r
1680\r
1681}\r
1682/**\r
1683 Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer and\r
1684 generates a 64-bit unsigned result.\r
1685\r
1686 This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit\r
1687 unsigned value Multiplier and generates a 64-bit unsigned result. This 64-\r
1688 bit unsigned result is returned.\r
1689\r
1690 @param Multiplicand A 64-bit unsigned value.\r
1691 @param Multiplier A 32-bit unsigned value.\r
1692\r
1693 @return Multiplicand * Multiplier.\r
1694\r
1695**/\r
1696UINT64\r
1697MultU64x32 (\r
1698 IN UINT64 Multiplicand,\r
1699 IN UINT32 Multiplier\r
1700 )\r
1701{\r
1702 return Multiplicand * Multiplier;\r
1703}\r
1704\r
1705/**\r
1706 Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates\r
1707 a 64-bit unsigned result.\r
1708\r
1709 This function divides the 64-bit unsigned value Dividend by the 32-bit\r
1710 unsigned value Divisor and generates a 64-bit unsigned quotient. This\r
1711 function returns the 64-bit unsigned quotient.\r
1712\r
1713 If Divisor is 0, then ASSERT().\r
1714\r
1715 @param Dividend A 64-bit unsigned value.\r
1716 @param Divisor A 32-bit unsigned value.\r
1717\r
1718 @return Dividend / Divisor\r
1719\r
1720**/\r
1721UINT64\r
1722DivU64x32 (\r
1723 IN UINT64 Dividend,\r
1724 IN UINT32 Divisor\r
1725 )\r
1726{\r
1727 ASSERT (Divisor != 0);\r
1728 return Dividend / Divisor;\r
1729}\r
1730\r
1731/**\r
1732 Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled\r
1733 with zeros. The shifted value is returned.\r
1734\r
1735 This function shifts the 64-bit value Operand to the left by Count bits. The\r
1736 low Count bits are set to zero. The shifted value is returned.\r
1737\r
1738 If Count is greater than 63, then ASSERT().\r
1739\r
1740 @param Operand The 64-bit operand to shift left.\r
1741 @param Count The number of bits to shift left.\r
1742\r
1743 @return Operand << Count.\r
1744\r
1745**/\r
1746UINT64\r
1747LShiftU64 (\r
1748 IN UINT64 Operand,\r
1749 IN UINTN Count\r
1750 )\r
1751{\r
1752 ASSERT (Count < 64);\r
1753 return Operand << Count;\r
1754}\r
1755\r
1756/**\r
1757 Shifts a 64-bit integer right between 0 and 63 bits. This high bits are\r
1758 filled with zeros. The shifted value is returned.\r
1759\r
1760 This function shifts the 64-bit value Operand to the right by Count bits. The\r
1761 high Count bits are set to zero. The shifted value is returned.\r
1762\r
1763 If Count is greater than 63, then ASSERT().\r
1764\r
1765 @param Operand The 64-bit operand to shift right.\r
1766 @param Count The number of bits to shift right.\r
1767\r
1768 @return Operand >> Count.\r
1769\r
1770**/\r
1771UINT64\r
1772RShiftU64 (\r
1773 IN UINT64 Operand,\r
1774 IN UINTN Count\r
1775 )\r
1776\r
1777{\r
1778 ASSERT (Count < 64);\r
1779 return Operand >> Count;\r
1780}\r
1781\r
1782\r
1783/**\r
1784 Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates\r
1785 a 64-bit unsigned result and an optional 32-bit unsigned remainder.\r
1786\r
1787 This function divides the 64-bit unsigned value Dividend by the 32-bit\r
1788 unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder\r
1789 is not NULL, then the 32-bit unsigned remainder is returned in Remainder.\r
1790 This function returns the 64-bit unsigned quotient.\r
1791\r
1792 If Divisor is 0, then ASSERT().\r
1793\r
1794 @param Dividend A 64-bit unsigned value.\r
1795 @param Divisor A 32-bit unsigned value.\r
1796 @param Remainder A pointer to a 32-bit unsigned value. This parameter is\r
1797 optional and may be NULL.\r
1798\r
1799 @return Dividend / Divisor\r
1800\r
1801**/\r
1802UINT64\r
1803DivU64x32Remainder (\r
1804 IN UINT64 Dividend,\r
1805 IN UINT32 Divisor,\r
1806 OUT UINT32 *Remainder\r
1807 )\r
1808{\r
1809 ASSERT (Divisor != 0);\r
1810\r
1811 if (Remainder != NULL) {\r
1812 *Remainder = (UINT32)(Dividend % Divisor);\r
1813 }\r
1814 return Dividend / Divisor;\r
1815}\r
1816\r
1817/**\r
1818 Copies a buffer to an allocated buffer.\r
1819\r
1820 Allocates the number bytes specified by AllocationSize, copies allocationSize bytes\r
1821 from Buffer to the newly allocated buffer, and returns a pointer to the allocated\r
1822 buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
1823 is not enough memory remaining to satisfy the request, then NULL is returned.\r
1824\r
1825 If Buffer is NULL, then ASSERT().\r
1826\r
1827 @param AllocationSize The number of bytes to allocate and zero.\r
1828 @param Buffer The buffer to copy to the allocated buffer.\r
1829\r
1830 @return A pointer to the allocated buffer or NULL if allocation fails.\r
1831\r
1832**/\r
1833VOID *\r
1834FceAllocateCopyPool (\r
1835 IN UINTN AllocationSize,\r
1836 IN CONST VOID *Buffer\r
1837 )\r
1838{\r
1839 VOID *Memory;\r
1840\r
1841 Memory = NULL;\r
1842\r
1843 if ((Buffer == NULL) || (AllocationSize == 0)) {\r
1844 return Memory;\r
1845 }\r
1846\r
1847 Memory = calloc (AllocationSize, sizeof (CHAR8));\r
1848 if (Memory != NULL) {\r
1849 Memory = memcpy (Memory, Buffer, AllocationSize);\r
1850 }\r
1851 return Memory;\r
1852}\r
1853\r
1854/**\r
1855 Initializes the head node of a doubly-linked list, and returns the pointer to\r
1856 the head node of the doubly-linked list.\r
1857\r
1858 Initializes the forward and backward links of a new linked list. After\r
1859 initializing a linked list with this function, the other linked list\r
1860 functions may be used to add and remove nodes from the linked list. It is up\r
1861 to the caller of this function to allocate the memory for ListHead.\r
1862\r
1863 If ListHead is NULL, then ASSERT().\r
1864\r
1865 @param ListHead A pointer to the head node of a new doubly-linked list.\r
1866\r
1867 @return ListHead\r
1868\r
1869**/\r
1870LIST_ENTRY *\r
1871InitializeListHead (\r
1872 IN OUT LIST_ENTRY *ListHead\r
1873 )\r
1874\r
1875{\r
1876 assert (ListHead != NULL);\r
1877\r
1878 ListHead->ForwardLink = ListHead;\r
1879 ListHead->BackLink = ListHead;\r
1880 return ListHead;\r
1881}\r
1882\r
1883/**\r
1884 Adds a node to the beginning of a doubly-linked list, and returns the pointer\r
1885 to the head node of the doubly-linked list.\r
1886\r
1887 Adds the node Entry at the beginning of the doubly-linked list denoted by\r
1888 ListHead, and returns ListHead.\r
1889\r
1890 If ListHead is NULL, then ASSERT().\r
1891 If Entry is NULL, then ASSERT().\r
1892 If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
1893 InitializeListHead(), then ASSERT().\r
1894 If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number\r
1895 of nodes in ListHead, including the ListHead node, is greater than or\r
1896 equal to PcdMaximumLinkedListLength, then ASSERT().\r
1897\r
1898 @param ListHead A pointer to the head node of a doubly-linked list.\r
1899 @param Entry A pointer to a node that is to be inserted at the beginning\r
1900 of a doubly-linked list.\r
1901\r
1902 @return ListHead\r
1903\r
1904**/\r
1905LIST_ENTRY *\r
1906InsertHeadList (\r
1907 IN OUT LIST_ENTRY *ListHead,\r
1908 IN OUT LIST_ENTRY *Entry\r
1909 )\r
1910{\r
1911 assert ((ListHead != NULL) && (Entry != NULL));\r
1912\r
1913 Entry->ForwardLink = ListHead->ForwardLink;\r
1914 Entry->BackLink = ListHead;\r
1915 Entry->ForwardLink->BackLink = Entry;\r
1916 ListHead->ForwardLink = Entry;\r
1917 return ListHead;\r
1918}\r
1919\r
1920/**\r
1921 Adds a node to the end of a doubly-linked list, and returns the pointer to\r
1922 the head node of the doubly-linked list.\r
1923\r
1924 Adds the node Entry to the end of the doubly-linked list denoted by ListHead,\r
1925 and returns ListHead.\r
1926\r
1927 If ListHead is NULL, then ASSERT().\r
1928 If Entry is NULL, then ASSERT().\r
1929 If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
1930 InitializeListHead(), then ASSERT().\r
1931 If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number\r
1932 of nodes in ListHead, including the ListHead node, is greater than or\r
1933 equal to PcdMaximumLinkedListLength, then ASSERT().\r
1934\r
1935 @param ListHead A pointer to the head node of a doubly-linked list.\r
1936 @param Entry A pointer to a node that is to be added at the end of the\r
1937 doubly-linked list.\r
1938\r
1939 @return ListHead\r
1940\r
1941**/\r
1942LIST_ENTRY *\r
1943InsertTailList (\r
1944 IN OUT LIST_ENTRY *ListHead,\r
1945 IN OUT LIST_ENTRY *Entry\r
1946 )\r
1947{\r
1948 assert ((ListHead != NULL) && (Entry != NULL));\r
1949\r
1950 Entry->ForwardLink = ListHead;\r
1951 Entry->BackLink = ListHead->BackLink;\r
1952 Entry->BackLink->ForwardLink = Entry;\r
1953 ListHead->BackLink = Entry;\r
1954 return ListHead;\r
1955}\r
1956\r
1957/**\r
1958 Retrieves the first node of a doubly-linked list.\r
1959\r
1960 Returns the first node of a doubly-linked list. List must have been\r
1961 initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().\r
1962 If List is empty, then List is returned.\r
1963\r
1964 If List is NULL, then ASSERT().\r
1965 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
1966 InitializeListHead(), then ASSERT().\r
1967 If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
1968 in List, including the List node, is greater than or equal to\r
1969 PcdMaximumLinkedListLength, then ASSERT().\r
1970\r
1971 @param List A pointer to the head node of a doubly-linked list.\r
1972\r
1973 @return The first node of a doubly-linked list.\r
1974 @retval NULL The list is empty.\r
1975\r
1976**/\r
1977LIST_ENTRY *\r
1978GetFirstNode (\r
1979 IN CONST LIST_ENTRY *List\r
1980 )\r
1981{\r
1982 assert (List != NULL);\r
1983\r
1984 return List->ForwardLink;\r
1985}\r
1986\r
1987/**\r
1988 Retrieves the next node of a doubly-linked list.\r
1989\r
1990 Returns the node of a doubly-linked list that follows Node.\r
1991 List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE()\r
1992 or InitializeListHead(). If List is empty, then List is returned.\r
1993\r
1994 If List is NULL, then ASSERT().\r
1995 If Node is NULL, then ASSERT().\r
1996 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
1997 InitializeListHead(), then ASSERT().\r
1998 If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
1999 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
2000 If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
2001\r
2002 @param List A pointer to the head node of a doubly-linked list.\r
2003 @param Node A pointer to a node in the doubly-linked list.\r
2004\r
2005 @return A pointer to the next node if one exists. Otherwise List is returned.\r
2006\r
2007**/\r
2008LIST_ENTRY *\r
2009GetNextNode (\r
2010 IN CONST LIST_ENTRY *List,\r
2011 IN CONST LIST_ENTRY *Node\r
2012 )\r
2013{\r
2014 assert ((List != NULL) && (Node != NULL));\r
2015\r
2016 return Node->ForwardLink;\r
2017}\r
2018\r
2019/**\r
2020 Retrieves the previous node of a doubly-linked list.\r
2021\r
2022 Returns the node of a doubly-linked list that precedes Node.\r
2023 List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE()\r
2024 or InitializeListHead(). If List is empty, then List is returned.\r
2025\r
2026 If List is NULL, then ASSERT().\r
2027 If Node is NULL, then ASSERT().\r
2028 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
2029 InitializeListHead(), then ASSERT().\r
2030 If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
2031 PcdMaximumLinkedListLenth nodes, then ASSERT().\r
2032 If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
2033\r
2034 @param List A pointer to the head node of a doubly-linked list.\r
2035 @param Node A pointer to a node in the doubly-linked list.\r
2036\r
2037 @return A pointer to the previous node if one exists. Otherwise List is returned.\r
2038\r
2039**/\r
2040LIST_ENTRY *\r
2041GetPreviousNode (\r
2042 IN CONST LIST_ENTRY *List,\r
2043 IN CONST LIST_ENTRY *Node\r
2044 )\r
2045{\r
2046 assert ((List != NULL) && (Node != NULL));\r
2047\r
2048 return Node->BackLink;\r
2049}\r
2050\r
2051/**\r
2052 Checks to see if a doubly-linked list is empty or not.\r
2053\r
2054 Checks to see if the doubly-linked list is empty. If the linked list contains\r
2055 zero nodes, this function returns TRUE. Otherwise, it returns FALSE.\r
2056\r
2057 If ListHead is NULL, then ASSERT().\r
2058 If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
2059 InitializeListHead(), then ASSERT().\r
2060 If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
2061 in List, including the List node, is greater than or equal to\r
2062 PcdMaximumLinkedListLength, then ASSERT().\r
2063\r
2064 @param ListHead A pointer to the head node of a doubly-linked list.\r
2065\r
2066 @retval TRUE The linked list is empty.\r
2067 @retval FALSE The linked list is not empty.\r
2068\r
2069**/\r
2070BOOLEAN\r
2071IsListEmpty (\r
2072 IN CONST LIST_ENTRY *ListHead\r
2073 )\r
2074{\r
2075 assert (ListHead != NULL);\r
2076\r
2077 return (BOOLEAN)(ListHead->ForwardLink == ListHead);\r
2078}\r
2079\r
2080/**\r
2081 Determines if a node in a doubly-linked list is the head node of a the same\r
2082 doubly-linked list. This function is typically used to terminate a loop that\r
2083 traverses all the nodes in a doubly-linked list starting with the head node.\r
2084\r
2085 Returns TRUE if Node is equal to List. Returns FALSE if Node is one of the\r
2086 nodes in the doubly-linked list specified by List. List must have been\r
2087 initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().\r
2088\r
2089 If List is NULL, then ASSERT().\r
2090 If Node is NULL, then ASSERT().\r
2091 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(),\r
2092 then ASSERT().\r
2093 If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
2094 in List, including the List node, is greater than or equal to\r
2095 PcdMaximumLinkedListLength, then ASSERT().\r
2096 If PcdVerifyNodeInList is TRUE and Node is not a node in List and Node is not\r
2097 equal to List, then ASSERT().\r
2098\r
2099 @param List A pointer to the head node of a doubly-linked list.\r
2100 @param Node A pointer to a node in the doubly-linked list.\r
2101\r
2102 @retval TRUE Node is the head of the doubly-linked list pointed by List.\r
2103 @retval FALSE Node is not the head of the doubly-linked list pointed by List.\r
2104\r
2105**/\r
2106BOOLEAN\r
2107IsNull (\r
2108 IN CONST LIST_ENTRY *List,\r
2109 IN CONST LIST_ENTRY *Node\r
2110 )\r
2111{\r
2112 assert ((List != NULL) && (Node != NULL));\r
2113\r
2114 return (BOOLEAN)(Node == List);\r
2115}\r
2116\r
2117/**\r
2118 Determines if a node the last node in a doubly-linked list.\r
2119\r
2120 Returns TRUE if Node is the last node in the doubly-linked list specified by\r
2121 List. Otherwise, FALSE is returned. List must have been initialized with\r
2122 INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().\r
2123\r
2124 If List is NULL, then ASSERT().\r
2125 If Node is NULL, then ASSERT().\r
2126 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
2127 InitializeListHead(), then ASSERT().\r
2128 If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
2129 in List, including the List node, is greater than or equal to\r
2130 PcdMaximumLinkedListLength, then ASSERT().\r
2131 If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
2132\r
2133 @param List A pointer to the head node of a doubly-linked list.\r
2134 @param Node A pointer to a node in the doubly-linked list.\r
2135\r
2136 @retval TRUE Node is the last node in the linked list.\r
2137 @retval FALSE Node is not the last node in the linked list.\r
2138\r
2139**/\r
2140BOOLEAN\r
2141IsNodeAtEnd (\r
2142 IN CONST LIST_ENTRY *List,\r
2143 IN CONST LIST_ENTRY *Node\r
2144 )\r
2145{\r
2146 assert ((List != NULL) && (Node != NULL));\r
2147\r
2148 return (BOOLEAN)(!IsNull (List, Node) && (List->BackLink == Node));\r
2149}\r
2150\r
2151/**\r
2152 Removes a node from a doubly-linked list, and returns the node that follows\r
2153 the removed node.\r
2154\r
2155 Removes the node Entry from a doubly-linked list. It is up to the caller of\r
2156 this function to release the memory used by this node if that is required. On\r
2157 exit, the node following Entry in the doubly-linked list is returned. If\r
2158 Entry is the only node in the linked list, then the head node of the linked\r
2159 list is returned.\r
2160\r
2161 If Entry is NULL, then ASSERT().\r
2162 If Entry is the head node of an empty list, then ASSERT().\r
2163 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
2164 linked list containing Entry, including the Entry node, is greater than\r
2165 or equal to PcdMaximumLinkedListLength, then ASSERT().\r
2166\r
2167 @param Entry A pointer to a node in a linked list.\r
2168\r
2169 @return Entry.\r
2170\r
2171**/\r
2172LIST_ENTRY *\r
2173RemoveEntryList (\r
2174 IN CONST LIST_ENTRY *Entry\r
2175 )\r
2176{\r
2177 assert (!IsListEmpty (Entry));\r
2178\r
2179 Entry->ForwardLink->BackLink = Entry->BackLink;\r
2180 Entry->BackLink->ForwardLink = Entry->ForwardLink;\r
2181 return Entry->ForwardLink;\r
2182}\r
2183\r