RSDT: Difference between revisions

From OSDev Wiki
Jump to navigation Jump to search
Line 25: Line 25:
}
}
</source>
</source>
(追記) === Header fields === (追記ここまで)
(追記) ==== Signature ==== (追記ここまで)
(追記) All the ACPI tables have a 4byte Signature field (except the RSDP which has an 8byte one). Using the signature, you can determine what table are you working with. (追記ここまで)
(追記) ==== Length ==== (追記ここまで)
(追記) Total size of the table, inclusive of the header. (追記ここまで)
(追記) ==== Checksum ==== (追記ここまで)
(追記) A 8bit checksum field of the whole table, inclusive of the header. All bytes of the table summed must be equal to 0 (mod 0xFF). You should always do a checksum of the table before using it, even if you found the table linked by other tables. (追記ここまで)
(追記) <source lang="c"> (追記ここまで)
(追記) bool doChecksum(ACPISDTHeader *tableHeader) (追記ここまで)
(追記) { (追記ここまで)
(追記) unsigned char sum = 0; (追記ここまで)


(追記) for (int i = 0; i < tableHeader->Length; i++) (追記ここまで)
(追記) { (追記ここまで)
(追記) sum += ((char *) tableHeader)[i]; (追記ここまで)
(追記) } (追記ここまで)
(追記) (追記ここまで)
(追記) return sum == 0; (追記ここまで)
(追記) } (追記ここまで)
(追記) </source> (追記ここまで)
(追記) === Other fields === (追記ここまで)
In case you used RsdtPointer, the complete table structure is:
In case you used RsdtPointer, the complete table structure is:
<source lang="c">
<source lang="c">
Line 45: Line 65:
You may use this code:
You may use this code:
<source lang="c">
<source lang="c">
void *findFACP(void *RootSDT) {
void *findFACP(void *RootSDT)
(削除) (削除ここまで)RSDT *rsdt = (RSDT *) RootSDT;
{
(削除) (削除ここまで)int (削除) n (削除ここまで)= (rsdt->h.Length - sizeof(rsdt->h)) / 4;
(追記) (追記ここまで)RSDT *rsdt = (RSDT *) RootSDT;
(削除) (削除ここまで)for (int i = 0; i < (削除) n (削除ここまで); i++) {
(追記) (追記ここまで)int (追記) entries (追記ここまで)= (rsdt->h.Length - sizeof(rsdt->h)) / 4;
(削除) (削除ここまで)ACPISDTHeader *h = (ACPISDTHeader *) rsdt->PointerToOtherSDT[i];
(削除) (削除ここまで)if (!strncmp(h->Signature, "FACP"))
(追記) (追記ここまで)for (int i = 0; i < (追記) entries (追記ここまで); i++)
(削除) (削除ここまで)return (void *) h;
(追記) (追記ここまで){
(削除) (削除ここまで)}
(追記) (追記ここまで)ACPISDTHeader *h = (ACPISDTHeader *) rsdt->PointerToOtherSDT[i];
(削除) (削除ここまで)return NULL;
(追記) (追記ここまで)if (!strncmp(h->Signature, "FACP"(追記) , 4 (追記ここまで)))
(追記) (追記ここまで)return (void *) h;
(追記) (追記ここまで)}
(追記) // No FACP found (追記ここまで)
(追記) (追記ここまで)return NULL;
}
}
</source>
</source>

Revision as of 16:25, 10 March 2011

RSDT (Root System Description Table) is a data structure used in the ACPI programming interface. This table contains pointers to all the other System Description Tables.

Detecting the RSDT

To find the RSDT you need first to locate and check the RSDP, then use the RsdtPointer for ACPI Version < 2.0 an XsdtPointer for any other case.

The ACPI standards state that an OS that complies with ACPI version 2.0 or later should use the XSDT instead of the RSDT, however I personally doubt that there is a difference on 80x86 computers. AFAIK the XSDT itself was introduced for Itanium's (IA64) and other 64 bit computers where it's likely that the BIOS (and ACPI tables) are above 4 GB. On 80x86 it's likely that the RSDT and the XSDT both point to the same tables below 4 GB for compatibility reasons (it doesn't make sense to have 2 versions of the same tables) -- Brendan.

Validating the RSDT

You only need to sum all the bytes in the table and compare the result to 0.

Structure

The RSDT is the main System Description Table. However there are many kinds of SDT. All the SDT may be split into two parts. One (the header) which is common to all the SDT an another (data) which is different for each table. The structure of the header is:

structACPISDTHeader{
charSignature[4];
uint32_tLength;
uint8_tRevision;
uint8_tChecksum;
charOEMID[6];
charOEMTableID[8];
uint32_tOEMRevision;
uint32_tCreatorID;
uint32_tCreatorRevision;
}

Header fields

Signature

All the ACPI tables have a 4byte Signature field (except the RSDP which has an 8byte one). Using the signature, you can determine what table are you working with.

Length

Total size of the table, inclusive of the header.

Checksum

A 8bit checksum field of the whole table, inclusive of the header. All bytes of the table summed must be equal to 0 (mod 0xFF). You should always do a checksum of the table before using it, even if you found the table linked by other tables.

booldoChecksum(ACPISDTHeader*tableHeader)
{
unsignedcharsum=0;
for(inti=0;i<tableHeader->Length;i++)
{
sum+=((char*)tableHeader)[i];
}
returnsum==0;
}

Other fields

In case you used RsdtPointer, the complete table structure is:

structRSDT{
structACPISDTHeaderh;
uint32_tPointerToOtherSDT[(h.Length-sizeof(h))/4];
}

If you instead used the XsdtPointer, then the table is:

structXSDT{
structACPISDTHeaderh;
uint64_tPointerToOtherSDT[(h.Length-sizeof(h))/8];
}

How to use

Well, suppose you want to find the FADT. The FADT, being a SDT has a ACPISDTHeader. It's signature is "FACP". You may use this code:

void*findFACP(void*RootSDT)
{
RSDT*rsdt=(RSDT*)RootSDT;
intentries=(rsdt->h.Length-sizeof(rsdt->h))/4;
for(inti=0;i<entries;i++)
{
ACPISDTHeader*h=(ACPISDTHeader*)rsdt->PointerToOtherSDT[i];
if(!strncmp(h->Signature,"FACP",4))
return(void*)h;
}
// No FACP found
returnNULL;
}

What's next?

You should now parse each table pointed by the RSDP. (Probably you will need only the FADT, the SSDT and the MADT

Retrieved from "https://wiki.osdev.org/index.php?title=RSDT&oldid=11234"