diff --git a/src/arch/i386/include/pxe_call.h b/src/arch/i386/include/pxe_call.h index 50667e62..4d245616 100644 --- a/src/arch/i386/include/pxe_call.h +++ b/src/arch/i386/include/pxe_call.h @@ -34,5 +34,24 @@ extern void pxe_activate ( struct net_device *netdev ); extern int pxe_deactivate ( void ); extern int pxe_start_nbp ( void ); extern __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ); +extern int _pxe_api_call_weak ( struct i386_all_regs *ix86 ) + __attribute__ (( weak )); + +/** + * Dispatch PXE API call weakly + * + * @v ix86 Registers for PXE call + * @ret present Zero if the PXE stack is present, nonzero if not + * + * A successful return only indicates that the PXE stack was available + * for dispatching the call; it says nothing about the success of + * whatever the call asked for. + */ +static inline int pxe_api_call_weak ( struct i386_all_regs *ix86 ) +{ + if ( _pxe_api_call_weak != NULL ) + return _pxe_api_call_weak ( ix86 ); + return -1; +} #endif /* _PXE_CALL_H */ diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c index 705afcab..a50d6437 100644 --- a/src/arch/i386/interface/pxe/pxe_call.c +++ b/src/arch/i386/interface/pxe/pxe_call.c @@ -339,6 +339,18 @@ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) { ix86->regs.ax = ret; } +/** + * Dispatch weak PXE API call with PXE stack available + * + * @v ix86 Registers for PXE call + * @ret present Zero (PXE stack present) + */ +int _pxe_api_call_weak ( struct i386_all_regs *ix86 ) +{ + pxe_api_call ( ix86 ); + return 0; +} + /** * Dispatch PXE loader call * diff --git a/src/arch/i386/interface/syslinux/comboot_call.c b/src/arch/i386/interface/syslinux/comboot_call.c index 08fd1736..0a17bf13 100644 --- a/src/arch/i386/interface/syslinux/comboot_call.c +++ b/src/arch/i386/interface/syslinux/comboot_call.c @@ -445,8 +445,10 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) { break; case 0x0009: /* Call PXE Stack */ - pxe_api_call ( ix86 ); - ix86->flags &= ~CF; + if ( pxe_api_call_weak ( ix86 ) != 0 ) + ix86->flags |= CF; + else + ix86->flags &= ~CF; break; case 0x000A: /* Get Derivative-Specific Information */ diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index d695fd92..952eccdd 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -126,6 +126,7 @@ prodstr_pci_id: .size prodstr, . - prodstr .globl undiheader + .weak undiloader undiheader: .ascii "UNDI" /* Signature */ .byte undiheader_len /* Length of structure */ @@ -495,6 +496,7 @@ init_message_done: * * May be either within option ROM space, or within PMM-allocated block. */ + .globl image_source image_source: .long 0 .size image_source, . - image_source @@ -503,6 +505,7 @@ image_source: * * May be either at HIGHMEM_LOADPOINT, or within PMM-allocated block. */ + .globl decompress_to decompress_to: .long HIGHMEM_LOADPOINT .size decompress_to, . - decompress_to @@ -644,50 +647,6 @@ exec_message: .asciz " starting execution\n" .size exec_message, . - exec_message -/* UNDI loader - * - * Called by an external program to load our PXE stack. - */ -undiloader: - /* Save registers */ - pushl %esi - pushl %edi - pushw %ds - pushw %es - pushw %bx - /* ROM segment address to %ds */ - pushw %cs - popw %ds - /* UNDI loader parameter structure address into %es:%di */ - movw %sp, %bx - movw %ss:18(%bx), %di - movw %ss:20(%bx), %es - /* Install to specified real-mode addresses */ - pushw %di - movw %es:12(%di), %bx - movw %es:14(%di), %ax - movl image_source, %esi - movl decompress_to, %edi - call install_prealloc - popw %di - /* Call UNDI loader C code */ - pushl $pxe_loader_call - pushw %cs - pushw $1f - pushw %ax - pushw $prot_call - lret -1: popw %bx /* discard */ - popw %bx /* discard */ - /* Restore registers and return */ - popw %bx - popw %es - popw %ds - popl %edi - popl %esi - lret - .size undiloader, . - undiloader - /* Wait for key press specified by %bl (masked by %bh) * * Used by init and INT19 code when prompting user. If the specified diff --git a/src/arch/i386/prefix/undiloader.S b/src/arch/i386/prefix/undiloader.S new file mode 100644 index 00000000..36c1bef3 --- /dev/null +++ b/src/arch/i386/prefix/undiloader.S @@ -0,0 +1,49 @@ + .text + .code16 + .arch i386 + .section ".prefix", "ax", @progbits + +/* UNDI loader + * + * Called by an external program to load our PXE stack. + */ + .globl undiloader +undiloader: + /* Save registers */ + pushl %esi + pushl %edi + pushw %ds + pushw %es + pushw %bx + /* ROM segment address to %ds */ + pushw %cs + popw %ds + /* UNDI loader parameter structure address into %es:%di */ + movw %sp, %bx + movw %ss:18(%bx), %di + movw %ss:20(%bx), %es + /* Install to specified real-mode addresses */ + pushw %di + movw %es:12(%di), %bx + movw %es:14(%di), %ax + movl image_source, %esi + movl decompress_to, %edi + call install_prealloc + popw %di + /* Call UNDI loader C code */ + pushl $pxe_loader_call + pushw %cs + pushw $1f + pushw %ax + pushw $prot_call + lret +1: popw %bx /* discard */ + popw %bx /* discard */ + /* Restore registers and return */ + popw %bx + popw %es + popw %ds + popl %edi + popl %esi + lret + .size undiloader, . - undiloader diff --git a/src/config/config.c b/src/config/config.c index f487ae97..82524025 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -91,6 +91,17 @@ REQUIRE_OBJECT ( efi_console ); REQUIRE_OBJECT ( ipv4 ); #endif +/* + * Drag in all requested PXE support + * + */ +#ifdef PXE_MENU +REQUIRE_OBJECT ( pxemenu ); +#endif +#ifdef PXE_STACK +REQUIRE_OBJECT ( pxe_call ); +#endif + /* * Drag in all requested download protocols * diff --git a/src/config/config_romprefix.c b/src/config/config_romprefix.c new file mode 100644 index 00000000..85f1e78a --- /dev/null +++ b/src/config/config_romprefix.c @@ -0,0 +1,24 @@ +/* + * 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, or (at + * your option) any later version. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** @file + * + * ROM prefix configuration options + * + */ + +/* + * Provide UNDI loader if PXE stack is requested + * + */ +#ifdef PXE_STACK +REQUIRE_OBJECT ( undiloader ); +#endif diff --git a/src/config/defaults/pcbios.h b/src/config/defaults/pcbios.h index 51d729e2..c09105cc 100644 --- a/src/config/defaults/pcbios.h +++ b/src/config/defaults/pcbios.h @@ -25,6 +25,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define IMAGE_BZIMAGE /* Linux bzImage image support */ #define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */ +#define PXE_STACK /* PXE stack in gPXE - required for PXELINUX */ +#define PXE_MENU /* PXE menu booting */ #define PXE_CMD /* PXE commands */ #define SANBOOT_PROTO_ISCSI /* iSCSI protocol */ diff --git a/src/config/general.h b/src/config/general.h index 5187e2a1..f721f612 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -41,6 +41,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define NET_PROTO_IPV4 /* IPv4 protocol */ +/* + * PXE support + * + */ +//#undef PXE_STACK /* PXE stack in gPXE - you want this! */ +//#undef PXE_MENU /* PXE menu booting */ + /* * Download protocols * diff --git a/src/include/usr/autoboot.h b/src/include/usr/autoboot.h index 16306cd0..a9180202 100644 --- a/src/include/usr/autoboot.h +++ b/src/include/usr/autoboot.h @@ -18,6 +18,8 @@ extern void autoboot ( void ); extern int boot_next_server_and_filename ( struct in_addr next_server, const char *filename ); extern int boot_root_path ( const char *root_path ); -extern int pxe_menu_boot ( struct net_device *netdev ); + +extern int pxe_menu_boot ( struct net_device *netdev ) + __attribute__ (( weak )); #endif /* _USR_AUTOBOOT_H */ diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index b9c1fdaa..8c4398c3 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -151,7 +151,7 @@ static int netboot ( struct net_device *netdev ) { buf, sizeof ( buf ) ); pxe_discovery_control = fetch_uintz_setting ( NULL, &pxe_discovery_control_setting ); - if ( ( strcmp ( buf, "PXEClient" ) == 0 ) && + if ( ( strcmp ( buf, "PXEClient" ) == 0 ) && pxe_menu_boot != NULL && setting_exists ( NULL, &pxe_boot_menu_setting ) && ( ! ( ( pxe_discovery_control & PXEBS_SKIP ) && setting_exists ( NULL, &filename_setting ) ) ) ) {