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 有四种主流方式:

  1. 固件内置 Shell:部分 UEFI BIOS 在启动菜单中直接提供 "UEFI Shell" 选项,选择即可进入。
  2. 从 U 盘加载 Shell:将 Shell.efi 文件放入 FAT32 格式 U 盘的 \EFI\BOOT\BOOTX64.EFI 位置,从 U 盘引导。
  3. 通过 UEFI Shell 2.0 规范:在固件设置中启用 "Shell" 或 "EFI Shell" 支持,重启后按特定热键(如 F2、F12)进入。
  4. 使用调试工具链:通过 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 在固件层中的位置及其与硬件、固件服务的关系:

UEFI Shell 环境架构 UEFI Shell 环境架构 硬件层(CPU / 内存 / 外设 / 存储 / 网络) UEFI 固件层 Boot Services | Runtime Services | 协议栈 | 设备驱动 UEFI Shell 应用程序(Shell.efi) 命令解析器 | 脚本引擎 | 环境变量 | 别名管理 用户交互(命令行 / .nsh 脚本) Shell 通过 UEFI 协议调用固件服务,间接操作硬件,不直接访问 I/O 端口或物理内存

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 到熟练使用帮助系统的典型学习路径:

Shell 帮助系统使用流程 Shell 帮助系统使用流程 进入 UEFI Shell 输入 help 查看命令列表 help -d <命令名> 查看详细说明 help -v <命令名> 查看完整语法树

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 开发和调试。