From owner-freebsd-hackers Thu Nov 6 23:15:02 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id XAA15147 for hackers-outgoing; Thu, 6 Nov 1997 23:15:02 -0800 (PST) (envelope-from owner-freebsd-hackers) Received: from word.smith.net.au (word.smith.net.au [202.0.75.3]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id XAA15131 for ; Thu, 6 Nov 1997 23:14:50 -0800 (PST) (envelope-from mike@word.smith.net.au) Received: from word.smith.net.au (localhost.smith.net.au [127.0.0.1]) by word.smith.net.au (8.8.7/8.8.5) with ESMTP id RAA01443 for ; Fri, 7 Nov 1997 17:41:02 +1030 (CST) Message-Id: <199711070711.RAA01443@word.smith.net.au> X-Mailer: exmh version 2.0zeta 7/24/97 To: hackers@freebsd.org Subject: x86 gods; advice? Suggestions? Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Fri, 07 Nov 1997 17:41:01 +1030 From: Mike Smith Sender: owner-freebsd-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Ok, I'm stumped. Short of someone responsible to shoot, I could do with some help doing Evil x86 things. We all know why talking to the PnP BIOS would be a good thing. I don't think there's any disagreement there. Actually doing it is being a little more challenging. The spec says "It is assumed that the 16-Bit Protected Mode interface is sufficient for 32-Bit Protected Mode operating systems". Maybe. To cut a long story short; it is necessary to construct three segments (one 16-bit code, two 16-bit data), mapped as per the PnP connection information. Done, no problem. You call into the 16-bit segment to a given entrypoint. Done, no problem. The 16-bit segment wants to return to the caller. It executes an 'lret', popping a 16-bit IP and CS off the stack. Oops. If you have the kernel CS there, you can return to any address in the first 64k of the kernel segment. Unfortunately, that won't get you anywhere near the kernel text. As an alternative, I tried stealing a spare segment and arranging that to be based at the bottom of the kernel, so that the return would be into kernel text space, then pushing the kernel CS and IP of a suitable label onto the stack and lret'ing again to get back into the kernel. *this* tries to access memory at vaddr 0x81: /* biospnp(int offset, int segment, int junk, u_int16_t args[...]) */ ENTRY(biospnp) popl %ecx /* save return address */ movl %pnpret,%bx /* local return point */ mov %bx,(2*4)(%esp) lret pnpret: pushl $8 pushl %ecx lret The high half of (junk) comes in with the prepared selector for return in it. This *works* until the pnpret: label. Unfortunately, at that point it's not (yet) running on the kernel text selector, so ddb can't actually tell me what's going on. The stack looks OK (I never touch it), so I am somewhat stuffed as to what is going wrong. Any ideas? Any better ways of getting back into the kernel from 16-bit mode? mike