TianoCore EDK2 master
Loading...
Searching...
No Matches
UefiShellCommandLib.c
Go to the documentation of this file.
1
12#include "UefiShellCommandLib.h"
13
14// STATIC local variables
16STATIC SCRIPT_FILE_LIST mScriptList;
17STATIC ALIAS_LIST mAliasList;
18STATIC BOOLEAN mEchoState;
19STATIC BOOLEAN mExitRequested;
20STATIC UINT64 mExitCode;
21STATIC BOOLEAN mExitScript;
22STATIC CHAR16 *mProfileList;
23STATIC UINTN mProfileListSize;
24STATIC UINTN mFsMaxCount = 0;
25STATIC UINTN mBlkMaxCount = 0;
26STATIC BUFFER_LIST mFileHandleList;
27
28STATIC CONST CHAR8 Hex[] = {
29 '0',
30 '1',
31 '2',
32 '3',
33 '4',
34 '5',
35 '6',
36 '7',
37 '8',
38 '9',
39 'A',
40 'B',
41 'C',
42 'D',
43 'E',
44 'F'
45};
46
47// global variables required by library class.
48EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation = NULL;
51
52CONST CHAR16 *SupportLevel[] = {
53 L"Minimal",
54 L"Scripting",
55 L"Basic",
56 L"Interactive"
57};
58
64EFIAPI
66 VOID
67 )
68{
69 UINTN NumHandles;
70 EFI_HANDLE *Handles;
72 CHAR8 *BestLanguage;
73 UINTN Index;
74 EFI_STATUS Status;
75 CHAR8 *PlatformLang;
76
77 if (gUnicodeCollation == NULL) {
79
80 Status = gBS->LocateHandleBuffer (
82 &gEfiUnicodeCollation2ProtocolGuid,
83 NULL,
84 &NumHandles,
85 &Handles
86 );
87 if (EFI_ERROR (Status)) {
88 NumHandles = 0;
89 Handles = NULL;
90 }
91
92 for (Index = 0; Index < NumHandles; Index++) {
93 //
94 // Open Unicode Collation Protocol
95 //
96 Status = gBS->OpenProtocol (
97 Handles[Index],
98 &gEfiUnicodeCollation2ProtocolGuid,
99 (VOID **)&Uc,
101 NULL,
102 EFI_OPEN_PROTOCOL_GET_PROTOCOL
103 );
104 if (EFI_ERROR (Status)) {
105 continue;
106 }
107
108 //
109 // Without clue provided use the first Unicode Collation2 protocol.
110 // This may happen when PlatformLang is NULL or when no installed Unicode
111 // Collation2 protocol instance supports PlatformLang.
112 //
113 if (gUnicodeCollation == NULL) {
114 gUnicodeCollation = Uc;
115 }
116
117 if (PlatformLang == NULL) {
118 break;
119 }
120
121 //
122 // Find the best matching matching language from the supported languages
123 // of Unicode Collation2 protocol.
124 //
125 BestLanguage = GetBestLanguage (
126 Uc->SupportedLanguages,
127 FALSE,
128 PlatformLang,
129 NULL
130 );
131 if (BestLanguage != NULL) {
132 FreePool (BestLanguage);
133 gUnicodeCollation = Uc;
134 break;
135 }
136 }
137
138 if (Handles != NULL) {
139 FreePool (Handles);
140 }
141
142 if (PlatformLang != NULL) {
143 FreePool (PlatformLang);
144 }
145 }
146
147 return (gUnicodeCollation == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS;
148}
149
160RETURN_STATUS
161EFIAPI
163 IN EFI_HANDLE ImageHandle,
164 IN EFI_SYSTEM_TABLE *SystemTable
165 )
166{
167 EFI_STATUS Status;
168
170 InitializeListHead (&mCommandList.Link);
171 InitializeListHead (&mAliasList.Link);
172 InitializeListHead (&mScriptList.Link);
173 InitializeListHead (&mFileHandleList.Link);
174 mEchoState = TRUE;
175
176 mExitRequested = FALSE;
177 mExitScript = FALSE;
178 mProfileListSize = 0;
179 mProfileList = NULL;
180
181 Status = CommandInit ();
182 if (EFI_ERROR (Status)) {
183 return EFI_DEVICE_ERROR;
184 }
185
186 return (RETURN_SUCCESS);
187}
188
194VOID
196 IN BUFFER_LIST *List
197 )
198{
199 BUFFER_LIST *BufferListEntry;
200
201 if (List == NULL) {
202 return;
203 }
204
205 //
206 // enumerate through the buffer list and free all memory
207 //
208 for ( BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
209 ; !IsListEmpty (&List->Link)
210 ; BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
211 )
212 {
213 RemoveEntryList (&BufferListEntry->Link);
214 ASSERT (BufferListEntry->Buffer != NULL);
215 SHELL_FREE_NON_NULL (((SHELL_COMMAND_FILE_HANDLE *)(BufferListEntry->Buffer))->Path);
216 SHELL_FREE_NON_NULL (BufferListEntry->Buffer);
217 SHELL_FREE_NON_NULL (BufferListEntry);
218 }
219}
220
229RETURN_STATUS
230EFIAPI
232 IN EFI_HANDLE ImageHandle,
233 IN EFI_SYSTEM_TABLE *SystemTable
234 )
235{
237 ALIAS_LIST *Node2;
238 SCRIPT_FILE_LIST *Node3;
239 SHELL_MAP_LIST *MapNode;
240
241 //
242 // enumerate throught the list and free all the memory
243 //
244 while (!IsListEmpty (&mCommandList.Link)) {
245 Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link);
246 RemoveEntryList (&Node->Link);
247 SHELL_FREE_NON_NULL (Node->CommandString);
248 FreePool (Node);
249 DEBUG_CODE (
250 Node = NULL;
251 );
252 }
253
254 //
255 // enumerate through the alias list and free all memory
256 //
257 while (!IsListEmpty (&mAliasList.Link)) {
258 Node2 = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link);
259 RemoveEntryList (&Node2->Link);
260 SHELL_FREE_NON_NULL (Node2->CommandString);
261 SHELL_FREE_NON_NULL (Node2->Alias);
262 SHELL_FREE_NON_NULL (Node2);
263 DEBUG_CODE (
264 Node2 = NULL;
265 );
266 }
267
268 //
269 // enumerate throught the list and free all the memory
270 //
271 while (!IsListEmpty (&mScriptList.Link)) {
272 Node3 = (SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link);
273 RemoveEntryList (&Node3->Link);
274 DeleteScriptFileStruct (Node3->Data);
275 FreePool (Node3);
276 }
277
278 //
279 // enumerate throught the mappings list and free all the memory
280 //
281 if (!IsListEmpty (&gShellMapList.Link)) {
282 for (MapNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
283 ; !IsListEmpty (&gShellMapList.Link)
284 ; MapNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
285 )
286 {
287 ASSERT (MapNode != NULL);
288 RemoveEntryList (&MapNode->Link);
289 SHELL_FREE_NON_NULL (MapNode->DevicePath);
290 SHELL_FREE_NON_NULL (MapNode->MapName);
291 SHELL_FREE_NON_NULL (MapNode->CurrentDirectoryPath);
292 FreePool (MapNode);
293 }
294 }
295
296 if (!IsListEmpty (&mFileHandleList.Link)) {
297 FreeFileHandleList (&mFileHandleList);
298 }
299
300 if (mProfileList != NULL) {
301 FreePool (mProfileList);
302 }
303
304 gUnicodeCollation = NULL;
306
307 return (RETURN_SUCCESS);
308}
309
320 IN CONST CHAR16 *CommandString
321 )
322{
323 EFI_STATUS Status;
324 EFI_HANDLE *CommandHandleList;
325 EFI_HANDLE *NextCommand;
327
328 CommandHandleList = GetHandleListByProtocol (&gEfiShellDynamicCommandProtocolGuid);
329 if (CommandHandleList == NULL) {
330 //
331 // not found or out of resources
332 //
333 return NULL;
334 }
335
336 for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
337 Status = gBS->HandleProtocol (
338 *NextCommand,
339 &gEfiShellDynamicCommandProtocolGuid,
340 (VOID **)&DynamicCommand
341 );
342
343 if (EFI_ERROR (Status)) {
344 continue;
345 }
346
347 if (gUnicodeCollation->StriColl (
348 gUnicodeCollation,
349 (CHAR16 *)CommandString,
350 (CHAR16 *)DynamicCommand->CommandName
351 ) == 0
352 )
353 {
354 FreePool (CommandHandleList);
355 return (DynamicCommand);
356 }
357 }
358
359 FreePool (CommandHandleList);
360 return (NULL);
361}
362
368BOOLEAN
370 IN CONST CHAR16 *CommandString
371 )
372{
373 return (BOOLEAN)((ShellCommandFindDynamicCommand (CommandString) != NULL));
374}
375
381BOOLEAN
383 IN CONST CHAR16 *CommandString
384 )
385{
387
388 //
389 // assert for NULL parameter
390 //
391 ASSERT (CommandString != NULL);
392
393 //
394 // check for the command
395 //
396 for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
397 ; !IsNull (&mCommandList.Link, &Node->Link)
398 ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
399 )
400 {
401 ASSERT (Node->CommandString != NULL);
402 if (gUnicodeCollation->StriColl (
403 gUnicodeCollation,
404 (CHAR16 *)CommandString,
405 Node->CommandString
406 ) == 0
407 )
408 {
409 return (TRUE);
410 }
411 }
412
413 return (FALSE);
414}
415
421BOOLEAN
422EFIAPI
424 IN CONST CHAR16 *CommandString
425 )
426{
427 if (ShellCommandIsCommandOnInternalList (CommandString)) {
428 return TRUE;
429 }
430
431 return ShellCommandDynamicCommandExists (CommandString);
432}
433
442CHAR16 *
444 IN CONST CHAR16 *CommandString
445 )
446{
448
449 DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand (CommandString);
450 if (DynamicCommand == NULL) {
451 return (NULL);
452 }
453
454 //
455 // TODO: how to get proper language?
456 //
457 return DynamicCommand->GetHelp (DynamicCommand, "en");
458}
459
468CHAR16 *
470 IN CONST CHAR16 *CommandString
471 )
472{
474
475 //
476 // assert for NULL parameter
477 //
478 ASSERT (CommandString != NULL);
479
480 //
481 // check for the command
482 //
483 for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
484 ; !IsNull (&mCommandList.Link, &Node->Link)
485 ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
486 )
487 {
488 ASSERT (Node->CommandString != NULL);
489 if (gUnicodeCollation->StriColl (
490 gUnicodeCollation,
491 (CHAR16 *)CommandString,
492 Node->CommandString
493 ) == 0
494 )
495 {
496 return (HiiGetString (Node->HiiHandle, Node->ManFormatHelp, NULL));
497 }
498 }
499
500 return (NULL);
501}
502
511CHAR16 *
512EFIAPI
514 IN CONST CHAR16 *CommandString
515 )
516{
517 CHAR16 *HelpStr;
518
519 HelpStr = ShellCommandGetInternalCommandHelp (CommandString);
520
521 if (HelpStr == NULL) {
522 HelpStr = ShellCommandGetDynamicCommandHelp (CommandString);
523 }
524
525 return HelpStr;
526}
527
575RETURN_STATUS
576EFIAPI
578 IN CONST CHAR16 *CommandString,
579 IN SHELL_RUN_COMMAND CommandHandler,
581 IN UINT32 ShellMinSupportLevel,
582 IN CONST CHAR16 *ProfileName,
583 IN CONST BOOLEAN CanAffectLE,
584 IN CONST EFI_HII_HANDLE HiiHandle,
585 IN CONST EFI_STRING_ID ManFormatHelp
586 )
587{
591 INTN LexicalMatchValue;
592
593 //
594 // Initialize local variables.
595 //
596 Command = NULL;
597 PrevCommand = NULL;
598 LexicalMatchValue = 0;
599
600 //
601 // ASSERTs for NULL parameters
602 //
603 ASSERT (CommandString != NULL);
604 ASSERT (GetManFileName != NULL);
605 ASSERT (CommandHandler != NULL);
606 ASSERT (ProfileName != NULL);
607
608 //
609 // check for shell support level
610 //
611 if (PcdGet8 (PcdShellSupportLevel) < ShellMinSupportLevel) {
612 return (RETURN_UNSUPPORTED);
613 }
614
615 //
616 // check for already on the list
617 //
618 if (ShellCommandIsCommandOnList (CommandString)) {
619 return (RETURN_ALREADY_STARTED);
620 }
621
622 //
623 // allocate memory for new struct
624 //
626 if (Node == NULL) {
628 }
629
630 Node->CommandString = AllocateCopyPool (StrSize (CommandString), CommandString);
631 if (Node->CommandString == NULL) {
632 FreePool (Node);
634 }
635
636 Node->GetManFileName = GetManFileName;
637 Node->CommandHandler = CommandHandler;
638 Node->LastError = CanAffectLE;
639 Node->HiiHandle = HiiHandle;
640 Node->ManFormatHelp = ManFormatHelp;
641
642 if ( (StrLen (ProfileName) > 0)
643 && (( (mProfileList != NULL)
644 && (StrStr (mProfileList, ProfileName) == NULL)) || (mProfileList == NULL))
645 )
646 {
647 ASSERT ((mProfileList == NULL && mProfileListSize == 0) || (mProfileList != NULL));
648 if (mProfileList == NULL) {
649 //
650 // If this is the first make a leading ';'
651 //
652 StrnCatGrow (&mProfileList, &mProfileListSize, L";", 0);
653 }
654
655 StrnCatGrow (&mProfileList, &mProfileListSize, ProfileName, 0);
656 StrnCatGrow (&mProfileList, &mProfileListSize, L";", 0);
657 }
658
659 //
660 // Insert a new entry on top of the list
661 //
662 InsertHeadList (&mCommandList.Link, &Node->Link);
663
664 //
665 // Move a new registered command to its sorted ordered location in the list
666 //
667 for (Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link),
668 PrevCommand = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
669 ; !IsNull (&mCommandList.Link, &Command->Link)
670 ; Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Command->Link))
671 {
672 //
673 // Get Lexical Comparison Value between PrevCommand and Command list entry
674 //
675 LexicalMatchValue = gUnicodeCollation->StriColl (
676 gUnicodeCollation,
677 PrevCommand->CommandString,
678 Command->CommandString
679 );
680
681 //
682 // Swap PrevCommand and Command list entry if PrevCommand list entry
683 // is alphabetically greater than Command list entry
684 //
685 if (LexicalMatchValue > 0) {
686 Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)SwapListEntries (&PrevCommand->Link, &Command->Link);
687 } else if (LexicalMatchValue < 0) {
688 //
689 // PrevCommand entry is lexically lower than Command entry
690 //
691 break;
692 }
693 }
694
695 return (RETURN_SUCCESS);
696}
697
704CONST CHAR16 *
705EFIAPI
707 VOID
708 )
709{
710 return (mProfileList);
711}
712
737RETURN_STATUS
738EFIAPI
740 IN CONST CHAR16 *CommandString,
741 IN OUT SHELL_STATUS *RetVal,
742 IN OUT BOOLEAN *CanAffectLE OPTIONAL
743 )
744{
747
748 //
749 // assert for NULL parameters
750 //
751 ASSERT (CommandString != NULL);
752
753 //
754 // check for the command
755 //
756 for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
757 ; !IsNull (&mCommandList.Link, &Node->Link)
758 ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
759 )
760 {
761 ASSERT (Node->CommandString != NULL);
762 if (gUnicodeCollation->StriColl (
763 gUnicodeCollation,
764 (CHAR16 *)CommandString,
765 Node->CommandString
766 ) == 0
767 )
768 {
769 if (CanAffectLE != NULL) {
770 *CanAffectLE = Node->LastError;
771 }
772
773 if (RetVal != NULL) {
774 *RetVal = Node->CommandHandler (NULL, gST);
775 } else {
776 Node->CommandHandler (NULL, gST);
777 }
778
779 return (RETURN_SUCCESS);
780 }
781 }
782
783 //
784 // An internal command was not found, try to find a dynamic command
785 //
786 DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand (CommandString);
787 if (DynamicCommand != NULL) {
788 if (RetVal != NULL) {
789 *RetVal = DynamicCommand->Handler (DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
790 } else {
791 DynamicCommand->Handler (DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
792 }
793
794 return (RETURN_SUCCESS);
795 }
796
797 return (RETURN_NOT_FOUND);
798}
799
813CONST CHAR16 *
814EFIAPI
816 IN CONST CHAR16 *CommandString
817 )
818{
820
821 //
822 // assert for NULL parameters
823 //
824 ASSERT (CommandString != NULL);
825
826 //
827 // check for the command
828 //
829 for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
830 ; !IsNull (&mCommandList.Link, &Node->Link)
831 ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Node->Link)
832 )
833 {
834 ASSERT (Node->CommandString != NULL);
835 if (gUnicodeCollation->StriColl (
836 gUnicodeCollation,
837 (CHAR16 *)CommandString,
838 Node->CommandString
839 ) == 0
840 )
841 {
842 return (Node->GetManFileName ());
843 }
844 }
845
846 return (NULL);
847}
848
859EFIAPI
861 IN CONST BOOLEAN Sort
862 )
863{
864 // if (!Sort) {
865 // return ((COMMAND_LIST*)(&mCommandList));
866 // }
867 return ((COMMAND_LIST *)(&mCommandList));
868}
869
883RETURN_STATUS
884EFIAPI
886 IN CONST CHAR16 *Command,
887 IN CONST CHAR16 *Alias
888 )
889{
890 ALIAS_LIST *Node;
891 ALIAS_LIST *CommandAlias;
892 ALIAS_LIST *PrevCommandAlias;
893 INTN LexicalMatchValue;
894
895 //
896 // Asserts for NULL
897 //
898 ASSERT (Command != NULL);
899 ASSERT (Alias != NULL);
900
901 //
902 // allocate memory for new struct
903 //
904 Node = AllocateZeroPool (sizeof (ALIAS_LIST));
905 if (Node == NULL) {
907 }
908
909 Node->CommandString = AllocateCopyPool (StrSize (Command), Command);
910 if (Node->CommandString == NULL) {
911 FreePool (Node);
913 }
914
915 Node->Alias = AllocateCopyPool (StrSize (Alias), Alias);
916 if (Node->Alias == NULL) {
917 FreePool (Node->CommandString);
918 FreePool (Node);
920 }
921
922 InsertHeadList (&mAliasList.Link, &Node->Link);
923
924 //
925 // Move a new pre-defined registered alias to its sorted ordered location in the list
926 //
927 for ( CommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link),
928 PrevCommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)
929 ; !IsNull (&mAliasList.Link, &CommandAlias->Link)
930 ; CommandAlias = (ALIAS_LIST *)GetNextNode (&mAliasList.Link, &CommandAlias->Link))
931 {
932 //
933 // Get Lexical comparison value between PrevCommandAlias and CommandAlias List Entry
934 //
935 LexicalMatchValue = gUnicodeCollation->StriColl (
936 gUnicodeCollation,
937 PrevCommandAlias->Alias,
938 CommandAlias->Alias
939 );
940
941 //
942 // Swap PrevCommandAlias and CommandAlias list entry if PrevCommandAlias list entry
943 // is alphabetically greater than CommandAlias list entry
944 //
945 if (LexicalMatchValue > 0) {
946 CommandAlias = (ALIAS_LIST *)SwapListEntries (&PrevCommandAlias->Link, &CommandAlias->Link);
947 } else if (LexicalMatchValue < 0) {
948 //
949 // PrevCommandAlias entry is lexically lower than CommandAlias entry
950 //
951 break;
952 }
953 }
954
955 return (RETURN_SUCCESS);
956}
957
966EFIAPI
968 VOID
969 )
970{
971 return (&mAliasList);
972}
973
982BOOLEAN
983EFIAPI
985 IN CONST CHAR16 *Alias
986 )
987{
988 ALIAS_LIST *Node;
989
990 //
991 // assert for NULL parameter
992 //
993 ASSERT (Alias != NULL);
994
995 //
996 // check for the Alias
997 //
998 for ( Node = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)
999 ; !IsNull (&mAliasList.Link, &Node->Link)
1000 ; Node = (ALIAS_LIST *)GetNextNode (&mAliasList.Link, &Node->Link)
1001 )
1002 {
1003 ASSERT (Node->CommandString != NULL);
1004 ASSERT (Node->Alias != NULL);
1005 if (gUnicodeCollation->StriColl (
1006 gUnicodeCollation,
1007 (CHAR16 *)Alias,
1008 Node->CommandString
1009 ) == 0
1010 )
1011 {
1012 return (TRUE);
1013 }
1014
1015 if (gUnicodeCollation->StriColl (
1016 gUnicodeCollation,
1017 (CHAR16 *)Alias,
1018 Node->Alias
1019 ) == 0
1020 )
1021 {
1022 return (TRUE);
1023 }
1024 }
1025
1026 return (FALSE);
1027}
1028
1036BOOLEAN
1037EFIAPI
1039 VOID
1040 )
1041{
1042 return (mEchoState);
1043}
1044
1054VOID
1055EFIAPI
1057 IN BOOLEAN State
1058 )
1059{
1060 mEchoState = State;
1061}
1062
1069VOID
1070EFIAPI
1072 IN BOOLEAN ScriptOnly,
1073 IN CONST UINT64 ErrorCode
1074 )
1075{
1076 mExitRequested = (BOOLEAN)(!mExitRequested);
1077 if (mExitRequested) {
1078 mExitScript = ScriptOnly;
1079 } else {
1080 mExitScript = FALSE;
1081 }
1082
1083 mExitCode = ErrorCode;
1084}
1085
1092BOOLEAN
1093EFIAPI
1095 VOID
1096 )
1097{
1098 return (mExitRequested);
1099}
1100
1108UINT64
1109EFIAPI
1111 VOID
1112 )
1113{
1114 return (mExitCode);
1115}
1116
1125BOOLEAN
1126EFIAPI
1128 VOID
1129 )
1130{
1131 return (mExitScript);
1132}
1133
1139VOID
1140EFIAPI
1142 IN SCRIPT_FILE *Script
1143 )
1144{
1145 UINTN LoopVar;
1146
1147 if (Script == NULL) {
1148 return;
1149 }
1150
1151 for (LoopVar = 0; LoopVar < Script->Argc; LoopVar++) {
1152 SHELL_FREE_NON_NULL (Script->Argv[LoopVar]);
1153 }
1154
1155 if (Script->Argv != NULL) {
1156 SHELL_FREE_NON_NULL (Script->Argv);
1157 }
1158
1159 Script->CurrentCommand = NULL;
1160 while (!IsListEmpty (&Script->CommandList)) {
1161 Script->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode (&Script->CommandList);
1162 if (Script->CurrentCommand != NULL) {
1163 RemoveEntryList (&Script->CurrentCommand->Link);
1164 if (Script->CurrentCommand->Cl != NULL) {
1165 SHELL_FREE_NON_NULL (Script->CurrentCommand->Cl);
1166 }
1167
1168 if (Script->CurrentCommand->Data != NULL) {
1169 SHELL_FREE_NON_NULL (Script->CurrentCommand->Data);
1170 }
1171
1172 SHELL_FREE_NON_NULL (Script->CurrentCommand);
1173 }
1174 }
1175
1176 SHELL_FREE_NON_NULL (Script->ScriptName);
1177 SHELL_FREE_NON_NULL (Script);
1178}
1179
1187EFIAPI
1189 VOID
1190 )
1191{
1192 SCRIPT_FILE_LIST *List;
1193
1194 if (IsListEmpty (&mScriptList.Link)) {
1195 return (NULL);
1196 }
1197
1198 List = ((SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link));
1199 return (List->Data);
1200}
1201
1214EFIAPI
1216 IN SCRIPT_FILE *Script OPTIONAL
1217 )
1218{
1219 SCRIPT_FILE_LIST *Node;
1220
1221 if (Script == NULL) {
1222 if (IsListEmpty (&mScriptList.Link)) {
1223 return (NULL);
1224 }
1225
1226 Node = (SCRIPT_FILE_LIST *)GetFirstNode (&mScriptList.Link);
1227 RemoveEntryList (&Node->Link);
1228 DeleteScriptFileStruct (Node->Data);
1229 FreePool (Node);
1230 } else {
1231 Node = AllocateZeroPool (sizeof (SCRIPT_FILE_LIST));
1232 if (Node == NULL) {
1233 return (NULL);
1234 }
1235
1236 Node->Data = Script;
1237 InsertHeadList (&mScriptList.Link, &Node->Link);
1238 }
1239
1241}
1242
1253CHAR16 *
1254EFIAPI
1256 IN CONST SHELL_MAPPING_TYPE Type
1257 )
1258{
1259 CHAR16 *String;
1260
1261 ASSERT (Type < MappingTypeMax);
1262
1263 String = NULL;
1264
1265 String = AllocateZeroPool (PcdGet8 (PcdShellMapNameLength) * sizeof (String[0]));
1266 if (String == NULL) {
1267 return (NULL);
1268 }
1269
1271 String,
1272 PcdGet8 (PcdShellMapNameLength) * sizeof (String[0]),
1273 Type == MappingTypeFileSystem ? L"FS%d:" : L"BLK%d:",
1274 Type == MappingTypeFileSystem ? mFsMaxCount++ : mBlkMaxCount++
1275 );
1276
1277 return (String);
1278}
1279
1298EFIAPI
1300 IN CONST CHAR16 *Name,
1301 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1302 IN CONST UINT64 Flags,
1303 IN CONST BOOLEAN Path
1304 )
1305{
1306 EFI_STATUS Status;
1307 SHELL_MAP_LIST *MapListNode;
1308 CONST CHAR16 *OriginalPath;
1309 CHAR16 *NewPath;
1310 UINTN NewPathSize;
1311
1312 NewPathSize = 0;
1313 NewPath = NULL;
1314 OriginalPath = NULL;
1315 Status = EFI_SUCCESS;
1316
1317 MapListNode = AllocateZeroPool (sizeof (SHELL_MAP_LIST));
1318 if (MapListNode == NULL) {
1319 Status = EFI_OUT_OF_RESOURCES;
1320 } else {
1321 MapListNode->Flags = Flags;
1322 MapListNode->MapName = AllocateCopyPool (StrSize (Name), Name);
1323 MapListNode->DevicePath = DuplicateDevicePath (DevicePath);
1324 if ((MapListNode->MapName == NULL) || (MapListNode->DevicePath == NULL)) {
1325 Status = EFI_OUT_OF_RESOURCES;
1326 } else {
1327 InsertTailList (&gShellMapList.Link, &MapListNode->Link);
1328 }
1329 }
1330
1331 if (EFI_ERROR (Status)) {
1332 if (MapListNode != NULL) {
1333 if (MapListNode->DevicePath != NULL) {
1334 FreePool (MapListNode->DevicePath);
1335 }
1336
1337 if (MapListNode->MapName != NULL) {
1338 FreePool (MapListNode->MapName);
1339 }
1340
1341 FreePool (MapListNode);
1342 }
1343 } else if (Path) {
1344 //
1345 // Since there was no error and Path was TRUE
1346 // Now add the correct path for that mapping
1347 //
1348 OriginalPath = gEfiShellProtocol->GetEnv (L"path");
1349 ASSERT ((NewPath == NULL && NewPathSize == 0) || (NewPath != NULL));
1350 if (OriginalPath != NULL) {
1351 StrnCatGrow (&NewPath, &NewPathSize, OriginalPath, 0);
1352 StrnCatGrow (&NewPath, &NewPathSize, L";", 0);
1353 }
1354
1355 StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
1356 StrnCatGrow (&NewPath, &NewPathSize, L"\\efi\\tools\\;", 0);
1357 StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
1358 StrnCatGrow (&NewPath, &NewPathSize, L"\\efi\\boot\\;", 0);
1359 StrnCatGrow (&NewPath, &NewPathSize, Name, 0);
1360 StrnCatGrow (&NewPath, &NewPathSize, L"\\", 0);
1361
1362 Status = gEfiShellProtocol->SetEnv (L"path", NewPath, TRUE);
1363 ASSERT_EFI_ERROR (Status);
1364 FreePool (NewPath);
1365 }
1366
1367 return (Status);
1368}
1369
1388EFIAPI
1390 VOID
1391 )
1392{
1393 EFI_STATUS Status;
1394 EFI_HANDLE *HandleList;
1395 UINTN Count;
1396 EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
1397 CHAR16 *NewDefaultName;
1398 CHAR16 *NewConsistName;
1399 EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
1400 SHELL_MAP_LIST *MapListNode;
1401 CONST CHAR16 *CurDir;
1402 CHAR16 *SplitCurDir;
1403 CHAR16 *MapName;
1404 SHELL_MAP_LIST *MapListItem;
1405
1406 ConsistMappingTable = NULL;
1407 SplitCurDir = NULL;
1408 MapName = NULL;
1409 MapListItem = NULL;
1410 HandleList = NULL;
1411
1412 //
1413 // Reset the static members back to zero
1414 //
1415 mFsMaxCount = 0;
1416 mBlkMaxCount = 0;
1417
1418 gEfiShellProtocol->SetEnv (L"path", L"", TRUE);
1419
1420 //
1421 // First empty out the existing list.
1422 //
1423 if (!IsListEmpty (&gShellMapList.Link)) {
1424 for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
1425 ; !IsListEmpty (&gShellMapList.Link)
1426 ; MapListNode = (SHELL_MAP_LIST *)GetFirstNode (&gShellMapList.Link)
1427 )
1428 {
1429 RemoveEntryList (&MapListNode->Link);
1430 SHELL_FREE_NON_NULL (MapListNode->DevicePath);
1431 SHELL_FREE_NON_NULL (MapListNode->MapName);
1432 SHELL_FREE_NON_NULL (MapListNode->CurrentDirectoryPath);
1433 FreePool (MapListNode);
1434 } // for loop
1435 }
1436
1437 //
1438 // Find each handle with Simple File System
1439 //
1440 HandleList = GetHandleListByProtocol (&gEfiSimpleFileSystemProtocolGuid);
1441 if (HandleList != NULL) {
1442 //
1443 // Do a count of the handles
1444 //
1445 for (Count = 0; HandleList[Count] != NULL; Count++) {
1446 }
1447
1448 //
1449 // Get all Device Paths
1450 //
1451 DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
1452 if (DevicePathList == NULL) {
1453 SHELL_FREE_NON_NULL (HandleList);
1454 return EFI_OUT_OF_RESOURCES;
1455 }
1456
1457 for (Count = 0; HandleList[Count] != NULL; Count++) {
1458 DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
1459 }
1460
1461 //
1462 // Sort all DevicePaths
1463 //
1464 PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
1465
1466 Status = ShellCommandConsistMappingInitialize (&ConsistMappingTable);
1467 if (EFI_ERROR (Status)) {
1468 SHELL_FREE_NON_NULL (HandleList);
1469 SHELL_FREE_NON_NULL (DevicePathList);
1470 return Status;
1471 }
1472
1473 //
1474 // Assign new Mappings to all...
1475 //
1476 for (Count = 0; HandleList[Count] != NULL; Count++) {
1477 //
1478 // Get default name first
1479 //
1480 NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeFileSystem);
1481 if (NewDefaultName == NULL) {
1482 ASSERT (NewDefaultName != NULL);
1483 Status = EFI_OUT_OF_RESOURCES;
1484 break;
1485 }
1486
1487 Status = ShellCommandAddMapItemAndUpdatePath (NewDefaultName, DevicePathList[Count], 0, TRUE);
1488 ASSERT_EFI_ERROR (Status);
1489 FreePool (NewDefaultName);
1490
1491 //
1492 // Now do consistent name
1493 //
1494 NewConsistName = ShellCommandConsistMappingGenMappingName (DevicePathList[Count], ConsistMappingTable);
1495 if (NewConsistName != NULL) {
1496 Status = ShellCommandAddMapItemAndUpdatePath (NewConsistName, DevicePathList[Count], 0, FALSE);
1497 ASSERT_EFI_ERROR (Status);
1498 FreePool (NewConsistName);
1499 }
1500 }
1501
1502 if (ConsistMappingTable != NULL) {
1503 ShellCommandConsistMappingUnInitialize (ConsistMappingTable);
1504 }
1505
1506 SHELL_FREE_NON_NULL (HandleList);
1507 SHELL_FREE_NON_NULL (DevicePathList);
1508
1509 HandleList = NULL;
1510
1511 //
1512 // gShellCurMapping point to node of current file system in the gShellMapList. When reset all mappings,
1513 // all nodes in the gShellMapList will be free. Then gShellCurMapping will be a dangling pointer, So,
1514 // after created new mappings, we should reset the gShellCurMapping pointer back to node of current file system.
1515 //
1516 if (gShellCurMapping != NULL) {
1518 CurDir = gEfiShellProtocol->GetEnv (L"cwd");
1519 if (CurDir != NULL) {
1520 MapName = AllocateCopyPool (StrSize (CurDir), CurDir);
1521 if (MapName == NULL) {
1522 return EFI_OUT_OF_RESOURCES;
1523 }
1524
1525 SplitCurDir = StrStr (MapName, L":");
1526 if (SplitCurDir == NULL) {
1527 SHELL_FREE_NON_NULL (MapName);
1528 return EFI_UNSUPPORTED;
1529 }
1530
1531 *(SplitCurDir + 1) = CHAR_NULL;
1532 MapListItem = ShellCommandFindMapItem (MapName);
1533 if (MapListItem != NULL) {
1534 gShellCurMapping = MapListItem;
1535 }
1536
1537 SHELL_FREE_NON_NULL (MapName);
1538 }
1539 }
1540 } else {
1541 Count = (UINTN)-1;
1542 }
1543
1544 //
1545 // Find each handle with Block Io
1546 //
1547 HandleList = GetHandleListByProtocol (&gEfiBlockIoProtocolGuid);
1548 if (HandleList != NULL) {
1549 for (Count = 0; HandleList[Count] != NULL; Count++) {
1550 }
1551
1552 //
1553 // Get all Device Paths
1554 //
1555 DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
1556 if (DevicePathList == NULL) {
1557 SHELL_FREE_NON_NULL (HandleList);
1558 return EFI_OUT_OF_RESOURCES;
1559 }
1560
1561 for (Count = 0; HandleList[Count] != NULL; Count++) {
1562 DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
1563 }
1564
1565 //
1566 // Sort all DevicePaths
1567 //
1568 PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
1569
1570 //
1571 // Assign new Mappings to all...
1572 //
1573 for (Count = 0; HandleList[Count] != NULL; Count++) {
1574 //
1575 // Get default name first
1576 //
1577 NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeBlockIo);
1578 if (NewDefaultName == NULL) {
1579 ASSERT (NewDefaultName != NULL);
1580 SHELL_FREE_NON_NULL (HandleList);
1581 SHELL_FREE_NON_NULL (DevicePathList);
1582 return EFI_OUT_OF_RESOURCES;
1583 }
1584
1585 Status = ShellCommandAddMapItemAndUpdatePath (NewDefaultName, DevicePathList[Count], 0, FALSE);
1586 ASSERT_EFI_ERROR (Status);
1587 FreePool (NewDefaultName);
1588 }
1589
1590 SHELL_FREE_NON_NULL (HandleList);
1591 SHELL_FREE_NON_NULL (DevicePathList);
1592 } else if (Count == (UINTN)-1) {
1593 return (EFI_NOT_FOUND);
1594 }
1595
1596 return (EFI_SUCCESS);
1597}
1598
1605EFIAPI
1607 VOID
1608 )
1609{
1610 EFI_STATUS Status;
1611 EFI_HANDLE *HandleList;
1612 UINTN Count;
1613 EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
1614 CHAR16 *NewDefaultName;
1615 CHAR16 *NewConsistName;
1616 EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
1617
1618 HandleList = NULL;
1619 Status = EFI_SUCCESS;
1620
1621 //
1622 // remove mappings that represent removed devices.
1623 //
1624
1625 //
1626 // Find each handle with Simple File System
1627 //
1628 HandleList = GetHandleListByProtocol (&gEfiSimpleFileSystemProtocolGuid);
1629 if (HandleList != NULL) {
1630 //
1631 // Do a count of the handles
1632 //
1633 for (Count = 0; HandleList[Count] != NULL; Count++) {
1634 }
1635
1636 //
1637 // Get all Device Paths
1638 //
1639 DevicePathList = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL *) * Count);
1640 if (DevicePathList == NULL) {
1641 return (EFI_OUT_OF_RESOURCES);
1642 }
1643
1644 for (Count = 0; HandleList[Count] != NULL; Count++) {
1645 DevicePathList[Count] = DevicePathFromHandle (HandleList[Count]);
1646 }
1647
1648 //
1649 // Sort all DevicePaths
1650 //
1651 PerformQuickSort (DevicePathList, Count, sizeof (EFI_DEVICE_PATH_PROTOCOL *), DevicePathCompare);
1652
1653 Status = ShellCommandConsistMappingInitialize (&ConsistMappingTable);
1654 if (EFI_ERROR (Status)) {
1655 SHELL_FREE_NON_NULL (HandleList);
1656 SHELL_FREE_NON_NULL (DevicePathList);
1657 return Status;
1658 }
1659
1660 //
1661 // Assign new Mappings to remainders
1662 //
1663 for (Count = 0; !EFI_ERROR (Status) && HandleList[Count] != NULL; Count++) {
1664 //
1665 // Skip ones that already have
1666 //
1667 if (gEfiShellProtocol->GetMapFromDevicePath (&DevicePathList[Count]) != NULL) {
1668 continue;
1669 }
1670
1671 //
1672 // Get default name
1673 //
1674 NewDefaultName = ShellCommandCreateNewMappingName (MappingTypeFileSystem);
1675 if (NewDefaultName == NULL) {
1676 Status = EFI_OUT_OF_RESOURCES;
1677 break;
1678 }
1679
1680 //
1681 // Call shell protocol SetMap function now...
1682 //
1683 Status = gEfiShellProtocol->SetMap (DevicePathList[Count], NewDefaultName);
1684
1685 if (!EFI_ERROR (Status)) {
1686 //
1687 // Now do consistent name
1688 //
1689 NewConsistName = ShellCommandConsistMappingGenMappingName (DevicePathList[Count], ConsistMappingTable);
1690 if (NewConsistName != NULL) {
1691 Status = gEfiShellProtocol->SetMap (DevicePathList[Count], NewConsistName);
1692 FreePool (NewConsistName);
1693 }
1694 }
1695
1696 FreePool (NewDefaultName);
1697 }
1698
1699 ShellCommandConsistMappingUnInitialize (ConsistMappingTable);
1700 SHELL_FREE_NON_NULL (HandleList);
1701 SHELL_FREE_NON_NULL (DevicePathList);
1702
1703 HandleList = NULL;
1704 } else {
1705 Count = (UINTN)-1;
1706 }
1707
1708 //
1709 // Do it all over again for gEfiBlockIoProtocolGuid
1710 //
1711
1712 return (Status);
1713}
1714
1723EFIAPI
1725 IN CONST SHELL_FILE_HANDLE Handle
1726 )
1727{
1728 return ((EFI_FILE_PROTOCOL *)(Handle));
1729}
1730
1740SHELL_FILE_HANDLE
1741EFIAPI
1743 IN CONST EFI_FILE_PROTOCOL *Handle,
1744 IN CONST CHAR16 *Path
1745 )
1746{
1748 BUFFER_LIST *NewNode;
1749
1750 if (Path != NULL) {
1751 Buffer = AllocateZeroPool (sizeof (SHELL_COMMAND_FILE_HANDLE));
1752 if (Buffer == NULL) {
1753 return (NULL);
1754 }
1755
1756 NewNode = AllocateZeroPool (sizeof (BUFFER_LIST));
1757 if (NewNode == NULL) {
1758 SHELL_FREE_NON_NULL (Buffer);
1759 return (NULL);
1760 }
1761
1762 Buffer->FileHandle = (EFI_FILE_PROTOCOL *)Handle;
1763 Buffer->Path = StrnCatGrow (&Buffer->Path, NULL, Path, 0);
1764 if (Buffer->Path == NULL) {
1765 SHELL_FREE_NON_NULL (NewNode);
1766 SHELL_FREE_NON_NULL (Buffer);
1767 return (NULL);
1768 }
1769
1770 NewNode->Buffer = Buffer;
1771
1772 InsertHeadList (&mFileHandleList.Link, &NewNode->Link);
1773 }
1774
1775 return ((SHELL_FILE_HANDLE)(Handle));
1776}
1777
1785CONST CHAR16 *
1786EFIAPI
1788 IN CONST SHELL_FILE_HANDLE Handle
1789 )
1790{
1791 BUFFER_LIST *Node;
1792
1793 for (Node = (BUFFER_LIST *)GetFirstNode (&mFileHandleList.Link)
1794 ; !IsNull (&mFileHandleList.Link, &Node->Link)
1795 ; Node = (BUFFER_LIST *)GetNextNode (&mFileHandleList.Link, &Node->Link)
1796 )
1797 {
1798 if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)) {
1799 return (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
1800 }
1801 }
1802
1803 return (NULL);
1804}
1805
1814BOOLEAN
1815EFIAPI
1817 IN CONST SHELL_FILE_HANDLE Handle
1818 )
1819{
1820 BUFFER_LIST *Node;
1821
1822 for (Node = (BUFFER_LIST *)GetFirstNode (&mFileHandleList.Link)
1823 ; !IsNull (&mFileHandleList.Link, &Node->Link)
1824 ; Node = (BUFFER_LIST *)GetNextNode (&mFileHandleList.Link, &Node->Link)
1825 )
1826 {
1827 if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)) {
1828 RemoveEntryList (&Node->Link);
1829 SHELL_FREE_NON_NULL (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
1830 SHELL_FREE_NON_NULL (Node->Buffer);
1831 SHELL_FREE_NON_NULL (Node);
1832 return (TRUE);
1833 }
1834 }
1835
1836 return (FALSE);
1837}
1838
1851BOOLEAN
1852EFIAPI
1854 IN SHELL_FILE_HANDLE Handle
1855 )
1856{
1857 EFI_FILE_INFO *Info;
1858 UINT64 Pos;
1859 BOOLEAN RetVal;
1860
1861 //
1862 // ASSERT if Handle is NULL
1863 //
1864 ASSERT (Handle != NULL);
1865
1866 gEfiShellProtocol->GetFilePosition (Handle, &Pos);
1867 Info = gEfiShellProtocol->GetFileInfo (Handle);
1868 gEfiShellProtocol->SetFilePosition (Handle, Pos);
1869
1870 if (Info == NULL) {
1871 return (FALSE);
1872 }
1873
1874 if (Pos == Info->FileSize) {
1875 RetVal = TRUE;
1876 } else {
1877 RetVal = FALSE;
1878 }
1879
1880 FreePool (Info);
1881
1882 return (RetVal);
1883}
1884
1890VOID
1891EFIAPI
1893 IN BUFFER_LIST *List
1894 )
1895{
1896 BUFFER_LIST *BufferListEntry;
1897
1898 if (List == NULL) {
1899 return;
1900 }
1901
1902 //
1903 // enumerate through the buffer list and free all memory
1904 //
1905 for ( BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
1906 ; !IsListEmpty (&List->Link)
1907 ; BufferListEntry = (BUFFER_LIST *)GetFirstNode (&List->Link)
1908 )
1909 {
1910 RemoveEntryList (&BufferListEntry->Link);
1911 if (BufferListEntry->Buffer != NULL) {
1912 FreePool (BufferListEntry->Buffer);
1913 }
1914
1915 FreePool (BufferListEntry);
1916 }
1917}
1918
1927VOID
1928EFIAPI
1930 IN UINTN Indent,
1931 IN UINTN Offset,
1932 IN UINTN DataSize,
1933 IN VOID *UserData
1934 )
1935{
1936 UINT8 *Data;
1937
1938 CHAR8 Val[50];
1939
1940 CHAR8 Str[20];
1941
1942 UINT8 TempByte;
1943 UINTN Size;
1944 UINTN Index;
1945
1946 Data = UserData;
1947 while (DataSize != 0) {
1948 Size = 16;
1949 if (Size > DataSize) {
1950 Size = DataSize;
1951 }
1952
1953 for (Index = 0; Index < Size; Index += 1) {
1954 TempByte = Data[Index];
1955 Val[Index * 3 + 0] = Hex[TempByte >> 4];
1956 Val[Index * 3 + 1] = Hex[TempByte & 0xF];
1957 Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
1958 Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > '~') ? '.' : TempByte);
1959 }
1960
1961 Val[Index * 3] = 0;
1962 Str[Index] = 0;
1963 ShellPrintEx (-1, -1, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
1964
1965 Data += Size;
1966 Offset += Size;
1967 DataSize -= Size;
1968 }
1969}
1970
1980CHAR16 *
1981EFIAPI
1983 IN CHAR16 *Buffer,
1984 IN UINTN Indent,
1985 IN UINTN Offset,
1986 IN UINTN DataSize,
1987 IN VOID *UserData
1988 )
1989{
1990 UINT8 *Data;
1991 UINT8 TempByte;
1992 UINTN Size;
1993 UINTN Index;
1994 CHAR8 Val[50];
1995 CHAR8 Str[20];
1996 CHAR16 *RetVal;
1997 CHAR16 *TempRetVal;
1998
1999 Data = UserData;
2000 RetVal = Buffer;
2001 while (DataSize != 0) {
2002 Size = 16;
2003 if (Size > DataSize) {
2004 Size = DataSize;
2005 }
2006
2007 for (Index = 0; Index < Size; Index += 1) {
2008 TempByte = Data[Index];
2009 Val[Index * 3 + 0] = Hex[TempByte >> 4];
2010 Val[Index * 3 + 1] = Hex[TempByte & 0xF];
2011 Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
2012 Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
2013 }
2014
2015 Val[Index * 3] = 0;
2016 Str[Index] = 0;
2017 TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
2018 SHELL_FREE_NON_NULL (RetVal);
2019 RetVal = TempRetVal;
2020
2021 Data += Size;
2022 Offset += Size;
2023 DataSize -= Size;
2024 }
2025
2026 return RetVal;
2027}
2028
2044STATIC
2045INTN
2046EFIAPI
2048 IN CONST VOID *Unique1AsVoid,
2049 IN CONST VOID *Unique2AsVoid
2050 )
2051{
2054
2055 Unique1 = Unique1AsVoid;
2056 Unique2 = Unique2AsVoid;
2057
2058 //
2059 // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
2060 //
2061 return gUnicodeCollation->StriColl (
2062 gUnicodeCollation,
2063 (CHAR16 *)Unique1->Alias,
2064 (CHAR16 *)Unique2->Alias
2065 );
2066}
2067
2083STATIC
2084INTN
2085EFIAPI
2087 IN CONST VOID *UniqueAliasAsVoid,
2088 IN CONST VOID *UniqueAsVoid
2089 )
2090{
2091 CONST CHAR16 *UniqueAlias;
2093
2094 UniqueAlias = UniqueAliasAsVoid;
2095 Unique = UniqueAsVoid;
2096
2097 //
2098 // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
2099 //
2100 return gUnicodeCollation->StriColl (
2101 gUnicodeCollation,
2102 (CHAR16 *)UniqueAlias,
2103 (CHAR16 *)Unique->Alias
2104 );
2105}
2106
2164EFIAPI
2166 IN OUT EFI_SHELL_FILE_INFO **FileList,
2167 OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL,
2168 IN SHELL_SORT_FILE_LIST Order
2169 )
2170{
2171 LIST_ENTRY *FilesHead;
2172 ORDERED_COLLECTION *Sort;
2173 LIST_ENTRY *FileEntry;
2175 SHELL_SORT_UNIQUE_NAME *Unique;
2176 EFI_STATUS Status;
2177 EFI_SHELL_FILE_INFO *Dupes;
2178 LIST_ENTRY *NextFileEntry;
2179 CONST CHAR16 *Alias;
2180 ORDERED_COLLECTION_ENTRY *SortEntry;
2181 LIST_ENTRY *TargetFileList;
2182 ORDERED_COLLECTION_ENTRY *NextSortEntry;
2183 VOID *UniqueAsVoid;
2184
2185 if ((UINTN)Order >= (UINTN)ShellSortFileListMax) {
2186 return EFI_INVALID_PARAMETER;
2187 }
2188
2189 if (FileList == NULL) {
2190 //
2191 // FileList is considered empty, hence already sorted, with no duplicates.
2192 //
2193 if (Duplicates != NULL) {
2194 *Duplicates = NULL;
2195 }
2196
2197 return EFI_SUCCESS;
2198 }
2199
2200 if (*FileList == NULL) {
2201 return EFI_INVALID_PARAMETER;
2202 }
2203
2204 FilesHead = &(*FileList)->Link;
2205
2206 //
2207 // Collect all the unique names.
2208 //
2210 if (Sort == NULL) {
2211 return EFI_OUT_OF_RESOURCES;
2212 }
2213
2214 BASE_LIST_FOR_EACH (FileEntry, FilesHead) {
2215 FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
2216
2217 //
2218 // Try to record the name of this file as a unique name.
2219 //
2220 Unique = AllocatePool (sizeof (*Unique));
2221 if (Unique == NULL) {
2222 Status = EFI_OUT_OF_RESOURCES;
2223 goto UninitSort;
2224 }
2225
2226 Unique->Alias = ((Order == ShellSortFileListByFileName) ?
2228 FileInfo->FullName);
2229 InitializeListHead (&Unique->SameNameList);
2230
2231 Status = OrderedCollectionInsert (Sort, NULL, Unique);
2232 if (EFI_ERROR (Status)) {
2233 //
2234 // Only two errors are possible: memory allocation failed, or this name
2235 // has been encountered before. In either case, the
2236 // SHELL_SORT_UNIQUE_NAME object being constructed has to be released.
2237 //
2238 FreePool (Unique);
2239 //
2240 // Memory allocation failure is fatal, while having seen the same name
2241 // before is normal.
2242 //
2243 if (Status == EFI_OUT_OF_RESOURCES) {
2244 goto UninitSort;
2245 }
2246
2247 ASSERT (Status == EFI_ALREADY_STARTED);
2248 }
2249 }
2250
2251 //
2252 // Set Dupes to suppress incorrect compiler/analyzer warnings.
2253 //
2254 Dupes = NULL;
2255
2256 //
2257 // If separation of duplicates has been requested, allocate the list for
2258 // them.
2259 //
2260 if (Duplicates != NULL) {
2261 Dupes = AllocateZeroPool (sizeof (*Dupes));
2262 if (Dupes == NULL) {
2263 Status = EFI_OUT_OF_RESOURCES;
2264 goto UninitSort;
2265 }
2266
2267 InitializeListHead (&Dupes->Link);
2268 }
2269
2270 //
2271 // No memory allocation beyond this point; thus, no chance to fail. We can
2272 // now migrate the EFI_SHELL_FILE_INFO objects from (*FileList) to Sort.
2273 //
2274 BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, FilesHead) {
2275 FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
2276 //
2277 // Look up the SHELL_SORT_UNIQUE_NAME that matches FileInfo's name.
2278 //
2279 Alias = ((Order == ShellSortFileListByFileName) ?
2281 FileInfo->FullName);
2282 SortEntry = OrderedCollectionFind (Sort, Alias);
2283 ASSERT (SortEntry != NULL);
2284 Unique = OrderedCollectionUserStruct (SortEntry);
2285 //
2286 // Move FileInfo from (*FileList) to the end of the list of files whose
2287 // names all compare identical to FileInfo's name.
2288 //
2289 RemoveEntryList (&FileInfo->Link);
2290 InsertTailList (&Unique->SameNameList, &FileInfo->Link);
2291 }
2292
2293 //
2294 // All EFI_SHELL_FILE_INFO objects originally in (*FileList) have been
2295 // distributed to Sort. Now migrate them back to (*FileList), advancing in
2296 // unique name order.
2297 //
2298 for (SortEntry = OrderedCollectionMin (Sort);
2299 SortEntry != NULL;
2300 SortEntry = OrderedCollectionNext (SortEntry))
2301 {
2302 Unique = OrderedCollectionUserStruct (SortEntry);
2303 //
2304 // The first FileInfo encountered for each unique name goes back on
2305 // (*FileList) unconditionally. Further FileInfo instances for the same
2306 // unique name -- that is, duplicates -- are either returned to (*FileList)
2307 // or separated, dependent on the caller's request.
2308 //
2309 TargetFileList = FilesHead;
2310 BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, &Unique->SameNameList) {
2311 RemoveEntryList (FileEntry);
2312 InsertTailList (TargetFileList, FileEntry);
2313 if (Duplicates != NULL) {
2314 TargetFileList = &Dupes->Link;
2315 }
2316 }
2317 }
2318
2319 //
2320 // We're done. If separation of duplicates has been requested, output the
2321 // list of duplicates -- and free that list at once, if it's empty (i.e., if
2322 // no duplicates have been found).
2323 //
2324 if (Duplicates != NULL) {
2325 if (IsListEmpty (&Dupes->Link)) {
2326 FreePool (Dupes);
2327 *Duplicates = NULL;
2328 } else {
2329 *Duplicates = Dupes;
2330 }
2331 }
2332
2333 Status = EFI_SUCCESS;
2334
2335 //
2336 // Fall through.
2337 //
2338UninitSort:
2339 for (SortEntry = OrderedCollectionMin (Sort);
2340 SortEntry != NULL;
2341 SortEntry = NextSortEntry)
2342 {
2343 NextSortEntry = OrderedCollectionNext (SortEntry);
2344 OrderedCollectionDelete (Sort, SortEntry, &UniqueAsVoid);
2345 Unique = UniqueAsVoid;
2346 ASSERT (IsListEmpty (&Unique->SameNameList));
2347 FreePool (Unique);
2348 }
2349
2351
2352 return Status;
2353}
UINT64 UINTN
INT64 INTN
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
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
#define BASE_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead)
Definition: BaseLib.h:2929
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI SwapListEntries(IN OUT LIST_ENTRY *FirstEntry, IN OUT LIST_ENTRY *SecondEntry)
Definition: LinkedList.c:522
#define BASE_LIST_FOR_EACH(Entry, ListHead)
Definition: BaseLib.h:2913
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
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
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DuplicateDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define EFI_PLATFORM_LANG_VARIABLE_NAME
EFI_HANDLE *EFIAPI GetHandleListByProtocol(IN CONST EFI_GUID *ProtocolGuid OPTIONAL)
EFI_STRING EFIAPI HiiGetString(IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID StringId, IN CONST CHAR8 *Language OPTIONAL)
Definition: HiiString.c:211
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 RETURN_NOT_FOUND
Definition: Base.h:1142
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_OUT_OF_RESOURCES
Definition: Base.h:1114
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define RETURN_ALREADY_STARTED
Definition: Base.h:1172
#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
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionFind(IN CONST ORDERED_COLLECTION *Collection, IN CONST VOID *StandaloneKey)
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionMin(IN CONST ORDERED_COLLECTION *Collection)
VOID *EFIAPI OrderedCollectionUserStruct(IN CONST ORDERED_COLLECTION_ENTRY *Entry)
RETURN_STATUS EFIAPI OrderedCollectionInsert(IN OUT ORDERED_COLLECTION *Collection, OUT ORDERED_COLLECTION_ENTRY **Entry OPTIONAL, IN VOID *UserStruct)
VOID EFIAPI OrderedCollectionUninit(IN ORDERED_COLLECTION *Collection)
ORDERED_COLLECTION *EFIAPI OrderedCollectionInit(IN ORDERED_COLLECTION_USER_COMPARE UserStructCompare, IN ORDERED_COLLECTION_KEY_COMPARE KeyCompare)
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionNext(IN CONST ORDERED_COLLECTION_ENTRY *Entry)
VOID EFIAPI OrderedCollectionDelete(IN OUT ORDERED_COLLECTION *Collection, IN ORDERED_COLLECTION_ENTRY *Entry, OUT VOID **UserStruct OPTIONAL)
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_FILE_INFO * FileInfo(IN EFI_FILE_HANDLE FHand)
SHELL_STATUS(EFIAPI * SHELL_RUN_COMMAND)(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
SHELL_MAP_LIST *EFIAPI ShellCommandFindMapItem(IN CONST CHAR16 *MapKey)
CONST CHAR16 *(EFIAPI * SHELL_GET_MAN_FILENAME)(VOID)
EFI_STATUS EFIAPI ShellCommandConsistMappingUnInitialize(EFI_DEVICE_PATH_PROTOCOL **Table)
CHAR16 *EFIAPI ShellCommandConsistMappingGenMappingName(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN EFI_DEVICE_PATH_PROTOCOL **Table)
EFI_STATUS EFIAPI ShellCommandConsistMappingInitialize(EFI_DEVICE_PATH_PROTOCOL ***Table)
CHAR16 *EFIAPI StrnCatGrow(IN OUT CHAR16 **Destination, IN OUT UINTN *CurrentSize, IN CONST CHAR16 *Source, IN UINTN Count)
EFI_STATUS EFIAPI ShellPrintEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR16 *Format,...)
CHAR16 * GetManFileName(IN CONST CHAR16 *ManFileName)
VOID EFIAPI PerformQuickSort(IN OUT VOID *BufferToSort, IN CONST UINTN Count, IN CONST UINTN ElementSize, IN SORT_COMPARE CompareFunction)
Definition: BaseSortLib.c:36
INTN EFIAPI DevicePathCompare(IN CONST VOID *Buffer1, IN CONST VOID *Buffer2)
Definition: BaseSortLib.c:73
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
VOID * EFI_HII_HANDLE
EFI_STATUS EFIAPI GetEfiGlobalVariable2(IN CONST CHAR16 *Name, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1470
CHAR16 *EFIAPI CatSPrint(IN CHAR16 *String OPTIONAL, IN CONST CHAR16 *FormatString,...)
Definition: UefiLibPrint.c:827
CHAR8 *EFIAPI GetBestLanguage(IN CONST CHAR8 *SupportedLanguages, IN UINTN Iso639Language,...)
Definition: UefiLib.c:1522
CHAR16 *EFIAPI ShellCommandCreateNewMappingName(IN CONST SHELL_MAPPING_TYPE Type)
BOOLEAN EFIAPI ShellCommandGetScriptExit(VOID)
CONST ALIAS_LIST *EFIAPI ShellCommandGetInitAliasList(VOID)
BOOLEAN EFIAPI ShellFileHandleRemove(IN CONST SHELL_FILE_HANDLE Handle)
STATIC INTN EFIAPI UniqueNameAliasCompare(IN CONST VOID *UniqueAliasAsVoid, IN CONST VOID *UniqueAsVoid)
BOOLEAN ShellCommandDynamicCommandExists(IN CONST CHAR16 *CommandString)
BOOLEAN ShellCommandIsCommandOnInternalList(IN CONST CHAR16 *CommandString)
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)
CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL * ShellCommandFindDynamicCommand(IN CONST CHAR16 *CommandString)
EFI_STATUS EFIAPI ShellCommandAddMapItemAndUpdatePath(IN CONST CHAR16 *Name, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST UINT64 Flags, IN CONST BOOLEAN Path)
CONST CHAR16 *EFIAPI ShellCommandGetManFileNameHandler(IN CONST CHAR16 *CommandString)
SHELL_MAP_LIST gShellMapList
List of Mappings - DeviceName and Drive Letter(ism).
BOOLEAN EFIAPI ShellCommandIsCommandOnList(IN CONST CHAR16 *CommandString)
CHAR16 * ShellCommandGetDynamicCommandHelp(IN CONST CHAR16 *CommandString)
CONST CHAR16 *EFIAPI ShellFileHandleGetPath(IN CONST SHELL_FILE_HANDLE Handle)
SHELL_MAP_LIST * gShellCurMapping
Pointer to node of current directory in the mMapList.
CHAR16 *EFIAPI ShellCommandGetCommandHelp(IN CONST CHAR16 *CommandString)
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)
EFI_FILE_PROTOCOL *EFIAPI ConvertShellHandleToEfiFileProtocol(IN CONST SHELL_FILE_HANDLE Handle)
RETURN_STATUS EFIAPI ShellCommandRegisterCommandName(IN CONST CHAR16 *CommandString, IN SHELL_RUN_COMMAND CommandHandler, IN SHELL_GET_MAN_FILENAME GetManFileName, IN UINT32 ShellMinSupportLevel, IN CONST CHAR16 *ProfileName, IN CONST BOOLEAN CanAffectLE, IN CONST EFI_HII_HANDLE HiiHandle, IN CONST EFI_STRING_ID ManFormatHelp)
UINT64 EFIAPI ShellCommandGetExitCode(VOID)
VOID EFIAPI DeleteScriptFileStruct(IN SCRIPT_FILE *Script)
STATIC INTN EFIAPI UniqueNameCompare(IN CONST VOID *Unique1AsVoid, IN CONST VOID *Unique2AsVoid)
SCRIPT_FILE *EFIAPI ShellCommandSetNewScript(IN SCRIPT_FILE *Script OPTIONAL)
BOOLEAN EFIAPI ShellCommandGetEchoState(VOID)
RETURN_STATUS EFIAPI ShellCommandLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
CONST COMMAND_LIST *EFIAPI ShellCommandGetCommandList(IN CONST BOOLEAN Sort)
RETURN_STATUS EFIAPI ShellCommandRegisterAlias(IN CONST CHAR16 *Command, IN CONST CHAR16 *Alias)
RETURN_STATUS EFIAPI ShellCommandLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI ShellCommandUpdateMapping(VOID)
EFI_STATUS EFIAPI ShellCommandCreateInitialMappingsAndPaths(VOID)
VOID FreeFileHandleList(IN BUFFER_LIST *List)
VOID EFIAPI ShellCommandSetEchoState(IN BOOLEAN State)
CHAR16 *EFIAPI CatSDumpHex(IN CHAR16 *Buffer, IN UINTN Indent, IN UINTN Offset, IN UINTN DataSize, IN VOID *UserData)
EFI_STATUS EFIAPI ShellSortFileList(IN OUT EFI_SHELL_FILE_INFO **FileList, OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL, IN SHELL_SORT_FILE_LIST Order)
BOOLEAN EFIAPI ShellCommandGetExit(VOID)
CONST CHAR16 *EFIAPI ShellCommandGetProfileList(VOID)
VOID EFIAPI DumpHex(IN UINTN Indent, IN UINTN Offset, IN UINTN DataSize, IN VOID *UserData)
SCRIPT_FILE *EFIAPI ShellCommandGetCurrentScriptFile(VOID)
CHAR16 * ShellCommandGetInternalCommandHelp(IN CONST CHAR16 *CommandString)
BOOLEAN EFIAPI ShellCommandIsOnAliasList(IN CONST CHAR16 *Alias)
@ ByProtocol
Definition: UefiSpec.h:1518
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL protocol structure.
CHAR16 FileName[1]
Definition: FileInfo.h:52
UINT64 FileSize
Definition: FileInfo.h:27
LIST_ENTRY Link
Linked list members.
Definition: Shell.h:153