Mail Archives: djgpp/2001/05/09/10:31:29
> > > Yes, _dos_ds is defined to span the first 1MB (plus 64KB). If you
> > > need to read memory above 1MB mark, you will have to create your own
> > > selector and use it instead of _dos_ds in the call to _farpeekb. The
> > > two sections of the FAQ I cited explain how to do that, and show
> > > examples of working code.
> >
> > I read the FAQ and the program works fine - with Windows 98 and Windows
Me!
> > On Windows 2000 it just reads the values i get via the _dos_ds selector.
> > When I want to allocate a selector in the high address space the program
> > stops without any error messages or warnings...
>
> Please post the shortest test program which exhibits these problems.
> Are you checking the return values of the DPMI functions you call?
> Perhaps some of them fail?
I checked the return values, but none of them failed...
After modifying the program (making it smaller) the first DMI function
fails - but only with Windows 2000....
Maybe I make some really silly mistakes, so don't laugh at me, I am a
absolute beginner.
So, this is a code that causes the strange behaviour...
(Maybe some variables are unused or some include files are unused, because I
stripped off much of the program...)
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <conio.h>
#include <dpmi.h>
#include <sys/farptr.h>
#include <go32.h>
#include <bios.h>
#include <pc.h>
#include <ctype.h>
#define _DEBUG
typedef struct dmistruct
{
unsigned long start;
char major, minor;
unsigned int maxsize, length, numstruct;
};
dmistruct dmi;
typedef struct dmiheader
{
unsigned char Type;
unsigned char Length;
unsigned short Handle;
};
__dpmi_meminfo mi; // DPMI memory information structure
int selector; // selector variable
// The following function searches for _SM_ in the memory range
// F000:0000 to F000:FFFF (DOS memory)
// But unfortunately this signature is only available on PCs with
// a SMBIOS 2.0 compliant BIOS
// from the location at F000:xxxx I then read a 32 bit physical address
// where the table begins which I need to read
// at first all the calls were successfull and the program stopped at the
// _farpeekb afterwards, but now my program already stops at physical
address mapping...
// With Windows Me this works fine!
// ?!?!?
// ah...
// I also found out, if I remark all the "exit (-1)"'s the program prints
// nothing at all in Windows 2000, but runs fine on Win Me
// Do I have memory leaks?
// Or do I have to set specific compiler options?!?
int main()
{
char result=0;
unsigned long bios = 0xF000 * 0x10; // this is for the offset Seg*16+Ofs
int dmistart = 0;
unsigned int offset = 0;
do
if (_farpeekb (_dos_ds, bios + offset) == '_')
if (_farpeekb (_dos_ds, bios + offset + 1) == 'S')
if (_farpeekb (_dos_ds, bios + offset + 2) == 'M')
if (_farpeekb (_dos_ds, bios + offset + 3) == '_')
{
result = 1;
#ifdef _DEBUG
printf ("SMBIOS Signature found at F000:%X\n",offset);
#endif
break;
}
while ((offset += 0x1) < 0xFFFF);
if (!result) // if _SM_ not found in memory search for _DMI_
{ ; // The rest ist not used here...
/* offset = 0;
do
if (_farpeekb (_dos_ds, bios + offset) == '_')
if (_farpeekb (_dos_ds, bios + offset + 1) == 'D')
if (_farpeekb (_dos_ds, bios + offset + 2) == 'M')
if (_farpeekb (_dos_ds, bios + offset + 3) == 'I')
if (_farpeekb (_dos_ds, bios + offset + 4) == '_')
{
printf ("obsoleted DMI Signature found at F000:%X\n",offset);
printf ("This version of the program cannot cope with old
DMI tables\n");
printf ("Please upgrade to an SMBIOS compliant BIOS
version.\n");
break;
}
while ((offset += 0x1) < 0xFFFF);*/
}
if (result)
{
dmistart = offset;
char major = _farpeekb (_dos_ds, bios + offset + 0x06);
char minor = _farpeekb (_dos_ds, bios + offset + 0x07);
// The above two lines read a version information
unsigned int maxsize = _farpeekb (_dos_ds, bios + offset + 0x08) + 0x100
* _farpeekb (_dos_ds, bios + offset + 0x09);
dmi.length = _farpeekb (_dos_ds, bios + offset + 0x05);
// on offset 5 there is stored the length of this table in BIOS (only
temporarily used for checksum ...)
unsigned char checksum=0;
for (unsigned int k = 0; k <= dmi.length; checksum += _farpeekb
(_dos_ds, bios + offset + k++));
dmi.length = 0;
dmi.length = _farpeekb (_dos_ds, bios + offset + 0x16) + _farpeekb
(_dos_ds, bios + offset + 0x17) * 0x100;
dmi.numstruct = _farpeekb (_dos_ds, bios + offset + 0x1C) + 0x100 *
_farpeekb (_dos_ds, bios + offset + 0x1D);
dmi.start = _farpeekb (_dos_ds, bios + offset + 0x18) + 0x100 *
_farpeekb (_dos_ds, bios + offset + 0x19) +
0x10000 * _farpeekb (_dos_ds, bios + offset + 0x1A) + 0x1000000 *
_farpeekb (_dos_ds, bios + offset + 0x1B);
}
mi.address = dmi.start;
mi.size = dmi.length;
printf ("mi.address = %08X\n", dmi.start);
printf ("mi.size = %08X\n", dmi.length);
if (__dpmi_physical_address_mapping (&mi) == -1)
{
printf ("Error occurred on physical address mapping\n");
exit(-1);
}
selector = __dpmi_allocate_ldt_descriptors (1);
if (selector == -1)
{
printf ("Error occurred on allocating ldt descriptor!\n");
exit (-1);
}
__dpmi_set_segment_base_address (selector, mi.address);
if (selector == -1)
{
printf ("Error occurred on setting Segment Base Address.\n");
exit(-1);
}
if (__dpmi_set_segment_limit (selector, mi.size - 1) == -1)
{
printf ("Error occurred on setting segment limit.\n");
exit (-1);
}
char c;
for (int i = 0; i < dmi.length; i++)
{
printf ("%c", _farpeekb (selector, i));
}
// return result;
return 0;
}
- Raw text -