Search code examples
cassemblykernelacpi

Kernel environment: RSDP points to invalid RSDT


I am currently developing a simple kernel that I would like to interface with the ACPI tables.

However, my code only seems to work in a virtual machine, namely Bochs, whereas on all real hardware that I have tried so far (hardware ranging from 2003 to 2011), the RSDP points to apparently invalid Root system descriptor tables.

Here is the screen from Bochs: notice all the descriptor tables are found.

enter image description here

The following in particular is an admittedly rather old AMD Athlon64 platform, however the BIOS is dated from 2003, so as far as I'm concerned it should have full support of the v1 ACPI revision.

enter image description here

I also tried running my detection program on a laptop from 2010 and 2011, both of which also gave me a valid Root system descriptor pointer, but the pointer pointed to either null memory, memory filled with 0xFF or simply junk.


The first and obvious possibility is that of an uninitialized register, as Bochs on powerup initializes all registers to zero, whereas the same cannot always be said for real hardware. However, I have checked for this possibility enough times to warrant posting a question on these forums.

I also found some old Linux kernel mailing list messages from circa 2002, in which the poster had a similar northbridge to the PC running in the image. They had the same RSDT address as the PC above, which further assures me that the RSDP is not wrong.

The checksum is also valid (sums to zero in low eax (AX) register), which the reader can additionally check.

I also suspected that perhaps my routine for printing the memory region works with an uninitialized value, and by Bochs' tendency to initialize registers worked there, and not on hardware - however, that would imply that erratic, irreproducible behavior could be observed, but on each machine I tested the memory region pointed to by the RSDP was consistently the same junk.


As I am unsure where to even look for the problem, I will fill in additional details or source code at the request of the reader - simply dumping all of it here would be inconvenient and make this uncomfortable to read.

kernel entry point:

void __kernel_entry() {

    clear_scr(0x0000);

    set_cur(0, 0);
    print_str("Scanning RSDP header: 0xe0000 - 0xfffff", 39);

    struct RSDP_descriptor* rd = __RSDP_find_address();

    if(rd) {
        set_cur(0, 1); // Set cursor position
        __RSDP_print(rd); // Prints the RSDP location, OEM string and the contained RSDT pointer

    }

    struct ACPI_SDT_header* rsdt = (struct ACPI_SDT_header*)rd->RSDT_address;
    memdump((void*)rd, 5, 15);
    memdump((void*)rsdt, VH-8, VH); //VH: Console height

    loop:;
    goto loop;
}

Solution

  • Your problem might be (obviously is) A20 not enabled. Most real hardware starts up that way, as opposed to a standard Bochs start-up.

    With A20 not enabled, you'll be reading from other addresses than you think you do (See comment from Michael).