使用 gnu-efi 编写我的第一个 EFI 应用程序

问题描述

我有一个 Alexa 设备,我正在使用 esp8266 从回声点获取请求。 我可以在我的电脑上醒来,但这还不够。我的电脑上有 Windows 和 Linux,所以我想“我需要在启动前运行一些代码,这样我才能与我的 esp8266 通信以了解应该启动女巫操作系统”。所以我开始到处寻找解决方案,我想我真的很接近它。我所做的是将 efi-shell 作为主引导,让它执行 startup.nsh。 在这个 startup.nsh 中,我想启动可以与 esp8266 通信的 efi 应用程序。 这是做这件事的正确方法吗?我应该做点别的吗? 问题是我无法编写这个应用程序。我无法理解如何使用协议以及哪些协议是解决方案。应用程序应该向 esp 发送一个简单的字符,让它知道计算机已准备好获取引导指令。对于 Windows,esp 应该回复“1”或对于 Linux 回复“2”。 有人可以给我一些关于这项任务的建议吗?这是正确的方法还是我做了很多无用的事情?也许存在更好的方法

解决方法

这是一个如何使用 EDK2 加载和启动 UEFI 应用程序的示例,将其移植到 gnu-efi 应该是一项简单的任务,使用 uefi_call_wrapper 包装所有 gBS-> 调用。

根据 esp8266 的响应,您必须启动 Linux 或 Windows 加载程序应用程序。

我将 UDP 示例作为 answer 发布到您的第一个问题。

#include <Uefi.h>
#include <Library\UefiLib.h>
#include <Protocol\LoadedImage.h>
#include <Protocol\DevicePath.h>
#include <Library\DevicePathLib.h>

#ifndef LOG
#define LOG(fmt,...) AsciiPrint(fmt,__VA_ARGS__)
#endif

#ifndef TRACE
#define TRACE(status)   LOG("Status: '%r',Function: '%a',File: '%a',Line: '%d'\r\n",status,__FUNCTION__,__FILE__,__LINE__)
#endif

extern EFI_BOOT_SERVICES    *gBS;

/*
Configuration
*/
static CHAR16 gFilePath[] = L"\\Tools\\Udp4Sample.efi";

EFI_STATUS
EFIAPI
UefiMain(
    IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable)
{
    EFI_STATUS                  Status;

    EFI_LOADED_IMAGE            *LoadedImageProtocol = NULL;

    EFI_DEVICE_PATH_PROTOCOL    *AppDevicePath = NULL;

    EFI_HANDLE                  AppHandle = NULL;
    
    /*
    Step 1: Handle the LoadedImageProtocol of the current application
    */

    Status = gBS->HandleProtocol(
        ImageHandle,&gEfiLoadedImageProtocolGuid,&LoadedImageProtocol);

    if (EFI_ERROR(Status)) {
        TRACE(Status);
        // Error handling
        return Status;
    }

    /*
    Step 2: Create a device path that points to the application,the application must be located on the same device (partition) as this one
    */

    AppDevicePath = FileDevicePath(LoadedImageProtocol->DeviceHandle,gFilePath);

    if (!AppDevicePath) {
        TRACE(EFI_INVALID_PARAMETER);
        // Error handling
        return EFI_INVALID_PARAMETER;
    }
    
    /*
    Step 3: Load the application
    */

    Status = gBS->LoadImage(
        FALSE,ImageHandle,AppDevicePath,NULL,&AppHandle);
    
    gBS->FreePool(AppDevicePath);

    if (EFI_ERROR(Status)) {
        TRACE(Status);
        // Error handling
        return Status;
    }

    /*
    Step 4: Start the application
    */

    Status = gBS->StartImage(
        AppHandle,NULL);

    if (EFI_ERROR(Status)) {
        TRACE(Status);
        // Error handling
        return Status;
    }

    return EFI_SUCCESS;
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...