]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/CommonLib.c
There is a limitation on WINDOWS OS for the length of entire file path can’t be large...
[mirror_edk2.git] / BaseTools / Source / C / Common / CommonLib.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
1be2ed90 3Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
40d841f6 4This program and the accompanying materials \r
30fdf114
LG
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 CommonLib.c\r
15\r
16Abstract:\r
17\r
18 Common basic Library Functions\r
19 \r
20**/\r
21\r
22#include <stdio.h>\r
23#include <string.h>\r
24#include <stdlib.h>\r
25#include <ctype.h>\r
1be2ed90
HC
26#ifdef __GNUC__\r
27#include <unistd.h>\r
28#else\r
29#include <direct.h>\r
30#endif\r
30fdf114
LG
31#include "CommonLib.h"\r
32#include "EfiUtilityMsgs.h"\r
33\r
34VOID\r
35PeiZeroMem (\r
36 IN VOID *Buffer,\r
37 IN UINTN Size\r
38 )\r
39/*++\r
40\r
41Routine Description:\r
42\r
43 Set Buffer to zero for Size bytes.\r
44\r
45Arguments:\r
46\r
47 Buffer - Memory to set.\r
48\r
49 Size - Number of bytes to set\r
50\r
51Returns:\r
52\r
53 None\r
54\r
55--*/\r
56{\r
57 INT8 *Ptr;\r
58\r
59 Ptr = Buffer;\r
60 while (Size--) {\r
61 *(Ptr++) = 0;\r
62 }\r
63}\r
64\r
65VOID\r
66PeiCopyMem (\r
67 IN VOID *Destination,\r
68 IN VOID *Source,\r
69 IN UINTN Length\r
70 )\r
71/*++\r
72\r
73Routine Description:\r
74\r
75 Copy Length bytes from Source to Destination.\r
76\r
77Arguments:\r
78\r
79 Destination - Target of copy\r
80\r
81 Source - Place to copy from\r
82\r
83 Length - Number of bytes to copy\r
84\r
85Returns:\r
86\r
87 None\r
88\r
89--*/\r
90{\r
91 CHAR8 *Destination8;\r
92 CHAR8 *Source8;\r
93\r
94 Destination8 = Destination;\r
95 Source8 = Source;\r
96 while (Length--) {\r
97 *(Destination8++) = *(Source8++);\r
98 }\r
99}\r
100\r
101VOID\r
102ZeroMem (\r
103 IN VOID *Buffer,\r
104 IN UINTN Size\r
105 )\r
106{\r
107 PeiZeroMem (Buffer, Size);\r
108}\r
109\r
110VOID\r
111CopyMem (\r
112 IN VOID *Destination,\r
113 IN VOID *Source,\r
114 IN UINTN Length\r
115 )\r
116{\r
117 PeiCopyMem (Destination, Source, Length);\r
118}\r
119\r
120INTN\r
121CompareGuid (\r
122 IN EFI_GUID *Guid1,\r
123 IN EFI_GUID *Guid2\r
124 )\r
125/*++\r
126\r
127Routine Description:\r
128\r
129 Compares to GUIDs\r
130\r
131Arguments:\r
132\r
133 Guid1 - guid to compare\r
134 Guid2 - guid to compare\r
135\r
136Returns:\r
137 = 0 if Guid1 == Guid2\r
138 != 0 if Guid1 != Guid2 \r
139\r
140--*/\r
141{\r
142 INT32 *g1;\r
143 INT32 *g2;\r
144 INT32 r;\r
145\r
146 //\r
147 // Compare 32 bits at a time\r
148 //\r
149 g1 = (INT32 *) Guid1;\r
150 g2 = (INT32 *) Guid2;\r
151\r
152 r = g1[0] - g2[0];\r
153 r |= g1[1] - g2[1];\r
154 r |= g1[2] - g2[2];\r
155 r |= g1[3] - g2[3];\r
156\r
157 return r;\r
158}\r
159\r
160\r
161EFI_STATUS\r
162GetFileImage (\r
163 IN CHAR8 *InputFileName,\r
164 OUT CHAR8 **InputFileImage,\r
165 OUT UINT32 *BytesRead\r
166 )\r
167/*++\r
168\r
169Routine Description:\r
170\r
171 This function opens a file and reads it into a memory buffer. The function \r
172 will allocate the memory buffer and returns the size of the buffer.\r
173\r
174Arguments:\r
175\r
176 InputFileName The name of the file to read.\r
177 InputFileImage A pointer to the memory buffer.\r
178 BytesRead The size of the memory buffer.\r
179\r
180Returns:\r
181\r
182 EFI_SUCCESS The function completed successfully.\r
183 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
184 EFI_ABORTED An error occurred.\r
185 EFI_OUT_OF_RESOURCES No resource to complete operations.\r
186\r
187--*/\r
188{\r
189 FILE *InputFile;\r
190 UINT32 FileSize;\r
191\r
192 //\r
193 // Verify input parameters.\r
194 //\r
195 if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {\r
196 return EFI_INVALID_PARAMETER;\r
197 }\r
198 //\r
199 // Open the file and copy contents into a memory buffer.\r
200 //\r
201 //\r
202 // Open the file\r
203 //\r
1be2ed90 204 InputFile = fopen (LongFilePath (InputFileName), "rb");\r
30fdf114
LG
205 if (InputFile == NULL) {\r
206 Error (NULL, 0, 0001, "Error opening the input file", InputFileName);\r
207 return EFI_ABORTED;\r
208 }\r
209 //\r
210 // Go to the end so that we can determine the file size\r
211 //\r
212 if (fseek (InputFile, 0, SEEK_END)) {\r
213 Error (NULL, 0, 0004, "Error reading the input file", InputFileName);\r
214 fclose (InputFile);\r
215 return EFI_ABORTED;\r
216 }\r
217 //\r
218 // Get the file size\r
219 //\r
220 FileSize = ftell (InputFile);\r
221 if (FileSize == -1) {\r
222 Error (NULL, 0, 0003, "Error parsing the input file", InputFileName);\r
223 fclose (InputFile);\r
224 return EFI_ABORTED;\r
225 }\r
226 //\r
227 // Allocate a buffer\r
228 //\r
229 *InputFileImage = malloc (FileSize);\r
230 if (*InputFileImage == NULL) {\r
231 fclose (InputFile);\r
232 return EFI_OUT_OF_RESOURCES;\r
233 }\r
234 //\r
235 // Reset to the beginning of the file\r
236 //\r
237 if (fseek (InputFile, 0, SEEK_SET)) {\r
238 Error (NULL, 0, 0004, "Error reading the input file", InputFileName);\r
239 fclose (InputFile);\r
240 free (*InputFileImage);\r
241 *InputFileImage = NULL;\r
242 return EFI_ABORTED;\r
243 }\r
244 //\r
245 // Read all of the file contents.\r
246 //\r
247 *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);\r
248 if (*BytesRead != sizeof (UINT8) * FileSize) {\r
249 Error (NULL, 0, 0004, "Error reading the input file", InputFileName);\r
250 fclose (InputFile);\r
251 free (*InputFileImage);\r
252 *InputFileImage = NULL;\r
253 return EFI_ABORTED;\r
254 }\r
255 //\r
256 // Close the file\r
257 //\r
258 fclose (InputFile);\r
259\r
260 return EFI_SUCCESS;\r
261}\r
262\r
263EFI_STATUS\r
264PutFileImage (\r
265 IN CHAR8 *OutputFileName,\r
266 IN CHAR8 *OutputFileImage,\r
267 IN UINT32 BytesToWrite\r
268 )\r
269/*++\r
270\r
271Routine Description:\r
272\r
273 This function opens a file and writes OutputFileImage into the file.\r
274\r
275Arguments:\r
276\r
277 OutputFileName The name of the file to write.\r
278 OutputFileImage A pointer to the memory buffer.\r
279 BytesToWrite The size of the memory buffer.\r
280\r
281Returns:\r
282\r
283 EFI_SUCCESS The function completed successfully.\r
284 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
285 EFI_ABORTED An error occurred.\r
286 EFI_OUT_OF_RESOURCES No resource to complete operations.\r
287\r
288--*/\r
289{\r
290 FILE *OutputFile;\r
291 UINT32 BytesWrote;\r
292\r
293 //\r
294 // Verify input parameters.\r
295 //\r
296 if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) {\r
297 return EFI_INVALID_PARAMETER;\r
298 }\r
299 //\r
300 // Open the file and copy contents into a memory buffer.\r
301 //\r
302 //\r
303 // Open the file\r
304 //\r
1be2ed90 305 OutputFile = fopen (LongFilePath (OutputFileName), "wb");\r
30fdf114
LG
306 if (OutputFile == NULL) {\r
307 Error (NULL, 0, 0001, "Error opening the output file", OutputFileName);\r
308 return EFI_ABORTED;\r
309 }\r
310\r
311 //\r
312 // Write all of the file contents.\r
313 //\r
314 BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile);\r
315 if (BytesWrote != sizeof (UINT8) * BytesToWrite) {\r
316 Error (NULL, 0, 0002, "Error writing the output file", OutputFileName);\r
317 fclose (OutputFile);\r
318 return EFI_ABORTED;\r
319 }\r
320 //\r
321 // Close the file\r
322 //\r
323 fclose (OutputFile);\r
324\r
325 return EFI_SUCCESS;\r
326}\r
327\r
328UINT8\r
329CalculateChecksum8 (\r
330 IN UINT8 *Buffer,\r
331 IN UINTN Size\r
332 )\r
333/*++\r
334 \r
335Routine Description:\r
336\r
337 This function calculates the value needed for a valid UINT8 checksum\r
338\r
339Arguments:\r
340\r
341 Buffer Pointer to buffer containing byte data of component.\r
342 Size Size of the buffer\r
343\r
344Returns:\r
345\r
346 The 8 bit checksum value needed.\r
347\r
348--*/\r
349{\r
350 return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));\r
351}\r
352\r
353UINT8\r
354CalculateSum8 (\r
355 IN UINT8 *Buffer,\r
356 IN UINTN Size\r
357 )\r
358/*++\r
359 \r
360Routine Description::\r
361\r
362 This function calculates the UINT8 sum for the requested region.\r
363\r
364Arguments:\r
365\r
366 Buffer Pointer to buffer containing byte data of component.\r
367 Size Size of the buffer\r
368\r
369Returns:\r
370\r
371 The 8 bit checksum value needed.\r
372\r
373--*/\r
374{\r
375 UINTN Index;\r
376 UINT8 Sum;\r
377\r
378 Sum = 0;\r
379\r
380 //\r
381 // Perform the byte sum for buffer\r
382 //\r
383 for (Index = 0; Index < Size; Index++) {\r
384 Sum = (UINT8) (Sum + Buffer[Index]);\r
385 }\r
386\r
387 return Sum;\r
388}\r
389\r
390UINT16\r
391CalculateChecksum16 (\r
392 IN UINT16 *Buffer,\r
393 IN UINTN Size\r
394 )\r
395/*++\r
396 \r
397Routine Description::\r
398\r
399 This function calculates the value needed for a valid UINT16 checksum\r
400\r
401Arguments:\r
402\r
403 Buffer Pointer to buffer containing byte data of component.\r
404 Size Size of the buffer\r
405\r
406Returns:\r
407\r
408 The 16 bit checksum value needed.\r
409\r
410--*/\r
411{\r
412 return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));\r
413}\r
414\r
415UINT16\r
416CalculateSum16 (\r
417 IN UINT16 *Buffer,\r
418 IN UINTN Size\r
419 )\r
420/*++\r
421 \r
422Routine Description:\r
423\r
424 This function calculates the UINT16 sum for the requested region.\r
425\r
426Arguments:\r
427\r
428 Buffer Pointer to buffer containing byte data of component.\r
429 Size Size of the buffer\r
430\r
431Returns:\r
432\r
433 The 16 bit checksum\r
434\r
435--*/\r
436{\r
437 UINTN Index;\r
438 UINT16 Sum;\r
439\r
440 Sum = 0;\r
441\r
442 //\r
443 // Perform the word sum for buffer\r
444 //\r
445 for (Index = 0; Index < Size; Index++) {\r
446 Sum = (UINT16) (Sum + Buffer[Index]);\r
447 }\r
448\r
449 return (UINT16) Sum;\r
450}\r
451\r
452EFI_STATUS\r
453PrintGuid (\r
454 IN EFI_GUID *Guid\r
455 )\r
456/*++\r
457\r
458Routine Description:\r
459\r
460 This function prints a GUID to STDOUT.\r
461\r
462Arguments:\r
463\r
464 Guid Pointer to a GUID to print.\r
465\r
466Returns:\r
467\r
468 EFI_SUCCESS The GUID was printed.\r
469 EFI_INVALID_PARAMETER The input was NULL.\r
470\r
471--*/\r
472{\r
473 if (Guid == NULL) {\r
474 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");\r
475 return EFI_INVALID_PARAMETER;\r
476 }\r
477\r
478 printf (\r
479 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",\r
fd171542 480 (unsigned) Guid->Data1,\r
30fdf114
LG
481 Guid->Data2,\r
482 Guid->Data3,\r
483 Guid->Data4[0],\r
484 Guid->Data4[1],\r
485 Guid->Data4[2],\r
486 Guid->Data4[3],\r
487 Guid->Data4[4],\r
488 Guid->Data4[5],\r
489 Guid->Data4[6],\r
490 Guid->Data4[7]\r
491 );\r
492 return EFI_SUCCESS;\r
493}\r
494\r
495EFI_STATUS\r
496PrintGuidToBuffer (\r
497 IN EFI_GUID *Guid,\r
498 IN OUT UINT8 *Buffer,\r
499 IN UINT32 BufferLen,\r
500 IN BOOLEAN Uppercase\r
501 )\r
502/*++\r
503\r
504Routine Description:\r
505\r
506 This function prints a GUID to a buffer\r
507\r
508Arguments:\r
509\r
510 Guid - Pointer to a GUID to print.\r
511 Buffer - Pointer to a user-provided buffer to print to\r
512 BufferLen - Size of the Buffer\r
513 Uppercase - If use upper case.\r
514\r
515Returns:\r
516\r
517 EFI_SUCCESS The GUID was printed.\r
518 EFI_INVALID_PARAMETER The input was NULL.\r
519 EFI_BUFFER_TOO_SMALL The input buffer was not big enough\r
520 \r
521--*/\r
522{\r
523 if (Guid == NULL) {\r
524 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");\r
525 return EFI_INVALID_PARAMETER;\r
526 }\r
527\r
528 if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {\r
529 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size");\r
530 return EFI_BUFFER_TOO_SMALL;\r
531 }\r
532\r
533 if (Uppercase) {\r
534 sprintf (\r
535 (CHAR8 *)Buffer,\r
536 "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
fd171542 537 (unsigned) Guid->Data1,\r
30fdf114
LG
538 Guid->Data2,\r
539 Guid->Data3,\r
540 Guid->Data4[0],\r
541 Guid->Data4[1],\r
542 Guid->Data4[2],\r
543 Guid->Data4[3],\r
544 Guid->Data4[4],\r
545 Guid->Data4[5],\r
546 Guid->Data4[6],\r
547 Guid->Data4[7]\r
548 );\r
549 } else {\r
550 sprintf (\r
551 (CHAR8 *)Buffer,\r
552 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
fd171542 553 (unsigned) Guid->Data1,\r
30fdf114
LG
554 Guid->Data2,\r
555 Guid->Data3,\r
556 Guid->Data4[0],\r
557 Guid->Data4[1],\r
558 Guid->Data4[2],\r
559 Guid->Data4[3],\r
560 Guid->Data4[4],\r
561 Guid->Data4[5],\r
562 Guid->Data4[6],\r
563 Guid->Data4[7]\r
564 );\r
565 }\r
566\r
567 return EFI_SUCCESS;\r
568}\r
569\r
570#ifdef __GNUC__\r
571\r
572size_t _filelength(int fd)\r
573{\r
574 struct stat stat_buf;\r
575 fstat(fd, &stat_buf);\r
576 return stat_buf.st_size;\r
577}\r
578\r
579#ifndef __CYGWIN__\r
580char *strlwr(char *s)\r
581{\r
582 char *p = s;\r
583 for(;*s;s++) {\r
584 *s = tolower(*s);\r
585 }\r
586 return p;\r
587}\r
588#endif\r
589#endif\r
1be2ed90
HC
590\r
591#define WINDOWS_EXTENSION_PATH "\\\\?\\"\r
592#define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"\r
593\r
594//\r
595// Global data to store full file path. It is not required to be free. \r
596//\r
597CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH];\r
598\r
599CHAR8 *\r
600LongFilePath (\r
601 IN CHAR8 *FileName\r
602 )\r
603/*++\r
604\r
605Routine Description:\r
606 Convert FileName to the long file path, which can support larger than 260 length. \r
607\r
608Arguments:\r
609 FileName - FileName. \r
610\r
611Returns:\r
612 LongFilePath A pointer to the converted long file path.\r
613 \r
614--*/\r
615{\r
616#ifdef __GNUC__\r
617 //\r
618 // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here. \r
619 // unix has no limitation on file path. Just return FileName. \r
620 //\r
621 return FileName;\r
622#else\r
623 CHAR8 *RootPath;\r
624 CHAR8 *PathPointer;\r
625 CHAR8 *NextPointer;\r
626 \r
627 PathPointer = (CHAR8 *) FileName;\r
628 \r
629 if (FileName != NULL) {\r
630 //\r
631 // Add the extension string first to support long file path. \r
632 //\r
633 mCommonLibFullPath[0] = 0;\r
634 strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH);\r
635\r
636 if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') {\r
637 //\r
638 // network path like \\server\share to \\?\UNC\server\share\r
639 //\r
640 strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH);\r
641 FileName ++;\r
642 } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) {\r
643 //\r
644 // Relative file path. Convert it to absolute path. \r
645 //\r
646 RootPath = getcwd (NULL, 0);\r
647 if (RootPath != NULL) {\r
648 strcat (mCommonLibFullPath, RootPath);\r
649 if (FileName[0] != '\\' && FileName[0] != '/') {\r
650 //\r
651 // Attach directory separator\r
652 //\r
653 strcat (mCommonLibFullPath, "\\");\r
654 }\r
655 free (RootPath);\r
656 }\r
657 }\r
658\r
659 //\r
660 // Construct the full file path\r
661 //\r
662 strcat (mCommonLibFullPath, FileName);\r
663 \r
664 //\r
665 // Convert directory separator '/' to '\\'\r
666 //\r
667 PathPointer = (CHAR8 *) mCommonLibFullPath;\r
668 do {\r
669 if (*PathPointer == '/') {\r
670 *PathPointer = '\\';\r
671 }\r
672 } while (*PathPointer ++ != '\0');\r
673 \r
674 //\r
675 // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
676 //\r
677 while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {\r
678 *PathPointer = '\0';\r
679 strcat (mCommonLibFullPath, PathPointer + 2);\r
680 }\r
681 \r
682 //\r
683 // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.\r
684 //\r
685 while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {\r
686 NextPointer = PathPointer + 3;\r
687 do {\r
688 PathPointer --;\r
689 } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');\r
690\r
691 if (*PathPointer == '\\') {\r
692 //\r
693 // Skip one directory\r
694 //\r
695 *PathPointer = '\0';\r
696 strcat (mCommonLibFullPath, NextPointer);\r
697 } else {\r
698 //\r
699 // No directory is found. Just break.\r
700 //\r
701 break;\r
702 }\r
703 }\r
704 \r
705 PathPointer = mCommonLibFullPath;\r
706 }\r
707 \r
708 return PathPointer;\r
709#endif\r
710}\r