/*++ Copyright (c) 2014 Minoca Corp. All Rights Reserved Module Name: video.c Abstract: This module implements support for VESA BIOS video services via int 0x10. Author: Evan Green 25-Mar-2014 Environment: Firmware --*/ // // ------------------------------------------------------------------- Includes // #include #include #include "biosfw.h" // // --------------------------------------------------------------------- Macros // // // This macro converts the segmented addresses given in the VESA information // structure into linear addresses that can be dereferenced in protected mode. // #define VESA_SEGMENTED_TO_LINEAR_ADDRESS(_Address) \ (VOID *)((((_Address) & 0xFFFF0000) >> 12) + \ ((_Address) & 0x0000FFFF)) // // ---------------------------------------------------------------- Definitions // #define EFI_VESA_DEVICE_MAGIC 0x61736556 // 'aseV' #define EFI_VESA_DEVICE_GUID \ { \ 0x19EEE1EB, 0x8F2A, 0x4DFA, \ {0xB0, 0xF9, 0xB1, 0x0B, 0xD5, 0xB8, 0x71, 0xB9} \ } // // Define the maximum number of supported modes. // #define VESA_MAX_MODES 70 // // Define the signature at the header of the VESA Information structure, for // versions 1 and 2. // #define VESA_1_SIGNATURE 0x41534556 // 'VESA' #define VESA_2_SIGNATURE 0x32454256 // 'VBE2' // // Define video mode attribute flags. // #define VESA_MODE_ATTRIBUTE_SUPPORTED 0x0001 #define VESA_MODE_ATTRIBUTE_TTY_SUPPORTED 0x0004 #define VESA_MODE_ATTRIBUTE_COLOR 0x0008 #define VESA_MODE_ATTRIBUTE_GRAPHICS 0x0010 #define VESA_MODE_ATTRIBUTE_NON_VGA 0x0020 #define VESA_MODE_ATTRIBUTE_VGA_WINDOWED 0x0040 #define VESA_MODE_ATTRIBUTE_LINEAR 0x0080 // // Define the meaningful bits in the mode number. // #define VESA_MODE_NUMBER_USE_LINEAR_MODEL 0x4000 #define VESA_MODE_NUMBER_DONT_CLEAR_DISPLAY 0x8000 // // Define values for AX (the different VESA function calls). // #define VESA_FUNCTION_GET_VESA_INFORMATION 0x4F00 #define VESA_FUNCTION_GET_MODE_INFORMATION 0x4F01 #define VESA_FUNCTION_SET_MODE 0x4F02 // // ------------------------------------------------------ Data Type Definitions // typedef enum _VESA_MEMORY_MODEL { VesaMemoryModelText = 0, VesaMemoryModelCga = 1, VesaMemoryModelHercules = 2, VesaMemoryModel4Plane = 3, VesaMemoryModelPackedPixel = 4, VesaMemoryModelNonChain4 = 5, VesaMemoryModelDirectColor = 6, VesaMemoryModelYuv = 7 } VESA_MEMORY_MODEL, *PVESA_MEMORY_MODEL; /*++ Structure Description: This structure stores information about BIOS compatibility with the VESA video standard. Members: Signature - Stores the signature indicating this is a valid structure. The magic constant for VESA v1 means the structure content is valid through the Total Memory field. In v2 all fields are valid. VesaVersion - Stores the major version in the high byte, and the minor version in the low byte. OemStringPointer - Supplies a pointer to a NULL terminated string describing the Original Equipment Manufacturer chip, board, configuration, or anything else. Capabilities - Stores a bitfield of capabilities. The only valid bit is bit 0, which defines whether or not the DAC is switchable (has multiple modes). VideoModePointer - Stores a pointer to a list of possibly supported mode numbers. Each mode number is 16 bits in length, and the list is terminated with a -1. TotalMemoryBlocks - Storse the number of 64kB blocks of video memory in the card. OemSoftwareRevision - Stores the OEM software revision number. This is the first field that is only filled out in VESA 2.0. OemVendorNamePointer - Stores a pointer to a NULL terminated string of the vendor name. OemProductNamePointer - Stores a pointer to a NULL terminated string of the product name. OemProductRevisionPointer - Stores a pointer to a NULL terminated string of the product revision. Reserved - Stores a bunch of bytes that shouldn't be touched. OemData - Stores a section of space reserved for OEM-specific information. --*/ typedef struct _VESA_INFORMATION { UINT32 Signature; UINT16 VesaVersion; UINT32 OemStringPointer; UINT32 Capabilities; UINT32 VideoModePointer; UINT16 TotalMemoryBlocks; UINT16 OemSoftwareRevision; UINT32 OemVendorNamePointer; UINT32 OemProductNamePointer; UINT32 OemProductRevisionPointer; //UCHAR Reserved[222]; //UCHAR OemData[256]; } PACKED VESA_INFORMATION, *PVESA_INFORMATION; /*++ Structure Description: This structure stores information about a particular video mode. Members: ModeAttributes - Stores a bitfield of attributes about the mode. Bit 0 specifies if the mode can be initialized in the present video configuration. Bit 1 specifies if the optional fields are filled in. Bit 2 specifies if the BIOS supports output functions like TTY output, scrolling, pixel output, etc. WindowAAttributes - Stores a bitfield of attributes relating to the first window buffer. Bit 0 stores whether or not the window is supported, bit 1 stores whether or not the window is readable, and bit 2 stores whether or not the window is writeable. WindowBAttributes - Stores a bitfield of attributes relating to the second window. The meaning of the bits are the same as window A. WindowGranularity - Stores the smallest boundary, in kilobytes, on which the window can be placed in the video memory. WindowSize - Stores the size of each window, in kilobytes. WindowASegment - Stores the segment address of the window in CPU address space. WindowBSegment - Stores the segment address of the second window in CPU address space. WindowFunctionPointer - Stores the address of the CPU video memory windowing function. The windowing function can be invoked by VESA BIOS function 5, or by calling this address directly. BytesPerScanLine - Stores the number of bytes in one horizontal line of the video frame. This value must be at least as large as the visible bytes per line. XResolution - Stores the width of the video mode, in pixels (for text modes, the units here are characters). YResolution - Stores the height of the video mode, in pixels or characters. XCharacterSize - Stores the width of one text character, in pixels. YCharacterSize - Stores the height of one text character, in pixels. NumberOfPlanes - Stores the number of memory planes available to software in the mode. For standard 16-color VGA graphics, this would be set to 4. For standard packed pixel modes, the field would be set to 1. BitsPerPixel - Stores the number of bits in one pixel on the screen. NumberOfBanks - Stores the number of memory banks used to display a window of the mode. MemoryModel - Stores the memory model for this video mode. See the VESA_MEMORY_MODEL for possible values. BankSize - Stores the size of a bank in 1 kilobyte units. NumberOfImagePages - Stores the number of additional complete display images that will fit into the VGA's memory at one time in this mode. Reserved1 - Stores a field reserved for a future VESA feature, and will always be set to 1. RedMaskSize - Stores the number of bits in the red component of a direct color pixel. RedFieldPosition - Stores the bit position of the least significant bit of the red color component. GreenMaskSize - Stores the number of bits in the green component of a direct color pixel. GreenFieldPosition - Stores the bit position of the least significant bit of the green color component. BlueMaskSize - Stores the number of bits in the blue component of a direct color pixel. BlueFieldPosition - Stores the bit position of the least significant bit of the Blue color component. ReservedMaskSize - Stores the number of bits in the reserved component of a direct color pixel. ReservedFieldPosition - Stores the bit position of the least significant bit of the reserved component. DirectColorModeInformation - Stores a bitfield of flags relating to the direct color mode. PhysicalBasePointer - Stores the physical address of the linear frame buffer. OffScreenMemoryOffset - Stores a pointer to the start of the off screen memory. OffScreenMemorySize - Stores the size of the off screen memory, in 1 kilobyte units. --*/ typedef struct _VESA_MODE_INFORMATION { UINT16 ModeAttributes; UINT8 WindowAAttributes; UINT8 WindowBAttributes; UINT16 WindowGranularity; UINT16 WindowSize; UINT16 WindowASegment; UINT16 WindowBSegment; UINT32 WindowFunctionPointer; UINT16 BytesPerScanLine; UINT16 XResolution; UINT16 YResolution; UINT8 XCharacterSize; UINT8 YCharacterSize; UINT8 NumberOfPlanes; UINT8 BitsPerPixel; UINT8 NumberOfBanks; UINT8 MemoryModel; UINT8 BankSize; UINT8 NumberOfImagePages; UINT8 Reserved1; UINT8 RedMaskSize; UINT8 RedFieldPosition; UINT8 GreenMaskSize; UINT8 GreenFieldPosition; UINT8 BlueMaskSize; UINT8 BlueFieldPosition; UINT8 ReservedMaskSize; UINT8 ReservedFieldPosition; UINT8 DirectColorModeInformation; UINT32 PhysicalBasePointer; UINT32 OffScreenMemoryOffset; UINT16 OffScreenMemorySize; //UCHAR Reserved2[206]; } PACKED VESA_MODE_INFORMATION, *PVESA_MODE_INFORMATION; /*++ Structure Description: This structure stores the VESA graphics output mode information. Members: Information - Stores the information structure. VesaModeNumber - Stores the VESA mode number associated with this mode. BitsPerPixels - Stores the number of bits of data in a pixel. FrameBufferBase - Stores the frame buffer base address associated with this mode. Failed - Stores a boolean indicating if a failure occurred trying to set this mode. --*/ typedef struct _EFI_VESA_MODE { EFI_GRAPHICS_OUTPUT_MODE_INFORMATION Information; UINT16 VesaModeNumber; UINT16 BitsPerPixel; EFI_PHYSICAL_ADDRESS FrameBufferBase; BOOLEAN Failed; } EFI_VESA_MODE, *PEFI_VESA_MODE; /*++ Structure Description: This structure stores the internal context for a VESA device. Members: Magic - Stores the constant magic value EFI_VESA_DEVICE_MAGIC. Handle - Stores the graphics out handle. GraphicsOut - Stores the graphics output protocol. GraphicsOutMode - Stores the graphics output protocol mode. --*/ typedef struct _EFI_VESA_DEVICE { UINT32 Magic; EFI_HANDLE Handle; EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOut; EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutMode; } EFI_VESA_DEVICE, *PEFI_VESA_DEVICE; /*++ Structure Description: This structure stores the structure of a VESA device path. Members: VendorPath - Stores the vendor path portion of the device path. End - Stores the end device path node. --*/ typedef struct _EFI_VESA_DEVICE_PATH { VENDOR_DEVICE_PATH VendorPath; EFI_DEVICE_PATH_PROTOCOL End; } EFI_VESA_DEVICE_PATH, *PEFI_VESA_DEVICE_PATH; // // ----------------------------------------------- Internal Function Prototypes // EFIAPI EFI_STATUS EfipPcatGraphicsQueryMode ( EFI_GRAPHICS_OUTPUT_PROTOCOL *This, UINT32 ModeNumber, UINTN *SizeOfInfo, EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info ); EFIAPI EFI_STATUS EfipPcatGraphicsSetMode ( EFI_GRAPHICS_OUTPUT_PROTOCOL *This, UINT32 ModeNumber ); EFIAPI EFI_STATUS EfipPcatGraphicsBlt ( EFI_GRAPHICS_OUTPUT_PROTOCOL *This, EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, UINTN SourceX, UINTN SourceY, UINTN DestinationX, UINTN DestinationY, UINTN Width, UINTN Height, UINTN Delta ); EFI_STATUS EfipPcatEnumerateVesaModes ( UINT16 *VesaModeList, UINTN VesaModeCount ); UINTN EfipPcatSelectInitialVideoMode ( VOID ); EFI_STATUS EfipPcatGetVesaInformation ( PVESA_INFORMATION Information ); EFI_STATUS EfipPcatGetVesaModeInformation ( UINT16 ModeNumber, PVESA_MODE_INFORMATION ModeInformation ); EFI_STATUS EfipPcatSetVesaMode ( UINT16 ModeNumber ); // // -------------------------------------------------------------------- Globals // PEFI_VESA_MODE EfiVesaModes; UINTN EfiVesaModeCount; EFI_VESA_DEVICE_PATH EfiVesaDevicePathTemplate = { { { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof(VENDOR_DEVICE_PATH) }, EFI_VESA_DEVICE_GUID, }, { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, END_DEVICE_PATH_LENGTH } }; // // ------------------------------------------------------------------ Functions // EFI_STATUS EfipPcatEnumerateVideo ( VOID ) /*++ Routine Description: This routine enumerates the video display on a BIOS machine. Arguments: None. Return Value: EFI Status code. --*/ { PEFI_VESA_DEVICE Device; VESA_INFORMATION Information; PEFI_VESA_MODE Mode; UINT16 ModeCount; UINTN ModeIndex; UINT16 *ModeList; UINTN SelectedMode; EFI_STATUS Status; UINT16 VesaModeList[VESA_MAX_MODES]; // // Attempt to get the VESA information structure. // Information.VesaVersion = 0; Information.Signature = VESA_2_SIGNATURE; Status = EfipPcatGetVesaInformation(&Information); if (EFI_ERROR(Status)) { goto PcatEnumerateVideoEnd; } if ((Information.Signature != VESA_1_SIGNATURE) || (Information.VesaVersion < 0x0200)) { Status = EFI_UNSUPPORTED; goto PcatEnumerateVideoEnd; } ModeList = VESA_SEGMENTED_TO_LINEAR_ADDRESS(Information.VideoModePointer); // // Copy the mode list to the global. // ModeCount = 0; while ((ModeList[ModeCount] != 0xFFFF) && (ModeCount < VESA_MAX_MODES - 1)) { VesaModeList[ModeCount] = ModeList[ModeCount]; ModeCount += 1; } Status = EfipPcatEnumerateVesaModes(VesaModeList, ModeCount); if (EFI_ERROR(Status)) { return Status; } // // Attempt to find and switch to the best video mode. // Mode = NULL; for (ModeIndex = 0; ModeIndex < EfiVesaModeCount; ModeIndex += 1) { SelectedMode = EfipPcatSelectInitialVideoMode(); Mode = &(EfiVesaModes[SelectedMode]); // // All video modes have been tried. // if (Mode->Failed != FALSE) { Status = EFI_UNSUPPORTED; break; } Status = EfipPcatSetVesaMode(Mode->VesaModeNumber); if (!EFI_ERROR(Status)) { break; } Mode->Failed = TRUE; } if (EFI_ERROR(Status)) { goto PcatEnumerateVideoEnd; } // // Everything's all set up, create the graphics output protocol. // Status = EfiAllocatePool(EfiBootServicesData, sizeof(EFI_VESA_DEVICE), (VOID **)&Device); if (EFI_ERROR(Status)) { goto PcatEnumerateVideoEnd; } EfiSetMem(Device, sizeof(EFI_VESA_DEVICE), 0); Device->Magic = EFI_VESA_DEVICE_MAGIC; Device->GraphicsOut.QueryMode = EfipPcatGraphicsQueryMode; Device->GraphicsOut.SetMode = EfipPcatGraphicsSetMode; Device->GraphicsOut.Blt = EfipPcatGraphicsBlt; Device->GraphicsOut.Mode = &(Device->GraphicsOutMode); Device->GraphicsOutMode.MaxMode = EfiVesaModeCount; Device->GraphicsOutMode.Mode = ModeIndex; Device->GraphicsOutMode.Info = &(Mode->Information); Device->GraphicsOutMode.SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); Device->GraphicsOutMode.FrameBufferBase = Mode->FrameBufferBase; Device->GraphicsOutMode.FrameBufferSize = Mode->Information.PixelsPerScanLine * (Mode->BitsPerPixel / 8) * Mode->Information.VerticalResolution; Status = EfiInstallMultipleProtocolInterfaces( &(Device->Handle), &EfiGraphicsOutputProtocolGuid, &(Device->GraphicsOut), &EfiDevicePathProtocolGuid, &EfiVesaDevicePathTemplate, NULL); if (EFI_ERROR(Status)) { EfiFreePool(Device); } PcatEnumerateVideoEnd: return Status; } // // --------------------------------------------------------- Internal Functions // EFIAPI EFI_STATUS EfipPcatGraphicsQueryMode ( EFI_GRAPHICS_OUTPUT_PROTOCOL *This, UINT32 ModeNumber, UINTN *SizeOfInfo, EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info ) /*++ Routine Description: This routine returns information about available graphics modes that the graphics device and set of active video output devices support. Arguments: This - Supplies a pointer to the protocol instance. ModeNumber - Supplies the mode number to return information about. SizeOfInfo - Supplies a pointer that on input contains the size in bytes of the information buffer. Info - Supplies a pointer where a callee-allocated buffer will be returned containing information about the mode. The caller is responsible for calling FreePool to free this data. Return Value: EFI_SUCCESS on success. EFI_DEVICE_ERROR if a hardware error occurred trying to retrieve the video mode. EFI_INVALID_PARAMETER if the mode number is not valid. --*/ { EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information; EFI_STATUS Status; if ((ModeNumber >= EfiVesaModeCount) || (SizeOfInfo == NULL)) { return EFI_INVALID_PARAMETER; } Status = EfiAllocatePool(EfiBootServicesData, sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), (VOID **)&Information); if (EFI_ERROR(Status)) { return Status; } EfiCopyMem(Information, &(EfiVesaModes[ModeNumber].Information), sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); *Info = Information; *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); return EFI_SUCCESS; } EFIAPI EFI_STATUS EfipPcatGraphicsSetMode ( EFI_GRAPHICS_OUTPUT_PROTOCOL *This, UINT32 ModeNumber ) /*++ Routine Description: This routine sets the video device into the specified mode and clears the visible portions of the output display to black. Arguments: This - Supplies a pointer to the protocol instance. ModeNumber - Supplies the mode number to set. Return Value: EFI_SUCCESS on success. EFI_DEVICE_ERROR if a hardware error occurred trying to set the video mode. EFI_UNSUPPORTED if the mode number is not supported by this device. --*/ { PEFI_VESA_MODE Mode; EFI_STATUS Status; if (ModeNumber >= EfiVesaModeCount) { return EFI_UNSUPPORTED; } Mode = &(EfiVesaModes[ModeNumber]); Status = EfipPcatSetVesaMode(Mode->VesaModeNumber); if (!EFI_ERROR(Status)) { This->Mode->Info = &(Mode->Information); This->Mode->Mode = ModeNumber; This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); This->Mode->FrameBufferBase = Mode->FrameBufferBase; This->Mode->FrameBufferSize = Mode->Information.PixelsPerScanLine * (Mode->BitsPerPixel / 8) * Mode->Information.VerticalResolution; } return Status; } EFIAPI EFI_STATUS EfipPcatGraphicsBlt ( EFI_GRAPHICS_OUTPUT_PROTOCOL *This, EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, UINTN SourceX, UINTN SourceY, UINTN DestinationX, UINTN DestinationY, UINTN Width, UINTN Height, UINTN Delta ) /*++ Routine Description: This routine performs a Blt (copy) operation of pixels on the graphics screen. Blt stands for Block Transfer for those not up on their video lingo. Arguments: This - Supplies a pointer to the protocol instance. BltBuffer - Supplies an optional pointer to the data to transfer to the graphics screen. The size must be at least width * height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). BltOperation - Supplies the operation to perform when copying the buffer to the screen. SourceX - Supplies the X coordinate of the source of the operation. SourceY - Supplies the Y coordinate of the source of the operation. DestinationX - Supplies the X coordinate of the destination of the operation. DestinationY - Supplies the Y coordinate of the destination of the operation. Width - Supplies the width of the rectangle in pixels. Height - Supplies the height of the rectangle in pixels. Delta - Supplies an optional number of bytes in a row of the given buffer. If a delta of zero is used, the entire buffer is being operated on. This is not used for EfiBltVideoFill or EfiBltVideoToVideo operations. Return Value: EFI_SUCCESS on success. EFI_INVALID_PARAMETER if the operation was not valid. EFI_DEVICE_ERROR if a hardware error occurred and the request could not be completed. --*/ { return EFI_UNSUPPORTED; } EFI_STATUS EfipPcatEnumerateVesaModes ( UINT16 *VesaModeList, UINTN VesaModeCount ) /*++ Routine Description: This routine creates the mode information array from the VESA mode list. Arguments: VesaModeList - Supplies a pointer to the list of VESA modes. VesaModeCount - Supplies the number of valid mode elements in the supplied list. Return Value: EFI status. --*/ { UINTN AllocationSize; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information; UINTN ModeCount; PEFI_VESA_MODE Modes; EFI_STATUS Status; VESA_MODE_INFORMATION VesaInformation; UINTN VesaModeIndex; Modes = NULL; if (VesaModeCount == 0) { return EFI_DEVICE_ERROR; } AllocationSize = sizeof(EFI_VESA_MODE) * VesaModeCount; Status = EfiAllocatePool(EfiBootServicesData, AllocationSize, (VOID **)&Modes); if (EFI_ERROR(Status)) { return Status; } EfiSetMem(Modes, AllocationSize, 0); ModeCount = 0; for (VesaModeIndex = 0; VesaModeIndex < VesaModeCount; VesaModeIndex += 1) { Status = EfipPcatGetVesaModeInformation(VesaModeList[VesaModeIndex], &VesaInformation); if (EFI_ERROR(Status)) { continue; } // // Skip non-graphical modes and modes without a linear frame buffer. // if (((VesaInformation.ModeAttributes & VESA_MODE_ATTRIBUTE_GRAPHICS) == 0) || ((VesaInformation.ModeAttributes & VESA_MODE_ATTRIBUTE_LINEAR) == 0)) { continue; } // // Fill out the EFI mode information based on the VESA mode information. // Information = &(Modes[ModeCount].Information); Information->Version = 0; Information->HorizontalResolution = VesaInformation.XResolution; Information->VerticalResolution = VesaInformation.YResolution; Information->PixelFormat = PixelBitMask; Information->PixelInformation.RedMask = ((1 << VesaInformation.RedMaskSize) - 1) << VesaInformation.RedFieldPosition; Information->PixelInformation.GreenMask = ((1 << VesaInformation.GreenMaskSize) - 1) << VesaInformation.GreenFieldPosition; Information->PixelInformation.BlueMask = ((1 << VesaInformation.BlueMaskSize) - 1) << VesaInformation.BlueFieldPosition; Information->PixelInformation.ReservedMask = ((1 << VesaInformation.ReservedMaskSize) - 1) << VesaInformation.ReservedFieldPosition; Information->PixelsPerScanLine = VesaInformation.BytesPerScanLine / (VesaInformation.BitsPerPixel / 8); if ((Information->PixelInformation.RedMask | Information->PixelInformation.GreenMask | Information->PixelInformation.BlueMask | Information->PixelInformation.ReservedMask) == 0) { continue; } Modes[ModeCount].VesaModeNumber = VesaModeList[VesaModeIndex]; Modes[ModeCount].BitsPerPixel = VesaInformation.BitsPerPixel; Modes[ModeCount].FrameBufferBase = VesaInformation.PhysicalBasePointer; ModeCount += 1; } if (EfiVesaModes != NULL) { EfiFreePool(EfiVesaModes); EfiVesaModes = NULL; } EfiVesaModeCount = 0; if (ModeCount == 0) { EfiFreePool(Modes); return EFI_UNSUPPORTED; } EfiVesaModes = Modes; EfiVesaModeCount = ModeCount; return EFI_SUCCESS; } UINTN EfipPcatSelectInitialVideoMode ( VOID ) /*++ Routine Description: This routine attempts to select an initial VESA graphics mode. Arguments: None. Return Value: Returns the mode index of the best video mode. --*/ { EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information; PEFI_VESA_MODE Mode; UINTN ModeIndex; BOOLEAN NewWinner; UINTN WinnerBitsPerPixel; UINTN WinnerIndex; UINTN WinnerX; UINTN WinnerY; // // Find the biggest supported video mode. // WinnerIndex = 0; WinnerBitsPerPixel = 0; WinnerX = 0; WinnerY = 0; for (ModeIndex = 0; ModeIndex < EfiVesaModeCount; ModeIndex += 1) { Mode = &(EfiVesaModes[ModeIndex]); Information = &(Mode->Information); if (Mode->Failed != FALSE) { continue; } NewWinner = FALSE; // // If the resolution is just better, take it. // if ((Information->HorizontalResolution > WinnerX) && (Information->VerticalResolution > WinnerY)) { NewWinner = TRUE; // // If the resolution is at least the same but the bits per pixel is // better, take it. // } else if ((Information->HorizontalResolution >= WinnerX) && (Information->VerticalResolution >= WinnerY) && (Mode->BitsPerPixel > WinnerBitsPerPixel)) { NewWinner = TRUE; } if (NewWinner != FALSE) { WinnerX = Information->HorizontalResolution; WinnerY = Information->VerticalResolution; WinnerBitsPerPixel = Mode->BitsPerPixel; WinnerIndex = ModeIndex; } } return WinnerIndex; } EFI_STATUS EfipPcatGetVesaInformation ( PVESA_INFORMATION Information ) /*++ Routine Description: This routine attempts to get the VESA information structure. Arguments: Information - Supplies a pointer where the VESA information will be returned. Return Value: EFI Status code. --*/ { PVESA_INFORMATION InformationData; BIOS_CALL_CONTEXT RealModeContext; EFI_STATUS Status; // // Create a standard BIOS call context. // Status = EfipCreateBiosCallContext(&RealModeContext, 0x10); if (EFI_ERROR(Status)) { goto GetVesaInformationEnd; } // // Copy the signature into the data page. // InformationData = RealModeContext.DataPage; InformationData->Signature = Information->Signature; // // Set up the call to int 10, VESA function 0, get information. // RealModeContext.Eax = VESA_FUNCTION_GET_VESA_INFORMATION; RealModeContext.Es = ADDRESS_TO_SEGMENT((UINTN)RealModeContext.DataPage); RealModeContext.Edi = (UINTN)(RealModeContext.DataPage) & 0x0F; // // Execute the firmware call. // EfipExecuteBiosCall(&RealModeContext); // // Check for an error. The status code is in Ah. // if (((RealModeContext.Eax & 0xFF00) != 0) || ((RealModeContext.Eax & 0x00FF) != 0x4F)) { Status = EFI_DEVICE_ERROR; goto GetVesaInformationEnd; } EfiCopyMem(Information, InformationData, sizeof(VESA_INFORMATION)); Status = EFI_SUCCESS; GetVesaInformationEnd: EfipDestroyBiosCallContext(&RealModeContext); return Status; } EFI_STATUS EfipPcatGetVesaModeInformation ( UINT16 ModeNumber, PVESA_MODE_INFORMATION ModeInformation ) /*++ Routine Description: This routine attempts to get detailed information for the given VESA mode number. Arguments: ModeNumber - Supplies the mode number to query. ModeInformation - Supplies a pointer where the detailed mode information will be returned. Return Value: EFI Status code. --*/ { BIOS_CALL_CONTEXT RealModeContext; EFI_STATUS Status; // // Create a standard BIOS call context. // Status = EfipCreateBiosCallContext(&RealModeContext, 0x10); if (EFI_ERROR(Status)) { goto GetVesaModeInformationEnd; } // // Set up the call to int 10, VESA function 1, get mode information. // RealModeContext.Eax = VESA_FUNCTION_GET_MODE_INFORMATION; RealModeContext.Es = ADDRESS_TO_SEGMENT((UINTN)RealModeContext.DataPage); RealModeContext.Edi = (UINTN)RealModeContext.DataPage & 0x0F; RealModeContext.Ecx = ModeNumber; // // Execute the firmware call. // EfipExecuteBiosCall(&RealModeContext); // // Check for an error. The status code is in Ah. // if (((RealModeContext.Eax & 0xFF00) != 0) || ((RealModeContext.Eax & 0x00FF) != 0x4F)) { Status = EFI_DEVICE_ERROR; goto GetVesaModeInformationEnd; } EfiCopyMem(ModeInformation, RealModeContext.DataPage, sizeof(VESA_MODE_INFORMATION)); Status = EFI_SUCCESS; GetVesaModeInformationEnd: EfipDestroyBiosCallContext(&RealModeContext); return Status; } EFI_STATUS EfipPcatSetVesaMode ( UINT16 ModeNumber ) /*++ Routine Description: This routine attempts to set the given VESA mode. Arguments: ModeNumber - Supplies the mode number to set. Return Value: EFI Status code. --*/ { BIOS_CALL_CONTEXT RealModeContext; EFI_STATUS Status; // // Create a standard BIOS call context. // Status = EfipCreateBiosCallContext(&RealModeContext, 0x10); if (EFI_ERROR(Status)) { goto PcatSetVesaModeEnd; } // // Set up the call to int 10, VESA function 1, get mode information. // RealModeContext.Eax = VESA_FUNCTION_SET_MODE; RealModeContext.Ebx = ModeNumber | VESA_MODE_NUMBER_USE_LINEAR_MODEL | VESA_MODE_NUMBER_DONT_CLEAR_DISPLAY; // // Execute the firmware call. // EfipExecuteBiosCall(&RealModeContext); // // Check for an error. The status code is in Ah. // if (((RealModeContext.Eax & 0xFF00) != 0) || ((RealModeContext.Eax & 0x00FF) != 0x4F)) { Status = EFI_DEVICE_ERROR; goto PcatSetVesaModeEnd; } Status = EFI_SUCCESS; PcatSetVesaModeEnd: EfipDestroyBiosCallContext(&RealModeContext); return Status; }