Locating PCI BIOS service through BIOS32

Programming, for all ages and all languages.
Post Reply
Peter Wright

Locating PCI BIOS service through BIOS32

Post by Peter Wright »

I'm trying to locate the PCI BIOS entry point. <a href="http://www.acos.34sp.com/docs/itemview.php?sectionid=1&sectionname=Hardware&groupid=2&groupname=Interconnect%20Buses&subgroupid=19&subgroupname=PCI&itemid=28">the PCI BIOS Specification</a> says that the way to do this is to use the bios32 service directory, and in order to use that, you have to scan for a 16byte structure located within the physical address range 0E0000h to 0FFFF0h. I'm trying to do this on a Windows 2000 machine (don't run please, I have to). I wrote the following function:

bool SetBSDLocationValues()
{ //TODO
   /*--------------------------------------------------------------------------------------
   search physical address range 0E0000h - 0FFFFFh for a 16-byte data structure,
   on a 16-byte boundary, described as follows:

         Offset       Size         Description
         0         4 bytes         The String "_32_".
         4         4 bytes         32 bit physical address (BIOS32 Entry Point)
         8         1 byte         Revision Level (00h)
         9         1 byte         Length (01h)
         0Ah         1 byte         Checksum of complete 16-byte structure(must==0 )
         0Bh         5 bytes         Reserved, must be 0
   
   ----------------------------------------------------------------------------------------*/

   UCHAR*   pStart      =(UCHAR*)0x0E0000;
   ULONG   pEnd      =0x100000;
   void*   pBIOS32      =NULL;
   UCHAR   Checksum   =0;

   while((ULONG)pStart<pEnd) {
      if(      (pStart[0]   ==   '_')
         &&   (pStart[1]   ==   '3')
         &&   (pStart[2]   ==   '2')
         &&   (pStart[3]   ==   '_')
         &&   (pBIOS32=(void*)pStart[4])
         &&   (pStart[8]   ==   0x00)
         &&   (pStart[9]   ==   0x01)
         &&   (Checksum=(UCHAR)pStart[10])
         &&   (pStart[11]   ==   0)
         &&   (pStart[12]   ==   0)
         &&   (pStart[13]   ==   0)
         &&   (pStart[14]   ==   0)
         &&   (pStart[15]   ==   0)
         )
      {
            for(int i=0;i<16;++i)
               Checksum+=pStart;
            if(Checksum==0)
            {
               SG2Control::BSD_EntryPoint=pBIOS32;
               return true;
            }
      }
      pStart+=16;
   }
   return false;
}


and obviously, it gives me a memory exception. I expected this to happen for one or both of the two reasons:

1)pStart could be treated as an offset from the virtual address space my programs running in, instead of the physical address,
2)Windows might not just let me access the physical memory that I want to, without some sort of formal request.

If anyone's ever had to use the PCI BIOS under windows 2000, or if you know how, any help would be greatly appreciated.

Thanks,
Peter
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re:Locating PCI BIOS service through BIOS32

Post by df »

runnung it under win32 i would have thought would not work as your are just using a pointer to address absolute memory. tho a dos extended app might work... hmm. dunno.

the code looks fine. i would test by just using the _32_ and then the crc bit and would remove the

Code: Select all

    &&   (pBIOS32=(void*)pStart[4])
         &&   (pStart[8]   ==   0x00)
         &&   (pStart[9]   ==   0x01)
         &&   (Checksum=(UCHAR)pStart[10])
         &&   (pStart[11]   ==   0)
         &&   (pStart[12]   ==   0)
         &&   (pStart[13]   ==   0)
         &&   (pStart[14]   ==   0)
         &&   (pStart[15]   ==   0)
bit...

my own code is this, which works fine

Code: Select all

UCHAR bios32_bsd_search(void)
{
   UCHAR      *p=(UCHAR*)0xE0000;
   BIOS32      *x;
   UCHAR      flag=1, crc;
   int         i;

   master_bios32=NULL;
   while(flag==1 && (ULONG)p<0x100000)
   {
      x=(BIOS32*)p;
      if(x->magic==0x5F32335F)      /* _32_ */
      {
         for(i=0, crc=0; i<(x->prg_lens*16); i++)
            crc+=*(p+i);
         if(crc==0)
         {
             flag=0;
             master_bios32=x;
         }
      }
      else
         p+=0x10;
   }

   if(flag==0)
   {
      vc_printf(2, "BIOS32 Service Dirctory found at : 0x%08lX, etntry 0x%08lX\n", (ULONG)master_bios32, master_bios32->phys_bsd_entry);
      if(master_bios32->phys_bsd_entry>0x100000)
         vc_printf(2, "BIOS32 BSD entry is in high memory... erkle!!\n");
   }
   else
      vc_printf(2, "Unable to find BIOS32 Service Directory \n");

   return flag;
}
-- Stu --
Peter Wright

Re:Locating PCI BIOS service through BIOS32

Post by Peter Wright »

Thank you for your reply,

I noticed that your code is similar to the reccomended code, posted <a href="http://www.osdev.org/osfaq2/index.php/I%20heard%20you%20can%20do%20PCI%20calls%20with%20the%20BIOS%20in%20Protected%20Mode%3F">here</a>, and it looked like it was doing the exact same thing as mine. Just to be exhaustive, I compiled and ran your code as well, which gave me the same error:

"Unhandled exception at 0x00411e0e in PCI Scan.exe: 0xC0000005: Access violation reading location 0x000e0000."

I don't usually program at this low of a level, so this is stretching my horizons, but sadly I've been at it a week and I still can't read the PCI configuration header.

When my code didn't work, It was encouraging to find that it was at least similar to the suggested way of doing things, but equally frustrating because the suggested code didn't work either (for me anyway) : /

How do I make sure that I'm accessing the the *physical* memory address 0E0000h? And how do i get permission (if i need it) to do so?

-Peter
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re:Locating PCI BIOS service through BIOS32

Post by df »

it might be accessable if you compile it under say djgpp or watcom and use dos4g. the ntvdm might let you see it.

otherwise you need win32 calls for locking physical memory stuff but ive never needed to do anything like this. so.. dunno. all i can tell you is my code works fine in a real machine + vmware..

check out craig harts pci stuff. he hs the source for his pci dumper available and it works under windows. it basically enumerates the pci busses and dumpes all the info.. good stuff.
-- Stu --
Peter Wright

Re:Locating PCI BIOS service through BIOS32

Post by Peter Wright »

under the circumstances, I wont be able to run the program through an emulator. It might not matter anyway, since according to webopedia, 'Windows NT will not allow NTVDM to execute instructions that try to directly manipulate hardware or memory locations'

I guess it's time to start searching for those mysterious win32 calls >< hopefully craig's code will be enlightening if I get my greedy eyes on it.

Thanks for your help,
Peter
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Locating PCI BIOS service through BIOS32

Post by Colonel Kernel »

You'll almost certainly have to write a kernel-mode driver to do what you want. NT does not allow the use of physical addresses in user-space. Your best bet is to start looking into the Windows DDK:

http://msdn.microsoft.com/library/en-us ... frame=true
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
Peter Wright

Re:Locating PCI BIOS service through BIOS32

Post by Peter Wright »

hmm... what do you mean by 'almost certainly' ?

Do I have to have the DDK to write a kernal mode driver for win2k, or , is it excruciatingly difficult to do so without the DDK ?

-Peter
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Locating PCI BIOS service through BIOS32

Post by Colonel Kernel »

I say "almost certainly" to cover my butt in case I'm wrong. ;) I've never written an NT kernel-mode driver before. I gather it's quite complex.
Do I have to have the DDK to write a kernal mode driver for win2k, or , is it excruciatingly difficult to do so without the DDK ?
If you don't use the DDK, what are you going to use? You need to know how your driver interacts with the kernel and what functions each calls in the other...
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
Post Reply