uefibiosvideo.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,161 行 · 第 1/5 页
C
2,161 行
BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
//
// See if the VESA call succeeded
//
EdidFound = FALSE;
if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
//
// Parse EDID data structure to retrieve modes supported by monitor
//
if (ParseEdidData ((UINT8 *) BiosVideoPrivate->VbeEdidDataBlock, &ValidEdidTiming) == TRUE) {
EdidFound = TRUE;
BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
Status = gBS->AllocatePool (
EfiBootServicesData,
VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,
&BiosVideoPrivate->EdidDiscovered.Edid
);
if (EFI_ERROR (Status)) {
goto Done;
}
gBS->CopyMem (
BiosVideoPrivate->EdidDiscovered.Edid,
BiosVideoPrivate->VbeEdidDataBlock,
VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
);
BiosVideoPrivate->EdidActive.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
Status = gBS->AllocatePool (
EfiBootServicesData,
VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,
&BiosVideoPrivate->EdidActive.Edid
);
if (EFI_ERROR (Status)) {
goto Done;
}
gBS->CopyMem (
BiosVideoPrivate->EdidActive.Edid,
BiosVideoPrivate->VbeEdidDataBlock,
VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
);
} else {
BiosVideoPrivate->EdidDiscovered.SizeOfEdid = 0;
BiosVideoPrivate->EdidDiscovered.Edid = NULL;
BiosVideoPrivate->EdidActive.SizeOfEdid = 0;
BiosVideoPrivate->EdidActive.Edid = NULL;
}
}
//
// Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
//
ModeNumberPtr = (UINT16 *)
(
(((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |
((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)
);
PreferMode = 0;
ModeNumber = 0;
for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {
//
// Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
//
if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {
continue;
}
//
// Get the information about the mode
//
gBS->SetMem (&Regs, sizeof (Regs), 0);
Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;
Regs.X.CX = *ModeNumberPtr;
gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);
Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
//
// See if the call succeeded. If it didn't, then try the next mode.
//
if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
continue;
}
//
// See if the mode supports color. If it doesn't then try the next mode.
//
if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {
continue;
}
//
// See if the mode supports graphics. If it doesn't then try the next mode.
//
if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {
continue;
}
//
// See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
//
if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {
continue;
}
//
// See if the mode supports 32 bit color. If it doesn't then try the next mode.
// 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
// number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
//
if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {
continue;
}
if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {
continue;
}
if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {
continue;
}
//
// See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
//
if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {
continue;
}
if (EdidFound) {
//
// EDID exist, check whether this mode match with any mode in EDID
//
Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
Timing.RefreshRate = 60;
if (SearchEdidTiming (&ValidEdidTiming, &Timing) == FALSE) {
continue;
}
}
//
// Select a reasonable mode to be set for current display mode
//
ModeFound = FALSE;
if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&
BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768
) {
ModeFound = TRUE;
}
if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&
BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600
) {
ModeFound = TRUE;
PreferMode = ModeNumber;
}
if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&
BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480
) {
ModeFound = TRUE;
}
if ((!EdidFound) && (!ModeFound)) {
//
// When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
//
continue;
}
//
// Add mode to the list of available modes
//
ModeNumber ++;
Status = gBS->AllocatePool (
EfiBootServicesData,
ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA),
(VOID **) &ModeBuffer
);
if (EFI_ERROR (Status)) {
goto Done;
}
if (ModeNumber > 1) {
gBS->CopyMem (
ModeBuffer,
BiosVideoPrivate->ModeData,
(ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)
);
}
if (BiosVideoPrivate->ModeData != NULL) {
gBS->FreePool (BiosVideoPrivate->ModeData);
}
CurrentModeData = &ModeBuffer[ModeNumber - 1];
CurrentModeData->VbeModeNumber = *ModeNumberPtr;
if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {
CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;
CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;
CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);
CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;
CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);
CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;
CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);
CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;
CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);
} else {
CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;
CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;
CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);
CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;
CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);
CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;
CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);
CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;
CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);
}
CurrentModeData->PixelFormat = PixelBitMask;
if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&
(CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {
CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
} else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {
CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
}
}
CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;
CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;
CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;
CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;
CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;
CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;
CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;
CurrentModeData->RefreshRate = 60;
BiosVideoPrivate->ModeData = ModeBuffer;
}
//
// Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
//
if (ModeNumber == 0) {
Status = EFI_DEVICE_ERROR;
goto Done;
}
//
// Allocate buffer for Graphics Output Protocol mode information
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
(VOID **) &BiosVideoPrivate->GraphicsOutput.Mode
);
if (EFI_ERROR (Status)) {
goto Done;
}
GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode;
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
(VOID **) &GraphicsOutputMode->Info
);
if (EFI_ERROR (Status)) {
goto Done;
}
GraphicsOutputMode->MaxMode = (UINT32) ModeNumber;
//
// Current mode is unknow till now, set it to an invalid mode.
//
GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
//
// Find the best mode to initialize
//
Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);
if (EFI_ERROR (Status)) {
for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {
Status = BiosVideoGraphicsOutputSetMode (
&BiosVideoPrivate->GraphicsOutput,
(UINT32) PreferMode
);
if (!EFI_ERROR (Status)) {
break;
}
}
if (PreferMode == ModeNumber) {
//
// None mode is set successfully.
//
goto Done;
}
}
Done:
//
// If there was an error, then free the mode structure
//
if (EFI_ERROR (Status)) {
if (BiosVideoPrivate->ModeData != NULL) {
gBS->FreePool (BiosVideoPrivate->ModeData);
}
if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
}
gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
}
}
return Status;
}
EFI_STATUS
EFIAPI
BiosVideoCheckForVga (
IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate
)
/*++
Routine Description:
Check for VGA device
Arguments:
BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
Returns:
EFI_SUCCESS - Standard VGA device found
--*/
{
EFI_STATUS Status;
BIOS_VIDEO_MODE_DATA *ModeBuffer;
//
// Fill in the Graphics Output Protocol
//
BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;
BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;
BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;
//
// Allocate buffer for Graphics Output Protocol mode information
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
(VOID **) &BiosVideoPrivate->GraphicsOutput.Mode
);
if (EFI_ERROR (Status)) {
goto Done;
}
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
(VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Add mode to the list of available modes
//
BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (BIOS_VIDEO_MODE_DATA),
(VOID **) &ModeBuffer
);
if (EFI_ERROR (Status)) {
goto Done;
}
ModeBuffer->VbeModeNumber = 0x0012;
ModeBuffer->BytesPerScanLine = 640;
ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);
ModeBuffer->FrameBufferSize = 0;
ModeBuffer->HorizontalResolution = 640;
ModeBuffer->VerticalResolution = 480;
ModeBuffer->RefreshRate = 60;
ModeBuffer->PixelFormat = PixelBltOnly;
BiosVideoPrivate->ModeData = ModeBuffer;
//
// Test to see if the Video Adapter support the 640x480 16 color mode
//
BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);
Done:
//
// If there was an error, then free the mode structure
//
if (EFI_ERROR (Status)) {
if (BiosVideoPrivate->ModeData != NULL) {
gBS->FreePool (BiosVideoPrivate->ModeData);
}
if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
}
gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
}
}
return Status;
}
//
// Graphics Output Protocol Member Functions for VESA BIOS Extensions
//
EFI_STATUS
EFIAPI
BiosVideoGraphicsOutputQueryMode (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN UINT32 ModeNumber,
OUT UINTN *SizeOfInfo,
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
)
/*++
Routine Description:
Graphics Output protocol interface to get video mode
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?