对于BIOS来说,用户能够看到的是非常重要的事情。开机Logo就是这样。自从 Win8.1开始,Windows在进入桌面的时候可以显示用户自定义的Logo,而不是Microsoft自定义的图片,这是很有意思的事情。
最近看了一篇介绍的文章,恍然大悟,原来是BIOS解压自己的Logo在内存中,然后通过ACPI Table将这个Logo传递给Windows,于是开机Logo比以前显示的时间更长更持久。
具体的Table就是 Boot Graphics Resource Table。在 ACPI 6.1的5.2.22有专门的介绍。

根据上面的原理,我们可以编写一个UEFI Application,将内存存放的 Logo Dump出来。具体操作:

1. 找到RSDP,找到 XSDT

2. 在XSDT中检查每一个Entry,根据 Signature 找到BGRT
3. 解析 BGRT ,得到Logo 图像的地址,这个 Logo一定是 BMP格式的
4. 根据BMP格式能够解析出文件大小,直接Memory Dump即可得到结果

完整的代码:

#include <Library/BaseLib.h>
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/BaseMemoryLib.h>
#include <Protocol/EfiShell.h>
#include <Library/ShellLib.h>#include "acpi.h"
#include "acpi61.h"extern EFI_BOOT_SERVICES         *gBS;
extern EFI_RUNTIME_SERVICES      *gRT;
extern EFI_SYSTEM_TABLE          *gST;#pragma pack(push, 1)
/** BGRT structure */
typedef struct {EFI_ACPI_DESCRIPTION_HEADER header;UINT16 version;UINT8 status;UINT8 image_type;UINT64 image_address;UINT32 image_offset_x;UINT32 image_offset_y;
} ACPI_BGRT;/** Bitmap file header */
typedef struct {UINT8 magic_BM[2];UINT32 file_size;UINT8 unused_0x06[4];UINT32 pixel_data_offset;UINT32 dib_header_size;UINT32 width;UINT32 height;UINT16 planes;UINT16 bpp;
} BMP;
#pragma pack(pop)EFI_GUID        gEfiAcpi20TableGuid =   { 0x8868E871, 0xE4F1, 0x11D3, { 0xBC, 0x22, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }};
EFI_GUID        gEfiSimpleFileSystemProtocolGuid ={ 0x964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};EFI_STATUS
SaveToFile(IN UINT8 *FileData, IN UINTN FileDataLength)
{EFI_STATUS          Status;EFI_FILE_PROTOCOL   *FileHandle;UINTN               BufferSize;EFI_FILE_PROTOCOL   *Root;EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;Status = gBS->LocateProtocol(&gEfiSimpleFileSystemProtocolGuid, NULL,(VOID **)&SimpleFileSystem);if (EFI_ERROR(Status)) {Print(L"Cannot find EFI_SIMPLE_FILE_SYSTEM_PROTOCOL \r\n");return Status;}Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &Root);if (EFI_ERROR(Status)) {Print(L"OpenVolume error \r\n");return Status;}Status = Root->Open(Root, &FileHandle, L"BIOSLogo.bmp",EFI_FILE_MODE_READ |EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);if (EFI_ERROR(Status)){Print(L"Error Open NULL  [%r]\n",Status);return Status;}BufferSize = FileDataLength;Status = FileHandle->Write(FileHandle, &BufferSize, FileData);FileHandle->Close(FileHandle);return Status;
}/***Demonstrates basic workings of the main() function by displaying awelcoming message.Note that the UEFI command line is composed of 16-bit UCS2 wide characters.The easiest way to access the command line parameters is to cast Argv as:wchar_t **wArgv = (wchar_t **)Argv;@param[in]  Argc    Number of argument tokens pointed to by Argv.@param[in]  Argv    Array of Argc pointers to command line tokens.@retval  0         The application exited normally.@retval  Other     An error occurred.
***/
INTN
EFIAPI
ShellAppMain (IN UINTN Argc,IN CHAR16 **Argv)
{EFI_STATUS      Status;EFI_ACPI_DESCRIPTION_HEADER                     *XSDT;EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_POINTER    *RSDP;UINT8           *p;UINTN           Index;UINT64          *Entry;ACPI_BGRT       *pBGRT;BMP             *pBMP;//1. Find RSDPStatus=EfiGetSystemConfigurationTable(&gEfiAcpi20TableGuid,(VOID**)&RSDP);if(EFI_ERROR(Status)) {Print(L"Can't find Acpi Table\n");return 0;}//2. Find XSDTPrint(L"RSDP address [%X]\n",RSDP);Print(L"XSDT address [%X]\n",RSDP->XsdtAddress);XSDT=(EFI_ACPI_DESCRIPTION_HEADER*)RSDP->XsdtAddress;Print(L"XSDT information\n");p=(UINT8*)XSDT;//Show some DSDT informationPrint(L" Signature [%c%c%c%c]\n",*p,*(p+1),*(p+2),*(p+3));//3.Find entriesEntry=(UINT64*)&XSDT[1];Print(L" Entry 0 @[0x%x]\n",Entry);for (Index=0;Index<(XSDT->Length-sizeof(EFI_ACPI_DESCRIPTION_HEADER))/8;Index++) {//Print(L" Entry [0x%x]",Index);p=(UINT8*)(*Entry);//You can show every signature here//Print(L" [%x][%c%c%c%c]\n",*Entry,*p,*(p+1),*(p+2),*(p+3));if ((*p=='B')&&(*(p+1)=='G')&&(*(p+2)=='R')&&(*(p+3)=='T')) {pBGRT=(ACPI_BGRT*)p;Print(L"  Found BGRT @[0x%X]\n",*Entry);Print(L"  Image address @[0x%X]\n",pBGRT->image_address);//Get BMP addresspBMP=(BMP*)(pBGRT->image_address);Print(L"     [0x%X]\n",pBMP);Print(L"     Image size  [0x%X]\n",pBMP->file_size);Print(L"     Data offset [0x%X]\n",pBMP->pixel_data_offset);Print(L"     Header size [0x%X]\n",pBMP->dib_header_size);Print(L"           Width [0x%X]\n",pBMP->width);Print(L"           Height[0x%X]\n",pBMP->height);Print(L"           Planes[0x%X]\n",pBMP->planes);Print(L"           BPP   [0x%X]\n",pBMP->bpp);                   SaveToFile((UINT8*)pBMP,pBMP->file_size);Print(L"BIOS logo has been saved to 'BIOSLogo.bmp'\n");}Entry++;}return 0;
}

运行结果,测试平台为 Intel Kabylake-R HDK,使用的是 Byo BIOS

(不知道为啥,他家的 Shell分辨率很高, 字体极小,看起来简直要瞎) 取得的 BIOSLogo.bmp 结果如下

完整的代码下载:FindBGRT

特别鸣谢sssky307在之前的文章中给出了EfiGetSystemConfigurationTable函数使得代码能够能够大幅度化简。

Step to UEFI (137) 通过 BGRT 取得当前系统的 LOGO相关推荐

  1. 联想服务器怎么使用uefi启动不了系统,联想小新如何用uefi启动在win10下装win7系统...

    原标题:联想小新如何用uefi启动在win10下装win7系统 联想小新系列是性能与轻薄兼得的轻薄笔记本电脑,想必大家对此系列的本本都不陌生吧,但是对联想小新系列本本如何装双系统却完全不了解,今天笔者 ...

  2. uefi安装win10原版镜像|uefi gpt模式安装win10官方系统教程

    原文摘自:http://www.xitongcheng.com/jiaocheng/xtazjc_article_34109.html uefi安装win10原版镜像|uefi gpt模式安装win1 ...

  3. UEFI模式安装Windows Linux双系统

    现在的好多电脑都支持UEFI功能了,但是大部分用户还在使用兼容的bios模式,这样显然延长了电脑的启动时间,对我来说这是不能容忍的.主流的Linux发行版和Win7及Win8都能够支持UEFI,对于预 ...

  4. u盘如何在UEFI模式下用GHOST装系统

    BIOS里设置成了UEFI启动模式,用普通的u盘启动发现进PE用GHOST装系统完成后启动不了. 一.BIOS设置启动模式.        1.legacy模式,也就是传统模式.在这种模式下,可以用各 ...

  5. 华硕uefi不识别linux安装u盘启动,uefi无法从u盘启动系统

    当Win10系统装机用户越来越多后,UEFI主板配置也浮现在用户计算机中,UEFI和BIOS 是主流的两种主板配置.这种新型UEFI主板配置也让很多用户措手不及,一些用户表示在计算机中插入U盘,UEF ...

  6. linux有读EC RAM的工具吗,Step to UEFI (179)Shell下 EC Ram 读取工具

    最近工作需要在 UEFI  Shell 下Check EC Ram 的设定,发现手上只有 Windows 下的读取工具(RW Everything).于是研究了一下如何在Shell 读取 EC Ram ...

  7. uefi启动u盘安装系统_技嘉uefi启动怎么安装win8.1系统【安装教程】

    近几年来,大多数厂商生产电脑主板都以uefi配置为主导,uefi类型主板优点主要是能加快启动速度,它绕过了bios自检流程便能直接引导操作系统.从win8/win8.1操作系统开始,都能用uefi引导 ...

  8. uefi模式下win10安装双系统ubuntu18.04LTS

    自己折腾了半天,血与泪啊(难得一个可爱的周末 wwww我一定要写下来 跟这个博客几乎一模一样了 https://blog.csdn.net/xrinosvip/article/details/8042 ...

  9. 技嘉的UEFI修复windows与Ubuntu双系统引导+老毛桃修复引导失败+No EFI system partition was found.

    ######################################################################### 下面是技嘉主板的一些快捷键 Del:BIOS SET ...

最新文章

  1. linux 查看san链路状态,linux系统运行状态检查
  2. C 语言编程 — uint8_t / uint16_t / uint32_t /uint64_t
  3. 类,对象,方法的使用
  4. 3-2:常见任务和主要工具之存储介质
  5. 摄像头拼接技术-远超海康大华
  6. 如何开始使用 Java 机器学习
  7. word/wps 实用技巧: 批量改大纲标题样式
  8. rar怎么用计算机打开,解答电脑rar文件怎么打开
  9. Debian查看系统版本信息
  10. Apollo星火计划学习笔记|控制模块
  11. Go实战--也许最快的Go语言Web框架kataras/iris初识四(i18n、filelogger、recaptcha)
  12. PCB中邮票孔的用处以及常用设置
  13. SpringBoot-端点详解
  14. Git Bash中怎么复制与粘贴
  15. 单双号限行微信小程序源码
  16. 一个神奇的开源项目:让照片快速 3D 化!
  17. 水题Eating Soup
  18. 【relativistic GAN :细节注入】
  19. 软件项目管理(CMMI成熟度)实践——之决策分析(2)
  20. 名画54 周季常 林庭珪《五百罗汉图》

热门文章

  1. 云基础架构安全_这是使您的云基础架构稳定,安全和可扩展的方法。
  2. TCHAR char wchar_t 的区别
  3. 初学stm32单片机可以做什么简单的小作品?
  4. 广告主、SSP、ADX、DSP之间的关系
  5. python移动光标至行首_Python re.sub()行首开始锚定
  6. hadoop实战-06.ubuntu14.0安装hadoop 2.7.1( 3台主机) 小集群
  7. 当使用maven的clear功能导致数据库链接出现Using a password on the command line interface can be insecure.的解决方案
  8. orcal复习及作业
  9. CICD之 gitlab和gtilab runner
  10. 将字符串的一部分拷贝到另一个字符串