搜索
您的当前位置:首页正文

打造BIOS

来源:筏尚旅游网


纯手工打造你自己的x86 BIOS(1)

存放BIOS的设备从早期都放在EEPROM到现在的Flash ROM,一路上的演变已经可以写成一部BIOS历史课本。

在早期的BIOS中,BIOS本身程序代码就是用来当成一个Boot Loader,但是由于后来的芯片功能越来越强大且BIOS除了初始化硬设备之外还要协助OS去支持一些功能,所以整个BIOS程序代码就已经变成了一个庞然大物,而维护整个BIOS程序代码也非一个人的能力所及。

因此后来的BIOS程序代码都是由一些BIOS供货商来负责维护,各家BIOS供货商会有自己的撰写方式与架构。正因为如此,开发BIOS的程序代码目前也都是使用各家厂商所提供的开发环境来建构。

而这篇文章的目的在于如何在目前的PC架构下纯手工打造一个属于自己的BIOS环境以及撰写一个简单的BIOS程序代码可以让系统输出一个值到Port 80h,我同事问我为什么不写一个mini BIOS可以开到DOS下去,因为如同我上述所说,写是可以写啦,要花很多的精力跟体力,这边只是抛砖引玉说一个大概,然后描述一下如果自己真的要撰写一个BIOS 要如何做? 或许有些人有兴趣可以找几个朋友一起写BIOS,或许哪一天就可以开ㄧ家台湾BIOS供货商...(呵呵,我自己在幻想啦!)

需要用到的工具以及相关知识:

1.MASM 6.15

2.Turbo C++ 3.0

3.基本汇编语言撰写能力

4.基本C语言撰写能力

5.IA32 Spec vol 1~3

6.EC BIOS ROM(可以请EC BIOS Eng协助)

实验目的与方法:

1. 建立一个BIOS 开发环境

2. 建立一个1MB BIOS ROM file

3. 利用汇编语言撰写一个64kb 大小的BIOS程序代码的 binary file

4. 利用C语言撰写一个Build Tools,并将EC与64k BIOS塞进去1MB BIOS ROM

5.利用烧入器将1MB BIOS ROM烧入到MLB中,并且上电后检查Port 80h是否有正确的输出我们程序代码中撰写的值。

上面的程序撰写部分不需要很强的能力,只要基本的C或是汇编语言语法就可以了,所以算是基本入门,重点还是在我ㄧ直强调的地方 \"懂架构才是重点,程序语言只是工具而已\"...。

纯手工打造你自己的x86 BIOS(2)

计算机发展至今已经经过了很长的时间,许多遇到的问题也都被ㄧ些前辈解决了,因此目前学校或是市面上的书籍几乎都是讲解如何在一个\"现成且成熟\"的平台上发展。

例如很多书会教你写VC/.net/Java ,但是,说到如何去写编译器、操作系统及开发BIOS的书就不多了,也因此大家比较专注于如何在成熟的平台上能够快速/有效率/有系统性的开发以及提出解决问题的办法,而像我因为兴趣而去探讨BIOS的本质的人就应该比较少吧,毕竟这些问题在之前的前辈都已经遭遇过,也提出了很好的解决方式,所以才会有目前一些实力坚强的BIOS 供货商的存在,因此也没必要像我这样纯手工打造。

在前ㄧ篇的文章中我已经大致上描述了一下我的实验方式,这边就针对整个流程作ㄧ些详细的介绍。

在纯手工打造你自己的x86 BIOS(1) 中有提到,你可以学习到的东西是比较基本的概念,所以我并不会把完整的Sample code贴上来,毕竟教钓鱼比给鱼吃还重要,因此请大家轻松看待我的拙作(小弟也只入行1年多 ,还请前辈还多多指导)。

前一篇文章中所提到的核心部份在于我撰写了64K 的BIOS程序代码 (MyBIOS.asm),实际不到64k ,只是我利用了填00h的方式填满到64k。

而组译与连结是透过ML.EXE ,输出的是一个MyBIOS.exe ,而这个是一个DOS下的执行档,所以里面有MZ Header ,因为被多加了这个Header 因此MyBIOS.exe约65k ,而我会再利用Build tools取出里面的64k ,然后变成MyBios.bin,当然这只是最简单的方法而已,但不是唯一。

[注] EXE2BIN 只能转换小于64k 的档案,所以这边不能使用它,所以我才自己转换。

当取出了MyBios.bin 之后连同EC.bin 经由Build.exe 产生一个1MB 大小的BIOS ROM Image file,然后把位置固定住。

固定地址是因为:

1. 我的范例中的Platform 上面的EC Controller是采用Share ROM方式,也就是把EC BIOS包在System BIOS中,因此我们需要固定住地址,这样子EC Controller 才能去System BIOS中读取EC BIOS的程序代码并且执行。

2.由于x86 CPU读取第一条指令是在 FFFF_FFF0h,所以我们必须要把BIOS code固定在尾端往下算的64k 范围内,如下图所示:

图中可以看到整个BIOS ROM Image file是1MB ,其中

64k是EC code另外64k是BIOS code,然后摆放在1MB 档案中的位置就如上图所示,其余空白的地方我都是填00h/ffh (须看BIOS ROM Spec中说明空白是00h/ffh)

总结:

●MyBios.asm 负责CPU 第一条指令以及组态CPU 模式还有设定Port 80h的输出并且输出一个99h 到Port 80h

●EC.bin EC的BIOS Code,由EC BIOS工程师撰写,我只是拿来用而已

●Build.exe 会先产生一个1MB 空白的BIOS ROM Image,然后把上面两个bin file塞到先前产生的1MB 空白BIOS ROM Image,并固定其摆放地址,而摆放时并没有考虑任何File System的架构问题,而是直接塞。

●MyBIOS.ROM 产生出的MyBIOS.ROM就是要用来烧入到BIOS part中的档案,也就是类似一般大家在Flash BIOS时的那个档案。

C:\\> Flash.exe /all MyBIOS.ROM

上面是一般大家使用某个Flash Utiltity 时会打的一些指令,因为工具不同所以参数也不同,不过相同的是都会有一个BIOS ROM Image file(例如MyBios.ROM)

另外这边有点不ㄧ样的地方在于我没有自己写Flash Utility(我们BIOS装在EC Controller下,而我又懒的看EC Spec),所以没办法像上面方式使用某个工具去更新 BIOS ROM,况且你们如果要实验相同的东西,Flash Utiltiy也不能共享,所以这部份有兴趣的人就自己研究一下你们公司内是怎样撰写这部份的工具。

而我的烧录方式是采用EC Controller提供的烧入器,所以直接点选我的MyBios.ROM就可以烧进去BIOS Part了,而这部份也不多做说明。

由于整个实验我才花了1.5天时间(0.5天写Build.exe + 1天写MyBios.asm),所以

很多地方没考虑进去,希望各位有其它意见请告诉我,谢谢!

纯手工打造你自己的x86 BIOS(3)

在前面两篇文章中的描述中其实大家就应该可以知道我的实验环境由几个部份所组成,所以我这边假设 \"如果我是ㄧ个BIOS Vendor\",我将会如何描述我前面所说的那些部分。

在我的实验中,整个BIOS Build Environment 我们可以得知如同下图的架构,我在后面将分别对这些部份做ㄧ个简单的说明。

1.Source code : 这就是我的MyBios.asm,只有一个档案,ㄧ般我会放在某个目录内,大家可以想一下如果扩充成7000多个档案的时候,你会放同一个目录吗? 如果分类你要如何分? 如果修改,你要直接改吗? 还是采用什么方式去覆盖?

2. Build Settings : 我使用的是MASM,而他在我的C:\\MASM,假如你是利用makefile产生结果,那么你就会需要设定一些工具的路径,组译或是编译的程序是哪ㄧ个,参数为何...等。

3.Build Tools : 像我提到的Build.exe就是我自己写的,用来辅助建立BIOS Image

时所使用,所以当你的环境越来越大的时候,所使用的Tools可能就不只一个。

4.Build : 当上面的部分都结合在一起后,就可以产生出结果,ㄧ般我们可以利用makefile 方式把上面步骤都结合在一起,然后就可以方便的产生出结果。

5.BIOS Image : 在我的实验中,产生的结果就是MyBIOS.ROM。

结论:

实验中大家可以发现,其实BIOS vendor所提供的环境基本的本质很简单,只是当你在实做的时候你会遇到一些问题,而你在解决这些问题的时候不知不觉整个架构就会越来越复杂,因此当我们接触到一个成熟的BIOS Build environment时,就会需要了解更多的东西以便我们更能够驾驭BIOS vendor所提供的环境。

前面这几篇文章大致上描述出BIOS Build Environment的基本架构,所以当你想要写一个BIOS然后提供给别人一个环境去撰写BIOS时,其基本本质大概就是这样,后面的文章中我会继续介绍实际上MyBIOS.asm 中我们该撰写什么后我们才能够在Port 80h 的7段显示器上显示99h。

纯手工打造你自己的x86 BIOS(4)

上ㄧ篇文章我已经针对我的实验做了叙述,这里我就针对实际上我的程序代码撰写的内容做一个介绍。

在程序代码的撰写中,其实我只有使用了简单的C语言跟汇编语言语法,重点是要让大家知道,其实BIOS跟一般的Boot Loader写法没什么不同,只是PC上面的BIOS需

要考虑的事情比一般的Boot Loader还多很多,因此程序代码 size可以大 到1MB甚至是2MB (ㄧ般Boot Loader不可能这么大),所以我有机会玩一个这么大的Boot Loader也真是很荣幸的啦!

废话不多说,我就先针对我前面提到的Build.exe 内的程序代码说明;

底下是我的Build.c 内的程序代码片段,其实我就只有使用到fopen() 、fputc() ...等基本的函数去读写一个档案,所以可以很容易的把我组译好的MyBIOS.bin 跟EC.bin 塞进去同一个档案内,做法其实很简单,就是像我下面做法一样,先利用fopen()开启档案,然后在把你要的数据写进去档案,只是写的时候你要考虑file offset 位置的问题,因为当你烧录到BIOS part中的时候,CPU是会固定重FFFF_FFF0h的地址读取第一条指令,因此你要像我前面说的一样,把MyBios.bin放在固定的地址中。

//建立一个空白的MyBIOS.ROM , 里面数据都是00h

void show_help(void)

{

printf(\"Build.exe v1.0.0 by Harrison Hsieh \\n\");

printf(\"===========================================\\n\");

printf(\"/C Init MyBIOS.ROM \\n\");

printf(\"/B [EC] [BIOS] Add Rom \\n\");

printf(\"Output : MyBios.ROM \\n\");

}

void InitBiosROM(char *argv[])

{

FILE *fo;

long i;

if ((fo = fopen (BiosRom, \"wb\")) == (FILE *) NULL)

{

exit(1);

}

for(i=0 ; i<= BIOSSIZE ; i++) //1MB

{

fputc(0x00,fo);

}

/* All done, close the file */

fclose (fo);

}

在说明完Build.c内的做法后,接着说明MyBIOS.bin 内的程序代码撰写;

其实在MyBios.asm 中,我只有做4 件事情:

1. 设定好FFFF_FFF0h的第一条指令

2.开启BigReal Mode (因为我要设定ICH9的RCRB内的缓存器,所以要开启)

3.设定ICH9内的缓存器,把所有Port 80h的讯号转送到LPC接口(我的Post card走LPC界面,所以要设定)

4.输出99h 到Port 80h(所以LPC接口上面的Post card就会显示99h)

底下是我的MyBIOS.asm 内的程序代码片段:

COLDBOOT:

CLI

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; 1. Enable big real mode

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

JMPREG di,Make4GBSegmentDI

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; 2. Set RCRB base address

;; 3. Config ICH9 Register

;; 4. Out 99h to Port 80h

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

....

mov dx, 0cfch

mov eax,RCRB_BaseAddr

out dx, eax

....

and BYTE PTR es:[esi], NOT (04h) ; RCRB+xxxxh bit 2=0 Output to LPC

....

fPostCode:

mov al,099h

mov dx,80h

out dx,al

jmp fPostCode ;无穷回圈ㄧ直显示99h

...

...

wbinvd ; ...begins here on power up

PUBLIC POWER

POWER:

JMP COLDBOOT ; first jump

DB '11/14/07',00,00,00 ; My release marker

以上就是我撰写的程序代码内容的说明,其实没有用到什么特别的东西,如果说比较难的部份大概就是如何把程序代码塞到正确的地址吧。

总结:

纯手工打造你自己的x86 BIOS 文章(1)~(4) 在这边就做一个结束,在这几篇文章中的实验我主要是要帮助刚入门的BIOS新手去了解整个BIOS vendor提供的BIOS环境架构以及实际上BIOS code撰写的第一步,因为很多东西都是入门的第一步比较难。

还记得ㄧ年前我刚入行的时候,我们学长跟我说写BIOS最简单的方式就是自己把一个BIOS写到能开机你大概就已经学会了,虽然我离能自己写到开机还有一段距离,不过在学习的过程中也学到了很多东西,因此当初会想自己纯手工写一个能让x86 CPU执行一段BIOS code的环境也是希望能帮助更多BIOS入门时遇到挫折的朋友 ^^Y。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top