stevend
驱动牛犊
驱动牛犊
  • 注册日期2002-02-21
  • 最后登录2003-03-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:3335回复:12

一种在BIOS中嵌入应用程序的方法及实现

楼主#
更多 发布于:2002-04-30 09:20
这是一篇关于BIOS开发的文章,作者是张定会,我也不知道该怎样联系他,贴出此文是为了抛砖引玉,希望能找到他的联系方法。

最新喜欢:

baoyibao99baoyib...
yiyiz
驱动小牛
驱动小牛
  • 注册日期2002-02-15
  • 最后登录2007-09-06
  • 粉丝0
  • 关注0
  • 积分50分
  • 威望5点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-05-02 10:51
stevend:
你好,你对BIOS开发有研究吗?
可否请教你一些问题?
stevend
驱动牛犊
驱动牛犊
  • 注册日期2002-02-21
  • 最后登录2003-03-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-05-02 13:50
我也是新手,不过我们可以探讨一下。
jacobqzl
驱动小牛
驱动小牛
  • 注册日期2001-10-10
  • 最后登录2005-04-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-05-02 20:51
也算我一个!
lijun
驱动牛犊
驱动牛犊
  • 注册日期2001-06-30
  • 最后登录2002-05-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-05-13 20:51
访问不了啊!
不用了吧?
yanghaoyun
驱动牛犊
驱动牛犊
  • 注册日期2002-03-22
  • 最后登录2002-08-20
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-05-15 17:00
好东东!

大家共同研究,也希望张定会先生早点现身。
stevend
驱动牛犊
驱动牛犊
  • 注册日期2002-02-21
  • 最后登录2003-03-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-05-15 17:06
同志们!我重新发上去。
huxiangming
驱动牛犊
驱动牛犊
  • 注册日期2002-03-14
  • 最后登录2002-06-16
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-05-17 23:09
还是访问不了!
stevend
驱动牛犊
驱动牛犊
  • 注册日期2002-02-21
  • 最后登录2003-03-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-05-18 09:23
一种在BIOS中嵌入应用程序的方法及实现

介绍
本文针对Award公司开发的计算机系统BIOS提出了一种嵌入应用程序的方法,其基本原理对别的品牌的BIOS也一样适用,仅需稍加修改。文中作者给出并讨论一个完整的例子程序,该程序已经通过实验验证。

一. BIOS简述
这里所讲的BIOS是指计算机主板上的BIOS,是整个计算机的关键和灵魂,计算机一启动就是执行BIOS程序,它负责加电自检,初始化计算系统,响应用户对系统配置的修改,记录数据到CMOS中,将常驻程序库(Runtime Program)常驻于内存中,提供给系统和应用程序调用,经过一系列复杂操作后,最后将控制权转移给操作系统。
一开始BIOS容量仅有8K,随着计算机复杂程度的提高,以及即插即用、高级电源管理等方面的需要,再加上个别主板厂商添加的辅助功能,BIOS容量迅速增大,目前通常主板上BIOS容量为256Kb,有些已经达到512Kb,这些BIOS中常常还会有几十Kb的剩余空间,而且由于BIOS多采用FlashRom作为存储芯片,便于修改,这就为我们在BIOS中嵌入自己的程序提供了便利。
在BIOS中嵌入程序具有多方面的应用,有些主板厂商在BIOS中嵌入杀毒程序,硬盘恢复精灵,超频工具等,提高了产品的竞争力;台湾威胜公司和Elegent公司联合开发出了嵌入在BIOS中的小型浏览器操作系统,整个BIOS大小仅有512Kb,计算机无需硬盘即可上网冲浪;有些监控系统由于功能简单,完全可以把程序做到BIOS中,一开机就自动运行,既提高了可靠性,又降低了成本。另一方面,将病毒嵌入到BIOS中,一开机就常驻内存也完全可以做到。
BIOS代码虽短,但技术含量相当高,全世界仅有AWARD、PHOENIX、AMI、ACER等几家公司有研发BIOS系统的能力(AWARD 已被PHOENIX收购),其他主板厂商有的是直接购买,有的也会在以上几家公司提供的平台上进行少量功能扩展。作为个别应用的场合,就要完全靠自己对BIOS进行改造。

二. 嵌入程序的基础知识
在进行工作前需要几个必备的工具,一个是AWARD公司的BIOS刷新工具AwdFlash;另一个Award BIOS 察看修改工具Cbrom;还有一个是MicroSoft 的汇编工具Masm6.11;最后是作者推荐的二进制文本编辑器HexWorkshop,这些工具都可以从网上下载,下面假定读者已经熟练使用这些工具,具体操作步骤不再祥述。
前面提到BIOS程序是存放在FlashROM芯片中的,实际上它是经过压缩后再存放进去的,仅留下少量启动代码和解压缩程序保持原样,BIOS的执行过程其实相当复杂,好在我们无需去了解其中的详细流程,但有一点应当清楚,BIOS程序实际上也是采用的模块化设计思想,用Cbrom可以察看到BIOS中各个子模块的名称,性质,压缩率等信息,BIOS在执行过程中会将这些模块解压缩到内存中,验证模块的合法性和正确性,如果满足条件,就会转到模块的入口处执行。这里面的详细机制和由来需要参考PNPBIOS协议、PNPISA协议、PCI总线协议和EISA总线协议,内容繁多,本文不拟做深入探讨。
BIOS中有一种模块是ISA模块,来源于ISA协议,由于ISA协议属于早期的协议,内容相对简单,BIOS对ISA模块的验证也较为简单,容易满足,我们可以将自己的程序做成ISA模块挂到BIOS中,这样机器一启动,我们的程序就会启动,而且我们程序的运行是先于操作系统的。
三. 程序设计详细步骤
1. 设计准备
由于系统固有的限制,BIOS中每个模块的大小不能超过64Kb,这里是指没有压缩前的大小,这和DOS下COM程序的限制很相似,实际上我们在用MASM6.11进行编程时的确采用是COM程序的模板,由编译器生成COM文件。然而它又和一般的COM文件具有以下几点不同:
1. 首先它有自己的堆栈段,堆栈大小默认为1K,而COM文件的堆栈是在64K之内的,默认是从段内偏移量0FFFEh处开始。
2. COM文件一开始就是执行代码,而模块一开始是模块头,储存有与模块相关的信息。模块执行代码的入口点在模块中的某一处。
3. COM文件执行完后返回到操作系统,通常通过子功能号4ch的中断INT21h返回到DOS,而模块是远程调用返回,也就是说必须用RETF返回。
4. ISA模块最后一个字节是校验码,所有的字节相加必须为0,BIOS利用这点来验证一个ISA模块的正确性。COM文件没有这点要求。
5. COM文件执行时是先被完整地复制到段内偏移量100h处,然后再执行,而模块的段内偏移量不能确定,有的模块会是0。所以涉及到段内偏移量的汇编指令,如LEA、OFFSET要谨慎适用。
下表是ISA模块头的格式,其中仅列出了几个最基本的相关字段,这是协议中的内容,我们在编写模块头时,需要严格遵循下表的格式:

偏 移 长 度 值 说  明
0h     1     55h 模块标签字节1
1h    1     AAh   模块标签字节2
2h   1    *    模块长度(以512字节为单位)
3h     3     *     入口点,BIOS对此位置做远调用,这里往往放一条跳转指令
6h~19h 20     *     保留

表一  模块头格式
通常一个BIOS嵌入程序设计的基本流程如下,每一步都很关键,有必要给出详细说明:
1. 首先用汇编编写DOS下的COM程序,必须注意到程序是先于操作系统执行的,所以程序中不能调用任何DOS的中断服务。为了程序转化方便,也不要用.code,.startup等汇编伪指令,尽量采用早期的汇编编写方式,争取对整个程序结构的完全控制。
2. 调试通过后,在COM文件前加上文件头,改变返回指令为RETF,控制文件大小为512字节的整数倍,重新编译生成COM文件。
3. 在HexWorkshop中调入刚生成的COM文件,利用其中的checksum工具生成文件的校验码,用100h减去该8位校验码后填入文件最后一个字节。再次生成文件的校验码,确认为零。
4. 用Cbrom将文件作为ISA模块嵌入到BIOS中,在本文中的操作为 “Cbrom save.bin/isa hello.com”,其中save.bin是事先用AwdFlash备份的BIOS文件。注意反复操作时,要先将前一个给释放掉,操作为“Cbrom save.bin/isa release”。
5. 用AwdFlash将新的BIOS文件烧录到FlashROM中。重起计算机,检验程序。
进行以上实验前,最好自备编程器,万一计算机不能正常启动,也可以重新恢复BIOS,如果可以用本身具有双BIOS保护功能的计算机进行实验则更加保险。
下面设计两个简单的Hello程序,分别采用了两种不同的方式,两个程序都是在屏幕上显示一行字“Hello!Press F1 to continue…”,当按下F1功能键后,程序退出,计算机继续启动。
2. Hello程序一
下面给出的源代码是在上面流程2中的文件,所以已经添加了文件头,编译后生成的COM文件是不能在DOS下执行的,请读者务必注意。另外由于程序功能简单,所以在这里文件大小限制为512字节,对不同规模的程序,会有一些小小的变动。程序中所有的中断调用都是BIOS中断服务调用,具体调用规则不做详细说明,请读者查阅有关资料。
;Hello源程序一
code segment
        assume cs:code,ds:code
start:

signature            db  55h,0aah
comlength        db  01h        ;文件长512字节
jmp         near ptr  begin0
reserved            db  20 dup(?)

begin0:

mov         di,25
mov         ah,2
mov         bh,0
mov         dx,di
mov         dh,10                ;将光标移至屏幕
int 10h                    ;10行25列处

mov         si,offset string
    ;在DOS下调试时应在这里添加    add        si,100h
showstr:
mov         ah,9
mov         al,[si]
and         al,0ffh
jz         kbinput
mov         bh,0
mov         bl,0DAh
mov         cx,1
int         10h
,
mov         ah,2
mov         bh,0
inc         di
mov         dx,di
mov         dh,10
int         10h
jmp         showstr            ;输出字符串

kbinput:
mov         ah,0
int         16h
cmp         ah,3bh            ;接受键盘输入
jne         kbinput            ;按F1往下执行

    mov     ax,0            ;返回参数
retf                        ;远程调用返回

string      db \'Hello! Press F1 to continue...\',00h    ;00h标志字符串结束
    org        511                ;文件末尾
checksum        db    ?                
code     ends
end         start

将上述程序烧入BIOS中运行时,在第一屏信息显示过后,会在第二屏正中央显示一条红底白字的信息,提示按F1键继续,按F1键后,BIOS继续下面的启动步骤。显示第三屏启动信息,即原先的第二屏信息,最后加载操作系统。
以上程序假定了BIOS会将模块解压至段首运行,事实也确是如此,但由于没查到相关资料,目前还不能肯定总会如此。这一点将在下一个Hello程序中有所改进。
3. Hello程序二
Hello程序一在BIOS没有初始化完全的时候即进入运行,所以对程序功能有更多限制,有些BIOS中断服务还不具备,任何对这些服务的调用都会产生意想不到的结果。考虑到BIOS在加载操作系统时实际上是用的INT 19h,Hello程序二就利用挂钩19h中断的方法抢在操作系统之前,BIOS初始化之后运行,这样就可以完整地利用整个计算机系统的所有资源了。
另外必须指出的是,模块本身有责任保持整个模块的校验和为零,也就是说,ISA模块进驻内存中后就不能卸出,BIOS会在模块返回后检查整个模块的检验和,判断模块的正确性,如果错误,则会死机。模块在初始运行时可以更改自己段内的数据,而在BIOS初始化完毕后,模块就不能再有改变自身数据的操作。
;Hello源程序二
.model tiny
.386
code segment
        assume cs:code,ds:code
start:
signature        db  55h,0aah
comlength    db  01h        ;文件长512字节
jmp near ptr  begin0
reserved        db  20 dup(?)
begin0:
call         getip            ;得到模块的起始段内偏移量
                        ;保存在参数ipstart中
mov         ax,0            ;挂钩19h中断
mov         es,ax        ;保存原来的入口到
mov         ax,es:[64h]    ;saveip与savecs
mov         saveip,ax
mov         ax,es:[66h]
mov         savecs,ax
mov         ax,offset begin1
add         ax,ipstart
mov         es:[64h],ax
mov         es:[66h],cs

mov         ax,0            ;重新计算校验码
mov         si,510        ;注意不要记入最后一个字节
again:     add ax,cs:[si]
dec         si
jns         again
neg         al            ;改变最后一个字节
mov         checksum,al    ;使整个模块校验和为零

mov ax,0
retf                    ;远程调用返回

begin1:                ;19h中断入口
sti                    ;开中断
pusha
push     es
push     ds            ;保存调用参数

mov         ax,cs
mov         ds,ax

mov         ax,0            ;恢复原19h中断入口
mov         es,ax
mov         ax,saveip
mov         es:[64h],ax
mov        ax,savecs
mov         es:[66h],ax
;以下基本与程序一相同
;这里为节约篇幅用……代替
;……
mov         si,offset string
add         si,ipstart        ;注意
;……
pop         ds
pop         es
popa
int         19h            ;激发19h中断
iret

getip     proc            ;得到模块的起始
pop         ax            ;段内偏移量子程序
push     ax
sub         ax,29        ;29=模块头大小加3
mov         ipstart,ax
ret
getip     endp

string  db \'Hello! Press F1 to continue...\',00h

saveip dw ?
savecs dw ?
ipstart dw ?

org 511
checksum db ?

code ends
end start

Hello2程序在执行时,会在第二屏启动画面的最后一行显示一段黑底白字“Hello! Press F1 to continue...”,当按下F1后,计算机就开始加载操作系统。
需要注意的是,在DOS或Windows下调试Hello程序二时,是不能用19h中断的,任何对19h中断的调用要么结束当前程序,要么会造成死机,所以调试时需要暂时用别的中断代替,如保留中断2bh,当调试成功以后,再将中断改回为19h。
另一个在Hello1与Hello2程序中都要注意的问题是,在程序中不要轻易改动模块头的模块长度字节的值,PCI模块支持并赞成这样的改动,而ISA模块没找到相关资料,笔者曾尝试过改动这一值,结果导致Windows98不能进入通常模式。
四. 结束语
在编程实践中作者感到编写BIOS的嵌入程序具有相当难度,它需要有扎实的汇编语言功底和对计算机硬件系统的深入了解,更需要在实践中不断地摸索BIOS程序的特点,只有这样才能够编写出精悍的代码,满足实践应用的需要。

正文完


finalseraph
驱动牛犊
驱动牛犊
  • 注册日期2001-03-23
  • 最后登录2018-05-30
  • 粉丝0
  • 关注0
  • 积分-11分
  • 威望146点
  • 贡献值0点
  • 好评度24点
  • 原创分0分
  • 专家分0分
  • 社区居民
9楼#
发布于:2002-05-18 10:47
张定会, You are the man....!!!

非常不错的文章!!!
kermit_shie
驱动牛犊
驱动牛犊
  • 注册日期2002-04-24
  • 最后登录2007-06-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-07-10 13:34
这种方法是不错,不过要烧主板BIOS,挺危险的,容量也有限制。我有一块PCI接口的扩展BIOS卡。我曾经把dos2。0操作系统装了进去,用的芯片是2Mbit的。市场上的什么硬盘保护卡也是用这种东西做的,如果大家又兴趣,我倒可以多做几块给大家玩玩。当然不是完全免费的,毕竟硬件是要钱买的。大家可以联系我xdxq@163.net,希望可以帮到大家。
kermit_shie
驱动牛犊
驱动牛犊
  • 注册日期2002-04-24
  • 最后登录2007-06-27
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2002-07-26 18:00
最近,有一部分人问道PCI扩展BIOS的问题,我在这提一下我的心得。PCI接口BIOS就是芯片的一端接PCI,另一端接BIOS。与ISA接口的不一样,接在PCI上的BIOS最大可做到几千M Byte。所以就算你要装入整个WINDOWS系统都没用问题。本人曾经装入过DOS2。0操作系统。所应用的技术是他会在低1M空间内占用一小片空间(例如D0000到D2000),主要是为了让系统能找到扩展BIOS,然后其余的会摆放在PCI高位空间,所以会涉及到保护模式编程。至于具体的技术问题,请参考PCI技术规范PCI接口BIOS部分。如果大家有兴趣的话,可以联系我xdxq@163.net。我可以提供一些参考线路,大家也可以和我讨论技术问题,我的QQ是6796245。谢谢

paris
驱动小牛
驱动小牛
  • 注册日期2002-01-30
  • 最后登录2006-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2002-08-19 13:59
玩BIOS不是好现象,至少态度不认真
BIOS中的确有许多不错的技术,
有点mcu,pci,isa,pnp,acpi,usb基础的,来交流交流,
Oliver
游客

返回顶部