pretty code

2020年10月26日 星期一

UEFI ShellOpt 概述

最近看 Spec 看到有點乏味,突然想到之前一直想試沒試的 ShellOpt,於是便來嘗試看看。

ShellOpt 是一個特殊的 UEFI Env Variable,照 Spec 所說,設了這個環境變數後,像是 Shell 的等待使用者按鍵時間,要不要印出版本資訊等,都可以透過這個環境變數來控制,不用像我之前一樣,需要修改 Shell.c 的預設值,編譯出自己的 Shell 執行檔。

嘗試的過程中遇到了一些問題,雖然還未完全解決,還是記錄一下遇到的問題及解決方式。

01. -delay 秒數的傳遞

-delay 是控制使用者按鍵時間的參數,當 set 指令遇到 - 符號時,會誤判為 set 的使用參數,解決方式便是把它跳脫,正常是使用 ^ 符號來跳脫特殊字元,但這裡要用 set ShellOpt "^^-delay 8" 來設定才能成功。


02. Shell 解析 Argv 不成功,如何 Debug

因為 UDK 的 code 有問題,導致無法使用使用者的設定值。為了判斷問題的地方,需要印出一些訊息,我這裡是使用下面方式來除錯。

CHAR16 DebugString[128];

UnicodeSPrint(DebugString, sizeof(DebugString), L"%02d - (%s) \r\n", LoopVar, CurrentArg);

gST->ConOut->OutputString(gST->ConOut, DebugString);

測試的結果,問題是出在最後一個 gEfiShellParametersProtocol->Argv,不知為什麼會多出一個奇怪的字串,嘗試列印來看,是一個重覆的無意義字串?也許是我還沒看懂 Shell 該段 Code 的意義,仍需要繼續嘗試。

我目前暫時的解決方式是先忽略最後一個有問題的 Argv,且傳遞給 -delay 的秒數一定要有 2 位數,不足便在前面補 0,這樣便可以解決 ShellOpt 的解析問題。


最終解決方式

下午繼續奮戰這個問題,最後確定奇怪字串是因為 set command 來的,應該是過程中底層不知道那個環節出錯?目前看來只能自己寫程式來設定此變數。

一開始試著使用 ShellSetEnvironmentVariable 來設定 ShellOpt,問題還是依舊,直到使用 gRT->SetVariable 函數,ShellOpt 的值才能順利設定,不過,當下無法反映在 set command 的顯示結果,另外 GUID 需使用 gShellVariableGuid,而不是 gEfiGlobalVariableGuid。


2020/10/27 更新

今天本來想寫支程式,抓取使用者的 argv,檢查後再幫忙設定 ShellOpt 變數。由於個人習慣使用 main Entry,故所有的字串都是使用 ASCII,本想最後再使用 UnicodeSPrintAsciiFormat 函數來轉換,無意間才發現,UEFI 在這些類似的函數中,需要使用 "%a" 來表示 ASCII 字串,而不是傳統 C 語言的 "%s",這讓我不禁思考,使用 main Entry 撰寫 UEFI Application 到底是好還是不好呢?

相關 Format 選項可以參考 MdePkg\Library\BasePrintLib\PrintLibInternal.c - BasePrintLibSPrintMarker。

https://github.com/tylpk1216/ShellOpt

2 則留言:

Leo 提到...

Hi Sir,
不知道你的 -delay 需要兩位數有沒有解
你可以透過 dmpstore -guid 158def5-656-419-027-731920792 檢查你寫入的資料
尤其是 Variable 的結尾特別要注意

tylpk 提到...

Hi Leo,

謝謝您的資訊。我後來覺得是 set command 有問題,故我放棄它改用自己的 UEFI Application 來設值,現在一切都正常。

原本是想要鑽下去看 set 發生了什麼事?後來想想就算了,反正確定是 set command 引起的,我也懶得再管它發生什麼事了XD