]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/CommonLib.c
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / C / Common / CommonLib.c
CommitLineData
30fdf114 1/** @file\r
97fa0ee9 2Common basic Library Functions\r
30fdf114 3\r
3710ec21 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
2e351cbe 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
30fdf114 6\r
30fdf114
LG
7**/\r
8\r
9#include <stdio.h>\r
10#include <string.h>\r
11#include <stdlib.h>\r
12#include <ctype.h>\r
1be2ed90
HC
13#ifdef __GNUC__\r
14#include <unistd.h>\r
15#else\r
16#include <direct.h>\r
17#endif\r
30fdf114
LG
18#include "CommonLib.h"\r
19#include "EfiUtilityMsgs.h"\r
20\r
7dbc50bd
YZ
21#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \\r
22 do { \\r
23 ASSERT (Expression); \\r
24 if (!(Expression)) { \\r
25 return Status; \\r
26 } \\r
27 } while (FALSE)\r
28\r
30fdf114
LG
29VOID\r
30PeiZeroMem (\r
31 IN VOID *Buffer,\r
32 IN UINTN Size\r
33 )\r
34/*++\r
35\r
36Routine Description:\r
37\r
38 Set Buffer to zero for Size bytes.\r
39\r
40Arguments:\r
41\r
42 Buffer - Memory to set.\r
43\r
44 Size - Number of bytes to set\r
45\r
46Returns:\r
47\r
48 None\r
49\r
50--*/\r
51{\r
52 INT8 *Ptr;\r
53\r
54 Ptr = Buffer;\r
55 while (Size--) {\r
56 *(Ptr++) = 0;\r
57 }\r
58}\r
59\r
60VOID\r
61PeiCopyMem (\r
62 IN VOID *Destination,\r
63 IN VOID *Source,\r
64 IN UINTN Length\r
65 )\r
66/*++\r
67\r
68Routine Description:\r
69\r
70 Copy Length bytes from Source to Destination.\r
71\r
72Arguments:\r
73\r
74 Destination - Target of copy\r
75\r
76 Source - Place to copy from\r
77\r
78 Length - Number of bytes to copy\r
79\r
80Returns:\r
81\r
82 None\r
83\r
84--*/\r
85{\r
86 CHAR8 *Destination8;\r
87 CHAR8 *Source8;\r
88\r
89 Destination8 = Destination;\r
90 Source8 = Source;\r
91 while (Length--) {\r
92 *(Destination8++) = *(Source8++);\r
93 }\r
94}\r
95\r
96VOID\r
97ZeroMem (\r
98 IN VOID *Buffer,\r
99 IN UINTN Size\r
100 )\r
101{\r
102 PeiZeroMem (Buffer, Size);\r
103}\r
104\r
105VOID\r
106CopyMem (\r
107 IN VOID *Destination,\r
108 IN VOID *Source,\r
109 IN UINTN Length\r
110 )\r
111{\r
112 PeiCopyMem (Destination, Source, Length);\r
113}\r
114\r
115INTN\r
116CompareGuid (\r
117 IN EFI_GUID *Guid1,\r
118 IN EFI_GUID *Guid2\r
119 )\r
120/*++\r
121\r
122Routine Description:\r
123\r
124 Compares to GUIDs\r
125\r
126Arguments:\r
127\r
128 Guid1 - guid to compare\r
129 Guid2 - guid to compare\r
130\r
131Returns:\r
132 = 0 if Guid1 == Guid2\r
f7496d71 133 != 0 if Guid1 != Guid2\r
30fdf114
LG
134\r
135--*/\r
136{\r
137 INT32 *g1;\r
138 INT32 *g2;\r
139 INT32 r;\r
140\r
141 //\r
142 // Compare 32 bits at a time\r
143 //\r
144 g1 = (INT32 *) Guid1;\r
145 g2 = (INT32 *) Guid2;\r
146\r
147 r = g1[0] - g2[0];\r
148 r |= g1[1] - g2[1];\r
149 r |= g1[2] - g2[2];\r
150 r |= g1[3] - g2[3];\r
151\r
152 return r;\r
153}\r
154\r
155\r
156EFI_STATUS\r
157GetFileImage (\r
158 IN CHAR8 *InputFileName,\r
159 OUT CHAR8 **InputFileImage,\r
160 OUT UINT32 *BytesRead\r
161 )\r
162/*++\r
163\r
164Routine Description:\r
165\r
f7496d71 166 This function opens a file and reads it into a memory buffer. The function\r
30fdf114
LG
167 will allocate the memory buffer and returns the size of the buffer.\r
168\r
169Arguments:\r
170\r
171 InputFileName The name of the file to read.\r
172 InputFileImage A pointer to the memory buffer.\r
173 BytesRead The size of the memory buffer.\r
174\r
175Returns:\r
176\r
177 EFI_SUCCESS The function completed successfully.\r
178 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
179 EFI_ABORTED An error occurred.\r
180 EFI_OUT_OF_RESOURCES No resource to complete operations.\r
181\r
182--*/\r
183{\r
184 FILE *InputFile;\r
185 UINT32 FileSize;\r
186\r
187 //\r
188 // Verify input parameters.\r
189 //\r
190 if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {\r
191 return EFI_INVALID_PARAMETER;\r
192 }\r
193 //\r
194 // Open the file and copy contents into a memory buffer.\r
195 //\r
196 //\r
197 // Open the file\r
198 //\r
1be2ed90 199 InputFile = fopen (LongFilePath (InputFileName), "rb");\r
30fdf114
LG
200 if (InputFile == NULL) {\r
201 Error (NULL, 0, 0001, "Error opening the input file", InputFileName);\r
202 return EFI_ABORTED;\r
203 }\r
204 //\r
205 // Go to the end so that we can determine the file size\r
206 //\r
207 if (fseek (InputFile, 0, SEEK_END)) {\r
208 Error (NULL, 0, 0004, "Error reading the input file", InputFileName);\r
209 fclose (InputFile);\r
210 return EFI_ABORTED;\r
211 }\r
212 //\r
213 // Get the file size\r
214 //\r
215 FileSize = ftell (InputFile);\r
216 if (FileSize == -1) {\r
217 Error (NULL, 0, 0003, "Error parsing the input file", InputFileName);\r
218 fclose (InputFile);\r
219 return EFI_ABORTED;\r
220 }\r
221 //\r
222 // Allocate a buffer\r
223 //\r
224 *InputFileImage = malloc (FileSize);\r
225 if (*InputFileImage == NULL) {\r
226 fclose (InputFile);\r
227 return EFI_OUT_OF_RESOURCES;\r
228 }\r
229 //\r
230 // Reset to the beginning of the file\r
231 //\r
232 if (fseek (InputFile, 0, SEEK_SET)) {\r
233 Error (NULL, 0, 0004, "Error reading the input file", InputFileName);\r
234 fclose (InputFile);\r
235 free (*InputFileImage);\r
236 *InputFileImage = NULL;\r
237 return EFI_ABORTED;\r
238 }\r
239 //\r
240 // Read all of the file contents.\r
241 //\r
242 *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);\r
243 if (*BytesRead != sizeof (UINT8) * FileSize) {\r
244 Error (NULL, 0, 0004, "Error reading the input file", InputFileName);\r
245 fclose (InputFile);\r
246 free (*InputFileImage);\r
247 *InputFileImage = NULL;\r
248 return EFI_ABORTED;\r
249 }\r
250 //\r
251 // Close the file\r
252 //\r
253 fclose (InputFile);\r
254\r
255 return EFI_SUCCESS;\r
256}\r
257\r
258EFI_STATUS\r
259PutFileImage (\r
260 IN CHAR8 *OutputFileName,\r
261 IN CHAR8 *OutputFileImage,\r
262 IN UINT32 BytesToWrite\r
263 )\r
264/*++\r
265\r
266Routine Description:\r
267\r
268 This function opens a file and writes OutputFileImage into the file.\r
269\r
270Arguments:\r
271\r
272 OutputFileName The name of the file to write.\r
273 OutputFileImage A pointer to the memory buffer.\r
274 BytesToWrite The size of the memory buffer.\r
275\r
276Returns:\r
277\r
278 EFI_SUCCESS The function completed successfully.\r
279 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
280 EFI_ABORTED An error occurred.\r
281 EFI_OUT_OF_RESOURCES No resource to complete operations.\r
282\r
283--*/\r
284{\r
285 FILE *OutputFile;\r
286 UINT32 BytesWrote;\r
287\r
288 //\r
289 // Verify input parameters.\r
290 //\r
291 if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) {\r
292 return EFI_INVALID_PARAMETER;\r
293 }\r
294 //\r
295 // Open the file and copy contents into a memory buffer.\r
296 //\r
297 //\r
298 // Open the file\r
299 //\r
1be2ed90 300 OutputFile = fopen (LongFilePath (OutputFileName), "wb");\r
30fdf114
LG
301 if (OutputFile == NULL) {\r
302 Error (NULL, 0, 0001, "Error opening the output file", OutputFileName);\r
303 return EFI_ABORTED;\r
304 }\r
305\r
306 //\r
307 // Write all of the file contents.\r
308 //\r
309 BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile);\r
310 if (BytesWrote != sizeof (UINT8) * BytesToWrite) {\r
311 Error (NULL, 0, 0002, "Error writing the output file", OutputFileName);\r
312 fclose (OutputFile);\r
313 return EFI_ABORTED;\r
314 }\r
315 //\r
316 // Close the file\r
317 //\r
318 fclose (OutputFile);\r
319\r
320 return EFI_SUCCESS;\r
321}\r
322\r
323UINT8\r
324CalculateChecksum8 (\r
325 IN UINT8 *Buffer,\r
326 IN UINTN Size\r
327 )\r
328/*++\r
f7496d71 329\r
30fdf114
LG
330Routine Description:\r
331\r
332 This function calculates the value needed for a valid UINT8 checksum\r
333\r
334Arguments:\r
335\r
336 Buffer Pointer to buffer containing byte data of component.\r
337 Size Size of the buffer\r
338\r
339Returns:\r
340\r
341 The 8 bit checksum value needed.\r
342\r
343--*/\r
344{\r
345 return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));\r
346}\r
347\r
348UINT8\r
349CalculateSum8 (\r
350 IN UINT8 *Buffer,\r
351 IN UINTN Size\r
352 )\r
353/*++\r
f7496d71 354\r
30fdf114
LG
355Routine Description::\r
356\r
357 This function calculates the UINT8 sum for the requested region.\r
358\r
359Arguments:\r
360\r
361 Buffer Pointer to buffer containing byte data of component.\r
362 Size Size of the buffer\r
363\r
364Returns:\r
365\r
366 The 8 bit checksum value needed.\r
367\r
368--*/\r
369{\r
370 UINTN Index;\r
371 UINT8 Sum;\r
372\r
373 Sum = 0;\r
374\r
375 //\r
376 // Perform the byte sum for buffer\r
377 //\r
378 for (Index = 0; Index < Size; Index++) {\r
379 Sum = (UINT8) (Sum + Buffer[Index]);\r
380 }\r
381\r
382 return Sum;\r
383}\r
384\r
385UINT16\r
386CalculateChecksum16 (\r
387 IN UINT16 *Buffer,\r
388 IN UINTN Size\r
389 )\r
390/*++\r
f7496d71 391\r
30fdf114
LG
392Routine Description::\r
393\r
394 This function calculates the value needed for a valid UINT16 checksum\r
395\r
396Arguments:\r
397\r
398 Buffer Pointer to buffer containing byte data of component.\r
399 Size Size of the buffer\r
400\r
401Returns:\r
402\r
403 The 16 bit checksum value needed.\r
404\r
405--*/\r
406{\r
407 return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));\r
408}\r
409\r
410UINT16\r
411CalculateSum16 (\r
412 IN UINT16 *Buffer,\r
413 IN UINTN Size\r
414 )\r
415/*++\r
f7496d71 416\r
30fdf114
LG
417Routine Description:\r
418\r
419 This function calculates the UINT16 sum for the requested region.\r
420\r
421Arguments:\r
422\r
423 Buffer Pointer to buffer containing byte data of component.\r
424 Size Size of the buffer\r
425\r
426Returns:\r
427\r
428 The 16 bit checksum\r
429\r
430--*/\r
431{\r
432 UINTN Index;\r
433 UINT16 Sum;\r
434\r
435 Sum = 0;\r
436\r
437 //\r
438 // Perform the word sum for buffer\r
439 //\r
440 for (Index = 0; Index < Size; Index++) {\r
441 Sum = (UINT16) (Sum + Buffer[Index]);\r
442 }\r
443\r
444 return (UINT16) Sum;\r
445}\r
446\r
447EFI_STATUS\r
448PrintGuid (\r
449 IN EFI_GUID *Guid\r
450 )\r
451/*++\r
452\r
453Routine Description:\r
454\r
455 This function prints a GUID to STDOUT.\r
456\r
457Arguments:\r
458\r
459 Guid Pointer to a GUID to print.\r
460\r
461Returns:\r
462\r
463 EFI_SUCCESS The GUID was printed.\r
464 EFI_INVALID_PARAMETER The input was NULL.\r
465\r
466--*/\r
467{\r
468 if (Guid == NULL) {\r
469 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");\r
470 return EFI_INVALID_PARAMETER;\r
471 }\r
472\r
473 printf (\r
474 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",\r
fd171542 475 (unsigned) Guid->Data1,\r
30fdf114
LG
476 Guid->Data2,\r
477 Guid->Data3,\r
478 Guid->Data4[0],\r
479 Guid->Data4[1],\r
480 Guid->Data4[2],\r
481 Guid->Data4[3],\r
482 Guid->Data4[4],\r
483 Guid->Data4[5],\r
484 Guid->Data4[6],\r
485 Guid->Data4[7]\r
486 );\r
487 return EFI_SUCCESS;\r
488}\r
489\r
490EFI_STATUS\r
491PrintGuidToBuffer (\r
492 IN EFI_GUID *Guid,\r
493 IN OUT UINT8 *Buffer,\r
494 IN UINT32 BufferLen,\r
495 IN BOOLEAN Uppercase\r
496 )\r
497/*++\r
498\r
499Routine Description:\r
500\r
501 This function prints a GUID to a buffer\r
502\r
503Arguments:\r
504\r
505 Guid - Pointer to a GUID to print.\r
506 Buffer - Pointer to a user-provided buffer to print to\r
507 BufferLen - Size of the Buffer\r
508 Uppercase - If use upper case.\r
509\r
510Returns:\r
511\r
512 EFI_SUCCESS The GUID was printed.\r
513 EFI_INVALID_PARAMETER The input was NULL.\r
514 EFI_BUFFER_TOO_SMALL The input buffer was not big enough\r
f7496d71 515\r
30fdf114
LG
516--*/\r
517{\r
518 if (Guid == NULL) {\r
519 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");\r
520 return EFI_INVALID_PARAMETER;\r
521 }\r
522\r
523 if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {\r
524 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size");\r
525 return EFI_BUFFER_TOO_SMALL;\r
526 }\r
527\r
528 if (Uppercase) {\r
529 sprintf (\r
530 (CHAR8 *)Buffer,\r
531 "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
fd171542 532 (unsigned) Guid->Data1,\r
30fdf114
LG
533 Guid->Data2,\r
534 Guid->Data3,\r
535 Guid->Data4[0],\r
536 Guid->Data4[1],\r
537 Guid->Data4[2],\r
538 Guid->Data4[3],\r
539 Guid->Data4[4],\r
540 Guid->Data4[5],\r
541 Guid->Data4[6],\r
542 Guid->Data4[7]\r
543 );\r
544 } else {\r
545 sprintf (\r
546 (CHAR8 *)Buffer,\r
547 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
fd171542 548 (unsigned) Guid->Data1,\r
30fdf114
LG
549 Guid->Data2,\r
550 Guid->Data3,\r
551 Guid->Data4[0],\r
552 Guid->Data4[1],\r
553 Guid->Data4[2],\r
554 Guid->Data4[3],\r
555 Guid->Data4[4],\r
556 Guid->Data4[5],\r
557 Guid->Data4[6],\r
558 Guid->Data4[7]\r
559 );\r
560 }\r
561\r
562 return EFI_SUCCESS;\r
563}\r
564\r
565#ifdef __GNUC__\r
566\r
567size_t _filelength(int fd)\r
568{\r
569 struct stat stat_buf;\r
570 fstat(fd, &stat_buf);\r
571 return stat_buf.st_size;\r
572}\r
573\r
574#ifndef __CYGWIN__\r
575char *strlwr(char *s)\r
576{\r
577 char *p = s;\r
578 for(;*s;s++) {\r
579 *s = tolower(*s);\r
580 }\r
581 return p;\r
582}\r
583#endif\r
584#endif\r
1be2ed90
HC
585\r
586#define WINDOWS_EXTENSION_PATH "\\\\?\\"\r
587#define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"\r
588\r
589//\r
f7496d71 590// Global data to store full file path. It is not required to be free.\r
1be2ed90
HC
591//\r
592CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH];\r
593\r
594CHAR8 *\r
595LongFilePath (\r
596 IN CHAR8 *FileName\r
597 )\r
598/*++\r
599\r
600Routine Description:\r
f7496d71 601 Convert FileName to the long file path, which can support larger than 260 length.\r
1be2ed90
HC
602\r
603Arguments:\r
f7496d71 604 FileName - FileName.\r
1be2ed90
HC
605\r
606Returns:\r
607 LongFilePath A pointer to the converted long file path.\r
f7496d71 608\r
1be2ed90
HC
609--*/\r
610{\r
611#ifdef __GNUC__\r
612 //\r
f7496d71
LG
613 // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here.\r
614 // unix has no limitation on file path. Just return FileName.\r
1be2ed90
HC
615 //\r
616 return FileName;\r
617#else\r
618 CHAR8 *RootPath;\r
619 CHAR8 *PathPointer;\r
620 CHAR8 *NextPointer;\r
f7496d71 621\r
1be2ed90 622 PathPointer = (CHAR8 *) FileName;\r
f7496d71 623\r
1be2ed90
HC
624 if (FileName != NULL) {\r
625 //\r
f7496d71 626 // Add the extension string first to support long file path.\r
1be2ed90
HC
627 //\r
628 mCommonLibFullPath[0] = 0;\r
629 strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH);\r
630\r
631 if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') {\r
632 //\r
633 // network path like \\server\share to \\?\UNC\server\share\r
634 //\r
635 strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH);\r
636 FileName ++;\r
637 } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) {\r
638 //\r
f7496d71 639 // Relative file path. Convert it to absolute path.\r
1be2ed90
HC
640 //\r
641 RootPath = getcwd (NULL, 0);\r
642 if (RootPath != NULL) {\r
938cf4b9
HW
643 if (strlen (mCommonLibFullPath) + strlen (RootPath) > MAX_LONG_FILE_PATH - 1) {\r
644 Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");\r
645 free (RootPath);\r
646 return NULL;\r
647 }\r
648 strncat (mCommonLibFullPath, RootPath, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
1be2ed90 649 if (FileName[0] != '\\' && FileName[0] != '/') {\r
938cf4b9
HW
650 if (strlen (mCommonLibFullPath) + 1 > MAX_LONG_FILE_PATH - 1) {\r
651 Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");\r
652 free (RootPath);\r
653 return NULL;\r
654 }\r
1be2ed90
HC
655 //\r
656 // Attach directory separator\r
657 //\r
938cf4b9 658 strncat (mCommonLibFullPath, "\\", MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
1be2ed90
HC
659 }\r
660 free (RootPath);\r
661 }\r
662 }\r
663\r
664 //\r
665 // Construct the full file path\r
666 //\r
b3520abd
HW
667 if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) {\r
668 Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName);\r
669 return NULL;\r
670 }\r
671 strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
f7496d71 672\r
1be2ed90
HC
673 //\r
674 // Convert directory separator '/' to '\\'\r
675 //\r
676 PathPointer = (CHAR8 *) mCommonLibFullPath;\r
677 do {\r
678 if (*PathPointer == '/') {\r
679 *PathPointer = '\\';\r
680 }\r
681 } while (*PathPointer ++ != '\0');\r
f7496d71 682\r
51b8553f
HC
683 //\r
684 // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
685 //\r
686 if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {\r
687 *(PathPointer + 2) = '\0';\r
938cf4b9 688 strncat (mCommonLibFullPath, PathPointer + 3, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
51b8553f 689 }\r
f7496d71 690\r
e878891e
LG
691 //\r
692 // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
693 //\r
694 while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {\r
695 *PathPointer = '\0';\r
938cf4b9 696 strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
e878891e 697 }\r
f7496d71 698\r
1be2ed90
HC
699 //\r
700 // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
701 //\r
702 while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {\r
703 *PathPointer = '\0';\r
938cf4b9 704 strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
1be2ed90 705 }\r
e878891e 706\r
1be2ed90
HC
707 //\r
708 // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.\r
709 //\r
710 while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {\r
711 NextPointer = PathPointer + 3;\r
712 do {\r
713 PathPointer --;\r
714 } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');\r
715\r
716 if (*PathPointer == '\\') {\r
717 //\r
718 // Skip one directory\r
719 //\r
720 *PathPointer = '\0';\r
938cf4b9 721 strncat (mCommonLibFullPath, NextPointer, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
1be2ed90
HC
722 } else {\r
723 //\r
724 // No directory is found. Just break.\r
725 //\r
726 break;\r
727 }\r
728 }\r
f7496d71 729\r
1be2ed90
HC
730 PathPointer = mCommonLibFullPath;\r
731 }\r
f7496d71 732\r
1be2ed90
HC
733 return PathPointer;\r
734#endif\r
735}\r
7dbc50bd
YZ
736\r
737CHAR16\r
738InternalCharToUpper (\r
739 CHAR16 Char\r
740 )\r
741{\r
742 if (Char >= L'a' && Char <= L'z') {\r
743 return (CHAR16) (Char - (L'a' - L'A'));\r
744 }\r
745\r
746 return Char;\r
747}\r
748\r
749UINTN\r
750StrnLenS (\r
751 CONST CHAR16 *String,\r
752 UINTN MaxSize\r
753 )\r
754{\r
755 UINTN Length;\r
756\r
757 ASSERT (((UINTN) String & BIT0) == 0);\r
758\r
759 //\r
760 // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.\r
761 //\r
762 if ((String == NULL) || (MaxSize == 0)) {\r
763 return 0;\r
764 }\r
765\r
766 Length = 0;\r
767 while (String[Length] != 0) {\r
768 if (Length >= MaxSize - 1) {\r
769 return MaxSize;\r
770 }\r
771 Length++;\r
772 }\r
773 return Length;\r
774}\r
775\r
776\r
777VOID *\r
778InternalAllocatePool (\r
779 UINTN AllocationSize\r
780 )\r
781{\r
782 VOID * Memory;\r
783\r
784 Memory = malloc(AllocationSize);\r
785 ASSERT(Memory != NULL);\r
786 return Memory;\r
787}\r
788\r
789\r
790VOID *\r
791InternalReallocatePool (\r
792 UINTN OldSize,\r
793 UINTN NewSize,\r
794 VOID *OldBuffer OPTIONAL\r
795 )\r
796{\r
797 VOID *NewBuffer;\r
798\r
799 NewBuffer = AllocateZeroPool (NewSize);\r
800 if (NewBuffer != NULL && OldBuffer != NULL) {\r
801 memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));\r
802 free(OldBuffer);\r
803 }\r
804 return NewBuffer;\r
805}\r
806\r
807VOID *\r
808ReallocatePool (\r
809 UINTN OldSize,\r
810 UINTN NewSize,\r
811 VOID *OldBuffer OPTIONAL\r
812 )\r
813{\r
814 return InternalReallocatePool (OldSize, NewSize, OldBuffer);\r
815}\r
816\r
817/**\r
818 Returns the length of a Null-terminated Unicode string.\r
819\r
820 This function returns the number of Unicode characters in the Null-terminated\r
821 Unicode string specified by String.\r
822\r
823 If String is NULL, then ASSERT().\r
824 If String is not aligned on a 16-bit boundary, then ASSERT().\r
825 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
826 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
827 Null-terminator, then ASSERT().\r
828\r
829 @param String A pointer to a Null-terminated Unicode string.\r
830\r
831 @return The length of String.\r
832\r
833**/\r
834UINTN\r
835StrLen (\r
836 CONST CHAR16 *String\r
837 )\r
838{\r
839 UINTN Length;\r
840\r
841 ASSERT (String != NULL);\r
842 ASSERT (((UINTN) String & BIT0) == 0);\r
843\r
844 for (Length = 0; *String != L'\0'; String++, Length++) {\r
845 //\r
846 // If PcdMaximumUnicodeStringLength is not zero,\r
847 // length should not more than PcdMaximumUnicodeStringLength\r
848 //\r
849 }\r
850 return Length;\r
851}\r
852\r
853BOOLEAN\r
854InternalSafeStringIsOverlap (\r
855 IN VOID *Base1,\r
856 IN UINTN Size1,\r
857 IN VOID *Base2,\r
858 IN UINTN Size2\r
859 )\r
860{\r
861 if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||\r
862 (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {\r
863 return TRUE;\r
864 }\r
865 return FALSE;\r
866}\r
867\r
868BOOLEAN\r
869InternalSafeStringNoStrOverlap (\r
870 IN CHAR16 *Str1,\r
871 IN UINTN Size1,\r
872 IN CHAR16 *Str2,\r
873 IN UINTN Size2\r
874 )\r
875{\r
876 return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));\r
877}\r
878\r
7dbc50bd
YZ
879/**\r
880 Convert a Null-terminated Unicode decimal string to a value of type UINT64.\r
881\r
882 This function outputs a value of type UINT64 by interpreting the contents of\r
883 the Unicode string specified by String as a decimal number. The format of the\r
884 input Unicode string String is:\r
885\r
886 [spaces] [decimal digits].\r
887\r
888 The valid decimal digit character is in the range [0-9]. The function will\r
889 ignore the pad space, which includes spaces or tab characters, before\r
890 [decimal digits]. The running zero in the beginning of [decimal digits] will\r
891 be ignored. Then, the function stops at the first character that is a not a\r
892 valid decimal character or a Null-terminator, whichever one comes first.\r
893\r
894 If String is NULL, then ASSERT().\r
895 If Data is NULL, then ASSERT().\r
896 If String is not aligned in a 16-bit boundary, then ASSERT().\r
897 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
898 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
899 Null-terminator, then ASSERT().\r
900\r
901 If String has no valid decimal digits in the above format, then 0 is stored\r
902 at the location pointed to by Data.\r
903 If the number represented by String exceeds the range defined by UINT64, then\r
904 MAX_UINT64 is stored at the location pointed to by Data.\r
905\r
906 If EndPointer is not NULL, a pointer to the character that stopped the scan\r
907 is stored at the location pointed to by EndPointer. If String has no valid\r
908 decimal digits right after the optional pad spaces, the value of String is\r
909 stored at the location pointed to by EndPointer.\r
910\r
911 @param String Pointer to a Null-terminated Unicode string.\r
912 @param EndPointer Pointer to character that stops scan.\r
913 @param Data Pointer to the converted value.\r
914\r
915 @retval RETURN_SUCCESS Value is translated from String.\r
916 @retval RETURN_INVALID_PARAMETER If String is NULL.\r
917 If Data is NULL.\r
918 If PcdMaximumUnicodeStringLength is not\r
919 zero, and String contains more than\r
920 PcdMaximumUnicodeStringLength Unicode\r
921 characters, not including the\r
922 Null-terminator.\r
923 @retval RETURN_UNSUPPORTED If the number represented by String exceeds\r
924 the range defined by UINT64.\r
925\r
926**/\r
927RETURN_STATUS\r
928StrDecimalToUint64S (\r
929 CONST CHAR16 *String,\r
930 CHAR16 **EndPointer, OPTIONAL\r
931 UINT64 *Data\r
932 )\r
933{\r
934 ASSERT (((UINTN) String & BIT0) == 0);\r
935\r
936 //\r
937 // 1. Neither String nor Data shall be a null pointer.\r
938 //\r
939 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
940 SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
941\r
942 //\r
943 // 2. The length of String shall not be greater than RSIZE_MAX.\r
944 //\r
945 if (RSIZE_MAX != 0) {\r
946 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
947 }\r
948\r
949 if (EndPointer != NULL) {\r
950 *EndPointer = (CHAR16 *) String;\r
951 }\r
952\r
953 //\r
954 // Ignore the pad spaces (space or tab)\r
955 //\r
956 while ((*String == L' ') || (*String == L'\t')) {\r
957 String++;\r
958 }\r
959\r
960 //\r
961 // Ignore leading Zeros after the spaces\r
962 //\r
963 while (*String == L'0') {\r
964 String++;\r
965 }\r
966\r
967 *Data = 0;\r
968\r
969 while (InternalIsDecimalDigitCharacter (*String)) {\r
970 //\r
971 // If the number represented by String overflows according to the range\r
972 // defined by UINT64, then MAX_UINT64 is stored in *Data and\r
973 // RETURN_UNSUPPORTED is returned.\r
974 //\r
975 if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {\r
976 *Data = MAX_UINT64;\r
977 if (EndPointer != NULL) {\r
978 *EndPointer = (CHAR16 *) String;\r
979 }\r
980 return RETURN_UNSUPPORTED;\r
981 }\r
982\r
983 *Data = (*Data) * 10 + (*String - L'0');\r
984 String++;\r
985 }\r
986\r
987 if (EndPointer != NULL) {\r
988 *EndPointer = (CHAR16 *) String;\r
989 }\r
990 return RETURN_SUCCESS;\r
991}\r
992\r
993/**\r
994 Convert a Null-terminated Unicode hexadecimal string to a value of type\r
98a9519f 995 UINT64.\r
7dbc50bd 996\r
98a9519f 997 This function outputs a value of type UINT64 by interpreting the contents of\r
7dbc50bd
YZ
998 the Unicode string specified by String as a hexadecimal number. The format of\r
999 the input Unicode string String is:\r
1000\r
1001 [spaces][zeros][x][hexadecimal digits].\r
1002\r
1003 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
1004 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
1005 If "x" appears in the input string, it must be prefixed with at least one 0.\r
1006 The function will ignore the pad space, which includes spaces or tab\r
1007 characters, before [zeros], [x] or [hexadecimal digit]. The running zero\r
1008 before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts\r
1009 after [x] or the first valid hexadecimal digit. Then, the function stops at\r
1010 the first character that is a not a valid hexadecimal character or NULL,\r
1011 whichever one comes first.\r
1012\r
1013 If String is NULL, then ASSERT().\r
1014 If Data is NULL, then ASSERT().\r
1015 If String is not aligned in a 16-bit boundary, then ASSERT().\r
1016 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
1017 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
1018 Null-terminator, then ASSERT().\r
1019\r
1020 If String has no valid hexadecimal digits in the above format, then 0 is\r
1021 stored at the location pointed to by Data.\r
98a9519f
AB
1022 If the number represented by String exceeds the range defined by UINT64, then\r
1023 MAX_UINT64 is stored at the location pointed to by Data.\r
7dbc50bd
YZ
1024\r
1025 If EndPointer is not NULL, a pointer to the character that stopped the scan\r
1026 is stored at the location pointed to by EndPointer. If String has no valid\r
1027 hexadecimal digits right after the optional pad spaces, the value of String\r
1028 is stored at the location pointed to by EndPointer.\r
1029\r
1030 @param String Pointer to a Null-terminated Unicode string.\r
1031 @param EndPointer Pointer to character that stops scan.\r
1032 @param Data Pointer to the converted value.\r
1033\r
1034 @retval RETURN_SUCCESS Value is translated from String.\r
1035 @retval RETURN_INVALID_PARAMETER If String is NULL.\r
1036 If Data is NULL.\r
1037 If PcdMaximumUnicodeStringLength is not\r
1038 zero, and String contains more than\r
1039 PcdMaximumUnicodeStringLength Unicode\r
1040 characters, not including the\r
1041 Null-terminator.\r
1042 @retval RETURN_UNSUPPORTED If the number represented by String exceeds\r
98a9519f 1043 the range defined by UINT64.\r
7dbc50bd
YZ
1044\r
1045**/\r
1046RETURN_STATUS\r
7dbc50bd
YZ
1047StrHexToUint64S (\r
1048 CONST CHAR16 *String,\r
1049 CHAR16 **EndPointer, OPTIONAL\r
1050 UINT64 *Data\r
1051 )\r
1052{\r
1053 ASSERT (((UINTN) String & BIT0) == 0);\r
1054\r
1055 //\r
1056 // 1. Neither String nor Data shall be a null pointer.\r
1057 //\r
1058 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
1059 SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
1060\r
1061 //\r
1062 // 2. The length of String shall not be greater than RSIZE_MAX.\r
1063 //\r
1064 if (RSIZE_MAX != 0) {\r
1065 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
1066 }\r
1067\r
1068 if (EndPointer != NULL) {\r
1069 *EndPointer = (CHAR16 *) String;\r
1070 }\r
1071\r
1072 //\r
1073 // Ignore the pad spaces (space or tab)\r
1074 //\r
1075 while ((*String == L' ') || (*String == L'\t')) {\r
1076 String++;\r
1077 }\r
1078\r
1079 //\r
1080 // Ignore leading Zeros after the spaces\r
1081 //\r
1082 while (*String == L'0') {\r
1083 String++;\r
1084 }\r
1085\r
1086 if (InternalCharToUpper (*String) == L'X') {\r
1087 if (*(String - 1) != L'0') {\r
1088 *Data = 0;\r
1089 return RETURN_SUCCESS;\r
1090 }\r
1091 //\r
1092 // Skip the 'X'\r
1093 //\r
1094 String++;\r
1095 }\r
1096\r
1097 *Data = 0;\r
1098\r
1099 while (InternalIsHexaDecimalDigitCharacter (*String)) {\r
1100 //\r
1101 // If the number represented by String overflows according to the range\r
1102 // defined by UINT64, then MAX_UINT64 is stored in *Data and\r
1103 // RETURN_UNSUPPORTED is returned.\r
1104 //\r
1105 if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {\r
1106 *Data = MAX_UINT64;\r
1107 if (EndPointer != NULL) {\r
1108 *EndPointer = (CHAR16 *) String;\r
1109 }\r
1110 return RETURN_UNSUPPORTED;\r
1111 }\r
1112\r
1113 *Data = ((*Data) << 4) + InternalHexCharToUintn (*String);\r
1114 String++;\r
1115 }\r
1116\r
1117 if (EndPointer != NULL) {\r
1118 *EndPointer = (CHAR16 *) String;\r
1119 }\r
1120 return RETURN_SUCCESS;\r
1121}\r
1122\r
1123UINT64\r
1124StrDecimalToUint64 (\r
1125 CONST CHAR16 *String\r
1126 )\r
1127{\r
1128 UINT64 Result;\r
1129\r
1130 StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);\r
1131 return Result;\r
1132}\r
1133\r
1134\r
1135UINT64\r
1136StrHexToUint64 (\r
1137 CONST CHAR16 *String\r
1138 )\r
1139{\r
1140 UINT64 Result;\r
1141\r
1142 StrHexToUint64S (String, (CHAR16 **) NULL, &Result);\r
1143 return Result;\r
1144}\r
1145\r
7dbc50bd
YZ
1146UINTN\r
1147StrSize (\r
1148 CONST CHAR16 *String\r
1149 )\r
1150{\r
1151 return (StrLen (String) + 1) * sizeof (*String);\r
1152}\r
1153\r
1154\r
1155UINT64\r
1156ReadUnaligned64 (\r
1157 CONST UINT64 *Buffer\r
1158 )\r
1159{\r
1160 ASSERT (Buffer != NULL);\r
1161\r
1162 return *Buffer;\r
1163}\r
1164\r
1165UINT64\r
1166WriteUnaligned64 (\r
1167 UINT64 *Buffer,\r
1168 UINT64 Value\r
1169 )\r
1170{\r
1171 ASSERT (Buffer != NULL);\r
1172\r
1173 return *Buffer = Value;\r
1174}\r
1175\r
1176\r
1177EFI_GUID *\r
1178CopyGuid (\r
1179 EFI_GUID *DestinationGuid,\r
1180 CONST EFI_GUID *SourceGuid\r
1181 )\r
1182{\r
1183 WriteUnaligned64 (\r
1184 (UINT64*)DestinationGuid,\r
1185 ReadUnaligned64 ((CONST UINT64*)SourceGuid)\r
1186 );\r
1187 WriteUnaligned64 (\r
1188 (UINT64*)DestinationGuid + 1,\r
1189 ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)\r
1190 );\r
1191 return DestinationGuid;\r
1192}\r
1193\r
1194UINT16\r
1195SwapBytes16 (\r
1196 UINT16 Value\r
1197 )\r
1198{\r
1199 return (UINT16) ((Value<< 8) | (Value>> 8));\r
1200}\r
1201\r
1202\r
1203UINT32\r
1204SwapBytes32 (\r
1205 UINT32 Value\r
1206 )\r
1207{\r
1208 UINT32 LowerBytes;\r
1209 UINT32 HigherBytes;\r
1210\r
1211 LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value);\r
1212 HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));\r
1213 return (LowerBytes << 16 | HigherBytes);\r
1214}\r
1215\r
1216BOOLEAN\r
1217InternalIsDecimalDigitCharacter (\r
1218 CHAR16 Char\r
1219 )\r
1220{\r
1221 return (BOOLEAN) (Char >= L'0' && Char <= L'9');\r
1222}\r
1223\r
1224VOID *\r
1225InternalAllocateCopyPool (\r
1226 UINTN AllocationSize,\r
1227 CONST VOID *Buffer\r
1228 )\r
1229{\r
1230 VOID *Memory;\r
1231\r
1232 ASSERT (Buffer != NULL);\r
7dbc50bd
YZ
1233\r
1234 Memory = malloc (AllocationSize);\r
1235 if (Memory != NULL) {\r
1236 Memory = memcpy (Memory, Buffer, AllocationSize);\r
1237 }\r
1238 return Memory;\r
1239}\r
1240\r
1241BOOLEAN\r
1242InternalIsHexaDecimalDigitCharacter (\r
1243 CHAR16 Char\r
1244 )\r
1245{\r
1246\r
1247 return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||\r
1248 (Char >= L'A' && Char <= L'F') ||\r
1249 (Char >= L'a' && Char <= L'f'));\r
1250}\r
1251\r
1252UINTN\r
1253InternalHexCharToUintn (\r
1254 CHAR16 Char\r
1255 )\r
1256{\r
1257 if (InternalIsDecimalDigitCharacter (Char)) {\r
1258 return Char - L'0';\r
1259 }\r
1260\r
1261 return (10 + InternalCharToUpper (Char) - L'A');\r
1262}\r
1263\r
1264\r
1265/**\r
1266 Convert a Null-terminated Unicode hexadecimal string to a byte array.\r
1267\r
1268 This function outputs a byte array by interpreting the contents of\r
1269 the Unicode string specified by String in hexadecimal format. The format of\r
1270 the input Unicode string String is:\r
1271\r
1272 [XX]*\r
1273\r
1274 X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].\r
1275 The function decodes every two hexadecimal digit characters as one byte. The\r
1276 decoding stops after Length of characters and outputs Buffer containing\r
1277 (Length / 2) bytes.\r
1278\r
1279 If String is not aligned in a 16-bit boundary, then ASSERT().\r
1280\r
1281 If String is NULL, then ASSERT().\r
1282\r
1283 If Buffer is NULL, then ASSERT().\r
1284\r
1285 If Length is not multiple of 2, then ASSERT().\r
1286\r
1287 If PcdMaximumUnicodeStringLength is not zero and Length is greater than\r
1288 PcdMaximumUnicodeStringLength, then ASSERT().\r
1289\r
1290 If MaxBufferSize is less than (Length / 2), then ASSERT().\r
1291\r
1292 @param String Pointer to a Null-terminated Unicode string.\r
1293 @param Length The number of Unicode characters to decode.\r
1294 @param Buffer Pointer to the converted bytes array.\r
1295 @param MaxBufferSize The maximum size of Buffer.\r
1296\r
1297 @retval RETURN_SUCCESS Buffer is translated from String.\r
1298 @retval RETURN_INVALID_PARAMETER If String is NULL.\r
1299 If Data is NULL.\r
1300 If Length is not multiple of 2.\r
1301 If PcdMaximumUnicodeStringLength is not zero,\r
1302 and Length is greater than\r
1303 PcdMaximumUnicodeStringLength.\r
1304 @retval RETURN_UNSUPPORTED If Length of characters from String contain\r
1305 a character that is not valid hexadecimal\r
1306 digit characters, or a Null-terminator.\r
1307 @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2).\r
1308**/\r
1309RETURN_STATUS\r
1310StrHexToBytes (\r
1311 CONST CHAR16 *String,\r
1312 UINTN Length,\r
1313 UINT8 *Buffer,\r
1314 UINTN MaxBufferSize\r
1315 )\r
1316{\r
1317 UINTN Index;\r
1318\r
1319 ASSERT (((UINTN) String & BIT0) == 0);\r
1320\r
1321 //\r
1322 // 1. None of String or Buffer shall be a null pointer.\r
1323 //\r
1324 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
1325 SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);\r
1326\r
1327 //\r
1328 // 2. Length shall not be greater than RSIZE_MAX.\r
1329 //\r
1330 if (RSIZE_MAX != 0) {\r
1331 SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
1332 }\r
1333\r
1334 //\r
1335 // 3. Length shall not be odd.\r
1336 //\r
1337 SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);\r
1338\r
1339 //\r
1340 // 4. MaxBufferSize shall equal to or greater than Length / 2.\r
1341 //\r
1342 SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);\r
1343\r
1344 //\r
1345 // 5. String shall not contains invalid hexadecimal digits.\r
1346 //\r
1347 for (Index = 0; Index < Length; Index++) {\r
1348 if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {\r
1349 break;\r
1350 }\r
1351 }\r
1352 if (Index != Length) {\r
1353 return RETURN_UNSUPPORTED;\r
1354 }\r
1355\r
1356 //\r
1357 // Convert the hex string to bytes.\r
1358 //\r
1359 for(Index = 0; Index < Length; Index++) {\r
1360\r
1361 //\r
1362 // For even characters, write the upper nibble for each buffer byte,\r
1363 // and for even characters, the lower nibble.\r
1364 //\r
1365 if ((Index & BIT0) == 0) {\r
1366 Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4;\r
1367 } else {\r
1368 Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);\r
1369 }\r
1370 }\r
1371 return RETURN_SUCCESS;\r
1372}\r
1373\r
1374/**\r
1375 Convert a Null-terminated Unicode GUID string to a value of type\r
1376 EFI_GUID.\r
1377\r
1378 This function outputs a GUID value by interpreting the contents of\r
1379 the Unicode string specified by String. The format of the input\r
1380 Unicode string String consists of 36 characters, as follows:\r
1381\r
1382 aabbccdd-eeff-gghh-iijj-kkllmmnnoopp\r
1383\r
1384 The pairs aa - pp are two characters in the range [0-9], [a-f] and\r
1385 [A-F], with each pair representing a single byte hexadecimal value.\r
1386\r
1387 The mapping between String and the EFI_GUID structure is as follows:\r
1388 aa Data1[24:31]\r
1389 bb Data1[16:23]\r
1390 cc Data1[8:15]\r
1391 dd Data1[0:7]\r
1392 ee Data2[8:15]\r
1393 ff Data2[0:7]\r
1394 gg Data3[8:15]\r
1395 hh Data3[0:7]\r
1396 ii Data4[0:7]\r
1397 jj Data4[8:15]\r
1398 kk Data4[16:23]\r
1399 ll Data4[24:31]\r
1400 mm Data4[32:39]\r
1401 nn Data4[40:47]\r
1402 oo Data4[48:55]\r
1403 pp Data4[56:63]\r
1404\r
1405 If String is NULL, then ASSERT().\r
1406 If Guid is NULL, then ASSERT().\r
1407 If String is not aligned in a 16-bit boundary, then ASSERT().\r
1408\r
1409 @param String Pointer to a Null-terminated Unicode string.\r
1410 @param Guid Pointer to the converted GUID.\r
1411\r
1412 @retval RETURN_SUCCESS Guid is translated from String.\r
1413 @retval RETURN_INVALID_PARAMETER If String is NULL.\r
1414 If Data is NULL.\r
1415 @retval RETURN_UNSUPPORTED If String is not as the above format.\r
1416\r
1417**/\r
1418RETURN_STATUS\r
1419StrToGuid (\r
1420 CONST CHAR16 *String,\r
1421 EFI_GUID *Guid\r
1422 )\r
1423{\r
1424 RETURN_STATUS Status;\r
1425 EFI_GUID LocalGuid;\r
1426\r
1427 ASSERT (((UINTN) String & BIT0) == 0);\r
1428\r
1429 //\r
1430 // 1. None of String or Guid shall be a null pointer.\r
1431 //\r
1432 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
1433 SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);\r
1434\r
1435 //\r
1436 // Get aabbccdd in big-endian.\r
1437 //\r
1438 Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));\r
1439 if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {\r
1440 return RETURN_UNSUPPORTED;\r
1441 }\r
1442 //\r
1443 // Convert big-endian to little-endian.\r
1444 //\r
1445 LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);\r
1446 String += 2 * sizeof (LocalGuid.Data1) + 1;\r
1447\r
1448 //\r
1449 // Get eeff in big-endian.\r
1450 //\r
1451 Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));\r
1452 if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {\r
1453 return RETURN_UNSUPPORTED;\r
1454 }\r
1455 //\r
1456 // Convert big-endian to little-endian.\r
1457 //\r
1458 LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);\r
1459 String += 2 * sizeof (LocalGuid.Data2) + 1;\r
1460\r
1461 //\r
1462 // Get gghh in big-endian.\r
1463 //\r
1464 Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));\r
1465 if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {\r
1466 return RETURN_UNSUPPORTED;\r
1467 }\r
1468 //\r
1469 // Convert big-endian to little-endian.\r
1470 //\r
1471 LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);\r
1472 String += 2 * sizeof (LocalGuid.Data3) + 1;\r
1473\r
1474 //\r
1475 // Get iijj.\r
1476 //\r
1477 Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);\r
1478 if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {\r
1479 return RETURN_UNSUPPORTED;\r
1480 }\r
1481 String += 2 * 2 + 1;\r
1482\r
1483 //\r
1484 // Get kkllmmnnoopp.\r
1485 //\r
1486 Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);\r
1487 if (RETURN_ERROR (Status)) {\r
1488 return RETURN_UNSUPPORTED;\r
1489 }\r
1490\r
1491 CopyGuid (Guid, &LocalGuid);\r
1492 return RETURN_SUCCESS;\r
1493}\r
1494\r
1495/**\r
1496 Compares up to a specified length the contents of two Null-terminated Unicode strings,\r
1497 and returns the difference between the first mismatched Unicode characters.\r
1498\r
1499 This function compares the Null-terminated Unicode string FirstString to the\r
1500 Null-terminated Unicode string SecondString. At most, Length Unicode\r
1501 characters will be compared. If Length is 0, then 0 is returned. If\r
1502 FirstString is identical to SecondString, then 0 is returned. Otherwise, the\r
1503 value returned is the first mismatched Unicode character in SecondString\r
1504 subtracted from the first mismatched Unicode character in FirstString.\r
1505\r
1506 If Length > 0 and FirstString is NULL, then ASSERT().\r
1507 If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().\r
1508 If Length > 0 and SecondString is NULL, then ASSERT().\r
1509 If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().\r
1510 If PcdMaximumUnicodeStringLength is not zero, and Length is greater than\r
1511 PcdMaximumUnicodeStringLength, then ASSERT().\r
1512 If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than\r
1513 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
1514 then ASSERT().\r
1515 If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than\r
1516 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
1517 then ASSERT().\r
1518\r
1519 @param FirstString A pointer to a Null-terminated Unicode string.\r
1520 @param SecondString A pointer to a Null-terminated Unicode string.\r
1521 @param Length The maximum number of Unicode characters to compare.\r
1522\r
1523 @retval 0 FirstString is identical to SecondString.\r
1524 @return others FirstString is not identical to SecondString.\r
1525\r
1526**/\r
1527INTN\r
1528StrnCmp (\r
1529 CONST CHAR16 *FirstString,\r
1530 CONST CHAR16 *SecondString,\r
1531 UINTN Length\r
1532 )\r
1533{\r
1534 if (Length == 0) {\r
1535 return 0;\r
1536 }\r
1537\r
1538 //\r
1539 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.\r
1540 // Length tests are performed inside StrLen().\r
1541 //\r
1542 ASSERT (StrSize (FirstString) != 0);\r
1543 ASSERT (StrSize (SecondString) != 0);\r
1544\r
1545 while ((*FirstString != L'\0') &&\r
1546 (*SecondString != L'\0') &&\r
1547 (*FirstString == *SecondString) &&\r
1548 (Length > 1)) {\r
1549 FirstString++;\r
1550 SecondString++;\r
1551 Length--;\r
1552 }\r
1553\r
1554 return *FirstString - *SecondString;\r
1555}\r
1556\r
1557VOID *\r
1558AllocateCopyPool (\r
1559 UINTN AllocationSize,\r
1560 CONST VOID *Buffer\r
1561 )\r
1562{\r
1563 return InternalAllocateCopyPool (AllocationSize, Buffer);\r
1564}\r
1565\r
1566INTN\r
1567StrCmp (\r
1568 CONST CHAR16 *FirstString,\r
1569 CONST CHAR16 *SecondString\r
1570 )\r
1571{\r
1572 //\r
1573 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength\r
1574 //\r
1575 ASSERT (StrSize (FirstString) != 0);\r
1576 ASSERT (StrSize (SecondString) != 0);\r
1577\r
1578 while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {\r
1579 FirstString++;\r
1580 SecondString++;\r
1581 }\r
1582 return *FirstString - *SecondString;\r
1583}\r
1584\r
1585UINT64\r
1586SwapBytes64 (\r
1587 UINT64 Value\r
1588 )\r
1589{\r
1590 return InternalMathSwapBytes64 (Value);\r
1591}\r
1592\r
1593UINT64\r
1594InternalMathSwapBytes64 (\r
1595 UINT64 Operand\r
1596 )\r
1597{\r
1598 UINT64 LowerBytes;\r
1599 UINT64 HigherBytes;\r
1600\r
1601 LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand);\r
1602 HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));\r
1603\r
1604 return (LowerBytes << 32 | HigherBytes);\r
1605}\r
1606\r
1607RETURN_STATUS\r
1608StrToIpv4Address (\r
1609 CONST CHAR16 *String,\r
1610 CHAR16 **EndPointer,\r
1611 EFI_IPv4_ADDRESS *Address,\r
1612 UINT8 *PrefixLength\r
1613 )\r
1614{\r
1615 RETURN_STATUS Status;\r
1616 UINTN AddressIndex;\r
93afbd15 1617 UINT64 Uint64;\r
7dbc50bd
YZ
1618 EFI_IPv4_ADDRESS LocalAddress;\r
1619 UINT8 LocalPrefixLength;\r
1620 CHAR16 *Pointer;\r
1621\r
1622 LocalPrefixLength = MAX_UINT8;\r
1623 LocalAddress.Addr[0] = 0;\r
1624\r
1625 ASSERT (((UINTN) String & BIT0) == 0);\r
1626\r
1627 //\r
1628 // 1. None of String or Guid shall be a null pointer.\r
1629 //\r
1630 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
1631 SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);\r
1632\r
1633 for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {\r
1634 if (!InternalIsDecimalDigitCharacter (*Pointer)) {\r
1635 //\r
1636 // D or P contains invalid characters.\r
1637 //\r
1638 break;\r
1639 }\r
1640\r
1641 //\r
1642 // Get D or P.\r
1643 //\r
93afbd15 1644 Status = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64);\r
7dbc50bd
YZ
1645 if (RETURN_ERROR (Status)) {\r
1646 return RETURN_UNSUPPORTED;\r
1647 }\r
1648 if (AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
1649 //\r
1650 // It's P.\r
1651 //\r
93afbd15 1652 if (Uint64 > 32) {\r
7dbc50bd
YZ
1653 return RETURN_UNSUPPORTED;\r
1654 }\r
93afbd15 1655 LocalPrefixLength = (UINT8) Uint64;\r
7dbc50bd
YZ
1656 } else {\r
1657 //\r
1658 // It's D.\r
1659 //\r
93afbd15 1660 if (Uint64 > MAX_UINT8) {\r
7dbc50bd
YZ
1661 return RETURN_UNSUPPORTED;\r
1662 }\r
93afbd15 1663 LocalAddress.Addr[AddressIndex] = (UINT8) Uint64;\r
7dbc50bd
YZ
1664 AddressIndex++;\r
1665 }\r
1666\r
1667 //\r
1668 // Check the '.' or '/', depending on the AddressIndex.\r
1669 //\r
1670 if (AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
1671 if (*Pointer == L'/') {\r
1672 //\r
1673 // '/P' is in the String.\r
1674 // Skip "/" and get P in next loop.\r
1675 //\r
1676 Pointer++;\r
1677 } else {\r
1678 //\r
1679 // '/P' is not in the String.\r
1680 //\r
1681 break;\r
1682 }\r
1683 } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {\r
1684 if (*Pointer == L'.') {\r
1685 //\r
1686 // D should be followed by '.'\r
1687 //\r
1688 Pointer++;\r
1689 } else {\r
1690 return RETURN_UNSUPPORTED;\r
1691 }\r
1692 }\r
1693 }\r
1694\r
1695 if (AddressIndex < ARRAY_SIZE (Address->Addr)) {\r
1696 return RETURN_UNSUPPORTED;\r
1697 }\r
1698\r
1699 memcpy (Address, &LocalAddress, sizeof (*Address));\r
1700 if (PrefixLength != NULL) {\r
1701 *PrefixLength = LocalPrefixLength;\r
1702 }\r
1703 if (EndPointer != NULL) {\r
1704 *EndPointer = Pointer;\r
1705 }\r
1706\r
1707 return RETURN_SUCCESS;\r
1708}\r
1709\r
1710RETURN_STATUS\r
1711StrToIpv6Address (\r
1712 CONST CHAR16 *String,\r
1713 CHAR16 **EndPointer,\r
1714 EFI_IPv6_ADDRESS *Address,\r
1715 UINT8 *PrefixLength\r
1716 )\r
1717{\r
1718 RETURN_STATUS Status;\r
1719 UINTN AddressIndex;\r
93afbd15 1720 UINT64 Uint64;\r
7dbc50bd
YZ
1721 EFI_IPv6_ADDRESS LocalAddress;\r
1722 UINT8 LocalPrefixLength;\r
1723 CONST CHAR16 *Pointer;\r
1724 CHAR16 *End;\r
1725 UINTN CompressStart;\r
1726 BOOLEAN ExpectPrefix;\r
1727\r
1728 LocalPrefixLength = MAX_UINT8;\r
1729 CompressStart = ARRAY_SIZE (Address->Addr);\r
1730 ExpectPrefix = FALSE;\r
1731\r
1732 ASSERT (((UINTN) String & BIT0) == 0);\r
1733\r
1734 //\r
1735 // 1. None of String or Guid shall be a null pointer.\r
1736 //\r
1737 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
1738 SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);\r
1739\r
1740 for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {\r
1741 if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {\r
1742 if (*Pointer != L':') {\r
1743 //\r
1744 // ":" or "/" should be followed by digit characters.\r
1745 //\r
1746 return RETURN_UNSUPPORTED;\r
1747 }\r
1748\r
1749 //\r
1750 // Meet second ":" after previous ":" or "/"\r
1751 // or meet first ":" in the beginning of String.\r
1752 //\r
1753 if (ExpectPrefix) {\r
1754 //\r
1755 // ":" shall not be after "/"\r
1756 //\r
1757 return RETURN_UNSUPPORTED;\r
1758 }\r
1759\r
1760 if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
1761 //\r
1762 // "::" can only appear once.\r
1763 // "::" can only appear when address is not full length.\r
1764 //\r
1765 return RETURN_UNSUPPORTED;\r
1766 } else {\r
1767 //\r
1768 // Remember the start of zero compressing.\r
1769 //\r
1770 CompressStart = AddressIndex;\r
1771 Pointer++;\r
1772\r
1773 if (CompressStart == 0) {\r
1774 if (*Pointer != L':') {\r
1775 //\r
1776 // Single ":" shall not be in the beginning of String.\r
1777 //\r
1778 return RETURN_UNSUPPORTED;\r
1779 }\r
1780 Pointer++;\r
1781 }\r
1782 }\r
1783 }\r
1784\r
1785 if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {\r
1786 if (*Pointer == L'/') {\r
1787 //\r
1788 // Might be optional "/P" after "::".\r
1789 //\r
1790 if (CompressStart != AddressIndex) {\r
1791 return RETURN_UNSUPPORTED;\r
1792 }\r
1793 } else {\r
1794 break;\r
1795 }\r
1796 } else {\r
1797 if (!ExpectPrefix) {\r
1798 //\r
1799 // Get X.\r
1800 //\r
93afbd15 1801 Status = StrHexToUint64S (Pointer, &End, &Uint64);\r
7dbc50bd
YZ
1802 if (RETURN_ERROR (Status) || End - Pointer > 4) {\r
1803 //\r
1804 // Number of hexadecimal digit characters is no more than 4.\r
1805 //\r
1806 return RETURN_UNSUPPORTED;\r
1807 }\r
1808 Pointer = End;\r
1809 //\r
93afbd15 1810 // Uint64 won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.\r
7dbc50bd
YZ
1811 //\r
1812 ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));\r
93afbd15
AB
1813 LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uint64 >> 8);\r
1814 LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64;\r
7dbc50bd
YZ
1815 AddressIndex += 2;\r
1816 } else {\r
1817 //\r
1818 // Get P, then exit the loop.\r
1819 //\r
93afbd15
AB
1820 Status = StrDecimalToUint64S (Pointer, &End, &Uint64);\r
1821 if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) {\r
7dbc50bd
YZ
1822 //\r
1823 // Prefix length should not exceed 128.\r
1824 //\r
1825 return RETURN_UNSUPPORTED;\r
1826 }\r
93afbd15 1827 LocalPrefixLength = (UINT8) Uint64;\r
7dbc50bd
YZ
1828 Pointer = End;\r
1829 break;\r
1830 }\r
1831 }\r
1832\r
1833 //\r
1834 // Skip ':' or "/"\r
1835 //\r
1836 if (*Pointer == L'/') {\r
1837 ExpectPrefix = TRUE;\r
1838 } else if (*Pointer == L':') {\r
1839 if (AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
1840 //\r
1841 // Meet additional ":" after all 8 16-bit address\r
1842 //\r
1843 break;\r
1844 }\r
1845 } else {\r
1846 //\r
1847 // Meet other character that is not "/" or ":" after all 8 16-bit address\r
1848 //\r
1849 break;\r
1850 }\r
1851 Pointer++;\r
1852 }\r
1853\r
1854 if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||\r
1855 (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))\r
1856 ) {\r
1857 //\r
1858 // Full length of address shall not have compressing zeros.\r
1859 // Non-full length of address shall have compressing zeros.\r
1860 //\r
1861 return RETURN_UNSUPPORTED;\r
1862 }\r
1863 memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);\r
7dbc50bd 1864 if (AddressIndex > CompressStart) {\r
3710ec21 1865 memset (&Address->Addr[CompressStart], 0, ARRAY_SIZE (Address->Addr) - AddressIndex);\r
7dbc50bd
YZ
1866 memcpy (\r
1867 &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],\r
1868 &LocalAddress.Addr[CompressStart],\r
1869 AddressIndex - CompressStart\r
1870 );\r
1871 }\r
1872\r
1873 if (PrefixLength != NULL) {\r
1874 *PrefixLength = LocalPrefixLength;\r
1875 }\r
1876 if (EndPointer != NULL) {\r
1877 *EndPointer = (CHAR16 *) Pointer;\r
1878 }\r
1879\r
1880 return RETURN_SUCCESS;\r
1881}\r
1882\r
1883\r
1884RETURN_STATUS\r
1885UnicodeStrToAsciiStrS (\r
1886 CONST CHAR16 *Source,\r
1887 CHAR8 *Destination,\r
1888 UINTN DestMax\r
1889 )\r
1890{\r
1891 UINTN SourceLen;\r
1892\r
1893 ASSERT (((UINTN) Source & BIT0) == 0);\r
1894\r
1895 //\r
1896 // 1. Neither Destination nor Source shall be a null pointer.\r
1897 //\r
1898 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
1899 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
1900\r
1901 //\r
1902 // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.\r
1903 //\r
1904 if (ASCII_RSIZE_MAX != 0) {\r
1905 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
1906 }\r
1907 if (RSIZE_MAX != 0) {\r
1908 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
1909 }\r
1910\r
1911 //\r
1912 // 3. DestMax shall not equal zero.\r
1913 //\r
1914 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
1915\r
1916 //\r
1917 // 4. DestMax shall be greater than StrnLenS (Source, DestMax).\r
1918 //\r
1919 SourceLen = StrnLenS (Source, DestMax);\r
1920 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
1921\r
1922 //\r
1923 // 5. Copying shall not take place between objects that overlap.\r
1924 //\r
1925 SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);\r
1926\r
1927 //\r
1928 // convert string\r
1929 //\r
1930 while (*Source != '\0') {\r
1931 //\r
1932 // If any Unicode characters in Source contain\r
1933 // non-zero value in the upper 8 bits, then ASSERT().\r
1934 //\r
1935 ASSERT (*Source < 0x100);\r
1936 *(Destination++) = (CHAR8) *(Source++);\r
1937 }\r
1938 *Destination = '\0';\r
1939\r
1940 return RETURN_SUCCESS;\r
1941}\r
1942\r
1943RETURN_STATUS\r
1944StrCpyS (\r
1945 CHAR16 *Destination,\r
1946 UINTN DestMax,\r
1947 CONST CHAR16 *Source\r
1948 )\r
1949{\r
1950 UINTN SourceLen;\r
1951\r
1952 ASSERT (((UINTN) Destination & BIT0) == 0);\r
1953 ASSERT (((UINTN) Source & BIT0) == 0);\r
1954\r
1955 //\r
1956 // 1. Neither Destination nor Source shall be a null pointer.\r
1957 //\r
1958 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
1959 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
1960\r
1961 //\r
1962 // 2. DestMax shall not be greater than RSIZE_MAX.\r
1963 //\r
1964 if (RSIZE_MAX != 0) {\r
1965 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
1966 }\r
1967\r
1968 //\r
1969 // 3. DestMax shall not equal zero.\r
1970 //\r
1971 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
1972\r
1973 //\r
1974 // 4. DestMax shall be greater than StrnLenS(Source, DestMax).\r
1975 //\r
1976 SourceLen = StrnLenS (Source, DestMax);\r
1977 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
1978\r
1979 //\r
1980 // 5. Copying shall not take place between objects that overlap.\r
1981 //\r
1982 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
1983\r
1984 //\r
1985 // The StrCpyS function copies the string pointed to by Source (including the terminating\r
1986 // null character) into the array pointed to by Destination.\r
1987 //\r
1988 while (*Source != 0) {\r
1989 *(Destination++) = *(Source++);\r
1990 }\r
1991 *Destination = 0;\r
1992\r
1993 return RETURN_SUCCESS;\r
1994}\r
1995\r
1996VOID *\r
1997AllocateZeroPool (\r
1998 UINTN AllocationSize\r
1999 )\r
2000{\r
2001 VOID * Memory;\r
2002 Memory = malloc(AllocationSize);\r
2003 ASSERT (Memory != NULL);\r
2004 if (Memory == NULL) {\r
2005 fprintf(stderr, "Not memory for malloc\n");\r
2006 }\r
2007 memset(Memory, 0, AllocationSize);\r
2008 return Memory;\r
2009}\r
2010\r
2011VOID *\r
2012AllocatePool (\r
2013 UINTN AllocationSize\r
2014 )\r
2015{\r
2016 return InternalAllocatePool (AllocationSize);\r
2017}\r
2018\r
2019UINT16\r
2020WriteUnaligned16 (\r
2021 UINT16 *Buffer,\r
2022 UINT16 Value\r
2023 )\r
2024{\r
2025 ASSERT (Buffer != NULL);\r
2026\r
2027 return *Buffer = Value;\r
2028}\r
2029\r
2030UINT16\r
2031ReadUnaligned16 (\r
2032 CONST UINT16 *Buffer\r
2033 )\r
2034{\r
2035 ASSERT (Buffer != NULL);\r
2036\r
2037 return *Buffer;\r
2038}\r
2039/**\r
2040 Return whether the integer string is a hex string.\r
2041\r
2042 @param Str The integer string\r
2043\r
2044 @retval TRUE Hex string\r
2045 @retval FALSE Decimal string\r
2046\r
2047**/\r
2048BOOLEAN\r
2049IsHexStr (\r
2050 CHAR16 *Str\r
2051 )\r
2052{\r
2053 //\r
fb0b35e0 2054 // skip preceding white space\r
7dbc50bd
YZ
2055 //\r
2056 while ((*Str != 0) && *Str == L' ') {\r
2057 Str ++;\r
2058 }\r
2059 //\r
fb0b35e0 2060 // skip preceding zeros\r
7dbc50bd
YZ
2061 //\r
2062 while ((*Str != 0) && *Str == L'0') {\r
2063 Str ++;\r
2064 }\r
2065\r
2066 return (BOOLEAN) (*Str == L'x' || *Str == L'X');\r
2067}\r
2068\r
2069/**\r
2070\r
2071 Convert integer string to uint.\r
2072\r
2073 @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.\r
2074\r
2075 @return A UINTN value represented by Str\r
2076\r
2077**/\r
2078UINTN\r
2079Strtoi (\r
2080 CHAR16 *Str\r
2081 )\r
2082{\r
2083 if (IsHexStr (Str)) {\r
76e5f493 2084 return (UINTN)StrHexToUint64 (Str);\r
7dbc50bd 2085 } else {\r
76e5f493 2086 return (UINTN)StrDecimalToUint64 (Str);\r
7dbc50bd
YZ
2087 }\r
2088}\r
2089\r
2090/**\r
2091\r
2092 Convert integer string to 64 bit data.\r
2093\r
2094 @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.\r
2095 @param Data A pointer to the UINT64 value represented by Str\r
2096\r
2097**/\r
2098VOID\r
2099Strtoi64 (\r
2100 CHAR16 *Str,\r
2101 UINT64 *Data\r
2102 )\r
2103{\r
2104 if (IsHexStr (Str)) {\r
2105 *Data = StrHexToUint64 (Str);\r
2106 } else {\r
2107 *Data = StrDecimalToUint64 (Str);\r
2108 }\r
2109}\r
2110\r
2111/**\r
2112 Converts a Unicode string to ASCII string.\r
2113\r
2114 @param Str The equivalent Unicode string\r
2115 @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points\r
2116 to the next ASCII string next to it\r
2117\r
2118**/\r
2119VOID\r
2120StrToAscii (\r
2121 CHAR16 *Str,\r
2122 CHAR8 **AsciiStr\r
2123 )\r
2124{\r
2125 CHAR8 *Dest;\r
2126\r
2127 Dest = *AsciiStr;\r
2128 while (!IS_NULL (*Str)) {\r
2129 *(Dest++) = (CHAR8) *(Str++);\r
2130 }\r
2131 *Dest = 0;\r
2132\r
2133 //\r
2134 // Return the string next to it\r
2135 //\r
2136 *AsciiStr = Dest + 1;\r
2137}\r
2138\r
2139/**\r
2140 Gets current sub-string from a string list, before return\r
2141 the list header is moved to next sub-string. The sub-string is separated\r
2142 by the specified character. For example, the separator is ',', the string\r
2143 list is "2,0,3", it returns "2", the remain list move to "0,3"\r
2144\r
2145 @param List A string list separated by the specified separator\r
2146 @param Separator The separator character\r
2147\r
2148 @return A pointer to the current sub-string\r
2149\r
2150**/\r
2151CHAR16 *\r
2152SplitStr (\r
2153 CHAR16 **List,\r
2154 CHAR16 Separator\r
2155 )\r
2156{\r
2157 CHAR16 *Str;\r
2158 CHAR16 *ReturnStr;\r
2159\r
2160 Str = *List;\r
2161 ReturnStr = Str;\r
2162\r
2163 if (IS_NULL (*Str)) {\r
2164 return ReturnStr;\r
2165 }\r
2166\r
2167 //\r
2168 // Find first occurrence of the separator\r
2169 //\r
2170 while (!IS_NULL (*Str)) {\r
2171 if (*Str == Separator) {\r
2172 break;\r
2173 }\r
2174 Str++;\r
2175 }\r
2176\r
2177 if (*Str == Separator) {\r
2178 //\r
2179 // Find a sub-string, terminate it\r
2180 //\r
2181 *Str = L'\0';\r
2182 Str++;\r
2183 }\r
2184\r
2185 //\r
2186 // Move to next sub-string\r
2187 //\r
2188 *List = Str;\r
2189 return ReturnStr;\r
2190}\r
2191\r