]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c
Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / BiosThunk / VideoDxe / BiosVideo.c
index f8830b1763c38f22c8b7ccad694c4295462035a1..7c718ba423d750031989c6f659c98c39d6cb9f80 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   ConsoleOut Routines that speak VGA.\r
 \r
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
@@ -37,6 +37,12 @@ UINT8                          mVgaRightMaskTable[]  = { 0x80, 0xc0, 0xe0, 0xf0,
 \r
 UINT8                          mVgaBitMaskTable[]    = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
 \r
+//\r
+// Save controller attributes during first start\r
+//\r
+UINT64                         mOriginalPciAttributes;\r
+BOOLEAN                        mPciAttributesSaved = FALSE;\r
+\r
 EFI_GRAPHICS_OUTPUT_BLT_PIXEL  mVgaColorToGraphicsOutputColor[] = {\r
   { 0x00, 0x00, 0x00, 0x00 },\r
   { 0x98, 0x00, 0x00, 0x00 },\r
@@ -192,7 +198,7 @@ BiosVideoDriverBindingSupported (
         //\r
         if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
             Node->DevPath.SubType != ACPI_ADR_DP ||\r
-            DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {\r
+            DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {\r
           Status = EFI_UNSUPPORTED;\r
         }\r
       }\r
@@ -235,9 +241,7 @@ BiosVideoDriverBindingStart (
   EFI_PCI_IO_PROTOCOL       *PciIo;\r
   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
   UINTN                     Flags;\r
-  UINT64                    OriginalPciAttributes;\r
   UINT64                    Supports;\r
-  BOOLEAN                   PciAttributesSaved;\r
 \r
   //\r
   // Initialize local variables\r
@@ -281,21 +285,22 @@ BiosVideoDriverBindingStart (
     return Status;\r
   }\r
 \r
-  PciAttributesSaved = FALSE;\r
   //\r
   // Save original PCI attributes\r
   //\r
-  Status = PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationGet,\r
-                    0,\r
-                    &OriginalPciAttributes\r
-                    );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto Done;\r
+  if (!mPciAttributesSaved) {\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationGet,\r
+                      0,\r
+                      &mOriginalPciAttributes\r
+                      );\r
+    \r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    mPciAttributesSaved = TRUE;\r
   }\r
-  PciAttributesSaved = TRUE;\r
 \r
   //\r
   // Get supported PCI attributes\r
@@ -398,8 +403,7 @@ BiosVideoDriverBindingStart (
              PciIo,\r
              LegacyBios,\r
              ParentDevicePath,\r
-             RemainingDevicePath,\r
-             OriginalPciAttributes\r
+             RemainingDevicePath\r
              );\r
 \r
 Done:\r
@@ -415,16 +419,18 @@ Done:
       EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,\r
       ParentDevicePath\r
       );\r
-    if (PciAttributesSaved) {\r
-      //\r
-      // Restore original PCI attributes\r
-      //\r
-      PciIo->Attributes (\r
-                      PciIo,\r
-                      EfiPciIoAttributeOperationSet,\r
-                      OriginalPciAttributes,\r
-                      NULL\r
-                      );\r
+    if (!HasChildHandle (Controller)) {\r
+      if (mPciAttributesSaved) {\r
+        //\r
+        // Restore original PCI attributes\r
+        //\r
+        PciIo->Attributes (\r
+                        PciIo,\r
+                        EfiPciIoAttributeOperationSet,\r
+                        mOriginalPciAttributes,\r
+                        NULL\r
+                        );\r
+      }\r
     }\r
     //\r
     // Release PCI I/O Protocols on the controller handle.\r
@@ -465,6 +471,7 @@ BiosVideoDriverBindingStop (
   EFI_STATUS                   Status;\r
   BOOLEAN                      AllChildrenStopped;\r
   UINTN                        Index;\r
+  EFI_PCI_IO_PROTOCOL          *PciIo;\r
 \r
   AllChildrenStopped = TRUE;\r
 \r
@@ -494,6 +501,29 @@ BiosVideoDriverBindingStop (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  if (!HasChildHandle (Controller)) {\r
+    if (mPciAttributesSaved) {\r
+      Status = gBS->HandleProtocol (\r
+                      Controller,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      (VOID **) &PciIo\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+      \r
+      //\r
+      // Restore original PCI attributes\r
+      //\r
+      Status = PciIo->Attributes (\r
+                        PciIo,\r
+                        EfiPciIoAttributeOperationSet,\r
+                        mOriginalPciAttributes,\r
+                        NULL\r
+                        );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -507,7 +537,6 @@ BiosVideoDriverBindingStop (
   @param  ParentLegacyBios       Parent LegacyBios interface\r
   @param  ParentDevicePath       Parent Device Path\r
   @param  RemainingDevicePath    Remaining Device Path\r
-  @param  OriginalPciAttributes  Original PCI Attributes\r
 \r
   @retval EFI_SUCCESS            If a child handle was added\r
   @retval other                  A child handle was not added\r
@@ -520,8 +549,7 @@ BiosVideoChildHandleInstall (
   IN  EFI_PCI_IO_PROTOCOL          *ParentPciIo,\r
   IN  EFI_LEGACY_BIOS_PROTOCOL     *ParentLegacyBios,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,\r
-  IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath,\r
-  IN  UINT64                       OriginalPciAttributes\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
   EFI_STATUS               Status;\r
@@ -684,7 +712,6 @@ BiosVideoChildHandleInstall (
   // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
   //\r
   BiosVideoPrivate->PciIo                 = ParentPciIo;\r
-  BiosVideoPrivate->OriginalPciAttributes = OriginalPciAttributes;\r
 \r
   //\r
   // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
@@ -871,17 +898,6 @@ BiosVideoChildHandleUninstall (
   Regs.H.BL = 0;\r
   BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
 \r
-  //\r
-  // Restore original PCI attributes\r
-  //\r
-  Status = BiosVideoPrivate->PciIo->Attributes (\r
-                    BiosVideoPrivate->PciIo,\r
-                    EfiPciIoAttributeOperationSet,\r
-                    BiosVideoPrivate->OriginalPciAttributes,\r
-                    NULL\r
-                    );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
   //\r
   // Close PCI I/O protocol that opened by child handle\r
   //\r
@@ -1113,49 +1129,79 @@ ParseEdidData (
                  ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;\r
     for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {\r
       if ((TimingBits & 0x1) != 0) {\r
+        DEBUG ((EFI_D_INFO, "Established Timing: %d x %d\n",\r
+        mEstablishedEdidTiming[Index].HorizontalResolution, mEstablishedEdidTiming[Index].VerticalResolution));\r
         ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);\r
         ValidNumber ++;\r
       }\r
       TimingBits = TimingBits >> 1;\r
     }\r
-  } else {\r
+  }\r
+\r
+  //\r
+  // Parse the standard timing data\r
+  //\r
+  BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
+  for (Index = 0; Index < 8; Index ++) {\r
     //\r
-    // If no Established timing data, read the standard timing data\r
+    // Check if this is a valid Standard Timing entry\r
+    // VESA documents unused fields should be set to 01h\r
     //\r
-    BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
-    for (Index = 0; Index < 8; Index ++) {\r
-      if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
-        //\r
-        // A valid Standard Timing\r
-        //\r
-        HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);\r
-        AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
-        switch (AspectRatio) {\r
-          case 0:\r
-            VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);\r
-            break;\r
-          case 1:\r
-            VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
-            break;\r
-          case 2:\r
-            VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);\r
-            break;\r
-          case 3:\r
-            VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);\r
-            break;\r
-          default:\r
-            VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
-            break;\r
-        }\r
-        RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\r
-        TempTiming.HorizontalResolution = HorizontalResolution;\r
-        TempTiming.VerticalResolution = VerticalResolution;\r
-        TempTiming.RefreshRate = RefreshRate;\r
-        ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
-        ValidNumber ++;\r
+    if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
+      //\r
+      // A valid Standard Timing\r
+      //\r
+      HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);\r
+      AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
+      switch (AspectRatio) {\r
+        case 0:\r
+          VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);\r
+          break;\r
+        case 1:\r
+          VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
+          break;\r
+        case 2:\r
+          VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);\r
+          break;\r
+        case 3:\r
+          VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);\r
+          break;\r
+        default:\r
+          VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
+          break;\r
       }\r
-      BufferIndex += 2;\r
+      RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\r
+      DEBUG ((EFI_D_INFO, "Standard Timing: %d x %d\n", HorizontalResolution, VerticalResolution));\r
+      TempTiming.HorizontalResolution = HorizontalResolution;\r
+      TempTiming.VerticalResolution = VerticalResolution;\r
+      TempTiming.RefreshRate = RefreshRate;\r
+      ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
+      ValidNumber ++;\r
     }\r
+    BufferIndex += 2;\r
+  }\r
+\r
+  //\r
+  // Parse the Detailed Timing data\r
+  //\r
+  BufferIndex = &EdidDataBlock->DetailedTimingDescriptions[0];\r
+  for (Index = 0; Index < 4; Index ++, BufferIndex += VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE) {\r
+    if ((BufferIndex[0] == 0x0) && (BufferIndex[1] == 0x0)) {\r
+      //\r
+      // Check if this is a valid Detailed Timing Descriptor\r
+      // If first 2 bytes are zero, it is monitor descriptor other than detailed timing descriptor\r
+      //\r
+      continue;\r
+    }\r
+    //\r
+    // Calculate Horizontal and Vertical resolution\r
+    //\r
+    TempTiming.HorizontalResolution = ((UINT16)(BufferIndex[4] & 0xF0) << 4) | (BufferIndex[2]);\r
+    TempTiming.VerticalResolution = ((UINT16)(BufferIndex[7] & 0xF0) << 4) | (BufferIndex[5]);\r
+    DEBUG ((EFI_D_INFO, "Detailed Timing %d: %d x %d\n",\r
+            Index, TempTiming.HorizontalResolution, TempTiming.VerticalResolution));\r
+    ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
+    ValidNumber ++;\r
   }\r
 \r
   ValidEdidTiming->ValidNumber = ValidNumber;\r
@@ -1193,6 +1239,42 @@ SearchEdidTiming (
   return FALSE;\r
 }\r
 \r
+/**\r
+  Check if all video child handles have been uninstalled.\r
+\r
+  @param  Controller             Video controller handle\r
+\r
+  @return TRUE                   Child handles exist.\r
+  @return FALSE                  All video child handles have been uninstalled.\r
+\r
+**/\r
+BOOLEAN\r
+HasChildHandle (\r
+  IN EFI_HANDLE  Controller\r
+  )\r
+{\r
+  UINTN                                Index;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;\r
+  UINTN                                EntryCount;\r
+  BOOLEAN                              HasChild;\r
+  EFI_STATUS                           Status;\r
+\r
+  EntryCount = 0;\r
+  HasChild   = FALSE;\r
+  Status = gBS->OpenProtocolInformation (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  &OpenInfoBuffer,\r
+                  &EntryCount\r
+                  );\r
+  for (Index = 0; Index < EntryCount; Index++) {\r
+    if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+      HasChild = TRUE;\r
+    }\r
+  }\r
+  \r
+  return HasChild;\r
+}\r
 \r
 /**\r
   Check for VBE device.\r
@@ -1210,6 +1292,7 @@ BiosVideoCheckForVbe (
   EFI_STATUS                             Status;\r
   EFI_IA32_REGISTER_SET                  Regs;\r
   UINT16                                 *ModeNumberPtr;\r
+  UINT16                                 VbeModeNumber;\r
   BOOLEAN                                ModeFound;\r
   BOOLEAN                                EdidFound;\r
   BIOS_VIDEO_MODE_DATA                   *ModeBuffer;\r
@@ -1225,12 +1308,18 @@ BiosVideoCheckForVbe (
   UINT8                                  *EdidOverrideDataBlock;\r
   UINTN                                  EdidActiveDataSize;\r
   UINT8                                  *EdidActiveDataBlock;\r
+  UINT32                                 HighestHorizontalResolution;\r
+  UINT32                                 HighestVerticalResolution;\r
+  UINTN                                  HighestResolutionMode;\r
 \r
   EdidFound             = TRUE;\r
   EdidOverrideFound     = FALSE;\r
   EdidOverrideDataBlock = NULL;\r
   EdidActiveDataSize    = 0;\r
   EdidActiveDataBlock   = NULL;\r
+  HighestHorizontalResolution = 0;\r
+  HighestVerticalResolution   = 0;\r
+  HighestResolutionMode       = 0;\r
 \r
   //\r
   // Allocate buffer under 1MB for VBE data structures\r
@@ -1315,7 +1404,7 @@ BiosVideoCheckForVbe (
     //\r
     // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow\r
     //\r
-    EdidOverrideDataBlock = AllocatePool (sizeof (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2));\r
+    EdidOverrideDataBlock = AllocatePool (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2);\r
     if (NULL == EdidOverrideDataBlock) {\r
                Status = EFI_OUT_OF_RESOURCES;\r
       goto Done;\r
@@ -1419,12 +1508,17 @@ BiosVideoCheckForVbe (
 \r
   PreferMode = 0;\r
   ModeNumber = 0;\r
-\r
-  for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
+  \r
+  //\r
+  // ModeNumberPtr may be not 16-byte aligned, so ReadUnaligned16 is used to access the buffer pointed by ModeNumberPtr.\r
+  //\r
+  for (VbeModeNumber = ReadUnaligned16 (ModeNumberPtr);\r
+       VbeModeNumber != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST;\r
+       VbeModeNumber = ReadUnaligned16 (++ModeNumberPtr)) {\r
     //\r
     // Make sure this is a mode number defined by the VESA VBE specification.  If it isn'tm then skip this mode number.\r
     //\r
-    if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
+    if ((VbeModeNumber & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
       continue;\r
     }\r
     //\r
@@ -1432,7 +1526,7 @@ BiosVideoCheckForVbe (
     //\r
     gBS->SetMem (&Regs, sizeof (Regs), 0);\r
     Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
-    Regs.X.CX = *ModeNumberPtr;\r
+    Regs.X.CX = VbeModeNumber;\r
     gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
     Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
     Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
@@ -1486,6 +1580,9 @@ BiosVideoCheckForVbe (
       continue;\r
     }\r
 \r
+    DEBUG ((EFI_D_INFO, "Video Controller Mode 0x%x: %d x %d\n",\r
+            VbeModeNumber, BiosVideoPrivate->VbeModeInformationBlock->XResolution, BiosVideoPrivate->VbeModeInformationBlock->YResolution));\r
+\r
     if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
       //\r
       // EDID exist, check whether this mode match with any mode in EDID\r
@@ -1493,7 +1590,16 @@ BiosVideoCheckForVbe (
       Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
       Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
       if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) {\r
+        //\r
+        // When EDID comes from INT10 call, EDID does not include 800x600, 640x480 and 1024x768,\r
+        // but INT10 can support these modes, we add them into GOP mode.\r
+        //\r
+        if ((BiosVideoPrivate->EdidDiscovered.SizeOfEdid != 0) &&\r
+            !((Timing.HorizontalResolution) == 1024 && (Timing.VerticalResolution == 768)) &&\r
+            !((Timing.HorizontalResolution) == 800 && (Timing.VerticalResolution == 600)) &&\r
+            !((Timing.HorizontalResolution) == 640 && (Timing.VerticalResolution == 480))) {\r
         continue;\r
+        }\r
       }\r
     }\r
 \r
@@ -1526,6 +1632,17 @@ BiosVideoCheckForVbe (
       continue;\r
     }\r
 \r
+    //\r
+    // Record the highest resolution mode to set later\r
+    //\r
+    if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution > HighestHorizontalResolution) ||\r
+        ((BiosVideoPrivate->VbeModeInformationBlock->XResolution == HighestHorizontalResolution) && \r
+         (BiosVideoPrivate->VbeModeInformationBlock->YResolution > HighestVerticalResolution))) {\r
+      HighestHorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
+      HighestVerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
+      HighestResolutionMode = ModeNumber;\r
+    }\r
+\r
     //\r
     // Add mode to the list of available modes\r
     //\r
@@ -1551,7 +1668,7 @@ BiosVideoCheckForVbe (
     }\r
 \r
     CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
-    CurrentModeData->VbeModeNumber = *ModeNumberPtr;\r
+    CurrentModeData->VbeModeNumber = VbeModeNumber;\r
     if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
       CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
       CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
@@ -1588,14 +1705,18 @@ BiosVideoCheckForVbe (
     CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
     CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
     CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
-    CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
 \r
     CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
     CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
     CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
 \r
     CurrentModeData->BitsPerPixel  = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
-\r
+    CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;\r
+    //\r
+    // Make sure the FrameBufferSize does not exceed the max available frame buffer size reported by VEB.\r
+    //\r
+    ASSERT (CurrentModeData->FrameBufferSize <= (UINTN)(BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024));\r
+    \r
     BiosVideoPrivate->ModeData = ModeBuffer;\r
   }\r
   //\r
@@ -1620,6 +1741,15 @@ BiosVideoCheckForVbe (
   //\r
   // Find the best mode to initialize\r
   //\r
+  if ((PcdGet32 (PcdVideoHorizontalResolution) == 0x0) || (PcdGet32 (PcdVideoVerticalResolution) == 0x0)) {\r
+    DEBUG_CODE (\r
+      BIOS_VIDEO_MODE_DATA    *ModeData;\r
+      ModeData = &BiosVideoPrivate->ModeData[HighestResolutionMode];\r
+      DEBUG ((EFI_D_INFO, "BiosVideo set highest resolution %d x %d\n",\r
+              ModeData->HorizontalResolution, ModeData->VerticalResolution));\r
+    );\r
+    PreferMode = HighestResolutionMode;\r
+  }\r
   Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
   if (EFI_ERROR (Status)) {\r
     for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
@@ -1984,12 +2114,8 @@ BiosVideoGraphicsOutputSetMode (
   CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask));\r
   This->Mode->Info->PixelsPerScanLine =  (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
   This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
-\r
-  //\r
-  // Frame BufferSize remain unchanged\r
-  //\r
-  This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;\r
   This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
+  This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;\r
 \r
   BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
 \r