【UEFI】--- 探究BIOS NvRam空间的位置以及大小

按照国际惯例--先上问题:
1. 什么是NvRam空间,里面存储了什么数据
2. 如何找到NvRam空间在BIOS-bin文件中的位置

NvRam空间的学名为: Non-Volatile Ram即非易失性存储空间,简单来说就是一段掉电也不丢失数据的存储空间。这类存储介质有很多,像多数的E2prom,Rom都是可以作为该类空间的介质。而具体到BIOS的话,多数情况下可以理解为在BIOS-Rom中挖了一段空间,用来作为我们希望掉电也不丢失数据的存储空间。

问题1:NvRam空间都存储了什么数据?
NvRam在BIOS实际用途中其实分为几类,其中最常用的应该是就是BiosSetup配置界面下你能看到的一大堆配置接口了吧。BIOS-Setup下所有的数据变量最终在代码中呈现的样子应该是这样:

 当然其实还有很多,没有完全显示出来,而通过最后的SYSTEM_CONFIGURATION这个结构体变量名应该也可以看到,所有的变量最终都被封装进了一个很大的结构体变量中。最终这个结构体变量会被存在NvRam空间中,用户每次在BIOS Setup界面下的操作其实最终都是修改这个变量并且最后保存在Rom中NvRam那段空间中。

 

问题2:NvRam空间在BIOS-Bin文件的哪个位置?

提出这个原因的目的是因为有一个需求是要求BMC在更新BIOS时要做到保存用户设置数据,那么方案就是BMC在更新BIOS的数据时,先从BIOS中把NvRam那段空间的数据读出来做备份,然后刷掉整个ROM空间中的数据,再把新版本得BIOS数据写入ROM存储介质中,最后再把预先备份的数据按照BIOS Layout布局写入指定的位置即可。基于这样的一个目的,因此BIOS需要提供NvRam空间的布局。也算是折腾了一段时间吧,大致的方式如下:

1)在layout布局文件中找到整个工程文件的整体布局,一般是在*.fdf文件中,例如我用的insyde的工程可以看到project.fdf文件可以看到每个区域的Size和Offset公式计算定义。标红框的时NVRam区域的SIZE,下面也有每个具体的NvRam区域的Offset计算,没截出来。根据这里的定义应该能最终可以计算出来。

 

扩展问题思考与分析:

问题3:如何快速计算频移地址?

在计算这一大堆数据的时候,请一定使用python/shell脚本,不然手算累死了,学会运用的你计算机技能,学习是为了用,学软件就是为了让事情变得更简单。

 

问题4:为何查阅最终的16M的Bin文件找不到期望的数据?

根据我最终计算出来的值为0x5b0000,我在编译出来的16M的BIOS-Bin文件找不到理想的值,全是0xff。

原因:由于当前的BIOS是已经将ME和最原始的BIOS-bin文件打包进一起后的文件,因此这里的0x005b0000实际根本就不是我们原始BIOS的数据。原始BIOS的文档应该是*.fd文件,按照我的工程可找到GRANGEVILLE.fd也就是GrangeVille这个平台的BIOS文件,通过二进制文档可查看结果如下图:GRANGEVILLE.fd这个BIOS源文件的大小是8M,这个文件无论大小,还是layout都是由是源码中*.fdf文件指定的,具体可查阅该文件。

 

 

问题5:为何在GRANGEVILLE.fd找到了目标数据,但实际数据的数量却少的可怜?

这个地方不得不牵扯到BIOS的代码执行,虽然BIOS已经定义了大量的NvRam的Variable数据来进行数据保存,但是这是第一次编译的结果,实际的数据应该是BIOS代码在执行时,读取后再写入到这个位置的。而且由于Variable实际存储是以Variable的方式来Get或者Set,所以甚至可能出现同一个ROM不做任何改动过,就在机器上做两次启动,然后用烧录器把BIOS-Bin文件读取出来,NvRam空间的数据都是不一样的。详细原因就要跟BIOS通过GUID来Get或者Set变量这种方式有关,有时间再把这个给普及下。

 

问题6:包过ME的Bin文件如何确定Offset,以及ME是按照什么规则来进行打包的?

刚已说过,实际BIOS的程序编译出来的文档大小是8M,但是我们通过ME工具打包后,通常可以将BIOS扩展到16M或者32M,那么是如何扩展的呢?我以16M的BIOS.bin构成介绍,如下图:32M的话,中间OXFF填充部分随之扩大。

 

问题7:借助工具进行分析

我也是后来才知道可以用工具直接分析BIOS最终Bin的构成,以此来确定。不过总归是要知道原理理解的才深刻,下面简单介绍下工具,来和我们上述分析过程进行验证.使用工具为UEFITool.exe工具

 

 

如上图,我们可以在该工具下,BIOS-Region中NVRam空间的类型,以及详细信息。Offset为0x5b0000,Full Size为0x30000。刚开始判断NvRam空间是,我以为仅有下面标红的一个,所以对比了半天bin文件数据,总是对不上。后来才意识到下图四个都是NvRam的布局,只是用途不同,下面四个数据的Size相加可得也是0x30000,和工具刚好对上。

 

问题8:就NvRam区域如何在BIOS升级时实现数据保留得功能

 通常情况下,用户在BIOS下得设置在版本更新时一般是需要保存的,而且还有个更重要的原因,在BIOS进行操作系统的枚举时对于新安装的未知操作系统,其引导文件的路径是在Nv区域中的Variable保存的,因此版本升级时,保留Nv区域的数据更为重要。

这里提供了一种由BMC系统更新BIOS固件时,保留数据的方案。

首先BIOS的Flash对CPU和BMC均可见,更新固件的动作由BMC完成,BMC系统擦除整个BIOS的Flash,然后将最新的镜像烧录写入的整个flash中。这其中为了实现BIOS的数据保存,Nv区域一定要提前备份,在写入新得镜像后,再将备份的数据写入到该段区域中。方案还是挺简单的。过程中遇到几个难点问题:

  1)  对于Nv区域的起始地址和Size确定,前文已经给出介绍

  2)笔者最开始为了省时省力,直接手动在BIOS的Bin文做了Nv区域的数据替换,但是始终不能成功,从code来看,应该是替换后的区域CRC校验不过,导致第一次启动BIOS又将Nv区域的数据作了恢复。但是这个动作交由BMC完成的时候,就不会遇到这个问题,也不知道什么原因。

至此,将此次分析中所遇到的所有问题,均分析完毕。如有错误之处,欢迎随时联系我指出。

也请随时关注我的公众号:像蚊子一样飞翔。

一起探讨,一起进步!谢谢!

posted @ 2020-02-18 19:11  一粒厘米  阅读(7322)  评论(0编辑  收藏  举报