Mail Archives: djgpp/1999/10/19/10:35:10
Message-ID: | <005f01bf1a10$4d4d6560$293f8589@gv015029.bgo.nera.no>
|
From: | "Gisle Vanem" <gvanem AT eunet DOT no>
|
To: | <djgpp AT delorie DOT com>
|
Subject: | Re: far call
|
Date: | Tue, 19 Oct 1999 10:59:26 +0200
|
MIME-Version: | 1.0
|
X-Priority: | 3
|
X-MSMail-Priority: | Normal
|
X-Mailer: | Microsoft Outlook Express 4.72.3110.5
|
X-MIMEOLE: | Produced By Microsoft MimeOLE V4.72.3110.3
|
Reply-To: | djgpp AT delorie DOT com
|
Eli Zaretskii <eliz AT is DOT elta DOT co DOT il> said:
>> bios32_api.offset32 = check.fields.entry;
>> bios32_api.selector = selector;
>
>You have defined a special selector for the memory region, but didn't
>adjust the offset accordingly. You need to subtract addr from
>check.fields.entry, to make it a segment-relative offset suitable to
>use with your selector. Otherwise, bios32_api.offset32 is way above
>the 4K limit you've set up for bios32_api.selector.
Thanks for the tips, but it's still crashing. Here the symify output and revised code:
BIOS32: BIOS32 Service Directory structure at 000FDB60h
BIOS32: BIOS32 Service Directory entry at 000FDB70h
BIOS32: pmode entry at 01D7h:00000010h
Exiting due to signal SIGSEGV
General Protection Fault at eip=00001dcc, error=01d4
eax=49435024 ebx=00000000 ecx=00000000 edx=00000035 esi=00000054 edi=49435024
ebp=0008f6e4 esp=0008f6d4 program=D:\NET\TCPDUMP\PCAP\PM_DRVR\B32.EXE
cs: sel=01b7 base=022a0000 limit=0009ffff
ds: sel=01bf base=022a0000 limit=0009ffff
es: sel=01bf base=022a0000 limit=0009ffff
fs: sel=0187 base=0001c320 limit=0000ffff
gs: sel=01c7 base=00000000 limit=0010ffff
ss: sel=01bf base=022a0000 limit=0009ffff
App stack: [0008f710..0000f710] Exceptn stack: [0000f5f8..0000d6b8]
Call frame traceback EIPs:
0x00001dcc _bios32_service+16, line 44 of b32.c
0x00002046 _main+22, line 132 of b32.c
0x00002fde ___crt1_startup+174
------------------------------- cut ---------------------------------------------
#include <stdio.h>
#include <string.h>
#include <dpmi.h>
#include <go32.h>
/* signatures: "_32_" + "$PCI"
*/
#define BIOS32_SIGNATURE (('_'<<0) + ('3'<<8) + ('2'<<16) + ('_'<<24))
#define PCI_SERVICE (('$'<<0) + ('P'<<8) + ('C'<<16) + ('I'<<24))
static __dpmi_paddr bios32_api;
#pragma pack(1) /* turn on packing, I'm sure this is equal to __attribute__((packed)) */
union bios32 {
struct {
unsigned long signature; /* "_32_" */
unsigned long entry; /* 32 bit physical address */
unsigned char revision; /* Revision level, 0 */
unsigned char length; /* Length in paragraphs should be 01 */
unsigned char checksum; /* All bytes must add up to zero */
unsigned char reserved[5]; /* Must be zero */
} fields;
char chars[16];
};
#pragma pack()
/* Returns the entry point for the given service, NULL on error
*/
unsigned long bios32_service (unsigned long service)
{
unsigned char return_code; /* %al */
unsigned long address; /* %ebx */
unsigned long length; /* %ecx */
unsigned long entry; /* %edx */
#if 0
__asm__ __volatile__ (
"lcall (%%edi)"
: "=a" (return_code), "=b" (address), "=c" (length), "=d" (entry)
: "0" (service), "1" (0), "D" (&bios32_api) );
#else
__asm__ __volatile__ (
"lcall _bios32_api" /* line 44, crashes here */
: "=a" (return_code), "=b" (address), "=c" (length), "=d" (entry)
: "0" (service), "1" (0) );
#endif
switch (return_code)
{
case 0:
return (address + entry);
case 0x80:
printf ("bios32_service(%08lX): not present\n", service);
return (0);
default:
printf ("bios32_service(%08lX): returned %X\n",
service, return_code);
return (0);
}
}
int pcibios_init (void)
{
unsigned char sum;
unsigned long addr;
int i, length;
for (addr = 0xe0000; addr <= 0xffff0; addr += 16)
{
union bios32 check;
unsigned short selector;
dosmemget (addr, sizeof(check), &check);
if (check.fields.signature != BIOS32_SIGNATURE)
continue;
length = check.fields.length * 16;
if (!length)
continue;
sum = 0;
for (i = 0; i < length; ++i)
sum += check.chars[i];
if (sum != 0)
continue;
if (check.fields.revision != 0)
{
printf ("BIOS32: unsupported revision %d at %08lX\n",
check.fields.revision, addr);
continue;
}
printf ("BIOS32: BIOS32 Service Directory structure at %08lXh\n",
addr);
if (check.fields.entry >= 0x100000)
{
printf ("BIOS32: entry in high memory!\n");
return (0);
}
selector = __dpmi_allocate_ldt_descriptors (1);
printf ("BIOS32: BIOS32 Service Directory entry at %08lXh\n",
check.fields.entry);
if (selector <= 0)
{
printf ("BIOS32: failed to create selector\n");
return (0);
}
__dpmi_set_segment_base_address (selector, addr);
__dpmi_set_segment_limit (selector, 4096-1);
bios32_api.offset32 = check.fields.entry - addr;
bios32_api.selector = selector;
printf ("BIOS32: pmode entry at %04Xh:%08lXh\n",
bios32_api.selector, bios32_api.offset32);
return (1);
}
return (0);
}
int main (void)
{
if (pcibios_init())
bios32_service (PCI_SERVICE);
return (0);
}
------------------------------- cut ---------------------------------------------
Generating asm-output, the "lcall" looks okay. Unless 'bios32_api' is
wrongly aligned. I didn't see that <dpmi.h> packs '__dpmi_paddr' in
any way.
Maybe I need to modify the selector for 'execute' ? (don't think so)
Gisle V.
- Raw text -