[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
UNDI/PXE driver for GRUB
From: |
Patrick J. LoPresti |
Subject: |
UNDI/PXE driver for GRUB |
Date: |
12 Aug 2002 12:46:49 -0400 |
User-agent: |
Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 |
(Note: To understand this message, it helps to have read the PXE 2.1
specification, especially chapter 3. You can download it from
<http://www.intel.com/labs/manage/wfm/wfmspecs.htm>.)
With hardware for which no Etherboot driver is available, it would be
nice if pxegrub could use the UNDI stack which is included with all
PXE-compliant network cards. In principle, this would allow pxegrub
to support any such card, current or future.
Since I have some hardware (mostly laptops) which Etherboot does not
support, I decided to take a crack at writing UNDI/PXE support this
weekend.
Let me describe what little I got working.
I began by adding a "pxe_trampoline" function to stage2/asm.S. This
function translates a protected-mode call to the real-mode call
required by the UNDI stack. (The PXE specification says that the UNDI
stack should work from protected mode, but that may mean 16-bit
protected mode (?). Anyway, I was unable to invoke the stack
successfully from protected mode.)
The trampoline function is pretty short, so I include it here:
/* Trampoline to call real-mode PXE functions.
pxe_trampoline(SEGOFF16 entry, int opcode, SEGOFF16 argptr)
*/
ENTRY(pxe_trampoline)
pushl %ebp
/* Copy arguments to scratch space */
movl 0x8(%esp), %eax
movl %eax, SCRATCHADDR
movl 0xc(%esp), %eax
movl %eax, SCRATCHADDR+4
movl 0x10(%esp), %eax
movl %eax, SCRATCHADDR+8
/* Drop to real mode */
call EXT_C(prot_to_real)
.code16
/* Get arguments from scratch segment */
movw $SCRATCHSEG, %ax
movw %ax, %es
/* segment of parameter block */
pushw %es:(10)
/* offset of parameter block */
pushw %es:(8)
/* PXE opcode (throwing away the high word) */
pushw %es:(4)
/* call PXE entry point */
lcall *%es:0
/* pop arguments */
addw $6, %sp
/* remember return value */
movw %ax, %dx
/* Return to protected mode */
DATA32 call EXT_C(real_to_prot)
.code32
/* Recover return value */
xorl %eax, %eax
movw %dx, %ax
popl %ebp
ret
Next, I began writing an "fsys_pxe" filesystem module. My idea was to
use the high-level TFTP support in the UNDI stack, ignoring most of
the existing netboot code since it depends on low-level polling
drivers. The low-level UNDI interface uses an interrupt-driven model.
I figured it would be easier to use the high-level UNDI TFTP interface
directly than to simulate the Etherboot polling model using the UNDI
interrupt-driven one.
The first thing my fsys_pxe module does is scan memory to find the
"!PXE" structure, which provides (among other things) the entry point
to the UNDI stack.
The next thing fsys_pxe does is call the PXENV_GET_CACHED_INFO routine
using the trampoline, requesting the DHCP ACK packet. This actually
works! It returns a valid and correct DHCP packet, complete with
gateway IP address, server IP address, client IP address, vendor
options, and so on. In other words, my pxe_trampoline function works,
which is the good news.
The bad news is that almost nothing else works. Most UNDI calls are
returning a failure code with the status field set to 0x01 ("general
failure"). Some calls (e.g., PXENV_TFTP_OPEN) pause for a while
before returning failure, but they do not actually emit any packets as
far as I can tell. Without anything more telling than "general
failure", I am at a bit of a loss for how to proceed.
I would be happy to make the rest of my code available to anybody who
is interested. I myself may end up using syslinux/pxelinux instead...
- Pat
- UNDI/PXE driver for GRUB,
Patrick J. LoPresti <=