近日研读了一下WindML中pc-bios的显卡驱动源码,有点收获。遂随手写下该驱动实现的大体过程,以备日后查阅!
PC-BIOS驱动顾名思义,就是该驱动调用了BIOS中断来实现对显卡驱动。
一:基础知识
1:real模式下的内存分布,大致情况如下:(只讲这篇文章能用到的)
| 高端内存 |
| 上位内存384K | (具体分布如下图)
| 常规内存640K | (0~1k:IVT,1k~2k:BIOS数据区)
Address
|
First 16K (x0000h-x3FFFh) |
Second 16K (x4000h-x7FFFh) |
Third 16K (x8000h-xBFFFh) |
Fourth 16K (xC000h-xFFFFh) |
A0000- AFFFFh
|
VGA Graphics Mode Video RAM
| |||
B0000- BFFFFh
|
VGA Monochrome Text Mode Video RAM
|
VGA Color Text Mode Video RAM
| ||
C0000- CFFFFh
|
VGA Video BIOS ROM
|
IDE Hard Disk BIOS ROM
|
Optional Adapter ROM BIOS or RAM UMBs
| |
D0000- DFFFFh
|
Optional Adapter ROM BIOS or RAM UMBs
| |||
E0000h- EFFFFh
|
System BIOS Plug and Play Extended Information
| |||
F0000- FFFFFh
|
System BIOS ROM
|
2:从机器上电到VxWorks运行的大致过程如下:
机器上电----->POST------>BIOS程序执行------>(INT19)装载bootloader (vxload)------->(INT13)装载bootrom.sys----->VxWorks
上述过程中,BIOS是运行于real模式的,她会对硬件做初始化。bootrom.sys和VxWorks是在protect模式下运行的,它们也会对硬件进行不同程度的初始化,但是bootrom.sys和VxWorks都不会用到BIOS的任何东西,即此时BIOS彻底的消失了。(bootrom.sys会对硬件做简单的初始化,其最主要的目标就是装载VxWorks,一旦装载VxWorks完成,它的使命也就终结了。VxWorks会对硬件又进行一番全面的初始化。其实,x86下VxWorks还是假定BIOS已对PCI资源的分配)
二:源码分析
说了这么多,好像扯远了:)protect模式想调用real模式下的BIOS中断,只能从protect模式切换到real模式,在real模式下调用BIOS INT10H来完成对显卡的驱动,然后再从real模式切换回原来的保护模式。PC-BIOS恰是这么做的。让我们来看看源码的具体实现!
1:对romInit.h的分析 (ugl/driver/graphics/pcbios/romInit.h)
#define UGL_BIOS_DATA_ADDRESS 0xbfb00 /* Location to store BIOS data */
#define UGL_BIOS_DATA_PREFIX (UGL_BIOS_DATA_ADDRESS - 8)
/* Location to store "BIOSDATA" */
#define UGL_BIOS_DATA_SIZE 0x500 /* Location to store BIOS data */
#define UGL_BIOS_KEY_1 0x534F4942 /* "BIOS" */
#define UGL_BIOS_KEY_2 0x41544144 /* "DATA" */
#define _romInit2 /
_romInit2:/
movl $UGL_BIOS_DATA_PREFIX,%ebx; /* Move BIOS prefix address to EBX *//
movl $UGL_BIOS_KEY_1,(%ebx); /* store "BIOS" */ /
addl $4,%ebx; /* increment ebx */ /
movl $UGL_BIOS_KEY_2,(%ebx); /* store "DATA" */ /
movl $UGL_BIOS_DATA_SIZE / 4,%ecx;/* load ecx with # dwords to copy */ /
movl $0,%esi; /* load esi with source address */ /
movl $UGL_BIOS_DATA_ADDRESS,%edi; /* load ebx with dest address */ /
rep; /* copy BIOS data to vram */ /
movsl; /
#
_romInit2 会在romInit.s中的romInit()中被调用。romInit2 的作用是把real模式下的从地址为0x0~(0x500 - 1)(包括1K的IVT,和256B的BIOS数据区数据)大小为0x500的数据备份到0xbfb00处,并在(0xbfb00 - 8 )处加上BIOSDATA标签,此标签作为后续程序检查BIOS数据有没有被存到0xbfb00处的依据。
为什么会把数据存于0xbfb00 - 8处?个人理解:在文本模式下,文本存于0xb8000处,大小为80x25x2 = 4000,即0xb8000 + 4000 < 0xbfb00 - 8 ,因此数据不会受到破坏。
二:对udpcvbe.c的分析(待续...)