bootvid.c

来自「一个类似windows」· C语言 代码 · 共 673 行 · 第 1/2 页

C
673
字号
/*
 * ReactOS Boot video driver
 *
 * Copyright (C) 2003 Casper S. Hornstroup
 * Copyright (C) 2004 Filip Navara
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Id: bootvid.c 21842 2006-05-07 19:16:11Z ion $
 */

/* INCLUDES ******************************************************************/

#include <ntddk.h>
#include <windef.h>
#include <ndk/ldrfuncs.h>
#include "bootvid.h"
#include "ntbootvid.h"
#include "resource.h"

#define NDEBUG
#include <debug.h>

/* GLOBALS *******************************************************************/

/*
 * NOTE:
 * This is based on SvgaLib 640x480x16 mode definition with the
 * following changes:
 * - Graphics: Data Rotate (Index 3)
 *   Set to zero to indicate that the data written to video memory by
 *   CPU should be processed unmodified.
 * - Graphics: Mode Register (Index 5)
 *   Set to Write Mode 2 and Read Mode 0.
 */

static const VGA_REGISTERS Mode12Regs =
{
   /* CRT Controller Registers */
   {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3},
   /* Attribute Controller Registers */
   {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
    0x0C, 0x0D, 0x0E, 0x0F, 0x81, 0x00, 0x0F, 0x00, 0x00},
   /* Graphics Controller Registers */
   {0x00, 0x0F, 0x00, 0x00, 0x00, 0x02, 0x05, 0x0F, 0xFF},
   /* Sequencer Registers */
   {0x03, 0x01, 0x0F, 0x00, 0x06},
   /* Misc Output Register */
   0xE3
};

PUCHAR VideoMemory;

/* Must be 4 bytes per entry */
long maskbit[640];

static CLIENT_ID BitmapThreadId;
static PUCHAR BootimageBitmap;

static LONG ShutdownNotify;
static KEVENT ShutdownCompleteEvent;

/* DATA **********************************************************************/

static PDRIVER_OBJECT BootVidDriverObject = NULL;

/* FUNCTIONS *****************************************************************/

static BOOLEAN FASTCALL
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 FASTCALL
InbvMapVideoMemory(VOID)
{
   PHYSICAL_ADDRESS PhysicalAddress;

   PhysicalAddress.QuadPart = 0xA0000;
   VideoMemory = MmMapIoSpace(PhysicalAddress, 0x10000, MmNonCached);

   return VideoMemory != NULL;
}


static BOOLEAN FASTCALL
InbvUnmapVideoMemory(VOID)
{
   MmUnmapIoSpace(VideoMemory, 0x10000);
   return TRUE;
}


static VOID FASTCALL
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;
   }
}


static VOID FASTCALL
vgaSetRegisters(const VGA_REGISTERS *Registers)
{
   UINT i;

   /* Update misc output register */
   WRITE_PORT_UCHAR(MISC, Registers->Misc);

   /* Synchronous reset on */
   WRITE_PORT_UCHAR(SEQ, 0x00);
   WRITE_PORT_UCHAR(SEQDATA, 0x01);

   /* Write sequencer registers */
   for (i = 1; i < sizeof(Registers->Sequencer); i++)
   {
      WRITE_PORT_UCHAR(SEQ, i);
      WRITE_PORT_UCHAR(SEQDATA, Registers->Sequencer[i]);
   }

   /* Synchronous reset off */
   WRITE_PORT_UCHAR(SEQ, 0x00);
   WRITE_PORT_UCHAR(SEQDATA, 0x03);

   /* Deprotect CRT registers 0-7 */
   WRITE_PORT_UCHAR(CRTC, 0x11);
   WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[0x11] & 0x7f);

   /* Write CRT registers */
   for (i = 0; i < sizeof(Registers->CRT); i++)
   {
      WRITE_PORT_UCHAR(CRTC, i);
      WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[i]);
   }

   /* Write graphics controller registers */
   for (i = 0; i < sizeof(Registers->Graphics); i++)
   {
      WRITE_PORT_UCHAR(GRAPHICS, i);
      WRITE_PORT_UCHAR(GRAPHICSDATA, Registers->Graphics[i]);
   }

   /* Write attribute controller registers */
   for (i = 0; i < sizeof(Registers->Attribute); i++)
   {
      READ_PORT_UCHAR(STATUS);
      WRITE_PORT_UCHAR(ATTRIB, i);
      WRITE_PORT_UCHAR(ATTRIB, Registers->Attribute[i]);
   }
}


static VOID
InbvInitVGAMode(VOID)
{
   /* Zero out video memory (clear a possibly trashed screen) */
   RtlZeroMemory(VideoMemory, 0x10000);

   vgaSetRegisters(&Mode12Regs);

   /* Set the PEL mask. */
   WRITE_PORT_UCHAR(PELMASK, 0xff);

   vgaPreCalc();
}


static BOOL STDCALL
VidResetDisplay(VOID)
{
   /*
    * We are only using standard VGA facilities so we can rely on the
    * HAL 'int10mode3' reset to cleanup the hardware state.
    */

   return FALSE;
}


static VOID STDCALL
VidCleanUp(VOID)
{
   InbvUnmapVideoMemory();
   InterlockedIncrement(&ShutdownNotify);
   KeWaitForSingleObject(&ShutdownCompleteEvent, Executive, KernelMode,
                         FALSE, NULL);
}


static VOID FASTCALL
InbvSetColor(INT Index, UCHAR Red, UCHAR Green, UCHAR Blue)
{
   WRITE_PORT_UCHAR(PELINDEX, Index);
   WRITE_PORT_UCHAR(PELDATA, Red >> 2);
   WRITE_PORT_UCHAR(PELDATA, Green >> 2);
   WRITE_PORT_UCHAR(PELDATA, Blue >> 2);
}


static VOID FASTCALL
InbvSetBlackPalette()
{
   register ULONG r = 0;

   /* Disable screen and enable palette access. */
   READ_PORT_UCHAR(STATUS);
   WRITE_PORT_UCHAR(ATTRIB, 0x00);

   for (r = 0; r < 16; r++)
   {
      InbvSetColor(r, 0, 0, 0);
   }

   /* Enable screen and enable palette access. */
   READ_PORT_UCHAR(STATUS);
   WRITE_PORT_UCHAR(ATTRIB, 0x20);
}


static VOID FASTCALL
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 FASTCALL
InbvDisplayCompressedBitmap()
{
   PBITMAPV5HEADER bminfo;
   ULONG i,j,k;
   ULONG x,y;
   ULONG curx,cury;
   ULONG bfOffBits;
   ULONG clen;
   PCHAR ImageData;
   UCHAR ClrUsed;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?