ที่อยู่ทางกายภาพ 0 ใน x86 Linux มีอะไรบ้าง


12

ฉันไม่แน่ใจว่าคำถามนี้ควรไปที่นี่หรือในreverseengineering.stackexchange.com

ข้อความจากวิกิพีเดีย :

ในโปรเซสเซอร์ 8086 ตารางขัดจังหวะเรียกว่า IVT (ตารางขัดจังหวะเวกเตอร์) IVT จะอยู่ที่ตำแหน่งเดียวกันในหน่วยความจำเสมอตั้งแต่ 0x0000 ถึง 0x03ff และประกอบด้วย 256 พอยน์เตอร์จริงโหมดสี่ไบต์ไบต์ (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

ฉันไม่แน่ใจว่าจะทำอย่างไรกับคุณค่าเหล่านั้น มันดูเหมือนโต๊ะตัวอธิบายอินเทอร์รัปต์ แล้วฉันกำลังดูอะไรที่นี่จริง ๆ ?

คำตอบ:


9

สิ่งที่เฟิร์มแวร์ของคุณทิ้งไว้ประกอบด้วย

ในระบบที่ทันสมัยที่สุดโปรเซสเซอร์ไม่เคยเข้าสู่โหมดจริงเลยดังที่ฉันได้อธิบายไว้ในคำถามและคำตอบของ SU: โหมดชิปพีซี Intel แบบ 64 บิตรุ่นใหม่ใช้บูตเซกเตอร์ได้อย่างไร KiB แรกของหน่วยความจำทางกายภาพนั้นไม่สำคัญเท่ากับ Johan Myréenทำให้มันกลายเป็นคำตอบในที่อื่น แต่เฟิร์มแวร์สมัยใหม่จำนวนมาก (ยัง) มีการรองรับความเข้ากันได้หมายความว่า

  • พวกเขาสามารถเลื่อนกลับ (ใช่กลับเนื่องจากพวกเขาโดยตรงจากโหมดจริงเพื่อป้องกันโหมด) จากโหมดป้องกันไปยังโหมดจริงเพื่อเรียกใช้ซอฟต์แวร์ระบบที่เขียนขึ้นสำหรับโหมดจริงเช่น PC / AT ในโหมดบูต MBRs และ VBRs; และ
  • พวกเขาจัดหา API ของเฟิร์มแวร์โหมดจริงแบบเก่าและตั้งค่าโครงสร้างข้อมูลทั้งหมดสำหรับ API เหล่านั้นซึ่งซอฟต์แวร์ระบบดังกล่าวข้างต้นพึ่งพา

โครงสร้างข้อมูลหนึ่งในนั้นคือโหมดจริง IVT API ของเฟิร์มแวร์โหมดจริงแบบเก่านั้นทำตามintคำแนะนำและ IVT ของโหมดจริงนั้นจะถูกบรรจุโดยเฟิร์มแวร์ซึ่งเป็นส่วนหนึ่งของการเริ่มต้นด้วยตัวชี้ไปยังรูทีนการจัดการเฟิร์มแวร์ต่างๆ

ซอฟต์แวร์ระบบโหมดที่ได้รับการปกป้องไม่จำเป็นต้องใช้เฟิร์มแวร์โหมดจริงแบบเก่าและไม่เคยเรียกใช้ตัวประมวลผลในโหมดจริงดังนั้นโหมดจริง IVT ใน 1KiB แรกของหน่วยความจำกายภาพจะไม่ถูกใช้ (โหมดที่ได้รับการป้องกัน v8086 ไม่ได้ระบุที่อยู่ทางกายภาพ 00000000 ขึ้นไปโปรดจำไว้ซึ่งจะระบุที่อยู่แบบลอจิคัล 00000000 และสูงกว่าซึ่งถูกแปลโดยตารางหน้า) ในระบบ EFI ที่ทันสมัยเฟิร์มแวร์จะส่งแผนที่หน่วยความจำ bootstrap โดยบอกว่าส่วนใดสงวนไว้กับเฟิร์มแวร์สำหรับจุดประสงค์ API ของโหมดป้องกันของตัวเองและส่วนใดของระบบปฏิบัติการที่มีอิสระที่จะไปข้างหน้าและใช้เป็นแหล่งรวมหน่วยความจำกายภาพ ในทางทฤษฎีหน้าแรกของหน่วยความจำกายภาพอาจอยู่ในหมวดหมู่หลัง

ในทางปฏิบัติประการแรกเฟิร์มแวร์มักจะทำเครื่องหมายหน้าแรกของหน่วยความจำกายภาพเป็น "รหัสบริการบู๊ต" ซึ่งหมายความว่าระบบปฏิบัติการสามารถอ้างสิทธิ์ได้และใช้งานเป็นส่วนหนึ่งของพูลหน่วยความจำทางกายภาพแต่หลังจากบูต บริการเวลาของเฟิร์มแวร์ EFI ถูกปิดลงโดยระบบปฏิบัติการและเฟิร์มแวร์ลดลงเพื่อให้บริการเวลาทำงานเท่านั้น ตัวอย่างนี้สามารถเห็นได้ในล็อกเคอร์เนล Linux (พร้อมadd_efi_memmapตัวเลือก) ที่แสดงโดย Finnbarr P. Murphy:

[0.000000] efi: mem00: type = 3, attr = 0xf, พิสัย = [0x00000000000000000000-0x0000000000001000) (0MB)
xe ตัวใดที่ถอดรหัสด้วยโปรแกรมอื่นในรูปแบบที่มนุษย์อ่านได้มากขึ้นเช่น:

[# 00] ประเภท: EfiBootServicesCode Attr: 0xF
      Phys: 0000000000000000-0000000000001000
      Virt: 0000000000000000-0000000000001000

ในทางปฏิบัติประการที่สอง Linux ไม่สนใจหน่วยความจำฟิสิคัลช่วงนี้แม้ว่าเฟิร์มแวร์จะบอกว่ามันสามารถใช้งานได้ต่อไป คุณจะพบว่าในเฟิร์มแวร์ทั้ง EFI และไม่ใช่ EFI เมื่อ Linux มีการแมปหน่วยความจำทางกายภาพมันจะแก้ไข ( ในชื่อฟังก์ชั่นtrim_bios_range ) ส่งผลให้ข้อความล็อกเคอร์เนลเช่น:

[0.000000] e820: อัปเดต [mem 0x00000000-0x00000fff] ใช้งานได้ ==> ลิขสิทธิ์

นี่ไม่มากที่จะรับมือกับเฟิร์มแวร์ของ EFI ที่ทันสมัยซึ่งโหมดจริง IVT ไม่ได้เป็นส่วนหนึ่งของเฟิร์มแวร์ API เนื่องจากเป็นการรับมือกับเฟิร์มแวร์ PC98 เก่าซึ่งเป็นส่วนหนึ่งของเฟิร์มแวร์ API แต่เฟิร์มแวร์รายงาน API ที่ตนเองเหมือนกัน) เป็นหน่วยความจำกายภาพที่สามารถเขียนทับได้โดยระบบปฏิบัติการ

ดังนั้นในทางทฤษฎีแล้วช่วงของหน่วยความจำกายภาพอาจมีรหัสหรือข้อมูลโดยพลการขึ้นอยู่กับความต้องการชั่วขณะของตัวจัดสรรหน่วยความจำเคอร์เนลและหน่วยความจำเสมือนที่ทำเพจตามความต้องการ ในทางปฏิบัติลีนุกซ์จะปล่อยให้มันไม่ถูกแตะต้องเท่าที่เฟิร์มแวร์ตั้งค่าไว้

และในระบบของคุณนั้นเฟิร์มแวร์นั้นบรรจุด้วยรายการ IVT โหมดจริง รายการโหมด IVT จริงเป็นเพียงตัวชี้ไกล 16:16 แน่นอนและถ้าคุณดูที่หน่วยความจำของคุณโดยใช้ hexdump 2 ไบต์คุณจะเห็นสิ่งนี้ชัดเจนจริงๆ ตัวอย่างบางส่วน:

  • รายการ IVT ส่วนใหญ่ของคุณชี้ไปที่ F000: FF53 ที่อยู่ในพื้นที่ ROM เฟิร์มแวร์โหมดจริง iretมันอาจจะเป็นงานประจำหุ่นที่ไม่ทำอะไรมากไปกว่า
  • รายการ IVT 1Eชี้ไปที่ F000: 6AA4 ซึ่งเป็นตารางในพื้นที่ ROM เดียวกันนั้น
  • รายการ IVT 1Fชี้ไปที่ C000: 8930 ซึ่งเป็นตารางในพื้นที่เฟิร์มแวร์วิดีโอโหมด ROM จริง
  • รายการ IVT 43คะแนนถึง C000: 6730 ซึ่งเป็นอีกหนึ่งตารางในพื้นที่เฟิร์มแวร์วิดีโอโหมด ROM จริง

อ่านเพิ่มเติม


ไม่ฉันหมายถึงสิ่งที่ฉันเขียน คู่มือผู้พัฒนาซอฟต์แวร์สถาปัตยกรรมซอฟต์แวร์ Intel 3 บทที่ 20 § 2.
JdeBP

ตอนนี้คุณมีเพราะมัน; ตามที่ประโยคแรกของส่วนนั้นอธิบาย ฉันสงสัยจากสิ่งนี้ว่าการไม่จดจำคำย่อทั่วไป "v8086" นั้นเป็น shibboleth (-:
JdeBP

คุณต้องเรียนรู้วิธีอ่านคำนามเชิง หรือเรียนรู้ที่จะอยู่ได้โดยไม่ต้องซุปเห็ด
JdeBP

7

สถาปัตยกรรมตัวประมวลผล 8086 ดั้งเดิม (ใช้งานเป็นโหมดจริงในตัวประมวลผล 80286+) ไม่มีความเกี่ยวข้องสำหรับ Linux ซึ่งทำงานในโหมดที่ได้รับการป้องกัน ไม่มีตารางเวกเตอร์ขัดจังหวะที่ที่อยู่จริง 0 แทนที่จะใช้ตารางอธิบายขัดจังหวะที่มีตัวอธิบายขัดจังหวะแทน IDT สามารถอยู่ที่ใดก็ได้ในหน่วยความจำ

เคอร์เนล Linux ได้รับการแม็พหน่วยความจำฟิสิคัลจากเฟิร์มแวร์ (BIOS หรือ EFI) ซึ่งจะบอกว่าเฟรมเพจหน่วยความจำฟิสิคัลใดที่สามารถใช้งานได้และถูกจองหรือไม่อยู่ ช่วงของกรอบหน้าใช้งานได้ไม่ต่อเนื่องกัน แต่โดยทั่วไปแล้วจะมีช่องโหว่ขนาดใหญ่ ตามเนื้อผ้าเคอร์เนล x86 Linux ได้ข้ามการเริ่มต้นของหน่วยความจำกายภาพแม้ว่าจะถูกทำเครื่องหมายว่าใช้งานได้ ดังนั้นฟิสิคัลแอดเดรส 0 จึงไม่ถูกใช้โดยเคอร์เนล Linux


มันสมเหตุสมผลแล้ว ความคิดใด ๆ ที่เหลือเนื้อหาในหน้าไม่ได้ใช้มาจากไหน
rhodeo

Googling สำหรับการ53 ffเปิดเผยว่านี่น่าจะเป็นจริงที่ตารางเวกเตอร์ขัดจังหวะ 8086 โหมดจริงที่ติดตั้งโดยเฟิร์มแวร์หรือบูตโหลดเดอร์
Johan Myréen

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 อาจเกี่ยวข้องกับ bootloader ทำไมฉันต้องสงสัยสิ่งนี้ โดยทั่วไปโค้ด 55aah ณ ตำแหน่ง000c0000สามารถเป็นเครื่องหมายในหน่วยความจำสำหรับสิ่งต่าง ๆ เช่นทริกเกอร์สำหรับ BIOS เพื่อเรียกใช้ bootloader สำรอง

การอ้างอิง: Boot Signature - BIOS

  เอสเอส # 1

อย่างไรก็ตามเนื่องจาก 55aah นี้เกิดขึ้นในช่วง c0000h-effffh มีแนวโน้มที่ส่วนนี้จะเป็นส่วนหัว PNP ส่วนขยาย:

ข้อมูลอ้างอิง: ข้อมูลจำเพาะการบูต BIOS

3.3 อุปกรณ์ที่มีส่วนขยาย PnP

อุปกรณ์ IPL ทั้งหมดที่มี ROM ตัวเลือกจะต้องมีส่วนหัว ROM ตัวเลือกที่ถูกต้องซึ่งอยู่ระหว่างหน่วยความจำระบบที่อยู่ C0000h และ EFFFFh ในขอบเขต 2k และเริ่มต้นด้วย 55AAh การควบคุมการบู๊ตอุปกรณ์สามารถควบคุมได้หากมีส่วนหัว PnP Expansion ส่วนหัวของส่วนขยายซึ่งมีที่อยู่อยู่ภายในส่วนหัว ROM ตัวเลือกมาตรฐานที่ออฟเซ็ต + 1Ah มีข้อมูลสำคัญที่ใช้ในการกำหนดค่าอุปกรณ์ นอกจากนี้ยังมีตัวชี้ไปยังรหัสใน ROM ตัวเลือกของอุปกรณ์ (BCV หรือ BEV) ที่ BIOS จะเรียกเพื่อบู๊ตจากอุปกรณ์ ดูภาคผนวก A สำหรับโครงสร้างของส่วนขยาย PnP มีสองวิธีที่อุปกรณ์ IPL ที่มีส่วนหัว PnP Expansion สามารถบู๊ตได้ ต้องมี BCV หรือ BEV

53ff ...

สำหรับข้อมูล 53ffh ที่เป็นจุดเริ่มต้น มันไม่ชัดเจนสำหรับฉันว่ามันคืออะไร การวิจัยเพิ่มเติมเป็นไปได้ว่าบางสิ่งที่เคอร์เนลลินุกซ์เขียนไว้หลังจากที่ bootloading BIOS ของ MBR ถูกส่งไปยังเคอร์เนล Linux เพื่อบูต

โดยปกติ bootloader จะโหลดเคอร์เนลลงในหน่วยความจำแล้วข้ามไปที่เคอร์เนล เคอร์เนลจะสามารถเรียกคืนหน่วยความจำที่ใช้โดย bootloader (เพราะมันได้ทำงานแล้ว) อย่างไรก็ตามมันเป็นไปได้ที่จะรวมรหัสระบบปฏิบัติการภายในบูตเซกเตอร์และให้มันอาศัยอยู่หลังจากที่ระบบปฏิบัติการเริ่มต้นขึ้น

การขุดต่อไปฉันสามารถค้นหาย่อหน้านี้จากรายงานการวิจัยเรื่องการฉีดโค้ดที่เป็นอันตรายผ่าน / dev / mem :

1 อุปกรณ์ mem

/ dev / mem เป็นอินเตอร์เฟสของไดรเวอร์ไปยังหน่วยความจำที่ระบุตำแหน่งทางกายภาพ จุดประสงค์ดั้งเดิมของทั้ง mem และ kmem มีไว้เพื่อช่วยในการดีบักเคอร์เนล เราสามารถใช้อุปกรณ์เช่นอุปกรณ์ตัวอักษรปกติโดยใช้ lseek () เพื่อเลือกที่อยู่ชดเชย อุปกรณ์ kmem คล้ายกัน แต่ให้ภาพของหน่วยความจำเคอร์เนลในบริบทของการกำหนดแอดเดรสเสมือน เซิร์ฟเวอร์ Xorg ใช้อุปกรณ์ mem ในการเข้าถึงหน่วยความจำวิดีโอ VESA เช่นเดียวกับ BIOS ROM Interrupt Vector Table (IVT) ที่อยู่ที่อยู่จริง 0x00000000 เพื่อจัดการโหมดวิดีโอในโหมด VM86 DOSEMU ยังใช้สิ่งนี้เพื่อเข้าถึง BIOS IVT เพื่อให้สามารถทำ BIOS Interrupts สำหรับงานต่าง ๆ (อ่านดิสก์, พิมพ์ไปยังคอนโซล, ฯลฯ )

อ้างอิง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.