[FZH] 谢谢 coreboot, 我懂得了内存是如何被 BIOS 识别的

microcai microcai在fedoraproject.org
星期日 五月 8 17:50:07 UTC 2011


> 
> 首先必须明确的一点是, BIOS 运行初期,CPU 其实是不能访问内存的。
> 
> BIOS 所在的 FLASH 是那种可以被 CPU 直接寻址的 FLASH 芯片。被都固定在
> 0x4FFFF (记不清具体地址了) 地址上了。类似 ARM 使用的 NOR FLASH。 uboot
> 就在 NOR FLASH上。
> 
> 然后,BIOS 初始化代码开始通过寄存器和北桥芯片沟通。
> 因为 BIOS 就是版卡厂商制作的,这不成问题。使用固化的 IO 地址就可以了。
> 
> 成功和北桥联系上后, BIOS 继续前进,利用北桥提供的寄存器操控SMBUS, SMBUS
> 是一种 I2C 总线,每个 SMBUS 设备都有一个固定的地址。SDRAM 的 EEPROM 就可
> 以通过 SMBUS 访问! 而 SDRAM 通常在 0x50 ~ 0x53 这4个地址上,对于主板上
> 的4个内存插槽。不过,主板厂商也可以改变这些地址。反正 BIOS 是自己出的,
> 可以固化这些地址,无所谓。
> 
> 读取 SDRAM eeprom 里超过 17 个参数后。 BIOS 就可以使用这些参数设置好北桥
> 的寄存器了。而在这之前, BIOS 严重依赖  CPU 的寄存器做这些操作,不能使用
> 任何内存! 北桥用来控制内存的寄存器地址,又是一个每个版卡都不一样的地方
> 了。无所谓, BIOS 自己出,爱怎么用就怎么用。
> 
> 搞定内存之后, BIOS 终于可以使用内存啦! BIOS 将内存的前 4k 作为临时
> stack 开始进入了第二步初始化,这个使用有了内存,就可以使用函数了。
> 前面,因为无法使用内存,无法进行复杂的运算,要小心编写汇编指令,全部使用
> 寄存器进行操作,所以没法进行复杂的运算。现在有 RAM 可以用了,自然就有内
> 存了。
> 
> BIOS 通过检查可用的内存值,将自己使用的临时 stack 移步到 >  640K 的地
> 方。 开始继续下面的工作。
> 
> 下面, BIOS 该开始检测 CPU 了。主要的工作是比较 CPU 的微代码版本是否和
> BIOS 里带的对应CPU的代码一致。否则更新 CPU 的微代码。所以刷新 BIOS 支持
> 新 CPU 的道理就在这里! ;)
> 
> 
> 再然后?那要看你是不是打开了 BIOS shadow 就会选择是不是做这一步了。
> 注意,这个时候 BIOS 是在一片能被 CPU 直接寻址的 FLASH 里运行的。但是
> FLASH毕竟比 SDRAM 慢.
> 所以, BIOS 会通过北桥重新映射 BIOS FLASH 的地址到内存空间的顶端,原有的
> 映射没有断开!这个时候由于 A20 gate 没有打开,高 12 位被忽略,导致 CPU
> 寻址仍然在 640k ~ 1M,也就是 BIOS 现在在的地址,所以 BIOS 继续运行。
> 这个时候 BIOS 切换到 32 位寻址,注意,是 32位寻址,但是还是 16 位 模式。
> 想知道详细情况的,可以自己网上 google . 因为先前已经映射好了 BIOS 到高位
> 内存,所以 BIOS 继续运行。 然后 BIOS 将原先自己所在的  6040k~1M 地址区间
> 通过操作北桥,断开映射!是的,没错,断开了! 这个时候,这个区间其实就是
> RAM 而不再是 BIOS ROM 了,这个很重要!接着打开 A20。
> 接下来就是很平常的 memcpy 了,将自己从高位内存拷贝回  640k ~1M 区间的地
> 位内存。 然后关闭 A20. 关闭 A20 后, CPU 寻址重新回到低位内存。 BIOS 完
> 成了将自己拷贝到同一个地址的工作. 但是 BIOS 将运行在 SDRAM 中,而不是
> FLASH 里。
> 
> 然后干嘛呢? 自然是继续检测基本硬件啦。基本硬件一般都已经固定使用某个 IO
> 端口了。 BIOS 就是发送一个无害的请求看是否有返回就可以知道硬件在不在。
> 
> 
> 对于显卡和网卡这类设备, BIOS 并不包括这些设备的初始化代码, BIOS 通过调
> 用这些设备的 BIOS 来实现。
> 
> 对于任何找到的 PCI 设备,BIOS 都是直接调用对应 BIOS 设备的 BIOS 来初始化
> 它的 。 这也是硬盘还原卡截获 init 13 中断的道理。
> 
> 而这些设备的 BIOS,自然初始化工作就是配置设备的寄存器地址了。
> 
> BIOS 搞定的 PCI 设备,会形成一个表格,叫 PCI CONFIG ,保存到 PCI 控制器
> 里 。可以通过 IO 端口 0xCFC-0xCFF 访问。
> 
> 对于集成设备,这些设备的 BIOS 其实都被包含在 system BIOS 里,但是逻辑上
> 并不是一个整体。如果用一些 BIOS 工具,还是可以分离各个设备的 BIOS 的。
> 
> 没用  BIOS 将设备配置好,并写入 PCI config , Linux 内核就会当这个设备不
> 存在 ... 囧。
> 
> 
> 还有,各个 PCI 设备除了几个基本寄存器,别的都是通过 MMIO 映射到内存地址
> 里进行的,而不是使用 IO 端口地址。BIOS 要负责分配好,使他们不会重叠。
> 
> PCI 设备的地址从 0xFFFFFFFF- sizeof (BIOS) 开始向下分配,SDRAM 的地址从
> 0x00000000 开始向上分配。这些都是通过操作北桥的寄存器实现的。
> 
> 自然,他们会在中间形成一个洞。不过,那是在你 SDRAM 内存比较少的情况下 .....
> 
> 如果你的 SDRAM 内存比较多,恭喜你,你又遇到问题了,你的内存将被吞掉一部
> 分 .... 被 PCI 设备覆盖掉了一部分高位内存... 对 CPU 而言,整个内存地址都
> 充满了设备咯,没有空洞。
> 
> 其实 Linux 认为的  640k~1MB 空洞也是不存在的。如果后续不使用 BIOS , 可
> 以放心的当 SDRAM 来用,因为就是 SDRAM . 自然,如果你没有开启 BIOS shadow
> 就另当别论了。
> 
> 我之所以接触 Linux , 也是我本来计划自己写系统,我很讨厌  640K~1M 的内存
> 空洞,想知道怎么解决,就去看别的 OS 是怎么实现的,结果就发现了 Linux ,
> 然后开始看 ....
> 
> 不过后来比较囧的是, Linux 确实没有利用这个区间的 RAM ... 真 TMD 有点浪
> 费啊! 现代的 BIOS 都默认 shadow 了,甚至没有地方给你配置了。 如果 Linux
> 不使用 BIOS , 不知道留这个洞在这里干嘛. 诶。
> 其实我 google 了  lkml , 是有人这么提出过这个问题。不过那个 Grek H 什么
> 的,就是貌似的Linux二号or三号人物,回的邮件里说,虽然多数系统可以回收这
> 个空洞,不过在个别系统上报告问题了。所以就默认不回收了。
> 如果你要回收,这里有 patch ... use at your own risk ....
> 
> 呵呵。
> 
> 扯远了。洗洗睡吧。明天估计开机会看到一堆回复了。
> 
> 
> 

给点反应吧大哥? 我找了4年才找到的答案啊!


关于邮件列表 Chinese 的更多信息