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