]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
pointer verification (not NULL) and buffer overrun fixes.
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Map.c
index 5d6a200c196abe88e45b129bb95c447deed2dc07..e7d19c9bed702c84d339c68265010282991aba3c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Main file for map shell level 2 command.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 #include <Library/HandleParsingLib.h>\r
 #include <Library/SortLib.h>\r
 \r
+/**\r
+  Determine if a string has only numbers and letters.\r
+\r
+  This is useful for such things as Map names which can only be letters and numbers.\r
+\r
+  @param[in] String       pointer to the string to analyze,\r
+  @param[in] Len          Number of characters to analyze.\r
+\r
+  @retval TRUE            String has only numbers and letters\r
+  @retval FALSE           String has at least one other character.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsNumberLetterOnly(\r
+  IN CONST CHAR16 *String,\r
+  IN CONST UINTN  Len\r
+  )\r
+{\r
+  UINTN Count;\r
+  for (Count = 0 ; Count < Len && String != NULL && *String != CHAR_NULL ; String++,Count++) {\r
+    if (! ((*String >= L'a' && *String <= L'z') ||\r
+           (*String >= L'A' && *String <= L'Z') ||\r
+           (*String >= L'0' && *String <= L'9'))\r
+        ){\r
+      return (FALSE);\r
+    }\r
+  }\r
+  return (TRUE);\r
+}\r
+\r
+/**\r
+  Do a search in the Target delimited list.\r
+\r
+  @param[in] List         The list to seatch in.\r
+  @param[in] MetaTarget   The item to search for. MetaMatching supported.\r
+  @param[out] FullName    Optional pointer to an allocated buffer containing \r
+                          the match.\r
+  @param[in] Meta         TRUE to use MetaMatching.\r
+  @param[in] SkipTrailingNumbers  TRUE to allow for numbers after the MetaTarget.\r
+  @param[in] Target       The single character that delimits list \r
+                          items (";" normally). \r
+**/\r
 BOOLEAN\r
 EFIAPI\r
 SearchList(\r
@@ -75,6 +117,11 @@ SearchList(
   return (FALSE);\r
 }\r
 \r
+/**\r
+  Add mappings for any devices without one.  Do not change any existing maps.\r
+\r
+  @retval EFI_SUCCESS   The operation was successful.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 UpdateMapping (\r
@@ -99,7 +146,7 @@ UpdateMapping (
   //\r
   // Find each handle with Simple File System\r
   //\r
-  HandleList = GetHandleListByPotocol(&gEfiSimpleFileSystemProtocolGuid);\r
+  HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);\r
   if (HandleList != NULL) {\r
     //\r
     // Do a count of the handles\r
@@ -109,7 +156,7 @@ UpdateMapping (
     //\r
     // Get all Device Paths\r
     //\r
-    DevicePathList = AllocatePool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);\r
+    DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);\r
     ASSERT(DevicePathList != NULL);\r
 \r
     for (Count = 0 ; HandleList[Count] != NULL ; Count++) {\r
@@ -172,6 +219,18 @@ UpdateMapping (
   return (Status);\r
 }\r
 \r
+/**\r
+  Determine what type of device is represented and return it's string.  The \r
+  string is in allocated memory and must be callee freed.  The HII is is listed below.\r
+  The actual string cannot be determined.\r
+\r
+  @param[in] DevicePath     The device to analyze.\r
+\r
+  @retval STR_MAP_MEDIA_UNKNOWN   The media type is unknown.\r
+  @retval STR_MAP_MEDIA_HARDDISK  The media is a hard drive.\r
+  @retval STR_MAP_MEDIA_CDROM     The media is a CD ROM.\r
+  @retval STR_MAP_MEDIA_FLOPPY    The media is a floppy drive.\r
+**/\r
 CHAR16*\r
 EFIAPI\r
 GetDeviceMediaType (\r
@@ -265,18 +324,30 @@ MappingListHasType(
   IN CONST BOOLEAN    Consist\r
   )\r
 {\r
+  CHAR16 *NewSpecific;\r
   //\r
   // specific has priority\r
   //\r
-  if ( Specific != NULL\r
-    && SearchList(MapList, Specific, NULL, TRUE, FALSE, L";")) {\r
-    return (TRUE);\r
-  }\r
+  if (Specific != NULL) {\r
+    NewSpecific = AllocateZeroPool(StrSize(Specific) + sizeof(CHAR16));\r
+    if (NewSpecific == NULL){\r
+      return FALSE;\r
+    }\r
+    StrCpy(NewSpecific, Specific);\r
+    if (NewSpecific[StrLen(NewSpecific)-1] != L':') {\r
+      StrCat(NewSpecific, L":");\r
+    }\r
 \r
+    if (SearchList(MapList, NewSpecific, NULL, TRUE, FALSE, L";")) {\r
+      FreePool(NewSpecific);\r
+      return (TRUE);\r
+    }\r
+    FreePool(NewSpecific);\r
+  }\r
   if (  Consist\r
     && (SearchList(MapList, L"HD*",  NULL, TRUE, TRUE, L";")\r
       ||SearchList(MapList, L"CD*",  NULL, TRUE, TRUE, L";")\r
-      ||SearchList(MapList, L"F*",   NULL, TRUE, TRUE, L";")\r
+      ||SearchList(MapList, L"AnyF*",   NULL, TRUE, TRUE, L";")\r
       ||SearchList(MapList, L"FP*",  NULL, TRUE, TRUE, L";"))){\r
     return (TRUE);\r
   }\r
@@ -294,7 +365,20 @@ MappingListHasType(
 }\r
 \r
 \r
-VOID\r
+/**\r
+  Display a single map line for device Handle if conditions are met.\r
+\r
+  @param[in] Verbose                TRUE to display (extra) verbose information.\r
+  @param[in] Consist                TRUE to display consistent mappings.\r
+  @param[in] Normal                 TRUE to display normal (not consist) mappings.\r
+  @param[in] TypeString             pointer to string of filter types.\r
+  @param[in] SFO                    TRUE to display output in Standard Output Format.\r
+  @param[in] Specific               pointer to string for specific map to display.\r
+  @param[in] Handle                 The handle to display from.\r
+\r
+  @retval EFI_SUCCESS               The mapping was displayed.\r
+**/\r
+EFI_STATUS\r
 EFIAPI\r
 PerformSingleMappingDisplay(\r
   IN CONST BOOLEAN    Verbose,\r
@@ -321,11 +405,11 @@ PerformSingleMappingDisplay(
   DevPathCopy = DevPath;\r
   MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);\r
   if (MapList == NULL) {\r
-    return;\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
   if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){\r
-    return;\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
   CurrentName = NULL;\r
@@ -384,9 +468,18 @@ PerformSingleMappingDisplay(
   }\r
   FreePool(DevPathString);\r
   FreePool(CurrentName);\r
-  return;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Delete Specific from the list of maps for device Handle.\r
+\r
+  @param[in] Specific   The name to delete.\r
+  @param[in] Handle     The device to look on.\r
+\r
+  @retval EFI_SUCCESS     The delete was successful.\r
+  @retval EFI_NOT_FOUND   Name was not a map on Handle.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 PerformSingleMappingDelete(\r
@@ -416,6 +509,10 @@ PerformSingleMappingDelete(
   return (gEfiShellProtocol->SetMap(NULL, CurrentName));\r
 }\r
 \r
+CONST CHAR16 Cd[] = L"cd*";\r
+CONST CHAR16 Hd[] = L"hd*";\r
+CONST CHAR16 Fp[] = L"fp*";\r
+CONST CHAR16 AnyF[] = L"F*";\r
 /**\r
   Function to display mapping information to the user.\r
 \r
@@ -433,10 +530,6 @@ PerformSingleMappingDelete(
   @retval SHELL_INVALID_PARAMETER     one of Consist or Normal must be TRUE if no Specific\r
 \r
 **/\r
-CONST CHAR16 Cd[] = L"cd*";\r
-CONST CHAR16 Hd[] = L"hd*";\r
-CONST CHAR16 Fp[] = L"fp*";\r
-CONST CHAR16 F[] = L"F*";\r
 SHELL_STATUS\r
 EFIAPI\r
 PerformMappingDisplay(\r
@@ -454,6 +547,7 @@ PerformMappingDisplay(
   UINTN                     BufferSize;\r
   UINTN                     LoopVar;\r
   CHAR16                    *Test;\r
+  BOOLEAN                   Found;\r
 \r
   if (!Consist && !Normal && Specific == NULL && TypeString == NULL) {\r
     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);\r
@@ -471,7 +565,7 @@ PerformMappingDisplay(
           return (SHELL_INVALID_PARAMETER);\r
         }\r
       } else if (Test == NULL) {\r
-        Test = (CHAR16*)F;\r
+        Test = (CHAR16*)AnyF;\r
       }\r
     }\r
   } else {\r
@@ -497,30 +591,31 @@ PerformMappingDisplay(
   //\r
   Status = gBS->LocateHandle(\r
     ByProtocol,\r
-    &gEfiDevicePathProtocolGuid,\r
+    &gEfiSimpleFileSystemProtocolGuid,\r
     NULL,\r
     &BufferSize,\r
     HandleBuffer);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    HandleBuffer = AllocatePool(BufferSize);\r
+    HandleBuffer = AllocateZeroPool(BufferSize);\r
+    if (HandleBuffer == NULL) {\r
+      return (SHELL_OUT_OF_RESOURCES);\r
+    }\r
     Status = gBS->LocateHandle(\r
       ByProtocol,\r
-      &gEfiDevicePathProtocolGuid,\r
+      &gEfiSimpleFileSystemProtocolGuid,\r
       NULL,\r
       &BufferSize,\r
       HandleBuffer);\r
   }\r
-  ASSERT_EFI_ERROR(Status);\r
-  ASSERT(HandleBuffer != NULL);\r
 \r
   //\r
   // Get the map name(s) for each one.\r
   //\r
-  for ( LoopVar = 0\r
-      ; LoopVar < (BufferSize / sizeof(EFI_HANDLE))\r
+  for ( LoopVar = 0, Found = FALSE\r
+      ; LoopVar < (BufferSize / sizeof(EFI_HANDLE)) && HandleBuffer != NULL\r
       ; LoopVar ++\r
      ){\r
-    PerformSingleMappingDisplay(\r
+    Status = PerformSingleMappingDisplay(\r
       Verbose,\r
       Consist,\r
       Normal,\r
@@ -528,6 +623,9 @@ PerformMappingDisplay(
       SFO,\r
       Specific,\r
       HandleBuffer[LoopVar]);\r
+    if (!EFI_ERROR(Status)) {\r
+      Found = TRUE;\r
+    }\r
   }\r
 \r
   //\r
@@ -540,8 +638,11 @@ PerformMappingDisplay(
     &BufferSize,\r
     HandleBuffer);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    FreePool(HandleBuffer);\r
-    HandleBuffer = AllocatePool(BufferSize);\r
+    SHELL_FREE_NON_NULL(HandleBuffer);\r
+    HandleBuffer = AllocateZeroPool(BufferSize);\r
+    if (HandleBuffer == NULL) {\r
+      return (SHELL_OUT_OF_RESOURCES);\r
+    }\r
     Status = gBS->LocateHandle(\r
       ByProtocol,\r
       &gEfiBlockIoProtocolGuid,\r
@@ -549,40 +650,60 @@ PerformMappingDisplay(
       &BufferSize,\r
       HandleBuffer);\r
   }\r
-  ASSERT_EFI_ERROR(Status);\r
-\r
-  //\r
-  // Get the map name(s) for each one.\r
-  //\r
-  for ( LoopVar = 0\r
-      ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
-      ; LoopVar ++\r
-     ){\r
+  if (!EFI_ERROR(Status)) {\r
     //\r
-    // Skip any that were already done...\r
+    // Get the map name(s) for each one.\r
     //\r
-    if (gBS->OpenProtocol(\r
-      HandleBuffer[LoopVar],\r
-      &gEfiDevicePathProtocolGuid,\r
-      NULL,\r
-      gImageHandle,\r
-      NULL,\r
-      EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {\r
-        continue;\r
+    for ( LoopVar = 0\r
+        ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
+        ; LoopVar ++\r
+       ){\r
+      //\r
+      // Skip any that were already done...\r
+      //\r
+      if (gBS->OpenProtocol(\r
+        HandleBuffer[LoopVar],\r
+        &gEfiSimpleFileSystemProtocolGuid,\r
+        NULL,\r
+        gImageHandle,\r
+        NULL,\r
+        EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {\r
+          continue;\r
+      }\r
+      Status = PerformSingleMappingDisplay(\r
+        Verbose,\r
+        Consist,\r
+        Normal,\r
+        Test,\r
+        SFO,\r
+        Specific,\r
+        HandleBuffer[LoopVar]);\r
+      if (!EFI_ERROR(Status)) {\r
+        Found = TRUE;\r
+      }\r
     }\r
-    PerformSingleMappingDisplay(\r
-      Verbose,\r
-      Consist,\r
-      Normal,\r
-      Test,\r
-      SFO,\r
-      Specific,\r
-      HandleBuffer[LoopVar]);\r
+    FreePool(HandleBuffer);\r
+  }\r
+  if (!Found) {\r
+    ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, Specific);\r
   }\r
-  FreePool(HandleBuffer);\r
   return (SHELL_SUCCESS);\r
 }\r
 \r
+/**\r
+  Perform a mapping display and parse for multiple types in the TypeString.\r
+\r
+  @param[in] Verbose      TRUE to use verbose output.\r
+  @param[in] Consist      TRUE to display consistent names.\r
+  @param[in] Normal       TRUE to display normal names.\r
+  @param[in] TypeString   An optional comma-delimited list of types.\r
+  @param[in] SFO          TRUE to display in SFO format.  See Spec.\r
+  @param[in] Specific     An optional specific map name to display alone.\r
+\r
+  @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
+  @retval SHELL_SUCCESS             The display was successful.\r
+  @sa PerformMappingDisplay\r
+**/\r
 SHELL_STATUS\r
 EFIAPI\r
 PerformMappingDisplay2(\r
@@ -627,6 +748,15 @@ PerformMappingDisplay2(
   return (ShellStatus);\r
 }\r
 \r
+/**\r
+  Delete a specific map.\r
+\r
+  @param[in] Specific  The pointer to the name of the map to delete.\r
+\r
+  @retval EFI_INVALID_PARAMETER     Specific was NULL.\r
+  @retval EFI_SUCCESS               The operation was successful.\r
+  @retval EFI_NOT_FOUND             Specific could not be found.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 PerformMappingDelete(\r
@@ -657,7 +787,10 @@ PerformMappingDelete(
     &BufferSize,\r
     HandleBuffer);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    HandleBuffer = AllocatePool(BufferSize);\r
+    HandleBuffer = AllocateZeroPool(BufferSize);\r
+    if (HandleBuffer == NULL) {\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
     Status = gBS->LocateHandle(\r
       ByProtocol,\r
       &gEfiDevicePathProtocolGuid,\r
@@ -665,21 +798,24 @@ PerformMappingDelete(
       &BufferSize,\r
       HandleBuffer);\r
   }\r
-  ASSERT_EFI_ERROR(Status);\r
-  ASSERT(HandleBuffer != NULL);\r
+  if (EFI_ERROR(Status)) {\r
+    SHELL_FREE_NON_NULL(HandleBuffer);\r
+    return (Status);\r
+  }\r
 \r
-  //\r
-  // Get the map name(s) for each one.\r
-  //\r
-  for ( LoopVar = 0\r
-      ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
-      ; LoopVar ++\r
-     ){\r
-    if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
-        Deleted = TRUE;\r
+  if (HandleBuffer != NULL) {\r
+    //\r
+    // Get the map name(s) for each one.\r
+    //\r
+    for ( LoopVar = 0\r
+        ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
+        ; LoopVar ++\r
+       ){\r
+      if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
+          Deleted = TRUE;\r
+      }\r
     }\r
   }\r
-\r
   //\r
   // Look up all BlockIo in the platform\r
   //\r
@@ -691,7 +827,10 @@ PerformMappingDelete(
     HandleBuffer);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     FreePool(HandleBuffer);\r
-    HandleBuffer = AllocatePool(BufferSize);\r
+    HandleBuffer = AllocateZeroPool(BufferSize);\r
+    if (HandleBuffer == NULL) {\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
     Status = gBS->LocateHandle(\r
       ByProtocol,\r
       &gEfiBlockIoProtocolGuid,\r
@@ -699,32 +838,37 @@ PerformMappingDelete(
       &BufferSize,\r
       HandleBuffer);\r
   }\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (EFI_ERROR(Status)) {\r
+    SHELL_FREE_NON_NULL(HandleBuffer);\r
+    return (Status);\r
+  }\r
 \r
-  //\r
-  // Get the map name(s) for each one.\r
-  //\r
-  for ( LoopVar = 0\r
-      ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
-      ; LoopVar ++\r
-     ){\r
+  if (HandleBuffer != NULL) {\r
     //\r
-    // Skip any that were already done...\r
+    // Get the map name(s) for each one.\r
     //\r
-    if (gBS->OpenProtocol(\r
-      HandleBuffer[LoopVar],\r
-      &gEfiDevicePathProtocolGuid,\r
-      NULL,\r
-      gImageHandle,\r
-      NULL,\r
-      EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {\r
-        continue;\r
-    }\r
-    if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
-        Deleted = TRUE;\r
+    for ( LoopVar = 0\r
+        ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
+        ; LoopVar ++\r
+       ){\r
+      //\r
+      // Skip any that were already done...\r
+      //\r
+      if (gBS->OpenProtocol(\r
+        HandleBuffer[LoopVar],\r
+        &gEfiDevicePathProtocolGuid,\r
+        NULL,\r
+        gImageHandle,\r
+        NULL,\r
+        EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {\r
+          continue;\r
+      }\r
+      if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
+          Deleted = TRUE;\r
+      }\r
     }\r
   }\r
-  FreePool(HandleBuffer);\r
+  SHELL_FREE_NON_NULL(HandleBuffer);\r
   if (!Deleted) {\r
     return (EFI_NOT_FOUND);\r
   }\r
@@ -753,54 +897,36 @@ AddMappingFromMapping(
 {\r
   CONST EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   EFI_STATUS                      Status;\r
+  CHAR16                          *NewSName;\r
+  \r
+  NewSName = AllocateZeroPool(StrSize(SName) + sizeof(CHAR16));\r
+  if (NewSName == NULL) {\r
+    return (SHELL_OUT_OF_RESOURCES);\r
+  }\r
+  StrCpy(NewSName, SName);\r
+  if (NewSName[StrLen(NewSName)-1] != L':') {\r
+    StrCat(NewSName, L":");\r
+  }\r
 \r
-  if (StrStr(SName, L"*") != NULL\r
-    ||StrStr(SName, L"?") != NULL\r
-    ||StrStr(SName, L"[") != NULL\r
-    ||StrStr(SName, L"]") != NULL) {\r
+  if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) {\r
+    FreePool(NewSName);\r
     return (SHELL_INVALID_PARAMETER);\r
   }\r
 \r
   DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);\r
   if (DevPath == NULL) {\r
+    FreePool(NewSName);\r
     return (SHELL_INVALID_PARAMETER);\r
   }\r
 \r
-  Status = gEfiShellProtocol->SetMap(DevPath, SName);\r
+  Status = gEfiShellProtocol->SetMap(DevPath, NewSName);\r
+  FreePool(NewSName);\r
   if (EFI_ERROR(Status)) {\r
     return (SHELL_DEVICE_ERROR);\r
   }\r
   return (SHELL_SUCCESS);\r
 }\r
 \r
-/**\r
-  function to determine if a string has only numbers and letters\r
-\r
-  This is useful for such things as Map names which can only be letters and numbers\r
-\r
-  @param[in] String       pointer to the string to analyze\r
-\r
-  @retval TRUE            String has only numbers and letters\r
-  @retval FALSE           String has at least one other character.\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-IsNumberLetterOnly(\r
-  IN CONST CHAR16 *String\r
-  )\r
-{\r
-  while(String != NULL && *String != CHAR_NULL) {\r
-    if (! ( *String >= L'a' && *String <= L'z'\r
-         || *String >= L'A' && *String <= L'Z'\r
-         || *String >= L'0' && *String <= L'9')\r
-        ){\r
-      return (FALSE);\r
-    }\r
-    String++;\r
-  }\r
-  return (TRUE);\r
-}\r
-\r
 /**\r
   function to add a mapping from an EFI_HANDLE.\r
 \r
@@ -824,8 +950,19 @@ AddMappingFromHandle(
 {\r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   EFI_STATUS                Status;\r
+  CHAR16                    *NewSName;\r
+  \r
+  NewSName = AllocateZeroPool(StrSize(SName) + sizeof(CHAR16));\r
+  if (NewSName == NULL) {\r
+    return (SHELL_OUT_OF_RESOURCES);\r
+  }\r
+  StrCpy(NewSName, SName);\r
+  if (NewSName[StrLen(NewSName)-1] != L':') {\r
+    StrCat(NewSName, L":");\r
+  }\r
 \r
-  if (!IsNumberLetterOnly(SName)) {\r
+  if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) {\r
+    FreePool(NewSName);\r
     return (SHELL_INVALID_PARAMETER);\r
   }\r
 \r
@@ -838,9 +975,11 @@ AddMappingFromHandle(
     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
    );\r
   if (EFI_ERROR(Status)) {\r
+    FreePool(NewSName);\r
     return (SHELL_DEVICE_ERROR);\r
   }\r
-  Status = gEfiShellProtocol->SetMap(DevPath, SName);\r
+  Status = gEfiShellProtocol->SetMap(DevPath, NewSName);\r
+  FreePool(NewSName);\r
   if (EFI_ERROR(Status)) {\r
     return (SHELL_DEVICE_ERROR);\r
   }\r
@@ -877,7 +1016,7 @@ ShellCommandRunMap (
   CHAR16        *ProblemParam;\r
   CONST CHAR16  *SName;\r
   CONST CHAR16  *Mapping;\r
-  EFI_HANDLE    MappingAsHandle;\r
+  EFI_HANDLE    MapAsHandle;\r
   CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
   SHELL_STATUS  ShellStatus;\r
   BOOLEAN       SfoMode;\r
@@ -885,13 +1024,14 @@ ShellCommandRunMap (
   BOOLEAN       NormlMode;\r
   CONST CHAR16  *Param1;\r
   CONST CHAR16  *TypeString;\r
+  UINTN         TempStringLength;\r
 \r
   ProblemParam  = NULL;\r
   Mapping       = NULL;\r
   SName         = NULL;\r
   DevPath       = NULL;\r
   ShellStatus   = SHELL_SUCCESS;\r
-  MappingAsHandle = NULL;\r
+  MapAsHandle = NULL;\r
 \r
   //\r
   // initialize the shell lib (we must be in non-auto-init...)\r
@@ -1062,18 +1202,30 @@ ShellCommandRunMap (
            );\r
         } else {\r
           if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {\r
-            MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping));\r
+            MapAsHandle = ConvertHandleIndexToHandle(ShellStrToUintn(Mapping));\r
           } else {\r
-            MappingAsHandle = NULL;\r
+            MapAsHandle = NULL;\r
           }\r
-          if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {\r
+          if (MapAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {\r
             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping);\r
             ShellStatus = SHELL_INVALID_PARAMETER;\r
           } else {\r
-            if (MappingAsHandle != NULL) {\r
-              ShellStatus = AddMappingFromHandle(MappingAsHandle, SName);\r
+            if (MapAsHandle != NULL) {\r
+              TempStringLength = StrLen(SName);\r
+              if (!IsNumberLetterOnly(SName, TempStringLength-(SName[TempStringLength-1]==L':'?1:0))) {\r
+                ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, SName);\r
+                ShellStatus = SHELL_INVALID_PARAMETER;\r
+              } else {\r
+                ShellStatus = AddMappingFromHandle(MapAsHandle, SName);\r
+              }\r
             } else {\r
-              ShellStatus = AddMappingFromMapping(Mapping, SName);\r
+              TempStringLength = StrLen(SName);\r
+              if (!IsNumberLetterOnly(SName, TempStringLength-(SName[TempStringLength-1]==L':'?1:0))) {\r
+                ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, SName);\r
+                ShellStatus = SHELL_INVALID_PARAMETER;\r
+              } else {\r
+                ShellStatus = AddMappingFromMapping(Mapping, SName);\r
+              }\r
             }\r
             if (ShellStatus != SHELL_SUCCESS) {\r
               switch (ShellStatus) {\r
@@ -1083,6 +1235,9 @@ ShellCommandRunMap (
                 case SHELL_INVALID_PARAMETER:\r
                   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);\r
                   break;\r
+                case SHELL_DEVICE_ERROR:\r
+                  ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NOF), gShellLevel2HiiHandle, Mapping);\r
+                  break;\r
                 default:\r
                   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT);\r
               }\r