2 This is THE shell (application)
4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Initialize the global structure
20 SHELL_INFO ShellInfoObject
= {
61 STATIC CONST CHAR16 mScriptExtension
[] = L
".NSH";
62 STATIC CONST CHAR16 mExecutableExtensions
[] = L
".NSH;.EFI";
63 STATIC CONST CHAR16 mStartupScript
[] = L
"startup.nsh";
66 Function to start monitoring for CTRL-S using SimpleTextInputEx. This
67 feature's enabled state was not known when the shell initially launched.
69 @retval EFI_SUCCESS The feature is enabled.
70 @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
74 InternalEfiShellStartCtrlSMonitor(
78 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*SimpleEx
;
82 Status
= gBS
->OpenProtocol(
84 &gEfiSimpleTextInputExProtocolGuid
,
88 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
89 if (EFI_ERROR(Status
)) {
94 STRING_TOKEN (STR_SHELL_NO_IN_EX
),
95 ShellInfoObject
.HiiHandle
);
99 KeyData
.KeyState
.KeyToggleState
= 0;
100 KeyData
.Key
.ScanCode
= 0;
101 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_LEFT_CONTROL_PRESSED
;
102 KeyData
.Key
.UnicodeChar
= L
's';
104 Status
= SimpleEx
->RegisterKeyNotify(
107 NotificationFunction
,
108 &ShellInfoObject
.CtrlSNotifyHandle1
);
110 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_RIGHT_CONTROL_PRESSED
;
111 if (!EFI_ERROR(Status
)) {
112 Status
= SimpleEx
->RegisterKeyNotify(
115 NotificationFunction
,
116 &ShellInfoObject
.CtrlSNotifyHandle2
);
118 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_LEFT_CONTROL_PRESSED
;
119 KeyData
.Key
.UnicodeChar
= 19;
121 if (!EFI_ERROR(Status
)) {
122 Status
= SimpleEx
->RegisterKeyNotify(
125 NotificationFunction
,
126 &ShellInfoObject
.CtrlSNotifyHandle2
);
128 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
|EFI_RIGHT_CONTROL_PRESSED
;
129 if (!EFI_ERROR(Status
)) {
130 Status
= SimpleEx
->RegisterKeyNotify(
133 NotificationFunction
,
134 &ShellInfoObject
.CtrlSNotifyHandle2
);
142 The entry point for the application.
144 @param[in] ImageHandle The firmware allocated handle for the EFI image.
145 @param[in] SystemTable A pointer to the EFI System Table.
147 @retval EFI_SUCCESS The entry point is executed successfully.
148 @retval other Some error occurs when executing this entry point.
154 IN EFI_HANDLE ImageHandle
,
155 IN EFI_SYSTEM_TABLE
*SystemTable
161 // EFI_INPUT_KEY Key;
163 // gST->ConOut->OutputString(gST->ConOut, L"ReadKeyStroke Calling\r\n");
165 // Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
167 // gST->ConOut->OutputString(gST->ConOut, L"ReadKeyStroke Done\r\n");
168 // gBS->Stall (1000000);
170 if (PcdGet8(PcdShellSupportLevel
) > 3) {
171 return (EFI_UNSUPPORTED
);
177 Status
= gST
->ConOut
->ClearScreen(gST
->ConOut
);
178 if (EFI_ERROR(Status
)) {
183 // Populate the global structure from PCDs
185 ShellInfoObject
.ImageDevPath
= NULL
;
186 ShellInfoObject
.FileDevPath
= NULL
;
187 ShellInfoObject
.PageBreakEnabled
= PcdGetBool(PcdShellPageBreakDefault
);
188 ShellInfoObject
.ViewingSettings
.InsertMode
= PcdGetBool(PcdShellInsertModeDefault
);
189 ShellInfoObject
.LogScreenCount
= PcdGet8 (PcdShellScreenLogCount
);
192 // verify we dont allow for spec violation
194 ASSERT(ShellInfoObject
.LogScreenCount
>= 3);
197 // Initialize the LIST ENTRY objects...
199 InitializeListHead(&ShellInfoObject
.BufferToFreeList
.Link
);
200 InitializeListHead(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
);
201 InitializeListHead(&ShellInfoObject
.SplitList
.Link
);
204 // Check PCDs for optional features that are not implemented yet.
206 if ( PcdGetBool(PcdShellSupportOldProtocols
)
207 || !FeaturePcdGet(PcdShellRequireHiiPlatform
)
208 || FeaturePcdGet(PcdShellSupportFrameworkHii
)
210 return (EFI_UNSUPPORTED
);
214 // turn off the watchdog timer
216 gBS
->SetWatchdogTimer (0, 0, 0, NULL
);
219 // install our console logger. This will keep a log of the output for back-browsing
221 Status
= ConsoleLoggerInstall(ShellInfoObject
.LogScreenCount
, &ShellInfoObject
.ConsoleInfo
);
222 if (!EFI_ERROR(Status
)) {
224 // Enable the cursor to be visible
226 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
229 // If supporting EFI 1.1 we need to install HII protocol
230 // only do this if PcdShellRequireHiiPlatform == FALSE
232 // remove EFI_UNSUPPORTED check above when complete.
233 ///@todo add support for Framework HII
236 // install our (solitary) HII package
238 ShellInfoObject
.HiiHandle
= HiiAddPackages (&gEfiCallerIdGuid
, gImageHandle
, ShellStrings
, NULL
);
239 if (ShellInfoObject
.HiiHandle
== NULL
) {
240 if (PcdGetBool(PcdShellSupportFrameworkHii
)) {
241 ///@todo Add our package into Framework HII
243 if (ShellInfoObject
.HiiHandle
== NULL
) {
244 return (EFI_NOT_STARTED
);
249 // create and install the EfiShellParametersProtocol
251 Status
= CreatePopulateInstallShellParametersProtocol(&ShellInfoObject
.NewShellParametersProtocol
, &ShellInfoObject
.RootShellInstance
);
252 ASSERT_EFI_ERROR(Status
);
253 ASSERT(ShellInfoObject
.NewShellParametersProtocol
!= NULL
);
256 // create and install the EfiShellProtocol
258 Status
= CreatePopulateInstallShellProtocol(&ShellInfoObject
.NewEfiShellProtocol
);
259 ASSERT_EFI_ERROR(Status
);
260 ASSERT(ShellInfoObject
.NewEfiShellProtocol
!= NULL
);
263 // Now initialize the shell library (it requires Shell Parameters protocol)
265 Status
= ShellInitialize();
266 ASSERT_EFI_ERROR(Status
);
268 Status
= CommandInit();
269 ASSERT_EFI_ERROR(Status
);
272 // Check the command line
274 Status
= ProcessCommandLine();
277 // If shell support level is >= 1 create the mappings and paths
279 if (PcdGet8(PcdShellSupportLevel
) >= 1) {
280 Status
= ShellCommandCreateInitialMappingsAndPaths();
284 // save the device path for the loaded image and the device path for the filepath (under loaded image)
285 // These are where to look for the startup.nsh file
287 Status
= GetDevicePathsForImageAndFile(&ShellInfoObject
.ImageDevPath
, &ShellInfoObject
.FileDevPath
);
288 ASSERT_EFI_ERROR(Status
);
291 // Display the version
293 if (!ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoVersion
) {
296 gST
->ConOut
->Mode
->CursorRow
,
298 STRING_TOKEN (STR_VER_OUTPUT_MAIN
),
299 ShellInfoObject
.HiiHandle
,
300 SupportLevel
[PcdGet8(PcdShellSupportLevel
)],
301 gEfiShellProtocol
->MajorVersion
,
302 gEfiShellProtocol
->MinorVersion
,
303 (gST
->Hdr
.Revision
&0xffff0000)>>16,
304 (gST
->Hdr
.Revision
&0x0000ffff),
306 gST
->FirmwareRevision
311 // Display the mapping
313 if (PcdGet8(PcdShellSupportLevel
) >= 2 && !ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoMap
) {
314 Status
= RunCommand(L
"map");
315 ASSERT_EFI_ERROR(Status
);
319 // init all the built in alias'
321 Status
= SetBuiltInAlias();
322 ASSERT_EFI_ERROR(Status
);
325 // Initialize environment variables
327 if (ShellCommandGetProfileList() != NULL
) {
328 Status
= InternalEfiShellSetEnv(L
"profiles", ShellCommandGetProfileList(), TRUE
);
329 ASSERT_EFI_ERROR(Status
);
333 TempString
= AllocateZeroPool(Size
);
335 UnicodeSPrint(TempString
, Size
, L
"%d", PcdGet8(PcdShellSupportLevel
));
336 Status
= InternalEfiShellSetEnv(L
"uefishellsupport", TempString
, TRUE
);
337 ASSERT_EFI_ERROR(Status
);
339 UnicodeSPrint(TempString
, Size
, L
"%d.%d", ShellInfoObject
.NewEfiShellProtocol
->MajorVersion
, ShellInfoObject
.NewEfiShellProtocol
->MinorVersion
);
340 Status
= InternalEfiShellSetEnv(L
"uefishellversion", TempString
, TRUE
);
341 ASSERT_EFI_ERROR(Status
);
343 UnicodeSPrint(TempString
, Size
, L
"%d.%d", (gST
->Hdr
.Revision
& 0xFFFF0000) >> 16, gST
->Hdr
.Revision
& 0x0000FFFF);
344 Status
= InternalEfiShellSetEnv(L
"uefiversion", TempString
, TRUE
);
345 ASSERT_EFI_ERROR(Status
);
347 FreePool(TempString
);
349 if (!EFI_ERROR(Status
)) {
350 if (!ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoInterrupt
) {
352 // Set up the event for CTRL-C monitoring...
354 Status
= InernalEfiShellStartMonitor();
357 if (!EFI_ERROR(Status
) && !ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleIn
) {
359 // Set up the event for CTRL-S monitoring...
361 Status
= InternalEfiShellStartCtrlSMonitor();
364 if (!EFI_ERROR(Status
) && PcdGet8(PcdShellSupportLevel
) >= 1) {
366 // process the startup script or launch the called app.
368 Status
= DoStartupScript(ShellInfoObject
.ImageDevPath
, ShellInfoObject
.FileDevPath
);
371 if (!ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel
) >= 3 || PcdGetBool(PcdShellForceConsole
)) && !EFI_ERROR(Status
) && !ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleIn
) {
373 // begin the UI waiting loop
377 // clean out all the memory allocated for CONST <something> * return values
378 // between each shell prompt presentation
380 if (!IsListEmpty(&ShellInfoObject
.BufferToFreeList
.Link
)){
381 FreeBufferList(&ShellInfoObject
.BufferToFreeList
);
385 // Reset page break back to default.
387 ShellInfoObject
.PageBreakEnabled
= PcdGetBool(PcdShellPageBreakDefault
);
388 ShellInfoObject
.ConsoleInfo
->Enabled
= TRUE
;
389 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
392 // Reset the CTRL-C event (yes we ignore the return values)
394 Status
= gBS
->CheckEvent (ShellInfoObject
.NewEfiShellProtocol
->ExecutionBreak
);
399 Status
= DoShellPrompt();
400 } while (!ShellCommandGetExit());
406 // uninstall protocols / free memory / etc...
408 if (ShellInfoObject
.UserBreakTimer
!= NULL
) {
409 gBS
->CloseEvent(ShellInfoObject
.UserBreakTimer
);
410 DEBUG_CODE(ShellInfoObject
.UserBreakTimer
= NULL
;);
412 if (ShellInfoObject
.ImageDevPath
!= NULL
) {
413 FreePool(ShellInfoObject
.ImageDevPath
);
414 DEBUG_CODE(ShellInfoObject
.ImageDevPath
= NULL
;);
416 if (ShellInfoObject
.FileDevPath
!= NULL
) {
417 FreePool(ShellInfoObject
.FileDevPath
);
418 DEBUG_CODE(ShellInfoObject
.FileDevPath
= NULL
;);
420 if (ShellInfoObject
.NewShellParametersProtocol
!= NULL
) {
421 CleanUpShellParametersProtocol(ShellInfoObject
.NewShellParametersProtocol
);
422 DEBUG_CODE(ShellInfoObject
.NewShellParametersProtocol
= NULL
;);
424 if (ShellInfoObject
.NewEfiShellProtocol
!= NULL
){
425 if (ShellInfoObject
.NewEfiShellProtocol
->IsRootShell()){
426 ShellInfoObject
.NewEfiShellProtocol
->SetEnv(L
"cwd", L
"", TRUE
);
428 CleanUpShellProtocol(ShellInfoObject
.NewEfiShellProtocol
);
429 DEBUG_CODE(ShellInfoObject
.NewEfiShellProtocol
= NULL
;);
432 if (!IsListEmpty(&ShellInfoObject
.BufferToFreeList
.Link
)){
433 FreeBufferList(&ShellInfoObject
.BufferToFreeList
);
436 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)){
437 ASSERT(FALSE
); ///@todo finish this de-allocation.
440 if (ShellInfoObject
.ShellInitSettings
.FileName
!= NULL
) {
441 FreePool(ShellInfoObject
.ShellInitSettings
.FileName
);
442 DEBUG_CODE(ShellInfoObject
.ShellInitSettings
.FileName
= NULL
;);
445 if (ShellInfoObject
.ShellInitSettings
.FileOptions
!= NULL
) {
446 FreePool(ShellInfoObject
.ShellInitSettings
.FileOptions
);
447 DEBUG_CODE(ShellInfoObject
.ShellInitSettings
.FileOptions
= NULL
;);
450 if (ShellInfoObject
.HiiHandle
!= NULL
) {
451 HiiRemovePackages(ShellInfoObject
.HiiHandle
);
452 DEBUG_CODE(ShellInfoObject
.HiiHandle
= NULL
;);
455 if (!IsListEmpty(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
)){
456 FreeBufferList(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
459 ASSERT(ShellInfoObject
.ConsoleInfo
!= NULL
);
460 if (ShellInfoObject
.ConsoleInfo
!= NULL
) {
461 ConsoleLoggerUninstall(ShellInfoObject
.ConsoleInfo
);
462 FreePool(ShellInfoObject
.ConsoleInfo
);
463 DEBUG_CODE(ShellInfoObject
.ConsoleInfo
= NULL
;);
470 Sets all the alias' that were registered with the ShellCommandLib library.
472 @retval EFI_SUCCESS all init commands were run sucessfully.
480 CONST ALIAS_LIST
*List
;
484 // Get all the commands we want to run
486 List
= ShellCommandGetInitAliasList();
489 // for each command in the List
491 for ( Node
= (ALIAS_LIST
*)GetFirstNode(&List
->Link
)
492 ; !IsNull (&List
->Link
, &Node
->Link
)
493 ; Node
= (ALIAS_LIST
*)GetNextNode(&List
->Link
, &Node
->Link
)
496 // install the alias'
498 Status
= InternalSetAlias(Node
->CommandString
, Node
->Alias
, TRUE
);
499 ASSERT_EFI_ERROR(Status
);
501 return (EFI_SUCCESS
);
505 Internal function to determine if 2 command names are really the same.
507 @param[in] Command1 The pointer to the first command name.
508 @param[in] Command2 The pointer to the second command name.
510 @retval TRUE The 2 command names are the same.
511 @retval FALSE The 2 command names are not the same.
516 IN CONST CHAR16
*Command1
,
517 IN CONST CHAR16
*Command2
520 if (StringNoCaseCompare(&Command1
, &Command2
) == 0) {
527 Internal function to determine if a command is a script only command.
529 @param[in] CommandName The pointer to the command name.
531 @retval TRUE The command is a script only command.
532 @retval FALSE The command is not a script only command.
537 IN CONST CHAR16
*CommandName
540 if (IsCommand(CommandName
, L
"for")
541 ||IsCommand(CommandName
, L
"endfor")
542 ||IsCommand(CommandName
, L
"if")
543 ||IsCommand(CommandName
, L
"else")
544 ||IsCommand(CommandName
, L
"endif")
545 ||IsCommand(CommandName
, L
"goto")) {
554 This function will populate the 2 device path protocol parameters based on the
555 global gImageHandle. The DevPath will point to the device path for the handle that has
556 loaded image protocol installed on it. The FilePath will point to the device path
557 for the file that was loaded.
559 @param[in,out] DevPath On a sucessful return the device path to the loaded image.
560 @param[in,out] FilePath On a sucessful return the device path to the file.
562 @retval EFI_SUCCESS The 2 device paths were sucessfully returned.
563 @retval other A error from gBS->HandleProtocol.
569 GetDevicePathsForImageAndFile (
570 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevPath
,
571 IN OUT EFI_DEVICE_PATH_PROTOCOL
**FilePath
575 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
576 EFI_DEVICE_PATH_PROTOCOL
*ImageDevicePath
;
578 ASSERT(DevPath
!= NULL
);
579 ASSERT(FilePath
!= NULL
);
581 Status
= gBS
->OpenProtocol (
583 &gEfiLoadedImageProtocolGuid
,
584 (VOID
**)&LoadedImage
,
587 EFI_OPEN_PROTOCOL_GET_PROTOCOL
589 if (!EFI_ERROR (Status
)) {
590 Status
= gBS
->OpenProtocol (
591 LoadedImage
->DeviceHandle
,
592 &gEfiDevicePathProtocolGuid
,
593 (VOID
**)&ImageDevicePath
,
596 EFI_OPEN_PROTOCOL_GET_PROTOCOL
598 if (!EFI_ERROR (Status
)) {
599 *DevPath
= DuplicateDevicePath (ImageDevicePath
);
600 *FilePath
= DuplicateDevicePath (LoadedImage
->FilePath
);
604 &gEfiLoadedImageProtocolGuid
,
611 STATIC CONST SHELL_PARAM_ITEM mShellParamList
[] = {
612 {L
"-nostartup", TypeFlag
},
613 {L
"-startup", TypeFlag
},
614 {L
"-noconsoleout", TypeFlag
},
615 {L
"-noconsolein", TypeFlag
},
616 {L
"-nointerrupt", TypeFlag
},
617 {L
"-nomap", TypeFlag
},
618 {L
"-noversion", TypeFlag
},
619 {L
"-startup", TypeFlag
},
620 {L
"-delay", TypeValue
},
624 Process all Uefi Shell 2.0 command line options.
626 see Uefi Shell 2.0 section 3.2 for full details.
628 the command line must resemble the following:
630 shell.efi [ShellOpt-options] [options] [file-name [file-name-options]]
632 ShellOpt-options Options which control the initialization behavior of the shell.
633 These options are read from the EFI global variable "ShellOpt"
634 and are processed before options or file-name.
636 options Options which control the initialization behavior of the shell.
638 file-name The name of a UEFI shell application or script to be executed
639 after initialization is complete. By default, if file-name is
640 specified, then -nostartup is implied. Scripts are not supported
643 file-name-options The command-line options that are passed to file-name when it
646 This will initialize the ShellInfoObject.ShellInitSettings global variable.
648 @retval EFI_SUCCESS The variable is initialized.
659 CONST CHAR16
*TempConst
;
662 CHAR16
*ProblemParam
;
668 Status
= ShellCommandLineParse (mShellParamList
, &Package
, NULL
, FALSE
);
672 TempConst
= ShellCommandLineGetRawValue(Package
, Count
++);
673 if (TempConst
!= NULL
&& StrLen(TempConst
)) {
674 ShellInfoObject
.ShellInitSettings
.FileName
= AllocateZeroPool(StrSize(TempConst
));
675 if (ShellInfoObject
.ShellInitSettings
.FileName
== NULL
) {
676 return (EFI_OUT_OF_RESOURCES
);
678 StrCpy(ShellInfoObject
.ShellInitSettings
.FileName
, TempConst
);
679 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoStartup
= 1;
680 for (LoopVar
= 0 ; LoopVar
< gEfiShellParametersProtocol
->Argc
; LoopVar
++) {
681 if (StrCmp(gEfiShellParametersProtocol
->Argv
[LoopVar
], ShellInfoObject
.ShellInitSettings
.FileName
)==0) {
684 // We found the file... add the rest of the params...
686 for ( ; LoopVar
< gEfiShellParametersProtocol
->Argc
; LoopVar
++) {
687 ASSERT((ShellInfoObject
.ShellInitSettings
.FileOptions
== NULL
&& Size
== 0) || (ShellInfoObject
.ShellInitSettings
.FileOptions
!= NULL
));
688 StrnCatGrow(&ShellInfoObject
.ShellInitSettings
.FileOptions
,
692 if (ShellInfoObject
.ShellInitSettings
.FileOptions
== NULL
) {
693 SHELL_FREE_NON_NULL(ShellInfoObject
.ShellInitSettings
.FileName
);
694 return (EFI_OUT_OF_RESOURCES
);
696 StrnCatGrow(&ShellInfoObject
.ShellInitSettings
.FileOptions
,
698 gEfiShellParametersProtocol
->Argv
[LoopVar
],
700 if (ShellInfoObject
.ShellInitSettings
.FileOptions
== NULL
) {
701 SHELL_FREE_NON_NULL(ShellInfoObject
.ShellInitSettings
.FileName
);
702 return (EFI_OUT_OF_RESOURCES
);
708 ShellCommandLineFreeVarList(Package
);
710 Status
= ShellCommandLineParse (mShellParamList
, &Package
, &ProblemParam
, FALSE
);
711 if (EFI_ERROR(Status
)) {
712 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), ShellInfoObject
.HiiHandle
, ProblemParam
);
713 FreePool(ProblemParam
);
714 ShellCommandLineFreeVarList(Package
);
715 return (EFI_INVALID_PARAMETER
);
719 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.Startup
= ShellCommandLineGetFlag(Package
, L
"-startup");
720 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoStartup
= ShellCommandLineGetFlag(Package
, L
"-nostartup");
721 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
= ShellCommandLineGetFlag(Package
, L
"-noconsoleout");
722 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleIn
= ShellCommandLineGetFlag(Package
, L
"-noconsolein");
723 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoInterrupt
= ShellCommandLineGetFlag(Package
, L
"-nointerrupt");
724 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoMap
= ShellCommandLineGetFlag(Package
, L
"-nomap");
725 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoVersion
= ShellCommandLineGetFlag(Package
, L
"-noversion");
726 ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.Delay
= ShellCommandLineGetFlag(Package
, L
"-delay");
728 ShellInfoObject
.ShellInitSettings
.Delay
= 5;
730 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoInterrupt
) {
731 ShellInfoObject
.ShellInitSettings
.Delay
= 0;
732 } else if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.Delay
) {
733 TempConst
= ShellCommandLineGetValue(Package
, L
"-delay");
734 if (TempConst
!= NULL
&& *TempConst
== L
':') {
737 if (TempConst
!= NULL
&& !EFI_ERROR(ShellConvertStringToUint64(TempConst
, &Intermediate
, FALSE
, FALSE
))) {
738 ShellInfoObject
.ShellInitSettings
.Delay
= (UINTN
)Intermediate
;
741 ShellCommandLineFreeVarList(Package
);
747 Handles all interaction with the default startup script.
749 this will check that the correct command line parameters were passed, handle the delay, and then start running the script.
751 @param ImagePath the path to the image for shell. first place to look for the startup script
752 @param FilePath the path to the file for shell. second place to look for the startup script.
754 @retval EFI_SUCCESS the variable is initialized.
759 EFI_DEVICE_PATH_PROTOCOL
*ImagePath
,
760 EFI_DEVICE_PATH_PROTOCOL
*FilePath
766 SHELL_FILE_HANDLE FileHandle
;
767 EFI_DEVICE_PATH_PROTOCOL
*NewPath
;
768 EFI_DEVICE_PATH_PROTOCOL
*NamePath
;
769 CHAR16
*FileStringPath
;
772 CONST CHAR16
*MapName
;
774 Key
.UnicodeChar
= CHAR_NULL
;
778 if (!ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.Startup
&& ShellInfoObject
.ShellInitSettings
.FileName
!= NULL
) {
780 // launch something else instead
782 NewSize
= StrSize(ShellInfoObject
.ShellInitSettings
.FileName
);
783 if (ShellInfoObject
.ShellInitSettings
.FileOptions
!= NULL
) {
784 NewSize
+= StrSize(ShellInfoObject
.ShellInitSettings
.FileOptions
) + sizeof(CHAR16
);
786 FileStringPath
= AllocateZeroPool(NewSize
);
787 if (FileStringPath
== NULL
) {
788 return (EFI_OUT_OF_RESOURCES
);
790 StrCpy(FileStringPath
, ShellInfoObject
.ShellInitSettings
.FileName
);
791 if (ShellInfoObject
.ShellInitSettings
.FileOptions
!= NULL
) {
792 StrCat(FileStringPath
, L
" ");
793 StrCat(FileStringPath
, ShellInfoObject
.ShellInitSettings
.FileOptions
);
795 Status
= RunCommand(FileStringPath
);
796 FreePool(FileStringPath
);
802 // for shell level 0 we do no scripts
803 // Without the Startup bit overriding we allow for nostartup to prevent scripts
805 if ( (PcdGet8(PcdShellSupportLevel
) < 1)
806 || (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoStartup
&& !ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.Startup
)
808 return (EFI_SUCCESS
);
812 // print out our warning and see if they press a key
814 for ( Status
= EFI_UNSUPPORTED
, Delay
= ShellInfoObject
.ShellInitSettings
.Delay
* 10
815 ; Delay
!= 0 && EFI_ERROR(Status
)
818 ShellPrintHiiEx(0, gST
->ConOut
->Mode
->CursorRow
, NULL
, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION
), ShellInfoObject
.HiiHandle
, Delay
/10);
820 if (!ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleIn
) {
821 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
824 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_CRLF
), ShellInfoObject
.HiiHandle
);
829 if (Status
== EFI_SUCCESS
&& Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_ESC
) {
830 return (EFI_SUCCESS
);
834 // Try the first location (must be file system)
836 MapName
= ShellInfoObject
.NewEfiShellProtocol
->GetMapFromDevicePath(&ImagePath
);
837 if (MapName
!= NULL
) {
838 FileStringPath
= NULL
;
840 FileStringPath
= StrnCatGrow(&FileStringPath
, &NewSize
, MapName
, 0);
841 TempSpot
= StrStr(FileStringPath
, L
";");
842 if (TempSpot
!= NULL
) {
843 *TempSpot
= CHAR_NULL
;
845 FileStringPath
= StrnCatGrow(&FileStringPath
, &NewSize
, ((FILEPATH_DEVICE_PATH
*)FilePath
)->PathName
, 0);
846 ChopLastSlash(FileStringPath
);
847 FileStringPath
= StrnCatGrow(&FileStringPath
, &NewSize
, mStartupScript
, 0);
848 Status
= ShellInfoObject
.NewEfiShellProtocol
->OpenFileByName(FileStringPath
, &FileHandle
, EFI_FILE_MODE_READ
);
849 FreePool(FileStringPath
);
851 if (EFI_ERROR(Status
)) {
852 NamePath
= FileDevicePath (NULL
, mStartupScript
);
853 NewPath
= AppendDevicePathNode (ImagePath
, NamePath
);
859 Status
= InternalOpenFileDevicePath(NewPath
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
863 // If we got a file, run it
865 if (!EFI_ERROR(Status
) && FileHandle
!= NULL
) {
866 Status
= RunScriptFileHandle (FileHandle
, mStartupScript
);
867 ShellInfoObject
.NewEfiShellProtocol
->CloseFile(FileHandle
);
869 FileStringPath
= ShellFindFilePath(mStartupScript
);
870 if (FileStringPath
== NULL
) {
872 // we return success since we dont need to have a startup script
874 Status
= EFI_SUCCESS
;
875 ASSERT(FileHandle
== NULL
);
877 Status
= RunScriptFile(FileStringPath
);
878 FreePool(FileStringPath
);
887 Function to perform the shell prompt looping. It will do a single prompt,
888 dispatch the result, and then return. It is expected that the caller will
889 call this function in a loop many times.
892 @retval RETURN_ABORTED
903 CONST CHAR16
*CurDir
;
910 // Get screen setting to decide size of the command line buffer
912 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &Column
, &Row
);
913 BufferSize
= Column
* Row
* sizeof (CHAR16
);
914 CmdLine
= AllocateZeroPool (BufferSize
);
915 if (CmdLine
== NULL
) {
916 return EFI_OUT_OF_RESOURCES
;
919 CurDir
= ShellInfoObject
.NewEfiShellProtocol
->GetEnv(L
"cwd");
924 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, 0, gST
->ConOut
->Mode
->CursorRow
);
926 if (CurDir
!= NULL
&& StrLen(CurDir
) > 1) {
927 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_CURDIR
), ShellInfoObject
.HiiHandle
, CurDir
);
929 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_SHELL
), ShellInfoObject
.HiiHandle
);
933 // Read a line from the console
935 Status
= ShellInfoObject
.NewEfiShellProtocol
->ReadFile(ShellInfoObject
.NewShellParametersProtocol
->StdIn
, &BufferSize
, CmdLine
);
938 // Null terminate the string and parse it
940 if (!EFI_ERROR (Status
)) {
941 CmdLine
[BufferSize
/ sizeof (CHAR16
)] = CHAR_NULL
;
942 Status
= RunCommand(CmdLine
);
946 // Done with this command
953 Add a buffer to the Buffer To Free List for safely returning buffers to other
954 places without risking letting them modify internal shell information.
956 @param Buffer Something to pass to FreePool when the shell is exiting.
964 BUFFER_LIST
*BufferListEntry
;
966 if (Buffer
== NULL
) {
970 BufferListEntry
= AllocateZeroPool(sizeof(BUFFER_LIST
));
971 ASSERT(BufferListEntry
!= NULL
);
972 BufferListEntry
->Buffer
= Buffer
;
973 InsertTailList(&ShellInfoObject
.BufferToFreeList
.Link
, &BufferListEntry
->Link
);
978 Add a buffer to the Line History List
980 @param Buffer The line buffer to add.
984 AddLineToCommandHistory(
985 IN CONST CHAR16
*Buffer
990 Node
= AllocateZeroPool(sizeof(BUFFER_LIST
));
991 ASSERT(Node
!= NULL
);
992 Node
->Buffer
= AllocateZeroPool(StrSize(Buffer
));
993 ASSERT(Node
->Buffer
!= NULL
);
994 StrCpy(Node
->Buffer
, Buffer
);
996 InsertTailList(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
);
1000 Checks if a string is an alias for another command. If yes, then it replaces the alias name
1001 with the correct command name.
1003 @param[in,out] CommandString Upon entry the potential alias. Upon return the
1004 command name if it was an alias. If it was not
1005 an alias it will be unchanged. This function may
1006 change the buffer to fit the command name.
1008 @retval EFI_SUCCESS The name was changed.
1009 @retval EFI_SUCCESS The name was not an alias.
1010 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1015 IN OUT CHAR16
**CommandString
1018 CONST CHAR16
*NewString
;
1020 NewString
= ShellInfoObject
.NewEfiShellProtocol
->GetAlias(*CommandString
, NULL
);
1021 if (NewString
== NULL
) {
1022 return (EFI_SUCCESS
);
1024 FreePool(*CommandString
);
1025 *CommandString
= AllocateZeroPool(StrSize(NewString
));
1026 if (*CommandString
== NULL
) {
1027 return (EFI_OUT_OF_RESOURCES
);
1029 StrCpy(*CommandString
, NewString
);
1030 return (EFI_SUCCESS
);
1034 Function allocates a new command line and replaces all instances of environment
1035 variable names that are correctly preset to their values.
1037 If the return value is not NULL the memory must be caller freed.
1039 @param[in] OriginalCommandLine The original command line
1041 @retval NULL An error ocurred.
1042 @return The new command line with no environment variables present.
1046 ShellConvertVariables (
1047 IN CONST CHAR16
*OriginalCommandLine
1050 CONST CHAR16
*MasterEnvList
;
1052 CHAR16
*NewCommandLine1
;
1053 CHAR16
*NewCommandLine2
;
1057 SCRIPT_FILE
*CurrentScriptFile
;
1058 ALIAS_LIST
*AliasListNode
;
1060 ASSERT(OriginalCommandLine
!= NULL
);
1063 NewSize
= StrSize(OriginalCommandLine
);
1064 CurrentScriptFile
= ShellCommandGetCurrentScriptFile();
1067 ///@todo update this to handle the %0 - %9 for scripting only (borrow from line 1256 area) ? ? ?
1070 // calculate the size required for the post-conversion string...
1072 if (CurrentScriptFile
!= NULL
) {
1073 for (AliasListNode
= (ALIAS_LIST
*)GetFirstNode(&CurrentScriptFile
->SubstList
)
1074 ; !IsNull(&CurrentScriptFile
->SubstList
, &AliasListNode
->Link
)
1075 ; AliasListNode
= (ALIAS_LIST
*)GetNextNode(&CurrentScriptFile
->SubstList
, &AliasListNode
->Link
)
1077 for (Temp
= StrStr(OriginalCommandLine
, AliasListNode
->Alias
)
1079 ; Temp
= StrStr(Temp
+1, AliasListNode
->Alias
)
1082 // we need a preceeding and if there is space no ^ preceeding (if no space ignore)
1084 if ((((Temp
-OriginalCommandLine
)>2) && *(Temp
-2) != L
'^') || ((Temp
-OriginalCommandLine
)<=2)) {
1085 NewSize
+= StrSize(AliasListNode
->CommandString
);
1091 for (MasterEnvList
= EfiShellGetEnv(NULL
)
1092 ; MasterEnvList
!= NULL
&& *MasterEnvList
!= CHAR_NULL
//&& *(MasterEnvList+1) != CHAR_NULL
1093 ; MasterEnvList
+= StrLen(MasterEnvList
) + 1
1095 if (StrSize(MasterEnvList
) > ItemSize
) {
1096 ItemSize
= StrSize(MasterEnvList
);
1098 for (Temp
= StrStr(OriginalCommandLine
, MasterEnvList
)
1100 ; Temp
= StrStr(Temp
+1, MasterEnvList
)
1103 // we need a preceeding and following % and if there is space no ^ preceeding (if no space ignore)
1105 if (*(Temp
-1) == L
'%' && *(Temp
+StrLen(MasterEnvList
)) == L
'%' &&
1106 ((((Temp
-OriginalCommandLine
)>2) && *(Temp
-2) != L
'^') || ((Temp
-OriginalCommandLine
)<=2))) {
1107 NewSize
+=StrSize(EfiShellGetEnv(MasterEnvList
));
1113 // Quick out if none were found...
1115 if (NewSize
== StrSize(OriginalCommandLine
)) {
1116 ASSERT(Temp
== NULL
);
1117 Temp
= StrnCatGrow(&Temp
, NULL
, OriginalCommandLine
, 0);
1122 // now do the replacements...
1124 NewCommandLine1
= AllocateZeroPool(NewSize
);
1125 NewCommandLine2
= AllocateZeroPool(NewSize
);
1126 ItemTemp
= AllocateZeroPool(ItemSize
+(2*sizeof(CHAR16
)));
1127 if (NewCommandLine1
== NULL
|| NewCommandLine2
== NULL
|| ItemTemp
== NULL
) {
1128 SHELL_FREE_NON_NULL(NewCommandLine1
);
1129 SHELL_FREE_NON_NULL(NewCommandLine2
);
1130 SHELL_FREE_NON_NULL(ItemTemp
);
1133 StrCpy(NewCommandLine1
, OriginalCommandLine
);
1134 for (MasterEnvList
= EfiShellGetEnv(NULL
)
1135 ; MasterEnvList
!= NULL
&& *MasterEnvList
!= CHAR_NULL
//&& *(MasterEnvList+1) != CHAR_NULL
1136 ; MasterEnvList
+= StrLen(MasterEnvList
) + 1
1138 StrCpy(ItemTemp
, L
"%");
1139 StrCat(ItemTemp
, MasterEnvList
);
1140 StrCat(ItemTemp
, L
"%");
1141 ShellCopySearchAndReplace(NewCommandLine1
, NewCommandLine2
, NewSize
, ItemTemp
, EfiShellGetEnv(MasterEnvList
), TRUE
, FALSE
);
1142 StrCpy(NewCommandLine1
, NewCommandLine2
);
1144 if (CurrentScriptFile
!= NULL
) {
1145 for (AliasListNode
= (ALIAS_LIST
*)GetFirstNode(&CurrentScriptFile
->SubstList
)
1146 ; !IsNull(&CurrentScriptFile
->SubstList
, &AliasListNode
->Link
)
1147 ; AliasListNode
= (ALIAS_LIST
*)GetNextNode(&CurrentScriptFile
->SubstList
, &AliasListNode
->Link
)
1149 ShellCopySearchAndReplace(NewCommandLine1
, NewCommandLine2
, NewSize
, AliasListNode
->Alias
, AliasListNode
->CommandString
, TRUE
, FALSE
);
1150 StrCpy(NewCommandLine1
, NewCommandLine2
);
1154 FreePool(NewCommandLine2
);
1157 return (NewCommandLine1
);
1161 Internal function to run a command line with pipe usage.
1163 @param[in] CmdLine The pointer to the command line.
1164 @param[in] StdIn The pointer to the Standard input.
1165 @param[in] StdOut The pointer to the Standard output.
1167 @retval EFI_SUCCESS The split command is executed successfully.
1168 @retval other Some error occurs when executing the split command.
1173 IN CONST CHAR16
*CmdLine
,
1174 IN SHELL_FILE_HANDLE
*StdIn
,
1175 IN SHELL_FILE_HANDLE
*StdOut
1179 CHAR16
*NextCommandLine
;
1180 CHAR16
*OurCommandLine
;
1184 SHELL_FILE_HANDLE
*TempFileHandle
;
1187 ASSERT(StdOut
== NULL
);
1189 ASSERT(StrStr(CmdLine
, L
"|") != NULL
);
1191 Status
= EFI_SUCCESS
;
1192 NextCommandLine
= NULL
;
1193 OurCommandLine
= NULL
;
1197 NextCommandLine
= StrnCatGrow(&NextCommandLine
, &Size1
, StrStr(CmdLine
, L
"|")+1, 0);
1198 OurCommandLine
= StrnCatGrow(&OurCommandLine
, &Size2
, CmdLine
, StrStr(CmdLine
, L
"|") - CmdLine
);
1199 if (NextCommandLine
[0] != CHAR_NULL
&&
1200 NextCommandLine
[0] == L
'a' &&
1201 NextCommandLine
[1] == L
' '
1203 CopyMem(NextCommandLine
, NextCommandLine
+1, StrSize(NextCommandLine
) - sizeof(NextCommandLine
[0]));
1211 // make a SPLIT_LIST item and add to list
1213 Split
= AllocateZeroPool(sizeof(SPLIT_LIST
));
1214 ASSERT(Split
!= NULL
);
1215 Split
->SplitStdIn
= StdIn
;
1216 Split
->SplitStdOut
= ConvertEfiFileProtocolToShellHandle(CreateFileInterfaceMem(Unicode
), NULL
);
1217 ASSERT(Split
->SplitStdOut
!= NULL
);
1218 InsertHeadList(&ShellInfoObject
.SplitList
.Link
, &Split
->Link
);
1220 ASSERT(StrStr(OurCommandLine
, L
"|") == NULL
);
1221 Status
= RunCommand(OurCommandLine
);
1224 // move the output from the first to the in to the second.
1226 TempFileHandle
= Split
->SplitStdOut
;
1227 if (Split
->SplitStdIn
== StdIn
) {
1228 Split
->SplitStdOut
= NULL
;
1230 Split
->SplitStdOut
= Split
->SplitStdIn
;
1232 Split
->SplitStdIn
= TempFileHandle
;
1233 ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split
->SplitStdIn
), 0);
1235 if (!EFI_ERROR(Status
)) {
1236 Status
= RunCommand(NextCommandLine
);
1240 // remove the top level from the ScriptList
1242 ASSERT((SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
) == Split
);
1243 RemoveEntryList(&Split
->Link
);
1246 // Note that the original StdIn is now the StdOut...
1248 if (Split
->SplitStdOut
!= NULL
&& Split
->SplitStdOut
!= StdIn
) {
1249 ShellInfoObject
.NewEfiShellProtocol
->CloseFile(ConvertShellHandleToEfiFileProtocol(Split
->SplitStdOut
));
1251 if (Split
->SplitStdIn
!= NULL
) {
1252 ShellInfoObject
.NewEfiShellProtocol
->CloseFile(ConvertShellHandleToEfiFileProtocol(Split
->SplitStdIn
));
1256 FreePool(NextCommandLine
);
1257 FreePool(OurCommandLine
);
1263 Function will process and run a command line.
1265 This will determine if the command line represents an internal shell
1266 command or dispatch an external application.
1268 @param[in] CmdLine The command line to parse.
1270 @retval EFI_SUCCESS The command was completed.
1271 @retval EFI_ABORTED The command's operation was aborted.
1276 IN CONST CHAR16
*CmdLine
1280 CHAR16
*CommandName
;
1281 SHELL_STATUS ShellStatus
;
1285 CHAR16 LeString
[11];
1286 CHAR16
*PostAliasCmdLine
;
1287 UINTN PostAliasSize
;
1288 CHAR16
*PostVariableCmdLine
;
1289 CHAR16
*CommandWithPath
;
1290 CONST EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1291 CONST CHAR16
*TempLocation
;
1292 CONST CHAR16
*TempLocation2
;
1293 SHELL_FILE_HANDLE OriginalStdIn
;
1294 SHELL_FILE_HANDLE OriginalStdOut
;
1295 SHELL_FILE_HANDLE OriginalStdErr
;
1296 SYSTEM_TABLE_INFO OriginalSystemTableInfo
;
1297 CHAR16
*TempLocation3
;
1300 CHAR16
*CleanOriginal
;
1303 ASSERT(CmdLine
!= NULL
);
1304 if (StrLen(CmdLine
) == 0) {
1305 return (EFI_SUCCESS
);
1309 PostVariableCmdLine
= NULL
;
1310 PostAliasCmdLine
= NULL
;
1311 CommandWithPath
= NULL
;
1313 Status
= EFI_SUCCESS
;
1314 CleanOriginal
= NULL
;
1317 CleanOriginal
= StrnCatGrow(&CleanOriginal
, NULL
, CmdLine
, 0);
1318 while (CleanOriginal
[StrLen(CleanOriginal
)-1] == L
' ') {
1319 CleanOriginal
[StrLen(CleanOriginal
)-1] = CHAR_NULL
;
1321 while (CleanOriginal
[0] == L
' ') {
1322 CopyMem(CleanOriginal
, CleanOriginal
+1, StrSize(CleanOriginal
) - sizeof(CleanOriginal
[0]));
1326 if (StrStr(CleanOriginal
, L
" ") == NULL
){
1327 StrnCatGrow(&CommandName
, NULL
, CleanOriginal
, 0);
1329 StrnCatGrow(&CommandName
, NULL
, CleanOriginal
, StrStr(CleanOriginal
, L
" ") - CleanOriginal
);
1332 ASSERT(PostAliasCmdLine
== NULL
);
1333 if (!ShellCommandIsCommandOnList(CommandName
)) {
1335 // Convert via alias
1337 Status
= ShellConvertAlias(&CommandName
);
1339 PostAliasCmdLine
= StrnCatGrow(&PostAliasCmdLine
, &PostAliasSize
, CommandName
, 0);
1340 PostAliasCmdLine
= StrnCatGrow(&PostAliasCmdLine
, &PostAliasSize
, StrStr(CleanOriginal
, L
" "), 0);
1341 ASSERT_EFI_ERROR(Status
);
1343 PostAliasCmdLine
= StrnCatGrow(&PostAliasCmdLine
, NULL
, CleanOriginal
, 0);
1346 if (CleanOriginal
!= NULL
) {
1347 FreePool(CleanOriginal
);
1348 CleanOriginal
= NULL
;
1351 if (CommandName
!= NULL
) {
1352 FreePool(CommandName
);
1356 PostVariableCmdLine
= ShellConvertVariables(PostAliasCmdLine
);
1359 // we can now free the modified by alias command line
1361 if (PostAliasCmdLine
!= NULL
) {
1362 FreePool(PostAliasCmdLine
);
1363 PostAliasCmdLine
= NULL
;
1366 if (PostVariableCmdLine
== NULL
) {
1367 return (EFI_OUT_OF_RESOURCES
);
1370 while (PostVariableCmdLine
[StrLen(PostVariableCmdLine
)-1] == L
' ') {
1371 PostVariableCmdLine
[StrLen(PostVariableCmdLine
)-1] = CHAR_NULL
;
1373 while (PostVariableCmdLine
[0] == L
' ') {
1374 CopyMem(PostVariableCmdLine
, PostVariableCmdLine
+1, StrSize(PostVariableCmdLine
) - sizeof(PostVariableCmdLine
[0]));
1378 // We dont do normal processing with a split command line (output from one command input to another)
1380 TempLocation3
= NULL
;
1381 if (StrStr(PostVariableCmdLine
, L
"|") != NULL
) {
1382 for (TempLocation3
= PostVariableCmdLine
; TempLocation3
!= NULL
&& *TempLocation3
!= CHAR_NULL
; TempLocation3
++) {
1383 if (*TempLocation3
== L
'^' && *(TempLocation3
+1) == L
'|') {
1385 } else if (*TempLocation3
== L
'|') {
1390 if (TempLocation3
!= NULL
&& *TempLocation3
!= CHAR_NULL
) {
1392 // are we in an existing split???
1394 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1395 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1398 if (Split
== NULL
) {
1399 Status
= RunSplitCommand(PostVariableCmdLine
, NULL
, NULL
);
1401 Status
= RunSplitCommand(PostVariableCmdLine
, Split
->SplitStdIn
, Split
->SplitStdOut
);
1406 // If this is a mapped drive change handle that...
1408 if (PostVariableCmdLine
[(StrLen(PostVariableCmdLine
)-1)] == L
':' && StrStr(PostVariableCmdLine
, L
" ") == NULL
) {
1409 Status
= ShellInfoObject
.NewEfiShellProtocol
->SetCurDir(NULL
, PostVariableCmdLine
);
1410 if (EFI_ERROR(Status
)) {
1411 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_INVALID_MAPPING
), ShellInfoObject
.HiiHandle
, PostVariableCmdLine
);
1413 FreePool(PostVariableCmdLine
);
1417 ///@todo update this section to divide into 3 ways - run internal command, run split (above), and run an external file...
1418 /// We waste a lot of time doing processing like StdIn,StdOut,Argv,Argc for things that are external files...
1422 Status
= UpdateStdInStdOutStdErr(ShellInfoObject
.NewShellParametersProtocol
, PostVariableCmdLine
, &OriginalStdIn
, &OriginalStdOut
, &OriginalStdErr
, &OriginalSystemTableInfo
);
1423 if (EFI_ERROR(Status
)) {
1424 if (Status
== EFI_NOT_FOUND
) {
1425 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR
), ShellInfoObject
.HiiHandle
);
1427 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_INVALID_REDIR
), ShellInfoObject
.HiiHandle
);
1431 // remove the < and/or > from the command line now
1433 for (TempLocation3
= PostVariableCmdLine
; TempLocation3
!= NULL
&& *TempLocation3
!= CHAR_NULL
; TempLocation3
++) {
1434 if (*TempLocation3
== L
'^') {
1435 if (*(TempLocation3
+1) == L
'<' || *(TempLocation3
+1) == L
'>') {
1436 CopyMem(TempLocation3
, TempLocation3
+1, StrSize(TempLocation3
) - sizeof(TempLocation3
[0]));
1438 } else if (*TempLocation3
== L
'>') {
1439 *TempLocation3
= CHAR_NULL
;
1440 } else if ((*TempLocation3
== L
'1' || *TempLocation3
== L
'2')&&(*(TempLocation3
+1) == L
'>')) {
1441 *TempLocation3
= CHAR_NULL
;
1445 while (PostVariableCmdLine
[StrLen(PostVariableCmdLine
)-1] == L
' ') {
1446 PostVariableCmdLine
[StrLen(PostVariableCmdLine
)-1] = CHAR_NULL
;
1448 while (PostVariableCmdLine
[0] == L
' ') {
1449 CopyMem(PostVariableCmdLine
, PostVariableCmdLine
+1, StrSize(PostVariableCmdLine
) - sizeof(PostVariableCmdLine
[0]));
1453 // get the argc and argv updated for internal commands
1455 Status
= UpdateArgcArgv(ShellInfoObject
.NewShellParametersProtocol
, PostVariableCmdLine
, &Argv
, &Argc
);
1456 ASSERT_EFI_ERROR(Status
);
1458 for (Count
= 0 ; Count
< ShellInfoObject
.NewShellParametersProtocol
->Argc
; Count
++) {
1459 if (StrStr(ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count
], L
"-?") == ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count
]
1460 || (ShellInfoObject
.NewShellParametersProtocol
->Argv
[0][0] == L
'?' && ShellInfoObject
.NewShellParametersProtocol
->Argv
[0][1] == CHAR_NULL
)
1463 // We need to redo the arguments since a parameter was -?
1464 // move them all down 1 to the end, then up one then replace the first with help
1466 FreePool(ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count
]);
1467 ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count
] = NULL
;
1468 for (Count2
= Count
; (Count2
+ 1) < ShellInfoObject
.NewShellParametersProtocol
->Argc
; Count2
++) {
1469 ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count2
] = ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count2
+1];
1471 ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count2
] = NULL
;
1472 for (Count2
= ShellInfoObject
.NewShellParametersProtocol
->Argc
-1 ; Count2
> 0 ; Count2
--) {
1473 ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count2
] = ShellInfoObject
.NewShellParametersProtocol
->Argv
[Count2
-1];
1475 ShellInfoObject
.NewShellParametersProtocol
->Argv
[0] = NULL
;
1476 ShellInfoObject
.NewShellParametersProtocol
->Argv
[0] = StrnCatGrow(&ShellInfoObject
.NewShellParametersProtocol
->Argv
[0], NULL
, L
"help", 0);
1484 if (ShellCommandIsCommandOnList(ShellInfoObject
.NewShellParametersProtocol
->Argv
[0])) {
1486 // Run the command (which was converted if it was an alias)
1488 if (!EFI_ERROR(Status
)) {
1489 Status
= ShellCommandRunCommandHandler(ShellInfoObject
.NewShellParametersProtocol
->Argv
[0], &ShellStatus
, &LastError
);
1490 ASSERT_EFI_ERROR(Status
);
1491 UnicodeSPrint(LeString
, sizeof(LeString
)*sizeof(LeString
[0]), L
"0x%08x", ShellStatus
);
1492 DEBUG_CODE(InternalEfiShellSetEnv(L
"DebugLasterror", LeString
, TRUE
););
1494 InternalEfiShellSetEnv(L
"Lasterror", LeString
, TRUE
);
1497 // Pass thru the exitcode from the app.
1499 if (ShellCommandGetExit()) {
1500 Status
= ShellStatus
;
1501 } else if (ShellStatus
!= 0 && IsScriptOnlyCommand(ShellInfoObject
.NewShellParametersProtocol
->Argv
[0])) {
1502 Status
= EFI_ABORTED
;
1507 // run an external file (or script)
1509 if (StrStr(ShellInfoObject
.NewShellParametersProtocol
->Argv
[0], L
":") != NULL
) {
1510 ASSERT (CommandWithPath
== NULL
);
1511 if (ShellIsFile(ShellInfoObject
.NewShellParametersProtocol
->Argv
[0]) == EFI_SUCCESS
) {
1512 CommandWithPath
= StrnCatGrow(&CommandWithPath
, NULL
, ShellInfoObject
.NewShellParametersProtocol
->Argv
[0], 0);
1515 if (CommandWithPath
== NULL
) {
1516 CommandWithPath
= ShellFindFilePathEx(ShellInfoObject
.NewShellParametersProtocol
->Argv
[0], mExecutableExtensions
);
1518 if (CommandWithPath
== NULL
|| ShellIsDirectory(CommandWithPath
) == EFI_SUCCESS
) {
1519 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_NOT_FOUND
), ShellInfoObject
.HiiHandle
, ShellInfoObject
.NewShellParametersProtocol
->Argv
[0]);
1522 // Check if it's a NSH (script) file.
1524 TempLocation
= CommandWithPath
+StrLen(CommandWithPath
)-4;
1525 TempLocation2
= mScriptExtension
;
1526 if ((StrLen(CommandWithPath
) > 4) && (StringNoCaseCompare((VOID
*)(&TempLocation
), (VOID
*)(&TempLocation2
)) == 0)) {
1527 Status
= RunScriptFile (CommandWithPath
);
1529 DevPath
= ShellInfoObject
.NewEfiShellProtocol
->GetDevicePathFromFilePath(CommandWithPath
);
1530 ASSERT(DevPath
!= NULL
);
1531 Status
= InternalShellExecuteDevicePath(
1534 PostVariableCmdLine
,
1541 CommandName
= StrnCatGrow(&CommandName
, NULL
, ShellInfoObject
.NewShellParametersProtocol
->Argv
[0], 0);
1543 RestoreArgcArgv(ShellInfoObject
.NewShellParametersProtocol
, &Argv
, &Argc
);
1545 RestoreStdInStdOutStdErr(ShellInfoObject
.NewShellParametersProtocol
, &OriginalStdIn
, &OriginalStdOut
, &OriginalStdErr
, &OriginalSystemTableInfo
);
1547 if (CommandName
!= NULL
) {
1548 if (ShellCommandGetCurrentScriptFile() != NULL
&& !IsScriptOnlyCommand(CommandName
)) {
1550 // if this is NOT a scipt only command return success so the script won't quit.
1551 // prevent killing the script - this is the only place where we know the actual command name (after alias and variable replacement...)
1553 Status
= EFI_SUCCESS
;
1558 SHELL_FREE_NON_NULL(CommandName
);
1559 SHELL_FREE_NON_NULL(CommandWithPath
);
1560 SHELL_FREE_NON_NULL(PostVariableCmdLine
);
1565 STATIC CONST UINT16 InvalidChars
[] = {L
'*', L
'?', L
'<', L
'>', L
'\\', L
'/', L
'\"', 0x0001, 0x0002};
1567 Function determins if the CommandName COULD be a valid command. It does not determine whether
1568 this is a valid command. It only checks for invalid characters.
1570 @param[in] CommandName The name to check
1572 @retval TRUE CommandName could be a command name
1573 @retval FALSE CommandName could not be a valid command name
1578 IN CONST CHAR16
*CommandName
1582 if (CommandName
== NULL
) {
1587 ; Count
< sizeof(InvalidChars
) / sizeof(InvalidChars
[0])
1590 if (ScanMem16(CommandName
, StrSize(CommandName
), InvalidChars
[Count
]) != NULL
) {
1598 Function to process a NSH script file via SHELL_FILE_HANDLE.
1600 @param[in] Handle The handle to the already opened file.
1601 @param[in] Name The name of the script file.
1603 @retval EFI_SUCCESS the script completed sucessfully
1607 RunScriptFileHandle (
1608 IN SHELL_FILE_HANDLE Handle
,
1609 IN CONST CHAR16
*Name
1613 SCRIPT_FILE
*NewScriptFile
;
1615 CHAR16
*CommandLine
;
1616 CHAR16
*CommandLine2
;
1617 CHAR16
*CommandLine3
;
1618 SCRIPT_COMMAND_LIST
*LastCommand
;
1620 BOOLEAN PreScriptEchoState
;
1621 CONST CHAR16
*CurDir
;
1624 ASSERT(!ShellCommandGetScriptExit());
1626 PreScriptEchoState
= ShellCommandGetEchoState();
1628 NewScriptFile
= (SCRIPT_FILE
*)AllocateZeroPool(sizeof(SCRIPT_FILE
));
1629 if (NewScriptFile
== NULL
) {
1630 return (EFI_OUT_OF_RESOURCES
);
1636 ASSERT(NewScriptFile
->ScriptName
== NULL
);
1637 NewScriptFile
->ScriptName
= StrnCatGrow(&NewScriptFile
->ScriptName
, NULL
, Name
, 0);
1638 if (NewScriptFile
->ScriptName
== NULL
) {
1639 DeleteScriptFileStruct(NewScriptFile
);
1640 return (EFI_OUT_OF_RESOURCES
);
1644 // Save the parameters (used to replace %0 to %9 later on)
1646 NewScriptFile
->Argc
= ShellInfoObject
.NewShellParametersProtocol
->Argc
;
1647 if (NewScriptFile
->Argc
!= 0) {
1648 NewScriptFile
->Argv
= (CHAR16
**)AllocateZeroPool(NewScriptFile
->Argc
* sizeof(CHAR16
*));
1649 if (NewScriptFile
->Argv
== NULL
) {
1650 DeleteScriptFileStruct(NewScriptFile
);
1651 return (EFI_OUT_OF_RESOURCES
);
1653 for (LoopVar
= 0 ; LoopVar
< 10 && LoopVar
< NewScriptFile
->Argc
; LoopVar
++) {
1654 ASSERT(NewScriptFile
->Argv
[LoopVar
] == NULL
);
1655 NewScriptFile
->Argv
[LoopVar
] = StrnCatGrow(&NewScriptFile
->Argv
[LoopVar
], NULL
, ShellInfoObject
.NewShellParametersProtocol
->Argv
[LoopVar
], 0);
1656 if (NewScriptFile
->Argv
[LoopVar
] == NULL
) {
1657 DeleteScriptFileStruct(NewScriptFile
);
1658 return (EFI_OUT_OF_RESOURCES
);
1662 NewScriptFile
->Argv
= NULL
;
1665 InitializeListHead(&NewScriptFile
->CommandList
);
1666 InitializeListHead(&NewScriptFile
->SubstList
);
1669 // Now build the list of all script commands.
1672 while(!ShellFileHandleEof(Handle
)) {
1673 CommandLine
= ShellFileHandleReturnLine(Handle
, &Ascii
);
1675 if (CommandLine
== NULL
|| StrLen(CommandLine
) == 0) {
1678 NewScriptFile
->CurrentCommand
= AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST
));
1679 if (NewScriptFile
->CurrentCommand
== NULL
) {
1680 DeleteScriptFileStruct(NewScriptFile
);
1681 return (EFI_OUT_OF_RESOURCES
);
1684 NewScriptFile
->CurrentCommand
->Cl
= CommandLine
;
1685 NewScriptFile
->CurrentCommand
->Data
= NULL
;
1686 NewScriptFile
->CurrentCommand
->Line
= LineCount
;
1688 InsertTailList(&NewScriptFile
->CommandList
, &NewScriptFile
->CurrentCommand
->Link
);
1692 // Add this as the topmost script file
1694 ShellCommandSetNewScript (NewScriptFile
);
1697 // Now enumerate through the commands and run each one.
1699 CommandLine
= AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize
));
1700 if (CommandLine
== NULL
) {
1701 DeleteScriptFileStruct(NewScriptFile
);
1702 return (EFI_OUT_OF_RESOURCES
);
1704 CommandLine2
= AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize
));
1705 if (CommandLine2
== NULL
) {
1706 FreePool(CommandLine
);
1707 DeleteScriptFileStruct(NewScriptFile
);
1708 return (EFI_OUT_OF_RESOURCES
);
1711 for ( NewScriptFile
->CurrentCommand
= (SCRIPT_COMMAND_LIST
*)GetFirstNode(&NewScriptFile
->CommandList
)
1712 ; !IsNull(&NewScriptFile
->CommandList
, &NewScriptFile
->CurrentCommand
->Link
)
1713 ; // conditional increment in the body of the loop
1715 ASSERT(CommandLine2
!= NULL
);
1716 StrCpy(CommandLine2
, NewScriptFile
->CurrentCommand
->Cl
);
1719 // NULL out comments
1721 for (CommandLine3
= CommandLine2
; CommandLine3
!= NULL
&& *CommandLine3
!= CHAR_NULL
; CommandLine3
++) {
1722 if (*CommandLine3
== L
'^') {
1723 if (*(CommandLine3
+1) == L
'#' || *(CommandLine3
+1) == L
':') {
1724 CopyMem(CommandLine3
, CommandLine3
+1, StrSize(CommandLine3
) - sizeof(CommandLine3
[0]));
1726 } else if (*CommandLine3
== L
'#') {
1727 *CommandLine3
= CHAR_NULL
;
1731 if (CommandLine2
!= NULL
&& StrLen(CommandLine2
) >= 1) {
1733 // Due to variability in starting the find and replace action we need to have both buffers the same.
1735 StrCpy(CommandLine
, CommandLine2
);
1738 // Remove the %0 to %9 from the command line (if we have some arguments)
1740 if (NewScriptFile
->Argv
!= NULL
) {
1741 switch (NewScriptFile
->Argc
) {
1743 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%9", NewScriptFile
->Argv
[9], FALSE
, TRUE
);
1744 ASSERT_EFI_ERROR(Status
);
1746 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%8", NewScriptFile
->Argv
[8], FALSE
, TRUE
);
1747 ASSERT_EFI_ERROR(Status
);
1749 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%7", NewScriptFile
->Argv
[7], FALSE
, TRUE
);
1750 ASSERT_EFI_ERROR(Status
);
1752 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%6", NewScriptFile
->Argv
[6], FALSE
, TRUE
);
1753 ASSERT_EFI_ERROR(Status
);
1755 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%5", NewScriptFile
->Argv
[5], FALSE
, TRUE
);
1756 ASSERT_EFI_ERROR(Status
);
1758 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%4", NewScriptFile
->Argv
[4], FALSE
, TRUE
);
1759 ASSERT_EFI_ERROR(Status
);
1761 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%3", NewScriptFile
->Argv
[3], FALSE
, TRUE
);
1762 ASSERT_EFI_ERROR(Status
);
1764 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%2", NewScriptFile
->Argv
[2], FALSE
, TRUE
);
1765 ASSERT_EFI_ERROR(Status
);
1767 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%1", NewScriptFile
->Argv
[1], FALSE
, TRUE
);
1768 ASSERT_EFI_ERROR(Status
);
1770 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%0", NewScriptFile
->Argv
[0], FALSE
, TRUE
);
1771 ASSERT_EFI_ERROR(Status
);
1777 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%1", L
"\"\"", FALSE
, FALSE
);
1778 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%2", L
"\"\"", FALSE
, FALSE
);
1779 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%3", L
"\"\"", FALSE
, FALSE
);
1780 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%4", L
"\"\"", FALSE
, FALSE
);
1781 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%5", L
"\"\"", FALSE
, FALSE
);
1782 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%6", L
"\"\"", FALSE
, FALSE
);
1783 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%7", L
"\"\"", FALSE
, FALSE
);
1784 Status
= ShellCopySearchAndReplace(CommandLine
, CommandLine2
, PcdGet16 (PcdShellPrintBufferSize
), L
"%8", L
"\"\"", FALSE
, FALSE
);
1785 Status
= ShellCopySearchAndReplace(CommandLine2
, CommandLine
, PcdGet16 (PcdShellPrintBufferSize
), L
"%9", L
"\"\"", FALSE
, FALSE
);
1787 StrCpy(CommandLine2
, CommandLine
);
1789 LastCommand
= NewScriptFile
->CurrentCommand
;
1791 for (CommandLine3
= CommandLine2
; CommandLine3
[0] == L
' ' ; CommandLine3
++);
1793 if (CommandLine3
!= NULL
&& CommandLine3
[0] == L
':' ) {
1795 // This line is a goto target / label
1798 if (CommandLine3
!= NULL
&& StrLen(CommandLine3
) > 0) {
1799 if (ShellCommandGetEchoState()) {
1800 CurDir
= ShellInfoObject
.NewEfiShellProtocol
->GetEnv(L
"cwd");
1801 if (CurDir
!= NULL
&& StrLen(CurDir
) > 1) {
1802 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_CURDIR
), ShellInfoObject
.HiiHandle
, CurDir
);
1804 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_SHELL
), ShellInfoObject
.HiiHandle
);
1806 ShellPrintEx(-1, -1, L
"%s\r\n", CommandLine2
);
1808 Status
= RunCommand(CommandLine3
);
1811 if (ShellCommandGetScriptExit()) {
1812 ShellCommandRegisterExit(FALSE
);
1813 Status
= EFI_SUCCESS
;
1816 if (EFI_ERROR(Status
)) {
1819 if (ShellCommandGetExit()) {
1824 // If that commend did not update the CurrentCommand then we need to advance it...
1826 if (LastCommand
== NewScriptFile
->CurrentCommand
) {
1827 NewScriptFile
->CurrentCommand
= (SCRIPT_COMMAND_LIST
*)GetNextNode(&NewScriptFile
->CommandList
, &NewScriptFile
->CurrentCommand
->Link
);
1828 if (!IsNull(&NewScriptFile
->CommandList
, &NewScriptFile
->CurrentCommand
->Link
)) {
1829 NewScriptFile
->CurrentCommand
->Reset
= TRUE
;
1833 NewScriptFile
->CurrentCommand
= (SCRIPT_COMMAND_LIST
*)GetNextNode(&NewScriptFile
->CommandList
, &NewScriptFile
->CurrentCommand
->Link
);
1834 if (!IsNull(&NewScriptFile
->CommandList
, &NewScriptFile
->CurrentCommand
->Link
)) {
1835 NewScriptFile
->CurrentCommand
->Reset
= TRUE
;
1841 FreePool(CommandLine
);
1842 FreePool(CommandLine2
);
1843 ShellCommandSetNewScript (NULL
);
1846 // Only if this was the last script reset the state.
1848 if (ShellCommandGetCurrentScriptFile()==NULL
) {
1849 ShellCommandSetEchoState(PreScriptEchoState
);
1851 return (EFI_SUCCESS
);
1855 Function to process a NSH script file.
1857 @param[in] ScriptPath Pointer to the script file name (including file system path).
1859 @retval EFI_SUCCESS the script completed sucessfully
1864 IN CONST CHAR16
*ScriptPath
1868 SHELL_FILE_HANDLE FileHandle
;
1870 if (ShellIsFile(ScriptPath
) != EFI_SUCCESS
) {
1871 return (EFI_INVALID_PARAMETER
);
1874 Status
= ShellOpenFileByName(ScriptPath
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
1875 if (EFI_ERROR(Status
)) {
1879 Status
= RunScriptFileHandle(FileHandle
, ScriptPath
);
1881 ShellCloseFile(&FileHandle
);