mirror of
https://github.com/xcat2/xNBA.git
synced 2026-04-24 21:51:28 +00:00
@@ -179,7 +179,12 @@ if ( $embedded_script != "" ) {
|
||||
|
||||
// Make the requested image. $status is set to 0 on success
|
||||
$make_target = "bin/${nic}.${fmt_extension}";
|
||||
$make_cmd = "make -C '$build_dir' '$make_target' $emb_script_cmd 2>&1";
|
||||
$gitversion = exec('git describe --always --abbrev=1 --match "" 2>/dev/null');
|
||||
if ($gitversion) {
|
||||
$gitversion = "GITVERSION=$gitversion";
|
||||
}
|
||||
|
||||
$make_cmd = "make -C '$build_dir' '$make_target' $gitversion $emb_script_cmd 2>&1";
|
||||
|
||||
exec ( $make_cmd, $maketxt, $status );
|
||||
|
||||
@@ -239,7 +244,7 @@ if ( $status == 0 ) {
|
||||
// Delete build directory as soon as it is not needed
|
||||
rm_build_dir ();
|
||||
|
||||
$output_filename = "ipxe-${version}-${nic}.${fmt_extension}";
|
||||
$output_filename = preg_replace('/[^a-z0-9\+\.\-]/i', '', "ipxe-${version}-${nic}.${fmt_extension}");
|
||||
|
||||
// Try to force IE to handle downloading right.
|
||||
Header ( "Cache-control: private");
|
||||
|
||||
@@ -109,6 +109,16 @@ $flag_table = array (
|
||||
"cfgsec" => "console"
|
||||
),
|
||||
|
||||
"LOG_LEVEL"
|
||||
=> array (
|
||||
"flag" => "LOG_LEVEL",
|
||||
"type" => "choice",
|
||||
"options" => array("LOG_NONE","LOG_EMERG","LOG_ALERT","LOG_CRIT","LOG_ERR",
|
||||
"LOG_WARNING","LOG_NOTICE","LOG_INFO","LOG_DEBUG","LOG_ALL"),
|
||||
"value" => "LOG_NONE",
|
||||
"cfgsec" => "console"
|
||||
),
|
||||
|
||||
// End Console Options
|
||||
|
||||
// Begin Network Protocol Options:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
31
src/Makefile
31
src/Makefile
@@ -143,7 +143,25 @@ everything :
|
||||
bin-i386-efi/ipxe.efirom \
|
||||
bin-x86_64-efi/ipxe.efi bin-x86_64-efi/ipxe.efidrv \
|
||||
bin-x86_64-efi/ipxe.efirom \
|
||||
bin-i386-linux/tap.linux bin-x86_64-linux/tap.linux
|
||||
bin-i386-linux/tap.linux bin-x86_64-linux/tap.linux \
|
||||
bin-i386-linux/tests.linux bin-x86_64-linux/tests.linux
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# VMware build target: all ROMs used with VMware
|
||||
#
|
||||
vmware : bin/8086100f.mrom bin/808610d3.mrom bin/10222000.rom bin/15ad07b0.rom
|
||||
@$(ECHO) '==========================================================='
|
||||
@$(ECHO)
|
||||
@$(ECHO) 'Available ROMs:'
|
||||
@$(ECHO) ' bin/8086100f.mrom -- intel/e1000'
|
||||
@$(ECHO) ' bin/808610d3.mrom -- intel/e1000e'
|
||||
@$(ECHO) ' bin/10222000.rom -- vlance/pcnet32'
|
||||
@$(ECHO) ' bin/15ad07b0.rom -- vmxnet3'
|
||||
@$(ECHO)
|
||||
@$(ECHO) 'For more information, see http://ipxe.org/howto/vmware'
|
||||
@$(ECHO)
|
||||
@$(ECHO) '==========================================================='
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
@@ -165,13 +183,12 @@ VERSION_PATCH = 3
|
||||
EXTRAVERSION = -$(shell date +%y%m%d)
|
||||
MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR)
|
||||
VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION)
|
||||
CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) \
|
||||
-DVERSION_MINOR=$(VERSION_MINOR) \
|
||||
-DVERSION_PATCH=$(VERSION_PATCH) \
|
||||
-DVERSION=\"$(VERSION)\"
|
||||
IDENT = '$(@F) $(VERSION) (GPL) ipxe.org'
|
||||
GITVERSION := $(shell git describe --always --abbrev=1 --match "" 2>/dev/null)
|
||||
ifneq ($(GITVERSION),)
|
||||
VERSION += ($(GITVERSION))
|
||||
endif
|
||||
version :
|
||||
@$(ECHO) $(VERSION)
|
||||
@$(ECHO) "$(VERSION)"
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
|
||||
@@ -162,9 +162,12 @@ endif
|
||||
# output of "size". Inhibit this.
|
||||
#
|
||||
ifeq ($(CCTYPE),gcc)
|
||||
CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -x c -c /dev/null \
|
||||
CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \
|
||||
-fno-asynchronous-unwind-tables -x c -c /dev/null \
|
||||
-o /dev/null >/dev/null 2>&1
|
||||
CFI_FLAGS := $(shell $(CFI_TEST) && $(ECHO) '-fno-dwarf2-cfi-asm')
|
||||
CFI_FLAGS := $(shell $(CFI_TEST) && \
|
||||
$(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \
|
||||
'-fno-unwind-tables -fno-asynchronous-unwind-tables')
|
||||
WORKAROUND_CFLAGS += $(CFI_FLAGS)
|
||||
endif
|
||||
|
||||
@@ -608,36 +611,39 @@ CFLAGS_clientcert += $(if $(CERT),-DCERTIFICATE="\"$(CERT_INC)\"")
|
||||
|
||||
# (Single-element) list of client private keys
|
||||
#
|
||||
KEY_LIST := $(BIN)/.private_key.list
|
||||
ifeq ($(wildcard $(KEY_LIST)),)
|
||||
KEY_OLD := <invalid>
|
||||
ifdef KEY
|
||||
PRIVKEY := $(KEY) # Maintain backwards compatibility
|
||||
endif
|
||||
PRIVKEY_LIST := $(BIN)/.private_key.list
|
||||
ifeq ($(wildcard $(PRIVKEY_LIST)),)
|
||||
PRIVKEY_OLD := <invalid>
|
||||
else
|
||||
KEY_OLD := $(shell cat $(KEY_LIST))
|
||||
PRIVKEY_OLD := $(shell cat $(PRIVKEY_LIST))
|
||||
endif
|
||||
ifneq ($(KEY_OLD),$(KEY))
|
||||
$(shell $(ECHO) "$(KEY)" > $(KEY_LIST))
|
||||
ifneq ($(PRIVKEY_OLD),$(PRIVKEY))
|
||||
$(shell $(ECHO) "$(PRIVKEY)" > $(PRIVKEY_LIST))
|
||||
endif
|
||||
|
||||
$(KEY_LIST) :
|
||||
$(PRIVKEY_LIST) :
|
||||
|
||||
VERYCLEANUP += $(KEY_LIST)
|
||||
VERYCLEANUP += $(PRIVKEY_LIST)
|
||||
|
||||
# Embedded client private key
|
||||
#
|
||||
KEY_INC := $(BIN)/.private_key.der
|
||||
PRIVKEY_INC := $(BIN)/.private_key.der
|
||||
|
||||
ifdef KEY
|
||||
$(KEY_INC) : $(KEY) $(KEY_LIST)
|
||||
ifdef PRIVKEY
|
||||
$(PRIVKEY_INC) : $(PRIVKEY) $(PRIVKEY_LIST)
|
||||
$(Q)$(OPENSSL) rsa -in $< -outform DER -out $@
|
||||
|
||||
clientcert_DEPS += $(KEY_INC)
|
||||
clientcert_DEPS += $(PRIVKEY_INC)
|
||||
endif
|
||||
|
||||
CLEANUP += $(KEY_INC)
|
||||
CLEANUP += $(PRIVKEY_INC)
|
||||
|
||||
clientcert_DEPS += $(KEY_LIST)
|
||||
clientcert_DEPS += $(PRIVKEY_LIST)
|
||||
|
||||
CFLAGS_clientcert += $(if $(KEY),-DPRIVATE_KEY="\"$(KEY_INC)\"")
|
||||
CFLAGS_clientcert += $(if $(PRIVKEY),-DPRIVATE_KEY="\"$(PRIVKEY_INC)\"")
|
||||
|
||||
# These files use .incbin inline assembly to include a binary file.
|
||||
# Unfortunately ccache does not detect this dependency and caches
|
||||
@@ -647,6 +653,17 @@ $(BIN)/embedded.o : override CC := env CCACHE_DISABLE=1 $(CC)
|
||||
|
||||
$(BIN)/clientcert.o : override CC := env CCACHE_DISABLE=1 $(CC)
|
||||
|
||||
# Version number
|
||||
#
|
||||
CFLAGS_version += -DVERSION_MAJOR=$(VERSION_MAJOR) \
|
||||
-DVERSION_MINOR=$(VERSION_MINOR) \
|
||||
-DVERSION_PATCH=$(VERSION_PATCH) \
|
||||
-DVERSION="\"$(VERSION)\""
|
||||
# Make sure the version number gets updated on every git checkout
|
||||
ifneq ($(GITVERSION),)
|
||||
$(BIN)/version.o : ../.git/index
|
||||
endif
|
||||
|
||||
# We automatically generate rules for any file mentioned in AUTO_SRCS
|
||||
# using the following set of templates. It would be cleaner to use
|
||||
# $(eval ...), but this function exists only in GNU make >= 3.80.
|
||||
@@ -660,7 +677,7 @@ $(BIN)/clientcert.o : override CC := env CCACHE_DISABLE=1 $(CC)
|
||||
define deps_template
|
||||
@$(ECHO) " [DEPS] $(1)"
|
||||
@$(MKDIR) -p $(BIN)/deps/$(dir $(1))
|
||||
@$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \
|
||||
$(Q)$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \
|
||||
-Wno-error -M $(1) -MG -MP | \
|
||||
sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d
|
||||
endef
|
||||
|
||||
@@ -54,6 +54,8 @@ CFLAGS += -m32
|
||||
ASFLAGS += --32
|
||||
ifeq ($(HOST_OS),FreeBSD)
|
||||
LDFLAGS += -m elf_i386_fbsd
|
||||
else ifeq ($(HOST_OS),OpenBSD)
|
||||
LDFLAGS += -m elf_i386_obsd
|
||||
else
|
||||
LDFLAGS += -m elf_i386
|
||||
endif
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cpu.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* CPU identification
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test to see if CPU flag is changeable
|
||||
*
|
||||
* @v flag Flag to test
|
||||
* @ret can_change Flag is changeable
|
||||
*/
|
||||
static inline int flag_is_changeable ( unsigned int flag ) {
|
||||
uint32_t f1, f2;
|
||||
|
||||
__asm__ ( "pushfl\n\t"
|
||||
"pushfl\n\t"
|
||||
"popl %0\n\t"
|
||||
"movl %0,%1\n\t"
|
||||
"xorl %2,%0\n\t"
|
||||
"pushl %0\n\t"
|
||||
"popfl\n\t"
|
||||
"pushfl\n\t"
|
||||
"popl %0\n\t"
|
||||
"popfl\n\t"
|
||||
: "=&r" ( f1 ), "=&r" ( f2 )
|
||||
: "ir" ( flag ) );
|
||||
|
||||
return ( ( ( f1 ^ f2 ) & flag ) != 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CPU information
|
||||
*
|
||||
* @v cpu CPU information structure to fill in
|
||||
*/
|
||||
void get_cpuinfo ( struct cpuinfo_x86 *cpu ) {
|
||||
unsigned int cpuid_level;
|
||||
unsigned int cpuid_extlevel;
|
||||
unsigned int discard_1, discard_2, discard_3;
|
||||
|
||||
memset ( cpu, 0, sizeof ( *cpu ) );
|
||||
|
||||
/* Check for CPUID instruction */
|
||||
if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) {
|
||||
DBG ( "CPUID not supported\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get features, if present */
|
||||
cpuid ( 0x00000000, &cpuid_level, &discard_1,
|
||||
&discard_2, &discard_3 );
|
||||
if ( cpuid_level >= 0x00000001 ) {
|
||||
cpuid ( 0x00000001, &discard_1, &discard_2,
|
||||
&discard_3, &cpu->features );
|
||||
} else {
|
||||
DBG ( "CPUID cannot return capabilities\n" );
|
||||
}
|
||||
|
||||
/* Get 64-bit features, if present */
|
||||
cpuid ( 0x80000000, &cpuid_extlevel, &discard_1,
|
||||
&discard_2, &discard_3 );
|
||||
if ( ( cpuid_extlevel & 0xffff0000 ) == 0x80000000 ) {
|
||||
if ( cpuid_extlevel >= 0x80000001 ) {
|
||||
cpuid ( 0x80000001, &discard_1, &discard_2,
|
||||
&discard_3, &cpu->amd_features );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -33,8 +33,10 @@ extern char _etextdata[];
|
||||
/**
|
||||
* Relocate iPXE
|
||||
*
|
||||
* @v ix86 x86 register dump from prefix
|
||||
* @ret ix86 x86 registers to return to prefix
|
||||
* @v ebp Maximum address to use for relocation
|
||||
* @ret esi Current physical address
|
||||
* @ret edi New physical address
|
||||
* @ret ecx Length to copy
|
||||
*
|
||||
* This finds a suitable location for iPXE near the top of 32-bit
|
||||
* address space, and returns the physical address of the new location
|
||||
@@ -59,7 +61,7 @@ __asmcall void relocate ( struct i386_all_regs *ix86 ) {
|
||||
|
||||
/* Determine maximum usable address */
|
||||
max = MAX_ADDR;
|
||||
if ( ix86->regs.ebp && ( ix86->regs.ebp < max ) ) {
|
||||
if ( ix86->regs.ebp < max ) {
|
||||
max = ix86->regs.ebp;
|
||||
DBG ( "Limiting relocation to [0,%lx)\n", max );
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -70,6 +71,9 @@ struct undi_nic {
|
||||
/** Delay between retries of PXENV_UNDI_INITIALIZE */
|
||||
#define UNDI_INITIALIZE_RETRY_DELAY_MS 200
|
||||
|
||||
/** Alignment of received frame payload */
|
||||
#define UNDI_RX_ALIGN 16
|
||||
|
||||
static void undinet_close ( struct net_device *netdev );
|
||||
|
||||
/** Address of UNDI entry point */
|
||||
@@ -299,6 +303,7 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||
struct s_PXENV_UNDI_ISR undi_isr;
|
||||
struct io_buffer *iobuf = NULL;
|
||||
size_t len;
|
||||
size_t reserve_len;
|
||||
size_t frag_len;
|
||||
size_t max_frag_len;
|
||||
int rc;
|
||||
@@ -340,6 +345,8 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||
/* Packet fragment received */
|
||||
len = undi_isr.FrameLength;
|
||||
frag_len = undi_isr.BufferLength;
|
||||
reserve_len = ( -undi_isr.FrameHeaderLength &
|
||||
( UNDI_RX_ALIGN - 1 ) );
|
||||
if ( ( len == 0 ) || ( len < frag_len ) ) {
|
||||
/* Don't laugh. VMWare does it. */
|
||||
DBGC ( undinic, "UNDINIC %p reported insane "
|
||||
@@ -348,15 +355,17 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||
netdev_rx_err ( netdev, NULL, -EINVAL );
|
||||
break;
|
||||
}
|
||||
if ( ! iobuf )
|
||||
iobuf = alloc_iob ( len );
|
||||
if ( ! iobuf ) {
|
||||
DBGC ( undinic, "UNDINIC %p could not "
|
||||
"allocate %zd bytes for RX buffer\n",
|
||||
undinic, len );
|
||||
/* Fragment will be dropped */
|
||||
netdev_rx_err ( netdev, NULL, -ENOMEM );
|
||||
goto done;
|
||||
iobuf = alloc_iob ( reserve_len + len );
|
||||
if ( ! iobuf ) {
|
||||
DBGC ( undinic, "UNDINIC %p could not "
|
||||
"allocate %zd bytes for RX "
|
||||
"buffer\n", undinic, len );
|
||||
/* Fragment will be dropped */
|
||||
netdev_rx_err ( netdev, NULL, -ENOMEM );
|
||||
goto done;
|
||||
}
|
||||
iob_reserve ( iobuf, reserve_len );
|
||||
}
|
||||
max_frag_len = iob_tailroom ( iobuf );
|
||||
if ( frag_len > max_frag_len ) {
|
||||
@@ -516,6 +525,53 @@ static struct net_device_operations undinet_operations = {
|
||||
.irq = undinet_irq,
|
||||
};
|
||||
|
||||
/** A device with broken support for generating interrupts */
|
||||
struct undinet_irq_broken {
|
||||
/** PCI vendor ID */
|
||||
uint16_t pci_vendor;
|
||||
/** PCI device ID */
|
||||
uint16_t pci_device;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of devices with broken support for generating interrupts
|
||||
*
|
||||
* Some PXE stacks are known to claim that IRQs are supported, but
|
||||
* then never generate interrupts. No satisfactory solution has been
|
||||
* found to this problem; the workaround is to add the PCI vendor and
|
||||
* device IDs to this list. This is something of a hack, since it
|
||||
* will generate false positives for identical devices with a working
|
||||
* PXE stack (e.g. those that have been reflashed with iPXE), but it's
|
||||
* an improvement on the current situation.
|
||||
*/
|
||||
static const struct undinet_irq_broken undinet_irq_broken_list[] = {
|
||||
/* HP XX70x laptops */
|
||||
{ .pci_vendor = 0x8086, .pci_device = 0x1502 },
|
||||
{ .pci_vendor = 0x8086, .pci_device = 0x1503 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Check for devices with broken support for generating interrupts
|
||||
*
|
||||
* @v undi UNDI device
|
||||
* @ret irq_is_broken Interrupt support is broken; no interrupts are generated
|
||||
*/
|
||||
static int undinet_irq_is_broken ( struct undi_device *undi ) {
|
||||
const struct undinet_irq_broken *broken;
|
||||
unsigned int i;
|
||||
|
||||
for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) /
|
||||
sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) {
|
||||
broken = &undinet_irq_broken_list[i];
|
||||
if ( ( undi->dev.desc.bus_type == BUS_TYPE_PCI ) &&
|
||||
( undi->dev.desc.vendor == broken->pci_vendor ) &&
|
||||
( undi->dev.desc.device == broken->pci_device ) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Probe UNDI device
|
||||
*
|
||||
@@ -632,6 +688,11 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||
undinic );
|
||||
undinic->hacks |= UNDI_HACK_EB54;
|
||||
}
|
||||
if ( undinet_irq_is_broken ( undi ) ) {
|
||||
DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
|
||||
"broken interrupts\n", undinic );
|
||||
undinic->irq_supported = 0;
|
||||
}
|
||||
|
||||
/* Register network device */
|
||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER )
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -189,6 +190,8 @@ static void hide_etherboot ( void ) {
|
||||
* possible.
|
||||
*/
|
||||
static void unhide_etherboot ( int flags __unused ) {
|
||||
struct memory_map memmap;
|
||||
int rc;
|
||||
|
||||
/* If we have more than one hooked interrupt at this point, it
|
||||
* means that some other vector is still hooked, in which case
|
||||
@@ -202,15 +205,23 @@ static void unhide_etherboot ( int flags __unused ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to unhook INT 15. If it fails, then just leave it
|
||||
* hooked; it takes care of protecting itself. :)
|
||||
*/
|
||||
unhook_bios_interrupt ( 0x15, ( unsigned int ) int15,
|
||||
&int15_vector );
|
||||
/* Try to unhook INT 15 */
|
||||
if ( ( rc = unhook_bios_interrupt ( 0x15, ( unsigned int ) int15,
|
||||
&int15_vector ) ) != 0 ) {
|
||||
DBG ( "Cannot unhook INT15: %s\n", strerror ( rc ) );
|
||||
/* Leave it hooked; there's nothing else we can do,
|
||||
* and it should be intrinsically safe (though
|
||||
* wasteful of RAM).
|
||||
*/
|
||||
}
|
||||
|
||||
/* Unhook fake E820 map, if used */
|
||||
if ( FAKE_E820 )
|
||||
unfake_e820();
|
||||
|
||||
/* Dump memory map after unhiding */
|
||||
DBG ( "Unhidden iPXE from system memory map\n" );
|
||||
get_memmap ( &memmap );
|
||||
}
|
||||
|
||||
/** Hide Etherboot startup function */
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -62,6 +63,10 @@ struct e820_entry {
|
||||
static struct e820_entry __bss16 ( e820buf );
|
||||
#define e820buf __use_data16 ( e820buf )
|
||||
|
||||
/** We are running during POST; inhibit INT 15,e820 and INT 15,e801 */
|
||||
uint8_t __bss16 ( memmap_post );
|
||||
#define memmap_post __use_data16 ( memmap_post )
|
||||
|
||||
/**
|
||||
* Get size of extended memory via INT 15,e801
|
||||
*
|
||||
@@ -73,6 +78,12 @@ static unsigned int extmemsize_e801 ( void ) {
|
||||
unsigned int flags;
|
||||
unsigned int extmem;
|
||||
|
||||
/* Inhibit INT 15,e801 during POST */
|
||||
if ( memmap_post ) {
|
||||
DBG ( "INT 15,e801 not available during POST\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
||||
"int $0x15\n\t"
|
||||
"pushfw\n\t"
|
||||
@@ -163,6 +174,12 @@ static int meme820 ( struct memory_map *memmap ) {
|
||||
unsigned int flags;
|
||||
unsigned int discard_D;
|
||||
|
||||
/* Inhibit INT 15,e820 during POST */
|
||||
if ( memmap_post ) {
|
||||
DBG ( "INT 15,e820 not available during POST\n" );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* Clear the E820 buffer. Do this once before starting,
|
||||
* rather than on each call; some BIOSes rely on the contents
|
||||
* being preserved between calls.
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <ipxe/netdevice.h>
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -79,9 +80,22 @@ int call_bootsector ( unsigned int segment, unsigned int offset,
|
||||
"movw %%ss, %%ax\n\t"
|
||||
"movw %%ax, %%cs:saved_ss\n\t"
|
||||
"movw %%sp, %%cs:saved_sp\n\t"
|
||||
/* Jump to boot sector */
|
||||
/* Prepare jump to boot sector */
|
||||
"pushw %%bx\n\t"
|
||||
"pushw %%di\n\t"
|
||||
/* Clear all registers */
|
||||
"xorl %%eax, %%eax\n\t"
|
||||
"xorl %%ebx, %%ebx\n\t"
|
||||
"xorl %%ecx, %%ecx\n\t"
|
||||
/* %edx contains drive number */
|
||||
"xorl %%esi, %%esi\n\t"
|
||||
"xorl %%edi, %%edi\n\t"
|
||||
"xorl %%ebp, %%ebp\n\t"
|
||||
"movw %%ax, %%ds\n\t"
|
||||
"movw %%ax, %%es\n\t"
|
||||
"movw %%ax, %%fs\n\t"
|
||||
"movw %%ax, %%gs\n\t"
|
||||
/* Jump to boot sector */
|
||||
"sti\n\t"
|
||||
"lret\n\t"
|
||||
/* Preserved variables */
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -32,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <assert.h>
|
||||
#include <realmode.h>
|
||||
#include <bzimage.h>
|
||||
#include <initrd.h>
|
||||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/segment.h>
|
||||
@@ -214,7 +216,8 @@ static void bzimage_update_header ( struct image *image,
|
||||
} else {
|
||||
bzimg->cmdline_magic.magic = BZI_CMDLINE_MAGIC;
|
||||
bzimg->cmdline_magic.offset = bzimg->rm_cmdline;
|
||||
bzimg->bzhdr.setup_move_size = bzimg->rm_memsz;
|
||||
if ( bzimg->version >= 0x0200 )
|
||||
bzimg->bzhdr.setup_move_size = bzimg->rm_memsz;
|
||||
}
|
||||
|
||||
/* Set video mode */
|
||||
@@ -302,11 +305,10 @@ static int bzimage_parse_cmdline ( struct image *image,
|
||||
* @v image bzImage image
|
||||
* @v bzimg bzImage context
|
||||
* @v cmdline Kernel command line
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int bzimage_set_cmdline ( struct image *image,
|
||||
struct bzimage_context *bzimg,
|
||||
const char *cmdline ) {
|
||||
static void bzimage_set_cmdline ( struct image *image,
|
||||
struct bzimage_context *bzimg,
|
||||
const char *cmdline ) {
|
||||
size_t cmdline_len;
|
||||
|
||||
/* Copy command line down to real-mode portion */
|
||||
@@ -316,8 +318,32 @@ static int bzimage_set_cmdline ( struct image *image,
|
||||
copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline,
|
||||
cmdline, cmdline_len );
|
||||
DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline );
|
||||
}
|
||||
|
||||
return 0;
|
||||
/**
|
||||
* Parse standalone image command line for cpio parameters
|
||||
*
|
||||
* @v image bzImage file
|
||||
* @v cpio CPIO header
|
||||
* @v cmdline Command line
|
||||
*/
|
||||
static void bzimage_parse_cpio_cmdline ( struct image *image,
|
||||
struct cpio_header *cpio,
|
||||
const char *cmdline ) {
|
||||
char *arg;
|
||||
char *end;
|
||||
unsigned int mode;
|
||||
|
||||
/* Look for "mode=" */
|
||||
if ( ( arg = strstr ( cmdline, "mode=" ) ) ) {
|
||||
arg += 5;
|
||||
mode = strtoul ( arg, &end, 8 /* Octal for file mode */ );
|
||||
if ( *end && ( *end != ' ' ) ) {
|
||||
DBGC ( image, "bzImage %p strange \"mode=\""
|
||||
"terminator '%c'\n", image, *end );
|
||||
}
|
||||
cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,14 +352,17 @@ static int bzimage_set_cmdline ( struct image *image,
|
||||
* @v image bzImage image
|
||||
* @v initrd initrd image
|
||||
* @v address Address at which to load, or UNULL
|
||||
* @ret len Length of loaded image, rounded up to 4 bytes
|
||||
* @ret len Length of loaded image, rounded up to INITRD_ALIGN
|
||||
*/
|
||||
static size_t bzimage_load_initrd ( struct image *image,
|
||||
struct image *initrd,
|
||||
userptr_t address ) {
|
||||
char *filename = initrd->cmdline;
|
||||
char *cmdline;
|
||||
struct cpio_header cpio;
|
||||
size_t offset = 0;
|
||||
size_t name_len;
|
||||
size_t pad_len;
|
||||
|
||||
/* Do not include kernel image itself as an initrd */
|
||||
if ( initrd == image )
|
||||
@@ -341,24 +370,28 @@ static size_t bzimage_load_initrd ( struct image *image,
|
||||
|
||||
/* Create cpio header before non-prebuilt images */
|
||||
if ( filename && filename[0] ) {
|
||||
size_t name_len = ( strlen ( filename ) + 1 );
|
||||
|
||||
DBGC ( image, "bzImage %p inserting initrd %p as %s\n",
|
||||
image, initrd, filename );
|
||||
cmdline = strchr ( filename, ' ' );
|
||||
name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) )
|
||||
: strlen ( filename ) ) + 1 /* NUL */ );
|
||||
memset ( &cpio, '0', sizeof ( cpio ) );
|
||||
memcpy ( cpio.c_magic, CPIO_MAGIC, sizeof ( cpio.c_magic ) );
|
||||
cpio_set_field ( cpio.c_mode, 0100644 );
|
||||
cpio_set_field ( cpio.c_nlink, 1 );
|
||||
cpio_set_field ( cpio.c_filesize, initrd->len );
|
||||
cpio_set_field ( cpio.c_namesize, name_len );
|
||||
if ( cmdline ) {
|
||||
bzimage_parse_cpio_cmdline ( image, &cpio,
|
||||
( cmdline + 1 /* ' ' */ ));
|
||||
}
|
||||
if ( address ) {
|
||||
copy_to_user ( address, offset, &cpio,
|
||||
sizeof ( cpio ) );
|
||||
}
|
||||
offset += sizeof ( cpio );
|
||||
if ( address ) {
|
||||
memset_user ( address, offset, 0, name_len );
|
||||
copy_to_user ( address, offset, filename,
|
||||
name_len );
|
||||
( name_len - 1 /* NUL (or space) */ ) );
|
||||
}
|
||||
offset += name_len;
|
||||
offset = ( ( offset + 0x03 ) & ~0x03 );
|
||||
@@ -366,17 +399,82 @@ static size_t bzimage_load_initrd ( struct image *image,
|
||||
|
||||
/* Copy in initrd image body */
|
||||
if ( address )
|
||||
memcpy_user ( address, offset, initrd->data, 0, initrd->len );
|
||||
offset += initrd->len;
|
||||
memmove_user ( address, offset, initrd->data, 0, initrd->len );
|
||||
if ( address ) {
|
||||
DBGC ( image, "bzImage %p has initrd %p at [%lx,%lx)\n",
|
||||
image, initrd, user_to_phys ( address, 0 ),
|
||||
user_to_phys ( address, offset ) );
|
||||
DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)"
|
||||
"%s%s\n", image, initrd, user_to_phys ( address, 0 ),
|
||||
user_to_phys ( address, offset ),
|
||||
user_to_phys ( address, ( offset + initrd->len ) ),
|
||||
( filename ? " " : "" ), ( filename ? filename : "" ) );
|
||||
DBGC2_MD5A ( image, user_to_phys ( address, offset ),
|
||||
user_to_virt ( address, offset ), initrd->len );
|
||||
}
|
||||
offset += initrd->len;
|
||||
|
||||
/* Round up to multiple of INITRD_ALIGN and zero-pad */
|
||||
pad_len = ( ( -offset ) & ( INITRD_ALIGN - 1 ) );
|
||||
if ( address )
|
||||
memset_user ( address, offset, 0, pad_len );
|
||||
offset += pad_len;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that initrds can be loaded
|
||||
*
|
||||
* @v image bzImage image
|
||||
* @v bzimg bzImage context
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int bzimage_check_initrds ( struct image *image,
|
||||
struct bzimage_context *bzimg ) {
|
||||
struct image *initrd;
|
||||
userptr_t bottom;
|
||||
size_t len = 0;
|
||||
int rc;
|
||||
|
||||
/* Calculate total loaded length of initrds */
|
||||
for_each_image ( initrd ) {
|
||||
|
||||
/* Skip kernel */
|
||||
if ( initrd == image )
|
||||
continue;
|
||||
|
||||
/* Calculate length */
|
||||
len += bzimage_load_initrd ( image, initrd, UNULL );
|
||||
|
||||
DBGC ( image, "bzImage %p initrd %p from [%#08lx,%#08lx)%s%s\n",
|
||||
image, initrd, user_to_phys ( initrd->data, 0 ),
|
||||
user_to_phys ( initrd->data, initrd->len ),
|
||||
( initrd->cmdline ? " " : "" ),
|
||||
( initrd->cmdline ? initrd->cmdline : "" ) );
|
||||
DBGC2_MD5A ( image, user_to_phys ( initrd->data, 0 ),
|
||||
user_to_virt ( initrd->data, 0 ), initrd->len );
|
||||
}
|
||||
|
||||
/* Round up to 4-byte boundary */
|
||||
offset = ( ( offset + 0x03 ) & ~0x03 );
|
||||
return offset;
|
||||
/* Calculate lowest usable address */
|
||||
bottom = userptr_add ( bzimg->pm_kernel, bzimg->pm_sz );
|
||||
|
||||
/* Check that total length fits within space available for
|
||||
* reshuffling. This is a conservative check, since CPIO
|
||||
* headers are not present during reshuffling, but this
|
||||
* doesn't hurt and keeps the code simple.
|
||||
*/
|
||||
if ( ( rc = initrd_reshuffle_check ( len, bottom ) ) != 0 ) {
|
||||
DBGC ( image, "bzImage %p failed reshuffle check: %s\n",
|
||||
image, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Check that total length fits within kernel's memory limit */
|
||||
if ( user_to_phys ( bottom, len ) > bzimg->mem_limit ) {
|
||||
DBGC ( image, "bzImage %p not enough space for initrds\n",
|
||||
image );
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,62 +482,63 @@ static size_t bzimage_load_initrd ( struct image *image,
|
||||
*
|
||||
* @v image bzImage image
|
||||
* @v bzimg bzImage context
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int bzimage_load_initrds ( struct image *image,
|
||||
struct bzimage_context *bzimg ) {
|
||||
static void bzimage_load_initrds ( struct image *image,
|
||||
struct bzimage_context *bzimg ) {
|
||||
struct image *initrd;
|
||||
size_t total_len = 0;
|
||||
physaddr_t address;
|
||||
int rc;
|
||||
struct image *highest = NULL;
|
||||
struct image *other;
|
||||
userptr_t top;
|
||||
userptr_t dest;
|
||||
size_t len;
|
||||
|
||||
/* Add up length of all initrd images */
|
||||
for_each_image ( initrd )
|
||||
total_len += bzimage_load_initrd ( image, initrd, UNULL );
|
||||
/* Reshuffle initrds into desired order */
|
||||
initrd_reshuffle ( userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ) );
|
||||
|
||||
/* Give up if no initrd images found */
|
||||
if ( ! total_len )
|
||||
return 0;
|
||||
|
||||
/* Find a suitable start address. Try 1MB boundaries,
|
||||
* starting from the downloaded kernel image itself and
|
||||
* working downwards until we hit an available region.
|
||||
*/
|
||||
for ( address = ( user_to_phys ( image->data, 0 ) & ~0xfffff ) ; ;
|
||||
address -= 0x100000 ) {
|
||||
/* Check that we're not going to overwrite the
|
||||
* kernel itself. This check isn't totally
|
||||
* accurate, but errs on the side of caution.
|
||||
*/
|
||||
if ( address <= ( BZI_LOAD_HIGH_ADDR + image->len ) ) {
|
||||
DBGC ( image, "bzImage %p could not find a location "
|
||||
"for initrd\n", image );
|
||||
return -ENOBUFS;
|
||||
}
|
||||
/* Check that we are within the kernel's range */
|
||||
if ( ( address + total_len - 1 ) > bzimg->mem_limit )
|
||||
continue;
|
||||
/* Prepare and verify segment */
|
||||
if ( ( rc = prep_segment ( phys_to_user ( address ), 0,
|
||||
total_len ) ) != 0 )
|
||||
continue;
|
||||
/* Use this address */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Record initrd location */
|
||||
bzimg->ramdisk_image = address;
|
||||
bzimg->ramdisk_size = total_len;
|
||||
|
||||
/* Construct initrd */
|
||||
DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n",
|
||||
image, address, ( address + total_len ) );
|
||||
/* Find highest initrd */
|
||||
for_each_image ( initrd ) {
|
||||
address += bzimage_load_initrd ( image, initrd,
|
||||
phys_to_user ( address ) );
|
||||
if ( ( highest == NULL ) ||
|
||||
( userptr_sub ( initrd->data, highest->data ) > 0 ) ) {
|
||||
highest = initrd;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* Do nothing if there are no initrds */
|
||||
if ( ! highest )
|
||||
return;
|
||||
|
||||
/* Find highest usable address */
|
||||
top = userptr_add ( highest->data,
|
||||
( ( highest->len + INITRD_ALIGN - 1 ) &
|
||||
~( INITRD_ALIGN - 1 ) ) );
|
||||
if ( user_to_phys ( top, 0 ) > bzimg->mem_limit )
|
||||
top = phys_to_user ( bzimg->mem_limit );
|
||||
DBGC ( image, "bzImage %p loading initrds from %#08lx downwards\n",
|
||||
image, user_to_phys ( top, 0 ) );
|
||||
|
||||
/* Load initrds in order */
|
||||
for_each_image ( initrd ) {
|
||||
|
||||
/* Calculate cumulative length of following
|
||||
* initrds (including padding).
|
||||
*/
|
||||
len = 0;
|
||||
for_each_image ( other ) {
|
||||
if ( other == initrd )
|
||||
len = 0;
|
||||
len += bzimage_load_initrd ( image, other, UNULL );
|
||||
}
|
||||
|
||||
/* Load initrd at this address */
|
||||
dest = userptr_add ( top, -len );
|
||||
bzimage_load_initrd ( image, initrd, dest );
|
||||
|
||||
/* Record initrd location */
|
||||
if ( ! bzimg->ramdisk_image ) {
|
||||
bzimg->ramdisk_image = user_to_phys ( dest, 0 );
|
||||
bzimg->ramdisk_size = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -472,33 +571,37 @@ static int bzimage_exec ( struct image *image ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Parse command line for bootloader parameters */
|
||||
if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
|
||||
return rc;
|
||||
|
||||
/* Check that initrds can be loaded */
|
||||
if ( ( rc = bzimage_check_initrds ( image, &bzimg ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Remove kernel from image list (without invalidating image pointer) */
|
||||
unregister_image ( image_get ( image ) );
|
||||
|
||||
/* Load segments */
|
||||
memcpy_user ( bzimg.rm_kernel, 0, image->data,
|
||||
0, bzimg.rm_filesz );
|
||||
memcpy_user ( bzimg.pm_kernel, 0, image->data,
|
||||
bzimg.rm_filesz, bzimg.pm_sz );
|
||||
|
||||
/* Update and write out header */
|
||||
bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
|
||||
|
||||
/* Parse command line for bootloader parameters */
|
||||
if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
|
||||
return rc;
|
||||
|
||||
/* Store command line */
|
||||
if ( ( rc = bzimage_set_cmdline ( image, &bzimg, cmdline ) ) != 0 )
|
||||
return rc;
|
||||
bzimage_set_cmdline ( image, &bzimg, cmdline );
|
||||
|
||||
/* Prepare for exiting. Must do this before loading initrds,
|
||||
* since loading the initrds will corrupt the external heap.
|
||||
*/
|
||||
shutdown_boot();
|
||||
|
||||
/* Load any initrds */
|
||||
if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 )
|
||||
return rc;
|
||||
bzimage_load_initrds ( image, &bzimg );
|
||||
|
||||
/* Update kernel header */
|
||||
bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
|
||||
|
||||
/* Prepare for exiting */
|
||||
shutdown_boot();
|
||||
|
||||
DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
|
||||
"(stack %04x:%04zx)\n", image, ( bzimg.rm_kernel_seg + 0x20 ),
|
||||
bzimg.rm_kernel_seg, bzimg.rm_heap );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -228,7 +229,7 @@ static int comboot_identify ( struct image *image ) {
|
||||
|
||||
++ext;
|
||||
|
||||
if ( strcasecmp( ext, "com" ) && strcasecmp( ext, "cbt" ) ) {
|
||||
if ( strcasecmp( ext, "cbt" ) ) {
|
||||
DBGC ( image, "COMBOOT %p: unrecognized extension %s\n",
|
||||
image, ext );
|
||||
return -ENOEXEC;
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
300
src/arch/i386/image/initrd.c
Normal file
300
src/arch/i386/image/initrd.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <errno.h>
|
||||
#include <initrd.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/init.h>
|
||||
#include <ipxe/memblock.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Initial ramdisk (initrd) reshuffling
|
||||
*
|
||||
*/
|
||||
|
||||
/** Maximum address available for initrd */
|
||||
userptr_t initrd_top;
|
||||
|
||||
/** Minimum address available for initrd */
|
||||
userptr_t initrd_bottom;
|
||||
|
||||
/**
|
||||
* Squash initrds as high as possible in memory
|
||||
*
|
||||
* @v top Highest possible address
|
||||
* @ret used Lowest address used by initrds
|
||||
*/
|
||||
static userptr_t initrd_squash_high ( userptr_t top ) {
|
||||
userptr_t current = top;
|
||||
struct image *initrd;
|
||||
struct image *highest;
|
||||
size_t len;
|
||||
|
||||
/* Squash up any initrds already within or below the region */
|
||||
while ( 1 ) {
|
||||
|
||||
/* Find the highest image not yet in its final position */
|
||||
highest = NULL;
|
||||
for_each_image ( initrd ) {
|
||||
if ( ( userptr_sub ( initrd->data, current ) < 0 ) &&
|
||||
( ( highest == NULL ) ||
|
||||
( userptr_sub ( initrd->data,
|
||||
highest->data ) > 0 ) ) ) {
|
||||
highest = initrd;
|
||||
}
|
||||
}
|
||||
if ( ! highest )
|
||||
break;
|
||||
|
||||
/* Move this image to its final position */
|
||||
len = ( ( highest->len + INITRD_ALIGN - 1 ) &
|
||||
~( INITRD_ALIGN - 1 ) );
|
||||
current = userptr_sub ( current, len );
|
||||
DBGC ( &images, "INITRD squashing %s [%#08lx,%#08lx)->"
|
||||
"[%#08lx,%#08lx)\n", highest->name,
|
||||
user_to_phys ( highest->data, 0 ),
|
||||
user_to_phys ( highest->data, highest->len ),
|
||||
user_to_phys ( current, 0 ),
|
||||
user_to_phys ( current, highest->len ) );
|
||||
memmove_user ( current, 0, highest->data, 0, highest->len );
|
||||
highest->data = current;
|
||||
}
|
||||
|
||||
/* Copy any remaining initrds (e.g. embedded images) to the region */
|
||||
for_each_image ( initrd ) {
|
||||
if ( userptr_sub ( initrd->data, top ) >= 0 ) {
|
||||
len = ( ( initrd->len + INITRD_ALIGN - 1 ) &
|
||||
~( INITRD_ALIGN - 1 ) );
|
||||
current = userptr_sub ( current, len );
|
||||
DBGC ( &images, "INITRD copying %s [%#08lx,%#08lx)->"
|
||||
"[%#08lx,%#08lx)\n", initrd->name,
|
||||
user_to_phys ( initrd->data, 0 ),
|
||||
user_to_phys ( initrd->data, initrd->len ),
|
||||
user_to_phys ( current, 0 ),
|
||||
user_to_phys ( current, initrd->len ) );
|
||||
memcpy_user ( current, 0, initrd->data, 0,
|
||||
initrd->len );
|
||||
initrd->data = current;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap position of two adjacent initrds
|
||||
*
|
||||
* @v low Lower initrd
|
||||
* @v high Higher initrd
|
||||
* @v free Free space
|
||||
* @v free_len Length of free space
|
||||
*/
|
||||
static void initrd_swap ( struct image *low, struct image *high,
|
||||
userptr_t free, size_t free_len ) {
|
||||
size_t len = 0;
|
||||
size_t frag_len;
|
||||
size_t new_len;
|
||||
|
||||
DBGC ( &images, "INITRD swapping %s [%#08lx,%#08lx)<->[%#08lx,%#08lx) "
|
||||
"%s\n", low->name, user_to_phys ( low->data, 0 ),
|
||||
user_to_phys ( low->data, low->len ),
|
||||
user_to_phys ( high->data, 0 ),
|
||||
user_to_phys ( high->data, high->len ), high->name );
|
||||
|
||||
/* Round down length of free space */
|
||||
free_len &= ~( INITRD_ALIGN - 1 );
|
||||
assert ( free_len > 0 );
|
||||
|
||||
/* Swap image data */
|
||||
while ( len < high->len ) {
|
||||
|
||||
/* Calculate maximum fragment length */
|
||||
frag_len = ( high->len - len );
|
||||
if ( frag_len > free_len )
|
||||
frag_len = free_len;
|
||||
new_len = ( ( len + frag_len + INITRD_ALIGN - 1 ) &
|
||||
~( INITRD_ALIGN - 1 ) );
|
||||
|
||||
/* Swap fragments */
|
||||
memcpy_user ( free, 0, high->data, len, frag_len );
|
||||
memmove_user ( low->data, new_len, low->data, len, low->len );
|
||||
memcpy_user ( low->data, len, free, 0, frag_len );
|
||||
len = new_len;
|
||||
}
|
||||
|
||||
/* Adjust data pointers */
|
||||
high->data = low->data;
|
||||
low->data = userptr_add ( low->data, len );
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap position of any two adjacent initrds not currently in the correct order
|
||||
*
|
||||
* @v free Free space
|
||||
* @v free_len Length of free space
|
||||
* @ret swapped A pair of initrds was swapped
|
||||
*/
|
||||
static int initrd_swap_any ( userptr_t free, size_t free_len ) {
|
||||
struct image *low;
|
||||
struct image *high;
|
||||
size_t padded_len;
|
||||
userptr_t adjacent;
|
||||
|
||||
/* Find any pair of initrds that can be swapped */
|
||||
for_each_image ( low ) {
|
||||
|
||||
/* Calculate location of adjacent image (if any) */
|
||||
padded_len = ( ( low->len + INITRD_ALIGN - 1 ) &
|
||||
~( INITRD_ALIGN - 1 ) );
|
||||
adjacent = userptr_add ( low->data, padded_len );
|
||||
|
||||
/* Search for adjacent image */
|
||||
for_each_image ( high ) {
|
||||
|
||||
/* If we have found the adjacent image, swap and exit */
|
||||
if ( high->data == adjacent ) {
|
||||
initrd_swap ( low, high, free, free_len );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Stop search if all remaining potential
|
||||
* adjacent images are already in the correct
|
||||
* order.
|
||||
*/
|
||||
if ( high == low )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing swapped */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump initrd locations (for debug)
|
||||
*
|
||||
*/
|
||||
static void initrd_dump ( void ) {
|
||||
struct image *initrd;
|
||||
|
||||
/* Do nothing unless debugging is enabled */
|
||||
if ( ! DBG_LOG )
|
||||
return;
|
||||
|
||||
/* Dump initrd locations */
|
||||
for_each_image ( initrd ) {
|
||||
DBGC ( &images, "INITRD %s at [%#08lx,%#08lx)\n",
|
||||
initrd->name, user_to_phys ( initrd->data, 0 ),
|
||||
user_to_phys ( initrd->data, initrd->len ) );
|
||||
DBGC2_MD5A ( &images, user_to_phys ( initrd->data, 0 ),
|
||||
user_to_virt ( initrd->data, 0 ), initrd->len );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reshuffle initrds into desired order at top of memory
|
||||
*
|
||||
* @v bottom Lowest address available for initrds
|
||||
*
|
||||
* After this function returns, the initrds have been rearranged in
|
||||
* memory and the external heap structures will have been corrupted.
|
||||
* Reshuffling must therefore take place immediately prior to jumping
|
||||
* to the loaded OS kernel; no further execution within iPXE is
|
||||
* permitted.
|
||||
*/
|
||||
void initrd_reshuffle ( userptr_t bottom ) {
|
||||
userptr_t top;
|
||||
userptr_t used;
|
||||
userptr_t free;
|
||||
size_t free_len;
|
||||
|
||||
/* Calculate limits of available space for initrds */
|
||||
top = initrd_top;
|
||||
if ( userptr_sub ( initrd_bottom, bottom ) > 0 )
|
||||
bottom = initrd_bottom;
|
||||
|
||||
/* Debug */
|
||||
DBGC ( &images, "INITRD region [%#08lx,%#08lx)\n",
|
||||
user_to_phys ( bottom, 0 ), user_to_phys ( top, 0 ) );
|
||||
initrd_dump();
|
||||
|
||||
/* Squash initrds as high as possible in memory */
|
||||
used = initrd_squash_high ( top );
|
||||
|
||||
/* Calculate available free space */
|
||||
free = bottom;
|
||||
free_len = userptr_sub ( used, free );
|
||||
|
||||
/* Bubble-sort initrds into desired order */
|
||||
while ( initrd_swap_any ( free, free_len ) ) {}
|
||||
|
||||
/* Debug */
|
||||
initrd_dump();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that there is enough space to reshuffle initrds
|
||||
*
|
||||
* @v len Total length of initrds (including padding)
|
||||
* @v bottom Lowest address available for initrds
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int initrd_reshuffle_check ( size_t len, userptr_t bottom ) {
|
||||
userptr_t top;
|
||||
size_t available;
|
||||
|
||||
/* Calculate limits of available space for initrds */
|
||||
top = initrd_top;
|
||||
if ( userptr_sub ( initrd_bottom, bottom ) > 0 )
|
||||
bottom = initrd_bottom;
|
||||
available = userptr_sub ( top, bottom );
|
||||
|
||||
/* Allow for a sensible minimum amount of free space */
|
||||
len += INITRD_MIN_FREE_LEN;
|
||||
|
||||
/* Check for available space */
|
||||
return ( ( len < available ) ? 0 : -ENOBUFS );
|
||||
}
|
||||
|
||||
/**
|
||||
* initrd startup function
|
||||
*
|
||||
*/
|
||||
static void initrd_startup ( void ) {
|
||||
size_t len;
|
||||
|
||||
/* Record largest memory block available. Do this after any
|
||||
* allocations made during driver startup (e.g. large host
|
||||
* memory blocks for Infiniband devices, which may still be in
|
||||
* use at the time of rearranging if a SAN device is hooked)
|
||||
* but before any allocations for downloaded images (which we
|
||||
* can safely reuse when rearranging).
|
||||
*/
|
||||
len = largest_memblock ( &initrd_bottom );
|
||||
initrd_top = userptr_add ( initrd_bottom, len );
|
||||
}
|
||||
|
||||
/** initrd startup function */
|
||||
struct startup_fn startup_initrd __startup_fn ( STARTUP_LATE ) = {
|
||||
.startup = initrd_startup,
|
||||
};
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -38,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/init.h>
|
||||
#include <ipxe/features.h>
|
||||
#include <ipxe/uri.h>
|
||||
#include <ipxe/version.h>
|
||||
|
||||
FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
|
||||
|
||||
@@ -246,7 +248,7 @@ static struct multiboot_info __bss16 ( mbinfo );
|
||||
#define mbinfo __use_data16 ( mbinfo )
|
||||
|
||||
/** The multiboot bootloader name */
|
||||
static char __data16_array ( mb_bootloader_name, [] ) = "iPXE " VERSION;
|
||||
static char __bss16_array ( mb_bootloader_name, [32] );
|
||||
#define mb_bootloader_name __use_data16 ( mb_bootloader_name )
|
||||
|
||||
/** The multiboot memory map */
|
||||
@@ -419,6 +421,8 @@ static int multiboot_exec ( struct image *image ) {
|
||||
mbinfo.cmdline = multiboot_add_cmdline ( image );
|
||||
mbinfo.mods_addr = virt_to_phys ( mbmodules );
|
||||
mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
|
||||
snprintf ( mb_bootloader_name, sizeof ( mb_bootloader_name ),
|
||||
"iPXE %s", product_version );
|
||||
mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
|
||||
if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules,
|
||||
( sizeof ( mbmodules ) /
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <ipxe/fakedhcp.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/features.h>
|
||||
#include <ipxe/version.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@@ -94,12 +95,6 @@ struct ebinfo {
|
||||
uint16_t flags; /* Bit flags */
|
||||
};
|
||||
|
||||
/** Info passed to NBI image */
|
||||
static struct ebinfo loaderinfo = {
|
||||
VERSION_MAJOR, VERSION_MINOR,
|
||||
0
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare a segment for an NBI image
|
||||
*
|
||||
@@ -281,6 +276,10 @@ static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
|
||||
* @ret rc Return status code, if image returns
|
||||
*/
|
||||
static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
|
||||
struct ebinfo loaderinfo = {
|
||||
product_major_version, product_minor_version,
|
||||
0
|
||||
};
|
||||
int discard_D, discard_S, discard_b;
|
||||
int rc;
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -35,6 +36,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 );
|
||||
|
||||
/** PXE command line */
|
||||
const char *pxe_cmdline;
|
||||
|
||||
/**
|
||||
* Execute PXE image
|
||||
*
|
||||
@@ -62,16 +66,29 @@ static int pxe_exec ( struct image *image ) {
|
||||
image );
|
||||
return -ENODEV;
|
||||
}
|
||||
netdev_get ( netdev );
|
||||
|
||||
/* Activate PXE */
|
||||
pxe_activate ( netdev );
|
||||
|
||||
/* Set PXE command line */
|
||||
pxe_cmdline = image->cmdline;
|
||||
|
||||
/* Start PXE NBP */
|
||||
rc = pxe_start_nbp();
|
||||
|
||||
/* Clear PXE command line */
|
||||
pxe_cmdline = NULL;
|
||||
|
||||
/* Deactivate PXE */
|
||||
pxe_deactivate();
|
||||
|
||||
/* Try to reopen network device. Ignore errors, since the NBP
|
||||
* may have called PXENV_STOP_UNDI.
|
||||
*/
|
||||
netdev_open ( netdev );
|
||||
netdev_put ( netdev );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
136
src/arch/i386/image/sdi.c
Normal file
136
src/arch/i386/image/sdi.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <realmode.h>
|
||||
#include <sdi.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/features.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* System Deployment Image (SDI)
|
||||
*
|
||||
* Based on the MSDN article "RAM boot using SDI in Windows XP
|
||||
* Embedded with Service Pack 1", available at the time of writing
|
||||
* from:
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/ms838543.aspx
|
||||
*/
|
||||
|
||||
FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 );
|
||||
|
||||
/**
|
||||
* Parse SDI image header
|
||||
*
|
||||
* @v image SDI file
|
||||
* @v sdi SDI header to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) {
|
||||
|
||||
/* Sanity check */
|
||||
if ( image->len < sizeof ( *sdi ) ) {
|
||||
DBGC ( image, "SDI %p too short for SDI header\n", image );
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* Read in header */
|
||||
copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) );
|
||||
|
||||
/* Check signature */
|
||||
if ( sdi->magic != SDI_MAGIC ) {
|
||||
DBGC ( image, "SDI %p is not an SDI image\n", image );
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute SDI image
|
||||
*
|
||||
* @v image SDI file
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int sdi_exec ( struct image *image ) {
|
||||
struct sdi_header sdi;
|
||||
uint32_t sdiptr;
|
||||
int rc;
|
||||
|
||||
/* Parse image header */
|
||||
if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Check that image is bootable */
|
||||
if ( sdi.boot_size == 0 ) {
|
||||
DBGC ( image, "SDI %p is not bootable\n", image );
|
||||
return -ENOTTY;
|
||||
}
|
||||
DBGC ( image, "SDI %p image at %08lx+%08zx\n",
|
||||
image, user_to_phys ( image->data, 0 ), image->len );
|
||||
DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image,
|
||||
user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size );
|
||||
|
||||
/* Copy boot code */
|
||||
memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0,
|
||||
image->data, sdi.boot_offset, sdi.boot_size );
|
||||
|
||||
/* Jump to boot code */
|
||||
sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF );
|
||||
__asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" )
|
||||
: : "i" ( SDI_BOOT_SEG ),
|
||||
"i" ( SDI_BOOT_OFF ),
|
||||
"d" ( sdiptr ) );
|
||||
|
||||
/* There is no way for the image to return, since we provide
|
||||
* no return address.
|
||||
*/
|
||||
assert ( 0 );
|
||||
|
||||
return -ECANCELED; /* -EIMPOSSIBLE */
|
||||
}
|
||||
|
||||
/**
|
||||
* Probe SDI image
|
||||
*
|
||||
* @v image SDI file
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int sdi_probe ( struct image *image ) {
|
||||
struct sdi_header sdi;
|
||||
int rc;
|
||||
|
||||
/* Parse image */
|
||||
if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** SDI image type */
|
||||
struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = {
|
||||
.name = "SDI",
|
||||
.probe = sdi_probe,
|
||||
.exec = sdi_exec,
|
||||
};
|
||||
@@ -6,6 +6,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define BDA_SEG 0x0040
|
||||
#define BDA_EQUIPMENT_WORD 0x0010
|
||||
#define BDA_FBMS 0x0013
|
||||
#define BDA_REBOOT 0x0072
|
||||
#define BDA_REBOOT_WARM 0x1234
|
||||
#define BDA_NUM_DRIVES 0x0075
|
||||
|
||||
#endif /* BIOS_H */
|
||||
|
||||
@@ -53,8 +53,8 @@ __bswap_variable_64 ( uint64_t x ) {
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
__bswap_64s ( uint64_t *x ) {
|
||||
struct {
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
uint32_t __attribute__ (( may_alias )) low;
|
||||
uint32_t __attribute__ (( may_alias )) high;
|
||||
} __attribute__ (( may_alias )) *dwords = ( ( void * ) x );
|
||||
uint32_t discard;
|
||||
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
#ifndef I386_BITS_CPU_H
|
||||
#define I386_BITS_CPU_H
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
|
||||
#define X86_FEATURE_FPU 0 /* Onboard FPU */
|
||||
#define X86_FEATURE_VME 1 /* Virtual Mode Extensions */
|
||||
#define X86_FEATURE_DE 2 /* Debugging Extensions */
|
||||
#define X86_FEATURE_PSE 3 /* Page Size Extensions */
|
||||
#define X86_FEATURE_TSC 4 /* Time Stamp Counter */
|
||||
#define X86_FEATURE_MSR 5 /* Model-Specific Registers, RDMSR, WRMSR */
|
||||
#define X86_FEATURE_PAE 6 /* Physical Address Extensions */
|
||||
#define X86_FEATURE_MCE 7 /* Machine Check Architecture */
|
||||
#define X86_FEATURE_CX8 8 /* CMPXCHG8 instruction */
|
||||
#define X86_FEATURE_APIC 9 /* Onboard APIC */
|
||||
#define X86_FEATURE_SEP 11 /* SYSENTER/SYSEXIT */
|
||||
#define X86_FEATURE_MTRR 12 /* Memory Type Range Registers */
|
||||
#define X86_FEATURE_PGE 13 /* Page Global Enable */
|
||||
#define X86_FEATURE_MCA 14 /* Machine Check Architecture */
|
||||
#define X86_FEATURE_CMOV 15 /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
|
||||
#define X86_FEATURE_PAT 16 /* Page Attribute Table */
|
||||
#define X86_FEATURE_PSE36 17 /* 36-bit PSEs */
|
||||
#define X86_FEATURE_PN 18 /* Processor serial number */
|
||||
#define X86_FEATURE_CLFLSH 19 /* Supports the CLFLUSH instruction */
|
||||
#define X86_FEATURE_DTES 21 /* Debug Trace Store */
|
||||
#define X86_FEATURE_ACPI 22 /* ACPI via MSR */
|
||||
#define X86_FEATURE_MMX 23 /* Multimedia Extensions */
|
||||
#define X86_FEATURE_FXSR 24 /* FXSAVE and FXRSTOR instructions (fast save and restore */
|
||||
/* of FPU context), and CR4.OSFXSR available */
|
||||
#define X86_FEATURE_XMM 25 /* Streaming SIMD Extensions */
|
||||
#define X86_FEATURE_XMM2 26 /* Streaming SIMD Extensions-2 */
|
||||
#define X86_FEATURE_SELFSNOOP 27 /* CPU self snoop */
|
||||
#define X86_FEATURE_HT 28 /* Hyper-Threading */
|
||||
#define X86_FEATURE_ACC 29 /* Automatic clock control */
|
||||
#define X86_FEATURE_IA64 30 /* IA-64 processor */
|
||||
|
||||
/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
|
||||
/* Don't duplicate feature flags which are redundant with Intel! */
|
||||
#define X86_FEATURE_SYSCALL 11 /* SYSCALL/SYSRET */
|
||||
#define X86_FEATURE_MMXEXT 22 /* AMD MMX extensions */
|
||||
#define X86_FEATURE_LM 29 /* Long Mode (x86-64) */
|
||||
#define X86_FEATURE_3DNOWEXT 30 /* AMD 3DNow! extensions */
|
||||
#define X86_FEATURE_3DNOW 31 /* 3DNow! */
|
||||
|
||||
/** x86 CPU information */
|
||||
struct cpuinfo_x86 {
|
||||
/** CPU features */
|
||||
unsigned int features;
|
||||
/** 64-bit CPU features */
|
||||
unsigned int amd_features;
|
||||
};
|
||||
|
||||
/*
|
||||
* EFLAGS bits
|
||||
*/
|
||||
#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
|
||||
#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
|
||||
#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
|
||||
#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
|
||||
#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
|
||||
#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
|
||||
#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
|
||||
#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
|
||||
#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
|
||||
#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
|
||||
#define X86_EFLAGS_NT 0x00004000 /* Nested Task */
|
||||
#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
|
||||
#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
|
||||
#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
|
||||
#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
|
||||
#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
|
||||
#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
|
||||
|
||||
/*
|
||||
* Generic CPUID function
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
cpuid ( int op, unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx ) {
|
||||
__asm__ ( "cpuid" :
|
||||
"=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
|
||||
: "0" ( op ) );
|
||||
}
|
||||
|
||||
extern void get_cpuinfo ( struct cpuinfo_x86 *cpu );
|
||||
|
||||
#endif /* I386_BITS_CPU_H */
|
||||
14
src/arch/i386/include/bits/reboot.h
Normal file
14
src/arch/i386/include/bits/reboot.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _BITS_REBOOT_H
|
||||
#define _BITS_REBOOT_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* i386-specific reboot API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <ipxe/bios_reboot.h>
|
||||
|
||||
#endif /* _BITS_REBOOT_H */
|
||||
29
src/arch/i386/include/initrd.h
Normal file
29
src/arch/i386/include/initrd.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef _INITRD_H
|
||||
#define _INITRD_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Initial ramdisk (initrd) reshuffling
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <ipxe/uaccess.h>
|
||||
|
||||
/** Minimum alignment for initrds
|
||||
*
|
||||
* Chosen to maximise memcpy() speeds
|
||||
*/
|
||||
#define INITRD_ALIGN 4
|
||||
|
||||
/** Minimum free space required to reshuffle initrds
|
||||
*
|
||||
* Chosen to avoid absurdly long reshuffling times
|
||||
*/
|
||||
#define INITRD_MIN_FREE_LEN ( 512 * 1024 )
|
||||
|
||||
extern void initrd_reshuffle ( userptr_t bottom );
|
||||
extern int initrd_reshuffle_check ( size_t len, userptr_t bottom );
|
||||
|
||||
#endif /* _INITRD_H */
|
||||
@@ -291,122 +291,6 @@ struct master_boot_record {
|
||||
/** MBR magic signature */
|
||||
#define INT13_MBR_MAGIC 0xaa55
|
||||
|
||||
/** ISO9660 block size */
|
||||
#define ISO9660_BLKSIZE 2048
|
||||
|
||||
/** An ISO9660 Primary Volume Descriptor (fixed portion) */
|
||||
struct iso9660_primary_descriptor_fixed {
|
||||
/** Descriptor type */
|
||||
uint8_t type;
|
||||
/** Identifier ("CD001") */
|
||||
uint8_t id[5];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** An ISO9660 Primary Volume Descriptor */
|
||||
struct iso9660_primary_descriptor {
|
||||
/** Fixed portion */
|
||||
struct iso9660_primary_descriptor_fixed fixed;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** ISO9660 Primary Volume Descriptor type */
|
||||
#define ISO9660_TYPE_PRIMARY 0x01
|
||||
|
||||
/** ISO9660 identifier */
|
||||
#define ISO9660_ID "CD001"
|
||||
|
||||
/** ISO9660 Primary Volume Descriptor block address */
|
||||
#define ISO9660_PRIMARY_LBA 16
|
||||
|
||||
/** An El Torito Boot Record Volume Descriptor (fixed portion) */
|
||||
struct eltorito_descriptor_fixed {
|
||||
/** Descriptor type */
|
||||
uint8_t type;
|
||||
/** Identifier ("CD001") */
|
||||
uint8_t id[5];
|
||||
/** Version, must be 1 */
|
||||
uint8_t version;
|
||||
/** Boot system indicator; must be "EL TORITO SPECIFICATION" */
|
||||
uint8_t system_id[32];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** An El Torito Boot Record Volume Descriptor */
|
||||
struct eltorito_descriptor {
|
||||
/** Fixed portion */
|
||||
struct eltorito_descriptor_fixed fixed;
|
||||
/** Unused */
|
||||
uint8_t unused[32];
|
||||
/** Boot catalog sector */
|
||||
uint32_t sector;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** ISO9660 Boot Volume Descriptor type */
|
||||
#define ISO9660_TYPE_BOOT 0x00
|
||||
|
||||
/** El Torito Boot Record Volume Descriptor block address */
|
||||
#define ELTORITO_LBA 17
|
||||
|
||||
/** An El Torito Boot Catalog Validation Entry */
|
||||
struct eltorito_validation_entry {
|
||||
/** Header ID; must be 1 */
|
||||
uint8_t header_id;
|
||||
/** Platform ID
|
||||
*
|
||||
* 0 = 80x86
|
||||
* 1 = PowerPC
|
||||
* 2 = Mac
|
||||
*/
|
||||
uint8_t platform_id;
|
||||
/** Reserved */
|
||||
uint16_t reserved;
|
||||
/** ID string */
|
||||
uint8_t id_string[24];
|
||||
/** Checksum word */
|
||||
uint16_t checksum;
|
||||
/** Signature; must be 0xaa55 */
|
||||
uint16_t signature;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** El Torito platform IDs */
|
||||
enum eltorito_platform_id {
|
||||
ELTORITO_PLATFORM_X86 = 0x00,
|
||||
ELTORITO_PLATFORM_POWERPC = 0x01,
|
||||
ELTORITO_PLATFORM_MAC = 0x02,
|
||||
};
|
||||
|
||||
/** A bootable entry in the El Torito Boot Catalog */
|
||||
struct eltorito_boot_entry {
|
||||
/** Boot indicator
|
||||
*
|
||||
* Must be @c ELTORITO_BOOTABLE for a bootable ISO image
|
||||
*/
|
||||
uint8_t indicator;
|
||||
/** Media type
|
||||
*
|
||||
*/
|
||||
uint8_t media_type;
|
||||
/** Load segment */
|
||||
uint16_t load_segment;
|
||||
/** System type */
|
||||
uint8_t filesystem;
|
||||
/** Unused */
|
||||
uint8_t reserved_a;
|
||||
/** Sector count */
|
||||
uint16_t length;
|
||||
/** Starting sector */
|
||||
uint32_t start;
|
||||
/** Unused */
|
||||
uint8_t reserved_b[20];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Boot indicator for a bootable ISO image */
|
||||
#define ELTORITO_BOOTABLE 0x88
|
||||
|
||||
/** El Torito media types */
|
||||
enum eltorito_media_type {
|
||||
/** No emulation */
|
||||
ELTORITO_NO_EMULATION = 0,
|
||||
};
|
||||
|
||||
/** A floppy disk geometry */
|
||||
struct int13_fdd_geometry {
|
||||
/** Number of tracks */
|
||||
|
||||
18
src/arch/i386/include/ipxe/bios_reboot.h
Normal file
18
src/arch/i386/include/ipxe/bios_reboot.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _IPXE_BIOS_REBOOT_H
|
||||
#define _IPXE_BIOS_REBOOT_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Standard PC-BIOS reboot mechanism
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifdef REBOOT_PCBIOS
|
||||
#define REBOOT_PREFIX_pcbios
|
||||
#else
|
||||
#define REBOOT_PREFIX_pcbios __pcbios_
|
||||
#endif
|
||||
|
||||
#endif /* _IPXE_BIOS_REBOOT_H */
|
||||
@@ -68,6 +68,12 @@ UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
|
||||
return trivial_userptr_add ( userptr, offset );
|
||||
}
|
||||
|
||||
static inline __always_inline off_t
|
||||
UACCESS_INLINE ( librm, userptr_sub ) ( userptr_t userptr,
|
||||
userptr_t subtrahend ) {
|
||||
return trivial_userptr_sub ( userptr, subtrahend );
|
||||
}
|
||||
|
||||
static inline __always_inline void
|
||||
UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
|
||||
userptr_t src, off_t src_off,
|
||||
|
||||
@@ -188,6 +188,7 @@ struct pcir_header {
|
||||
( ( 'P' << 0 ) + ( 'C' << 8 ) + ( 'I' << 16 ) + ( 'R' << 24 ) )
|
||||
|
||||
extern struct net_device *pxe_netdev;
|
||||
extern const char *pxe_cmdline;
|
||||
|
||||
extern void pxe_set_netdev ( struct net_device *netdev );
|
||||
extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* As an alternative, at your option, you may use this file under the
|
||||
* following terms, known as the "MIT license":
|
||||
@@ -1690,6 +1691,27 @@ typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t;
|
||||
|
||||
/** @} */ /* pxenv_file_exit_hook */
|
||||
|
||||
/** @defgroup pxenv_file_cmdline PXENV_FILE_CMDLINE
|
||||
*
|
||||
* FILE CMDLINE
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** PXE API function code for pxenv_file_cmdline() */
|
||||
#define PXENV_FILE_CMDLINE 0x00e8
|
||||
|
||||
/** Parameter block for pxenv_file_cmdline() */
|
||||
struct s_PXENV_FILE_CMDLINE {
|
||||
PXENV_STATUS_t Status; /**< PXE status code */
|
||||
UINT16_t BufferSize; /**< Data buffer size */
|
||||
SEGOFF16_t Buffer; /**< Data buffer */
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
typedef struct s_PXENV_FILE_CMDLINE PXENV_FILE_CMDLINE_t;
|
||||
|
||||
/** @} */ /* pxe_file_cmdline */
|
||||
|
||||
/** @} */ /* pxe_file_api */
|
||||
|
||||
/** @defgroup pxe_loader_api PXE Loader API
|
||||
|
||||
39
src/arch/i386/include/sdi.h
Normal file
39
src/arch/i386/include/sdi.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _SDI_H
|
||||
#define _SDI_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* System Deployment Image (SDI)
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** SDI image header */
|
||||
struct sdi_header {
|
||||
/** Signature */
|
||||
uint32_t magic;
|
||||
/** Version (as an ASCII string) */
|
||||
uint32_t version;
|
||||
/** Reserved */
|
||||
uint8_t reserved[8];
|
||||
/** Boot code offset */
|
||||
uint64_t boot_offset;
|
||||
/** Boot code size */
|
||||
uint64_t boot_size;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** SDI image signature */
|
||||
#define SDI_MAGIC \
|
||||
( ( '$' << 0 ) | ( 'S' << 8 ) | ( 'D' << 16 ) | ( 'I' << 24 ) )
|
||||
|
||||
/** SDI boot segment */
|
||||
#define SDI_BOOT_SEG 0x0000
|
||||
|
||||
/** SDI boot offset */
|
||||
#define SDI_BOOT_OFF 0x7c00
|
||||
|
||||
/** Constant to binary-OR with physical address of SDI image */
|
||||
#define SDI_WTF 0x41
|
||||
|
||||
#endif /* _SDI_H */
|
||||
48
src/arch/i386/interface/pcbios/bios_reboot.c
Normal file
48
src/arch/i386/interface/pcbios/bios_reboot.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Standard PC-BIOS reboot mechanism
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ipxe/reboot.h>
|
||||
#include <realmode.h>
|
||||
#include <bios.h>
|
||||
|
||||
/**
|
||||
* Reboot system
|
||||
*
|
||||
* @v warm Perform a warm reboot
|
||||
*/
|
||||
static void bios_reboot ( int warm ) {
|
||||
uint16_t flag;
|
||||
|
||||
/* Configure BIOS for cold/warm reboot */
|
||||
flag = ( warm ? BDA_REBOOT_WARM : 0 );
|
||||
put_real ( flag, BDA_SEG, BDA_REBOOT );
|
||||
|
||||
/* Jump to system reset vector */
|
||||
__asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : );
|
||||
}
|
||||
|
||||
PROVIDE_REBOOT ( pcbios, reboot, bios_reboot );
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -76,6 +77,8 @@ static int bios_find_smbios ( struct smbios *smbios ) {
|
||||
smbios->address = phys_to_user ( u.entry.smbios_address );
|
||||
smbios->len = u.entry.smbios_len;
|
||||
smbios->count = u.entry.smbios_count;
|
||||
smbios->version =
|
||||
SMBIOS_VERSION ( u.entry.major, u.entry.minor );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -37,6 +38,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/sanboot.h>
|
||||
#include <ipxe/device.h>
|
||||
#include <ipxe/pci.h>
|
||||
#include <ipxe/iso9660.h>
|
||||
#include <ipxe/eltorito.h>
|
||||
#include <realmode.h>
|
||||
#include <bios.h>
|
||||
#include <biosint.h>
|
||||
@@ -626,7 +629,7 @@ static const struct int13_fdd_geometry int13_fdd_geometries[] = {
|
||||
static int int13_guess_geometry_fdd ( struct int13_drive *int13,
|
||||
unsigned int *heads,
|
||||
unsigned int *sectors ) {
|
||||
unsigned int blocks = int13_blksize ( int13 );
|
||||
unsigned int blocks = int13_capacity ( int13 );
|
||||
const struct int13_fdd_geometry *geometry;
|
||||
unsigned int cylinders;
|
||||
unsigned int i;
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -30,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/hidemem.h>
|
||||
#include <ipxe/io.h>
|
||||
#include <ipxe/memblock.h>
|
||||
#include <ipxe/umalloc.h>
|
||||
|
||||
/** Alignment of external allocated memory */
|
||||
@@ -58,53 +60,14 @@ static size_t heap_size;
|
||||
/**
|
||||
* Initialise external heap
|
||||
*
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int init_eheap ( void ) {
|
||||
struct memory_map memmap;
|
||||
unsigned int i;
|
||||
|
||||
DBG ( "Allocating external heap\n" );
|
||||
|
||||
get_memmap ( &memmap );
|
||||
heap_size = 0;
|
||||
for ( i = 0 ; i < memmap.count ; i++ ) {
|
||||
struct memory_region *region = &memmap.regions[i];
|
||||
unsigned long r_start, r_end;
|
||||
unsigned long r_size;
|
||||
|
||||
DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
|
||||
|
||||
/* Truncate block to 4GB */
|
||||
if ( region->start > UINT_MAX ) {
|
||||
DBG ( "...starts after 4GB\n" );
|
||||
continue;
|
||||
}
|
||||
r_start = region->start;
|
||||
if ( region->end > UINT_MAX ) {
|
||||
DBG ( "...end truncated to 4GB\n" );
|
||||
r_end = 0; /* =4GB, given the wraparound */
|
||||
} else {
|
||||
r_end = region->end;
|
||||
}
|
||||
|
||||
/* Use largest block */
|
||||
r_size = ( r_end - r_start );
|
||||
if ( r_size > heap_size ) {
|
||||
DBG ( "...new best block found\n" );
|
||||
top = bottom = phys_to_user ( r_end );
|
||||
heap_size = r_size;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! heap_size ) {
|
||||
DBG ( "No external heap available\n" );
|
||||
return -ENOMEM;
|
||||
}
|
||||
static void init_eheap ( void ) {
|
||||
userptr_t base;
|
||||
|
||||
heap_size = largest_memblock ( &base );
|
||||
bottom = top = userptr_add ( base, heap_size );
|
||||
DBG ( "External heap grows downwards from %lx (size %zx)\n",
|
||||
user_to_phys ( top, 0 ), heap_size );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,13 +106,10 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
|
||||
struct external_memory extmem;
|
||||
userptr_t new = ptr;
|
||||
size_t align;
|
||||
int rc;
|
||||
|
||||
/* Initialise external memory allocator if necessary */
|
||||
if ( bottom == top ) {
|
||||
if ( ( rc = init_eheap() ) != 0 )
|
||||
return UNULL;
|
||||
}
|
||||
/* (Re)initialise external memory allocator if necessary */
|
||||
if ( bottom == top )
|
||||
init_eheap();
|
||||
|
||||
/* Get block properties into extmem */
|
||||
if ( ptr && ( ptr != UNOWHERE ) ) {
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -232,6 +233,42 @@ static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
|
||||
return PXENV_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* FILE CMDLINE
|
||||
*
|
||||
* @v file_cmdline Pointer to a struct s_PXENV_FILE_CMDLINE
|
||||
* @v s_PXENV_FILE_CMDLINE::Buffer Buffer to contain command line
|
||||
* @v s_PXENV_FILE_CMDLINE::BufferSize Size of buffer
|
||||
* @ret #PXENV_EXIT_SUCCESS Command was executed successfully
|
||||
* @ret #PXENV_EXIT_FAILURE Command was not executed successfully
|
||||
* @ret s_PXENV_FILE_EXEC::Status PXE status code
|
||||
* @ret s_PXENV_FILE_EXEC::BufferSize Length of command line (including NUL)
|
||||
*
|
||||
*/
|
||||
static PXENV_EXIT_t
|
||||
pxenv_file_cmdline ( struct s_PXENV_FILE_CMDLINE *file_cmdline ) {
|
||||
userptr_t buffer;
|
||||
size_t max_len;
|
||||
size_t len;
|
||||
|
||||
DBG ( "PXENV_FILE_CMDLINE to %04x:%04x+%04x \"%s\"\n",
|
||||
file_cmdline->Buffer.segment, file_cmdline->Buffer.offset,
|
||||
file_cmdline->BufferSize, pxe_cmdline );
|
||||
|
||||
buffer = real_to_user ( file_cmdline->Buffer.segment,
|
||||
file_cmdline->Buffer.offset );
|
||||
len = file_cmdline->BufferSize;
|
||||
max_len = ( pxe_cmdline ?
|
||||
( strlen ( pxe_cmdline ) + 1 /* NUL */ ) : 0 );
|
||||
if ( len > max_len )
|
||||
len = max_len;
|
||||
copy_to_user ( buffer, 0, pxe_cmdline, len );
|
||||
file_cmdline->BufferSize = max_len;
|
||||
|
||||
file_cmdline->Status = PXENV_STATUS_SUCCESS;
|
||||
return PXENV_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* FILE API CHECK
|
||||
*
|
||||
@@ -298,6 +335,8 @@ struct pxe_api_call pxe_file_api[] __pxe_api_call = {
|
||||
struct s_PXENV_GET_FILE_SIZE ),
|
||||
PXE_API_CALL ( PXENV_FILE_EXEC, pxenv_file_exec,
|
||||
struct s_PXENV_FILE_EXEC ),
|
||||
PXE_API_CALL ( PXENV_FILE_CMDLINE, pxenv_file_cmdline,
|
||||
struct s_PXENV_FILE_CMDLINE ),
|
||||
PXE_API_CALL ( PXENV_FILE_API_CHECK, pxenv_file_api_check,
|
||||
struct s_PXENV_FILE_API_CHECK ),
|
||||
};
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -70,6 +71,17 @@ static void pxe_tftp_close ( struct pxe_tftp_connection *pxe_tftp, int rc ) {
|
||||
pxe_tftp->rc = rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check flow control window
|
||||
*
|
||||
* @v pxe_tftp PXE TFTP connection
|
||||
* @ret len Length of window
|
||||
*/
|
||||
static size_t pxe_tftp_xfer_window ( struct pxe_tftp_connection *pxe_tftp ) {
|
||||
|
||||
return pxe_tftp->blksize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive new data
|
||||
*
|
||||
@@ -127,6 +139,8 @@ static int pxe_tftp_xfer_deliver ( struct pxe_tftp_connection *pxe_tftp,
|
||||
static struct interface_operation pxe_tftp_xfer_ops[] = {
|
||||
INTF_OP ( xfer_deliver, struct pxe_tftp_connection *,
|
||||
pxe_tftp_xfer_deliver ),
|
||||
INTF_OP ( xfer_window, struct pxe_tftp_connection *,
|
||||
pxe_tftp_xfer_window ),
|
||||
INTF_OP ( intf_close, struct pxe_tftp_connection *, pxe_tftp_close ),
|
||||
};
|
||||
|
||||
@@ -166,19 +180,19 @@ static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
|
||||
/* Reset PXE TFTP connection structure */
|
||||
memset ( &pxe_tftp, 0, sizeof ( pxe_tftp ) );
|
||||
intf_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_desc, NULL );
|
||||
if ( blksize < TFTP_DEFAULT_BLKSIZE )
|
||||
blksize = TFTP_DEFAULT_BLKSIZE;
|
||||
pxe_tftp.blksize = blksize;
|
||||
pxe_tftp.rc = -EINPROGRESS;
|
||||
|
||||
/* Construct URI string */
|
||||
address.s_addr = ipaddress;
|
||||
if ( ! port )
|
||||
port = htons ( TFTP_PORT );
|
||||
if ( blksize < TFTP_DEFAULT_BLKSIZE )
|
||||
blksize = TFTP_DEFAULT_BLKSIZE;
|
||||
snprintf ( uri_string, sizeof ( uri_string ),
|
||||
"tftp%s://%s:%d%s%s?blksize=%zd",
|
||||
sizeonly ? "size" : "",
|
||||
inet_ntoa ( address ), ntohs ( port ),
|
||||
( ( filename[0] == '/' ) ? "" : "/" ), filename, blksize );
|
||||
snprintf ( uri_string, sizeof ( uri_string ), "tftp%s://%s:%d%s%s",
|
||||
sizeonly ? "size" : "", inet_ntoa ( address ),
|
||||
ntohs ( port ), ( ( filename[0] == '/' ) ? "" : "/" ),
|
||||
filename );
|
||||
DBG ( " %s", uri_string );
|
||||
|
||||
/* Open PXE TFTP connection */
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -357,7 +358,8 @@ pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT *undi_transmit ) {
|
||||
}
|
||||
|
||||
/* Allocate and fill I/O buffer */
|
||||
iobuf = alloc_iob ( MAX_LL_HEADER_LEN + len );
|
||||
iobuf = alloc_iob ( MAX_LL_HEADER_LEN +
|
||||
( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) );
|
||||
if ( ! iobuf ) {
|
||||
DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" );
|
||||
undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER )
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -38,12 +39,13 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/serial.h>
|
||||
#include <ipxe/init.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/version.h>
|
||||
#include <usr/imgmgmt.h>
|
||||
#include "config/console.h"
|
||||
#include "config/serial.h"
|
||||
|
||||
/** The "SYSLINUX" version string */
|
||||
static char __data16_array ( syslinux_version, [] ) = "\r\niPXE " VERSION;
|
||||
static char __bss16_array ( syslinux_version, [32] );
|
||||
#define syslinux_version __use_data16 ( syslinux_version )
|
||||
|
||||
/** The "SYSLINUX" copyright string */
|
||||
@@ -325,6 +327,10 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
|
||||
/* SYSLINUX derivative ID */
|
||||
ix86->regs.dl = BZI_LOADER_TYPE_IPXE;
|
||||
|
||||
/* SYSLINUX version */
|
||||
snprintf ( syslinux_version, sizeof ( syslinux_version ),
|
||||
"\r\niPXE %s", product_version );
|
||||
|
||||
/* SYSLINUX version and copyright strings */
|
||||
ix86->segs.es = rm_ds;
|
||||
ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -90,7 +91,7 @@ static int guestinfo_fetch_type ( struct settings *settings,
|
||||
/* Allocate temporary block to hold GuestInfo value */
|
||||
info = zalloc ( info_len + 1 /* NUL */ );
|
||||
if ( ! info ) {
|
||||
DBGC ( settings, "GuestInfo %p could not allocate %zd bytes\n",
|
||||
DBGC ( settings, "GuestInfo %p could not allocate %d bytes\n",
|
||||
settings, info_len );
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc;
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -113,7 +114,7 @@ _exe_start:
|
||||
call alloc_basemem
|
||||
xorl %esi, %esi
|
||||
movl $EXE_DECOMPRESS_ADDRESS, %edi
|
||||
xorl %ebp, %ebp
|
||||
orl $0xffffffff, %ebp /* Allow arbitrary relocation */
|
||||
call install_prealloc
|
||||
|
||||
/* Set up real-mode stack */
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -544,8 +545,7 @@ alloc_basemem:
|
||||
* Free space allocated with alloc_basemem.
|
||||
*
|
||||
* Parameters:
|
||||
* %ax : .text16 segment address
|
||||
* %bx : .data16 segment address
|
||||
* none (.text16 segment address is implicit in %cs)
|
||||
* Returns:
|
||||
* %ax : 0 if successfully freed
|
||||
* Corrupts:
|
||||
@@ -558,14 +558,14 @@ alloc_basemem:
|
||||
free_basemem:
|
||||
/* Preserve registers */
|
||||
pushw %fs
|
||||
pushw %ax
|
||||
|
||||
/* Check FBMS counter */
|
||||
pushw %ax
|
||||
movw %cs, %ax
|
||||
shrw $6, %ax
|
||||
pushw $0x40
|
||||
popw %fs
|
||||
cmpw %ax, %fs:0x13
|
||||
popw %ax
|
||||
jne 1f
|
||||
|
||||
/* Check hooked interrupt count */
|
||||
@@ -573,6 +573,7 @@ free_basemem:
|
||||
jne 1f
|
||||
|
||||
/* OK to free memory */
|
||||
movw %cs, %ax
|
||||
addw $_text16_memsz_pgh, %ax
|
||||
addw $_data16_memsz_pgh, %ax
|
||||
shrw $6, %ax
|
||||
@@ -580,6 +581,7 @@ free_basemem:
|
||||
xorw %ax, %ax
|
||||
|
||||
1: /* Restore registers and return */
|
||||
popw %ax
|
||||
popw %fs
|
||||
ret
|
||||
.size free_basemem, . - free_basemem
|
||||
@@ -620,7 +622,7 @@ install:
|
||||
/* Image destination = default */
|
||||
xorl %edi, %edi
|
||||
/* Allow arbitrary relocation */
|
||||
xorl %ebp, %ebp
|
||||
orl $0xffffffff, %ebp
|
||||
/* Install text and data segments */
|
||||
call install_prealloc
|
||||
/* Restore registers and return */
|
||||
@@ -640,7 +642,9 @@ install:
|
||||
* %bx : .data16 segment address
|
||||
* %esi : Image source physical address (or zero for %cs:0000)
|
||||
* %edi : Decompression temporary area physical address (or zero for default)
|
||||
* %ebp : Maximum end address for relocation (or zero for no maximum)
|
||||
* %ebp : Maximum end address for relocation
|
||||
* - 0xffffffff for no maximum
|
||||
* - 0x00000000 to inhibit use of INT 15,e820 and INT 15,e801
|
||||
* Corrupts:
|
||||
* none
|
||||
****************************************************************************
|
||||
@@ -663,18 +667,22 @@ install_prealloc:
|
||||
/* Save decompression temporary area physical address */
|
||||
pushl %edi
|
||||
|
||||
/* Install .text16.early */
|
||||
/* Install .text16.early and calculate %ecx as offset to next block */
|
||||
progress " .text16.early\n"
|
||||
pushl %esi
|
||||
xorl %esi, %esi
|
||||
movw %cs, %si
|
||||
shll $4, %esi
|
||||
pushl %esi /* Save original %cs:0000 */
|
||||
addl $_text16_early_lma, %esi
|
||||
movzwl %ax, %edi
|
||||
shll $4, %edi
|
||||
movl $_text16_early_filesz, %ecx
|
||||
movl $_text16_early_memsz, %edx
|
||||
call install_block /* .text16.early */
|
||||
popl %ecx /* Calculate offset to next block */
|
||||
subl %esi, %ecx
|
||||
negl %ecx
|
||||
popl %esi
|
||||
|
||||
#ifndef KEEP_IT_REAL
|
||||
@@ -729,7 +737,7 @@ payload_death_message:
|
||||
jnz 1f
|
||||
movw %cs, %si
|
||||
shll $4, %esi
|
||||
1: addl payload_lma, %esi
|
||||
1: addl %ecx, %esi
|
||||
|
||||
/* Install .text16.late and .data16 */
|
||||
progress " .text16.late\n"
|
||||
@@ -790,6 +798,13 @@ payload_death_message:
|
||||
movw %ax, (init_librm_vector+2)
|
||||
lcall *init_librm_vector
|
||||
|
||||
/* Inhibit INT 15,e820 and INT 15,e801 if applicable */
|
||||
testl %ebp, %ebp
|
||||
jnz 1f
|
||||
incb memmap_post
|
||||
decl %ebp
|
||||
1:
|
||||
|
||||
/* Call relocate() to determine target address for relocation.
|
||||
* relocate() will return with %esi, %edi and %ecx set up
|
||||
* ready for the copy to the new location.
|
||||
@@ -850,17 +865,6 @@ close_payload_vector:
|
||||
.word 0
|
||||
.size close_payload_vector, . - close_payload_vector
|
||||
|
||||
/* Payload address */
|
||||
.section ".prefix.lib", "awx", @progbits
|
||||
payload_lma:
|
||||
.long 0
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "ADHL"
|
||||
.long payload_lma
|
||||
.long 1
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
/* Dummy routines to open and close payload */
|
||||
.section ".text16.early.data", "aw", @progbits
|
||||
.weak open_payload
|
||||
@@ -878,8 +882,7 @@ close_payload:
|
||||
* Uninstall all text and data segments.
|
||||
*
|
||||
* Parameters:
|
||||
* %ax : .text16 segment address
|
||||
* %bx : .data16 segment address
|
||||
* none (.text16 segment address is implicit in %cs)
|
||||
* Returns:
|
||||
* none
|
||||
* Corrupts:
|
||||
@@ -914,6 +917,10 @@ uninstall:
|
||||
.ascii "PAYL"
|
||||
.long 0
|
||||
.long 0
|
||||
.long _payload_align
|
||||
.ascii "COPY"
|
||||
.long _pprefix_lma
|
||||
.long _pprefix_filesz
|
||||
.long _max_align
|
||||
.ascii PACK_OR_COPY
|
||||
.long _text16_late_lma
|
||||
@@ -927,3 +934,6 @@ uninstall:
|
||||
.long _textdata_lma
|
||||
.long _textdata_filesz
|
||||
.long _max_align
|
||||
|
||||
.weak _payload_align
|
||||
.equ _payload_align, 1
|
||||
|
||||
@@ -231,9 +231,12 @@ run_ipxe:
|
||||
movzwl %sp, %edx
|
||||
no_cmd_line:
|
||||
|
||||
/* Retrieve initrd pointer and size */
|
||||
movl %ds:ramdisk_image, %ebp
|
||||
movl %ds:ramdisk_size, %ecx
|
||||
/* Calculate maximum relocation address */
|
||||
movl ramdisk_image, %ebp
|
||||
testl %ebp, %ebp
|
||||
jnz 1f
|
||||
orl $0xffffffff, %ebp /* Allow arbitrary relocation if no initrd */
|
||||
1:
|
||||
|
||||
/* Install iPXE */
|
||||
call alloc_basemem
|
||||
@@ -251,6 +254,10 @@ no_cmd_line:
|
||||
lret
|
||||
.section ".text16", "awx", @progbits
|
||||
1:
|
||||
/* Retrieve initrd pointer and size */
|
||||
movl ramdisk_image, %ebp
|
||||
movl ramdisk_size, %ecx
|
||||
|
||||
/* Set up %ds for access to .data16 */
|
||||
movw %bx, %ds
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -30,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
|
||||
#define PCI_BAR_EXPROM 0x30
|
||||
|
||||
#define ROMPREFIX_EXCLUDE_PAYLOAD 1
|
||||
#define ROMPREFIX_MORE_IMAGES 1
|
||||
#define _rom_start _mrom_start
|
||||
#include "romprefix.S"
|
||||
|
||||
@@ -46,8 +48,10 @@ FILE_LICENCE ( GPL2_OR_LATER )
|
||||
* Parameters:
|
||||
* %ds:0000 : Prefix
|
||||
* %esi : Buffer for copy of image source (or zero if no buffer available)
|
||||
* %ecx : Expected offset within buffer of first payload block
|
||||
* Returns:
|
||||
* %esi : Valid image source address (buffered or unbuffered)
|
||||
* %ecx : Actual offset within buffer of first payload block
|
||||
* CF set on error
|
||||
*/
|
||||
.section ".text16.early", "awx", @progbits
|
||||
@@ -56,23 +60,25 @@ open_payload:
|
||||
/* Preserve registers */
|
||||
pushl %eax
|
||||
pushw %bx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %edi
|
||||
pushw %bp
|
||||
pushw %es
|
||||
pushw %ds
|
||||
|
||||
/* Retrieve bus:dev.fn and image source length from .prefix */
|
||||
/* Retrieve bus:dev.fn from .prefix */
|
||||
movw init_pci_busdevfn, %bx
|
||||
movl image_source_len_dword, %ecx
|
||||
|
||||
/* Set up %ds for access to .text16.early */
|
||||
pushw %cs
|
||||
popw %ds
|
||||
|
||||
/* Store bus:dev.fn and image source length to .text16.early */
|
||||
/* Set up %es for access to flat address space */
|
||||
xorw %ax, %ax
|
||||
movw %ax, %es
|
||||
|
||||
/* Store bus:dev.fn to .text16.early */
|
||||
movw %bx, payload_pci_busdevfn
|
||||
movl %ecx, rom_bar_copy_len_dword
|
||||
|
||||
/* Get expansion ROM BAR current value */
|
||||
movw $PCI_BAR_EXPROM, %di
|
||||
@@ -149,6 +155,18 @@ find_mem_bar:
|
||||
movw $PCI_BAR_EXPROM, %di
|
||||
call pci_write_config_dword
|
||||
|
||||
/* Locate our ROM image */
|
||||
1: addr32 es cmpw $0xaa55, (%eax)
|
||||
stc
|
||||
jne 99f
|
||||
addr32 es cmpl $_build_id, build_id(%eax)
|
||||
je 2f
|
||||
addr32 es movzbl 2(%eax), %ecx
|
||||
shll $9, %ecx
|
||||
addl %ecx, %eax
|
||||
jmp 1b
|
||||
2:
|
||||
|
||||
/* Copy payload to buffer, or set buffer address to BAR address */
|
||||
testl %esi, %esi
|
||||
jz 1f
|
||||
@@ -159,27 +177,32 @@ find_mem_bar:
|
||||
* properly support flat real mode, it will die horribly.)
|
||||
*/
|
||||
pushl %esi
|
||||
pushw %es
|
||||
movl %esi, %edi
|
||||
movl %eax, %esi
|
||||
movl rom_bar_copy_len_dword, %ecx
|
||||
xorw %ax, %ax
|
||||
movw %ax, %es
|
||||
addr32 es movzbl 2(%esi), %ecx
|
||||
shll $7, %ecx
|
||||
addr32 es movzbl 2(%esi,%ecx,4), %edx
|
||||
shll $7, %edx
|
||||
addl %edx, %ecx
|
||||
addr32 es rep movsl
|
||||
popw %es
|
||||
popl %esi
|
||||
jmp 2f
|
||||
1: /* We have no buffer; set %esi to the BAR address */
|
||||
movl %eax, %esi
|
||||
2:
|
||||
|
||||
/* Locate first payload block (after the dummy ROM header) */
|
||||
addr32 es movzbl 2(%esi), %ecx
|
||||
shll $9, %ecx
|
||||
addl $_pprefix_skip, %ecx
|
||||
|
||||
clc
|
||||
/* Restore registers and return */
|
||||
99: popw %ds
|
||||
popw %es
|
||||
popw %bp
|
||||
popl %edi
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popw %bx
|
||||
popl %eax
|
||||
lret
|
||||
@@ -200,11 +223,6 @@ rom_bar_size:
|
||||
.long 0
|
||||
.size rom_bar_size, . - rom_bar_size
|
||||
|
||||
.section ".text16.early.data", "aw", @progbits
|
||||
rom_bar_copy_len_dword:
|
||||
.long 0
|
||||
.size rom_bar_copy_len_dword, . - rom_bar_copy_len_dword
|
||||
|
||||
.section ".text16.early.data", "aw", @progbits
|
||||
stolen_bar_register:
|
||||
.word 0
|
||||
@@ -419,16 +437,68 @@ pci_set_mem_access:
|
||||
ret
|
||||
.size pci_set_mem_access, . - pci_set_mem_access
|
||||
|
||||
/* Image source area length (in dwords)
|
||||
/* Payload prefix
|
||||
*
|
||||
* We include a dummy ROM header to cover the "hidden" portion of the
|
||||
* overall ROM image.
|
||||
*/
|
||||
.section ".prefix", "ax", @progbits
|
||||
image_source_len_dword:
|
||||
.long 0
|
||||
.size image_source_len_dword, . - image_source_len_dword
|
||||
.globl _payload_align
|
||||
.equ _payload_align, 512
|
||||
.section ".pprefix", "ax", @progbits
|
||||
.org 0x00
|
||||
mromheader:
|
||||
.word 0xaa55 /* BIOS extension signature */
|
||||
mromheader_size: .byte 0 /* Size in 512-byte blocks */
|
||||
.org 0x18
|
||||
.word mpciheader
|
||||
.org 0x1a
|
||||
.word 0
|
||||
.size mromheader, . - mromheader
|
||||
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "ADDL"
|
||||
.long image_source_len_dword
|
||||
.long 4
|
||||
.ascii "APPB"
|
||||
.long mromheader_size
|
||||
.long 512
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
mpciheader:
|
||||
.ascii "PCIR" /* Signature */
|
||||
.word pci_vendor_id /* Vendor identification */
|
||||
.word pci_device_id /* Device identification */
|
||||
.word 0x0000 /* Device list pointer */
|
||||
.word mpciheader_len /* PCI data structure length */
|
||||
.byte 0x03 /* PCI data structure revision */
|
||||
.byte 0x02, 0x00, 0x00 /* Class code */
|
||||
mpciheader_image_length:
|
||||
.word 0 /* Image length */
|
||||
.word 0x0001 /* Revision level */
|
||||
.byte 0xff /* Code type */
|
||||
.byte 0x80 /* Last image indicator */
|
||||
mpciheader_runtime_length:
|
||||
.word 0 /* Maximum run-time image length */
|
||||
.word 0x0000 /* Configuration utility code header */
|
||||
.word 0x0000 /* DMTF CLP entry point */
|
||||
.equ mpciheader_len, . - mpciheader
|
||||
.size mpciheader, . - mpciheader
|
||||
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "APPW"
|
||||
.long mpciheader_image_length
|
||||
.long 512
|
||||
.long 0
|
||||
.ascii "APPW"
|
||||
.long mpciheader_runtime_length
|
||||
.long 512
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
/* Fix up additional image source size
|
||||
*
|
||||
*/
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "ADPW"
|
||||
.long extra_size
|
||||
.long 512
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
@@ -54,6 +54,10 @@ _nbi_start:
|
||||
/* Install iPXE */
|
||||
call install
|
||||
|
||||
/* Set up real-mode stack */
|
||||
movw %bx, %ss
|
||||
movw $_estack16, %sp
|
||||
|
||||
/* Jump to .text16 segment */
|
||||
pushw %ax
|
||||
pushw $1f
|
||||
|
||||
@@ -5,6 +5,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
|
||||
#define PXENV_UNDI_GET_IFACE_INFO 0x0013
|
||||
#define PXENV_STOP_UNDI 0x0015
|
||||
#define PXENV_UNLOAD_STACK 0x0070
|
||||
#define PXENV_FILE_CMDLINE 0x00e8
|
||||
|
||||
#define PXE_HACK_EB54 0x0001
|
||||
|
||||
@@ -19,6 +20,8 @@ FILE_LICENCE ( GPL2_OR_LATER )
|
||||
#define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) )
|
||||
#define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) )
|
||||
|
||||
#define PREFIX_STACK_SIZE 2048
|
||||
|
||||
/*****************************************************************************
|
||||
* Entry point: set operating context, print welcome message
|
||||
*****************************************************************************
|
||||
@@ -46,10 +49,11 @@ _pxe_start:
|
||||
movw %ax, %ds
|
||||
movw $0x40, %ax /* BIOS data segment access */
|
||||
movw %ax, %fs
|
||||
/* Set up stack just below 0x7c00 */
|
||||
xorw %ax, %ax
|
||||
/* Set up temporary stack immediately after the iPXE image */
|
||||
movw %cs, %ax
|
||||
addw image_size_pgh, %ax
|
||||
movw %ax, %ss
|
||||
movl $0x7c00, %esp
|
||||
movl $PREFIX_STACK_SIZE, %esp
|
||||
/* Clear direction flag, for the sake of sanity */
|
||||
cld
|
||||
/* Print welcome message */
|
||||
@@ -60,6 +64,18 @@ _pxe_start:
|
||||
10: .asciz "PXE->EB:"
|
||||
.previous
|
||||
|
||||
/* Image size (for stack placement calculation) */
|
||||
.section ".prefix.data", "aw", @progbits
|
||||
image_size_pgh:
|
||||
.word 0
|
||||
.previous
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "ADDW"
|
||||
.long image_size_pgh
|
||||
.long 16
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
/*****************************************************************************
|
||||
* Find us a usable !PXE or PXENV+ entry point
|
||||
*****************************************************************************
|
||||
@@ -366,6 +382,35 @@ get_iface_type:
|
||||
99: movb $0x0a, %al
|
||||
call print_character
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Check for a command line
|
||||
*****************************************************************************
|
||||
*/
|
||||
get_cmdline:
|
||||
/* Issue PXENV_FILE_CMDLINE */
|
||||
xorl %esi, %esi
|
||||
movw %ss, %si
|
||||
movw %si, ( pxe_parameter_structure + 0x06 )
|
||||
movw $PREFIX_STACK_SIZE, ( pxe_parameter_structure + 0x04 )
|
||||
movw $0xffff, ( pxe_parameter_structure + 0x02 )
|
||||
movw $PXENV_FILE_CMDLINE, %bx
|
||||
call pxe_call
|
||||
jc 99f /* Suppress errors; this is an iPXE extension API call */
|
||||
/* Check for non-NULL command line */
|
||||
movw ( pxe_parameter_structure + 0x02 ), %ax
|
||||
testw %ax, %ax
|
||||
jz 99f
|
||||
/* Record command line */
|
||||
shll $4, %esi
|
||||
addl $PREFIX_STACK_SIZE, %esi
|
||||
movl %esi, pxe_cmdline
|
||||
99:
|
||||
.section ".prefix.data", "aw", @progbits
|
||||
pxe_cmdline:
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
/*****************************************************************************
|
||||
* Leave NIC in a safe state
|
||||
*****************************************************************************
|
||||
@@ -713,6 +758,9 @@ run_ipxe:
|
||||
movw pxe_ss, %di
|
||||
movl pxe_esp, %ebp
|
||||
|
||||
/* Retrieve PXE command line, if any */
|
||||
movl pxe_cmdline, %esi
|
||||
|
||||
/* Jump to .text16 segment with %ds pointing to .data16 */
|
||||
movw %bx, %ds
|
||||
pushw %ax
|
||||
@@ -723,6 +771,9 @@ run_ipxe:
|
||||
/* Update the exit hook */
|
||||
movw %cs, ( pxe_exit_hook + 2 )
|
||||
|
||||
/* Store command-line pointer */
|
||||
movl %esi, cmdline_phys
|
||||
|
||||
/* Run main program */
|
||||
pushl $main
|
||||
pushw %cs
|
||||
|
||||
@@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
|
||||
( PMM_HANDLE_BASE | 0x00001000 )
|
||||
#define PMM_HANDLE_BASE_DECOMPRESS_TO \
|
||||
( PMM_HANDLE_BASE | 0x00002000 )
|
||||
#define PCI_FUNC_MASK 0x07
|
||||
|
||||
/* ROM banner timeout. Based on the configurable BANNER_TIMEOUT in
|
||||
* config.h, but converted to a number of (18Hz) timer ticks, and
|
||||
@@ -39,6 +40,14 @@ FILE_LICENCE ( GPL2_OR_LATER )
|
||||
#else
|
||||
#define ZINFO_TYPE_ADxB "ADDB"
|
||||
#define ZINFO_TYPE_ADxW "ADDW"
|
||||
#endif
|
||||
|
||||
/* Allow ROM to be marked as containing multiple images
|
||||
*/
|
||||
#if ROMPREFIX_MORE_IMAGES
|
||||
#define INDICATOR 0x00
|
||||
#else
|
||||
#define INDICATOR 0x80
|
||||
#endif
|
||||
|
||||
.text
|
||||
@@ -55,6 +64,8 @@ romheader_size: .byte 0 /* Size in 512-byte blocks */
|
||||
jmp init /* Initialisation vector */
|
||||
checksum:
|
||||
.byte 0
|
||||
.org 0x10
|
||||
.word ipxeheader
|
||||
.org 0x16
|
||||
.word undiheader
|
||||
.org 0x18
|
||||
@@ -70,9 +81,6 @@ checksum:
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
build_id:
|
||||
.long _build_id /* Randomly-generated build ID */
|
||||
|
||||
pciheader:
|
||||
.ascii "PCIR" /* Signature */
|
||||
.word pci_vendor_id /* Vendor identification */
|
||||
@@ -85,7 +93,7 @@ pciheader_image_length:
|
||||
.word 0 /* Image length */
|
||||
.word 0x0001 /* Revision level */
|
||||
.byte 0x00 /* Code type */
|
||||
.byte 0x80 /* Last image indicator */
|
||||
.byte INDICATOR /* Last image indicator */
|
||||
pciheader_runtime_length:
|
||||
.word 0 /* Maximum run-time image length */
|
||||
.word 0x0000 /* Configuration utility code header */
|
||||
@@ -167,6 +175,25 @@ undiheader:
|
||||
.equ undiheader_len, . - undiheader
|
||||
.size undiheader, . - undiheader
|
||||
|
||||
ipxeheader:
|
||||
.ascii "iPXE" /* Signature */
|
||||
.byte ipxeheader_len /* Length of structure */
|
||||
.byte 0 /* Checksum */
|
||||
shrunk_rom_size:
|
||||
.byte 0 /* Shrunk size (in 512-byte blocks) */
|
||||
.byte 0 /* Reserved */
|
||||
build_id:
|
||||
.long _build_id /* Randomly-generated build ID */
|
||||
.equ ipxeheader_len, . - ipxeheader
|
||||
.size ipxeheader, . - ipxeheader
|
||||
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "ADHB"
|
||||
.long shrunk_rom_size
|
||||
.long 512
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
/* Initialisation (called once during POST)
|
||||
*
|
||||
* Determine whether or not this is a PnP system via a signature
|
||||
@@ -326,14 +353,19 @@ pmm_scan:
|
||||
call print_message
|
||||
/* We have PMM and so a 1kB stack: preserve whole registers */
|
||||
pushal
|
||||
/* Allocate image source PMM block */
|
||||
movzwl image_source_size, %ecx
|
||||
/* Allocate image source PMM block. Round up the size to the
|
||||
* nearest 4kB (8 512-byte sectors) to work around AMI BIOS bugs.
|
||||
*/
|
||||
movzbl romheader_size, %ecx
|
||||
addw extra_size, %cx
|
||||
addw $0x0007, %cx /* Round up to multiple of 8 512-byte sectors */
|
||||
andw $0xfff8, %cx
|
||||
shll $5, %ecx
|
||||
movl $PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx
|
||||
movw $get_pmm_image_source, %bp
|
||||
call get_pmm
|
||||
movl %esi, image_source
|
||||
jc 1f
|
||||
jz 1f
|
||||
/* Copy ROM to image source PMM block */
|
||||
pushw %es
|
||||
xorw %ax, %ax
|
||||
@@ -341,8 +373,8 @@ pmm_scan:
|
||||
movl %esi, %edi
|
||||
xorl %esi, %esi
|
||||
movzbl romheader_size, %ecx
|
||||
shll $9, %ecx
|
||||
addr32 rep movsb /* PMM presence implies flat real mode */
|
||||
shll $7, %ecx
|
||||
addr32 rep movsl /* PMM presence implies flat real mode */
|
||||
popw %es
|
||||
/* Shrink ROM */
|
||||
movb shrunk_rom_size, %al
|
||||
@@ -391,6 +423,9 @@ no_pmm:
|
||||
xorw %di, %di
|
||||
cs rep movsb
|
||||
|
||||
/* Skip prompt if this is not the first PCI function */
|
||||
testb $PCI_FUNC_MASK, init_pci_busdevfn
|
||||
jnz no_shell
|
||||
/* Prompt for POST-time shell */
|
||||
movw $init_message_prompt, %si
|
||||
xorw %di, %di
|
||||
@@ -409,15 +444,19 @@ no_pmm:
|
||||
movw $init_message_done, %si
|
||||
call print_message
|
||||
popf
|
||||
jnz 2f
|
||||
jnz no_shell
|
||||
/* Ctrl-B was pressed: invoke iPXE. The keypress will be
|
||||
* picked up by the initial shell prompt, and we will drop
|
||||
* into a shell.
|
||||
*/
|
||||
movl $0xa0000, %ebp /* Inhibit relocation during POST */
|
||||
xorl %ebp, %ebp /* Inhibit use of INT 15,e820 and INT 15,e801 */
|
||||
pushw %cs
|
||||
call exec
|
||||
2:
|
||||
no_shell:
|
||||
movb $( '\n' ), %al
|
||||
xorw %di, %di
|
||||
call print_character
|
||||
|
||||
/* Restore registers */
|
||||
popw %gs
|
||||
popw %fs
|
||||
@@ -439,7 +478,7 @@ no_pmm:
|
||||
* %es:0000 : PMM structure
|
||||
* Returns:
|
||||
* %ebx : PMM handle
|
||||
* %esi : allocated block address, or zero (with CF set) if allocation failed
|
||||
* %esi : allocated block address, or zero (with ZF set) if allocation failed
|
||||
*/
|
||||
get_pmm:
|
||||
/* Preserve registers */
|
||||
@@ -455,7 +494,10 @@ get_pmm_find:
|
||||
pushw %dx
|
||||
pushw %ax
|
||||
popl %esi
|
||||
testl %esi, %esi
|
||||
/* Treat 0xffffffff (not supported) as 0x00000000 (not found) */
|
||||
incl %esi
|
||||
jz get_pmm_allocate
|
||||
decl %esi
|
||||
jz get_pmm_allocate
|
||||
/* Block found - check acceptability */
|
||||
call *%bp
|
||||
@@ -475,19 +517,20 @@ get_pmm_allocate:
|
||||
pushw %ax
|
||||
popl %esi
|
||||
movw $( '+' ), %di /* Indicate allocation attempt */
|
||||
testl %esi, %esi
|
||||
jnz get_pmm_done
|
||||
stc
|
||||
get_pmm_done:
|
||||
/* Print block address */
|
||||
pushfw
|
||||
movw %di, %ax
|
||||
xorw %di, %di
|
||||
call print_character
|
||||
movl %esi, %eax
|
||||
call print_hex_dword
|
||||
popfw
|
||||
/* Restore registers and return */
|
||||
/* Treat 0xffffffff (not supported) as 0x00000000 (allocation
|
||||
* failed), and set ZF to indicate a zero result.
|
||||
*/
|
||||
incl %esi
|
||||
jz 1f
|
||||
decl %esi
|
||||
1: /* Restore registers and return */
|
||||
popw %di
|
||||
popl %eax
|
||||
ret
|
||||
@@ -560,7 +603,7 @@ init_message_done:
|
||||
*
|
||||
*/
|
||||
init_pci_busdevfn:
|
||||
.word 0xffff
|
||||
.word 0
|
||||
.size init_pci_busdevfn, . - init_pci_busdevfn
|
||||
|
||||
/* Image source area
|
||||
@@ -573,31 +616,12 @@ image_source:
|
||||
.long 0
|
||||
.size image_source, . - image_source
|
||||
|
||||
/* Image source size (in 512-byte sectors)
|
||||
/* Additional image source size (in 512-byte sectors)
|
||||
*
|
||||
*/
|
||||
image_source_size:
|
||||
extra_size:
|
||||
.word 0
|
||||
.size image_source_size, . - image_source_size
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "ADDW"
|
||||
.long image_source_size
|
||||
.long 512
|
||||
.long 0
|
||||
.previous
|
||||
|
||||
/* Shrunk ROM size (in 512-byte sectors)
|
||||
*
|
||||
*/
|
||||
shrunk_rom_size:
|
||||
.byte 0
|
||||
.size shrunk_rom_size, . - shrunk_rom_size
|
||||
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
||||
.ascii "ADHB"
|
||||
.long shrunk_rom_size
|
||||
.long 512
|
||||
.long 0
|
||||
.previous
|
||||
.size extra_size, . - extra_size
|
||||
|
||||
/* Temporary decompression area
|
||||
*
|
||||
@@ -614,7 +638,7 @@ decompress_to:
|
||||
* Called by the PnP BIOS when it wants to boot us.
|
||||
*/
|
||||
bev_entry:
|
||||
xorl %ebp, %ebp /* Allow relocation */
|
||||
orl $0xffffffff, %ebp /* Allow arbitrary relocation */
|
||||
pushw %cs
|
||||
call exec
|
||||
lret
|
||||
@@ -649,7 +673,7 @@ int19_entry:
|
||||
/* Leave keypress in buffer and start iPXE. The keypress will
|
||||
* cause the usual initial Ctrl-B prompt to be skipped.
|
||||
*/
|
||||
xorl %ebp, %ebp /* Allow relocation */
|
||||
orl $0xffffffff, %ebp /* Allow arbitrary relocation */
|
||||
pushw %cs
|
||||
call exec
|
||||
1: /* Try to call original INT 19 vector */
|
||||
|
||||
@@ -31,7 +31,7 @@ undiloader:
|
||||
movw %es:14(%di), %ax
|
||||
movl image_source, %esi
|
||||
movl decompress_to, %edi
|
||||
xorl %ebp, %ebp /* Allow relocation */
|
||||
orl $0xffffffff, %ebp /* Allow arbitrary relocation */
|
||||
call install_prealloc
|
||||
popw %di
|
||||
/* Call UNDI loader C code */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* -*- sh -*- */
|
||||
/* -*- ld-script -*- */
|
||||
|
||||
/*
|
||||
* Linker script for i386 images
|
||||
@@ -121,6 +121,23 @@ SECTIONS {
|
||||
_textdata_filesz = ABSOLUTE ( _mtextdata ) - ABSOLUTE ( _textdata );
|
||||
_textdata_memsz = ABSOLUTE ( _etextdata ) - ABSOLUTE ( _textdata );
|
||||
|
||||
/*
|
||||
* Payload prefix
|
||||
*
|
||||
* If present, this will be placed between .text16.early and .text16.late.
|
||||
*
|
||||
*/
|
||||
.pprefix 0x0 : AT ( _pprefix_lma ) {
|
||||
_pprefix = .;
|
||||
KEEP(*(.pprefix))
|
||||
KEEP(*(.pprefix.*))
|
||||
_mpprefix = .;
|
||||
} .bss.pprefix (NOLOAD) : AT ( _end_lma ) {
|
||||
_epprefix = .;
|
||||
}
|
||||
_pprefix_filesz = ABSOLUTE ( _mpprefix ) - ABSOLUTE ( _pprefix );
|
||||
_pprefix_memsz = ABSOLUTE ( _epprefix ) - ABSOLUTE ( _pprefix );
|
||||
|
||||
/*
|
||||
* Compressor information block
|
||||
*
|
||||
@@ -187,8 +204,14 @@ SECTIONS {
|
||||
_text16_early_lma = .;
|
||||
. += _text16_early_filesz;
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
. = ALIGN ( _payload_align );
|
||||
_pprefix_lma = .;
|
||||
. += _pprefix_filesz;
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
_payload_lma = .;
|
||||
_pprefix_skip = ABSOLUTE ( _payload_lma ) - ABSOLUTE ( _pprefix_lma );
|
||||
_text16_late_lma = .;
|
||||
. += _text16_late_filesz;
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ INCDIRS += arch/x86/include
|
||||
SRCDIRS += arch/x86/core
|
||||
SRCDIRS += arch/x86/interface/efi
|
||||
SRCDIRS += arch/x86/prefix
|
||||
SRCDIRS += arch/x86/hci/commands
|
||||
|
||||
# breaks building some of the linux-related objects
|
||||
CFLAGS += -Ulinux
|
||||
|
||||
155
src/arch/x86/core/cpuid.c
Normal file
155
src/arch/x86/core/cpuid.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <string.h>
|
||||
#include <ipxe/cpuid.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* x86 CPU feature detection
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check whether or not CPUID instruction is supported
|
||||
*
|
||||
* @ret is_supported CPUID instruction is supported
|
||||
*/
|
||||
static int cpuid_is_supported ( void ) {
|
||||
unsigned long original;
|
||||
unsigned long inverted;
|
||||
|
||||
__asm__ ( "pushf\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %0\n\t"
|
||||
"mov %0,%1\n\t"
|
||||
"xor %2,%1\n\t"
|
||||
"push %1\n\t"
|
||||
"popf\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %1\n\t"
|
||||
"popf\n\t"
|
||||
: "=&r" ( original ), "=&r" ( inverted )
|
||||
: "ir" ( CPUID_FLAG ) );
|
||||
return ( ( original ^ inverted ) & CPUID_FLAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue CPUID instruction
|
||||
*
|
||||
* @v operation CPUID operation
|
||||
* @v eax Output via %eax
|
||||
* @v ebx Output via %ebx
|
||||
* @v ecx Output via %ecx
|
||||
* @v edx Output via %edx
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
|
||||
uint32_t *edx ) {
|
||||
|
||||
__asm__ ( "cpuid"
|
||||
: "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
|
||||
: "0" ( operation ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Intel-defined x86 CPU features
|
||||
*
|
||||
* @v features x86 CPU features to fill in
|
||||
*/
|
||||
static void x86_intel_features ( struct x86_features *features ) {
|
||||
uint32_t max_level;
|
||||
uint32_t discard_a;
|
||||
uint32_t discard_b;
|
||||
uint32_t discard_c;
|
||||
uint32_t discard_d;
|
||||
|
||||
/* Check that features are available via CPUID */
|
||||
cpuid ( CPUID_VENDOR_ID, &max_level, &discard_b, &discard_c,
|
||||
&discard_d );
|
||||
if ( max_level < CPUID_FEATURES ) {
|
||||
DBGC ( features, "CPUID has no Intel-defined features (max "
|
||||
"level %08x)\n", max_level );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get features */
|
||||
cpuid ( CPUID_FEATURES, &discard_a, &discard_b,
|
||||
&features->intel.ecx, &features->intel.edx );
|
||||
DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n",
|
||||
features->intel.ecx, features->intel.edx );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AMD-defined x86 CPU features
|
||||
*
|
||||
* @v features x86 CPU features to fill in
|
||||
*/
|
||||
static void x86_amd_features ( struct x86_features *features ) {
|
||||
uint32_t max_level;
|
||||
uint32_t discard_a;
|
||||
uint32_t discard_b;
|
||||
uint32_t discard_c;
|
||||
uint32_t discard_d;
|
||||
|
||||
/* Check that features are available via CPUID */
|
||||
cpuid ( CPUID_AMD_MAX_FN, &max_level, &discard_b, &discard_c,
|
||||
&discard_d );
|
||||
if ( ( max_level & CPUID_AMD_CHECK_MASK ) != CPUID_AMD_CHECK ) {
|
||||
DBGC ( features, "CPUID has no extended functions\n" );
|
||||
return;
|
||||
}
|
||||
if ( max_level < CPUID_AMD_FEATURES ) {
|
||||
DBGC ( features, "CPUID has no AMD-defined features (max "
|
||||
"level %08x)\n", max_level );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get features */
|
||||
cpuid ( CPUID_AMD_FEATURES, &discard_a, &discard_b,
|
||||
&features->amd.ecx, &features->amd.edx );
|
||||
DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n",
|
||||
features->amd.ecx, features->amd.edx );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get x86 CPU features
|
||||
*
|
||||
* @v features x86 CPU features to fill in
|
||||
*/
|
||||
void x86_features ( struct x86_features *features ) {
|
||||
|
||||
/* Clear all features */
|
||||
memset ( features, 0, sizeof ( *features ) );
|
||||
|
||||
/* Check that CPUID instruction is available */
|
||||
if ( ! cpuid_is_supported() ) {
|
||||
DBGC ( features, "CPUID instruction is not supported\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get Intel-defined features */
|
||||
x86_intel_features ( features );
|
||||
|
||||
/* Get AMD-defined features */
|
||||
x86_amd_features ( features );
|
||||
}
|
||||
86
src/arch/x86/core/debugcon.c
Normal file
86
src/arch/x86/core/debugcon.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Debug port console
|
||||
*
|
||||
* The debug port is supported by bochs (via the "port_e9_hack"
|
||||
* configuration file directive) and by qemu (via the "-debugcon"
|
||||
* command-line option).
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ipxe/io.h>
|
||||
#include <ipxe/console.h>
|
||||
#include <ipxe/init.h>
|
||||
#include <config/console.h>
|
||||
|
||||
/** Debug port */
|
||||
#define DEBUG_PORT 0xe9
|
||||
|
||||
/** Debug port installation check magic value */
|
||||
#define DEBUG_PORT_CHECK 0xe9
|
||||
|
||||
/* Set default console usage if applicable */
|
||||
#if ! ( defined ( CONSOLE_DEBUGCON ) && CONSOLE_EXPLICIT ( CONSOLE_DEBUGCON ) )
|
||||
#undef CONSOLE_DEBUGCON
|
||||
#define CONSOLE_DEBUGCON ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Print a character to debug port console
|
||||
*
|
||||
* @v character Character to be printed
|
||||
*/
|
||||
static void debugcon_putchar ( int character ) {
|
||||
|
||||
/* Write character to debug port */
|
||||
outb ( character, DEBUG_PORT );
|
||||
}
|
||||
|
||||
/** Debug port console driver */
|
||||
struct console_driver debugcon_console __console_driver = {
|
||||
.putchar = debugcon_putchar,
|
||||
.usage = CONSOLE_DEBUGCON,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise debug port console
|
||||
*
|
||||
*/
|
||||
static void debugcon_init ( void ) {
|
||||
uint8_t check;
|
||||
|
||||
/* Check if console is present */
|
||||
check = inb ( DEBUG_PORT );
|
||||
if ( check != DEBUG_PORT_CHECK ) {
|
||||
DBG ( "Debug port not present; disabling console\n" );
|
||||
debugcon_console.disabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug port console initialisation function
|
||||
*/
|
||||
struct init_fn debugcon_init_fn __init_fn ( INIT_EARLY ) = {
|
||||
.initialise = debugcon_init,
|
||||
};
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -35,7 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
* This routine uses MMX instructions.
|
||||
*/
|
||||
static uint64_t x86_readq ( volatile uint64_t *io_addr ) {
|
||||
static __unused uint64_t i386_readq ( volatile uint64_t *io_addr ) {
|
||||
uint64_t data;
|
||||
__asm__ __volatile__ ( "pushl %%edx\n\t"
|
||||
"pushl %%eax\n\t"
|
||||
@@ -56,7 +57,7 @@ static uint64_t x86_readq ( volatile uint64_t *io_addr ) {
|
||||
*
|
||||
* This routine uses MMX instructions.
|
||||
*/
|
||||
static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
|
||||
static __unused void i386_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
|
||||
__asm__ __volatile__ ( "pushl %%edx\n\t"
|
||||
"pushl %%eax\n\t"
|
||||
"movq (%%esp), %%mm0\n\t"
|
||||
@@ -75,11 +76,9 @@ PROVIDE_IOAPI_INLINE ( x86, io_to_bus );
|
||||
PROVIDE_IOAPI_INLINE ( x86, readb );
|
||||
PROVIDE_IOAPI_INLINE ( x86, readw );
|
||||
PROVIDE_IOAPI_INLINE ( x86, readl );
|
||||
PROVIDE_IOAPI ( x86, readq, x86_readq );
|
||||
PROVIDE_IOAPI_INLINE ( x86, writeb );
|
||||
PROVIDE_IOAPI_INLINE ( x86, writew );
|
||||
PROVIDE_IOAPI_INLINE ( x86, writel );
|
||||
PROVIDE_IOAPI ( x86, writeq, x86_writeq );
|
||||
PROVIDE_IOAPI_INLINE ( x86, inb );
|
||||
PROVIDE_IOAPI_INLINE ( x86, inw );
|
||||
PROVIDE_IOAPI_INLINE ( x86, inl );
|
||||
@@ -94,3 +93,10 @@ PROVIDE_IOAPI_INLINE ( x86, outsw );
|
||||
PROVIDE_IOAPI_INLINE ( x86, outsl );
|
||||
PROVIDE_IOAPI_INLINE ( x86, iodelay );
|
||||
PROVIDE_IOAPI_INLINE ( x86, mb );
|
||||
#ifdef __x86_64__
|
||||
PROVIDE_IOAPI_INLINE ( x86, readq );
|
||||
PROVIDE_IOAPI_INLINE ( x86, writeq );
|
||||
#else
|
||||
PROVIDE_IOAPI ( x86, readq, i386_readq );
|
||||
PROVIDE_IOAPI ( x86, writeq, i386_writeq );
|
||||
#endif
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -34,7 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
void * __memcpy ( void *dest, const void *src, size_t len ) {
|
||||
void * __attribute__ (( noinline )) __memcpy ( void *dest, const void *src,
|
||||
size_t len ) {
|
||||
void *edi = dest;
|
||||
const void *esi = src;
|
||||
int discard_ecx;
|
||||
@@ -43,21 +45,146 @@ void * __memcpy ( void *dest, const void *src, size_t len ) {
|
||||
* moves. Using movsl rather than movsb speeds these up by
|
||||
* around 32%.
|
||||
*/
|
||||
if ( len >> 2 ) {
|
||||
__asm__ __volatile__ ( "rep movsl"
|
||||
: "=&D" ( edi ), "=&S" ( esi ),
|
||||
"=&c" ( discard_ecx )
|
||||
: "0" ( edi ), "1" ( esi ),
|
||||
"2" ( len >> 2 )
|
||||
: "memory" );
|
||||
}
|
||||
if ( len & 0x02 ) {
|
||||
__asm__ __volatile__ ( "movsw" : "=&D" ( edi ), "=&S" ( esi )
|
||||
: "0" ( edi ), "1" ( esi ) : "memory" );
|
||||
}
|
||||
if ( len & 0x01 ) {
|
||||
__asm__ __volatile__ ( "movsb" : "=&D" ( edi ), "=&S" ( esi )
|
||||
: "0" ( edi ), "1" ( esi ) : "memory" );
|
||||
}
|
||||
__asm__ __volatile__ ( "rep movsl"
|
||||
: "=&D" ( edi ), "=&S" ( esi ),
|
||||
"=&c" ( discard_ecx )
|
||||
: "0" ( edi ), "1" ( esi ), "2" ( len >> 2 )
|
||||
: "memory" );
|
||||
__asm__ __volatile__ ( "rep movsb"
|
||||
: "=&D" ( edi ), "=&S" ( esi ),
|
||||
"=&c" ( discard_ecx )
|
||||
: "0" ( edi ), "1" ( esi ), "2" ( len & 3 )
|
||||
: "memory" );
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy memory area backwards
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v src Source address
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
void * __attribute__ (( noinline )) __memcpy_reverse ( void *dest,
|
||||
const void *src,
|
||||
size_t len ) {
|
||||
void *edi = ( dest + len - 1 );
|
||||
const void *esi = ( src + len - 1 );
|
||||
int discard_ecx;
|
||||
|
||||
/* Assume memmove() is not performance-critical, and perform a
|
||||
* bytewise copy for simplicity.
|
||||
*/
|
||||
__asm__ __volatile__ ( "std\n\t"
|
||||
"rep movsb\n\t"
|
||||
"cld\n\t"
|
||||
: "=&D" ( edi ), "=&S" ( esi ),
|
||||
"=&c" ( discard_ecx )
|
||||
: "0" ( edi ), "1" ( esi ),
|
||||
"2" ( len )
|
||||
: "memory" );
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy (possibly overlapping) memory area
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v src Source address
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
void * __memmove ( void *dest, const void *src, size_t len ) {
|
||||
|
||||
if ( dest <= src ) {
|
||||
return __memcpy ( dest, src, len );
|
||||
} else {
|
||||
return __memcpy_reverse ( dest, src, len );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap memory areas
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v src Source address
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
void * memswap ( void *dest, void *src, size_t len ) {
|
||||
size_t discard_c;
|
||||
int discard;
|
||||
|
||||
__asm__ __volatile__ ( "\n1:\n\t"
|
||||
"dec %2\n\t"
|
||||
"js 2f\n\t"
|
||||
"movb (%0,%2), %b3\n\t"
|
||||
"xchgb (%1,%2), %b3\n\t"
|
||||
"movb %b3, (%0,%2)\n\t"
|
||||
"jmp 1b\n\t"
|
||||
"2:\n\t"
|
||||
: "=r" ( src ), "=r" ( dest ),
|
||||
"=&c" ( discard_c ), "=&q" ( discard )
|
||||
: "0" ( src ), "1" ( dest ), "2" ( len )
|
||||
: "memory" );
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate length of string
|
||||
*
|
||||
* @v string String
|
||||
* @ret len Length (excluding NUL)
|
||||
*/
|
||||
size_t strlen ( const char *string ) {
|
||||
const char *discard_D;
|
||||
size_t len_plus_one;
|
||||
|
||||
__asm__ __volatile__ ( "repne scasb\n\t"
|
||||
"not %1\n\t"
|
||||
: "=&D" ( discard_D ), "=&c" ( len_plus_one )
|
||||
: "0" ( string ), "1" ( -1UL ), "a" ( 0 ) );
|
||||
|
||||
return ( len_plus_one - 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare strings (up to a specified length)
|
||||
*
|
||||
* @v str1 First string
|
||||
* @v str2 Second string
|
||||
* @v len Maximum length
|
||||
* @ret diff Difference
|
||||
*/
|
||||
int strncmp ( const char *str1, const char *str2, size_t len ) {
|
||||
const void *discard_S;
|
||||
const void *discard_D;
|
||||
size_t discard_c;
|
||||
int diff;
|
||||
|
||||
__asm__ __volatile__ ( "\n1:\n\t"
|
||||
"dec %2\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"scasb\n\t"
|
||||
"jne 3f\n\t"
|
||||
"testb %b3, %b3\n\t"
|
||||
"jnz 1b\n\t"
|
||||
/* Equal */
|
||||
"\n2:\n\t"
|
||||
"xor %3, %3\n\t"
|
||||
"jmp 4f\n\t"
|
||||
/* Not equal; CF indicates difference */
|
||||
"\n3:\n\t"
|
||||
"sbb %3, %3\n\t"
|
||||
"orb $1, %b3\n\t"
|
||||
"\n4:\n\t"
|
||||
: "=&S" ( discard_S ), "=&D" ( discard_D ),
|
||||
"=&c" ( discard_c ), "=&a" ( diff )
|
||||
: "0" ( str1 ), "1" ( str2 ), "2" ( len ) );
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
169
src/arch/x86/core/x86_tcpip.c
Normal file
169
src/arch/x86/core/x86_tcpip.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* TCP/IP checksum
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <ipxe/tcpip.h>
|
||||
|
||||
extern char x86_tcpip_loop_end[];
|
||||
|
||||
/**
|
||||
* Calculate continued TCP/IP checkum
|
||||
*
|
||||
* @v partial Checksum of already-summed data, in network byte order
|
||||
* @v data Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret cksum Updated checksum, in network byte order
|
||||
*/
|
||||
uint16_t x86_tcpip_continue_chksum ( uint16_t partial,
|
||||
const void *data, size_t len ) {
|
||||
unsigned long sum = ( ( ~partial ) & 0xffff );
|
||||
unsigned long initial_word_count;
|
||||
unsigned long loop_count;
|
||||
unsigned long loop_partial_count;
|
||||
unsigned long final_word_count;
|
||||
unsigned long final_byte;
|
||||
unsigned long discard_S;
|
||||
unsigned long discard_c;
|
||||
unsigned long discard_a;
|
||||
unsigned long discard_r1;
|
||||
unsigned long discard_r2;
|
||||
|
||||
/* Calculate number of initial 16-bit words required to bring
|
||||
* the main loop into alignment. (We don't care about the
|
||||
* speed for data aligned to less than 16 bits, since this
|
||||
* situation won't occur in practice.)
|
||||
*/
|
||||
if ( len >= sizeof ( sum ) ) {
|
||||
initial_word_count = ( ( -( ( intptr_t ) data ) &
|
||||
( sizeof ( sum ) - 1 ) ) >> 1 );
|
||||
} else {
|
||||
initial_word_count = 0;
|
||||
}
|
||||
len -= ( initial_word_count * 2 );
|
||||
|
||||
/* Calculate number of iterations of the main loop. This loop
|
||||
* processes native machine words (32-bit or 64-bit), and is
|
||||
* unrolled 16 times. We calculate an overall iteration
|
||||
* count, and a starting point for the first iteration.
|
||||
*/
|
||||
loop_count = ( len / ( sizeof ( sum ) * 16 ) );
|
||||
loop_partial_count =
|
||||
( ( len % ( sizeof ( sum ) * 16 ) ) / sizeof ( sum ) );
|
||||
|
||||
/* Calculate number of 16-bit words remaining after the main
|
||||
* loop completes.
|
||||
*/
|
||||
final_word_count = ( ( len % sizeof ( sum ) ) / 2 );
|
||||
|
||||
/* Calculate whether or not a final byte remains at the end */
|
||||
final_byte = ( len & 1 );
|
||||
|
||||
/* Calculate the checksum */
|
||||
__asm__ ( /* Calculate position at which to jump into the
|
||||
* unrolled loop.
|
||||
*/
|
||||
"imul $( -x86_tcpip_loop_step_size ), %4\n\t"
|
||||
"add %5, %4\n\t"
|
||||
|
||||
/* Clear carry flag before starting checksumming */
|
||||
"clc\n\t"
|
||||
|
||||
/* Checksum initial words */
|
||||
"jmp 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"lodsw\n\t"
|
||||
"adcw %w2, %w0\n\t"
|
||||
"\n2:\n\t"
|
||||
"loop 1b\n\t"
|
||||
|
||||
/* Main "lods;adc" loop, unrolled x16 */
|
||||
"mov %12, %3\n\t"
|
||||
"jmp *%4\n\t"
|
||||
"\nx86_tcpip_loop_start:\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"lods%z2\n\tadc %2, %0\n\t"
|
||||
"\nx86_tcpip_loop_end:\n\t"
|
||||
"loop x86_tcpip_loop_start\n\t"
|
||||
".equ x86_tcpip_loop_step_size, "
|
||||
" ( ( x86_tcpip_loop_end - x86_tcpip_loop_start ) >> 4 )\n\t"
|
||||
|
||||
/* Checksum remaining whole words */
|
||||
"mov %13, %3\n\t"
|
||||
"jmp 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"lodsw\n\t"
|
||||
"adcw %w2, %w0\n\t"
|
||||
"\n2:\n\t"
|
||||
"loop 1b\n\t"
|
||||
|
||||
/* Checksum final byte if applicable */
|
||||
"mov %14, %3\n\t"
|
||||
"loop 1f\n\t"
|
||||
"adcb (%1), %b0\n\t"
|
||||
"adcb $0, %h0\n\t"
|
||||
"\n1:\n\t"
|
||||
|
||||
/* Fold down to a uint16_t */
|
||||
"push %0\n\t"
|
||||
"popw %w0\n\t"
|
||||
"popw %w2\n\t"
|
||||
"adcw %w2, %w0\n\t"
|
||||
#if ULONG_MAX > 0xffffffffUL /* 64-bit only */
|
||||
"popw %w2\n\t"
|
||||
"adcw %w2, %w0\n\t"
|
||||
"popw %w2\n\t"
|
||||
"adcw %w2, %w0\n\t"
|
||||
#endif /* 64-bit only */
|
||||
|
||||
/* Consume CF */
|
||||
"adcw $0, %w0\n\t"
|
||||
"adcw $0, %w0\n\t"
|
||||
|
||||
: "=&Q" ( sum ), "=&S" ( discard_S ), "=&a" ( discard_a ),
|
||||
"=&c" ( discard_c ), "=&r" ( discard_r1 ),
|
||||
"=&r" ( discard_r2 )
|
||||
: "0" ( sum ), "1" ( data ), "2" ( 0 ),
|
||||
"3" ( initial_word_count + 1 ), "4" ( loop_partial_count ),
|
||||
"5" ( x86_tcpip_loop_end ), "g" ( loop_count + 1 ),
|
||||
"g" ( final_word_count + 1 ), "g" ( final_byte ) );
|
||||
|
||||
return ( ~sum & 0xffff );
|
||||
}
|
||||
98
src/arch/x86/hci/commands/cpuid_cmd.c
Normal file
98
src/arch/x86/hci/commands/cpuid_cmd.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/cpuid.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* x86 CPU feature detection command
|
||||
*
|
||||
*/
|
||||
|
||||
/** "cpuid" options */
|
||||
struct cpuid_options {
|
||||
/** Check AMD-defined features (%eax=0x80000001) */
|
||||
int amd;
|
||||
/** Check features defined via %ecx */
|
||||
int ecx;
|
||||
};
|
||||
|
||||
/** "cpuid" option list */
|
||||
static struct option_descriptor cpuid_opts[] = {
|
||||
OPTION_DESC ( "ext", 'e', no_argument,
|
||||
struct cpuid_options, amd, parse_flag ),
|
||||
/* "--amd" retained for backwards compatibility */
|
||||
OPTION_DESC ( "amd", 'a', no_argument,
|
||||
struct cpuid_options, amd, parse_flag ),
|
||||
OPTION_DESC ( "ecx", 'c', no_argument,
|
||||
struct cpuid_options, ecx, parse_flag ),
|
||||
};
|
||||
|
||||
/** "cpuid" command descriptor */
|
||||
static struct command_descriptor cpuid_cmd =
|
||||
COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1,
|
||||
"[--ext] [--ecx] <bit>" );
|
||||
|
||||
/**
|
||||
* The "cpuid" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int cpuid_exec ( int argc, char **argv ) {
|
||||
struct cpuid_options opts;
|
||||
struct x86_features features;
|
||||
struct x86_feature_registers *feature_regs;
|
||||
uint32_t feature_reg;
|
||||
unsigned int bit;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &cpuid_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse bit number */
|
||||
if ( ( rc = parse_integer ( argv[optind], &bit ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Get CPU features */
|
||||
x86_features ( &features );
|
||||
|
||||
/* Extract relevant feature register */
|
||||
feature_regs = ( opts.amd ? &features.amd : &features.intel );
|
||||
feature_reg = ( opts.ecx ? feature_regs->ecx : feature_regs->edx );
|
||||
|
||||
/* Check presence of specified feature */
|
||||
return ( ( feature_reg & ( 1 << bit ) ) ? 0 : -ENOENT );
|
||||
}
|
||||
|
||||
/** x86 CPU feature detection command */
|
||||
struct command cpuid_command __command = {
|
||||
.name = "cpuid",
|
||||
.exec = cpuid_exec,
|
||||
};
|
||||
@@ -31,6 +31,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_com32 ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00080000 )
|
||||
#define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 )
|
||||
#define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 )
|
||||
#define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 )
|
||||
#define ERRFILE_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 )
|
||||
|
||||
#define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
|
||||
#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )
|
||||
@@ -38,8 +40,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_undionly ( ERRFILE_ARCH | ERRFILE_NET | 0x00030000 )
|
||||
#define ERRFILE_undirom ( ERRFILE_ARCH | ERRFILE_NET | 0x00040000 )
|
||||
|
||||
#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
|
||||
#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
|
||||
#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
|
||||
#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
|
||||
|
||||
#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/** @file
|
||||
*
|
||||
* i386-specific I/O API implementations
|
||||
* x86-specific I/O API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
#ifndef ETHERBOOT_BITS_STRING_H
|
||||
#define ETHERBOOT_BITS_STRING_H
|
||||
/*
|
||||
* Taken from Linux /usr/include/asm/string.h
|
||||
* All except memcpy, memmove, memset and memcmp removed.
|
||||
*
|
||||
* Non-standard memswap() function added because it saves quite a bit
|
||||
* of code (mbrown@fensystems.co.uk).
|
||||
*/
|
||||
#ifndef X86_BITS_STRING_H
|
||||
#define X86_BITS_STRING_H
|
||||
|
||||
/*
|
||||
* This string-include defines all string functions as inline
|
||||
* functions. Use gcc. It also assumes ds=es=data space, this should be
|
||||
* normal. Most of the string-functions are rather heavily hand-optimized,
|
||||
* see especially strtok,strstr,str[c]spn. They should work, but are not
|
||||
* very easy to understand. Everything is done entirely within the register
|
||||
* set, making the functions fast and clean. String instructions have been
|
||||
* used through-out, making for "slightly" unclear code :-)
|
||||
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* NO Copyright (C) 1991, 1992 Linus Torvalds,
|
||||
* consider these trivial functions to be PD.
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( PUBLIC_DOMAIN );
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Optimised string operations
|
||||
*
|
||||
*/
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
|
||||
extern void * __memcpy ( void *dest, const void *src, size_t len );
|
||||
extern void * __memcpy_reverse ( void *dest, const void *src, size_t len );
|
||||
|
||||
#if 0
|
||||
static inline __attribute__ (( always_inline )) void *
|
||||
__memcpy ( void *dest, const void *src, size_t len ) {
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__ ( "rep ; movsb"
|
||||
: "=&c" ( d0 ), "=&S" ( d1 ), "=&D" ( d2 )
|
||||
: "0" ( len ), "1" ( src ), "2" ( dest )
|
||||
: "memory" );
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copy memory area (where length is a compile-time constant)
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v src Source address
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void *
|
||||
__constant_memcpy ( void *dest, const void *src, size_t len ) {
|
||||
union {
|
||||
@@ -150,103 +152,81 @@ __constant_memcpy ( void *dest, const void *src, size_t len ) {
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define memcpy( dest, src, len ) \
|
||||
( __builtin_constant_p ( (len) ) ? \
|
||||
__constant_memcpy ( (dest), (src), (len) ) : \
|
||||
__memcpy ( (dest), (src), (len) ) )
|
||||
/**
|
||||
* Copy memory area
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v src Source address
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void *
|
||||
memcpy ( void *dest, const void *src, size_t len ) {
|
||||
if ( __builtin_constant_p ( len ) ) {
|
||||
return __constant_memcpy ( dest, src, len );
|
||||
} else {
|
||||
return __memcpy ( dest, src, len );
|
||||
}
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_MEMMOVE
|
||||
static inline void * memmove(void * dest,const void * src, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
if (dest<src)
|
||||
__asm__ __volatile__(
|
||||
"cld\n\t"
|
||||
"rep\n\t"
|
||||
"movsb"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
:"0" (n),"1" (src),"2" (dest)
|
||||
: "memory");
|
||||
else
|
||||
__asm__ __volatile__(
|
||||
"std\n\t"
|
||||
"rep\n\t"
|
||||
"movsb\n\t"
|
||||
"cld"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
:"0" (n),
|
||||
"1" (n-1+(const char *)src),
|
||||
"2" (n-1+(char *)dest)
|
||||
:"memory");
|
||||
return dest;
|
||||
|
||||
extern void * __memmove ( void *dest, const void *src, size_t len );
|
||||
|
||||
/**
|
||||
* Copy (possibly overlapping) memory area
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v src Source address
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void *
|
||||
memmove ( void *dest, const void *src, size_t len ) {
|
||||
ssize_t offset = ( dest - src );
|
||||
|
||||
if ( __builtin_constant_p ( offset ) ) {
|
||||
if ( offset <= 0 ) {
|
||||
return memcpy ( dest, src, len );
|
||||
} else {
|
||||
return __memcpy_reverse ( dest, src, len );
|
||||
}
|
||||
} else {
|
||||
return __memmove ( dest, src, len );
|
||||
}
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
static inline void * memset(void *s, int c,size_t count)
|
||||
{
|
||||
int d0, d1;
|
||||
__asm__ __volatile__(
|
||||
"cld\n\t"
|
||||
"rep\n\t"
|
||||
"stosb"
|
||||
: "=&c" (d0), "=&D" (d1)
|
||||
:"a" (c),"1" (s),"0" (count)
|
||||
:"memory");
|
||||
return s;
|
||||
|
||||
/**
|
||||
* Fill memory region
|
||||
*
|
||||
* @v dest Destination address
|
||||
* @v fill Fill pattern
|
||||
* @v len Length
|
||||
* @ret dest Destination address
|
||||
*/
|
||||
static inline void * memset ( void *dest, int fill, size_t len ) {
|
||||
void *discard_D;
|
||||
size_t discard_c;
|
||||
|
||||
__asm__ __volatile__ ( "rep stosb"
|
||||
: "=&D" ( discard_D ), "=&c" ( discard_c )
|
||||
: "0" ( dest ), "1" ( len ), "a" ( fill )
|
||||
: "memory" );
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_MEMSWAP
|
||||
static inline void * memswap(void *dest, void *src, size_t n)
|
||||
{
|
||||
long d0, d1, d2, d3;
|
||||
__asm__ __volatile__(
|
||||
"\n1:\t"
|
||||
"movb (%2),%%al\n\t"
|
||||
"xchgb (%1),%%al\n\t"
|
||||
"inc %1\n\t"
|
||||
"stosb\n\t"
|
||||
"loop 1b"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2), "=&a" (d3)
|
||||
: "0" (n), "1" (src), "2" (dest)
|
||||
: "memory" );
|
||||
return dest;
|
||||
}
|
||||
|
||||
extern void * memswap ( void *dest, void *src, size_t len );
|
||||
|
||||
#define __HAVE_ARCH_STRNCMP
|
||||
static inline int strncmp(const char * cs,const char * ct,size_t count)
|
||||
{
|
||||
register int __res;
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"1:\tdecl %3\n\t"
|
||||
"js 2f\n\t"
|
||||
"lodsb\n\t"
|
||||
"scasb\n\t"
|
||||
"jne 3f\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b\n"
|
||||
"2:\txorl %%eax,%%eax\n\t"
|
||||
"jmp 4f\n"
|
||||
"3:\tsbbl %%eax,%%eax\n\t"
|
||||
"orb $1,%%al\n"
|
||||
"4:"
|
||||
:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
|
||||
:"1" (cs),"2" (ct),"3" (count));
|
||||
return __res;
|
||||
}
|
||||
|
||||
extern int strncmp ( const char *str1, const char *str2, size_t len );
|
||||
|
||||
#define __HAVE_ARCH_STRLEN
|
||||
static inline size_t strlen(const char * s)
|
||||
{
|
||||
int d0;
|
||||
register int __res;
|
||||
__asm__ __volatile__(
|
||||
"repne\n\t"
|
||||
"scasb\n\t"
|
||||
"notl %0\n\t"
|
||||
"decl %0"
|
||||
:"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
|
||||
return __res;
|
||||
}
|
||||
|
||||
#endif /* ETHERBOOT_BITS_STRING_H */
|
||||
extern size_t strlen ( const char *string );
|
||||
|
||||
#endif /* X86_BITS_STRING_H */
|
||||
|
||||
17
src/arch/x86/include/bits/tcpip.h
Normal file
17
src/arch/x86/include/bits/tcpip.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _BITS_TCPIP_H
|
||||
#define _BITS_TCPIP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Transport-network layer interface
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
extern uint16_t x86_tcpip_continue_chksum ( uint16_t partial,
|
||||
const void *data, size_t len );
|
||||
|
||||
#define tcpip_continue_chksum x86_tcpip_continue_chksum
|
||||
|
||||
#endif /* _BITS_TCPIP_H */
|
||||
53
src/arch/x86/include/ipxe/cpuid.h
Normal file
53
src/arch/x86/include/ipxe/cpuid.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef _IPXE_CPUID_H
|
||||
#define _IPXE_CPUID_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* x86 CPU feature detection
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** An x86 CPU feature register set */
|
||||
struct x86_feature_registers {
|
||||
/** Features returned via %ecx */
|
||||
uint32_t ecx;
|
||||
/** Features returned via %edx */
|
||||
uint32_t edx;
|
||||
};
|
||||
|
||||
/** x86 CPU features */
|
||||
struct x86_features {
|
||||
/** Intel-defined features (%eax=0x00000001) */
|
||||
struct x86_feature_registers intel;
|
||||
/** AMD-defined features (%eax=0x80000001) */
|
||||
struct x86_feature_registers amd;
|
||||
};
|
||||
|
||||
/** CPUID support flag */
|
||||
#define CPUID_FLAG 0x00200000UL
|
||||
|
||||
/** Get vendor ID and largest standard function */
|
||||
#define CPUID_VENDOR_ID 0x00000000UL
|
||||
|
||||
/** Get standard features */
|
||||
#define CPUID_FEATURES 0x00000001UL
|
||||
|
||||
/** Get largest extended function */
|
||||
#define CPUID_AMD_MAX_FN 0x80000000UL
|
||||
|
||||
/** Extended function existence check */
|
||||
#define CPUID_AMD_CHECK 0x80000000UL
|
||||
|
||||
/** Extended function existence check mask */
|
||||
#define CPUID_AMD_CHECK_MASK 0xffff0000UL
|
||||
|
||||
/** Get extended features */
|
||||
#define CPUID_AMD_FEATURES 0x80000001UL
|
||||
|
||||
extern void x86_features ( struct x86_features *features );
|
||||
|
||||
#endif /* _IPXE_CPUID_H */
|
||||
@@ -5,14 +5,14 @@
|
||||
*
|
||||
* iPXE I/O API for x86
|
||||
*
|
||||
* i386 uses direct pointer dereferences for accesses to memory-mapped
|
||||
* x86 uses direct pointer dereferences for accesses to memory-mapped
|
||||
* I/O space, and the inX/outX instructions for accesses to
|
||||
* port-mapped I/O space.
|
||||
*
|
||||
* 64-bit atomic accesses (readq() and writeq()) use MMX instructions,
|
||||
* and will crash original Pentium and earlier CPUs. Fortunately, no
|
||||
* hardware that requires atomic 64-bit accesses will physically fit
|
||||
* into a machine with such an old CPU anyway.
|
||||
* 64-bit atomic accesses (readq() and writeq()) use MMX instructions
|
||||
* under i386, and will crash original Pentium and earlier CPUs.
|
||||
* Fortunately, no hardware that requires atomic 64-bit accesses will
|
||||
* physically fit into a machine with such an old CPU anyway.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
@@ -59,7 +59,7 @@ IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
|
||||
}
|
||||
|
||||
/*
|
||||
* MMIO reads and writes up to 32 bits
|
||||
* MMIO reads and writes up to native word size
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -71,6 +71,9 @@ IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
|
||||
X86_READX ( readb, uint8_t );
|
||||
X86_READX ( readw, uint16_t );
|
||||
X86_READX ( readl, uint32_t );
|
||||
#ifdef __x86_64__
|
||||
X86_READX ( readq, uint64_t );
|
||||
#endif
|
||||
|
||||
#define X86_WRITEX( _api_func, _type ) \
|
||||
static inline __always_inline void \
|
||||
@@ -81,6 +84,9 @@ IOAPI_INLINE ( x86, _api_func ) ( _type data, \
|
||||
X86_WRITEX ( writeb, uint8_t );
|
||||
X86_WRITEX ( writew, uint16_t );
|
||||
X86_WRITEX ( writel, uint32_t );
|
||||
#ifdef __x86_64__
|
||||
X86_WRITEX ( writeq, uint64_t );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PIO reads and writes up to 32 bits
|
||||
@@ -13,7 +13,8 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user