Home | History | Annotate | Download | only in UefiShellDebug1CommandsLib
      1 /** @file
      2   Main file for NULL named library for debug1 profile shell command functions.
      3 
      4   Copyright (c) 2010 - 2011, 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 "UefiShellDebug1CommandsLib.h"
     16 #include <Library/BcfgCommandLib.h>
     17 
     18 STATIC CONST CHAR16 mFileName[] = L"Debug1Commands";
     19 EFI_HANDLE gShellDebug1HiiHandle = NULL;
     20 
     21 /**
     22   Gets the debug file name.  This will be used if HII is not working.
     23 
     24   @retval NULL    No file is available.
     25   @return         The NULL-terminated filename to get help from.
     26 **/
     27 CONST CHAR16*
     28 EFIAPI
     29 ShellCommandGetManFileNameDebug1 (
     30   VOID
     31   )
     32 {
     33   return (mFileName);
     34 }
     35 
     36 /**
     37   Constructor for the Shell Debug1 Commands library.
     38 
     39   @param ImageHandle    the image handle of the process
     40   @param SystemTable    the EFI System Table pointer
     41 
     42   @retval EFI_SUCCESS        the shell command handlers were installed sucessfully
     43   @retval EFI_UNSUPPORTED    the shell level required was not found.
     44 **/
     45 EFI_STATUS
     46 EFIAPI
     47 UefiShellDebug1CommandsLibConstructor (
     48   IN EFI_HANDLE        ImageHandle,
     49   IN EFI_SYSTEM_TABLE  *SystemTable
     50   )
     51 {
     52   //
     53   // check our bit of the profiles mask
     54   //
     55   if ((PcdGet8(PcdShellProfileMask) & BIT1) == 0) {
     56     return (EFI_SUCCESS);
     57   }
     58 
     59   //
     60   // install the HII stuff.
     61   //
     62   gShellDebug1HiiHandle = HiiAddPackages (&gShellDebug1HiiGuid, gImageHandle, UefiShellDebug1CommandsLibStrings, NULL);
     63   if (gShellDebug1HiiHandle == NULL) {
     64     return (EFI_DEVICE_ERROR);
     65   }
     66 
     67   //
     68   // install our shell command handlers that are always installed
     69   //
     70   ShellCommandRegisterCommandName(L"setsize",       ShellCommandRunSetSize            , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETSIZE)      );
     71   ShellCommandRegisterCommandName(L"comp",          ShellCommandRunComp               , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_COMP)         );
     72   ShellCommandRegisterCommandName(L"mode",          ShellCommandRunMode               , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MODE)         );
     73   ShellCommandRegisterCommandName(L"memmap",        ShellCommandRunMemMap             , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MEMMAP)       );
     74   ShellCommandRegisterCommandName(L"eficompress",   ShellCommandRunEfiCompress        , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFICOMPRESS)  );
     75   ShellCommandRegisterCommandName(L"efidecompress", ShellCommandRunEfiDecompress      , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFIDCOMPRESS) );
     76   ShellCommandRegisterCommandName(L"dmem",          ShellCommandRunDmem               , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMEM)         );
     77   ShellCommandRegisterCommandName(L"loadpcirom",    ShellCommandRunLoadPciRom         , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD_PCI_ROM) );
     78   ShellCommandRegisterCommandName(L"mm",            ShellCommandRunMm                 , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MM)           );
     79   ShellCommandRegisterCommandName(L"setvar",        ShellCommandRunSetVar             , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETVAR)       );
     80   ShellCommandRegisterCommandName(L"sermode",       ShellCommandRunSerMode            , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SERMODE)      );
     81   ShellCommandRegisterCommandName(L"pci",           ShellCommandRunPci                , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_PCI)          );
     82   ShellCommandRegisterCommandName(L"smbiosview",    ShellCommandRunSmbiosView         , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SMBIOSVIEW)   );
     83   ShellCommandRegisterCommandName(L"dmpstore",      ShellCommandRunDmpStore           , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMPSTORE)     );
     84   ShellCommandRegisterCommandName(L"dblk",          ShellCommandRunDblk               , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DBLK)         );
     85   ShellCommandRegisterCommandName(L"edit",          ShellCommandRunEdit               , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EDIT)         );
     86   ShellCommandRegisterCommandName(L"hexedit",       ShellCommandRunHexEdit            , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_HEXEDIT)      );
     87 
     88   ShellCommandRegisterAlias(L"dmem", L"mem");
     89 
     90   BcfgLibraryRegisterBcfgCommand(ImageHandle, SystemTable, L"Debug1");
     91 
     92   return (EFI_SUCCESS);
     93 }
     94 
     95 /**
     96   Destructor for the library.  free any resources.
     97 
     98   @param ImageHandle            The image handle of the process.
     99   @param SystemTable            The EFI System Table pointer.
    100 **/
    101 EFI_STATUS
    102 EFIAPI
    103 UefiShellDebug1CommandsLibDestructor (
    104   IN EFI_HANDLE        ImageHandle,
    105   IN EFI_SYSTEM_TABLE  *SystemTable
    106   )
    107 {
    108   if (gShellDebug1HiiHandle != NULL) {
    109     HiiRemovePackages(gShellDebug1HiiHandle);
    110   }
    111 
    112   BcfgLibraryUnregisterBcfgCommand(ImageHandle, SystemTable);
    113   return (EFI_SUCCESS);
    114 }
    115 
    116 STATIC CONST CHAR8 Hex[] = {
    117   '0',
    118   '1',
    119   '2',
    120   '3',
    121   '4',
    122   '5',
    123   '6',
    124   '7',
    125   '8',
    126   '9',
    127   'A',
    128   'B',
    129   'C',
    130   'D',
    131   'E',
    132   'F'
    133 };
    134 
    135 /**
    136   Dump some hexadecimal data to the screen.
    137 
    138   @param[in] Indent     How many spaces to indent the output.
    139   @param[in] Offset     The offset of the printing.
    140   @param[in] DataSize   The size in bytes of UserData.
    141   @param[in] UserData   The data to print out.
    142 **/
    143 VOID
    144 DumpHex (
    145   IN UINTN        Indent,
    146   IN UINTN        Offset,
    147   IN UINTN        DataSize,
    148   IN VOID         *UserData
    149   )
    150 {
    151   UINT8 *Data;
    152 
    153   CHAR8 Val[50];
    154 
    155   CHAR8 Str[20];
    156 
    157   UINT8 TempByte;
    158   UINTN Size;
    159   UINTN Index;
    160 
    161   Data = UserData;
    162   while (DataSize != 0) {
    163     Size = 16;
    164     if (Size > DataSize) {
    165       Size = DataSize;
    166     }
    167 
    168     for (Index = 0; Index < Size; Index += 1) {
    169       TempByte            = Data[Index];
    170       Val[Index * 3 + 0]  = Hex[TempByte >> 4];
    171       Val[Index * 3 + 1]  = Hex[TempByte & 0xF];
    172       Val[Index * 3 + 2]  = (CHAR8) ((Index == 7) ? '-' : ' ');
    173       Str[Index]          = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
    174     }
    175 
    176     Val[Index * 3]  = 0;
    177     Str[Index]      = 0;
    178     ShellPrintEx(-1, -1, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
    179 
    180     Data += Size;
    181     Offset += Size;
    182     DataSize -= Size;
    183   }
    184 }
    185 
    186 /**
    187   Convert a Unicode character to upper case only if
    188   it maps to a valid small-case ASCII character.
    189 
    190   This internal function only deal with Unicode character
    191   which maps to a valid small-case ASCII character, i.e.
    192   L'a' to L'z'. For other Unicode character, the input character
    193   is returned directly.
    194 
    195   @param  Char  The character to convert.
    196 
    197   @retval LowerCharacter   If the Char is with range L'a' to L'z'.
    198   @retval Unchanged        Otherwise.
    199 
    200 
    201   //Stolen from MdePkg Baselib
    202 **/
    203 CHAR16
    204 EFIAPI
    205 CharToUpper (
    206   IN      CHAR16                    Char
    207   )
    208 {
    209   if (Char >= L'a' && Char <= L'z') {
    210     return (CHAR16) (Char - (L'a' - L'A'));
    211   }
    212 
    213   return Char;
    214 }
    215 
    216 /**
    217   Function returns a system configuration table that is stored in the
    218   EFI System Table based on the provided GUID.
    219 
    220   @param[in]  TableGuid     A pointer to the table's GUID type.
    221   @param[in, out] Table     On exit, a pointer to a system configuration table.
    222 
    223   @retval EFI_SUCCESS      A configuration table matching TableGuid was found.
    224   @retval EFI_NOT_FOUND    A configuration table matching TableGuid was not found.
    225 **/
    226 EFI_STATUS
    227 EFIAPI
    228 GetSystemConfigurationTable (
    229   IN EFI_GUID *TableGuid,
    230   IN OUT VOID **Table
    231   )
    232 {
    233   UINTN Index;
    234   ASSERT (Table != NULL);
    235 
    236   for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
    237     if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
    238       *Table = gST->ConfigurationTable[Index].VendorTable;
    239       return EFI_SUCCESS;
    240     }
    241   }
    242 
    243   return EFI_NOT_FOUND;
    244 }
    245 
    246 /**
    247   Convert a Unicode character to numerical value.
    248 
    249   This internal function only deal with Unicode character
    250   which maps to a valid hexadecimal ASII character, i.e.
    251   L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
    252   Unicode character, the value returned does not make sense.
    253 
    254   @param  Char  The character to convert.
    255 
    256   @return The numerical value converted.
    257 
    258 **/
    259 UINTN
    260 EFIAPI
    261 HexCharToUintn (
    262   IN      CHAR16                    Char
    263   )
    264 {
    265   if (Char >= L'0' && Char <= L'9') {
    266     return Char - L'0';
    267   }
    268 
    269   return (UINTN) (10 + CharToUpper (Char) - L'A');
    270 }
    271 
    272 /**
    273   Convert a string representation of a guid to a Guid value.
    274 
    275   @param[in] StringGuid    The pointer to the string of a guid.
    276   @param[in, out] Guid     The pointer to the GUID structure to populate.
    277 
    278   @retval EFI_INVALID_PARAMETER   A parameter was invalid.
    279   @retval EFI_SUCCESS             The conversion was successful.
    280 **/
    281 EFI_STATUS
    282 EFIAPI
    283 ConvertStringToGuid (
    284   IN CONST CHAR16 *StringGuid,
    285   IN OUT EFI_GUID *Guid
    286   )
    287 {
    288   CHAR16  *TempCopy;
    289   CHAR16  *TempSpot;
    290   CHAR16  *Walker;
    291   UINT64  TempVal;
    292   EFI_STATUS Status;
    293 
    294   if (StringGuid == NULL) {
    295     return (EFI_INVALID_PARAMETER);
    296   } else if (StrLen(StringGuid) != 36) {
    297     return (EFI_INVALID_PARAMETER);
    298   }
    299   TempCopy = NULL;
    300   TempCopy = StrnCatGrow(&TempCopy, NULL, StringGuid, 0);
    301   if (TempCopy == NULL) {
    302     return (EFI_OUT_OF_RESOURCES);
    303   }
    304   Walker   = TempCopy;
    305   TempSpot = StrStr(Walker, L"-");
    306   if (TempSpot != NULL) {
    307     *TempSpot = CHAR_NULL;
    308   }
    309   Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
    310   if (EFI_ERROR(Status)) {
    311     FreePool(TempCopy);
    312     return (Status);
    313   }
    314   Guid->Data1 = (UINT32)TempVal;
    315   Walker += 9;
    316   TempSpot = StrStr(Walker, L"-");
    317   if (TempSpot != NULL) {
    318     *TempSpot = CHAR_NULL;
    319   }
    320   Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
    321   if (EFI_ERROR(Status)) {
    322     FreePool(TempCopy);
    323     return (Status);
    324   }
    325   Guid->Data2 = (UINT16)TempVal;
    326   Walker += 5;
    327   TempSpot = StrStr(Walker, L"-");
    328   if (TempSpot != NULL) {
    329     *TempSpot = CHAR_NULL;
    330   }
    331   Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
    332   if (EFI_ERROR(Status)) {
    333     FreePool(TempCopy);
    334     return (Status);
    335   }
    336   Guid->Data3 = (UINT16)TempVal;
    337   Walker += 5;
    338   Guid->Data4[0] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    339   Guid->Data4[0] = (UINT8)(Guid->Data4[0]+ (UINT8)HexCharToUintn(Walker[1]));
    340   Walker += 2;
    341   Guid->Data4[1] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    342   Guid->Data4[1] = (UINT8)(Guid->Data4[1] + (UINT8)HexCharToUintn(Walker[1]));
    343   Walker += 3;
    344   Guid->Data4[2] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    345   Guid->Data4[2] = (UINT8)(Guid->Data4[2] + (UINT8)HexCharToUintn(Walker[1]));
    346   Walker += 2;
    347   Guid->Data4[3] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    348   Guid->Data4[3] = (UINT8)(Guid->Data4[3] + (UINT8)HexCharToUintn(Walker[1]));
    349   Walker += 2;
    350   Guid->Data4[4] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    351   Guid->Data4[4] = (UINT8)(Guid->Data4[4] + (UINT8)HexCharToUintn(Walker[1]));
    352   Walker += 2;
    353   Guid->Data4[5] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    354   Guid->Data4[5] = (UINT8)(Guid->Data4[5] + (UINT8)HexCharToUintn(Walker[1]));
    355   Walker += 2;
    356   Guid->Data4[6] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    357   Guid->Data4[6] = (UINT8)(Guid->Data4[6] + (UINT8)HexCharToUintn(Walker[1]));
    358   Walker += 2;
    359   Guid->Data4[7] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
    360   Guid->Data4[7] = (UINT8)(Guid->Data4[7] + (UINT8)HexCharToUintn(Walker[1]));
    361   FreePool(TempCopy);
    362   return (EFI_SUCCESS);
    363 }
    364 
    365 /**
    366   Clear the line at the specified Row.
    367 
    368   @param[in] Row                The row number to be cleared ( start from 1 )
    369   @param[in] LastCol            The last printable column.
    370   @param[in] LastRow            The last printable row.
    371 **/
    372 VOID
    373 EFIAPI
    374 EditorClearLine (
    375   IN UINTN Row,
    376   IN UINTN LastCol,
    377   IN UINTN LastRow
    378   )
    379 {
    380   CHAR16 Line[200];
    381 
    382   if (Row == 0) {
    383     Row = 1;
    384   }
    385 
    386   //
    387   // prepare a blank line
    388   //
    389   SetMem16(Line, LastCol*sizeof(CHAR16), L' ');
    390 
    391   if (Row == LastRow) {
    392     //
    393     // if CHAR_NULL is still at position 80, it will cause first line error
    394     //
    395     Line[LastCol - 1] = CHAR_NULL;
    396   } else {
    397     Line[LastCol] = CHAR_NULL;
    398   }
    399 
    400   //
    401   // print out the blank line
    402   //
    403   ShellPrintEx (0, ((INT32)Row) - 1, Line);
    404 }
    405 
    406 /**
    407   Determine if the character is valid for a filename.
    408 
    409   @param[in] Ch     The character to test.
    410 
    411   @retval TRUE      The character is valid.
    412   @retval FALSE     The character is not valid.
    413 **/
    414 BOOLEAN
    415 EFIAPI
    416 IsValidFileNameChar (
    417   IN CONST CHAR16 Ch
    418   )
    419 {
    420   //
    421   // See if there are any illegal characters within the name
    422   //
    423   if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|') {
    424     return FALSE;
    425   }
    426 
    427   return TRUE;
    428 }
    429 
    430 /**
    431   Check if file name has illegal characters.
    432 
    433   @param Name       The filename to check.
    434 
    435   @retval TRUE      The filename is ok.
    436   @retval FALSE     The filename is not ok.
    437 **/
    438 BOOLEAN
    439 EFIAPI
    440 IsValidFileName (
    441   IN CONST CHAR16 *Name
    442   )
    443 {
    444 
    445   UINTN Index;
    446   UINTN Len;
    447 
    448   //
    449   // check the length of Name
    450   //
    451   for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) {
    452     if (Name[Index] == '\\' || Name[Index] == ':') {
    453       break;
    454     }
    455   }
    456 
    457   if (Len == 0 || Len > 255) {
    458     return FALSE;
    459   }
    460   //
    461   // check whether any char in Name not appears in valid file name char
    462   //
    463   for (Index = 0; Index < StrLen (Name); Index++) {
    464     if (!IsValidFileNameChar (Name[Index])) {
    465       return FALSE;
    466     }
    467   }
    468 
    469   return TRUE;
    470 }
    471 
    472 /**
    473   Find a filename that is valid (not taken) with the given extension.
    474 
    475   @param[in] Extension      The file extension.
    476 
    477   @retval NULL  Something went wrong.
    478   @return the valid filename.
    479 **/
    480 CHAR16 *
    481 EFIAPI
    482 EditGetDefaultFileName (
    483   IN CONST CHAR16 *Extension
    484   )
    485 {
    486   EFI_STATUS         Status;
    487   UINTN              Suffix;
    488   CHAR16             *FileNameTmp;
    489 
    490   Suffix       = 0;
    491 
    492   do {
    493     FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension);
    494 
    495     //
    496     // after that filename changed to path
    497     //
    498     Status = ShellFileExists (FileNameTmp);
    499 
    500     if (Status == EFI_NOT_FOUND) {
    501       return FileNameTmp;
    502     }
    503 
    504     FreePool (FileNameTmp);
    505     FileNameTmp = NULL;
    506     Suffix++;
    507   } while (Suffix != 0);
    508 
    509   FreePool (FileNameTmp);
    510   return NULL;
    511 }
    512 
    513 /**
    514   Read a file into an allocated buffer.  The buffer is the responsibility
    515   of the caller to free.
    516 
    517   @param[in]  FileName          The filename of the file to open.
    518   @param[out] Buffer            Upon successful return, the pointer to the
    519                                 address of the allocated buffer.
    520   @param[out] BufferSize        If not NULL, then the pointer to the size
    521                                 of the allocated buffer.
    522   @param[out] ReadOnly          Upon successful return TRUE if the file is
    523                                 read only.  FALSE otherwise.
    524 
    525   @retval EFI_NOT_FOUND         The filename did not represent a file in the
    526                                 file system.
    527   @retval EFI_SUCCESS           The file was read into the buffer.
    528   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
    529   @retval EFI_LOAD_ERROR        The file read operation failed.
    530   @retval EFI_INVALID_PARAMETER A parameter was invalid.
    531   @retval EFI_INVALID_PARAMETER FileName was NULL.
    532   @retval EFI_INVALID_PARAMETER FileName was a directory.
    533 **/
    534 EFI_STATUS
    535 EFIAPI
    536 ReadFileIntoBuffer (
    537   IN CONST CHAR16 *FileName,
    538   OUT VOID        **Buffer,
    539   OUT UINTN       *BufferSize OPTIONAL,
    540   OUT BOOLEAN     *ReadOnly
    541   )
    542 {
    543   VOID              *InternalBuffer;
    544   UINTN             FileSize;
    545   SHELL_FILE_HANDLE FileHandle;
    546   BOOLEAN           CreateFile;
    547   EFI_STATUS        Status;
    548   EFI_FILE_INFO     *Info;
    549 
    550   InternalBuffer  = NULL;
    551   FileSize        = 0;
    552   FileHandle      = NULL;
    553   CreateFile      = FALSE;
    554   Status          = EFI_SUCCESS;
    555   Info            = NULL;
    556 
    557   if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) {
    558     return (EFI_INVALID_PARAMETER);
    559   }
    560 
    561   //
    562   // try to open the file
    563   //
    564   Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
    565 
    566   if (!EFI_ERROR(Status)) {
    567     ASSERT(CreateFile == FALSE);
    568     if (FileHandle == NULL) {
    569       return EFI_LOAD_ERROR;
    570     }
    571 
    572     Info = ShellGetFileInfo(FileHandle);
    573 
    574     if (Info->Attribute & EFI_FILE_DIRECTORY) {
    575       FreePool (Info);
    576       return EFI_INVALID_PARAMETER;
    577     }
    578 
    579     if (Info->Attribute & EFI_FILE_READ_ONLY) {
    580       *ReadOnly = TRUE;
    581     } else {
    582       *ReadOnly = FALSE;
    583     }
    584     //
    585     // get file size
    586     //
    587     FileSize = (UINTN) Info->FileSize;
    588 
    589     FreePool (Info);
    590   } else if (Status == EFI_NOT_FOUND) {
    591     //
    592     // file not exists.  add create and try again
    593     //
    594     Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
    595     if (EFI_ERROR (Status)) {
    596       return Status;
    597     } else {
    598       //
    599       // it worked.  now delete it and move on with the name (now validated)
    600       //
    601       Status = ShellDeleteFile (&FileHandle);
    602       if (Status == EFI_WARN_DELETE_FAILURE) {
    603         Status = EFI_ACCESS_DENIED;
    604       }
    605       if (EFI_ERROR (Status)) {
    606         return Status;
    607       }
    608     }
    609     //
    610     // file doesn't exist, so set CreateFile to TRUE and can't be read-only
    611     //
    612     CreateFile = TRUE;
    613     *ReadOnly  = FALSE;
    614   }
    615 
    616   //
    617   // the file exists
    618   //
    619   if (!CreateFile) {
    620     //
    621     // allocate buffer to read file
    622     //
    623     InternalBuffer = AllocateZeroPool (FileSize);
    624     if (InternalBuffer == NULL) {
    625       return EFI_OUT_OF_RESOURCES;
    626     }
    627     //
    628     // read file into InternalBuffer
    629     //
    630     Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer);
    631     ShellCloseFile(&FileHandle);
    632     FileHandle = NULL;
    633     if (EFI_ERROR (Status)) {
    634       SHELL_FREE_NON_NULL (InternalBuffer);
    635       return EFI_LOAD_ERROR;
    636     }
    637   }
    638   *Buffer = InternalBuffer;
    639   if (BufferSize != NULL) {
    640     *BufferSize = FileSize;
    641   }
    642   return (EFI_SUCCESS);
    643 
    644 }
    645