NASM开发UEFI内核VMware启动黑屏无法引导故障排查
NASM编写UEFI内核VMware黑屏无输出修复方案
核心错误排查
UEFI环境下自定义内核启动直接黑屏,基本都是以下必现问题导致,逐一对应修复即可:
- PE可执行头不符合规范:UEFI固件仅识别标准PE32(32位)/PE32+(64位)格式的EFI应用,直接编译裸二进制、PE头字段填错、节区属性配置错误都会被固件直接拒绝加载,无任何报错提示。
- 调用约定不匹配:64位UEFI遵循Microsoft x64调用约定,前4个参数依次存入
rcx/rdx/r8/r9寄存器,函数调用前必须在栈上预留32字节影子空间、保持16字节栈对齐,传参顺序、栈操作错误会直接触发固件异常死机。 - 入口参数未保存:UEFI应用入口点默认传入两个核心参数:
rcx为当前镜像句柄,rdx为System Table指针,入口第一时间未保存这两个值,后续无法调用任何UEFI服务(包括屏幕打印)。 - 遗留传统BIOS逻辑:代码中如果保留实模式切换、16位/32位模式跳转、直接访问0xB8000 VGA显存的逻辑,会直接触发异常——UEFI入口已经处于64位长模式,VGA显存默认未做身份映射,直接访问会触发页错误。
- VMware配置错误:虚拟机固件类型选了传统BIOS、开启了安全启动(未签名自定义内核会被拦截)、EFI文件存放路径不符合规范,都会导致引导失败。
最小可运行修复代码
替换原有入口文件kernel.asm为以下标准实现,其余文件对应调整调用逻辑即可:
bits 64 org 0 ; DOS头 必须以MZ签名开头 dos_header: dw 0x5A4D times 0x3C - ($ - $$) db 0 dd pe_header ; PE标准头 pe_header: dd 0x00004550 dw 0x8664 ; 标记为64位可执行 dw 1 dd 0 dd 0 dd 0 dw opt_header_end - opt_header dw 0x2022 opt_header: dw 0x20B ; PE32+ 标识 db 0 db 0 dd code_end - code_entry dd 0 dd 0 dd code_entry dd code_entry dq 0 dd 0x1000 dd 0x200 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dd 0 dd 0x10000 dd 0x200 dd 0 dw 10 ; 标记为EFI应用子系统 dw 0 dq 0x100000 dq 0x10000 dq 0x100000 dq 0x10000 dd 0 dd 0x10 times 0x10 * 8 dq 0 opt_header_end: ; .text节区头 section_header: db '.text' times 8 - ($ - section_header) db 0 dd code_end - code_entry dd code_entry dd code_end - code_entry dd code_entry dd 0 dd 0 dw 0 dw 0 dd 0x60000020 ; 节属性:可读、可执行 code_entry: ; 保存UEFI入口核心参数 mov [image_handle], rcx mov [system_table], rdx ; 调用ConOut输出引导成功字符串 mov rcx, [rdx + 0x40] ; 取ConOut指针 mov rdx, boot_msg sub rsp, 32 ; 预留32字节影子空间 call [rcx + 0x8] ; 调用OutputString方法 add rsp, 32 ; 停机等待 hang: hlt jmp hang ; 数据定义 image_handle dq 0 system_table dq 0 boot_msg dw __utf16__('UEFI Kernel Loaded Successfully'), 0x0D, 0x0A, 0 code_end: ; 文件对齐填充 times 0x200 - ($ - $$) db 0
编译与运行配置
- 编译直接生成EFI文件,避免额外转换损坏PE头:
nasm -f bin kernel.asm -o BOOTX64.EFI - 虚拟机配置:VMware新建虚拟机时固件类型选择UEFI,关闭安全启动选项;将生成的
BOOTX64.EFI放到虚拟磁盘EFI分区的/EFI/BOOT/路径下。 - 其余代码调整要求:
kernel-efi.asm中所有UEFI服务调用严格遵循x64调用约定,禁止用System V ABI传参。kernel-api.asm、kernel-functions.asm中删除所有实模式、32位模式切换逻辑,删除直接访问0xB8000显存的代码,退出Boot Service前所有IO操作必须通过UEFI协议完成。
内容的提问来源于stack exchange,提问作者user15799783
相关产品推荐
相关产品推荐

