From: "Thomas Schachtner" 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 #include #include #include #include #include #include #include #include #include #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; }