www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2001/05/09/10:31:29

From: "Thomas Schachtner" <thomas DOT schachtner AT gmx DOT de>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: read a specific memory address
Date: Wed, 9 May 2001 16:24:24 +0200
Organization: Deutsche Telekom AG
Lines: 192
Message-ID: <9dbjel$35j$2@news2.dtag.de>
References: <9cp464$ju8$1 AT news2 DOT dtag DOT de> <9cp8nj$ap6$1 AT nets3 DOT rz DOT RWTH-Aachen DOT DE> <9cu780$5rr$1 AT news2 DOT dtag DOT de> <3028-Fri04May2001183719+0300-eliz AT is DOT elta DOT co DOT il> <000c01c0d56e$77a9a7e0$cb099d3e AT iron> <9003-Sat05May2001175837+0300-eliz AT is DOT elta DOT co DOT il> <001901c0d577$954622c0$cb099d3e AT iron> <1659-Sat05May2001211357+0300-eliz AT is DOT elta DOT co DOT il> <9d8src$9kc$1 AT news2 DOT dtag DOT de> <5137-Tue08May2001211326+0300-eliz AT is DOT elta DOT co DOT il>
NNTP-Posting-Host: masked-user.toshiba-tro.de
X-Trace: news2.dtag.de 989417749 3251 194.25.188.1 (9 May 2001 14:15:49 GMT)
X-Complaints-To: usenet AT news DOT dtag DOT de
NNTP-Posting-Date: 9 May 2001 14:15:49 GMT
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 5.50.4522.1200
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4522.1200
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

> > > 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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019