BIOS排错

江西财经大学国贸学院 舒 剑
BIOS排错有否方法可循?有。但从哪学?不知道。自我从事BIOS研发以来,强烈的感觉就是,BIOS有如以前的中医,只能靠传帮带才能学的东西,而这还视乎做师傅的观念,看他愿否教于你。我也就想,或许过不了几天,他也会象中医一样,需要挽救。

内地的BIOS工程师,我一直以为,应该叫做BUG工程师。因为,BIOS一直是几家寡头公司在研发,而各厂商都是利用它的源码做一些修补。所以,我也只学到一些排错的方法,只能是一个BUG工程师。

在公司兼职已好几年了,每年都要做BIOS方面的培训,而且听众还不只是BIOS工程师,包括那些主板调测维修人员和逻辑设计工程师。这个机会促使我对平时的工作进行总结,并努力着眼于“为什么有故障,怎样解决”。

为此,始有此排错三法:

一、 排雷法

初做BIOS的人,首先遇到问题多是:BIOS停了,Debug Code是XX。象这种问题一般是一块主板刚做出来,接上CPU、内存条等必备设备,一开机,停了。或者,刚换了一个新的设备,如内存、显卡等等,开机,也停了,市场已经在卖的主板是不常见的。我将导致BIOS停滞的代码(段)称为“地雷”,踩到地雷了,自然无法往前走了。排雷法,就是设法找到地雷所在,排除它。这里“找”是关键。有人说了,不是有“Debug Code”,有什么好找的。说这话的,大多是我们的主管,他很纳闷,认为我们是在浪费时间。

要使用排雷法,有两件工具需要推荐。一是ROMTER+ROM卡,它的意义在于可以随时修改随时刷BIOS以看效果,一是有双端口监视的DEBUG卡,强调双端口是因为80Port已经被原厂BIOS用了,我们在排雷程中尽量使用另一端口。

现在要施法了,根据Debug Code的指引,我们能找到“丢”(这是AMIBIOS工程师常用的说法,我现在做AMIBIOS,自不能免)出该code的代码行位置,暂称之为A点,这个位置并不一定是“地雷”,但地雷一定在这个位置和下一个debug code丢出来的代码行之间。将下一个位置也找出来,称之为B点。怎么找?文件查找呀,什么FF之类,像VC都可以跨文件查找。AMIBIOS相对好些,在《BIOS研发技术》中公开了其流程,且该流程就是以debug code 为结点,虽说有点过时,但参考价值很大。有了A点和B点,这时大可以使用大学里学的《数据结构》中的“二分法”(谁说大学里学的没用来着?),在A点和B点代码之间均匀的间插一些(不要只局限于两处)你的代码。你的代码也不用做什么,只需要往DEBUG卡的另一端口丢一些你看得懂的数据——也是一种debug code就行。好了,重新编译,写入ROM卡,复位。什么?又停了。当然停了,你还没修改呢。没关系,你仔细看看你的代码所丢出的code,相应的代码行就是一个新的A点,同理也有一个新的B点,以此A、B点,重复前面的方法,如是几次,你就能找到造成BIOS停滞的地雷了。至于找到后如何排雷就没有通用的办法了,你要看此地雷形成的原因是什么,特殊情况特殊处理。
方法说起来很简单,但使用过程还是有几点要注意。

1、你的代码不能随意改变寄存器的值,以不影响原代码执行路径为原则。如果你的代码所在位置可以使用堆栈那就用堆栈保护你要用的寄存器,典型如下(以8位端口为例):
push ax
push dx
mov al, debug_code
mov dx, port_address
out dx, al
pop dx
pop ax
如果你的端口地址小于100h,那dx都可以不用了,直接” out 82h, al”。如果你的代码还不能使用堆栈,如在bootblock段,那就使用sp(堆栈指针),因为堆栈不能用,该寄存器大多数情况下也就“没有用”。如:
xchg dx, sp
mov dx, port_address
mov al, debug_code
out dx, al
xchg dx, sp
al寄存器在很多代码行间隙是可以被改变而不影响程序执行的。你只要看后随的代码是不是先对它赋值再使用就知道了。

2、BIOS代码是分层结构的,上一层总是不断调用下一层的子过程。在排雷的过程中间插代码时,一次也尽量在同一层,判定地雷不在此层后再继续到下一层使用排雷法。对于文件也可以遵循此规则,先判定是否在同一文件中,如果不是再到另一文件中继续。

3、在找到地雷后千万别忘了抽去你插的“桩”。这一点很多高手都不在意,认为那样对代码没有影响,就让它了。但后来人看到这套源码,会不知所云,就象一条原来平直的高速公路,变成波浪形。

二、比较法

一客户买了一块PCI SCSI控制卡,插在某公司的主板上则该卡所接硬盘上安装的某个windows 应用软件就不能正常运行,但该卡插在别的主板上就一切OK。做为一个公司的BUG工程师,只有认同此乃BUG并开始努力解之。

所谓比较法,就是两个具有可比性的系统,一个已知没有故障,一个已知有故障,通过种种现状、参数的比较,找到故障系统的原因,并排除之。记住,前提是具有可比性,比如使用相同芯片的两个主板。

使用比较法也需要推荐一个工具,此工具是AMI公司的ru.exe,它适用于dos/windows98,windows2000版叫做se.exe。虽然,Award公司也有类似功能的工具软件,但在比较法中,该软件的file->save(F2)功能特别受用。该功能可以将某个PCI设备配置空间、系统所有PCI设备配置空间、你正查看的某段I/O、MEM、SIO、CMOS等等的内容保存至一个文件中。同时,它的另一个功能file->compare (F8)又可以从一个文件中读取其内容与正在查看的内容进行比较,区别显示相同与不同的单元。

介绍完上面ru.exe的两个功能,比较法的具体使用也就相当明了了。就是,将你所怀疑可能会引起故障的一些寄存器、I/O、MEM值从好的系统读取并保存到文件上,拿到故障系统中进行比较,如果有不同,则修改故障系统的值为好系统中对应值。如此逐个比较修改,你很可能幸运的发现故障消失了。(据说概率有70%之高)这是说很可能,是因为不是每个故障都可以修改设备的静态配置就能解决的,有些还是其它原因。它的难点是难以找到一个可比较的BIOS。

也有同几点需要在使用比较法给予提醒的:

1、尽量让硬件平台完全相同。这样,可减少一些不必的干扰。因为,一旦硬件发现改变,自然一些寄存器需要设置不同的值的。

2、在修改故障系统的寄存器之前,务必熟读其datasheet,明白修改后可能造成的后果,不要烧了主板。

3、经验不同的BIOS工程师所需要比较的工作量不同,一些有经验的工程师很容易知道该比较那些寄存器。给新手提个醒,除了PCI设备配置空间,Super I/O寄存器外别忘了Power Manage I/O寄存器,GPIO控制寄存器等,SiS芯片组还有APC寄存器。

4、相同的硬件不一定所有寄存器设置相同,有一些寄存器不同的BIOS有不同的值是正常的,如PIRQ就可以因不同厂家的BIOS而不现,还有像Power Manage I/O、GPIO的基地址等。
多年经验发现,比较法特别适用于内存、PCI设备不兼容等故障。另外比较法还可以扩展到相同厂家不同版本芯片间进行比较。

三、陷井法

陷井——我想各位都不陌生,小的时候谁没用它逮过麻雀或捉过小鱼,就连大文豪鲁迅先生也用过了。陷井法,也就是在“猎物”的必经之路上做好手脚,或引诱或等待“猎物”中套。这里的“猎物”就是BUG——具体的说是引起BUG的代码段。

在一个新的BIOS刚刚走完它的全程时,最大的考验就是windows的安装过程,最常见的就是安装过程中猝死(蓝屏)或怠工(那种象陷入死循环的死机)。这种BUG由于BIOS已经顺利运行完毕,用前面的“排雷法”已经没有机会,用“比较法”又找不到合适的可比较的BIOS。这时,只好考虑动点心思布“陷井”了。

在具体布“陷井”之前,先谈谈“陷井”的制作。非常之简单,象前面讲的“排雷法”一样,间插一些往DEBUG卡第二端口上丢自定义的CODE的代码——我将这些代码称之为“陷井”。通过在各个可疑的代码路径上布一些“陷井”,配以相应的DEBUG卡,从而判断出最后一次对BIOS的调用是哪些代码(段),再进一步分析这些“最后值守的可疑分子”不难找出“真凶”。这里提醒一点,DEBUG卡最好是那种数码显示不受系统复位影响的那种,因为有些BUG的现象就是系统复位,如果数码显示也被系统复位给清掉了,就看不清最后一个CODE是什么了。

熟手已经想到,这种BUG应该属BIOS Runtime模块的BUG。但Runtime代码没有约定的执行流程,完全取决于应用层对其的调用。那我们的陷井布哪呢?其实,BIOS的Runtime代码主要集中:PCI/PnP、INT15、SMI、INT10和INT13。其中INT10和INT13分别是显示和磁盘的ISR,这些代码产生的BUG都比较直观,或者显示出错但系统可照常运行或者是磁盘I/O发生错误,而且这两个模块也容易使用各种测试软件测出。我们要布的陷井集中在PCI/PnP、INT15和SMI的处理代码中,windows安装过程产生的系统死机也常是深藏于上述代码中的BUG引起。对AMI BIOS(我只能以AMI BIOS为例,因为它的源码已经公开过,不会有版权之虞)这三功能的总入口点就分别在RT.ASM、INT15.ASM、SMI.ASM。不妨先在此三个总入口处布下陷井,看看“猎物”走的是哪一条道,而后再逐步分清它走的是哪一条子道,耐心点重复几次,不难发现其藏身之处。
陷井法的原理就是这样,使用过程中就看各人的手法了,几点还是提出来给大家参考:

1、 布陷井之前可以充分使用setup的设置功能关闭/打开一些设备,以排除一些不必布陷的代码,提高陷井的命中率。

2、 陷井法与前面的排雷法之本质区别在于陷井法首先是找路,就如在一个交通错综复杂的城市,先确定“猎物”是否经过某条代码路径,只是找到路径后才可以利用排雷法定位具体的代码段。

3、 windows安装过程中的BUG,可以借助ghost这个工具,将发生问题之前的系统备份下来,免去每次重新安装。

4、 如果你的DEBUG卡允许(不允许的时候可以使用BDA[Bios Data Area]中一些未定义的内存),你尽量将一些现场密切相关的寄存器值也丢出来,为下一次布陷井提供更多的参考,如一些中断状态值或子功能号等。

来源:ccw

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xtdumpling/archive/2008/03/28/2226787.aspx

你可能感兴趣的:(数据结构,windows,软件测试,vc++,交通)