之前的文章提到过,我注意到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