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