Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 07 Nov 1997 17:41:01 +1030
From:      Mike Smith <mike@smith.net.au>
To:        hackers@freebsd.org
Subject:   x86 gods; advice?  Suggestions?
Message-ID:  <199711070711.RAA01443@word.smith.net.au>

next in thread | raw e-mail | index | archive | help

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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711070711.RAA01443>