]> 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 cc53355e75bd12bbda20413af135c5126577d3e0..7c718ba423d750031989c6f659c98c39d6cb9f80 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   ConsoleOut Routines that speak VGA.\r
 \r
-Copyright (c) 2007 - 2012, 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
@@ -1129,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
@@ -1262,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
@@ -1373,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
@@ -1477,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
@@ -1490,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
@@ -1544,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
@@ -1551,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
@@ -1587,8 +1635,9 @@ BiosVideoCheckForVbe (
     //\r
     // Record the highest resolution mode to set later\r
     //\r
-    if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution >= HighestHorizontalResolution) &&\r
-        (BiosVideoPrivate->VbeModeInformationBlock->YResolution >= HighestVerticalResolution)) {\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
@@ -1619,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
@@ -1656,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
@@ -2061,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