UEFI 自定义菜单开发完整流程指南

🎯 目标

在 UEFI Setup 的 Advanced 菜单下添加一个自定义子菜单,包含配置选项。


第一步:创建驱动程序目录结构

1.1 创建驱动程序目录

# 在 Drivers 目录下创建新的驱动程序目录
mkdir -p LsFwSdk/LsRefCodePkg/Drivers/YourMenuDxe

1.2 创建必需的文件

YourMenuDxe/
├── YourMenu.c              # 主驱动程序文件
├── YourMenu.h              # 头文件
├── YourMenuNv.h            # 配置定义文件
├── YourMenuVfr.vfr         # 表单定义文件
├── YourMenuStrings.uni     # 字符串资源文件
└── YourMenuDxe.inf         # 构建配置文件

第二步:配置文件创建(照着模板修改)

2.1 INF 文件模板 (YourMenuDxe.inf)

[Defines]
  INF_VERSION                    = 0x00010005
  BASE_NAME                      = YourMenuDxe        # 重要:影响符号命名
  MODULE_UNI_FILE                = YourMenuStrings.uni
  FILE_GUID                      = XXXX-XXXX-XXXX-XXXX-XXXX  # 生成新GUID
  MODULE_TYPE                    = DXE_DRIVER
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = YourMenuInit
  UNLOAD_IMAGE                   = YourMenuUnload

[Sources]
  YourMenu.c
  YourMenu.h
  YourMenuNv.h
  YourMenuStrings.uni           # 必须包含此项
  YourMenuVfr.vfr

[Packages]
  MdePkg/MdePkg.dec
  MdeModulePkg/MdeModulePkg.dec
  LsRefCodePkg/Loongson.dec

[LibraryClasses]
  BaseLib
  MemoryAllocationLib
  UefiBootServicesTableLib
  UefiDriverEntryPoint
  UefiRuntimeServicesTableLib
  BaseMemoryLib
  DebugLib
  HiiLib
  PrintLib
  UefiLib

[Guids]
  gEfiIfrTianoGuid
  gEfiIfrFrontPageGuid
  gEfiIfrAdvancedManagerGuid    # 重要:使菜单显示在Advanced下
  gYourMenuFormSetGuid          # 在Loongson.dec中定义

[Protocols]
  gEfiHiiConfigRoutingProtocolGuid
  gEfiHiiConfigAccessProtocolGuid
  gEfiFormBrowser2ProtocolGuid
  gEdkiiFormBrowserExProtocolGuid

[Depex]
  gEfiSimpleTextOutProtocolGuid AND gEfiHiiDatabaseProtocolGuid AND gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid

2.2 配置定义文件 (YourMenuNv.h)

#ifndef _YOUR_MENU_NV_H_
#define _YOUR_MENU_NV_H_

#include <Guid/HiiPlatformSetupFormset.h>
#include <Guid/HiiFormMapMethodGuid.h>
#include <Guid/DriverSampleHii.h>
#include <Guid/ZeroGuid.h>
#include <SetupStru.h>

#define YOUR_MENU_SETTINGS_VARSTORE_ID    0x12XX  # 使用唯一ID
#define YOUR_MENU_FORMSET_GUID { \
 0xXXXXXXXX, 0xXXXX, 0xXXXX, { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX } \
}

#endif

2.3 在平台配置文件中注册GUID (Loongson.dec)

gYourMenuFormSetGuid                        = { 0xXXXXXXXX, 0xXXXX, 0xXXXX, { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX } }

第三步:配置数据结构定义

3.1 在 SetupStru.h 中添加配置结构体

/*************************************
 *  YOUR_MENU_SETTING
 ************************************/
typedef struct {
  UINT8 YourOption;           # OneOf控件必须使用UINT8/16/32/64
  // 可以添加更多配置字段
} YOUR_MENU_SETTING;

第四步:字符串资源文件 (YourMenuStrings.uni)

4.1 字符串文件模板

#langdef en-US  "English"
#langdef fr-FR  "Francais" 
#langdef x-UEFI-ns "UefiNameSpace"
#langdef zh-Hans "简体中文"

#string STR_YOUR_MENU_FORM_SET_TITLE      #language en-US  "Your Menu Title"
                                        #language zh-Hans "您的菜单标题"

#string STR_YOUR_MENU_FORM_SET_TITLE_HELP #language en-US  "Your menu help text"
                                        #language zh-Hans "菜单帮助文本"

#string STR_YOUR_OPTION                  #language en-US  "Your Option"
                                        #language zh-Hans "您的选项"

#string STR_YOUR_OPTION_HELP             #language en-US  "Option help text"
                                        #language zh-Hans "选项帮助文本"

#string STR_OPTION_VALUE_1               #language en-US  "Option 1"
                                        #language zh-Hans "选项1"

#string STR_OPTION_VALUE_2               #language en-US  "Option 2" 
                                        #language zh-Hans "选项2"

#string STR_EMPTY_STRING                 #language en-US  ""
                                        #language zh-Hans ""

#string STR_DEVICE_PATH                 #language en-US  ""
                                        #language zh-Hans ""

⚠️ 重要注意事项:

  • 字符串标识符不能包含特殊字符(如 ‘x’ 要改为 ‘_’)
  • 必须包含 STR_EMPTY_STRINGSTR_DEVICE_PATH

第五步:表单定义文件 (YourMenuVfr.vfr)

5.1 VFR 文件模板

#include "YourMenuNv.h"

formset
  guid      = YOUR_MENU_FORMSET_GUID,
  title     = STRING_TOKEN(STR_YOUR_MENU_FORM_SET_TITLE),
  help      = STRING_TOKEN(STR_YOUR_MENU_FORM_SET_TITLE_HELP),
  classguid = gEfiIfrAdvancedManagerGuid,  # 重要:显示在Advanced菜单下

  # 配置存储定义 - 必须与SetupStru.h中的结构体名称一致
  varstore YOUR_MENU_SETTING,
    varid = YOUR_MENU_SETTINGS_VARSTORE_ID,
    name  = YourCfg,
    guid  = YOUR_MENU_FORMSET_GUID;

  form formid = 0x1,
    title  = STRING_TOKEN(STR_YOUR_MENU_FORM_SET_TITLE);

    subtitle text = STRING_TOKEN(STR_YOUR_MENU_FORM_SET_TITLE);
    subtitle text = STRING_TOKEN(STR_EMPTY_STRING);

    # OneOf控件 - 只支持UINT8/16/32/64数据类型
    oneof name = YourCfg,
      varid = YourCfg.YourOption,        # 格式:变量名.字段名
      prompt = STRING_TOKEN(STR_YOUR_OPTION),
      help = STRING_TOKEN(STR_YOUR_OPTION_HELP),
      option text = STRING_TOKEN(STR_OPTION_VALUE_1), value=0x0, flags=DEFAULT;
      option text = STRING_TOKEN(STR_OPTION_VALUE_2), value=0x1, flags=0;
    endoneof;

  endform;
endformset;

⚠️ 重要注意事项:

  • varstore 后的结构体名称必须与 SetupStru.h 中定义的一致
  • OneOf 控件只支持 UINT8/16/32/64 数据类型
  • 变量引用格式:变量名.字段名

第六步:驱动程序实现 (YourMenu.c)

6.1 驱动程序模板

#include "YourMenu.h"

// 全局变量
CHAR16 VariableName[] = L"YourMenuConfig";
YOUR_MENU_PRIVATE_DATA *mPrivateData = NULL;
HII_VENDOR_DEVICE_PATH mYourMenuHiiVendorDevicePath;

// 配置访问协议实现
EFI_STATUS EFIAPI ExtractConfig(...) {
    // 实现配置提取逻辑
}

EFI_STATUS EFIAPI RouteConfig(...) {
    // 实现配置路由逻辑  
}

EFI_STATUS EFIAPI Callback(...) {
    // 实现回调逻辑
}

// 驱动程序入口点
EFI_STATUS EFIAPI YourMenuInit(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) {
    EFI_STATUS Status;
    EFI_HANDLE DriverHandle = NULL;
    EFI_HII_HANDLE HiiHandle;
    
    // 1. 分配私有数据结构
    mPrivateData = AllocateZeroPool(sizeof(YOUR_MENU_PRIVATE_DATA));
    
    // 2. 初始化设备路径结构体(运行时初始化,避免编译时常量问题)
    mYourMenuHiiVendorDevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;
    mYourMenuHiiVendorDevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;
    mYourMenuHiiVendorDevicePath.VendorDevicePath.Header.Length[0] = (UINT8)(sizeof(VENDOR_DEVICE_PATH));
    mYourMenuHiiVendorDevicePath.VendorDevicePath.Header.Length[1] = (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8);
    CopyMem(&mYourMenuHiiVendorDevicePath.VendorDevicePath.Guid, &gYourMenuFormSetGuid, sizeof(EFI_GUID));
    
    // 3. 安装协议接口
    Status = gBS->InstallMultipleProtocolInterfaces(
        &DriverHandle,
        &gEfiDevicePathProtocolGuid, &mYourMenuHiiVendorDevicePath,
        &gEfiHiiConfigAccessProtocolGuid, &mPrivateData->ConfigAccess,
        NULL
    );
    
    // 4. 添加HII包 - 重要:字符串包符号命名规则
    HiiHandle = HiiAddPackages(
        &gYourMenuFormSetGuid,
        DriverHandle,
        YourMenuDxeStrings,        # BASE_NAME + "Strings"
        YourMenuVfrBin,
        NULL
    );
    
    return Status;
}

// 驱动程序卸载函数
EFI_STATUS EFIAPI YourMenuUnload(IN EFI_HANDLE ImageHandle) {
    // 清理资源
}

⚠️ 重要注意事项:

  • 字符串包符号:BASE_NAME + “Strings”(如:YourMenuDxeStrings
  • 设备路径结构体必须在运行时初始化
  • 必须实现配置访问协议的三个函数

第七步:平台集成配置

7.1 修改平台 DSC 文件

在每个平台的 DSC 文件中添加:

LsRefCodePkg/Drivers/YourMenuDxe/YourMenuDxe.inf

7.2 修改平台 FDF 文件

在每个平台的 FDF 文件中添加:

INF LsRefCodePkg/Drivers/YourMenuDxe/YourMenuDxe.inf

第八步:构建和调试

8.1 构建命令

# 清理构建缓存(遇到奇怪错误时使用)
rm -rf Build/Ls2k3000/

# 重新构建
python build.py -p LsFwSdk/LsRefCodePkg/LsRefCodePkg.dsc -a LOONGARCH64 -t GCC5 -b DEBUG

8.2 常见错误及解决方案

错误类型错误信息解决方案
VFR编译错误undefined检查结构体名称是否一致
字符串错误No such file or directory确认UNI文件在[Sources]中
链接错误undefined reference检查字符串包符号命名
类型错误not constant改为运行时结构体初始化

✅ 成功验证标准

  1. 编译通过:无错误信息
  2. 链接成功:生成 EFI 驱动程序文件
  3. 菜单显示:在 UEFI Setup → Advanced 下看到自定义菜单
  4. 功能正常:选项可以选择和保存

📋 快速检查清单

  • INF 文件中 UNI 文件在 [Sources] 中
  • 字符串包符号命名正确(BASE_NAME + “Strings”)
  • VFR 文件中结构体名称与 SetupStru.h 一致
  • 平台 DSC/FDF 文件中添加了驱动程序引用
  • GUID 在 Loongson.dec 中注册
  • 设备路径结构体运行时初始化
UEFI Shell是一个强大的接口,允许用户在启动过程中直接与UEFI固件交互。要实现一个自定义的启动项,首先需要熟悉UEFI Shell 2.0规范,这份文档提供了关于如何在UEFI环境中使用Shell进行操作的详细信息。以下是在UEFI Shell 2.0中实现自定义启动项的步骤和注意事项: 参考资源链接:[UEFI Shell 规范2.0详解](https://wenku.csdn.net/doc/64af557f8799832548ed7db2?spm=1055.2569.3001.10343) 1. **了解Shell命令和启动脚本**:熟悉UEFI Shell中的命令,特别是那些能够修改启动项的命令,如`bcfg`命令系列。了解启动脚本的编写方式,通常这些脚本被命名为`.efi`或`.txt`文件。 2. **准备启动脚本**:编写一个启动脚本,这个脚本包含了在启动时需要执行的命令序列。脚本可以使用Shell的批处理功能或者直接通过UEFI应用程序执行。 3. **使用`bcfg`命令添加启动项**:使用`bcfg`命令将你的启动脚本或程序添加到启动菜单中。例如,使用`bcfg boot add N <path/to/your/script.efi>`命令添加一个新的启动项,其中N是启动项的编号。 4. **配置启动项属性**:通过`bcfg`命令还可以配置启动项的名称和属性,如启动优先级、可见性等。例如,`bcfg boot mod N 参考资源链接:[UEFI Shell 规范2.0详解](https://wenku.csdn.net/doc/64af557f8799832548ed7db2?spm=1055.2569.3001.10343)
内容概要:本文介绍了一种基于深度学习分类方法的时相关MIMO信道递归CSI量化技术的Matlab代码实现,旨在通过融合信道时域相关性与递归神经网络结构,采用分类策略对多输入多输出(MIMO)系统中的信道状态信息(CSI)进行高效压缩与量化,从而显著降低反馈开销并提升无线通信系统的频谱效率。该方法不仅实现了CSI的高精度重建,还结合了深度学习在非线性映射和特征提取方面的优势,增强了模型对动态时变信道的适应能力。项目配套提供了完整的仿真代码与技术文档,涵盖算法设计、训练流程与性能评估,并关联智能优化算法、路径规划、电力系统调度、无人机控制等多个工程应用场景,服务于5G/6G通信、智能通信系统等前沿科研方向。; 适合人群:具备通信原理、信号处理基础知识及Matlab编程能力,从事无线通信、MIMO系统设计、深度学习在通信中应用研究的研究生、科研人员和工程技术开发者。; 使用场景及目标:①研究MIMO系统中低开销、高效率的CSI反馈机制;②探索深度学习在时变信道建模、特征提取与量化编码中的融合应用;③为下一代移动通信系统(如5G/6G)设计高性能、低延迟的CSI压缩方案提供算法原型与仿真验证平台。; 阅读建议:建议读者结合Matlab代码深入理解模型架构与训练细节,重点关注递归网络结构与时域特征提取模块的设计逻辑,并通过对比传统量化方法评估性能增益,同时可拓展至其他信道估计与反馈优化任务中进行迁移应用。
内容概要:本文研究了基于模型预测控制(MPC)与滚动时域估计(MHE)集成的目标点镇定方法,并提供了完整的Matlab代码实现。通过融合MPC的多步优化控制能力与MHE对系统状态的高精度动态估计优势,构建了一套适用于存在模型不确定性、外部干扰或状态不可测问题的复杂动态系统的闭环控制框架,有效提升了系统在目标点镇定过程中的鲁棒性、控制精度与稳定性。研究详细阐述了MPC与MHE的数学建模过程、优化问题构建、求解算法设计及二者在反馈回路中的协同机制,并通过仿真实验验证了该集成策略在抑制扰动、补偿状态误差和实现精确镇定方面的优越性能。; 适合人群:具备一定控制理论基础和Matlab编程能力的研究生、科研人员及自动化、电气工程、机器人、航空航天等相关领域的工程技术人员。; 使用场景及目标:①应用于先进控制系统的仿真研究,如机器人轨迹镇定、飞行器姿态控制、智能车辆路径跟踪等高精度控制任务;②为MPC与MHE算法的联合设计与工程化实现提供可复现的技术参考与实践范例;③服务于高校教学演示、科研项目开发及工业控制算法原型验证,推动先进估计与控制理论的实际应用。; 阅读建议:建议读者结合Matlab代码与文本说明同步学习,重点关注MPC与MHE的协同机制、状态估计与控制输入的闭环交互过程,并可通过修改系统模型、噪声参数或优化权重进行扩展实验,以深化对算法原理的理解与工程应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值