Long time since I posted. Well I learned a lot in the time, with due help from the osdev-wiki, the forum (It might sound weird, but if I got free time from coding and reading some specifications or the osdev-wiki, I would browse through the forum, and read threads related to what I am doing, and I have completed 25 pages till now) and the IRC channel.
Anyway, the problem comes as following. I have been trying to find and parse the ACPI tables, so that I can find the MADT table and find the APIC's present. This would help me in initializing all the logical processors present on the system, and I would further go on with multi-tasking/multi-threading.
So I found the RSDP, and checked that all its values were correct. The signature, OEMID, and the Revision were as expected. The RSDP even get past the checksum. However, the RsdtAddress was given as 0xFFFF0000, while I was expecting it to be in the higher memory. I didn't give it much though, and went on to parsing the RSDT. However the strange part occured over here. The RSDT contained all rubbish values, including the signature. I will first show the code before I tell what all steps I took:
Code: Select all
#ifndef TABLES_H
#define TABLES_H
#include "Common.h"
typedef struct RSDPDescriptor
{
char Signature[8];
u8int Checksum;
char OEMID[6];
u8int Revision;
u32int RsdtAddress;
} __attribute__((packed)) RSDP_t;
typedef struct ACPISDTHeader
{
char Signature[4];
u32int Length;
u8int Revision;
u8int Checksum;
char OEMID[6];
char OEMTableID[8];
u32int OEMRevision;
u32int CreatorID;
u32int CreatorRevision;
} __attribute__((packed)) SDTHeader_t;
typedef struct RSDTable
{
SDTHeader_t header;
u32int firstSDT;
} __attribute__((packed)) RSDT_t;
// Finds the RSDP, and the corresponding tables.
void ktables();
// Checks the address given, to see if it contains a valid
// table or not. Returns 0 if it isnt valid, or 1 if valid.
s32int checkSum(void *address, int length);
// Finds the entry based on the identifier given, and returns
// null if the RSDT is null, or the table with the signature
// isn't found, or the checksum failed.
void* findEntry(char* identifier);
#endif
Code: Select all
#include <Common.h>
#include <Tables.h>
#include <Monitor.h>
RSDP_t *RSDP = 0;
RSDT_t *RSDT = 0;
// Finds the RSDP, and the corresponding tables.
void ktables()
{
u16int *realModeEbda = (u16int*)0x40E;
u8int *ebda = (u8int*)(*realModeEbda << 4);
u8int *bios = (u8int*)(0x000E0000);
u8int *pebda = ebda;
u8int *pbios = bios;
while((u32int)pebda < 0x000A0000)
{
if(!memcmp(pebda, "RSD PTR ", 8))
if(checkSum((u32int*)pebda, sizeof(RSDP_t)))
{
RSDP = (RSDP_t*)pebda;
break;
}
pebda += 16;
}
if(RSDP == 0)
while((u32int)pbios < 0x000FFFFF)
{
if(!memcmp(pbios, "RSD PTR ", 8))
if(checkSum((u32int*)pbios, sizeof(RSDP_t)))
{
RSDP = (RSDP_t*)pbios;
break;
}
pbios += 16;
}
if(RSDP != 0)
{
// The ACPI Tables exist and now we are ready to parse them.
RSDT = (RSDT_t*)RSDP->RsdtAddress;
if(!checkSum((u32int*)RSDT, RSDT->header.Length))
RSDT = 0;
else
{
u32int *madt = findEntry("APIC");
if(madt != 0)
kputs("MADT detected.\n");
}
}
else
{
// Lets search for and parse the MP Tables.
}
}
// Checks the address given, to see if it contains a valid
// table or not. Returns 0 if it isnt valid, or 1 if valid.
s32int checkSum(void *address, int length)
{
char *bptr = (char*)address;
char check = 0;
int i;
for(i = 0; i < length; i++)
{
check += *bptr;
bptr++;
}
if (check == 0)
return 1;
return 0;
}
// Finds the entry based on the identifier given, and returns
// null if the RSDT is null, or the table with the signature
// isn't found, or the checksum failed.
void* findEntry(char* identifier)
{
if(RSDT == 0)
return NULL;
u32int n = (RSDT->header.Length - sizeof(RSDT->header)) / 4, i;
for(i = 0; i < n; i++)
{
SDTHeader_t* header = (SDTHeader_t*)(RSDT->firstSDT + i);
if(!memcmp((void*)header, (void*)identifier, 4))
if(checkSum((u32int*)header, header->Length))
return (void*)header;
}
return NULL;
}
Secondly, I debugged the memory where the RSDP existed, and found the address of the RSDT as my code tells me (0xFFFF0000).
Thirdly, I double checked that paging isnt initialized before doing this, and ACPI is enabled in Bochs.
Fourthly, I checked that all my tables are aligned properly, using the official specifications, and found them to be. (Excluding the RSDP, as I
exlcluse the XSDT part. Leaving the XSDT part, it is aligned properly)
Fifthly, I STFW with terms like "RSDP containing invalid RSDT" thinking, that would show something. Again, NOTHING!
Sixthly, I even tried banging my head against the wall, thinking it would solve the problem. End result: Head aches!
Well, I personally I think it would be a noobish mistake rather than something big, but believe me I checked it for more than 24 hours, and moreover, asked 2 more people that whether they can find anything wrong in it before posting on the forum.
Regards,
Shikhin