ShellPkg/map: Fix out-of-bound read when "map fsn"
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Map.c
1 /** @file\r
2   Main file for map shell level 2 command.\r
3 \r
4   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
5   (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
6   (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
7   \r
8   This program and the accompanying materials\r
9   are licensed and made available under the terms and conditions of the BSD License\r
10   which accompanies this distribution.  The full text of the license may be found at\r
11   http://opensource.org/licenses/bsd-license.php\r
12 \r
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15 \r
16 **/\r
17 \r
18 #include "UefiShellLevel2CommandsLib.h"\r
19 #include <Protocol/SimpleFileSystem.h>\r
20 #include <Protocol/BlockIo.h>\r
21 #include <Library/DevicePathLib.h>\r
22 #include <Library/HandleParsingLib.h>\r
23 #include <Library/SortLib.h>\r
24 \r
25 /**\r
26   Determine if a string has only numbers and letters.\r
27 \r
28   This is useful for such things as Map names which can only be letters and numbers.\r
29 \r
30   @param[in] String       pointer to the string to analyze,\r
31   @param[in] Len          Number of characters to analyze.\r
32 \r
33   @retval TRUE            String has only numbers and letters\r
34   @retval FALSE           String has at least one other character.\r
35 **/\r
36 BOOLEAN\r
37 IsNumberLetterOnly(\r
38   IN CONST CHAR16 *String,\r
39   IN CONST UINTN  Len\r
40   )\r
41 {\r
42   UINTN Count;\r
43   for (Count = 0 ; Count < Len && String != NULL && *String != CHAR_NULL ; String++,Count++) {\r
44     if (! ((*String >= L'a' && *String <= L'z') ||\r
45            (*String >= L'A' && *String <= L'Z') ||\r
46            (*String >= L'0' && *String <= L'9'))\r
47         ){\r
48       return (FALSE);\r
49     }\r
50   }\r
51   return (TRUE);\r
52 }\r
53 \r
54 /**\r
55   Do a search in the Target delimited list.\r
56 \r
57   @param[in] List         The list to seatch in.\r
58   @param[in] MetaTarget   The item to search for. MetaMatching supported.\r
59   @param[out] FullName    Optional pointer to an allocated buffer containing \r
60                           the match.\r
61   @param[in] Meta         TRUE to use MetaMatching.\r
62   @param[in] SkipTrailingNumbers  TRUE to allow for numbers after the MetaTarget.\r
63   @param[in] Target       The single character that delimits list \r
64                           items (";" normally). \r
65 **/\r
66 BOOLEAN\r
67 SearchList(\r
68   IN CONST CHAR16   *List,\r
69   IN CONST CHAR16   *MetaTarget,\r
70   OUT CHAR16        **FullName OPTIONAL,\r
71   IN CONST BOOLEAN  Meta,\r
72   IN CONST BOOLEAN  SkipTrailingNumbers,\r
73   IN CONST CHAR16   *Target\r
74 \r
75   )\r
76 {\r
77   CHAR16        *TempList;\r
78   CONST CHAR16  *ListWalker;\r
79   BOOLEAN       Result;\r
80   CHAR16        *TempSpot;\r
81 \r
82   for (ListWalker = List , TempList = NULL\r
83      ; ListWalker != NULL && *ListWalker != CHAR_NULL\r
84      ;\r
85    ) {\r
86     TempList = StrnCatGrow(&TempList, NULL, ListWalker, 0);\r
87     ASSERT(TempList != NULL);\r
88     TempSpot = StrStr(TempList, Target);\r
89     if (TempSpot != NULL) {\r
90       *TempSpot = CHAR_NULL;\r
91     }\r
92 \r
93     while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter(TempList[StrLen(TempList)-1]) || TempList[StrLen(TempList)-1] == L':')) {\r
94       TempList[StrLen(TempList)-1] = CHAR_NULL;\r
95     }\r
96 \r
97     ListWalker = StrStr(ListWalker, Target);\r
98     while(ListWalker != NULL && *ListWalker == *Target) {\r
99       ListWalker++;\r
100     }\r
101     if (Meta) {\r
102       Result = gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)TempList, (CHAR16*)MetaTarget);\r
103     } else {\r
104       Result = (BOOLEAN)(StrCmp(TempList, MetaTarget)==0);\r
105     }\r
106     if (Result) {\r
107       if (FullName != NULL) {\r
108         *FullName = TempList;\r
109       } else {\r
110         FreePool(TempList);\r
111       }\r
112       return (TRUE);\r
113     }\r
114     FreePool(TempList);\r
115     TempList = NULL;\r
116   }\r
117 \r
118   return (FALSE);\r
119 }\r
120 \r
121 /**\r
122   Determine what type of device is represented and return it's string.  The \r
123   string is in allocated memory and must be callee freed.  The HII is is listed below.\r
124   The actual string cannot be determined.\r
125 \r
126   @param[in] DevicePath     The device to analyze.\r
127 \r
128   @retval STR_MAP_MEDIA_UNKNOWN   The media type is unknown.\r
129   @retval STR_MAP_MEDIA_HARDDISK  The media is a hard drive.\r
130   @retval STR_MAP_MEDIA_CDROM     The media is a CD ROM.\r
131   @retval STR_MAP_MEDIA_FLOPPY    The media is a floppy drive.\r
132 **/\r
133 CHAR16*\r
134 GetDeviceMediaType (\r
135   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
136   )\r
137 {\r
138   ACPI_HID_DEVICE_PATH  *Acpi;\r
139 \r
140   //\r
141   //  Parse the device path:\r
142   //  Devicepath sub type                 mediatype\r
143   //    MEDIA_HANRDDRIVE_DP      ->       Hard Disk\r
144   //    MEDIA_CDROM_DP           ->       CD Rom\r
145   //    Acpi.HID = 0X0604        ->       Floppy\r
146   //\r
147   if (NULL == DevicePath) {\r
148     return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);\r
149   }\r
150 \r
151   for (;!IsDevicePathEndType (DevicePath) ;DevicePath = NextDevicePathNode (DevicePath)) {\r
152     if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {\r
153       switch (DevicePathSubType (DevicePath)) {\r
154       case MEDIA_HARDDRIVE_DP:\r
155         return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_HARDDISK), NULL);\r
156       case MEDIA_CDROM_DP:\r
157         return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_CDROM), NULL);\r
158       }\r
159     } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) {\r
160       Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;\r
161       if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {\r
162         return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_FLOPPY), NULL);\r
163       }\r
164     }\r
165   }\r
166 \r
167   return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);\r
168 }\r
169 \r
170 /**\r
171   Function to detemine if a handle has removable storage.\r
172 \r
173   @param[in] DevicePath             DevicePath to test.\r
174 \r
175   @retval TRUE                      The handle has removable storage.\r
176   @retval FALSE                     The handle does not have removable storage.\r
177 **/\r
178 BOOLEAN\r
179 IsRemoveableDevice (\r
180   IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
181   )\r
182 {\r
183   if (NULL == DevicePath) {\r
184     return FALSE;\r
185   }\r
186 \r
187   while (!IsDevicePathEndType (DevicePath)) {\r
188     if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) {\r
189       switch (DevicePathSubType (DevicePath)) {\r
190       case MSG_USB_DP:\r
191       case MSG_SCSI_DP:\r
192         return TRUE;\r
193       default:\r
194         return FALSE;\r
195       }\r
196     }\r
197     DevicePath = NextDevicePathNode (DevicePath);\r
198   }\r
199   return FALSE;\r
200 }\r
201 \r
202 /**\r
203   Function to detemine if a something on the map list matches.\r
204 \r
205   @param[in] MapList          The pointer to the list to test.\r
206   @param[in] Specific         The pointer to a specific name to test for.\r
207   @param[in] TypeString       The pointer to the list of types.\r
208   @param[in] Normal           Always show normal mappings.\r
209   @param[in] Consist          Always show consistent mappings.\r
210 \r
211   @retval TRUE                The map should be displayed.\r
212   @retval FALSE               The map should not be displayed.\r
213 **/\r
214 BOOLEAN\r
215 MappingListHasType(\r
216   IN CONST CHAR16     *MapList,\r
217   IN CONST CHAR16     *Specific,\r
218   IN CONST CHAR16     *TypeString,\r
219   IN CONST BOOLEAN    Normal,\r
220   IN CONST BOOLEAN    Consist\r
221   )\r
222 {\r
223   CHAR16              *NewSpecific;\r
224   RETURN_STATUS       Status;\r
225   UINTN               Length;\r
226   \r
227   //\r
228   // specific has priority\r
229   //\r
230   if (Specific != NULL) {\r
231     Length      = StrLen (Specific);\r
232     //\r
233     // Allocate enough buffer for Specific and potential ":"\r
234     //\r
235     NewSpecific = AllocatePool ((Length + 2) * sizeof(CHAR16));\r
236     if (NewSpecific == NULL){\r
237       return FALSE;\r
238     }\r
239     StrCpyS (NewSpecific, Length + 2, Specific);\r
240     if (Specific[Length - 1] != L':') {\r
241       Status = StrnCatS(NewSpecific, Length + 2, L":", StrLen(L":"));\r
242       if (EFI_ERROR (Status)) {\r
243         FreePool(NewSpecific);\r
244         return FALSE;\r
245       }\r
246     }\r
247 \r
248     if (SearchList(MapList, NewSpecific, NULL, TRUE, FALSE, L";")) {\r
249       FreePool(NewSpecific);\r
250       return (TRUE);\r
251     }\r
252     FreePool(NewSpecific);\r
253   }\r
254   if (  Consist\r
255     && Specific == NULL\r
256     && (SearchList(MapList, L"HD*",  NULL, TRUE, TRUE, L";")\r
257       ||SearchList(MapList, L"CD*",  NULL, TRUE, TRUE, L";")\r
258       ||SearchList(MapList, L"F*",   NULL, TRUE, TRUE, L";")\r
259       ||SearchList(MapList, L"FP*",  NULL, TRUE, TRUE, L";"))){\r
260     return (TRUE);\r
261   }\r
262 \r
263   if (  Normal\r
264     && Specific == NULL\r
265     && (SearchList(MapList, L"FS",  NULL, FALSE, TRUE, L";")\r
266       ||SearchList(MapList, L"BLK", NULL, FALSE, TRUE, L";"))){\r
267     return (TRUE);\r
268   }\r
269 \r
270   if (TypeString != NULL && SearchList(MapList, TypeString,  NULL, TRUE, TRUE, L";")) {\r
271     return (TRUE);\r
272   }\r
273   return (FALSE);\r
274 }\r
275 \r
276 \r
277 /**\r
278   Display a single map line for device Handle if conditions are met.\r
279 \r
280   @param[in] Verbose                TRUE to display (extra) verbose information.\r
281   @param[in] Consist                TRUE to display consistent mappings.\r
282   @param[in] Normal                 TRUE to display normal (not consist) mappings.\r
283   @param[in] TypeString             pointer to string of filter types.\r
284   @param[in] SFO                    TRUE to display output in Standard Output Format.\r
285   @param[in] Specific               pointer to string for specific map to display.\r
286   @param[in] Handle                 The handle to display from.\r
287 \r
288   @retval EFI_SUCCESS               The mapping was displayed.\r
289 **/\r
290 EFI_STATUS\r
291 PerformSingleMappingDisplay(\r
292   IN CONST BOOLEAN    Verbose,\r
293   IN CONST BOOLEAN    Consist,\r
294   IN CONST BOOLEAN    Normal,\r
295   IN CONST CHAR16     *TypeString,\r
296   IN CONST BOOLEAN    SFO,\r
297   IN CONST CHAR16     *Specific OPTIONAL,\r
298   IN CONST EFI_HANDLE Handle\r
299   )\r
300 {\r
301   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
302   EFI_DEVICE_PATH_PROTOCOL  *DevPathCopy;\r
303   CONST CHAR16              *MapList;\r
304   CHAR16                    *CurrentName;\r
305   CHAR16                    *MediaType;\r
306   CHAR16                    *DevPathString;\r
307   CHAR16                    *TempSpot;\r
308   CHAR16                    *Alias;\r
309   UINTN                     TempLen;\r
310   BOOLEAN                   Removable;\r
311   CONST CHAR16              *TempSpot2;\r
312 \r
313   Alias       = NULL;\r
314   TempSpot2   = NULL;\r
315   CurrentName = NULL;\r
316   DevPath = DevicePathFromHandle(Handle);\r
317   DevPathCopy = DevPath;\r
318   MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);\r
319   if (MapList == NULL) {\r
320     return EFI_NOT_FOUND;\r
321   }\r
322 \r
323   if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){\r
324     return EFI_NOT_FOUND;\r
325   }\r
326 \r
327   if (Normal || !Consist) {\r
328     //\r
329     // need the Normal here since people can use both on command line.  otherwise unused.\r
330     //\r
331 \r
332     //\r
333     // Allocate a name\r
334     //\r
335     CurrentName = NULL;\r
336     CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0);\r
337     if (CurrentName == NULL) {\r
338       return (EFI_OUT_OF_RESOURCES);\r
339     }\r
340 \r
341     //\r
342     // Chop off the other names that become "Alias(s)"\r
343     // leaving just the normal name\r
344     //\r
345     TempSpot = StrStr(CurrentName, L";");\r
346     if (TempSpot != NULL) {\r
347       *TempSpot = CHAR_NULL;\r
348     }\r
349   } else {\r
350     CurrentName = NULL;\r
351 \r
352     //\r
353     // Skip the first name.  This is the standard name.\r
354     //\r
355     TempSpot = StrStr(MapList, L";");\r
356     if (TempSpot != NULL) {\r
357       TempSpot++;\r
358     }\r
359     SearchList(TempSpot, L"HD*", &CurrentName, TRUE, FALSE, L";");\r
360     if (CurrentName == NULL) {\r
361       SearchList(TempSpot, L"CD*", &CurrentName, TRUE, FALSE, L";");\r
362     }\r
363     if (CurrentName == NULL) {\r
364       SearchList(TempSpot, L"FP*", &CurrentName, TRUE, FALSE, L";");\r
365     }\r
366     if (CurrentName == NULL) {\r
367       SearchList(TempSpot, L"F*",  &CurrentName, TRUE, FALSE, L";");\r
368     }\r
369     if (CurrentName == NULL) {\r
370       //\r
371       // We didnt find anything, so just the first one in the list...\r
372       //\r
373       CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0);\r
374       if (CurrentName == NULL) {\r
375         return (EFI_OUT_OF_RESOURCES);\r
376       }\r
377       TempSpot = StrStr(CurrentName, L";");\r
378       if (TempSpot != NULL) {\r
379         *TempSpot = CHAR_NULL;\r
380       }\r
381     } else {\r
382       Alias = StrnCatGrow(&Alias, 0, MapList, 0);\r
383       if (Alias == NULL) {\r
384         return EFI_OUT_OF_RESOURCES;\r
385       }\r
386       TempSpot = StrStr(Alias, CurrentName);\r
387       if (TempSpot != NULL) {\r
388         TempSpot2 = StrStr(TempSpot, L";");\r
389         if (TempSpot2 != NULL) {\r
390           TempSpot2++; // Move past ";" from CurrentName\r
391           CopyMem(TempSpot, TempSpot2, StrSize(TempSpot2));\r
392         } else {\r
393           *TempSpot = CHAR_NULL;\r
394         }\r
395       }\r
396       if (Alias[StrLen(Alias)-1] == L';') {\r
397         Alias[StrLen(Alias)-1] = CHAR_NULL;\r
398       }\r
399     }\r
400   }\r
401   DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE);\r
402   TempLen = StrLen(CurrentName);\r
403   if (!SFO) {\r
404     ShellPrintHiiEx (\r
405       -1,\r
406       -1,\r
407       NULL,\r
408       STRING_TOKEN (STR_MAP_ENTRY),\r
409       gShellLevel2HiiHandle,\r
410       CurrentName,\r
411       Alias!=NULL?Alias:(TempLen < StrLen(MapList)?MapList + TempLen+1:L""),\r
412       DevPathString\r
413      );\r
414     if (Verbose) {\r
415       //\r
416       // also print handle, media type, removable (y/n), and current directory\r
417       //\r
418       MediaType = GetDeviceMediaType(DevPath);\r
419       if ((TypeString != NULL &&MediaType != NULL && StrStr(TypeString, MediaType) != NULL) || TypeString == NULL) {\r
420         Removable = IsRemoveableDevice(DevPath);\r
421         TempSpot2 = ShellGetCurrentDir(CurrentName);\r
422         ShellPrintHiiEx (\r
423           -1,\r
424           -1,\r
425           NULL,\r
426           STRING_TOKEN (STR_MAP_ENTRY_VERBOSE),\r
427           gShellLevel2HiiHandle,\r
428           ConvertHandleToHandleIndex(Handle),\r
429           MediaType,\r
430           Removable?L"Yes":L"No",\r
431           TempSpot2\r
432          );\r
433       }\r
434       SHELL_FREE_NON_NULL(MediaType);\r
435     }\r
436   } else {\r
437     ShellPrintHiiEx (\r
438       -1,\r
439       -1,\r
440       NULL,\r
441       STRING_TOKEN (STR_MAP_SFO_MAPPINGS),\r
442       gShellLevel2HiiHandle,\r
443       CurrentName,\r
444       DevPathString,\r
445       Consist?L"":(TempLen < StrLen(MapList)?MapList + TempLen+1:L"")\r
446      );\r
447   }\r
448   SHELL_FREE_NON_NULL(DevPathString);\r
449   SHELL_FREE_NON_NULL(CurrentName);\r
450   SHELL_FREE_NON_NULL(Alias);\r
451   return EFI_SUCCESS;\r
452 }\r
453 \r
454 /**\r
455   Delete Specific from the list of maps for device Handle.\r
456 \r
457   @param[in] Specific   The name to delete.\r
458   @param[in] Handle     The device to look on.\r
459 \r
460   @retval EFI_SUCCESS     The delete was successful.\r
461   @retval EFI_NOT_FOUND   Name was not a map on Handle.\r
462 **/\r
463 EFI_STATUS\r
464 PerformSingleMappingDelete(\r
465   IN CONST CHAR16     *Specific,\r
466   IN CONST EFI_HANDLE Handle\r
467   )\r
468 {\r
469   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
470   EFI_DEVICE_PATH_PROTOCOL  *DevPathCopy;\r
471   CONST CHAR16              *MapList;\r
472   CHAR16                    *CurrentName;\r
473 \r
474   DevPath     = DevicePathFromHandle(Handle);\r
475   DevPathCopy = DevPath;\r
476   MapList     = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);\r
477   CurrentName = NULL;\r
478 \r
479   if (MapList == NULL) {\r
480     return (EFI_NOT_FOUND);\r
481   }\r
482   //\r
483   // if there is a specific and its not on the list...\r
484   //\r
485   if (!SearchList(MapList, Specific, &CurrentName, TRUE, FALSE, L";")) {\r
486     return (EFI_NOT_FOUND);\r
487   }\r
488   return (gEfiShellProtocol->SetMap(NULL, CurrentName));\r
489 }\r
490 \r
491 CONST CHAR16 Cd[] = L"cd*";\r
492 CONST CHAR16 Hd[] = L"hd*";\r
493 CONST CHAR16 Fp[] = L"fp*";\r
494 CONST CHAR16 AnyF[] = L"F*";\r
495 /**\r
496   Function to display mapping information to the user.\r
497 \r
498   If Specific is specified then Consist and Normal will be ignored since information will\r
499   be printed for the specific item only.\r
500 \r
501   @param[in] Verbose                TRUE to display (extra) verbose information.\r
502   @param[in] Consist                TRUE to display consistent mappings.\r
503   @param[in] Normal                 TRUE to display normal (not consist) mappings.\r
504   @param[in] TypeString             Pointer to string of filter types.\r
505   @param[in] SFO                    TRUE to display output in Standard Output Format.\r
506   @param[in] Specific               Pointer to string for specific map to display.\r
507   @param[in] Header                 TRUE to print the header block.\r
508 \r
509   @retval SHELL_SUCCESS               The display was printed.\r
510   @retval SHELL_INVALID_PARAMETER     One of Consist or Normal must be TRUE if no Specific.\r
511 \r
512 **/\r
513 SHELL_STATUS\r
514 PerformMappingDisplay(\r
515   IN CONST BOOLEAN Verbose,\r
516   IN CONST BOOLEAN Consist,\r
517   IN CONST BOOLEAN Normal,\r
518   IN CONST CHAR16  *TypeString,\r
519   IN CONST BOOLEAN SFO,\r
520   IN CONST CHAR16  *Specific OPTIONAL,\r
521   IN CONST BOOLEAN Header\r
522   )\r
523 {\r
524   EFI_STATUS                Status;\r
525   EFI_HANDLE                *HandleBuffer;\r
526   UINTN                     BufferSize;\r
527   UINTN                     LoopVar;\r
528   CHAR16                    *Test;\r
529   BOOLEAN                   Found;\r
530 \r
531   if (!Consist && !Normal && Specific == NULL && TypeString == NULL) {\r
532     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map");  \r
533     return (SHELL_INVALID_PARAMETER);\r
534   }\r
535 \r
536   if (TypeString != NULL) {\r
537     Test = (CHAR16*)Cd;\r
538     if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {\r
539       Test = (CHAR16*)Hd;\r
540       if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {\r
541         Test = (CHAR16*)Fp;\r
542         if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {\r
543           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", TypeString);  \r
544           return (SHELL_INVALID_PARAMETER);\r
545         }\r
546       } else if (Test == NULL) {\r
547         Test = (CHAR16*)AnyF;\r
548       }\r
549     }\r
550   } else {\r
551     Test = NULL;\r
552   }\r
553 \r
554   if (Header) {\r
555     //\r
556     // Print the header\r
557     //\r
558     if (!SFO) {\r
559       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle);\r
560     } else {\r
561       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map");\r
562     }\r
563   }\r
564 \r
565   BufferSize    = 0;\r
566   HandleBuffer  = NULL;\r
567 \r
568   //\r
569   // Look up all SimpleFileSystems in the platform\r
570   //\r
571   Status = gBS->LocateHandle(\r
572     ByProtocol,\r
573     &gEfiSimpleFileSystemProtocolGuid,\r
574     NULL,\r
575     &BufferSize,\r
576     HandleBuffer);\r
577   if (Status == EFI_BUFFER_TOO_SMALL) {\r
578     HandleBuffer = AllocateZeroPool(BufferSize);\r
579     if (HandleBuffer == NULL) {\r
580       return (SHELL_OUT_OF_RESOURCES);\r
581     }\r
582     Status = gBS->LocateHandle(\r
583       ByProtocol,\r
584       &gEfiSimpleFileSystemProtocolGuid,\r
585       NULL,\r
586       &BufferSize,\r
587       HandleBuffer);\r
588   }\r
589 \r
590   //\r
591   // Get the map name(s) for each one.\r
592   //\r
593   for ( LoopVar = 0, Found = FALSE\r
594       ; LoopVar < (BufferSize / sizeof(EFI_HANDLE)) && HandleBuffer != NULL\r
595       ; LoopVar ++\r
596      ){\r
597     Status = PerformSingleMappingDisplay(\r
598       Verbose,\r
599       Consist,\r
600       Normal,\r
601       Test,\r
602       SFO,\r
603       Specific,\r
604       HandleBuffer[LoopVar]);\r
605     if (!EFI_ERROR(Status)) {\r
606       Found = TRUE;\r
607     }\r
608   }\r
609 \r
610   //\r
611   // Look up all BlockIo in the platform\r
612   //\r
613   Status = gBS->LocateHandle(\r
614     ByProtocol,\r
615     &gEfiBlockIoProtocolGuid,\r
616     NULL,\r
617     &BufferSize,\r
618     HandleBuffer);\r
619   if (Status == EFI_BUFFER_TOO_SMALL) {\r
620     SHELL_FREE_NON_NULL(HandleBuffer);\r
621     HandleBuffer = AllocateZeroPool(BufferSize);\r
622     if (HandleBuffer == NULL) {\r
623       return (SHELL_OUT_OF_RESOURCES);\r
624     }\r
625     Status = gBS->LocateHandle(\r
626       ByProtocol,\r
627       &gEfiBlockIoProtocolGuid,\r
628       NULL,\r
629       &BufferSize,\r
630       HandleBuffer);\r
631   }\r
632   if (!EFI_ERROR(Status) && HandleBuffer != NULL) {\r
633     //\r
634     // Get the map name(s) for each one.\r
635     //\r
636     for ( LoopVar = 0\r
637         ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
638         ; LoopVar ++\r
639        ){\r
640       //\r
641       // Skip any that were already done...\r
642       //\r
643       if (gBS->OpenProtocol(\r
644         HandleBuffer[LoopVar],\r
645         &gEfiSimpleFileSystemProtocolGuid,\r
646         NULL,\r
647         gImageHandle,\r
648         NULL,\r
649         EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {\r
650           continue;\r
651       }\r
652       Status = PerformSingleMappingDisplay(\r
653         Verbose,\r
654         Consist,\r
655         Normal,\r
656         Test,\r
657         SFO,\r
658         Specific,\r
659         HandleBuffer[LoopVar]);\r
660       if (!EFI_ERROR(Status)) {\r
661         Found = TRUE;\r
662       }\r
663     }\r
664     FreePool(HandleBuffer);\r
665   }\r
666   if (!Found) {\r
667     if (Specific != NULL) {\r
668       ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", Specific);  \r
669     } else {\r
670       ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"map");  \r
671     }\r
672   }\r
673   return (SHELL_SUCCESS);\r
674 }\r
675 \r
676 /**\r
677   Perform a mapping display and parse for multiple types in the TypeString.\r
678 \r
679   @param[in] Verbose      TRUE to use verbose output.\r
680   @param[in] Consist      TRUE to display consistent names.\r
681   @param[in] Normal       TRUE to display normal names.\r
682   @param[in] TypeString   An optional comma-delimited list of types.\r
683   @param[in] SFO          TRUE to display in SFO format.  See Spec.\r
684   @param[in] Specific     An optional specific map name to display alone.\r
685 \r
686   @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
687   @retval SHELL_SUCCESS             The display was successful.\r
688   @sa PerformMappingDisplay\r
689 **/\r
690 SHELL_STATUS\r
691 PerformMappingDisplay2(\r
692   IN CONST BOOLEAN Verbose,\r
693   IN CONST BOOLEAN Consist,\r
694   IN CONST BOOLEAN Normal,\r
695   IN CONST CHAR16  *TypeString,\r
696   IN CONST BOOLEAN SFO,\r
697   IN CONST CHAR16  *Specific OPTIONAL\r
698   )\r
699 {\r
700   CONST CHAR16  *TypeWalker;\r
701   SHELL_STATUS  ShellStatus;\r
702   CHAR16        *Comma;\r
703 \r
704 \r
705   if (TypeString == NULL) {\r
706     return (PerformMappingDisplay(Verbose, Consist, Normal, NULL, SFO, Specific, TRUE));\r
707   }\r
708   ShellStatus = SHELL_SUCCESS;\r
709   for (TypeWalker = TypeString ; TypeWalker != NULL && *TypeWalker != CHAR_NULL ;) {\r
710     Comma = StrStr(TypeWalker, L",");\r
711     if (Comma == NULL) {\r
712       if (ShellStatus == SHELL_SUCCESS) {\r
713         ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));\r
714       } else {\r
715         PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));\r
716       }\r
717       break;\r
718     } else {\r
719       *Comma = CHAR_NULL;\r
720       if (ShellStatus == SHELL_SUCCESS) {\r
721         ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));\r
722       } else {\r
723         PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));\r
724       }\r
725       *Comma = L',';\r
726       TypeWalker = Comma + 1;\r
727     }\r
728   }\r
729 \r
730   return (ShellStatus);\r
731 }\r
732 \r
733 /**\r
734   Delete a specific map.\r
735 \r
736   @param[in] Specific  The pointer to the name of the map to delete.\r
737 \r
738   @retval EFI_INVALID_PARAMETER     Specific was NULL.\r
739   @retval EFI_SUCCESS               The operation was successful.\r
740   @retval EFI_NOT_FOUND             Specific could not be found.\r
741 **/\r
742 EFI_STATUS\r
743 PerformMappingDelete(\r
744   IN CONST CHAR16  *Specific\r
745   )\r
746 {\r
747   EFI_STATUS                Status;\r
748   EFI_HANDLE                *HandleBuffer;\r
749   UINTN                     BufferSize;\r
750   UINTN                     LoopVar;\r
751   BOOLEAN                   Deleted;\r
752 \r
753   if (Specific == NULL) {\r
754     return (EFI_INVALID_PARAMETER);\r
755   }\r
756 \r
757   BufferSize    = 0;\r
758   HandleBuffer  = NULL;\r
759   Deleted       = FALSE;\r
760 \r
761   //\r
762   // Look up all SimpleFileSystems in the platform\r
763   //\r
764   Status = gBS->LocateHandle(\r
765     ByProtocol,\r
766     &gEfiDevicePathProtocolGuid,\r
767     NULL,\r
768     &BufferSize,\r
769     HandleBuffer);\r
770   if (Status == EFI_BUFFER_TOO_SMALL) {\r
771     HandleBuffer = AllocateZeroPool(BufferSize);\r
772     if (HandleBuffer == NULL) {\r
773       return (EFI_OUT_OF_RESOURCES);\r
774     }\r
775     Status = gBS->LocateHandle(\r
776       ByProtocol,\r
777       &gEfiDevicePathProtocolGuid,\r
778       NULL,\r
779       &BufferSize,\r
780       HandleBuffer);\r
781   }\r
782   if (EFI_ERROR(Status)) {\r
783     SHELL_FREE_NON_NULL(HandleBuffer);\r
784     return (Status);\r
785   }\r
786 \r
787   if (HandleBuffer != NULL) {\r
788     //\r
789     // Get the map name(s) for each one.\r
790     //\r
791     for ( LoopVar = 0\r
792         ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
793         ; LoopVar ++\r
794        ){\r
795       if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
796           Deleted = TRUE;\r
797       }\r
798     }\r
799   }\r
800   //\r
801   // Look up all BlockIo in the platform\r
802   //\r
803   Status = gBS->LocateHandle(\r
804     ByProtocol,\r
805     &gEfiBlockIoProtocolGuid,\r
806     NULL,\r
807     &BufferSize,\r
808     HandleBuffer);\r
809   if (Status == EFI_BUFFER_TOO_SMALL) {\r
810     FreePool(HandleBuffer);\r
811     HandleBuffer = AllocateZeroPool(BufferSize);\r
812     if (HandleBuffer == NULL) {\r
813       return (EFI_OUT_OF_RESOURCES);\r
814     }\r
815     Status = gBS->LocateHandle(\r
816       ByProtocol,\r
817       &gEfiBlockIoProtocolGuid,\r
818       NULL,\r
819       &BufferSize,\r
820       HandleBuffer);\r
821   }\r
822   if (EFI_ERROR(Status)) {\r
823     SHELL_FREE_NON_NULL(HandleBuffer);\r
824     return (Status);\r
825   }\r
826 \r
827   if (HandleBuffer != NULL) {\r
828     //\r
829     // Get the map name(s) for each one.\r
830     //\r
831     for ( LoopVar = 0\r
832         ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
833         ; LoopVar ++\r
834        ){\r
835       //\r
836       // Skip any that were already done...\r
837       //\r
838       if (gBS->OpenProtocol(\r
839         HandleBuffer[LoopVar],\r
840         &gEfiDevicePathProtocolGuid,\r
841         NULL,\r
842         gImageHandle,\r
843         NULL,\r
844         EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {\r
845           continue;\r
846       }\r
847       if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
848           Deleted = TRUE;\r
849       }\r
850     }\r
851   }\r
852   SHELL_FREE_NON_NULL(HandleBuffer);\r
853   if (!Deleted) {\r
854     return (EFI_NOT_FOUND);\r
855   }\r
856   return (EFI_SUCCESS);\r
857 }\r
858 \r
859 /**\r
860   function to add a mapping from mapping.\r
861 \r
862   This function will get the device path associated with the mapping and call SetMap.\r
863 \r
864   @param[in] Map         The Map to add a mapping for\r
865   @param[in] SName       The name of the new mapping\r
866 \r
867   @retval SHELL_SUCCESS             the mapping was added\r
868   @retval SHELL_INVALID_PARAMETER   the device path for Map could not be retrieved.\r
869   @return                           Shell version of a return value from EfiShellProtocol->SetMap\r
870 \r
871 **/\r
872 SHELL_STATUS\r
873 AddMappingFromMapping(\r
874   IN CONST CHAR16     *Map,\r
875   IN CONST CHAR16     *SName\r
876   )\r
877 {\r
878   CONST EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
879   EFI_STATUS                      Status;\r
880   CHAR16                          *NewSName;\r
881   RETURN_STATUS                   StrRetStatus;\r
882   \r
883   NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName);\r
884   if (NewSName == NULL) {\r
885     return (SHELL_OUT_OF_RESOURCES);\r
886   }\r
887   if (NewSName[StrLen(NewSName)-1] != L':') {\r
888     StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":"));\r
889     if (EFI_ERROR(StrRetStatus)) {\r
890       FreePool(NewSName);\r
891       return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT)));\r
892     }\r
893   }\r
894 \r
895   if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) {\r
896     FreePool(NewSName);\r
897     return (SHELL_INVALID_PARAMETER);\r
898   }\r
899 \r
900   DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);\r
901   if (DevPath == NULL) {\r
902     FreePool(NewSName);\r
903     return (SHELL_INVALID_PARAMETER);\r
904   }\r
905 \r
906   Status = gEfiShellProtocol->SetMap(DevPath, NewSName);\r
907   FreePool(NewSName);\r
908   if (EFI_ERROR(Status)) {\r
909     return (SHELL_DEVICE_ERROR);\r
910   }\r
911   return (SHELL_SUCCESS);\r
912 }\r
913 \r
914 /**\r
915   function to add a mapping from an EFI_HANDLE.\r
916 \r
917   This function will get the device path associated with the Handle and call SetMap.\r
918 \r
919   @param[in] Handle       The handle to add a mapping for\r
920   @param[in] SName        The name of the new mapping\r
921 \r
922   @retval SHELL_SUCCESS           the mapping was added\r
923   @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.\r
924   @return                         Shell version of a return value from either\r
925                                   gBS->OpenProtocol or EfiShellProtocol->SetMap\r
926 \r
927 **/\r
928 SHELL_STATUS\r
929 AddMappingFromHandle(\r
930   IN CONST EFI_HANDLE Handle,\r
931   IN CONST CHAR16     *SName\r
932   )\r
933 {\r
934   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
935   EFI_STATUS                Status;\r
936   CHAR16                    *NewSName;\r
937   RETURN_STATUS             StrRetStatus;\r
938   \r
939   NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName);\r
940   if (NewSName == NULL) {\r
941     return (SHELL_OUT_OF_RESOURCES);\r
942   }\r
943   if (NewSName[StrLen(NewSName)-1] != L':') {\r
944     StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":"));\r
945     if (EFI_ERROR(StrRetStatus)) {\r
946       FreePool(NewSName);\r
947       return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT)));\r
948     }\r
949   }\r
950 \r
951   if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) {\r
952     FreePool(NewSName);\r
953     return (SHELL_INVALID_PARAMETER);\r
954   }\r
955 \r
956   Status = gBS->OpenProtocol(\r
957     Handle,\r
958     &gEfiDevicePathProtocolGuid,\r
959     (VOID**)&DevPath,\r
960     gImageHandle,\r
961     NULL,\r
962     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
963    );\r
964   if (EFI_ERROR(Status)) {\r
965     FreePool(NewSName);\r
966     return (SHELL_DEVICE_ERROR);\r
967   }\r
968   Status = gEfiShellProtocol->SetMap(DevPath, NewSName);\r
969   FreePool(NewSName);\r
970   if (EFI_ERROR(Status)) {\r
971     return (SHELL_DEVICE_ERROR);\r
972   }\r
973   return (SHELL_SUCCESS);\r
974 }\r
975 \r
976 STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {\r
977   {L"-d", TypeValue},\r
978   {L"-r", TypeFlag},\r
979   {L"-v", TypeFlag},\r
980   {L"-c", TypeFlag},\r
981   {L"-f", TypeFlag},\r
982   {L"-u", TypeFlag},\r
983   {L"-t", TypeValue},\r
984   {L"-sfo", TypeValue},\r
985   {NULL, TypeMax}\r
986   };\r
987 \r
988 /**\r
989   The routine issues dummy read for every physical block device to cause\r
990   the BlockIo re-installed if media change happened.\r
991 **/\r
992 VOID\r
993 ProbeForMediaChange (\r
994   VOID\r
995   )\r
996 {\r
997   EFI_STATUS                            Status;\r
998   UINTN                                 HandleCount;\r
999   EFI_HANDLE                            *Handles;\r
1000   EFI_BLOCK_IO_PROTOCOL                 *BlockIo;\r
1001   UINTN                                 Index;\r
1002 \r
1003   gBS->LocateHandleBuffer (\r
1004          ByProtocol,\r
1005          &gEfiBlockIoProtocolGuid,\r
1006          NULL,\r
1007          &HandleCount,\r
1008          &Handles\r
1009          );\r
1010   //\r
1011   // Probe for media change for every physical block io\r
1012   //\r
1013   for (Index = 0; Index < HandleCount; Index++) {\r
1014     Status = gBS->HandleProtocol (\r
1015                     Handles[Index],\r
1016                     &gEfiBlockIoProtocolGuid,\r
1017                     (VOID **) &BlockIo\r
1018                     );\r
1019     if (!EFI_ERROR (Status)) {\r
1020       if (!BlockIo->Media->LogicalPartition) {\r
1021         //\r
1022         // Per spec:\r
1023         //   The function (ReadBlocks) must return EFI_NO_MEDIA or\r
1024         //   EFI_MEDIA_CHANGED even if LBA, BufferSize, or Buffer are invalid so the caller can probe\r
1025         //   for changes in media state.\r
1026         //\r
1027         BlockIo->ReadBlocks (\r
1028                    BlockIo,\r
1029                    BlockIo->Media->MediaId,\r
1030                    0,\r
1031                    0,\r
1032                    NULL\r
1033                    );\r
1034       }\r
1035     }\r
1036   }\r
1037 }\r
1038 \r
1039 /**\r
1040   Function for 'map' command.\r
1041 \r
1042   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
1043   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
1044 **/\r
1045 SHELL_STATUS\r
1046 EFIAPI\r
1047 ShellCommandRunMap (\r
1048   IN EFI_HANDLE        ImageHandle,\r
1049   IN EFI_SYSTEM_TABLE  *SystemTable\r
1050   )\r
1051 {\r
1052   EFI_STATUS    Status;\r
1053   LIST_ENTRY    *Package;\r
1054   CHAR16        *ProblemParam;\r
1055   CONST CHAR16  *SName;\r
1056   CONST CHAR16  *Mapping;\r
1057   EFI_HANDLE    MapAsHandle;\r
1058   SHELL_STATUS  ShellStatus;\r
1059   BOOLEAN       SfoMode;\r
1060   BOOLEAN       ConstMode;\r
1061   BOOLEAN       NormlMode;\r
1062   CONST CHAR16  *Param1;\r
1063   CONST CHAR16  *TypeString;\r
1064   UINTN         TempStringLength;\r
1065 \r
1066   ProblemParam  = NULL;\r
1067   Mapping       = NULL;\r
1068   SName         = NULL;\r
1069   ShellStatus   = SHELL_SUCCESS;\r
1070   MapAsHandle = NULL;\r
1071 \r
1072   //\r
1073   // initialize the shell lib (we must be in non-auto-init...)\r
1074   //\r
1075   Status = ShellInitialize();\r
1076   ASSERT_EFI_ERROR(Status);\r
1077 \r
1078   Status = CommandInit();\r
1079   ASSERT_EFI_ERROR(Status);\r
1080 \r
1081   //\r
1082   // parse the command line\r
1083   //\r
1084   Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE);\r
1085   if (EFI_ERROR(Status)) {\r
1086     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
1087       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"map", ProblemParam);  \r
1088       FreePool(ProblemParam);\r
1089       ShellStatus = SHELL_INVALID_PARAMETER;\r
1090     } else {\r
1091       ASSERT(FALSE);\r
1092     }\r
1093   } else {\r
1094     //\r
1095     // check for "-?"\r
1096     //\r
1097     SfoMode   = ShellCommandLineGetFlag(Package, L"-sfo");\r
1098     ConstMode = ShellCommandLineGetFlag(Package, L"-c");\r
1099     NormlMode = ShellCommandLineGetFlag(Package, L"-f");\r
1100     if (ShellCommandLineGetFlag(Package, L"-?")) {\r
1101       ASSERT(FALSE);\r
1102     } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {\r
1103       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"map");  \r
1104       ShellStatus = SHELL_INVALID_PARAMETER;\r
1105     } else {\r
1106       //\r
1107       // Deleting a map name...\r
1108       //\r
1109       if (ShellCommandLineGetFlag(Package, L"-d")) {\r
1110         if ( ShellCommandLineGetFlag(Package, L"-r")\r
1111           || ShellCommandLineGetFlag(Package, L"-v")\r
1112           || ConstMode\r
1113           || NormlMode\r
1114           || ShellCommandLineGetFlag(Package, L"-u")\r
1115           || ShellCommandLineGetFlag(Package, L"-t")\r
1116          ){\r
1117           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"map");  \r
1118           ShellStatus = SHELL_INVALID_PARAMETER;\r
1119         } else {\r
1120           SName = ShellCommandLineGetValue(Package, L"-d");\r
1121           if (SName != NULL) {\r
1122             Status = PerformMappingDelete(SName);\r
1123             if (EFI_ERROR(Status)) {\r
1124               if (Status == EFI_ACCESS_DENIED) {\r
1125                 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map");  \r
1126                 ShellStatus = SHELL_ACCESS_DENIED;\r
1127               } else if (Status == EFI_NOT_FOUND) {\r
1128                 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", SName);  \r
1129                 ShellStatus = SHELL_INVALID_PARAMETER;\r
1130               } else {\r
1131                 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);  \r
1132                 ShellStatus = SHELL_UNSUPPORTED;\r
1133               }\r
1134             }\r
1135           } else {\r
1136             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map");  \r
1137             ShellStatus = SHELL_INVALID_PARAMETER;\r
1138           }\r
1139         }\r
1140       } else if ( ShellCommandLineGetFlag(Package, L"-r")\r
1141 //               || ShellCommandLineGetFlag(Package, L"-v")\r
1142                || ConstMode\r
1143                || NormlMode\r
1144                || ShellCommandLineGetFlag(Package, L"-u")\r
1145                || ShellCommandLineGetFlag(Package, L"-t")\r
1146               ){\r
1147         ProbeForMediaChange ();\r
1148         if ( ShellCommandLineGetFlag(Package, L"-r")) {\r
1149           //\r
1150           // Do the reset\r
1151           //\r
1152           Status = ShellCommandCreateInitialMappingsAndPaths();\r
1153           if (EFI_ERROR(Status)) {\r
1154             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);  \r
1155             ShellStatus = SHELL_UNSUPPORTED;\r
1156           }\r
1157         }\r
1158         if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) {\r
1159           //\r
1160           // Do the Update\r
1161           //\r
1162           Status = ShellCommandUpdateMapping ();\r
1163           if (EFI_ERROR(Status)) {\r
1164             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);  \r
1165             ShellStatus = SHELL_UNSUPPORTED;\r
1166           }\r
1167         }\r
1168         if (ShellStatus == SHELL_SUCCESS) {\r
1169           Param1 = ShellCommandLineGetRawValue(Package, 1);\r
1170           TypeString = ShellCommandLineGetValue(Package, L"-t");\r
1171           if (!ConstMode\r
1172             &&!NormlMode\r
1173             &&TypeString  == NULL\r
1174             ) {\r
1175             //\r
1176             // now do the display...\r
1177             //\r
1178             ShellStatus = PerformMappingDisplay(\r
1179               ShellCommandLineGetFlag(Package, L"-v"),\r
1180               TRUE,\r
1181               TRUE,\r
1182               NULL,\r
1183               SfoMode,\r
1184               Param1,\r
1185               TRUE\r
1186              );\r
1187           } else {\r
1188             //\r
1189             // now do the display...\r
1190             //\r
1191             ShellStatus = PerformMappingDisplay2(\r
1192               ShellCommandLineGetFlag(Package, L"-v"),\r
1193               ConstMode,\r
1194               NormlMode,\r
1195               TypeString,\r
1196               SfoMode,\r
1197               Param1\r
1198              );\r
1199           }\r
1200         }\r
1201       } else {\r
1202         //\r
1203         // adding or displaying (there were no flags)\r
1204         //\r
1205         SName = ShellCommandLineGetRawValue(Package, 1);\r
1206         Mapping = ShellCommandLineGetRawValue(Package, 2);\r
1207         if ( SName == NULL\r
1208           && Mapping == NULL\r
1209          ){\r
1210           //\r
1211           // display only since no flags\r
1212           //\r
1213           ShellStatus = PerformMappingDisplay(\r
1214             ShellCommandLineGetFlag(Package, L"-v"),\r
1215             TRUE,\r
1216             TRUE,\r
1217             NULL,\r
1218             SfoMode,\r
1219             NULL,\r
1220             TRUE\r
1221            );\r
1222         } else if ( SName == NULL\r
1223           || Mapping == NULL\r
1224          ){\r
1225             //\r
1226             // Display only the one specified\r
1227             //\r
1228           ShellStatus = PerformMappingDisplay(\r
1229             FALSE,\r
1230             FALSE,\r
1231             FALSE,\r
1232             NULL,\r
1233             SfoMode,\r
1234             SName, // note the variable here...\r
1235             TRUE\r
1236            );\r
1237         } else {\r
1238           if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {\r
1239             MapAsHandle = ConvertHandleIndexToHandle(ShellStrToUintn(Mapping));\r
1240           } else {\r
1241             MapAsHandle = NULL;\r
1242           }\r
1243           if (MapAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {\r
1244             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping);  \r
1245             ShellStatus = SHELL_INVALID_PARAMETER;\r
1246           } else {\r
1247             TempStringLength = StrLen(SName);\r
1248             if (!IsNumberLetterOnly(SName, TempStringLength-(SName[TempStringLength-1]==L':'?1:0))) {\r
1249               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", SName);\r
1250               ShellStatus = SHELL_INVALID_PARAMETER;\r
1251             }\r
1252 \r
1253             if (ShellStatus == SHELL_SUCCESS) {\r
1254               if (MapAsHandle != NULL) {\r
1255                 ShellStatus = AddMappingFromHandle(MapAsHandle, SName);\r
1256               } else {\r
1257                 ShellStatus = AddMappingFromMapping(Mapping, SName);\r
1258               }\r
1259 \r
1260               if (ShellStatus != SHELL_SUCCESS) {\r
1261                 switch (ShellStatus) {\r
1262                   case SHELL_ACCESS_DENIED:\r
1263                     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map");\r
1264                     break;\r
1265                   case SHELL_INVALID_PARAMETER:\r
1266                     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping);\r
1267                     break;\r
1268                   case SHELL_DEVICE_ERROR:\r
1269                     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NOF), gShellLevel2HiiHandle, L"map", Mapping);\r
1270                     break;\r
1271                   default:\r
1272                     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", ShellStatus|MAX_BIT);\r
1273                 }\r
1274               } else {\r
1275                 //\r
1276                 // now do the display...\r
1277                 //\r
1278                 ShellStatus = PerformMappingDisplay(\r
1279                   FALSE,\r
1280                   FALSE,\r
1281                   FALSE,\r
1282                   NULL,\r
1283                   SfoMode,\r
1284                   SName,\r
1285                   TRUE\r
1286                  );\r
1287               } // we were sucessful so do an output\r
1288             }\r
1289           } // got a valid map target\r
1290         } // got 2 variables\r
1291       } // we are adding a mapping\r
1292     } // got valid parameters\r
1293   }\r
1294 \r
1295   //\r
1296   // free the command line package\r
1297   //\r
1298   ShellCommandLineFreeVarList (Package);\r
1299 \r
1300   return (ShellStatus);\r
1301 }\r
1302 \r