ACPI Version in Bochs

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
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

ACPI Version in Bochs

Post by JohnnyTheDon »

I have been writing some code in my OS to use ACPI. When running in bochs, I am able to find the RSDP and checksum it. When I check the revision, it reports 0 (ACPI 1.0). However, the changelog for bochs 2.3.5 says
[1763578] ACPI Table Revision 0 -> 1
Is this wrong, or am I interpreting the RSDP incorrectly?

Here is the code for my RSDP structure:

Code: Select all

#pragma pack(push, 1)
/* Root System Descriptor Pointer */
typedef struct _RSDP
{
	char Signature[8];
	uint8 Checksum;
	char OEMID[6];
	uint8 Revision;
	uint32 RSDTAddress;
	/* Following fields do not exist in ACPI 1.0 (Revision = 0) */
	uint32 Length;
	uint64 XSDTAddress;
	uint8 ExtendedChecksum;
	char Reserved[3];
} RSDP_t;
#pragma pack(pop)
And here is the code for finding it:

Code: Select all

static RSDP_t* RSDP;

bool InitACPI()
{
	/* Step 1: Find the RSDP */
	uint16 ebdaAddrSeg = *((uint16*)(PTOV(ACPI_RSDP_EBDA_PTR_LOCATION)));
	char buffer[80];
	void* ebdaAddr = PTOV(ebdaAddrSeg);
	void* i;
	/* Maybe its in the EBDA? */
	for(i = ebdaAddr; i < ebdaAddr+ACPI_RSDP_EBDA_SIZE; i += ACPI_RSDP_ALIGNMENT)
	{
		if(strncmp(i, APIC_RSDP_SIG, 8) == 0)
			break;
	}
	if(i>=ebdaAddr+ACPI_RSDP_EBDA_SIZE)
	{
		/* No? Then it must be in the BIOS. */
		for( i = PTOV(0x000E0000); i < PTOV(0x000FFFFF); i += ACPI_RSDP_ALIGNMENT)
		{
			if(strncmp(i, APIC_RSDP_SIG, 8) == 0)
				break;
		}
		if(i >= PTOV(0x000FFFFF)) 
			return false; /* No RSDP! */
	}
	RSDP = (RSDP_t*)i;
	
	/* Check the validity of the table using the checksum */
	uint8 checksum = 0;
	for(i = (void*)RSDP; i < ((void*)RSDP)+ACPI_RSDP_1_SIZE; i++)
	{
		checksum += *((uint8*)i);
	}
	if(checksum != 0) 
		return false; /* INVALID RSDP! */
	uitoa(RSDP->Revision, buffer, 10);
	WriteTextModeLine(buffer, 0x07);
	/* Check the revision */
	if(RSDP->Revision > ACPI_REVISION_1)
	{
		/* If this is a later revision table than 1.0, check the validity of the table using the second checksum */
		uint8 checksum = 0;
		for(i = (void*)RSDP; i < ((void*)RSDP)+sizeof(RSDP_t); i++)
		{
			checksum += *((uint8*)i);
		}
		if(checksum != 0) 
			return false; /* INVALID RSDP! */
	}
	return true;
}
A few notes about the code...
  • My OS is for x86_64 only (i know this isn't the issue because everything else works, just not ACPI)
  • PTOV is a macro that just adds a number to physical addresses to turn them into their virtual counterparts. I map the first 16GB of physical addresses inside the virtual address space before this function is called
  • uitoa() just converts 64-bit unsigned integers into text
  • WriteTextModeLine() just writes text to the screen while in text mode
  • The RSDP that is found is inside the BIOS, not the EBDA
Thanks for any help in advance.
Hyperdrive
Member
Member
Posts: 93
Joined: Mon Nov 24, 2008 9:13 am

Re: ACPI Version in Bochs

Post by Hyperdrive »

My OS reports the same revision (1.0) as yours for the RSDP.

And that is correct for the Bochs BIOS. From the Bochs BIOS source:

Code: Select all

1223 void acpi_bios_init(void)
1224 {
1225     struct rsdp_descriptor *rsdp;
[...]
1279     /* RSDP */
1280     memset(rsdp, 0, sizeof(*rsdp));
1281     memcpy(rsdp->signature, "RSD PTR ", 8);
1282 #ifdef BX_QEMU
1283     memcpy(rsdp->oem_id, "QEMU  ", 6);
1284 #else
1285     memcpy(rsdp->oem_id, "BOCHS ", 6);
1286 #endif
1287     rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
1288     rsdp->checksum = acpi_checksum((void *)rsdp, 20);
[...]
1356 }
Regards,
Thilo
stlw
Member
Member
Posts: 357
Joined: Fri Apr 04, 2008 6:43 am
Contact:

Re: ACPI Version in Bochs

Post by stlw »

Hyperdrive wrote:My OS reports the same revision (1.0) as yours for the RSDP.

And that is correct for the Bochs BIOS. From the Bochs BIOS source:

Code: Select all

1223 void acpi_bios_init(void)
1224 {
1225     struct rsdp_descriptor *rsdp;
[...]
1279     /* RSDP */
1280     memset(rsdp, 0, sizeof(*rsdp));
1281     memcpy(rsdp->signature, "RSD PTR ", 8);
1282 #ifdef BX_QEMU
1283     memcpy(rsdp->oem_id, "QEMU  ", 6);
1284 #else
1285     memcpy(rsdp->oem_id, "BOCHS ", 6);
1286 #endif
1287     rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
1288     rsdp->checksum = acpi_checksum((void *)rsdp, 20);
[...]
1356 }
Regards,
Thilo
This patch means the line :

acpi_build_table_header((struct acpi_table_header *)rsdt,
"RSDT", sizeof(*rsdt), 1);

if you go into the function you will see:

Code: Select all

    memcpy(h->signature, sig, 4);
    h->length = cpu_to_le32(len);
    h->revision = rev;
Might be you looking into different field of rsdt, there are two field with revision:

Code: Select all

#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
	uint8_t                            signature [4];          /* ACPI signature (4 ASCII characters) */\
	uint32_t                             length;                 /* Length of table, in bytes, including header */\
	uint8_t                              revision;               /* ACPI Specification minor version # */\               <===== this one
	uint8_t                              checksum;               /* To make sum of entire table == 0 */\
	uint8_t                            oem_id [6];             /* OEM identification */\
	uint8_t                            oem_table_id [8];       /* OEM table identification */\
	uint32_t                             oem_revision;           /* OEM revision number */\
	uint8_t                            asl_compiler_id [4];    /* ASL compiler vendor ID */\
	uint32_t                             asl_compiler_revision;  /* ASL compiler revision number */
and

Code: Select all

struct rsdp_descriptor         /* Root System Descriptor Pointer */
{
	uint8_t                            signature [8];          /* ACPI signature, contains "RSD PTR " */
	uint8_t                              checksum;               /* To make sum of struct == 0 */
	uint8_t                            oem_id [6];             /* OEM identification */
	uint8_t                              revision;               /* Must be 0 for 1.0, 2 for 2.0 */                         <===== looks like you are looking into this one
	uint32_t                             rsdt_physical_address;  /* 32-bit physical address of RSDT */
	uint32_t                             length;                 /* XSDT Length in bytes including hdr */
	uint64_t                             xsdt_physical_address;  /* 64-bit physical address of XSDT */
	uint8_t                              extended_checksum;      /* Checksum of entire table */
	uint8_t                            reserved [3];           /* Reserved field must be 0 */
};
I suggest you to ask the question in Bochs-Developers forum, I have no idea what is actually should be and if Bochs has any bug here ...

Stanislav
Hyperdrive
Member
Member
Posts: 93
Joined: Mon Nov 24, 2008 9:13 am

Re: ACPI Version in Bochs

Post by Hyperdrive »

stlw wrote:
Hyperdrive wrote:My OS reports the same revision (1.0) as yours for the RSDP.

And that is correct for the Bochs BIOS. From the Bochs BIOS source:

Code: Select all

1223 void acpi_bios_init(void)
1224 {
1225     struct rsdp_descriptor *rsdp;
[...]
1279     /* RSDP */
1280     memset(rsdp, 0, sizeof(*rsdp));
1281     memcpy(rsdp->signature, "RSD PTR ", 8);
1282 #ifdef BX_QEMU
1283     memcpy(rsdp->oem_id, "QEMU  ", 6);
1284 #else
1285     memcpy(rsdp->oem_id, "BOCHS ", 6);
1286 #endif
1287     rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
1288     rsdp->checksum = acpi_checksum((void *)rsdp, 20);
[...]
1356 }
Regards,
Thilo
This patch means the line :

acpi_build_table_header((struct acpi_table_header *)rsdt,
"RSDT", sizeof(*rsdt), 1);

if you go into the function you will see:

Code: Select all

    memcpy(h->signature, sig, 4);
    h->length = cpu_to_le32(len);
    h->revision = rev;
Might be you looking into different field of rsdt, there are two field with revision:

Code: Select all

#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
[...snip...]
and

Code: Select all

struct rsdp_descriptor         /* Root System Descriptor Pointer */
{
[...snip...]
};
The RSDP and the RSDT are different tables. The RSDP has no standard ACPI table header. And therefore there is just only one revision number. For RSDT, FADT and MADT they are building the header via acpi_build_table_header and use revision "1".

Regards,
Thilo
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: ACPI Version in Bochs

Post by JohnnyTheDon »

Thanks, I probably should have looked at the bochs bios source first :P

Code: Select all

/*
  * ACPI 1.0 Root System Description Table (RSDT)
*/
It seems that all the structures use the ACPI 1.0 standard. No XSDT :(.
Post Reply