UEFI互換ファームウェアのNVRAMデバイス、パート4

読者の皆さん、こんにちは。

さまざまなUEFI実装で使用されるNVRAMストレージ形式について、 前の 3つの パートで始めた会話は、論理的な終わりに近づいています。 検証されていない形式は1つだけでした-NVARは、AMI Aptioコードベースに基づくファームウェアで使用されます。 AMI社は、かつてデスクトップおよびサーバーマザーボードのファームウェアの市場全体をほぼ「サドル化」することができたため、NVAR形式は元の「標準」VSSよりも一般的でした。

AMI NVRAMストレージ形式の長所と短所に興味がある場合は、catへようこそ。



免責事項4



繰り返しは記憶基礎であるst音の母であるため、作者はファームウェアを選ぶことは危険なことであると読者に納得させようとはしません。日(または週)。 作成者は、スリップ以外については一切責任を負いません。スリップに関する情報は、L / Cに送信することができます。リバースエンジニアリングによって得られたこの知識は、ユーザー自身の責任とリスクで使用してください。



AMI NVAR



さて、ようやく、NVRAMストレージ形式のリストの最後にたどり着きました。ヘッダーで使用される署名によってNVARを呼び出します。 前のパートで説明した他のすべての形式とは異なり、NVAR形式のデータはGUID FFF12B8D-7696-4C8B-A985-2747075B4F50 (EFI_SYSTEM_NV_DATA_FV_GUID)のボリュームに保存されませんが、GUID CEF5B9A3F476の通常のFFSファイルに保存されます-E98143E0422C (NVAR_STORE_FILE_GUID)または9221315B-30BB-46B5-813E-1B1BF4712BD3 (NVAR_EXTERNAL_DEFAULTS_FILE_GUID)。

最初のGUIDを持つファイルは、NVRAM用に特別に設計された別のボリュームに保存されます。ほとんどの場合、プライマリボリュームとバックアップの2つのボリュームがあります。 。 ファームウェアアセンブリの段階でもバックアップストレージがいっぱいになる場合がありますが、多くの場合、スペースが単純に残され、最初の起動時に作成されます(したがって、ファームウェアの更新後の最初の起動は非常に長くなる可能性があります)。 2番目のファイルはDXEボリュームに格納され、特定のプラットフォームに応じてわずかに異なる形式を持ち、メインストレージと追加ストレージの両方が回復不可能な損傷を受けた場合に一部の変数の「デフォルト」を復元するために使用されます



NVAR形式のデータはファイル内に保存されるため、UEFI FFSサービスのおかげで、最大ストレージサイズとその場所に関する情報がファームウェアですでに利用可能になっているため、AMI開発者は追加のヘッダーを作成せず、ヘッダーの直後に、パックされ、アライメントなしで、NVAR記録が開始されます。



このエントリのタイトルは次のようになります。

struct NVAR_ENTRY_HEADER { UINT32 Signature; //  NVAR UINT16 Size; //      UINT32 Next : 24; //     , //    (0  0xFFFFFF   ErasePolarity) UINT32 Attributes : 8; //   };
      
      





彼はスクリーンショットにあります:



これまでのところ、すべてが非常に単純です。最初に正しい署名はNVAR、次にレコードサイズは0x5D3、 次のフィールドは空、 属性は0x83、わかりにくい8ビットフィールドは0x00、ASCIIエンコードの変数名StdDefaultsです。



データのデータ形式は、次のように表すことができる属性フィールドのビットに大きく依存していることがわかります。
 enum NVAR_ENTRY_ATTRIBUTES { RuntimeVariable = 0x01, // ,     (       ) ,   RT AsciiName = 0x02, //     ASCII  UCS2 LocalGuid = 0x04, // GUID     ,          GUID DataOnly = 0x08, //     ,         ExtendedHeader = 0x10, //   ,      HwErrorRecord = 0x20, // ,     (       ) ,   HW AuthWrite = 0x40, // ,     (       ) , //   AV / TA EntryValid = 0x80 //  ,     ,     };
      
      





したがって、0x83 属性は実際にはEntryValid + AsciiName + RuntimeVariableであり、以前は理解できなかった8ビットのフィールドGUIDデータベースのインデックスです。 また、名前の長さはどこにも保存されないことに注意してください。データの始まりを見つけるには、毎回strlen()を呼び出す必要があります。 LocalGuid属性が1バイトのインデックスの代わりに設定された場合、16のGUID全体が存在します。GUIDデータベース(秘密をお伝えします。ファイルの最後にあり、上に向かって成長します。つまり、ゼロのGUIDは最後の16です。 NVRAMストレージを備えたファイルのバイト、最初-最後から2番目の16バイトなど)は256個までの異なるGUIDで保存できますが、これは現時点で考えられるNVRAMアプリケーションには十分であり、多くのスペースを節約します。



UEFITool NEウィンドウからも同じ:





属性値は、フォーマットが時間とともにどのように進化したかを示します。 UEFI 2.1標準以前は、NVRAM変数には3つの属性( NVBSRT)しかありませんでした。 NV属性は保存する意味がありません。 そのような変数のみがNVRAMストレージに入り、BSとRTは相互に排他的ではなく、「 正常な」変更はBSまたはBS + RTのいずれかのみであるため、これらの属性に使用されるのは1ビットのみです-RuntimeVariable 。 すばらしいことに、変数ごとに最大24ビットを節約できることがわかりました。

その後、NVRAMの物理レベルが常に信頼できるとは限らないことが判明し、破損した変数を通常の変数と区別するためにデータからチェックサムを読み取る必要があるため、 ExtendedHeaderビットが設定され、チェックサムはデータの最後のレコードの最後に保存されました。

時間が経ち、UEFI 2.1でのMicrosoftのプレッシャーの下で、 WHEA変数に使用される別の属性HWが追加されました 。 わかりました、 HwErrorRecordビットがその下にもたらされました、あなたがする必要があります。

その後、UEFI 2.3.1Cでは、変数の2つの新しい属性AVAWとともにSecureBootが予期せず追加されました。 幸いなことに、後者を保存する必要はあまりなく(そのような変数dbxが 1つしかないため)、 AuthWriteの最後の空きビットを最初に割り当てる必要がありました。

喜ぶのはそう長くはありませんでしたが、すでにUEFI 2.4では別の属性が追加されました-TAは、突然、どこにも貼り付けられませんでした。 一度に最大24ビットを節約しました。 その結果、拡張ヘッダーに追加のフィールドを作成する必要がありました。これはデータの後に保存されます。 そこで、AV / TA変数のタイムスタンプとハッシュを保存する必要がありました。



これらすべての改善の後、拡張ヘッダーは次のようになりました。
 struct NVAR_EXTENDED_HEADER { UINT8 ExtendedAttributes; //    // UINT64 TimeStamp; // ,  ExtendedAttributes | ExtTimeBased (0x20) // UINT8 Sha256Hash[32]; // ,  ExtendedAttributes | ExtAuthWrite (0x10) //  ExtendedAttributes | ExtTimeBased (0x20) // UINT8 Checksum; // ,  ExtendedAttributes | ExtChecksum (0x01) UINT16 ExtendedDataSize; //     ExtendedAttributes };
      
      





彼はスクリーンショットにあります:



合計で、拡張ヘッダーのサイズは0x2C、 チェックサムは0x10、 ハッシュはゼロ、 タイムスタンプは0x5537BB5D、 属性は0x21( ExtChecksum + ExtTimeBased )です。



変数の属性の値を取得するには、全体として分析し、変位を動的に計算し、ファイル内のいくつかの異なる場所から値を収集する必要があることがわかります。 そしてこれはまさに、長い間一度に24バイトも節約されたからです。 あなたはあなた自身のフォーマットを開発します-試合で節約するのではなく、自分自身を未来からの恩恵を受けてください!



ただし、これはすべてではありません。DataOnly属性とヘッダーのNextフィールドを考慮していないためです。 記録が実行される変数が既に存在する場合、GUID、名前、および属性を保存するために使用されます。 EntryValid属性を古いレコードから削除して新しいレコード全体を書き込む代わりに、Nextフィールドが古いレコードのヘッダーに書き込まれ、ファイルの空き領域にDataOnly属性を持つレコードが作成され 、このNextが参照し、GUIDはなくなります、名前ではなく、拡張ヘッダーがあります。 さらに、次回変数の値が書き換えられると、この一意の単一リンクリストの最初のレコードではなく、リストを拡張することで、最後のフィールドの[ 次へ]フィールドが修正されます。 そして以来 再起動ごとに更新される変数があり(同じMonotonicCounter )、すぐにこの変数のデータのコピーでNVRAMがいっぱいになり、再起動ごとにアクセスが遅くなり、スペースがないことが判明し、NVRAMドライバーを構築する必要があります。ゴミ。 なぜこれが行われるのか-別の大きな秘密、私はそのような行動の正当な理由を思い付くことができません。



UEFITool NEでは、 Go to dataアクションを追加する必要がありました。これは、 リンクタイプの変数(つまり、 Nextフィールドが空でない変数)で動作し、単一リンクリストの最後の要素を選択します。悪魔が知っていたのはいつですか?





NVRAM変数へのアクセスは、過去5年間でデスクトップとサーバーの95%でこのように機能します。 親愛なる読者、バイトを節約し、NVRAMドライバーを再度書き換えないように必死に試みて、古い形式を新しい松葉杖で重み付けした結果を見てください。



おわりに



NVAR形式について検閲が何を言っているのかわかりません。 AMIはコンパクトさを追求して他のすべてを犠牲にしましたが、最初はUEFI仕様の開発によりこの犠牲が小さく目立たないと思われた場合、形式は不可解なものから組み立てられた不可解なものから組み立てられたAbominationのローカルアナログに変わりました。 AMI NVRAMドライバーは、ストレージ内のゴミを迅速かつ静かに除去し、メインストレージが破損した場合にバックアップストレージに切り替え、破壊されたNVRAMから始め、「カバーの真下」で記録を生き延びるなど、十分に幸運です。ありがたいことではなく、むしろ反対です。

NVRAMフォーマットの話は終わりになったと思いますが、今ではほとんど私と同じように知っています。 ご清聴ありがとうございました。ファームウェア、チップ、NVRAMに成功しました。



All Articles