0

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;
}
Maxim Blinov
  • 886
  • 9
  • 33
  • 4
    You're sure you're not tripping over A20? That is initially different from the real thing in Bochs AFAIK – tofro Oct 05 '16 at 22:12
  • 3
    Yep i agree with tofro. If A20 is not enabled when the BIOS calls your boot sector (which is the case for most real hardware I know of) you'll actually be reading data one megabyte lower in memory when the memory address you access is in an odd numbered megabyte region. 0x3FFF3000 is in an odd numbered megabyte range so would read from 0x3FEF3000.I think BOCHS does enable A20 in most builds, but it is possible to turn that off if you recompile BOCHS from source. Technically speaking most 386s will boot with A20 enabled but then the BIOS disables it before transferring control to a boot loader. – Michael Petch Oct 05 '16 at 22:48
  • There is a program named `acpidump` available for most Linux distributions. Either look into the source (GPL, so you might not want to do that out of legal reasons) or at least check what's actually in the table. I don't have hardware of that age at hand (either much more modern or much more ancient) to check myself but the output does not look very off. – deamentiaemundi Oct 05 '16 at 22:51
  • The other possibility is if you are in protected mode with paging enabled and you didn't properly identity map the ACPI region and pointed it to the wrong physical address. I think this is a lot less likely to be your problem compared with A20 being off because I'd expect your code would fail on real and emulated hardware. – Michael Petch Oct 05 '16 at 22:52
  • @tofro It worked! Using the fast A20 Gate enable in my bootsector code solved the problem. If you could post it as an answer, ill accept it. I never considered that the A20 line would be relevant in 32 bit protected mode, but then again, why wouldnt it. Thanks Michael for the detailed explanation. – Maxim Blinov Oct 05 '16 at 23:12

1 Answers1

2

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).

tofro
  • 5,640
  • 14
  • 31