如何通过EDKII编程实现带参数启动UEFI Shell?
解决方案
首先纠正你对协议的理解误区:EFI_SHELL_PARAMETERS_PROTOCOL 是UEFI Shell自身启动后,为后续在Shell环境中运行的第三方UEFI应用提供参数解析能力的协议,由Shell在自身初始化完成后、加载其他应用前安装。你在调用StartImage启动Shell前,Shell的代码还未执行,自然不可能找到这个协议,你之前对规范的描述存在理解偏差。
UEFI标准中所有UEFI应用的启动参数,都是通过其镜像句柄对应的EFI_LOADED_IMAGE_PROTOCOL的LoadOptions、LoadOptionsSize两个字段传递的,UEFI Shell也完全遵循这个规则,你已经拿到了Shell镜像的ImageInfo(就是该协议的实例),直接修改这两个字段即可实现带参数启动。
具体代码修改
在你现有代码的OpenProtocol拿到ImageInfo成功后、调用StartImage之前,添加如下代码即可:
// 示例参数:启动Shell后自动执行echo、ls命令,执行完成后退出 // 参数规则:第一个字段是Shell镜像名,后面跟参数,-c参数表示执行后续字符串中的命令 CONST CHAR16 *ShellArgs = L"Shell.efi -c \"echo Test parameter from loader && ls\""; // LoadOptions要求是双NULL结尾的UTF-16字符串,所以长度计算要多算2个CHAR16的位置 UINTN ArgsByteSize = (StrLen(ShellArgs) + 2) * sizeof(CHAR16); // 分配LoadOptions的内存,必须用堆内存,不可用栈内存,避免上下文切换后内存失效 Status = gBS->AllocatePool(EfiLoaderData, ArgsByteSize, &ImageInfo->LoadOptions); if (!EFI_ERROR(Status)) { StrCpy((CHAR16 *)ImageInfo->LoadOptions, ShellArgs); ImageInfo->LoadOptionsSize = ArgsByteSize; } else { Print(L"Failed to allocate load options: %r\n, fallback to no args", Status); ImageInfo->LoadOptions = NULL; ImageInfo->LoadOptionsSize = 0; }
补充说明
- Shell常用启动参数:
- 不带额外参数:直接进入交互模式
-v:启动时输出verbose日志-c "命令串":执行指定命令,执行完成后自动退出Shell,多个命令用&&分隔
- 如果你不需要在Shell退出后保留参数内存,可以在
StartImage调用返回后调用gBS->FreePool(ImageInfo->LoadOptions)手动释放内存,不手动释放也会随着Boot Services销毁自动回收。
内容的提问来源于stack exchange,提问作者CuriousSmith
相关产品推荐
相关产品推荐

