一个程序是如何开始运行的呢?这个问题,一千个人有一千种回答。电脑用户说:“双击程序图标就行了啊。”;初级程序员信心满满的回答:“是从main函数开始执行的。”;高级程序员也许会和你聊到c运行时库,那里才是程序编译运行的第一条指令;而熟悉操作系统的专家却并不知道如何说起,程序加载器、重定位、堆和栈的建立、进程和线程的创建等等细节闪过脑海,哪里才是真正的源头呢?

同样问道计算机是如何启动的,也许答案就是按下电源键而已。但在那个简单到极致的动作后面却隐藏了复杂的机理。启动的开始并不仅仅是操作系统引导,亦或BIOS运行,甚至CPU在reset vector执行第一条指令之前,很多事情已经发生了。正如地球生命的发端并不由人类的到来而伊始,秘密隐藏在远古而不为人知的远古时代。让我们顺着时间回溯,站在一切发生的起点:“电源键按下”,通过时间的流转,梳理其中所有的硬件软件过程,来深入了解计算机的工作原理。

史前时代:上电时序

上电时序,也叫做Power-up Sequence,是指电源时序关系。它牵扯到诸多计算机部件,在正式开始时间之旅之前,我们来介绍一下所有参与的小伙伴们。

电源

ATX电源提供+12V、-12V、+5V、-5V、+3V和+5VSB等六种电压。也就是我们图上的两个白色的电源接入口。主板其他的不同电压是主板上的变压线路转换过来的,他们包括+3VSB、+1.5VSB、1.8VDual、2.5VDual、3VDual、VCore、VTDDR等等很多。

+12V主要是给CPU内核供电,它可以单独给PCIe设备供电,包括显卡等等。+5V应用最广,给USB等等外设供电。+5VSB等各种带SB的电压,是提供Stand By的供电,即在S3 Sleep时提供电力,保障唤醒和刷新。

主板右边中间那个纽扣电池,它叫做RTC电源,永不掉电。除非电池没电并且没接任何外部电源。 RTC用以保持机器内部时钟的运转和保证CMOS配置信息在断电的情况下不丢失。

时钟

电脑中的CPU,AGP、PCI插槽、SATA、USB端口和PS/2端口等在通信速度上有很大差异,所以需要提供不同的时钟频率。由ck410、ck505和iCLK等芯片将原先散布在不同地方的晶振和分频电路整合在一起,为CPU、SATA、PCI、USB等等设备提供基础频率。

电源时序控制芯片/电路

主板对于上电的要求是很严格的,各种上电的必备 条件都要有着先后的顺序,一项条件满足后才可以转到下一步,如果其中的某一个环节出现了故障,则整个上电过程不能继续下去。谁来控制和协调整个时序过程呢?不同的主板、芯片组、代际之间都有不同的方案,在笔记本上过去经常采用EC的方案、台式机则很多用SIO或者定制芯片,服务器上多用CPLD等等。现在很多电源时序控制被整合进了ME中,在面向嵌入式设备的Atom系列主板上则越来越多的引入了在手机等设备上常用的PMIC。

时间开始

我们通过一个古老的例子来了解一下开机的整个过程:

  1. 在G3(未接电源)情况下,RTC电源提供RTC_RST#和VCC_RTC电源给南桥。
  2. 插入电源或者电池。系统进入G2,S5的状态。EC检查电源的可靠性,并发送PM_RSMRST#通知南桥各种SB电压已经准备完毕。南桥复位,部分功能SB功能激活,进入待机状态。
  3. 用户按下电源键,时间开始。
  4. EC收到PWRSW#信号,通过PM_PWRBTN#通知南桥。南桥收到PM_PWRBTN#信号后依次拉高SLP_S5#,SLP_S4#,SLP_S3#信号给EC。
  5. EC发出PCON#给ATX电源。
  6. ATX电源接到低电平的PSON#信号后,开始工作,发出各路基本电压给主板上的各个元件。
  7. 基本电压变换的其他电压也被转换出来。
  8. 电源发出PWROK#给EC,EC转交给南桥和北桥(有的话)
  9. VRM和CPU通讯,根据VID送出Vcore
  10. VRM发生VRMPWRGD#给南桥,表示核心电压OK。
  11. 南桥发送PLT_RST#给北桥。
  12. 南桥发送PWRGOOD#给CPU。
  13. 北桥在收到PLT_RST#信号后,1秒钟后发生CPU_RST#,让CPU复位

时序图如下:

青铜时代:神秘消失的时间

在CPU复位后,是不是要立刻跳到reset vector开始执行BIOS程序了呢?还没有,pcode、on die rom会在这个阶段执行,TXT、boot guard等安全保障措施也在这里运行。

城邦时代:UEFI的四个阶段

CPU终于开始执行reset vector的代码了,这就进入了我们熟悉的UEFI的世界。我们之前已经有很多文章都有介绍UEFI的各个阶段,这里简单回顾一下:

• 在SEC阶段,系统从复位开始运行(由主机引导处理器取回的第一指令),通过初始化处理器高速缓存(Cache)来作为临时内存使用,我们有了堆栈,从而可以执行c程序,然后转到PEI阶段。

• 在PEI最开始阶段,仅少量栈和堆可用,我们需要找到并使能足够我们使用的永久内存,通常是内存颗粒或内存条(DIMM),然后转入DXE。

• DXE阶段有了永久存储空间,真正开始负责初始化核心芯片,然后转换到BDS阶段。

• 核心芯片初始化完成后BDS阶段开始,并继续初始化引导操作系统(输入,输出和存储设备)所需的硬件。 纵观PI的整个阶段,BDS对应的是“执行UEFI驱动程序模型”来引导OS这一过程。

UEFI引导阶段步骤和驱动程序众多,经过多年发展,核心代码已经超过一百万行,俨然已经是个独立的小王国了。要理解UEFI,必须理解UEFI的目的:初始化硬件,安全启动操作系统,并为操作系统提供统一的硬件抽象。所有纷繁复杂的驱动和表象后面,都在为了这一目的服务。只要抓住这条主线,再遇到其他的知识点也就会豁然开朗了。

近代和现代:引导程序和操作系统

UEFI会在BDS阶段后加载操作系统引导程序,也就是OS loader。不同的OS有不同的Loader。一般用户都十分熟悉,我们这里不再赘述。

另外传统BIOS和BIOS引导方式已经被淘汰。Intel也宣布对传统BIOS兼容模式(CSM)在2020后不再支持(参考资料1)。网上诸多Int13、引导扇区等内容,除非对历史有兴趣,全部可以一笑而过了。

结论

按下电源键,CPU并不是第一个得到通知并立刻执行代码的。简单的开机后面隐藏了如此丰富的内容,这是很多人想象不到的。很多主板,尤其是很多服务器主板,从按下电源键到CPU开始执行UEFI固件程序,期间经历了很多隐藏的片段。这些片段可长可短,有的转瞬即逝、有的却让人等上片刻。它们究竟是什么,为什么存在,值得大家细细探究。

 

转载自:https://zhuanlan.zhihu.com/p/31180815

 

 

 

版权声明:本文为wangwust原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wangwust/p/8596727.html