将 UEFI 应用程序从 AARCH64 移植到 X64 时,我遇到了以下问题:启用周期性计时器后应用程序挂起(计时器用于 I/O 轮询的应用程序)。计时器回调完成,之后不执行任何操作。
在调试过程中,我试图找到代码中的错误,但未能成功。现在我有一个非常小的 helloworld 示例,具有以下属性:
此示例是否损坏或者 AMI BIOS 中存在错误?
这是崩溃应用程序的完整源代码。如您所见,它仅尝试覆盖计时器回调中静态数组中的两个字节,但是应用程序在首次执行回调后挂起。删除代码的任何部分(仅使用 1 个数组、内联函数)可以防止应用程序挂起。 预期结果:“Hello World”、“计时器开始”、“计时器结束”消息的垃圾邮件。这就是 QEMU 和 AARCH64 设备上发生的情况。 收到的内容:几条“Hello World”消息,然后是计时器回调的一次迭代,之后该应用程序挂起。 默认情况下,EDK2 使用“-Os”优化,这需要更复杂的代码才能崩溃,因此该函数明确具有“-O0”优化。 现代 AMI BIOS 实现中是否存在严重错误或者我的代码有问题?
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
static volatile UINT8 test_buf1[200];
static volatile UINT8 test_buf2[200];
void* timer;
__attribute((optimize("O0")))
void assign(volatile UINT8* ptr, int ind)
{
ptr[ind] = 10;
}
__attribute((optimize("O0")))
void test_func(void)
{
assign(test_buf1, 0);
assign(test_buf2, 0);
}
__attribute((optimize("O0")))
void test_interrupt(EFI_EVENT Event, VOID *Context)
{
DEBUG ((EFI_D_ERROR, "timer begin\r\n"));
test_func();
DEBUG ((EFI_D_ERROR, "timer end\r\n"));
}
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Print(L"Hello World \n");
Status = gBS->CreateEvent( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, (EFI_EVENT_NOTIFY)test_interrupt, NULL, &timer);
if (EFI_ERROR(Status)) {
return -1;
}
Status = gBS->SetTimer( timer, TimerPeriodic, EFI_TIMER_PERIOD_MILLISECONDS (16));
if (EFI_ERROR(Status)) {
return -1;
}
while(1)
Print(L"Hello World \n");
return EFI_SUCCESS;
}
计时器回调函数未声明为 EFIAPI。这个属性成功地解决了一切。
EFIAPI void test_interrupt(EFI_EVENT Event, VOID *Context)