/** @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
((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
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
//\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
\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
//\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
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
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
//\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
}\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
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
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