EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

ShellPkg/Library/UefiShellLib/UefiShellLib.c

Go to the documentation of this file.
00001 
00015 #include "UefiShellLib.h"
00016 #include <ShellBase.h>
00017 #include <Library/SortLib.h>
00018 
00019 #define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)
00020 
00021 //
00022 // globals...
00023 //
00024 SHELL_PARAM_ITEM EmptyParamList[] = {
00025   {NULL, TypeMax}
00026   };
00027 SHELL_PARAM_ITEM SfoParamList[] = {
00028   {L"-sfo", TypeFlag},
00029   {NULL, TypeMax}
00030   };
00031 EFI_SHELL_ENVIRONMENT2        *mEfiShellEnvironment2;
00032 EFI_SHELL_INTERFACE           *mEfiShellInterface;
00033 EFI_SHELL_PROTOCOL            *gEfiShellProtocol;
00034 EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol;
00035 EFI_HANDLE                    mEfiShellEnvironment2Handle;
00036 FILE_HANDLE_FUNCTION_MAP      FileFunctionMap;
00037 
00051 BOOLEAN
00052 EFIAPI
00053 ShellIsHexaDecimalDigitCharacter (
00054   IN      CHAR16                    Char
00055   )
00056 {
00057   return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
00058 }
00059 
00074 BOOLEAN
00075 EFIAPI
00076 ShellIsDecimalDigitCharacter (
00077   IN      CHAR16                    Char
00078   )
00079 {
00080   return (BOOLEAN) (Char >= L'0' && Char <= L'9');
00081 }
00082 
00090 EFI_STATUS
00091 EFIAPI
00092 ShellFindSE2 (
00093   IN EFI_HANDLE        ImageHandle
00094   )
00095 {
00096   EFI_STATUS  Status;
00097   EFI_HANDLE  *Buffer;
00098   UINTN       BufferSize;
00099   UINTN       HandleIndex;
00100 
00101   BufferSize = 0;
00102   Buffer = NULL;
00103   Status = gBS->OpenProtocol(ImageHandle,
00104                              &gEfiShellEnvironment2Guid,
00105                              (VOID **)&mEfiShellEnvironment2,
00106                              ImageHandle,
00107                              NULL,
00108                              EFI_OPEN_PROTOCOL_GET_PROTOCOL
00109                             );
00110   //
00111   // look for the mEfiShellEnvironment2 protocol at a higher level
00112   //
00113   if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid))){
00114     //
00115     // figure out how big of a buffer we need.
00116     //
00117     Status = gBS->LocateHandle (ByProtocol,
00118                                 &gEfiShellEnvironment2Guid,
00119                                 NULL, // ignored for ByProtocol
00120                                 &BufferSize,
00121                                 Buffer
00122                                );
00123     //
00124     // maybe it's not there???
00125     //
00126     if (Status == EFI_BUFFER_TOO_SMALL) {
00127       Buffer = (EFI_HANDLE*)AllocateZeroPool(BufferSize);
00128       if (Buffer == NULL) {
00129         return (EFI_OUT_OF_RESOURCES);
00130       }
00131       Status = gBS->LocateHandle (ByProtocol,
00132                                   &gEfiShellEnvironment2Guid,
00133                                   NULL, // ignored for ByProtocol
00134                                   &BufferSize,
00135                                   Buffer
00136                                  );
00137     }
00138     if (!EFI_ERROR (Status) && Buffer != NULL) {
00139       //
00140       // now parse the list of returned handles
00141       //
00142       Status = EFI_NOT_FOUND;
00143       for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) {
00144         Status = gBS->OpenProtocol(Buffer[HandleIndex],
00145                                    &gEfiShellEnvironment2Guid,
00146                                    (VOID **)&mEfiShellEnvironment2,
00147                                    ImageHandle,
00148                                    NULL,
00149                                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
00150                                   );
00151          if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid)) {
00152           mEfiShellEnvironment2Handle = Buffer[HandleIndex];
00153           Status = EFI_SUCCESS;
00154           break;
00155         }
00156       }
00157     }
00158   }
00159   if (Buffer != NULL) {
00160     FreePool (Buffer);
00161   }
00162   return (Status);
00163 }
00164 
00174 EFI_STATUS
00175 EFIAPI
00176 ShellLibConstructorWorker (
00177   IN EFI_HANDLE        ImageHandle,
00178   IN EFI_SYSTEM_TABLE  *SystemTable
00179   )
00180 {
00181   EFI_STATUS  Status;
00182 
00183   //
00184   // UEFI 2.0 shell interfaces (used preferentially)
00185   //
00186   Status = gBS->OpenProtocol(
00187     ImageHandle,
00188     &gEfiShellProtocolGuid,
00189     (VOID **)&gEfiShellProtocol,
00190     ImageHandle,
00191     NULL,
00192     EFI_OPEN_PROTOCOL_GET_PROTOCOL
00193    );
00194   if (EFI_ERROR(Status)) {
00195     //
00196     // Search for the shell protocol
00197     //
00198     Status = gBS->LocateProtocol(
00199       &gEfiShellProtocolGuid,
00200       NULL,
00201       (VOID **)&gEfiShellProtocol
00202      );
00203     if (EFI_ERROR(Status)) {
00204       gEfiShellProtocol = NULL;
00205     }
00206   }
00207   Status = gBS->OpenProtocol(
00208     ImageHandle,
00209     &gEfiShellParametersProtocolGuid,
00210     (VOID **)&gEfiShellParametersProtocol,
00211     ImageHandle,
00212     NULL,
00213     EFI_OPEN_PROTOCOL_GET_PROTOCOL
00214    );
00215   if (EFI_ERROR(Status)) {
00216     gEfiShellParametersProtocol = NULL;
00217   }
00218 
00219   if (gEfiShellParametersProtocol == NULL || gEfiShellProtocol == NULL) {
00220     //
00221     // Moved to seperate function due to complexity
00222     //
00223     Status = ShellFindSE2(ImageHandle);
00224 
00225     if (EFI_ERROR(Status)) {
00226       DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status));
00227       mEfiShellEnvironment2 = NULL;
00228     }
00229     Status = gBS->OpenProtocol(ImageHandle,
00230                                &gEfiShellInterfaceGuid,
00231                                (VOID **)&mEfiShellInterface,
00232                                ImageHandle,
00233                                NULL,
00234                                EFI_OPEN_PROTOCOL_GET_PROTOCOL
00235                               );
00236     if (EFI_ERROR(Status)) {
00237       mEfiShellInterface = NULL;
00238     }
00239   }
00240 
00241   //
00242   // only success getting 2 of either the old or new, but no 1/2 and 1/2
00243   //
00244   if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface          != NULL) ||
00245       (gEfiShellProtocol     != NULL && gEfiShellParametersProtocol != NULL)   ) {
00246     if (gEfiShellProtocol != NULL) {
00247       FileFunctionMap.GetFileInfo     = gEfiShellProtocol->GetFileInfo;
00248       FileFunctionMap.SetFileInfo     = gEfiShellProtocol->SetFileInfo;
00249       FileFunctionMap.ReadFile        = gEfiShellProtocol->ReadFile;
00250       FileFunctionMap.WriteFile       = gEfiShellProtocol->WriteFile;
00251       FileFunctionMap.CloseFile       = gEfiShellProtocol->CloseFile;
00252       FileFunctionMap.DeleteFile      = gEfiShellProtocol->DeleteFile;
00253       FileFunctionMap.GetFilePosition = gEfiShellProtocol->GetFilePosition;
00254       FileFunctionMap.SetFilePosition = gEfiShellProtocol->SetFilePosition;
00255       FileFunctionMap.FlushFile       = gEfiShellProtocol->FlushFile;
00256       FileFunctionMap.GetFileSize     = gEfiShellProtocol->GetFileSize;
00257     } else {
00258       FileFunctionMap.GetFileInfo     = (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo;
00259       FileFunctionMap.SetFileInfo     = (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo;
00260       FileFunctionMap.ReadFile        = (EFI_SHELL_READ_FILE)FileHandleRead;
00261       FileFunctionMap.WriteFile       = (EFI_SHELL_WRITE_FILE)FileHandleWrite;
00262       FileFunctionMap.CloseFile       = (EFI_SHELL_CLOSE_FILE)FileHandleClose;
00263       FileFunctionMap.DeleteFile      = (EFI_SHELL_DELETE_FILE)FileHandleDelete;
00264       FileFunctionMap.GetFilePosition = (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition;
00265       FileFunctionMap.SetFilePosition = (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition;
00266       FileFunctionMap.FlushFile       = (EFI_SHELL_FLUSH_FILE)FileHandleFlush;
00267       FileFunctionMap.GetFileSize     = (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize;
00268     }
00269     return (EFI_SUCCESS);
00270   }
00271   return (EFI_NOT_FOUND);
00272 }
00284 EFI_STATUS
00285 EFIAPI
00286 ShellLibConstructor (
00287   IN EFI_HANDLE        ImageHandle,
00288   IN EFI_SYSTEM_TABLE  *SystemTable
00289   )
00290 {
00291   mEfiShellEnvironment2       = NULL;
00292   gEfiShellProtocol           = NULL;
00293   gEfiShellParametersProtocol = NULL;
00294   mEfiShellInterface          = NULL;
00295   mEfiShellEnvironment2Handle = NULL;
00296 
00297   //
00298   // verify that auto initialize is not set false
00299   //
00300   if (PcdGetBool(PcdShellLibAutoInitialize) == 0) {
00301     return (EFI_SUCCESS);
00302   }
00303 
00304   return (ShellLibConstructorWorker(ImageHandle, SystemTable));
00305 }
00306 
00316 EFI_STATUS
00317 EFIAPI
00318 ShellLibDestructor (
00319   IN EFI_HANDLE        ImageHandle,
00320   IN EFI_SYSTEM_TABLE  *SystemTable
00321   )
00322 {
00323   if (mEfiShellEnvironment2 != NULL) {
00324     gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,
00325                        &gEfiShellEnvironment2Guid,
00326                        ImageHandle,
00327                        NULL);
00328     mEfiShellEnvironment2 = NULL;
00329   }
00330   if (mEfiShellInterface != NULL) {
00331     gBS->CloseProtocol(ImageHandle,
00332                        &gEfiShellInterfaceGuid,
00333                        ImageHandle,
00334                        NULL);
00335     mEfiShellInterface = NULL;
00336   }
00337   if (gEfiShellProtocol != NULL) {
00338     gBS->CloseProtocol(ImageHandle,
00339                        &gEfiShellProtocolGuid,
00340                        ImageHandle,
00341                        NULL);
00342     gEfiShellProtocol = NULL;
00343   }
00344   if (gEfiShellParametersProtocol != NULL) {
00345     gBS->CloseProtocol(ImageHandle,
00346                        &gEfiShellParametersProtocolGuid,
00347                        ImageHandle,
00348                        NULL);
00349     gEfiShellParametersProtocol = NULL;
00350   }
00351   mEfiShellEnvironment2Handle = NULL;
00352 
00353   return (EFI_SUCCESS);
00354 }
00355 
00369 EFI_STATUS
00370 EFIAPI
00371 ShellInitialize (
00372   )
00373 {
00374   //
00375   // if auto initialize is not false then skip
00376   //
00377   if (PcdGetBool(PcdShellLibAutoInitialize) != 0) {
00378     return (EFI_SUCCESS);
00379   }
00380 
00381   //
00382   // deinit the current stuff
00383   //
00384   ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST));
00385 
00386   //
00387   // init the new stuff
00388   //
00389   return (ShellLibConstructorWorker(gImageHandle, gST));
00390 }
00391 
00406 EFI_FILE_INFO*
00407 EFIAPI
00408 ShellGetFileInfo (
00409   IN SHELL_FILE_HANDLE                     FileHandle
00410   )
00411 {
00412   return (FileFunctionMap.GetFileInfo(FileHandle));
00413 }
00414 
00434 EFI_STATUS
00435 EFIAPI
00436 ShellSetFileInfo (
00437   IN SHELL_FILE_HANDLE                    FileHandle,
00438   IN EFI_FILE_INFO              *FileInfo
00439   )
00440 {
00441   return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));
00442 }
00443 
00474 EFI_STATUS
00475 EFIAPI
00476 ShellOpenFileByDevicePath(
00477   IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
00478   OUT EFI_HANDLE                      *DeviceHandle,
00479   OUT SHELL_FILE_HANDLE               *FileHandle,
00480   IN UINT64                           OpenMode,
00481   IN UINT64                           Attributes
00482   )
00483 {
00484   CHAR16                          *FileName;
00485   EFI_STATUS                      Status;
00486   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
00487   EFI_FILE_PROTOCOL               *Handle1;
00488   EFI_FILE_PROTOCOL               *Handle2;
00489 
00490   if (FilePath == NULL || FileHandle == NULL || DeviceHandle == NULL) {
00491     return (EFI_INVALID_PARAMETER);
00492   }
00493 
00494   //
00495   // which shell interface should we use
00496   //
00497   if (gEfiShellProtocol != NULL) {
00498     //
00499     // use UEFI Shell 2.0 method.
00500     //
00501     FileName = gEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);
00502     if (FileName == NULL) {
00503       return (EFI_INVALID_PARAMETER);
00504     }
00505     Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes);
00506     FreePool(FileName);
00507     return (Status);
00508   }
00509 
00510 
00511   //
00512   // use old shell method.
00513   //
00514   Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid,
00515                                   FilePath,
00516                                   DeviceHandle);
00517   if (EFI_ERROR (Status)) {
00518     return Status;
00519   }
00520   Status = gBS->OpenProtocol(*DeviceHandle,
00521                              &gEfiSimpleFileSystemProtocolGuid,
00522                              (VOID**)&EfiSimpleFileSystemProtocol,
00523                              gImageHandle,
00524                              NULL,
00525                              EFI_OPEN_PROTOCOL_GET_PROTOCOL);
00526   if (EFI_ERROR (Status)) {
00527     return Status;
00528   }
00529   Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
00530   if (EFI_ERROR (Status)) {
00531     FileHandle = NULL;
00532     return Status;
00533   }
00534 
00535   //
00536   // go down directories one node at a time.
00537   //
00538   while (!IsDevicePathEnd (*FilePath)) {
00539     //
00540     // For file system access each node should be a file path component
00541     //
00542     if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
00543         DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
00544        ) {
00545       FileHandle = NULL;
00546       return (EFI_INVALID_PARAMETER);
00547     }
00548     //
00549     // Open this file path node
00550     //
00551     Handle2  = Handle1;
00552     Handle1 = NULL;
00553 
00554     //
00555     // Try to test opening an existing file
00556     //
00557     Status = Handle2->Open (
00558                           Handle2,
00559                           &Handle1,
00560                           ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
00561                           OpenMode &~EFI_FILE_MODE_CREATE,
00562                           0
00563                          );
00564 
00565     //
00566     // see if the error was that it needs to be created
00567     //
00568     if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
00569       Status = Handle2->Open (
00570                             Handle2,
00571                             &Handle1,
00572                             ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
00573                             OpenMode,
00574                             Attributes
00575                            );
00576     }
00577     //
00578     // Close the last node
00579     //
00580     Handle2->Close (Handle2);
00581 
00582     if (EFI_ERROR(Status)) {
00583       return (Status);
00584     }
00585 
00586     //
00587     // Get the next node
00588     //
00589     *FilePath = NextDevicePathNode (*FilePath);
00590   }
00591 
00592   //
00593   // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
00594   //
00595   *FileHandle = (VOID*)Handle1;
00596   return (EFI_SUCCESS);
00597 }
00598 
00630 EFI_STATUS
00631 EFIAPI
00632 ShellOpenFileByName(
00633   IN CONST CHAR16               *FileName,
00634   OUT SHELL_FILE_HANDLE         *FileHandle,
00635   IN UINT64                     OpenMode,
00636   IN UINT64                     Attributes
00637   )
00638 {
00639   EFI_HANDLE                    DeviceHandle;
00640   EFI_DEVICE_PATH_PROTOCOL      *FilePath;
00641   EFI_STATUS                    Status;
00642   EFI_FILE_INFO                 *FileInfo;
00643 
00644   //
00645   // ASSERT if FileName is NULL
00646   //
00647   ASSERT(FileName != NULL);
00648 
00649   if (FileName == NULL) {
00650     return (EFI_INVALID_PARAMETER);
00651   }
00652 
00653   if (gEfiShellProtocol != NULL) {
00654     if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE && (Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
00655       return ShellCreateDirectory(FileName, FileHandle);
00656     }
00657     //
00658     // Use UEFI Shell 2.0 method
00659     //
00660     Status = gEfiShellProtocol->OpenFileByName(FileName,
00661                                                FileHandle,
00662                                                OpenMode);
00663     if (StrCmp(FileName, L"NUL") != 0 && !EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){
00664       FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);
00665       ASSERT(FileInfo != NULL);
00666       FileInfo->Attribute = Attributes;
00667       Status = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);
00668       FreePool(FileInfo);
00669     }
00670     return (Status);
00671   }
00672   //
00673   // Using EFI Shell version
00674   // this means convert name to path and call that function
00675   // since this will use EFI method again that will open it.
00676   //
00677   ASSERT(mEfiShellEnvironment2 != NULL);
00678   FilePath = mEfiShellEnvironment2->NameToPath ((CHAR16*)FileName);
00679   if (FilePath != NULL) {
00680     return (ShellOpenFileByDevicePath(&FilePath,
00681                                       &DeviceHandle,
00682                                       FileHandle,
00683                                       OpenMode,
00684                                       Attributes));
00685   }
00686   return (EFI_DEVICE_ERROR);
00687 }
00716 EFI_STATUS
00717 EFIAPI
00718 ShellCreateDirectory(
00719   IN CONST CHAR16             *DirectoryName,
00720   OUT SHELL_FILE_HANDLE                  *FileHandle
00721   )
00722 {
00723   if (gEfiShellProtocol != NULL) {
00724     //
00725     // Use UEFI Shell 2.0 method
00726     //
00727     return (gEfiShellProtocol->CreateFile(DirectoryName,
00728                           EFI_FILE_DIRECTORY,
00729                           FileHandle
00730                          ));
00731   } else {
00732     return (ShellOpenFileByName(DirectoryName,
00733                                 FileHandle,
00734                                 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
00735                                 EFI_FILE_DIRECTORY
00736                                ));
00737   }
00738 }
00739 
00769 EFI_STATUS
00770 EFIAPI
00771 ShellReadFile(
00772   IN SHELL_FILE_HANDLE                     FileHandle,
00773   IN OUT UINTN                  *BufferSize,
00774   OUT VOID                      *Buffer
00775   )
00776 {
00777   return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));
00778 }
00779 
00780 
00805 EFI_STATUS
00806 EFIAPI
00807 ShellWriteFile(
00808   IN SHELL_FILE_HANDLE          FileHandle,
00809   IN OUT UINTN                  *BufferSize,
00810   IN VOID                       *Buffer
00811   )
00812 {
00813   return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));
00814 }
00815 
00827 EFI_STATUS
00828 EFIAPI
00829 ShellCloseFile (
00830   IN SHELL_FILE_HANDLE                     *FileHandle
00831   )
00832 {
00833   return (FileFunctionMap.CloseFile(*FileHandle));
00834 }
00835 
00850 EFI_STATUS
00851 EFIAPI
00852 ShellDeleteFile (
00853   IN SHELL_FILE_HANDLE            *FileHandle
00854   )
00855 {
00856   return (FileFunctionMap.DeleteFile(*FileHandle));
00857 }
00858 
00878 EFI_STATUS
00879 EFIAPI
00880 ShellSetFilePosition (
00881   IN SHELL_FILE_HANDLE              FileHandle,
00882   IN UINT64             Position
00883   )
00884 {
00885   return (FileFunctionMap.SetFilePosition(FileHandle, Position));
00886 }
00887 
00903 EFI_STATUS
00904 EFIAPI
00905 ShellGetFilePosition (
00906   IN SHELL_FILE_HANDLE                     FileHandle,
00907   OUT UINT64                    *Position
00908   )
00909 {
00910   return (FileFunctionMap.GetFilePosition(FileHandle, Position));
00911 }
00926 EFI_STATUS
00927 EFIAPI
00928 ShellFlushFile (
00929   IN SHELL_FILE_HANDLE                     FileHandle
00930   )
00931 {
00932   return (FileFunctionMap.FlushFile(FileHandle));
00933 }
00934 
00957 EFI_STATUS
00958 EFIAPI
00959 ShellFindFirstFile (
00960   IN SHELL_FILE_HANDLE                     DirHandle,
00961   OUT EFI_FILE_INFO             **Buffer
00962   )
00963 {
00964   //
00965   // pass to file handle lib
00966   //
00967   return (FileHandleFindFirstFile(DirHandle, Buffer));
00968 }
00987 EFI_STATUS
00988 EFIAPI
00989 ShellFindNextFile(
00990   IN SHELL_FILE_HANDLE                      DirHandle,
00991   OUT EFI_FILE_INFO              *Buffer,
00992   OUT BOOLEAN                    *NoFile
00993   )
00994 {
00995   //
00996   // pass to file handle lib
00997   //
00998   return (FileHandleFindNextFile(DirHandle, Buffer, NoFile));
00999 }
01015 EFI_STATUS
01016 EFIAPI
01017 ShellGetFileSize (
01018   IN SHELL_FILE_HANDLE                     FileHandle,
01019   OUT UINT64                    *Size
01020   )
01021 {
01022   return (FileFunctionMap.GetFileSize(FileHandle, Size));
01023 }
01032 BOOLEAN
01033 EFIAPI
01034 ShellGetExecutionBreakFlag(
01035   VOID
01036   )
01037 {
01038   //
01039   // Check for UEFI Shell 2.0 protocols
01040   //
01041   if (gEfiShellProtocol != NULL) {
01042 
01043     //
01044     // We are using UEFI Shell 2.0; see if the event has been triggered
01045     //
01046     if (gBS->CheckEvent(gEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {
01047       return (FALSE);
01048     }
01049     return (TRUE);
01050   }
01051 
01052   //
01053   // using EFI Shell; call the function to check
01054   //
01055   if (mEfiShellEnvironment2 != NULL) {
01056     return (mEfiShellEnvironment2->GetExecutionBreak());
01057   }
01058 
01059   return (FALSE);
01060 }
01072 CONST CHAR16*
01073 EFIAPI
01074 ShellGetEnvironmentVariable (
01075   IN CONST CHAR16                *EnvKey
01076   )
01077 {
01078   //
01079   // Check for UEFI Shell 2.0 protocols
01080   //
01081   if (gEfiShellProtocol != NULL) {
01082     return (gEfiShellProtocol->GetEnv(EnvKey));
01083   }
01084 
01085   //
01086   // Check for EFI shell
01087   //
01088   if (mEfiShellEnvironment2 != NULL) {
01089     return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey));
01090   }
01091 
01092   return NULL;
01093 }
01114 EFI_STATUS
01115 EFIAPI
01116 ShellSetEnvironmentVariable (
01117   IN CONST CHAR16               *EnvKey,
01118   IN CONST CHAR16               *EnvVal,
01119   IN BOOLEAN                    Volatile
01120   )
01121 {
01122   //
01123   // Check for UEFI Shell 2.0 protocols
01124   //
01125   if (gEfiShellProtocol != NULL) {
01126     return (gEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));
01127   }
01128 
01129   //
01130   // This feature does not exist under EFI shell
01131   //
01132   return (EFI_UNSUPPORTED);
01133 }
01134 
01165 EFI_STATUS
01166 EFIAPI
01167 ShellExecute (
01168   IN EFI_HANDLE                 *ParentHandle,
01169   IN CHAR16                     *CommandLine OPTIONAL,
01170   IN BOOLEAN                    Output OPTIONAL,
01171   IN CHAR16                     **EnvironmentVariables OPTIONAL,
01172   OUT EFI_STATUS                *Status OPTIONAL
01173   )
01174 {
01175   //
01176   // Check for UEFI Shell 2.0 protocols
01177   //
01178   if (gEfiShellProtocol != NULL) {
01179     //
01180     // Call UEFI Shell 2.0 version (not using Output parameter)
01181     //
01182     return (gEfiShellProtocol->Execute(ParentHandle,
01183                                       CommandLine,
01184                                       EnvironmentVariables,
01185                                       Status));
01186   }
01187 
01188   //
01189   // Check for EFI shell
01190   //
01191   if (mEfiShellEnvironment2 != NULL) {
01192     //
01193     // Call EFI Shell version (not using EnvironmentVariables or Status parameters)
01194     // Due to oddity in the EFI shell we want to dereference the ParentHandle here
01195     //
01196     return (mEfiShellEnvironment2->Execute(*ParentHandle,
01197                                           CommandLine,
01198                                           Output));
01199   }
01200 
01201   return (EFI_UNSUPPORTED);
01202 }
01215 CONST CHAR16*
01216 EFIAPI
01217 ShellGetCurrentDir (
01218   IN CHAR16                     * CONST DeviceName OPTIONAL
01219   )
01220 {
01221   //
01222   // Check for UEFI Shell 2.0 protocols
01223   //
01224   if (gEfiShellProtocol != NULL) {
01225     return (gEfiShellProtocol->GetCurDir(DeviceName));
01226   }
01227 
01228   //
01229   // Check for EFI shell
01230   //
01231   if (mEfiShellEnvironment2 != NULL) {
01232     return (mEfiShellEnvironment2->CurDir(DeviceName));
01233   }
01234 
01235   return (NULL);
01236 }
01245 VOID
01246 EFIAPI
01247 ShellSetPageBreakMode (
01248   IN BOOLEAN                    CurrentState
01249   )
01250 {
01251   //
01252   // check for enabling
01253   //
01254   if (CurrentState != 0x00) {
01255     //
01256     // check for UEFI Shell 2.0
01257     //
01258     if (gEfiShellProtocol != NULL) {
01259       //
01260       // Enable with UEFI 2.0 Shell
01261       //
01262       gEfiShellProtocol->EnablePageBreak();
01263       return;
01264     } else {
01265       //
01266       // Check for EFI shell
01267       //
01268       if (mEfiShellEnvironment2 != NULL) {
01269         //
01270         // Enable with EFI Shell
01271         //
01272         mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);
01273         return;
01274       }
01275     }
01276   } else {
01277     //
01278     // check for UEFI Shell 2.0
01279     //
01280     if (gEfiShellProtocol != NULL) {
01281       //
01282       // Disable with UEFI 2.0 Shell
01283       //
01284       gEfiShellProtocol->DisablePageBreak();
01285       return;
01286     } else {
01287       //
01288       // Check for EFI shell
01289       //
01290       if (mEfiShellEnvironment2 != NULL) {
01291         //
01292         // Disable with EFI Shell
01293         //
01294         mEfiShellEnvironment2->DisablePageBreak ();
01295         return;
01296       }
01297     }
01298   }
01299 }
01300 
01305 typedef struct {
01306   LIST_ENTRY Link;
01307   EFI_STATUS Status;
01308   CHAR16 *FullName;
01309   CHAR16 *FileName;
01310   SHELL_FILE_HANDLE          Handle;
01311   EFI_FILE_INFO *Info;
01312 } EFI_SHELL_FILE_INFO_NO_CONST;
01313 
01328 LIST_ENTRY*
01329 EFIAPI
01330 InternalShellConvertFileListType (
01331   IN LIST_ENTRY                 *FileList,
01332   IN OUT LIST_ENTRY             *ListHead
01333   )
01334 {
01335   SHELL_FILE_ARG                *OldInfo;
01336   LIST_ENTRY                    *Link;
01337   EFI_SHELL_FILE_INFO_NO_CONST  *NewInfo;
01338 
01339   //
01340   // ASSERTs
01341   //
01342   ASSERT(FileList  != NULL);
01343   ASSERT(ListHead  != NULL);
01344 
01345   //
01346   // enumerate through each member of the old list and copy
01347   //
01348   for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {
01349     OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
01350     ASSERT(OldInfo           != NULL);
01351 
01352     //
01353     // Skip ones that failed to open...
01354     //
01355     if (OldInfo->Status != EFI_SUCCESS) {
01356       continue;
01357     }
01358 
01359     //
01360     // make sure the old list was valid
01361     //
01362     ASSERT(OldInfo->Info     != NULL);
01363     ASSERT(OldInfo->FullName != NULL);
01364     ASSERT(OldInfo->FileName != NULL);
01365 
01366     //
01367     // allocate a new EFI_SHELL_FILE_INFO object
01368     //
01369     NewInfo               = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
01370     if (NewInfo == NULL) {
01371       ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));
01372       ListHead = NULL;
01373       break;
01374     }
01375 
01376     //
01377     // copy the simple items
01378     //
01379     NewInfo->Handle       = OldInfo->Handle;
01380     NewInfo->Status       = OldInfo->Status;
01381 
01382     // old shell checks for 0 not NULL
01383     OldInfo->Handle = 0;
01384 
01385     //
01386     // allocate new space to copy strings and structure
01387     //
01388     NewInfo->FullName     = AllocateZeroPool(StrSize(OldInfo->FullName));
01389     NewInfo->FileName     = AllocateZeroPool(StrSize(OldInfo->FileName));
01390     NewInfo->Info         = AllocateZeroPool((UINTN)OldInfo->Info->Size);
01391 
01392     //
01393     // make sure all the memory allocations were sucessful
01394     //
01395     if (NULL == NewInfo->FullName || NewInfo->FileName == NULL || NewInfo->Info == NULL) {
01396       ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));
01397       ListHead = NULL;
01398       break;
01399     }
01400 
01401     //
01402     // Copt the strings and structure
01403     //
01404     StrCpy(NewInfo->FullName, OldInfo->FullName);
01405     StrCpy(NewInfo->FileName, OldInfo->FileName);
01406     gBS->CopyMem (NewInfo->Info, OldInfo->Info, (UINTN)OldInfo->Info->Size);
01407 
01408     //
01409     // add that to the list
01410     //
01411     InsertTailList(ListHead, &NewInfo->Link);
01412   }
01413   return (ListHead);
01414 }
01438 EFI_STATUS
01439 EFIAPI
01440 ShellOpenFileMetaArg (
01441   IN CHAR16                     *Arg,
01442   IN UINT64                     OpenMode,
01443   IN OUT EFI_SHELL_FILE_INFO    **ListHead
01444   )
01445 {
01446   EFI_STATUS                    Status;
01447   LIST_ENTRY                    mOldStyleFileList;
01448 
01449   //
01450   // ASSERT that Arg and ListHead are not NULL
01451   //
01452   ASSERT(Arg      != NULL);
01453   ASSERT(ListHead != NULL);
01454 
01455   //
01456   // Check for UEFI Shell 2.0 protocols
01457   //
01458   if (gEfiShellProtocol != NULL) {
01459     if (*ListHead == NULL) {
01460       *ListHead = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
01461       if (*ListHead == NULL) {
01462         return (EFI_OUT_OF_RESOURCES);
01463       }
01464       InitializeListHead(&((*ListHead)->Link));
01465     }
01466     Status = gEfiShellProtocol->OpenFileList(Arg,
01467                                            OpenMode,
01468                                            ListHead);
01469     if (EFI_ERROR(Status)) {
01470       gEfiShellProtocol->RemoveDupInFileList(ListHead);
01471     } else {
01472       Status = gEfiShellProtocol->RemoveDupInFileList(ListHead);
01473     }
01474     if (*ListHead != NULL && IsListEmpty(&(*ListHead)->Link)) {
01475       FreePool(*ListHead);
01476       *ListHead = NULL;
01477       return (EFI_NOT_FOUND);
01478     }
01479     return (Status);
01480   }
01481 
01482   //
01483   // Check for EFI shell
01484   //
01485   if (mEfiShellEnvironment2 != NULL) {
01486     //
01487     // make sure the list head is initialized
01488     //
01489     InitializeListHead(&mOldStyleFileList);
01490 
01491     //
01492     // Get the EFI Shell list of files
01493     //
01494     Status = mEfiShellEnvironment2->FileMetaArg(Arg, &mOldStyleFileList);
01495     if (EFI_ERROR(Status)) {
01496       *ListHead = NULL;
01497       return (Status);
01498     }
01499 
01500     if (*ListHead == NULL) {
01501       *ListHead = (EFI_SHELL_FILE_INFO    *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
01502       if (*ListHead == NULL) {
01503         return (EFI_OUT_OF_RESOURCES);
01504       }
01505       InitializeListHead(&((*ListHead)->Link));
01506     }
01507 
01508     //
01509     // Convert that to equivalent of UEFI Shell 2.0 structure
01510     //
01511     InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link);
01512 
01513     //
01514     // Free the EFI Shell version that was converted.
01515     //
01516     mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);
01517 
01518     if ((*ListHead)->Link.ForwardLink == (*ListHead)->Link.BackLink && (*ListHead)->Link.BackLink == &((*ListHead)->Link)) {
01519       FreePool(*ListHead);
01520       *ListHead = NULL;
01521       Status = EFI_NOT_FOUND;
01522     }
01523     return (Status);
01524   }
01525 
01526   return (EFI_UNSUPPORTED);
01527 }
01537 EFI_STATUS
01538 EFIAPI
01539 ShellCloseFileMetaArg (
01540   IN OUT EFI_SHELL_FILE_INFO    **ListHead
01541   )
01542 {
01543   LIST_ENTRY                    *Node;
01544 
01545   //
01546   // ASSERT that ListHead is not NULL
01547   //
01548   ASSERT(ListHead != NULL);
01549 
01550   //
01551   // Check for UEFI Shell 2.0 protocols
01552   //
01553   if (gEfiShellProtocol != NULL) {
01554     return (gEfiShellProtocol->FreeFileList(ListHead));
01555   } else if (mEfiShellEnvironment2 != NULL) {
01556     //
01557     // Since this is EFI Shell version we need to free our internally made copy
01558     // of the list
01559     //
01560     for ( Node = GetFirstNode(&(*ListHead)->Link)
01561         ; *ListHead != NULL && !IsListEmpty(&(*ListHead)->Link)
01562         ; Node = GetFirstNode(&(*ListHead)->Link)) {
01563       RemoveEntryList(Node);
01564       ((EFI_FILE_PROTOCOL*)((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle)->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);
01565       FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName);
01566       FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName);
01567       FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);
01568       FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);
01569     }
01570     return EFI_SUCCESS;
01571   }
01572 
01573   return (EFI_UNSUPPORTED);
01574 }
01575 
01588 CHAR16 *
01589 EFIAPI
01590 ShellFindFilePath (
01591   IN CONST CHAR16 *FileName
01592   )
01593 {
01594   CONST CHAR16      *Path;
01595   SHELL_FILE_HANDLE Handle;
01596   EFI_STATUS        Status;
01597   CHAR16            *RetVal;
01598   CHAR16            *TestPath;
01599   CONST CHAR16      *Walker;
01600   UINTN             Size;
01601   CHAR16            *TempChar;
01602 
01603   RetVal = NULL;
01604 
01605   //
01606   // First make sure its not an absolute path.
01607   //
01608   Status = ShellOpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ, 0);
01609   if (!EFI_ERROR(Status)){
01610     if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
01611       ASSERT(RetVal == NULL);
01612       RetVal = StrnCatGrow(&RetVal, NULL, FileName, 0);
01613       ShellCloseFile(&Handle);
01614       return (RetVal);
01615     } else {
01616       ShellCloseFile(&Handle);
01617     }
01618   }
01619 
01620   Path = ShellGetEnvironmentVariable(L"cwd");
01621   if (Path != NULL) {
01622     Size = StrSize(Path);
01623     Size += StrSize(FileName);
01624     TestPath = AllocateZeroPool(Size);
01625     if (TestPath == NULL) {
01626       return (NULL);
01627     }
01628     StrCpy(TestPath, Path);
01629     StrCat(TestPath, FileName);
01630     Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);
01631     if (!EFI_ERROR(Status)){
01632       if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
01633         ASSERT(RetVal == NULL);
01634         RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
01635         ShellCloseFile(&Handle);
01636         FreePool(TestPath);
01637         return (RetVal);
01638       } else {
01639         ShellCloseFile(&Handle);
01640       }
01641     }
01642     FreePool(TestPath);
01643   }
01644   Path = ShellGetEnvironmentVariable(L"path");
01645   if (Path != NULL) {
01646     Size = StrSize(Path)+sizeof(CHAR16);
01647     Size += StrSize(FileName);
01648     TestPath = AllocateZeroPool(Size);
01649     if (TestPath == NULL) {
01650       return (NULL);
01651     }
01652     Walker = (CHAR16*)Path;
01653     do {
01654       CopyMem(TestPath, Walker, StrSize(Walker));
01655       if (TestPath != NULL) {
01656         TempChar = StrStr(TestPath, L";");
01657         if (TempChar != NULL) {
01658           *TempChar = CHAR_NULL;
01659         }
01660         if (TestPath[StrLen(TestPath)-1] != L'\\') {
01661           StrCat(TestPath, L"\\");
01662         }
01663         if (FileName[0] == L'\\') {
01664           FileName++;
01665         }
01666         StrCat(TestPath, FileName);
01667         if (StrStr(Walker, L";") != NULL) {
01668           Walker = StrStr(Walker, L";") + 1;
01669         } else {
01670           Walker = NULL;
01671         }
01672         Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);
01673         if (!EFI_ERROR(Status)){
01674           if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
01675             ASSERT(RetVal == NULL);
01676             RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
01677             ShellCloseFile(&Handle);
01678             break;
01679           } else {
01680             ShellCloseFile(&Handle);
01681           }
01682         }
01683       }
01684     } while (Walker != NULL && Walker[0] != CHAR_NULL);
01685     FreePool(TestPath);
01686   }
01687   return (RetVal);
01688 }
01689 
01706 CHAR16 *
01707 EFIAPI
01708 ShellFindFilePathEx (
01709   IN CONST CHAR16 *FileName,
01710   IN CONST CHAR16 *FileExtension
01711   )
01712 {
01713   CHAR16            *TestPath;
01714   CHAR16            *RetVal;
01715   CONST CHAR16      *ExtensionWalker;
01716   UINTN             Size;
01717   CHAR16            *TempChar;
01718   CHAR16            *TempChar2;
01719 
01720   ASSERT(FileName != NULL);
01721   if (FileExtension == NULL) {
01722     return (ShellFindFilePath(FileName));
01723   }
01724   RetVal = ShellFindFilePath(FileName);
01725   if (RetVal != NULL) {
01726     return (RetVal);
01727   }
01728   Size =  StrSize(FileName);
01729   Size += StrSize(FileExtension);
01730   TestPath = AllocateZeroPool(Size);
01731   if (TestPath == NULL) {
01732     return (NULL);
01733   }
01734   for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension;  TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){
01735     StrCpy(TestPath, FileName);
01736     if (ExtensionWalker != NULL) {
01737       StrCat(TestPath, ExtensionWalker);
01738     }
01739     TempChar = StrStr(TestPath, L";");
01740     if (TempChar != NULL) {
01741       *TempChar = CHAR_NULL;
01742     }
01743     RetVal = ShellFindFilePath(TestPath);
01744     if (RetVal != NULL) {
01745       break;
01746     }
01747     ASSERT(ExtensionWalker != NULL);
01748     TempChar2 = StrStr(ExtensionWalker, L";");
01749   }
01750   FreePool(TestPath);
01751   return (RetVal);
01752 }
01753 
01754 typedef struct {
01755   LIST_ENTRY     Link;
01756   CHAR16         *Name;
01757   SHELL_PARAM_TYPE      Type;
01758   CHAR16         *Value;
01759   UINTN          OriginalPosition;
01760 } SHELL_PARAM_PACKAGE;
01761 
01777 BOOLEAN
01778 EFIAPI
01779 InternalIsOnCheckList (
01780   IN CONST CHAR16               *Name,
01781   IN CONST SHELL_PARAM_ITEM     *CheckList,
01782   OUT SHELL_PARAM_TYPE          *Type
01783   )
01784 {
01785   SHELL_PARAM_ITEM              *TempListItem;
01786   CHAR16                        *TempString;
01787 
01788   //
01789   // ASSERT that all 3 pointer parameters aren't NULL
01790   //
01791   ASSERT(CheckList  != NULL);
01792   ASSERT(Type       != NULL);
01793   ASSERT(Name       != NULL);
01794 
01795   //
01796   // question mark and page break mode are always supported
01797   //
01798   if ((StrCmp(Name, L"-?") == 0) ||
01799       (StrCmp(Name, L"-b") == 0)
01800      ) {
01801      *Type = TypeFlag;
01802      return (TRUE);
01803   }
01804 
01805   //
01806   // Enumerate through the list
01807   //
01808   for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) {
01809     //
01810     // If the Type is TypeStart only check the first characters of the passed in param
01811     // If it matches set the type and return TRUE
01812     //
01813     if (TempListItem->Type == TypeStart) {
01814       if (StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) {
01815         *Type = TempListItem->Type;
01816         return (TRUE);
01817       }
01818       TempString = NULL;
01819       TempString = StrnCatGrow(&TempString, NULL, Name, StrLen(TempListItem->Name));
01820       if (TempString != NULL) {
01821         if (StringNoCaseCompare(&TempString, &TempListItem->Name) == 0) {
01822           *Type = TempListItem->Type;
01823           FreePool(TempString);
01824           return (TRUE);
01825         }
01826         FreePool(TempString);
01827       }
01828     } else if (StringNoCaseCompare(&Name, &TempListItem->Name) == 0) {
01829       *Type = TempListItem->Type;
01830       return (TRUE);
01831     }
01832   }
01833 
01834   return (FALSE);
01835 }
01845 BOOLEAN
01846 EFIAPI
01847 InternalIsFlag (
01848   IN CONST CHAR16               *Name,
01849   IN BOOLEAN                    AlwaysAllowNumbers
01850   )
01851 {
01852   //
01853   // ASSERT that Name isn't NULL
01854   //
01855   ASSERT(Name != NULL);
01856 
01857   //
01858   // If we accept numbers then dont return TRUE. (they will be values)
01859   //
01860   if (((Name[0] == L'-' || Name[0] == L'+') && ShellIsHexaDecimalDigitCharacter(Name[1])) && AlwaysAllowNumbers) {
01861     return (FALSE);
01862   }
01863 
01864   //
01865   // If the Name has a /, +, or - as the first character return TRUE
01866   //
01867   if ((Name[0] == L'/') ||
01868       (Name[0] == L'-') ||
01869       (Name[0] == L'+')
01870      ) {
01871       return (TRUE);
01872   }
01873   return (FALSE);
01874 }
01875 
01901 EFI_STATUS
01902 EFIAPI
01903 InternalCommandLineParse (
01904   IN CONST SHELL_PARAM_ITEM     *CheckList,
01905   OUT LIST_ENTRY                **CheckPackage,
01906   OUT CHAR16                    **ProblemParam OPTIONAL,
01907   IN BOOLEAN                    AutoPageBreak,
01908   IN CONST CHAR16               **Argv,
01909   IN UINTN                      Argc,
01910   IN BOOLEAN                    AlwaysAllowNumbers
01911   )
01912 {
01913   UINTN                         LoopCounter;
01914   SHELL_PARAM_TYPE              CurrentItemType;
01915   SHELL_PARAM_PACKAGE           *CurrentItemPackage;
01916   UINTN                         GetItemValue;
01917   UINTN                         ValueSize;
01918   UINTN                         Count;
01919   CONST CHAR16                  *TempPointer;
01920 
01921   CurrentItemPackage = NULL;
01922   GetItemValue = 0;
01923   ValueSize = 0;
01924   Count = 0;
01925 
01926   //
01927   // If there is only 1 item we dont need to do anything
01928   //
01929   if (Argc < 1) {
01930     *CheckPackage = NULL;
01931     return (EFI_SUCCESS);
01932   }
01933 
01934   //
01935   // ASSERTs
01936   //
01937   ASSERT(CheckList  != NULL);
01938   ASSERT(Argv       != NULL);
01939 
01940   //
01941   // initialize the linked list
01942   //
01943   *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY));
01944   if (*CheckPackage == NULL) {
01945     return (EFI_OUT_OF_RESOURCES);
01946   }
01947 
01948   InitializeListHead(*CheckPackage);
01949 
01950   //
01951   // loop through each of the arguments
01952   //
01953   for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) {
01954     if (Argv[LoopCounter] == NULL) {
01955       //
01956       // do nothing for NULL argv
01957       //
01958     } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType)) {
01959       //
01960       // We might have leftover if last parameter didnt have optional value
01961       //
01962       if (GetItemValue != 0) {
01963         GetItemValue = 0;
01964         InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
01965       }
01966       //
01967       // this is a flag
01968       //
01969       CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));
01970       if (CurrentItemPackage == NULL) {
01971         ShellCommandLineFreeVarList(*CheckPackage);
01972         *CheckPackage = NULL;
01973         return (EFI_OUT_OF_RESOURCES);
01974       }
01975       CurrentItemPackage->Name  = AllocateZeroPool(StrSize(Argv[LoopCounter]));
01976       if (CurrentItemPackage->Name == NULL) {
01977         ShellCommandLineFreeVarList(*CheckPackage);
01978         *CheckPackage = NULL;
01979         return (EFI_OUT_OF_RESOURCES);
01980       }
01981       StrCpy(CurrentItemPackage->Name,  Argv[LoopCounter]);
01982       CurrentItemPackage->Type  = CurrentItemType;
01983       CurrentItemPackage->OriginalPosition = (UINTN)(-1);
01984       CurrentItemPackage->Value = NULL;
01985 
01986       //
01987       // Does this flag require a value
01988       //
01989       switch (CurrentItemPackage->Type) {
01990         //
01991         // possibly trigger the next loop(s) to populate the value of this item
01992         //
01993         case TypeValue:
01994           GetItemValue = 1;
01995           ValueSize = 0;
01996           break;
01997         case TypeDoubleValue:
01998           GetItemValue = 2;
01999           ValueSize = 0;
02000           break;
02001         case TypeMaxValue:
02002           GetItemValue = (UINTN)(-1);
02003           ValueSize = 0;
02004           break;
02005         default:
02006           //
02007           // this item has no value expected; we are done
02008           //
02009           InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
02010           ASSERT(GetItemValue == 0);
02011           break;
02012       }
02013     } else if (GetItemValue != 0 && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers)) {
02014       ASSERT(CurrentItemPackage != NULL);
02015       //
02016       // get the item VALUE for a previous flag
02017       //
02018       CurrentItemPackage->Value = ReallocatePool(ValueSize, ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16), CurrentItemPackage->Value);
02019       ASSERT(CurrentItemPackage->Value != NULL);
02020       if (ValueSize == 0) {
02021         StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);
02022       } else {
02023         StrCat(CurrentItemPackage->Value, L" ");
02024         StrCat(CurrentItemPackage->Value, Argv[LoopCounter]);
02025       }
02026       ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);
02027       GetItemValue--;
02028       if (GetItemValue == 0) {
02029         InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
02030       }
02031     } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) ){ //|| ProblemParam == NULL) {
02032       //
02033       // add this one as a non-flag
02034       //
02035 
02036       TempPointer = Argv[LoopCounter];
02037       if ((*TempPointer == L'^' && *(TempPointer+1) == L'-')
02038        || (*TempPointer == L'^' && *(TempPointer+1) == L'/')
02039        || (*TempPointer == L'^' && *(TempPointer+1) == L'+')
02040       ){
02041         TempPointer++;
02042       }
02043       CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));
02044       if (CurrentItemPackage == NULL) {
02045         ShellCommandLineFreeVarList(*CheckPackage);
02046         *CheckPackage = NULL;
02047         return (EFI_OUT_OF_RESOURCES);
02048       }
02049       CurrentItemPackage->Name  = NULL;
02050       CurrentItemPackage->Type  = TypePosition;
02051       CurrentItemPackage->Value = AllocateZeroPool(StrSize(TempPointer));
02052       if (CurrentItemPackage->Value == NULL) {
02053         ShellCommandLineFreeVarList(*CheckPackage);
02054         *CheckPackage = NULL;
02055         return (EFI_OUT_OF_RESOURCES);
02056       }
02057       StrCpy(CurrentItemPackage->Value, TempPointer);
02058       CurrentItemPackage->OriginalPosition = Count++;
02059       InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
02060     } else {
02061       //
02062       // this was a non-recognised flag... error!
02063       //
02064       if (ProblemParam != NULL) {
02065         *ProblemParam = AllocateZeroPool(StrSize(Argv[LoopCounter]));
02066         if (*ProblemParam != NULL) {
02067           StrCpy(*ProblemParam, Argv[LoopCounter]);
02068         }
02069       }
02070       ShellCommandLineFreeVarList(*CheckPackage);
02071       *CheckPackage = NULL;
02072       return (EFI_VOLUME_CORRUPTED);
02073     }
02074   }
02075   if (GetItemValue != 0) {
02076     GetItemValue = 0;
02077     InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
02078   }
02079   //
02080   // support for AutoPageBreak
02081   //
02082   if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) {
02083     ShellSetPageBreakMode(TRUE);
02084   }
02085   return (EFI_SUCCESS);
02086 }
02087 
02112 EFI_STATUS
02113 EFIAPI
02114 ShellCommandLineParseEx (
02115   IN CONST SHELL_PARAM_ITEM     *CheckList,
02116   OUT LIST_ENTRY                **CheckPackage,
02117   OUT CHAR16                    **ProblemParam OPTIONAL,
02118   IN BOOLEAN                    AutoPageBreak,
02119   IN BOOLEAN                    AlwaysAllowNumbers
02120   )
02121 {
02122   //
02123   // ASSERT that CheckList and CheckPackage aren't NULL
02124   //
02125   ASSERT(CheckList    != NULL);
02126   ASSERT(CheckPackage != NULL);
02127 
02128   //
02129   // Check for UEFI Shell 2.0 protocols
02130   //
02131   if (gEfiShellParametersProtocol != NULL) {
02132     return (InternalCommandLineParse(CheckList,
02133                                      CheckPackage,
02134                                      ProblemParam,
02135                                      AutoPageBreak,
02136                                      (CONST CHAR16**) gEfiShellParametersProtocol->Argv,
02137                                      gEfiShellParametersProtocol->Argc,
02138                                      AlwaysAllowNumbers));
02139   }
02140 
02141   //
02142   // ASSERT That EFI Shell is not required
02143   //
02144   ASSERT (mEfiShellInterface != NULL);
02145   return (InternalCommandLineParse(CheckList,
02146                                    CheckPackage,
02147                                    ProblemParam,
02148                                    AutoPageBreak,
02149                                    (CONST CHAR16**) mEfiShellInterface->Argv,
02150                                    mEfiShellInterface->Argc,
02151                                    AlwaysAllowNumbers));
02152 }
02153 
02166 VOID
02167 EFIAPI
02168 ShellCommandLineFreeVarList (
02169   IN LIST_ENTRY                 *CheckPackage
02170   )
02171 {
02172   LIST_ENTRY                    *Node;
02173 
02174   //
02175   // check for CheckPackage == NULL
02176   //
02177   if (CheckPackage == NULL) {
02178     return;
02179   }
02180 
02181   //
02182   // for each node in the list
02183   //
02184   for ( Node = GetFirstNode(CheckPackage)
02185       ; !IsListEmpty(CheckPackage)
02186       ; Node = GetFirstNode(CheckPackage)
02187      ){
02188     //
02189     // Remove it from the list
02190     //
02191     RemoveEntryList(Node);
02192 
02193     //
02194     // if it has a name free the name
02195     //
02196     if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {
02197       FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name);
02198     }
02199 
02200     //
02201     // if it has a value free the value
02202     //
02203     if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) {
02204       FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value);
02205     }
02206 
02207     //
02208     // free the node structure
02209     //
02210     FreePool((SHELL_PARAM_PACKAGE*)Node);
02211   }
02212   //
02213   // free the list head node
02214   //
02215   FreePool(CheckPackage);
02216 }
02231 BOOLEAN
02232 EFIAPI
02233 ShellCommandLineGetFlag (
02234   IN CONST LIST_ENTRY         * CONST CheckPackage,
02235   IN CONST CHAR16             * CONST KeyString
02236   )
02237 {
02238   LIST_ENTRY                    *Node;
02239   CHAR16                        *TempString;
02240 
02241   //
02242   // return FALSE for no package or KeyString is NULL
02243   //
02244   if (CheckPackage == NULL || KeyString == NULL) {
02245     return (FALSE);
02246   }
02247 
02248   //
02249   // enumerate through the list of parametrs
02250   //
02251   for ( Node = GetFirstNode(CheckPackage)
02252       ; !IsNull (CheckPackage, Node)
02253       ; Node = GetNextNode(CheckPackage, Node)
02254       ){
02255     //
02256     // If the Name matches, return TRUE (and there may be NULL name)
02257     //
02258     if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {
02259       //
02260       // If Type is TypeStart then only compare the begining of the strings
02261       //
02262       if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {
02263         if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {
02264           return (TRUE);
02265         }
02266         TempString = NULL;
02267         TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));
02268         if (TempString != NULL) {
02269           if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
02270             FreePool(TempString);
02271             return (TRUE);
02272           }
02273           FreePool(TempString);
02274         }
02275       } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
02276         return (TRUE);
02277       }
02278     }
02279   }
02280   return (FALSE);
02281 }
02295 CONST CHAR16*
02296 EFIAPI
02297 ShellCommandLineGetValue (
02298   IN CONST LIST_ENTRY           *CheckPackage,
02299   IN CHAR16                     *KeyString
02300   )
02301 {
02302   LIST_ENTRY                    *Node;
02303   CHAR16                        *TempString;
02304 
02305   //
02306   // return NULL for no package or KeyString is NULL
02307   //
02308   if (CheckPackage == NULL || KeyString == NULL) {
02309     return (NULL);
02310   }
02311 
02312   //
02313   // enumerate through the list of parametrs
02314   //
02315   for ( Node = GetFirstNode(CheckPackage)
02316       ; !IsNull (CheckPackage, Node)
02317       ; Node = GetNextNode(CheckPackage, Node)
02318       ){
02319     //
02320     // If the Name matches, return TRUE (and there may be NULL name)
02321     //
02322     if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {
02323       //
02324       // If Type is TypeStart then only compare the begining of the strings
02325       //
02326       if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {
02327         if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {
02328           return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));
02329         }
02330         TempString = NULL;
02331         TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));
02332         if (TempString != NULL) {
02333           if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
02334             FreePool(TempString);
02335             return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));
02336           }
02337           FreePool(TempString);
02338         }
02339       } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
02340         return (((SHELL_PARAM_PACKAGE*)Node)->Value);
02341       }
02342     }
02343   }
02344   return (NULL);
02345 }
02346 
02360 CONST CHAR16*
02361 EFIAPI
02362 ShellCommandLineGetRawValue (
02363   IN CONST LIST_ENTRY           * CONST CheckPackage,
02364   IN UINTN                      Position
02365   )
02366 {
02367   LIST_ENTRY                    *Node;
02368 
02369   //
02370   // check for CheckPackage == NULL
02371   //
02372   if (CheckPackage == NULL) {
02373     return (NULL);
02374   }
02375 
02376   //
02377   // enumerate through the list of parametrs
02378   //
02379   for ( Node = GetFirstNode(CheckPackage)
02380       ; !IsNull (CheckPackage, Node)
02381       ; Node = GetNextNode(CheckPackage, Node)
02382      ){
02383     //
02384     // If the position matches, return the value
02385     //
02386     if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) {
02387       return (((SHELL_PARAM_PACKAGE*)Node)->Value);
02388     }
02389   }
02390   return (NULL);
02391 }
02392 
02403 UINTN
02404 EFIAPI
02405 ShellCommandLineGetCount(
02406   IN CONST LIST_ENTRY              *CheckPackage
02407   )
02408 {
02409   LIST_ENTRY  *Node1;
02410   UINTN       Count;
02411 
02412   if (CheckPackage == NULL) {
02413     return (0);
02414   }
02415   for ( Node1 = GetFirstNode(CheckPackage), Count = 0
02416       ; !IsNull (CheckPackage, Node1)
02417       ; Node1 = GetNextNode(CheckPackage, Node1)
02418      ){
02419     if (((SHELL_PARAM_PACKAGE*)Node1)->Name == NULL) {
02420       Count++;
02421     }
02422   }
02423   return (Count);
02424 }
02425 
02440 EFI_STATUS
02441 EFIAPI
02442 ShellCommandLineCheckDuplicate (
02443   IN CONST LIST_ENTRY              *CheckPackage,
02444   OUT CHAR16                       **Param
02445   )
02446 {
02447   LIST_ENTRY                    *Node1;
02448   LIST_ENTRY                    *Node2;
02449 
02450   ASSERT(CheckPackage != NULL);
02451 
02452   for ( Node1 = GetFirstNode(CheckPackage)
02453       ; !IsNull (CheckPackage, Node1)
02454       ; Node1 = GetNextNode(CheckPackage, Node1)
02455      ){
02456     for ( Node2 = GetNextNode(CheckPackage, Node1)
02457         ; !IsNull (CheckPackage, Node2)
02458         ; Node2 = GetNextNode(CheckPackage, Node2)
02459        ){
02460       if ((((SHELL_PARAM_PACKAGE*)Node1)->Name != NULL) && (((SHELL_PARAM_PACKAGE*)Node2)->Name != NULL) && StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {
02461         if (Param != NULL) {
02462           *Param = NULL;
02463           *Param = StrnCatGrow(Param, NULL, ((SHELL_PARAM_PACKAGE*)Node1)->Name, 0);
02464         }
02465         return (EFI_DEVICE_ERROR);
02466       }
02467     }
02468   }
02469   return (EFI_SUCCESS);
02470 }
02471 
02499 EFI_STATUS
02500 EFIAPI
02501 ShellCopySearchAndReplace(
02502   IN CHAR16 CONST                     *SourceString,
02503   IN OUT CHAR16                       *NewString,
02504   IN UINTN                            NewSize,
02505   IN CONST CHAR16                     *FindTarget,
02506   IN CONST CHAR16                     *ReplaceWith,
02507   IN CONST BOOLEAN                    SkipPreCarrot,
02508   IN CONST BOOLEAN                    ParameterReplacing
02509   )
02510 {
02511   UINTN Size;
02512   CHAR16 *Replace;
02513 
02514   if ( (SourceString == NULL)
02515     || (NewString    == NULL)
02516     || (FindTarget   == NULL)
02517     || (ReplaceWith  == NULL)
02518     || (StrLen(FindTarget) < 1)
02519     || (StrLen(SourceString) < 1)
02520    ){
02521     return (EFI_INVALID_PARAMETER);
02522   }
02523   Replace = NULL;
02524   if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) {
02525     Replace = StrnCatGrow(&Replace, NULL, ReplaceWith, 0);
02526   } else {
02527     Replace = AllocateZeroPool(StrSize(ReplaceWith) + 2*sizeof(CHAR16));
02528     if (Replace != NULL) {
02529       UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith);
02530     }
02531   }
02532   if (Replace == NULL) {
02533     return (EFI_OUT_OF_RESOURCES);
02534   }
02535   NewString = SetMem16(NewString, NewSize, CHAR_NULL);
02536   while (*SourceString != CHAR_NULL) {
02537     //
02538     // if we find the FindTarget and either Skip == FALSE or Skip  and we
02539     // dont have a carrot do a replace...
02540     //
02541     if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0
02542       && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot)
02543      ){
02544       SourceString += StrLen(FindTarget);
02545       Size = StrSize(NewString);
02546       if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) {
02547         FreePool(Replace);
02548         return (EFI_BUFFER_TOO_SMALL);
02549       }
02550       StrCat(NewString, Replace);
02551     } else {
02552       Size = StrSize(NewString);
02553       if (Size + sizeof(CHAR16) > NewSize) {
02554         FreePool(Replace);
02555         return (EFI_BUFFER_TOO_SMALL);
02556       }
02557       StrnCat(NewString, SourceString, 1);
02558       SourceString++;
02559     }
02560   }
02561   FreePool(Replace);
02562   return (EFI_SUCCESS);
02563 }
02564 
02575 EFI_STATUS
02576 EFIAPI
02577 InternalPrintTo (
02578   IN CONST CHAR16 *String
02579   )
02580 {
02581   UINTN Size;
02582   Size = StrSize(String) - sizeof(CHAR16);
02583   if (Size == 0) {
02584     return (EFI_SUCCESS);
02585   }
02586   if (gEfiShellParametersProtocol != NULL) {
02587     return (gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));
02588   }
02589   if (mEfiShellInterface          != NULL) {
02590     //
02591     // Divide in half for old shell.  Must be string length not size.
02592     //
02593     Size /= 2;
02594     return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut,          &Size, (VOID*)String));
02595   }
02596   ASSERT(FALSE);
02597   return (EFI_UNSUPPORTED);
02598 }
02599 
02629 EFI_STATUS
02630 EFIAPI
02631 InternalShellPrintWorker(
02632   IN INT32                Col OPTIONAL,
02633   IN INT32                Row OPTIONAL,
02634   IN CONST CHAR16         *Format,
02635   IN VA_LIST              Marker
02636   )
02637 {
02638   EFI_STATUS        Status;
02639   CHAR16            *ResumeLocation;
02640   CHAR16            *FormatWalker;
02641   UINTN             OriginalAttribute;
02642   CHAR16            *mPostReplaceFormat;
02643   CHAR16            *mPostReplaceFormat2;
02644 
02645   mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));
02646   mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));
02647 
02648   if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) {
02649     SHELL_FREE_NON_NULL(mPostReplaceFormat);
02650     SHELL_FREE_NON_NULL(mPostReplaceFormat2);
02651     return (EFI_OUT_OF_RESOURCES);
02652   }
02653 
02654   Status            = EFI_SUCCESS;
02655   OriginalAttribute = gST->ConOut->Mode->Attribute;
02656 
02657   //
02658   // Back and forth each time fixing up 1 of our flags...
02659   //
02660   Status = ShellCopySearchAndReplace(Format,             mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N", FALSE, FALSE);
02661   ASSERT_EFI_ERROR(Status);
02662   Status = ShellCopySearchAndReplace(mPostReplaceFormat,  mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E", FALSE, FALSE);
02663   ASSERT_EFI_ERROR(Status);
02664   Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H", FALSE, FALSE);
02665   ASSERT_EFI_ERROR(Status);
02666   Status = ShellCopySearchAndReplace(mPostReplaceFormat,  mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B", FALSE, FALSE);
02667   ASSERT_EFI_ERROR(Status);
02668   Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V", FALSE, FALSE);
02669   ASSERT_EFI_ERROR(Status);
02670 
02671   //
02672   // Use the last buffer from replacing to print from...
02673   //
02674   UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);
02675 
02676   if (Col != -1 && Row != -1) {
02677     Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
02678   }
02679 
02680   FormatWalker = mPostReplaceFormat2;
02681   while (*FormatWalker != CHAR_NULL) {
02682     //
02683     // Find the next attribute change request
02684     //
02685     ResumeLocation = StrStr(FormatWalker, L"%");
02686     if (ResumeLocation != NULL) {
02687       *ResumeLocation = CHAR_NULL;
02688     }
02689     //
02690     // print the current FormatWalker string
02691     //
02692     if (StrLen(FormatWalker)>0) {
02693       Status = InternalPrintTo(FormatWalker);
02694       if (EFI_ERROR(Status)) {
02695         break;
02696       }
02697     }
02698 
02699     //
02700     // update the attribute
02701     //
02702     if (ResumeLocation != NULL) {
02703       if (*(ResumeLocation-1) == L'^') {
02704         //
02705         // Print a simple '%' symbol
02706         //
02707         Status = InternalPrintTo(L"%");
02708         ResumeLocation = ResumeLocation - 1;
02709       } else {
02710         switch (*(ResumeLocation+1)) {
02711           case (L'N'):
02712             gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);
02713             break;
02714           case (L'E'):
02715             gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
02716             break;
02717           case (L'H'):
02718             gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
02719             break;
02720           case (L'B'):
02721             gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
02722             break;
02723           case (L'V'):
02724             gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
02725             break;
02726           default:
02727             //
02728             // Print a simple '%' symbol
02729             //
02730             Status = InternalPrintTo(L"%");
02731             if (EFI_ERROR(Status)) {
02732               break;
02733             }
02734             ResumeLocation = ResumeLocation - 1;
02735             break;
02736         }
02737       }
02738     } else {
02739       //
02740       // reset to normal now...
02741       //
02742       break;
02743     }
02744 
02745     //
02746     // update FormatWalker to Resume + 2 (skip the % and the indicator)
02747     //
02748     FormatWalker = ResumeLocation + 2;
02749   }
02750 
02751   gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);
02752 
02753   SHELL_FREE_NON_NULL(mPostReplaceFormat);
02754   SHELL_FREE_NON_NULL(mPostReplaceFormat2);
02755   return (Status);
02756 }
02757 
02787 EFI_STATUS
02788 EFIAPI
02789 ShellPrintEx(
02790   IN INT32                Col OPTIONAL,
02791   IN INT32                Row OPTIONAL,
02792   IN CONST CHAR16         *Format,
02793   ...
02794   )
02795 {
02796   VA_LIST           Marker;
02797   EFI_STATUS        RetVal;
02798   if (Format == NULL) {
02799     return (EFI_INVALID_PARAMETER);
02800   }
02801   VA_START (Marker, Format);
02802   RetVal = InternalShellPrintWorker(Col, Row, Format, Marker);
02803   VA_END(Marker);
02804   return(RetVal);
02805 }
02806 
02839 EFI_STATUS
02840 EFIAPI
02841 ShellPrintHiiEx(
02842   IN INT32                Col OPTIONAL,
02843   IN INT32                Row OPTIONAL,
02844   IN CONST CHAR8          *Language OPTIONAL,
02845   IN CONST EFI_STRING_ID  HiiFormatStringId,
02846   IN CONST EFI_HANDLE     HiiFormatHandle,
02847   ...
02848   )
02849 {
02850   VA_LIST           Marker;
02851   CHAR16            *HiiFormatString;
02852   EFI_STATUS        RetVal;
02853 
02854   VA_START (Marker, HiiFormatHandle);
02855   HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, Language);
02856   ASSERT(HiiFormatString != NULL);
02857 
02858   RetVal = InternalShellPrintWorker(Col, Row, HiiFormatString, Marker);
02859 
02860   SHELL_FREE_NON_NULL(HiiFormatString);
02861   VA_END(Marker);
02862 
02863   return (RetVal);
02864 }
02865 
02876 EFI_STATUS
02877 EFIAPI
02878 ShellIsDirectory(
02879   IN CONST CHAR16 *DirName
02880   )
02881 {
02882   EFI_STATUS        Status;
02883   SHELL_FILE_HANDLE Handle;
02884   CHAR16            *TempLocation;
02885   CHAR16            *TempLocation2;
02886 
02887   ASSERT(DirName != NULL);
02888 
02889   Handle        = NULL;
02890   TempLocation  = NULL;
02891 
02892   Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0);
02893   if (EFI_ERROR(Status)) {
02894     //
02895     // try good logic first.
02896     //
02897     if (gEfiShellProtocol != NULL) {
02898       TempLocation  = StrnCatGrow(&TempLocation, NULL, DirName, 0);
02899       if (TempLocation == NULL) {
02900         ShellCloseFile(&Handle);
02901         return (EFI_OUT_OF_RESOURCES);
02902       }
02903       TempLocation2 = StrStr(TempLocation, L":");
02904       if (TempLocation2 != NULL && StrLen(StrStr(TempLocation, L":")) == 2) {
02905         *(TempLocation2+1) = CHAR_NULL;
02906       }
02907       if (gEfiShellProtocol->GetDevicePathFromMap(TempLocation) != NULL) {
02908         FreePool(TempLocation);
02909         return (EFI_SUCCESS);
02910       }
02911       FreePool(TempLocation);
02912     } else {
02913       //
02914       // probably a map name?!?!!?
02915       //
02916       TempLocation = StrStr(DirName, L"\\");
02917       if (TempLocation != NULL && *(TempLocation+1) == CHAR_NULL) {
02918         return (EFI_SUCCESS);
02919       }
02920     }
02921     return (Status);
02922   }
02923 
02924   if (FileHandleIsDirectory(Handle) == EFI_SUCCESS) {
02925     ShellCloseFile(&Handle);
02926     return (EFI_SUCCESS);
02927   }
02928   ShellCloseFile(&Handle);
02929   return (EFI_NOT_FOUND);
02930 }
02931 
02941 EFI_STATUS
02942 EFIAPI
02943 ShellIsFile(
02944   IN CONST CHAR16 *Name
02945   )
02946 {
02947   EFI_STATUS        Status;
02948   SHELL_FILE_HANDLE            Handle;
02949 
02950   ASSERT(Name != NULL);
02951 
02952   Handle = NULL;
02953 
02954   Status = ShellOpenFileByName(Name, &Handle, EFI_FILE_MODE_READ, 0);
02955   if (EFI_ERROR(Status)) {
02956     return (Status);
02957   }
02958 
02959   if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
02960     ShellCloseFile(&Handle);
02961     return (EFI_SUCCESS);
02962   }
02963   ShellCloseFile(&Handle);
02964   return (EFI_NOT_FOUND);
02965 }
02966 
02980 EFI_STATUS
02981 EFIAPI
02982 ShellIsFileInPath(
02983   IN CONST CHAR16 *Name
02984   )
02985 {
02986   CHAR16      *NewName;
02987   EFI_STATUS  Status;
02988 
02989   if (!EFI_ERROR(ShellIsFile(Name))) {
02990     return (EFI_SUCCESS);
02991   }
02992 
02993   NewName = ShellFindFilePath(Name);
02994   if (NewName == NULL) {
02995     return (EFI_NOT_FOUND);
02996   }
02997   Status = ShellIsFile(NewName);
02998   FreePool(NewName);
02999   return (Status);
03000 }
03001 
03011 UINTN
03012 EFIAPI
03013 ShellStrToUintn(
03014   IN CONST CHAR16 *String
03015   )
03016 {
03017   UINT64        RetVal;
03018   BOOLEAN       Hex;
03019 
03020   Hex = FALSE;
03021 
03022   if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE)) {
03023     Hex = TRUE;
03024   }
03025 
03026   if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, Hex, TRUE))) {
03027     return ((UINTN)RetVal);
03028   }
03029   return ((UINTN)(-1));
03030 }
03031 
03064 CHAR16*
03065 EFIAPI
03066 StrnCatGrow (
03067   IN OUT CHAR16           **Destination,
03068   IN OUT UINTN            *CurrentSize,
03069   IN     CONST CHAR16     *Source,
03070   IN     UINTN            Count
03071   )
03072 {
03073   UINTN DestinationStartSize;
03074   UINTN NewSize;
03075 
03076   //
03077   // ASSERTs
03078   //
03079   ASSERT(Destination != NULL);
03080 
03081   //
03082   // If there's nothing to do then just return Destination
03083   //
03084   if (Source == NULL) {
03085     return (*Destination);
03086   }
03087 
03088   //
03089   // allow for un-initialized pointers, based on size being 0
03090   //
03091   if (CurrentSize != NULL && *CurrentSize == 0) {
03092     *Destination = NULL;
03093   }
03094 
03095   //
03096   // allow for NULL pointers address as Destination
03097   //
03098   if (*Destination != NULL) {
03099     ASSERT(CurrentSize != 0);
03100     DestinationStartSize = StrSize(*Destination);
03101     ASSERT(DestinationStartSize <= *CurrentSize);
03102   } else {
03103     DestinationStartSize = 0;
03104 //    ASSERT(*CurrentSize == 0);
03105   }
03106 
03107   //
03108   // Append all of Source?
03109   //
03110   if (Count == 0) {
03111     Count = StrLen(Source);
03112   }
03113 
03114   //
03115   // Test and grow if required
03116   //
03117   if (CurrentSize != NULL) {
03118     NewSize = *CurrentSize;
03119     while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {
03120       NewSize += 2 * Count * sizeof(CHAR16);
03121     }
03122     *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);
03123     *CurrentSize = NewSize;
03124   } else {
03125     *Destination = AllocateZeroPool((Count+1)*sizeof(CHAR16));
03126   }
03127 
03128   //
03129   // Now use standard StrnCat on a big enough buffer
03130   //
03131   if (*Destination == NULL) {
03132     return (NULL);
03133   }
03134   return StrnCat(*Destination, Source, Count);
03135 }
03136 
03161 EFI_STATUS
03162 EFIAPI
03163 ShellPromptForResponse (
03164   IN SHELL_PROMPT_REQUEST_TYPE   Type,
03165   IN CHAR16         *Prompt OPTIONAL,
03166   IN OUT VOID       **Response OPTIONAL
03167   )
03168 {
03169   EFI_STATUS        Status;
03170   EFI_INPUT_KEY     Key;
03171   UINTN             EventIndex;
03172   SHELL_PROMPT_RESPONSE          *Resp;
03173   UINTN             Size;
03174   CHAR16            *Buffer;
03175 
03176   Status  = EFI_UNSUPPORTED;
03177   Resp    = NULL;
03178   Buffer  = NULL;
03179   Size    = 0;
03180   if (Type != ShellPromptResponseTypeFreeform) {
03181     Resp = (SHELL_PROMPT_RESPONSE*)AllocateZeroPool(sizeof(SHELL_PROMPT_RESPONSE));
03182     if (Resp == NULL) {
03183       return (EFI_OUT_OF_RESOURCES);
03184     }
03185   }
03186 
03187   switch(Type) {
03188     case ShellPromptResponseTypeQuitContinue:
03189       if (Prompt != NULL) {
03190         ShellPrintEx(-1, -1, L"%s", Prompt);
03191       }
03192       //
03193       // wait for valid response
03194       //
03195       gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
03196       Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
03197       ASSERT_EFI_ERROR(Status);
03198       ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
03199       if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {
03200         *Resp = ShellPromptResponseQuit;
03201       } else {
03202         *Resp = ShellPromptResponseContinue;
03203       }
03204       break;
03205     case ShellPromptResponseTypeYesNoCancel:
03206        if (Prompt != NULL) {
03207         ShellPrintEx(-1, -1, L"%s", Prompt);
03208       }
03209       //
03210       // wait for valid response
03211       //
03212       *Resp = ShellPromptResponseMax;
03213       while (*Resp == ShellPromptResponseMax) {
03214         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
03215         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
03216         ASSERT_EFI_ERROR(Status);
03217         ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
03218         switch (Key.UnicodeChar) {
03219           case L'Y':
03220           case L'y':
03221             *Resp = ShellPromptResponseYes;
03222             break;
03223           case L'N':
03224           case L'n':
03225             *Resp = ShellPromptResponseNo;
03226             break;
03227           case L'C':
03228           case L'c':
03229             *Resp = ShellPromptResponseCancel;
03230             break;
03231         }
03232       }
03233       break;    case ShellPromptResponseTypeYesNoAllCancel:
03234        if (Prompt != NULL) {
03235         ShellPrintEx(-1, -1, L"%s", Prompt);
03236       }
03237       //
03238       // wait for valid response
03239       //
03240       *Resp = ShellPromptResponseMax;
03241       while (*Resp == ShellPromptResponseMax) {
03242         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
03243         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
03244         ASSERT_EFI_ERROR(Status);
03245         ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
03246         switch (Key.UnicodeChar) {
03247           case L'Y':
03248           case L'y':
03249             *Resp = ShellPromptResponseYes;
03250             break;
03251           case L'N':
03252           case L'n':
03253             *Resp = ShellPromptResponseNo;
03254             break;
03255           case L'A':
03256           case L'a':
03257             *Resp = ShellPromptResponseAll;
03258             break;
03259           case L'C':
03260           case L'c':
03261             *Resp = ShellPromptResponseCancel;
03262             break;
03263         }
03264       }
03265       break;
03266     case ShellPromptResponseTypeEnterContinue:
03267     case ShellPromptResponseTypeAnyKeyContinue:
03268       if (Prompt != NULL) {
03269         ShellPrintEx(-1, -1, L"%s", Prompt);
03270       }
03271       //
03272       // wait for valid response
03273       //
03274       *Resp = ShellPromptResponseMax;
03275       while (*Resp == ShellPromptResponseMax) {
03276         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
03277         if (Type == ShellPromptResponseTypeEnterContinue) {
03278           Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
03279           ASSERT_EFI_ERROR(Status);
03280           ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
03281           if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
03282             *Resp = ShellPromptResponseContinue;
03283             break;
03284           }
03285         }
03286         if (Type == ShellPromptResponseTypeAnyKeyContinue) {
03287           Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
03288           ASSERT_EFI_ERROR(Status);
03289           *Resp = ShellPromptResponseContinue;
03290           break;
03291         }
03292       }
03293       break;
03294     case ShellPromptResponseTypeYesNo:
03295        if (Prompt != NULL) {
03296         ShellPrintEx(-1, -1, L"%s", Prompt);
03297       }
03298       //
03299       // wait for valid response
03300       //
03301       *Resp = ShellPromptResponseMax;
03302       while (*Resp == ShellPromptResponseMax) {
03303         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
03304         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
03305         ASSERT_EFI_ERROR(Status);
03306         ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
03307         switch (Key.UnicodeChar) {
03308           case L'Y':
03309           case L'y':
03310             *Resp = ShellPromptResponseYes;
03311             break;
03312           case L'N':
03313           case L'n':
03314             *Resp = ShellPromptResponseNo;
03315             break;
03316         }
03317       }
03318       break;
03319     case ShellPromptResponseTypeFreeform:
03320       if (Prompt != NULL) {
03321         ShellPrintEx(-1, -1, L"%s", Prompt);
03322       }
03323       while(1) {
03324         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
03325         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
03326         ASSERT_EFI_ERROR(Status);
03327         ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
03328         if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
03329           break;
03330         }
03331         ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL));
03332         StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1);
03333       }
03334       break;
03335     //
03336     // This is the location to add new prompt types.
03337     //
03338     default:
03339       ASSERT(FALSE);
03340   }
03341 
03342   if (Response != NULL) {
03343     if (Resp != NULL) {
03344       *Response = Resp;
03345     } else if (Buffer != NULL) {
03346       *Response = Buffer;
03347     }
03348   } else {
03349     if (Resp != NULL) {
03350       FreePool(Resp);
03351     }
03352     if (Buffer != NULL) {
03353       FreePool(Buffer);
03354     }
03355   }
03356 
03357   ShellPrintEx(-1, -1, L"\r\n");
03358   return (Status);
03359 }
03360 
03378 EFI_STATUS
03379 EFIAPI
03380 ShellPromptForResponseHii (
03381   IN SHELL_PROMPT_REQUEST_TYPE         Type,
03382   IN CONST EFI_STRING_ID  HiiFormatStringId,
03383   IN CONST EFI_HANDLE     HiiFormatHandle,
03384   IN OUT VOID             **Response
03385   )
03386 {
03387   CHAR16      *Prompt;
03388   EFI_STATUS  Status;
03389 
03390   Prompt = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL);
03391   Status = ShellPromptForResponse(Type, Prompt, Response);
03392   FreePool(Prompt);
03393   return (Status);
03394 }
03395 
03408 BOOLEAN
03409 EFIAPI
03410 InternalShellIsHexOrDecimalNumber (
03411   IN CONST CHAR16   *String,
03412   IN CONST BOOLEAN  ForceHex,
03413   IN CONST BOOLEAN  StopAtSpace
03414   )
03415 {
03416   BOOLEAN Hex;
03417 
03418   //
03419   // chop off a single negative sign
03420   //
03421   if (String != NULL && *String == L'-') {
03422     String++;
03423   }
03424 
03425   if (String == NULL) {
03426     return (FALSE);
03427   }
03428 
03429   //
03430   // chop leading zeroes
03431   //
03432   while(String != NULL && *String == L'0'){
03433     String++;
03434   }
03435   //
03436   // allow '0x' or '0X', but not 'x' or 'X'
03437   //
03438   if (String != NULL && (*String == L'x' || *String == L'X')) {
03439     if (*(String-1) != L'0') {
03440       //
03441       // we got an x without a preceeding 0
03442       //
03443       return (FALSE);
03444     }
03445     String++;
03446     Hex = TRUE;
03447   } else if (ForceHex) {
03448     Hex = TRUE;
03449   } else {
03450     Hex = FALSE;
03451   }
03452 
03453   //
03454   // loop through the remaining characters and use the lib function
03455   //
03456   for ( ; String != NULL && *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){
03457     if (Hex) {
03458       if (!ShellIsHexaDecimalDigitCharacter(*String)) {
03459         return (FALSE);
03460       }
03461     } else {
03462       if (!ShellIsDecimalDigitCharacter(*String)) {
03463         return (FALSE);
03464       }
03465     }
03466   }
03467 
03468   return (TRUE);
03469 }
03470 
03480 EFI_STATUS
03481 EFIAPI
03482 ShellFileExists(
03483   IN CONST CHAR16 *Name
03484   )
03485 {
03486   EFI_STATUS          Status;
03487   EFI_SHELL_FILE_INFO *List;
03488 
03489   ASSERT(Name != NULL);
03490 
03491   List = NULL;
03492   Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List);
03493   if (EFI_ERROR(Status)) {
03494     return (Status);
03495   }
03496 
03497   ShellCloseFileMetaArg(&List);
03498 
03499   return (EFI_SUCCESS);
03500 }
03501 
03517 CHAR16
03518 EFIAPI
03519 InternalShellCharToUpper (
03520   IN      CHAR16                    Char
03521   )
03522 {
03523   if (Char >= L'a' && Char <= L'z') {
03524     return (CHAR16) (Char - (L'a' - L'A'));
03525   }
03526 
03527   return Char;
03528 }
03529 
03543 UINTN
03544 EFIAPI
03545 InternalShellHexCharToUintn (
03546   IN      CHAR16                    Char
03547   )
03548 {
03549   if (ShellIsDecimalDigitCharacter (Char)) {
03550     return Char - L'0';
03551   }
03552 
03553   return (UINTN) (10 + InternalShellCharToUpper (Char) - L'A');
03554 }
03555 
03586 EFI_STATUS
03587 EFIAPI
03588 InternalShellStrHexToUint64 (
03589   IN CONST CHAR16   *String,
03590      OUT   UINT64   *Value,
03591   IN CONST BOOLEAN  StopAtSpace
03592   )
03593 {
03594   UINT64    Result;
03595 
03596   if (String == NULL || StrSize(String) == 0 || Value == NULL) {
03597     return (EFI_INVALID_PARAMETER);
03598   }
03599 
03600   //
03601   // Ignore the pad spaces (space or tab)
03602   //
03603   while ((*String == L' ') || (*String == L'\t')) {
03604     String++;
03605   }
03606 
03607   //
03608   // Ignore leading Zeros after the spaces
03609   //
03610   while (*String == L'0') {
03611     String++;
03612   }
03613 
03614   if (InternalShellCharToUpper (*String) == L'X') {
03615     if (*(String - 1) != L'0') {
03616       return 0;
03617     }
03618     //
03619     // Skip the 'X'
03620     //
03621     String++;
03622   }
03623 
03624   Result = 0;
03625 
03626   //
03627   // Skip spaces if requested
03628   //
03629   while (StopAtSpace && *String == L' ') {
03630     String++;
03631   }
03632 
03633   while (ShellIsHexaDecimalDigitCharacter (*String)) {
03634     //
03635     // If the Hex Number represented by String overflows according
03636     // to the range defined by UINTN, then ASSERT().
03637     //
03638     if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) {
03639 //    if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) {
03640       return (EFI_DEVICE_ERROR);
03641     }
03642 
03643     Result = (LShiftU64(Result, 4));
03644     Result += InternalShellHexCharToUintn (*String);
03645     String++;
03646 
03647     //
03648     // Skip spaces if requested
03649     //
03650     while (StopAtSpace && *String == L' ') {
03651       String++;
03652     }
03653   }
03654 
03655   *Value = Result;
03656   return (EFI_SUCCESS);
03657 }
03658 
03688 EFI_STATUS
03689 EFIAPI
03690 InternalShellStrDecimalToUint64 (
03691   IN CONST CHAR16 *String,
03692      OUT   UINT64 *Value,
03693   IN CONST BOOLEAN  StopAtSpace
03694   )
03695 {
03696   UINT64     Result;
03697 
03698   if (String == NULL || StrSize (String) == 0 || Value == NULL) {
03699     return (EFI_INVALID_PARAMETER);
03700   }
03701 
03702   //
03703   // Ignore the pad spaces (space or tab)
03704   //
03705   while ((*String == L' ') || (*String == L'\t')) {
03706     String++;
03707   }
03708 
03709   //
03710   // Ignore leading Zeros after the spaces
03711   //
03712   while (*String == L'0') {
03713     String++;
03714   }
03715 
03716   Result = 0;
03717 
03718   //
03719   // Skip spaces if requested
03720   //
03721   while (StopAtSpace && *String == L' ') {
03722     String++;
03723   }
03724   while (ShellIsDecimalDigitCharacter (*String)) {
03725     //
03726     // If the number represented by String overflows according
03727     // to the range defined by UINT64, then ASSERT().
03728     //
03729 
03730     if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) {
03731       return (EFI_DEVICE_ERROR);
03732     }
03733 
03734     Result = MultU64x32(Result, 10) + (*String - L'0');
03735     String++;
03736 
03737     //
03738     // Stop at spaces if requested
03739     //
03740     if (StopAtSpace && *String == L' ') {
03741       break;
03742     }
03743   }
03744 
03745   *Value = Result;
03746 
03747   return (EFI_SUCCESS);
03748 }
03749 
03764 EFI_STATUS
03765 EFIAPI
03766 ShellConvertStringToUint64(
03767   IN CONST CHAR16   *String,
03768      OUT   UINT64   *Value,
03769   IN CONST BOOLEAN  ForceHex,
03770   IN CONST BOOLEAN  StopAtSpace
03771   )
03772 {
03773   UINT64        RetVal;
03774   CONST CHAR16  *Walker;
03775   EFI_STATUS    Status;
03776   BOOLEAN       Hex;
03777 
03778   Hex = ForceHex;
03779 
03780   if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace)) {
03781     if (!Hex) {
03782       Hex = TRUE;
03783       if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace)) {
03784         return (EFI_INVALID_PARAMETER);
03785       }
03786     } else {
03787       return (EFI_INVALID_PARAMETER);
03788     }
03789   }
03790 
03791   //
03792   // Chop off leading spaces
03793   //
03794   for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);
03795 
03796   //
03797   // make sure we have something left that is numeric.
03798   //
03799   if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace)) {
03800     return (EFI_INVALID_PARAMETER);
03801   }
03802 
03803   //
03804   // do the conversion.
03805   //
03806   if (Hex || StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){
03807     Status = InternalShellStrHexToUint64(Walker, &RetVal, StopAtSpace);
03808   } else {
03809     Status = InternalShellStrDecimalToUint64(Walker, &RetVal, StopAtSpace);
03810   }
03811 
03812   if (Value == NULL && !EFI_ERROR(Status)) {
03813     return (EFI_NOT_FOUND);
03814   }
03815 
03816   if (Value != NULL) {
03817     *Value = RetVal;
03818   }
03819 
03820   return (Status);
03821 }
03822 
03835 BOOLEAN
03836 EFIAPI
03837 ShellIsHexOrDecimalNumber (
03838   IN CONST CHAR16   *String,
03839   IN CONST BOOLEAN  ForceHex,
03840   IN CONST BOOLEAN  StopAtSpace
03841   )
03842 {
03843   if (ShellConvertStringToUint64(String, NULL, ForceHex, StopAtSpace) == EFI_NOT_FOUND) {
03844     return (TRUE);
03845   }
03846   return (FALSE);
03847 }
03848 
03865 CHAR16*
03866 EFIAPI
03867 ShellFileHandleReturnLine(
03868   IN SHELL_FILE_HANDLE            Handle,
03869   IN OUT BOOLEAN                *Ascii
03870   )
03871 {
03872   CHAR16          *RetVal;
03873   UINTN           Size;
03874   EFI_STATUS      Status;
03875 
03876   Size = 0;
03877   RetVal = NULL;
03878 
03879   Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);
03880   if (Status == EFI_BUFFER_TOO_SMALL) {
03881     RetVal = AllocateZeroPool(Size);
03882     if (RetVal == NULL) {
03883       return (NULL);
03884     }
03885     Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);
03886 
03887   }
03888   if (EFI_ERROR(Status) && (RetVal != NULL)) {
03889     FreePool(RetVal);
03890     RetVal = NULL;
03891   }
03892   return (RetVal);
03893 }
03894 
03920 EFI_STATUS
03921 EFIAPI
03922 ShellFileHandleReadLine(
03923   IN SHELL_FILE_HANDLE          Handle,
03924   IN OUT CHAR16                 *Buffer,
03925   IN OUT UINTN                  *Size,
03926   IN BOOLEAN                    Truncate,
03927   IN OUT BOOLEAN                *Ascii
03928   )
03929 {
03930   EFI_STATUS  Status;
03931   CHAR16      CharBuffer;
03932   UINTN       CharSize;
03933   UINTN       CountSoFar;
03934   UINT64      OriginalFilePosition;
03935 
03936 
03937   if (Handle == NULL
03938     ||Size   == NULL
03939    ){
03940     return (EFI_INVALID_PARAMETER);
03941   }
03942   if (Buffer == NULL) {
03943     ASSERT(*Size == 0);
03944   } else {
03945     *Buffer = CHAR_NULL;
03946   }
03947   gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);
03948   if (OriginalFilePosition == 0) {
03949     CharSize = sizeof(CHAR16);
03950     Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
03951     ASSERT_EFI_ERROR(Status);
03952     if (CharBuffer == gUnicodeFileTag) {
03953       *Ascii = FALSE;
03954     } else {
03955       *Ascii = TRUE;
03956       gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
03957     }
03958   }
03959 
03960   for (CountSoFar = 0;;CountSoFar++){
03961     CharBuffer = 0;
03962     if (*Ascii) {
03963       CharSize = sizeof(CHAR8);
03964     } else {
03965       CharSize = sizeof(CHAR16);
03966     }
03967     Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
03968     if (  EFI_ERROR(Status)
03969        || CharSize == 0
03970        || (CharBuffer == L'\n' && !(*Ascii))
03971        || (CharBuffer ==  '\n' && *Ascii)
03972      ){
03973       break;
03974     }
03975     //
03976     // if we have space save it...
03977     //
03978     if ((CountSoFar+1)*sizeof(CHAR16) < *Size){
03979       ASSERT(Buffer != NULL);
03980       ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;
03981       ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;
03982     }
03983   }
03984 
03985   //
03986   // if we ran out of space tell when...
03987   //
03988   if ((CountSoFar+1)*sizeof(CHAR16) > *Size){
03989     *Size = (CountSoFar+1)*sizeof(CHAR16);
03990     if (!Truncate) {
03991       gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
03992     } else {
03993       DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));
03994     }
03995     return (EFI_BUFFER_TOO_SMALL);
03996   }
03997   while(Buffer[StrLen(Buffer)-1] == L'\r') {
03998     Buffer[StrLen(Buffer)-1] = CHAR_NULL;
03999   }
04000 
04001   return (Status);
04002 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines