TianoCore EDK2 master
Loading...
Searching...
No Matches
Shell.c
Go to the documentation of this file.
1
12#include "Shell.h"
13
14//
15// Initialize the global structure
16//
17SHELL_INFO ShellInfoObject = {
18 NULL,
19 NULL,
20 FALSE,
21 FALSE,
22 {
23 {
24 {
25 0,
26 0,
27 0,
28 0,
29 0,
30 0,
31 0,
32 0,
33 0,
34 0
35 }
36 },
37 0,
38 NULL,
39 NULL
40 },
41 {
42 { NULL,NULL }, NULL
43 },
44 {
45 {
46 { NULL,NULL }, NULL
47 },
48 0,
49 0,
50 TRUE
51 },
52 NULL,
53 0,
54 NULL,
55 NULL,
56 NULL,
57 NULL,
58 NULL,
59 {
60 { NULL,NULL }, NULL, NULL
61 },
62 {
63 { NULL,NULL }, NULL, NULL
64 },
65 NULL,
66 NULL,
67 NULL,
68 NULL,
69 NULL,
70 NULL,
71 NULL,
72 NULL,
73 FALSE
74};
75
76STATIC CONST CHAR16 mScriptExtension[] = L".NSH";
77STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";
78STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";
79CONST CHAR16 mNoNestingEnvVarName[] = L"nonesting";
80CONST CHAR16 mNoNestingTrue[] = L"True";
81CONST CHAR16 mNoNestingFalse[] = L"False";
82
90 IN CHAR16 **String
91 )
92{
93 ASSERT (String != NULL);
94 ASSERT (*String != NULL);
95 //
96 // Remove any spaces and tabs at the beginning of the (*String).
97 //
98 while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) {
99 CopyMem ((*String), (*String)+1, StrSize ((*String)) - sizeof ((*String)[0]));
100 }
101
102 //
103 // Remove any spaces and tabs at the end of the (*String).
104 //
105 while ((StrLen (*String) > 0) && (((*String)[StrLen ((*String))-1] == L' ') || ((*String)[StrLen ((*String))-1] == L'\t'))) {
106 (*String)[StrLen ((*String))-1] = CHAR_NULL;
107 }
108
109 return (EFI_SUCCESS);
110}
111
120CHAR16 *
122 IN CONST CHAR16 *SourceString,
123 IN CONST CHAR16 *FindString,
124 IN CONST BOOLEAN CheckForEscapeCharacter
125 )
126{
127 CHAR16 *Temp;
128
129 if (SourceString == NULL) {
130 return (NULL);
131 }
132
133 Temp = StrStr (SourceString, FindString);
134
135 //
136 // If nothing found, or we don't care about escape characters
137 //
138 if ((Temp == NULL) || !CheckForEscapeCharacter) {
139 return (Temp);
140 }
141
142 //
143 // If we found an escaped character, try again on the remainder of the string
144 //
145 if ((Temp > (SourceString)) && (*(Temp-1) == L'^')) {
146 return FindNextInstance (Temp+1, FindString, CheckForEscapeCharacter);
147 }
148
149 //
150 // we found the right character
151 //
152 return (Temp);
153}
154
164BOOLEAN
166 IN CONST CHAR16 *BeginPercent,
167 IN CONST CHAR16 *EndPercent
168 )
169{
170 CONST CHAR16 *Walker;
171
172 Walker = NULL;
173
174 ASSERT (BeginPercent != NULL);
175 ASSERT (EndPercent != NULL);
176 ASSERT (BeginPercent < EndPercent);
177
178 if ((BeginPercent + 1) == EndPercent) {
179 return FALSE;
180 }
181
182 for (Walker = BeginPercent + 1; Walker < EndPercent; Walker++) {
183 if (
184 ((*Walker >= L'0') && (*Walker <= L'9')) ||
185 ((*Walker >= L'A') && (*Walker <= L'Z')) ||
186 ((*Walker >= L'a') && (*Walker <= L'z')) ||
187 (*Walker == L'_')
188 )
189 {
190 if ((Walker == BeginPercent + 1) && ((*Walker >= L'0') && (*Walker <= L'9'))) {
191 return FALSE;
192 } else {
193 continue;
194 }
195 } else {
196 return FALSE;
197 }
198 }
199
200 return TRUE;
201}
202
211BOOLEAN
213 IN CONST CHAR16 *CmdLine
214 )
215{
216 CONST CHAR16 *TempSpot;
217 CONST CHAR16 *FirstQuote;
218 CONST CHAR16 *SecondQuote;
219
220 FirstQuote = FindNextInstance (CmdLine, L"\"", TRUE);
221 SecondQuote = NULL;
222 TempSpot = FindFirstCharacter (CmdLine, L"|", L'^');
223
224 if ((FirstQuote == NULL) ||
225 (TempSpot == NULL) ||
226 (TempSpot == CHAR_NULL) ||
227 (FirstQuote > TempSpot)
228 )
229 {
230 return (BOOLEAN)((TempSpot != NULL) && (*TempSpot != CHAR_NULL));
231 }
232
233 while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) {
234 if ((FirstQuote == NULL) || (FirstQuote > TempSpot)) {
235 break;
236 }
237
238 SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE);
239 if (SecondQuote == NULL) {
240 break;
241 }
242
243 if (SecondQuote < TempSpot) {
244 FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);
245 continue;
246 } else {
247 FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);
248 TempSpot = FindFirstCharacter (TempSpot + 1, L"|", L'^');
249 continue;
250 }
251 }
252
253 return (BOOLEAN)((TempSpot != NULL) && (*TempSpot != CHAR_NULL));
254}
255
265 VOID
266 )
267{
269 EFI_KEY_DATA KeyData;
270 EFI_STATUS Status;
271
272 Status = gBS->OpenProtocol (
274 &gEfiSimpleTextInputExProtocolGuid,
275 (VOID **)&SimpleEx,
277 NULL,
278 EFI_OPEN_PROTOCOL_GET_PROTOCOL
279 );
280 if (EFI_ERROR (Status)) {
282 -1,
283 -1,
284 NULL,
285 STRING_TOKEN (STR_SHELL_NO_IN_EX),
286 ShellInfoObject.HiiHandle
287 );
288 return (EFI_SUCCESS);
289 }
290
291 KeyData.KeyState.KeyToggleState = 0;
292 KeyData.Key.ScanCode = 0;
293 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
294 KeyData.Key.UnicodeChar = L's';
295
296 Status = SimpleEx->RegisterKeyNotify (
297 SimpleEx,
298 &KeyData,
300 &ShellInfoObject.CtrlSNotifyHandle1
301 );
302
303 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
304 if (!EFI_ERROR (Status)) {
305 Status = SimpleEx->RegisterKeyNotify (
306 SimpleEx,
307 &KeyData,
309 &ShellInfoObject.CtrlSNotifyHandle2
310 );
311 }
312
313 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
314 KeyData.Key.UnicodeChar = 19;
315
316 if (!EFI_ERROR (Status)) {
317 Status = SimpleEx->RegisterKeyNotify (
318 SimpleEx,
319 &KeyData,
321 &ShellInfoObject.CtrlSNotifyHandle3
322 );
323 }
324
325 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
326 if (!EFI_ERROR (Status)) {
327 Status = SimpleEx->RegisterKeyNotify (
328 SimpleEx,
329 &KeyData,
331 &ShellInfoObject.CtrlSNotifyHandle4
332 );
333 }
334
335 return (Status);
336}
337
349EFIAPI
351 IN EFI_HANDLE ImageHandle,
352 IN EFI_SYSTEM_TABLE *SystemTable
353 )
354{
355 EFI_STATUS Status;
356 CHAR16 *TempString;
357 UINTN Size;
358 EFI_HANDLE ConInHandle;
361
362 if (PcdGet8 (PcdShellSupportLevel) > 3) {
363 return (EFI_UNSUPPORTED);
364 }
365
366 //
367 // Clear the screen
368 //
369 Status = gST->ConOut->ClearScreen (gST->ConOut);
370 if (EFI_ERROR (Status)) {
371 return (Status);
372 }
373
374 //
375 // Populate the global structure from PCDs
376 //
377 ShellInfoObject.ImageDevPath = NULL;
378 ShellInfoObject.FileDevPath = NULL;
379 ShellInfoObject.PageBreakEnabled = PcdGetBool (PcdShellPageBreakDefault);
380 ShellInfoObject.ViewingSettings.InsertMode = PcdGetBool (PcdShellInsertModeDefault);
381 ShellInfoObject.LogScreenCount = PcdGet8 (PcdShellScreenLogCount);
382
383 //
384 // verify we dont allow for spec violation
385 //
386 ASSERT (ShellInfoObject.LogScreenCount >= 3);
387
388 //
389 // Initialize the LIST ENTRY objects...
390 //
391 InitializeListHead (&ShellInfoObject.BufferToFreeList.Link);
392 InitializeListHead (&ShellInfoObject.ViewingSettings.CommandHistory.Link);
393 InitializeListHead (&ShellInfoObject.SplitList.Link);
394
395 //
396 // Check PCDs for optional features that are not implemented yet.
397 //
398 if ( PcdGetBool (PcdShellSupportOldProtocols)
399 || !FeaturePcdGet (PcdShellRequireHiiPlatform)
400 || FeaturePcdGet (PcdShellSupportFrameworkHii)
401 )
402 {
403 return (EFI_UNSUPPORTED);
404 }
405
406 //
407 // turn off the watchdog timer
408 //
409 gBS->SetWatchdogTimer (0, 0, 0, NULL);
410
411 //
412 // install our console logger. This will keep a log of the output for back-browsing
413 //
414 Status = ConsoleLoggerInstall (ShellInfoObject.LogScreenCount, &ShellInfoObject.ConsoleInfo);
415 if (!EFI_ERROR (Status)) {
416 //
417 // Enable the cursor to be visible
418 //
419 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
420
421 //
422 // If supporting EFI 1.1 we need to install HII protocol
423 // only do this if PcdShellRequireHiiPlatform == FALSE
424 //
425 // remove EFI_UNSUPPORTED check above when complete.
427
428 //
429 // install our (solitary) HII package
430 //
431 ShellInfoObject.HiiHandle = HiiAddPackages (&gEfiCallerIdGuid, gImageHandle, ShellStrings, NULL);
432 if (ShellInfoObject.HiiHandle == NULL) {
433 if (PcdGetBool (PcdShellSupportFrameworkHii)) {
435 }
436
437 if (ShellInfoObject.HiiHandle == NULL) {
438 Status = EFI_NOT_STARTED;
439 goto FreeResources;
440 }
441 }
442
443 //
444 // create and install the EfiShellParametersProtocol
445 //
446 Status = CreatePopulateInstallShellParametersProtocol (&ShellInfoObject.NewShellParametersProtocol, &ShellInfoObject.RootShellInstance);
447 ASSERT_EFI_ERROR (Status);
448 ASSERT (ShellInfoObject.NewShellParametersProtocol != NULL);
449
450 //
451 // create and install the EfiShellProtocol
452 //
453 Status = CreatePopulateInstallShellProtocol (&ShellInfoObject.NewEfiShellProtocol);
454 ASSERT_EFI_ERROR (Status);
455 ASSERT (ShellInfoObject.NewEfiShellProtocol != NULL);
456
457 //
458 // Now initialize the shell library (it requires Shell Parameters protocol)
459 //
460 Status = ShellInitialize ();
461 ASSERT_EFI_ERROR (Status);
462
463 Status = CommandInit ();
464 ASSERT_EFI_ERROR (Status);
465
466 Status = ShellInitEnvVarList ();
467
468 //
469 // Check the command line
470 //
471 Status = ProcessCommandLine ();
472 if (EFI_ERROR (Status)) {
473 goto FreeResources;
474 }
475
476 //
477 // If shell support level is >= 1 create the mappings and paths
478 //
479 if (PcdGet8 (PcdShellSupportLevel) >= 1) {
481 }
482
483 //
484 // Set the environment variable for nesting support
485 //
486 Size = 0;
487 TempString = NULL;
488 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {
489 //
490 // No change. require nesting in Shell Protocol Execute()
491 //
493 &TempString,
494 &Size,
495 L"False",
496 0
497 );
498 } else {
500 &TempString,
501 &Size,
502 mNoNestingTrue,
503 0
504 );
505 }
506
507 Status = InternalEfiShellSetEnv (mNoNestingEnvVarName, TempString, TRUE);
508 SHELL_FREE_NON_NULL (TempString);
509 Size = 0;
510
511 //
512 // save the device path for the loaded image and the device path for the filepath (under loaded image)
513 // These are where to look for the startup.nsh file
514 //
515 Status = GetDevicePathsForImageAndFile (&ShellInfoObject.ImageDevPath, &ShellInfoObject.FileDevPath);
516 ASSERT_EFI_ERROR (Status);
517
518 //
519 // Display the version
520 //
521 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion) {
523 0,
525 NULL,
526 STRING_TOKEN (STR_VER_OUTPUT_MAIN_SHELL),
527 ShellInfoObject.HiiHandle,
528 SupportLevel[PcdGet8 (PcdShellSupportLevel)],
529 gEfiShellProtocol->MajorVersion,
530 gEfiShellProtocol->MinorVersion
531 );
532
534 -1,
535 -1,
536 NULL,
537 STRING_TOKEN (STR_VER_OUTPUT_MAIN_SUPPLIER),
538 ShellInfoObject.HiiHandle,
539 (CHAR16 *)PcdGetPtr (PcdShellSupplier)
540 );
541
543 -1,
544 -1,
545 NULL,
546 STRING_TOKEN (STR_VER_OUTPUT_MAIN_UEFI),
547 ShellInfoObject.HiiHandle,
548 (gST->Hdr.Revision&0xffff0000)>>16,
549 (gST->Hdr.Revision&0x0000ffff),
552 );
553 }
554
555 //
556 // Display the mapping
557 //
558 if ((PcdGet8 (PcdShellSupportLevel) >= 2) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) {
559 Status = RunCommand (L"map");
560 ASSERT_EFI_ERROR (Status);
561 }
562
563 //
564 // init all the built in alias'
565 //
566 Status = SetBuiltInAlias ();
567 ASSERT_EFI_ERROR (Status);
568
569 //
570 // Initialize environment variables
571 //
573 Status = InternalEfiShellSetEnv (L"profiles", ShellCommandGetProfileList (), TRUE);
574 ASSERT_EFI_ERROR (Status);
575 }
576
577 Size = 100;
578 TempString = AllocateZeroPool (Size);
579 if (TempString == NULL) {
580 ASSERT (TempString != NULL);
581 Status = EFI_OUT_OF_RESOURCES;
582 goto FreeResources;
583 }
584
585 UnicodeSPrint (TempString, Size, L"%d", PcdGet8 (PcdShellSupportLevel));
586 Status = InternalEfiShellSetEnv (L"uefishellsupport", TempString, TRUE);
587 ASSERT_EFI_ERROR (Status);
588
589 UnicodeSPrint (TempString, Size, L"%d.%d", ShellInfoObject.NewEfiShellProtocol->MajorVersion, ShellInfoObject.NewEfiShellProtocol->MinorVersion);
590 Status = InternalEfiShellSetEnv (L"uefishellversion", TempString, TRUE);
591 ASSERT_EFI_ERROR (Status);
592
593 UnicodeSPrint (TempString, Size, L"%d.%d", (gST->Hdr.Revision & 0xFFFF0000) >> 16, gST->Hdr.Revision & 0x0000FFFF);
594 Status = InternalEfiShellSetEnv (L"uefiversion", TempString, TRUE);
595 ASSERT_EFI_ERROR (Status);
596
597 FreePool (TempString);
598
599 if (!EFI_ERROR (Status)) {
600 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {
601 //
602 // Set up the event for CTRL-C monitoring...
603 //
604 Status = InernalEfiShellStartMonitor ();
605 }
606
607 if (!EFI_ERROR (Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
608 //
609 // Set up the event for CTRL-S monitoring...
610 //
612 }
613
614 if (!EFI_ERROR (Status) && ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
615 //
616 // close off the gST->ConIn
617 //
618 OldConIn = gST->ConIn;
619 ConInHandle = gST->ConsoleInHandle;
621 } else {
622 OldConIn = NULL;
623 ConInHandle = NULL;
624 }
625
626 if (!EFI_ERROR (Status) && (PcdGet8 (PcdShellSupportLevel) >= 1)) {
627 //
628 // process the startup script or launch the called app.
629 //
630 Status = DoStartupScript (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
631 }
632
633 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit () && ((PcdGet8 (PcdShellSupportLevel) >= 3) || PcdGetBool (PcdShellForceConsole)) && !EFI_ERROR (Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
634 //
635 // begin the UI waiting loop
636 //
637 do {
638 //
639 // clean out all the memory allocated for CONST <something> * return values
640 // between each shell prompt presentation
641 //
642 if (!IsListEmpty (&ShellInfoObject.BufferToFreeList.Link)) {
643 FreeBufferList (&ShellInfoObject.BufferToFreeList);
644 }
645
646 //
647 // Reset page break back to default.
648 //
649 ShellInfoObject.PageBreakEnabled = PcdGetBool (PcdShellPageBreakDefault);
650 ASSERT (ShellInfoObject.ConsoleInfo != NULL);
651 ShellInfoObject.ConsoleInfo->Enabled = TRUE;
652 ShellInfoObject.ConsoleInfo->RowCounter = 0;
653
654 //
655 // Display Prompt
656 //
657 Status = DoShellPrompt ();
658 } while (!ShellCommandGetExit ());
659 }
660
661 if ((OldConIn != NULL) && (ConInHandle != NULL)) {
663 gST->ConIn = OldConIn;
664 gST->ConsoleInHandle = ConInHandle;
665 }
666 }
667 }
668
669FreeResources:
670 //
671 // uninstall protocols / free memory / etc...
672 //
673 if (ShellInfoObject.UserBreakTimer != NULL) {
674 gBS->CloseEvent (ShellInfoObject.UserBreakTimer);
675 DEBUG_CODE (
676 ShellInfoObject.UserBreakTimer = NULL;
677 );
678 }
679
680 if (ShellInfoObject.ImageDevPath != NULL) {
681 FreePool (ShellInfoObject.ImageDevPath);
682 DEBUG_CODE (
683 ShellInfoObject.ImageDevPath = NULL;
684 );
685 }
686
687 if (ShellInfoObject.FileDevPath != NULL) {
688 FreePool (ShellInfoObject.FileDevPath);
689 DEBUG_CODE (
690 ShellInfoObject.FileDevPath = NULL;
691 );
692 }
693
694 if (ShellInfoObject.NewShellParametersProtocol != NULL) {
695 CleanUpShellParametersProtocol (ShellInfoObject.NewShellParametersProtocol);
696 DEBUG_CODE (
697 ShellInfoObject.NewShellParametersProtocol = NULL;
698 );
699 }
700
701 if (ShellInfoObject.NewEfiShellProtocol != NULL) {
702 if (ShellInfoObject.NewEfiShellProtocol->IsRootShell ()) {
704 }
705
706 CleanUpShellEnvironment (ShellInfoObject.NewEfiShellProtocol);
707 DEBUG_CODE (
708 ShellInfoObject.NewEfiShellProtocol = NULL;
709 );
710 }
711
712 if (!IsListEmpty (&ShellInfoObject.BufferToFreeList.Link)) {
713 FreeBufferList (&ShellInfoObject.BufferToFreeList);
714 }
715
716 if (!IsListEmpty (&ShellInfoObject.SplitList.Link)) {
717 ASSERT (FALSE);
718
719 for ( Split = (SPLIT_LIST *)GetFirstNode (&ShellInfoObject.SplitList.Link)
720 ; !IsNull (&ShellInfoObject.SplitList.Link, &Split->Link)
721 ; Split = (SPLIT_LIST *)GetNextNode (&ShellInfoObject.SplitList.Link, &Split->Link)
722 )
723 {
724 RemoveEntryList (&Split->Link);
725 FreePool (Split);
726 }
727
728 DEBUG_CODE (
729 InitializeListHead (&ShellInfoObject.SplitList.Link);
730 );
731 }
732
733 if (ShellInfoObject.ShellInitSettings.FileName != NULL) {
734 FreePool (ShellInfoObject.ShellInitSettings.FileName);
735 DEBUG_CODE (
736 ShellInfoObject.ShellInitSettings.FileName = NULL;
737 );
738 }
739
740 if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
741 FreePool (ShellInfoObject.ShellInitSettings.FileOptions);
742 DEBUG_CODE (
743 ShellInfoObject.ShellInitSettings.FileOptions = NULL;
744 );
745 }
746
747 if (ShellInfoObject.HiiHandle != NULL) {
748 HiiRemovePackages (ShellInfoObject.HiiHandle);
749 DEBUG_CODE (
750 ShellInfoObject.HiiHandle = NULL;
751 );
752 }
753
754 if (!IsListEmpty (&ShellInfoObject.ViewingSettings.CommandHistory.Link)) {
755 FreeBufferList (&ShellInfoObject.ViewingSettings.CommandHistory);
756 }
757
758 ASSERT (ShellInfoObject.ConsoleInfo != NULL);
759 if (ShellInfoObject.ConsoleInfo != NULL) {
760 ConsoleLoggerUninstall (ShellInfoObject.ConsoleInfo);
761 FreePool (ShellInfoObject.ConsoleInfo);
762 DEBUG_CODE (
763 ShellInfoObject.ConsoleInfo = NULL;
764 );
765 }
766
768
769 if (ShellCommandGetExit ()) {
771 }
772
773 return (Status);
774}
775
783 VOID
784 )
785{
786 EFI_STATUS Status;
787 CONST ALIAS_LIST *List;
788 ALIAS_LIST *Node;
789
790 //
791 // Get all the commands we want to run
792 //
794
795 //
796 // for each command in the List
797 //
798 for ( Node = (ALIAS_LIST *)GetFirstNode (&List->Link)
799 ; !IsNull (&List->Link, &Node->Link)
800 ; Node = (ALIAS_LIST *)GetNextNode (&List->Link, &Node->Link)
801 )
802 {
803 //
804 // install the alias'
805 //
806 Status = InternalSetAlias (Node->CommandString, Node->Alias, TRUE);
807 ASSERT_EFI_ERROR (Status);
808 }
809
810 return (EFI_SUCCESS);
811}
812
822BOOLEAN
824 IN CONST CHAR16 *Command1,
825 IN CONST CHAR16 *Command2
826 )
827{
828 if (StringNoCaseCompare (&Command1, &Command2) == 0) {
829 return (TRUE);
830 }
831
832 return (FALSE);
833}
834
843BOOLEAN
845 IN CONST CHAR16 *CommandName
846 )
847{
848 if ( IsCommand (CommandName, L"for")
849 || IsCommand (CommandName, L"endfor")
850 || IsCommand (CommandName, L"if")
851 || IsCommand (CommandName, L"else")
852 || IsCommand (CommandName, L"endif")
853 || IsCommand (CommandName, L"goto"))
854 {
855 return (TRUE);
856 }
857
858 return (FALSE);
859}
860
879 )
880{
881 EFI_STATUS Status;
882 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
883 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
884
885 ASSERT (DevPath != NULL);
886 ASSERT (FilePath != NULL);
887
888 Status = gBS->OpenProtocol (
890 &gEfiLoadedImageProtocolGuid,
891 (VOID **)&LoadedImage,
893 NULL,
894 EFI_OPEN_PROTOCOL_GET_PROTOCOL
895 );
896 if (!EFI_ERROR (Status)) {
897 Status = gBS->OpenProtocol (
898 LoadedImage->DeviceHandle,
899 &gEfiDevicePathProtocolGuid,
900 (VOID **)&ImageDevicePath,
902 NULL,
903 EFI_OPEN_PROTOCOL_GET_PROTOCOL
904 );
905 if (!EFI_ERROR (Status)) {
906 *DevPath = DuplicateDevicePath (ImageDevicePath);
907 *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
908 gBS->CloseProtocol (
909 LoadedImage->DeviceHandle,
910 &gEfiDevicePathProtocolGuid,
912 NULL
913 );
914 }
915
916 gBS->CloseProtocol (
918 &gEfiLoadedImageProtocolGuid,
920 NULL
921 );
922 }
923
924 return (Status);
925}
926
956 VOID
957 )
958{
959 UINTN Size;
960 UINTN LoopVar;
961 CHAR16 *CurrentArg;
962 CHAR16 *DelayValueStr;
963 UINT64 DelayValue;
964 EFI_STATUS Status;
965 EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation;
966
967 // `file-name-options` will contain arguments to `file-name` that we don't
968 // know about. This would cause ShellCommandLineParse to error, so we parse
969 // arguments manually, ignoring those after the first thing that doesn't look
970 // like a shell option (which is assumed to be `file-name`).
971
972 Status = gBS->LocateProtocol (
973 &gEfiUnicodeCollation2ProtocolGuid,
974 NULL,
975 (VOID **)&UnicodeCollation
976 );
977 if (EFI_ERROR (Status)) {
978 Status = gBS->LocateProtocol (
979 &gEfiUnicodeCollationProtocolGuid,
980 NULL,
981 (VOID **)&UnicodeCollation
982 );
983 if (EFI_ERROR (Status)) {
984 return Status;
985 }
986 }
987
988 // Set default options
989 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = FALSE;
990 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = FALSE;
991 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = FALSE;
992 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = FALSE;
993 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = FALSE;
994 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = FALSE;
995 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = FALSE;
996 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = FALSE;
997 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = FALSE;
998 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = FALSE;
999 ShellInfoObject.ShellInitSettings.Delay = PcdGet32 (PcdShellDefaultDelay);
1000
1001 //
1002 // Start LoopVar at 0 to parse only optional arguments at Argv[0]
1003 // and parse other parameters from Argv[1]. This is for use case that
1004 // UEFI Shell boot option is created, and OptionalData is provided
1005 // that starts with shell command-line options.
1006 //
1007 for (LoopVar = 0; LoopVar < gEfiShellParametersProtocol->Argc; LoopVar++) {
1008 CurrentArg = gEfiShellParametersProtocol->Argv[LoopVar];
1009 if (UnicodeCollation->StriColl (
1010 UnicodeCollation,
1011 L"-startup",
1012 CurrentArg
1013 ) == 0)
1014 {
1015 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = TRUE;
1016 } else if (UnicodeCollation->StriColl (
1017 UnicodeCollation,
1018 L"-nostartup",
1019 CurrentArg
1020 ) == 0)
1021 {
1022 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = TRUE;
1023 } else if (UnicodeCollation->StriColl (
1024 UnicodeCollation,
1025 L"-noconsoleout",
1026 CurrentArg
1027 ) == 0)
1028 {
1029 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = TRUE;
1030 } else if (UnicodeCollation->StriColl (
1031 UnicodeCollation,
1032 L"-noconsolein",
1033 CurrentArg
1034 ) == 0)
1035 {
1036 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = TRUE;
1037 } else if (UnicodeCollation->StriColl (
1038 UnicodeCollation,
1039 L"-nointerrupt",
1040 CurrentArg
1041 ) == 0)
1042 {
1043 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = TRUE;
1044 } else if (UnicodeCollation->StriColl (
1045 UnicodeCollation,
1046 L"-nomap",
1047 CurrentArg
1048 ) == 0)
1049 {
1050 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = TRUE;
1051 } else if (UnicodeCollation->StriColl (
1052 UnicodeCollation,
1053 L"-noversion",
1054 CurrentArg
1055 ) == 0)
1056 {
1057 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = TRUE;
1058 } else if (UnicodeCollation->StriColl (
1059 UnicodeCollation,
1060 L"-nonest",
1061 CurrentArg
1062 ) == 0)
1063 {
1064 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = TRUE;
1065 } else if (UnicodeCollation->StriColl (
1066 UnicodeCollation,
1067 L"-delay",
1068 CurrentArg
1069 ) == 0)
1070 {
1071 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = TRUE;
1072 // Check for optional delay value following "-delay"
1073 if ((LoopVar + 1) >= gEfiShellParametersProtocol->Argc) {
1074 DelayValueStr = NULL;
1075 } else {
1076 DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1];
1077 }
1078
1079 if (DelayValueStr != NULL) {
1080 if (*DelayValueStr == L':') {
1081 DelayValueStr++;
1082 }
1083
1084 if (!EFI_ERROR (
1086 DelayValueStr,
1087 &DelayValue,
1088 FALSE,
1089 FALSE
1090 )
1091 ))
1092 {
1093 ShellInfoObject.ShellInitSettings.Delay = (UINTN)DelayValue;
1094 LoopVar++;
1095 }
1096 }
1097 } else if (UnicodeCollation->StriColl (
1098 UnicodeCollation,
1099 L"-exit",
1100 CurrentArg
1101 ) == 0)
1102 {
1103 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = TRUE;
1104 } else if (StrnCmp (L"-", CurrentArg, 1) == 0) {
1105 // Unrecognized option
1107 -1,
1108 -1,
1109 NULL,
1110 STRING_TOKEN (STR_GEN_PROBLEM),
1111 ShellInfoObject.HiiHandle,
1112 CurrentArg
1113 );
1114 return EFI_INVALID_PARAMETER;
1115 } else {
1116 //
1117 // First argument should be Shell.efi image name
1118 //
1119 if (LoopVar == 0) {
1120 continue;
1121 }
1122
1123 ShellInfoObject.ShellInitSettings.FileName = NULL;
1124 Size = 0;
1125 //
1126 // If first argument contains a space, then add double quotes before the argument
1127 //
1128 if (StrStr (CurrentArg, L" ") != NULL) {
1129 StrnCatGrow (&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0);
1130 if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
1131 return (EFI_OUT_OF_RESOURCES);
1132 }
1133 }
1134
1135 StrnCatGrow (&ShellInfoObject.ShellInitSettings.FileName, &Size, CurrentArg, 0);
1136 if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
1137 return (EFI_OUT_OF_RESOURCES);
1138 }
1139
1140 //
1141 // If first argument contains a space, then add double quotes after the argument
1142 //
1143 if (StrStr (CurrentArg, L" ") != NULL) {
1144 StrnCatGrow (&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0);
1145 if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
1146 return (EFI_OUT_OF_RESOURCES);
1147 }
1148 }
1149
1150 //
1151 // We found `file-name`.
1152 //
1153 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1;
1154 LoopVar++;
1155
1156 // Add `file-name-options`
1157 for (Size = 0; LoopVar < gEfiShellParametersProtocol->Argc; LoopVar++) {
1158 ASSERT ((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL));
1159 //
1160 // Add a space between arguments
1161 //
1162 if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
1163 StrnCatGrow (&ShellInfoObject.ShellInitSettings.FileOptions, &Size, L" ", 0);
1164 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
1165 SHELL_FREE_NON_NULL (ShellInfoObject.ShellInitSettings.FileName);
1166 return (EFI_OUT_OF_RESOURCES);
1167 }
1168 }
1169
1170 //
1171 // If an argument contains a space, then add double quotes before the argument
1172 //
1173 if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {
1174 StrnCatGrow (
1175 &ShellInfoObject.ShellInitSettings.FileOptions,
1176 &Size,
1177 L"\"",
1178 0
1179 );
1180 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
1181 SHELL_FREE_NON_NULL (ShellInfoObject.ShellInitSettings.FileName);
1182 return (EFI_OUT_OF_RESOURCES);
1183 }
1184 }
1185
1186 StrnCatGrow (
1187 &ShellInfoObject.ShellInitSettings.FileOptions,
1188 &Size,
1189 gEfiShellParametersProtocol->Argv[LoopVar],
1190 0
1191 );
1192 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
1193 SHELL_FREE_NON_NULL (ShellInfoObject.ShellInitSettings.FileName);
1194 return (EFI_OUT_OF_RESOURCES);
1195 }
1196
1197 //
1198 // If an argument contains a space, then add double quotes after the argument
1199 //
1200 if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {
1201 StrnCatGrow (
1202 &ShellInfoObject.ShellInitSettings.FileOptions,
1203 &Size,
1204 L"\"",
1205 0
1206 );
1207 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
1208 SHELL_FREE_NON_NULL (ShellInfoObject.ShellInitSettings.FileName);
1209 return (EFI_OUT_OF_RESOURCES);
1210 }
1211 }
1212 }
1213 }
1214 }
1215
1216 // "-nointerrupt" overrides "-delay"
1217 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {
1218 ShellInfoObject.ShellInitSettings.Delay = 0;
1219 }
1220
1221 return EFI_SUCCESS;
1222}
1223
1235CHAR16 *
1237 IN EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,
1239 )
1240{
1241 CHAR16 *StartupScriptPath;
1242 CHAR16 *TempSpot;
1243 CONST CHAR16 *MapName;
1244 UINTN Size;
1245
1246 StartupScriptPath = NULL;
1247 Size = 0;
1248
1249 //
1250 // Try to find 'Startup.nsh' in the directory where the shell itself was launched.
1251 //
1252 MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath (&ImageDevicePath);
1253 if (MapName != NULL) {
1254 StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, MapName, 0);
1255 if (StartupScriptPath == NULL) {
1256 //
1257 // Do not locate the startup script in sys path when out of resource.
1258 //
1259 return NULL;
1260 }
1261
1262 TempSpot = StrStr (StartupScriptPath, L";");
1263 if (TempSpot != NULL) {
1264 *TempSpot = CHAR_NULL;
1265 }
1266
1267 InternalEfiShellSetEnv (L"homefilesystem", StartupScriptPath, TRUE);
1268
1269 StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, ((FILEPATH_DEVICE_PATH *)FileDevicePath)->PathName, 0);
1270 PathRemoveLastItem (StartupScriptPath);
1271 StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, mStartupScript, 0);
1272 }
1273
1274 //
1275 // Try to find 'Startup.nsh' in the execution path defined by the environment variable PATH.
1276 //
1277 if ((StartupScriptPath == NULL) || EFI_ERROR (ShellIsFile (StartupScriptPath))) {
1278 SHELL_FREE_NON_NULL (StartupScriptPath);
1279 StartupScriptPath = ShellFindFilePath (mStartupScript);
1280 }
1281
1282 return StartupScriptPath;
1283}
1284
1297 IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,
1299 )
1300{
1301 EFI_STATUS Status;
1302 EFI_STATUS CalleeStatus;
1303 UINTN Delay;
1304 EFI_INPUT_KEY Key;
1305 CHAR16 *FileStringPath;
1306 CHAR16 *FullFileStringPath;
1307 UINTN NewSize;
1308
1309 CalleeStatus = EFI_SUCCESS;
1310 Key.UnicodeChar = CHAR_NULL;
1311 Key.ScanCode = 0;
1312
1313 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup && (ShellInfoObject.ShellInitSettings.FileName != NULL)) {
1314 //
1315 // launch something else instead
1316 //
1317 NewSize = StrSize (ShellInfoObject.ShellInitSettings.FileName);
1318 if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
1319 NewSize += StrSize (ShellInfoObject.ShellInitSettings.FileOptions) + sizeof (CHAR16);
1320 }
1321
1322 FileStringPath = AllocateZeroPool (NewSize);
1323 if (FileStringPath == NULL) {
1324 return (EFI_OUT_OF_RESOURCES);
1325 }
1326
1327 StrCpyS (FileStringPath, NewSize/sizeof (CHAR16), ShellInfoObject.ShellInitSettings.FileName);
1328 if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
1329 StrnCatS (FileStringPath, NewSize/sizeof (CHAR16), L" ", NewSize/sizeof (CHAR16) - StrLen (FileStringPath) -1);
1330 StrnCatS (FileStringPath, NewSize/sizeof (CHAR16), ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof (CHAR16) - StrLen (FileStringPath) -1);
1331 }
1332
1333 Status = RunShellCommand (FileStringPath, &CalleeStatus);
1334 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) {
1335 ShellCommandRegisterExit (gEfiShellProtocol->BatchIsActive (), (UINT64)CalleeStatus);
1336 }
1337
1338 FreePool (FileStringPath);
1339 return (Status);
1340 }
1341
1342 //
1343 // for shell level 0 we do no scripts
1344 // Without the Startup bit overriding we allow for nostartup to prevent scripts
1345 //
1346 if ( (PcdGet8 (PcdShellSupportLevel) < 1)
1347 || (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup)
1348 )
1349 {
1350 return (EFI_SUCCESS);
1351 }
1352
1353 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
1354 //
1355 // print out our warning and see if they press a key
1356 //
1357 for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay
1358 ; Delay != 0 && EFI_ERROR (Status)
1359 ; Delay--
1360 )
1361 {
1362 ShellPrintHiiEx (0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay);
1363 gBS->Stall (1000000);
1364 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
1365 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1366 }
1367 }
1368
1369 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle);
1370 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
1371
1372 //
1373 // ESC was pressed
1374 //
1375 if ((Status == EFI_SUCCESS) && (Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_ESC)) {
1376 return (EFI_SUCCESS);
1377 }
1378
1379 FileStringPath = LocateStartupScript (ImagePath, FilePath);
1380 if (FileStringPath != NULL) {
1381 FullFileStringPath = FullyQualifyPath (FileStringPath);
1382 if (FullFileStringPath == NULL) {
1383 Status = RunScriptFile (FileStringPath, NULL, FileStringPath, ShellInfoObject.NewShellParametersProtocol);
1384 } else {
1385 Status = RunScriptFile (FullFileStringPath, NULL, FullFileStringPath, ShellInfoObject.NewShellParametersProtocol);
1386 FreePool (FullFileStringPath);
1387 }
1388
1389 FreePool (FileStringPath);
1390 } else {
1391 //
1392 // we return success since startup script is not mandatory.
1393 //
1394 Status = EFI_SUCCESS;
1395 }
1396
1397 return (Status);
1398}
1399
1410 VOID
1411 )
1412{
1413 UINTN Column;
1414 UINTN Row;
1415 CHAR16 *CmdLine;
1416 CONST CHAR16 *CurDir;
1417 UINTN BufferSize;
1418 EFI_STATUS Status;
1419 LIST_ENTRY OldBufferList;
1420
1421 CurDir = NULL;
1422
1423 //
1424 // Get screen setting to decide size of the command line buffer
1425 //
1426 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Column, &Row);
1427 BufferSize = Column * Row * sizeof (CHAR16);
1428 CmdLine = AllocateZeroPool (BufferSize);
1429 if (CmdLine == NULL) {
1430 return EFI_OUT_OF_RESOURCES;
1431 }
1432
1433 SaveBufferList (&OldBufferList);
1434 CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv (L"cwd");
1435
1436 //
1437 // Prompt for input
1438 //
1439 gST->ConOut->SetCursorPosition (gST->ConOut, 0, gST->ConOut->Mode->CursorRow);
1440
1441 if ((CurDir != NULL) && (StrLen (CurDir) > 1)) {
1442 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);
1443 } else {
1444 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);
1445 }
1446
1447 //
1448 // Read a line from the console
1449 //
1450 Status = ShellInfoObject.NewEfiShellProtocol->ReadFile (ShellInfoObject.NewShellParametersProtocol->StdIn, &BufferSize, CmdLine);
1451
1452 //
1453 // Null terminate the string and parse it
1454 //
1455 if (!EFI_ERROR (Status)) {
1456 //
1457 // Reset the CTRL-C event just before running the command (yes we ignore the return values)
1458 //
1459 Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);
1460
1461 CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;
1462 Status = RunCommand (CmdLine);
1463 }
1464
1465 //
1466 // Done with this command
1467 //
1468 RestoreBufferList (&OldBufferList);
1469 FreePool (CmdLine);
1470 return Status;
1471}
1472
1479VOID *
1481 VOID *Buffer
1482 )
1483{
1484 BUFFER_LIST *BufferListEntry;
1485
1486 if (Buffer == NULL) {
1487 return (NULL);
1488 }
1489
1490 BufferListEntry = AllocateZeroPool (sizeof (BUFFER_LIST));
1491 if (BufferListEntry == NULL) {
1492 return NULL;
1493 }
1494
1495 BufferListEntry->Buffer = Buffer;
1496 InsertTailList (&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);
1497 return (Buffer);
1498}
1499
1505VOID
1507 OUT LIST_ENTRY *OldBufferList
1508 )
1509{
1510 CopyMem (OldBufferList, &ShellInfoObject.BufferToFreeList.Link, sizeof (LIST_ENTRY));
1511 InitializeListHead (&ShellInfoObject.BufferToFreeList.Link);
1512}
1513
1519VOID
1521 IN OUT LIST_ENTRY *OldBufferList
1522 )
1523{
1524 FreeBufferList (&ShellInfoObject.BufferToFreeList);
1525 CopyMem (&ShellInfoObject.BufferToFreeList.Link, OldBufferList, sizeof (LIST_ENTRY));
1526}
1527
1533VOID
1535 IN CONST CHAR16 *Buffer
1536 )
1537{
1538 BUFFER_LIST *Node;
1539 BUFFER_LIST *Walker;
1540 UINT16 MaxHistoryCmdCount;
1541 UINT16 Count;
1542
1543 Count = 0;
1544 MaxHistoryCmdCount = PcdGet16 (PcdShellMaxHistoryCommandCount);
1545
1546 if (MaxHistoryCmdCount == 0) {
1547 return;
1548 }
1549
1550 Node = AllocateZeroPool (sizeof (BUFFER_LIST));
1551 if (Node == NULL) {
1552 return;
1553 }
1554
1555 Node->Buffer = AllocateCopyPool (StrSize (Buffer), Buffer);
1556 if (Node->Buffer == NULL) {
1557 FreePool (Node);
1558 return;
1559 }
1560
1561 for ( Walker = (BUFFER_LIST *)GetFirstNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link)
1562 ; !IsNull (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)
1563 ; Walker = (BUFFER_LIST *)GetNextNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)
1564 )
1565 {
1566 Count++;
1567 }
1568
1569 if (Count < MaxHistoryCmdCount) {
1570 InsertTailList (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);
1571 } else {
1572 Walker = (BUFFER_LIST *)GetFirstNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link);
1573 RemoveEntryList (&Walker->Link);
1574 if (Walker->Buffer != NULL) {
1575 FreePool (Walker->Buffer);
1576 }
1577
1578 FreePool (Walker);
1579 InsertTailList (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);
1580 }
1581}
1582
1598 IN OUT CHAR16 **CommandString
1599 )
1600{
1601 CONST CHAR16 *NewString;
1602
1603 NewString = ShellInfoObject.NewEfiShellProtocol->GetAlias (*CommandString, NULL);
1604 if (NewString == NULL) {
1605 return (EFI_SUCCESS);
1606 }
1607
1608 FreePool (*CommandString);
1609 *CommandString = AllocateCopyPool (StrSize (NewString), NewString);
1610 if (*CommandString == NULL) {
1611 return (EFI_OUT_OF_RESOURCES);
1612 }
1613
1614 return (EFI_SUCCESS);
1615}
1616
1624 IN OUT CHAR16 *CmdLine
1625 )
1626{
1627 CHAR16 *FirstPercent;
1628 CHAR16 *FirstQuote;
1629 CHAR16 *SecondPercent;
1630 CHAR16 *SecondQuote;
1631 CHAR16 *CurrentLocator;
1632
1633 for (CurrentLocator = CmdLine; CurrentLocator != NULL; ) {
1634 FirstQuote = FindNextInstance (CurrentLocator, L"\"", TRUE);
1635 FirstPercent = FindNextInstance (CurrentLocator, L"%", TRUE);
1636 SecondPercent = FirstPercent != NULL ? FindNextInstance (FirstPercent+1, L"%", TRUE) : NULL;
1637 if ((FirstPercent == NULL) || (SecondPercent == NULL)) {
1638 //
1639 // If we ever don't have 2 % we are done.
1640 //
1641 break;
1642 }
1643
1644 if ((FirstQuote != NULL) && (FirstQuote < FirstPercent)) {
1645 SecondQuote = FindNextInstance (FirstQuote+1, L"\"", TRUE);
1646 //
1647 // Quote is first found
1648 //
1649
1650 if (SecondQuote < FirstPercent) {
1651 //
1652 // restart after the pair of "
1653 //
1654 CurrentLocator = SecondQuote + 1;
1655 } else {
1656 /* FirstPercent < SecondQuote */
1657 //
1658 // Restart on the first percent
1659 //
1660 CurrentLocator = FirstPercent;
1661 }
1662
1663 continue;
1664 }
1665
1666 if ((FirstQuote == NULL) || (SecondPercent < FirstQuote)) {
1667 if (IsValidEnvironmentVariableName (FirstPercent, SecondPercent)) {
1668 //
1669 // We need to remove from FirstPercent to SecondPercent
1670 //
1671 CopyMem (FirstPercent, SecondPercent + 1, StrSize (SecondPercent + 1));
1672 //
1673 // don't need to update the locator. both % characters are gone.
1674 //
1675 } else {
1676 CurrentLocator = SecondPercent + 1;
1677 }
1678
1679 continue;
1680 }
1681
1682 CurrentLocator = FirstQuote;
1683 }
1684
1685 return (EFI_SUCCESS);
1686}
1687
1699CHAR16 *
1701 IN CONST CHAR16 *OriginalCommandLine
1702 )
1703{
1704 CONST CHAR16 *MasterEnvList;
1705 UINTN NewSize;
1706 CHAR16 *NewCommandLine1;
1707 CHAR16 *NewCommandLine2;
1708 CHAR16 *Temp;
1709 UINTN ItemSize;
1710 CHAR16 *ItemTemp;
1711 SCRIPT_FILE *CurrentScriptFile;
1712 ALIAS_LIST *AliasListNode;
1713
1714 ASSERT (OriginalCommandLine != NULL);
1715
1716 ItemSize = 0;
1717 NewSize = StrSize (OriginalCommandLine);
1718 CurrentScriptFile = ShellCommandGetCurrentScriptFile ();
1719 Temp = NULL;
1720
1722
1723 //
1724 // calculate the size required for the post-conversion string...
1725 //
1726 if (CurrentScriptFile != NULL) {
1727 for (AliasListNode = (ALIAS_LIST *)GetFirstNode (&CurrentScriptFile->SubstList)
1728 ; !IsNull (&CurrentScriptFile->SubstList, &AliasListNode->Link)
1729 ; AliasListNode = (ALIAS_LIST *)GetNextNode (&CurrentScriptFile->SubstList, &AliasListNode->Link)
1730 )
1731 {
1732 for (Temp = StrStr (OriginalCommandLine, AliasListNode->Alias)
1733 ; Temp != NULL
1734 ; Temp = StrStr (Temp+1, AliasListNode->Alias)
1735 )
1736 {
1737 //
1738 // we need a preceding and if there is space no ^ preceding (if no space ignore)
1739 //
1740 if ((((Temp-OriginalCommandLine) > 2) && (*(Temp-2) != L'^')) || ((Temp-OriginalCommandLine) <= 2)) {
1741 NewSize += StrSize (AliasListNode->CommandString);
1742 }
1743 }
1744 }
1745 }
1746
1747 for (MasterEnvList = EfiShellGetEnv (NULL)
1748 ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL // && *(MasterEnvList+1) != CHAR_NULL
1749 ; MasterEnvList += StrLen (MasterEnvList) + 1
1750 )
1751 {
1752 if (StrSize (MasterEnvList) > ItemSize) {
1753 ItemSize = StrSize (MasterEnvList);
1754 }
1755
1756 for (Temp = StrStr (OriginalCommandLine, MasterEnvList)
1757 ; Temp != NULL
1758 ; Temp = StrStr (Temp+1, MasterEnvList)
1759 )
1760 {
1761 //
1762 // we need a preceding and following % and if there is space no ^ preceding (if no space ignore)
1763 //
1764 if ((*(Temp-1) == L'%') && (*(Temp+StrLen (MasterEnvList)) == L'%') &&
1765 ((((Temp-OriginalCommandLine) > 2) && (*(Temp-2) != L'^')) || ((Temp-OriginalCommandLine) <= 2)))
1766 {
1767 NewSize += StrSize (EfiShellGetEnv (MasterEnvList));
1768 }
1769 }
1770 }
1771
1772 //
1773 // now do the replacements...
1774 //
1775 NewCommandLine1 = AllocateZeroPool (NewSize);
1776 NewCommandLine2 = AllocateZeroPool (NewSize);
1777 ItemTemp = AllocateZeroPool (ItemSize+(2*sizeof (CHAR16)));
1778 if ((NewCommandLine1 == NULL) || (NewCommandLine2 == NULL) || (ItemTemp == NULL)) {
1779 SHELL_FREE_NON_NULL (NewCommandLine1);
1780 SHELL_FREE_NON_NULL (NewCommandLine2);
1781 SHELL_FREE_NON_NULL (ItemTemp);
1782 return (NULL);
1783 }
1784
1785 CopyMem (NewCommandLine1, OriginalCommandLine, StrSize (OriginalCommandLine));
1786
1787 for (MasterEnvList = EfiShellGetEnv (NULL)
1788 ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL
1789 ; MasterEnvList += StrLen (MasterEnvList) + 1
1790 )
1791 {
1792 StrCpyS (
1793 ItemTemp,
1794 ((ItemSize+(2*sizeof (CHAR16)))/sizeof (CHAR16)),
1795 L"%"
1796 );
1797 StrCatS (
1798 ItemTemp,
1799 ((ItemSize+(2*sizeof (CHAR16)))/sizeof (CHAR16)),
1800 MasterEnvList
1801 );
1802 StrCatS (
1803 ItemTemp,
1804 ((ItemSize+(2*sizeof (CHAR16)))/sizeof (CHAR16)),
1805 L"%"
1806 );
1807 ShellCopySearchAndReplace (NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv (MasterEnvList), TRUE, FALSE);
1808 StrCpyS (NewCommandLine1, NewSize/sizeof (CHAR16), NewCommandLine2);
1809 }
1810
1811 if (CurrentScriptFile != NULL) {
1812 for (AliasListNode = (ALIAS_LIST *)GetFirstNode (&CurrentScriptFile->SubstList)
1813 ; !IsNull (&CurrentScriptFile->SubstList, &AliasListNode->Link)
1814 ; AliasListNode = (ALIAS_LIST *)GetNextNode (&CurrentScriptFile->SubstList, &AliasListNode->Link)
1815 )
1816 {
1817 ShellCopySearchAndReplace (NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);
1818 StrCpyS (NewCommandLine1, NewSize/sizeof (CHAR16), NewCommandLine2);
1819 }
1820 }
1821
1822 //
1823 // Remove non-existent environment variables
1824 //
1825 StripUnreplacedEnvironmentVariables (NewCommandLine1);
1826
1827 //
1828 // Now cleanup any straggler intentionally ignored "%" characters
1829 //
1830 ShellCopySearchAndReplace (NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);
1831 StrCpyS (NewCommandLine1, NewSize/sizeof (CHAR16), NewCommandLine2);
1832
1833 FreePool (NewCommandLine2);
1834 FreePool (ItemTemp);
1835
1836 return (NewCommandLine1);
1837}
1838
1851 IN CONST CHAR16 *CmdLine,
1852 IN SHELL_FILE_HANDLE StdIn,
1853 IN SHELL_FILE_HANDLE StdOut
1854 )
1855{
1856 EFI_STATUS Status;
1857 CHAR16 *NextCommandLine;
1858 CHAR16 *OurCommandLine;
1859 UINTN Size1;
1860 UINTN Size2;
1862 SHELL_FILE_HANDLE TempFileHandle;
1863 BOOLEAN Unicode;
1864
1865 ASSERT (StdOut == NULL);
1866
1867 ASSERT (StrStr (CmdLine, L"|") != NULL);
1868
1869 Status = EFI_SUCCESS;
1870 NextCommandLine = NULL;
1871 OurCommandLine = NULL;
1872 Size1 = 0;
1873 Size2 = 0;
1874
1875 NextCommandLine = StrnCatGrow (&NextCommandLine, &Size1, StrStr (CmdLine, L"|")+1, 0);
1876 OurCommandLine = StrnCatGrow (&OurCommandLine, &Size2, CmdLine, StrStr (CmdLine, L"|") - CmdLine);
1877
1878 if ((NextCommandLine == NULL) || (OurCommandLine == NULL)) {
1879 SHELL_FREE_NON_NULL (OurCommandLine);
1880 SHELL_FREE_NON_NULL (NextCommandLine);
1881 return (EFI_OUT_OF_RESOURCES);
1882 } else if ((StrStr (OurCommandLine, L"|") != NULL) || (Size1 == 0) || (Size2 == 0)) {
1883 SHELL_FREE_NON_NULL (OurCommandLine);
1884 SHELL_FREE_NON_NULL (NextCommandLine);
1885 return (EFI_INVALID_PARAMETER);
1886 } else if ((NextCommandLine[0] == L'a') &&
1887 ((NextCommandLine[1] == L' ') || (NextCommandLine[1] == CHAR_NULL))
1888 )
1889 {
1890 CopyMem (NextCommandLine, NextCommandLine+1, StrSize (NextCommandLine) - sizeof (NextCommandLine[0]));
1891 while (NextCommandLine[0] == L' ') {
1892 CopyMem (NextCommandLine, NextCommandLine+1, StrSize (NextCommandLine) - sizeof (NextCommandLine[0]));
1893 }
1894
1895 if (NextCommandLine[0] == CHAR_NULL) {
1896 SHELL_FREE_NON_NULL (OurCommandLine);
1897 SHELL_FREE_NON_NULL (NextCommandLine);
1898 return (EFI_INVALID_PARAMETER);
1899 }
1900
1901 Unicode = FALSE;
1902 } else {
1903 Unicode = TRUE;
1904 }
1905
1906 //
1907 // make a SPLIT_LIST item and add to list
1908 //
1909 Split = AllocateZeroPool (sizeof (SPLIT_LIST));
1910 if (Split == NULL) {
1911 return EFI_OUT_OF_RESOURCES;
1912 }
1913
1914 Split->SplitStdIn = StdIn;
1916 ASSERT (Split->SplitStdOut != NULL);
1917 InsertHeadList (&ShellInfoObject.SplitList.Link, &Split->Link);
1918
1919 Status = RunCommand (OurCommandLine);
1920
1921 //
1922 // move the output from the first to the in to the second.
1923 //
1924 TempFileHandle = Split->SplitStdOut;
1925 if (Split->SplitStdIn == StdIn) {
1926 Split->SplitStdOut = NULL;
1927 } else {
1928 Split->SplitStdOut = Split->SplitStdIn;
1929 }
1930
1931 Split->SplitStdIn = TempFileHandle;
1932 ShellInfoObject.NewEfiShellProtocol->SetFilePosition (Split->SplitStdIn, 0);
1933
1934 if (!EFI_ERROR (Status)) {
1935 Status = RunCommand (NextCommandLine);
1936 }
1937
1938 //
1939 // remove the top level from the ScriptList
1940 //
1941 ASSERT ((SPLIT_LIST *)GetFirstNode (&ShellInfoObject.SplitList.Link) == Split);
1942 RemoveEntryList (&Split->Link);
1943
1944 //
1945 // Note that the original StdIn is now the StdOut...
1946 //
1947 if (Split->SplitStdOut != NULL) {
1948 ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdOut);
1949 }
1950
1951 if (Split->SplitStdIn != NULL) {
1952 ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdIn);
1953 }
1954
1955 FreePool (Split);
1956 FreePool (NextCommandLine);
1957 FreePool (OurCommandLine);
1958
1959 return (Status);
1960}
1961
1973 IN CHAR16 **CmdLine
1974 )
1975{
1976 CHAR16 *NewCmdLine;
1977
1978 NewCmdLine = ShellConvertVariables (*CmdLine);
1979 SHELL_FREE_NON_NULL (*CmdLine);
1980 if (NewCmdLine == NULL) {
1981 return (EFI_OUT_OF_RESOURCES);
1982 }
1983
1984 *CmdLine = NewCmdLine;
1985 return (EFI_SUCCESS);
1986}
1987
1999 IN CHAR16 **CmdLine
2000 )
2001{
2002 CHAR16 *NewCmdLine;
2003 CHAR16 *CommandName;
2004 EFI_STATUS Status;
2005 UINTN PostAliasSize;
2006
2007 ASSERT (CmdLine != NULL);
2008 ASSERT (*CmdLine != NULL);
2009
2010 CommandName = NULL;
2011 if (StrStr ((*CmdLine), L" ") == NULL) {
2012 StrnCatGrow (&CommandName, NULL, (*CmdLine), 0);
2013 } else {
2014 StrnCatGrow (&CommandName, NULL, (*CmdLine), StrStr ((*CmdLine), L" ") - (*CmdLine));
2015 }
2016
2017 //
2018 // This cannot happen 'inline' since the CmdLine can need extra space.
2019 //
2020 NewCmdLine = NULL;
2021 if (!ShellCommandIsCommandOnList (CommandName)) {
2022 //
2023 // Convert via alias
2024 //
2025 Status = ShellConvertAlias (&CommandName);
2026 if (EFI_ERROR (Status)) {
2027 return (Status);
2028 }
2029
2030 PostAliasSize = 0;
2031 NewCmdLine = StrnCatGrow (&NewCmdLine, &PostAliasSize, CommandName, 0);
2032 if (NewCmdLine == NULL) {
2033 SHELL_FREE_NON_NULL (CommandName);
2034 SHELL_FREE_NON_NULL (*CmdLine);
2035 return (EFI_OUT_OF_RESOURCES);
2036 }
2037
2038 NewCmdLine = StrnCatGrow (&NewCmdLine, &PostAliasSize, StrStr ((*CmdLine), L" "), 0);
2039 if (NewCmdLine == NULL) {
2040 SHELL_FREE_NON_NULL (CommandName);
2041 SHELL_FREE_NON_NULL (*CmdLine);
2042 return (EFI_OUT_OF_RESOURCES);
2043 }
2044 } else {
2045 NewCmdLine = StrnCatGrow (&NewCmdLine, NULL, (*CmdLine), 0);
2046 }
2047
2048 SHELL_FREE_NON_NULL (*CmdLine);
2049 SHELL_FREE_NON_NULL (CommandName);
2050
2051 //
2052 // re-assign the passed in double pointer to point to our newly allocated buffer
2053 //
2054 *CmdLine = NewCmdLine;
2055
2056 return (EFI_SUCCESS);
2057}
2058
2070SHELL_OPERATION_TYPES
2072 IN CONST CHAR16 *CmdName
2073 )
2074{
2075 CHAR16 *FileWithPath;
2076 CONST CHAR16 *TempLocation;
2077 CONST CHAR16 *TempLocation2;
2078
2079 FileWithPath = NULL;
2080 //
2081 // test for an internal command.
2082 //
2083 if (ShellCommandIsCommandOnList (CmdName)) {
2084 return (Internal_Command);
2085 }
2086
2087 //
2088 // Test for file system change request. anything ending with first : and cant have spaces.
2089 //
2090 if (CmdName[(StrLen (CmdName)-1)] == L':') {
2091 if ( (StrStr (CmdName, L" ") != NULL)
2092 || (StrLen (StrStr (CmdName, L":")) > 1)
2093 )
2094 {
2095 return (Unknown_Invalid);
2096 }
2097
2098 return (File_Sys_Change);
2099 }
2100
2101 //
2102 // Test for a file
2103 //
2104 if ((FileWithPath = ShellFindFilePathEx (CmdName, mExecutableExtensions)) != NULL) {
2105 //
2106 // See if that file has a script file extension
2107 //
2108 if (StrLen (FileWithPath) > 4) {
2109 TempLocation = FileWithPath+StrLen (FileWithPath)-4;
2110 TempLocation2 = mScriptExtension;
2111 if (StringNoCaseCompare ((VOID *)(&TempLocation), (VOID *)(&TempLocation2)) == 0) {
2112 SHELL_FREE_NON_NULL (FileWithPath);
2113 return (Script_File_Name);
2114 }
2115 }
2116
2117 //
2118 // Was a file, but not a script. we treat this as an application.
2119 //
2120 SHELL_FREE_NON_NULL (FileWithPath);
2121 return (Efi_Application);
2122 }
2123
2124 SHELL_FREE_NON_NULL (FileWithPath);
2125 //
2126 // No clue what this is... return invalid flag...
2127 //
2128 return (Unknown_Invalid);
2129}
2130
2142 IN CONST CHAR16 *CmdLine
2143 )
2144{
2145 CHAR16 *Temp;
2146 CHAR16 *FirstParameter;
2147 CHAR16 *TempWalker;
2148 EFI_STATUS Status;
2149
2150 Temp = NULL;
2151
2152 Temp = StrnCatGrow (&Temp, NULL, CmdLine, 0);
2153 if (Temp == NULL) {
2154 return (EFI_OUT_OF_RESOURCES);
2155 }
2156
2157 FirstParameter = StrStr (Temp, L"|");
2158 if (FirstParameter != NULL) {
2159 *FirstParameter = CHAR_NULL;
2160 }
2161
2162 FirstParameter = NULL;
2163
2164 //
2165 // Process the command line
2166 //
2167 Status = ProcessCommandLineToFinal (&Temp);
2168
2169 if (!EFI_ERROR (Status)) {
2170 FirstParameter = AllocateZeroPool (StrSize (CmdLine));
2171 if (FirstParameter == NULL) {
2172 SHELL_FREE_NON_NULL (Temp);
2173 return (EFI_OUT_OF_RESOURCES);
2174 }
2175
2176 TempWalker = (CHAR16 *)Temp;
2177 if (!EFI_ERROR (GetNextParameter (&TempWalker, &FirstParameter, StrSize (CmdLine), TRUE))) {
2178 if (GetOperationType (FirstParameter) == Unknown_Invalid) {
2179 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
2181 Status = EFI_NOT_FOUND;
2182 }
2183 }
2184 }
2185
2186 SHELL_FREE_NON_NULL (Temp);
2187 SHELL_FREE_NON_NULL (FirstParameter);
2188 return Status;
2189}
2190
2201 IN CONST CHAR16 *CmdLine
2202 )
2203{
2204 CONST CHAR16 *TempSpot;
2205 EFI_STATUS Status;
2206
2207 //
2208 // If this was the only item, then get out
2209 //
2210 if (!ContainsSplit (CmdLine)) {
2211 return (EFI_SUCCESS);
2212 }
2213
2214 //
2215 // Verify up to the pipe or end character
2216 //
2217 Status = IsValidSplit (CmdLine);
2218 if (EFI_ERROR (Status)) {
2219 return (Status);
2220 }
2221
2222 //
2223 // recurse to verify the next item
2224 //
2225 TempSpot = FindFirstCharacter (CmdLine, L"|", L'^') + 1;
2226 if ((*TempSpot == L'a') &&
2227 ((*(TempSpot + 1) == L' ') || (*(TempSpot + 1) == CHAR_NULL))
2228 )
2229 {
2230 // If it's an ASCII pipe '|a'
2231 TempSpot += 1;
2232 }
2233
2234 return (VerifySplit (TempSpot));
2235}
2236
2247 IN CONST CHAR16 *CmdLine
2248 )
2249{
2251 EFI_STATUS Status;
2252
2253 Status = VerifySplit (CmdLine);
2254 if (EFI_ERROR (Status)) {
2255 return (Status);
2256 }
2257
2258 Split = NULL;
2259
2260 //
2261 // are we in an existing split???
2262 //
2263 if (!IsListEmpty (&ShellInfoObject.SplitList.Link)) {
2264 Split = (SPLIT_LIST *)GetFirstNode (&ShellInfoObject.SplitList.Link);
2265 }
2266
2267 if (Split == NULL) {
2268 Status = RunSplitCommand (CmdLine, NULL, NULL);
2269 } else {
2270 Status = RunSplitCommand (CmdLine, Split->SplitStdIn, Split->SplitStdOut);
2271 }
2272
2273 if (EFI_ERROR (Status)) {
2274 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, CmdLine);
2275 }
2276
2277 return (Status);
2278}
2279
2289 IN CONST CHAR16 *CmdLine
2290 )
2291{
2292 EFI_STATUS Status;
2293
2294 Status = EFI_SUCCESS;
2295
2296 //
2297 // make sure we are the right operation
2298 //
2299 ASSERT (CmdLine[(StrLen (CmdLine)-1)] == L':' && StrStr (CmdLine, L" ") == NULL);
2300
2301 //
2302 // Call the protocol API to do the work
2303 //
2304 Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir (NULL, CmdLine);
2305
2306 //
2307 // Report any errors
2308 //
2309 if (EFI_ERROR (Status)) {
2310 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, CmdLine);
2311 }
2312
2313 return (Status);
2314}
2315
2325 IN OUT CHAR16 **CmdLine
2326 )
2327{
2328 CHAR16 *CurrentParameter;
2329 CHAR16 *Walker;
2330 CHAR16 *NewCommandLine;
2331 EFI_STATUS Status;
2332 UINTN NewCmdLineSize;
2333
2334 Status = EFI_SUCCESS;
2335
2336 CurrentParameter = AllocateZeroPool (StrSize (*CmdLine));
2337 if (CurrentParameter == NULL) {
2338 return (EFI_OUT_OF_RESOURCES);
2339 }
2340
2341 Walker = *CmdLine;
2342 while (Walker != NULL && *Walker != CHAR_NULL) {
2343 if (!EFI_ERROR (GetNextParameter (&Walker, &CurrentParameter, StrSize (*CmdLine), TRUE))) {
2344 if (StrStr (CurrentParameter, L"-?") == CurrentParameter) {
2345 CurrentParameter[0] = L' ';
2346 CurrentParameter[1] = L' ';
2347 NewCmdLineSize = StrSize (L"help ") + StrSize (*CmdLine);
2348 NewCommandLine = AllocateZeroPool (NewCmdLineSize);
2349 if (NewCommandLine == NULL) {
2350 Status = EFI_OUT_OF_RESOURCES;
2351 break;
2352 }
2353
2354 //
2355 // We know the space is sufficient since we just calculated it.
2356 //
2357 StrnCpyS (NewCommandLine, NewCmdLineSize/sizeof (CHAR16), L"help ", 5);
2358 StrnCatS (NewCommandLine, NewCmdLineSize/sizeof (CHAR16), *CmdLine, StrLen (*CmdLine));
2359 SHELL_FREE_NON_NULL (*CmdLine);
2360 *CmdLine = NewCommandLine;
2361 break;
2362 }
2363 }
2364 }
2365
2366 SHELL_FREE_NON_NULL (CurrentParameter);
2367
2368 return (Status);
2369}
2370
2378 IN CONST SHELL_STATUS ErrorCode
2379 )
2380{
2381 CHAR16 LeString[19];
2382
2383 if (sizeof (EFI_STATUS) == sizeof (UINT64)) {
2384 UnicodeSPrint (LeString, sizeof (LeString), L"0x%Lx", ErrorCode);
2385 } else {
2386 UnicodeSPrint (LeString, sizeof (LeString), L"0x%x", ErrorCode);
2387 }
2388
2389 DEBUG_CODE (
2390 InternalEfiShellSetEnv (L"debuglasterror", LeString, TRUE);
2391 );
2392 InternalEfiShellSetEnv (L"lasterror", LeString, TRUE);
2393
2394 return (EFI_SUCCESS);
2395}
2396
2408 IN OUT CHAR16 **CmdLine
2409 )
2410{
2411 EFI_STATUS Status;
2412
2413 TrimSpaces (CmdLine);
2414
2415 Status = ShellSubstituteAliases (CmdLine);
2416 if (EFI_ERROR (Status)) {
2417 return (Status);
2418 }
2419
2420 TrimSpaces (CmdLine);
2421
2422 Status = ShellSubstituteVariables (CmdLine);
2423 if (EFI_ERROR (Status)) {
2424 return (Status);
2425 }
2426
2427 ASSERT (*CmdLine != NULL);
2428
2429 TrimSpaces (CmdLine);
2430
2431 //
2432 // update for help parsing
2433 //
2434 if (StrStr (*CmdLine, L"?") != NULL) {
2435 //
2436 // This may do nothing if the ? does not indicate help.
2437 // Save all the details for in the API below.
2438 //
2439 Status = DoHelpUpdate (CmdLine);
2440 }
2441
2442 TrimSpaces (CmdLine);
2443
2444 return (EFI_SUCCESS);
2445}
2446
2462 IN CONST CHAR16 *CmdLine,
2463 IN CHAR16 *FirstParameter,
2464 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
2465 OUT EFI_STATUS *CommandStatus
2466 )
2467{
2468 EFI_STATUS Status;
2469 UINTN Argc;
2470 CHAR16 **Argv;
2471 SHELL_STATUS CommandReturnedStatus;
2472 BOOLEAN LastError;
2473 CHAR16 *Walker;
2474 CHAR16 *NewCmdLine;
2475
2476 NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine);
2477 if (NewCmdLine == NULL) {
2478 return EFI_OUT_OF_RESOURCES;
2479 }
2480
2481 for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL; Walker++) {
2482 if ((*Walker == L'^') && (*(Walker+1) == L'#')) {
2483 CopyMem (Walker, Walker+1, StrSize (Walker) - sizeof (Walker[0]));
2484 }
2485 }
2486
2487 //
2488 // get the argc and argv updated for internal commands
2489 //
2490 Status = UpdateArgcArgv (ParamProtocol, NewCmdLine, Internal_Command, &Argv, &Argc);
2491 if (!EFI_ERROR (Status)) {
2492 //
2493 // Run the internal command.
2494 //
2495 Status = ShellCommandRunCommandHandler (FirstParameter, &CommandReturnedStatus, &LastError);
2496
2497 if (!EFI_ERROR (Status)) {
2498 if (CommandStatus != NULL) {
2499 if (CommandReturnedStatus != SHELL_SUCCESS) {
2500 *CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT);
2501 } else {
2502 *CommandStatus = EFI_SUCCESS;
2503 }
2504 }
2505
2506 //
2507 // Update last error status.
2508 // some commands do not update last error.
2509 //
2510 if (LastError) {
2511 SetLastError (CommandReturnedStatus);
2512 }
2513
2514 //
2515 // Pass thru the exitcode from the app.
2516 //
2517 if (ShellCommandGetExit ()) {
2518 //
2519 // An Exit was requested ("exit" command), pass its value up.
2520 //
2521 Status = CommandReturnedStatus;
2522 } else if ((CommandReturnedStatus != SHELL_SUCCESS) && IsScriptOnlyCommand (FirstParameter)) {
2523 //
2524 // Always abort when a script only command fails for any reason
2525 //
2526 Status = EFI_ABORTED;
2527 } else if ((ShellCommandGetCurrentScriptFile () != NULL) && (CommandReturnedStatus == SHELL_ABORTED)) {
2528 //
2529 // Abort when in a script and a command aborted
2530 //
2531 Status = EFI_ABORTED;
2532 }
2533 }
2534 }
2535
2536 //
2537 // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.
2538 // This is safe even if the update API failed. In this case, it may be a no-op.
2539 //
2540 RestoreArgcArgv (ParamProtocol, &Argv, &Argc);
2541
2542 //
2543 // If a script is running and the command is not a script only command, then
2544 // change return value to success so the script won't halt (unless aborted).
2545 //
2546 // Script only commands have to be able halt the script since the script will
2547 // not operate if they are failing.
2548 //
2550 && !IsScriptOnlyCommand (FirstParameter)
2551 && (Status != EFI_ABORTED)
2552 )
2553 {
2554 Status = EFI_SUCCESS;
2555 }
2556
2557 FreePool (NewCmdLine);
2558 return (Status);
2559}
2560
2575 IN SHELL_OPERATION_TYPES Type,
2576 IN CONST CHAR16 *CmdLine,
2577 IN CHAR16 *FirstParameter,
2578 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
2579 OUT EFI_STATUS *CommandStatus
2580 )
2581{
2582 EFI_STATUS Status;
2583 EFI_STATUS StartStatus;
2584 CHAR16 *CommandWithPath;
2585 CHAR16 *FullCommandWithPath;
2586 EFI_DEVICE_PATH_PROTOCOL *DevPath;
2587 SHELL_STATUS CalleeExitStatus;
2588
2589 Status = EFI_SUCCESS;
2590 CommandWithPath = NULL;
2591 DevPath = NULL;
2592 CalleeExitStatus = SHELL_INVALID_PARAMETER;
2593
2594 switch (Type) {
2595 case Internal_Command:
2596 Status = RunInternalCommand (CmdLine, FirstParameter, ParamProtocol, CommandStatus);
2597 break;
2598 case Script_File_Name:
2599 case Efi_Application:
2600 //
2601 // Process a fully qualified path
2602 //
2603 if (StrStr (FirstParameter, L":") != NULL) {
2604 ASSERT (CommandWithPath == NULL);
2605 if (ShellIsFile (FirstParameter) == EFI_SUCCESS) {
2606 CommandWithPath = StrnCatGrow (&CommandWithPath, NULL, FirstParameter, 0);
2607 }
2608 }
2609
2610 //
2611 // Process a relative path and also check in the path environment variable
2612 //
2613 if (CommandWithPath == NULL) {
2614 CommandWithPath = ShellFindFilePathEx (FirstParameter, mExecutableExtensions);
2615 }
2616
2617 if (CommandWithPath == NULL) {
2618 //
2619 // This should be impossible now.
2620 //
2621 ASSERT (CommandWithPath != NULL);
2622 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
2624 return EFI_NOT_FOUND;
2625 }
2626
2627 //
2628 // Make sure that path is not just a directory (or not found)
2629 //
2630 if (!EFI_ERROR (ShellIsDirectory (CommandWithPath))) {
2631 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
2633 }
2634
2635 switch (Type) {
2636 case Script_File_Name:
2637 FullCommandWithPath = FullyQualifyPath (CommandWithPath);
2638 if (FullCommandWithPath == NULL) {
2639 Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);
2640 } else {
2641 Status = RunScriptFile (FullCommandWithPath, NULL, CmdLine, ParamProtocol);
2642 FreePool (FullCommandWithPath);
2643 }
2644
2645 break;
2646 case Efi_Application:
2647 //
2648 // Get the device path of the application image
2649 //
2650 DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath (CommandWithPath);
2651 if (DevPath == NULL) {
2652 Status = EFI_OUT_OF_RESOURCES;
2653 break;
2654 }
2655
2656 //
2657 // Execute the device path
2658 //
2660 &gImageHandle,
2661 DevPath,
2662 CmdLine,
2663 NULL,
2664 &StartStatus
2665 );
2666
2667 SHELL_FREE_NON_NULL (DevPath);
2668
2669 if (EFI_ERROR (Status)) {
2670 CalleeExitStatus = (SHELL_STATUS)(Status & (~MAX_BIT));
2671 } else {
2672 CalleeExitStatus = (SHELL_STATUS)StartStatus;
2673 }
2674
2675 if (CommandStatus != NULL) {
2676 *CommandStatus = CalleeExitStatus;
2677 }
2678
2679 //
2680 // Update last error status.
2681 //
2682 // Status is an EFI_STATUS. Clear top bit to convert to SHELL_STATUS
2683 SetLastError (CalleeExitStatus);
2684 break;
2685 default:
2686 //
2687 // Do nothing.
2688 //
2689 break;
2690 }
2691
2692 break;
2693 default:
2694 //
2695 // Do nothing.
2696 //
2697 break;
2698 }
2699
2700 SHELL_FREE_NON_NULL (CommandWithPath);
2701
2702 return (Status);
2703}
2704
2719 IN SHELL_OPERATION_TYPES Type,
2720 IN CHAR16 *CmdLine,
2721 IN CHAR16 *FirstParameter,
2722 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
2723 OUT EFI_STATUS *CommandStatus
2724 )
2725{
2726 EFI_STATUS Status;
2727 SHELL_FILE_HANDLE OriginalStdIn;
2728 SHELL_FILE_HANDLE OriginalStdOut;
2729 SHELL_FILE_HANDLE OriginalStdErr;
2730 SYSTEM_TABLE_INFO OriginalSystemTableInfo;
2731 CONST SCRIPT_FILE *ConstScriptFile;
2732
2733 //
2734 // Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII
2735 //
2736 Status = UpdateStdInStdOutStdErr (ParamProtocol, CmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);
2737
2738 //
2739 // The StdIn, StdOut, and StdErr are set up.
2740 // Now run the command, script, or application
2741 //
2742 if (!EFI_ERROR (Status)) {
2743 TrimSpaces (&CmdLine);
2744 Status = RunCommandOrFile (Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus);
2745 }
2746
2747 //
2748 // Now print errors
2749 //
2750 if (EFI_ERROR (Status)) {
2751 ConstScriptFile = ShellCommandGetCurrentScriptFile ();
2752 if ((ConstScriptFile == NULL) || (ConstScriptFile->CurrentCommand == NULL)) {
2753 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID *)(Status));
2754 } else {
2755 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR_SCRIPT), ShellInfoObject.HiiHandle, (VOID *)(Status), ConstScriptFile->CurrentCommand->Line);
2756 }
2757 }
2758
2759 //
2760 // put back the original StdIn, StdOut, and StdErr
2761 //
2762 RestoreStdInStdOutStdErr (ParamProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);
2763
2764 return (Status);
2765}
2766
2781 IN CONST CHAR16 *CmdLine,
2782 OUT EFI_STATUS *CommandStatus
2783 )
2784{
2785 EFI_STATUS Status;
2786 CHAR16 *CleanOriginal;
2787 CHAR16 *FirstParameter;
2788 CHAR16 *TempWalker;
2789 SHELL_OPERATION_TYPES Type;
2790 CONST CHAR16 *CurDir;
2791
2792 ASSERT (CmdLine != NULL);
2793 if (StrLen (CmdLine) == 0) {
2794 return (EFI_SUCCESS);
2795 }
2796
2797 Status = EFI_SUCCESS;
2798 CleanOriginal = NULL;
2799
2800 CleanOriginal = StrnCatGrow (&CleanOriginal, NULL, CmdLine, 0);
2801 if (CleanOriginal == NULL) {
2802 return (EFI_OUT_OF_RESOURCES);
2803 }
2804
2805 TrimSpaces (&CleanOriginal);
2806
2807 //
2808 // NULL out comments (leveraged from RunScriptFileHandle() ).
2809 // The # character on a line is used to denote that all characters on the same line
2810 // and to the right of the # are to be ignored by the shell.
2811 // Afterwards, again remove spaces, in case any were between the last command-parameter and '#'.
2812 //
2813 for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) {
2814 if (*TempWalker == L'^') {
2815 if (*(TempWalker + 1) == L'#') {
2816 TempWalker++;
2817 }
2818 } else if (*TempWalker == L'#') {
2819 *TempWalker = CHAR_NULL;
2820 }
2821 }
2822
2823 TrimSpaces (&CleanOriginal);
2824
2825 //
2826 // Handle case that passed in command line is just 1 or more " " characters.
2827 //
2828 if (StrLen (CleanOriginal) == 0) {
2829 SHELL_FREE_NON_NULL (CleanOriginal);
2830 return (EFI_SUCCESS);
2831 }
2832
2833 Status = ProcessCommandLineToFinal (&CleanOriginal);
2834 if (EFI_ERROR (Status)) {
2835 SHELL_FREE_NON_NULL (CleanOriginal);
2836 return (Status);
2837 }
2838
2839 //
2840 // We don't do normal processing with a split command line (output from one command input to another)
2841 //
2842 if (ContainsSplit (CleanOriginal)) {
2843 Status = ProcessNewSplitCommandLine (CleanOriginal);
2844 SHELL_FREE_NON_NULL (CleanOriginal);
2845 return (Status);
2846 }
2847
2848 //
2849 // We need the first parameter information so we can determine the operation type
2850 //
2851 FirstParameter = AllocateZeroPool (StrSize (CleanOriginal));
2852 if (FirstParameter == NULL) {
2853 SHELL_FREE_NON_NULL (CleanOriginal);
2854 return (EFI_OUT_OF_RESOURCES);
2855 }
2856
2857 TempWalker = CleanOriginal;
2858 if (!EFI_ERROR (GetNextParameter (&TempWalker, &FirstParameter, StrSize (CleanOriginal), TRUE))) {
2859 //
2860 // Depending on the first parameter we change the behavior
2861 //
2862 switch (Type = GetOperationType (FirstParameter)) {
2863 case File_Sys_Change:
2864 Status = ChangeMappedDrive (FirstParameter);
2865 break;
2866 case Internal_Command:
2867 case Script_File_Name:
2868 case Efi_Application:
2869 Status = SetupAndRunCommandOrFile (Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus);
2870 break;
2871 default:
2872 //
2873 // Whatever was typed, it was invalid.
2874 //
2875 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
2877 break;
2878 }
2879 } else {
2880 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
2882 }
2883
2884 //
2885 // Check whether the current file system still exists. If not exist, we need update "cwd" and gShellCurMapping.
2886 //
2887 CurDir = EfiShellGetCurDir (NULL);
2888 if (CurDir != NULL) {
2889 if (EFI_ERROR (ShellFileExists (CurDir))) {
2890 //
2891 // EfiShellSetCurDir() cannot set current directory to NULL.
2892 // EfiShellSetEnv() is not allowed to set the "cwd" variable.
2893 // Only InternalEfiShellSetEnv () is allowed setting the "cwd" variable.
2894 //
2895 InternalEfiShellSetEnv (L"cwd", NULL, TRUE);
2897 }
2898 }
2899
2900 SHELL_FREE_NON_NULL (CleanOriginal);
2901 SHELL_FREE_NON_NULL (FirstParameter);
2902
2903 return (Status);
2904}
2905
2919 IN CONST CHAR16 *CmdLine
2920 )
2921{
2922 return (RunShellCommand (CmdLine, NULL));
2923}
2924
2935 IN SHELL_FILE_HANDLE Handle,
2936 IN CONST CHAR16 *Name
2937 )
2938{
2939 EFI_STATUS Status;
2940 SCRIPT_FILE *NewScriptFile;
2941 UINTN LoopVar;
2942 UINTN PrintBuffSize;
2943 CHAR16 *CommandLine;
2944 CHAR16 *CommandLine2;
2945 CHAR16 *CommandLine3;
2946 SCRIPT_COMMAND_LIST *LastCommand;
2947 BOOLEAN Ascii;
2948 BOOLEAN PreScriptEchoState;
2949 BOOLEAN PreCommandEchoState;
2950 CONST CHAR16 *CurDir;
2951 UINTN LineCount;
2952 CHAR16 LeString[50];
2953 LIST_ENTRY OldBufferList;
2954
2955 ASSERT (!ShellCommandGetScriptExit ());
2956
2957 PreScriptEchoState = ShellCommandGetEchoState ();
2958 PrintBuffSize = PcdGet32 (PcdShellPrintBufferSize);
2959
2960 NewScriptFile = (SCRIPT_FILE *)AllocateZeroPool (sizeof (SCRIPT_FILE));
2961 if (NewScriptFile == NULL) {
2962 return (EFI_OUT_OF_RESOURCES);
2963 }
2964
2965 //
2966 // Set up the name
2967 //
2968 ASSERT (NewScriptFile->ScriptName == NULL);
2969 NewScriptFile->ScriptName = StrnCatGrow (&NewScriptFile->ScriptName, NULL, Name, 0);
2970 if (NewScriptFile->ScriptName == NULL) {
2971 DeleteScriptFileStruct (NewScriptFile);
2972 return (EFI_OUT_OF_RESOURCES);
2973 }
2974
2975 //
2976 // Save the parameters (used to replace %0 to %9 later on)
2977 //
2978 NewScriptFile->Argc = ShellInfoObject.NewShellParametersProtocol->Argc;
2979 if (NewScriptFile->Argc != 0) {
2980 NewScriptFile->Argv = (CHAR16 **)AllocateZeroPool (NewScriptFile->Argc * sizeof (CHAR16 *));
2981 if (NewScriptFile->Argv == NULL) {
2982 DeleteScriptFileStruct (NewScriptFile);
2983 return (EFI_OUT_OF_RESOURCES);
2984 }
2985
2986 //
2987 // Put the full path of the script file into Argv[0] as required by section
2988 // 3.6.2 of version 2.2 of the shell specification.
2989 //
2990 NewScriptFile->Argv[0] = StrnCatGrow (&NewScriptFile->Argv[0], NULL, NewScriptFile->ScriptName, 0);
2991 for (LoopVar = 1; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) {
2992 ASSERT (NewScriptFile->Argv[LoopVar] == NULL);
2993 NewScriptFile->Argv[LoopVar] = StrnCatGrow (&NewScriptFile->Argv[LoopVar], NULL, ShellInfoObject.NewShellParametersProtocol->Argv[LoopVar], 0);
2994 if (NewScriptFile->Argv[LoopVar] == NULL) {
2995 DeleteScriptFileStruct (NewScriptFile);
2996 return (EFI_OUT_OF_RESOURCES);
2997 }
2998 }
2999 } else {
3000 NewScriptFile->Argv = NULL;
3001 }
3002
3003 InitializeListHead (&NewScriptFile->CommandList);
3004 InitializeListHead (&NewScriptFile->SubstList);
3005
3006 //
3007 // Now build the list of all script commands.
3008 //
3009 LineCount = 0;
3010 while (!ShellFileHandleEof (Handle)) {
3011 CommandLine = ShellFileHandleReturnLine (Handle, &Ascii);
3012 LineCount++;
3013 if ((CommandLine == NULL) || (StrLen (CommandLine) == 0) || (CommandLine[0] == '#')) {
3014 SHELL_FREE_NON_NULL (CommandLine);
3015 continue;
3016 }
3017
3018 NewScriptFile->CurrentCommand = AllocateZeroPool (sizeof (SCRIPT_COMMAND_LIST));
3019 if (NewScriptFile->CurrentCommand == NULL) {
3020 SHELL_FREE_NON_NULL (CommandLine);
3021 DeleteScriptFileStruct (NewScriptFile);
3022 return (EFI_OUT_OF_RESOURCES);
3023 }
3024
3025 NewScriptFile->CurrentCommand->Cl = CommandLine;
3026 NewScriptFile->CurrentCommand->Data = NULL;
3027 NewScriptFile->CurrentCommand->Line = LineCount;
3028
3029 InsertTailList (&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);
3030 }
3031
3032 //
3033 // Add this as the topmost script file
3034 //
3035 ShellCommandSetNewScript (NewScriptFile);
3036
3037 //
3038 // Now enumerate through the commands and run each one.
3039 //
3040 CommandLine = AllocateZeroPool (PrintBuffSize);
3041 if (CommandLine == NULL) {
3042 DeleteScriptFileStruct (NewScriptFile);
3043 return (EFI_OUT_OF_RESOURCES);
3044 }
3045
3046 CommandLine2 = AllocateZeroPool (PrintBuffSize);
3047 if (CommandLine2 == NULL) {
3048 FreePool (CommandLine);
3049 DeleteScriptFileStruct (NewScriptFile);
3050 return (EFI_OUT_OF_RESOURCES);
3051 }
3052
3053 for ( NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode (&NewScriptFile->CommandList)
3054 ; !IsNull (&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)
3055 ; // conditional increment in the body of the loop
3056 )
3057 {
3058 ASSERT (CommandLine2 != NULL);
3059 StrnCpyS (
3060 CommandLine2,
3061 PrintBuffSize/sizeof (CHAR16),
3062 NewScriptFile->CurrentCommand->Cl,
3063 PrintBuffSize/sizeof (CHAR16) - 1
3064 );
3065
3066 SaveBufferList (&OldBufferList);
3067
3068 //
3069 // NULL out comments
3070 //
3071 for (CommandLine3 = CommandLine2; CommandLine3 != NULL && *CommandLine3 != CHAR_NULL; CommandLine3++) {
3072 if (*CommandLine3 == L'^') {
3073 if ( *(CommandLine3+1) == L':') {
3074 CopyMem (CommandLine3, CommandLine3+1, StrSize (CommandLine3) - sizeof (CommandLine3[0]));
3075 } else if (*(CommandLine3+1) == L'#') {
3076 CommandLine3++;
3077 }
3078 } else if (*CommandLine3 == L'#') {
3079 *CommandLine3 = CHAR_NULL;
3080 }
3081 }
3082
3083 if ((CommandLine2 != NULL) && (StrLen (CommandLine2) >= 1)) {
3084 //
3085 // Due to variability in starting the find and replace action we need to have both buffers the same.
3086 //
3087 StrnCpyS (
3088 CommandLine,
3089 PrintBuffSize/sizeof (CHAR16),
3090 CommandLine2,
3091 PrintBuffSize/sizeof (CHAR16) - 1
3092 );
3093
3094 //
3095 // Remove the %0 to %9 from the command line (if we have some arguments)
3096 //
3097 if (NewScriptFile->Argv != NULL) {
3098 switch (NewScriptFile->Argc) {
3099 default:
3100 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE);
3101 ASSERT_EFI_ERROR (Status);
3102 case 9:
3103 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE);
3104 ASSERT_EFI_ERROR (Status);
3105 case 8:
3106 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE);
3107 ASSERT_EFI_ERROR (Status);
3108 case 7:
3109 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE);
3110 ASSERT_EFI_ERROR (Status);
3111 case 6:
3112 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE);
3113 ASSERT_EFI_ERROR (Status);
3114 case 5:
3115 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE);
3116 ASSERT_EFI_ERROR (Status);
3117 case 4:
3118 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE);
3119 ASSERT_EFI_ERROR (Status);
3120 case 3:
3121 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE);
3122 ASSERT_EFI_ERROR (Status);
3123 case 2:
3124 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE);
3125 ASSERT_EFI_ERROR (Status);
3126 case 1:
3127 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE);
3128 ASSERT_EFI_ERROR (Status);
3129 break;
3130 case 0:
3131 break;
3132 }
3133 }
3134
3135 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%1", L"\"\"", FALSE, FALSE);
3136 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%2", L"\"\"", FALSE, FALSE);
3137 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%3", L"\"\"", FALSE, FALSE);
3138 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%4", L"\"\"", FALSE, FALSE);
3139 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%5", L"\"\"", FALSE, FALSE);
3140 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%6", L"\"\"", FALSE, FALSE);
3141 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%7", L"\"\"", FALSE, FALSE);
3142 Status = ShellCopySearchAndReplace (CommandLine, CommandLine2, PrintBuffSize, L"%8", L"\"\"", FALSE, FALSE);
3143 Status = ShellCopySearchAndReplace (CommandLine2, CommandLine, PrintBuffSize, L"%9", L"\"\"", FALSE, FALSE);
3144
3145 StrnCpyS (
3146 CommandLine2,
3147 PrintBuffSize/sizeof (CHAR16),
3148 CommandLine,
3149 PrintBuffSize/sizeof (CHAR16) - 1
3150 );
3151
3152 LastCommand = NewScriptFile->CurrentCommand;
3153
3154 for (CommandLine3 = CommandLine2; CommandLine3[0] == L' '; CommandLine3++) {
3155 }
3156
3157 if ((CommandLine3 != NULL) && (CommandLine3[0] == L':')) {
3158 //
3159 // This line is a goto target / label
3160 //
3161 } else {
3162 if ((CommandLine3 != NULL) && (StrLen (CommandLine3) > 0)) {
3163 if (CommandLine3[0] == L'@') {
3164 //
3165 // We need to save the current echo state
3166 // and disable echo for just this command.
3167 //
3168 PreCommandEchoState = ShellCommandGetEchoState ();
3170 Status = RunCommand (CommandLine3+1);
3171
3172 //
3173 // If command was "@echo -off" or "@echo -on" then don't restore echo state
3174 //
3175 if ((StrCmp (L"@echo -off", CommandLine3) != 0) &&
3176 (StrCmp (L"@echo -on", CommandLine3) != 0))
3177 {
3178 //
3179 // Now restore the pre-'@' echo state.
3180 //
3181 ShellCommandSetEchoState (PreCommandEchoState);
3182 }
3183 } else {
3184 if (ShellCommandGetEchoState ()) {
3185 CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv (L"cwd");
3186 if ((CurDir != NULL) && (StrLen (CurDir) > 1)) {
3187 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);
3188 } else {
3189 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);
3190 }
3191
3192 ShellPrintEx (-1, -1, L"%s\r\n", CommandLine2);
3193 }
3194
3195 Status = RunCommand (CommandLine3);
3196 }
3197 }
3198
3200 //
3201 // ShellCommandGetExitCode() always returns a UINT64
3202 //
3203 UnicodeSPrint (LeString, sizeof (LeString), L"0x%Lx", ShellCommandGetExitCode ());
3204 DEBUG_CODE (
3205 InternalEfiShellSetEnv (L"debuglasterror", LeString, TRUE);
3206 );
3207 InternalEfiShellSetEnv (L"lasterror", LeString, TRUE);
3208
3210 Status = EFI_SUCCESS;
3211 RestoreBufferList (&OldBufferList);
3212 break;
3213 }
3214
3216 RestoreBufferList (&OldBufferList);
3217 break;
3218 }
3219
3220 if (EFI_ERROR (Status)) {
3221 RestoreBufferList (&OldBufferList);
3222 break;
3223 }
3224
3225 if (ShellCommandGetExit ()) {
3226 RestoreBufferList (&OldBufferList);
3227 break;
3228 }
3229 }
3230
3231 //
3232 // If that commend did not update the CurrentCommand then we need to advance it...
3233 //
3234 if (LastCommand == NewScriptFile->CurrentCommand) {
3235 NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode (&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);
3236 if (!IsNull (&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) {
3237 NewScriptFile->CurrentCommand->Reset = TRUE;
3238 }
3239 }
3240 } else {
3241 NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode (&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);
3242 if (!IsNull (&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) {
3243 NewScriptFile->CurrentCommand->Reset = TRUE;
3244 }
3245 }
3246
3247 RestoreBufferList (&OldBufferList);
3248 }
3249
3250 FreePool (CommandLine);
3251 FreePool (CommandLine2);
3253
3254 //
3255 // Only if this was the last script reset the state.
3256 //
3258 ShellCommandSetEchoState (PreScriptEchoState);
3259 }
3260
3261 return (EFI_SUCCESS);
3262}
3263
3276 IN CONST CHAR16 *ScriptPath,
3277 IN SHELL_FILE_HANDLE Handle OPTIONAL,
3278 IN CONST CHAR16 *CmdLine,
3279 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
3280 )
3281{
3282 EFI_STATUS Status;
3283 SHELL_FILE_HANDLE FileHandle;
3284 UINTN Argc;
3285 CHAR16 **Argv;
3286
3287 if (ShellIsFile (ScriptPath) != EFI_SUCCESS) {
3288 return (EFI_INVALID_PARAMETER);
3289 }
3290
3291 //
3292 // get the argc and argv updated for scripts
3293 //
3294 Status = UpdateArgcArgv (ParamProtocol, CmdLine, Script_File_Name, &Argv, &Argc);
3295 if (!EFI_ERROR (Status)) {
3296 if (Handle == NULL) {
3297 //
3298 // open the file
3299 //
3300 Status = ShellOpenFileByName (ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0);
3301 if (!EFI_ERROR (Status)) {
3302 //
3303 // run it
3304 //
3305 Status = RunScriptFileHandle (FileHandle, ScriptPath);
3306
3307 //
3308 // now close the file
3309 //
3310 ShellCloseFile (&FileHandle);
3311 }
3312 } else {
3313 Status = RunScriptFileHandle (Handle, ScriptPath);
3314 }
3315 }
3316
3317 //
3318 // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.
3319 // This is safe even if the update API failed. In this case, it may be a no-op.
3320 //
3321 RestoreArgcArgv (ParamProtocol, &Argv, &Argc);
3322
3323 return (Status);
3324}
3325
3336CONST CHAR16 *
3338 IN CONST CHAR16 *String,
3339 IN CONST CHAR16 *CharacterList,
3340 IN CONST CHAR16 EscapeCharacter
3341 )
3342{
3343 UINTN WalkChar;
3344 UINTN WalkStr;
3345
3346 for (WalkStr = 0; WalkStr < StrLen (String); WalkStr++) {
3347 if (String[WalkStr] == EscapeCharacter) {
3348 WalkStr++;
3349 continue;
3350 }
3351
3352 for (WalkChar = 0; WalkChar < StrLen (CharacterList); WalkChar++) {
3353 if (String[WalkStr] == CharacterList[WalkChar]) {
3354 return (&String[WalkStr]);
3355 }
3356 }
3357 }
3358
3359 return (String + StrLen (String));
3360}
#define MAX_BIT
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
RETURN_STATUS EFIAPI StrCatS(IN OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:405
INTN EFIAPI StrnCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString, IN UINTN Length)
Definition: String.c:162
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
BOOLEAN EFIAPI PathRemoveLastItem(IN OUT CHAR16 *Path)
Definition: FilePaths.c:22
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
RETURN_STATUS EFIAPI StrnCatS(IN OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
Definition: SafeString.c:507
RETURN_STATUS EFIAPI StrnCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
Definition: SafeString.c:310
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
CHAR16 *EFIAPI StrStr(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString)
Definition: String.c:224
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS ConsoleLoggerInstall(IN CONST UINTN ScreensToSave, OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo)
Definition: ConsoleLogger.c:26
EFI_STATUS ConsoleLoggerUninstall(IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo)
EFI_STATUS CloseSimpleTextInOnFile(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn)
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * CreateSimpleTextInOnFile(IN SHELL_FILE_HANDLE FileHandleToUse, IN EFI_HANDLE *HandleLocation)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI FileDevicePath(IN EFI_HANDLE Device OPTIONAL, IN CONST CHAR16 *FileName)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DuplicateDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
EFI_STATUS EFIAPI NotificationFunction(IN EFI_KEY_DATA *KeyData)
Definition: DriverSample.c:117
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_FILE_PROTOCOL * CreateFileInterfaceMem(IN CONST BOOLEAN Unicode)
EFI_FILE_PROTOCOL FileInterfaceNulFile
EFI_HII_HANDLE EFIAPI HiiAddPackages(IN CONST EFI_GUID *PackageListGuid, IN EFI_HANDLE DeviceHandle OPTIONAL,...)
Definition: HiiLib.c:141
VOID EFIAPI HiiRemovePackages(IN EFI_HII_HANDLE HiiHandle)
Definition: HiiLib.c:253
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG_CODE(Expression)
Definition: DebugLib.h:590
SHELL_STATUS
Definition: Shell.h:21
@ SHELL_ABORTED
Definition: Shell.h:128
@ SHELL_SUCCESS
Definition: Shell.h:25
@ SHELL_NOT_FOUND
Definition: Shell.h:101
@ SHELL_INVALID_PARAMETER
Definition: Shell.h:35
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
EFI_STRING_ID NewString(IN CHAR16 *String, IN EFI_HII_HANDLE HiiHandle)
Definition: Setup.c:981
BOOLEAN IsValidEnvironmentVariableName(IN CONST CHAR16 *BeginPercent, IN CONST CHAR16 *EndPercent)
Definition: Shell.c:165
CHAR16 * ShellConvertVariables(IN CONST CHAR16 *OriginalCommandLine)
Definition: Shell.c:1700
EFI_STATUS TrimSpaces(IN CHAR16 **String)
Definition: Shell.c:89
EFI_STATUS SetupAndRunCommandOrFile(IN SHELL_OPERATION_TYPES Type, IN CHAR16 *CmdLine, IN CHAR16 *FirstParameter, IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, OUT EFI_STATUS *CommandStatus)
Definition: Shell.c:2718
EFI_STATUS RunInternalCommand(IN CONST CHAR16 *CmdLine, IN CHAR16 *FirstParameter, IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, OUT EFI_STATUS *CommandStatus)
Definition: Shell.c:2461
BOOLEAN IsScriptOnlyCommand(IN CONST CHAR16 *CommandName)
Definition: Shell.c:844
EFI_STATUS SetBuiltInAlias(VOID)
Definition: Shell.c:782
EFI_STATUS DoShellPrompt(VOID)
Definition: Shell.c:1409
EFI_STATUS RunScriptFile(IN CONST CHAR16 *ScriptPath, IN SHELL_FILE_HANDLE Handle OPTIONAL, IN CONST CHAR16 *CmdLine, IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol)
Definition: Shell.c:3275
BOOLEAN ContainsSplit(IN CONST CHAR16 *CmdLine)
Definition: Shell.c:212
EFI_STATUS RunShellCommand(IN CONST CHAR16 *CmdLine, OUT EFI_STATUS *CommandStatus)
Definition: Shell.c:2780
EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Shell.c:350
BOOLEAN IsCommand(IN CONST CHAR16 *Command1, IN CONST CHAR16 *Command2)
Definition: Shell.c:823
VOID RestoreBufferList(IN OUT LIST_ENTRY *OldBufferList)
Definition: Shell.c:1520
EFI_STATUS GetDevicePathsForImageAndFile(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath, IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath)
Definition: Shell.c:876
EFI_STATUS RunSplitCommand(IN CONST CHAR16 *CmdLine, IN SHELL_FILE_HANDLE StdIn, IN SHELL_FILE_HANDLE StdOut)
Definition: Shell.c:1850
VOID AddLineToCommandHistory(IN CONST CHAR16 *Buffer)
Definition: Shell.c:1534
EFI_STATUS SetLastError(IN CONST SHELL_STATUS ErrorCode)
Definition: Shell.c:2377
EFI_STATUS RunCommand(IN CONST CHAR16 *CmdLine)
Definition: Shell.c:2918
CHAR16 * LocateStartupScript(IN EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *FileDevicePath)
Definition: Shell.c:1236
EFI_STATUS VerifySplit(IN CONST CHAR16 *CmdLine)
Definition: Shell.c:2200
CHAR16 * FindNextInstance(IN CONST CHAR16 *SourceString, IN CONST CHAR16 *FindString, IN CONST BOOLEAN CheckForEscapeCharacter)
Definition: Shell.c:121
EFI_STATUS ProcessNewSplitCommandLine(IN CONST CHAR16 *CmdLine)
Definition: Shell.c:2246
VOID * AddBufferToFreeList(VOID *Buffer)
Definition: Shell.c:1480
EFI_STATUS ShellConvertAlias(IN OUT CHAR16 **CommandString)
Definition: Shell.c:1597
EFI_STATUS InternalEfiShellStartCtrlSMonitor(VOID)
Definition: Shell.c:264
EFI_STATUS ShellSubstituteVariables(IN CHAR16 **CmdLine)
Definition: Shell.c:1972
EFI_STATUS DoHelpUpdate(IN OUT CHAR16 **CmdLine)
Definition: Shell.c:2324
EFI_STATUS ShellSubstituteAliases(IN CHAR16 **CmdLine)
Definition: Shell.c:1998
EFI_STATUS ProcessCommandLine(VOID)
Definition: Shell.c:955
EFI_STATUS RunScriptFileHandle(IN SHELL_FILE_HANDLE Handle, IN CONST CHAR16 *Name)
Definition: Shell.c:2934
EFI_STATUS DoStartupScript(IN EFI_DEVICE_PATH_PROTOCOL *ImagePath, IN EFI_DEVICE_PATH_PROTOCOL *FilePath)
Definition: Shell.c:1296
EFI_STATUS RunCommandOrFile(IN SHELL_OPERATION_TYPES Type, IN CONST CHAR16 *CmdLine, IN CHAR16 *FirstParameter, IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, OUT EFI_STATUS *CommandStatus)
Definition: Shell.c:2574
VOID SaveBufferList(OUT LIST_ENTRY *OldBufferList)
Definition: Shell.c:1506
EFI_STATUS ChangeMappedDrive(IN CONST CHAR16 *CmdLine)
Definition: Shell.c:2288
CONST CHAR16 * FindFirstCharacter(IN CONST CHAR16 *String, IN CONST CHAR16 *CharacterList, IN CONST CHAR16 EscapeCharacter)
Definition: Shell.c:3337
EFI_STATUS ProcessCommandLineToFinal(IN OUT CHAR16 **CmdLine)
Definition: Shell.c:2407
EFI_STATUS StripUnreplacedEnvironmentVariables(IN OUT CHAR16 *CmdLine)
Definition: Shell.c:1623
EFI_STATUS IsValidSplit(IN CONST CHAR16 *CmdLine)
Definition: Shell.c:2141
SHELL_OPERATION_TYPES GetOperationType(IN CONST CHAR16 *CmdName)
Definition: Shell.c:2071
BOOLEAN EFIAPI ShellCommandGetScriptExit(VOID)
CONST ALIAS_LIST *EFIAPI ShellCommandGetInitAliasList(VOID)
EFI_STATUS EFIAPI CommandInit(VOID)
SHELL_FILE_HANDLE EFIAPI ConvertEfiFileProtocolToShellHandle(IN CONST EFI_FILE_PROTOCOL *Handle, IN CONST CHAR16 *Path)
VOID EFIAPI FreeBufferList(IN BUFFER_LIST *List)
BOOLEAN EFIAPI ShellFileHandleEof(IN SHELL_FILE_HANDLE Handle)
BOOLEAN EFIAPI ShellCommandIsCommandOnList(IN CONST CHAR16 *CommandString)
SHELL_MAP_LIST * gShellCurMapping
Pointer to node of current directory in the mMapList.
VOID EFIAPI ShellCommandRegisterExit(IN BOOLEAN ScriptOnly, IN CONST UINT64 ErrorCode)
RETURN_STATUS EFIAPI ShellCommandRunCommandHandler(IN CONST CHAR16 *CommandString, IN OUT SHELL_STATUS *RetVal, IN OUT BOOLEAN *CanAffectLE OPTIONAL)
UINT64 EFIAPI ShellCommandGetExitCode(VOID)
VOID EFIAPI DeleteScriptFileStruct(IN SCRIPT_FILE *Script)
SCRIPT_FILE *EFIAPI ShellCommandSetNewScript(IN SCRIPT_FILE *Script OPTIONAL)
BOOLEAN EFIAPI ShellCommandGetEchoState(VOID)
EFI_STATUS EFIAPI ShellCommandCreateInitialMappingsAndPaths(VOID)
VOID EFIAPI ShellCommandSetEchoState(IN BOOLEAN State)
BOOLEAN EFIAPI ShellCommandGetExit(VOID)
CONST CHAR16 *EFIAPI ShellCommandGetProfileList(VOID)
SCRIPT_FILE *EFIAPI ShellCommandGetCurrentScriptFile(VOID)
EFI_STATUS ShellInitEnvVarList(VOID)
Definition: ShellEnvVar.c:576
VOID ShellFreeEnvVarList(VOID)
Definition: ShellEnvVar.c:593
CHAR16 *EFIAPI ShellFileHandleReturnLine(IN SHELL_FILE_HANDLE Handle, IN OUT BOOLEAN *Ascii)
CHAR16 *EFIAPI FullyQualifyPath(IN CONST CHAR16 *Path)
Definition: UefiShellLib.c:64
EFI_STATUS EFIAPI ShellCopySearchAndReplace(IN CHAR16 CONST *SourceString, IN OUT CHAR16 *NewString, IN UINTN NewSize, IN CONST CHAR16 *FindTarget, IN CONST CHAR16 *ReplaceWith, IN CONST BOOLEAN SkipPreCarrot, IN CONST BOOLEAN ParameterReplacing)
BOOLEAN EFIAPI ShellGetExecutionBreakFlag(VOID)
EFI_STATUS EFIAPI ShellPrintHiiEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR8 *Language OPTIONAL, IN CONST EFI_STRING_ID HiiFormatStringId, IN CONST EFI_HII_HANDLE HiiFormatHandle,...)
EFI_STATUS EFIAPI ShellOpenFileByName(IN CONST CHAR16 *FileName, OUT SHELL_FILE_HANDLE *FileHandle, IN UINT64 OpenMode, IN UINT64 Attributes)
Definition: UefiShellLib.c:720
CHAR16 *EFIAPI StrnCatGrow(IN OUT CHAR16 **Destination, IN OUT UINTN *CurrentSize, IN CONST CHAR16 *Source, IN UINTN Count)
CHAR16 *EFIAPI ShellFindFilePathEx(IN CONST CHAR16 *FileName, IN CONST CHAR16 *FileExtension)
EFI_STATUS EFIAPI ShellFileExists(IN CONST CHAR16 *Name)
EFI_STATUS EFIAPI ShellInitialize(VOID)
Definition: UefiShellLib.c:532
EFI_STATUS EFIAPI ShellIsFile(IN CONST CHAR16 *Name)
EFI_STATUS EFIAPI ShellIsDirectory(IN CONST CHAR16 *DirName)
CHAR16 *EFIAPI ShellFindFilePath(IN CONST CHAR16 *FileName)
EFI_STATUS EFIAPI ShellPrintEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR16 *Format,...)
EFI_STATUS EFIAPI ShellConvertStringToUint64(IN CONST CHAR16 *String, OUT UINT64 *Value, IN CONST BOOLEAN ForceHex, IN CONST BOOLEAN StopAtSpace)
EFI_STATUS EFIAPI ShellCloseFile(IN SHELL_FILE_HANDLE *FileHandle)
Definition: UefiShellLib.c:969
EFI_STATUS CreatePopulateInstallShellParametersProtocol(IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters, IN OUT BOOLEAN *RootShellInstance)
EFI_STATUS RestoreStdInStdOutStdErr(IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN SHELL_FILE_HANDLE *OldStdIn, IN SHELL_FILE_HANDLE *OldStdOut, IN SHELL_FILE_HANDLE *OldStdErr, IN SYSTEM_TABLE_INFO *SystemTableInfo)
VOID RestoreArgcArgv(IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN CHAR16 ***OldArgv, IN UINTN *OldArgc)
EFI_STATUS CleanUpShellParametersProtocol(IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters)
EFI_STATUS UpdateArgcArgv(IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN CONST CHAR16 *NewCommandLine, IN SHELL_OPERATION_TYPES Type, OUT CHAR16 ***OldArgv OPTIONAL, OUT UINTN *OldArgc OPTIONAL)
EFI_STATUS GetNextParameter(IN OUT CHAR16 **Walker, IN OUT CHAR16 **TempParameter, IN CONST UINTN Length, IN BOOLEAN StripQuotation)
EFI_STATUS UpdateStdInStdOutStdErr(IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN CHAR16 *NewCommandLine, OUT SHELL_FILE_HANDLE *OldStdIn, OUT SHELL_FILE_HANDLE *OldStdOut, OUT SHELL_FILE_HANDLE *OldStdErr, OUT SYSTEM_TABLE_INFO *SystemTableInfo)
CONST CHAR16 *EFIAPI EfiShellGetEnv(IN CONST CHAR16 *Name)
CONST CHAR16 *EFIAPI EfiShellGetCurDir(IN CONST CHAR16 *FileSystemMapping OPTIONAL)
EFI_STATUS InternalShellExecuteDevicePath(IN CONST EFI_HANDLE *ParentImageHandle, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 *CommandLine OPTIONAL, IN CONST CHAR16 **Environment OPTIONAL, OUT EFI_STATUS *StartImageStatus OPTIONAL)
EFI_STATUS InternalEfiShellSetEnv(IN CONST CHAR16 *Name, IN CONST CHAR16 *Value, IN BOOLEAN Volatile)
EFI_STATUS InternalSetAlias(IN CONST CHAR16 *Command, IN CONST CHAR16 *Alias, IN BOOLEAN Volatile)
EFI_STATUS CreatePopulateInstallShellProtocol(IN OUT EFI_SHELL_PROTOCOL **NewShell)
EFI_STATUS InernalEfiShellStartMonitor(VOID)
EFI_STATUS CleanUpShellEnvironment(IN OUT EFI_SHELL_PROTOCOL *NewShell)
INTN EFIAPI StringNoCaseCompare(IN CONST VOID *Buffer1, IN CONST VOID *Buffer2)
Definition: BaseSortLib.c:92
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_SYSTEM_TABLE * gST
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
#define STRING_TOKEN(t)
STATIC CONST CHAR8 ** Split(IN CHAR8 *Strings, IN UINTN Len, OUT UINT32 *NumPtr)
Definition: XenStore.c:212
BOOLEAN Enabled
Set to FALSE when a break is requested.
Definition: ConsoleLogger.h:35
UINTN RowCounter
Initial row of each print job.
Definition: ConsoleLogger.h:36
EFI_KEY_TOGGLE_STATE KeyToggleState
UINT32 KeyShiftState
EFI_SIMPLE_TEXT_OUTPUT_MODE * Mode
EFI_INPUT_KEY Key
EFI_KEY_STATE KeyState
EFI_DEVICE_PATH_PROTOCOL * FilePath
Definition: LoadedImage.h:54
EFI_HANDLE DeviceHandle
The device handle that the EFI Image was loaded from.
Definition: LoadedImage.h:53
UINT32 FirmwareRevision
Definition: UefiSpec.h:2042
EFI_HANDLE ConsoleInHandle
Definition: UefiSpec.h:2048
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn
Definition: UefiSpec.h:2053
CHAR16 * FirmwareVendor
Definition: UefiSpec.h:2037
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut
Definition: UefiSpec.h:2064
EFI_TABLE_HEADER Hdr
Definition: UefiSpec.h:2032
LIST_ENTRY Link
List enumerator items.
VOID * Data
The data structure format dependant upon Command. (not always used)
UINTN Line
What line of the script file this was on.
BOOLEAN Reset
Reset the command (it must be treated like a initial run (but it may have data already))
CHAR16 * Cl
The original command line.
CHAR16 * ScriptName
The filename of this script.
UINTN Argc
The count of parameters.
LIST_ENTRY CommandList
The script converted to a list of commands (SCRIPT_COMMAND_LIST objects).
SCRIPT_COMMAND_LIST * CurrentCommand
The command currently being operated. If !=NULL must be a member of CommandList.
CHAR16 ** Argv
The parmameters to the script file.
LIST_ENTRY SubstList
A list of current script loop alias' (ALIAS_LIST objects) (Used for the for %-based replacement).
UINT32 NoInterrupt
Was "-nointerrupt" found on command line.
Definition: Shell.h:69
UINT32 NoMap
Was "-nomap" found on command line.
Definition: Shell.h:70
UINT32 NoConsoleOut
Was "-noconsoleout" found on command line.
Definition: Shell.h:67
UINT32 NoConsoleIn
Was "-noconsolein" found on command line.
Definition: Shell.h:68
UINT32 Exit
Was "-_exit" found on command line.
Definition: Shell.h:73
UINT32 NoNest
Was "-nonest" found on command line.
Definition: Shell.h:74
UINT32 Delay
Was "-delay[:n] found on command line.
Definition: Shell.h:72
UINT32 Startup
Was "-startup" found on command line.
Definition: Shell.h:65
UINT32 NoStartup
Was "-nostartup" found on command line.
Definition: Shell.h:66
UINT32 NoVersion
Was "-noversion" found on command line.
Definition: Shell.h:71
UINTN LogScreenCount
How many screens of log information to save.
Definition: Shell.h:106
SPLIT_LIST SplitList
List of Splits in FILO stack.
Definition: Shell.h:113
EFI_DEVICE_PATH_PROTOCOL * FileDevPath
DevicePath for ourselves.
Definition: Shell.h:109
BUFFER_LIST BufferToFreeList
List of buffers that were returned to the user to free.
Definition: Shell.h:103
EFI_DEVICE_PATH_PROTOCOL * ImageDevPath
DevicePath for ourselves.
Definition: Shell.h:108
EFI_HII_HANDLE HiiHandle
Handle from HiiLib.
Definition: Shell.h:105
VOID * CtrlSNotifyHandle4
The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
Definition: Shell.h:121
VOID * CtrlSNotifyHandle2
The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
Definition: Shell.h:119
EFI_EVENT UserBreakTimer
Timer event for polling for CTRL-C.
Definition: Shell.h:107
VOID * CtrlSNotifyHandle3
The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
Definition: Shell.h:120
VOID * CtrlSNotifyHandle1
The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
Definition: Shell.h:118
CONSOLE_LOGGER_PRIVATE_DATA * ConsoleInfo
Pointer for ConsoleInformation.
Definition: Shell.h:110
CHAR16 * FileOptions
Options to pass to FileName.
Definition: Shell.h:87
UINTN Delay
Seconds of delay default:5.
Definition: Shell.h:85
CHAR16 * FileName
Filename to run upon successful initialization.
Definition: Shell.h:86
BOOLEAN InsertMode
Is the current typing mode insert (FALSE = overwrite).
Definition: Shell.h:94
LIST_ENTRY Link
Standard linked list handler.
Definition: Shell.h:59