]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
Add more checking to avoid the buffer overflow.
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / BdsConsole.c
index cb89a8d501d6668167c359655c0e3e6042d610dc..0eadec9fe7effd559be2f90b57ca167ee50ade52 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   BDS Lib functions which contain all the code to connect console device\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+Copyright (c) 2004 - 2009, Intel Corporation. <BR>\r
 All rights reserved. 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
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "InternalBdsLib.h"\r
+#include "Bmp.h"\r
 \r
 /**\r
   Check if we need to save the EFI variable with "ConVarName" as name\r
@@ -40,6 +41,10 @@ IsNvNeed (
     Ptr++;\r
   }\r
 \r
+  if ((((UINTN)Ptr - (UINTN)ConVarName) / sizeof (CHAR16)) <= 3) {\r
+    return TRUE;\r
+  }\r
+  \r
   if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {\r
     return FALSE;\r
   } else {\r
@@ -47,6 +52,121 @@ IsNvNeed (
   }\r
 }\r
 \r
+/**\r
+  Fill console handle in System Table if there are no valid console handle in.\r
+\r
+  Firstly, check the validation of console handle in System Table. If it is invalid,\r
+  update it by the first console device handle from EFI console variable. \r
+\r
+  @param  VarName            The name of the EFI console variable.\r
+  @param  ConsoleGuid        Specified Console protocol GUID.\r
+  @param  ConsoleHandle      On IN,  console handle in System Table to be checked. \r
+                             On OUT, new console hanlde in system table.\r
+  @param  ProtocolInterface  On IN,  console protocol on console handle in System Table to be checked. \r
+                             On OUT, new console protocol on new console hanlde in system table.\r
+\r
+  @retval TRUE               System Table has been updated.\r
+  @retval FALSE              System Table hasn't been updated.\r
+\r
+**/\r
+BOOLEAN \r
+UpdateSystemTableConsole (\r
+  IN     CHAR16                          *VarName,\r
+  IN     EFI_GUID                        *ConsoleGuid,\r
+  IN OUT EFI_HANDLE                      *ConsoleHandle,\r
+  IN OUT VOID                            **ProtocolInterface\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     DevicePathSize;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FullDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *VarConsole;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  VOID                      *Interface;\r
+  EFI_HANDLE                NewHandle;\r
+\r
+  ASSERT (VarName != NULL);\r
+  ASSERT (ConsoleHandle != NULL);\r
+  ASSERT (ConsoleGuid != NULL);\r
+  ASSERT (ProtocolInterface != NULL);\r
+\r
+  if (*ConsoleHandle != NULL) {\r
+    Status = gBS->HandleProtocol (\r
+                   *ConsoleHandle,\r
+                   ConsoleGuid,\r
+                   &Interface\r
+                   );\r
+    if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {\r
+      //\r
+      // If ConsoleHandle is valid and console protocol on this handle also\r
+      // also matched, just return.\r
+      //\r
+      return FALSE;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Get all possible consoles device path from EFI variable\r
+  //\r
+  VarConsole = BdsLibGetVariableAndSize (\r
+                VarName,\r
+                &gEfiGlobalVariableGuid,\r
+                &DevicePathSize\r
+                );\r
+  if (VarConsole == NULL) {\r
+    //\r
+    // If there is no any console device, just return.\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  FullDevicePath = VarConsole;\r
+\r
+  do {\r
+    //\r
+    // Check every instance of the console variable\r
+    //\r
+    Instance  = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);\r
+    if (Instance == NULL) {\r
+      FreePool (FullDevicePath);\r
+      ASSERT (FALSE);\r
+    }\r
+    \r
+    //\r
+    // Find console device handle by device path instance\r
+    //\r
+    Status = gBS->LocateDevicePath (\r
+                   ConsoleGuid,\r
+                   &Instance,\r
+                   &NewHandle\r
+                   );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Get the console protocol on this console device handle\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                     NewHandle,\r
+                     ConsoleGuid,\r
+                     &Interface\r
+                     );\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Update new console handle in System Table.\r
+        //\r
+        *ConsoleHandle     = NewHandle;\r
+        *ProtocolInterface = Interface;\r
+        return TRUE;\r
+      }\r
+    }\r
+\r
+  } while (Instance != NULL);\r
+\r
+  //\r
+  // No any available console devcie found.\r
+  //\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   This function update console variable based on ConVarName, it can\r
   add or remove one specific console device path from the variable\r
@@ -373,6 +493,7 @@ BdsLibConnectAllDefaultConsoles (
   )\r
 {\r
   EFI_STATUS                Status;\r
+  BOOLEAN                   SystemTableUpdated;\r
 \r
   //\r
   // Connect all default console variables\r
@@ -405,6 +526,32 @@ BdsLibConnectAllDefaultConsoles (
   //\r
   BdsLibConnectConsoleVariable (L"ErrOut");\r
 \r
+  SystemTableUpdated = FALSE;\r
+  //\r
+  // Fill console handles in System Table if no console device assignd.\r
+  //\r
+  if (UpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {\r
+    SystemTableUpdated = TRUE;\r
+  }\r
+  if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {\r
+    SystemTableUpdated = TRUE;\r
+  }\r
+  if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {\r
+    SystemTableUpdated = TRUE;\r
+  }\r
+\r
+  if (SystemTableUpdated) {\r
+    //\r
+    // Update the CRC32 in the EFI System Table header\r
+    //\r
+    gST->Hdr.CRC32 = 0;\r
+    gBS->CalculateCrc32 (\r
+          (UINT8 *) &gST->Hdr,\r
+          gST->Hdr.HeaderSize,\r
+          &gST->Hdr.CRC32\r
+          );\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 \r
 }\r
@@ -444,7 +591,7 @@ ConvertBmpToGopBlt (
   BMP_COLOR_MAP                 *BmpColorMap;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
-  UINT                        BltBufferSize;\r
+  UINT64                        BltBufferSize;\r
   UINTN                         Index;\r
   UINTN                         Height;\r
   UINTN                         Width;\r
@@ -480,12 +627,19 @@ ConvertBmpToGopBlt (
   // Calculate the BltBuffer needed size.\r
   //\r
   BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+  if (BltBufferSize >= SIZE_4GB) {\r
+    //\r
+    // If the BMP resolution is too large\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
   IsAllocated   = FALSE;\r
   if (*GopBlt == NULL) {\r
     //\r
     // GopBlt is not allocated by caller.\r
     //\r
-    *GopBltSize = BltBufferSize;\r
+    *GopBltSize = (UINTN) BltBufferSize;\r
     *GopBlt     = AllocatePool (*GopBltSize);\r
     IsAllocated = TRUE;\r
     if (*GopBlt == NULL) {\r
@@ -495,8 +649,8 @@ ConvertBmpToGopBlt (
     //\r
     // GopBlt has been allocated by caller.\r
     //\r
-    if (*GopBltSize < BltBufferSize) {\r
-      *GopBltSize = BltBufferSize;\r
+    if (*GopBltSize < (UINTN) BltBufferSize) {\r
+      *GopBltSize = (UINTN) BltBufferSize;\r
       return EFI_BUFFER_TOO_SMALL;\r
     }\r
   }\r
@@ -609,16 +763,7 @@ LockKeyboards (
   IN  CHAR16    *Password\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
-\r
-  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
-  if (EFI_ERROR (Status)) {\r
     return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Status = ConsoleControl->LockStdIn (ConsoleControl, Password);\r
-  return Status;\r
 }\r
 \r
 \r
@@ -639,7 +784,6 @@ EnableQuietBoot (
   )\r
 {\r
   EFI_STATUS                    Status;\r
-  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
   EFI_OEM_BADGING_PROTOCOL      *Badging;\r
   UINT32                        SizeOfX;\r
   UINT32                        SizeOfY;\r
@@ -661,11 +805,6 @@ EnableQuietBoot (
   UINT32                        RefreshRate;\r
   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;\r
 \r
-  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
   UgaDraw = NULL;\r
   //\r
   // Try to open GOP first\r
@@ -682,16 +821,13 @@ EnableQuietBoot (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Badging = NULL;\r
-  Status  = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
-\r
   //\r
-  // Set console control to graphics mode.\r
+  // Erase Cursor from screen\r
   //\r
-  Status = ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+  Badging = NULL;\r
+  Status  = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
 \r
   if (GraphicsOutput != NULL) {\r
     SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
@@ -885,17 +1021,11 @@ DisableQuietBoot (
   VOID\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
-\r
-  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
 \r
   //\r
-  // Set console control to text mode.\r
+  // Enable Cursor on Screen\r
   //\r
-  return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+  gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+  return EFI_SUCCESS;\r
 }\r
 \r