3. 文件系统与设备管理:设备路径概念、映射设备(map)、文件系统导航(cd, ls, dir)

UEFI Shell 的核心能力之一是对硬件设备与文件系统的统一管理。与操作系统不同,UEFI 环境没有盘符(C:、D:),而是通过 设备路径(Device Path) 和 映射(Mapping) 机制来定位存储设备与文件系统。本章将深入讲解设备路径的结构、map 命令的使用,以及如何在 Shell 中高效导航文件系统。

3.1 设备路径(Device Path)概念

设备路径是 UEFI 规范定义的一种标准化的、与总线无关的硬件寻址方式。每个物理或逻辑设备在固件层面都有一个唯一的设备路径。它由一系列路径节点(Path Node)组成,每个节点描述设备在总线拓扑中的位置。

关键理解: 设备路径是 UEFI 的“硬件身份证”。无论是硬盘、USB 设备、光驱还是网络适配器,都通过设备路径被唯一标识。Shell 脚本中常通过设备路径来精确指定操作目标,避免因映射别名变化导致的错误。

3.1.1 设备路径的典型结构

一个完整的设备路径通常包含以下节点类型(按顺序组合):

节点类型 描述 示例
ACPI 节点 描述系统总线(如 PCI 根桥) ACPI(PNP0A03,0)
PCI 节点 描述 PCI 设备(功能号、设备号) PCI(0x1F,0x2)
SATA 节点 描述 SATA 端口与通道 SATA(0x0,0x0,0x0)
硬盘介质节点 描述硬盘分区(MBR/GPT) HD(1,MBR,0x00000000,0x3F,0x3E8000)
文件路径节点 描述文件系统内的路径 \EFI\BOOT\BOOTX64.EFI
实战提示: 使用 devtree 命令可以查看完整的设备树结构,展示所有设备的层级关系。这是理解设备路径最直观的方式。
设备路径层级结构示例 ACPI(PNP0A03,0) PCI(0x1F,0x2) SATA(0x0,0x0,0x0) HD(1,GPT,...) 路径节点顺序 从系统总线 → 控制器 → 端口 → 分区 每个节点描述一级硬件

3.2 映射设备(map)

设备路径虽然精确,但冗长且难以记忆。UEFI Shell 提供了 映射(Mapping) 机制,为设备路径分配简短易记的别名(Alias)。map 命令是管理这些映射的核心工具。

3.2.1 map 命令常用用法

命令 功能 示例输出/说明
map 列出所有当前映射 显示所有块设备、文件系统映射
map -r 重新扫描所有总线并刷新映射 热插拔设备后使用
map fs0: 显示 fs0: 对应的完整设备路径 fs0: ... HD(1,GPT,...)
map -c 清除所有用户定义的映射 恢复默认映射状态
map -u 仅显示用户定义的映射 过滤系统默认映射

3.2.2 映射的命名规则

UEFI Shell 自动为设备分配以下类型的映射名称:

  • 文件系统映射: fs0:、fs1:、fs2: … 对应可识别的文件系统分区。
  • 块设备映射: blk0:、blk1: … 对应未格式化或无法识别的块设备。
  • 用户定义映射: 可通过 map 别名 设备路径 创建自定义别名,如 map MYDISK fs0:。
常见陷阱: 映射编号(如 fs0:)在每次启动或重新扫描后可能变化。如果脚本依赖固定映射编号,建议在脚本开头使用 map 命令动态获取目标设备的当前映射,或使用用户定义映射固定别名。

3.2.3 创建持久化映射

用户定义的映射仅在当前 Shell 会话中有效。若需持久化,可将 map 命令写入启动脚本(如 startup.nsh)或使用 set 命令配合环境变量实现。

# 创建用户定义映射
map MYHD fs0:

# 验证映射
map MYHD

# 切换到自定义映射
MYHD:
cd \EFI\BOOT

3.3 文件系统导航(cd, ls, dir)

一旦通过映射进入文件系统,就可以使用熟悉的导航命令操作目录和文件。UEFI Shell 的导航命令与 DOS/Linux 风格类似,但有一些关键差异。

3.3.1 核心导航命令对比

命令 功能 示例 注意事项
cd 切换当前目录 cd \EFI\BOOT 使用反斜杠 \ 作为路径分隔符
ls 列出目录内容(详细格式) ls -l -l 显示文件大小和属性
dir 列出目录内容(简洁格式) dir *.efi 支持通配符 * 和 ?

3.3.2 路径表示法

  • 绝对路径: 以 \ 开头,从当前文件系统根目录开始。例如:\EFI\BOOT\BOOTX64.EFI。
  • 相对路径: 不以 \ 开头,从当前工作目录开始。例如:..\..\test.nsh。
  • 当前目录: . 表示当前目录;.. 表示父目录。
  • 切换文件系统: 直接输入映射名称加冒号,如 fs1:,即可切换到另一个文件系统。

3.3.3 实战导航示例

# 查看当前所有映射
Shell> map

# 切换到第一个文件系统
Shell> fs0:
fs0:\>

# 查看根目录内容
fs0:\> ls -l
Directory of: fs0:\
01/01/2020  12:00  <DIR>         1024  EFI
01/01/2020  12:00  <DIR>         1024  TOOLS
01/01/2020  12:00         256000  startup.nsh

# 进入 EFI 目录
fs0:\> cd EFI\BOOT

# 列出所有 .efi 文件
fs0:\EFI\BOOT> dir *.efi
Directory of: fs0:\EFI\BOOT
01/01/2020  12:00         983040  BOOTX64.EFI
01/01/2020  12:00         524288  SHELLX64.EFI

# 返回根目录
fs0:\EFI\BOOT> cd \
fs0:\>
效率技巧: 使用 ls -l 可以查看文件大小和属性,对判断文件完整性很有帮助。使用 ls -s 可以按大小排序输出,便于快速定位大文件。
文件系统导航流程 步骤 1:map 查看可用映射 步骤 2:fs0: 切换到目标文件系统 步骤 3:cd \路径 导航到目标目录 步骤 4:ls / dir 查看文件列表 导航要点 • 使用 \ 作为路径分隔符 • .. 返回父目录

3.4 综合实战:设备发现与文件系统遍历

以下脚本演示了如何结合 map、cd 和 ls 编写一个自动发现并遍历所有文件系统的工具:

# 脚本:list_all_fs.nsh
# 功能:遍历所有文件系统,列出根目录内容

echo "=== 开始扫描所有文件系统 ==="

# 重新扫描总线,确保设备列表最新
map -r

# 获取所有 fs 映射并遍历
for %fs in fs0 fs1 fs2 fs3 fs4 fs5
do
  # 检查映射是否存在
  map %fs: > nul 2>&1
  if %?% == 0 then
    echo "----------------------------------------"
    echo "文件系统: %fs:"
    echo "设备路径: "
    map %fs:
    echo "根目录内容:"
    %fs:
    cd \
    ls -l
    echo ""
  endif
endfor

echo "=== 扫描完成 ==="
脚本要点:
  • map -r 确保热插拔设备被识别。
  • map %fs: > nul 2>&1 检查映射是否存在,避免访问不存在的设备导致脚本中断。
  • %?% 是 UEFI Shell 的环境变量,保存上一条命令的返回值(0 表示成功)。
  • 遍历范围可根据实际环境调整(如 fs0 到 fs9)。

3.5 本章小结

  • 设备路径 是 UEFI 硬件寻址的基础,由多个路径节点组成,精确描述设备在总线拓扑中的位置。
  • map 命令 将冗长的设备路径映射为简短别名(如 fs0:),是 Shell 脚本与硬件交互的桥梁。
  • 文件系统导航 使用 cd、ls、dir 命令,路径分隔符为反斜杠 \,支持绝对路径和相对路径。
  • 编写健壮的脚本时,应动态获取映射信息,避免硬编码映射编号。