EFIバイトコードの理論と実践

90年代後半、当時の名声のビデオカードデザインであるNumber Nine Visual Technologyは、PCIデバイス用のWebサイトでVGA BIOSを提供しました。 このイベントには目立ったものは何もありません。 場合を除き、Number Nineビデオカードは、IBM PC互換プラットフォームとPower PCを使用するMACシステムの両方で機能します。 したがって、同じデバイスに異なるBIOSファイルが装備されていました。



ほとんどの場合、それ以外の場合はできません。 さまざまなハードウェア環境で動作するように設計されたデバイスのサポートにより、現在の状況はどうですか? この質問に対する答えは、 EFIバイトコードまたはEBCというエレガントなソリューションが提案されているフレームワーク内で、UEFI仕様によって与えられます。 これにより、ファームウェア用のクロスプラットフォームアプリケーションを作成できます。



EBCはどのように機能しますか?



UEFI規格のフレームワーク内で、レジスタタイプEFIバイトコード仮想マシンの仮想マシンのアーキテクチャ定義されています。 コマンドインタープリターは、システムボード上のファームウェアの一部です。 拡張カードのファームウェアは、理想的には、中央処理装置の命令を使用せずに、仮想マシンのコマンドシステムに書き込まれます。 したがって、拡張カードは、CPUのタイプに関係なく、EBCをサポートするマザーボード上で機能します。 今日、それらのリストはさまざまに輝いているわけではありません。いつものように、AMDとIntelは32ビット版と64ビット版、Itanium、ARMです。



EBC仮想プロセッサアーキテクチャ



64ビットEBC仮想プロセッサには、8つの汎用レジスタ(R0〜R7)が含まれ、オペランドの直接、間接、および直接アドレス指定をサポートしています。 コマンドシステムには、算術演算と論理演算、シフト、符号展開をサポートするオペランド転送、条件付きおよび無条件の制御転送、サブプログラムの呼び出しと戻り、多数の補助演算が含まれます。 スタックがサポートされますが、スタックポインター(レジスターR0)は、x86アーキテクチャーの伝統に従って、汎用レジスターとして分類されます。 CALL命令の特別な形式により、EBCサブプログラムからプラットフォームの「 ネイティブ 」言語で記述されたサブルーチンを呼び出すことができることに注意してください。 同様に、EBCプログラムから、中央処理装置のタイプに依存しない入力および出力パラメーターの送信モデルを使用して、UEFIプロトコルのサポート手順を呼び出すことができます。



実験を始める



推奨例「 こんにちは、EBC! 「EBC仮想マシンのコマンドシステム(EFIバイトコード)で記述されたUEFIアプリケーションです。 前述のように、このタイプのモジュールを実行できるEBCコマンドインタープリターは、マザーボードのUEFIファームウェアの一部です。 マシンコードの代わりにEBCを使用すると、さまざまな拡張カードのファームウェアを含むクロスプラットフォームアプリケーションとドライバーを作成でき、これらのデバイスはx86以外のアーキテクチャの中央処理装置を使用するプラットフォームと互換性があります。



例の説明



プログラムは、 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL関数セットの行出力手順を使用してテキストメッセージを表示します。 そのソースコードをさらに詳しく考えてみましょう。



スタックでこのEFI関数を呼び出すには、2つのパラメーターを渡す必要があります。使用されるプロトコルのインターフェイスユニットへのポインターと、UNICODE形式で提示される文字列へのポインターです。 これらのパラメーターはレジスターR1およびR2で準備され、最後のパラメーターからPUSHn命令によってスタックにプッシュされます。 次に、レジスタR3に、使用されるプロトコルのインターフェイスブロックから読み取られたプロシージャコールのアドレスが配置され、ターゲットライン出力プロシージャが呼び出されます。 戻った後、POPn命令でスタックを解放します。



システムテーブルとクロスプラットフォーム



UEFIプロトコルのサービス手順を呼び出すために、アプリケーションはUEFIシステムテーブルとさまざまなインターフェイスユニットにあるポインターを使用します。 32ビットUEFI実装では、サイズが4バイトのポインターが使用され、64ビットではサイズが8バイトです。 したがって、テーブル内のポインターのアドレスは、中央処理装置の容量に依存します。 クロスプラットフォームはどのように提供されますか?



レジスタR1の初期値にoffsetを加えたものに等しいアドレスを持つメモリセルの内容をレジスタR1に転送する命令の例を考えてみましょう。



MOVnw R1,@R1(+5,+24)







オフセットは、+ 5と+24の2つの用語の形式で与えられます。



最初の用語+5は、アドレス指定されたポインターの番号です。 EBCコマンドインタープリターは、この値にポインターのサイズを掛けます。これは、32ビットUEFI実装の場合は4、64ビットの場合は8です。



2番目の用語+24は、プラットフォームのタイプに依存しない定数です。 EFI_SYSTEM_TABLEテーブルのヘッダーサイズを設定するために使用されます。



呼び出されたプロシージャのスタックフレームを準備する際に使用されるPUSHn(Push Natural)命令も同様に機能します。 スタックに書き込まれるパラメーターの容量(32または64ビット)は、中央処理装置の容量に依存します。 これにより、アプリケーションのEBCコードと、中央処理装置のコマンドシステムで記述されたUEFIファームウェアの一部である手順との間のゲートウェイが提供されます。



放送と打ち上げ



プログラムブロードキャストして EBCアプリケーションを生成するには、FASM 1.69.50が使用されます。 EFI Byte Code仮想マシンの命令は、16進定数として指定されています。 私たちは、研究への関心に導かれて、意図的に高級言語の使用を放棄し、アセンブラーEBCで例を作成しました。 同時に、FASMトランスレーターがEBCをサポートしていないという事実に関連するいくつかの問題を解決する必要がありました。



ブロードキャスト後、 helloebc.efiファイルのヘッダーのアドレス84h、85h、バイト64h、86hをBCh、0Ehに置き換える必要があります。 したがって、元々8664h(x86-64マシン)が含まれていたマシンタイプフィールドは、0EBCh(EBCマシン)に置き換えられます。 UEFIシェルに組み込まれたエディターを開始するには、コマンドプロンプトでhexedit helloebc.efiと入力する必要があります。



  Machine Type



図1アプリケーションヘッダーのマシンタイプフィールドの修正



その後、アプリケーションを実行できます。







図2応募結果



アプリケーションは、Intel EBC Debuggerの下でも実行できます。



   load   EBC-



図3loadコマンドでデバッガーをロードし、Intel EBCデバッガーの下でEBCアプリケーションを起動します



まとめ



IA32 EFIおよびx64 UEFI環境でテストケースをテストしました。 理論的には、ItaniumおよびARMプロセッサを搭載したプラットフォームで動作するはずですが、これらのシステムにアクセスできないため、これを確認できませんでした。



アプリケーションはPE64(Portable Executable 64-bit)モードでブロードキャストされます。 一部のレガシーEFI実装(たとえば、ブートディスケットから起動されたIntel EFIバージョン1.10.14.59サンプル実装エミュレーター)は、このアプリケーション形式と互換性がありません。 これは、アドレスをロードするようにモジュールを構成するときに使用される再配置可能要素のテーブルの誤った解釈に反映されます。 1つの解決策は、ソフトウェアを構成することです。



FASMトランスレータはEFIバイトコードをサポートしていないため、FASM環境でEBCアセンブラレベルで効率的なプログラミングを行うには、次のことを行う必要があります。



  1. モジュールチェックサムの再計算を使用して、UEFIアプリケーションのヘッダーのマシンタイプフィールドの書き換えを自動化するための小さなユーティリティユーティリティを作成します。
  2. FASM環境でアセンブラーEBCニーモニックを使用するための一連のマクロを準備します。




情報源






All Articles