之前的文章提到过,我注意到UDK2014自带的Shell 使用的是 Fsnt0 这样的盘符,而我重新编译生成的却是 Fs0 这样的盘符。今天研究和实验相关代码,解开了困扰已久的问题。
首先,这个盘符的概念不是UEFI 的,而是Shell 这个程序自己创建和分配的。于是在代码中搜索,在UefiShellCommandLib.c 找到了下面的代码:
/**
Function to generate the next default mapping name.
If the return value is not NULL then it must be callee freed.
@param Type What kind of mapping name to make.
@retval NULL a memory allocation failed.
@return a new map name string
**/
CHAR16*
EFIAPI
ShellCommandCreateNewMappingName(
IN CONST SHELL_MAPPING_TYPE Type
)
{
CHAR16 *String;
ASSERT(Type < MappingTypeMax);
String = NULL;
String = AllocateZeroPool(PcdGet8(PcdShellMapNameLength) * sizeof(String[0]));
UnicodeSPrint(
String,
PcdGet8(PcdShellMapNameLength) * sizeof(String[0]),
Type == MappingTypeFileSystem?L"FS%d:":L"BLK%d:",
Type == MappingTypeFileSystem?mFsMaxCount++:mBlkMaxCount++);
return (String);
}
可以看到,使用的是FS%d 这样的来进行分配,用重新编译Shell的方式确定这个位置。
然后我们修改代码,增加一个字符作为标记:
Type == MappingTypeFileSystem?L"FSz%d:":L"BLK%d:",
根据【参考1】进行编译,当然我们已经工作在UDK2015上,但是之前的方法仍然是可行的。编译好Shell.efi 之后,我们还要查看一下 \Nt32Pkg\Nt32Pkg.fdf 对于 Shell 的调用。看起来和之前不同了,我们猜测使用了UefiShell.inf 。
################################################################################
#
# FILE statements are provided so that a platform integrator can include
# complete EFI FFS files, as well as a method for constructing FFS files
# using curly "{}" brace scoping. The following three FILEs are
# for binary shell, binary fat and logo module.
#
################################################################################
!ifndef $(USE_OLD_SHELL)
INF ShellBinPkg/UefiShell/UefiShell.inf
!else
INF EdkShellBinPkg/FullShell/FullShell.inf
!endif
INF FatBinPkg/EnhancedFatDxe/Fat.inf
FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) {
SECTION RAW = MdeModulePkg/Logo/Logo.bmp
}
在打开UefiShell.inf 根据指引替换了 Shell.efi 为新编译出来的。再 build nt32和 build run。 得到的结果如下,可以看到,盘符发生了变化:
我们再用十六进制工具打开 shell.efi ,搜索 fsz (特别注意这是unicode不是 ascii)
因此,盘符的前缀就是在这里生成的。
然后我们再返回到 UDK2014中,打开模拟器运行结果如下:
这就是我们一直疑惑的 FsntX: 直接使用十六进制编辑工具打开 Shell_Full.efi ,搜索 Fsnt 。找到之后我们修改为 Fsnz,再保存,重新build Nt32,然后再次运行编译器,结果就发生了变化:

于是,可以解释我们之前的疑惑了:他们 Publish 的 Shell.efi 和我们拿到的并非一套代码,一些细节存在差别。
本文只相当于定性的分析,后面我们还会进行更详细的分析,到底盘符是如何来的,就是这样。
参考:
1. http://www.lab-z.com/how2buildshell/ How to build Shell.efi


