UEFI Shell脚本开发实战工程 - 第2节
2.1 UEFI Shell 环境概述
UEFI Shell 是一个运行在 UEFI 固件层之上的交互式命令行环境,它提供了访问系统固件、内存、存储设备、网络和启动管理器等底层资源的直接接口。与操作系统中的 Shell(如 Bash、CMD)不同,UEFI Shell 在操作系统加载之前即可运行,是固件开发、系统调试和故障恢复的利器。
2.1.1 Shell 环境的组成
一个完整的 UEFI Shell 环境由以下核心组件构成:
| 组件 | 说明 | 典型文件/接口 |
|---|---|---|
| Shell 核心 | 命令解析器与执行引擎 | Shell.efi |
| 文件系统协议 | 支持 FAT12/16/32、ISO9660 等 | Simple File System Protocol |
| 设备路径 | 统一标识硬件设备的路径语法 | Device Path Protocol |
| Shell 脚本引擎 | 支持 .nsh 脚本的批处理执行 | Shell Protocol |
| 内置命令集 | 约 40 个标准 Shell 命令 | Shell 命令表 |
关键概念:UEFI Shell 不是操作系统,而是一个运行在 UEFI 引导阶段的应用程序。它依赖 UEFI 固件提供的 Boot Services 和 Runtime Services 来操作硬件。
2.2 进入 UEFI Shell 的方法
根据平台固件配置和开发阶段的不同,进入 UEFI Shell 有四种主流方式:
- 固件内置 Shell:部分 UEFI BIOS 在启动菜单中直接提供 "UEFI Shell" 选项,选择即可进入。
- 从 U 盘加载 Shell:将 Shell.efi 文件放入 FAT32 格式 U 盘的 \EFI\BOOT\BOOTX64.EFI 位置,从 U 盘引导。
- 通过 UEFI Shell 2.0 规范:在固件设置中启用 "Shell" 或 "EFI Shell" 支持,重启后按特定热键(如 F2、F12)进入。
- 使用调试工具链:通过 EDK II 编译生成 Shell.efi,利用串口或 JTAG 加载到目标板内存执行。
开发建议:在 EDK II 开发环境中,推荐使用
build -a X64 -p ShellPkg/ShellPkg.dsc 命令编译生成最新的 Shell.efi,然后放入 FAT32 U 盘使用。
2.3 Shell 基本命令与帮助系统
UEFI Shell 的命令体系分为内置命令(built-in)和外部命令(external)。内置命令固化在 Shell.efi 中,外部命令则是独立的 .efi 文件,存放在文件系统或固件卷中。
2.3.1 常用内置命令速查表
| 命令 | 功能 | 示例 |
|---|---|---|
map | 显示当前映射的设备映射表 | map -r 重新扫描设备 |
ls | 列出目录或文件 | ls fs0:\ |
cd | 切换当前目录 | cd fs0:\EFI |
type | 显示文本文件内容 | type startup.nsh |
edit | 全屏文本编辑器 | edit script.nsh |
reset | 重启系统 | reset -w 冷重启 |
help | 显示帮助信息 | help -v 详细帮助 |
alias | 管理命令别名 | alias ll "ls -l" |
set | 显示或设置环境变量 | set MyVar Hello |
echo | 输出字符串或变量值 | echo %MyVar% |
2.3.2 帮助系统的使用
UEFI Shell 提供了分层帮助系统,支持三种查询方式:
- 全局帮助:直接输入
help显示所有可用命令的简要列表。 - 命令详情:
help -d <命令名>显示指定命令的详细说明、参数和示例。 - 语法帮助:
help -v <命令名>显示命令的完整语法树和选项说明。
常见误区:UEFI Shell 命令区分大小写!所有内置命令均为小写。例如
HELP 会报错,必须使用 help。外部命令的文件名则遵循 FAT 文件系统的大小写不敏感规则。
2.4 Shell 环境架构图
下图展示了 UEFI Shell 在固件层中的位置及其与硬件、固件服务的关系:
2.5 设备映射与文件系统导航
UEFI Shell 使用 映射(Mapping) 机制来标识存储设备。每个设备被分配一个映射名称,格式为 fsX:(文件系统)或 blkX:(块设备),其中 X 从 0 开始编号。
2.5.1 设备映射示例
Shell> map -r
Mapping table
fs0: Alias(s): HD1a1b1c:;PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0xFFFF,0x0)/HD(1,MBR,0x12345678,0x800,0x100000)
fs1: Alias(s): HD2a1b1c:;PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x1,0xFFFF,0x0)/HD(1,GPT,0x87654321,0x1000,0x200000)
blk0: Alias(s): ;PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0xFFFF,0x0)
blk1: Alias(s): ;PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x1,0xFFFF,0x0)
2.5.2 文件系统导航命令
| 操作 | 命令 | 说明 |
|---|---|---|
| 切换文件系统 | fs0: | 直接输入映射名切换当前文件系统 |
| 列出目录 | ls [-l] [路径] | -l 显示详细信息(大小、属性) |
| 切换目录 | cd [路径] | 支持相对路径和绝对路径 |
| 查看当前路径 | pwd | 显示当前工作目录 |
| 创建目录 | mkdir [目录名] | 一次只能创建一个目录 |
| 删除文件 | rm [文件名] | 删除后不可恢复 |
| 复制文件 | cp [源] [目标] | 支持跨文件系统复制 |
实用技巧:使用
map -r 重新扫描设备后,新插入的 U 盘或硬盘分区会立即出现在映射表中。如果设备未显示,请检查分区格式是否为 FAT12/16/32。
2.6 Shell 环境变量与脚本基础
环境变量在 UEFI Shell 中扮演重要角色,用于存储路径、配置参数和脚本中间结果。变量名不区分大小写,但建议统一使用大写以增强可读性。
2.6.1 环境变量操作
Shell> set # 显示所有环境变量
Shell> set MyPath fs0:\EFI # 设置变量 MyPath = fs0:\EFI
Shell> set -d MyPath # 删除变量 MyPath
Shell> echo %MyPath% # 输出变量值,输出: fs0:\EFI
Shell> set -v MyPath # 显示变量属性(只读/非易失等)
2.6.2 第一个 Shell 脚本
创建一个名为 hello.nsh 的脚本文件,内容如下:
@echo -off
echo "Hello, UEFI Shell!"
echo "Current file system: %cwd%"
echo "System firmware vendor: %firmware_vendor%"
pause
在 Shell 中执行:hello.nsh 或 fs0:\hello.nsh。
脚本执行规则:Shell 脚本文件扩展名为
.nsh。执行时,Shell 逐行解释执行,支持条件判断(if)、循环(for)、goto 跳转等流程控制结构。脚本中可以使用所有内置命令和外部命令。
2.7 Shell 命令帮助系统使用流程
下图展示了从进入 Shell 到熟练使用帮助系统的典型学习路径:
2.8 本章小结
- UEFI Shell 是运行在固件层的命令行环境,提供硬件访问和系统调试能力。
- 进入 Shell 的方式包括固件内置、U 盘引导、热键进入和调试工具链加载。
- 内置命令约 40 个,涵盖文件操作、设备管理、环境变量和脚本控制。
- 帮助系统支持
help、help -d、help -v三级查询。 - 设备映射使用
fsX:和blkX:格式,通过map -r刷新。 - 环境变量用
set管理,脚本文件以.nsh为扩展名。
注意事项:UEFI Shell 对 FAT 文件系统有强依赖。如果使用 NTFS 或 exFAT 格式的 U 盘,Shell 将无法识别。始终使用 FAT32 格式的存储介质进行 Shell 开发和调试。