RSDP Points to invalid RSDT? [Not-So-Solved]

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
shikhin
Member
Member
Posts: 274
Joined: Sat Oct 09, 2010 3:35 am
Libera.chat IRC: shikhin
Contact:

RSDP Points to invalid RSDT? [Not-So-Solved]

Post by shikhin »

Good evening Ladies (As a matter of fact, are their any ladies over here?) and Gentlemen,

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 :shock: 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;
}
First of all, I know my RSDP isn't complete, and only contains the RSDT part, as I am ignoring the XSDT (Till RSDT doesnt work :lol: ).
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
Last edited by shikhin on Thu Dec 30, 2010 8:38 pm, edited 8 times in total.
http://shikhin.in/

Current status: Gandr.
tom9876543
Member
Member
Posts: 170
Joined: Wed Jul 18, 2007 5:51 am

Re: RSDP Points to invalid RSDT?

Post by tom9876543 »

Are you sure Bochs has an accurate ACPI implementation??

Maybe try it on a real PC and see if you get the same problem?
shikhin
Member
Member
Posts: 274
Joined: Sat Oct 09, 2010 3:35 am
Libera.chat IRC: shikhin
Contact:

Re: RSDP Points to invalid RSDT?

Post by shikhin »

tom9876543 wrote:Are you sure Bochs has an accurate ACPI implementation??

Maybe try it on a real PC and see if you get the same problem?
Well sir, thanks for the response, as nobody else could point me in another direction except you.
So anyway, I tried on a real PC, and the following was what I noticed:

a) The RSDP was perfect on Bochs. On Bochs, the RSDT contained garbage values, the number of entries (tables) came as billions, and I couldnt search through all, and it just hung up.

b) The RSDP was perfect on Real PC too.On real PC, the RSDT too contained garbage values, but the number of entries came as 9, and the MADT wasn't found. My laptop has Core 2 Duo as processor, and so if the RSDP exists I think the MADT shall too exist.

This problem is very strange, and is bugging me day and night. :cry: If anyone has any things on it which can help me, please tell.

Regards,
Shikhin
http://shikhin.in/

Current status: Gandr.
shikhin
Member
Member
Posts: 274
Joined: Sat Oct 09, 2010 3:35 am
Libera.chat IRC: shikhin
Contact:

Re: RSDP Points to invalid RSDT? [Solved]

Post by shikhin »

Well, with due help from Brendan I was able to solve the problem. The problem as I see was that I was using Bochs to have 4096 MiB of memory, and so Bochs BIOS was making the tables in the wrong place, at 0xFFFF0000. I reduced the memory to 16 MiB and it is working as smoothly as possible. (Okay not really, I am having a small bug, but I would solve that myself.)
http://shikhin.in/

Current status: Gandr.
shikhin
Member
Member
Posts: 274
Joined: Sat Oct 09, 2010 3:35 am
Libera.chat IRC: shikhin
Contact:

Re: RSDP Points to invalid RSDT? [Solved]

Post by shikhin »

Well "Hello Again" everybody,

The code worked perfecly well for sometime but as of now here is what is happening:

I was working on some kernel code, implemented many a things, and then did a few major changes for which I had to change *some* of the ACPI code. Now what happens is almost completely opposite of what was previously happening. Here are the symptoms:

* I get a completely valid RSDP/RSDT in bochs and my dad's laptop. I find the MADT and enable all the virtual CPU's too. So this is a total happy situation for me, and I am very very happy for this. :D
* I get a completely valid RSDP on my laptop, but the RSDT is completely invalid, which means that everything is wrong (e.g. total number of headers comes into billions, the signature and OEMID come as something strange). :cry: I am wondering why I am always getting this kind of bug.

I checked all the values of the RSDP, printed them out and the only conclusion I can get is that the Revision field of the RSDP contains 0 in both Bochs and my dad's laptop, while in my laptop it comes as 2. So shall I rather check the XSDT than the RSDT? Maybe, the BIOS is generating a invalid RSDT at random times, as the revision is above 0 and I am expected to use the XSDT? (the code worked for some time, and I am sure I have changed nothing which would cause it to become like it is)

If anyone wants I can post the code too.

P.S. I have rather become mad in these 5 hours, trying to solve the problem, thinking if anything is wrong. I would like if somebody helps me (fast) to solve it.

EDIT: I got happy for a moment thinking the XSDT would be fine, but it seems I was totally wrong. Any help?

Regards,
Shikhin
http://shikhin.in/

Current status: Gandr.
Post Reply