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