
简介这是一份围绕 Windows 10 开机 LOGO 个性化定制的小型工具包面向希望替换系统启动画面、且具备基本动手能力的用户与开发者。压缩包共 20 个文件约 73KB主体由 C# 与 C 源码cs、c、h构成并附带 Makefile、Markdown 说明、示例 BMP 图、配置文本及许可证等目录按源码、配置、文档和示例素材分区便于了解 BGRT 修改工具的组织方式与编译线索。已有 4783 人学习下载说明该主题在系统美化和启动界面定制群体中具有一定关注度。包内源码与说明可帮助读者理解开机画面替换的实现思路、配置项含义及图片规格要求如 480×270 像素 PNG也可作为研究 UEFI/BIOS 启动图形显示与二次开发的参考资料示例图与文档便于对照验证效果适合想深入原理而非仅套用现成工具的中高级用户。1. 开机图标这事小到没人写文档却卡住过不少人装过几十台机器之后你会发现客户第一眼看的东西不是配置单是开机那三秒钟的图标。开机图标这个需求小到没人愿意为它单独写一份说明却实实在在卡住过一批人改注册表没用换主题没用把设置翻遍了也找不到这一项最后只能去问“是不是要刷 BIOS”。HackBGRT-1.5.1 这个压缩包就是冲这一件事来的它把 Windows 引导管理器画的那个 logo 换成你自己的图片不装驱动、不常驻后台、不改系统主题。它适合做展厅机、工控面板、批量装机的从业者也适合只想把开机画面换成自己作品的人。前提是机器走 UEFI 引导而且你愿意动手碰一次引导分区。2. HackBGRT 的工作机制BGRT 表、bootmgfw.efi 与被改掉的那一刀在动手之前得先搞清楚这一刀切在哪儿。很多人以为开机图标是系统起来之后画的所以去改登录界面、改锁屏、改 OEM 信息全都白费力气。真相是那个画面出现在内核加载之前画它的是引导管理器跟系统里的任何设置项都没有关系。搞不清这一层后面每一次失败你都不知道该往哪个方向查。2.1 开机那一秒的画面究竟是谁画的一台 UEFI 机器从上电到进桌面的链路大致是固件自检 → 读 EFI 系统分区ESP里的引导程序 →bootmgfw.efiWindows 引导管理器→winload.efi→ 内核。厂商的 logo 由固件画Windows 的那个窗口图标由bootmgfw.efi画位置则由 ACPI 里的 BGRT 表Boot Graphics Resource Table告诉系统——固件把自己画 logo 的坐标和尺寸登记在这张表里引导管理器接着在同一个位置画自己的东西所以你看到的画面切换才不会跳一下。这就解释了为什么改系统设置永远不会有反应那个画面出生的时候系统还没加载完成注册表还没被读取。想让开机图标变成你想要的东西只能去改引导阶段执行的那个二进制。HackBGRT 的名字本身就来自这张表它做的事说穿了很简单——在bootmgfw.efi被固件调用之前先插一段自己的代码进去把画面画完再把控制权交回原来的引导流程。理解了这条链路后面所有的“为什么必须关某个开关”“为什么改完要重启两次”“为什么升级系统之后又变回去了”答案都能自己推出来。2.2 替换式注入bootmgfw.efi 被动了哪一刀HackBGRT 采用的是替换式注入具体动作分三步。第一步把 ESP 分区上原有的\EFI\Microsoft\Boot\bootmgfw.efi改名备份通常是加个后缀放在同一目录这一步是整套流程的保底措施也是后面能不能把机器救回来的关键。第二步把自带的 loader 放到同一个路径、同一个文件名上因为固件只认这个路径不认文件内容。第三步这个 loader 启动后先按配置画出你给的 BMP再链式加载刚才备份的原版引导文件让系统正常起来。这个设计带来两个必须接受的约束。其一由于替换后的二进制没有经过签名Secure Boot 打开时固件会拒绝执行它所以这一项必须关闭这不是让你绕过什么而是这类引导期定制绕不开的前提接受不了就别做。其二所有风险都集中在引导分区上改坏了的结果不是蓝屏是根本进不去系统连安全模式都摸不到。反过来说只要备份还在用任意一个能读 ESP 的环境把文件改回来机器就能恢复这也是我一直强调“先确认备份”的原因。需要说清楚边界这套改动只发生在引导阶段不进内核、不加驱动、不 hook 系统调用进系统之后它就不存在了。所以它不会影响性能也不会跟杀毒软件打架。2.3 包内文件的分工与它们的角色解压之后不要急着双击先认清每个文件是干什么的这比看十篇教程都管用。文件作用我的处理方式setup.exe挂载 ESP、备份原引导文件、写入 loader只在确认过分区和 Secure Boot 状态后以管理员身份运行config.txt指定图片路径、背景色、显示超时等先复制一份原版留档再改splash.bmp默认图片被config.txt引用直接用自己的图覆盖同名文件最省事引导相关文件注入到 ESP 的 loader 本体不手工动交给 setup 处理源码/说明供二次开发和排错出问题时对照配置项含义用这里有个经验新手最容易犯的错是绕过setup.exe手工往 ESP 里拷文件。手工拷不是不行但你会漏掉备份这一步而备份恰恰是唯一的后悔药。至于config.txt的具体键名和取值范围不同小版本的注释写法会有出入我一般直接打开包内那份原文件读注释比在网上翻半天靠谱——文件里的注释永远和你手上的这个版本对得上。3. 动手替换从环境盘点到最后一次重启流程本身并不长十分钟能走完但每一步都有前置条件。我习惯把顺序固定成“先验环境、再做图、最后写盘”因为一旦写盘失败前面两步的成果还能留到下次用反过来先写盘再发现图片尺寸不对就得重来一遍。3.1 动手前的环境盘点有三件事必须在改之前确认固件是 UEFI 而不是 Legacy、系统盘是 GPT、Secure Boot 的当前状态。三条里有一条不符后面的步骤大概率白做。用管理员权限开 PowerShell逐条跑# 1) 固件类型期望输出 UEFI如果是 Bios 就到此为止 (Get-ComputerInfo).BiosFirmwareType # 2) 系统盘分区表格式期望是 GPT Get-Disk | Select-Object Number, PartitionStyle, FriendlyName, Size # 3) Secure Boot 状态True 表示开着需要进固件设置关掉 Confirm-SecureBootUEFI # 4) 找到 EFI 系统分区确认它在哪块盘上 Get-Partition | Where-Object GptType -eq {c12a7328-f81f-11d2-ba4b-00a0c93ec93b} | Select-Object DiskNumber, PartitionNumber, Size第 1 条的含义不用多解释。第 2 条之所以要单独查是因为不少人装系统时用了第三方工具把 GPT 盘转成了 MBR这种情况下 ESP 根本不存在工具自然无从下手。第 3 条的输出如果是 True就重启进固件设置把 Secure Boot 关掉同时留意一件事关闭 Secure Boot 有可能触发 BitLocker 要求输入恢复密钥如果你开着系统盘加密先把 48 位恢复密钥找出来抄在纸上这一步省不得。第 4 条在多硬盘机器上尤其重要。我曾经在一台双硬盘的机器上折腾了半小时图标就是不变最后发现setup.exe把文件写到了另一块盘的 ESP 上——固件启动的是第一块盘的引导项。所以看到多块盘都有 ESP 时先确认 BIOS 里第一启动项是哪块盘。提示三条检查里任何一条不满足都不要抱着“试试看”的心态往下走。引导阶段的问题没有中间态要么正常开机要么开不了机。3.2 图片预处理分辨率、色深与体积的取舍引导阶段能读的图片格式非常有限实践上就是未压缩的 BMP。PNG、JPG 直接改后缀是不行的文件头对不上loader 读不出来结果就是开机一片黑或者干脆跳回原图标。所以必须做一次真正的格式转换。分辨率上有个取舍。用屏幕原生分辨率最清晰但 BMP 是位图体积随像素线性膨胀1920×1080 的 24 位图大概 6 MB1280×720 约 2.7 MB1024×768 约 2.3 MB。而 ESP 分区通常只有 100 MB 左右还要留给引导文件和其他工具所以我一般把成品压在 2 MB 以内宁可稍微降一点分辨率也不要让图片把分区撑爆。from PIL import Image import os TARGET_W, TARGET_H 1920, 1080 # 目标分辨率尽量贴合面板原生值 MAX_BYTES 2 * 1024 * 1024 # 自定的体积上限 src Image.open(logo_src.png).convert(RGB) # 强制 24 位丢掉 alpha # 等比缩放避免直接拉伸把人像或文字拉变形 scale min(TARGET_W / src.width, TARGET_H / src.height) new src.resize((int(src.width * scale), int(src.height * scale)), Image.LANCZOS) # 居中贴到纯黑画布上四周留黑比拉伸铺满好看得多 canvas Image.new(RGB, (TARGET_W, TARGET_H), (0, 0, 0)) canvas.paste(new, ((TARGET_W - new.width) // 2, (TARGET_H - new.height) // 2)) canvas.save(splash.bmp, formatBMP) print(bytes:, os.path.getsize(splash.bmp))这段代码有三个关键点。convert(RGB)是为了去掉 alpha 通道32 位带透明度的 BMP 在引导阶段很可能被当成花屏处理。等比缩放加居中贴图是为了避免非原生比例的画面被拉伸——开机图标变形是最常见的返工原因。最后打印体积是为了在写盘前就发现超限而不是等到写完才发现分区满。生成之后再做一次头部校验比肉眼确认可靠得多import struct with open(splash.bmp, rb) as f: header f.read(54) # BMP 文件头 信息头共 54 字节 magic, struct.unpack(H, header[0:2]) # 必须是 BM width, struct.unpack(i, header[18:22]) height, struct.unpack(i, header[22:26]) bpp, struct.unpack(H, header[28:30]) compression, struct.unpack(I, header[30:34]) # 0 表示不压缩 print(fmagic{magic:#x} {width}x{abs(height)} {bpp}bpp compression{compression}) assert magic 0x4D42, 不是 BMP 文件 assert compression 0, 必须是未压缩位图 assert bpp in (24, 32), 色深不支持这四行断言覆盖了绝大多数“图放了但没显示”的情况。很多转图工具默认输出 RLE 压缩的 BMP肉眼看着完全正常loader 却读不了校验能提前把这类问题挡掉。3.3 写入引导分区与第一次重启把生成好的splash.bmp覆盖到解压目录里的同名文件然后打开config.txt确认图片路径指向它。配置项大致是这样组织的键名和取值范围以包内注释为准# 只列最常用的几项剩下的保持默认即可 image splash.bmp background 000000 timeout 3image是相对路径一般相对于工具目录本身改成绝对路径也能用但换机器时会失效我倾向保持相对。background是画布底色用六位十六进制不带#和你的图片边缘颜色对齐能减少突兀感。timeout是画面停留时间设太小会一闪而过设太大又会拖慢开机3 秒上下是个比较稳的值。配置改完右键以管理员身份运行setup.exe。它会挂载 ESP、备份原引导文件、把 loader 写进去全程有文字输出。这里不要急着关窗口把输出读完重点确认两件事一是它操作的确实是系统盘那块 ESP二是备份动作确实执行了。确认完重启第一次开机就是验证时刻。3.4 验证改动是否真的生效重启后如果看到了自己的图说明写入成功。但“能看到”不等于“全都对”还要确认系统能正常进桌面、能正常重启和关机各一次。有些机器第一次能进第二次就卡住通常是原引导文件的链式加载写得不对或者 ESP 上有多个引导项互相干扰。想更确定一点可以重新挂载 ESP 看一眼文件状态# 把 ESP 挂到一个空闲盘符S 被占用就换别的 mountvol S: /S # 看备份在不在以及在不在同一个目录下 Get-ChildItem S:\EFI\Microsoft\Boot\ | Where-Object Name -like bootmgfw* | Select-Object Name, Length, LastWriteTime # 检查完记得卸载长期挂着会影响后续系统更新 mountvol S: /D备份文件存在且修改时间早于你运行setup.exe的时间说明整个流程是干净的。做完这一步再卸载盘符别图省事一直挂着——系统更新时会对 ESP 做操作多一个挂载点容易出岔子。4. 配置文件详解分辨率、超时与回滚路径配置文件不复杂但每一项都对应一个具体的视觉结果改错一项就得重启一次看效果代价不低。与其反复试不如先把每项的作用和边界弄清楚。这一章按“参数—效果—坑”的顺序拆最后一节专门讲怎么把机器还原成没动过的样子。4.1 常用参数逐项拆解不同小版本的注释文案会有差异但核心就那么几项功能是稳定的参数作用取值建议常见误用image指定要显示的图片相对路径指向同目录的 BMP写成 PNG 路径或路径含中文和空格background画布底色六位十六进制如000000带#前缀导致解析失败timeout画面停留秒数25 之间设成 0 或过大前者一闪而过后者拖慢开机多图相关项轮换显示多张图按注释格式追加条目条目数超限或格式不统一路径这一项值得单独说。中文路径和带空格的路径在引导阶段解析时容易出问题我一般把整个工具目录放到一个纯英文、无空格的短路径下比如C:\bgr\tool\改完再运行。这个习惯让我少排查过至少三四次“图明明在那儿就是不显示”的问题。还有一点把config.txt保存为 UTF-8 无 BOM。带 BOM 的文件第一个键名前面会多出不可见字符解析器把它当成未知项跳过表现为“整份配置只有第一行不生效”——这种问题靠读配置是看不出来的只能靠保存格式规避。4.2 多图、超时与背景色的配合想显示多张图做轮换需要在配置里追加多条图片条目每一条指向一个 BMP。这里有个容易被忽略的约束所有图片的尺寸最好保持一致因为画布大小是固定的混用不同分辨率会出现某一张被裁切或者缩放到角落的情况。背景色和图片边缘的配合也值得花两分钟。如果你的图是深色底背景色设成000000就融为一体看不出边界如果图是浅色底背景设黑反而会显出一个明显的方框。我通常的做法是先看图的主色调取边缘像素的颜色填进去这样在低亮度屏幕上过渡最自然。超时这一项装机场景和展厅场景的取值完全不同。批量装机追求效率2 秒足够用户还没反应过来就进系统了展厅机希望画面多停留一会儿让人看清品牌可以给到 45 秒但不要超过 5 秒否则每天开关机几十次累积起来的时间很可观。4.3 回滚把机器还原成没动过的样子回滚的优先级是先用工具自带的恢复功能再考虑手工操作。setup.exe重新运行一次通常会检测到已经注入过并给出恢复选项能走这条路就走这条因为它会把备份原样改回来不需要你知道文件名是什么。工具走不通时手工恢复也不难核心就是“把备份改回原名”mountvol S: /S # 先看清楚备份的实际文件名不同版本命名可能是 .bak 或 .orig Get-ChildItem S:\EFI\Microsoft\Boot\ | Where-Object Name -like bootmgfw* # 假设备份名是 bootmgfw.efi.bak先把注入的挪开再改回来 Rename-Item S:\EFI\Microsoft\Boot\bootmgfw.efi bootmgfw.efi.injected Rename-Item S:\EFI\Microsoft\Boot\bootmgfw.efi.bak bootmgfw.efi mountvol S: /D命令里的文件名一定要按你机器上实际看到的改不要照抄。操作完重启图标回到原样就说明恢复成功。如果连备份都找不到了还有最后一招用系统安装介质启动到修复环境执行bcdboot C:\Windows /s S: /f UEFI重建引导文件这条命令能让机器重新开得了机但开机图标会回到系统默认属于保命而不是复原。注意回滚操作同样在动引导分区做之前把该存的东西存好并且在操作期间别断电。5. 避坑与排查五个让人想重装系统的瞬间下面五条都是我在真机上遇到过的按“现象—原因—解决”写遇到对应症状直接对号入座不用从头排查。现象一改完重启图标纹丝不动系统一切正常。原因通常是写错了分区。多硬盘机器上setup.exe可能把文件写到了另一块盘的 ESP而固件启动的是第一块盘。解决方式进固件设置确认第一启动项对应的物理盘用Get-Partition比对磁盘编号只保留目标盘的数据线再跑一次或者临时在固件里把启动顺序调整到正确的那块盘。现象二开机黑屏只有一行白字或者直接跳进固件设置。这说明引导文件被替换但加载失败常见于替换过程中断、备份丢失或者 loader 版本与固件不兼容。解决方式用任意能读 ESP 的环境系统安装介质、PE 环境把备份改名回bootmgfw.efi备份也没了就用bcdboot重建引导。这类问题九成出在“没等setup.exe跑完就关窗口”上。现象三图标显示了但变形、只显示左上角一块或者四周被裁掉。原因是图片分辨率和面板原生分辨率不匹配且没有做居中贴图处理。解决方式回第 3.2 节用等比缩放加居中贴到目标尺寸画布的方式重新生成别直接拉伸原图。顺带检查一下 BMP 的头里宽度高度是不是你以为的那个值。现象四画面花屏、颜色明显不对、像老电视的雪花。大概率是图片不是标准 24 位未压缩 BMP或者带了 alpha 通道。解决方式用第 3.2 节末尾的四行断言校验一遍compression必须是 0bpp必须是 24。有些在线转换工具输出的是 RLE 压缩格式视觉上完全正常但 loader 读出来就是乱的。现象五用了一年都好好的某次系统大版本更新后图标变回默认。原因是累积更新重写了\EFI\Microsoft\Boot\bootmgfw.efi你注入的那份被覆盖掉了备份文件可能还在但已经不起作用。解决方式重新跑一遍setup.exe即可配置文件和图片都还在不用重做。建议把工具目录连同配置一起放在一个固定的地方别用完就删。另外补一条不算坑但很致命的开着 BitLocker 的机器关 Secure Boot 之后重启会要求输入 48 位恢复密钥。密钥在你第一次启用加密时被要求备份过通常在账户里或者打印出来了。如果实在找不到先别关机把密钥找出来再继续否则只能走数据恢复流程。6. 进阶把开机图标做成一条能复用的流水线单台机器改一次十分钟的事按上面流程走就行。但如果手上是几十台同型号的展厅机、工控面板要批量处理逐台点setup.exe就不可接受了而且人一多漏掉备份、图片尺寸不统一这类问题必然出现。我后来把它整理成了一条固定流水线素材统一进一个目录一个脚本批量出图并校验一个检查脚本在每次系统更新后跑一遍判断需不需要重新注入。批量出图的部分直接复用第 3.2 节的逻辑加一层目录遍历就行关键是把断言放在循环里任何一张图不合格就整批停下而不是带着一张坏图去写盘import os, struct from PIL import Image SRC_DIR, OUT_DIR src_logos, out_bmp TARGET (1920, 1080) os.makedirs(OUT_DIR, exist_okTrue) def to_bmp(src_path, dst_path): img Image.open(src_path).convert(RGB) scale min(TARGET[0] / img.width, TARGET[1] / img.height) img img.resize((int(img.width * scale), int(img.height * scale)), Image.LANCZOS) canvas Image.new(RGB, TARGET, (0, 0, 0)) canvas.paste(img, ((TARGET[0] - img.width) // 2, (TARGET[1] - img.height) // 2)) canvas.save(dst_path, formatBMP) def check_bmp(path): with open(path, rb) as f: h f.read(54) assert struct.unpack(H, h[0:2])[0] 0x4D42, f{path} 不是 BMP assert struct.unpack(I, h[30:34])[0] 0, f{path} 被压缩了 assert struct.unpack(H, h[28:30])[0] 24, f{path} 不是 24 位 for name in os.listdir(SRC_DIR): base os.path.splitext(name)[0] out os.path.join(OUT_DIR, base .bmp) to_bmp(os.path.join(SRC_DIR, name), out) check_bmp(out) # 任何一张不合格整个循环抛出异常 print(base, os.path.getsize(out), bytes)循环里那句check_bmp是整个脚本的价值所在。它把“图看着没问题”这种主观判断换成了三条硬断言出问题时直接告诉你哪一张、错在哪一项不用靠开机重启去试。第二个脚本用来做更新后的自检。系统大版本更新会覆盖引导文件但更新完你不会立刻知道往往是某天开机发现图标没了才想起来。我习惯在每次更新后跑一次mountvol S: /S $boot S:\EFI\Microsoft\Boot $cur Get-Item $boot\bootmgfw.efi -ErrorAction SilentlyContinue $bak Get-ChildItem $boot -Filter bootmgfw*.bak -ErrorAction SilentlyContinue if ($bak) { 备份存在注入文件时间: $cur.LastWriteTime if ($cur.LastWriteTime -gt $bak.LastWriteTime) { 疑似被更新覆盖需要重新注入 } } else { 没有备份说明当前是原厂引导或已回滚 } mountvol S: /D判断依据很朴素如果当前引导文件的修改时间比备份还新说明它被别的东西重写过注入已经失效。这个判据不依赖版本号也不会误伤是我用得最顺手的一条。有个细节值得提一句批量场景下我建议给每台机器留一份配置快照把config.txt和成品 BMP 一起归档到带机器编号的目录里。原因是半年后你可能会被问“这台机器当时用的是哪张图”而机器上的文件早被覆盖过好几轮了。归档这件事花不了几分钟能省掉后面一堆对不上账的麻烦。说到底这类引导期改动的坑都不在技术难度上而在“没备份就动手”和“没验证就写盘”上。从那以后我每次碰 ESP 之前都会先挂载、先看备份、先把恢复命令在记事本里写好再执行注入——哪怕这台机器我已经改过十次。希望帮到你。本文还有配套的精品资源点击获取