【特别提醒:下面的全部操作都是在UDK2014中完成,具体代码会与2010有差别】
第一个问题:我们运行的模拟环境(NT32)中的Shell是来自哪里?
回答:在 \Nt32Pkg\Nt32Pkg.fdf 中你可以看到下面的定义
################################################################################
#
# 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.
#
################################################################################
INF EdkShellBinPkg/FullShell/FullShell.inf
INF FatBinPkg/EnhancedFatDxe/Fat.inf
FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) {
SECTION RAW = MdeModulePkg/Logo/Logo.bmp
如果你把上面的 FullShell.inf 替换成 EdkShellBinPkg\MinimumShell 下面的MinimumShell.inf 再次编译之后会发现使用的是Mini版本的Shell. 例如: Hexedit 这个命令只在Full版本中才有,Mini版本下不支持。(实验时候特别注意,如果你 Build了 MinimumShell.inf, 在 fsnt1: 下面有一个 Hexedit.efi)
2.如何重新Build Shell.efi?
根据 ShellBinPkg 目录下的 Readme.txt (没错,我也不知道为什么是在这个目录而不是ShellPkg下面的 ReadMe.txt) ,可以使用下面的命令进行Build:
build -a IA32 -p ShellPkg\ShellPkg.dsc -b RELEASE
3.实际操作。这是我们最常见到的Shell的模样,我下面要尝试给他添加一段String.
在 \ShellPkg\Application\Shell\Shell.c 可以看到输出版本信息的语句
//
// Display the version
//
if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion) {
ShellPrintHiiEx (
0,
gST->ConOut->Mode->CursorRow,
NULL,
STRING_TOKEN (STR_VER_OUTPUT_MAIN_SHELL),
ShellInfoObject.HiiHandle,
SupportLevel[PcdGet8(PcdShellSupportLevel)],
gEfiShellProtocol->MajorVersion,
gEfiShellProtocol->MinorVersion
);
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_VER_OUTPUT_MAIN_SUPPLIER),
ShellInfoObject.HiiHandle,
(CHAR16 *) PcdGetPtr (PcdShellSupplier)
);
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_VER_OUTPUT_MAIN_UEFI),
ShellInfoObject.HiiHandle,
(gST->Hdr.Revision&0xffff0000)>>16,
(gST->Hdr.Revision&0x0000ffff),
gST->FirmwareVendor,
gST->FirmwareRevision
);
}
//
// Display the version
//
if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion) {
ShellPrintHiiEx (
0,
gST->ConOut->Mode->CursorRow,
NULL,
STRING_TOKEN (STR_VER_OUTPUT_MAIN_SHELL),
ShellInfoObject.HiiHandle,
SupportLevel[PcdGet8(PcdShellSupportLevel)],
gEfiShellProtocol->MajorVersion,
gEfiShellProtocol->MinorVersion
);
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_VER_OUTPUT_MAIN_SUPPLIER),
ShellInfoObject.HiiHandle,
(CHAR16 *) PcdGetPtr (PcdShellSupplier)
);
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_VER_OUTPUT_MAIN_UEFI),
ShellInfoObject.HiiHandle,
(gST->Hdr.Revision&0xffff0000)>>16,
(gST->Hdr.Revision&0x0000ffff),
gST->FirmwareVendor,
gST->FirmwareRevision
);
}
//LabZDebug_Start 加入我们定义的String
ShellPrintHiiEx (
-1,
-1,
NULL,
STRING_TOKEN (STR_LABZ_UEFI),
ShellInfoObject.HiiHandle
);
//LabZDebug_End
//
// Display the mapping
//
if (PcdGet8(PcdShellSupportLevel) >= 2 && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) {
Status = RunCommand(L"map", NULL);
ASSERT_EFI_ERROR(Status);
}
同时在 \ShellPkg\Application\Shell\Shell.uni 加入我们自定义的字符串
#string STR_LABZ_UEFI #language en-US "www.lab-z.com 2014/12/12 build.....\r\n"
最后的结果如下,可以看到多出来一行我们自己定义的字符串:
特别提醒:请注意文章中两张图片,实际上盘符是有差别的,一个是 FSNTx: 一个是 FSx。就是说在虚拟环境下模拟出来的盘符还是有差别的。目前我不清楚这个差别是如何导致的。
========================================================================
2015年3月31日补充
1.build shell.efi 之后生成的文件在 Build\Shell\RELEASE_MYTOOLS\IA32下面。同样他的子目录中也能找到Shell.efi (总共三个),他们内容相同
2.有一种情况是你替换了 Shell_Full.efi 之后,模拟器无法进入 shell,始终停留在Setup中。这种情况请检查输出的Log信息,我遇到的情况是因为改动有问题,导致 Shell.efi 是损坏的,无法正常Load起来。