作者:Maxwell Li
日期:2017/12/20
未經(jīng)作者允許,禁止轉(zhuǎn)載本文任何內(nèi)容。如需轉(zhuǎn)載請(qǐng)留言。
[TOC]
16.1 Shell 的編譯與執(zhí)行
ShellPkg 目錄下包含了 Shell 的源代碼,可以通過以下命令編譯獲得 shell.efi。
build -a IA32 -p ShellPkg\ShellPkg.dsc
build -a X64 -p ShellPkg\ShellPkg.dsc
將32位或64位的 shell.efi 復(fù)制到 ESP 分區(qū)的 efi\boot 目錄下并重命名為 BootIA32.efi 或 BootX64.efi,啟動(dòng) UEFI 系統(tǒng)時(shí)就會(huì)執(zhí)行 BootIA32.efi 或 BootX64.efi 從而進(jìn)入 Shell。
該方式啟動(dòng) Shell 時(shí)通常不帶參數(shù)(使用系統(tǒng)參數(shù))。
- UEFI 進(jìn)入 Shell 時(shí),會(huì)將 Shell Protocol 安裝到 Shell 的 ImageHandle 上。然后 UEFI 系統(tǒng)中的應(yīng)用才可以使用 Shell Protocol 服務(wù)。
- 進(jìn)入 UEFI 后, Shell 首先檢查 efi\Boot\ 目錄下是否有 startup.nsh 腳本。
- 如果有,則執(zhí)行該腳本,然后進(jìn)入 Shell 命令行等待用戶輸入;
- 如果沒有,則直接進(jìn)入命令行等待用戶輸入。
- 執(zhí)行外部命令時(shí):
- Shell 先用 Load Image Protocol 將可執(zhí)行文件載入內(nèi)存生成 Image;
- 在該 Image 上安裝 Shell Parameter Protocol;
- 調(diào)用這個(gè) Image 的入口函數(shù)從而執(zhí)行該外部命令。
Shell 啟動(dòng)參數(shù):
shell.efi [ShellOpt-options] [options] [file-name [file-name-options]]
Shell 啟動(dòng)參數(shù)表
啟動(dòng)參數(shù) | 作用 |
---|---|
-nostartup | 進(jìn)入 Shell 時(shí)不執(zhí)行腳本 startup.nsh |
-noconsoleout | Shell 標(biāo)準(zhǔn)輸出不顯示 |
-noconsolein | Shell 無標(biāo)準(zhǔn)輸入 |
-delay[:n] | 指定等待 startup.nsh 啟動(dòng)的時(shí)間。默認(rèn)是5秒,-delay:0 表示立即執(zhí)行 |
-nointerrupt | 不支持 <Ctrl+C> 的終止程序功能 |
-nomap | 啟動(dòng)后不顯示塊設(shè)備的 map 信息 |
-noversion | 啟動(dòng)后不顯示 version |
-startup | 進(jìn)入 Shell 是執(zhí)行腳本 startup.nsh |
當(dāng) ShellOpt-optitions 和 options 中均不包含 -startup 時(shí),可以使用 file-name [file-name-options] 指定 Shell 啟動(dòng)后要執(zhí)行的文件。如果啟動(dòng)參數(shù)中既有 -startup 又有 file-name [file-name-options],則 file-name [file-name-options] 被忽略。
16.2 Shell 服務(wù)
Shell 為程序開發(fā)者提供了兩種使用 Shell 服務(wù)的方式:使用 Shell Protocol 和 Shell Parameters Protocol;使用 UEFIShellLib 提供的函數(shù)。
Shell Protocol 提供服務(wù)
EFI_SHELL_PROTOCOL 結(jié)構(gòu)體如下:
typedef struct _EFI_SHELL_PROTOCOL {
EFI_SHELL_EXECUTE Execute; // 執(zhí)行 Shell 命令行命令
EFI_SHELL_GET_ENV GetEnv; // 獲得環(huán)境變量的值
EFI_SHELL_SET_ENV SetEnv; // 設(shè)置環(huán)境變量的值
EFI_SHELL_GET_ALIAS GetAlias; // 獲得 Shell 命令的別名
EFI_SHELL_SET_ALIAS SetAlias; // 設(shè)置 Shell 命令的別名
EFI_SHELL_GET_HELP_TEXT GetHelpText; // 獲得 Shell 命令的幫助信息
EFI_SHELL_GET_DEVICE_PATH_FROM_MAP GetDevicePathFromMap; // 從 Map 名獲得 DevicePath
EFI_SHELL_GET_MAP_FROM_DEVICE_PATH GetMapFromDevicePath; // 從 DevicePath 獲得 Map 名
EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH GetDevicePathFromFilePath;
EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH GetFilePathFromDevicePath;
EFI_SHELL_SET_MAP SetMap; // 設(shè)置設(shè)備的 Map 名
EFI_SHELL_GET_CUR_DIR GetCurDir;
EFI_SHELL_SET_CUR_DIR SetCurDir;
EFI_SHELL_OPEN_FILE_LIST OpenFileList;
EFI_SHELL_FREE_FILE_LIST FreeFileList;
EFI_SHELL_REMOVE_DUP_IN_FILE_LIST RemoveDupInFileList;
EFI_SHELL_BATCH_IS_ACTIVE BatchIsActive; // 是否正在執(zhí)行腳本
EFI_SHELL_IS_ROOT_SHELL IsRootShell; // 是否為 Root
EFI_SHELL_ENABLE_PAGE_BREAK EnablePageBreak; // 啟動(dòng)分屏顯示模式
EFI_SHELL_DISABLE_PAGE_BREAK DisablePageBreak; // 禁止分屏顯示模式
EFI_SHELL_GET_PAGE_BREAK GetPageBreak; // 獲取當(dāng)前分屏顯示模式狀態(tài)
EFI_SHELL_GET_DEVICE_NAME GetDeviceName; // 獲取設(shè)備的名字
EFI_SHELL_GET_FILE_INFO GetFileInfo;
EFI_SHELL_SET_FILE_INFO SetFileInfo;
EFI_SHELL_OPEN_FILE_BY_NAME OpenFileByName;
EFI_SHELL_CLOSE_FILE CloseFile;
EFI_SHELL_CREATE_FILE CreateFile;
EFI_SHELL_READ_FILE ReadFile;
EFI_SHELL_WRITE_FILE WriteFile;
EFI_SHELL_DELETE_FILE DeleteFile;
EFI_SHELL_DELETE_FILE_BY_NAME DeleteFileByName;
EFI_SHELL_GET_FILE_POSITION GetFilePosition;
EFI_SHELL_SET_FILE_POSITION SetFilePosition;
EFI_SHELL_FLUSH_FILE FlushFile;
EFI_SHELL_FIND_FILES FindFiles;
EFI_SHELL_FIND_FILES_IN_DIR FindFilesInDir;
EFI_SHELL_GET_FILE_SIZE GetFileSize;
EFI_SHELL_OPEN_ROOT OpenRoot; // 打開設(shè)備的根目錄
EFI_SHELL_OPEN_ROOT_BY_HANDLE OpenRootByHandle; // 打開 Handle 指定的設(shè)備根目錄
EFI_EVENT ExecutionBreak; // 用戶按下“Ctrl+C”時(shí)觸發(fā)該事件
UINT32 MajorVersion;
UINT32 MinorVersion;
// Added for Shell 2.1
EFI_SHELL_REGISTER_GUID_NAME RegisterGuidName;
EFI_SHELL_GET_GUID_NAME GetGuidName;
EFI_SHELL_GET_GUID_FROM_NAME GetGuidFromName;
EFI_SHELL_GET_ENV_EX GetEnvEx;
} EFI_SHELL_PROTOCOL;
EFI_SHELL_PROTOCOL 的 Execute 服務(wù)函數(shù)原型如下:
typedef EFI_STATUS (EFIAPI *EFI_SHELL_EXECUTE) (
IN EFI_HANDLE *ParentImageHandle, // 執(zhí)行 Execute 函數(shù)的 ImageHandle
IN CHAR16 *CommandLine OPTIONAL, // Shell 命令行命令
IN CHAR16 **Environment OPTIONAL, // 環(huán)境變量
OUT EFI_STATUS *StatusCode OPTIONAL // Shell 命令返回值
);
該函數(shù)會(huì)啟動(dòng)一個(gè)子 Shell,并在子 Shell 中執(zhí)行指定命令,命令的退出碼將作為 Execute 函數(shù)的返回值。
- 參數(shù) ParentImageHandle 是執(zhí)行 Execute 命令的 Image 的 ImageHandle,通常是 gImageHandle;
- 參數(shù) CommandLine 是啟動(dòng) Shell 時(shí)的命令行參數(shù);
- 參數(shù) Environment 是字符串?dāng)?shù)組,數(shù)組以 NULL 為最后一項(xiàng),其余每一項(xiàng)表示一個(gè)環(huán)境變量,格式為 Var=Value;
- 如果 Environment 為 NULL,當(dāng)前的環(huán)境變量會(huì)傳遞到子 Shell 中,從子 Shell 返回時(shí),對(duì)環(huán)境變量的更改被保存。
- 如果 Environment 不為 NULL,子 Shell 使用指定的環(huán)境變量,從子 Shell 返回時(shí),對(duì)環(huán)境變量的更改被丟棄。
- 參數(shù) StatusCode 是 Shell 命令的返回值,該返回值通過 exit 命令設(shè)置。
基本上對(duì)于所有 Shell Protocol 中的函數(shù),在 UefiShellLib 中都有與之對(duì)應(yīng)的函數(shù)。例如 Shell Protocol 中的 Execute 函數(shù), UefiShellLib 提供了對(duì)應(yīng)的 ShellExecute 函數(shù),函數(shù)原型如下:
EFI_STATUS EFIAPI ShellExecute (
IN EFI_HANDLE *ParentHandle,
IN CHAR16 *CommandLine OPTIONAL,
IN BOOLEAN Output OPTIONAL,
IN CHAR16 **EnvironmentVariables OPTIONAL,
OUT EFI_STATUS *Status OPTIONAL
)
Output 為 TURE,表示現(xiàn)實(shí)調(diào)試信息。
UefiShellLib 的初始化
gEfiShellProtocol 是 EFI_SHELL_PROTOCOL* 類型的變量,由 UefiShellLib 提供。Library 可以提供構(gòu)造函數(shù),構(gòu)造函數(shù)在 ENTRY_POINT 之前執(zhí)行。在 UefiSHellLib 的工程文件中定義了 CONSTRUCTOR 和 DESTRUCTOR。引用 UeifShellLib 時(shí),“Status=ShellLibConstructor(ImageHandle, SystemTable);”會(huì)被添加到 ProcessLibraryConstructorList 函數(shù)中,從而在調(diào)用 ShellAppMain 之前執(zhí)行。
16.3 Shell 腳本
在 UEFI Shell 中可以執(zhí)行 Shell 腳本,Shell 腳本是以 .nsh 為擴(kuò)展名的文件,在腳本中可以執(zhí)行 Shell 命令和外部命令,也可以使用內(nèi)置的流程控制命令 for、endfor、goto、if、else、endif、exit。
if 語句比較運(yùn)算符
運(yùn)算符 | 含義 |
---|---|
gt | 大于 |
lt | 小于 |
ne | 等于 |
ugt | 無符號(hào)值大于 |
ult | 無符號(hào)值小于 |
eq | 相等 |
ge | 大于或等于 |
le | 小于或等于 |
= = | 相等 |
uge | 無符號(hào)值大于或等于 |
ule | 無符號(hào)值小于或等于 |
if語句布爾函數(shù)說明
布爾函數(shù) | 當(dāng)返回值為 TRUE 時(shí) | 當(dāng)返回值為 FALSE 時(shí) |
---|---|---|
isInt(para) | para 是數(shù)字 | para 不是數(shù)字 |
Exists file | file 存在 | file 不存在 |
Avaliable file | file 存在于 path 指定的目錄或當(dāng)前目錄 | 均不存在 |
Profile para | para 匹配 profile 中某項(xiàng) | para 不匹配 profile 中任一項(xiàng) |
16.4 Shell 內(nèi)置命令
16.4.1 調(diào)試設(shè)備的相關(guān)命令
deme 命令用于查看內(nèi)存或設(shè)備內(nèi)存。address、size 都是十六進(jìn)制數(shù),-MMIO 指定地址為設(shè)備內(nèi)存。
dmem [-b] [address] [size] [-MMIO]
mm 命令用于查看或修改 MEM(系統(tǒng)內(nèi)存)、MMIO(設(shè)備內(nèi)存)、IO(寄存器)、PCI(PCI 配置空間)、PCIE(PCIE 配置空間)。
mm address [value] [-w 1|2|4|8] [-MEM| -MMIO | -IO | -PCI | -PCIE] [-n]
address 為地址;value 為要寫入的值;-w 后跟訪問寬度;-n 表示非交互模式,若不指定 -n,則該命令會(huì)進(jìn)入交互模式。
pci 命令顯示 PCI 設(shè)備列表或顯示 PCI 配置空間。
pci [Bus Dev [Func] [-s Seg] [-i]]
不帶參數(shù)的 pci 命令用于列出所有 PCI 設(shè)備。帶參數(shù)時(shí),總線號(hào)(Bus)\設(shè)備號(hào)(Dev)\功能號(hào)(Func)用于指定 PCI 設(shè)備。-s Seg 用于指定 Segment。Func 和 Seg 默認(rèn)值為0。
16.4.2 驅(qū)動(dòng)相關(guān)命令
dh 命令用于列出系統(tǒng)中的所有設(shè)備信息,或某個(gè)設(shè)備的相關(guān)信息。
dh [-l<lang>] [handle | -p <prot_id>] [-d] [-v]
- -l<lang> 表使用指定的語言顯示。
- handle 是指 UEFI Handle 在系統(tǒng)中的編號(hào)。
- -p <prot_id> 列出所有安裝了 protocol prot_id 的設(shè)備信息。
- -d 用于列出驅(qū)動(dòng)相關(guān)信息。
- -v 用于輸出 verbose 信息。
device 命令用于顯示所有被驅(qū)動(dòng)管理的設(shè)備。
drivers 命令用于列出系統(tǒng)中的 driver。
Connect 命令用于加載驅(qū)動(dòng)到設(shè)備上并啟動(dòng)加載的驅(qū)動(dòng)。
Connect [[DeviceHandle] [DriverHandle] | [-c] | [-r]]
- -c 用于連接控制臺(tái)設(shè)備。
- -r 用于遞歸掃描所有 handle,發(fā)現(xiàn)匹配的設(shè)備和驅(qū)動(dòng)就加進(jìn)來,沒有 -r,新產(chǎn)生的設(shè)備將不會(huì)被連接。
load 命令用于加載驅(qū)動(dòng)。
load [-nc] file [file2 ...]
-nc 表示只加載驅(qū)動(dòng)到內(nèi)存,不進(jìn)行 connect。不帶 -nc 選項(xiàng)時(shí),load 加載驅(qū)動(dòng)后會(huì)調(diào)用 connect 將該驅(qū)動(dòng)加載到匹配的設(shè)備上。
unload 命令用于將驅(qū)動(dòng)從內(nèi)存中清楚。
unload [-n] [-v] Handle
-n 表示在執(zhí)行 unload 過程中跳過所有提示信息,不需要用戶確認(rèn)。
16.4.3 網(wǎng)絡(luò)相關(guān)命令
ifconfig 命令用于配置網(wǎng)絡(luò)設(shè)備。
ifconfig [-?] [-c [Name]] [-l [Name]] [-s <Name> dhcp | <static <IP><MASK><Geteway>> [permanent]]
- Name是網(wǎng)絡(luò)適配器的名字。
- -c 用于清除網(wǎng)絡(luò)適配器的配置。
- -l 用于列出網(wǎng)絡(luò)適配器的配置。
- -s 用于設(shè)備網(wǎng)絡(luò)適配器的IP地址。
ping命令用于 ping 目標(biāo)機(jī)器。
ping [ -n number] [-l size] TargetIP
- -l size 用于發(fā)送 size 字節(jié)的數(shù)據(jù)。
- -n number 表示發(fā)送數(shù)據(jù)的次數(shù)。