Linux啟動時如何定位BIOS提供的ACPI表
Linux啟動時如何定位BIOS提供的ACPI表
來自專欄河馬虛擬化3 人贊了文章
ACPI(Advanced Configuration and Power Interface)是在系統啟動階段由BIOS/UEFI收集系統各方面信息並創建的,它大致以樹形的組織形式(如下圖所示)存在系統物理內存中。
載入超時,點擊重試
整個ACPI表以RSDP(Root System Descriptor Pointer Table)為入口點,每個非葉子節點都會包含指向其他子表的指針,各個表都會有一個表頭,在該表頭中包含了相應的Signature,用於標識該表,有點類似與該表的ID,除此之外,在表頭中還會包含Checksum、Revision、OEM ID等信息。所以查找ACPI表的關鍵就是在內存中定位到RSDP表。
對於基於Legacy BIOS的系統而言,RSDP表所在的物理地址並不固定,要麼位於EBDA(Extended BIOS Data Area)(位於物理地址0x40E)的前1KB範圍內;要麼位於0x000E0000 到0x000FFFFF的物理地址範圍內。Linux kernel在啟動的時候,會去這兩個物理地址範圍,通過遍歷物理地址空間的方法尋找RSDP表,即通過尋找RSDP表的Signature(RSD PTR)來定位RSDP的位置,並通過該表的length和checksum來確保找到的表是正確的。
用RW讀取的RSD PTR表
來看一下Linux內核源碼,在內核啟動的時候會調用acpi_boot_table_init()函數,該函數會調用到acpi_find_root_pointer()函數用於定位RSDP表,其函數的調用順序如下:
arch/x86/kernel/head64.S -> arch/x86/kernel/head64.c:x86_64_start_kernel() -> arch/x86/kernel/head64.c:x86_64_start_reservations -> init/main.c:start_kernel() -> arch/x86/kernel/setup.c:setup_arch() -> acpi_boot_table_init() -> acpi_table_init() -> acpi_initialize_tables() -> acpi_os_get_root_pointer() -> acpi_find_root_pointer()
在acpi_find_root_pointer()函數中,會先後在EBDA和0x000E0000 到0x000FFFFF的物理地址範圍內調用acpi_tb_scan_memory_for_rsdp()函數來檢測RSDP表的Signature 「RSD PTR」。
對於基於UEFI的系統而言,RSDP Table位於EFI_SYSTEM_TABLE,所以Linux內核可以直接到該表裡面查找RSDP表,然後定位所有的ACPI表。
推薦閱讀: