- Moved boot video support to a seperate driver.

svn path=/trunk/; revision=5819
This commit is contained in:
David Welch 2003-08-24 12:11:13 +00:00
parent d75ef2bebd
commit 26c230dd5a
8 changed files with 1037 additions and 1 deletions

View file

@ -59,7 +59,7 @@ DRIVERS_LIB = bzip2
# Kernel mode device drivers
# Obsolete: ide
# beep blue floppy null parallel ramdrv serenum serial vga videoprt
DEVICE_DRIVERS = beep blue debugout floppy null serial vga videoprt
DEVICE_DRIVERS = beep blue debugout floppy null serial vga videoprt bootvid
# Kernel mode input drivers
INPUT_DRIVERS = keyboard mouclass psaux sermouse

View file

@ -0,0 +1,8 @@
base.tmp
junk.tmp
temp.exp
bootvid.coff
*.sym
*.o
*.sys
*.map

View file

@ -0,0 +1,13 @@
# $Id: Makefile,v 1.1 2003/08/24 12:11:13 dwelch Exp $
PATH_TO_TOP = ../../..
TARGET_TYPE = driver
TARGET_NAME = bootvid
TARGET_OBJECTS = bootvid.o pixelsup_i386.o
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

View file

@ -0,0 +1,863 @@
/* $Id: bootvid.c,v 1.1 2003/08/24 12:11:13 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/inbv/bootvid.c
* PURPOSE: Boot video support
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 12-07-2003 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h>
#include <ddk/ntbootvid.h>
#include <reactos/resource.h>
#include "../../../ntoskrnl/include/internal/v86m.h"
#define NDEBUG
#include <debug.h>
#define RT_BITMAP 2
typedef struct tagRGBQUAD {
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD, *PRGBQUAD;
typedef long FXPT2DOT30;
typedef struct tagCIEXYZ {
FXPT2DOT30 ciexyzX;
FXPT2DOT30 ciexyzY;
FXPT2DOT30 ciexyzZ;
} CIEXYZ;
typedef CIEXYZ * LPCIEXYZ;
typedef struct tagCIEXYZTRIPLE {
CIEXYZ ciexyzRed;
CIEXYZ ciexyzGreen;
CIEXYZ ciexyzBlue;
} CIEXYZTRIPLE;
typedef CIEXYZTRIPLE *LPCIEXYZTRIPLE;
typedef struct {
DWORD bV5Size;
LONG bV5Width;
LONG bV5Height;
WORD bV5Planes;
WORD bV5BitCount;
DWORD bV5Compression;
DWORD bV5SizeImage;
LONG bV5XPelsPerMeter;
LONG bV5YPelsPerMeter;
DWORD bV5ClrUsed;
DWORD bV5ClrImportant;
DWORD bV5RedMask;
DWORD bV5GreenMask;
DWORD bV5BlueMask;
DWORD bV5AlphaMask;
DWORD bV5CSType;
CIEXYZTRIPLE bV5Endpoints;
DWORD bV5GammaRed;
DWORD bV5GammaGreen;
DWORD bV5GammaBlue;
DWORD bV5Intent;
DWORD bV5ProfileData;
DWORD bV5ProfileSize;
DWORD bV5Reserved;
} BITMAPV5HEADER, *PBITMAPV5HEADER;
#define MISC 0x3c2
#define SEQ 0x3c4
#define CRTC 0x3d4
#define GRAPHICS 0x3ce
#define FEATURE 0x3da
#define ATTRIB 0x3c0
#define STATUS 0x3da
typedef struct _VideoMode {
unsigned short VidSeg;
unsigned char Misc;
unsigned char Feature;
unsigned short Seq[6];
unsigned short Crtc[25];
unsigned short Gfx[9];
unsigned char Attrib[21];
} VideoMode;
typedef struct {
ULONG r;
ULONG g;
ULONG b;
} FADER_PALETTE_ENTRY;
/* In pixelsups.S */
extern VOID
InbvPutPixels(int x, int y, unsigned long c);
/* GLOBALS *******************************************************************/
char *vidmem;
/* Must be 4 bytes per entry */
long maskbit[640];
long y80[480];
static HANDLE BitmapThreadHandle;
static CLIENT_ID BitmapThreadId;
static BOOLEAN BitmapIsDrawn;
static BOOLEAN BitmapThreadShouldTerminate;
static PUCHAR BootimageBitmap;
static BOOLEAN InGraphicsMode = FALSE;
/* DATA **********************************************************************/
static VideoMode Mode12 = {
0xa000, 0xe3, 0x00,
{0x03, 0x01, 0x0f, 0x00, 0x06 },
{0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x59, 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
0xff},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff},
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x81, 0x00, 0x0f, 0x00, 0x00}
};
static BOOLEAN VideoAddressSpaceInitialized = FALSE;
static PVOID NonBiosBaseAddress;
static PDRIVER_OBJECT BootVidDriverObject = NULL;
/* FUNCTIONS *****************************************************************/
static BOOLEAN
InbvFindBootimage()
{
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
LDR_RESOURCE_INFO ResourceInfo;
NTSTATUS Status;
PVOID BaseAddress = BootVidDriverObject->DriverStart;
ULONG Size;
ResourceInfo.Type = RT_BITMAP;
ResourceInfo.Name = IDB_BOOTIMAGE;
ResourceInfo.Language = 0x09;
Status = LdrFindResource_U(BaseAddress,
&ResourceInfo,
RESOURCE_DATA_LEVEL,
&ResourceDataEntry);
if (!NT_SUCCESS(Status))
{
DPRINT("LdrFindResource_U() failed with status 0x%.08x\n", Status);
return FALSE;
}
Status = LdrAccessResource(BaseAddress,
ResourceDataEntry,
(PVOID*)&BootimageBitmap,
&Size);
if (!NT_SUCCESS(Status))
{
DPRINT("LdrAccessResource() failed with status 0x%.08x\n", Status);
return FALSE;
}
return TRUE;
}
static BOOLEAN
InbvInitializeVideoAddressSpace(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING PhysMemName;
NTSTATUS Status;
HANDLE PhysMemHandle;
PVOID BaseAddress;
LARGE_INTEGER Offset;
ULONG ViewSize;
CHAR IVT[1024];
CHAR BDA[256];
PVOID start = (PVOID)0x0;
/*
* Open the physical memory section
*/
RtlInitUnicodeStringFromLiteral(&PhysMemName, L"\\Device\\PhysicalMemory");
InitializeObjectAttributes(&ObjectAttributes,
&PhysMemName,
0,
NULL,
NULL);
Status = ZwOpenSection(&PhysMemHandle, SECTION_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("Couldn't open \\Device\\PhysicalMemory\n");
return FALSE;
}
/*
* Map the BIOS and device registers into the address space
*/
Offset.QuadPart = 0xa0000;
ViewSize = 0x100000 - 0xa0000;
BaseAddress = (PVOID)0xa0000;
Status = NtMapViewOfSection(PhysMemHandle,
NtCurrentProcess(),
&BaseAddress,
0,
8192,
&Offset,
&ViewSize,
ViewUnmap,
0,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT("Couldn't map physical memory (%x)\n", Status);
NtClose(PhysMemHandle);
return FALSE;
}
NtClose(PhysMemHandle);
if (BaseAddress != (PVOID)0xa0000)
{
DPRINT("Couldn't map physical memory at the right address "
"(was %x)\n", BaseAddress);
return FALSE;
}
/*
* Map some memory to use for the non-BIOS parts of the v86 mode address
* space
*/
NonBiosBaseAddress = (PVOID)0x1;
ViewSize = 0xa0000 - 0x1000;
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
&NonBiosBaseAddress,
0,
&ViewSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT("Failed to allocate virtual memory (Status %x)\n", Status);
return FALSE;
}
if (NonBiosBaseAddress != (PVOID)0x0)
{
DPRINT("Failed to allocate virtual memory at right address "
"(was %x)\n", NonBiosBaseAddress);
return FALSE;
}
/*
* Get the real mode IVT from the kernel
*/
Status = NtVdmControl(0, IVT);
if (!NT_SUCCESS(Status))
{
DPRINT("NtVdmControl failed (status %x)\n", Status);
return FALSE;
}
/*
* Copy the real mode IVT into the right place
*/
memcpy(start, IVT, 1024);
/*
* Get the BDA from the kernel
*/
Status = NtVdmControl(1, BDA);
if (!NT_SUCCESS(Status))
{
DPRINT("NtVdmControl failed (status %x)\n", Status);
return FALSE;
}
/*
* Copy the BDA into the right place
*/
memcpy((PVOID)0x400, BDA, 256);
return TRUE;
}
static BOOLEAN
InbvDeinitializeVideoAddressSpace(VOID)
{
ULONG RegionSize;
PUCHAR ViewBase;
RegionSize = 0xa0000 - 0x1000;
NtFreeVirtualMemory(NtCurrentProcess(),
&NonBiosBaseAddress,
&RegionSize,
MEM_RELEASE);
ViewBase = (PUCHAR) 0xa0000;
ZwUnmapViewOfSection(NtCurrentProcess(), ViewBase);
return TRUE;
}
static VOID
vgaPreCalc()
{
ULONG j;
for(j = 0; j < 80; j++)
{
maskbit[j * 8 + 0] = 128;
maskbit[j * 8 + 1] = 64;
maskbit[j * 8 + 2] = 32;
maskbit[j * 8 + 3] = 16;
maskbit[j * 8 + 4] = 8;
maskbit[j * 8 + 5] = 4;
maskbit[j * 8 + 6] = 2;
maskbit[j * 8 + 7] = 1;
}
for(j = 0; j < 480; j++)
{
y80[j] = j * 80; /* 80 = 640 / 8 = Number of bytes per scanline */
}
}
static __inline__ VOID
InbvOutxay(PUSHORT ad, UCHAR x, UCHAR y)
{
USHORT xy = (x << 8) + y;
WRITE_PORT_USHORT(ad, xy);
}
static VOID
InbvSetMode(VideoMode mode)
{
unsigned char x;
WRITE_PORT_UCHAR((PUCHAR)MISC, mode.Misc);
WRITE_PORT_UCHAR((PUCHAR)STATUS, 0);
WRITE_PORT_UCHAR((PUCHAR)FEATURE, mode.Feature);
for(x=0; x<5; x++)
{
InbvOutxay((PUSHORT)SEQ, mode.Seq[x], x);
}
WRITE_PORT_USHORT((PUSHORT)CRTC, 0x11);
WRITE_PORT_USHORT((PUSHORT)CRTC, (mode.Crtc[0x11] & 0x7f));
for(x=0; x<25; x++)
{
InbvOutxay((PUSHORT)CRTC, mode.Crtc[x], x);
}
for(x=0; x<9; x++)
{
InbvOutxay((PUSHORT)GRAPHICS, mode.Gfx[x], x);
}
x=READ_PORT_UCHAR((PUCHAR)FEATURE);
for(x=0; x<21; x++)
{
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, x);
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, mode.Attrib[x]);
}
x=READ_PORT_UCHAR((PUCHAR)STATUS);
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, 0x20);
}
static VOID
InbvInitVGAMode(VOID)
{
KV86M_REGISTERS Regs;
NTSTATUS Status;
vidmem = (char *)(0xd0000000 + 0xa0000);
memset(&Regs, 0, sizeof(Regs));
Regs.Eax = 0x0012;
Status = Ke386CallBios(0x10, &Regs);
assert(NT_SUCCESS(Status));
/* Get VGA registers into the correct state (mainly for setting up the palette registers correctly) */
InbvSetMode(Mode12);
/* Get the VGA into the mode we want to work with */
WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); /* Set */
WRITE_PORT_UCHAR((PUCHAR)0x3cf,0); /* the MASK */
WRITE_PORT_USHORT((PUSHORT)0x3ce,0x0205); /* write mode = 2 (bits 0,1) read mode = 0 (bit 3) */
(UCHAR) READ_REGISTER_UCHAR(vidmem); /* Update bit buffer */
WRITE_REGISTER_UCHAR(vidmem, 0); /* Write the pixel */
WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);
WRITE_PORT_UCHAR((PUCHAR)0x3cf,0xff);
/* Zero out video memory (clear a possibly trashed screen) */
RtlZeroMemory(vidmem, 64000);
vgaPreCalc();
}
BOOLEAN
STDCALL
VidResetDisplay(VOID)
{
/*
We are only using standard VGA facilities so we can rely on the HAL 'int10mode3'
reset to cleanup the hardware state.
*/
InGraphicsMode = FALSE;
return FALSE;
}
VOID
STDCALL
VidCleanUp(VOID)
{
/*
We are only using standard VGA facilities so we can rely on the HAL 'int10mode3'
reset to cleanup the hardware state.
*/
InGraphicsMode = FALSE;
BitmapThreadShouldTerminate = TRUE;
}
static __inline__ VOID
InbvSetColor(int cindex, unsigned char red, unsigned char green, unsigned char blue)
{
red = red / (256 / 64);
green = green / (256 / 64);
blue = blue / (256 / 64);
WRITE_PORT_UCHAR((PUCHAR)0x03c8, cindex);
WRITE_PORT_UCHAR((PUCHAR)0x03c9, red);
WRITE_PORT_UCHAR((PUCHAR)0x03c9, green);
WRITE_PORT_UCHAR((PUCHAR)0x03c9, blue);
}
static __inline__ VOID
InbvSetBlackPalette()
{
register ULONG r = 0;
for (r = 0; r < 16; r++)
{
InbvSetColor(r, 0, 0, 0);
}
}
static VOID
InbvDisplayBitmap(ULONG Width, ULONG Height, PCHAR ImageData)
{
ULONG j,k,y;
register ULONG i;
register ULONG x;
register ULONG c;
k = 0;
for (y = 0; y < Height; y++)
{
for (j = 0; j < 8; j++)
{
x = j;
/*
* Loop through the line and process every 8th pixel.
* This way we can get a way with using the same bit mask
* for several pixels and thus not need to do as much I/O
* communication.
*/
while (x < 640)
{
c = 0;
if (x < Width)
{
c = ImageData[k + x];
for (i = 1; i < 4; i++)
{
if (x + i*8 < Width)
{
c |= (ImageData[k + x + i * 8] << i * 8);
}
}
}
InbvPutPixels(x, 479 - y, c);
x += 8*4;
}
}
k += Width;
}
}
static VOID
InbvDisplayCompressedBitmap()
{
PBITMAPV5HEADER bminfo;
ULONG i,j,k;
ULONG x,y;
ULONG curx,cury;
ULONG bfOffBits;
ULONG clen;
PCHAR ImageData;
bminfo = (PBITMAPV5HEADER) &BootimageBitmap[0];
DPRINT("bV5Size = %d\n", bminfo->bV5Size);
DPRINT("bV5Width = %d\n", bminfo->bV5Width);
DPRINT("bV5Height = %d\n", bminfo->bV5Height);
DPRINT("bV5Planes = %d\n", bminfo->bV5Planes);
DPRINT("bV5BitCount = %d\n", bminfo->bV5BitCount);
DPRINT("bV5Compression = %d\n", bminfo->bV5Compression);
DPRINT("bV5SizeImage = %d\n", bminfo->bV5SizeImage);
DPRINT("bV5XPelsPerMeter = %d\n", bminfo->bV5XPelsPerMeter);
DPRINT("bV5YPelsPerMeter = %d\n", bminfo->bV5YPelsPerMeter);
DPRINT("bV5ClrUsed = %d\n", bminfo->bV5ClrUsed);
DPRINT("bV5ClrImportant = %d\n", bminfo->bV5ClrImportant);
bfOffBits = bminfo->bV5Size + bminfo->bV5ClrUsed * sizeof(RGBQUAD);
DPRINT("bfOffBits = %d\n", bfOffBits);
DPRINT("size of color indices = %d\n", bminfo->bV5ClrUsed * sizeof(RGBQUAD));
DPRINT("first byte of data = %d\n", BootimageBitmap[bfOffBits]);
InbvSetBlackPalette();
ImageData = ExAllocatePool(NonPagedPool, bminfo->bV5Width * bminfo->bV5Height);
RtlZeroMemory(ImageData, bminfo->bV5Width * bminfo->bV5Height);
/*
* ImageData has 1 pixel per byte.
* bootimage has 2 pixels per byte.
*/
if (bminfo->bV5Compression == 2)
{
k = 0;
j = 0;
while ((j < bminfo->bV5SizeImage) && (k < (ULONG) (bminfo->bV5Width * bminfo->bV5Height)))
{
unsigned char b;
clen = BootimageBitmap[bfOffBits + j];
j++;
if (clen > 0)
{
/* Encoded mode */
b = BootimageBitmap[bfOffBits + j];
j++;
for (i = 0; i < (clen / 2); i++)
{
ImageData[k] = (b & 0xf0) >> 4;
k++;
ImageData[k] = b & 0xf;
k++;
}
if ((clen & 1) > 0)
{
ImageData[k] = (b & 0xf0) >> 4;
k++;
}
}
else
{
/* Absolute mode */
b = BootimageBitmap[bfOffBits + j];
j++;
if (b == 0)
{
/* End of line */
}
else if (b == 1)
{
/* End of image */
break;
}
else if (b == 2)
{
x = BootimageBitmap[bfOffBits + j];
j++;
y = BootimageBitmap[bfOffBits + j];
j++;
curx = k % bminfo->bV5Width;
cury = k / bminfo->bV5Width;
k = (cury + y) * bminfo->bV5Width + (curx + x);
}
else
{
if ((j & 1) > 0)
{
DPRINT("Unaligned copy!\n");
}
clen = b;
for (i = 0; i < (clen / 2); i++)
{
b = BootimageBitmap[bfOffBits + j];
j++;
ImageData[k] = (b & 0xf0) >> 4;
k++;
ImageData[k] = b & 0xf;
k++;
}
if ((clen & 1) > 0)
{
b = BootimageBitmap[bfOffBits + j];
j++;
ImageData[k] = (b & 0xf0) >> 4;
k++;
}
/* Word align */
j += (j & 1);
}
}
}
InbvDisplayBitmap(bminfo->bV5Width, bminfo->bV5Height, ImageData);
}
else
{
DbgPrint("Warning boot image need to be compressed using RLE4\n");
}
ExFreePool(ImageData);
}
#define PALETTE_FADE_STEPS 20
#define PALETTE_FADE_TIME 20 * 10000 /* 20ms */
static VOID
InbvFadeUpPalette()
{
PBITMAPV5HEADER bminfo;
PRGBQUAD Palette;
ULONG i;
unsigned char r,g,b;
register ULONG c;
LARGE_INTEGER Interval;
FADER_PALETTE_ENTRY FaderPalette[16];
FADER_PALETTE_ENTRY FaderPaletteDelta[16];
RtlZeroMemory(&FaderPalette, sizeof(FaderPalette));
RtlZeroMemory(&FaderPaletteDelta, sizeof(FaderPaletteDelta));
bminfo = (PBITMAPV5HEADER) &BootimageBitmap[0]; //sizeof(BITMAPFILEHEADER)];
Palette = (PRGBQUAD) &BootimageBitmap[/* sizeof(BITMAPFILEHEADER) + */ bminfo->bV5Size];
for (i = 0; i < 16; i++)
{
if (i < bminfo->bV5ClrUsed)
{
FaderPaletteDelta[i].r = ((Palette[i].rgbRed << 8) / PALETTE_FADE_STEPS);
FaderPaletteDelta[i].g = ((Palette[i].rgbGreen << 8) / PALETTE_FADE_STEPS);
FaderPaletteDelta[i].b = ((Palette[i].rgbBlue << 8) / PALETTE_FADE_STEPS);
}
}
for (i = 0; i < PALETTE_FADE_STEPS; i++)
{
for (c = 0; c < bminfo->bV5ClrUsed; c++)
{
/* Add the delta */
FaderPalette[c].r += FaderPaletteDelta[c].r;
FaderPalette[c].g += FaderPaletteDelta[c].g;
FaderPalette[c].b += FaderPaletteDelta[c].b;
/* Get the integer values */
r = FaderPalette[c].r >> 8;
g = FaderPalette[c].g >> 8;
b = FaderPalette[c].b >> 8;
/* Don't go too far */
if (r > Palette[c].rgbRed)
r = Palette[c].rgbRed;
if (g > Palette[c].rgbGreen)
g = Palette[c].rgbGreen;
if (b > Palette[c].rgbBlue)
b = Palette[c].rgbBlue;
/* Update the hardware */
InbvSetColor(c, r, g, b);
}
Interval.QuadPart = -PALETTE_FADE_TIME;
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
}
}
static VOID STDCALL
InbvBitmapThreadMain(PVOID Ignored)
{
if (InbvFindBootimage())
{
InbvDisplayCompressedBitmap();
InbvFadeUpPalette();
}
else
{
DbgPrint("Warning: Cannot find boot image\n");
}
BitmapIsDrawn = TRUE;
for(;;)
{
if (BitmapThreadShouldTerminate)
{
DPRINT("Terminating\n");
return;
}
ZwYieldExecution();
}
}
BOOLEAN
STDCALL
VidIsBootDriverInstalled(VOID)
{
return InGraphicsMode;
}
BOOLEAN
STDCALL
VidInitialize(VOID)
{
NTSTATUS Status;
if (!VideoAddressSpaceInitialized)
{
InbvInitializeVideoAddressSpace();
}
InbvInitVGAMode();
InGraphicsMode = TRUE;
BitmapIsDrawn = FALSE;
BitmapThreadShouldTerminate = FALSE;
Status = PsCreateSystemThread(&BitmapThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&BitmapThreadId,
InbvBitmapThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
InbvDeinitializeVideoAddressSpace();
VideoAddressSpaceInitialized = FALSE;
return TRUE;
}
NTSTATUS STDCALL_FUNC
VidDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS nErrCode;
NTBOOTVID_FUNCTION_TABLE* FunctionTable;
nErrCode = STATUS_SUCCESS;
switch(piosStack->MajorFunction)
{
/* opening and closing handles to the device */
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
break;
case IRP_MJ_DEVICE_CONTROL:
switch (piosStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_BOOTVID_INITIALIZE:
VidInitialize();
FunctionTable = (NTBOOTVID_FUNCTION_TABLE*)
Irp->AssociatedIrp.SystemBuffer;
FunctionTable->ResetDisplay = VidResetDisplay;
break;
case IOCTL_BOOTVID_CLEANUP:
VidCleanUp();
break;
default:
nErrCode = STATUS_NOT_IMPLEMENTED;
break;
}
break;
/* unsupported operations */
default:
nErrCode = STATUS_NOT_IMPLEMENTED;
}
Irp->IoStatus.Status = nErrCode;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return nErrCode;
}
NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT BootVidDevice;
UNICODE_STRING DeviceName;
UNICODE_STRING DosName;
NTSTATUS Status;
BootVidDriverObject = DriverObject;
/* register driver routines */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)VidDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)VidDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
(PDRIVER_DISPATCH)VidDispatch;
DriverObject->DriverUnload = NULL;
/* create device */
RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\BootVid");
Status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_BOOTVID,
0, FALSE, &BootVidDevice);
if (! NT_SUCCESS(Status))
{
return Status;
}
BootVidDevice->Flags |= DO_BUFFERED_IO;
return Status;
}

View file

@ -0,0 +1,40 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "ReactOS Boot Video\0"
VALUE "FileVersion", RES_STR_FILE_VERSION
VALUE "InternalName", "bootvid\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "bootvid.sys\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
IDB_BOOTIMAGE BITMAP DISCARDABLE "bootimage.bmp"

View file

@ -0,0 +1,101 @@
/* $Id: pixelsup_i386.S,v 1.1 2003/08/24 12:11:13 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/inbv/i386/pixelsup.S
* PURPOSE: Boot video support
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
/*
* VOID
* InbvPutPixels(int x, int y, unsigned long c);
*
* Will put 4 pixels on the screen at
* (x+0*8,y), (x+1*8,y), (x+2*8,y), and (x+3*8,y)
* c will contain:
* bits 0- 3: Palette index for pixel at (x+0*8,y)
* bits 8-11: Palette index for pixel at (x+1*8,y)
* bits 16-19: Palette index for pixel at (x+2*8,y)
* bits 24-27: Palette index for pixel at (x+3*8,y)
*
* Parameters:
* [EBP+08h] - x X-coordinate of first pixel
* [ESP+0Ch] - y Y-coordinate of first pixel
* [ESP+10h] - c 4*4-bit color indices
*/
.globl _InbvPutPixels
_InbvPutPixels:
pushl %ebp
movl %esp, %ebp
/* Compute mask and put it in EBX
mask = maskbit[x] */
movl 0x8(%ebp), %esi
movl _maskbit(,%esi, 4), %ebx
/* Don't set bit mask if it is already set */
cmpl (inbv_last_mask),%ebx
je .nomask
/* Set Mask Bit Register
WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);
WRITE_PORT_UCHAR((PUCHAR)0x3cf,mask); */
movl %ebx,(inbv_last_mask)
movw $0x3ce,%dx
movb $0x08,%al
outb %al,%dx
movw $0x3cf,%dx
movb %bl,%al
outb %al,%dx
.nomask:
/* Compute offset in video memory and put it in EBX
offset = (x >> 3) + y80[y]; */
movl 0xC(%ebp), %esi /* y */
movl _y80(,%esi, 4), %ebx
movl 0x8(%ebp), %eax /* x */
shrl $0x3, %eax
addl %eax, %ebx
/* Latch first byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+0); */
movl (_vidmem), %esi
addl %ebx, %esi
movb 0x0(%esi), %bl
/* Write color index for first pixel
*((PUCHAR)(vidmem + offset+0)) = (c >> 0*8) & 0xff; */
movl 0x10(%ebp), %eax
movb %al, 0x0(%esi)
/* Latch second byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+1); */
movb 0x1(%esi), %bl
/* Write color index for second pixel
*((PUCHAR)(vidmem + offset+1)) = (c >> 1*8) & 0xff; */
shrl $0x8, %eax
movb %al, 0x1(%esi)
/* Latch third byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+2); */
movb 0x2(%esi), %bl
/* Write color index for third pixel
*((PUCHAR)(vidmem + offset+2)) = (c >> 2*8) & 0xff; */
shrl $0x8, %eax
movb %al, 0x2(%esi)
/* Latch fourth byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+3); */
movb 0x3(%esi), %bl
/* Write color index for fourth pixel
*((PUCHAR)(vidmem + offset+3)) = (c >> 3*8) & 0xff; */
shrl $0x8, %eax
movb %al, 0x3(%esi)
popl %ebp
ret
.bss
inbv_last_mask:
.short 0

View file

@ -0,0 +1,11 @@
#define FILE_DEVICE_BOOTVID 53335
#define IOCTL_BOOTVID_INITIALIZE \
CTL_CODE(FILE_DEVICE_BOOTVID, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_BOOTVID_CLEANUP \
CTL_CODE(FILE_DEVICE_BOOTVID, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct
{
BOOL STDCALL (*ResetDisplay)(VOID);
} NTBOOTVID_FUNCTION_TABLE;