Home | History | Annotate | Download | only in Common
      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
     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         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