Added (not yet tested) PXE API entry point and support functions.
This commit is contained in:
parent
d12383f1d3
commit
18c112d205
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <gpxe/uaccess.h>
|
#include <gpxe/uaccess.h>
|
||||||
#include <registers.h>
|
#include <registers.h>
|
||||||
|
#include <biosint.h>
|
||||||
#include <pxe.h>
|
#include <pxe.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
@ -25,6 +26,21 @@
|
||||||
* PXE API entry point
|
* PXE API entry point
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** Vector for chaining INT 1A */
|
||||||
|
extern struct segoff __text16 ( pxe_int_1a_vector );
|
||||||
|
#define pxe_int_1a_vector __use_text16 ( pxe_int_1a_vector )
|
||||||
|
|
||||||
|
/** INT 1A handler */
|
||||||
|
extern void pxe_int_1a ( void );
|
||||||
|
|
||||||
|
/** !PXE structure */
|
||||||
|
extern struct s_PXE __text16 ( pxe );
|
||||||
|
#define pxe __use_text16 ( pxe )
|
||||||
|
|
||||||
|
/** PXENV+ structure */
|
||||||
|
extern struct s_PXENV __text16 ( pxenv );
|
||||||
|
#define pxenv __use_text16 ( pxenv )
|
||||||
|
|
||||||
/** A function pointer to hold any PXE API call
|
/** A function pointer to hold any PXE API call
|
||||||
*
|
*
|
||||||
* Used by pxe_api_call() to avoid large swathes of duplicated code.
|
* Used by pxe_api_call() to avoid large swathes of duplicated code.
|
||||||
|
@ -288,3 +304,95 @@ void pxe_api_call ( struct i386_all_regs *ix86 ) {
|
||||||
copy_to_user ( parameters, 0, &pxenv_any, param_len );
|
copy_to_user ( parameters, 0, &pxenv_any, param_len );
|
||||||
ix86->regs.ax = ret;
|
ix86->regs.ax = ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook INT 1A for PXE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void pxe_hook_int ( void ) {
|
||||||
|
hook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
|
||||||
|
&pxe_int_1a_vector );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unhook INT 1A for PXE
|
||||||
|
*
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int pxe_unhook_int ( void ) {
|
||||||
|
return unhook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
|
||||||
|
&pxe_int_1a_vector );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate byte checksum as used by PXE
|
||||||
|
*
|
||||||
|
* @v data Data
|
||||||
|
* @v size Length of data
|
||||||
|
* @ret sum Checksum
|
||||||
|
*/
|
||||||
|
static uint8_t pxe_checksum ( void *data, size_t size ) {
|
||||||
|
uint8_t *bytes = data;
|
||||||
|
uint8_t sum = 0;
|
||||||
|
|
||||||
|
while ( size-- ) {
|
||||||
|
sum += *bytes++;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise PXE stack
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void init_pxe ( void ) {
|
||||||
|
uint32_t rm_cs_phys = ( rm_cs << 4 );
|
||||||
|
uint32_t rm_ds_phys = ( rm_ds << 4 );
|
||||||
|
|
||||||
|
/* Fill in missing segment fields */
|
||||||
|
pxe.EntryPointSP.segment = rm_cs;
|
||||||
|
pxe.EntryPointESP.segment = rm_cs;
|
||||||
|
pxe.Stack.segment_address = rm_ds;
|
||||||
|
pxe.Stack.Physical_address = rm_ds_phys;
|
||||||
|
pxe.UNDIData.segment_address = rm_ds;
|
||||||
|
pxe.UNDIData.Physical_address = rm_ds_phys;
|
||||||
|
pxe.UNDICode.segment_address = rm_cs;
|
||||||
|
pxe.UNDICode.Physical_address = rm_cs_phys;
|
||||||
|
pxe.UNDICodeWrite.segment_address = rm_cs;
|
||||||
|
pxe.UNDICodeWrite.Physical_address = rm_cs_phys;
|
||||||
|
pxenv.RMEntry.segment = rm_cs;
|
||||||
|
pxenv.StackSeg = rm_ds;
|
||||||
|
pxenv.UNDIDataSeg = rm_ds;
|
||||||
|
pxenv.UNDICodeSeg = rm_cs;
|
||||||
|
pxenv.PXEPtr.segment = rm_cs;
|
||||||
|
|
||||||
|
/* Update checksums */
|
||||||
|
pxe.StructCksum -= pxe_checksum ( &pxe, sizeof ( pxe ) );
|
||||||
|
pxenv.Checksum -= pxe_checksum ( &pxenv, sizeof ( pxenv ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot via PXE NBP
|
||||||
|
*
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int pxe_boot ( void ) {
|
||||||
|
int discard_b, discard_c;
|
||||||
|
uint16_t rc;
|
||||||
|
|
||||||
|
/* Ensure that PXE stack is ready to use */
|
||||||
|
init_pxe();
|
||||||
|
pxe_hook_int();
|
||||||
|
|
||||||
|
/* Far call to PXE NBP */
|
||||||
|
__asm__ __volatile__ ( REAL_CODE ( "pushw %%cx\n\t"
|
||||||
|
"pushw %%ax\n\t"
|
||||||
|
"movw %%cx, %%es\n\t"
|
||||||
|
"lcall $0, $0x7c00\n\t" )
|
||||||
|
: "=a" ( rc ), "=b" ( discard_b ),
|
||||||
|
"=c" ( discard_c )
|
||||||
|
: "a" ( &pxe ), "b" ( &pxenv ), "c" ( rm_cs )
|
||||||
|
: "edx", "esi", "edi", "ebp", "memory" );
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.arch i386
|
||||||
|
.section ".text16", "awx", @progbits
|
||||||
|
.section ".text16.data", "aw", @progbits
|
||||||
|
.section ".data16", "aw", @progbits
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* !PXE structure
|
||||||
|
****************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".text16.data"
|
||||||
|
.globl pxe
|
||||||
|
pxe:
|
||||||
|
.ascii "!PXE" /* Signature */
|
||||||
|
.byte pxe_length /* StructLength */
|
||||||
|
.byte 0 /* StructCksum */
|
||||||
|
.byte 0 /* StructRev */
|
||||||
|
.byte 0 /* reserved_1 */
|
||||||
|
.word 0, 0 /* UNDIROMID */
|
||||||
|
.word 0, 0 /* BaseROMID */
|
||||||
|
.word pxe_entry_sp, 0 /* EntryPointSP */
|
||||||
|
.word pxe_entry_esp, 0 /* EntryPointESP */
|
||||||
|
.word -1, -1 /* StatusCallout */
|
||||||
|
.byte 0 /* reserved_2 */
|
||||||
|
.byte SegDescCnt /* SegDescCnt */
|
||||||
|
.word 0 /* FirstSelector */
|
||||||
|
pxe_segments:
|
||||||
|
.word 0, 0, 0, _data16_size /* Stack */
|
||||||
|
.word 0, 0, 0, _data16_size /* UNDIData */
|
||||||
|
.word 0, 0, 0, _text16_size /* UNDICode */
|
||||||
|
.word 0, 0, 0, _text16_size /* UNDICodeWrite */
|
||||||
|
.word 0, 0, 0, 0 /* BC_Data */
|
||||||
|
.word 0, 0, 0, 0 /* BC_Code */
|
||||||
|
.word 0, 0, 0, 0 /* BC_CodeWrite */
|
||||||
|
.equ SegDescCnt, ( ( . - pxe_segments ) / 8 )
|
||||||
|
.equ pxe_length, . - pxe
|
||||||
|
.size pxe, . - pxe
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* PXENV+ structure
|
||||||
|
****************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".text16.data"
|
||||||
|
.globl pxenv
|
||||||
|
pxenv:
|
||||||
|
.ascii "PXENV+" /* Signature */
|
||||||
|
.word 0x0201 /* Version */
|
||||||
|
.byte pxenv_length /* Length */
|
||||||
|
.byte 0 /* Checksum */
|
||||||
|
.word pxenv_entry, 0 /* RMEntry */
|
||||||
|
.long 0 /* PMEntry */
|
||||||
|
.word 0 /* PMSelector */
|
||||||
|
.word 0 /* StackSeg */
|
||||||
|
.word _data16_size /* StackSize */
|
||||||
|
.word 0 /* BC_CodeSeg */
|
||||||
|
.word 0 /* BC_CodeSize */
|
||||||
|
.word 0 /* BC_DataSeg */
|
||||||
|
.word 0 /* BC_DataSize */
|
||||||
|
.word 0 /* UNDIDataSeg */
|
||||||
|
.word _data16_size /* UNDIDataSize */
|
||||||
|
.word 0 /* UNDICodeSeg */
|
||||||
|
.word _text16_size /* UNDICodeSize */
|
||||||
|
.word pxe, 0 /* PXEPtr */
|
||||||
|
.equ pxenv_length, . - pxenv
|
||||||
|
.size pxenv, . - pxenv
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* pxenv_entry (16-bit far call)
|
||||||
|
*
|
||||||
|
* PXE API call PXENV+ entry point
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* %es:di : Far pointer to PXE parameter structure
|
||||||
|
* %bx : PXE API call
|
||||||
|
* Returns:
|
||||||
|
* %ax : PXE exit status
|
||||||
|
* Corrupts:
|
||||||
|
* none
|
||||||
|
****************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".text16"
|
||||||
|
.code16
|
||||||
|
pxenv_entry:
|
||||||
|
pushl $pxe_api_call
|
||||||
|
pushw %cs
|
||||||
|
call prot_call
|
||||||
|
addl $4, %esp
|
||||||
|
lret
|
||||||
|
.size pxenv_entry, . - pxenv_entry
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* pxe_entry
|
||||||
|
*
|
||||||
|
* PXE API call !PXE entry point
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* stack : Far pointer to PXE parameter structure
|
||||||
|
* stack : PXE API call
|
||||||
|
* Returns:
|
||||||
|
* %ax : PXE exit status
|
||||||
|
* Corrupts:
|
||||||
|
* none
|
||||||
|
****************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".text16"
|
||||||
|
.code16
|
||||||
|
pxe_entry:
|
||||||
|
pxe_entry_sp:
|
||||||
|
/* Preserve original %esp */
|
||||||
|
pushl %esp
|
||||||
|
/* Zero high word of %esp to allow use of common code */
|
||||||
|
movzwl %sp, %esp
|
||||||
|
jmp pxe_entry_common
|
||||||
|
pxe_entry_esp:
|
||||||
|
/* Preserve %esp to match behaviour of pxe_entry_sp */
|
||||||
|
pushl %esp
|
||||||
|
pxe_entry_common:
|
||||||
|
/* Save PXENV+ API call registers */
|
||||||
|
pushw %es
|
||||||
|
pushw %di
|
||||||
|
pushw %bx
|
||||||
|
/* Load !PXE parameters from stack into PXENV+ registers */
|
||||||
|
movw 16(%esp), %bx
|
||||||
|
movw %bx, %es
|
||||||
|
movw 14(%esp), %di
|
||||||
|
movw 12(%esp), %bx
|
||||||
|
/* Make call as for PXENV+ */
|
||||||
|
pushw %cs
|
||||||
|
call pxenv_entry
|
||||||
|
/* Restore PXENV+ registers */
|
||||||
|
popw %bx
|
||||||
|
popw %di
|
||||||
|
popw %es
|
||||||
|
/* Restore original %esp and return */
|
||||||
|
popl %esp
|
||||||
|
lret
|
||||||
|
.size pxe_entry, . - pxe_entry
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* pxe_int_1a
|
||||||
|
*
|
||||||
|
* PXE INT 1A handler
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* %ax : 0x5650
|
||||||
|
* Returns:
|
||||||
|
* %ax : 0x564e
|
||||||
|
* %es:bx : Far pointer to the PXENV+ structure
|
||||||
|
* CF cleared
|
||||||
|
* Corrupts:
|
||||||
|
* none
|
||||||
|
****************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".text16"
|
||||||
|
.code16
|
||||||
|
pxe_int_1a:
|
||||||
|
pushfw
|
||||||
|
cmpw $0x5650, %ax
|
||||||
|
jne 1f
|
||||||
|
/* INT 1A,5650 - PXE installation check */
|
||||||
|
pushw %cs
|
||||||
|
popw %es
|
||||||
|
movw $pxenv, %bx
|
||||||
|
movw $0x564e, %ax
|
||||||
|
popfw
|
||||||
|
clc
|
||||||
|
lret $2
|
||||||
|
1: /* INT 1A,other - pass through */
|
||||||
|
popfw
|
||||||
|
ljmp *%cs:pxe_int_1a_vector
|
||||||
|
|
||||||
|
.section ".text16.data"
|
||||||
|
.globl pxe_int_1a_vector
|
||||||
|
pxe_int_1a_vector: .long 0
|
Reference in New Issue