查看 Log 的过程中,发现在 DXE 阶段有错误报出,本文针对这个问题进行了一点研究。
首先,遇到的错误信息如下:
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 7543E98
ProtectUefiImageCommon - 0x7543B40
- 0x0000000007105000 - 0x0000000000005E60
InstallProtocolInterface: AA0E8BC1-DABC-46B0-A844-37B8169B2BEA 710A9C0
Loading driver 4B28E4C7-FF36-4E10-93CF-A82159E777C5
InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 7543140
!!!!!!!! InsertImageRecord - Section Alignment(0x20) is not 4K !!!!!!!!
!!!!!!!! Image - c:\buildbs\stable202108org\Build\OvmfX64\DEBUG_VS2015x86\X64\MdeModulePkg\Universal\ResetSystemRuntimeDxe\ResetSystemRuntimeDxe\DEBUG\ResetSystemRuntimeDxe.pdb !!!!!!!!
Loading driver at 0x00007AE1000 EntryPoint=0x00007AE14D4 ResetSystemRuntimeDxe.efi
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 7543418
ProtectUefiImageCommon - 0x7543140
- 0x0000000007AE1000 - 0x00000000000041A0
接下来定位。输出错误的代码位于 \mdemodulepkg\core\dxe\misc\MemoryAttributesTable.c 中的InsertImageRecord() 函数中:
/**
Insert image record.
@param RuntimeImage Runtime image information
**/
VOID
InsertImageRecord (
IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
)
……………
//
// Get SectionAlignment
//
if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
} else {
SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
}
SetMemoryAttributesTableSectionAlignment (SectionAlignment);
if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
DEBUG ((DEBUG_WARN, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));
PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
if (PdbPointer != NULL) {
DEBUG ((DEBUG_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
}
goto Finish;
}
…………
在\MdePkg\Include\X64\ProcessorBind.h 有如下定义:
///
/// Page allocation granularity for x64
///
#define DEFAULT_PAGE_ALLOCATION_GRANULARITY (0x1000)
#define RUNTIME_PAGE_ALLOCATION_GRANULARITY (0x1000)
可以看到,SectionAlignment 来自 Hdr.Pe32Plus->OptionalHeader.SectionAlignment,使用 CFF 查看 ResetSystemRuntimeDxe.efi 这个文件,注意下图中的2个位置。上述代码首先检查ImageType(Subsystem) 是否为EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,如果是再继续检查SectionAlignment是否为4K,如果不是 4K 对齐那么就进行报错。
ImageType的定义在\MdeModulePkg\Universal\ResetSystemRuntimeDxe\ResetSystemRuntimeDxe.inf 文件中:
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = ResetSystemRuntimeDxe
MODULE_UNI_FILE = ResetSystemRuntimeDxe.uni
FILE_GUID = 4B28E4C7-FF36-4e10-93CF-A82159E777C5
MODULE_TYPE = DXE_RUNTIME_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InitializeResetSystem
搜索所有 MODULE_TYPE 为 DXE_RUNTIME_DRIVER 的 Module 发现在运行期都有这样的问题。
确定了问题,找到了问题点,接下来就开始分析“为什么出现不满足条件”。
检查\Build\OvmfX64\DEBUG_VS2015x86\X64\MdeModulePkg\Universal\ResetSystemRuntimeDxe\ResetSystemRuntimeDxe\Makefile 文件有下面一行:
DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
(注意 /ALIGN:32 参数)
尝试修改上面为 /ALIGN:0x1000 修改之后再次编译(需要同样的环境,进入 Debug 目录直接运行 NMAKE,这种方法在之前的实验中有介绍过),生成的EFI如下:
我们需要修改EFI 的生成方式。在\Conf\tools_def.txt 可以看到默认的编译参数:
DEBUG_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
RELEASE_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data
NOOPT_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
这里我们使用的是DEBUG版,所以需要修改为下面这样(/ALIGN:0x1000)
DEBUG_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:0x1000 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
修改之后重新编译OVMF,得到的ResetSystemRuntimeDxe.efi 和前面手工修改的结果相同。但是这样修改会导致编译最后一步无法通过:
Generating FVMAIN_COMPACT FV
Generating PEIFV FV
##### ['GenFv', '-a', 'c:\\buildbs\\stable202108org\\Build\\OvmfX64\\DEBUG_VS2015x86\\FV\\Ffs\\PEIFV.inf', '-o', 'c:\\buildbs\\stable202108org\\Build\\OvmfX64\\DEBUG_VS2015x86\\FV\\PEIFV.Fv', '-i', 'c:\\buildbs\\stable202108org\\Build\\OvmfX64\\DEBUG_VS2015x86\\FV\\PEIFV.inf']
Return Value = 2
GenFv: ERROR 3000: Invalid
PE image Section-Alignment and File-Alignment do not match : c:\buildbs\stable202108org\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\52C05B14-0B98-496c-BC3B-04B50211D680PeiCore\52C05B14-0B98-496c-BC3B-04B50211D680.ffs.
GenFv: ERROR 3000: Invalid
Could not rebase c:\buildbs\stable202108org\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\52C05B14-0B98-496c-BC3B-04B50211D680PeiCore\52C05B14-0B98-496c-BC3B-04B50211D680.ffs.
build.py...
: error 7000: Failed to generate FV
build.py...
: error 7000: Failed to execute command
看起来是因为 PE头中 SectionAlignment和FileAlignment 不同导致的,在【参考1】介绍了一个设置 FileAlignment 的参数。同样的,将这个参数加入到 tools_def.txt 文件中:
DEBUG_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:0x1000 /FILEALIGN:0x1000 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
(注意 /FILEALIGN:0x1000 )
再次编译可以得到OVMF.FD ,使用QEMU 运行,Log 中就没有这个错误了。
这样的修改虽然能够解决问题,但是我们并不了解 InsertImageRecord() 函数的用途,后面有机会再继续进行分析。
参考:
1.https://blog.csdn.net/bagboy_taobao_com/article/details/7295575/