ACPI RSDT address out of memory

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Oxmose
Member
Member
Posts: 28
Joined: Sun Dec 18, 2016 5:10 am
Contact:

ACPI RSDT address out of memory

Post by Oxmose »

Hi everyone!

So, I started adding ACPI support to my kernel but I stumbled upon a strange bug.
I'm scanning the memory to find the RSDP, which is successfully done since the OEM info I get is BOCHS.
But then, when getting the RSDT address, I get 0x07FE154E. Then trying to access this address make the kernel crash.
This thing is, when running the kernel I launch QEMU with 128Mb of memory, so my guess is that the address 0x07FE154E is definitely out of memory.

Can you try to tell me what I'm doing wrong here?
The RSDT address is retreived thanks to this code :
uint32_t rsdt_addr = *(uint32_t *)(rsdp_base + 16);

Then the code that make the kernel crash is :
rsdt_addr->length;

Thanks!
Some of my projects are gathered here: https://github.com/Oxmose
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: ACPI RSDT address out of memory

Post by Korona »

What is the type of rsdp_base? Why don't you use a proper struct to extract the information? You'll have to show us more code if you want real help.
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
Oxmose
Member
Member
Posts: 28
Joined: Sun Dec 18, 2016 5:10 am
Contact:

Re: ACPI RSDT address out of memory

Post by Oxmose »

Sorry for not posting too much code ^^ here is what I have

Code: Select all

typedef struct acpi_header
{
    uint32_t    signature;
    uint32_t    length;
    uint8_t     revision;
    uint8_t     checksum;

    uint8_t     oem[6];
    uint8_t     oem_table_id[8];
    uint32_t    oem_revision;

    uint32_t    creator_id;
    uint32_t    creator_revision;
} __attribute__((__packed__)) acpi_header_t;

Code: Select all

uint32_t rsdt_addr = *(uint32_t *)(rsdp_base + 16);
where rsdp_base is an uint8_t pointer

Then, rsdt_addr is sent to a function as a acpi_header_t pointer.

Then I am using the structure in this code:

Code: Select all

if(rsdt == NULL)
    {
        return OS_ERR_NULL_POINTER;
    }

    printf("PARSING RSDT 1");

    uint32_t *range_begin = (uint32_t *)(rsdt + 1);
    uint32_t *range_end = (uint32_t *)((uint8_t*)rsdt + rsdt->length);

    printf("PARSING RSDT 2\n");
the code crashes when reaching the rsdt->length access.

EDIT:
I've also tried to parse the descriptor like this

Code: Select all

static OS_RETURN_E acpi_parse_rsdp(rsdp_descriptor_t *rsdp_desc)
{
    if(rsdp_desc == NULL)
    {
        return OS_ERR_NULL_POINTER;
    }

    // Verify checksum
    uint8_t sum = 0;

    for (uint8_t i = 0; i < 20; ++i)
    {
        sum += ((uint8_t*)rsdp_desc)[i];
    }

    if (sum)
    {
        printf("Checksum failed\n");
        return OS_ERR_CHECKSUM_FAILED;
    }

    printf("OEM = %s\n", rsdp_desc->oemid);

    OS_RETURN_E err;

    // Check version
    if (rsdp_desc->revision == 0)
    {
        printf("ACPI Version 1\n");
        printf("ADDR  %p\n", rsdp_desc->rsdt_address);
        err = acpi_parse_rsdt((acpi_header_t *) rsdp_desc->rsdt_address);
        printf("PARSED RSDT\n");
        if(err != OS_NO_ERR)
        {
            return err;
        }
    }
}
where rsdp_descriptor_t is

Code: Select all

typedef struct rsdp_descriptor 
{
    char     signature[8];
    uint8_t  checksum;
    char     oemid[6];
    uint8_t  revision;
    uint32_t rsdt_address;
} __attribute__ ((packed)) rsdp_descriptor_t;
Some of my projects are gathered here: https://github.com/Oxmose
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: ACPI RSDT address out of memory

Post by MichaelPetch »

An observation: 0x07FE154E would still be within 128mb. I'm curious, is paging enabled and if it is have you properly identity mapped the region in question? Have you also enabled the A20 line (A20 gate)?
Oxmose
Member
Member
Posts: 28
Joined: Sun Dec 18, 2016 5:10 am
Contact:

Re: ACPI RSDT address out of memory

Post by Oxmose »

You are definitely right, my metal calculus was totally wrong! It is in the memory.
Paging is enabled.
A20 gate is untouched, I'm using multiboot to boostrap the kernel on qemu.
Though, if I recall great (I am not at home right now) I may have forgot to map the memory after 48Mb, which might be why I get this error. Thanks for the feedback I'll test that when I'm home.
Some of my projects are gathered here: https://github.com/Oxmose
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: ACPI RSDT address out of memory

Post by MichaelPetch »

Oxmose wrote:I may have forgot to map the memory after 48Mb, which might be why I get this error.
If you use multiboot compliant loader A20 is enabled so won't be an issue. I didn't know how you booted based on info given. With that being said, the address seems reasonable so I think it almost certainly a paging problem and that the area in question isn't identity mapped.

No problem with giving feedback, you are welcome.
Oxmose
Member
Member
Posts: 28
Joined: Sun Dec 18, 2016 5:10 am
Contact:

Re: ACPI RSDT address out of memory

Post by Oxmose »

Hey ! Thanks, that was a pagging issue, I started writting the kernel one year ago and completly forgot how I managed pagging back then!
Issue solved! (well, this one at least)
Some of my projects are gathered here: https://github.com/Oxmose
Post Reply