为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

我所知道的BIOS

2017-10-14 50页 doc 127KB 73阅读

用户头像

is_963767

暂无简介

举报
我所知道的BIOS我所知道的BIOS [我所知道的BIOS]->[前言] 1 本身从事BIOS相关工作已经六年了;今年由于生涯规划,决定暂时(?)离开BIOS而转做其它工作;即使如此,对于 BIOS仍是有着极大的兴趣以及期待. 从小就是喜欢做整理以及分享的人,所以最近有个冲动是:何不将自己所知道的整理一下,并将之POST出来,让更多对BIOS有兴趣的人可以有点深入的了解BIOS? 也让版上的诸多前辈可以提出指教及批评,进而纠正我的一些观念 ? 基于这样的想法,我选择了这里来作为我这个念头付诸实现的地方,请大家多多挹注,多多指教,多多批评 !...
我所知道的BIOS
我所知道的BIOS [我所知道的BIOS]->[前言] 1 本身从事BIOS相关工作已经六年了;今年由于生涯规划,决定暂时(?)离开BIOS而转做其它工作;即使如此,对于 BIOS仍是有着极大的兴趣以及期待. 从小就是喜欢做整理以及分享的人,所以最近有个冲动是:何不将自己所知道的整理一下,并将之POST出来,让更多对BIOS有兴趣的人可以有点深入的了解BIOS? 也让版上的诸多前辈可以提出指教及批评,进而纠正我的一些观念 ? 基于这样的想法,我选择了这里来作为我这个念头付诸实现的地方,请大家多多挹注,多多指教,多多批评 ! 欢迎任何的建议 ^_^ 首先要说明的是,我觉得BIOS在台湾可以分成三类的人:(自己的分法,仅供参考) 1. 撰写BIOS kernel的人 2. 撰写chipset code的人 3. 撰写 OEM code的人 我是属于第二类的人,所以我的观点(view point)也是从chipset出发 ! 对于第一及第三类,我的接触不多 ! 要先这样说明的原因是:有些问题我无法回答或 comment,因此,就有赖版上诸位的帮忙了(if available) 还有,我本身是撰写某一家BIOS(A, P, or M)的,所以会几乎以该家的所教给我的 flow/information 来叙述事情;当然,我会尽量抽离这种成分来叙述,让大家了解 "事情的本质即可 "...若有偏颇之处仍须请大家包涵... 最后,我所撰写的几乎是亲身经历的 information,因此,不会有天马行空的想象(不过,做BIOS仍是需要想象力的...^_^...) 若有错误,那应该是我的经验不足,或是我的经验有误,还是要请大家指正啰 ! 就这样... liaoo 任何 firmware 都有相对应的硬件;也唯有深入了解硬件,才能写出好的 firmware ! (当然,对 programming language 很熟,有技巧的的人可以写出好的 firmware,但是,另一个层面是:对硬件很了解,所以所写的firmware 与 H/W 搭配良好,这也是另一种值得追求的地步) BIOS 就是 "主机板的 F/W". 所以,它的对象就是主机板上的所有 devices. (为了后续的解说,我只列出一些,其它的坊间书上都可找到) - [CPU] => central process unit. 依架构不同有分 Intel or AMD cpu. 其工作之一是: fetch code->decode it->fetch operands->calculate->store result. - [North bridge] => 即俗称的北桥. 常见的 Intel 945/P/G,965 等是其北桥芯片代号. 它可以约略区分成四个 blocks(H/W view) 1. Host interface: 即 与 CPU interface 的部分. 2. DRAM interface: 即与 DRAM interface的部分 3. Display interface: 即与 AGP/PCIe VGA interface的部分 4. Link interface: 即与 South bridge(南桥) interface的部分 简单说,North bridge的功能是: Host block 承接 CPU 所 issue 的 cycle, 辨认(identify),并且将之 forward至 "正确的接收者" ( Ex. DRAM block, display block, or Link block ) 所以,它像交通警察一样,接收中央的命令,将来自四面八方的车流引导至正确的地方,让整个城市的各部分各角落可以相互交流无虞. -[South bridge] => 及俗称的南桥. 常见的 Intel ICH7/8为其南桥芯片代号. 它"可能"包含以下的 blocks: 1. Link interface: 即呼应北桥的部分. 2. PCI block: 处理 PCI request部分(即 implement PCI spec H/W part) 3. ACPI block: implement ACPI H/W part 4. USB 5. Audio 6. SATA(AHCI) 7. ... 所以, 南桥里面包含许多我们常见的名词, USB/1394/SATA/HDA/TPM/PCIE...等 -[BIOS ROM] => 储存 BIOS image的device. 常见的有 ISA ROM/LPC ROM/SPI ROM. 编译出来的 BIOS binary file透过烧录器或是 flash tool 烧录到此 ROM中. 内容是0101...的 binary code 所以,总结来说: BIOS code被CPU fetch, 经过 decode后, 会转发给NB.NB接到后也会自行decode 此 request;若是 与 DRAM有关的,则 forward to DRAM block;若与 display有关,则forward to display block;若是与 PCI有关的,则将之转发给 SB(透过两者中间的Link),请SB再找适合的人 Ex. USB, SATA, or 1394 controller ! ( 别忘了 PCI H/W是在SB里...) 以上依序所讲到的 CPU->NB->SB->ROM,将在后面的叙述中用来说明一些观念及flow. Summary: 1. BIOS可以说是 chipset's driver !!! 2. CPU所 issue 的 cycle会先抵达NB,由NB判定是给谁的;若不是 for DRAM or display, 则会再转发给SB,由它判定是要给谁的 在此将以DeskTop platform来说明(Notebook platform 的 power-on sequence 牵涉到 EC,可参考讨论区中 "power on sequence" 文章);还有,所叙为rough flow,详细的时序图依据design会有些许不同. [Power-On sequence] - AUX power ok - Main power ok - PCI reset - SB state-machine runs... - NB state-machine runs... - CPU power-Good ok - CPU reset - 1st code-read by CPU ( <- BIOS entry point,即 CPU 会抓取 FFFFFFF0h 处的 BIOS code 来执行) * 当然CPU一次抓取的BIOS data不仅仅是几个Byte ! 而是一堆的data(Ex. 64 bytes);之后会从中 extract 出 FFFFFFF0h处的 data,然后来执行. 补充: 为什么CPU 发的第一个位置不会只有FFFFFFF0h? 而是多抓很多个? 范例中为什么是64 bytes? 原因在于 cache的支持. cache不是细分为单一byte 的, 而是以block(many bytes)为单位. 这个block的大小的名词就是 cache line size. 也就是要填入cache一次要写入的bytes量. 例如 cache line size 为 16 bytes. 那么一次就要读16 bytes到cache去. CPU 一但发生cache miss(第一次开机一定是cache miss)的状况时.就会通过host bus 对外取得资料. 这时就会产生burst read cycle来达成fill cache line的需求. 所以由CPU 的 cache line size的大小就可以知道CPU一次会抓多少的 bytes. P4以后CPU 的cache line size 为 64 bytes, 所以CPU 就会产生一个 burst length 为8 的 memory read cycle. 所以CPU 发出的位置就需往下减.然后在读取的数据中可以包含到 FFFFFFF0h以后的数据. 自此,CPU便循着 CPU->NB->SB->ROM 的 path,循序地至BIOS ROM中抓code,执行 fetch->decode->calculate->store...自此开始便是BIOS POST stage starts... [有可能遇到的问题是] debug code = "00" or "FF" (意即BIOS常用的 Port80 card所显示出的 "code" ) !!! * 此时,强烈建议:请在BIOS entry point 处 丢Port 80(value可自行定义),因为,即使BIOS有跑到,但因为距离 1st 丢 Port80 的 code仍有一小段程序代码;若系统 hang在此其间,Port80仍是没有 code,因此,在BIOS一开始进来便先 out Port80 将有助于判定: system hang before BIOS entry point or NOT !!! ) # Assume system hang 'before' BIOS entry point, 可能的原因有: - incorrect power sequence: 此 sequence 有 spec,讯号间的相对关系与 assert/deassert的时间,violate spec有可能导致 system hang;此时需要 H/W or board designer来量测 - incorrect power-on frequency:有发生过因为 Power-On CPU frequency错误而不开机者.请用 scope量测 - incorrect chipset behavior: 意即上述的 power-on sequence中有关于 NB/SB的 state-machine部分,有可能这部分的行为不正常,因此需要 H/W designer来 clarify * 曾听说,某家chipset需要BIOS image 中 include 几个 bytes 来 config NB/SB的 registers;这些 settings也会影响 power-on时 chipset的 behavior;因此,这几个 byte 若是错的,也有可能 system hang 补充:很多chipset都(or 曾经)有这个功能, SiS, NV, VIA, Intel. 以前有个词叫ROMSIP就是指这玩意儿... 即使在现今的intel platform也有预留这东东. #Assume system hang 'after' BIOS entry point => 这就是BIOS engineer的时间了,就 debug吧...(尽管,有些 issue 是 board or H/W造成的...) * 此时的 debug方式,若有 辅助工具的(Ex. P debug card) 就用,没有的就用Port80 card啰 ! [Summary]: 没进入到 BIOS entry point前....不要找我....真的没办法 >_< * 关于 BIOS entry point,请参考 讨论区中 "追踪BIOS code 的进入点" 文章 !!! [Power Button开始的动作] 一般Power Btn 都是EC 控制(或称PCU),如果你说要知道Power Btn之后的动作就是问EC 师就对啦。 我印象中好像是Power btn按下后-->EC 侦测到动作(应该是KBC 发Event给EC BIOS或是EC BIOS自己每隔一段时间去检查有没有Event..没K过EC Spec,纯猜测...)-->EC 检查目前系统状态(不同时间点按下Power Btn , EC可能会做一些动作,因此要判断),检查的时候主要会去检查南桥ICH接到EC的讯号线,判断Sx state-->如果是正常开机,则开始供电--->系统上电后,CPU会从起始地址开始读取BIOS第一条指令(至于CPU何时收到重置讯号可能要看一下其它Spec...)。 另外印象中EC BIOS有分成两种形式,因为EC Controller可能里面的记体器容量会不足,或是说节省成本故意做成那样,所以 EC BIOS 会是包在SBIOS或是放在EC Controller里面两种格式。 如果真的要K流程,应该是去看EC Spec跟ICH Spec吧... 当EC 收到power event (指power button的动作后...), 会根据目前系统的状态来决定是否要开某些电源...For example, 当系统处于s3(suspend)的状态时, 当user按下power button后, EC 会发一个讯号给南桥, 然后EC 会wait for SUSB and SUSC 的讯号assert. 然后开 main power的电(我指的是非suspend的power)...但是详细的动作应该各家都不太一样才对. 而且这些spec都是各公司的knowhow 上一篇所提到的是:BIOS entry point. 它是第一个被 CPU 所抓取并执行指令之处.每家BIOS都有其相应的 file,要牢记. 在本文中,要提及: Jumpless ! 在此要先说明Jumpless的意义.它代表:"用 s/w方式来 config clockgen generator,使之产生正确的 频率s 来供应系统运作". 重要性在于:假如某个 frequency错了,则将导致 system abnormal or malfunction... 有哪些 frequencies由 clockgen 提供? - CPU clock (在此指的是 : host clock, Ex. FSB800 CPU 需被 supply 200MHz clock) - DRAM clock( depends on chipset design; Ex. DDR 533要被 supply 266MHz clock) 更正 : DRAM clock现在都是由NB产生 . 外部的最多是 buffer而已. 并非 clock generator. 原因是为了保持较良好的 host clock & DRAM clock的同步. 补充:我举的例子是以前的chipset design. 现在我做过的 chipset 其 DRAM clock的确由北桥来推. 北桥中有一会 register定义: CPU-DRAM ratio. Ex. CPU clock = 100MHz. Ratio = 3:5,则可得 DRAM clock = 166MHz - AGP clock: is 66.6MHz (= 1/2 PCI clock) - PCI clock: 33.3MHz - SATA clock: 100MHz(see SATA spec,似乎还要更精确...) - Link clock: 即假如NB/SB中间有 link,亦由clockgen提供 - USB 1.1 clock: 12MHz 更正: USB 的 clock 是 48MHz 补充:我们 chipset的 design是: 由 clockgen提供 12MHz clock(或由 external crystal提供),被 PLL吃进去后,会产生 48MHz给 USB 1.1(你说的应该是这部分). 至于 USB 2.0,则是 supplied other freuencies ! - SIO clock...etc Clock Generator的架构 => ClockGen基本组成为 PLL(Phase Looked Loop) + Div. PLL 的输入为 14.318MHz, 利用 回授方式产生出 frequency F;之后 经过 Div 除频,便得到 desired frequency,见下列图示: 14.318MHz -> PLL -> F -> Div -> f Ex. F = 400MHz, 为 PLL振出来的;若 Div = 4,则 f = 100MHz ClockGen的 spec中,会列出许多 registers,好比是 Function 的 "contact window",透过这些 registers可以设定此clockgen ! 更正:其实PLL 不是单纯一个的 div. 锁相回路的参数是两的divider 组成 M(VCO divider)/N(REF divider) 补充:观念上来说是 PLL所振出的频率经 div后可得到 desired frequency. 但在 clockgen中: 1. 有 2 bytes(即所谓的M,N)来决定 VCO 2. 有几个 bits来决定 div;一些主要的 frequency都有相对应的div 3. VCO / div = frequency How to access ClockGen =>现今存取 clockgen的方式,都是透过 SMBUS来达成. SMBUS 有分 1.1 and 2.0,不过大同小异. SMBUS是 2-wire protocol;由 SMBUS master(即内建在南桥内部的 SMBUS controller )来下 command 给 SMBUS device(Ex. Clockgen);Command中常用的有 Block Read/Write & Byte Read/Write 不同家 chipset 的 SMBUS controller implement方式不同,自然下command的方式亦不同;主要的步骤是: - pre-init( clear status or ...) - put slave address(要 access 的对象) - decide Read or Write - put command(Protocol type, Ex. Block or Byte access) - put offset(要存取 自 clockgen中的哪一个 Byte开始...) - put data if (Write device) - start transaction !!! (... processing ...) - get "Complete" status to check if transaction is done successfully (...wait for system reset...) * 当 start transaction后, SMBUS controller便会将 programmer所 prepare的信息将之转成 SMBUS command打给 device;完成后应该在 controller端有 status register可以检查,看看是否 transaction ok or failed,或是有其它 error conditions. 透过这样的方法,programmer便可以 config clockgen使之产生正确的 frequencies. [2 Programming ways for clockgen] => 现今的 ClockGen有提供两种方式 for S/W config. 一为 table mode,一为linear mode. Table mode指的是: ClockGen spec 中会有一个 table,里面说明: 要产生 ? frequency 要填 ? 值.因此,这种方式只需program 1 byte to Clockgen就行了. 若是 linear mode,则是坊间所说的无段变频,即可以微调frequency. Ex. table mode只提供 100/133/166/200MHz,但 linear mode则可以提供类似 102.6/136.3/168.7..等的频率. 此时,要program的 byte数就很多了.....除此之外, linear mode也可以config 所谓的 spread spectrum(%),板厂测EMI时会用到 【Notes】 1. For NB platform power-on CPU frequency 由 2 pins来决定;DT platform会由 Jumper决定.不管如何,之后做Jumpless都可以 override掉原 clock settings 更正: 不是只有NB如此.不管DT 或server. CPU FSB 也是 pin(由于FSB频率比NB多.所以是 3 pins )来决定的.不是jumper. 即使要做超频会对这三pin做手脚, 也不会使用jumper 2. 有些 clockgen所提供的 SS 都是 center spread. 若需要 Down spread则可以由 center spread搭配 改变后的 frequency(类似直流准位)来达成 给我正确的频率,其余免谈 ...^_^... ===================================================================== Q&A ===================================================================== >前辈我有几个问题要发问! >1. 你这边说的Table方式频率是指供应给CPU频率吗? Intel网站的CPU说明,他说是固定的不可调的? 所以这不是HW固定住(Latch)设定值了吗? > >2. 可以解释一下Down Spread/Center Spread /...所代表的意思吗? 还有用途? > >3. 我目前也在尝试Program ClcokGen(新手上路),很多专有名词还没搞懂,另外目前ClockGen不是可以 >输出不同频率吗? 为什么Table方式只需要Program 1 byte就好 ???还是说各家厂商设定方式不同,有些厂 >商只要利用1 Byte 就已经选择好所有的频率了 (33MHZ/48MHz/DOT96MHZ/LCD27MHZ...)? [For #1] => 我所谓的 "Table"方式指的是: 为了方便设定,clockgen designer会专门提供一个byte register(8-bit);此 byte的某些 bit fields(Ex. bit[4:0])可以让programmer填一组值,例如 01001b. 此值 write 至 clockgen成功后, CPU/DRAM/AGP/PCI/...etc 都会是固定的频率. Ex. 100/133/66/33/...etc. 所以才说只填 1 byte only ! 此值一旦填至 clockgen, clockgen便依据该 byte(可参考 spec前几页,会有一张表说明: bit[4:0] <-> frequency combinations)来产生出 frequencies. 不管用哪一种方式(table or linear mode),都会 supply CPU frequency !!!不过,此时的 CPU frequency is CPU的外频 ( CPU 总频率(core) = (外频)*(倍频 <-multiplier) ) Ex. 外频 200MHz(Merom CPU, FSB 800),倍频 = 12 -> core freq = 2.4GHz 还有,BIOS可以调整 外频 & 倍频 ! 没问题 ! 不过,若遇到锁频的CPU(Ex. 量产版的CPU),倍频可能无法调整.但外频还是可以靠 config clockgen来达到 !!! For #2 => 假设要达到 100MHz 且 SS = 0.5% center spread.则: (...想象以前学的直流与交流的讯号...) 100MHz 相当于 直流的部分,其值不随时间而变; 0.5% center spread好比弦波讯号(振幅是 100M * 0.005 * (1/2);所以,两者的合成便是: 以 100MHz为中心,其值随时间而变,振幅 is 100M * 0.005 * (1/2) 的讯号 !!! 我 '猜' 要这样测试的原因是:所产生的 clock一定不会是 perfect的 100MHz,有可能因为组件或是外部干扰而被 "改变".为了模拟这样的情况,我们会将 clock的 spread spectrum enable,产生 "随时间而改变"的频率,来测试系统的稳定度...等 Down spread 0.5% 指的是:距离 水平 100MHz, 最低的值是 100M-100M*0.005,最高值则是 100M本身( 等同于: 水平值 99.5 + center spread 0.5%, right ? ) For #3 => 前面提过,只设 1 byte 就可以产生所有频率是因为: clockgen公司已经把设定各频率的功能"浓缩"在一个 byte里面 ; programmer只要 config this byte 就可以了... * 关于 EMI 测试部分,有错请指正. ( ...我有用到 "猜" 字眼...^_^ ) [[EMI 测试的知识]] 由于 对clock信号来说. 锋(peak)值是能量最强的地方. 所以peak的能量就会不断累积, 发射出来. 因此在频谱上就会出现能量很强的频率. EMI 工程师的工作就是要想办法屏闭这些电磁波的干扰. 为什么需要 spread spectrum? 由于PLL 十分精准. 也就是说 100MHz的clock, 其 peak & peak之间的距离一致(波长固定). 所以能量十分惊人. 使用展频可以使 peak 的距离改变(由于频率不断的在一个范围内改变, 这个可以用示波器累积clock信号来看) 所以累积的能量会比较低. 这样EMI 可以比较好处理. 至于为什么会有要求BIOS一开始就把展频开着, 以确保板子的稳定? 很简单.不开展频clock很稳定.自然比较不会有问题. 展频一开. 由于频率是浮动的. 很多设计欠佳的板子就会不稳定. 及早发现才能及早修改. [[补充数据~~运作原理]] CPU本身有默认值的BSEL[2:0]值,这个值是与Clockgen所产生的BCLK是对应的,CPU本身Spec会有一个Table定义这个值,然后CPU透过BSEL[2:0](输出pin) 连接到Clockgen与NB(这两个都是输入pin),所以当Power on的时候,Clcokgen会依照CPU预设的BSEL[2:0]去产生BCLK给CPU,而FSB 频率也是经由CPU接到NB的BSEL[2:0] 来同步(一般都是1/4 CLK 提取一次数据,所以假设BCLK=200MHZ ,而Clockgen输出到NB的Host Clk=200MHz,一般都会同步,所以 FSB=Host clk*4 = 800MHZ) ※ Clockgen 分别透过BCLK与HostClk pins输出频率给CPU与NB 然后CPU开始执行BIOS Code,当执行到Program Clockgen时,BIOS可以透过Clockgen内的缓存器的某个Byte 内的FSC/FSB/FSA 这3个bit 来改变BCLK输出频率(应该可看作override BSEL[2:0]设定),当CPU接收到新的BCLK频率后可能的反应有: 1. CPU本身不支持这个BCLK所以系统当机或是Shutdown 2. CPU 可工作在这个BCLK频率,依照这个频率对照Table,然后改变BSEL[2:0]的设定 另外CPU 是否能工作在266Mhz or 200Mhz or both,这部份依照每颗CPU不同而有所不同,有些CPU只能工作在266Mhz,所以当BLCK=200Mhz时,CPU就不会工作。 假设CPU可工作在266Mhz与200Mhz,则当BCLK从200MHZ-->266Mhz时,CPU一样可以工作。 还有CPU内部的调整ratio的MSR缓存器可分成测试版的CPU跟出货版CPU的不同: a)测试版CPU的Ratio可调,如何调要看Spec b)出货版CPU不可调,也就是锁倍频 --------------------------------------------------------------- 1. Clockgen 会送两组 differential-pair clocks给 CPU & NB. 目前这两组 clocks是相同的频率. 2. CPU有两 pins 称 BCLK[1:0]. Input. NB HostClk[1:0]. Input * bit[1:0] 是代表: differential-pair clock都会有 2 clocks,分别是 true clock and complementary clock 3. 开机时的 behavior 是: 1) CPU内部自己会产生一组 default BSEL[2:0] 给 Clockgen的 FSC/B/A (依据经验,这组 default 值 可以由 CPU MSR 得到 ; 也等于这颗CPU所能支持的最大外频,BCLK) 2) Clockgen据此 FSC/B/A会产生对应的频率,送给 CPU 的 pins BCLK[1:0] Ex. 266MHz 3) 之后,若有需要, BIOS可以透过 config FSC/B/A 或是 M/N programming(透过clockgen内部的缓存器)来 "override"掉原来的 clock setting以达到改变 BCLK的目的. ------------------------------------------------------------------ CPU 工作频率=外频 (BCLK)* 倍频(MSR调整) FSB 频宽= CPU Spec说由 BSEL[2:0] "同步决定",但是看Clockgen电路有分成,BCLK与HostClk(两者应该输出同样频率) 所以应该是北桥拿HostClk当参考,每1/4 Clk提取一次Data,所以应该是HostClk * 4 以前FSB频宽=FSB工作频率,所以有人把CPU工作频率计算方式看作 " FSB频率 * 倍 频 ",但是由于FSB频宽目前已经不等于FSB 工作频率,且Clockgen 分别拉了两组pins(BCLK与HostClk)给CPU以及北桥,所以计算CPU工作频率的方式才会变成目前的 "BCLK * 倍频" 加注: 1. FSB1066指的是: bandwidth ! 不是频率. 一般不会说 FSB266,而会说 host clock = 266MHz ! 2. *4 应该是因为 ( clock的上下缘都可以触发 ) + ( differential-pair) 的关系 我先解释一下这三pin,就我印象中除了之前 NV chip + K7 和 SiS的chipset以外. CPU 的FS0, FS1, FS2会接到clockgen (FSA,B,C)和NB (BSEL0,1,2)的对应pin. CPU 是负责产生准位, clockgen & NB 会在自己的powerok ready的时候把资料latch进去. clockgen 除了利用这三pin来产生对应频率的CPU clock外, 另外也会根据这个频率来产生合适的PCI-E, PCI clock..., 而北桥则是利用来产生正确的 DRAM clock(host/dram ratio), 对intel来说也有PCI-E的同步关系. 至于超频跟这三pin 的关系, 我稍微解说一下.一般而言要超频的话, MB 必须把到NB & clockgen的路径断开, 由另外设计的线路来取代CPU的FS0,1,2.也就是说NB & clockgen 一开机必须收到一个由这个控制线路决定的FSB. 这样才能作所谓的 133-> 200 or 200 -> 266的大幅度超频.因为此时NB 和 clockgen 才会正确的分配. 别忘了NB, SB, PCI-E, PCI, DRAM是没有CPU这么强的超频力. 直接利用软件改变clockgen会造成很多不该变化的频率跟着变. Note:此超频线路, default是一个所有CPU都能开的安全值, 一但BIOS完成设定, 就会latch住数据 此外还必须配合watchdog 来处理过度超频不能开机的问题. linear mode只用来处理小超频的部份 以前遇到的 clockgen 是 CPU & DRAM clocks 由同一个 PLL决定,其余 clocks由另一个PLL决定. 当时有写一个OS下的小程序,可以微调 CPU频率(以1MHz为单位). 不过,微调CPU的同时也会微调到DRAM clock(<-同一个PLL),只是微调值不同(depends on divider). 现在遇到的 clockgen + chipset design 是: CPU由一PLL供给,而DRAM clock由北桥推.同样的,微调CPU clock一样牵动DRAM clock. 至于其它 frequencies是否会跟着变, depends on Clockgen design;现在的clockgen几乎都有 2以上的PLLs;所以类似PCI/AGP/SATA clocks都会有专门的 PLL控制. 而CPU则由另一个PLL控制. 有兴趣及时间的人可以试试看 M/N programming(小微调). 看着 (Ex. FSB800 CPU)由200MHz 操到 210MHz,也是一种快乐 ^_^ Q: 这边刚好有提到watchdog...想请问一下前辈这个东西在PC系统上是何时开始使用? 用途为何或是应用为何? 以前学校没看到过这个东西,不过我在嵌入式系统常看到一些应用,另外在南桥Spec有看到过,而BIOS端需要如何去应用以及设定它? 另外使用 watchdog 来处理过度超频不能开机是怎样的一个方式? 频率不对,CPU已经无法work,连BIOS code都不能执行了? 所以他是靠HW去处理吗? A:我曾用过关于watchdog timer 的经验是 => 在 config clockgen完后, 需要 system发 PCI reset ! 此时会需要 watchdog timer... 因为, write clockgen完后,有可能系统当掉 !!! (<-frequency settings被改变了...)因此,我知道的作法是: 在 write clockgen之前,先 enable watchdog timer ! (当然,一定会指明要"多少时 间后"才发 PCI reset ! ) 一 enable完,便匆匆去 write clockgen(当然,这段时间要够长,以免 write clockgen没完成,PCI reset就出来了 >_< ). 一旦 write clockgen完毕,code会写 "jmp $"...然后等 watchdog timer 时间到,然后PCI reset出来 reset system... 你所说当机时的 watchdog timer,我没做过 ! 不过,watchdog timer 不一定是要在 SB内啊!(或是即使做在 SB内,也是"独立的"...)做成外部的电路就不怕 chipset hang时 timer会失效了...^_^ 一般我知道的 watchdog timer control 大概有: - enable/disable ( => 开始记时...) - time to bomb (=>多少时间后爆炸 ?) - event routing ( => 时间到要干嘛 ?) [[WatchDog]] watchdog是个硬件机制. watchdog 在嵌入式应用中主要就是用来做系统自动回复用的.通常用在机器处理很critical 的任务, 不能当机超过一定时间的事务. 一般的用法是, 系统的软件要固定时间去重设timer. 例如: watchdog timer 设定10秒以后会重置系统, 那么系统软件可以每5秒有一个task 去重设timer. 万一系统当机了. 由于软件无法重设timer. timer 数完了以后就会发出reset , 让系统重新恢复状态. 在MB 中superI/O 有watchdog, clockgen 也有支援watchdog. 以超频来说, 往往设定完clock generator的瞬间, 系统可能会当机. 这时有两种状况. 1. 因为clock 变化造成, 这种状况只要一个PCI reset. 系统就可以继续执行. 这时BIOS 可以借用 watchdog来发PCI reset. 只要在定clock之前先设好watchdog timer, 然后在一段时间后关掉watchdog timer. 这样就可以解决这个问题. 一种是 clock 增加太多造成chip 死当. 这种就需要依靠 clock gen 里面的watch dog来让clock 回复成default value(Note:要视clock gen的设计, 有些只是发reset而已). 另外一种我知道的应用是双 BIOS的主板. 利用watchdog来切换BIOS. 一旦正确的频率供给给system后, BIOS便依据既定的POST table(类似行程表)来做事. 首先,与chipset最为相关的便是 [chipset config stage]. 意即,在此阶段BIOS必须对 chipset registers填入正确的值,俾使其正常运作. 一般而言,要config下列的 devices: - NB(还记得前面有提过北桥内部约可分 4 blocks; "有些" blocks 需要 在此 program...) - SB(即 PCI-ISA bridge) - ACPI registers - USB registers - SATA registers - PATA registers ... * 在此所谓的 registers指的是: PCI config registers(除了ACPI registers以外). PCI spec所定义的 PCI config registers 00~3Fh 为 PCI header part,这个范围的registers并不是此阶段的主要工作(当然还是会touch,只是不多),而是稍后BIOS PCI kernel的事情.此阶段将 focus on :offset 40h以后的 registers,因为,这些是 device specific的部分,是 chipset自己加function/feature之处 !!! * ACPI registers通常透过 IO 来存取 Ex. // assume ACPI Base is 800h,要 access ACPI Reg55h mov dx, 855h in al, dx ; <- al = ACPI Reg55h's value * 上述所列的 devices多为 PCI device,也都有唯一的PFA(PCI Function Address,即 bus#,device#,func#),也因此,只要对 device 下 PCI configuration read/write便可以 config device registers. Ex. 假设: set SATA register offset 52h bit3 = 1;SATA controller PFA is (0,4,3) => 简单的 assembly can be: mov eax, 80002750h mov dx, 0cf8h out dx, eax mov dx, 0cfeh in al, dx or al, 00001000b out dx, al 事实上每家BIOS都 maintain many "tables" 来说明: 哪一个 device 中的哪些 registers要填?值.相关的 access routine都已经写好. Programmer只需更改表里面的值即可 ^_^ *当有人要求改 register setting时,我们必须知道三件事: 1. why (为什么要改?) 2. what(改成何值?) 3. when(什么点改?) *对于 BIOS kernel与 OEM coding的人言,这部分会是较少碰触的,因为,这些code会由 chipset porting的人负责撰写及维护. 在此,想先提一下所谓的系统资源(system resources). 在计算机的世界里,所谓的系统资源约可分为四大类,亦即: DMA, Memory, IO, and Interrupts. (大家若是仔细检视一下 [我的计算机]->[内容]->[硬件]->[装置管理员]->[检视]->[资源(依类型)],便可以发现我想表达的) * DMA: => CPU可以说是系统的大脑;在没有DMA时,CPU几乎得参与所有的事情;但是有了DMA后,可以让 DMA controller或是bus-mastering devices自己来执行data transfer from and to memory,CPU只在开始及结束时参与;如此CPU可以做其它事情. 典型的计算机系统有八个 DMA channels. 检视 "资源(依类型)"中DMA的部分可以知道哪一个 channel被哪一个 device使用. * Interrupt: => 周边devices请求 cpu 服务的方式. 一般的计算机系统中有 16IRQs(IRQ0~15). 由两个 cascade的8259所提供. 当有device透过 IRQx发 interrupt时, CPU会被告知;然后,CPU最后会得到对应于该IRQx的 service routine的 entry point,之后便跳到该处去执行ISR(interrupt service routine). 现在的计算机系统有发展出APIC mode(有别于原有的8259 mode),其目的在于提供更多的 interrupt inputs以及专有的interrupt机制. 在检视 "资源(依类型)"中的interrupt可发现: IRQ 0/1/4/6/8/12/13/14/15其实是dedicated to specific devices使用的;而剩下的IRQs则是分给PCI devices共同/单独使用. 若是APIC mode,则可以看到超过15的IRQ ! * Memory: =>在此所谓的memory,并非指内存模块那种memory,而是: CPU memory addressing space ! 亦即,以32-bit CPU而言,可以寻址到的 memory space is 2^32 = 4GB. 这么大的空间就是一种资源 !因为,在此范围内,CPU可以完全存取,而且,也是有限的 !那,要如何利用这么大的资源 呢 ? 方法就是所谓的 "Mapping(映射)". 举FM为例,在收音机上一定有旋钮可以调,亦即, FM的波段是有范围的. 只有在此范围,才能收到讯号(<-这也是资源). 然后,在此范围内,要发射讯号的人,会先提出申请,看要使用那个频率,经过认可后便可以使用该频率波段了. 所以在此范围内便可以听到警广,中广,空中英语教室...等的广播. (记住: "每个人" 都可以使用该资源中的"一部份",只要"被核准"...) Memory space 也是一样 ! 在广大的 0~4G space中,也有很多人可以使用. Ex. 内存模块可以使用某一块,BIOS ROM也可以使用某一块, PCI devices也可以使用某一块,APIC也可以使用某一块,...etc. 常见的字眼 "Memory map" 就是阐述这样的观念 ! *I/O => 同理, IO 指的也是 CPU I/O addressing space. 也是一种资源. 现在 I/O addressing space 是 0000h~FFFFh,共64KB的范围. [Summary] 资源是有限的,要斟酌使用 ^_^ [补充memory部分] 假设系统插有1G内存,使用外部的显示卡,且使用512KB BIOS ROM,则: [Part1] -memory space 0~(1G-1)被此1G内存所占用;或说此1G内存被映像到memory space 0~(1G-1);只要CPU存取这个范围,就会存取到此1G内存. Ex. 在BIOS中写:(前提: in big-real mode) xor ax,ax mov es,ax mov esi, 00000000h mov al, BYTE PTR es:[esi] ; access 此1G内存中 位置0处的数据 ! [Part2] -memory space 1G~4G 则是由"其它人"所占用,例如:(below are examples ONLY) 1.memory space 0xD4100000~D410FFFF是由 Ethernet card的 operational registers 所占用 2.memory space 0xD4204000~D4204FFF是由 USB 1.1 host的 operational registers 所占用 3.memory space 0xD4206000~D4206FFF是由 USB 2.0 host的 operational registers 所占用 4.memory space 0xD4200000~D4203FFF是由 High Definition Audio的 Operational registers 所占用 5.memory space 0xFEC00000~FECFFFFF是被 IO APIC 所占用 6.memory space 0xFFF80000~FFFFFFFF是被 512KB BIOS ROM 所占用 ..... 只要CPU存取这范围,则会access到 "对应" 的device registers. Ex. 假设要access USB 1.1 HOST's operational register offset 0,则BIOS只要写: (前提: big-real mode) xor ax,ax mov es,ax mov esi, 0D4204000h add esi, 0 ; 0 means offset 0 mov al, DWORD PTR es:[esi] ; access [Q] 那问题来了:CPU发了一个memory cycle,谁来决定/如何决定要给谁(内存 or USB 1.1 HOST OP registers)呢? =>chipset一定知道系统插了1G内存,也会将此信息,1G( = 40000000h ),在内部register中.当cpu要存取内存而发 address: 00000000h 的cycle时,chipset会将 address与 1G比较;因为小于1G,则 "知道" 要发给内存 ! 当cpu要存取USB OP而发 address: 0D4204000h 的cycle时,chipset会将 address与 1G比较;因为大于1G,则 "知道" 要发给PCI devices, Ex. USB host ! * 1G这个 information 的有一个名词代表它: Top Memory ! 代表可用的内存的上限. [结论]: 4G memory space 充斥着各式各样的 "H/W registers"(假如把内存也视为 registers,ROM chip也视为registers.....) Q:问个问题一下古时候, VGA 的memory 是被mapping 到0xA000 的一个64KB 的area,如果你的VGA card 有1MB 的memory 就无法全部mapping, 需要banking 的动作.在big-real mode 中, 如果还是1MB 的memory 会是多大 ,它会比mapping 从哪到哪? A:就我所知,以前的VGA display会使用到 installed memory A0000h~BFFFFh间的范围;这是属于UMA(upper memory area)的一部份;其中A0000h~AFFFFh(64k) for VGA graphics mode memory;B0000h~B7FFFh for VGA mono text mode memory;B8000H~BFFFFh for VGA color text mode memory. *上述的 三块 memory 都是 video memory(or called frame buffer),用来储存要显示的image的内存 * 还记得组语练习中有 output color text to screen,其中所用到的 segment = B800h !!! ( for color text ) 当program存取到这块时,VGA card便会 read it and 负责将之显示到 monitor ! 现在的 VGA cards则是含有 built-in video memory;虽然不是使用系统内存,仍是被 mapped to A0000h~BFFFFh.(此时,很重要的一点是:系统内存的 A0000h~BFFFFh不再被VGA display用了....这点之后会提到,将被用来放 SMI code...) 你所说的1M memory,因为无法全部 mapped,所以有 bank switch来解决;那么我的感觉是:还是一样用 bank switch来解决 !!! 没有变... 因为,我所知道的 memory map中在1M以下只有 A0000h~BFFFFh for Video card用的(你从 资源(依类型)中去看,也可以发现这范围是给 display用的...) 而且,in big-real mode 也不会让 1M memory可以完全 mapped,这是没关系的 ! 这个其实跟系统chipset无关, 跟VGA chip比较有关. 如果VGA chip不支持 linear frame buffer, 我想你只有用banking的方法做. 如果有支持, 正确方式是要透过VBIOS. VBE 2.0以后有定义linear frame buffer的地址位置.你可以呼叫 return VBE mode infomation 这个 function call 来取得地址. 现在要提到的是BIOS POST中一个重要的 task : DRAM sizing ! 它主要的工作是:让我们所插的内存可以正常且稳定的运作 ! [Q] 为什么稳定的内存这么重要 ? => 因为,有太多东西需要存放其上了,例如: BIOS code(之后在 shadow部分会提到), 开机之后所需要的 device drivers and OS,etc...假如内存不稳,在存取 memory时无法得到需要的数据,或是根本连 read or write都不行,那么便会发现: 不是 system hang(maybe randomly) during POST ,或是进OS后 blue screen... 所以,"BIOS DRAM sizing不好" 是系统不稳的原因之一. (地基都不稳了,怎能奢求其上的房子可以坚固 ^_^ ) 在介绍 DRAM sizing之前,先稍微简单说明 DRAM 的相关知识.(若有不足或错误之处,请不吝指正...) 1. DRAM chip 可看做是 square array;基本的单位 is cell. 每一个 cell 是由数个晶体管组成(depends on cell width;记得是: 1 bit 由一个晶体管组成,可以记录 0 and 1的信息; 1 cell 可能含 n bits;读取DRAM cell属于破坏性的读取,因此读取的同时常伴随着 "refresh" <- 与 SRAM不同) 2. 要存取 DRAM chip 中的数据,必须提供 row and column address;这两个 address是有先后顺序的;意即: row address先送,然后再送 column address to chip. (呼应前面所言: square array,类似 x,y 寻址) 最后 指到的 data 将被放到 data bus上,CPU会读走 *若有空可以上网查: 为什么DRAM chip所需的 pins 是减半(half)的 ^_^ 3. DRAM controller 现在一般都做在 chipset 中,Ex. NB内(AMD K8 CPU则是将 memory controller做在CPU内 ,for better performance);其工作便是 interfacing DRAM chip;充作其它 devices(Ex. CPU,DMA controller...etc) 与 DRAM chip 之间的桥梁 ! Ex. In BIOS ,写下列的 code 欲 "read", "内存", "位置8处"的数据: xor ax, ax mov es, ax mov edi, 00000008h mov al, BYTE PTR es:[edi] [00000008h] 是 programmer所"知"的 linear address,但DRAM chip 只认得 MA0~MAx,BA0~BA1..etc讯号,如何沟通 ? => 靠 DRAM controller 来转换 !!! 4. DRAM access time => 从 DRAM chip 接到 address signals 直到 valid data 出现在 data bus上的时间(assume "read" memory),称之;也是DRAM chip的特性之一. 5. 现今常见的 DRAM is DDR/DDR2 SDRAM. 所谓的 "S"DRAM 指的是 Synchronous DRAM,即 DRAM operation 都是参考一个 clock执行的;即与它同步(synchronous). DDR 指得是 Double Data Rate,亦即在 clock 的 rising and falling edge都可以传数据. 而DDR2指的是: DDR的 "第二代" ! (别想成 DDR2 = DDR x 2 !!! 虽然刚好有些数值是两倍的关系...) Ex. DDR2 533(or called PC2 4200) => 1. "2" means DDR2 2. 533 is transfer rate( 每一秒可做 533笔资料 transfer ) 3. 4200 means: 533笔资料/s * 每笔 8 bytes( => 64 bit width) ~= 4200MB/s 下一章将介绍 DRAM sizing 的 flow/information ! DRAM Sizing 的程序与chipset design息息相关,不同家chipset其DRAM sizing sequence亦不同.在此只列出 rough sequence以供参考. (真正的 detailed sequence仍须以各家的 code为准) [假设]: A. memory controller integrated into NB => NB PCI config space有一部份与DRAM相关 B. This chipset support 4 DRAM sockets(max.) => 存在 4 registers,分别代表此 4-socket DRAMs' information => 存在 4 bits ,分别控制 4-socket's CS(chip select;enable DRAM用的) [程序] 1. Configure registers by DRAM frequency: => 许多DRAM相关的 registers(Ex. tRFC,tRP,tRCD,tWTR,CAS,...etc)都必须根据DRAM operating frequency来设定. (DRAM frequency 可由 CPU freq and CPU/DRAM ratio求得) 2. Execute Initial sequence for DDR(or DDR2) => DRAM spec都有列 initial sequence;既定的流程. 3. Set MAX-supported Size of this chipset for 4 sockets ! => 因为"不知道"插进来的DRAM到底多大,所以假设: 每一个 socket上都有插DRAM,且size 是->此 chipset所 support的最大 size(Ex. 2G) 4. Do the followings for Socket 0/1/2/3 sequentially (<-此时,一次 "只 enable 1 socket"来做事) 1) check DRAM exist or NOT => 藉由简单的 write-then-read pattern来判定 socket上是否有 installed DRAM 2) decide DRAM "TYPE" if DRAM exist => 假如DRAM有在socket上,则进一步去取得其 "TYPE" information 以DDR2 SDRAM为例,此步骤即:求取该内存的 (Bank,Row,Column,Side) information Ex. 2x12x9's DRAM 且 double side ,则内存大小为 128MB * 找DRAM information 有分 MA table & by SPD. 3) write this information to corresponding register 5. Configure registers by DRAM loading => 步骤4做完后,所有 installed DRAM已经找到. 此时,需要对一些与 "loading" 相关的DRAM registers做调整(因为: 不同数目的DRAM需要有不同的 driving strength !) 6. Remaining tasks: => disable one-page mode enable dynamic reset enable refresh cycle ( <- DRAM is ok to use ^_^ ) [注意事项] 1. 至此 Top memory( "可使用的内存上限" 已经...决定了 ^_^) 2. 在此 stage,并没有对 DRAM 做严密的测试. 测试阶段在后面的 tasks 3. 一般若 register config错误,或是 DRAM frequency不对(起因于clockgen config 错误),都会 hang在这个 stage ! 若系统侥幸 passed this stage并进到DOS,则可以再用 memory test utility来 verify DRAM is stable or NOT !!! [补充] 在此stage(Sizing)完成之前, DRAM is not ready to use. 故撰写此code时得全靠 CPU GPR(general purpose register)来传递参数 or return address ! 因此,得时时注意是否 register content 被改变 ( 因为 GPRs不多...) 但是,若是 activate CAR(Cache as Ram),则在此stage就可以使用 push/pop,所撰写的code将较为模块化及弹性,也不必担心 register content会被破坏了... Ex. AMD Kx sizing code便是很早便使用 cache 来当作RAM,因此可以写出 module code for sizing !!! [Why shadow BIOS ?] 在此之前所提的BIOS tasks,都是循着 CPU->NB->SB->SIO->ROM的路径来达成的;意即: CPU是去BIOS ROM里面抓code来执行 ! 明显的一件事是: ROM access time > DRAM access time ! 且RAM access width is 32bits,而 ROM access width 通常为 16 bits. 因此,便有了所谓" BIOS Shadowing"的观念产生 ! <- "performance consideration" !!! [What is shadowing] 意即: 将部分BIOS CODE(in ROM)拷贝至DRAM中 ! (此后, CPU将从DRAM中抓code来执行...)这样的动作便称做 "Shadowing" ! 而该处的DRAM即称为 shadow memory. Shadowing 在BIOS 中是极为复杂的 kernel code part ! 想深入了解的人最好有 source code可 trace. [When to shadow BIOS] => 当然是等内存稳定了,可以使用后,才做 ^_^ *因此,假如 DRAM sizing 有问题, BIOS shadowing必定有问题 !!! 以下是之前在其它文章中发表关于 shadow 的文章,再次节录以供参考 ! [System Behavior before & after shadow] 说的更白话一点就是 : 当 Power On后, 跑完 system power-on sequence后, CPU会被 reset ( reset 指的是 CPU 的 内容会回到 "初始值" ); 而 CPU内部的 EIP (32-bit )的初值是 FFFFFFF0h, 所以, CPU的 第一个 code read 就是到 FFFFFFF0h fetch code... 这个 memory cycle 从 CPU发出, 先会经过 North bridge ; 此时, north bridge会说 "这不是我的"...然后,往 south bridge 丢 ; south bridge 会说, "这是我的",收下后丢给 ROM ! 所以, FFFFFFF0h 会被 ROM 接走 !!! ( 所以 前人才说 "硬件初始值要把0xFFFFFFF0 和 0x000FFFF0 要mapping到同一个地方", 这个地方就是.....ROM !!! ) 之后, CPU所发的 cycle 都会照上述的方式一路抵达 ROM...由 CPU循着 fetch, decode, execute, store的顺序作事情... 但到某一个阶段前, BIOS的 code 会指示 " 要将 BIOS data 从 ROM 搬到 DRAM" ! 而在此阶段之后, BIOS会设定 north bridge 缓存器, 告诉 north bridge "之后 CPU所发的 cycle 不可以不收而传到 south bridge".... 自此之后, CPU 所发的 cycle 全部转到 DRAM 中,由 CPU循着 fetch, decode, execute, store的顺序作事情... [Summary] 总而言之, BIOS 一开始是CPU读取 ROM content来执行,之后是CPU 读取 DRAM content 执行 ^_^ [补充][以提问的方式^_^] [Q]: shadow memory到底是那一块 ? [A]: 以现在的计算机系统而言, shadow memory 是在UMA(upper memory area;传统内存 640K以上至1M之间) "里面"(part of it) ;在此UMA内可以分为 6 segments(64kB/each), total 384KB. 其中 C0000h~DFFFFh: for VGA BIOS and other devices' Option ROMs E0000h~FFFFFh: BIOS ROM code 这两个 blocks 本质是 memory;之后会被载以ROM content;因此,便称为 shadow memory(好像: ROM在上面, memory在下面,是ROM的 "shadow"...) [Q]: shadow memory 的内容 完全 "=" ROM content ? [A]: of course NOT ! 除了 UMA不大以外,BIOS ROM因为必须support more and more functions/features,size已经越长越大;除此之外,BIOS ROM中也有部分module是经过压缩的.(UMA不够放...) 当BIOS shadow时,只会 copy necessary code(Ex. run-time要用的...etc)至 shadow memory ! 另外,已经执行过后的code也不会被加载. 因此,不是 1-1的copy... [Q]: what Shadow enabled/disable mean in chipset ? [A]: 前面提过, CPU要 fetch的code由 shadow memory 提供 or ROM提供,其根本关键在于 chipset's behavior ! 意即,NB必须做此决定 ! 所以,这机制一般是由NB来实现的. NB内有所谓的 shadow registers. 当 shadow register enable时, memory cycle由 shadow memory 来回应;若 shadow disable,则由ROM回应. 意即: 000E0000h~000FFFFFh由 shadow memory replies if (shadow enabled) 000E0000h~000FFFFFh由 ROM chip replies if (shadow disabled) 若FFFE000h~FFFFFFFFh呢 ? 必定由ROM chip来回应(不然一开机怎么办?). 与 shadow disable/enable无关 !!! *若使用 ru.exe 并检视 memory space,可发现上述的情况. [Q]: shadow有何好处 ? [A]: 因为 slower ROM v.s faster RAM,所以放在RAM可以增加 system performance. *各位可以发现,同样的code放在 rom & dram中执行速度将大不相同 ! [Q]: shadow memory的 issue ? [A]: 被 shadowed 的 memory area都会被设成 write-protected ! 因此,这块area是不能 write 的.所以,若有程序会 "write"这块,则会有问题 !!! 其实, BIOS shadow这段code大家不太会碰触到...了解基本information即可. 有错误请指正 !!! [附注] [Q1] "BIOS的所有动作都必须先从ROM COPY至DRAM之后CPU才有办法去执行" Ans : 讲简单一点就是对CPU来说,他只负责提取指令,译码指令,执行指令。至于是读取到哪边的指令他就不管了(IA32 架构)。例如CPU要读取F0000h的指令来执行,那F0000h有可能是ROM也有能是DRAM。 [Q2] "那BIOS一开始的0E05BH是ROM的位置,还是DRAM的位置呢," ==>0~4G 是指地址线的地址(因为Address bus = 32 bits=2^32),至于地址线上面是分配给DRAM还是ROM使用还是Others...就要看实际的硬件架构,例如IA32 架构就有其分配的方式。 ==>所以某个地址线的地址可以被分配给ROM使用也可以分配给DRAM使用,还可以重迭一起使用,例如 F segment (000F_0000h)就是重迭使用,所谓的重迭就是就像是CPU 对F0000h存取的时候,他是存取到DRAM的数据还是ROM的数据 ? 答案就是看北桥....如果北桥在此时把这个地址是映对到ROM,那么CPU读取到的F0000h数据是ROM里面的,如果北桥是映对到DRAM那么CPU一样是读取F0000h但是会读取到DRAM内的数据。 ==> 所以0E05Bh 是地址线的地址。 ==> 另外BIOS一开始的地址是在FFFF_FFF0 不是在0E05Bh... ==> BIOS的程序代码会去改变北桥设定,让在不同阶段的执行期间去存取到DRAM/ROM的数据,我们称为shadow....例如从F0000h的 ROM读数据,写到F0000h 的DRAM中 ==> 这边说的都是IA32,其它架构要看Spec 说明。 这次要提的是: PCI ! [About PCI device] 1. 每一个PCI device都有其 unique PFA(PCI Function Address). PFA由 bus number,device number & function number所组成. Ex. USB device PFA is (0,6,0) <- USB is a PCI device and its bus/dev/function is 0/6/0 2. 有了PFA,就可以存取其 PCI configuration registers. Ex. write USB PCI register 43h bit1 = 1 => mov eax, 80003040h mov dx, 0cf8h out dx, eax mov dx, 0cffh in al, dx or al, 00000010b out dx, al * IO port 0cf8/0cfc 为 PCI config address port & data port,意即:将 address(80003040h)送到config port(0cf8h),然后从 data port(0cfch + 3)来存取 data(al) * 注意: 32-bit address(80003040h) 中 bit[1:0] = 00b(固定的),所以虽然存取的是 43h,但还是写成40h ! 而要存取到 43h,则从 0cfch+3来达成 (因为: 0cfch<-> 40h,0cfdh<->41h,0cfeh<->42h, 0cffh<->43h) 3. 基本的PCI device的 config registers可分成 2 parts: A. header region(offset 00h~3Fh) B. device specific region(40h~FFh) 在BIOS's PCI_SCAN stage中,会touch到 part A. Ex. command byte, BARs, Interrupt line, latency timer,...etc. 而Part B是制作 or design这个device的厂商所附加的 function/feature. 4. 每个PCI device都可以 request 之前所提的 4 resources: A. memory resource:透过 Base Address Register(BAR) B. IO resource:透过 Base Address Register(BAR) C. Interrupt: 透过 interrupt pin D. DMA: 这需要 device本身即具有 bus master function(status byte会indicate) [Why need PCI SCAN] 现在的computer system泰半由许多PCI devices所组成,因此,BIOS POST中另一个重要的 task is : PCI_SCAN !!! 它代表的是: BIOS会扫瞄 whole system,找出所有的PCI devices; initial them and build a linked list of PCI devices.在此list中的每一个node都代表一个PCI device,且含有其 characteristics ! Ex. Vendor ID,Device ID, PFA,Option ROM exist or NOT,...etc. 一旦建好此表,以后的 tasks 随时都可以参考 !!! 所以, after PCI_SCAN,有两件事完成了: 1. PCI device initialization;device config registers(Part A) are correctly set ... 2. One data structure is built to describe the PCI devices in whole system(建在memory中) 这也是属于kernel code part ^_^ ( system 一般很少 hang at this stage...) 符合PCI spec的device即称为........PCI device ^_^ [补充] PCIe device PCIe device => 符合PCIe spec的device(...废话...) 对软件而言,它仍是PCI device. 因此,基本的 header region and device specific region也有. 不过,PCIe新定义了 extended config space,即 offset 100h(含)以上,直到 FFFh( 所以, 最大可以至 4096 bytes ) 存取 PCI config space的方式,用原来 0cf8/0cfc的方式依然可行,但只能 access offset 00h~FFh. 要 access 100h(含)以上的 extended config space,则必须用 memory transaction的方式 ! Ex. mov ax, [50400000h] <- read device (4,0,0)'s register 0;2 bytes here 50000000h: PCIe extended base address. 可以从 chipset register得知 bit[27:20]: Bus information [19:15]: Device information [14:12]: Function information [11: 8]: Extended Register [7:2]: DW number [1:0]: Byte enable 因此,只要知道 PCIe extended base address,就可以像以前一样,可以任意存取 PCIe config registers, even > 0FFh ! 除此之外, PCIe device可以由其 Capability pointer(points to a linked list of capabilities)辨认出来. 因为,在众多的 capabilities中,会有一个 PCIe capability;其 ID value = 10h. Note: PCIe extended base address 要 reserve and report to OS. Size is 256MByte. 这是BIOS需要做的. (当然,BIOS也要将此 base address写入 chipset register,让 chipset 知道:有这样的 cycle时,是给PCIe device的 ! ) [补充] For P2P bridge P2P bridge = PCI-to-PCI bridge. 其存在可以 introduce 另一 new PCI bus,可以容纳更多的 PCI device. P2P bridge亦有其 PCI config space,但是 lauout 与 PCI device有点不同,大家可以参阅P2P spec并与PCI device's config space比较一下. 在 P2P config space中,我常遇到的 issue是和下列 register有关的: - Primary bus register: offset 18h - Secondary bus register: offset 19h - Subordinate bus register: offset 1Ah ---------------------------------------- Notes: 这三个 registers是BIOS在 PCI_SCAN时会决定的;所代表的意义是:这个 P2P bridge的上面 PCI bus number is ? 下面的PCI bus number is ? 及包含此 P2P bridge的 "branch" 最深的 PCI bus number is ? Ex. 18/19/1Ah of one P2P bridge is 0/2/3 => 此 P2P bridge 是 "bridge" PCI bus 0 and 2的(桥接在 PCI bus 0 and 2之间);而包含此P2P bridge的 PCI branch(想象成 tree structure) 最大(深)的PCI bus number is 3 ---------------------------------------- - memory base/limit - IO base/limit ---------------------------------------- Notes: 这两个是 BIOS 在 PCI_SCAN时所 assign的. 所代表的是: resource "window" for devices behind this bridge.意即:若P2P bridge下面(就上例言:是 Bus 2上)有 PCI devices,则他们的 BARs 必须被包含在此 window 之内 !!! ---------------------------------------- [Practice] [Q]假设有一个 P2P bridge ,下面有一PCI device;现在必须要去 accessPCI device's Device ID/Vendor ID(that is, PCI config read). 但是,问题是:做这事的"点"要在 PCI_SCAN之"前"....那要如何做到呢 ^_^ ? Ans:假如要在很早前(Ex. PCI SCAN之前)去 access P2P bridge后面的 device,照理是做不到的,因为: P2P bridge没有被正确的 configed... 在此例中,P2P bridge的 primary/secondary/subordinate bus要被 set,后面的device才能被 accessed到 ! 所以,假如要在 PCI SCAN前就 access,则BIOS必须手动去 set 此 3 bytes;然后,PCI config access才能被 forward to 其后的 PCI devices... [Q] 如何 disable memory or IO resource window ? Ans: 只要将 base设成比 limit "大" 即可 !!! --------------- - 相关讨论 Part1 - --------------- 前辈已经提到P2P Bridge我就直接问我的问题了 [Q1] Bridge 是用来扩充PCI Bus,在PCI Bus Spec与PCI-PCI Bridge Spec中定义,PCI Device是透过IDSEL来决定他的身分,其中PCI Bus Spec定义AD[31:11],而PCI Bridge Spec定义AD[31:16] 当做IDSEL,这中间差异为何? 为什么一个要从Bit 11开始当作是Dev 0 ,而另一个由Bit 16 才当作是 Dev 0 ? Ans: 1. IDSEL对PCI device而言是 input,是用来当作 device's "chip-select"讯号. 而且,IDSEL "如何连接" 是 H/W决定的,BIOS无法决定. 假如将板子上某个device's IDSEL "割断",则此 device将无法接受 PCI configuration read/write(以 ru.exe来说,就是按F6后,是看不到它的...) 那要如何决定 device's IDSEL ? 一般而言, board designer会将 "unused AD lines"拿来做 IDSEL,以连接至 PCI device. 在 configuration access时,所下的 Ex. "o cf8 80001020"(看起来是 I/O transaction)会被 host bridge转成 configuration transaction;此时, host bridge即可判断此 transaction 要 access的 device是否在该 PCI bus上;if YES 转成 Type 0 transaction;If NO 转成 Type 1 transaction,并往下发送...(host bridge只要 check latched "bus information"即可完成此判断 !) 以 Type 0言,AD bus上的 format as follows: bit[1:0] = 00 ( indicates "Type 0" ) bit[7:2] indicates register number bit[10:8] indicates function number 那 Bus number ? Device number ? => Bus number不必知道 ! 因为:Type 0产生即代表 bus number = 现在的 bus # => Device number呢 ? 因为,此时(Config transaction && address phase) AD bus bit[31:11] 没人用 !!! 因此, board designer会把此 21 bits拿来做 IDSEL用 ! 因此, AD bus bit11 <-> device 0 12 <-> device 1 ....... 当然,不可能 21 bits都拿来接 PCI devices;因为电路上的现实考虑... .................以上为:我所知为何从 bit11开始来当作 IDSEL................ 以 Type 1言,PCI-PCI bridge收到后,会将其 bus information与自己的 secondary bus number比较;若是 addressed device是在 secondary bus上,则将 Type 1 -> Type 0;若否,继续包成Type 1往下一层送... 在P2P spec v1.1 page 22 有一张表,说明 IDSEL generation(from primary address -> secondary address),其中有提到: if primary address bit[15:11] =0,则 secondary address AD [31:16] = 0000 0000 0000 0001;以此类推. 所以,我觉得为什么 for P2P bridge 其 IDSEL可由 bit[31:16] 来决定的原因在此 !!!(表的关系...) .................以上为:我推论为何从 bit16开始来当作 IDSEL................ [补充] PCI config index register里面的数据其实和硬件解出configuration cycle是相关的. 一.转换出来是type 0 cycle的话. 硬件只要做以下两件事. 1. mask 掉bus number(bit 16 ~ 31)以上的部份. 2.译码 device number的部份即可到对应的 AD bit. 所以其最低可以使用的就是AD11.也就是说一个bus上最多只能有 21个 devices(只是由于推动力问题, 往往是做不到的). Note:其实也可以设计成其它大于AD 11开始, 这要看chip设计者决定了. 二. 转换出来是type 1 cycle的话. 只要做 1. mask 掉reserved以上的部份(bit 24 ~31) 2. bit 0 = 1 由于P2P跟其它device不同的地方就是, 除了type 0 clcye以外, 还必须处理 type 1 cycle. 这也是分成两部份 一. type 1 -> type 0. 当 bus number 等于 secondary bus number 时候出现. 1. 解碼 device number 到对应的 AD. spec中有提到转换的表. dev 0 = AD16....etc 2. 把 bit 0 由1 变成 0 二. type 1-> type 1. 当 bus number 介于 secondary bus number和 subordinate bus number 1. 直接往下一层送即可.交给其它的P2P 处理. [Q2] 在IA32下,CONFIG_ADDRESS 会被转成Configuration Cycles,当Bus Number <>0 时,NB会转成Type 1 然后往 DMI送到SB,当P2P Bridge收到后,然后寻址到Slot上面的PCI Device,这样说法对吗? Ans: 总而言之, 是自己local bus上的,就会转成 Type 0,然后打在AD bus上,等待认领;若否就转成 Type 1,往下一个bridge送,继续寻找...对的人...for each bridge,都是一样... [补充] 对 PCI spec是, 如果以Intel PCI express架构来说. 那个已经被封装成 pci express的 package了.没有所谓的 type 0, type 1 cycle了. [Q3]PCI Device透过IDSEL来决定身分,那PCIE Device呢? 我查过数据,好像PCIE不需要IDSEL那他是如何决定Device Number ? Ans: 我所遇的 PCIe device也是由 AD bit[31:11]中找线拉至 device's IDSEL决定的.不知其它家 chipset是如何 implement. [补充] PCI express 是internal routing. PCI express是个跟PCI 完全不同的架构. 只是为了软件兼容性的关系, 把software架构做的跟PCI bus一样. PCI express是point-to-point架构, 一个link 只会连接一个device. 跟PCI 这种可以多个device在同一bus上是不一样的. 所以 device number对PCI express是完全不重要的. Note. AMD的Hyper transport 也是基于一样的心态来设计软件架构的. ※ PCIe 的device是 internal routing. 以规格来看,下一层的 device number都是为0. ------------------ - 相关讨论 Part 2 - ------------------ DMI指的是 Intel 南北桥中间的通道 ! 之前也是不知P2P bridge部份关于IDSEL的配置,查了表才知道原来有这样的 mapping(primary address<->secondary address). 其实,可以说 "unused AD bus 会被拿来当 IDSEL用"就是了吧 ^_^ [补充] 是的, 只要软件能够知道routing 关系.怎么接都可以. 只要bus controller控好实际的IDSEL即可. P2P之所以会有严格规定(两项, 1. IDSEL&device number表, 2. secondary bus IRQ routing)是因为P2P 不一定是在板子上. 包含卡都可以有P2P bridge. 在板子上的P2P 可以靠BIOS来建立正确的 routing, 但是插卡不行. 所以必须把这些定义好. 这样 PnP software(BIOS or OS)才能正确的完成IRQ 分配.让卡正常工作. 所以如果观察某些板厂. 就算是真的p2p 没有存在在板子上, 很多PCI slot的IRQ routing都是依据p2p spec里面的规定做(因为SB的PCI bus还是落在P2P之后). 在 PCI scan时,BIOS会扫描整个系统的PCI architecture(包含 device & bridge);其扫描方式由BIOS's PCI kernel来决定 ! [补充] 其实了解PCI spec. 要写PCI scan其实可以效率好又正确. 常见的新进工程师写法大概就是 3个 loop来处理. bus:0~255, device:0~31, function:0~7. 扫个 256*32*8次, 反正都是程序做, 结果往往也看来正确.这种写法其实是不对的. (其实,若是多了解硬件的架构,就可以写出有效率的code了 ! 这也是F/W工程师的价值...) Ex. Assume 系统架构是这样的: NB,P2Px3, PCIe bridge x2;其中: A. 3 P2Ps的配置 is: P2P0下面接P2P1;P2P下面接P2P2 B. PCIe x 2 & P2P0都在 bus 0;其PFA为 NB(0,0,0) P2P0(0,1,0) PCIE0(0,4,0) PCIE1(0,5,0) => 最后的 PCI achitecture is: Bus 0---------------------- NB(0,0,0),P2P0(0,1,0),PCIE0(0,5,0),PCIE1(0,6,0) *下面 Bus 1/2/3由 P2P0/1/2所 introduce: Bus 1---------------------- P2P1(1,0,0) Bus 2---------------------- P2P2(2,0,0) Bus 3---------------------- *下面 Bus 4由 PCIE0所 introduce: Bus 4---------------------- *下面 Bus 5由 PCIE1所 introduce: Bus 5---------------------- 所以,Bus number 是由BIOS's scanning "algorithm"所决定的;假如采用 depth-first,则会产 生上述的结果 ! 决定后的值会填到 bridge的 Primary/secondary/subordinate bus number registers ! [Q]顺便问个问题好了. 其实function number不应该是永远需要scan的, 为什么?什么时候才需要scan function number? Ans: 我想,对于 function number的问题,应该是: PCI header region offset 0Eh bit7代表: milti-function or NOT ! 因此,可以先 check此bit,再决定要不要往下扫了...这样又少做了许多虚工...^_^ Ex. PFA (0,3,0) 有回应(that is, Vendor ID/Device ID != 0xFFFFFFFF),则先check (0,3,0)'s PCI Reg0Eh bit7; if "1" then 此device为 multi-function device,还要再往下找 Ex. (0,3,1~7) 有无回应;if "0" then try next device number...! [补充,加快速的的方式] 检查multi function bit是正确的, 但是不只是因为效率问题. 而是PCI 规格中, single function装置可以不译码 config cycle type 0 bit[8~10], 也就是说 一个 single function装置, 会对 所有的function number响应, 也就是会出现 8 个相同的device. 顺便说一下我的scan加速法. 其实我不是使用 vandor ID & device ID来判断装置存在与否. 我是用 class/subclass/interfae ID来作判断. default 只scan bus 0, 遇到 P2P bridge才会把taget bus number+1, 如果遇到multi host(host bridge 数量> 1)的板子才会完整扫描 255个 bus. ^_^ --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- ~转贴自艾克索夫实验室~ Rootkit in PCI Option ROM 「Rootkit」一字来自 UNIX 界;但目前通常用于描述 Windows 木马程序作者所运用的隐形技术。 起初,Rootkit指的是一组程序,可让黑客躲过侦测。 为达成此目的,可执行的系统档案 (如 login、ps、ls、netstat 等) 或系统链接库 (libproc.a) 会遭到更换,或安装核心模块。 这两种动作只有一个相同目的;防止使用者收到正确信息,知道计算机上发生了什么事。 首先介绍PCI的基本常识, PCI Bus是在约1990年由Intel发展出来, 用来连接主机板上的各项装置的总线标准, 后来成为业界的标准之一, Spec可以在PCI-SIG注册会员之后下载, 架构上简单的说, 就是一个Host bridge, 在一般的PC上通常指的就是North Brdige, 这个brdige后面就是bus#0(当然也有Multi Host-Bridge的状况, 这边举例的是最单纯的情况), 然后接到South Bridge, South Bridge之后可能接的是ISA Bus, IDE Controller, USB, IDE, DMA Controller等等, 如果bus#0上还有别的PCI Bridge, 这个Bridge后面就是bus#1, 如果有多个Bridge存在(PCI最多可以有256个bus), bus#就不一定是固定的了, 一个PCI Bus上可以有32个device, 每个device可以有8个function, 每个function都有属于自己的256个register. 在PCI的规范里, 256个register中的前0×40个是公定的功能, 从0×40到0xff则由各家厂商自行实作, 存取这些register的方法, 一般的PC上是透过IO port 0xCF8~0xCFF, 如果是新的PCI-Express则是直接透过Memory Mapped IO, 以存取内存的方式直接进行存取, 例如我们想要读取一个在bus#0 dev#1 func#0的register#40~43, 透过IO的方式如下: mov eax, (0x01 << 31 ) // Type-1 PCI Configuration + (0x00 << 16 ) // Bus#0 + (0x01 << 11 ) // Device#1 + (0x00 << 8 ) // Function#0 + 0x40 // Register#40 mov dx, 0xCF8 // Index Port 0xCF8 ~ 0xCFB out dx, eax mov dx, 0xCFC // Data Port 0xCFC ~ 0xCFF in eax, dx // Get Data in EAX 如果是透过MMIO的方式则简单多了: mov esi, (MMIO_BASE) + (0x00 << 20) + (0x01 << 15) + (0x00 << 12) + 0x40 mov eax, [esi] 今天我们比较有兴趣的是位在0×30~0×33的register, 在PCI Spec定义中, 这里的值存放的就是expansion rom在physical memory中被decode到IO的地址, 比如说这个地址是0xFE000000, 如果你在0×30把bit0设为0×1(io->mem decode), Command Register(0×04~0×05)的Memory Space Bit打开, 在0xFE000000的地方你就可以找到这个rom, 开头是0×55AA(这当然也是规范之一, 用来辨视是否为一个PCI rom), BIOS在POST过程中, 会逐一扫描位于主机板上所有的PCI Device, 假如device上有rom, 就会把它给拷贝到memory中, 然后用jmp指令跳到ROM开头offset 0×02(别忘了开头offset 0×00是0×55AA)的地方开始执行PCI ROM, 执行完后ROM会再把控制权交回到BIOS手上, 一般而言, 在传统记体空间中, 0xC0000~0xCFFFF是给VGA ROM用的, 0xD0000~0xEFFFF则是留给一般的PCI ROM使用, 当然各种情况下还是会有些许差异, 例如有些BIOS会保留0xE0000~0xFFFFF给自己使用, 像是BIOS的interrupt service, DMI data….等等杂七杂八的东西, 执行完的ROM仍然会保留在内存中, 因为有些ROM会修改IVT(Interrupt Vector Table), 将某些interrupt service导向自己的code, 像是VGA ROM可能就会hook int 0×10, 这是很合理的, 因为int 0×10是BIOS所提供用来控制屏幕的service, 聪明的你看到这里应该就知道前面所提的那篇文章想说什么了, 如果有个”恶意”的程序被埋在PCI ROM里面, 只要一开机就会自动被执行, 它的运作并不是一时的, 它可以hook某个OS一定会用到的BIOS Interrupt Service, 然后在这个interrupt service被呼叫的时候动作就可以了, 而且麻烦的是即使你format你的HDD也没用, 除非你把有问题的PCI Device从你的主机板上移除, 嗯….听起来蛮炫的, 但是, 有可能吗? 要回答这个问题之前, 需要知道一些基本的常识, 在保护模式下, 因为IO动作受到限制的关系, 要存取IO并不像在DOS那样容易, 但如果想尝试Re-flash一颗PCI ROM, 势必得进行IO动作, 所幸在Windows下这并不是不可能的事, 有些人可能知道利用SeTcbPrivilege和使用ProcessUserModeIOPL structure呼叫undocumented Native API NtSetInformationProcess()就可以达成目的. 一旦攻击者有办法修改PCI ROM, 他就可以利用文章中所提到的例子: int 0×10(Windows在开机过程中会透过Ke386CallBios()呼叫int x010), 作他想作的任何事了. 可惜不论哪种攻击方式, 最终都是要对OS kernel动手脚, 利用各种侦测工具(如: Archon Scanner), 一定可以找到有问题的地方, 如果最后的箭头指向PCI ROM, 我们可以透过上文所述, 将存在PCI Device和memory中的ROM给dump出来, 需要dump两边的rom, 是因为PCI Spec规范中允许实际上所需要配置的内存不一定要等于原本rom的大小, 藉以节省保贵的内存(别忘了PCI ROM只能被配置到几个64KB的segment里而已), 然后向PCI Device的制造商索取正常版本的rom进行比对, 藉以得知是否为被修改的版本. 假如发现有不一样的地方, 接下来可以朝几个方向继续分析是否为有问题的ROM, 我们可以检查一下它是否修改了不必要的IVT, 像PXE ROM就不太可能hook int 0×10, 或是有保护模式相关的程序代码, 因为一般的ROM应该都是在real mode下执行, 所以应该不会切到protected mode, 如果有相关的程序代码那就非常可疑, 还有rom里面是否有可疑的字符串, 或是位在Windows Kernel地址空间里的32-bit address, 另外ROM里面也不太可能出现编码过的code, 如果rom里的code很难被disassemble, 或是充满了一堆obfuscated code, 那也是很有问题. 除了软件的方式, 最近兴起的新技术TPM也能克制这种攻击手法 一般而言,BIOS会在POST时 locate 3 devices: - Input device(Ex. Keyboard) - Output device(Ex. Display device) - IPL(Initial Program Load, Ex. HDD) 这次要提到的是 Display device,即 VGA ! 在PCI_SCAN之后,BIOS会在内存中建立一个data structure,代表整个系统的 PCI architecture. Ex. Ponter-> NB->P2P->SB->IDE->AUDIO->LAN->USB 2.0->USB 1.1->...->VGA->...->End 在VGA_init的阶段,BIOS会去 go-through this list,一个个的问:"有没有人需要shadow Option ROM的 ?" ------------------------------- *1 在此,先break,并说明一些观念: 1. Option ROM是 for H/W的 firmware;像BIOS一样是 for MB.有可能直接在硬件上 ,or 包在BIOS image中 2. 有Option ROM的 H/W可能有: VGA card,Lan card, RAID card,...etc 3. VGA's Option ROM 也就是 VBIOS ! 专门处理 screen I/O operation(主要是int10h) 4. VGA "shadow" 即代表: 将 VBIOS copy 到 shadow RAM, Ex. C0000h~C7FFFh处(32K) 5. VGA init这个阶段只 consider "VGA device" ! for 其它 device,之后再考虑其 shadow的事宜 ------------------------------- (承接前面的 flow):此时,VGA device会举手说:"我要" !此时,BIOS会去寻找VGA device's Option ROM(即VBIOS)在哪里;此时,VBIOS有可能在card上 or "当初" 被包在 BIOS image中(*2) 一但找到,则会先 作一些 checks:Ex. - Option ROM signature is 0xAA55 ? - 比较 Option ROM内的 Vendor ID/Device ID = H/W's IDs ? - class code and sub-class code correct ? - length = 0 ? ...etc... 若都符合,则视它为 VGA Option ROM(VBIOS) ! 之后,利用 memory2memory copy将之 copy到 shadow memory,从 C0000h处开始存放... 复制完后,再 check "checksum"是否正确;if yes then jump to "entry of initialization code",控制权自此转移至 VGA Option ROM,由它去做 initialize VGA的工作 ! ( 若是CRT屏幕,user会听到ㄉ一ㄤ的一声 ! 即代表 initialize VGA成功 !!! ) <- 此为 VGA_init的工作 !!! *2 说"当初"的原因是: VGA BIOS若包在BIOS image中,在 BIOS shadow时,也会被一并 copy到内存的某处放着;当然,会记住存放处 ! [Note] 一般遇到 VGA init fail的issue时,可以先 check:是否 VGA BIOS已被 copy 至 C0000h处;若有,则check是否已经 jump to VBIOS or NOT;若否,则可以往前 check是否前面所列的一些 "关卡"没过 (Ex. ID不 match, or checksum 不相等...etc ) VGA 若 ok,计算机就是彩色的 ^_^ --------------------------- - 相关讨论 ----------------- --------------------------- 通常都是板子一来就会去开始Debug VGA... VBIOS 若坏,屏幕是黑ㄟ VBIOS若好,屏幕是彩色ㄟ 没屏幕的情况下要继续Porting BIOS就比较麻烦一点 [Q]Option ROM是 for H/W的 firmware;像BIOS一样是 for MB.有可能直接在硬件上 ,or 包在BIOS image中。前者我叫它SW ROM,后者叫legacy ROM,您已经提到sw rom的load方式,那么legacy rom load方式是否应该有所不同呢,一但找到OpROM,则BIOS 会先作一些 checks: Ex. - Option ROM signature is 0xAA55 ? - 比较 Option ROM内的 Vendor ID/Device ID = H/W's IDs ? - class code and sub-class code correct ? - length = 0 ? ...etc... 两种rom都是通过这种方式吗, Ans: 我所说的都是 rough flow,而这两种ROM的"处理方式"不同,但"检查的机制"大同小异...建议去trace BIOS code比较清楚 [补充1] 1.可以查看PCI ROM Spec... 里面有详细说明如何Load OpROM 的方式,而检查项目就各家BIOS不同... 2.可以用HEX编辑器直接开启ROM File,例如VBIOS.bin or OpROM.dat ...etc 来查看内容(Binary file),例如某VBIOS.DAT 的内容如下: 00000 55 AA 80 E9 4B .... 00010 30 30 00 22 E9 19 21 5F 40 00 ....................................... 00040 50 43 49 52 86 80 42 2A .............. 其中: a)55AA是这个ROM的Signature <--代表他是符合规范的ROM b)80 这个ROM的Code size <--需查阅Spec确定一下 c) 接着是EntryPoint Address <--实际上会执行的程序代码进入点的地址,所以一般都是讲 Jmp OpRomBaseAddr+3 <-- 你如果trace BIOS 程序代码,这就是 +3 的由来 d) 000018h=40 代表另一个PCI Header在Offset 00040h的地方 所以 50 43 49 52 是Signature,如果用ACSII 来看就是"PCIR" 其它更多信息可以查看PCI ROM Spec说明..... e) "PCIR"后面紧跟着这个OpRom的VID与DID ...即8086 2A42 <--Intel=8086 3.如果想要改OpRom里面的Code,可以使用反组译工具去修改或是用Debug去修改 如果比较简单的OpROM要做实验的话我都用Debug.com 把OpROM 加载到Mem,接着利用T /P 指令单步执行去追踪与修改,修改好之后再查看机器码,再利用Hex编辑器 or 反组译工具写回去OpROM (找Bug时可以尝试这样写啦,不过违反智慧财产权,最好还是叫Vendor帮你改,而且光看懂OpROm的流程就需要一点时间了 ^^!) 如果要用汇编语言写一个Dummy OpRom的做法就像下面范例去仿真一个OpROM... 至于你BIOS端可不可以run 就要看你的检查机制严谨程度或是你自己修改你的BIOS code来达到模拟的目的 : .586p .code YourCodeStart: ORG 0 db 55h, 0AAh TotalCodeSize db (offset YourCodeEnd) - (offset YourCodeStart) ORG 3 jmp entrypoint entrypoint: ........ YourCodeEnd: END 组译完之后可以利用微软工具EXE2BIN.EXE 把他转成xxx.bin (binary file)然后你就可以包进去BIOS测试。 [补充2] 当VGA init时,那时VGA BIOS的放置处可能有: case 1: 在 memory中(当初在 shadow stage时被 copy 到 memory) case 2: 在 card上(Ex. 一般的 external VGA card上都有一颗小rom) 因此,这两种case的处理方式便不同. Ex. In case 2 若VGA card在 bridge后面,则还需要 config 该 bridge's resource window 使Option(in card)可以被正确的 accessed...<- 所以处理方式有所不同 ! 至于检查机制;因为Option ROM不管放哪里,其 content都是一样 ! 因此检查机制大同小异...还有,不同家BIOS的 "checks" 也未必完全相同 !!! 除了之前所提的 tasks外,还有下列 main tasks是 BIOS POST会执行的: [USB init] => initialize USB的部份.这方面的code几乎是 kernel code,再加上少许的 chipset code(因为,chipset's USB controller是哪一种需要 customize, Ex. OHCI or UHCI...etc). 主要在 implement USB spec的部份(USB 1.1/2.0 and USB legacy). (天书也...没看过...) [KB init] => init KBC的部份 [HDD init] => 这是 locate IPL(Initial Program Load)的code.因为最终系统需要 load OS,而OS是存在 storage device中,因此需要让storage....动起来 ! 主要的工作有: - 设定 chipset端的 storage controller(PATA or SATA)'s settings - identify HDD - config HDD by set-feature(<-设定 device端的 settings) 这样一来,controller端与 device端有了 "相同的认知" 后,就可以 access HDD了 ! [ACPI] => 主要是将所有的 ACPI tables建至 memory中;让ACPI OS可以 parse & config. [Boot-to-OS] => 最后 BIOS's 工作是: invoke int19h(for Boot-strap) !此中断服务程序会尝试去找 boot device,并从中(storage)将 boot-loader 载入至 memory中;然后跳到 boot loader处,开始执行加载OS的工作 ! * 一但进入OS后,与BIOS会有关的....几乎只剩 ACPI 了 ! BIOS不是鸡肋 ^_^
/
本文档为【我所知道的BIOS】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索