1 /** @file
2 Common basic Library Functions
3
4 Copyright (c) 2004 - 2016, 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
PeiZeroMem(IN VOID * Buffer,IN UINTN Size)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
PeiCopyMem(IN VOID * Destination,IN VOID * Source,IN UINTN Length)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
ZeroMem(IN VOID * Buffer,IN UINTN Size)95 ZeroMem (
96 IN VOID *Buffer,
97 IN UINTN Size
98 )
99 {
100 PeiZeroMem (Buffer, Size);
101 }
102
103 VOID
CopyMem(IN VOID * Destination,IN VOID * Source,IN UINTN Length)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
CompareGuid(IN EFI_GUID * Guid1,IN EFI_GUID * Guid2)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
GetFileImage(IN CHAR8 * InputFileName,OUT CHAR8 ** InputFileImage,OUT UINT32 * BytesRead)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
PutFileImage(IN CHAR8 * OutputFileName,IN CHAR8 * OutputFileImage,IN UINT32 BytesToWrite)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
CalculateChecksum8(IN UINT8 * Buffer,IN UINTN Size)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
CalculateSum8(IN UINT8 * Buffer,IN UINTN Size)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
CalculateChecksum16(IN UINT16 * Buffer,IN UINTN Size)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
CalculateSum16(IN UINT16 * Buffer,IN UINTN Size)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
PrintGuid(IN EFI_GUID * Guid)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
PrintGuidToBuffer(IN EFI_GUID * Guid,IN OUT UINT8 * Buffer,IN UINT32 BufferLen,IN BOOLEAN Uppercase)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
_filelength(int fd)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__
strlwr(char * s)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 *
LongFilePath(IN CHAR8 * FileName)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 strcat (mCommonLibFullPath, RootPath);
642 if (FileName[0] != '\\' && FileName[0] != '/') {
643 //
644 // Attach directory separator
645 //
646 strcat (mCommonLibFullPath, "\\");
647 }
648 free (RootPath);
649 }
650 }
651
652 //
653 // Construct the full file path
654 //
655 if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) {
656 Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName);
657 return NULL;
658 }
659 strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
660
661 //
662 // Convert directory separator '/' to '\\'
663 //
664 PathPointer = (CHAR8 *) mCommonLibFullPath;
665 do {
666 if (*PathPointer == '/') {
667 *PathPointer = '\\';
668 }
669 } while (*PathPointer ++ != '\0');
670
671 //
672 // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
673 //
674 if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {
675 *(PathPointer + 2) = '\0';
676 strcat (mCommonLibFullPath, PathPointer + 3);
677 }
678
679 //
680 // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.
681 //
682 while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {
683 *PathPointer = '\0';
684 strcat (mCommonLibFullPath, PathPointer + 2);
685 }
686
687 //
688 // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
689 //
690 while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {
691 *PathPointer = '\0';
692 strcat (mCommonLibFullPath, PathPointer + 2);
693 }
694
695 //
696 // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.
697 //
698 while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {
699 NextPointer = PathPointer + 3;
700 do {
701 PathPointer --;
702 } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');
703
704 if (*PathPointer == '\\') {
705 //
706 // Skip one directory
707 //
708 *PathPointer = '\0';
709 strcat (mCommonLibFullPath, NextPointer);
710 } else {
711 //
712 // No directory is found. Just break.
713 //
714 break;
715 }
716 }
717
718 PathPointer = mCommonLibFullPath;
719 }
720
721 return PathPointer;
722 #endif
723 }
724