1 /** @file
2 Common basic Library Functions
3 
4 Copyright (c) 2004 - 2014, 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     strcat (mCommonLibFullPath, FileName);
656 
657     //
658     // Convert directory separator '/' to '\\'
659     //
660     PathPointer = (CHAR8 *) mCommonLibFullPath;
661     do {
662       if (*PathPointer == '/') {
663         *PathPointer = '\\';
664       }
665     } while (*PathPointer ++ != '\0');
666 
667     //
668     // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
669     //
670     if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {
671       *(PathPointer + 2) = '\0';
672       strcat (mCommonLibFullPath, PathPointer + 3);
673     }
674 
675     //
676     // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.
677     //
678     while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {
679       *PathPointer = '\0';
680       strcat (mCommonLibFullPath, PathPointer + 2);
681     }
682 
683     //
684     // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
685     //
686     while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {
687       *PathPointer = '\0';
688       strcat (mCommonLibFullPath, PathPointer + 2);
689     }
690 
691     //
692     // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.
693     //
694     while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {
695       NextPointer = PathPointer + 3;
696       do {
697         PathPointer --;
698       } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');
699 
700       if (*PathPointer == '\\') {
701         //
702         // Skip one directory
703         //
704         *PathPointer = '\0';
705         strcat (mCommonLibFullPath, NextPointer);
706       } else {
707         //
708         // No directory is found. Just break.
709         //
710         break;
711       }
712     }
713 
714     PathPointer = mCommonLibFullPath;
715   }
716 
717   return PathPointer;
718 #endif
719 }
720