Skip to content

Commit

Permalink
pxe: Export the initial stack and PXE(NV) structure, fix pxechn
Browse files Browse the repository at this point in the history
Export the initial stack and PXE(NV) structure pointers properly, even
for users which need seg:offs.  Use this in pxechn.c rather than the
already-removed INT 22h AX=000Ah call.

Signed-off-by: H. Peter Anvin <[email protected]>
Cc: Gene Cumm <[email protected]>
  • Loading branch information
H. Peter Anvin committed Feb 13, 2014
1 parent e6374f1 commit 8c11d92
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 26 deletions.
4 changes: 2 additions & 2 deletions com32/include/syslinux/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ union syslinux_derivative_info {
const uint64_t *partoffset;
} disk; /* syslinux/extlinux */
struct {
uint16_t _gs, _fs, _es, _ds;
uint32_t _edi, _esi, _ebp, _esp, _ebx;
uint16_t _gs, stack_seg, pxenv_seg, _ds;
uint32_t _edi, stack_offs, _ebp, _esp, pxenv_offs;
uint16_t apiver;
uint16_t _dxh;
uint32_t myip;
Expand Down
32 changes: 17 additions & 15 deletions com32/modules/pxechn.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,25 +326,27 @@ void print_pxe_bootp_t(pxe_bootp_t *p, size_t len)

void pxe_set_regs(struct syslinux_rm_regs *regs)
{
com32sys_t tregs;
const union syslinux_derivative_info *sdi;
const com32sys_t *pxe_regs;

sdi = syslinux_derivative_info();
pxe_regs = sdi->pxe.stack; /* Original register values */

/* Just to be sure... */
memset(regs, 0, sizeof *regs);

memset(&tregs,0,sizeof(tregs));
regs->ip = 0x7C00;
/* Plan A uses SS:[SP + 4] */
/* sdi->pxe.stack is a usable pointer, not something that can be nicely
and reliably split to SS:SP without causing issues */
tregs.eax.l = 0x000A;
__intcall(0x22, &tregs, &tregs);
regs->ss = tregs.fs;
regs->esp.l = tregs.esi.w[0] + sizeof(tregs);
/* Plan B uses [ES:BX] */
regs->es = tregs.es;
regs->ebx = tregs.ebx;

/* Point to the original stack */
regs->ss = sdi->pxe.stack_seg;
regs->esp.l = sdi->pxe.stack_offs + sizeof(com32sys_t);

/* Point to the PXENV+ address */
regs->es = pxe_regs->es;
regs->ebx.l = pxe_regs->ebx.l;

dprintf("\nsp:%04x ss:%04x es:%04x bx:%04x\n", regs->esp.w[0],
regs->ss, regs->es, regs->ebx.w[0]);
/* Zero out everything else just to be sure */
regs->cs = regs->ds = regs->fs = regs->gs = 0;
regs->eax.l = regs->ecx.l = regs->edx.l = 0;
}

int hostlen_limit(int len)
Expand Down
19 changes: 16 additions & 3 deletions core/fs/pxe/bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ static uint16_t real_base_mem; /* Amount of DOS memory after freeing */
static bool has_gpxe;
static uint32_t gpxe_funcs;

far_ptr_t StrucPtr;

/*
* Validity check on possible !PXE structure in buf
* return 1 for success, 0 for failure.
Expand Down Expand Up @@ -162,20 +164,28 @@ int pxe_init(bool quiet)
regs.eax.w[0] = 0x5650;
call16(pxe_int1a, &regs, &regs);
if (!(regs.eflags.l & EFLAGS_CF) && (regs.eax.w[0] == 0x564e)) {
pxenv = MK_PTR(regs.es, regs.ebx.w[0]);
off = regs.ebx.w[0];
seg = regs.es;
pxenv = MK_PTR(seg, off);
if (is_pxenv(pxenv))
goto have_pxenv;
}

/* Plan D: !PXE memory scan */
plan++;
if ((pxe = memory_scan_for_pxe_struct()))
if ((pxe = memory_scan_for_pxe_struct())) {
off = OFFS(pxe);
seg = SEG(pxe);
goto have_pxe;
}

/* Plan E: PXENV+ memory scan */
plan++;
if ((pxenv = memory_scan_for_pxenv_struct()))
if ((pxenv = memory_scan_for_pxenv_struct())) {
off = OFFS(pxenv);
seg = SEG(pxenv);
goto have_pxenv;
}

/* Found nothing at all !! */
if (!quiet)
Expand Down Expand Up @@ -222,6 +232,9 @@ int pxe_init(bool quiet)
type = "!PXE";

have_entrypoint:
StrucPtr.offs = off;
StrucPtr.seg = seg;

if (!quiet) {
ddprintf("%s entry point found (we hope) at %04X:%04X via plan %c\n",
type, PXEEntry.seg, PXEEntry.offs, plan);
Expand Down
11 changes: 7 additions & 4 deletions core/pxelinux-c.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include <syslinux/config.h>
#include <com32.h>

extern void *StrucPtr;
extern void *InitStack;
extern far_ptr_t InitStack, StrucPtr;

/*
* IP information. Note that the field are in the same order as the
Expand All @@ -15,8 +14,12 @@ __export void get_derivative_info(union syslinux_derivative_info *di)
{
di->pxe.filesystem = SYSLINUX_FS_PXELINUX;
di->pxe.apiver = APIVer;
di->pxe.pxenvptr = &StrucPtr;
di->pxe.stack = &InitStack;
di->pxe.pxenvptr = GET_PTR(StrucPtr);
di->pxe.pxenv_offs = StrucPtr.offs;
di->pxe.pxenv_seg = StrucPtr.seg;
di->pxe.stack = GET_PTR(InitStack);
di->pxe.stack_offs = InitStack.offs;
di->pxe.stack_seg = InitStack.seg;
di->pxe.ipinfo = &IPInfo;
di->pxe.myip = IPInfo.myip;
}
3 changes: 1 addition & 2 deletions core/pxelinux.asm
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ InitStack resd 1
PXEStack resd 1 ; Saved stack during PXE call

alignb 4
global DHCPMagic, RebootTime, StrucPtr, BIOSName
global DHCPMagic, RebootTime, BIOSName
RebootTime resd 1 ; Reboot timeout, if set by option
StrucPtr resw 2 ; Pointer to PXENV+ or !PXE structure
LocalBootType resw 1 ; Local boot return code
DHCPMagic resb 1 ; PXELINUX magic flags
BIOSName resw 1 ; Dummy variable - always 0
Expand Down

0 comments on commit 8c11d92

Please sign in to comment.