x86 Linuxの物理アドレス0には何が含まれますか?


12

この質問がここに行くのか、reverseengineering.stackexchange.comに行くのかわからない

ウィキペディアからの引用:

8086プロセッサでは、割り込みテーブルはIVT(割り込みベクターテーブル)と呼ばれます。IVTは常にメモリ内の同じ場所にあり、0x0000〜0x03ffの範囲で、256個の4バイトリアルモードfarポインター(256×4 = 1024バイトのメモリ)で構成されています。

これは私がqemuモニターで見つけたものです:

(qemu) xp/128xw 0
0000000000000000: 0xf000ff53 0xf000ff53 0xf000e2c3 0xf000ff53
0000000000000010: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000020: 0xf000fea5 0xf000e987 0xf000d62c 0xf000d62c
0000000000000030: 0xf000d62c 0xf000d62c 0xf000ef57 0xf000d62c
0000000000000040: 0xc0005526 0xf000f84d 0xf000f841 0xf000e3fe
0000000000000050: 0xf000e739 0xf000f859 0xf000e82e 0xf000efd2
0000000000000060: 0xf000d648 0xf000e6f2 0xf000fe6e 0xf000ff53
0000000000000070: 0xf000ff53 0xf000ff53 0xf0006aa4 0xc0008930
0000000000000080: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000090: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000c0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000d0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000e0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000100: 0xf000ec59 0xf000ff53 0xf000ff53 0xc0006730
0000000000000110: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000120: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000130: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000140: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000150: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000160: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000170: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000180: 0x00000000 0x00000000 0x00000000 0x00000000
0000000000000190: 0x00000000 0x00000000 0x00000000 0xf000ff53
00000000000001a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001c0: 0xf000d611 0xf000ec4e 0xf000ec4e 0xf000ec4e
00000000000001d0: 0xf000d61a 0xf000d623 0xf000d608 0xf000ec4e
00000000000001e0: 0xf000ff53 0x00000000 0xf000ff53 0xf000ff53
00000000000001f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53

これらの値をどうするかはわかりません。割り込み記述子テーブルのようには見えません(これらの値を逆参照すると、すべてnullになります)。だから私は実際にここで何を見ていますか?

回答:


9

ファームウェアに含まれているものは何でも。

理想的な最新のシステムでは、このSU Q&Aで説明したように、プロセッサがリアルモードに移行することはありません。最新の64ビットIntelチップPCはどのセクターでブートセクターを実行しますか 、物理メモリの最初のKiBは、JohanMyréenがここで別の答えを見つけたのと同じくらい無関係です。しかし、多くの最新のファームウェア(まだ)には互換性サポートがあり、

  • 古いモードのPC / ATブートプログラムなど、リアルモード用に記述されたシステムソフトウェアを実行するために、保護モードからリアルモードに戻る(はい、戻る、非リアルモードから保護モードに直接移行した場合) MBRおよびVBR。そして
  • これらは古いリアルモードファームウェアAPIを提供し、前述のシステムソフトウェアが依存しているAPIのすべてのデータ構造をセットアップします。

これらのデータ構造の1つは、リアルモードIVTです。古いリアルモードファームウェアAPIはint命令に基づいており、リアルモードIVTは、それらの命令のさまざまなファームウェア処理ルーチンへのポインターを使用して、初期化の一部としてファームウェアによって読み込まれます。

保護モードのシステムソフトウェアは古いリアルモードファームウェアAPIを必要とせず、プロセッサをリアルモードで実行することはないため、物理メモリの最初の1KiBのリアルモードIVTは使用されません。(v8086保護モードは、物理アドレス00000000以上をアドレスしません。ページテーブルによって変換される論理アドレス00000000以上をアドレスします。)現代のEFIシステムでは、ファームウェアは物理メモリのメモリマップをオペレーティングシステムに渡します。ブートストラップ。どのパーツが独自のプロテクトモードAPIの目的のためにファームウェアに予約されているか、およびオペレーティングシステムが物理メモリーのプールにそのまま使用できるパーツを伝えます。理論的には、物理​​メモリの最初のページは後者のカテゴリに含まれます。

実際には、まず、ファームウェアは、多くの場合、オペレーティングシステムがあることを意味し、「ブート・サービス・コード」などの物理メモリの最初のページをマークすることができ、それを主張し、ちょうど先に行くと、その物理的なメモリプールの一部としてそれを使用するだけで後 boot- EFIファームウェアのタイムサービスはオペレーティングシステムによってシャットダウンされ、ファームウェアはランタイムサービスのみを提供するように削減されました。この例はadd_efi_memmap、Finnbarr P. Murphyが表示するLinuxカーネルログ(オプション付き)で確認できます。

[0.000000] efi:mem00:type = 3、attr = 0xf、range = [0x0000000000000000-0x0000000000001000)(0MB)
次のように、xeはより人間が読める形式の別のプログラムでデコードします。

[#00]タイプ:EfiBootServicesCode Attr:0xF
      物理:0000000000000000-0000000000001000
      仮想:0000000000000000-0000000000001000

第二に、Linuxは、ファームウェアが先に進んで使用できると言っていても、この範囲の物理メモリを明示的に無視します。EFIファームウェアと非EFIファームウェアの両方で、Linuxが(という名前の関数でtrim_bios_range)物理メモリマップにパッチを適用すると、次のようなカーネルログメッセージが表示されることがわかります。

[0.000000] e820:アップデート[mem 0x00000000-0x00000fff]使用可能==>予約済み

これは、リアルモードIVTがファームウェアAPIの一部ではない最新のEFIファームウェアに対処することではありません。古いPC98ファームウェアに対処するためです。ファームウェアAPIの一部であるが、ファームウェアは(その自己同一のAPI)は、オペレーティングシステムによって簡単に上書きできる物理メモリとして利用できます。

そのため、理論上は、カーネルメモリアロケータとデマンドページ仮想メモリの一時的なニーズに応じて、物理メモリの範囲に任意のコードまたはデータを含めることができます。実際には、Linuxはファームウェアが最初に設定したので、そのまま残します。

お使いのシステムでは、ファームウェアにリアルモードIVTエントリが入力されています。もちろん、リアルモードのIVTエントリは16:16のポインターだけです。2バイトの16進ダンプを使用してメモリを見ると、実際にこれをはっきりと見ることができます。いくつかの例:

  • ほとんどのIVTエントリは、リアルモードファームウェアROM領域のアドレスであるF000:FF53を指します。それはたぶんiret
  • IVTエントリ1Eは、同じROM領域のテーブルであるF000:6AA4を指します。
  • IVTエントリ1Fは、リアルモードビデオROMファームウェア領域のテーブルであるC000:8930を指します。
  • IVTエントリ43は、リアルモードビデオROMファームウェア領域の別のテーブルであるC000:6730を指します。

参考文献


いいえ、私が書いたことを意味します。 Intel Architecture Software Developers 'Manual volume 3
Chapter 20§2

そうですね そのセクションの最初の文で説明しています。このことから、一般的な略語「v8086」を認識しないことは一種のシボレスであると思われます。(-:
JdeBP

限定名詞の読み方を学ぶ必要があります。または、キノコのスープなしで生きることを学びます。
JdeBP

7

元の8086プロセッサアーキテクチャ(80286+プロセッサのリアルモードとして実装)は、保護モードで動作するLinuxには関係ありません。物理アドレス0には割り込みベクタテーブルがありません。代わりに、割り込み記述子を含む割り込み記述子テーブルが使用されます。IDTはメモリ内のどこにでも配置できます。

Linuxカーネルは、ファームウェア(BIOSまたはEFI)から物理メモリマップを取得します。これは、使用可能な物理メモリページフレームと予約済みまたは存在しないフレームページを示します。使用可能なページフレームの範囲は連続していませんが、通常は大きな穴があります。従来、x86 Linuxカーネルは、使用可能とマークされていても、物理メモリの開始をスキップしていました。したがって、物理アドレス0はLinuxカーネルでは使用されません。


意味あり。その未使用のページの残りのコンテンツが何であるかはわかりませんか?
ロデオ

グーグル53 ffは、これが実際にはほとんどの場合、ファームウェアまたはブートローダーによってセットアップされた8086リアルモード割り込みベクトルテーブルであることを明らかにします。
ヨハンMyréen18年

4

ダンプメモリ

以下は、システム内のメモリの内容をダンプする代わりに、外部で行う必要がある代替方法です。

$ head /dev/mem | hexdump -C
00000000  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
00000010  53 ff 00 f0 53 ff 00 f0  cc e9 00 f0 53 ff 00 f0  |S...S.......S...|
00000020  a5 fe 00 f0 87 e9 00 f0  53 ff 00 f0 46 e7 00 f0  |........S...F...|
00000030  46 e7 00 f0 46 e7 00 f0  57 ef 00 f0 53 ff 00 f0  |F...F...W...S...|
00000040  22 00 00 c0 4d f8 00 f0  41 f8 00 f0 fe e3 00 f0  |"...M...A.......|
00000050  39 e7 00 f0 59 f8 00 f0  2e e8 00 f0 d4 ef 00 f0  |9...Y...........|
00000060  a4 f0 00 f0 f2 e6 00 f0  6e fe 00 f0 53 ff 00 f0  |........n...S...|
00000070  ed ef 00 f0 53 ff 00 f0  c7 ef 00 f0 ed 57 00 c0  |....S........W..|
00000080  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
...
...
000afea0  00 00 00 00 00 00 00 00  aa aa aa 00 aa aa aa 00  |................|
000afeb0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000b0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
000c0000  55 aa 40 e9 62 0a 00 00  00 00 00 00 00 00 00 00  |U.@.b...........|
000c0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 49 42  |..............IB|

分析

000c0000の上の部分は、ブートローダーに関連する可能性があります。なぜこれを疑うのですか?場所のコード55aah 000c0000は通常、BIOSがセカンダリブートローダーを実行するためのトリガーなど、メモリ内のマークになります。

参照:ブート署名-BIOS

  ss#1

ただし、この55aahがc0000h-effffhの範囲で発生する場合、この部分はPNP拡張ヘッダーである可能性が高くなります。

参照:BIOSブート仕様

3.3 PnP拡張ヘッダーを備えたデバイス

オプションROMを備えたすべてのIPLデバイスには、2k境界のシステムメモリアドレスC0000hとEFFFFhの間にあり、55AAhで始まる有効なオプションROMヘッダーが含まれている必要があります。デバイスの起動は、PnP拡張ヘッダーがある場合にのみ制御できます。アドレスがオフセット+ 1Ahの標準オプションROMヘッダー内にある拡張ヘッダーには、デバイスの構成に使用される重要な情報が含まれています。BIOSがデバイスから起動するために呼び出すデバイスのオプションROM(BCVまたはBEV)のコードへのポインターも含まれています。PnP拡張ヘッダーの構造については、付録Aを参照してください。PnP拡張ヘッダーを持つIPLデバイスを起動するには、2つの方法があります。BCVまたはBEVが含まれている必要があります。

53ff ...

先頭にある53ffhデータについて。それが実際に何であるかは私にはわかりません。さらに調査すると、BIOSによるMBRのブートローディングがLinuxカーネルに渡されて起動した後に、Linuxカーネルがそこに書き込んだ可能性があります。

通常、ブートローダーはカーネルをメモリにロードし、カーネルにジャンプします。カーネルは、ブートローダーによって使用されたメモリを再利用できます(すでにジョブを実行しているため)。ただし、ブートセクター内にOSコードを含め、OSの開始後も常駐させることは可能です。

さらに掘り下げると、/ dev / memを介したMalicious Code Injectionというタイトルの研究論文からこの段落を見つけることができました。

1 memデバイス

/ dev / memは、物理的にアドレス可能なメモリへのドライバーインターフェイスです。memとkmemの両方の本来の目的は、カーネルのデバッグを支援することでした。lseek()を使用してアドレスオフセットを選択し、通常のキャラクターデバイスのようにデバイスを使用できます。kmemデバイスも同様ですが、仮想アドレッシングのコンテキストでカーネルメモリのイメージを提供します。Xorgサーバーはmemデバイスを使用してVESAビデオメモリと物理アドレス0x00000000にあるBIOS ROM割り込みベクターテーブル(IVT)にアクセスし、VM86モードでビデオモードを操作します。また、DOSEMUはこれを使用してBIOS IVTにアクセスし、さまざまなタスク(ディスクの読み取り、コンソールへの印刷など)のためにBIOS割り込みを行うことができます。

参照資料

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.