From 9dd1c65cae010f7af6e3abf4f08e3ac487a4e0f4 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Sun, 13 Mar 2022 14:59:31 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E6=9E=90RSDT=20header=E7=9A=84sign?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/common/glib.h | 3 ++ kernel/driver/acpi/acpi.c | 66 ++++++++++++++++++++++++++++++--------- kernel/driver/acpi/acpi.h | 7 +++-- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/kernel/common/glib.h b/kernel/common/glib.h index 8666cb10..a66cdcfb 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -49,6 +49,9 @@ typedef long long int ll; #define max(x, y) ((x > y) ? (x) : (y)) #define min(x, y) ((x < y) ? (x) : (y)) +// 遮罩高32bit +#define MASK_HIGH_32bit(x) (x & (0x00000000ffffffffUL)) + // 四舍五入成整数 ul round(double x) { diff --git a/kernel/driver/acpi/acpi.c b/kernel/driver/acpi/acpi.c index f4f7dbbd..2a2bda10 100644 --- a/kernel/driver/acpi/acpi.c +++ b/kernel/driver/acpi/acpi.c @@ -8,8 +8,16 @@ static struct acpi_RSDP_t *rsdpv1; static struct acpi_RSDP_2_t *rsdpv2; static struct acpi_RSDT_Structure_t *rsdt; +static struct multiboot_tag_old_acpi_t old_acpi; +static struct multiboot_tag_new_acpi_t new_acpi; + static ul acpi_RSDT_offset = 0; static uint acpi_RSDT_Entry_num = 0; + + +// RSDT中的第一个entry所在物理页的基地址 +static ul acpi_RSDT_entry_phys_base = 0; + /** * @brief 迭代器,用于迭代描述符头(位于ACPI标准文件的Table 5-29) * @param _fun 迭代操作调用的函数 @@ -20,6 +28,10 @@ void acpi_iter_SDT(bool (*_fun)(const struct acpi_iter_SDT_header_t *, void *), { } +static ul acpi_get_RSDT_entry_vaddr(ul phys_addr) +{ + return ACPI_DESCRIPTION_HEDERS_BASE + MASK_HIGH_32bit(phys_addr) - acpi_RSDT_entry_phys_base; +} /** * @brief 初始化acpi模块 * @@ -29,37 +41,63 @@ void acpi_init() kinfo("Initializing ACPI..."); // 获取rsdp - struct multiboot_tag_old_acpi_t tmp1; int reserved; - multiboot2_iter(multiboot2_get_acpi_old_RSDP, &tmp1, &reserved); + multiboot2_iter(multiboot2_get_acpi_old_RSDP, &old_acpi, &reserved); - *rsdpv1 = (tmp1.rsdp); + *rsdpv1 = (old_acpi.rsdp); - - kdebug("Rsdt_phys_Address=%#018lx", rsdpv1->RsdtAddress); + kdebug("RSDT_phys_Address=%#018lx", rsdpv1->RsdtAddress); kdebug("RSDP_Revision=%d", rsdpv1->Revision); - // 映射RSDT区域的物理地址到页表 + // 映射RSDT的物理地址到页表 // 暂定字节数为2MB // 由于页表映射的原因,需要清除低21位地址,才能填入页表 - ul base = rsdpv1->RsdtAddress & (~(0x1fffff)); - acpi_RSDT_offset = rsdpv1->RsdtAddress - base; - mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + ul rsdt_phys_base = rsdpv1->RsdtAddress & PAGE_2M_MASK; + acpi_RSDT_offset = rsdpv1->RsdtAddress - rsdt_phys_base; + mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); kdebug("RSDT mapped!"); - struct multiboot_tag_new_acpi_t tmp2; - multiboot2_iter(multiboot2_get_acpi_new_RSDP, &tmp2, &reserved); - *rsdpv2 = tmp2.rsdp; + multiboot2_iter(multiboot2_get_acpi_new_RSDP, &new_acpi, &reserved); + *rsdpv2 = new_acpi.rsdp; kdebug("Rsdt_v2_phys_Address=%#018lx", rsdpv2->rsdp1.RsdtAddress); kdebug("RSDP_v2_Revision=%d", rsdpv2->rsdp1.Revision); rsdt = ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset; // 计算RSDT Entry的数量 - acpi_RSDT_Entry_num = (rsdt->header.Length - 32) / 4; - + kdebug("offset=%d", sizeof(rsdt->header)); + acpi_RSDT_Entry_num = (rsdt->header.Length - 36) / 4; + printk_color(ORANGE, BLACK, "%s\n", rsdt->header.Signature); printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length); printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num); + + // 映射所有的Entry的物理地址 + acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK; + // 由于地址只是32bit的,并且存在脏数据,这里需要手动清除高32bit,否则会触发#GP + acpi_RSDT_entry_phys_base = MASK_HIGH_32bit(acpi_RSDT_entry_phys_base); + + + kdebug("entry=%#018lx", rsdt->Entry); + kdebug("acpi_RSDT_entry_phys_base=%#018lx", acpi_RSDT_entry_phys_base); + + mm_map_phys_addr(ACPI_DESCRIPTION_HEDERS_BASE, acpi_RSDT_entry_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + + // 设置第一个entry的虚拟地址 + struct acpi_system_description_table_header_t *sdt_header; + uint* ent = &(rsdt->Entry); + for (int i = 0; i < acpi_RSDT_Entry_num; ++i) + { + kdebug("entry_addr_phys[ %d ]= %#018lx", i, MASK_HIGH_32bit((ul)(*(ent+i)))); + sdt_header = (struct acpi_system_description_table_header_t *)(acpi_get_RSDT_entry_vaddr((ul)(*(ent+i)))); + if(i<7) + { + struct acpi_Multiple_APIC_Description_Table_t *madt = (struct acpi_Multiple_APIC_Description_Table_t*)sdt_header; + for(int j=0;j<4;++j) + printk_color(ORANGE, BLACK, "%c", madt->header.Signature[j]); + printk("\n"); + kdebug("length=%d", madt->header.Length); + } + } } \ No newline at end of file diff --git a/kernel/driver/acpi/acpi.h b/kernel/driver/acpi/acpi.h index 3e545065..e72ff2a4 100644 --- a/kernel/driver/acpi/acpi.h +++ b/kernel/driver/acpi/acpi.h @@ -26,6 +26,9 @@ // 0x80-0xff Reserved for OEM use #define ACPI_RSDT_VIRT_ADDR_BASE 0xffff80000a000000UL +#define ACPI_DESCRIPTION_HEDERS_BASE ACPI_RSDT_VIRT_ADDR_BASE + PAGE_2M_SIZE + + struct acpi_RSDP_t { @@ -123,7 +126,7 @@ struct acpi_RSDT_Structure_t struct acpi_system_description_table_header_t header; // 一个包含了n个32bit物理地址的数组,指向了其他的description headers - uint *Entry; + uint Entry; }; // =========== XSDT 结构 ============= @@ -149,7 +152,7 @@ struct acpi_iter_SDT_header_t * @param _data 数据 */ void acpi_iter_SDT(bool (*_fun)(const struct acpi_iter_SDT_header_t *, void *), - void *_data); + void *_data); /** * @brief 获取MADT信息