mirror of
https://github.com/xcat2/xNBA.git
synced 2025-02-09 15:23:30 +00:00
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 <registers.h>
|
||||
#include <biosint.h>
|
||||
#include <pxe.h>
|
||||
|
||||
/** @file
|
||||
@ -25,6 +26,21 @@
|
||||
* 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
|
||||
*
|
||||
* 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 );
|
||||
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;
|
||||
}
|
||||
|
192
src/arch/i386/interface/pxe/pxe_entry.S
Normal file
192
src/arch/i386/interface/pxe/pxe_entry.S
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user