使用 gnu-efi 编写我的第一个 EFI 应用程序
Writing my first EFI application with gnu-efi
我有一个 Alexa 设备,我正在使用 esp8266 从 echo dot 获取请求。
我可以在 LAN 上唤醒我的电脑,但这还不够。我的电脑上有 windows 和 Linux,所以我想“我需要一些代码来 运行 才能启动,这样我就可以与我的 esp8266 通信以了解 os 应该被引导”。所以我开始到处寻找解决方案,我想我真的很喜欢它。我做的是把efi-shell作为主引导,让它执行startup.nsh。
在这个 startup.nsh 中,我想启动可以与 esp8266 通信的 efi 应用程序。
这是做这件事的正确方法吗?我应该做点别的吗?
问题是我无法编写此应用程序的代码。我不明白如何使用协议以及哪些协议是解决方案。应用程序应该向 esp 发送一个简单的字符,让它知道计算机已准备好接收引导指令。 esp 应该为 windows 回复“1”或为 Linux 回复“2”。
有人可以给我一些关于这项任务的建议吗?这是正确的方法还是我做了很多无用的事情?也许存在更好的方法
这是一个如何使用 EDK2 加载和启动 UEFI 应用程序的示例,将其移植到 gnu-efi 应该是一个简单的任务,用 uefi_call_wrapper.[=12= 包装所有 gBS-> 调用]
根据 esp8266 的响应,您必须启动 Linux 或 Windows 加载程序应用程序。
我将 UDP 示例作为 发布到您的第一个问题。
#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,
0,
&AppHandle);
gBS->FreePool(AppDevicePath);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
/*
Step 4: Start the application
*/
Status = gBS->StartImage(
AppHandle,
NULL,
NULL);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
return EFI_SUCCESS;
}
我有一个 Alexa 设备,我正在使用 esp8266 从 echo dot 获取请求。 我可以在 LAN 上唤醒我的电脑,但这还不够。我的电脑上有 windows 和 Linux,所以我想“我需要一些代码来 运行 才能启动,这样我就可以与我的 esp8266 通信以了解 os 应该被引导”。所以我开始到处寻找解决方案,我想我真的很喜欢它。我做的是把efi-shell作为主引导,让它执行startup.nsh。 在这个 startup.nsh 中,我想启动可以与 esp8266 通信的 efi 应用程序。 这是做这件事的正确方法吗?我应该做点别的吗? 问题是我无法编写此应用程序的代码。我不明白如何使用协议以及哪些协议是解决方案。应用程序应该向 esp 发送一个简单的字符,让它知道计算机已准备好接收引导指令。 esp 应该为 windows 回复“1”或为 Linux 回复“2”。 有人可以给我一些关于这项任务的建议吗?这是正确的方法还是我做了很多无用的事情?也许存在更好的方法
这是一个如何使用 EDK2 加载和启动 UEFI 应用程序的示例,将其移植到 gnu-efi 应该是一个简单的任务,用 uefi_call_wrapper.[=12= 包装所有 gBS-> 调用]
根据 esp8266 的响应,您必须启动 Linux 或 Windows 加载程序应用程序。
我将 UDP 示例作为
#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,
0,
&AppHandle);
gBS->FreePool(AppDevicePath);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
/*
Step 4: Start the application
*/
Status = gBS->StartImage(
AppHandle,
NULL,
NULL);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
return EFI_SUCCESS;
}