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