uefibiosvideo.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,161 行 · 第 1/5 页
C
2,161 行
Arguments:
This - Protocol instance pointer.
ModeNumber - The mode number to return information on.
Info - Caller allocated buffer that returns information about ModeNumber.
SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
Returns:
EFI_SUCCESS - Mode information returned.
EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
EFI_INVALID_PARAMETER - One of the input args was NULL.
--*/
{
BIOS_VIDEO_DEV *BiosVideoPrivate;
EFI_STATUS Status;
BIOS_VIDEO_MODE_DATA *ModeData;
BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
if (BiosVideoPrivate->HardwareNeedsStarting) {
return EFI_NOT_STARTED;
}
if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
Info
);
if (EFI_ERROR (Status)) {
return Status;
}
*SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
(*Info)->Version = 0;
(*Info)->HorizontalResolution = ModeData->HorizontalResolution;
(*Info)->VerticalResolution = ModeData->VerticalResolution;
(*Info)->PixelFormat = ModeData->PixelFormat;
(*Info)->PixelInformation = ModeData->PixelBitMask;
(*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
BiosVideoGraphicsOutputSetMode (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
IN UINT32 ModeNumber
)
/*++
Routine Description:
Graphics Output protocol interface to set video mode
Arguments:
This - Protocol instance pointer.
ModeNumber - The mode number to be set.
Returns:
EFI_SUCCESS - Graphics mode was changed.
EFI_DEVICE_ERROR - The device had an error and could not complete the request.
EFI_UNSUPPORTED - ModeNumber is not supported by this device.
--*/
{
EFI_STATUS Status;
BIOS_VIDEO_DEV *BiosVideoPrivate;
EFI_IA32_REGISTER_SET Regs;
BIOS_VIDEO_MODE_DATA *ModeData;
BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
if (ModeNumber >= This->Mode->MaxMode) {
return EFI_UNSUPPORTED;
}
if (ModeNumber == This->Mode->Mode) {
return EFI_SUCCESS;
}
ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
if (BiosVideoPrivate->LineBuffer) {
gBS->FreePool (BiosVideoPrivate->LineBuffer);
}
if (BiosVideoPrivate->VgaFrameBuffer) {
gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);
}
if (BiosVideoPrivate->VbeFrameBuffer) {
gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);
}
BiosVideoPrivate->LineBuffer = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
ModeData->BytesPerScanLine,
&BiosVideoPrivate->LineBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Clear all registers
//
gBS->SetMem (&Regs, sizeof (Regs), 0);
if (ModeData->VbeModeNumber < 0x100) {
//
// Allocate a working buffer for BLT operations to the VGA frame buffer
//
BiosVideoPrivate->VgaFrameBuffer = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
4 * 480 * 80,
&BiosVideoPrivate->VgaFrameBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Set VGA Mode
//
Regs.X.AX = ModeData->VbeModeNumber;
BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
} else {
//
// Allocate a working buffer for BLT operations to the VBE frame buffer
//
BiosVideoPrivate->VbeFrameBuffer = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
ModeData->BytesPerScanLine * ModeData->VerticalResolution,
&BiosVideoPrivate->VbeFrameBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Set VBE mode
//
Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;
Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);
gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);
Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
//
// Check to see if the call succeeded
//
if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
return EFI_DEVICE_ERROR;
}
//
// Initialize the state of the VbeFrameBuffer
//
Status = BiosVideoPrivate->PciIo->Mem.Read (
BiosVideoPrivate->PciIo,
EfiPciIoWidthUint32,
EFI_PCI_IO_PASS_THROUGH_BAR,
(UINT64) (UINTN) ModeData->LinearFrameBuffer,
(ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,
BiosVideoPrivate->VbeFrameBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
}
This->Mode->Mode = ModeNumber;
This->Mode->Info->Version = 0;
This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
This->Mode->Info->PixelFormat = ModeData->PixelFormat;
This->Mode->Info->PixelInformation = ModeData->PixelBitMask;
This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
//
// Frame BufferSize remain unchanged
//
This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) ModeData->LinearFrameBuffer;
This->Mode->FrameBufferSize = ModeData->FrameBufferSize;
BiosVideoPrivate->HardwareNeedsStarting = FALSE;
return EFI_SUCCESS;
}
//
// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes
//
EFI_STATUS
EFIAPI
BiosVideoGraphicsOutputVbeBlt (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta
)
/*++
Routine Description:
Graphics Output protocol instance to block transfer for VBE device
Arguments:
This - Pointer to Graphics Output protocol instance
BltBuffer - The data to transfer to screen
BltOperation - The operation to perform
SourceX - The X coordinate of the source for BltOperation
SourceY - The Y coordinate of the source for BltOperation
DestinationX - The X coordinate of the destination for BltOperation
DestinationY - The Y coordinate of the destination for BltOperation
Width - The width of a rectangle in the blt rectangle in pixels
Height - The height of a rectangle in the blt rectangle in pixels
Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
If a Delta of 0 is used, the entire BltBuffer will be operated on.
If a subrectangle of the BltBuffer is used, then Delta represents
the number of bytes in a row of the BltBuffer.
Returns:
EFI_INVALID_PARAMETER - Invalid parameter passed in
EFI_SUCCESS - Blt operation success
--*/
{
BIOS_VIDEO_DEV *BiosVideoPrivate;
BIOS_VIDEO_MODE_DATA *Mode;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_TPL OriginalTPL;
UINTN DstY;
UINTN SrcY;
UINTN DstX;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
VOID *MemAddress;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
UINTN BytesPerScanLine;
UINTN Index;
UINT8 *VbeBuffer;
UINT8 *VbeBuffer1;
UINT8 *BltUint8;
UINT32 VbePixelWidth;
UINT32 Pixel;
BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];
PciIo = BiosVideoPrivate->PciIo;
VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;
MemAddress = Mode->LinearFrameBuffer;
BytesPerScanLine = Mode->BytesPerScanLine;
VbePixelWidth = Mode->BitsPerPixel / 8;
BltUint8 = (UINT8 *) BltBuffer;
if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
return EFI_INVALID_PARAMETER;
}
if (Width == 0 || Height == 0) {
return EFI_INVALID_PARAMETER;
}
//
// We need to fill the Virtual Screen buffer with the blt data.
// The virtual screen is upside down, as the first row is the bootom row of
// the image.
//
if (BltOperation == EfiBltVideoToBltBuffer) {
//
// Video to BltBuffer: Source is Video, destination is BltBuffer
//
if (SourceY + Height > Mode->VerticalResolution) {
return EFI_INVALID_PARAMETER;
}
if (SourceX + Width > Mode->HorizontalResolution) {
return EFI_INVALID_PARAMETER;
}
} else {
//
// BltBuffer to Video: Source is BltBuffer, destination is Video
//
if (DestinationY + Height > Mode->VerticalResolution) {
return EFI_INVALID_PARAMETER;
}
if (DestinationX + Width > Mode->HorizontalResolution) {
return EFI_INVALID_PARAMETER;
}
}
//
// If Delta is zero, then the entire BltBuffer is being used, so Delta
// is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
// the number of bytes in each row can be computed.
//
if (Delta == 0) {
Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
}
//
// We have to raise to TPL Notify, so we make an atomic write the frame buffer.
// We would not want a timer based event (Cursor, ...) to come in while we are
// doing this operation.
//
OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY);
switch (BltOperation) {
case EfiBltVideoToBltBuffer:
for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
//
// Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
//
VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
Pixel = *(UINT32 *) (VbeBuffer);
Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
Blt->Reserved = 0;
Blt++;
VbeBuffer += VbePixelWidth;
}
}
break;
case EfiBltVideoToVideo:
for (Index = 0; Index < Height; Index++) {
if (DestinationY <= SourceY) {
SrcY = SourceY + Index;
DstY = DestinationY + Index;
} else {
SrcY = SourceY + Height - Index - 1;
DstY = DestinationY + Height - Index - 1;
}
VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
gBS->CopyMem (
VbeBuffer,
VbeBuffer1,
Width * VbePixelWidth
);
if (VbePixelWidth == 4) {
PciIo->Mem.Write (
PciIo,
EfiPciIoWidthUint32,
EFI_PCI_IO_PASS_THROUGH_BAR,
(UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
Width,
VbeBuffer
);
} else {
PciIo->Mem.Write (
PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
(UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
Width * VbePixelWidth,
VbeBuffer
);
}
}
break;
case EfiBltVideoFill:
VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
//
// Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
//
Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
(
(Blt->Green & Mode->Green.Mask) <<
Mode->Green.Position
) |
((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
for (Index = 0; Index < Width; Index++) {
gBS->CopyMem (
VbeBuffer,
&Pixel,
VbePixelWidth
);
VbeBuffer += VbePixelWidth;
}
VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
gBS->CopyMem (
(VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
VbeBuffer,
Width * VbePixelWidth
);
}
for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
PciIo->Mem.Write (
PciIo,
EfiPciIoWidthUint8,
EFI_PCI_IO_PASS_THROUGH_BAR,
(UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?