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