singrdk/base/boot/SingLdrPc/blvesa.cpp

234 lines
5.6 KiB
C++

//++
//
// Copyright (c) Microsoft Corporation
//
// Module Name:
//
// blvesa.cpp
//
// Abstract:
//
// This module implements VESA grahics support for the boot loader.
//
//--
#include "bl.h"
#pragma pack(1)
typedef union __declspec(align(16)) _BL_VESA_INFO {
struct {
UINT8 Signature[4];
UINT16 Version;
FAR_POINTER Oem; // LPCHAR
UINT8 Capabilities[4];
FAR_POINTER Modes; // LPUSHORT
UINT16 Memory;
};
UINT8 Raw[1024];
} BL_VESA_INFO, *PBL_VESA_INFO;
typedef union __declspec(align(16)) _BL_VESA_MODE {
struct {
UINT16 Attributes;
UINT8 WindowA;
UINT8 WindowB;
UINT16 Granularity;
UINT16 Size;
UINT16 WindowASegment;
UINT16 WindowBSegment;
FAR_POINTER WindowFuncPtr; // LPUCHAR
UINT16 BytesPerLine;
UINT16 XRes;
UINT16 YRes;
UINT8 XCharSize;
UINT8 YCharSize;
UINT8 Planes;
UINT8 BitsPerPixel;
UINT8 Banks;
UINT8 MemoryModel;
UINT8 BankSize;
UINT8 ImagePages;
UINT8 Reserved;
UINT8 RedMaskSize;
UINT8 RedFieldPos;
UINT8 GreenMaskSize;
UINT8 GreenFieldPos;
UINT8 BlueMaskSize;
UINT8 BlueFieldPos;
UINT8 ReservedMaskSize;
UINT8 ReservedFieldPos;
UINT8 DirectColorInfo;
// VBE 2.0
UINT32 PhysBasePtr;
UINT32 Reserved1;
UINT16 Reserved2;
};
UINT8 Raw[1024];
} BL_VESA_MODE, *PBL_VESA_MODE;
#pragma pack()
BL_VESA_INFO BlVesaInfo;
BL_VESA_MODE BlVesaMode;
ULONG_PTR BlVesaVideoBuffer;
UINT32
BlVesaInvoke(
UINT32 Ax,
UINT32 Bx,
UINT32 Cx,
PVOID Buffer
)
{
ULONG_PTR Address;
BL_LEGACY_CALL_CONTEXT Context;
BlRtlZeroMemory(&Context, sizeof(Context));
Context.eax = Ax;
Context.ebx = Bx;
Context.ecx = Cx;
Address = (ULONG_PTR)Buffer;
Context.es = (UINT32)(Address >> 4);
Context.edi = (UINT32)(Address & 0xF);
BlRtlCallLegacyInterruptService(0x10, &Context, &Context);
return Context.eax;
}
BOOLEAN
BlVesaInitialize(
VOID
)
{
UINT32 Returned;
PUINT16 ModeList;
UINT16 Mode;
ULONG_PTR Video;
//
// Determine if a VESA video card is enabled.
//
BlRtlZeroMemory(&BlVesaInfo, sizeof(BlVesaInfo));
Returned = BlVesaInvoke(0x4f00, 0, 0, &BlVesaInfo);
if (Returned != 0x4f ||
BlVesaInfo.Signature[0] != 'V' ||
BlVesaInfo.Signature[1] != 'E' ||
BlVesaInfo.Signature[2] != 'S' ||
BlVesaInfo.Signature[3] != 'A' ||
BlVesaInfo.Version < 0x200) {
BlRtlPrintf("VESA: No VESA found.\n");
return FALSE;
}
//
// Print the VESA identification information.
//
BlRtlPrintf("VESA: %c%c%c%c V%x %s (%d MB)\n",
BlVesaInfo.Signature[0],
BlVesaInfo.Signature[1],
BlVesaInfo.Signature[2],
BlVesaInfo.Signature[3],
BlVesaInfo.Version,
(PCHAR) BlRtlConvertFarPointerToLinearPointer(&BlVesaInfo.Oem),
BlVesaInfo.Memory / 16);
//
// Search list of modes for 1024 x 768 x 16.
//
ModeList = (PUINT16) BlRtlConvertFarPointerToLinearPointer((PFAR_POINTER) &BlVesaInfo.Modes);
for (; *ModeList != 0xffff; ModeList++) {
Mode = *ModeList;
//
// Query for the mode information.
//
BlRtlZeroMemory(&BlVesaMode, sizeof(BlVesaMode));
Returned = BlVesaInvoke(0x4f01, 0, Mode, &BlVesaMode);
if (Returned != 0x4f || BlVesaMode.BitsPerPixel > 8) {
BlRtlPrintf("VESA: Mode %03x: Attr=%04x, Addr=%p Res=%dx%dx%d\n",
Mode,
BlVesaMode.Attributes,
(ULONG_PTR)BlVesaMode.PhysBasePtr,
BlVesaMode.XRes,
BlVesaMode.YRes,
BlVesaMode.BitsPerPixel);
//
// See if one of the modes suport 1024 x 768 x 16 bits.
//
if (BlVesaMode.XRes == 1024 &&
BlVesaMode.YRes == 768 &&
BlVesaMode.BitsPerPixel == 16) {
Video = (ULONG_PTR)BlVesaMode.PhysBasePtr;
BlRtlZeroMemory(&BlVesaMode, sizeof(BlVesaMode));
if (Mode >= 0x100) {
Returned = BlVesaInvoke(0x4f02, 0x4000 | Mode, 0, &BlVesaMode);
}
else {
Returned = BlVesaInvoke(0x4f02, Mode, 0, &BlVesaMode);
}
if (Returned != 0x4f) {
BlRtlPrintf(" Couldn't enable Linear Frame Buffer.\n");
continue;
}
BlRtlPrintf("VESA: Select 1024 x 768 x 16 @ %p\n", Video);
BlVesaVideoBuffer = Video;
}
}
}
if (BlVesaVideoBuffer != 0) {
PUINT16 Buffer = (PUINT16)BlVesaVideoBuffer;
INT32 i = 0;
for (; i < 1 * 1024; i++) {
Buffer[i] = 0xf800;
}
for (; i < 2 * 1024; i++) {
Buffer[i] = 0x07e0;
}
for (; i < 3 * 1024; i++) {
Buffer[i] = 0x001f;
}
for (; i < 4 * 1024; i++) {
Buffer[i] = 0xffff;
}
}
return FALSE;
}