web-dev-qa-db-ja.com

EFIスタートアップシェルスクリプトでのエラー処理

UEFIファームウェアが付属しているDellOptiPlex 9010というコンピューターを使用していますが、PCI-ExpressNVMeデバイスからの起動はサポートされていません。

[〜#〜] duet [〜#〜] を使用してこれを回避し、USBスティック上にEFIブートパーティションを作成します。このパーティションにはNVMeドライバーがロードされ、実行されます。 OSのEFIブートプログラム。

これを行うためのコマンドは現在手動で入力されています。プロセスは次のとおりです。

  1. コンピューターの電源がオフになっています。
  2. DUET USBスティックをUSBポートに挿入します(私は常にプラグを差し込んだままにします)
  3. コンピューターの電源を入れます
  4. (UEFIは、常に最初にそのUSBスティックから起動し、接続した他のドライブのブートローダーを無視するように構成されています)
  5. DUET USBスティックはEFIシェルをロードします(_EFI Shell version 2.31 [4.653]_)
  6. mapコマンドは、DUET USBスティックが_fs0:_に自動的にマウントされることを示しています)
  7. NVMeドライバーをロードします:_load fs0:\EFI\Drivers\NvmExpressDxe-64.efi_
  8. _map -r_を使用してボリュームマッピングの更新をトリガーします。このコマンドは問題なく正常に完了します。
  9. (私のNVMeボリュームは、_fs1:_として表示されることもあれば、_fs0:_として表示されることもあります)
  10. 次のコマンドを実行してWindowsを起動します:_fs1:\EFI\Boot\Bootx64.efi_
  11. Windowsの起動画面が表示され、コンピュータはWindowsの起動を再開します

コマンドを_startup.nsh_スクリプト(DOSの_autoexec.bat_に相当するEFI)内に配置することにより、これを自動化しようとしました。

私のスクリプトはこれです:

_echo Step 1
load fs0:\EFI\Drivers\NvmExpressDxe-64.efi
echo Step 2
map -r
echo Step 3
fs0:
echo Step 4
fs0:\EFI\Boot\Bootx64.efi
echo Step 5
_

(このスクリプトは、_fs0:_の代わりに_fs1:_を使用します。これは、_startup.nsh_が実行されると、NVMeドライブが_fs0:_に再マップされるためですが、コマンドをインタラクティブに実行すると、代わりに_fs1:_。なぜ、どのようにこれが起こるのかわかりません)。

起動してシェルに_startup.nsh_を実行させると、次の出力が得られます。

_startup.nsh> Step 1
startup.nsh> load fs0:\EFI\Drivers\NvmExpressDxe-64.efi
load: Image fs0:\EFI\Drivers\NvmExpressDxe-64.efi loaded at D7C3F000 - Success
startup.nsh> Step 2
startup.nsh> map -r
Device mapping table
  fs0  :PciRoot(0x0)/Pci(0x1c,0x4)/...
  fs1  :PciRoot(0x0)/Pci(0x1c,0x4)/...
  blk0 :PciRoot(0x0)/Pci(0x1c,0x4)/...
  ...
Shell: Cannot read from file - No Media
Shell> _
_

したがって、_map -r_が_startup.nsh_内から実行されると、実行されますが、「ファイルから読み取ることができません-メディアがありません」エラーで失敗し、スクリプトの残りの部分の実行が中止されます( _echo Step 3_出力)、ただし、手動で_fs0:\EFI\Boot\Bootx64.efi_コマンドを入力すると、Windowsは正常にロードされます。

EFIシェルコマンドのドキュメントを確認しましたが、try、_on error resume next_、_on error goto :label_のようなコマンドが見当たらないため、スクリプトは失敗する運命にあります。

1
Dai

map -rが起動スクリプトを壊していることを確認できます。

これは、再マッピングによってスクリプトの場所が変更され、シェルが次に実行するコマンドを読み取れないために発生します。これは、EFIシェルモードを変更し、マッピングの更新方法を使用することで修正できます。

つまり、map -rの代わりに、次のことを試してください。

connect -r
set -v efishellmode 1.1.2
map -u
1
Filip

私見、あなたのアプローチは非常に複雑です。コンピューターの組み込みEFIのCSMを使用して、外部ディスクから2番目のEFI実装を実行し、2番目のEFI実装にEFIドライバーをロードしています。私にはいくつかの選択肢があります。

  • コンピューターのネイティブEFIでEFIシェルを実行し、そこからスクリプトを実行してEFIドライバーをロードできます。これにより、CSMと2番目のEFI実装が削減され、起動時間が短縮され、信頼性が向上します。そうは言っても、このオプションはおそらくあなたが見ているのと同じ問題を引き起こすでしょう。
  • コンピューターのネイティブEFIでmy rEFInd を実行し、rEFIndが自動的にロードするドライバーとしてドライバーを構成できます。これに関する大きな注意点は、rEFIndのドライバー読み込みコードはファイルシステムで十分にテストされていますが、他のタイプのドライバーではテストされていないため、ドライバーが読み込まれるとは約束できません。また、ドライバーが読み込まれたとしても、すでに発生している問題と同様の問題が発生する可能性があります。
  • ブートローダー、および必要に応じてOSカーネルを、ネイティブEFIが読み取ることができるメディアに配置して、NVMeドライバーの必要性を回避することができます。すでにDUET用のUSBフラッシュドライブを使用しているので、それを使用できます。または、おそらくお使いのコンピュータは他のタイプのハードディスクをサポートしているので、プライマリストレージタイプでなくても、そのうちの1つを使用できます。私はWindowsの専門家ではないため、これを行うためにWindowsをレイアウトする方法を具体的に提案することはできません。

とはいえ、あなたの直接の質問に対する答えはわかりません。これは明らかに、新しいドライバーをロードしたときにデバイスが再マッピングされ、シェルから「ラグが引き出される」ことが原因です。

0
Rod Smith