Page 1 of 1
XSDT struct padding problem
Posted: Fri Apr 15, 2016 9:30 am
by interrupt
I'm trying to retrieve the IOAPIC address from the ACPI table. I succeeded to get the pointer address to the XSDT. I tried to get the SDTs' addresses from the XSDT structure. Unfortunately, the addresses were incorrect : 0x7ef300000000000, 0x7ef200000000000, 0x7ef100000000000 instead of 0x7ef30000, 0x7ef20000, 0x7ef10000 and 0x7ef40000, i.e. on the example below the address of the SDTs field in my XSDT structure points to 0x4 where it should point to 0x0.
0x0
|
07ef40000 00000000 07ef3000 00000000 07ef2000 00000000 07ef1000 00000000
The SDTheader and XSDT structures :
Code: Select all
struct SDTheader {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t sum;
char OEMid[6];
char OEMtableId[8];
uint32_t OEMRevision;
uint32_t creatorID;
uint32_t creatorRevision;
} __attribute__((packed));
struct XSDT {
struct SDTheader header;
uint64_t sdts[];
} __attribute__((packed));
Furthermore, I realized my XSDT structure was 0x28 bytes wide instead of 0x24 and discovered there was some kind of "padding" between the last field and the first one. The padding was 0x4 bytes wide, which might explain the difference. This seems to be related to the problem mentioned above : if I subtract 0x4 from the address of stds[0], I get the right address.
This is strange as I put __attribute__((packed)) to avoid such a problem.
Has anyone an idea on why is there a padding ?
I'm using UEFI and a cross-compiler targeting x86_64-w64-mingw32 as shown in
UEFI Bare Bones.
Re: XSDT struct padding problem
Posted: Fri Apr 15, 2016 11:05 am
by BrightLight
I've tried my best to understand your question, and here goes.
The XSDT contains 64-bit pointers to the ACPI tables. On x86(_64), these pointers are in little endian order. The least significant byte is stored first in memory. This also means the least significant DWORD of the QWORD are stored first in memory. There doesn't seem to be anything wrong with your XSDT. So if the first ACPI table was at 0x01010101FFEECCDD, that entry would look like this in a hexdump:
Or if using DWORDs instead of bytes:
EDIT: Just noticed your first statement.
interrupt wrote:I'm trying to retrieve the IOAPIC address from the ACPI table.
By default, the first I/O APIC is at 0xFEC00000 and the local APIC is at 0xFEE00000.
Re: XSDT struct padding problem
Posted: Fri Apr 15, 2016 1:49 pm
by interrupt
By default, the first I/O APIC is at 0xFEC00000 and the local APIC is at 0xFEE00000.
I'd rather use a safe way to get the I/O APIC address and there's not just the FADT I want from the ACPI.
So if the first ACPI table was at 0x01010101FFEECCDD, that entry would look like this in a hexdump:
Code:
That's exactly my point. I should have :
And I've got :
And it seems to come from the padding between the two fields of the XSDT (as my sdts field now points to the wrong address and the padding "shifts" the rest to the right).
Re: XSDT struct padding problem
Posted: Fri Apr 15, 2016 2:05 pm
by MDenham
omarrx024 wrote:I've tried my best to understand your question, and here goes.
The XSDT contains 64-bit pointers to the ACPI tables. On x86(_64), these pointers are in little endian order. The least significant byte is stored first in memory. This also means the least significant DWORD of the QWORD are stored first in memory. There doesn't seem to be anything wrong with your XSDT. So if the first ACPI table was at 0x01010101FFEECCDD, that entry would look like this in a hexdump:
Or if using DWORDs instead of bytes:
The problem he's running into is that the least significant dword is getting written into an area that's apparently turning into padding when there shouldn't be padding between the header and the array of pointers. As a result, everything's shifted over 32 bits. (Specifically, what's happening is the uint64_t array is getting aligned to 8-byte multiples when he doesn't want it aligned.)
I suspect the compiler isn't respecting __attribute__((packed)) correctly with respect to uint64_t; you could try adding __attribute__((aligned (4))) to the sdts[] declaration and see if that fixes things (it
should as that ought to override whatever is making the compiler think they need to be 8-byte aligned, but the real question is why it's thinking that in the first place...).
Re: XSDT struct padding problem
Posted: Fri Apr 15, 2016 2:17 pm
by interrupt
you could try adding __attribute__((aligned (4))) to the sdts[]
This doesn't change a thing. I still get 0x7EF300000000000.
Re: XSDT struct padding problem
Posted: Fri Apr 15, 2016 2:35 pm
by BrightLight
interrupt wrote:you could try adding __attribute__((aligned (4))) to the sdts[]
This doesn't change a thing. I still get 0x7EF300000000000.
Is there any code? Can you try to read the first uint64 from the XSDT? What is the value there?
Re: XSDT struct padding problem
Posted: Fri Apr 15, 2016 2:38 pm
by BrightLight
interrupt wrote:I'd rather use a safe way to get the I/O APIC address and there's not just the FADT I want from the ACPI.
The I/O APIC and local APIC addresses are in the MADT, not the FADT. All you'd like from the FADT is the DSDT and the PM1a_EVENT/CONTROL blocks.
interrupt wrote:That's exactly my point. I should have :
And I've got :
And it seems to come from the padding between the two fields of the XSDT (as my sdts field now points to the wrong address and the padding "shifts" the rest to the right).
When you read a QWORD from the XSDT, you get 0x07EF300000000000? I wouldn't think so.
Re: XSDT struct padding problem
Posted: Fri Apr 15, 2016 2:53 pm
by interrupt
omarrx024 wrote:The I/O APIC and local APIC addresses are in the MADT, not the FADT. All you'd like from the FADT is the DSDT and the PM1a_EVENT/CONTROL blocks.
Ah yes, I confused the FADT with the MADT. It's the I/O APIC address field from the MADT I need.
omarrx024 wrote:Is there any code? Can you try to read the first uint64 from the XSDT? What is the value there?
I'm using UEFI, so I've just got to print the value of xsdt->stds.
The signature (the first uint64) is valid ("XSDT", or 0x58 0x53 0x44 0x54).
omarrx024 wrote:When you read a QWORD from the XSDT, you get 0x07EF300000000000?
Actually 0x07EF300000000000 is the first value pointed by the sdts[] field.
EDIT:
I didn't call ExitBootServices yet, so I still can use UEFI protocols.