From 4cd6d5d2346cb25810ea77796c721f3f070f52f2 Mon Sep 17 00:00:00 2001
From: Brendan Jackman <Brendan.Jackman@arm.com>
Date: Wed, 22 Jan 2014 15:28:08 +0000
Subject: ShellPkg/ShellProtocol.c: Fix case sensitivity in GetAlias and SetAlias

ShellCommandIsOnAliasList is case insensitive, but GetAlias and SetAlias use the
UEFI variable services, which are case sensitive.

Force alias names to lowercase to get around this.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brendan Jackman <Brendan.Jackman@arm.com>
Reviewed-By: Olivier Martin <olivier.martin@arm.com>
---
 ShellPkg/Application/Shell/ShellProtocol.c | 78 ++++++++++++++++++++++++------
 1 file changed, 63 insertions(+), 15 deletions(-)

diff --git a/ShellPkg/Application/Shell/ShellProtocol.c b/ShellPkg/Application/Shell/ShellProtocol.c
index b397610..7ad730c 100644
--- a/ShellPkg/Application/Shell/ShellProtocol.c
+++ b/ShellPkg/Application/Shell/ShellProtocol.c
@@ -3018,6 +3018,26 @@ InternalEfiShellGetListAlias(
 }
 
 /**
+  Convert a null-terminated unicode string, in-place, to all lowercase.
+  Then return it.
+**/
+STATIC
+CHAR16 *
+ToLower (
+  CHAR16 *Str
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; Str[Index] != L'\0'; Index++) {
+    if (Str[Index] >= L'A' && Str[Index] <= L'Z') {
+      Str[Index] -= (L'A' - L'a');
+    }
+  }
+  return Str;
+}
+
+/**
   This function returns the command associated with a alias or a list of all
   alias'.
 
@@ -3046,17 +3066,23 @@ EfiShellGetAlias(
   UINTN       RetSize;
   UINT32      Attribs;
   EFI_STATUS  Status;
+  CHAR16      *AliasLower;
 
+  // Convert to lowercase to make aliases case-insensitive
   if (Alias != NULL) {
+    AliasLower = AllocateCopyPool (StrSize (Alias), Alias);
+    ASSERT (AliasLower != NULL);
+    ToLower (AliasLower);
+
     if (Volatile == NULL) {
-      return (AddBufferToFreeList(GetVariable((CHAR16*)Alias, &gShellAliasGuid)));
+      return (AddBufferToFreeList(GetVariable(AliasLower, &gShellAliasGuid)));
     }
     RetSize = 0;
     RetVal = NULL;
-    Status = gRT->GetVariable((CHAR16*)Alias, &gShellAliasGuid, &Attribs, &RetSize, RetVal);
+    Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal);
     if (Status == EFI_BUFFER_TOO_SMALL) {
       RetVal = AllocateZeroPool(RetSize);
-      Status = gRT->GetVariable((CHAR16*)Alias, &gShellAliasGuid, &Attribs, &RetSize, RetVal);
+      Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal);
     }
     if (EFI_ERROR(Status)) {
       if (RetVal != NULL) {
@@ -3070,6 +3096,7 @@ EfiShellGetAlias(
       *Volatile = TRUE;
     }
 
+    FreePool (AliasLower);
     return (AddBufferToFreeList(RetVal));
   }
   return (AddBufferToFreeList(InternalEfiShellGetListAlias()));
@@ -3099,6 +3126,18 @@ InternalSetAlias(
   IN BOOLEAN Volatile
   )
 {
+  EFI_STATUS  Status;
+  CHAR16      *AliasLower;
+
+  // Convert to lowercase to make aliases case-insensitive
+  if (Alias != NULL) {
+    AliasLower = AllocateCopyPool (StrSize (Alias), Alias);
+    ASSERT (AliasLower != NULL);
+    ToLower (AliasLower);
+  } else {
+    AliasLower = NULL;
+  }
+
   //
   // We must be trying to remove one if Alias is NULL
   //
@@ -3106,7 +3145,7 @@ InternalSetAlias(
     //
     // remove an alias (but passed in COMMAND parameter)
     //
-    return (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));
+    Status = (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));
   } else {
     //
     // Add and replace are the same
@@ -3115,8 +3154,13 @@ InternalSetAlias(
     // We dont check the error return on purpose since the variable may not exist.
     gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL);
 
-    return (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));
+    Status = (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));
   }
+
+  if (Alias != NULL) {
+    FreePool (AliasLower);
+  }
+  return Status;
 }
 
 /**
@@ -3138,6 +3182,7 @@ InternalSetAlias(
   @retval EFI_NOT_FOUND         the Alias intended to be deleted was not found
   @retval EFI_ACCESS_DENIED     The alias is a built-in alias or already existed and Replace was set to
                                 FALSE.
+  @retval EFI_INVALID_PARAMETER Command is null or the empty string.
 **/
 EFI_STATUS
 EFIAPI
@@ -3148,21 +3193,24 @@ EfiShellSetAlias(
   IN BOOLEAN Volatile
   )
 {
-  //
-  // cant set over a built in alias
-  //
   if (ShellCommandIsOnAliasList(Alias==NULL?Command:Alias)) {
+    //
+    // cant set over a built in alias
+    //
     return (EFI_ACCESS_DENIED);
-  }
-  if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) {
+  } else if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) {
+    //
+    // Command is null or empty
+    //
     return (EFI_INVALID_PARAMETER);
-  }
-
-  if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) {
+  } else if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) {
+    //
+    // Alias already exists, Replace not set
+    //
     return (EFI_ACCESS_DENIED);
+  } else {
+    return (InternalSetAlias(Command, Alias, Volatile));
   }
-
-  return (InternalSetAlias(Command, Alias, Volatile));
 }
 
 // Pure FILE_HANDLE operations are passed to FileHandleLib
-- 
1.8.5

