diff options
Diffstat (limited to 'gpxe/src/arch')
188 files changed, 0 insertions, 27771 deletions
diff --git a/gpxe/src/arch/i386/Makefile b/gpxe/src/arch/i386/Makefile deleted file mode 100644 index dd8da802..00000000 --- a/gpxe/src/arch/i386/Makefile +++ /dev/null @@ -1,117 +0,0 @@ -# Force i386-only instructions -# -CFLAGS += -march=i386 - -# Code size reduction. -# -CFLAGS += -fomit-frame-pointer - -# Code size reduction. -# -ifeq ($(CCTYPE),gcc) -CFLAGS += -fstrength-reduce -endif - -# Code size reduction. gcc3 needs a different syntax to gcc2 if you -# want to avoid spurious warnings. -# -ifeq ($(CCTYPE),gcc) -GCC_VERSION := $(subst ., ,$(shell $(CC) -dumpversion)) -GCC_MAJOR := $(firstword $(GCC_VERSION)) -ifeq ($(GCC_MAJOR),2) -CFLAGS += -malign-jumps=1 -malign-loops=1 -malign-functions=1 -else -CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1 -endif # gcc2 -endif # gcc - -# Code size reduction. This is almost always a win. The kernel uses -# it, too. -# -ifeq ($(CCTYPE),gcc) -CFLAGS += -mpreferred-stack-boundary=2 -endif - -# Code size reduction. Use regparm for all functions - C functions -# called from assembly (or vice versa) need __asmcall now -# -CFLAGS += -mregparm=3 - -# Code size reduction. Use -mrtd (same __asmcall requirements as above) -ifeq ($(CCTYPE),gcc) -CFLAGS += -mrtd -endif - -# Code size reduction. This is the logical complement to -mregparm=3. -# It doesn't currently buy us anything, but if anything ever tries to -# return small structures, let's be prepared -# -CFLAGS += -freg-struct-return - -# Force 32-bit code even on an x86-64 machine -# -CFLAGS += -m32 -ASFLAGS += --32 -ifeq ($(HOST_OS),FreeBSD) -LDFLAGS += -m elf_i386_fbsd -else -LDFLAGS += -m elf_i386 -endif - -# EFI requires -fshort-wchar, and nothing else currently uses wchar_t -# -CFLAGS += -fshort-wchar - -# We need to undefine the default macro "i386" when compiling .S -# files, otherwise ".arch i386" translates to ".arch 1"... -# -CFLAGS += -Ui386 - -# Locations of utilities -# -ISOLINUX_BIN = /usr/lib/syslinux/isolinux.bin - -# i386-specific directories containing source files -# -SRCDIRS += arch/i386/core arch/i386/transitions arch/i386/prefix -SRCDIRS += arch/i386/firmware/pcbios -SRCDIRS += arch/i386/image -SRCDIRS += arch/i386/drivers -SRCDIRS += arch/i386/drivers/net -SRCDIRS += arch/i386/interface/pcbios -SRCDIRS += arch/i386/interface/pxe -SRCDIRS += arch/i386/interface/pxeparent -SRCDIRS += arch/i386/interface/syslinux -SRCDIRS += arch/i386/hci/commands - -# The various xxx_loader.c files are #included into core/loader.c and -# should not be compiled directly. -# -NON_AUTO_SRCS += arch/i386/core/aout_loader.c -NON_AUTO_SRCS += arch/i386/core/freebsd_loader.c -NON_AUTO_SRCS += arch/i386/core/wince_loader.c - -# Include common x86 Makefile -# -MAKEDEPS += arch/x86/Makefile -include arch/x86/Makefile - -# Include platform-specific Makefile -# -MAKEDEPS += arch/i386/Makefile.$(PLATFORM) -include arch/i386/Makefile.$(PLATFORM) - -# Some suffixes (e.g. %.fd0) are generated directly from other -# finished files (e.g. %.dsk), rather than having their own prefix. - -# rule to write disk images to /dev/fd0 -NON_AUTO_MEDIA += fd0 -%fd0 : %dsk - $(QM)$(ECHO) " [DD] $@" - $(Q)dd if=$< bs=512 conv=sync of=/dev/fd0 - $(Q)sync - -# Add NON_AUTO_MEDIA to the media list, so that they show up in the -# output of "make" -# -MEDIA += $(NON_AUTO_MEDIA) diff --git a/gpxe/src/arch/i386/Makefile.efi b/gpxe/src/arch/i386/Makefile.efi deleted file mode 100644 index 8d651b04..00000000 --- a/gpxe/src/arch/i386/Makefile.efi +++ /dev/null @@ -1,10 +0,0 @@ -# -*- makefile -*- : Force emacs to use Makefile mode - -# Specify EFI image builder -# -ELF2EFI = $(ELF2EFI32) - -# Include generic EFI Makefile -# -MAKEDEPS += arch/x86/Makefile.efi -include arch/x86/Makefile.efi diff --git a/gpxe/src/arch/i386/Makefile.pcbios b/gpxe/src/arch/i386/Makefile.pcbios deleted file mode 100644 index e38fbca0..00000000 --- a/gpxe/src/arch/i386/Makefile.pcbios +++ /dev/null @@ -1,70 +0,0 @@ -# -*- makefile -*- : Force emacs to use Makefile mode - -# The i386 linker script -# -LDSCRIPT = arch/i386/scripts/i386.lds - -# Stop ld from complaining about our customised linker script -# -LDFLAGS += -N --no-check-sections - -# Media types. -# -MEDIA += rom -MEDIA += hrom -MEDIA += xrom -MEDIA += pxe -MEDIA += kpxe -MEDIA += kkpxe -MEDIA += lkrn -MEDIA += dsk -MEDIA += nbi -MEDIA += hd -MEDIA += raw - -# Padding rules -# -PAD_rom = $(PADIMG) --blksize=512 --byte=0xff $@ -PAD_hrom = $(PAD_rom) -PAD_xrom = $(PAD_rom) -PAD_dsk = $(PADIMG) --blksize=512 $@ -PAD_hd = $(PADIMG) --blksize=32768 $@ - -# rule to make a non-emulation ISO boot image -NON_AUTO_MEDIA += iso -%iso: %lkrn util/geniso - $(QM)$(ECHO) " [GENISO] $@" - $(Q)ISOLINUX_BIN=$(ISOLINUX_BIN) bash util/geniso $@ $< - -# rule to make a floppy emulation ISO boot image -NON_AUTO_MEDIA += liso -%liso: %lkrn util/genliso - $(QM)$(ECHO) " [GENLISO] $@" - $(Q)bash util/genliso $@ $< - -# rule to make a syslinux floppy image (mountable, bootable) -NON_AUTO_MEDIA += sdsk -%sdsk: %lkrn util/gensdsk - $(QM)$(ECHO) " [GENSDSK] $@" - $(Q)bash util/gensdsk $@ $< - -# Special target for building Master Boot Record binary -$(BIN)/mbr.bin : $(BIN)/mbr.o - $(QM)$(ECHO) " [OBJCOPY] $@" - $(Q)$(OBJCOPY) -O binary $< $@ - -# rule to make a USB disk image -$(BIN)/usbdisk.bin : $(BIN)/usbdisk.o - $(QM)$(ECHO) " [OBJCOPY] $@" - $(Q)$(OBJCOPY) -O binary $< $@ - -NON_AUTO_MEDIA += usb -%usb: $(BIN)/usbdisk.bin %hd - $(QM)$(ECHO) " [FINISH] $@" - $(Q)cat $^ > $@ - -# Padded floppy image (e.g. for iLO) -NON_AUTO_MEDIA += pdsk -%pdsk : %dsk - $(Q)cp $< $@ - $(Q)$(PADIMG) --blksize=1474560 $@ diff --git a/gpxe/src/arch/i386/README.i386 b/gpxe/src/arch/i386/README.i386 deleted file mode 100644 index b9b79cc4..00000000 --- a/gpxe/src/arch/i386/README.i386 +++ /dev/null @@ -1,197 +0,0 @@ -Etherboot/NILO i386 initialisation path and external call interface -=================================================================== - -1. Background - -GCC compiles 32-bit code. It is capable of producing -position-independent code, but the resulting binary is about 25% -bigger than the corresponding fixed-position code. Since one main use -of Etherboot is as firmware to be burned into an EPROM, code size must -be kept as small as possible. - -This means that we want to compile fixed-position code with GCC, and -link it to have a predetermined start address. The problem then is -that we must know the address that the code will be loaded to when it -runs. There are several ways to solve this: - -1. Pick an address, link the code with this start address, then make - sure that the code gets loaded at that location. This is - problematic, because we may pick an address that we later end up - wanting to use to load the operating system that we're booting. - -2. Pick an address, link the code with this start address, then set up - virtual addressing so that the virtual addresses match the - link-time addresses regardless of the real physical address that - the code is loaded to. This enables us to relocate Etherboot to - the top of high memory, where it will be out of the way of any - loading operating system. - -3. Link the code with a text start address of zero and a data start - address also of zero. Use 16-bit real mode and the - quasi-position-independence it gives you via segment addressing. - Doing this requires that we generate 16-bit code, rather than - 32-bit code, and restricts us to a maximum of 64kB in each segment. - -There are other possible approaches (e.g. including a relocation table -and code that performs standard dynamic relocation), but the three -options listed above are probably the best available. - -Etherboot can be invoked in a variety of ways (ROM, floppy, as a PXE -NBP, etc). Several of these ways involve control being passed to -Etherboot with the CPU in 16-bit real mode. Some will involve the CPU -being in 32-bit protected mode, and there's an outside chance that -some may involve the CPU being in 16-bit protected mode. We will -almost certainly have to effect a CPU mode change in order to reach -the mode we want to be in to execute the C code. - -Additionally, Etherboot may wish to call external routines, such as -BIOS interrupts, which must be called in 16-bit real mode. When -providing a PXE API, Etherboot must provide a mechanism for external -code to call it from 16-bit real mode. - -Not all i386 builds of Etherboot will want to make real-mode calls. -For example, when built for LinuxBIOS rather than the standard PCBIOS, -no real-mode calls are necessary. - -For the ultimate in PXE compatibility, we may want to build Etherboot -to run permanently in real mode. - -There is a wide variety of potential combinations of mode switches -that we may wish to implement. There are additional complications, -such as the inability to access a high-memory stack when running in -real mode. - -2. Transition libraries - -To handle all these various combinations of mode switches, we have -several "transition" libraries in Etherboot. We also have the concept -of an "internal" and an "external" environment. The internal -environment is the environment within which we can execute C code. -The external environment is the environment of whatever external code -we're trying to interface to, such as the system BIOS or a PXE NBP. - -As well as having a separate addressing scheme, the internal -environment also has a separate stack. - -The transition libraries are: - -a) librm - -librm handles transitions between an external 16-bit real-mode -environment and an internal 32-bit protected-mode environment with -virtual addresses. - -b) libkir - -libkir handles transitions between an external 16-bit real-mode (or -16:16 or 16:32 protected-mode) environment and an internal 16-bit -real-mode (or 16:16 protected-mode) environment. - -c) libpm - -libpm handles transitions between an external 32-bit protected-mode -environment with flat physical addresses and an internal 32-bit -protected-mode environment with virtual addresses. - -The transition libraries handle the transitions required when -Etherboot is started up for the first time, the transitions required -to execute any external code, and the transitions required when -Etherboot exits (if it exits). When Etherboot provides a PXE API, -they also handle the transitions required when a PXE client makes a -PXE API call to Etherboot. - -Etherboot may use multiple transition libraries. For example, an -Etherboot ELF image does not require librm for its initial transitions -from prefix to runtime, but may require librm for calling external -real-mode functions. - -3. Setup and initialisation - -Etherboot is conceptually divided into the prefix, the decompressor, -and the runtime image. (For non-compressed images, the decompressor -is a no-op.) The complete image comprises all three parts and is -distinct from the runtime image, which exclude the prefix and the -decompressor. - -The prefix does several tasks: - - Load the complete image into memory. (For example, the floppy - prefix issues BIOS calls to load the remainder of the complete image - from the floppy disk into RAM, and the ISA ROM prefix copies the ROM - contents into RAM for faster access.) - - Call the decompressor, if the runtime image is compressed. This - decompresses the runtime image. - - Call the runtime image's setup() routine. This is a routine - implemented in assembly code which sets up the internal environment - so that C code can execute. - - Call the runtime image's arch_initialise() routine. This is a - routine implemented in C which does some basic startup tasks, such - as initialising the console device, obtaining a memory map and - relocating the runtime image to high memory. - - Call the runtime image's arch_main() routine. This records the exit - mechanism requested by the prefix and calls main(). (The prefix - needs to register an exit mechanism because by the time main() - returns, the memory occupied by the prefix has most likely been - overwritten.) - -When acting as a PXE ROM, the ROM prefix contains an UNDI loader -routine in addition to its usual code. The UNDI loader performs a -similar sequence of steps: - - Load the complete image into memory. - - Call the decompressor. - - Call the runtime image's setup() routine. - - Call the runtime image's arch_initialise() routine. - - Call the runtime image's install_pxe_stack() routine. - - Return to caller. - -The runtime image's setup() routine will perform the following steps: - - Switch to the internal environment using an appropriate transition - library. This will record the parameters of the external - environment. - - Set up the internal environment: load a stack, and set up a GDT for - virtual addressing if virtual addressing is to be used. - - Switch back to the external environment using the transition - library. This will record the parameters of the internal - environment. - -Once the setup() routine has returned, the internal environment has been -set up ready for C code to run. The prefix can call C routines using -a function from the transition library. - -The runtime image's arch_initialise() routine will perform the -following steps: - - Zero the bss - - Initialise the console device(s) and print a welcome message. - - Obtain a memory map via the INT 15,E820 BIOS call or suitable - fallback mechanism. [not done if libkir is being used] - - Relocate the runtime image to the top of high memory. [not done if - libkir is being used] - - Install librm to base memory. [done only if librm is being used] - - Call initialise(). - - Return to the prefix, setting registers to indicate to the prefix - the new location of the transition library, if applicable. Which - registers these are is specific to the transition library being - used. - -Once the arch_initialise() routine has returned, the prefix will -probably call arch_main(). diff --git a/gpxe/src/arch/i386/core/aout_loader.c b/gpxe/src/arch/i386/core/aout_loader.c deleted file mode 100644 index f85620e9..00000000 --- a/gpxe/src/arch/i386/core/aout_loader.c +++ /dev/null @@ -1,144 +0,0 @@ -/* a.out */ -struct exec { - unsigned long a_midmag; /* flags<<26 | mid<<16 | magic */ - unsigned long a_text; /* text segment size */ - unsigned long a_data; /* initialized data size */ - unsigned long a_bss; /* uninitialized data size */ - unsigned long a_syms; /* symbol table size */ - unsigned long a_entry; /* entry point */ - unsigned long a_trsize; /* text relocation size */ - unsigned long a_drsize; /* data relocation size */ -}; - -struct aout_state { - struct exec head; - unsigned long curaddr; - int segment; /* current segment number, -1 for none */ - unsigned long loc; /* start offset of current block */ - unsigned long skip; /* padding to be skipped to current segment */ - unsigned long toread; /* remaining data to be read in the segment */ -}; - -static struct aout_state astate; - -static sector_t aout_download(unsigned char *data, unsigned int len, int eof); -static inline os_download_t aout_probe(unsigned char *data, unsigned int len) -{ - unsigned long start, mid, end, istart, iend; - if (len < sizeof(astate.head)) { - return 0; - } - memcpy(&astate.head, data, sizeof(astate.head)); - if ((astate.head.a_midmag & 0xffff) != 0x010BL) { - return 0; - } - - printf("(a.out"); - aout_freebsd_probe(); - printf(")... "); - /* Check the aout image */ - start = astate.head.a_entry; - mid = (((start + astate.head.a_text) + 4095) & ~4095) + astate.head.a_data; - end = ((mid + 4095) & ~4095) + astate.head.a_bss; - istart = 4096; - iend = istart + (mid - start); - if (!prep_segment(start, mid, end, istart, iend)) - return dead_download; - astate.segment = -1; - astate.loc = 0; - astate.skip = 0; - astate.toread = 0; - return aout_download; -} - -static sector_t aout_download(unsigned char *data, unsigned int len, int eof) -{ - unsigned int offset; /* working offset in the current data block */ - - offset = 0; - -#ifdef AOUT_LYNX_KDI - astate.segment++; - if (astate.segment == 0) { - astate.curaddr = 0x100000; - astate.head.a_entry = astate.curaddr + 0x20; - } - memcpy(phys_to_virt(astate.curaddr), data, len); - astate.curaddr += len; - return 0; -#endif - - do { - if (astate.segment != -1) { - if (astate.skip) { - if (astate.skip >= len - offset) { - astate.skip -= len - offset; - break; - } - offset += astate.skip; - astate.skip = 0; - } - - if (astate.toread) { - if (astate.toread >= len - offset) { - memcpy(phys_to_virt(astate.curaddr), data+offset, - len - offset); - astate.curaddr += len - offset; - astate.toread -= len - offset; - break; - } - memcpy(phys_to_virt(astate.curaddr), data+offset, astate.toread); - offset += astate.toread; - astate.toread = 0; - } - } - - /* Data left, but current segment finished - look for the next - * segment. This is quite simple for a.out files. */ - astate.segment++; - switch (astate.segment) { - case 0: - /* read text */ - astate.curaddr = astate.head.a_entry; - astate.skip = 4096; - astate.toread = astate.head.a_text; - break; - case 1: - /* read data */ - /* skip and curaddr may be wrong, but I couldn't find - * examples where this failed. There is no reasonable - * documentation for a.out available. */ - astate.skip = ((astate.curaddr + 4095) & ~4095) - astate.curaddr; - astate.curaddr = (astate.curaddr + 4095) & ~4095; - astate.toread = astate.head.a_data; - break; - case 2: - /* initialize bss and start kernel */ - astate.curaddr = (astate.curaddr + 4095) & ~4095; - astate.skip = 0; - astate.toread = 0; - memset(phys_to_virt(astate.curaddr), '\0', astate.head.a_bss); - goto aout_startkernel; - default: - break; - } - } while (offset < len); - - astate.loc += len; - - if (eof) { - unsigned long entry; - -aout_startkernel: - entry = astate.head.a_entry; - done(1); - - aout_freebsd_boot(); -#ifdef AOUT_LYNX_KDI - xstart32(entry); -#endif - printf("unexpected a.out variant\n"); - longjmp(restart_etherboot, -2); - } - return 0; -} diff --git a/gpxe/src/arch/i386/core/basemem_packet.c b/gpxe/src/arch/i386/core/basemem_packet.c deleted file mode 100644 index d487cce3..00000000 --- a/gpxe/src/arch/i386/core/basemem_packet.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * Packet buffer in base memory. Used by various components which - * need to pass packets to and from external real-mode code. - * - */ - -#include <basemem_packet.h> - -#undef basemem_packet -char __bss16_array ( basemem_packet, [BASEMEM_PACKET_LEN] ); diff --git a/gpxe/src/arch/i386/core/cpu.c b/gpxe/src/arch/i386/core/cpu.c deleted file mode 100644 index c24fa4e6..00000000 --- a/gpxe/src/arch/i386/core/cpu.c +++ /dev/null @@ -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 ); - } - } -} diff --git a/gpxe/src/arch/i386/core/dumpregs.c b/gpxe/src/arch/i386/core/dumpregs.c deleted file mode 100644 index 82dc2184..00000000 --- a/gpxe/src/arch/i386/core/dumpregs.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <stdio.h> -#include <realmode.h> - -void __asmcall _dump_regs ( struct i386_all_regs *ix86 ) { - - __asm__ __volatile__ ( - TEXT16_CODE ( ".globl dump_regs\n\t" - "\ndump_regs:\n\t" - "pushl $_dump_regs\n\t" - "pushw %%cs\n\t" - "call prot_call\n\t" - "addr32 leal 4(%%esp), %%esp\n\t" - "ret\n\t" ) : : ); - - printf ( "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" - "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" - "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", - ix86->regs.eax, ix86->regs.ebx, ix86->regs.ecx, - ix86->regs.edx, ix86->regs.esi, ix86->regs.edi, - ix86->regs.ebp, ix86->regs.esp, - ix86->segs.cs, ix86->segs.ss, ix86->segs.ds, - ix86->segs.es, ix86->segs.fs, ix86->segs.gs ); -} diff --git a/gpxe/src/arch/i386/core/freebsd_loader.c b/gpxe/src/arch/i386/core/freebsd_loader.c deleted file mode 100644 index 464f6d93..00000000 --- a/gpxe/src/arch/i386/core/freebsd_loader.c +++ /dev/null @@ -1,377 +0,0 @@ -/* bootinfo */ -#define BOOTINFO_VERSION 1 -#define NODEV (-1) /* non-existent device */ -#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */ -#define PAGE_SIZE (1<<PAGE_SHIFT) /* bytes/page */ -#define PAGE_MASK (PAGE_SIZE-1) -#define N_BIOS_GEOM 8 - -struct bootinfo { - unsigned int bi_version; - const unsigned char *bi_kernelname; - struct nfs_diskless *bi_nfs_diskless; - /* End of fields that are always present. */ -#define bi_endcommon bi_n_bios_used - unsigned int bi_n_bios_used; - unsigned long bi_bios_geom[N_BIOS_GEOM]; - unsigned int bi_size; - unsigned char bi_memsizes_valid; - unsigned char bi_pad[3]; - unsigned long bi_basemem; - unsigned long bi_extmem; - unsigned long bi_symtab; - unsigned long bi_esymtab; - /* Note that these are in the FreeBSD headers but were not here... */ - unsigned long bi_kernend; /* end of kernel space */ - unsigned long bi_envp; /* environment */ - unsigned long bi_modulep; /* preloaded modules */ -}; - -static struct bootinfo bsdinfo; - -#ifdef ELF_IMAGE -static Elf32_Shdr *shdr; /* To support the FreeBSD kludge! */ -static Address symtab_load; -static Address symstr_load; -static int symtabindex; -static int symstrindex; -#endif - -static enum { - Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD, -} image_type = Unknown; - -static unsigned int off; - - -#ifdef ELF_IMAGE -static void elf_freebsd_probe(void) -{ - image_type = Elf; - if ( (estate.e.elf32.e_entry & 0xf0000000) && - (estate.e.elf32.e_type == ET_EXEC)) - { - image_type = Elf_FreeBSD; - printf("/FreeBSD"); - off = -(estate.e.elf32.e_entry & 0xff000000); - estate.e.elf32.e_entry += off; - } - /* Make sure we have a null to start with... */ - shdr = 0; - - /* Clear the symbol index values... */ - symtabindex = -1; - symstrindex = -1; - - /* ...and the load addresses of the symbols */ - symtab_load = 0; - symstr_load = 0; -} - -static void elf_freebsd_fixup_segment(void) -{ - if (image_type == Elf_FreeBSD) { - estate.p.phdr32[estate.segment].p_paddr += off; - } -} - -static void elf_freebsd_find_segment_end(void) -{ - /* Count the bytes read even for the last block - * as we will need to know where the last block - * ends in order to load the symbols correctly. - * (plus it could be useful elsewhere...) - * Note that we need to count the actual size, - * not just the end of the disk image size. - */ - estate.curaddr += - (estate.p.phdr32[estate.segment].p_memsz - - estate.p.phdr32[estate.segment].p_filesz); -} - -static int elf_freebsd_debug_loader(unsigned int offset) -{ - /* No more segments to be loaded - time to start the - * nasty state machine to support the loading of - * FreeBSD debug symbols due to the fact that FreeBSD - * uses/exports the kernel's debug symbols in order - * to make much of the system work! Amazing (arg!) - * - * We depend on the fact that for the FreeBSD kernel, - * there is only one section of debug symbols and that - * the section is after all of the loaded sections in - * the file. This assumes a lot but is somewhat required - * to make this code not be too annoying. (Where do you - * load symbols when the code has not loaded yet?) - * Since this function is actually just a callback from - * the network data transfer code, we need to be able to - * work with the data as it comes in. There is no chance - * for doing a seek other than forwards. - * - * The process we use is to first load the section - * headers. Once they are loaded (shdr != 0) we then - * look for where the symbol table and symbol table - * strings are and setup some state that we found - * them and fall into processing the first one (which - * is the symbol table) and after that has been loaded, - * we try the symbol strings. Note that the order is - * actually required as the memory image depends on - * the symbol strings being loaded starting at the - * end of the symbol table. The kernel assumes this - * layout of the image. - * - * At any point, if we get to the end of the load file - * or the section requested is earlier in the file than - * the current file pointer, we just end up falling - * out of this and booting the kernel without this - * information. - */ - - /* Make sure that the next address is long aligned... */ - /* Assumes size of long is a power of 2... */ - estate.curaddr = (estate.curaddr + sizeof(long) - 1) & ~(sizeof(long) - 1); - - /* If we have not yet gotten the shdr loaded, try that */ - if (shdr == 0) - { - estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize; - estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset); - if (estate.toread) - { -#if ELF_DEBUG - printf("shdr *, size %lX, curaddr %lX\n", - estate.toread, estate.curaddr); -#endif - - /* Start reading at the curaddr and make that the shdr */ - shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr); - - /* Start to read... */ - return 1; - } - } - else - { - /* We have the shdr loaded, check if we have found - * the indexs where the symbols are supposed to be */ - if ((symtabindex == -1) && (symstrindex == -1)) - { - int i; - /* Make sure that the address is page aligned... */ - /* Symbols need to start in their own page(s)... */ - estate.curaddr = (estate.curaddr + 4095) & ~4095; - - /* Need to make new indexes... */ - for (i=0; i < estate.e.elf32.e_shnum; i++) - { - if (shdr[i].sh_type == SHT_SYMTAB) - { - int j; - for (j=0; j < estate.e.elf32.e_phnum; j++) - { - /* Check only for loaded sections */ - if ((estate.p.phdr32[j].p_type | 0x80) == (PT_LOAD | 0x80)) - { - /* Only the extra symbols */ - if ((shdr[i].sh_offset >= estate.p.phdr32[j].p_offset) && - ((shdr[i].sh_offset + shdr[i].sh_size) <= - (estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz))) - { - shdr[i].sh_offset=0; - shdr[i].sh_size=0; - break; - } - } - } - if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0)) - { - symtabindex = i; - symstrindex = shdr[i].sh_link; - } - } - } - } - - /* Check if we have a symbol table index and have not loaded it */ - if ((symtab_load == 0) && (symtabindex >= 0)) - { - /* No symbol table yet? Load it first... */ - - /* This happens to work out in a strange way. - * If we are past the point in the file already, - * we will skip a *large* number of bytes which - * ends up bringing us to the end of the file and - * an old (default) boot. Less code and lets - * the state machine work in a cleaner way but this - * is a nasty side-effect trick... */ - estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset); - - /* And we need to read this many bytes... */ - estate.toread = shdr[symtabindex].sh_size; - - if (estate.toread) - { -#if ELF_DEBUG - printf("db sym, size %lX, curaddr %lX\n", - estate.toread, estate.curaddr); -#endif - /* Save where we are loading this... */ - symtab_load = estate.curaddr; - - *((long *)phys_to_virt(estate.curaddr)) = estate.toread; - estate.curaddr += sizeof(long); - - /* Start to read... */ - return 1; - } - } - else if ((symstr_load == 0) && (symstrindex >= 0)) - { - /* We have already loaded the symbol table, so - * now on to the symbol strings... */ - - - /* Same nasty trick as above... */ - estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset); - - /* And we need to read this many bytes... */ - estate.toread = shdr[symstrindex].sh_size; - - if (estate.toread) - { -#if ELF_DEBUG - printf("db str, size %lX, curaddr %lX\n", - estate.toread, estate.curaddr); -#endif - /* Save where we are loading this... */ - symstr_load = estate.curaddr; - - *((long *)phys_to_virt(estate.curaddr)) = estate.toread; - estate.curaddr += sizeof(long); - - /* Start to read... */ - return 1; - } - } - } - /* all done */ - return 0; -} - -static void elf_freebsd_boot(unsigned long entry) -{ - if (image_type != Elf_FreeBSD) - return; - - memset(&bsdinfo, 0, sizeof(bsdinfo)); - bsdinfo.bi_basemem = meminfo.basememsize; - bsdinfo.bi_extmem = meminfo.memsize; - bsdinfo.bi_memsizes_valid = 1; - bsdinfo.bi_version = BOOTINFO_VERSION; - bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF); - bsdinfo.bi_nfs_diskless = NULL; - bsdinfo.bi_size = sizeof(bsdinfo); -#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */ - if(freebsd_kernel_env[0] != '\0'){ - freebsd_howto |= RB_BOOTINFO; - bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env; - } - - /* Check if we have symbols loaded, and if so, - * made the meta_data needed to pass those to - * the kernel. */ - if ((symtab_load !=0) && (symstr_load != 0)) - { - unsigned long *t; - - bsdinfo.bi_symtab = symtab_load; - - /* End of symbols (long aligned...) */ - /* Assumes size of long is a power of 2... */ - bsdinfo.bi_esymtab = (symstr_load + - sizeof(long) + - *((long *)phys_to_virt(symstr_load)) + - sizeof(long) - 1) & ~(sizeof(long) - 1); - - /* Where we will build the meta data... */ - t = phys_to_virt(bsdinfo.bi_esymtab); - -#if ELF_DEBUG - printf("Metadata at %lX\n",t); -#endif - - /* Set up the pointer to the memory... */ - bsdinfo.bi_modulep = virt_to_phys(t); - - /* The metadata structure is an array of 32-bit - * words where we store some information about the - * system. This is critical, as FreeBSD now looks - * only for the metadata for the extended symbol - * information rather than in the bootinfo. - */ - /* First, do the kernel name and the kernel type */ - /* Note that this assumed x86 byte order... */ - - /* 'kernel\0\0' */ - *t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65; - - /* 'elf kernel\0\0' */ - *t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65; - - /* Now the symbol start/end - note that they are - * here in local/physical address - the Kernel - * boot process will relocate the addresses. */ - *t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab; - *t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab; - - *t++=MODINFO_END; *t++=0; /* end of metadata */ - - /* Since we have symbols we need to make - * sure that the kernel knows its own end - * of memory... It is not _end but after - * the symbols and the metadata... */ - bsdinfo.bi_kernend = virt_to_phys(t); - - /* Signal locore.s that we have a valid bootinfo - * structure that was completely filled in. */ - freebsd_howto |= 0x80000000; - } - - xstart32(entry, freebsd_howto, NODEV, 0, 0, 0, - virt_to_phys(&bsdinfo), 0, 0, 0); - longjmp(restart_etherboot, -2); -} -#endif - -#ifdef AOUT_IMAGE -static void aout_freebsd_probe(void) -{ - image_type = Aout; - if (((astate.head.a_midmag >> 16) & 0xffff) == 0) { - /* Some other a.out variants have a different - * value, and use other alignments (e.g. 1K), - * not the 4K used by FreeBSD. */ - image_type = Aout_FreeBSD; - printf("/FreeBSD"); - off = -(astate.head.a_entry & 0xff000000); - astate.head.a_entry += off; - } -} - -static void aout_freebsd_boot(void) -{ - if (image_type == Aout_FreeBSD) { - memset(&bsdinfo, 0, sizeof(bsdinfo)); - bsdinfo.bi_basemem = meminfo.basememsize; - bsdinfo.bi_extmem = meminfo.memsize; - bsdinfo.bi_memsizes_valid = 1; - bsdinfo.bi_version = BOOTINFO_VERSION; - bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF); - bsdinfo.bi_nfs_diskless = NULL; - bsdinfo.bi_size = sizeof(bsdinfo); - xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0, - virt_to_phys(&bsdinfo), 0, 0, 0); - longjmp(restart_etherboot, -2); - } -} -#endif diff --git a/gpxe/src/arch/i386/core/gdbidt.S b/gpxe/src/arch/i386/core/gdbidt.S deleted file mode 100644 index cd8b38a9..00000000 --- a/gpxe/src/arch/i386/core/gdbidt.S +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Interrupt Descriptor Table (IDT) setup and interrupt handlers for GDB stub. - */ - -#include <librm.h> - -#define SIZEOF_I386_REGS 32 -#define SIZEOF_I386_FLAGS 4 - -/**************************************************************************** - * Interrupt Descriptor Table - **************************************************************************** - */ - .section ".data16", "aw", @progbits - .globl idtr -idtr: -idt_limit: - .word idt_length - 1 -idt_base: - .long 0 - -/* IDT entries have the following format: - * offset_lo, segment selector, flags, offset_hi - * - * Since it is not possible to specify relocations in arbitrary - * expressions like (int_overflow & 0xffff), we initialise the - * IDT with entries in an incorrect format. - * - * The entries are shuffled into the correct format in init_librm(). - */ -#define IDT_ENTRY_EMPTY(name) .word 0, 0, 0, 0 -#define IDT_ENTRY_PRESENT(name) \ - .long int_##name; \ - .word 0x8e00, VIRTUAL_CS - -.align 16 -idt: - IDT_ENTRY_PRESENT(divide_error) - IDT_ENTRY_PRESENT(debug_trap) - IDT_ENTRY_EMPTY(non_maskable_interrupt) - IDT_ENTRY_PRESENT(breakpoint) - IDT_ENTRY_PRESENT(overflow) - IDT_ENTRY_PRESENT(bound_range_exceeded) - IDT_ENTRY_PRESENT(invalid_opcode) - IDT_ENTRY_EMPTY(device_not_available) - IDT_ENTRY_PRESENT(double_fault) - IDT_ENTRY_EMPTY(coprocessor_segment_overrun) - IDT_ENTRY_PRESENT(invalid_tss) - IDT_ENTRY_PRESENT(segment_not_present) - IDT_ENTRY_PRESENT(stack_segment_fault) - IDT_ENTRY_PRESENT(general_protection) - IDT_ENTRY_PRESENT(page_fault) -idt_end: - .equ idt_length, idt_end - idt - -/* The IDT entries are fixed up (once) in init_librm() */ -idt_fixed: - .byte 0 - -/**************************************************************************** - * idt_init (real-mode near call, 16-bit real-mode near return address) - * - * Initialise the IDT, called from init_librm. - * - * Parameters: - * %eax : IDT base address - * - * Destroys %ax, %bx, and %di. - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 - .globl idt_init -idt_init: - movl %eax, idt_base - addl $idt, idt_base - - /* IDT entries are only fixed up once */ - movb idt_fixed, %al - orb %al, %al - jnz 2f - movb $1, idt_fixed - - /* Shuffle IDT entries into the correct format */ - movb $(idt_length / 8), %al - movw $idt, %bx - or %al, %al - jz 2f -1: - movw 2(%bx), %di - xchg %di, 6(%bx) - movw %di, 2(%bx) - addw $8, %bx - dec %al - jnz 1b -2: - ret - -/**************************************************************************** - * Interrupt handlers - **************************************************************************** - */ - .section ".text", "ax", @progbits - .code32 - -/* POSIX signal numbers for reporting traps to GDB */ -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGSEGV 11 -#define SIGSTKFLT 16 - -int_divide_error: - pushl $SIGFPE - jmp do_interrupt - -int_debug_trap: -int_breakpoint: - pushl $SIGTRAP - jmp do_interrupt - -int_overflow: -int_bound_range_exceeded: - pushl $SIGSTKFLT - jmp do_interrupt - -int_invalid_opcode: - pushl $SIGILL - jmp do_interrupt - -int_double_fault: - movl $SIGBUS, (%esp) - jmp do_interrupt - -int_invalid_tss: -int_segment_not_present: -int_stack_segment_fault: -int_general_protection: -int_page_fault: - movl $SIGSEGV, (%esp) - jmp do_interrupt - -/* When invoked, the stack contains: eflags, cs, eip, signo. */ -#define IH_OFFSET_GDB_REGS ( 0 ) -#define IH_OFFSET_GDB_EIP ( IH_OFFSET_GDB_REGS + SIZEOF_I386_REGS ) -#define IH_OFFSET_GDB_EFLAGS ( IH_OFFSET_GDB_EIP + 4 ) -#define IH_OFFSET_GDB_SEG_REGS ( IH_OFFSET_GDB_EFLAGS + SIZEOF_I386_FLAGS ) -#define IH_OFFSET_GDB_END ( IH_OFFSET_GDB_SEG_REGS + 6 * 4 ) -#define IH_OFFSET_SIGNO ( IH_OFFSET_GDB_END ) -#define IH_OFFSET_OLD_EIP ( IH_OFFSET_SIGNO + 4 ) -#define IH_OFFSET_OLD_CS ( IH_OFFSET_OLD_EIP + 4 ) -#define IH_OFFSET_OLD_EFLAGS ( IH_OFFSET_OLD_CS + 4 ) -#define IH_OFFSET_END ( IH_OFFSET_OLD_EFLAGS + 4 ) - -/* We also access the stack whilst still storing or restoring - * the register snapshot. Since ESP is in flux, we need - * special offsets. - */ -#define IH_OFFSET_FLUX_OLD_CS ( IH_OFFSET_OLD_CS - 44 ) -#define IH_OFFSET_FLUX_OLD_EFLAGS ( IH_OFFSET_OLD_EFLAGS - 40 ) -#define IH_OFFSET_FLUX_OLD_EIP ( IH_OFFSET_OLD_EIP - 36 ) -#define IH_OFFSET_FLUX_END ( IH_OFFSET_END - 20 ) -do_interrupt: - /* Store CPU state in GDB register snapshot */ - pushw $0 - pushw %gs - pushw $0 - pushw %fs - pushw $0 - pushw %es - pushw $0 - pushw %ds - pushw $0 - pushw %ss - pushw $0 - pushw IH_OFFSET_FLUX_OLD_CS + 2(%esp) - pushl IH_OFFSET_FLUX_OLD_EFLAGS(%esp) - pushl IH_OFFSET_FLUX_OLD_EIP(%esp) - pushl %edi - pushl %esi - pushl %ebp - leal IH_OFFSET_FLUX_END(%esp), %edi - pushl %edi /* old ESP */ - pushl %ebx - pushl %edx - pushl %ecx - pushl %eax - - /* Call GDB stub exception handler */ - pushl %esp - pushl (IH_OFFSET_SIGNO + 4)(%esp) - call gdbmach_handler - addl $8, %esp - - /* Restore CPU state from GDB register snapshot */ - popl %eax - popl %ecx - popl %edx - popl %ebx - addl $4, %esp /* Changing ESP currently not supported */ - popl %ebp - popl %esi - popl %edi - popl IH_OFFSET_FLUX_OLD_EIP(%esp) - popl IH_OFFSET_FLUX_OLD_EFLAGS(%esp) - popl IH_OFFSET_FLUX_OLD_CS(%esp) - popl %ss - popl %ds - popl %es - popl %fs - popl %gs - - addl $4, %esp /* drop signo */ - iret diff --git a/gpxe/src/arch/i386/core/gdbmach.c b/gpxe/src/arch/i386/core/gdbmach.c deleted file mode 100644 index 97827ecb..00000000 --- a/gpxe/src/arch/i386/core/gdbmach.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stddef.h> -#include <stdio.h> -#include <assert.h> -#include <gpxe/uaccess.h> -#include <gpxe/gdbstub.h> -#include <gdbmach.h> - -/** @file - * - * GDB architecture-specific bits for i386 - * - */ - -enum { - DR7_CLEAR = 0x00000400, /* disable hardware breakpoints */ - DR6_CLEAR = 0xffff0ff0, /* clear breakpoint status */ -}; - -/** Hardware breakpoint, fields stored in x86 bit pattern form */ -struct hwbp { - int type; /* type (1=write watchpoint, 3=access watchpoint) */ - unsigned long addr; /* linear address */ - size_t len; /* length (0=1-byte, 1=2-byte, 3=4-byte) */ - int enabled; -}; - -static struct hwbp hwbps [ 4 ]; -static gdbreg_t dr7 = DR7_CLEAR; - -static struct hwbp *gdbmach_find_hwbp ( int type, unsigned long addr, size_t len ) { - struct hwbp *available = NULL; - unsigned int i; - for ( i = 0; i < sizeof hwbps / sizeof hwbps [ 0 ]; i++ ) { - if ( hwbps [ i ].type == type && hwbps [ i ].addr == addr && hwbps [ i ].len == len ) { - return &hwbps [ i ]; - } - if ( !hwbps [ i ].enabled ) { - available = &hwbps [ i ]; - } - } - return available; -} - -static void gdbmach_commit_hwbp ( struct hwbp *bp ) { - unsigned int regnum = bp - hwbps; - - /* Set breakpoint address */ - assert ( regnum < ( sizeof hwbps / sizeof hwbps [ 0 ] ) ); - switch ( regnum ) { - case 0: - __asm__ __volatile__ ( "movl %0, %%dr0\n" : : "r" ( bp->addr ) ); - break; - case 1: - __asm__ __volatile__ ( "movl %0, %%dr1\n" : : "r" ( bp->addr ) ); - break; - case 2: - __asm__ __volatile__ ( "movl %0, %%dr2\n" : : "r" ( bp->addr ) ); - break; - case 3: - __asm__ __volatile__ ( "movl %0, %%dr3\n" : : "r" ( bp->addr ) ); - break; - } - - /* Set type */ - dr7 &= ~( 0x3 << ( 16 + 4 * regnum ) ); - dr7 |= bp->type << ( 16 + 4 * regnum ); - - /* Set length */ - dr7 &= ~( 0x3 << ( 18 + 4 * regnum ) ); - dr7 |= bp->len << ( 18 + 4 * regnum ); - - /* Set/clear local enable bit */ - dr7 &= ~( 0x3 << 2 * regnum ); - dr7 |= bp->enabled << 2 * regnum; -} - -int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ) { - struct hwbp *bp; - - /* Check and convert breakpoint type to x86 type */ - switch ( type ) { - case GDBMACH_WATCH: - type = 0x1; - break; - case GDBMACH_AWATCH: - type = 0x3; - break; - default: - return 0; /* unsupported breakpoint type */ - } - - /* Only lengths 1, 2, and 4 are supported */ - if ( len != 2 && len != 4 ) { - len = 1; - } - len--; /* convert to x86 breakpoint length bit pattern */ - - /* Calculate linear address by adding segment base */ - addr += virt_offset; - - /* Set up the breakpoint */ - bp = gdbmach_find_hwbp ( type, addr, len ); - if ( !bp ) { - return 0; /* ran out of hardware breakpoints */ - } - bp->type = type; - bp->addr = addr; - bp->len = len; - bp->enabled = enable; - gdbmach_commit_hwbp ( bp ); - return 1; -} - -static void gdbmach_disable_hwbps ( void ) { - /* Store and clear hardware breakpoints */ - __asm__ __volatile__ ( "movl %0, %%dr7\n" : : "r" ( DR7_CLEAR ) ); -} - -static void gdbmach_enable_hwbps ( void ) { - /* Clear breakpoint status register */ - __asm__ __volatile__ ( "movl %0, %%dr6\n" : : "r" ( DR6_CLEAR ) ); - - /* Restore hardware breakpoints */ - __asm__ __volatile__ ( "movl %0, %%dr7\n" : : "r" ( dr7 ) ); -} - -__asmcall void gdbmach_handler ( int signo, gdbreg_t *regs ) { - gdbmach_disable_hwbps(); - gdbstub_handler ( signo, regs ); - gdbmach_enable_hwbps(); -} diff --git a/gpxe/src/arch/i386/core/nulltrap.c b/gpxe/src/arch/i386/core/nulltrap.c deleted file mode 100644 index 3046fbec..00000000 --- a/gpxe/src/arch/i386/core/nulltrap.c +++ /dev/null @@ -1,51 +0,0 @@ -#include <stdint.h> -#include <stdio.h> - -__attribute__ (( noreturn, section ( ".text.null_trap" ) )) -void null_function_trap ( void ) { - void *stack; - - /* 128 bytes of NOPs; the idea of this is that if something - * dereferences a NULL pointer and overwrites us, we at least - * have some chance of still getting to execute the printf() - * statement. - */ - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - __asm__ __volatile__ ( "nop ; nop ; nop ; nop" ); - - __asm__ __volatile__ ( "movl %%esp, %0" : "=r" ( stack ) ); - printf ( "NULL method called from %p (stack %p)\n", - __builtin_return_address ( 0 ), stack ); - DBG_HD ( stack, 256 ); - while ( 1 ) {} -} diff --git a/gpxe/src/arch/i386/core/pic8259.c b/gpxe/src/arch/i386/core/pic8259.c deleted file mode 100644 index 1e2d23c5..00000000 --- a/gpxe/src/arch/i386/core/pic8259.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/io.h> -#include <pic8259.h> - -/** @file - * - * Minimal support for the 8259 Programmable Interrupt Controller - * - */ - -/** - * Send non-specific EOI(s) - * - * @v irq IRQ number - * - * This seems to be inherently unsafe. - */ -static inline void send_nonspecific_eoi ( unsigned int irq ) { - DBG ( "Sending non-specific EOI for IRQ %d\n", irq ); - if ( irq >= IRQ_PIC_CUTOFF ) { - outb ( ICR_EOI_NON_SPECIFIC, PIC2_ICR ); - } - outb ( ICR_EOI_NON_SPECIFIC, PIC1_ICR ); -} - -/** - * Send specific EOI(s) - * - * @v irq IRQ number - */ -static inline void send_specific_eoi ( unsigned int irq ) { - DBG ( "Sending specific EOI for IRQ %d\n", irq ); - if ( irq >= IRQ_PIC_CUTOFF ) { - outb ( ( ICR_EOI_SPECIFIC | ICR_VALUE ( CHAINED_IRQ ) ), - ICR_REG ( CHAINED_IRQ ) ); - } - outb ( ( ICR_EOI_SPECIFIC | ICR_VALUE ( irq ) ), ICR_REG ( irq ) ); -} - -/** - * Send End-Of-Interrupt to the PIC - * - * @v irq IRQ number - */ -void send_eoi ( unsigned int irq ) { - send_specific_eoi ( irq ); -} diff --git a/gpxe/src/arch/i386/core/rdtsc_timer.c b/gpxe/src/arch/i386/core/rdtsc_timer.c deleted file mode 100644 index 76679173..00000000 --- a/gpxe/src/arch/i386/core/rdtsc_timer.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** @file - * - * RDTSC timer - * - */ - -#include <assert.h> -#include <gpxe/timer.h> -#include <gpxe/timer2.h> - -/** - * Number of TSC ticks per microsecond - * - * This is calibrated on the first use of the timer. - */ -static unsigned long rdtsc_ticks_per_usec; - -/** - * Delay for a fixed number of microseconds - * - * @v usecs Number of microseconds for which to delay - */ -static void rdtsc_udelay ( unsigned long usecs ) { - unsigned long start; - unsigned long elapsed; - - /* Sanity guard, since we may divide by this */ - if ( ! usecs ) - usecs = 1; - - start = currticks(); - if ( rdtsc_ticks_per_usec ) { - /* Already calibrated; busy-wait until done */ - do { - elapsed = ( currticks() - start ); - } while ( elapsed < ( usecs * rdtsc_ticks_per_usec ) ); - } else { - /* Not yet calibrated; use timer2 and calibrate - * based on result. - */ - timer2_udelay ( usecs ); - elapsed = ( currticks() - start ); - rdtsc_ticks_per_usec = ( elapsed / usecs ); - DBG ( "RDTSC timer calibrated: %ld ticks in %ld usecs " - "(%ld MHz)\n", elapsed, usecs, - ( rdtsc_ticks_per_usec << TSC_SHIFT ) ); - } -} - -/** - * Get number of ticks per second - * - * @ret ticks_per_sec Number of ticks per second - */ -static unsigned long rdtsc_ticks_per_sec ( void ) { - - /* Calibrate timer, if not already done */ - if ( ! rdtsc_ticks_per_usec ) - udelay ( 1 ); - - /* Sanity check */ - assert ( rdtsc_ticks_per_usec != 0 ); - - return ( rdtsc_ticks_per_usec * 1000 * 1000 ); -} - -PROVIDE_TIMER ( rdtsc, udelay, rdtsc_udelay ); -PROVIDE_TIMER_INLINE ( rdtsc, currticks ); -PROVIDE_TIMER ( rdtsc, ticks_per_sec, rdtsc_ticks_per_sec ); diff --git a/gpxe/src/arch/i386/core/relocate.c b/gpxe/src/arch/i386/core/relocate.c deleted file mode 100644 index 44e764fe..00000000 --- a/gpxe/src/arch/i386/core/relocate.c +++ /dev/null @@ -1,170 +0,0 @@ -#include <gpxe/io.h> -#include <registers.h> -#include <gpxe/memmap.h> - -/* - * Originally by Eric Biederman - * - * Heavily modified by Michael Brown - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * The linker passes in the symbol _max_align, which is the alignment - * that we must preserve, in bytes. - * - */ -extern char _max_align[]; -#define max_align ( ( unsigned int ) _max_align ) - -/* Linker symbols */ -extern char _textdata[]; -extern char _etextdata[]; - -/* within 1MB of 4GB is too close. - * MAX_ADDR is the maximum address we can easily do DMA to. - * - * Not sure where this constraint comes from, but kept it from Eric's - * old code - mcb30 - */ -#define MAX_ADDR (0xfff00000UL) - -/** - * Relocate Etherboot - * - * @v ix86 x86 register dump from prefix - * @ret ix86 x86 registers to return to prefix - * - * This finds a suitable location for Etherboot near the top of 32-bit - * address space, and returns the physical address of the new location - * to the prefix in %edi. - */ -__asmcall void relocate ( struct i386_all_regs *ix86 ) { - struct memory_map memmap; - unsigned long start, end, size, padded_size; - unsigned long new_start, new_end; - unsigned i; - - /* Get memory map and current location */ - get_memmap ( &memmap ); - start = virt_to_phys ( _textdata ); - end = virt_to_phys ( _etextdata ); - size = ( end - start ); - padded_size = ( size + max_align - 1 ); - - DBG ( "Relocate: currently at [%lx,%lx)\n" - "...need %lx bytes for %d-byte alignment\n", - start, end, padded_size, max_align ); - - /* Walk through the memory map and find the highest address - * below 4GB that etherboot will fit into. Ensure etherboot - * lies entirely within a range with A20=0. This means that - * even if something screws up the state of the A20 line, the - * etherboot code is still visible and we have a chance to - * diagnose the problem. - */ - new_end = end; - for ( i = 0 ; i < memmap.count ; i++ ) { - struct memory_region *region = &memmap.regions[i]; - unsigned long r_start, r_end; - - DBG ( "Considering [%llx,%llx)\n", region->start, region->end); - - /* Truncate block to MAX_ADDR. This will be less than - * 4GB, which means that we can get away with using - * just 32-bit arithmetic after this stage. - */ - if ( region->start > MAX_ADDR ) { - DBG ( "...starts after MAX_ADDR=%lx\n", MAX_ADDR ); - continue; - } - r_start = region->start; - if ( region->end > MAX_ADDR ) { - DBG ( "...end truncated to MAX_ADDR=%lx\n", MAX_ADDR ); - r_end = MAX_ADDR; - } else { - r_end = region->end; - } - - /* Shrink the range down to use only even megabytes - * (i.e. A20=0). - */ - if ( ( r_end - 1 ) & 0x100000 ) { - /* If last byte that might be used (r_end-1) - * is in an odd megabyte, round down r_end to - * the top of the next even megabyte. - * - * Make sure that we don't accidentally wrap - * r_end below 0. - */ - if ( r_end >= 1 ) { - r_end = ( r_end - 1 ) & ~0xfffff; - DBG ( "...end truncated to %lx " - "(avoid ending in odd megabyte)\n", - r_end ); - } - } else if ( ( r_end - size ) & 0x100000 ) { - /* If the last byte that might be used - * (r_end-1) is in an even megabyte, but the - * first byte that might be used (r_end-size) - * is an odd megabyte, round down to the top - * of the next even megabyte. - * - * Make sure that we don't accidentally wrap - * r_end below 0. - */ - if ( r_end >= 0x100000 ) { - r_end = ( r_end - 0x100000 ) & ~0xfffff; - DBG ( "...end truncated to %lx " - "(avoid starting in odd megabyte)\n", - r_end ); - } - } - - DBG ( "...usable portion is [%lx,%lx)\n", r_start, r_end ); - - /* If we have rounded down r_end below r_ start, skip - * this block. - */ - if ( r_end < r_start ) { - DBG ( "...truncated to negative size\n" ); - continue; - } - - /* Check that there is enough space to fit in Etherboot */ - if ( ( r_end - r_start ) < size ) { - DBG ( "...too small (need %lx bytes)\n", size ); - continue; - } - - /* If the start address of the Etherboot we would - * place in this block is higher than the end address - * of the current highest block, use this block. - * - * Note that this avoids overlaps with the current - * Etherboot, as well as choosing the highest of all - * viable blocks. - */ - if ( ( r_end - size ) > new_end ) { - new_end = r_end; - DBG ( "...new best block found.\n" ); - } - } - - /* Calculate new location of Etherboot, and align it to the - * required alignemnt. - */ - new_start = new_end - padded_size; - new_start += ( start - new_start ) & ( max_align - 1 ); - new_end = new_start + size; - - DBG ( "Relocating from [%lx,%lx) to [%lx,%lx)\n", - start, end, new_start, new_end ); - - /* Let prefix know what to copy */ - ix86->regs.esi = start; - ix86->regs.edi = new_start; - ix86->regs.ecx = size; -} diff --git a/gpxe/src/arch/i386/core/setjmp.S b/gpxe/src/arch/i386/core/setjmp.S deleted file mode 100644 index 03727148..00000000 --- a/gpxe/src/arch/i386/core/setjmp.S +++ /dev/null @@ -1,42 +0,0 @@ -/* setjmp and longjmp. Use of these functions is deprecated. */ - -FILE_LICENCE ( GPL2_OR_LATER ) - - .text - .arch i386 - .code32 - -/************************************************************************** -SETJMP - Save stack context for non-local goto -**************************************************************************/ - .globl setjmp -setjmp: - movl 4(%esp),%ecx /* jmpbuf */ - movl 0(%esp),%edx /* return address */ - movl %edx,0(%ecx) - movl %ebx,4(%ecx) - movl %esp,8(%ecx) - movl %ebp,12(%ecx) - movl %esi,16(%ecx) - movl %edi,20(%ecx) - movl $0,%eax - ret - -/************************************************************************** -LONGJMP - Non-local jump to a saved stack context -**************************************************************************/ - .globl longjmp -longjmp: - movl 4(%esp),%edx /* jumpbuf */ - movl 8(%esp),%eax /* result */ - movl 0(%edx),%ecx - movl 4(%edx),%ebx - movl 8(%edx),%esp - movl 12(%edx),%ebp - movl 16(%edx),%esi - movl 20(%edx),%edi - cmpl $0,%eax - jne 1f - movl $1,%eax -1: movl %ecx,0(%esp) - ret diff --git a/gpxe/src/arch/i386/core/stack.S b/gpxe/src/arch/i386/core/stack.S deleted file mode 100644 index 737ec0ee..00000000 --- a/gpxe/src/arch/i386/core/stack.S +++ /dev/null @@ -1,15 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ) - - .arch i386 - -/**************************************************************************** - * Internal stack - **************************************************************************** - */ - .section ".stack", "aw", @nobits - .align 8 - .globl _stack -_stack: - .space 4096 - .globl _estack -_estack: diff --git a/gpxe/src/arch/i386/core/stack16.S b/gpxe/src/arch/i386/core/stack16.S deleted file mode 100644 index 523f0288..00000000 --- a/gpxe/src/arch/i386/core/stack16.S +++ /dev/null @@ -1,15 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ) - - .arch i386 - -/**************************************************************************** - * Internal stack - **************************************************************************** - */ - .section ".stack16", "aw", @nobits - .align 8 - .globl _stack16 -_stack16: - .space 4096 - .globl _estack16 -_estack16: diff --git a/gpxe/src/arch/i386/core/timer2.c b/gpxe/src/arch/i386/core/timer2.c deleted file mode 100644 index 6e76b2eb..00000000 --- a/gpxe/src/arch/i386/core/timer2.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * arch/i386/core/i386_timer.c - * - * Use the "System Timer 2" to implement the udelay callback in - * the BIOS timer driver. Also used to calibrate the clock rate - * in the RTDSC timer driver. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2, or (at - * your option) any later version. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stddef.h> -#include <gpxe/timer2.h> -#include <gpxe/io.h> - -/* Timers tick over at this rate */ -#define TIMER2_TICKS_PER_SEC 1193180U - -/* Parallel Peripheral Controller Port B */ -#define PPC_PORTB 0x61 - -/* Meaning of the port bits */ -#define PPCB_T2OUT 0x20 /* Bit 5 */ -#define PPCB_SPKR 0x02 /* Bit 1 */ -#define PPCB_T2GATE 0x01 /* Bit 0 */ - -/* Ports for the 8254 timer chip */ -#define TIMER2_PORT 0x42 -#define TIMER_MODE_PORT 0x43 - -/* Meaning of the mode bits */ -#define TIMER0_SEL 0x00 -#define TIMER1_SEL 0x40 -#define TIMER2_SEL 0x80 -#define READBACK_SEL 0xC0 - -#define LATCH_COUNT 0x00 -#define LOBYTE_ACCESS 0x10 -#define HIBYTE_ACCESS 0x20 -#define WORD_ACCESS 0x30 - -#define MODE0 0x00 -#define MODE1 0x02 -#define MODE2 0x04 -#define MODE3 0x06 -#define MODE4 0x08 -#define MODE5 0x0A - -#define BINARY_COUNT 0x00 -#define BCD_COUNT 0x01 - -static void load_timer2 ( unsigned int ticks ) { - /* - * Now let's take care of PPC channel 2 - * - * Set the Gate high, program PPC channel 2 for mode 0, - * (interrupt on terminal count mode), binary count, - * load 5 * LATCH count, (LSB and MSB) to begin countdown. - * - * Note some implementations have a bug where the high bits byte - * of channel 2 is ignored. - */ - /* Set up the timer gate, turn off the speaker */ - /* Set the Gate high, disable speaker */ - outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB); - /* binary, mode 0, LSB/MSB, Ch 2 */ - outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT); - /* LSB of ticks */ - outb(ticks & 0xFF, TIMER2_PORT); - /* MSB of ticks */ - outb(ticks >> 8, TIMER2_PORT); -} - -static int timer2_running ( void ) { - return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0); -} - -void timer2_udelay ( unsigned long usecs ) { - load_timer2 ( ( usecs * TIMER2_TICKS_PER_SEC ) / ( 1000 * 1000 ) ); - while (timer2_running()) { - /* Do nothing */ - } -} diff --git a/gpxe/src/arch/i386/core/video_subr.c b/gpxe/src/arch/i386/core/video_subr.c deleted file mode 100644 index c821cd02..00000000 --- a/gpxe/src/arch/i386/core/video_subr.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * modified from linuxbios code - * by Cai Qiang <rimy2000@hotmail.com> - * - */ - -#include "stddef.h" -#include "string.h" -#include <gpxe/io.h> -#include "console.h" -#include <gpxe/init.h> -#include "vga.h" - -struct console_driver vga_console; - -static char *vidmem; /* The video buffer */ -static int video_line, video_col; - -#define VIDBUFFER 0xB8000 - -static void memsetw(void *s, int c, unsigned int n) -{ - unsigned int i; - u16 *ss = (u16 *) s; - - for (i = 0; i < n; i++) { - ss[i] = ( u16 ) c; - } -} - -static void video_init(void) -{ - static int inited=0; - - vidmem = (char *)phys_to_virt(VIDBUFFER); - - if (!inited) { - video_line = 0; - video_col = 0; - - memsetw(vidmem, VGA_ATTR_CLR_WHT, 2*1024); // - - inited=1; - } -} - -static void video_scroll(void) -{ - int i; - - memcpy(vidmem, vidmem + COLS * 2, (LINES - 1) * COLS * 2); - for (i = (LINES - 1) * COLS * 2; i < LINES * COLS * 2; i += 2) - vidmem[i] = ' '; -} - -static void vga_putc(int byte) -{ - if (byte == '\n') { - video_line++; - video_col = 0; - - } else if (byte == '\r') { - video_col = 0; - - } else if (byte == '\b') { - video_col--; - - } else if (byte == '\t') { - video_col += 4; - - } else if (byte == '\a') { - //beep - //beep(500); - - } else { - vidmem[((video_col + (video_line *COLS)) * 2)] = byte; - vidmem[((video_col + (video_line *COLS)) * 2) +1] = VGA_ATTR_CLR_WHT; - video_col++; - } - if (video_col < 0) { - video_col = 0; - } - if (video_col >= COLS) { - video_line++; - video_col = 0; - } - if (video_line >= LINES) { - video_scroll(); - video_line--; - } - // move the cursor - write_crtc((video_col + (video_line *COLS)) >> 8, CRTC_CURSOR_HI); - write_crtc((video_col + (video_line *COLS)) & 0x0ff, CRTC_CURSOR_LO); -} - -struct console_driver vga_console __console_driver = { - .putchar = vga_putc, - .disabled = 1, -}; - -struct init_fn video_init_fn __init_fn ( INIT_EARLY ) = { - .initialise = video_init, -}; diff --git a/gpxe/src/arch/i386/core/virtaddr.S b/gpxe/src/arch/i386/core/virtaddr.S deleted file mode 100644 index aae1e1ed..00000000 --- a/gpxe/src/arch/i386/core/virtaddr.S +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Functions to support the virtual addressing method of relocation - * that Etherboot uses. - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -#include "librm.h" - - .arch i386 - .text - .code32 - -/**************************************************************************** - * _virt_to_phys (virtual addressing) - * - * Switch from virtual to flat physical addresses. %esp is adjusted - * to a physical value. Segment registers are set to flat physical - * selectors. All other registers are preserved. Flags are - * preserved. - * - * Parameters: none - * Returns: none - **************************************************************************** - */ - .globl _virt_to_phys -_virt_to_phys: - /* Preserve registers and flags */ - pushfl - pushl %eax - pushl %ebp - - /* Change return address to a physical address */ - movl virt_offset, %ebp - addl %ebp, 12(%esp) - - /* Switch to physical code segment */ - pushl $PHYSICAL_CS - leal 1f(%ebp), %eax - pushl %eax - lret -1: - /* Reload other segment registers and adjust %esp */ - movl $PHYSICAL_DS, %eax - movl %eax, %ds - movl %eax, %es - movl %eax, %fs - movl %eax, %gs - movl %eax, %ss - addl %ebp, %esp - - /* Restore registers and flags, and return */ - popl %ebp - popl %eax - popfl - ret - -/**************************************************************************** - * _phys_to_virt (flat physical addressing) - * - * Switch from flat physical to virtual addresses. %esp is adjusted - * to a virtual value. Segment registers are set to virtual - * selectors. All other registers are preserved. Flags are - * preserved. - * - * Note that this depends on the GDT already being correctly set up - * (e.g. by a call to run_here()). - * - * Parameters: none - * Returns: none - **************************************************************************** - */ - .globl _phys_to_virt -_phys_to_virt: - /* Preserve registers and flags */ - pushfl - pushl %eax - pushl %ebp - - /* Switch to virtual code segment */ - ljmp $VIRTUAL_CS, $1f -1: - /* Reload data segment registers */ - movl $VIRTUAL_DS, %eax - movl %eax, %ds - movl %eax, %es - movl %eax, %fs - movl %eax, %gs - - /* Reload stack segment and adjust %esp */ - movl virt_offset, %ebp - movl %eax, %ss - subl %ebp, %esp - - /* Change the return address to a virtual address */ - subl %ebp, 12(%esp) - - /* Restore registers and flags, and return */ - popl %ebp - popl %eax - popfl - ret diff --git a/gpxe/src/arch/i386/core/wince_loader.c b/gpxe/src/arch/i386/core/wince_loader.c deleted file mode 100644 index f452b659..00000000 --- a/gpxe/src/arch/i386/core/wince_loader.c +++ /dev/null @@ -1,273 +0,0 @@ -#define LOAD_DEBUG 0 - -static int get_x_header(unsigned char *data, unsigned long now); -static void jump_2ep(); -static unsigned char ce_signature[] = {'B', '0', '0', '0', 'F', 'F', '\n',}; -static char ** ep; - -#define BOOT_ARG_PTR_LOCATION 0x001FFFFC - -typedef struct _BOOT_ARGS{ - unsigned char ucVideoMode; - unsigned char ucComPort; - unsigned char ucBaudDivisor; - unsigned char ucPCIConfigType; - - unsigned long dwSig; - #define BOOTARG_SIG 0x544F4F42 - unsigned long dwLen; - - unsigned char ucLoaderFlags; - unsigned char ucEshellFlags; - unsigned char ucEdbgAdapterType; - unsigned char ucEdbgIRQ; - - unsigned long dwEdbgBaseAddr; - unsigned long dwEdbgDebugZone; - unsigned long dwDHCPLeaseTime; - unsigned long dwEdbgFlags; - - unsigned long dwEBootFlag; - unsigned long dwEBootAddr; - unsigned long dwLaunchAddr; - - unsigned long pvFlatFrameBuffer; - unsigned short vesaMode; - unsigned short cxDisplayScreen; - unsigned short cyDisplayScreen; - unsigned short cxPhysicalScreen; - unsigned short cyPhysicalScreen; - unsigned short cbScanLineLength; - unsigned short bppScreen; - - unsigned char RedMaskSize; - unsigned char REdMaskPosition; - unsigned char GreenMaskSize; - unsigned char GreenMaskPosition; - unsigned char BlueMaskSize; - unsigned char BlueMaskPosition; -} BOOT_ARGS; - -BOOT_ARGS BootArgs; - -static struct segment_info{ - unsigned long addr; // Section Address - unsigned long size; // Section Size - unsigned long checksum; // Section CheckSum -} X; - -#define PSIZE (1500) //Max Packet Size -#define DSIZE (PSIZE+12) -static unsigned long dbuffer_available =0; -static unsigned long not_loadin =0; -static unsigned long d_now =0; - -unsigned long entry; -static unsigned long ce_curaddr; - - -static sector_t ce_loader(unsigned char *data, unsigned int len, int eof); -static os_download_t wince_probe(unsigned char *data, unsigned int len) -{ - if (strncmp(ce_signature, data, sizeof(ce_signature)) != 0) { - return 0; - } - printf("(WINCE)"); - return ce_loader; -} - -static sector_t ce_loader(unsigned char *data, unsigned int len, int eof) -{ - static unsigned char dbuffer[DSIZE]; - int this_write = 0; - static int firsttime = 1; - - /* - * new packet in, we have to - * [1] copy data to dbuffer, - * - * update... - * [2] dbuffer_available - */ - memcpy( (dbuffer+dbuffer_available), data, len); //[1] - dbuffer_available += len; // [2] - len = 0; - - d_now = 0; - -#if 0 - printf("dbuffer_available =%ld \n", dbuffer_available); -#endif - - if (firsttime) - { - d_now = sizeof(ce_signature); - printf("String Physical Address = %lx \n", - *(unsigned long *)(dbuffer+d_now)); - - d_now += sizeof(unsigned long); - printf("Image Size = %ld [%lx]\n", - *(unsigned long *)(dbuffer+d_now), - *(unsigned long *)(dbuffer+d_now)); - - d_now += sizeof(unsigned long); - dbuffer_available -= d_now; - - d_now = (unsigned long)get_x_header(dbuffer, d_now); - firsttime = 0; - } - - if (not_loadin == 0) - { - d_now = get_x_header(dbuffer, d_now); - } - - while ( not_loadin > 0 ) - { - /* dbuffer do not have enough data to loading, copy all */ -#if LOAD_DEBUG - printf("[0] not_loadin = [%ld], dbuffer_available = [%ld] \n", - not_loadin, dbuffer_available); - printf("[0] d_now = [%ld] \n", d_now); -#endif - - if( dbuffer_available <= not_loadin) - { - this_write = dbuffer_available ; - memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write ); - ce_curaddr += this_write; - not_loadin -= this_write; - - /* reset index and available in the dbuffer */ - dbuffer_available = 0; - d_now = 0; -#if LOAD_DEBUG - printf("[1] not_loadin = [%ld], dbuffer_available = [%ld] \n", - not_loadin, dbuffer_available); - printf("[1] d_now = [%ld], this_write = [%d] \n", - d_now, this_write); -#endif - - // get the next packet... - return (0); - } - - /* dbuffer have more data then loading ... , copy partital.... */ - else - { - this_write = not_loadin; - memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write); - ce_curaddr += this_write; - not_loadin = 0; - - /* reset index and available in the dbuffer */ - dbuffer_available -= this_write; - d_now += this_write; -#if LOAD_DEBUG - printf("[2] not_loadin = [%ld], dbuffer_available = [%ld] \n", - not_loadin, dbuffer_available); - printf("[2] d_now = [%ld], this_write = [%d] \n\n", - d_now, this_write); -#endif - - /* dbuffer not empty, proceed processing... */ - - // don't have enough data to get_x_header.. - if ( dbuffer_available < (sizeof(unsigned long) * 3) ) - { -// printf("we don't have enough data remaining to call get_x. \n"); - memcpy( (dbuffer+0), (dbuffer+d_now), dbuffer_available); - return (0); - } - else - { -#if LOAD_DEBUG - printf("with remaining data to call get_x \n"); - printf("dbuffer available = %ld , d_now = %ld\n", - dbuffer_available, d_now); -#endif - d_now = get_x_header(dbuffer, d_now); - } - } - } - return (0); -} - -static int get_x_header(unsigned char *dbuffer, unsigned long now) -{ - X.addr = *(unsigned long *)(dbuffer + now); - X.size = *(unsigned long *)(dbuffer + now + sizeof(unsigned long)); - X.checksum = *(unsigned long *)(dbuffer + now + sizeof(unsigned long)*2); - - if (X.addr == 0) - { - entry = X.size; - done(1); - printf("Entry Point Address = [%lx] \n", entry); - jump_2ep(); - } - - if (!prep_segment(X.addr, X.addr + X.size, X.addr + X.size, 0, 0)) { - longjmp(restart_etherboot, -2); - } - - ce_curaddr = X.addr; - now += sizeof(unsigned long)*3; - - /* re-calculate dbuffer available... */ - dbuffer_available -= sizeof(unsigned long)*3; - - /* reset index of this section */ - not_loadin = X.size; - -#if 1 - printf("\n"); - printf("\t Section Address = [%lx] \n", X.addr); - printf("\t Size = %d [%lx]\n", X.size, X.size); - printf("\t Checksum = %ld [%lx]\n", X.checksum, X.checksum); -#endif -#if LOAD_DEBUG - printf("____________________________________________\n"); - printf("\t dbuffer_now = %ld \n", now); - printf("\t dbuffer available = %ld \n", dbuffer_available); - printf("\t not_loadin = %ld \n", not_loadin); -#endif - - return now; -} - -static void jump_2ep() -{ - BootArgs.ucVideoMode = 1; - BootArgs.ucComPort = 1; - BootArgs.ucBaudDivisor = 1; - BootArgs.ucPCIConfigType = 1; // do not fill with 0 - - BootArgs.dwSig = BOOTARG_SIG; - BootArgs.dwLen = sizeof(BootArgs); - - if(BootArgs.ucVideoMode == 0) - { - BootArgs.cxDisplayScreen = 640; - BootArgs.cyDisplayScreen = 480; - BootArgs.cxPhysicalScreen = 640; - BootArgs.cyPhysicalScreen = 480; - BootArgs.bppScreen = 16; - BootArgs.cbScanLineLength = 1024; - BootArgs.pvFlatFrameBuffer = 0x800a0000; // ollie say 0x98000000 - } - else if(BootArgs.ucVideoMode != 0xFF) - { - BootArgs.cxDisplayScreen = 0; - BootArgs.cyDisplayScreen = 0; - BootArgs.cxPhysicalScreen = 0; - BootArgs.cyPhysicalScreen = 0; - BootArgs.bppScreen = 0; - BootArgs.cbScanLineLength = 0; - BootArgs.pvFlatFrameBuffer = 0; - } - - ep = phys_to_virt(BOOT_ARG_PTR_LOCATION); - *ep= virt_to_phys(&BootArgs); - xstart32(entry); -} diff --git a/gpxe/src/arch/i386/core/x86_io.c b/gpxe/src/arch/i386/core/x86_io.c deleted file mode 100644 index d2c363b9..00000000 --- a/gpxe/src/arch/i386/core/x86_io.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/io.h> -#include <gpxe/x86_io.h> - -/** @file - * - * gPXE I/O API for x86 - * - */ - -/** - * Read 64-bit qword from memory-mapped device - * - * @v io_addr I/O address - * @ret data Value read - * - * This routine uses MMX instructions. - */ -static uint64_t x86_readq ( volatile uint64_t *io_addr ) { - uint64_t data; - __asm__ __volatile__ ( "pushl %%edx\n\t" - "pushl %%eax\n\t" - "movq (%1), %%mm0\n\t" - "movq %%mm0, (%%esp)\n\t" - "popl %%eax\n\t" - "popl %%edx\n\t" - "emms\n\t" - : "=A" ( data ) : "r" ( io_addr ) ); - return data; -} - -/** - * Write 64-bit qword to memory-mapped device - * - * @v data Value to write - * @v io_addr I/O address - * - * This routine uses MMX instructions. - */ -static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) { - __asm__ __volatile__ ( "pushl %%edx\n\t" - "pushl %%eax\n\t" - "movq (%%esp), %%mm0\n\t" - "movq %%mm0, (%1)\n\t" - "popl %%eax\n\t" - "popl %%edx\n\t" - "emms\n\t" - : : "A" ( data ), "r" ( io_addr ) ); -} - -PROVIDE_IOAPI_INLINE ( x86, phys_to_bus ); -PROVIDE_IOAPI_INLINE ( x86, bus_to_phys ); -PROVIDE_IOAPI_INLINE ( x86, ioremap ); -PROVIDE_IOAPI_INLINE ( x86, iounmap ); -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 ); -PROVIDE_IOAPI_INLINE ( x86, outb ); -PROVIDE_IOAPI_INLINE ( x86, outw ); -PROVIDE_IOAPI_INLINE ( x86, outl ); -PROVIDE_IOAPI_INLINE ( x86, insb ); -PROVIDE_IOAPI_INLINE ( x86, insw ); -PROVIDE_IOAPI_INLINE ( x86, insl ); -PROVIDE_IOAPI_INLINE ( x86, outsb ); -PROVIDE_IOAPI_INLINE ( x86, outsw ); -PROVIDE_IOAPI_INLINE ( x86, outsl ); -PROVIDE_IOAPI_INLINE ( x86, iodelay ); -PROVIDE_IOAPI_INLINE ( x86, mb ); diff --git a/gpxe/src/arch/i386/drivers/net/undi.c b/gpxe/src/arch/i386/drivers/net/undi.c deleted file mode 100644 index c6e253c0..00000000 --- a/gpxe/src/arch/i386/drivers/net/undi.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <gpxe/pci.h> -#include <undi.h> -#include <undirom.h> -#include <undiload.h> -#include <undinet.h> -#include <undipreload.h> - -/** @file - * - * UNDI PCI driver - * - */ - -/** - * Find UNDI ROM for PCI device - * - * @v pci PCI device - * @ret undirom UNDI ROM, or NULL - * - * Try to find a driver for this device. Try an exact match on the - * ROM address first, then fall back to a vendor/device ID match only - */ -static struct undi_rom * undipci_find_rom ( struct pci_device *pci ) { - struct undi_rom *undirom; - unsigned long rombase; - - rombase = pci_bar_start ( pci, PCI_ROM_ADDRESS ); - undirom = undirom_find_pci ( pci->vendor, pci->device, rombase ); - if ( ! undirom ) - undirom = undirom_find_pci ( pci->vendor, pci->device, 0 ); - return undirom; -} - -/** - * Probe PCI device - * - * @v pci PCI device - * @v id PCI ID - * @ret rc Return status code - */ -static int undipci_probe ( struct pci_device *pci, - const struct pci_device_id *id __unused ) { - struct undi_device *undi; - struct undi_rom *undirom; - unsigned int busdevfn = PCI_BUSDEVFN ( pci->bus, pci->devfn ); - int rc; - - /* Ignore non-network devices */ - if ( PCI_BASE_CLASS ( pci->class ) != PCI_BASE_CLASS_NETWORK ) - return -ENOTTY; - - /* Allocate UNDI device structure */ - undi = zalloc ( sizeof ( *undi ) ); - if ( ! undi ) - return -ENOMEM; - pci_set_drvdata ( pci, undi ); - - /* Find/create our pixie */ - if ( preloaded_undi.pci_busdevfn == busdevfn ) { - /* Claim preloaded UNDI device */ - DBGC ( undi, "UNDI %p using preloaded UNDI device\n", undi ); - memcpy ( undi, &preloaded_undi, sizeof ( *undi ) ); - memset ( &preloaded_undi, 0, sizeof ( preloaded_undi ) ); - } else { - /* Find UNDI ROM for PCI device */ - if ( ! ( undirom = undipci_find_rom ( pci ) ) ) { - rc = -ENODEV; - goto err_find_rom; - } - - /* Call UNDI ROM loader to create pixie */ - if ( ( rc = undi_load_pci ( undi, undirom, busdevfn ) ) != 0 ) - goto err_load_pci; - } - - /* Add to device hierarchy */ - snprintf ( undi->dev.name, sizeof ( undi->dev.name ), - "UNDI-%s", pci->dev.name ); - memcpy ( &undi->dev.desc, &pci->dev.desc, sizeof ( undi->dev.desc ) ); - undi->dev.parent = &pci->dev; - INIT_LIST_HEAD ( &undi->dev.children ); - list_add ( &undi->dev.siblings, &pci->dev.children ); - - /* Create network device */ - if ( ( rc = undinet_probe ( undi ) ) != 0 ) - goto err_undinet_probe; - - return 0; - - err_undinet_probe: - undi_unload ( undi ); - list_del ( &undi->dev.siblings ); - err_find_rom: - err_load_pci: - free ( undi ); - pci_set_drvdata ( pci, NULL ); - return rc; -} - -/** - * Remove PCI device - * - * @v pci PCI device - */ -static void undipci_remove ( struct pci_device *pci ) { - struct undi_device *undi = pci_get_drvdata ( pci ); - - undinet_remove ( undi ); - undi_unload ( undi ); - list_del ( &undi->dev.siblings ); - free ( undi ); - pci_set_drvdata ( pci, NULL ); -} - -static struct pci_device_id undipci_nics[] = { -PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)", 0 ), -}; - -struct pci_driver undipci_driver __pci_driver = { - .ids = undipci_nics, - .id_count = ( sizeof ( undipci_nics ) / sizeof ( undipci_nics[0] ) ), - .probe = undipci_probe, - .remove = undipci_remove, -}; diff --git a/gpxe/src/arch/i386/drivers/net/undiisr.S b/gpxe/src/arch/i386/drivers/net/undiisr.S deleted file mode 100644 index b27effe1..00000000 --- a/gpxe/src/arch/i386/drivers/net/undiisr.S +++ /dev/null @@ -1,87 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ) - -#define PXENV_UNDI_ISR 0x0014 -#define PXENV_UNDI_ISR_IN_START 1 -#define PXENV_UNDI_ISR_OUT_OURS 0 -#define PXENV_UNDI_ISR_OUT_NOT_OURS 1 - -#define IRQ_PIC_CUTOFF 8 -#define ICR_EOI_NON_SPECIFIC 0x20 -#define PIC1_ICR 0x20 -#define PIC2_ICR 0xa0 - - .text - .arch i386 - .code16 - - .section ".text16", "ax", @progbits - .globl undiisr -undiisr: - - /* Preserve registers */ - pushw %ds - pushw %es - pushw %fs - pushw %gs - pushfl - pushal - - /* Set up our segment registers */ - movw %cs:rm_ds, %ax - movw %ax, %ds - - /* Check that we have an UNDI entry point */ - cmpw $0, pxeparent_entry_point - je chain - - /* Issue UNDI API call */ - movw %ax, %es - movw $undinet_params, %di - movw $PXENV_UNDI_ISR, %bx - movw $PXENV_UNDI_ISR_IN_START, funcflag - pushw %es - pushw %di - pushw %bx - lcall *pxeparent_entry_point - cli /* Just in case */ - addw $6, %sp - cmpw $PXENV_UNDI_ISR_OUT_OURS, funcflag - jne eoi - -trig: /* Record interrupt occurence */ - incb undiisr_trigger_count - -eoi: /* Send EOI */ - movb $ICR_EOI_NON_SPECIFIC, %al - cmpb $IRQ_PIC_CUTOFF, undiisr_irq - jb 1f - outb %al, $PIC2_ICR -1: outb %al, $PIC1_ICR - jmp exit - -chain: /* Chain to next handler */ - pushfw - lcall *undiisr_next_handler - -exit: /* Restore registers and return */ - cli - popal - movzwl %sp, %esp - addr32 movl -20(%esp), %esp /* %esp isn't restored by popal */ - popfl - popw %gs - popw %fs - popw %es - popw %ds - iret - - .section ".data16", "aw", @progbits -undinet_params: -status: .word 0 -funcflag: .word 0 -bufferlength: .word 0 -framelength: .word 0 -frameheaderlength: .word 0 -frame: .word 0, 0 -prottype: .byte 0 -pkttype: .byte 0 diff --git a/gpxe/src/arch/i386/drivers/net/undiload.c b/gpxe/src/arch/i386/drivers/net/undiload.c deleted file mode 100644 index 1d4e88d7..00000000 --- a/gpxe/src/arch/i386/drivers/net/undiload.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <pxe.h> -#include <realmode.h> -#include <bios.h> -#include <pnpbios.h> -#include <basemem.h> -#include <gpxe/pci.h> -#include <undi.h> -#include <undirom.h> -#include <undiload.h> - -/** @file - * - * UNDI load/unload - * - */ - -/** Parameter block for calling UNDI loader */ -static struct s_UNDI_LOADER __bss16 ( undi_loader ); -#define undi_loader __use_data16 ( undi_loader ) - -/** UNDI loader entry point */ -static SEGOFF16_t __bss16 ( undi_loader_entry ); -#define undi_loader_entry __use_data16 ( undi_loader_entry ) - -/** - * Call UNDI loader to create a pixie - * - * @v undi UNDI device - * @v undirom UNDI ROM - * @ret rc Return status code - */ -int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) { - struct s_PXE ppxe; - unsigned int fbms_seg; - uint16_t exit; - int rc; - - /* Set up START_UNDI parameters */ - memset ( &undi_loader, 0, sizeof ( undi_loader ) ); - undi_loader.AX = undi->pci_busdevfn; - undi_loader.BX = undi->isapnp_csn; - undi_loader.DX = undi->isapnp_read_port; - undi_loader.ES = BIOS_SEG; - undi_loader.DI = find_pnp_bios(); - - /* Allocate base memory for PXE stack */ - undi->restore_fbms = get_fbms(); - fbms_seg = ( undi->restore_fbms << 6 ); - fbms_seg -= ( ( undirom->code_size + 0x0f ) >> 4 ); - undi_loader.UNDI_CS = fbms_seg; - fbms_seg -= ( ( undirom->data_size + 0x0f ) >> 4 ); - undi_loader.UNDI_DS = fbms_seg; - - /* Debug info */ - DBGC ( undi, "UNDI %p loading UNDI ROM %p to CS %04x DS %04x for ", - undi, undirom, undi_loader.UNDI_CS, undi_loader.UNDI_DS ); - if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) { - unsigned int bus = ( undi->pci_busdevfn >> 8 ); - unsigned int devfn = ( undi->pci_busdevfn & 0xff ); - DBGC ( undi, "PCI %02x:%02x.%x\n", - bus, PCI_SLOT ( devfn ), PCI_FUNC ( devfn ) ); - } - if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) { - DBGC ( undi, "ISAPnP(%04x) CSN %04x\n", - undi->isapnp_read_port, undi->isapnp_csn ); - } - - /* Call loader */ - undi_loader_entry = undirom->loader_entry; - __asm__ __volatile__ ( REAL_CODE ( "pushw %%ds\n\t" - "pushw %%ax\n\t" - "lcall *undi_loader_entry\n\t" - "addw $4, %%sp\n\t" ) - : "=a" ( exit ) - : "a" ( __from_data16 ( &undi_loader ) ) - : "ebx", "ecx", "edx", "esi", "edi", "ebp" ); - - /* UNDI API calls may rudely change the status of A20 and not - * bother to restore it afterwards. Intel is known to be - * guilty of this. - * - * Note that we will return to this point even if A20 gets - * screwed up by the UNDI driver, because Etherboot always - * resides in an even megabyte of RAM. - */ - gateA20_set(); - - if ( exit != PXENV_EXIT_SUCCESS ) { - rc = -undi_loader.Status; - if ( rc == 0 ) /* Paranoia */ - rc = -EIO; - DBGC ( undi, "UNDI %p loader failed: %s\n", - undi, strerror ( rc ) ); - return rc; - } - - /* Populate PXE device structure */ - undi->pxenv = undi_loader.PXENVptr; - undi->ppxe = undi_loader.PXEptr; - copy_from_real ( &ppxe, undi->ppxe.segment, undi->ppxe.offset, - sizeof ( ppxe ) ); - undi->entry = ppxe.EntryPointSP; - DBGC ( undi, "UNDI %p loaded PXENV+ %04x:%04x !PXE %04x:%04x " - "entry %04x:%04x\n", undi, undi->pxenv.segment, - undi->pxenv.offset, undi->ppxe.segment, undi->ppxe.offset, - undi->entry.segment, undi->entry.offset ); - - /* Update free base memory counter */ - undi->fbms = ( fbms_seg >> 6 ); - set_fbms ( undi->fbms ); - DBGC ( undi, "UNDI %p using [%d,%d) kB of base memory\n", - undi, undi->fbms, undi->restore_fbms ); - - return 0; -} - -/** - * Unload a pixie - * - * @v undi UNDI device - * @ret rc Return status code - * - * Erases the PXENV+ and !PXE signatures, and frees the used base - * memory (if possible). - */ -int undi_unload ( struct undi_device *undi ) { - static uint32_t dead = 0xdeaddead; - - DBGC ( undi, "UNDI %p unloading\n", undi ); - - /* Erase signatures */ - if ( undi->pxenv.segment ) - put_real ( dead, undi->pxenv.segment, undi->pxenv.offset ); - if ( undi->ppxe.segment ) - put_real ( dead, undi->ppxe.segment, undi->ppxe.offset ); - - /* Free base memory, if possible */ - if ( undi->fbms == get_fbms() ) { - DBGC ( undi, "UNDI %p freeing [%d,%d) kB of base memory\n", - undi, undi->fbms, undi->restore_fbms ); - set_fbms ( undi->restore_fbms ); - return 0; - } else { - DBGC ( undi, "UNDI %p leaking [%d,%d) kB of base memory\n", - undi, undi->fbms, undi->restore_fbms ); - return -EBUSY; - } -} diff --git a/gpxe/src/arch/i386/drivers/net/undinet.c b/gpxe/src/arch/i386/drivers/net/undinet.c deleted file mode 100644 index 83b79e7f..00000000 --- a/gpxe/src/arch/i386/drivers/net/undinet.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <string.h> -#include <pxe.h> -#include <realmode.h> -#include <pic8259.h> -#include <biosint.h> -#include <pnpbios.h> -#include <basemem_packet.h> -#include <gpxe/io.h> -#include <gpxe/iobuf.h> -#include <gpxe/netdevice.h> -#include <gpxe/if_ether.h> -#include <gpxe/ethernet.h> -#include <undi.h> -#include <undinet.h> -#include <pxeparent.h> - - -/** @file - * - * UNDI network device driver - * - */ - -/** An UNDI NIC */ -struct undi_nic { - /** Assigned IRQ number */ - unsigned int irq; - /** Currently processing ISR */ - int isr_processing; - /** Bug workarounds */ - int hacks; -}; - -/** - * @defgroup undi_hacks UNDI workarounds - * @{ - */ - -/** Work around Etherboot 5.4 bugs */ -#define UNDI_HACK_EB54 0x0001 - -/** @} */ - -static void undinet_close ( struct net_device *netdev ); - -/** Address of UNDI entry point */ -static SEGOFF16_t undinet_entry; - -/***************************************************************************** - * - * UNDI interrupt service routine - * - ***************************************************************************** - */ - -/** - * UNDI interrupt service routine - * - * The UNDI ISR increments a counter (@c trigger_count) and exits. - */ -extern void undiisr ( void ); - -/** IRQ number */ -uint8_t __data16 ( undiisr_irq ); -#define undiisr_irq __use_data16 ( undiisr_irq ) - -/** IRQ chain vector */ -struct segoff __data16 ( undiisr_next_handler ); -#define undiisr_next_handler __use_data16 ( undiisr_next_handler ) - -/** IRQ trigger count */ -volatile uint8_t __data16 ( undiisr_trigger_count ) = 0; -#define undiisr_trigger_count __use_data16 ( undiisr_trigger_count ) - -/** Last observed trigger count */ -static unsigned int last_trigger_count = 0; - -/** - * Hook UNDI interrupt service routine - * - * @v irq IRQ number - */ -static void undinet_hook_isr ( unsigned int irq ) { - - assert ( irq <= IRQ_MAX ); - assert ( undiisr_irq == 0 ); - - undiisr_irq = irq; - hook_bios_interrupt ( IRQ_INT ( irq ), - ( ( unsigned int ) undiisr ), - &undiisr_next_handler ); -} - -/** - * Unhook UNDI interrupt service routine - * - * @v irq IRQ number - */ -static void undinet_unhook_isr ( unsigned int irq ) { - - assert ( irq <= IRQ_MAX ); - - unhook_bios_interrupt ( IRQ_INT ( irq ), - ( ( unsigned int ) undiisr ), - &undiisr_next_handler ); - undiisr_irq = 0; -} - -/** - * Test to see if UNDI ISR has been triggered - * - * @ret triggered ISR has been triggered since last check - */ -static int undinet_isr_triggered ( void ) { - unsigned int this_trigger_count; - - /* Read trigger_count. Do this only once; it is volatile */ - this_trigger_count = undiisr_trigger_count; - - if ( this_trigger_count == last_trigger_count ) { - /* Not triggered */ - return 0; - } else { - /* Triggered */ - last_trigger_count = this_trigger_count; - return 1; - } -} - -/***************************************************************************** - * - * UNDI network device interface - * - ***************************************************************************** - */ - -/** UNDI transmit buffer descriptor */ -static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd ); -#define undinet_tbd __use_data16 ( undinet_tbd ) - -/** - * Transmit packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int undinet_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { - struct s_PXENV_UNDI_TRANSMIT undi_transmit; - size_t len = iob_len ( iobuf ); - int rc; - - /* Technically, we ought to make sure that the previous - * transmission has completed before we re-use the buffer. - * However, many PXE stacks (including at least some Intel PXE - * stacks and Etherboot 5.4) fail to generate TX completions. - * In practice this won't be a problem, since our TX datapath - * has a very low packet volume and we can get away with - * assuming that a TX will be complete by the time we want to - * transmit the next packet. - */ - - /* Copy packet to UNDI I/O buffer */ - if ( len > sizeof ( basemem_packet ) ) - len = sizeof ( basemem_packet ); - memcpy ( &basemem_packet, iobuf->data, len ); - - /* Create PXENV_UNDI_TRANSMIT data structure */ - memset ( &undi_transmit, 0, sizeof ( undi_transmit ) ); - undi_transmit.DestAddr.segment = rm_ds; - undi_transmit.DestAddr.offset = __from_data16 ( &undinet_tbd ); - undi_transmit.TBD.segment = rm_ds; - undi_transmit.TBD.offset = __from_data16 ( &undinet_tbd ); - - /* Create PXENV_UNDI_TBD data structure */ - undinet_tbd.ImmedLength = len; - undinet_tbd.Xmit.segment = rm_ds; - undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet ); - - /* Issue PXE API call */ - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT, - &undi_transmit, - sizeof ( undi_transmit ) ) ) != 0 ) - goto done; - - /* Free I/O buffer */ - netdev_tx_complete ( netdev, iobuf ); - - done: - return rc; -} - -/** - * Poll for received packets - * - * @v netdev Network device - * - * Fun, fun, fun. UNDI drivers don't use polling; they use - * interrupts. We therefore cheat and pretend that an interrupt has - * occurred every time undinet_poll() is called. This isn't too much - * of a hack; PCI devices share IRQs and so the first thing that a - * proper ISR should do is call PXENV_UNDI_ISR to determine whether or - * not the UNDI NIC generated the interrupt; there is no harm done by - * spurious calls to PXENV_UNDI_ISR. Similarly, we wouldn't be - * handling them any more rapidly than the usual rate of - * undinet_poll() being called even if we did implement a full ISR. - * So it should work. Ha! - * - * Addendum (21/10/03). Some cards don't play nicely with this trick, - * so instead of doing it the easy way we have to go to all the hassle - * of installing a genuine interrupt service routine and dealing with - * the wonderful 8259 Programmable Interrupt Controller. Joy. - * - * Addendum (10/07/07). When doing things such as iSCSI boot, in - * which we have to co-operate with a running OS, we can't get away - * with the "ISR-just-increments-a-counter-and-returns" trick at all, - * because it involves tying up the PIC for far too long, and other - * interrupt-dependent components (e.g. local disks) start breaking. - * We therefore implement a "proper" ISR which calls PXENV_UNDI_ISR - * from within interrupt context in order to deassert the device - * interrupt, and sends EOI if applicable. - */ -static void undinet_poll ( struct net_device *netdev ) { - struct undi_nic *undinic = netdev->priv; - struct s_PXENV_UNDI_ISR undi_isr; - struct io_buffer *iobuf = NULL; - size_t len; - size_t frag_len; - size_t max_frag_len; - int rc; - - if ( ! undinic->isr_processing ) { - /* Do nothing unless ISR has been triggered */ - if ( ! undinet_isr_triggered() ) { - /* Allow interrupt to occur */ - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - "nop\n\t" - "nop\n\t" - "cli\n\t" ) : : ); - return; - } - - /* Start ISR processing */ - undinic->isr_processing = 1; - undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS; - } else { - /* Continue ISR processing */ - undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; - } - - /* Run through the ISR loop */ - while ( 1 ) { - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR, - &undi_isr, - sizeof ( undi_isr ) ) ) != 0 ) - break; - switch ( undi_isr.FuncFlag ) { - case PXENV_UNDI_ISR_OUT_TRANSMIT: - /* We don't care about transmit completions */ - break; - case PXENV_UNDI_ISR_OUT_RECEIVE: - /* Packet fragment received */ - len = undi_isr.FrameLength; - frag_len = undi_isr.BufferLength; - if ( ( len == 0 ) || ( len < frag_len ) ) { - /* Don't laugh. VMWare does it. */ - DBGC ( undinic, "UNDINIC %p reported insane " - "fragment (%zd of %zd bytes)\n", - undinic, frag_len, len ); - 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; - } - max_frag_len = iob_tailroom ( iobuf ); - if ( frag_len > max_frag_len ) { - DBGC ( undinic, "UNDINIC %p fragment too big " - "(%zd+%zd does not fit into %zd)\n", - undinic, iob_len ( iobuf ), frag_len, - ( iob_len ( iobuf ) + max_frag_len ) ); - frag_len = max_frag_len; - } - copy_from_real ( iob_put ( iobuf, frag_len ), - undi_isr.Frame.segment, - undi_isr.Frame.offset, frag_len ); - if ( iob_len ( iobuf ) == len ) { - /* Whole packet received; deliver it */ - netdev_rx ( netdev, iob_disown ( iobuf ) ); - /* Etherboot 5.4 fails to return all packets - * under mild load; pretend it retriggered. - */ - if ( undinic->hacks & UNDI_HACK_EB54 ) - --last_trigger_count; - } - break; - case PXENV_UNDI_ISR_OUT_DONE: - /* Processing complete */ - undinic->isr_processing = 0; - goto done; - default: - /* Should never happen. VMWare does it routinely. */ - DBGC ( undinic, "UNDINIC %p ISR returned invalid " - "FuncFlag %04x\n", undinic, undi_isr.FuncFlag ); - undinic->isr_processing = 0; - goto done; - } - undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; - } - - done: - if ( iobuf ) { - DBGC ( undinic, "UNDINIC %p returned incomplete packet " - "(%zd of %zd)\n", undinic, iob_len ( iobuf ), - ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) ); - netdev_rx_err ( netdev, iobuf, -EINVAL ); - } -} - -/** - * Open NIC - * - * @v netdev Net device - * @ret rc Return status code - */ -static int undinet_open ( struct net_device *netdev ) { - struct undi_nic *undinic = netdev->priv; - struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_address; - struct s_PXENV_UNDI_OPEN undi_open; - int rc; - - /* Hook interrupt service routine and enable interrupt */ - undinet_hook_isr ( undinic->irq ); - enable_irq ( undinic->irq ); - send_eoi ( undinic->irq ); - - /* Set station address. Required for some PXE stacks; will - * spuriously fail on others. Ignore failures. We only ever - * use it to set the MAC address to the card's permanent value - * anyway. - */ - memcpy ( undi_set_address.StationAddress, netdev->ll_addr, - sizeof ( undi_set_address.StationAddress ) ); - pxeparent_call ( undinet_entry, PXENV_UNDI_SET_STATION_ADDRESS, - &undi_set_address, sizeof ( undi_set_address ) ); - - /* Open NIC. We ask for promiscuous operation, since it's the - * only way to ask for all multicast addresses. On any - * switched network, it shouldn't really make a difference to - * performance. - */ - memset ( &undi_open, 0, sizeof ( undi_open ) ); - undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS ); - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_OPEN, - &undi_open, sizeof ( undi_open ) ) ) != 0 ) - goto err; - - DBGC ( undinic, "UNDINIC %p opened\n", undinic ); - return 0; - - err: - undinet_close ( netdev ); - return rc; -} - -/** - * Close NIC - * - * @v netdev Net device - */ -static void undinet_close ( struct net_device *netdev ) { - struct undi_nic *undinic = netdev->priv; - struct s_PXENV_UNDI_ISR undi_isr; - struct s_PXENV_UNDI_CLOSE undi_close; - int rc; - - /* Ensure ISR has exited cleanly */ - while ( undinic->isr_processing ) { - undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR, - &undi_isr, - sizeof ( undi_isr ) ) ) != 0 ) - break; - switch ( undi_isr.FuncFlag ) { - case PXENV_UNDI_ISR_OUT_TRANSMIT: - case PXENV_UNDI_ISR_OUT_RECEIVE: - /* Continue draining */ - break; - default: - /* Stop processing */ - undinic->isr_processing = 0; - break; - } - } - - /* Close NIC */ - pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE, - &undi_close, sizeof ( undi_close ) ); - - /* Disable interrupt and unhook ISR */ - disable_irq ( undinic->irq ); - undinet_unhook_isr ( undinic->irq ); - - DBGC ( undinic, "UNDINIC %p closed\n", undinic ); -} - -/** - * Enable/disable interrupts - * - * @v netdev Net device - * @v enable Interrupts should be enabled - */ -static void undinet_irq ( struct net_device *netdev, int enable ) { - struct undi_nic *undinic = netdev->priv; - - /* Cannot support interrupts yet */ - DBGC ( undinic, "UNDINIC %p cannot %s interrupts\n", - undinic, ( enable ? "enable" : "disable" ) ); -} - -/** UNDI network device operations */ -static struct net_device_operations undinet_operations = { - .open = undinet_open, - .close = undinet_close, - .transmit = undinet_transmit, - .poll = undinet_poll, - .irq = undinet_irq, -}; - -/** - * Probe UNDI device - * - * @v undi UNDI device - * @ret rc Return status code - */ -int undinet_probe ( struct undi_device *undi ) { - struct net_device *netdev; - struct undi_nic *undinic; - struct s_PXENV_START_UNDI start_undi; - struct s_PXENV_UNDI_STARTUP undi_startup; - struct s_PXENV_UNDI_INITIALIZE undi_initialize; - struct s_PXENV_UNDI_GET_INFORMATION undi_info; - struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface; - struct s_PXENV_UNDI_SHUTDOWN undi_shutdown; - struct s_PXENV_UNDI_CLEANUP undi_cleanup; - struct s_PXENV_STOP_UNDI stop_undi; - int rc; - - /* Allocate net device */ - netdev = alloc_etherdev ( sizeof ( *undinic ) ); - if ( ! netdev ) - return -ENOMEM; - netdev_init ( netdev, &undinet_operations ); - undinic = netdev->priv; - undi_set_drvdata ( undi, netdev ); - netdev->dev = &undi->dev; - memset ( undinic, 0, sizeof ( *undinic ) ); - undinet_entry = undi->entry; - DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi ); - - /* Hook in UNDI stack */ - if ( ! ( undi->flags & UNDI_FL_STARTED ) ) { - memset ( &start_undi, 0, sizeof ( start_undi ) ); - start_undi.AX = undi->pci_busdevfn; - start_undi.BX = undi->isapnp_csn; - start_undi.DX = undi->isapnp_read_port; - start_undi.ES = BIOS_SEG; - start_undi.DI = find_pnp_bios(); - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_START_UNDI, - &start_undi, - sizeof ( start_undi ) ) ) != 0 ) - goto err_start_undi; - } - undi->flags |= UNDI_FL_STARTED; - - /* Bring up UNDI stack */ - if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) { - memset ( &undi_startup, 0, sizeof ( undi_startup ) ); - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_STARTUP, - &undi_startup, - sizeof ( undi_startup ) ) ) != 0 ) - goto err_undi_startup; - memset ( &undi_initialize, 0, sizeof ( undi_initialize ) ); - if ( ( rc = pxeparent_call ( undinet_entry, - PXENV_UNDI_INITIALIZE, - &undi_initialize, - sizeof ( undi_initialize ))) != 0 ) - goto err_undi_initialize; - } - undi->flags |= UNDI_FL_INITIALIZED; - - /* Get device information */ - memset ( &undi_info, 0, sizeof ( undi_info ) ); - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_INFORMATION, - &undi_info, sizeof ( undi_info ) ) ) != 0 ) - goto err_undi_get_information; - memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN ); - undinic->irq = undi_info.IntNumber; - if ( undinic->irq > IRQ_MAX ) { - DBGC ( undinic, "UNDINIC %p invalid IRQ %d\n", - undinic, undinic->irq ); - goto err_bad_irq; - } - DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n", - undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq ); - - /* Get interface information */ - memset ( &undi_iface, 0, sizeof ( undi_iface ) ); - if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_IFACE_INFO, - &undi_iface, - sizeof ( undi_iface ) ) ) != 0 ) - goto err_undi_get_iface_info; - DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n", - undinic, undi_iface.IfaceType, undi_iface.LinkSpeed, - undi_iface.ServiceFlags ); - if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot", - sizeof ( undi_iface.IfaceType ) ) == 0 ) { - DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n", - undinic ); - undinic->hacks |= UNDI_HACK_EB54; - } - - /* Mark as link up; we don't handle link state */ - netdev_link_up ( netdev ); - - /* Register network device */ - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register; - - DBGC ( undinic, "UNDINIC %p added\n", undinic ); - return 0; - - err_register: - err_undi_get_iface_info: - err_bad_irq: - err_undi_get_information: - err_undi_initialize: - /* Shut down UNDI stack */ - memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) ); - pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN, &undi_shutdown, - sizeof ( undi_shutdown ) ); - memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) ); - pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP, &undi_cleanup, - sizeof ( undi_cleanup ) ); - undi->flags &= ~UNDI_FL_INITIALIZED; - err_undi_startup: - /* Unhook UNDI stack */ - memset ( &stop_undi, 0, sizeof ( stop_undi ) ); - pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi, - sizeof ( stop_undi ) ); - undi->flags &= ~UNDI_FL_STARTED; - err_start_undi: - netdev_nullify ( netdev ); - netdev_put ( netdev ); - undi_set_drvdata ( undi, NULL ); - return rc; -} - -/** - * Remove UNDI device - * - * @v undi UNDI device - */ -void undinet_remove ( struct undi_device *undi ) { - struct net_device *netdev = undi_get_drvdata ( undi ); - struct undi_nic *undinic = netdev->priv; - struct s_PXENV_UNDI_SHUTDOWN undi_shutdown; - struct s_PXENV_UNDI_CLEANUP undi_cleanup; - struct s_PXENV_STOP_UNDI stop_undi; - - /* Unregister net device */ - unregister_netdev ( netdev ); - - /* If we are preparing for an OS boot, or if we cannot exit - * via the PXE stack, then shut down the PXE stack. - */ - if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) { - - /* Shut down UNDI stack */ - memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) ); - pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN, - &undi_shutdown, sizeof ( undi_shutdown ) ); - memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) ); - pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP, - &undi_cleanup, sizeof ( undi_cleanup ) ); - undi->flags &= ~UNDI_FL_INITIALIZED; - - /* Unhook UNDI stack */ - memset ( &stop_undi, 0, sizeof ( stop_undi ) ); - pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi, - sizeof ( stop_undi ) ); - undi->flags &= ~UNDI_FL_STARTED; - } - - /* Clear entry point */ - memset ( &undinet_entry, 0, sizeof ( undinet_entry ) ); - - /* Free network device */ - netdev_nullify ( netdev ); - netdev_put ( netdev ); - - DBGC ( undinic, "UNDINIC %p removed\n", undinic ); -} diff --git a/gpxe/src/arch/i386/drivers/net/undionly.c b/gpxe/src/arch/i386/drivers/net/undionly.c deleted file mode 100644 index 7dfb5d15..00000000 --- a/gpxe/src/arch/i386/drivers/net/undionly.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <gpxe/device.h> -#include <gpxe/init.h> -#include <undi.h> -#include <undinet.h> -#include <undipreload.h> - -/** @file - * - * "Pure" UNDI driver - * - * This is the UNDI driver without explicit support for PCI or any - * other bus type. It is capable only of using the preloaded UNDI - * device. It must not be combined in an image with any other - * drivers. - * - * If you want a PXE-loadable image that contains only the UNDI - * driver, build "bin/undionly.kpxe". - * - * If you want any other image format, or any other drivers in - * addition to the UNDI driver, build e.g. "bin/undi.dsk". - */ - -/** - * Probe UNDI root bus - * - * @v rootdev UNDI bus root device - * - * Scans the UNDI bus for devices and registers all devices it can - * find. - */ -static int undibus_probe ( struct root_device *rootdev ) { - struct undi_device *undi = &preloaded_undi; - int rc; - - /* Check for a valie preloaded UNDI device */ - if ( ! undi->entry.segment ) { - DBG ( "No preloaded UNDI device found!\n" ); - return -ENODEV; - } - - /* Add to device hierarchy */ - strncpy ( undi->dev.name, "UNDI", - ( sizeof ( undi->dev.name ) - 1 ) ); - if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) { - undi->dev.desc.bus_type = BUS_TYPE_PCI; - undi->dev.desc.location = undi->pci_busdevfn; - undi->dev.desc.vendor = undi->pci_vendor; - undi->dev.desc.device = undi->pci_device; - } else if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) { - undi->dev.desc.bus_type = BUS_TYPE_ISAPNP; - } - undi->dev.parent = &rootdev->dev; - list_add ( &undi->dev.siblings, &rootdev->dev.children); - INIT_LIST_HEAD ( &undi->dev.children ); - - /* Create network device */ - if ( ( rc = undinet_probe ( undi ) ) != 0 ) - goto err; - - return 0; - - err: - list_del ( &undi->dev.siblings ); - return rc; -} - -/** - * Remove UNDI root bus - * - * @v rootdev UNDI bus root device - */ -static void undibus_remove ( struct root_device *rootdev __unused ) { - struct undi_device *undi = &preloaded_undi; - - undinet_remove ( undi ); - list_del ( &undi->dev.siblings ); -} - -/** UNDI bus root device driver */ -static struct root_driver undi_root_driver = { - .probe = undibus_probe, - .remove = undibus_remove, -}; - -/** UNDI bus root device */ -struct root_device undi_root_device __root_device = { - .dev = { .name = "UNDI" }, - .driver = &undi_root_driver, -}; - -/** - * Prepare for exit - * - * @v flags Shutdown flags - */ -static void undionly_shutdown ( int flags ) { - /* If we are shutting down to boot an OS, clear the "keep PXE - * stack" flag. - */ - if ( flags & SHUTDOWN_BOOT ) - preloaded_undi.flags &= ~UNDI_FL_KEEP_ALL; -} - -struct startup_fn startup_undionly __startup_fn ( STARTUP_LATE ) = { - .shutdown = undionly_shutdown, -}; diff --git a/gpxe/src/arch/i386/drivers/net/undipreload.c b/gpxe/src/arch/i386/drivers/net/undipreload.c deleted file mode 100644 index a4b2f4ac..00000000 --- a/gpxe/src/arch/i386/drivers/net/undipreload.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <realmode.h> -#include <undipreload.h> - -/** @file - * - * Preloaded UNDI stack - * - */ - -/** - * Preloaded UNDI device - * - * This is the UNDI device that was present when Etherboot started - * execution (i.e. when loading a .kpxe image). The first driver to - * claim this device must zero out this data structure. - */ -struct undi_device __data16 ( preloaded_undi ); diff --git a/gpxe/src/arch/i386/drivers/net/undirom.c b/gpxe/src/arch/i386/drivers/net/undirom.c deleted file mode 100644 index 2463d969..00000000 --- a/gpxe/src/arch/i386/drivers/net/undirom.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <pxe.h> -#include <realmode.h> -#include <undirom.h> - -/** @file - * - * UNDI expansion ROMs - * - */ - -/** List of all UNDI ROMs */ -static LIST_HEAD ( undiroms ); - -/** - * Parse PXE ROM ID structure - * - * @v undirom UNDI ROM - * @v pxeromid Offset within ROM to PXE ROM ID structure - * @ret rc Return status code - */ -static int undirom_parse_pxeromid ( struct undi_rom *undirom, - unsigned int pxeromid ) { - struct undi_rom_id undi_rom_id; - unsigned int undiloader; - - DBGC ( undirom, "UNDIROM %p has PXE ROM ID at %04x:%04x\n", undirom, - undirom->rom_segment, pxeromid ); - - /* Read PXE ROM ID structure and verify */ - copy_from_real ( &undi_rom_id, undirom->rom_segment, pxeromid, - sizeof ( undi_rom_id ) ); - if ( undi_rom_id.Signature != UNDI_ROM_ID_SIGNATURE ) { - DBGC ( undirom, "UNDIROM %p has bad PXE ROM ID signature " - "%08x\n", undirom, undi_rom_id.Signature ); - return -EINVAL; - } - - /* Check for UNDI loader */ - undiloader = undi_rom_id.UNDILoader; - if ( ! undiloader ) { - DBGC ( undirom, "UNDIROM %p has no UNDI loader\n", undirom ); - return -EINVAL; - } - - /* Fill in UNDI ROM loader fields */ - undirom->loader_entry.segment = undirom->rom_segment; - undirom->loader_entry.offset = undiloader; - undirom->code_size = undi_rom_id.CodeSize; - undirom->data_size = undi_rom_id.DataSize; - - DBGC ( undirom, "UNDIROM %p has UNDI loader at %04x:%04x " - "(code %04zx data %04zx)\n", undirom, - undirom->loader_entry.segment, undirom->loader_entry.offset, - undirom->code_size, undirom->data_size ); - return 0; -} - -/** - * Parse PCI expansion header - * - * @v undirom UNDI ROM - * @v pcirheader Offset within ROM to PCI expansion header - */ -static int undirom_parse_pcirheader ( struct undi_rom *undirom, - unsigned int pcirheader ) { - struct pcir_header pcir_header; - - DBGC ( undirom, "UNDIROM %p has PCI expansion header at %04x:%04x\n", - undirom, undirom->rom_segment, pcirheader ); - - /* Read PCI expansion header and verify */ - copy_from_real ( &pcir_header, undirom->rom_segment, pcirheader, - sizeof ( pcir_header ) ); - if ( pcir_header.signature != PCIR_SIGNATURE ) { - DBGC ( undirom, "UNDIROM %p has bad PCI expansion header " - "signature %08x\n", undirom, pcir_header.signature ); - return -EINVAL; - } - - /* Fill in UNDI ROM PCI device fields */ - undirom->bus_type = PCI_NIC; - undirom->bus_id.pci.vendor_id = pcir_header.vendor_id; - undirom->bus_id.pci.device_id = pcir_header.device_id; - - DBGC ( undirom, "UNDIROM %p is for PCI devices %04x:%04x\n", undirom, - undirom->bus_id.pci.vendor_id, undirom->bus_id.pci.device_id ); - return 0; - -} - -/** - * Probe UNDI ROM - * - * @v rom_segment ROM segment address - * @ret rc Return status code - */ -static int undirom_probe ( unsigned int rom_segment ) { - struct undi_rom *undirom = NULL; - struct undi_rom_header romheader; - size_t rom_len; - unsigned int pxeromid; - unsigned int pcirheader; - int rc; - - /* Read expansion ROM header and verify */ - copy_from_real ( &romheader, rom_segment, 0, sizeof ( romheader ) ); - if ( romheader.Signature != ROM_SIGNATURE ) { - rc = -EINVAL; - goto err; - } - rom_len = ( romheader.ROMLength * 512 ); - - /* Allocate memory for UNDI ROM */ - undirom = zalloc ( sizeof ( *undirom ) ); - if ( ! undirom ) { - DBG ( "Could not allocate UNDI ROM structure\n" ); - rc = -ENOMEM; - goto err; - } - DBGC ( undirom, "UNDIROM %p trying expansion ROM at %04x:0000 " - "(%zdkB)\n", undirom, rom_segment, ( rom_len / 1024 ) ); - undirom->rom_segment = rom_segment; - - /* Check for and parse PXE ROM ID */ - pxeromid = romheader.PXEROMID; - if ( ! pxeromid ) { - DBGC ( undirom, "UNDIROM %p has no PXE ROM ID\n", undirom ); - rc = -EINVAL; - goto err; - } - if ( pxeromid > rom_len ) { - DBGC ( undirom, "UNDIROM %p PXE ROM ID outside ROM\n", - undirom ); - rc = -EINVAL; - goto err; - } - if ( ( rc = undirom_parse_pxeromid ( undirom, pxeromid ) ) != 0 ) - goto err; - - /* Parse PCIR header, if present */ - pcirheader = romheader.PCIRHeader; - if ( pcirheader ) - undirom_parse_pcirheader ( undirom, pcirheader ); - - /* Add to UNDI ROM list and return */ - DBGC ( undirom, "UNDIROM %p registered\n", undirom ); - list_add ( &undirom->list, &undiroms ); - return 0; - - err: - free ( undirom ); - return rc; -} - -/** - * Create UNDI ROMs for all possible expansion ROMs - * - * @ret - */ -static void undirom_probe_all_roms ( void ) { - static int probed = 0; - unsigned int rom_segment; - - /* Perform probe only once */ - if ( probed ) - return; - - DBG ( "Scanning for PXE expansion ROMs\n" ); - - /* Scan through expansion ROM region at 512 byte intervals */ - for ( rom_segment = 0xc000 ; rom_segment < 0x10000 ; - rom_segment += 0x20 ) { - undirom_probe ( rom_segment ); - } - - probed = 1; -} - -/** - * Find UNDI ROM for PCI device - * - * @v vendor_id PCI vendor ID - * @v device_id PCI device ID - * @v rombase ROM base address, or 0 for any - * @ret undirom UNDI ROM, or NULL - */ -struct undi_rom * undirom_find_pci ( unsigned int vendor_id, - unsigned int device_id, - unsigned int rombase ) { - struct undi_rom *undirom; - - undirom_probe_all_roms(); - - list_for_each_entry ( undirom, &undiroms, list ) { - if ( undirom->bus_type != PCI_NIC ) - continue; - if ( undirom->bus_id.pci.vendor_id != vendor_id ) - continue; - if ( undirom->bus_id.pci.device_id != device_id ) - continue; - if ( rombase && ( ( undirom->rom_segment << 4 ) != rombase ) ) - continue; - DBGC ( undirom, "UNDIROM %p matched PCI %04x:%04x (%08x)\n", - undirom, vendor_id, device_id, rombase ); - return undirom; - } - - DBG ( "No UNDI ROM matched PCI %04x:%04x (%08x)\n", - vendor_id, device_id, rombase ); - return NULL; -} diff --git a/gpxe/src/arch/i386/firmware/pcbios/basemem.c b/gpxe/src/arch/i386/firmware/pcbios/basemem.c deleted file mode 100644 index 1ba7d1f6..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/basemem.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <realmode.h> -#include <bios.h> -#include <basemem.h> -#include <gpxe/hidemem.h> - -/** @file - * - * Base memory allocation - * - */ - -/** - * Set the BIOS free base memory counter - * - * @v new_fbms New free base memory counter (in kB) - */ -void set_fbms ( unsigned int new_fbms ) { - uint16_t fbms = new_fbms; - - /* Update the BIOS memory counter */ - put_real ( fbms, BDA_SEG, BDA_FBMS ); - - /* Update our hidden memory region map */ - hide_basemem(); -} diff --git a/gpxe/src/arch/i386/firmware/pcbios/bios_console.c b/gpxe/src/arch/i386/firmware/pcbios/bios_console.c deleted file mode 100644 index 1d18e54c..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/bios_console.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <assert.h> -#include <realmode.h> -#include <console.h> -#include <gpxe/ansiesc.h> - -#define ATTR_BOLD 0x08 - -#define ATTR_FCOL_MASK 0x07 -#define ATTR_FCOL_BLACK 0x00 -#define ATTR_FCOL_BLUE 0x01 -#define ATTR_FCOL_GREEN 0x02 -#define ATTR_FCOL_CYAN 0x03 -#define ATTR_FCOL_RED 0x04 -#define ATTR_FCOL_MAGENTA 0x05 -#define ATTR_FCOL_YELLOW 0x06 -#define ATTR_FCOL_WHITE 0x07 - -#define ATTR_BCOL_MASK 0x70 -#define ATTR_BCOL_BLACK 0x00 -#define ATTR_BCOL_BLUE 0x10 -#define ATTR_BCOL_GREEN 0x20 -#define ATTR_BCOL_CYAN 0x30 -#define ATTR_BCOL_RED 0x40 -#define ATTR_BCOL_MAGENTA 0x50 -#define ATTR_BCOL_YELLOW 0x60 -#define ATTR_BCOL_WHITE 0x70 - -#define ATTR_DEFAULT ATTR_FCOL_WHITE - -/** Current character attribute */ -static unsigned int bios_attr = ATTR_DEFAULT; - -/** - * Handle ANSI CUP (cursor position) - * - * @v count Parameter count - * @v params[0] Row (1 is top) - * @v params[1] Column (1 is left) - */ -static void bios_handle_cup ( unsigned int count __unused, int params[] ) { - int cx = ( params[1] - 1 ); - int cy = ( params[0] - 1 ); - - if ( cx < 0 ) - cx = 0; - if ( cy < 0 ) - cy = 0; - - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - "int $0x10\n\t" - "cli\n\t" ) - : : "a" ( 0x0200 ), "b" ( 1 ), - "d" ( ( cy << 8 ) | cx ) ); -} - -/** - * Handle ANSI ED (erase in page) - * - * @v count Parameter count - * @v params[0] Region to erase - */ -static void bios_handle_ed ( unsigned int count __unused, - int params[] __unused ) { - /* We assume that we always clear the whole screen */ - assert ( params[0] == ANSIESC_ED_ALL ); - - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - "int $0x10\n\t" - "cli\n\t" ) - : : "a" ( 0x0600 ), "b" ( bios_attr << 8 ), - "c" ( 0 ), "d" ( 0xffff ) ); -} - -/** - * Handle ANSI SGR (set graphics rendition) - * - * @v count Parameter count - * @v params List of graphic rendition aspects - */ -static void bios_handle_sgr ( unsigned int count, int params[] ) { - static const uint8_t bios_attr_fcols[10] = { - ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN, - ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA, - ATTR_FCOL_CYAN, ATTR_FCOL_WHITE, - ATTR_FCOL_WHITE, ATTR_FCOL_WHITE /* defaults */ - }; - static const uint8_t bios_attr_bcols[10] = { - ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN, - ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA, - ATTR_BCOL_CYAN, ATTR_BCOL_WHITE, - ATTR_BCOL_BLACK, ATTR_BCOL_BLACK /* defaults */ - }; - unsigned int i; - int aspect; - - for ( i = 0 ; i < count ; i++ ) { - aspect = params[i]; - if ( aspect == 0 ) { - bios_attr = ATTR_DEFAULT; - } else if ( aspect == 1 ) { - bios_attr |= ATTR_BOLD; - } else if ( aspect == 22 ) { - bios_attr &= ~ATTR_BOLD; - } else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) { - bios_attr &= ~ATTR_FCOL_MASK; - bios_attr |= bios_attr_fcols[ aspect - 30 ]; - } else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) { - bios_attr &= ~ATTR_BCOL_MASK; - bios_attr |= bios_attr_bcols[ aspect - 40 ]; - } - } -} - -/** BIOS console ANSI escape sequence handlers */ -static struct ansiesc_handler bios_ansiesc_handlers[] = { - { ANSIESC_CUP, bios_handle_cup }, - { ANSIESC_ED, bios_handle_ed }, - { ANSIESC_SGR, bios_handle_sgr }, - { 0, NULL } -}; - -/** BIOS console ANSI escape sequence context */ -static struct ansiesc_context bios_ansiesc_ctx = { - .handlers = bios_ansiesc_handlers, -}; - -/** - * Print a character to BIOS console - * - * @v character Character to be printed - */ -static void bios_putchar ( int character ) { - int discard_a, discard_b, discard_c; - - /* Intercept ANSI escape sequences */ - character = ansiesc_process ( &bios_ansiesc_ctx, character ); - if ( character < 0 ) - return; - - /* Print character with attribute */ - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - /* Skip non-printable characters */ - "cmpb $0x20, %%al\n\t" - "jb 1f\n\t" - /* Set attribute */ - "movw $0x0001, %%cx\n\t" - "movb $0x09, %%ah\n\t" - "int $0x10\n\t" - "\n1:\n\t" - /* Print character */ - "xorw %%bx, %%bx\n\t" - "movb $0x0e, %%ah\n\t" - "int $0x10\n\t" - "cli\n\t" ) - : "=a" ( discard_a ), "=b" ( discard_b ), - "=c" ( discard_c ) - : "a" ( character ), "b" ( bios_attr ) - : "ebp" ); -} - -/** - * Pointer to current ANSI output sequence - * - * While we are in the middle of returning an ANSI sequence for a - * special key, this will point to the next character to return. When - * not in the middle of such a sequence, this will point to a NUL - * (note: not "will be NULL"). - */ -static const char *ansi_input = ""; - -/** - * Lowest BIOS scancode of interest - * - * Most of the BIOS key scancodes that we are interested in are in a - * dense range, so subtracting a constant and treating them as offsets - * into an array works efficiently. - */ -#define BIOS_KEY_MIN 0x42 - -/** Offset into list of interesting BIOS scancodes */ -#define BIOS_KEY(scancode) ( (scancode) - BIOS_KEY_MIN ) - -/** Mapping from BIOS scan codes to ANSI escape sequences */ -static const char *ansi_sequences[] = { - [ BIOS_KEY ( 0x42 ) ] = "[19~", /* F8 (required for PXE) */ - [ BIOS_KEY ( 0x47 ) ] = "[H", /* Home */ - [ BIOS_KEY ( 0x48 ) ] = "[A", /* Up arrow */ - [ BIOS_KEY ( 0x4b ) ] = "[D", /* Left arrow */ - [ BIOS_KEY ( 0x4d ) ] = "[C", /* Right arrow */ - [ BIOS_KEY ( 0x4f ) ] = "[F", /* End */ - [ BIOS_KEY ( 0x50 ) ] = "[B", /* Down arrow */ - [ BIOS_KEY ( 0x53 ) ] = "[3~", /* Delete */ -}; - -/** - * Get ANSI escape sequence corresponding to BIOS scancode - * - * @v scancode BIOS scancode - * @ret ansi_seq ANSI escape sequence, if any, otherwise NULL - */ -static const char * scancode_to_ansi_seq ( unsigned int scancode ) { - unsigned int bios_key = BIOS_KEY ( scancode ); - - if ( bios_key < ( sizeof ( ansi_sequences ) / - sizeof ( ansi_sequences[0] ) ) ) { - return ansi_sequences[bios_key]; - } - DBG ( "Unrecognised BIOS scancode %02x\n", scancode ); - return NULL; -} - -/** - * Get character from BIOS console - * - * @ret character Character read from console - */ -static int bios_getchar ( void ) { - uint16_t keypress; - unsigned int character; - const char *ansi_seq; - - /* If we are mid-sequence, pass out the next byte */ - if ( ( character = *ansi_input ) ) { - ansi_input++; - return character; - } - - /* Read character from real BIOS console */ - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - "int $0x16\n\t" - "cli\n\t" ) - : "=a" ( keypress ) : "a" ( 0x1000 ) ); - character = ( keypress & 0xff ); - - /* If it's a normal character, just return it */ - if ( character && ( character < 0x80 ) ) - return character; - - /* Otherwise, check for a special key that we know about */ - if ( ( ansi_seq = scancode_to_ansi_seq ( keypress >> 8 ) ) ) { - /* Start of escape sequence: return ESC (0x1b) */ - ansi_input = ansi_seq; - return 0x1b; - } - - return 0; -} - -/** - * Check for character ready to read from BIOS console - * - * @ret True Character available to read - * @ret False No character available to read - */ -static int bios_iskey ( void ) { - unsigned int discard_a; - unsigned int flags; - - /* If we are mid-sequence, we are always ready */ - if ( *ansi_input ) - return 1; - - /* Otherwise check the real BIOS console */ - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - "int $0x16\n\t" - "pushfw\n\t" - "popw %w0\n\t" - "cli\n\t" ) - : "=r" ( flags ), "=a" ( discard_a ) - : "a" ( 0x0100 ) ); - return ( ! ( flags & ZF ) ); -} - -struct console_driver bios_console __console_driver = { - .putchar = bios_putchar, - .getchar = bios_getchar, - .iskey = bios_iskey, -}; diff --git a/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S b/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S deleted file mode 100644 index 99ca519b..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - - .text - .arch i386 - .code16 - -#define SMAP 0x534d4150 - -/* Most documentation refers to the E820 buffer as being 20 bytes, and - * the API makes it perfectly legitimate to pass only a 20-byte buffer - * and expect to get valid data. However, some morons at ACPI decided - * to extend the data structure by adding an extra "extended - * attributes" field and by including critical information within this - * field, such as whether or not the region is enabled. A caller who - * passes in only a 20-byte buffer therefore risks getting very, very - * misleading information. - * - * I have personally witnessed an HP BIOS that returns a value of - * 0x0009 in the extended attributes field. If we don't pass this - * value through to the caller, 32-bit WinPE will die, usually with a - * PAGE_FAULT_IN_NONPAGED_AREA blue screen of death. - * - * Allow a ridiculously large maximum value (64 bytes) for the E820 - * buffer as a guard against insufficiently creative idiots in the - * future. - */ -#define E820MAXSIZE 64 - -/**************************************************************************** - * - * Allowed memory windows - * - * There are two ways to view this list. The first is as a list of - * (non-overlapping) allowed memory regions, sorted by increasing - * address. The second is as a list of (non-overlapping) hidden - * memory regions, again sorted by increasing address. The second - * view is offset by half an entry from the first: think about this - * for a moment and it should make sense. - * - * xxx_memory_window is used to indicate an "allowed region" - * structure, hidden_xxx_memory is used to indicate a "hidden region" - * structure. Each structure is 16 bytes in length. - * - **************************************************************************** - */ - .section ".data16", "aw", @progbits - .align 16 - .globl hidemem_base - .globl hidemem_umalloc - .globl hidemem_textdata -memory_windows: -base_memory_window: .long 0x00000000, 0x00000000 /* Start of memory */ - -hidemem_base: .long 0x000a0000, 0x00000000 /* Changes at runtime */ -ext_memory_window: .long 0x000a0000, 0x00000000 /* 640kB mark */ - -hidemem_umalloc: .long 0xffffffff, 0xffffffff /* Changes at runtime */ - .long 0xffffffff, 0xffffffff /* Changes at runtime */ - -hidemem_textdata: .long 0xffffffff, 0xffffffff /* Changes at runtime */ - .long 0xffffffff, 0xffffffff /* Changes at runtime */ - - .long 0xffffffff, 0xffffffff /* End of memory */ -memory_windows_end: - -/**************************************************************************** - * Truncate region to memory window - * - * Parameters: - * %edx:%eax Start of region - * %ecx:%ebx Length of region - * %si Memory window - * Returns: - * %edx:%eax Start of windowed region - * %ecx:%ebx Length of windowed region - **************************************************************************** - */ - .section ".text16", "ax", @progbits -window_region: - /* Convert (start,len) to (start, end) */ - addl %eax, %ebx - adcl %edx, %ecx - /* Truncate to window start */ - cmpl 4(%si), %edx - jne 1f - cmpl 0(%si), %eax -1: jae 2f - movl 4(%si), %edx - movl 0(%si), %eax -2: /* Truncate to window end */ - cmpl 12(%si), %ecx - jne 1f - cmpl 8(%si), %ebx -1: jbe 2f - movl 12(%si), %ecx - movl 8(%si), %ebx -2: /* Convert (start, end) back to (start, len) */ - subl %eax, %ebx - sbbl %edx, %ecx - /* If length is <0, set length to 0 */ - jae 1f - xorl %ebx, %ebx - xorl %ecx, %ecx - ret - .size window_region, . - window_region - -/**************************************************************************** - * Patch "memory above 1MB" figure - * - * Parameters: - * %ax Memory above 1MB, in 1kB blocks - * Returns: - * %ax Modified memory above 1M in 1kB blocks - **************************************************************************** - */ - .section ".text16", "ax", @progbits -patch_1m: - pushal - /* Convert to (start,len) format and call truncate */ - xorl %ecx, %ecx - movzwl %ax, %ebx - shll $10, %ebx - xorl %edx, %edx - movl $0x100000, %eax - movw $ext_memory_window, %si - call window_region - /* Convert back to "memory above 1MB" format and return via %ax */ - pushfw - shrl $10, %ebx - popfw - movw %sp, %bp - movw %bx, 28(%bp) - popal - ret - .size patch_1m, . - patch_1m - -/**************************************************************************** - * Patch "memory above 16MB" figure - * - * Parameters: - * %bx Memory above 16MB, in 64kB blocks - * Returns: - * %bx Modified memory above 16M in 64kB blocks - **************************************************************************** - */ - .section ".text16", "ax", @progbits -patch_16m: - pushal - /* Convert to (start,len) format and call truncate */ - xorl %ecx, %ecx - shll $16, %ebx - xorl %edx, %edx - movl $0x1000000, %eax - movw $ext_memory_window, %si - call window_region - /* Convert back to "memory above 16MB" format and return via %bx */ - pushfw - shrl $16, %ebx - popfw - movw %sp, %bp - movw %bx, 16(%bp) - popal - ret - .size patch_16m, . - patch_16m - -/**************************************************************************** - * Patch "memory between 1MB and 16MB" and "memory above 16MB" figures - * - * Parameters: - * %ax Memory between 1MB and 16MB, in 1kB blocks - * %bx Memory above 16MB, in 64kB blocks - * Returns: - * %ax Modified memory between 1MB and 16MB, in 1kB blocks - * %bx Modified memory above 16MB, in 64kB blocks - **************************************************************************** - */ - .section ".text16", "ax", @progbits -patch_1m_16m: - call patch_1m - call patch_16m - /* If 1M region is no longer full-length, kill off the 16M region */ - cmpw $( 15 * 1024 ), %ax - je 1f - xorw %bx, %bx -1: ret - .size patch_1m_16m, . - patch_1m_16m - -/**************************************************************************** - * Get underlying e820 memory region to underlying_e820 buffer - * - * Parameters: - * As for INT 15,e820 - * Returns: - * As for INT 15,e820 - * - * Wraps the underlying INT 15,e820 call so that the continuation - * value (%ebx) is a 16-bit simple sequence counter (with the high 16 - * bits ignored), and termination is always via CF=1 rather than - * %ebx=0. - * - **************************************************************************** - */ - .section ".text16", "ax", @progbits -get_underlying_e820: - - /* If the requested region is in the cache, return it */ - cmpw %bx, underlying_e820_index - jne 2f - pushw %di - pushw %si - movw $underlying_e820_cache, %si - cmpl underlying_e820_cache_size, %ecx - jbe 1f - movl underlying_e820_cache_size, %ecx -1: pushl %ecx - rep movsb - popl %ecx - popw %si - popw %di - incw %bx - movl %edx, %eax - clc - ret -2: - /* If the requested region is earlier than the cached region, - * invalidate the cache. - */ - cmpw %bx, underlying_e820_index - jbe 1f - movw $0xffff, underlying_e820_index -1: - /* If the cache is invalid, reset the underlying %ebx */ - cmpw $0xffff, underlying_e820_index - jne 1f - andl $0, underlying_e820_ebx -1: - /* If the cache is valid but the continuation value is zero, - * this means that the previous underlying call returned with - * %ebx=0. Return with CF=1 in this case. - */ - cmpw $0xffff, underlying_e820_index - je 1f - cmpl $0, underlying_e820_ebx - jne 1f - stc - ret -1: - /* Get the next region into the cache */ - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi /* Some implementations corrupt %esi, so we */ - pushl %edi /* preserve %esi, %edi and %ebp to be paranoid */ - pushl %ebp - pushw %es - pushw %ds - popw %es - movw $underlying_e820_cache, %di - cmpl $E820MAXSIZE, %ecx - jbe 1f - movl $E820MAXSIZE, %ecx -1: movl underlying_e820_ebx, %ebx - stc - pushfw - lcall *%cs:int15_vector - popw %es - popl %ebp - popl %edi - popl %esi - /* Check for error return from underlying e820 call */ - jc 2f /* CF set: error */ - cmpl $SMAP, %eax - je 3f /* 'SMAP' missing: error */ -2: /* An error occurred: return values returned by underlying e820 call */ - stc /* Force CF set if SMAP was missing */ - addr32 leal 16(%esp), %esp /* avoid changing other flags */ - ret -3: /* No error occurred */ - movl %ebx, underlying_e820_ebx - movl %ecx, underlying_e820_cache_size - popl %edx - popl %ecx - popl %ebx - popl %eax - /* Mark cache as containing this result */ - incw underlying_e820_index - - /* Loop until found */ - jmp get_underlying_e820 - .size get_underlying_e820, . - get_underlying_e820 - - .section ".data16", "aw", @progbits -underlying_e820_index: - .word 0xffff /* Initialise to an invalid value */ - .size underlying_e820_index, . - underlying_e820_index - - .section ".bss16", "aw", @nobits -underlying_e820_ebx: - .long 0 - .size underlying_e820_ebx, . - underlying_e820_ebx - - .section ".bss16", "aw", @nobits -underlying_e820_cache: - .space E820MAXSIZE - .size underlying_e820_cache, . - underlying_e820_cache - - .section ".bss16", "aw", @nobits -underlying_e820_cache_size: - .long 0 - .size underlying_e820_cache_size, . - underlying_e820_cache_size - -/**************************************************************************** - * Get windowed e820 region, without empty region stripping - * - * Parameters: - * As for INT 15,e820 - * Returns: - * As for INT 15,e820 - * - * Wraps the underlying INT 15,e820 call so that each underlying - * region is returned N times, windowed to fit within N visible-memory - * windows. Termination is always via CF=1. - * - **************************************************************************** - */ - .section ".text16", "ax", @progbits -get_windowed_e820: - - /* Preserve registers */ - pushl %esi - pushw %bp - - /* Split %ebx into %si:%bx, store original %bx in %bp */ - pushl %ebx - popw %bp - popw %si - - /* %si == 0 => start of memory_windows list */ - testw %si, %si - jne 1f - movw $memory_windows, %si -1: - /* Get (cached) underlying e820 region to buffer */ - call get_underlying_e820 - jc 99f /* Abort on error */ - - /* Preserve registers */ - pushal - /* start => %edx:%eax, len => %ecx:%ebx */ - movl %es:0(%di), %eax - movl %es:4(%di), %edx - movl %es:8(%di), %ebx - movl %es:12(%di), %ecx - /* Truncate region to current window */ - call window_region -1: /* Store modified values in e820 map entry */ - movl %eax, %es:0(%di) - movl %edx, %es:4(%di) - movl %ebx, %es:8(%di) - movl %ecx, %es:12(%di) - /* Restore registers */ - popal - - /* Derive continuation value for next call */ - addw $16, %si - cmpw $memory_windows_end, %si - jne 1f - /* End of memory windows: reset %si and allow %bx to continue */ - xorw %si, %si - jmp 2f -1: /* More memory windows to go: restore original %bx */ - movw %bp, %bx -2: /* Construct %ebx from %si:%bx */ - pushw %si - pushw %bx - popl %ebx - -98: /* Clear CF */ - clc -99: /* Restore registers and return */ - popw %bp - popl %esi - ret - .size get_windowed_e820, . - get_windowed_e820 - -/**************************************************************************** - * Get windowed e820 region, with empty region stripping - * - * Parameters: - * As for INT 15,e820 - * Returns: - * As for INT 15,e820 - * - * Wraps the underlying INT 15,e820 call so that each underlying - * region is returned up to N times, windowed to fit within N - * visible-memory windows. Empty windows are never returned. - * Termination is always via CF=1. - * - **************************************************************************** - */ - .section ".text16", "ax", @progbits -get_nonempty_e820: - - /* Record entry parameters */ - pushl %eax - pushl %ecx - pushl %edx - - /* Get next windowed region */ - call get_windowed_e820 - jc 99f /* abort on error */ - - /* If region is non-empty, finish here */ - cmpl $0, %es:8(%di) - jne 98f - cmpl $0, %es:12(%di) - jne 98f - - /* Region was empty: restore entry parameters and go to next region */ - popl %edx - popl %ecx - popl %eax - jmp get_nonempty_e820 - -98: /* Clear CF */ - clc -99: /* Return values from underlying call */ - addr32 leal 12(%esp), %esp /* avoid changing flags */ - ret - .size get_nonempty_e820, . - get_nonempty_e820 - -/**************************************************************************** - * Get mangled e820 region, with empty region stripping - * - * Parameters: - * As for INT 15,e820 - * Returns: - * As for INT 15,e820 - * - * Wraps the underlying INT 15,e820 call so that underlying regions - * are windowed to the allowed memory regions. Empty regions are - * stripped from the map. Termination is always via %ebx=0. - * - **************************************************************************** - */ - .section ".text16", "ax", @progbits -get_mangled_e820: - - /* Get a nonempty region */ - call get_nonempty_e820 - jc 99f /* Abort on error */ - - /* Peek ahead to see if there are any further nonempty regions */ - pushal - pushw %es - movw %sp, %bp - subw %cx, %sp - movl $0xe820, %eax - movl $SMAP, %edx - pushw %ss - popw %es - movw %sp, %di - call get_nonempty_e820 - movw %bp, %sp - popw %es - popal - jnc 99f /* There are further nonempty regions */ - - /* No futher nonempty regions: zero %ebx and clear CF */ - xorl %ebx, %ebx - -99: /* Return */ - ret - .size get_mangled_e820, . - get_mangled_e820 - -/**************************************************************************** - * Set/clear CF on the stack as appropriate, assumes stack is as it should - * be immediately before IRET - **************************************************************************** - */ -patch_cf: - pushw %bp - movw %sp, %bp - setc 8(%bp) /* Set/reset CF; clears PF, AF, ZF, SF */ - popw %bp - ret - -/**************************************************************************** - * INT 15,e820 handler - **************************************************************************** - */ - .section ".text16", "ax", @progbits -int15_e820: - pushw %ds - pushw %cs:rm_ds - popw %ds - call get_mangled_e820 - popw %ds - call patch_cf - iret - .size int15_e820, . - int15_e820 - -/**************************************************************************** - * INT 15,e801 handler - **************************************************************************** - */ - .section ".text16", "ax", @progbits -int15_e801: - /* Call previous handler */ - pushfw - lcall *%cs:int15_vector - call patch_cf - /* Edit result */ - pushw %ds - pushw %cs:rm_ds - popw %ds - call patch_1m_16m - xchgw %ax, %cx - xchgw %bx, %dx - call patch_1m_16m - xchgw %ax, %cx - xchgw %bx, %dx - popw %ds - iret - .size int15_e801, . - int15_e801 - -/**************************************************************************** - * INT 15,88 handler - **************************************************************************** - */ - .section ".text16", "ax", @progbits -int15_88: - /* Call previous handler */ - pushfw - lcall *%cs:int15_vector - call patch_cf - /* Edit result */ - pushw %ds - pushw %cs:rm_ds - popw %ds - call patch_1m - popw %ds - iret - .size int15_88, . - int15_88 - -/**************************************************************************** - * INT 15 handler - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .globl int15 -int15: - /* See if we want to intercept this call */ - pushfw - cmpw $0xe820, %ax - jne 1f - cmpl $SMAP, %edx - jne 1f - popfw - jmp int15_e820 -1: cmpw $0xe801, %ax - jne 2f - popfw - jmp int15_e801 -2: cmpb $0x88, %ah - jne 3f - popfw - jmp int15_88 -3: popfw - ljmp *%cs:int15_vector - .size int15, . - int15 - - .section ".text16.data", "aw", @progbits - .globl int15_vector -int15_vector: - .long 0 - .size int15_vector, . - int15_vector diff --git a/gpxe/src/arch/i386/firmware/pcbios/fakee820.c b/gpxe/src/arch/i386/firmware/pcbios/fakee820.c deleted file mode 100644 index ea116fe5..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/fakee820.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <realmode.h> -#include <biosint.h> - -/** Assembly routine in inline asm */ -extern void int15_fakee820(); - -/** Original INT 15 handler */ -static struct segoff __text16 ( real_int15_vector ); -#define real_int15_vector __use_text16 ( real_int15_vector ) - -/** An INT 15,e820 memory map entry */ -struct e820_entry { - /** Start of region */ - uint64_t start; - /** Length of region */ - uint64_t len; - /** Type of region */ - uint32_t type; -} __attribute__ (( packed )); - -#define E820_TYPE_RAM 1 /**< Normal memory */ -#define E820_TYPE_RSVD 2 /**< Reserved and unavailable */ -#define E820_TYPE_ACPI 3 /**< ACPI reclaim memory */ -#define E820_TYPE_NVS 4 /**< ACPI NVS memory */ - -/** Fake e820 map */ -static struct e820_entry __text16_array ( e820map, [] ) __used = { - { 0x00000000ULL, ( 0x000a0000ULL - 0x00000000ULL ), E820_TYPE_RAM }, - { 0x00100000ULL, ( 0xcfb50000ULL - 0x00100000ULL ), E820_TYPE_RAM }, - { 0xcfb50000ULL, ( 0xcfb64000ULL - 0xcfb50000ULL ), E820_TYPE_RSVD }, - { 0xcfb64000ULL, ( 0xcfb66000ULL - 0xcfb64000ULL ), E820_TYPE_RSVD }, - { 0xcfb66000ULL, ( 0xcfb85c00ULL - 0xcfb66000ULL ), E820_TYPE_ACPI }, - { 0xcfb85c00ULL, ( 0xd0000000ULL - 0xcfb85c00ULL ), E820_TYPE_RSVD }, - { 0xe0000000ULL, ( 0xf0000000ULL - 0xe0000000ULL ), E820_TYPE_RSVD }, - { 0xfe000000ULL, (0x100000000ULL - 0xfe000000ULL ), E820_TYPE_RSVD }, - {0x100000000ULL, (0x230000000ULL -0x100000000ULL ), E820_TYPE_RAM }, -}; -#define e820map __use_text16 ( e820map ) - -void fake_e820 ( void ) { - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint15_fakee820:\n\t" - "pushfw\n\t" - "cmpl $0xe820, %%eax\n\t" - "jne 99f\n\t" - "cmpl $0x534d4150, %%edx\n\t" - "jne 99f\n\t" - "pushaw\n\t" - "movw %%sp, %%bp\n\t" - "andb $~0x01, 22(%%bp)\n\t" /* Clear return CF */ - "leaw e820map(%%bx), %%si\n\t" - "cs rep movsb\n\t" - "popaw\n\t" - "movl %%edx, %%eax\n\t" - "addl $20, %%ebx\n\t" - "cmpl %0, %%ebx\n\t" - "jne 1f\n\t" - "xorl %%ebx,%%ebx\n\t" - "\n1:\n\t" - "popfw\n\t" - "iret\n\t" - "\n99:\n\t" - "popfw\n\t" - "ljmp *%%cs:real_int15_vector\n\t" ) - : : "i" ( sizeof ( e820map ) ) ); - - hook_bios_interrupt ( 0x15, ( unsigned int ) int15_fakee820, - &real_int15_vector ); -} - -void unfake_e820 ( void ) { - unhook_bios_interrupt ( 0x15, ( unsigned int ) int15_fakee820, - &real_int15_vector ); -} diff --git a/gpxe/src/arch/i386/firmware/pcbios/gateA20.c b/gpxe/src/arch/i386/firmware/pcbios/gateA20.c deleted file mode 100644 index 1a71472d..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/gateA20.c +++ /dev/null @@ -1,176 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdio.h> -#include <realmode.h> -#include <bios.h> -#include <gpxe/io.h> -#include <gpxe/timer.h> - -#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ -#define K_STATUS 0x64 /* keyboard status */ -#define K_CMD 0x64 /* keybd ctlr command (write-only) */ - -#define K_OBUF_FUL 0x01 /* output buffer full */ -#define K_IBUF_FUL 0x02 /* input buffer full */ - -#define KC_CMD_WIN 0xd0 /* read output port */ -#define KC_CMD_WOUT 0xd1 /* write output port */ -#define KC_CMD_NULL 0xff /* null command ("pulse nothing") */ -#define KB_SET_A20 0xdf /* enable A20, - enable output buffer full interrupt - enable data line - disable clock line */ -#define KB_UNSET_A20 0xdd /* enable A20, - enable output buffer full interrupt - enable data line - disable clock line */ - -#define SCP_A 0x92 /* System Control Port A */ - -enum { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402, - Query_A20_Support = 0x2403 }; - -enum a20_methods { - A20_UNKNOWN = 0, - A20_INT15, - A20_KBC, - A20_SCPA, -}; - -#define A20_MAX_RETRIES 32 -#define A20_INT15_RETRIES 32 -#define A20_KBC_RETRIES (2^21) -#define A20_SCPA_RETRIES (2^21) - -/** - * Drain keyboard controller - */ -static void empty_8042 ( void ) { - unsigned long time; - - time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */ - while ( ( inb ( K_CMD ) & ( K_IBUF_FUL | K_OBUF_FUL ) ) && - currticks() < time ) { - iodelay(); - ( void ) inb_p ( K_RDWR ); - iodelay(); - } -} - -/** - * Fast test to see if gate A20 is already set - * - * @v retries Number of times to retry before giving up - * @ret set Gate A20 is set - */ -static int gateA20_is_set ( int retries ) { - static uint32_t test_pattern = 0xdeadbeef; - physaddr_t test_pattern_phys = virt_to_phys ( &test_pattern ); - physaddr_t verify_pattern_phys = ( test_pattern_phys ^ 0x100000 ); - userptr_t verify_pattern_user = phys_to_user ( verify_pattern_phys ); - uint32_t verify_pattern; - - do { - /* Check for difference */ - copy_from_user ( &verify_pattern, verify_pattern_user, 0, - sizeof ( verify_pattern ) ); - if ( verify_pattern != test_pattern ) - return 1; - - /* Avoid false negatives */ - test_pattern++; - - iodelay(); - - /* Always retry at least once, to avoid false negatives */ - } while ( retries-- >= 0 ); - - /* Pattern matched every time; gate A20 is not set */ - return 0; -} - -/* - * Gate A20 for high memory - * - * Note that this function gets called as part of the return path from - * librm's real_call, which is used to make the int15 call if librm is - * being used. To avoid an infinite recursion, we make gateA20_set - * return immediately if it is already part of the call stack. - */ -void gateA20_set ( void ) { - static char reentry_guard = 0; - static int a20_method = A20_UNKNOWN; - unsigned int discard_a; - unsigned int scp_a; - int retries = 0; - - /* Avoid potential infinite recursion */ - if ( reentry_guard ) - return; - reentry_guard = 1; - - /* Fast check to see if gate A20 is already enabled */ - if ( gateA20_is_set ( 0 ) ) - goto out; - - for ( ; retries < A20_MAX_RETRIES ; retries++ ) { - switch ( a20_method ) { - case A20_UNKNOWN: - case A20_INT15: - /* Try INT 15 method */ - __asm__ __volatile__ ( REAL_CODE ( "int $0x15" ) - : "=a" ( discard_a ) - : "a" ( Enable_A20 ) ); - if ( gateA20_is_set ( A20_INT15_RETRIES ) ) { - DBG ( "Enabled gate A20 using BIOS\n" ); - a20_method = A20_INT15; - goto out; - } - /* fall through */ - case A20_KBC: - /* Try keyboard controller method */ - empty_8042(); - outb ( KC_CMD_WOUT, K_CMD ); - empty_8042(); - outb ( KB_SET_A20, K_RDWR ); - empty_8042(); - outb ( KC_CMD_NULL, K_CMD ); - empty_8042(); - if ( gateA20_is_set ( A20_KBC_RETRIES ) ) { - DBG ( "Enabled gate A20 using " - "keyboard controller\n" ); - a20_method = A20_KBC; - goto out; - } - /* fall through */ - case A20_SCPA: - /* Try "Fast gate A20" method */ - scp_a = inb ( SCP_A ); - scp_a &= ~0x01; /* Avoid triggering a reset */ - scp_a |= 0x02; /* Enable A20 */ - iodelay(); - outb ( scp_a, SCP_A ); - iodelay(); - if ( gateA20_is_set ( A20_SCPA_RETRIES ) ) { - DBG ( "Enabled gate A20 using " - "Fast Gate A20\n" ); - a20_method = A20_SCPA; - goto out; - } - } - } - - /* Better to die now than corrupt memory later */ - printf ( "FATAL: Gate A20 stuck\n" ); - while ( 1 ) {} - - out: - if ( retries ) - DBG ( "%d attempts were required to enable A20\n", - ( retries + 1 ) ); - reentry_guard = 0; -} - -void gateA20_unset ( void ) { - /* Not currently implemented */ -} diff --git a/gpxe/src/arch/i386/firmware/pcbios/hidemem.c b/gpxe/src/arch/i386/firmware/pcbios/hidemem.c deleted file mode 100644 index 17082c35..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/hidemem.c +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <assert.h> -#include <realmode.h> -#include <biosint.h> -#include <basemem.h> -#include <fakee820.h> -#include <gpxe/init.h> -#include <gpxe/memmap.h> -#include <gpxe/hidemem.h> - -/** Set to true if you want to test a fake E820 map */ -#define FAKE_E820 0 - -/** Alignment for hidden memory regions */ -#define ALIGN_HIDDEN 4096 /* 4kB page alignment should be enough */ - -/** - * A hidden region of gPXE - * - * This represents a region that will be edited out of the system's - * memory map. - * - * This structure is accessed by assembly code, so must not be - * changed. - */ -struct hidden_region { - /** Physical start address */ - uint64_t start; - /** Physical end address */ - uint64_t end; -}; - -/** Hidden base memory */ -extern struct hidden_region __data16 ( hidemem_base ); -#define hidemem_base __use_data16 ( hidemem_base ) - -/** Hidden umalloc memory */ -extern struct hidden_region __data16 ( hidemem_umalloc ); -#define hidemem_umalloc __use_data16 ( hidemem_umalloc ) - -/** Hidden text memory */ -extern struct hidden_region __data16 ( hidemem_textdata ); -#define hidemem_textdata __use_data16 ( hidemem_textdata ) - -/** Assembly routine in e820mangler.S */ -extern void int15(); - -/** Vector for storing original INT 15 handler */ -extern struct segoff __text16 ( int15_vector ); -#define int15_vector __use_text16 ( int15_vector ) - -/* The linker defines these symbols for us */ -extern char _textdata[]; -extern char _etextdata[]; -extern char _text16_memsz[]; -#define _text16_memsz ( ( unsigned int ) _text16_memsz ) -extern char _data16_memsz[]; -#define _data16_memsz ( ( unsigned int ) _data16_memsz ) - -/** - * Hide region of memory from system memory map - * - * @v region Hidden memory region - * @v start Start of region - * @v end End of region - */ -static void hide_region ( struct hidden_region *region, - physaddr_t start, physaddr_t end ) { - - /* Some operating systems get a nasty shock if a region of the - * E820 map seems to start on a non-page boundary. Make life - * safer by rounding out our edited region. - */ - region->start = ( start & ~( ALIGN_HIDDEN - 1 ) ); - region->end = ( ( end + ALIGN_HIDDEN - 1 ) & ~( ALIGN_HIDDEN - 1 ) ); - - DBG ( "Hiding region [%llx,%llx)\n", region->start, region->end ); -} - -/** - * Hide used base memory - * - */ -void hide_basemem ( void ) { - /* Hide from the top of free base memory to 640kB. Don't use - * hide_region(), because we don't want this rounded to the - * nearest page boundary. - */ - hidemem_base.start = ( get_fbms() * 1024 ); -} - -/** - * Hide umalloc() region - * - */ -void hide_umalloc ( physaddr_t start, physaddr_t end ) { - assert ( end <= virt_to_phys ( _textdata ) ); - hide_region ( &hidemem_umalloc, start, end ); -} - -/** - * Hide .text and .data - * - */ -void hide_textdata ( void ) { - hide_region ( &hidemem_textdata, virt_to_phys ( _textdata ), - virt_to_phys ( _etextdata ) ); -} - -/** - * Hide Etherboot - * - * Installs an INT 15 handler to edit Etherboot out of the memory map - * returned by the BIOS. - */ -static void hide_etherboot ( void ) { - struct memory_map memmap; - unsigned int rm_ds_top; - unsigned int rm_cs_top; - unsigned int fbms; - - /* Dump memory map before mangling */ - DBG ( "Hiding gPXE from system memory map\n" ); - get_memmap ( &memmap ); - - /* Hook in fake E820 map, if we're testing one */ - if ( FAKE_E820 ) { - DBG ( "Hooking in fake E820 map\n" ); - fake_e820(); - get_memmap ( &memmap ); - } - - /* Initialise the hidden regions */ - hide_basemem(); - hide_umalloc ( virt_to_phys ( _textdata ), virt_to_phys ( _textdata ) ); - hide_textdata(); - - /* Some really moronic BIOSes bring up the PXE stack via the - * UNDI loader entry point and then don't bother to unload it - * before overwriting the code and data segments. If this - * happens, we really don't want to leave INT 15 hooked, - * because that will cause any loaded OS to die horribly as - * soon as it attempts to fetch the system memory map. - * - * We use a heuristic to guess whether or not we are being - * loaded sensibly. - */ - rm_cs_top = ( ( ( rm_cs << 4 ) + _text16_memsz + 1024 - 1 ) >> 10 ); - rm_ds_top = ( ( ( rm_ds << 4 ) + _data16_memsz + 1024 - 1 ) >> 10 ); - fbms = get_fbms(); - if ( ( rm_cs_top < fbms ) && ( rm_ds_top < fbms ) ) { - DBG ( "Detected potentially unsafe UNDI load at CS=%04x " - "DS=%04x FBMS=%dkB\n", rm_cs, rm_ds, fbms ); - DBG ( "Disabling INT 15 memory hiding\n" ); - return; - } - - /* Hook INT 15 */ - hook_bios_interrupt ( 0x15, ( unsigned int ) int15, - &int15_vector ); - - /* Dump memory map after mangling */ - DBG ( "Hidden gPXE from system memory map\n" ); - get_memmap ( &memmap ); -} - -/** - * Unhide Etherboot - * - * Uninstalls the INT 15 handler installed by hide_etherboot(), if - * possible. - */ -static void unhide_etherboot ( int flags __unused ) { - - /* If we have more than one hooked interrupt at this point, it - * means that some other vector is still hooked, in which case - * we can't safely unhook INT 15 because we need to keep our - * memory protected. (We expect there to be at least one - * hooked interrupt, because INT 15 itself is still hooked). - */ - if ( hooked_bios_interrupts > 1 ) { - DBG ( "Cannot unhide: %d interrupt vectors still hooked\n", - hooked_bios_interrupts ); - 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 ); - - /* Unhook fake E820 map, if used */ - if ( FAKE_E820 ) - unfake_e820(); -} - -/** Hide Etherboot startup function */ -struct startup_fn hide_etherboot_startup_fn __startup_fn ( STARTUP_EARLY ) = { - .startup = hide_etherboot, - .shutdown = unhide_etherboot, -}; diff --git a/gpxe/src/arch/i386/firmware/pcbios/memmap.c b/gpxe/src/arch/i386/firmware/pcbios/memmap.c deleted file mode 100644 index 8a30dbae..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/memmap.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <errno.h> -#include <realmode.h> -#include <bios.h> -#include <memsizes.h> -#include <gpxe/memmap.h> - -/** - * @file - * - * Memory mapping - * - */ - -/** Magic value for INT 15,e820 calls */ -#define SMAP ( 0x534d4150 ) - -/** An INT 15,e820 memory map entry */ -struct e820_entry { - /** Start of region */ - uint64_t start; - /** Length of region */ - uint64_t len; - /** Type of region */ - uint32_t type; - /** Extended attributes (optional) */ - uint32_t attrs; -} __attribute__ (( packed )); - -#define E820_TYPE_RAM 1 /**< Normal memory */ -#define E820_TYPE_RESERVED 2 /**< Reserved and unavailable */ -#define E820_TYPE_ACPI 3 /**< ACPI reclaim memory */ -#define E820_TYPE_NVS 4 /**< ACPI NVS memory */ - -#define E820_ATTR_ENABLED 0x00000001UL -#define E820_ATTR_NONVOLATILE 0x00000002UL -#define E820_ATTR_UNKNOWN 0xfffffffcUL - -#define E820_MIN_SIZE 20 - -/** Buffer for INT 15,e820 calls */ -static struct e820_entry __bss16 ( e820buf ); -#define e820buf __use_data16 ( e820buf ) - -/** - * Get size of extended memory via INT 15,e801 - * - * @ret extmem Extended memory size, in kB, or 0 - */ -static unsigned int extmemsize_e801 ( void ) { - uint16_t extmem_1m_to_16m_k, extmem_16m_plus_64k; - uint16_t confmem_1m_to_16m_k, confmem_16m_plus_64k; - unsigned int flags; - unsigned int extmem; - - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" - "int $0x15\n\t" - "pushfw\n\t" - "popw %w0\n\t" ) - : "=r" ( flags ), - "=a" ( extmem_1m_to_16m_k ), - "=b" ( extmem_16m_plus_64k ), - "=c" ( confmem_1m_to_16m_k ), - "=d" ( confmem_16m_plus_64k ) - : "a" ( 0xe801 ) ); - - if ( flags & CF ) { - DBG ( "INT 15,e801 failed with CF set\n" ); - return 0; - } - - if ( ! ( extmem_1m_to_16m_k | extmem_16m_plus_64k ) ) { - DBG ( "INT 15,e801 extmem=0, using confmem\n" ); - extmem_1m_to_16m_k = confmem_1m_to_16m_k; - extmem_16m_plus_64k = confmem_16m_plus_64k; - } - - extmem = ( extmem_1m_to_16m_k + ( extmem_16m_plus_64k * 64 ) ); - DBG ( "INT 15,e801 extended memory size %d+64*%d=%d kB " - "[100000,%llx)\n", extmem_1m_to_16m_k, extmem_16m_plus_64k, - extmem, ( 0x100000 + ( ( ( uint64_t ) extmem ) * 1024 ) ) ); - - /* Sanity check. Some BIOSes report the entire 4GB address - * space as available, which cannot be correct (since that - * would leave no address space available for 32-bit PCI - * BARs). - */ - if ( extmem == ( 0x400000 - 0x400 ) ) { - DBG ( "INT 15,e801 reported whole 4GB; assuming insane\n" ); - return 0; - } - - return extmem; -} - -/** - * Get size of extended memory via INT 15,88 - * - * @ret extmem Extended memory size, in kB - */ -static unsigned int extmemsize_88 ( void ) { - uint16_t extmem; - - /* Ignore CF; it is not reliable for this call */ - __asm__ __volatile__ ( REAL_CODE ( "int $0x15" ) - : "=a" ( extmem ) : "a" ( 0x8800 ) ); - - DBG ( "INT 15,88 extended memory size %d kB [100000, %x)\n", - extmem, ( 0x100000 + ( extmem * 1024 ) ) ); - return extmem; -} - -/** - * Get size of extended memory - * - * @ret extmem Extended memory size, in kB - * - * Note that this is only an approximation; for an accurate picture, - * use the E820 memory map obtained via get_memmap(); - */ -unsigned int extmemsize ( void ) { - unsigned int extmem; - - /* Try INT 15,e801 first, then fall back to INT 15,88 */ - extmem = extmemsize_e801(); - if ( ! extmem ) - extmem = extmemsize_88(); - return extmem; -} - -/** - * Get e820 memory map - * - * @v memmap Memory map to fill in - * @ret rc Return status code - */ -static int meme820 ( struct memory_map *memmap ) { - struct memory_region *region = memmap->regions; - uint32_t next = 0; - uint32_t smap; - size_t size; - unsigned int flags; - unsigned int discard_D; - - /* Clear the E820 buffer. Do this once before starting, - * rather than on each call; some BIOSes rely on the contents - * being preserved between calls. - */ - memset ( &e820buf, 0, sizeof ( e820buf ) ); - - do { - /* Some BIOSes corrupt %esi for fun. Guard against - * this by telling gcc that all non-output registers - * may be corrupted. - */ - __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" - "stc\n\t" - "int $0x15\n\t" - "pushfw\n\t" - "popw %%dx\n\t" - "popl %%ebp\n\t" ) - : "=a" ( smap ), "=b" ( next ), - "=c" ( size ), "=d" ( flags ), - "=D" ( discard_D ) - : "a" ( 0xe820 ), "b" ( next ), - "D" ( __from_data16 ( &e820buf ) ), - "c" ( sizeof ( e820buf ) ), - "d" ( SMAP ) - : "esi", "memory" ); - - if ( smap != SMAP ) { - DBG ( "INT 15,e820 failed SMAP signature check\n" ); - return -ENOTSUP; - } - - if ( size < E820_MIN_SIZE ) { - DBG ( "INT 15,e820 returned only %zd bytes\n", size ); - return -EINVAL; - } - - if ( flags & CF ) { - DBG ( "INT 15,e820 terminated on CF set\n" ); - break; - } - - /* If first region is not RAM, assume map is invalid */ - if ( ( memmap->count == 0 ) && - ( e820buf.type != E820_TYPE_RAM ) ) { - DBG ( "INT 15,e820 failed, first entry not RAM\n" ); - return -EINVAL; - } - - DBG ( "INT 15,e820 region [%llx,%llx) type %d", - e820buf.start, ( e820buf.start + e820buf.len ), - ( int ) e820buf.type ); - if ( size > offsetof ( typeof ( e820buf ), attrs ) ) { - DBG ( " (%s", ( ( e820buf.attrs & E820_ATTR_ENABLED ) - ? "enabled" : "disabled" ) ); - if ( e820buf.attrs & E820_ATTR_NONVOLATILE ) - DBG ( ", non-volatile" ); - if ( e820buf.attrs & E820_ATTR_UNKNOWN ) - DBG ( ", other [%08x]", e820buf.attrs ); - DBG ( ")" ); - } - DBG ( "\n" ); - - /* Discard non-RAM regions */ - if ( e820buf.type != E820_TYPE_RAM ) - continue; - - /* Check extended attributes, if present */ - if ( size > offsetof ( typeof ( e820buf ), attrs ) ) { - if ( ! ( e820buf.attrs & E820_ATTR_ENABLED ) ) - continue; - if ( e820buf.attrs & E820_ATTR_NONVOLATILE ) - continue; - } - - region->start = e820buf.start; - region->end = e820buf.start + e820buf.len; - region++; - memmap->count++; - - if ( memmap->count >= ( sizeof ( memmap->regions ) / - sizeof ( memmap->regions[0] ) ) ) { - DBG ( "INT 15,e820 too many regions returned\n" ); - /* Not a fatal error; what we've got so far at - * least represents valid regions of memory, - * even if we couldn't get them all. - */ - break; - } - } while ( next != 0 ); - - /* Sanity checks. Some BIOSes report complete garbage via INT - * 15,e820 (especially at POST time), despite passing the - * signature checks. We currently check for a base memory - * region (starting at 0) and at least one high memory region - * (starting at 0x100000). - */ - if ( memmap->count < 2 ) { - DBG ( "INT 15,e820 returned only %d regions; assuming " - "insane\n", memmap->count ); - return -EINVAL; - } - if ( memmap->regions[0].start != 0 ) { - DBG ( "INT 15,e820 region 0 starts at %llx (expected 0); " - "assuming insane\n", memmap->regions[0].start ); - return -EINVAL; - } - if ( memmap->regions[1].start != 0x100000 ) { - DBG ( "INT 15,e820 region 1 starts at %llx (expected 100000); " - "assuming insane\n", memmap->regions[0].start ); - return -EINVAL; - } - - return 0; -} - -/** - * Get memory map - * - * @v memmap Memory map to fill in - */ -void get_memmap ( struct memory_map *memmap ) { - unsigned int basemem, extmem; - int rc; - - DBG ( "Fetching system memory map\n" ); - - /* Clear memory map */ - memset ( memmap, 0, sizeof ( *memmap ) ); - - /* Get base and extended memory sizes */ - basemem = basememsize(); - DBG ( "FBMS base memory size %d kB [0,%x)\n", - basemem, ( basemem * 1024 ) ); - extmem = extmemsize(); - - /* Try INT 15,e820 first */ - if ( ( rc = meme820 ( memmap ) ) == 0 ) { - DBG ( "Obtained system memory map via INT 15,e820\n" ); - return; - } - - /* Fall back to constructing a map from basemem and extmem sizes */ - DBG ( "INT 15,e820 failed; constructing map\n" ); - memmap->regions[0].end = ( basemem * 1024 ); - memmap->regions[1].start = 0x100000; - memmap->regions[1].end = 0x100000 + ( extmem * 1024 ); - memmap->count = 2; -} diff --git a/gpxe/src/arch/i386/firmware/pcbios/pnpbios.c b/gpxe/src/arch/i386/firmware/pcbios/pnpbios.c deleted file mode 100644 index c572914f..00000000 --- a/gpxe/src/arch/i386/firmware/pcbios/pnpbios.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <realmode.h> -#include <pnpbios.h> - -/** @file - * - * PnP BIOS - * - */ - -/** PnP BIOS structure */ -struct pnp_bios { - /** Signature - * - * Must be equal to @c PNP_BIOS_SIGNATURE - */ - uint32_t signature; - /** Version as BCD (e.g. 1.0 is 0x10) */ - uint8_t version; - /** Length of this structure */ - uint8_t length; - /** System capabilities */ - uint16_t control; - /** Checksum */ - uint8_t checksum; -} __attribute__ (( packed )); - -/** Signature for a PnP BIOS structure */ -#define PNP_BIOS_SIGNATURE \ - ( ( '$' << 0 ) + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) ) - -/** - * Test address for PnP BIOS structure - * - * @v offset Offset within BIOS segment to test - * @ret rc Return status code - */ -static int is_pnp_bios ( unsigned int offset ) { - union { - struct pnp_bios pnp_bios; - uint8_t bytes[256]; /* 256 is maximum length possible */ - } u; - size_t len; - unsigned int i; - uint8_t sum = 0; - - /* Read start of header and verify signature */ - copy_from_real ( &u.pnp_bios, BIOS_SEG, offset, sizeof ( u.pnp_bios )); - if ( u.pnp_bios.signature != PNP_BIOS_SIGNATURE ) - return -EINVAL; - - /* Read whole header and verify checksum */ - len = u.pnp_bios.length; - copy_from_real ( &u.bytes, BIOS_SEG, offset, len ); - for ( i = 0 ; i < len ; i++ ) { - sum += u.bytes[i]; - } - if ( sum != 0 ) - return -EINVAL; - - DBG ( "Found PnP BIOS at %04x:%04x\n", BIOS_SEG, offset ); - - return 0; -} - -/** - * Locate Plug-and-Play BIOS - * - * @ret pnp_offset Offset of PnP BIOS structure within BIOS segment - * - * The PnP BIOS structure will be at BIOS_SEG:pnp_offset. If no PnP - * BIOS is found, -1 is returned. - */ -int find_pnp_bios ( void ) { - static int pnp_offset = 0; - - if ( pnp_offset ) - return pnp_offset; - - for ( pnp_offset = 0 ; pnp_offset < 0x10000 ; pnp_offset += 0x10 ) { - if ( is_pnp_bios ( pnp_offset ) == 0 ) - return pnp_offset; - } - - pnp_offset = -1; - return pnp_offset; -} diff --git a/gpxe/src/arch/i386/hci/commands/pxe_cmd.c b/gpxe/src/arch/i386/hci/commands/pxe_cmd.c deleted file mode 100644 index b5df2d1b..00000000 --- a/gpxe/src/arch/i386/hci/commands/pxe_cmd.c +++ /dev/null @@ -1,33 +0,0 @@ -#include <gpxe/netdevice.h> -#include <gpxe/command.h> -#include <hci/ifmgmt_cmd.h> -#include <pxe_call.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -static int startpxe_payload ( struct net_device *netdev ) { - if ( netdev->state & NETDEV_OPEN ) - pxe_activate ( netdev ); - return 0; -} - -static int startpxe_exec ( int argc, char **argv ) { - return ifcommon_exec ( argc, argv, startpxe_payload, - "Activate PXE on" ); -} - -static int stoppxe_exec ( int argc __unused, char **argv __unused ) { - pxe_deactivate(); - return 0; -} - -struct command pxe_commands[] __command = { - { - .name = "startpxe", - .exec = startpxe_exec, - }, - { - .name = "stoppxe", - .exec = stoppxe_exec, - }, -}; diff --git a/gpxe/src/arch/i386/image/bootsector.c b/gpxe/src/arch/i386/image/bootsector.c deleted file mode 100644 index f96cf201..00000000 --- a/gpxe/src/arch/i386/image/bootsector.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * x86 bootsector image format - * - */ - -#include <errno.h> -#include <realmode.h> -#include <biosint.h> -#include <bootsector.h> - -/** Vector for storing original INT 18 handler - * - * We do not chain to this vector, so there is no need to place it in - * .text16. - */ -static struct segoff int18_vector; - -/** Vector for storing original INT 19 handler - * - * We do not chain to this vector, so there is no need to place it in - * .text16. - */ -static struct segoff int19_vector; - -/** Restart point for INT 18 or 19 */ -extern void bootsector_exec_fail ( void ); - -/** - * Jump to preloaded bootsector - * - * @v segment Real-mode segment - * @v offset Real-mode offset - * @v drive Drive number to pass to boot sector - * @ret rc Return status code - */ -int call_bootsector ( unsigned int segment, unsigned int offset, - unsigned int drive ) { - int discard_b, discard_D, discard_d; - - DBG ( "Booting from boot sector at %04x:%04x\n", segment, offset ); - - /* Hook INTs 18 and 19 to capture failure paths */ - hook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail, - &int18_vector ); - hook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail, - &int19_vector ); - - /* Boot the loaded sector - * - * We assume that the boot sector may completely destroy our - * real-mode stack, so we preserve everything we need in - * static storage. - */ - __asm__ __volatile__ ( REAL_CODE ( /* Save return address off-stack */ - "popw %%cs:saved_retaddr\n\t" - /* Save stack pointer */ - "movw %%ss, %%ax\n\t" - "movw %%ax, %%cs:saved_ss\n\t" - "movw %%sp, %%cs:saved_sp\n\t" - /* Jump to boot sector */ - "pushw %%bx\n\t" - "pushw %%di\n\t" - "sti\n\t" - "lret\n\t" - /* Preserved variables */ - "\nsaved_ss: .word 0\n\t" - "\nsaved_sp: .word 0\n\t" - "\nsaved_retaddr: .word 0\n\t" - /* Boot failure return point */ - "\nbootsector_exec_fail:\n\t" - /* Restore stack pointer */ - "movw %%cs:saved_ss, %%ax\n\t" - "movw %%ax, %%ss\n\t" - "movw %%cs:saved_sp, %%sp\n\t" - /* Return via saved address */ - "jmp *%%cs:saved_retaddr\n\t" ) - : "=b" ( discard_b ), "=D" ( discard_D ), - "=d" ( discard_d ) - : "b" ( segment ), "D" ( offset ), - "d" ( drive ) - : "eax", "ecx", "esi", "ebp" ); - - DBG ( "Booted disk returned via INT 18 or 19\n" ); - - /* Unhook INTs 18 and 19 */ - unhook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail, - &int18_vector ); - unhook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail, - &int19_vector ); - - return -ECANCELED; -} diff --git a/gpxe/src/arch/i386/image/bzimage.c b/gpxe/src/arch/i386/image/bzimage.c deleted file mode 100644 index 19450990..00000000 --- a/gpxe/src/arch/i386/image/bzimage.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * Linux bzImage image format - * - */ - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <realmode.h> -#include <bzimage.h> -#include <gpxe/uaccess.h> -#include <gpxe/image.h> -#include <gpxe/segment.h> -#include <gpxe/init.h> -#include <gpxe/cpio.h> -#include <gpxe/features.h> - -FEATURE ( FEATURE_IMAGE, "bzImage", DHCP_EB_FEATURE_BZIMAGE, 1 ); - -struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ); - -/** - * bzImage context - */ -struct bzimage_context { - /** Boot protocol version */ - unsigned int version; - /** Real-mode kernel portion load segment address */ - unsigned int rm_kernel_seg; - /** Real-mode kernel portion load address */ - userptr_t rm_kernel; - /** Real-mode kernel portion file size */ - size_t rm_filesz; - /** Real-mode heap top (offset from rm_kernel) */ - size_t rm_heap; - /** Command line (offset from rm_kernel) */ - size_t rm_cmdline; - /** Command line maximum length */ - size_t cmdline_size; - /** Real-mode kernel portion total memory size */ - size_t rm_memsz; - /** Non-real-mode kernel portion load address */ - userptr_t pm_kernel; - /** Non-real-mode kernel portion file and memory size */ - size_t pm_sz; - /** Video mode */ - unsigned int vid_mode; - /** Memory limit */ - uint64_t mem_limit; - /** Initrd address */ - physaddr_t ramdisk_image; - /** Initrd size */ - physaddr_t ramdisk_size; - - /** Command line magic block */ - struct bzimage_cmdline cmdline_magic; - /** bzImage header */ - struct bzimage_header bzhdr; -}; - -/** - * Parse bzImage header - * - * @v image bzImage file - * @v bzimg bzImage context - * @v src bzImage to parse - * @ret rc Return status code - */ -static int bzimage_parse_header ( struct image *image, - struct bzimage_context *bzimg, - userptr_t src ) { - unsigned int syssize; - int is_bzimage; - - /* Sanity check */ - if ( image->len < ( BZI_HDR_OFFSET + sizeof ( bzimg->bzhdr ) ) ) { - DBGC ( image, "bzImage %p too short for kernel header\n", - image ); - return -ENOEXEC; - } - - /* Read in header structures */ - memset ( bzimg, 0, sizeof ( *bzimg ) ); - copy_from_user ( &bzimg->cmdline_magic, src, BZI_CMDLINE_OFFSET, - sizeof ( bzimg->cmdline_magic ) ); - copy_from_user ( &bzimg->bzhdr, src, BZI_HDR_OFFSET, - sizeof ( bzimg->bzhdr ) ); - - /* Calculate size of real-mode portion */ - bzimg->rm_filesz = - ( ( bzimg->bzhdr.setup_sects ? bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9; - if ( bzimg->rm_filesz > image->len ) { - DBGC ( image, "bzImage %p too short for %zd byte of setup\n", - image, bzimg->rm_filesz ); - return -ENOEXEC; - } - bzimg->rm_memsz = BZI_ASSUMED_RM_SIZE; - - /* Calculate size of protected-mode portion */ - bzimg->pm_sz = ( image->len - bzimg->rm_filesz ); - syssize = ( ( bzimg->pm_sz + 15 ) / 16 ); - - /* Check for signatures and determine version */ - if ( bzimg->bzhdr.boot_flag != BZI_BOOT_FLAG ) { - DBGC ( image, "bzImage %p missing 55AA signature\n", image ); - return -ENOEXEC; - } - if ( bzimg->bzhdr.header == BZI_SIGNATURE ) { - /* 2.00+ */ - bzimg->version = bzimg->bzhdr.version; - } else { - /* Pre-2.00. Check that the syssize field is correct, - * as a guard against accepting arbitrary binary data, - * since the 55AA check is pretty lax. Note that the - * syssize field is unreliable for protocols between - * 2.00 and 2.03 inclusive, so we should not always - * check this field. - */ - bzimg->version = 0x0100; - if ( bzimg->bzhdr.syssize != syssize ) { - DBGC ( image, "bzImage %p bad syssize %x (expected " - "%x)\n", image, bzimg->bzhdr.syssize, syssize ); - return -ENOEXEC; - } - } - - /* Determine image type */ - is_bzimage = ( ( bzimg->version >= 0x0200 ) ? - ( bzimg->bzhdr.loadflags & BZI_LOAD_HIGH ) : 0 ); - - /* Calculate load address of real-mode portion */ - bzimg->rm_kernel_seg = ( is_bzimage ? 0x1000 : 0x9000 ); - bzimg->rm_kernel = real_to_user ( bzimg->rm_kernel_seg, 0 ); - - /* Allow space for the stack and heap */ - bzimg->rm_memsz += BZI_STACK_SIZE; - bzimg->rm_heap = bzimg->rm_memsz; - - /* Allow space for the command line */ - bzimg->rm_cmdline = bzimg->rm_memsz; - bzimg->rm_memsz += BZI_CMDLINE_SIZE; - - /* Calculate load address of protected-mode portion */ - bzimg->pm_kernel = phys_to_user ( is_bzimage ? BZI_LOAD_HIGH_ADDR - : BZI_LOAD_LOW_ADDR ); - - /* Extract video mode */ - bzimg->vid_mode = bzimg->bzhdr.vid_mode; - - /* Extract memory limit */ - bzimg->mem_limit = ( ( bzimg->version >= 0x0203 ) ? - bzimg->bzhdr.initrd_addr_max : BZI_INITRD_MAX ); - - /* Extract command line size */ - bzimg->cmdline_size = ( ( bzimg->version >= 0x0206 ) ? - bzimg->bzhdr.cmdline_size : BZI_CMDLINE_SIZE ); - - DBGC ( image, "bzImage %p version %04x RM %#lx+%#zx PM %#lx+%#zx " - "cmdlen %zd\n", image, bzimg->version, - user_to_phys ( bzimg->rm_kernel, 0 ), bzimg->rm_filesz, - user_to_phys ( bzimg->pm_kernel, 0 ), bzimg->pm_sz, - bzimg->cmdline_size ); - - return 0; -} - -/** - * Update bzImage header in loaded kernel - * - * @v image bzImage file - * @v bzimg bzImage context - * @v dst bzImage to update - */ -static void bzimage_update_header ( struct image *image, - struct bzimage_context *bzimg, - userptr_t dst ) { - - /* Set loader type */ - if ( bzimg->version >= 0x0200 ) - bzimg->bzhdr.type_of_loader = BZI_LOADER_TYPE_GPXE; - - /* Set heap end pointer */ - if ( bzimg->version >= 0x0201 ) { - bzimg->bzhdr.heap_end_ptr = ( bzimg->rm_heap - 0x200 ); - bzimg->bzhdr.loadflags |= BZI_CAN_USE_HEAP; - } - - /* Set command line */ - if ( bzimg->version >= 0x0202 ) { - bzimg->bzhdr.cmd_line_ptr = user_to_phys ( bzimg->rm_kernel, - bzimg->rm_cmdline ); - } else { - bzimg->cmdline_magic.magic = BZI_CMDLINE_MAGIC; - bzimg->cmdline_magic.offset = bzimg->rm_cmdline; - bzimg->bzhdr.setup_move_size = bzimg->rm_memsz; - } - - /* Set video mode */ - bzimg->bzhdr.vid_mode = bzimg->vid_mode; - - /* Set initrd address */ - if ( bzimg->version >= 0x0200 ) { - bzimg->bzhdr.ramdisk_image = bzimg->ramdisk_image; - bzimg->bzhdr.ramdisk_size = bzimg->ramdisk_size; - } - - /* Write out header structures */ - copy_to_user ( dst, BZI_CMDLINE_OFFSET, &bzimg->cmdline_magic, - sizeof ( bzimg->cmdline_magic ) ); - copy_to_user ( dst, BZI_HDR_OFFSET, &bzimg->bzhdr, - sizeof ( bzimg->bzhdr ) ); - - DBGC ( image, "bzImage %p vidmode %d\n", image, bzimg->vid_mode ); -} - -/** - * Parse kernel command line for bootloader parameters - * - * @v image bzImage file - * @v bzimg bzImage context - * @v cmdline Kernel command line - * @ret rc Return status code - */ -static int bzimage_parse_cmdline ( struct image *image, - struct bzimage_context *bzimg, - const char *cmdline ) { - char *vga; - char *mem; - - /* Look for "vga=" */ - if ( ( vga = strstr ( cmdline, "vga=" ) ) ) { - vga += 4; - if ( strcmp ( vga, "normal" ) == 0 ) { - bzimg->vid_mode = BZI_VID_MODE_NORMAL; - } else if ( strcmp ( vga, "ext" ) == 0 ) { - bzimg->vid_mode = BZI_VID_MODE_EXT; - } else if ( strcmp ( vga, "ask" ) == 0 ) { - bzimg->vid_mode = BZI_VID_MODE_ASK; - } else { - bzimg->vid_mode = strtoul ( vga, &vga, 0 ); - if ( *vga && ( *vga != ' ' ) ) { - DBGC ( image, "bzImage %p strange \"vga=\"" - "terminator '%c'\n", image, *vga ); - } - } - } - - /* Look for "mem=" */ - if ( ( mem = strstr ( cmdline, "mem=" ) ) ) { - mem += 4; - bzimg->mem_limit = strtoul ( mem, &mem, 0 ); - switch ( *mem ) { - case 'G': - case 'g': - bzimg->mem_limit <<= 10; - case 'M': - case 'm': - bzimg->mem_limit <<= 10; - case 'K': - case 'k': - bzimg->mem_limit <<= 10; - break; - case '\0': - case ' ': - break; - default: - DBGC ( image, "bzImage %p strange \"mem=\" " - "terminator '%c'\n", image, *mem ); - break; - } - bzimg->mem_limit -= 1; - } - - return 0; -} - -/** - * Set command line - * - * @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 ) { - size_t cmdline_len; - - /* Copy command line down to real-mode portion */ - cmdline_len = ( strlen ( cmdline ) + 1 ); - if ( cmdline_len > bzimg->cmdline_size ) - cmdline_len = bzimg->cmdline_size; - copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline, - cmdline, cmdline_len ); - DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline ); - - return 0; -} - -/** - * Load initrd - * - * @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 - */ -static size_t bzimage_load_initrd ( struct image *image, - struct image *initrd, - userptr_t address ) { - char *filename = initrd->cmdline; - struct cpio_header cpio; - size_t offset = 0; - - /* Do not include kernel image itself as an initrd */ - if ( initrd == image ) - return 0; - - /* 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 ); - 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 ( address ) { - copy_to_user ( address, offset, &cpio, - sizeof ( cpio ) ); - } - offset += sizeof ( cpio ); - if ( address ) { - copy_to_user ( address, offset, filename, - name_len ); - } - offset += name_len; - offset = ( ( offset + 0x03 ) & ~0x03 ); - } - - /* Copy in initrd image body */ - if ( address ) - memcpy_user ( address, offset, initrd->data, 0, initrd->len ); - offset += 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 ) ); - } - - /* Round up to 4-byte boundary */ - offset = ( ( offset + 0x03 ) & ~0x03 ); - return offset; -} - -/** - * Load initrds, if any - * - * @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 ) { - struct image *initrd; - size_t total_len = 0; - physaddr_t address; - int rc; - - /* Add up length of all initrd images */ - for_each_image ( initrd ) - total_len += bzimage_load_initrd ( image, initrd, UNULL ); - - /* 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 ) ); - for_each_image ( initrd ) { - address += bzimage_load_initrd ( image, initrd, - phys_to_user ( address ) ); - } - - return 0; -} - -/** - * Execute bzImage image - * - * @v image bzImage image - * @ret rc Return status code - */ -static int bzimage_exec ( struct image *image ) { - struct bzimage_context bzimg; - const char *cmdline = ( image->cmdline ? image->cmdline : "" ); - int rc; - - /* Read and parse header from loaded kernel */ - if ( ( rc = bzimage_parse_header ( image, &bzimg, - image->priv.user ) ) != 0 ) - return rc; - assert ( bzimg.rm_kernel == image->priv.user ); - - /* 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; - - /* Load any initrds */ - if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 ) - return rc; - - /* Update kernel header */ - bzimage_update_header ( image, &bzimg, bzimg.rm_kernel ); - - /* Prepare for exiting */ - shutdown ( 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 ); - - /* Jump to the kernel */ - __asm__ __volatile__ ( REAL_CODE ( "movw %w0, %%ds\n\t" - "movw %w0, %%es\n\t" - "movw %w0, %%fs\n\t" - "movw %w0, %%gs\n\t" - "movw %w0, %%ss\n\t" - "movw %w1, %%sp\n\t" - "pushw %w2\n\t" - "pushw $0\n\t" - "lret\n\t" ) - : : "r" ( bzimg.rm_kernel_seg ), - "r" ( bzimg.rm_heap ), - "r" ( bzimg.rm_kernel_seg + 0x20 ) ); - - /* There is no way for the image to return, since we provide - * no return address. - */ - assert ( 0 ); - - return -ECANCELED; /* -EIMPOSSIBLE */ -} - -/** - * Load bzImage image into memory - * - * @v image bzImage file - * @ret rc Return status code - */ -int bzimage_load ( struct image *image ) { - struct bzimage_context bzimg; - int rc; - - /* Read and parse header from image */ - if ( ( rc = bzimage_parse_header ( image, &bzimg, - image->data ) ) != 0 ) - return rc; - - /* This is a bzImage image, valid or otherwise */ - if ( ! image->type ) - image->type = &bzimage_image_type; - - /* Prepare segments */ - if ( ( rc = prep_segment ( bzimg.rm_kernel, bzimg.rm_filesz, - bzimg.rm_memsz ) ) != 0 ) { - DBGC ( image, "bzImage %p could not prepare RM segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - if ( ( rc = prep_segment ( bzimg.pm_kernel, bzimg.pm_sz, - bzimg.pm_sz ) ) != 0 ) { - DBGC ( image, "bzImage %p could not prepare PM segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* 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 ); - - /* Record real-mode segment in image private data field */ - image->priv.user = bzimg.rm_kernel; - - return 0; -} - -/** Linux bzImage image type */ -struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ) = { - .name = "bzImage", - .load = bzimage_load, - .exec = bzimage_exec, -}; diff --git a/gpxe/src/arch/i386/image/com32.c b/gpxe/src/arch/i386/image/com32.c deleted file mode 100644 index 6ab347c1..00000000 --- a/gpxe/src/arch/i386/image/com32.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * @file - * - * SYSLINUX COM32 image format - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <errno.h> -#include <assert.h> -#include <realmode.h> -#include <basemem.h> -#include <comboot.h> -#include <gpxe/uaccess.h> -#include <gpxe/image.h> -#include <gpxe/segment.h> -#include <gpxe/init.h> -#include <gpxe/memmap.h> - -struct image_type com32_image_type __image_type ( PROBE_NORMAL ); - -/** - * Execute COMBOOT image - * - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_exec ( struct image *image ) { - struct memory_map memmap; - unsigned int i; - int state; - uint32_t avail_mem_top; - - state = rmsetjmp ( comboot_return ); - - switch ( state ) { - case 0: /* First time through; invoke COM32 program */ - - /* Get memory map */ - get_memmap ( &memmap ); - - /* Find end of block covering COM32 image loading area */ - for ( i = 0, avail_mem_top = 0 ; i < memmap.count ; i++ ) { - if ( (memmap.regions[i].start <= COM32_START_PHYS) && - (memmap.regions[i].end > COM32_START_PHYS + image->len) ) { - avail_mem_top = memmap.regions[i].end; - break; - } - } - - DBGC ( image, "COM32 %p: available memory top = 0x%x\n", - image, avail_mem_top ); - - assert ( avail_mem_top != 0 ); - - com32_external_esp = phys_to_virt ( avail_mem_top ); - - /* Hook COMBOOT API interrupts */ - hook_comboot_interrupts(); - - /* Unregister image, so that a "boot" command doesn't - * throw us into an execution loop. We never - * reregister ourselves; COMBOOT images expect to be - * removed on exit. - */ - unregister_image ( image ); - - __asm__ __volatile__ ( - "movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */ - "movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */ - "call _virt_to_phys\n\t" /* Switch to flat physical address space */ - "pushl %0\n\t" /* Pointer to CDECL helper function */ - "pushl %1\n\t" /* Pointer to FAR call helper function */ - "pushl %2\n\t" /* Size of low memory bounce buffer */ - "pushl %3\n\t" /* Pointer to low memory bounce buffer */ - "pushl %4\n\t" /* Pointer to INT call helper function */ - "pushl %5\n\t" /* Pointer to the command line arguments */ - "pushl $6\n\t" /* Number of additional arguments */ - "call *%6\n\t" /* Execute image */ - "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */ - "movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */ - : - : - /* %0 */ "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ), - /* %1 */ "r" ( virt_to_phys ( com32_farcall_wrapper ) ), - /* %2 */ "r" ( get_fbms() * 1024 - (COM32_BOUNCE_SEG << 4) ), - /* %3 */ "i" ( COM32_BOUNCE_SEG << 4 ), - /* %4 */ "r" ( virt_to_phys ( com32_intcall_wrapper ) ), - /* %5 */ "r" ( virt_to_phys ( image->cmdline ) ), - /* %6 */ "r" ( COM32_START_PHYS ) - : - "memory" ); - DBGC ( image, "COM32 %p: returned\n", image ); - break; - - case COMBOOT_EXIT: - DBGC ( image, "COM32 %p: exited\n", image ); - break; - - case COMBOOT_EXIT_RUN_KERNEL: - DBGC ( image, "COM32 %p: exited to run kernel %p\n", - image, comboot_replacement_image ); - image->replacement = comboot_replacement_image; - comboot_replacement_image = NULL; - image_autoload ( image->replacement ); - break; - - case COMBOOT_EXIT_COMMAND: - DBGC ( image, "COM32 %p: exited after executing command\n", - image ); - break; - - default: - assert ( 0 ); - break; - } - - unhook_comboot_interrupts(); - comboot_force_text_mode(); - - return 0; -} - -/** - * Check image name extension - * - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_identify ( struct image *image ) { - const char *ext; - static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 }; - uint8_t buf[5]; - - if ( image->len >= 5 ) { - /* Check for magic number - * mov eax,21cd4cffh - * B8 FF 4C CD 21 - */ - copy_from_user ( buf, image->data, 0, sizeof(buf) ); - if ( ! memcmp ( buf, magic, sizeof(buf) ) ) { - DBGC ( image, "COM32 %p: found magic number\n", - image ); - return 0; - } - } - - /* Magic number not found; check filename extension */ - - ext = strrchr( image->name, '.' ); - - if ( ! ext ) { - DBGC ( image, "COM32 %p: no extension\n", - image ); - return -ENOEXEC; - } - - ++ext; - - if ( strcasecmp( ext, "c32" ) ) { - DBGC ( image, "COM32 %p: unrecognized extension %s\n", - image, ext ); - return -ENOEXEC; - } - - return 0; -} - - -/** - * Load COM32 image into memory - * @v image COM32 image - * @ret rc Return status code - */ -static int comboot_load_image ( struct image *image ) { - size_t filesz, memsz; - userptr_t buffer; - int rc; - - filesz = image->len; - memsz = filesz; - buffer = phys_to_user ( COM32_START_PHYS ); - if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) { - DBGC ( image, "COM32 %p: could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* Copy image to segment */ - memcpy_user ( buffer, 0, image->data, 0, filesz ); - - return 0; -} - -/** - * Prepare COM32 low memory bounce buffer - * @v image COM32 image - * @ret rc Return status code - */ -static int comboot_prepare_bounce_buffer ( struct image * image ) { - unsigned int seg; - userptr_t seg_userptr; - size_t filesz, memsz; - int rc; - - seg = COM32_BOUNCE_SEG; - seg_userptr = real_to_user ( seg, 0 ); - - /* Ensure the entire 64k segment is free */ - memsz = 0xFFFF; - filesz = 0; - - /* Prepare, verify, and load the real-mode segment */ - if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) { - DBGC ( image, "COM32 %p: could not prepare bounce buffer segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Load COM32 image into memory - * - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_load ( struct image *image ) { - int rc; - - DBGC ( image, "COM32 %p: name '%s', cmdline '%s'\n", - image, image->name, image->cmdline ); - - /* Check if this is a COMBOOT image */ - if ( ( rc = com32_identify ( image ) ) != 0 ) { - return rc; - } - - /* This is a COM32 image, valid or otherwise */ - if ( ! image->type ) - image->type = &com32_image_type; - - /* Load image */ - if ( ( rc = comboot_load_image ( image ) ) != 0 ) { - return rc; - } - - /* Prepare bounce buffer segment */ - if ( ( rc = comboot_prepare_bounce_buffer ( image ) ) != 0 ) { - return rc; - } - - return 0; -} - -/** SYSLINUX COM32 image type */ -struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = { - .name = "COM32", - .load = com32_load, - .exec = com32_exec, -}; diff --git a/gpxe/src/arch/i386/image/comboot.c b/gpxe/src/arch/i386/image/comboot.c deleted file mode 100644 index a00b2b95..00000000 --- a/gpxe/src/arch/i386/image/comboot.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * @file - * - * SYSLINUX COMBOOT (16-bit) image format - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <errno.h> -#include <assert.h> -#include <realmode.h> -#include <basemem.h> -#include <comboot.h> -#include <gpxe/uaccess.h> -#include <gpxe/image.h> -#include <gpxe/segment.h> -#include <gpxe/init.h> -#include <gpxe/features.h> - -FEATURE ( FEATURE_IMAGE, "COMBOOT", DHCP_EB_FEATURE_COMBOOT, 1 ); - -struct image_type comboot_image_type __image_type ( PROBE_NORMAL ); - -/** - * COMBOOT PSP, copied to offset 0 of code segment - */ -struct comboot_psp { - /** INT 20 instruction, executed if COMBOOT image returns with RET */ - uint16_t int20; - /** Segment of first non-free paragraph of memory */ - uint16_t first_non_free_para; -}; - -/** Offset in PSP of command line */ -#define COMBOOT_PSP_CMDLINE_OFFSET 0x81 - -/** Maximum length of command line in PSP - * (127 bytes minus space and CR) */ -#define COMBOOT_MAX_CMDLINE_LEN 125 - - -/** - * Copy command line to PSP - * - * @v image COMBOOT image - */ -static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr ) { - const char *cmdline = ( image->cmdline ? image->cmdline : "" ); - int cmdline_len = strlen ( cmdline ); - if( cmdline_len > COMBOOT_MAX_CMDLINE_LEN ) - cmdline_len = COMBOOT_MAX_CMDLINE_LEN; - uint8_t len_byte = cmdline_len; - char spc = ' ', cr = '\r'; - - /* Copy length to byte before command line */ - copy_to_user ( seg_userptr, COMBOOT_PSP_CMDLINE_OFFSET - 1, - &len_byte, 1 ); - - /* Command line starts with space */ - copy_to_user ( seg_userptr, - COMBOOT_PSP_CMDLINE_OFFSET, - &spc, 1 ); - - /* Copy command line */ - copy_to_user ( seg_userptr, - COMBOOT_PSP_CMDLINE_OFFSET + 1, - cmdline, cmdline_len ); - - /* Command line ends with CR */ - copy_to_user ( seg_userptr, - COMBOOT_PSP_CMDLINE_OFFSET + cmdline_len + 1, - &cr, 1 ); -} - -/** - * Initialize PSP - * - * @v image COMBOOT image - * @v seg_userptr segment to initialize - */ -static void comboot_init_psp ( struct image * image, userptr_t seg_userptr ) { - struct comboot_psp psp; - - /* Fill PSP */ - - /* INT 20h instruction, byte order reversed */ - psp.int20 = 0x20CD; - - /* get_fbms() returns BIOS free base memory counter, which is in - * kilobytes; x * 1024 / 16 == x * 64 == x << 6 */ - psp.first_non_free_para = get_fbms() << 6; - - DBGC ( image, "COMBOOT %p: first non-free paragraph = 0x%x\n", - image, psp.first_non_free_para ); - - /* Copy the PSP to offset 0 of segment. - * The rest of the PSP was already zeroed by - * comboot_prepare_segment. */ - copy_to_user ( seg_userptr, 0, &psp, sizeof( psp ) ); - - /* Copy the command line to the PSP */ - comboot_copy_cmdline ( image, seg_userptr ); -} - -/** - * Execute COMBOOT image - * - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_exec ( struct image *image ) { - userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 ); - int state; - - state = rmsetjmp ( comboot_return ); - - switch ( state ) { - case 0: /* First time through; invoke COMBOOT program */ - - /* Initialize PSP */ - comboot_init_psp ( image, seg_userptr ); - - /* Hook COMBOOT API interrupts */ - hook_comboot_interrupts(); - - DBGC ( image, "executing 16-bit COMBOOT image at %4x:0100\n", - COMBOOT_PSP_SEG ); - - /* Unregister image, so that a "boot" command doesn't - * throw us into an execution loop. We never - * reregister ourselves; COMBOOT images expect to be - * removed on exit. - */ - unregister_image ( image ); - - /* Store stack segment at 0x38 and stack pointer at 0x3A - * in the PSP and jump to the image */ - __asm__ __volatile__ ( - REAL_CODE ( /* Save return address with segment on old stack */ - "popw %%ax\n\t" - "pushw %%cs\n\t" - "pushw %%ax\n\t" - /* Set DS=ES=segment with image */ - "movw %w0, %%ds\n\t" - "movw %w0, %%es\n\t" - /* Set SS:SP to new stack (end of image segment) */ - "movw %w0, %%ss\n\t" - "xor %%sp, %%sp\n\t" - "pushw $0\n\t" - "pushw %w0\n\t" - "pushw $0x100\n\t" - /* Zero registers (some COM files assume GP regs are 0) */ - "xorw %%ax, %%ax\n\t" - "xorw %%bx, %%bx\n\t" - "xorw %%cx, %%cx\n\t" - "xorw %%dx, %%dx\n\t" - "xorw %%si, %%si\n\t" - "xorw %%di, %%di\n\t" - "xorw %%bp, %%bp\n\t" - "lret\n\t" ) - : : "r" ( COMBOOT_PSP_SEG ) : "eax" ); - DBGC ( image, "COMBOOT %p: returned\n", image ); - break; - - case COMBOOT_EXIT: - DBGC ( image, "COMBOOT %p: exited\n", image ); - break; - - case COMBOOT_EXIT_RUN_KERNEL: - DBGC ( image, "COMBOOT %p: exited to run kernel %p\n", - image, comboot_replacement_image ); - image->replacement = comboot_replacement_image; - comboot_replacement_image = NULL; - image_autoload ( image->replacement ); - break; - - case COMBOOT_EXIT_COMMAND: - DBGC ( image, "COMBOOT %p: exited after executing command\n", - image ); - break; - - default: - assert ( 0 ); - break; - } - - unhook_comboot_interrupts(); - comboot_force_text_mode(); - - return 0; -} - -/** - * Check image name extension - * - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_identify ( struct image *image ) { - const char *ext; - - ext = strrchr( image->name, '.' ); - - if ( ! ext ) { - DBGC ( image, "COMBOOT %p: no extension\n", - image ); - return -ENOEXEC; - } - - ++ext; - - if ( strcasecmp( ext, "com" ) && strcasecmp( ext, "cbt" ) ) { - DBGC ( image, "COMBOOT %p: unrecognized extension %s\n", - image, ext ); - return -ENOEXEC; - } - - return 0; -} - -/** - * Load COMBOOT image into memory, preparing a segment and returning it - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_prepare_segment ( struct image *image ) -{ - userptr_t seg_userptr; - size_t filesz, memsz; - int rc; - - /* Load image in segment */ - seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 ); - - /* Allow etra 0x100 bytes before image for PSP */ - filesz = image->len + 0x100; - - /* Ensure the entire 64k segment is free */ - memsz = 0xFFFF; - - /* Prepare, verify, and load the real-mode segment */ - if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) { - DBGC ( image, "COMBOOT %p: could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* Zero PSP */ - memset_user ( seg_userptr, 0, 0, 0x100 ); - - /* Copy image to segment:0100 */ - memcpy_user ( seg_userptr, 0x100, image->data, 0, image->len ); - - return 0; -} - -/** - * Load COMBOOT image into memory - * - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_load ( struct image *image ) { - int rc; - - DBGC ( image, "COMBOOT %p: name '%s'\n", - image, image->name ); - - /* Check if this is a COMBOOT image */ - if ( ( rc = comboot_identify ( image ) ) != 0 ) { - - return rc; - } - - /* This is a 16-bit COMBOOT image, valid or otherwise */ - if ( ! image->type ) - image->type = &comboot_image_type; - - /* Sanity check for filesize */ - if( image->len >= 0xFF00 ) { - DBGC( image, "COMBOOT %p: image too large\n", - image ); - return -ENOEXEC; - } - - /* Prepare segment and load image */ - if ( ( rc = comboot_prepare_segment ( image ) ) != 0 ) { - return rc; - } - - return 0; -} - -/** SYSLINUX COMBOOT (16-bit) image type */ -struct image_type comboot_image_type __image_type ( PROBE_NORMAL ) = { - .name = "COMBOOT", - .load = comboot_load, - .exec = comboot_exec, -}; diff --git a/gpxe/src/arch/i386/image/elfboot.c b/gpxe/src/arch/i386/image/elfboot.c deleted file mode 100644 index a41040e8..00000000 --- a/gpxe/src/arch/i386/image/elfboot.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <errno.h> -#include <elf.h> -#include <gpxe/image.h> -#include <gpxe/elf.h> -#include <gpxe/features.h> -#include <gpxe/init.h> - -/** - * @file - * - * ELF bootable image - * - */ - -FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 ); - -struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ); - -/** - * Execute ELF image - * - * @v image ELF image - * @ret rc Return status code - */ -static int elfboot_exec ( struct image *image ) { - physaddr_t entry = image->priv.phys; - - /* An ELF image has no callback interface, so we need to shut - * down before invoking it. - */ - shutdown ( SHUTDOWN_BOOT ); - - /* Jump to OS with flat physical addressing */ - DBGC ( image, "ELF %p starting execution at %lx\n", image, entry ); - __asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" ) - : : "D" ( entry ) - : "eax", "ebx", "ecx", "edx", "esi", "ebp", - "memory" ); - - DBGC ( image, "ELF %p returned\n", image ); - - /* It isn't safe to continue after calling shutdown() */ - while ( 1 ) {} - - return -ECANCELED; /* -EIMPOSSIBLE, anyone? */ -} - -/** - * Load ELF image into memory - * - * @v image ELF file - * @ret rc Return status code - */ -static int elfboot_load ( struct image *image ) { - Elf32_Ehdr ehdr; - static const uint8_t e_ident[] = { - [EI_MAG0] = ELFMAG0, - [EI_MAG1] = ELFMAG1, - [EI_MAG2] = ELFMAG2, - [EI_MAG3] = ELFMAG3, - [EI_CLASS] = ELFCLASS32, - [EI_DATA] = ELFDATA2LSB, - [EI_VERSION] = EV_CURRENT, - }; - int rc; - - /* Read ELF header */ - copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); - if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) { - DBG ( "Invalid ELF identifier\n" ); - return -ENOEXEC; - } - - /* This is an ELF image, valid or otherwise */ - if ( ! image->type ) - image->type = &elfboot_image_type; - - /* Load the image using core ELF support */ - if ( ( rc = elf_load ( image ) ) != 0 ) { - DBGC ( image, "ELF %p could not load: %s\n", - image, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** ELF image type */ -struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = { - .name = "ELF", - .load = elfboot_load, - .exec = elfboot_exec, -}; diff --git a/gpxe/src/arch/i386/image/eltorito.c b/gpxe/src/arch/i386/image/eltorito.c deleted file mode 100644 index 53eb2c02..00000000 --- a/gpxe/src/arch/i386/image/eltorito.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * El Torito bootable ISO image format - * - */ - -#include <stdint.h> -#include <errno.h> -#include <assert.h> -#include <realmode.h> -#include <bootsector.h> -#include <int13.h> -#include <gpxe/uaccess.h> -#include <gpxe/image.h> -#include <gpxe/segment.h> -#include <gpxe/ramdisk.h> -#include <gpxe/init.h> - -#define ISO9660_BLKSIZE 2048 -#define ELTORITO_VOL_DESC_OFFSET ( 17 * ISO9660_BLKSIZE ) - -/** An El Torito Boot Record Volume Descriptor */ -struct eltorito_vol_desc { - /** Boot record indicator; must be 0 */ - uint8_t record_indicator; - /** ISO-9660 identifier; must be "CD001" */ - uint8_t iso9660_id[5]; - /** Version, must be 1 */ - uint8_t version; - /** Boot system indicator; must be "EL TORITO SPECIFICATION" */ - uint8_t system_indicator[32]; - /** Unused */ - uint8_t unused[32]; - /** Boot catalog sector */ - uint32_t sector; -} __attribute__ (( packed )); - -/** 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 )); - -/** 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, -}; - -struct image_type eltorito_image_type __image_type ( PROBE_NORMAL ); - -/** - * Calculate 16-bit word checksum - * - * @v data Data to checksum - * @v len Length (in bytes, must be even) - * @ret sum Checksum - */ -static unsigned int word_checksum ( void *data, size_t len ) { - uint16_t *words; - uint16_t sum = 0; - - for ( words = data ; len ; words++, len -= 2 ) { - sum += *words; - } - return sum; -} - -/** - * Execute El Torito image - * - * @v image El Torito image - * @ret rc Return status code - */ -static int eltorito_exec ( struct image *image ) { - struct ramdisk ramdisk; - struct int13_drive int13_drive; - unsigned int load_segment = image->priv.ul; - unsigned int load_offset = ( load_segment ? 0 : 0x7c00 ); - int rc; - - memset ( &ramdisk, 0, sizeof ( ramdisk ) ); - init_ramdisk ( &ramdisk, image->data, image->len, ISO9660_BLKSIZE ); - - memset ( &int13_drive, 0, sizeof ( int13_drive ) ); - int13_drive.blockdev = &ramdisk.blockdev; - register_int13_drive ( &int13_drive ); - - if ( ( rc = call_bootsector ( load_segment, load_offset, - int13_drive.drive ) ) != 0 ) { - DBGC ( image, "ElTorito %p boot failed: %s\n", - image, strerror ( rc ) ); - goto err; - } - - rc = -ECANCELED; /* -EIMPOSSIBLE */ - err: - unregister_int13_drive ( &int13_drive ); - return rc; -} - -/** - * Read and verify El Torito Boot Record Volume Descriptor - * - * @v image El Torito file - * @ret catalog_offset Offset of Boot Catalog - * @ret rc Return status code - */ -static int eltorito_read_voldesc ( struct image *image, - unsigned long *catalog_offset ) { - static const struct eltorito_vol_desc vol_desc_signature = { - .record_indicator = 0, - .iso9660_id = "CD001", - .version = 1, - .system_indicator = "EL TORITO SPECIFICATION", - }; - struct eltorito_vol_desc vol_desc; - - /* Sanity check */ - if ( image->len < ( ELTORITO_VOL_DESC_OFFSET + ISO9660_BLKSIZE ) ) { - DBGC ( image, "ElTorito %p too short\n", image ); - return -ENOEXEC; - } - - /* Read and verify Boot Record Volume Descriptor */ - copy_from_user ( &vol_desc, image->data, ELTORITO_VOL_DESC_OFFSET, - sizeof ( vol_desc ) ); - if ( memcmp ( &vol_desc, &vol_desc_signature, - offsetof ( typeof ( vol_desc ), sector ) ) != 0 ) { - DBGC ( image, "ElTorito %p invalid Boot Record Volume " - "Descriptor\n", image ); - return -ENOEXEC; - } - *catalog_offset = ( vol_desc.sector * ISO9660_BLKSIZE ); - - DBGC ( image, "ElTorito %p boot catalog at offset %#lx\n", - image, *catalog_offset ); - - return 0; -} - -/** - * Read and verify El Torito Boot Catalog - * - * @v image El Torito file - * @v catalog_offset Offset of Boot Catalog - * @ret boot_entry El Torito boot entry - * @ret rc Return status code - */ -static int eltorito_read_catalog ( struct image *image, - unsigned long catalog_offset, - struct eltorito_boot_entry *boot_entry ) { - struct eltorito_validation_entry validation_entry; - - /* Sanity check */ - if ( image->len < ( catalog_offset + ISO9660_BLKSIZE ) ) { - DBGC ( image, "ElTorito %p bad boot catalog offset %#lx\n", - image, catalog_offset ); - return -ENOEXEC; - } - - /* Read and verify the Validation Entry of the Boot Catalog */ - copy_from_user ( &validation_entry, image->data, catalog_offset, - sizeof ( validation_entry ) ); - if ( word_checksum ( &validation_entry, - sizeof ( validation_entry ) ) != 0 ) { - DBGC ( image, "ElTorito %p bad Validation Entry checksum\n", - image ); - return -ENOEXEC; - } - - /* Read and verify the Initial/Default entry */ - copy_from_user ( boot_entry, image->data, - ( catalog_offset + sizeof ( validation_entry ) ), - sizeof ( *boot_entry ) ); - if ( boot_entry->indicator != ELTORITO_BOOTABLE ) { - DBGC ( image, "ElTorito %p not bootable\n", image ); - return -ENOEXEC; - } - if ( boot_entry->media_type != ELTORITO_NO_EMULATION ) { - DBGC ( image, "ElTorito %p cannot support media type %d\n", - image, boot_entry->media_type ); - return -ENOTSUP; - } - - DBGC ( image, "ElTorito %p media type %d segment %04x\n", - image, boot_entry->media_type, boot_entry->load_segment ); - - return 0; -} - -/** - * Load El Torito virtual disk image into memory - * - * @v image El Torito file - * @v boot_entry El Torito boot entry - * @ret rc Return status code - */ -static int eltorito_load_disk ( struct image *image, - struct eltorito_boot_entry *boot_entry ) { - unsigned long start = ( boot_entry->start * ISO9660_BLKSIZE ); - unsigned long length = ( boot_entry->length * ISO9660_BLKSIZE ); - unsigned int load_segment; - userptr_t buffer; - int rc; - - /* Sanity check */ - if ( image->len < ( start + length ) ) { - DBGC ( image, "ElTorito %p virtual disk lies outside image\n", - image ); - return -ENOEXEC; - } - DBGC ( image, "ElTorito %p virtual disk at %#lx+%#lx\n", - image, start, length ); - - /* Calculate load address */ - load_segment = boot_entry->load_segment; - buffer = real_to_user ( load_segment, ( load_segment ? 0 : 0x7c00 ) ); - - /* Verify and prepare segment */ - if ( ( rc = prep_segment ( buffer, length, length ) ) != 0 ) { - DBGC ( image, "ElTorito %p could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* Copy image to segment */ - memcpy_user ( buffer, 0, image->data, start, length ); - - return 0; -} - -/** - * Load El Torito image into memory - * - * @v image El Torito file - * @ret rc Return status code - */ -static int eltorito_load ( struct image *image ) { - struct eltorito_boot_entry boot_entry; - unsigned long bootcat_offset; - int rc; - - /* Read Boot Record Volume Descriptor, if present */ - if ( ( rc = eltorito_read_voldesc ( image, &bootcat_offset ) ) != 0 ) - return rc; - - /* This is an El Torito image, valid or otherwise */ - if ( ! image->type ) - image->type = &eltorito_image_type; - - /* Read Boot Catalog */ - if ( ( rc = eltorito_read_catalog ( image, bootcat_offset, - &boot_entry ) ) != 0 ) - return rc; - - /* Load Virtual Disk image */ - if ( ( rc = eltorito_load_disk ( image, &boot_entry ) ) != 0 ) - return rc; - - /* Record load segment in image private data field */ - image->priv.ul = boot_entry.load_segment; - - return 0; -} - -/** El Torito image type */ -struct image_type eltorito_image_type __image_type ( PROBE_NORMAL ) = { - .name = "El Torito", - .load = eltorito_load, - .exec = eltorito_exec, -}; diff --git a/gpxe/src/arch/i386/image/multiboot.c b/gpxe/src/arch/i386/image/multiboot.c deleted file mode 100644 index 5b620956..00000000 --- a/gpxe/src/arch/i386/image/multiboot.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * Multiboot image format - * - */ - -#include <stdio.h> -#include <errno.h> -#include <assert.h> -#include <realmode.h> -#include <multiboot.h> -#include <gpxe/uaccess.h> -#include <gpxe/image.h> -#include <gpxe/segment.h> -#include <gpxe/memmap.h> -#include <gpxe/elf.h> -#include <gpxe/init.h> -#include <gpxe/features.h> - -FEATURE ( FEATURE_IMAGE, "Multiboot", DHCP_EB_FEATURE_MULTIBOOT, 1 ); - -struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ); - -/** - * Maximum number of modules we will allow for - * - * If this has bitten you: sorry. I did have a perfect scheme with a - * dynamically allocated list of modules on the protected-mode stack, - * but it was incompatible with some broken OSes that can only access - * low memory at boot time (even though we kindly set up 4GB flat - * physical addressing as per the multiboot specification. - * - */ -#define MAX_MODULES 8 - -/** - * Maximum combined length of command lines - * - * Again; sorry. Some broken OSes zero out any non-base memory that - * isn't part of the loaded module set, so we can't just use - * virt_to_phys(cmdline) to point to the command lines, even though - * this would comply with the Multiboot spec. - */ -#define MB_MAX_CMDLINE 512 - -/** Multiboot flags that we support */ -#define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \ - MB_FLAG_VIDMODE | MB_FLAG_RAW ) - -/** Compulsory feature multiboot flags */ -#define MB_COMPULSORY_FLAGS 0x0000ffff - -/** Optional feature multiboot flags */ -#define MB_OPTIONAL_FLAGS 0xffff0000 - -/** - * Multiboot flags that we don't support - * - * We only care about the compulsory feature flags (bits 0-15); we are - * allowed to ignore the optional feature flags. - */ -#define MB_UNSUPPORTED_FLAGS ( MB_COMPULSORY_FLAGS & ~MB_SUPPORTED_FLAGS ) - -/** A multiboot header descriptor */ -struct multiboot_header_info { - /** The actual multiboot header */ - struct multiboot_header mb; - /** Offset of header within the multiboot image */ - size_t offset; -}; - -/** Multiboot module command lines */ -static char __bss16_array ( mb_cmdlines, [MB_MAX_CMDLINE] ); -#define mb_cmdlines __use_data16 ( mb_cmdlines ) - -/** Offset within module command lines */ -static unsigned int mb_cmdline_offset; - -/** - * Build multiboot memory map - * - * @v image Multiboot image - * @v mbinfo Multiboot information structure - * @v mbmemmap Multiboot memory map - * @v limit Maxmimum number of memory map entries - */ -static void multiboot_build_memmap ( struct image *image, - struct multiboot_info *mbinfo, - struct multiboot_memory_map *mbmemmap, - unsigned int limit ) { - struct memory_map memmap; - unsigned int i; - - /* Get memory map */ - get_memmap ( &memmap ); - - /* Translate into multiboot format */ - memset ( mbmemmap, 0, sizeof ( *mbmemmap ) ); - for ( i = 0 ; i < memmap.count ; i++ ) { - if ( i >= limit ) { - DBGC ( image, "MULTIBOOT %p limit of %d memmap " - "entries reached\n", image, limit ); - break; - } - mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) - - sizeof ( mbmemmap[i].size ) ); - mbmemmap[i].base_addr = memmap.regions[i].start; - mbmemmap[i].length = ( memmap.regions[i].end - - memmap.regions[i].start ); - mbmemmap[i].type = MBMEM_RAM; - mbinfo->mmap_length += sizeof ( mbmemmap[i] ); - if ( memmap.regions[i].start == 0 ) - mbinfo->mem_lower = ( memmap.regions[i].end / 1024 ); - if ( memmap.regions[i].start == 0x100000 ) - mbinfo->mem_upper = ( ( memmap.regions[i].end - - 0x100000 ) / 1024 ); - } -} - -/** - * Add command line in base memory - * - * @v imgname Image name - * @v cmdline Command line - * @ret physaddr Physical address of command line - */ -physaddr_t multiboot_add_cmdline ( const char *imgname, const char *cmdline ) { - char *mb_cmdline; - - if ( ! cmdline ) - cmdline = ""; - - /* Copy command line to base memory buffer */ - mb_cmdline = ( mb_cmdlines + mb_cmdline_offset ); - mb_cmdline_offset += - ( snprintf ( mb_cmdline, - ( sizeof ( mb_cmdlines ) - mb_cmdline_offset ), - "%s %s", imgname, cmdline ) + 1 ); - - /* Truncate to terminating NUL in buffer if necessary */ - if ( mb_cmdline_offset > sizeof ( mb_cmdlines ) ) - mb_cmdline_offset = ( sizeof ( mb_cmdlines ) - 1 ); - - return virt_to_phys ( mb_cmdline ); -} - -/** - * Build multiboot module list - * - * @v image Multiboot image - * @v modules Module list to fill, or NULL - * @ret count Number of modules - */ -static unsigned int -multiboot_build_module_list ( struct image *image, - struct multiboot_module *modules, - unsigned int limit ) { - struct image *module_image; - struct multiboot_module *module; - unsigned int count = 0; - unsigned int insert; - physaddr_t start; - physaddr_t end; - unsigned int i; - - /* Add each image as a multiboot module */ - for_each_image ( module_image ) { - - if ( count >= limit ) { - DBGC ( image, "MULTIBOOT %p limit of %d modules " - "reached\n", image, limit ); - break; - } - - /* Do not include kernel image itself as a module */ - if ( module_image == image ) - continue; - - /* At least some OSes expect the multiboot modules to - * be in ascending order, so we have to support it. - */ - start = user_to_phys ( module_image->data, 0 ); - end = user_to_phys ( module_image->data, module_image->len ); - for ( insert = 0 ; insert < count ; insert++ ) { - if ( start < modules[insert].mod_start ) - break; - } - module = &modules[insert]; - memmove ( ( module + 1 ), module, - ( ( count - insert ) * sizeof ( *module ) ) ); - module->mod_start = start; - module->mod_end = end; - module->string = multiboot_add_cmdline ( module_image->name, - module_image->cmdline ); - module->reserved = 0; - - /* We promise to page-align modules */ - assert ( ( module->mod_start & 0xfff ) == 0 ); - - count++; - } - - /* Dump module configuration */ - for ( i = 0 ; i < count ; i++ ) { - DBGC ( image, "MULTIBOOT %p module %d is [%x,%x)\n", - image, i, modules[i].mod_start, - modules[i].mod_end ); - } - - return count; -} - -/** - * The multiboot information structure - * - * Kept in base memory because some OSes won't find it elsewhere, - * along with the other structures belonging to the Multiboot - * information table. - */ -static struct multiboot_info __bss16 ( mbinfo ); -#define mbinfo __use_data16 ( mbinfo ) - -/** The multiboot bootloader name */ -static char __data16_array ( mb_bootloader_name, [] ) = "gPXE " VERSION; -#define mb_bootloader_name __use_data16 ( mb_bootloader_name ) - -/** The multiboot memory map */ -static struct multiboot_memory_map - __bss16_array ( mbmemmap, [MAX_MEMORY_REGIONS] ); -#define mbmemmap __use_data16 ( mbmemmap ) - -/** The multiboot module list */ -static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] ); -#define mbmodules __use_data16 ( mbmodules ) - -/** - * Execute multiboot image - * - * @v image Multiboot image - * @ret rc Return status code - */ -static int multiboot_exec ( struct image *image ) { - physaddr_t entry = image->priv.phys; - - /* Populate multiboot information structure */ - memset ( &mbinfo, 0, sizeof ( mbinfo ) ); - mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP | - MBI_FLAG_CMDLINE | MBI_FLAG_MODS ); - mb_cmdline_offset = 0; - mbinfo.cmdline = multiboot_add_cmdline ( image->name, image->cmdline ); - mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules, - ( sizeof(mbmodules) / sizeof(mbmodules[0]) ) ); - mbinfo.mods_addr = virt_to_phys ( mbmodules ); - mbinfo.mmap_addr = virt_to_phys ( mbmemmap ); - mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name ); - - /* Multiboot images may not return and have no callback - * interface, so shut everything down prior to booting the OS. - */ - shutdown ( SHUTDOWN_BOOT ); - - /* Build memory map after unhiding bootloader memory regions as part of - * shutting everything down. - */ - multiboot_build_memmap ( image, &mbinfo, mbmemmap, - ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) ); - - /* Jump to OS with flat physical addressing */ - DBGC ( image, "MULTIBOOT %p starting execution at %lx\n", - image, entry ); - __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t" - "call *%%edi\n\t" - "popl %%ebp\n\t" ) - : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ), - "b" ( virt_to_phys ( &mbinfo ) ), - "D" ( entry ) - : "ecx", "edx", "esi", "memory" ); - - DBGC ( image, "MULTIBOOT %p returned\n", image ); - - /* It isn't safe to continue after calling shutdown() */ - while ( 1 ) {} - - return -ECANCELED; /* -EIMPOSSIBLE, anyone? */ -} - -/** - * Find multiboot header - * - * @v image Multiboot file - * @v hdr Multiboot header descriptor to fill in - * @ret rc Return status code - */ -static int multiboot_find_header ( struct image *image, - struct multiboot_header_info *hdr ) { - uint32_t buf[64]; - size_t offset; - unsigned int buf_idx; - uint32_t checksum; - - /* Scan through first 8kB of image file 256 bytes at a time. - * (Use the buffering to avoid the overhead of a - * copy_from_user() for every dword.) - */ - for ( offset = 0 ; offset < 8192 ; offset += sizeof ( buf[0] ) ) { - /* Check for end of image */ - if ( offset > image->len ) - break; - /* Refill buffer if applicable */ - buf_idx = ( ( offset % sizeof ( buf ) ) / sizeof ( buf[0] ) ); - if ( buf_idx == 0 ) { - copy_from_user ( buf, image->data, offset, - sizeof ( buf ) ); - } - /* Check signature */ - if ( buf[buf_idx] != MULTIBOOT_HEADER_MAGIC ) - continue; - /* Copy header and verify checksum */ - copy_from_user ( &hdr->mb, image->data, offset, - sizeof ( hdr->mb ) ); - checksum = ( hdr->mb.magic + hdr->mb.flags + - hdr->mb.checksum ); - if ( checksum != 0 ) - continue; - /* Record offset of multiboot header and return */ - hdr->offset = offset; - return 0; - } - - /* No multiboot header found */ - return -ENOEXEC; -} - -/** - * Load raw multiboot image into memory - * - * @v image Multiboot file - * @v hdr Multiboot header descriptor - * @ret rc Return status code - */ -static int multiboot_load_raw ( struct image *image, - struct multiboot_header_info *hdr ) { - size_t offset; - size_t filesz; - size_t memsz; - userptr_t buffer; - int rc; - - /* Sanity check */ - if ( ! ( hdr->mb.flags & MB_FLAG_RAW ) ) { - DBGC ( image, "MULTIBOOT %p is not flagged as a raw image\n", - image ); - return -EINVAL; - } - - /* Verify and prepare segment */ - offset = ( hdr->offset - hdr->mb.header_addr + hdr->mb.load_addr ); - filesz = ( hdr->mb.load_end_addr ? - ( hdr->mb.load_end_addr - hdr->mb.load_addr ) : - ( image->len - offset ) ); - memsz = ( hdr->mb.bss_end_addr ? - ( hdr->mb.bss_end_addr - hdr->mb.load_addr ) : filesz ); - buffer = phys_to_user ( hdr->mb.load_addr ); - if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) { - DBGC ( image, "MULTIBOOT %p could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* Copy image to segment */ - memcpy_user ( buffer, 0, image->data, offset, filesz ); - - /* Record execution entry point in image private data field */ - image->priv.phys = hdr->mb.entry_addr; - - return 0; -} - -/** - * Load ELF multiboot image into memory - * - * @v image Multiboot file - * @ret rc Return status code - */ -static int multiboot_load_elf ( struct image *image ) { - int rc; - - /* Load ELF image*/ - if ( ( rc = elf_load ( image ) ) != 0 ) { - DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n", - image, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Load multiboot image into memory - * - * @v image Multiboot file - * @ret rc Return status code - */ -static int multiboot_load ( struct image *image ) { - struct multiboot_header_info hdr; - int rc; - - /* Locate multiboot header, if present */ - if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) { - DBGC ( image, "MULTIBOOT %p has no multiboot header\n", - image ); - return rc; - } - DBGC ( image, "MULTIBOOT %p found header with flags %08x\n", - image, hdr.mb.flags ); - - /* This is a multiboot image, valid or otherwise */ - if ( ! image->type ) - image->type = &multiboot_image_type; - - /* Abort if we detect flags that we cannot support */ - if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) { - DBGC ( image, "MULTIBOOT %p flags %08x not supported\n", - image, ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) ); - return -ENOTSUP; - } - - /* There is technically a bit MB_FLAG_RAW to indicate whether - * this is an ELF or a raw image. In practice, grub will use - * the ELF header if present, and Solaris relies on this - * behaviour. - */ - if ( ( ( rc = multiboot_load_elf ( image ) ) != 0 ) && - ( ( rc = multiboot_load_raw ( image, &hdr ) ) != 0 ) ) - return rc; - - return 0; -} - -/** Multiboot image type */ -struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ) = { - .name = "Multiboot", - .load = multiboot_load, - .exec = multiboot_exec, -}; diff --git a/gpxe/src/arch/i386/image/nbi.c b/gpxe/src/arch/i386/image/nbi.c deleted file mode 100644 index a4ee4420..00000000 --- a/gpxe/src/arch/i386/image/nbi.c +++ /dev/null @@ -1,442 +0,0 @@ -#include <errno.h> -#include <assert.h> -#include <realmode.h> -#include <gateA20.h> -#include <memsizes.h> -#include <basemem_packet.h> -#include <gpxe/uaccess.h> -#include <gpxe/segment.h> -#include <gpxe/init.h> -#include <gpxe/netdevice.h> -#include <gpxe/fakedhcp.h> -#include <gpxe/image.h> -#include <gpxe/features.h> - -/** @file - * - * NBI image format. - * - * The Net Boot Image format is defined by the "Draft Net Boot Image - * Proposal 0.3" by Jamie Honan, Gero Kuhlmann and Ken Yap. It is now - * considered to be a legacy format, but it still included because a - * large amount of software (e.g. nymph, LTSP) makes use of NBI files. - * - * Etherboot does not implement the INT 78 callback interface - * described by the NBI specification. For a callback interface on - * x86 architecture, use PXE. - * - */ - -FEATURE ( FEATURE_IMAGE, "NBI", DHCP_EB_FEATURE_NBI, 1 ); - -struct image_type nbi_image_type __image_type ( PROBE_NORMAL ); - -/** - * An NBI image header - * - * Note that the length field uses a peculiar encoding; use the - * NBI_LENGTH() macro to decode the actual header length. - * - */ -struct imgheader { - unsigned long magic; /**< Magic number (NBI_MAGIC) */ - union { - unsigned char length; /**< Nibble-coded header length */ - unsigned long flags; /**< Image flags */ - }; - segoff_t location; /**< 16-bit seg:off header location */ - union { - segoff_t segoff; /**< 16-bit seg:off entry point */ - unsigned long linear; /**< 32-bit entry point */ - } execaddr; -} __attribute__ (( packed )); - -/** NBI magic number */ -#define NBI_MAGIC 0x1B031336UL - -/* Interpretation of the "length" fields */ -#define NBI_NONVENDOR_LENGTH(len) ( ( (len) & 0x0f ) << 2 ) -#define NBI_VENDOR_LENGTH(len) ( ( (len) & 0xf0 ) >> 2 ) -#define NBI_LENGTH(len) ( NBI_NONVENDOR_LENGTH(len) + NBI_VENDOR_LENGTH(len) ) - -/* Interpretation of the "flags" fields */ -#define NBI_PROGRAM_RETURNS(flags) ( (flags) & ( 1 << 8 ) ) -#define NBI_LINEAR_EXEC_ADDR(flags) ( (flags) & ( 1 << 31 ) ) - -/** NBI header length */ -#define NBI_HEADER_LENGTH 512 - -/** - * An NBI segment header - * - * Note that the length field uses a peculiar encoding; use the - * NBI_LENGTH() macro to decode the actual header length. - * - */ -struct segheader { - unsigned char length; /**< Nibble-coded header length */ - unsigned char vendortag; /**< Vendor-defined private tag */ - unsigned char reserved; - unsigned char flags; /**< Segment flags */ - unsigned long loadaddr; /**< Load address */ - unsigned long imglength; /**< Segment length in NBI file */ - unsigned long memlength; /**< Segment length in memory */ -}; - -/* Interpretation of the "flags" fields */ -#define NBI_LOADADDR_FLAGS(flags) ( (flags) & 0x03 ) -#define NBI_LOADADDR_ABS 0x00 -#define NBI_LOADADDR_AFTER 0x01 -#define NBI_LOADADDR_END 0x02 -#define NBI_LOADADDR_BEFORE 0x03 -#define NBI_LAST_SEGHEADER(flags) ( (flags) & ( 1 << 2 ) ) - -/* Define a type for passing info to a loaded program */ -struct ebinfo { - uint8_t major, minor; /* Version */ - 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 - * - * @v image NBI image - * @v offset Offset within NBI image - * @v filesz Length of initialised-data portion of the segment - * @v memsz Total length of the segment - * @v src Source for initialised data - * @ret rc Return status code - */ -static int nbi_prepare_segment ( struct image *image, size_t offset __unused, - userptr_t dest, size_t filesz, size_t memsz ){ - int rc; - - if ( ( rc = prep_segment ( dest, filesz, memsz ) ) != 0 ) { - DBGC ( image, "NBI %p could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Load a segment for an NBI image - * - * @v image NBI image - * @v offset Offset within NBI image - * @v filesz Length of initialised-data portion of the segment - * @v memsz Total length of the segment - * @v src Source for initialised data - * @ret rc Return status code - */ -static int nbi_load_segment ( struct image *image, size_t offset, - userptr_t dest, size_t filesz, - size_t memsz __unused ) { - memcpy_user ( dest, 0, image->data, offset, filesz ); - return 0; -} - -/** - * Process segments of an NBI image - * - * @v image NBI image - * @v imgheader Image header information - * @v process Function to call for each segment - * @ret rc Return status code - */ -static int nbi_process_segments ( struct image *image, - struct imgheader *imgheader, - int ( * process ) ( struct image *image, - size_t offset, - userptr_t dest, - size_t filesz, - size_t memsz ) ) { - struct segheader sh; - size_t offset = 0; - size_t sh_off; - userptr_t dest; - size_t filesz; - size_t memsz; - int rc; - - /* Copy image header to target location */ - dest = real_to_user ( imgheader->location.segment, - imgheader->location.offset ); - filesz = memsz = NBI_HEADER_LENGTH; - if ( ( rc = process ( image, offset, dest, filesz, memsz ) ) != 0 ) - return rc; - offset += filesz; - - /* Process segments in turn */ - sh_off = NBI_LENGTH ( imgheader->length ); - do { - /* Read segment header */ - copy_from_user ( &sh, image->data, sh_off, sizeof ( sh ) ); - if ( sh.length == 0 ) { - /* Avoid infinite loop? */ - DBGC ( image, "NBI %p invalid segheader length 0\n", - image ); - return -ENOEXEC; - } - - /* Calculate segment load address */ - switch ( NBI_LOADADDR_FLAGS ( sh.flags ) ) { - case NBI_LOADADDR_ABS: - dest = phys_to_user ( sh.loadaddr ); - break; - case NBI_LOADADDR_AFTER: - dest = userptr_add ( dest, memsz + sh.loadaddr ); - break; - case NBI_LOADADDR_BEFORE: - dest = userptr_add ( dest, -sh.loadaddr ); - break; - case NBI_LOADADDR_END: - /* Not correct according to the spec, but - * maintains backwards compatibility with - * previous versions of Etherboot. - */ - dest = phys_to_user ( ( extmemsize() + 1024 ) * 1024 - - sh.loadaddr ); - break; - default: - /* Cannot be reached */ - assert ( 0 ); - } - - /* Process this segment */ - filesz = sh.imglength; - memsz = sh.memlength; - if ( ( offset + filesz ) > image->len ) { - DBGC ( image, "NBI %p segment outside file\n", image ); - return -ENOEXEC; - } - if ( ( rc = process ( image, offset, dest, - filesz, memsz ) ) != 0 ) { - return rc; - } - offset += filesz; - - /* Next segheader */ - sh_off += NBI_LENGTH ( sh.length ); - if ( sh_off >= NBI_HEADER_LENGTH ) { - DBGC ( image, "NBI %p header overflow\n", image ); - return -ENOEXEC; - } - - } while ( ! NBI_LAST_SEGHEADER ( sh.flags ) ); - - if ( offset != image->len ) { - DBGC ( image, "NBI %p length wrong (file %zd, metadata %zd)\n", - image, image->len, offset ); - return -ENOEXEC; - } - - return 0; -} - -/** - * Load an NBI image into memory - * - * @v image NBI image - * @ret rc Return status code - */ -static int nbi_load ( struct image *image ) { - struct imgheader imgheader; - int rc; - - /* If we don't have enough data give up */ - if ( image->len < NBI_HEADER_LENGTH ) { - DBGC ( image, "NBI %p too short for an NBI image\n", image ); - return -ENOEXEC; - } - - /* Check image header */ - copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) ); - if ( imgheader.magic != NBI_MAGIC ) { - DBGC ( image, "NBI %p has no NBI signature\n", image ); - return -ENOEXEC; - } - - /* This is an NBI image, valid or otherwise */ - if ( ! image->type ) - image->type = &nbi_image_type; - - DBGC ( image, "NBI %p placing header at %hx:%hx\n", image, - imgheader.location.segment, imgheader.location.offset ); - - /* NBI files can have overlaps between segments; the bss of - * one segment may overlap the initialised data of another. I - * assume this is a design flaw, but there are images out - * there that we need to work with. We therefore do two - * passes: first to initialise the segments, then to copy the - * data. This avoids zeroing out already-copied data. - */ - if ( ( rc = nbi_process_segments ( image, &imgheader, - nbi_prepare_segment ) ) != 0 ) - return rc; - if ( ( rc = nbi_process_segments ( image, &imgheader, - nbi_load_segment ) ) != 0 ) - return rc; - - /* Record header address in image private data field */ - image->priv.user = real_to_user ( imgheader.location.segment, - imgheader.location.offset ); - - return 0; -} - -/** - * Boot a 16-bit NBI image - * - * @v imgheader Image header information - * @ret rc Return status code, if image returns - */ -static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) { - int discard_D, discard_S, discard_b; - int rc; - - DBGC ( image, "NBI %p executing 16-bit image at %04x:%04x\n", image, - imgheader->execaddr.segoff.segment, - imgheader->execaddr.segoff.offset ); - - gateA20_unset(); - - __asm__ __volatile__ ( - REAL_CODE ( "pushw %%ds\n\t" /* far pointer to bootp data */ - "pushw %%bx\n\t" - "pushl %%esi\n\t" /* location */ - "pushw %%cs\n\t" /* lcall execaddr */ - "call 1f\n\t" - "jmp 2f\n\t" - "\n1:\n\t" - "pushl %%edi\n\t" - "lret\n\t" - "\n2:\n\t" - "addw $8,%%sp\n\t" /* clean up stack */ ) - : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ), - "=b" ( discard_b ) - : "D" ( imgheader->execaddr.segoff ), - "S" ( imgheader->location ), - "b" ( __from_data16 ( basemem_packet ) ) - : "ecx", "edx", "ebp" ); - - gateA20_set(); - - return rc; -} - -/** - * Boot a 32-bit NBI image - * - * @v imgheader Image header information - * @ret rc Return status code, if image returns - */ -static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) { - int discard_D, discard_S, discard_b; - int rc; - - DBGC ( image, "NBI %p executing 32-bit image at %lx\n", - image, imgheader->execaddr.linear ); - - /* no gateA20_unset for PM call */ - - /* Jump to OS with flat physical addressing */ - __asm__ __volatile__ ( - PHYS_CODE ( "pushl %%ebx\n\t" /* bootp data */ - "pushl %%esi\n\t" /* imgheader */ - "pushl %%eax\n\t" /* loaderinfo */ - "call *%%edi\n\t" - "addl $12, %%esp\n\t" /* clean up stack */ ) - : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ), - "=b" ( discard_b ) - : "D" ( imgheader->execaddr.linear ), - "S" ( ( imgheader->location.segment << 4 ) + - imgheader->location.offset ), - "b" ( virt_to_phys ( basemem_packet ) ), - "a" ( virt_to_phys ( &loaderinfo ) ) - : "ecx", "edx", "ebp", "memory" ); - - return rc; -} - -/** - * Prepare DHCP parameter block for NBI image - * - * @v image NBI image - * @ret rc Return status code - */ -static int nbi_prepare_dhcp ( struct image *image ) { - struct net_device *boot_netdev; - int rc; - - boot_netdev = last_opened_netdev(); - if ( ! boot_netdev ) { - DBGC ( image, "NBI %p could not identify a network device\n", - image ); - return -ENODEV; - } - - if ( ( rc = create_fakedhcpack ( boot_netdev, basemem_packet, - sizeof ( basemem_packet ) ) ) != 0 ) { - DBGC ( image, "NBI %p failed to build DHCP packet\n", image ); - return rc; - } - - return 0; -} - -/** - * Execute a loaded NBI image - * - * @v image NBI image - * @ret rc Return status code - */ -static int nbi_exec ( struct image *image ) { - struct imgheader imgheader; - int may_return; - int rc; - - copy_from_user ( &imgheader, image->priv.user, 0, - sizeof ( imgheader ) ); - - /* Prepare DHCP option block */ - if ( ( rc = nbi_prepare_dhcp ( image ) ) != 0 ) - return rc; - - /* Shut down now if NBI image will not return */ - may_return = NBI_PROGRAM_RETURNS ( imgheader.flags ); - if ( ! may_return ) - shutdown ( SHUTDOWN_BOOT ); - - /* Execute NBI image */ - if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) { - rc = nbi_boot32 ( image, &imgheader ); - } else { - rc = nbi_boot16 ( image, &imgheader ); - } - - if ( ! may_return ) { - /* Cannot continue after shutdown() called */ - DBGC ( image, "NBI %p returned %d from non-returnable image\n", - image, rc ); - while ( 1 ) {} - } - - DBGC ( image, "NBI %p returned %d\n", image, rc ); - - return rc; -} - -/** NBI image type */ -struct image_type nbi_image_type __image_type ( PROBE_NORMAL ) = { - .name = "NBI", - .load = nbi_load, - .exec = nbi_exec, -}; diff --git a/gpxe/src/arch/i386/image/pxe_image.c b/gpxe/src/arch/i386/image/pxe_image.c deleted file mode 100644 index 63429f87..00000000 --- a/gpxe/src/arch/i386/image/pxe_image.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * PXE image format - * - */ - -#include <pxe.h> -#include <pxe_call.h> -#include <gpxe/uaccess.h> -#include <gpxe/image.h> -#include <gpxe/segment.h> -#include <gpxe/netdevice.h> -#include <gpxe/features.h> - -FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 ); - -struct image_type pxe_image_type __image_type ( PROBE_PXE ); - -/** - * Execute PXE image - * - * @v image PXE image - * @ret rc Return status code - */ -static int pxe_exec ( struct image *image ) { - struct net_device *netdev; - int rc; - - /* Arbitrarily pick the most recently opened network device */ - if ( ( netdev = last_opened_netdev() ) == NULL ) { - DBGC ( image, "IMAGE %p could not locate PXE net device\n", - image ); - return -ENODEV; - } - - /* Activate PXE */ - pxe_activate ( netdev ); - - /* Start PXE NBP */ - rc = pxe_start_nbp(); - - /* Deactivate PXE */ - pxe_deactivate(); - - return rc; -} - -/** - * Load PXE image into memory - * - * @v image PXE file - * @ret rc Return status code - */ -int pxe_load ( struct image *image ) { - userptr_t buffer = real_to_user ( 0, 0x7c00 ); - size_t filesz = image->len; - size_t memsz = image->len; - int rc; - - /* Images too large to fit in base memory cannot be PXE - * images. We include this check to help prevent unrecognised - * images from being marked as PXE images, since PXE images - * have no signature we can check against. - */ - if ( filesz > ( 0xa0000 - 0x7c00 ) ) - return -ENOEXEC; - - /* Rejecting zero-length images is also useful, since these - * end up looking to the user like bugs in gPXE. - */ - if ( ! filesz ) - return -ENOEXEC; - - /* There are no signature checks for PXE; we will accept anything */ - if ( ! image->type ) - image->type = &pxe_image_type; - - /* Verify and prepare segment */ - if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) { - DBGC ( image, "IMAGE %p could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* Copy image to segment */ - memcpy_user ( buffer, 0, image->data, 0, filesz ); - - return 0; -} - -/** PXE image type */ -struct image_type pxe_image_type __image_type ( PROBE_PXE ) = { - .name = "PXE", - .load = pxe_load, - .exec = pxe_exec, -}; diff --git a/gpxe/src/arch/i386/include/basemem.h b/gpxe/src/arch/i386/include/basemem.h deleted file mode 100644 index c477c7fe..00000000 --- a/gpxe/src/arch/i386/include/basemem.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _BASEMEM_H -#define _BASEMEM_H - -/** @file - * - * Base memory allocation - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <realmode.h> -#include <bios.h> - -/** - * Read the BIOS free base memory counter - * - * @ret fbms Free base memory counter (in kB) - */ -static inline unsigned int get_fbms ( void ) { - uint16_t fbms; - - get_real ( fbms, BDA_SEG, BDA_FBMS ); - return fbms; -} - -extern void set_fbms ( unsigned int new_fbms ); - -/* Actually in hidemem.c, but putting it here avoids polluting the - * architecture-independent include/hidemem.h. - */ -extern void hide_basemem ( void ); - -#endif /* _BASEMEM_H */ diff --git a/gpxe/src/arch/i386/include/basemem_packet.h b/gpxe/src/arch/i386/include/basemem_packet.h deleted file mode 100644 index 3cb47767..00000000 --- a/gpxe/src/arch/i386/include/basemem_packet.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef BASEMEM_PACKET_H -#define BASEMEM_PACKET_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <realmode.h> - -/** Maximum length of base memory packet buffer */ -#define BASEMEM_PACKET_LEN 1514 - -/** Base memory packet buffer */ -extern char __bss16_array ( basemem_packet, [BASEMEM_PACKET_LEN] ); -#define basemem_packet __use_data16 ( basemem_packet ) - -#endif /* BASEMEM_PACKET_H */ diff --git a/gpxe/src/arch/i386/include/bios.h b/gpxe/src/arch/i386/include/bios.h deleted file mode 100644 index 70bb73da..00000000 --- a/gpxe/src/arch/i386/include/bios.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef BIOS_H -#define BIOS_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#define BDA_SEG 0x0040 -#define BDA_FBMS 0x0013 -#define BDA_NUM_DRIVES 0x0075 - -#endif /* BIOS_H */ diff --git a/gpxe/src/arch/i386/include/bios_disks.h b/gpxe/src/arch/i386/include/bios_disks.h deleted file mode 100644 index 0dd7c4eb..00000000 --- a/gpxe/src/arch/i386/include/bios_disks.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef BIOS_DISKS_H -#define BIOS_DISKS_H - -#include "dev.h" - -/* - * Constants - * - */ - -#define BIOS_DISK_MAX_NAME_LEN 6 - -struct bios_disk_sector { - char data[512]; -}; - -/* - * The location of a BIOS disk - * - */ -struct bios_disk_loc { - uint8_t drive; -}; - -/* - * A physical BIOS disk device - * - */ -struct bios_disk_device { - char name[BIOS_DISK_MAX_NAME_LEN]; - uint8_t drive; - uint8_t type; -}; - -/* - * A BIOS disk driver, with a valid device ID range and naming - * function. - * - */ -struct bios_disk_driver { - void ( *fill_drive_name ) ( char *buf, uint8_t drive ); - uint8_t min_drive; - uint8_t max_drive; -}; - -/* - * Define a BIOS disk driver - * - */ -#define BIOS_DISK_DRIVER( _name, _fill_drive_name, _min_drive, _max_drive ) \ - static struct bios_disk_driver _name = { \ - .fill_drive_name = _fill_drive_name, \ - .min_drive = _min_drive, \ - .max_drive = _max_drive, \ - } - -/* - * Functions in bios_disks.c - * - */ - - -/* - * bios_disk bus global definition - * - */ -extern struct bus_driver bios_disk_driver; - -#endif /* BIOS_DISKS_H */ diff --git a/gpxe/src/arch/i386/include/biosint.h b/gpxe/src/arch/i386/include/biosint.h deleted file mode 100644 index ab466af3..00000000 --- a/gpxe/src/arch/i386/include/biosint.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef BIOSINT_H -#define BIOSINT_H - -/** - * @file BIOS interrupts - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <realmode.h> - -struct segoff; - -/** - * Hooked interrupt count - * - * At exit, after unhooking all possible interrupts, this counter - * should be examined. If it is non-zero, it means that we failed to - * unhook at least one interrupt vector, and so must not free up the - * memory we are using. (Note that this also implies that we should - * re-hook INT 15 in order to hide ourselves from the memory map). - */ -extern uint16_t __text16 ( hooked_bios_interrupts ); -#define hooked_bios_interrupts __use_text16 ( hooked_bios_interrupts ) - -extern void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler, - struct segoff *chain_vector ); -extern int unhook_bios_interrupt ( unsigned int interrupt, - unsigned int handler, - struct segoff *chain_vector ); - -#endif /* BIOSINT_H */ diff --git a/gpxe/src/arch/i386/include/bits/byteswap.h b/gpxe/src/arch/i386/include/bits/byteswap.h deleted file mode 100644 index ddbd40ed..00000000 --- a/gpxe/src/arch/i386/include/bits/byteswap.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef ETHERBOOT_BITS_BYTESWAP_H -#define ETHERBOOT_BITS_BYTESWAP_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -static inline __attribute__ ((always_inline, const)) uint16_t -__bswap_variable_16(uint16_t x) -{ - __asm__("xchgb %b0,%h0\n\t" - : "=q" (x) - : "0" (x)); - return x; -} - -static inline __attribute__ ((always_inline, const)) uint32_t -__bswap_variable_32(uint32_t x) -{ - __asm__("xchgb %b0,%h0\n\t" - "rorl $16,%0\n\t" - "xchgb %b0,%h0" - : "=q" (x) - : "0" (x)); - return x; -} - -static inline __attribute__ ((always_inline, const)) uint64_t -__bswap_variable_64(uint64_t x) -{ - union { - uint64_t qword; - uint32_t dword[2]; - } u; - - u.qword = x; - u.dword[0] = __bswap_variable_32(u.dword[0]); - u.dword[1] = __bswap_variable_32(u.dword[1]); - __asm__("xchgl %0,%1" - : "=r" ( u.dword[0] ), "=r" ( u.dword[1] ) - : "0" ( u.dword[0] ), "1" ( u.dword[1] ) ); - return u.qword; -} - -#endif /* ETHERBOOT_BITS_BYTESWAP_H */ diff --git a/gpxe/src/arch/i386/include/bits/compiler.h b/gpxe/src/arch/i386/include/bits/compiler.h deleted file mode 100644 index 000db0c1..00000000 --- a/gpxe/src/arch/i386/include/bits/compiler.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _BITS_COMPILER_H -#define _BITS_COMPILER_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef ASSEMBLY - -/** Declare a function with standard calling conventions */ -#define __asmcall __attribute__ (( cdecl, regparm(0) )) - -/** - * Declare a function with libgcc implicit linkage - * - * It seems as though gcc expects its implicit arithmetic functions to - * be cdecl, even if -mrtd is specified. This is somewhat - * inconsistent; for example, if -mregparm=3 is used then the implicit - * functions do become regparm(3). - * - * The implicit calls to memcpy() and memset() which gcc can generate - * do not seem to have this inconsistency; -mregparm and -mrtd affect - * them in the same way as any other function. - */ -#define __libgcc __attribute__ (( cdecl )) - -#endif /* ASSEMBLY */ - -#endif /* _BITS_COMPILER_H */ diff --git a/gpxe/src/arch/i386/include/bits/cpu.h b/gpxe/src/arch/i386/include/bits/cpu.h deleted file mode 100644 index 83339ddd..00000000 --- a/gpxe/src/arch/i386/include/bits/cpu.h +++ /dev/null @@ -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 */ diff --git a/gpxe/src/arch/i386/include/bits/eltorito.h b/gpxe/src/arch/i386/include/bits/eltorito.h deleted file mode 100644 index d43e9aac..00000000 --- a/gpxe/src/arch/i386/include/bits/eltorito.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef ELTORITO_PLATFORM -#define ELTORITO_PLATFORM ELTORITO_PLATFORM_X86 -#endif /* ELTORITO_PLATFORM */ diff --git a/gpxe/src/arch/i386/include/bits/endian.h b/gpxe/src/arch/i386/include/bits/endian.h deleted file mode 100644 index 84188542..00000000 --- a/gpxe/src/arch/i386/include/bits/endian.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ETHERBOOT_BITS_ENDIAN_H -#define ETHERBOOT_BITS_ENDIAN_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#define __BYTE_ORDER __LITTLE_ENDIAN - -#endif /* ETHERBOOT_BITS_ENDIAN_H */ diff --git a/gpxe/src/arch/i386/include/bits/errfile.h b/gpxe/src/arch/i386/include/bits/errfile.h deleted file mode 100644 index 32b8a085..00000000 --- a/gpxe/src/arch/i386/include/bits/errfile.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _BITS_ERRFILE_H -#define _BITS_ERRFILE_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @addtogroup errfile Error file identifiers - * @{ - */ - -#define ERRFILE_memtop_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 ) -#define ERRFILE_memmap ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 ) -#define ERRFILE_pnpbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 ) -#define ERRFILE_bios_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 ) -#define ERRFILE_biosint ( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 ) -#define ERRFILE_int13 ( ERRFILE_ARCH | ERRFILE_CORE | 0x00050000 ) -#define ERRFILE_pxeparent ( ERRFILE_ARCH | ERRFILE_CORE | 0x00060000 ) - -#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 ) -#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 ) -#define ERRFILE_eltorito ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00020000 ) -#define ERRFILE_multiboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00030000 ) -#define ERRFILE_nbi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00040000 ) -#define ERRFILE_pxe_image ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00050000 ) -#define ERRFILE_elfboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00060000 ) -#define ERRFILE_comboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00070000 ) -#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_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 ) -#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 ) -#define ERRFILE_undinet ( ERRFILE_ARCH | ERRFILE_NET | 0x00020000 ) -#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 ) - -/** @} */ - -#endif /* _BITS_ERRFILE_H */ diff --git a/gpxe/src/arch/i386/include/bits/io.h b/gpxe/src/arch/i386/include/bits/io.h deleted file mode 100644 index eded9778..00000000 --- a/gpxe/src/arch/i386/include/bits/io.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BITS_IO_H -#define _BITS_IO_H - -/** @file - * - * i386-specific I/O API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/x86_io.h> - -#endif /* _BITS_IO_H */ diff --git a/gpxe/src/arch/i386/include/bits/nap.h b/gpxe/src/arch/i386/include/bits/nap.h deleted file mode 100644 index 1354f6bb..00000000 --- a/gpxe/src/arch/i386/include/bits/nap.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _BITS_NAP_H -#define _BITS_NAP_H - -/** @file - * - * i386-specific CPU sleeping API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/bios_nap.h> -#include <gpxe/efi/efix86_nap.h> - -#endif /* _BITS_MAP_H */ diff --git a/gpxe/src/arch/i386/include/bits/smbios.h b/gpxe/src/arch/i386/include/bits/smbios.h deleted file mode 100644 index a68413aa..00000000 --- a/gpxe/src/arch/i386/include/bits/smbios.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BITS_SMBIOS_H -#define _BITS_SMBIOS_H - -/** @file - * - * i386-specific SMBIOS API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/bios_smbios.h> - -#endif /* _BITS_SMBIOS_H */ diff --git a/gpxe/src/arch/i386/include/bits/stdint.h b/gpxe/src/arch/i386/include/bits/stdint.h deleted file mode 100644 index 8edf1319..00000000 --- a/gpxe/src/arch/i386/include/bits/stdint.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _BITS_STDINT_H -#define _BITS_STDINT_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -typedef __SIZE_TYPE__ size_t; -typedef signed long ssize_t; -typedef signed long off_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef signed long long int64_t; - -typedef unsigned long physaddr_t; -typedef unsigned long intptr_t; - -#endif /* _BITS_STDINT_H */ diff --git a/gpxe/src/arch/i386/include/bits/timer.h b/gpxe/src/arch/i386/include/bits/timer.h deleted file mode 100644 index 32e6bd47..00000000 --- a/gpxe/src/arch/i386/include/bits/timer.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _BITS_TIMER_H -#define _BITS_TIMER_H - -/** @file - * - * i386-specific timer API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/bios_timer.h> -#include <gpxe/rdtsc_timer.h> - -#endif /* _BITS_TIMER_H */ diff --git a/gpxe/src/arch/i386/include/bits/uaccess.h b/gpxe/src/arch/i386/include/bits/uaccess.h deleted file mode 100644 index 2bb52e02..00000000 --- a/gpxe/src/arch/i386/include/bits/uaccess.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BITS_UACCESS_H -#define _BITS_UACCESS_H - -/** @file - * - * i386-specific user access API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <librm.h> - -#endif /* _BITS_UACCESS_H */ diff --git a/gpxe/src/arch/i386/include/bits/umalloc.h b/gpxe/src/arch/i386/include/bits/umalloc.h deleted file mode 100644 index 17ba2cb2..00000000 --- a/gpxe/src/arch/i386/include/bits/umalloc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BITS_UMALLOC_H -#define _BITS_UMALLOC_H - -/** @file - * - * i386-specific user memory allocation API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/memtop_umalloc.h> - -#endif /* _BITS_UMALLOC_H */ diff --git a/gpxe/src/arch/i386/include/bochs.h b/gpxe/src/arch/i386/include/bochs.h deleted file mode 100644 index 9d090fc1..00000000 --- a/gpxe/src/arch/i386/include/bochs.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef BOCHS_H -#define BOCHS_H - -/** @file - * - * bochs breakpoints - * - * This file defines @c bochsbp, the magic breakpoint instruction that - * is incredibly useful when debugging under bochs. This file should - * never be included in production code. - * - * Use the pseudo-instruction @c bochsbp in assembly code, or the - * bochsbp() function in C code. - * - */ - -#ifdef ASSEMBLY - -/* Breakpoint for when debugging under bochs */ -#define bochsbp xchgw %bx, %bx -#define BOCHSBP bochsbp - -#else /* ASSEMBLY */ - -/** Breakpoint for when debugging under bochs */ -static inline void bochsbp ( void ) { - __asm__ __volatile__ ( "xchgw %bx, %bx" ); -} - -#endif /* ASSEMBLY */ - -#warning "bochs.h should not be included into production code" - -#endif /* BOCHS_H */ diff --git a/gpxe/src/arch/i386/include/bootsector.h b/gpxe/src/arch/i386/include/bootsector.h deleted file mode 100644 index 8730fbfc..00000000 --- a/gpxe/src/arch/i386/include/bootsector.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BOOTSECTOR_H -#define _BOOTSECTOR_H - -/** @file - * - * x86 bootsector image format - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -extern int call_bootsector ( unsigned int segment, unsigned int offset, - unsigned int drive ); - -#endif /* _BOOTSECTOR_H */ diff --git a/gpxe/src/arch/i386/include/bzimage.h b/gpxe/src/arch/i386/include/bzimage.h deleted file mode 100644 index 42b31fe4..00000000 --- a/gpxe/src/arch/i386/include/bzimage.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef _BZIMAGE_H -#define _BZIMAGE_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> - -/** - * A bzImage header - * - * As documented in Documentation/i386/boot.txt - */ -struct bzimage_header { - /** The size of the setup in sectors - * - * If this field contains 0, assume it contains 4. - */ - uint8_t setup_sects; - /** If set, the root is mounted readonly */ - uint16_t root_flags; - /** DO NOT USE - for bootsect.S use only */ - uint16_t syssize; - /** DO NOT USE - obsolete */ - uint16_t swap_dev; - /** DO NOT USE - for bootsect.S use only */ - uint16_t ram_size; - /** Video mode control */ - uint16_t vid_mode; - /** Default root device number */ - uint16_t root_dev; - /** 0xAA55 magic number */ - uint16_t boot_flag; - /** Jump instruction */ - uint16_t jump; - /** Magic signature "HdrS" */ - uint32_t header; - /** Boot protocol version supported */ - uint16_t version; - /** Boot loader hook (see below) */ - uint32_t realmode_swtch; - /** The load-low segment (0x1000) (obsolete) */ - uint16_t start_sys; - /** Pointer to kernel version string */ - uint16_t kernel_version; - /** Boot loader identifier */ - uint8_t type_of_loader; - /** Boot protocol option flags */ - uint8_t loadflags; - /** Move to high memory size (used with hooks) */ - uint16_t setup_move_size; - /** Boot loader hook (see below) */ - uint32_t code32_start; - /** initrd load address (set by boot loader) */ - uint32_t ramdisk_image; - /** initrd size (set by boot loader) */ - uint32_t ramdisk_size; - /** DO NOT USE - for bootsect.S use only */ - uint32_t bootsect_kludge; - /** Free memory after setup end */ - uint16_t heap_end_ptr; - /** Unused */ - uint16_t pad1; - /** 32-bit pointer to the kernel command line */ - uint32_t cmd_line_ptr; - /** Highest legal initrd address */ - uint32_t initrd_addr_max; - /** Physical addr alignment required for kernel */ - uint32_t kernel_alignment; - /** Whether kernel is relocatable or not */ - uint8_t relocatable_kernel; - /** Unused */ - uint8_t pad2[3]; - /** Maximum size of the kernel command line */ - uint32_t cmdline_size; -} __attribute__ (( packed )); - -/** Offset of bzImage header within kernel image */ -#define BZI_HDR_OFFSET 0x1f1 - -/** bzImage boot flag value */ -#define BZI_BOOT_FLAG 0xaa55 - -/** bzImage magic signature value */ -#define BZI_SIGNATURE 0x53726448 - -/** bzImage boot loader identifier for Etherboot */ -#define BZI_LOADER_TYPE_ETHERBOOT 0x40 - -/** bzImage boot loader identifier for gPXE - * - * We advertise ourselves as Etherboot version 6. - */ -#define BZI_LOADER_TYPE_GPXE ( BZI_LOADER_TYPE_ETHERBOOT | 0x06 ) - -/** bzImage "load high" flag */ -#define BZI_LOAD_HIGH 0x01 - -/** Load address for high-loaded kernels */ -#define BZI_LOAD_HIGH_ADDR 0x100000 - -/** Load address for low-loaded kernels */ -#define BZI_LOAD_LOW_ADDR 0x10000 - -/** bzImage "kernel can use heap" flag */ -#define BZI_CAN_USE_HEAP 0x80 - -/** bzImage special video mode "normal" */ -#define BZI_VID_MODE_NORMAL 0xffff - -/** bzImage special video mode "ext" */ -#define BZI_VID_MODE_EXT 0xfffe - -/** bzImage special video mode "ask" */ -#define BZI_VID_MODE_ASK 0xfffd - -/** bzImage maximum initrd address for versions < 2.03 */ -#define BZI_INITRD_MAX 0x37ffffff - -/** bzImage command-line structure used by older kernels */ -struct bzimage_cmdline { - /** Magic signature */ - uint16_t magic; - /** Offset to command line */ - uint16_t offset; -} __attribute__ (( packed )); - -/** Offset of bzImage command-line structure within kernel image */ -#define BZI_CMDLINE_OFFSET 0x20 - -/** bzImage command line present magic marker value */ -#define BZI_CMDLINE_MAGIC 0xa33f - -/** Assumed size of real-mode portion (including .bss) */ -#define BZI_ASSUMED_RM_SIZE 0x8000 - -/** Amount of stack space to provide */ -#define BZI_STACK_SIZE 0x1000 - -/** Maximum size of command line */ -#define BZI_CMDLINE_SIZE 0x100 - -#endif /* _BZIMAGE_H */ diff --git a/gpxe/src/arch/i386/include/comboot.h b/gpxe/src/arch/i386/include/comboot.h deleted file mode 100644 index 1232f0a7..00000000 --- a/gpxe/src/arch/i386/include/comboot.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef COMBOOT_H -#define COMBOOT_H - -/** - * @file - * - * SYSLINUX COMBOOT - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <setjmp.h> -#include <gpxe/in.h> - -/** Segment used for COMBOOT PSP and image */ -#define COMBOOT_PSP_SEG 0x07C0 - -/** Entry point address of COM32 images */ -#define COM32_START_PHYS 0x101000 - -/** COM32 bounce buffer segment */ -#define COM32_BOUNCE_SEG 0x07C0 - -/** Size of SYSLINUX file block in bytes */ -#define COMBOOT_FILE_BLOCKSZ 512 - -/** COMBOOT feature flags (INT 22h AX=15h) */ -#define COMBOOT_FEATURE_LOCAL_BOOT (1 << 0) -#define COMBOOT_FEATURE_IDLE_LOOP (1 << 1) - -/** Maximum number of shuffle descriptors for - * shuffle and boot functions - * (INT 22h AX=0012h, 001Ah, 001Bh) - */ -#define COMBOOT_MAX_SHUFFLE_DESCRIPTORS 682 - -typedef union { - uint32_t l; - uint16_t w[2]; - uint8_t b[4]; -} com32_reg32_t; - -typedef struct { - uint16_t gs; /* Offset 0 */ - uint16_t fs; /* Offset 2 */ - uint16_t es; /* Offset 4 */ - uint16_t ds; /* Offset 6 */ - - com32_reg32_t edi; /* Offset 8 */ - com32_reg32_t esi; /* Offset 12 */ - com32_reg32_t ebp; /* Offset 16 */ - com32_reg32_t _unused_esp; /* Offset 20 */ - com32_reg32_t ebx; /* Offset 24 */ - com32_reg32_t edx; /* Offset 28 */ - com32_reg32_t ecx; /* Offset 32 */ - com32_reg32_t eax; /* Offset 36 */ - - com32_reg32_t eflags; /* Offset 40 */ -} com32sys_t; - -typedef struct { - uint32_t eax; /* Offset 0 */ - uint32_t ecx; /* Offset 4 */ - uint32_t edx; /* Offset 8 */ - uint32_t ebx; /* Offset 12 */ - uint32_t esp; /* Offset 16 */ - uint32_t ebp; /* Offset 20 */ - uint32_t esi; /* Offset 24 */ - uint32_t edi; /* Offset 28 */ - - uint32_t eip; /* Offset 32 */ -} syslinux_pm_regs; - -typedef struct { - uint16_t es; /* Offset 0 */ - uint16_t _unused_cs; /* Offset 2 */ - uint16_t ds; /* Offset 4 */ - uint16_t ss; /* Offset 6 */ - uint16_t fs; /* Offset 8 */ - uint16_t gs; /* Offset 10 */ - - uint32_t eax; /* Offset 12 */ - uint32_t ecx; /* Offset 16 */ - uint32_t edx; /* Offset 20 */ - uint32_t ebx; /* Offset 24 */ - uint32_t esp; /* Offset 28 */ - uint32_t ebp; /* Offset 32 */ - uint32_t esi; /* Offset 36 */ - uint32_t edi; /* Offset 40 */ - - uint16_t ip; /* Offset 44 */ - uint16_t cs; /* Offset 46 */ -} syslinux_rm_regs; - -typedef struct { - uint32_t dest; - uint32_t src; - uint32_t len; -} comboot_shuffle_descriptor; - -extern void hook_comboot_interrupts ( ); -extern void unhook_comboot_interrupts ( ); - -/* These are not the correct prototypes, but it doens't matter, - * as we only ever get the address of these functions; - * they are only called from COM32 code running in PHYS_CODE - */ -extern void com32_intcall_wrapper ( ); -extern void com32_farcall_wrapper ( ); -extern void com32_cfarcall_wrapper ( ); - -/* Resolve a hostname to an (IPv4) address */ -extern int comboot_resolv ( const char *name, struct in_addr *address ); - -/* setjmp/longjmp context buffer used to return after loading an image */ -extern rmjmp_buf comboot_return; - -/* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */ -extern struct image *comboot_replacement_image; - -extern void *com32_external_esp; - -#define COMBOOT_EXIT 1 -#define COMBOOT_EXIT_RUN_KERNEL 2 -#define COMBOOT_EXIT_COMMAND 3 - -extern void comboot_force_text_mode ( void ); - -#define COMBOOT_VIDEO_GRAPHICS 0x01 -#define COMBOOT_VIDEO_NONSTANDARD 0x02 -#define COMBOOT_VIDEO_VESA 0x04 -#define COMBOOT_VIDEO_NOTEXT 0x08 - -#endif diff --git a/gpxe/src/arch/i386/include/fakee820.h b/gpxe/src/arch/i386/include/fakee820.h deleted file mode 100644 index 9d00fb67..00000000 --- a/gpxe/src/arch/i386/include/fakee820.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _FAKEE820_H -#define _FAKEE820_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -extern void fake_e820 ( void ); -extern void unfake_e820 ( void ); - -#endif /* _FAKEE820_H */ diff --git a/gpxe/src/arch/i386/include/gateA20.h b/gpxe/src/arch/i386/include/gateA20.h deleted file mode 100644 index 297ad6f2..00000000 --- a/gpxe/src/arch/i386/include/gateA20.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef GATEA20_H -#define GATEA20_H - -extern void gateA20_set ( void ); -extern void gateA20_unset ( void ); - -#endif /* GATEA20_H */ diff --git a/gpxe/src/arch/i386/include/gdbmach.h b/gpxe/src/arch/i386/include/gdbmach.h deleted file mode 100644 index 794dab19..00000000 --- a/gpxe/src/arch/i386/include/gdbmach.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef GDBMACH_H -#define GDBMACH_H - -/** @file - * - * GDB architecture specifics - * - * This file declares functions for manipulating the machine state and - * debugging context. - * - */ - -#include <stdint.h> - -typedef unsigned long gdbreg_t; - -/* The register snapshot, this must be in sync with interrupt handler and the - * GDB protocol. */ -enum { - GDBMACH_EAX, - GDBMACH_ECX, - GDBMACH_EDX, - GDBMACH_EBX, - GDBMACH_ESP, - GDBMACH_EBP, - GDBMACH_ESI, - GDBMACH_EDI, - GDBMACH_EIP, - GDBMACH_EFLAGS, - GDBMACH_CS, - GDBMACH_SS, - GDBMACH_DS, - GDBMACH_ES, - GDBMACH_FS, - GDBMACH_GS, - GDBMACH_NREGS, - GDBMACH_SIZEOF_REGS = GDBMACH_NREGS * sizeof ( gdbreg_t ) -}; - -/* Breakpoint types */ -enum { - GDBMACH_BPMEM, - GDBMACH_BPHW, - GDBMACH_WATCH, - GDBMACH_RWATCH, - GDBMACH_AWATCH, -}; - -static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) { - regs [ GDBMACH_EIP ] = pc; -} - -static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) { - regs [ GDBMACH_EFLAGS ] &= ~( 1 << 8 ); /* Trace Flag (TF) */ - regs [ GDBMACH_EFLAGS ] |= ( step << 8 ); -} - -static inline void gdbmach_breakpoint ( void ) { - __asm__ __volatile__ ( "int $3\n" ); -} - -extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ); - -#endif /* GDBMACH_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/abft.h b/gpxe/src/arch/i386/include/gpxe/abft.h deleted file mode 100644 index 9065e61a..00000000 --- a/gpxe/src/arch/i386/include/gpxe/abft.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _GPXE_ABFT_H -#define _GPXE_ABFT_H - -/** @file - * - * AoE boot firmware table - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <gpxe/acpi.h> -#include <gpxe/if_ether.h> - -/** AoE boot firmware table signature */ -#define ABFT_SIG "aBFT" - -/** - * AoE Boot Firmware Table (aBFT) - */ -struct abft_table { - /** ACPI header */ - struct acpi_description_header acpi; - /** AoE shelf */ - uint16_t shelf; - /** AoE slot */ - uint8_t slot; - /** Reserved */ - uint8_t reserved_a; - /** MAC address */ - uint8_t mac[ETH_ALEN]; -} __attribute__ (( packed )); - -extern void abft_fill_data ( struct aoe_session *aoe ); - -#endif /* _GPXE_ABFT_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/bios_nap.h b/gpxe/src/arch/i386/include/gpxe/bios_nap.h deleted file mode 100644 index c32429b9..00000000 --- a/gpxe/src/arch/i386/include/gpxe/bios_nap.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _GPXE_BIOS_NAP_H -#define _GPXE_BIOS_NAP_H - -/** @file - * - * BIOS CPU sleeping - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef NAP_PCBIOS -#define NAP_PREFIX_pcbios -#else -#define NAP_PREFIX_pcbios __pcbios_ -#endif - -#endif /* _GPXE_BIOS_NAP_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/bios_smbios.h b/gpxe/src/arch/i386/include/gpxe/bios_smbios.h deleted file mode 100644 index 83726b11..00000000 --- a/gpxe/src/arch/i386/include/gpxe/bios_smbios.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _GPXE_BIOS_SMBIOS_H -#define _GPXE_BIOS_SMBIOS_H - -/** @file - * - * Standard PC-BIOS SMBIOS interface - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef SMBIOS_PCBIOS -#define SMBIOS_PREFIX_pcbios -#else -#define SMBIOS_PREFIX_pcbios __pcbios_ -#endif - -#endif /* _GPXE_BIOS_SMBIOS_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/bios_timer.h b/gpxe/src/arch/i386/include/gpxe/bios_timer.h deleted file mode 100644 index ed9df522..00000000 --- a/gpxe/src/arch/i386/include/gpxe/bios_timer.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _GPXE_BIOS_TIMER_H -#define _GPXE_BIOS_TIMER_H - -/** @file - * - * BIOS timer - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef TIMER_PCBIOS -#define TIMER_PREFIX_pcbios -#else -#define TIMER_PREFIX_pcbios __pcbios_ -#endif - -#include <gpxe/timer2.h> - -/** - * Delay for a fixed number of microseconds - * - * @v usecs Number of microseconds for which to delay - */ -static inline __always_inline void -TIMER_INLINE ( pcbios, udelay ) ( unsigned long usecs ) { - /* BIOS timer is not high-resolution enough for udelay(), so - * we use timer2 - */ - timer2_udelay ( usecs ); -} - -/** - * Get number of ticks per second - * - * @ret ticks_per_sec Number of ticks per second - */ -static inline __always_inline unsigned long -TIMER_INLINE ( pcbios, ticks_per_sec ) ( void ) { - /* BIOS timer ticks over at 18.2 ticks per second */ - return 18; -} - -#endif /* _GPXE_BIOS_TIMER_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/ibft.h b/gpxe/src/arch/i386/include/gpxe/ibft.h deleted file mode 100644 index c41e2e40..00000000 --- a/gpxe/src/arch/i386/include/gpxe/ibft.h +++ /dev/null @@ -1,302 +0,0 @@ -#ifndef _GPXE_IBFT_H -#define _GPXE_IBFT_H - -/* - * Copyright Fen Systems Ltd. 2007. Portions of this code are derived - * from IBM Corporation Sample Programs. Copyright IBM Corporation - * 2004, 2007. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -FILE_LICENCE ( BSD2 ); - -/** @file - * - * iSCSI boot firmware table - * - * The information in this file is derived from the document "iSCSI - * Boot Firmware Table (iBFT)" as published by IBM at - * - * ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf - * - */ - -#include <stdint.h> -#include <gpxe/acpi.h> -#include <gpxe/in.h> - -/** iSCSI Boot Firmware Table signature */ -#define IBFT_SIG "iBFT" - -/** An offset from the start of the iBFT */ -typedef uint16_t ibft_off_t; - -/** Length of a string within the iBFT (excluding terminating NUL) */ -typedef uint16_t ibft_size_t; - -/** A string within the iBFT */ -struct ibft_string { - /** Length of string */ - ibft_size_t length; - /** Offset to string */ - ibft_off_t offset; -} __attribute__ (( packed )); - -/** An IP address within the iBFT */ -struct ibft_ipaddr { - /** Reserved; must be zero */ - uint16_t zeroes[5]; - /** Must be 0xffff if IPv4 address is present, otherwise zero */ - uint16_t ones; - /** The IPv4 address, or zero if not present */ - struct in_addr in; -} __attribute__ (( packed )); - -/** - * iBFT structure header - * - * This structure is common to several sections within the iBFT. - */ -struct ibft_header { - /** Structure ID - * - * This is an IBFT_STRUCTURE_ID_XXX constant - */ - uint8_t structure_id; - /** Version (always 1) */ - uint8_t version; - /** Length, including this header */ - uint16_t length; - /** Index - * - * This is the number of the NIC or Target, when applicable. - */ - uint8_t index; - /** Flags */ - uint8_t flags; -} __attribute__ (( packed )); - -/** - * iBFT Control structure - * - */ -struct ibft_control { - /** Common header */ - struct ibft_header header; - /** Extensions */ - uint16_t extensions; - /** Offset to Initiator structure */ - ibft_off_t initiator; - /** Offset to NIC structure for NIC 0 */ - ibft_off_t nic_0; - /** Offset to Target structure for target 0 */ - ibft_off_t target_0; - /** Offset to NIC structure for NIC 1 */ - ibft_off_t nic_1; - /** Offset to Target structure for target 1 */ - ibft_off_t target_1; -} __attribute__ (( packed )); - -/** Structure ID for Control section */ -#define IBFT_STRUCTURE_ID_CONTROL 0x01 - -/** Attempt login only to specified target - * - * If this flag is not set, all targets will be logged in to. - */ -#define IBFT_FL_CONTROL_SINGLE_LOGIN_ONLY 0x01 - -/** - * iBFT Initiator structure - * - */ -struct ibft_initiator { - /** Common header */ - struct ibft_header header; - /** iSNS server */ - struct ibft_ipaddr isns_server; - /** SLP server */ - struct ibft_ipaddr slp_server; - /** Primary and secondary Radius servers */ - struct ibft_ipaddr radius[2]; - /** Initiator name */ - struct ibft_string initiator_name; -} __attribute__ (( packed )); - -/** Structure ID for Initiator section */ -#define IBFT_STRUCTURE_ID_INITIATOR 0x02 - -/** Initiator block valid */ -#define IBFT_FL_INITIATOR_BLOCK_VALID 0x01 - -/** Initiator firmware boot selected */ -#define IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED 0x02 - -/** - * iBFT NIC structure - * - */ -struct ibft_nic { - /** Common header */ - struct ibft_header header; - /** IP address */ - struct ibft_ipaddr ip_address; - /** Subnet mask - * - * This is the length of the subnet mask in bits (e.g. /24). - */ - uint8_t subnet_mask_prefix; - /** Origin */ - uint8_t origin; - /** Default gateway */ - struct ibft_ipaddr gateway; - /** Primary and secondary DNS servers */ - struct ibft_ipaddr dns[2]; - /** DHCP server */ - struct ibft_ipaddr dhcp; - /** VLAN tag */ - uint16_t vlan; - /** MAC address */ - uint8_t mac_address[6]; - /** PCI bus:dev:fn */ - uint16_t pci_bus_dev_func; - /** Hostname */ - struct ibft_string hostname; -} __attribute__ (( packed )); - -/** Structure ID for NIC section */ -#define IBFT_STRUCTURE_ID_NIC 0x03 - -/** NIC block valid */ -#define IBFT_FL_NIC_BLOCK_VALID 0x01 - -/** NIC firmware boot selected */ -#define IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED 0x02 - -/** NIC global / link local */ -#define IBFT_FL_NIC_GLOBAL 0x04 - -/** - * iBFT Target structure - * - */ -struct ibft_target { - /** Common header */ - struct ibft_header header; - /** IP address */ - struct ibft_ipaddr ip_address; - /** TCP port */ - uint16_t socket; - /** Boot LUN */ - uint64_t boot_lun; - /** CHAP type - * - * This is an IBFT_CHAP_XXX constant. - */ - uint8_t chap_type; - /** NIC association */ - uint8_t nic_association; - /** Target name */ - struct ibft_string target_name; - /** CHAP name */ - struct ibft_string chap_name; - /** CHAP secret */ - struct ibft_string chap_secret; - /** Reverse CHAP name */ - struct ibft_string reverse_chap_name; - /** Reverse CHAP secret */ - struct ibft_string reverse_chap_secret; -} __attribute__ (( packed )); - -/** Structure ID for Target section */ -#define IBFT_STRUCTURE_ID_TARGET 0x04 - -/** Target block valid */ -#define IBFT_FL_TARGET_BLOCK_VALID 0x01 - -/** Target firmware boot selected */ -#define IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED 0x02 - -/** Target use Radius CHAP */ -#define IBFT_FL_TARGET_USE_CHAP 0x04 - -/** Target use Radius rCHAP */ -#define IBFT_FL_TARGET_USE_RCHAP 0x08 - -/* Values for chap_type */ -#define IBFT_CHAP_NONE 0 /**< No CHAP authentication */ -#define IBFT_CHAP_ONE_WAY 1 /**< One-way CHAP */ -#define IBFT_CHAP_MUTUAL 2 /**< Mutual CHAP */ - -/** - * iSCSI Boot Firmware Table (iBFT) - */ -struct ibft_table { - /** ACPI header */ - struct acpi_description_header acpi; - /** Reserved */ - uint8_t reserved[12]; - /** Control structure */ - struct ibft_control control; -} __attribute__ (( packed )); - -/** - * iSCSI string block descriptor - * - * This is an internal structure that we use to keep track of the - * allocation of string data. - */ -struct ibft_string_block { - /** The iBFT containing these strings */ - struct ibft_table *table; - /** Offset of first free byte within iBFT */ - unsigned int offset; -}; - -/** Amount of space reserved for strings in a gPXE iBFT */ -#define IBFT_STRINGS_SIZE 384 - -/** - * An iBFT created by gPXE - * - */ -struct gpxe_ibft { - /** The fixed section */ - struct ibft_table table; - /** The Initiator section */ - struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) )); - /** The NIC section */ - struct ibft_nic nic __attribute__ (( aligned ( 16 ) )); - /** The Target section */ - struct ibft_target target __attribute__ (( aligned ( 16 ) )); - /** Strings block */ - char strings[IBFT_STRINGS_SIZE]; -} __attribute__ (( packed, aligned ( 16 ) )); - -struct net_device; -struct iscsi_session; - -extern int ibft_fill_data ( struct net_device *netdev, - struct iscsi_session *iscsi ); - -#endif /* _GPXE_IBFT_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h b/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h deleted file mode 100644 index eaf7025b..00000000 --- a/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _GPXE_MEMTOP_UMALLOC_H -#define _GPXE_MEMTOP_UMALLOC_H - -/** @file - * - * External memory allocation - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef UMALLOC_MEMTOP -#define UMALLOC_PREFIX_memtop -#else -#define UMALLOC_PREFIX_memtop __memtop_ -#endif - -#endif /* _GPXE_MEMTOP_UMALLOC_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h b/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h deleted file mode 100644 index 67ba22f0..00000000 --- a/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _GPXE_RDTSC_TIMER_H -#define _GPXE_RDTSC_TIMER_H - -/** @file - * - * RDTSC timer - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef TIMER_RDTSC -#define TIMER_PREFIX_rdtsc -#else -#define TIMER_PREFIX_rdtsc __rdtsc_ -#endif - -/** - * RDTSC values can easily overflow an unsigned long. We discard the - * low-order bits in order to obtain sensibly-scaled values. - */ -#define TSC_SHIFT 8 - -/** - * Get current system time in ticks - * - * @ret ticks Current time, in ticks - */ -static inline __always_inline unsigned long -TIMER_INLINE ( rdtsc, currticks ) ( void ) { - unsigned long ticks; - - __asm__ __volatile__ ( "rdtsc\n\t" - "shrdl %1, %%edx, %%eax\n\t" - : "=a" ( ticks ) : "i" ( TSC_SHIFT ) : "edx" ); - return ticks; -} - -#endif /* _GPXE_RDTSC_TIMER_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/sbft.h b/gpxe/src/arch/i386/include/gpxe/sbft.h deleted file mode 100644 index 30038436..00000000 --- a/gpxe/src/arch/i386/include/gpxe/sbft.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef _GPXE_SBFT_H -#define _GPXE_SBFT_H - -/* - * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -FILE_LICENCE ( BSD2 ); - -/** @file - * - * SRP boot firmware table - * - * The working draft specification for the SRP boot firmware table can - * be found at - * - * http://etherboot.org/wiki/srp/sbft - * - */ - -#include <stdint.h> -#include <gpxe/acpi.h> -#include <gpxe/scsi.h> -#include <gpxe/srp.h> -#include <gpxe/ib_srp.h> - -/** SRP Boot Firmware Table signature */ -#define SBFT_SIG "sBFT" - -/** An offset from the start of the sBFT */ -typedef uint16_t sbft_off_t; - -/** - * SRP Boot Firmware Table - */ -struct sbft_table { - /** ACPI header */ - struct acpi_description_header acpi; - /** Offset to SCSI subtable */ - sbft_off_t scsi_offset; - /** Offset to SRP subtable */ - sbft_off_t srp_offset; - /** Offset to IB subtable, if present */ - sbft_off_t ib_offset; - /** Reserved */ - uint8_t reserved[6]; -} __attribute__ (( packed )); - -/** - * sBFT SCSI subtable - */ -struct sbft_scsi_subtable { - /** LUN */ - struct scsi_lun lun; -} __attribute__ (( packed )); - -/** - * sBFT SRP subtable - */ -struct sbft_srp_subtable { - /** Initiator and target ports */ - struct srp_port_ids port_ids; -} __attribute__ (( packed )); - -/** - * sBFT IB subtable - */ -struct sbft_ib_subtable { - /** Source GID */ - struct ib_gid sgid; - /** Destination GID */ - struct ib_gid dgid; - /** Service ID */ - struct ib_gid_half service_id; - /** Partition key */ - uint16_t pkey; - /** Reserved */ - uint8_t reserved[6]; -} __attribute__ (( packed )); - -/** - * An sBFT created by gPXE - */ -struct gpxe_sbft { - /** The table header */ - struct sbft_table table; - /** The SCSI subtable */ - struct sbft_scsi_subtable scsi; - /** The SRP subtable */ - struct sbft_srp_subtable srp; - /** The IB subtable */ - struct sbft_ib_subtable ib; -} __attribute__ (( packed, aligned ( 16 ) )); - -struct srp_device; - -extern int sbft_fill_data ( struct srp_device *srp ); - -#endif /* _GPXE_SBFT_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/timer2.h b/gpxe/src/arch/i386/include/gpxe/timer2.h deleted file mode 100644 index 8f119515..00000000 --- a/gpxe/src/arch/i386/include/gpxe/timer2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _GPXE_TIMER2_H -#define _GPXE_TIMER2_H - -/** @file - * - * Timer chip control - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -extern void timer2_udelay ( unsigned long usecs ); - -#endif /* _GPXE_TIMER2_H */ diff --git a/gpxe/src/arch/i386/include/gpxe/x86_io.h b/gpxe/src/arch/i386/include/gpxe/x86_io.h deleted file mode 100644 index beb5b22a..00000000 --- a/gpxe/src/arch/i386/include/gpxe/x86_io.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef _GPXE_X86_IO_H -#define _GPXE_X86_IO_H - -/** @file - * - * gPXE I/O API for x86 - * - * i386 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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef IOAPI_X86 -#define IOAPI_PREFIX_x86 -#else -#define IOAPI_PREFIX_x86 __x86_ -#endif - -/* - * Memory space mappings - * - */ - -/* - * Physical<->Bus and Bus<->I/O address mappings - * - */ - -static inline __always_inline unsigned long -IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) { - return phys_addr; -} - -static inline __always_inline unsigned long -IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) { - return bus_addr; -} - -static inline __always_inline void * -IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) { - return phys_to_virt ( bus_addr ); -} - -static inline __always_inline void -IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) { - /* Nothing to do */ -} - -static inline __always_inline unsigned long -IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) { - return virt_to_phys ( io_addr ); -} - -/* - * MMIO reads and writes up to 32 bits - * - */ - -#define X86_READX( _api_func, _type ) \ -static inline __always_inline _type \ -IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \ - return *io_addr; \ -} -X86_READX ( readb, uint8_t ); -X86_READX ( readw, uint16_t ); -X86_READX ( readl, uint32_t ); - -#define X86_WRITEX( _api_func, _type ) \ -static inline __always_inline void \ -IOAPI_INLINE ( x86, _api_func ) ( _type data, \ - volatile _type *io_addr ) { \ - *io_addr = data; \ -} -X86_WRITEX ( writeb, uint8_t ); -X86_WRITEX ( writew, uint16_t ); -X86_WRITEX ( writel, uint32_t ); - -/* - * PIO reads and writes up to 32 bits - * - */ - -#define X86_INX( _insn_suffix, _type, _reg_prefix ) \ -static inline __always_inline _type \ -IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \ - _type data; \ - __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \ - : "=a" ( data ) : "Nd" ( io_addr ) ); \ - return data; \ -} \ -static inline __always_inline void \ -IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \ - _type *data, \ - unsigned int count ) { \ - unsigned int discard_D; \ - __asm__ __volatile__ ( "rep ins" #_insn_suffix \ - : "=D" ( discard_D ) \ - : "d" ( io_addr ), "c" ( count ), \ - "0" ( data ) ); \ -} -X86_INX ( b, uint8_t, "b" ); -X86_INX ( w, uint16_t, "w" ); -X86_INX ( l, uint32_t, "k" ); - -#define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \ -static inline __always_inline void \ -IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \ - volatile _type *io_addr ) { \ - __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \ - : : "a" ( data ), "Nd" ( io_addr ) ); \ -} \ -static inline __always_inline void \ -IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \ - const _type *data, \ - unsigned int count ) { \ - unsigned int discard_S; \ - __asm__ __volatile__ ( "rep outs" #_insn_suffix \ - : "=S" ( discard_S ) \ - : "d" ( io_addr ), "c" ( count ), \ - "0" ( data ) ); \ -} -X86_OUTX ( b, uint8_t, "b" ); -X86_OUTX ( w, uint16_t, "w" ); -X86_OUTX ( l, uint32_t, "k" ); - -/* - * Slow down I/O - * - */ - -static inline __always_inline void -IOAPI_INLINE ( x86, iodelay ) ( void ) { - __asm__ __volatile__ ( "outb %al, $0x80" ); -} - -/* - * Memory barrier - * - */ - -static inline __always_inline void -IOAPI_INLINE ( x86, mb ) ( void ) { - __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" ); -} - -#endif /* _GPXE_X86_IO_H */ diff --git a/gpxe/src/arch/i386/include/int13.h b/gpxe/src/arch/i386/include/int13.h deleted file mode 100644 index e1884d94..00000000 --- a/gpxe/src/arch/i386/include/int13.h +++ /dev/null @@ -1,292 +0,0 @@ -#ifndef INT13_H -#define INT13_H - -/** @file - * - * INT 13 emulation - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <gpxe/list.h> -#include <realmode.h> - -struct block_device; - -/** - * @defgroup int13ops INT 13 operation codes - * @{ - */ - -/** Reset disk system */ -#define INT13_RESET 0x00 -/** Get status of last operation */ -#define INT13_GET_LAST_STATUS 0x01 -/** Read sectors */ -#define INT13_READ_SECTORS 0x02 -/** Write sectors */ -#define INT13_WRITE_SECTORS 0x03 -/** Get drive parameters */ -#define INT13_GET_PARAMETERS 0x08 -/** Get disk type */ -#define INT13_GET_DISK_TYPE 0x15 -/** Extensions installation check */ -#define INT13_EXTENSION_CHECK 0x41 -/** Extended read */ -#define INT13_EXTENDED_READ 0x42 -/** Extended write */ -#define INT13_EXTENDED_WRITE 0x43 -/** Get extended drive parameters */ -#define INT13_GET_EXTENDED_PARAMETERS 0x48 -/** Get CD-ROM status / terminate emulation */ -#define INT13_CDROM_STATUS_TERMINATE 0x4b - -/** @} */ - -/** - * @defgroup int13status INT 13 status codes - * @{ - */ - -/** Operation completed successfully */ -#define INT13_STATUS_SUCCESS 0x00 -/** Invalid function or parameter */ -#define INT13_STATUS_INVALID 0x01 -/** Read error */ -#define INT13_STATUS_READ_ERROR 0x04 -/** Write error */ -#define INT13_STATUS_WRITE_ERROR 0xcc - -/** @} */ - -/** Block size for non-extended INT 13 calls */ -#define INT13_BLKSIZE 512 - -/** An INT 13 emulated drive */ -struct int13_drive { - /** List of all registered drives */ - struct list_head list; - - /** Underlying block device */ - struct block_device *blockdev; - - /** BIOS in-use drive number (0x80-0xff) */ - unsigned int drive; - /** BIOS natural drive number (0x80-0xff) - * - * This is the drive number that would have been assigned by - * 'naturally' appending the drive to the end of the BIOS - * drive list. - * - * If the emulated drive replaces a preexisting drive, this is - * the drive number that the preexisting drive gets remapped - * to. - */ - unsigned int natural_drive; - - /** Number of cylinders - * - * The cylinder number field in an INT 13 call is ten bits - * wide, giving a maximum of 1024 cylinders. Conventionally, - * when the 7.8GB limit of a CHS address is exceeded, it is - * the number of cylinders that is increased beyond the - * addressable limit. - */ - unsigned int cylinders; - /** Number of heads - * - * The head number field in an INT 13 call is eight bits wide, - * giving a maximum of 256 heads. However, apparently all - * versions of MS-DOS up to and including Win95 fail with 256 - * heads, so the maximum encountered in practice is 255. - */ - unsigned int heads; - /** Number of sectors per track - * - * The sector number field in an INT 13 call is six bits wide, - * giving a maximum of 63 sectors, since sector numbering - * (unlike head and cylinder numbering) starts at 1, not 0. - */ - unsigned int sectors_per_track; - - /** Status of last operation */ - int last_status; -}; - -/** An INT 13 disk address packet */ -struct int13_disk_address { - /** Size of the packet, in bytes */ - uint8_t bufsize; - /** Reserved, must be zero */ - uint8_t reserved; - /** Block count */ - uint16_t count; - /** Data buffer */ - struct segoff buffer; - /** Starting block number */ - uint64_t lba; - /** Data buffer (EDD-3.0 only) */ - uint64_t buffer_phys; -} __attribute__ (( packed )); - -/** INT 13 disk parameters */ -struct int13_disk_parameters { - /** Size of this structure */ - uint16_t bufsize; - /** Flags */ - uint16_t flags; - /** Number of cylinders */ - uint32_t cylinders; - /** Number of heads */ - uint32_t heads; - /** Number of sectors per track */ - uint32_t sectors_per_track; - /** Total number of sectors on drive */ - uint64_t sectors; - /** Bytes per sector */ - uint16_t sector_size; - -} __attribute__ (( packed )); - -/** - * @defgroup int13types INT 13 disk types - * @{ - */ - -/** No such drive */ -#define INT13_DISK_TYPE_NONE 0x00 -/** Floppy without change-line support */ -#define INT13_DISK_TYPE_FDD 0x01 -/** Floppy with change-line support */ -#define INT13_DISK_TYPE_FDD_CL 0x02 -/** Hard disk */ -#define INT13_DISK_TYPE_HDD 0x03 - -/** @} */ - -/** - * @defgroup int13flags INT 13 disk parameter flags - * @{ - */ - -/** DMA boundary errors handled transparently */ -#define INT13_FL_DMA_TRANSPARENT 0x01 -/** CHS information is valid */ -#define INT13_FL_CHS_VALID 0x02 -/** Removable drive */ -#define INT13_FL_REMOVABLE 0x04 -/** Write with verify supported */ -#define INT13_FL_VERIFIABLE 0x08 -/** Has change-line supported (valid only for removable drives) */ -#define INT13_FL_CHANGE_LINE 0x10 -/** Drive can be locked (valid only for removable drives) */ -#define INT13_FL_LOCKABLE 0x20 -/** CHS is max possible, not current media (valid only for removable drives) */ -#define INT13_FL_CHS_MAX 0x40 - -/** @} */ - -/** - * @defgroup int13exts INT 13 extension flags - * @{ - */ - -/** Extended disk access functions supported */ -#define INT13_EXTENSION_LINEAR 0x01 -/** Removable drive functions supported */ -#define INT13_EXTENSION_REMOVABLE 0x02 -/** EDD functions supported */ -#define INT13_EXTENSION_EDD 0x04 - -/** @} */ - -/** - * @defgroup int13vers INT 13 extension versions - * @{ - */ - -/** INT13 extensions version 1.x */ -#define INT13_EXTENSION_VER_1_X 0x01 -/** INT13 extensions version 2.0 (EDD-1.0) */ -#define INT13_EXTENSION_VER_2_0 0x20 -/** INT13 extensions version 2.1 (EDD-1.1) */ -#define INT13_EXTENSION_VER_2_1 0x21 -/** INT13 extensions version 3.0 (EDD-3.0) */ -#define INT13_EXTENSION_VER_3_0 0x30 - -/** @} */ - -/** Bootable CD-ROM specification packet */ -struct int13_cdrom_specification { - /** Size of packet in bytes */ - uint8_t size; - /** Boot media type */ - uint8_t media_type; - /** Drive number */ - uint8_t drive; - /** CD-ROM controller number */ - uint8_t controller; - /** LBA of disk image to emulate */ - uint32_t lba; - /** Device specification */ - uint16_t device; - /** Segment of 3K buffer for caching CD-ROM reads */ - uint16_t cache_segment; - /** Load segment for initial boot image */ - uint16_t load_segment; - /** Number of 512-byte sectors to load */ - uint16_t load_sectors; - /** Low 8 bits of cylinder number */ - uint8_t cyl; - /** Sector number, plus high 2 bits of cylinder number */ - uint8_t cyl_sector; - /** Head number */ - uint8_t head; -} __attribute__ (( packed )); - -/** A C/H/S address within a partition table entry */ -struct partition_chs { - /** Head number */ - uint8_t head; - /** Sector number, plus high 2 bits of cylinder number */ - uint8_t cyl_sector; - /** Low 8 bits of cylinder number */ - uint8_t cyl; -} __attribute__ (( packed )); - -#define PART_HEAD(chs) ( (chs).head ) -#define PART_SECTOR(chs) ( (chs).cyl_sector & 0x3f ) -#define PART_CYLINDER(chs) ( (chs).cyl | ( ( (chs).cyl_sector & 0xc0 ) << 2 ) ) - -/** A partition table entry within the MBR */ -struct partition_table_entry { - /** Bootable flag */ - uint8_t bootable; - /** C/H/S start address */ - struct partition_chs chs_start; - /** System indicator (partition type) */ - uint8_t type; - /** C/H/S end address */ - struct partition_chs chs_end; - /** Linear start address */ - uint32_t start; - /** Linear length */ - uint32_t length; -} __attribute__ (( packed )); - -/** A Master Boot Record */ -struct master_boot_record { - uint8_t pad[446]; - /** Partition table */ - struct partition_table_entry partitions[4]; - /** 0x55aa MBR signature */ - uint16_t signature; -} __attribute__ (( packed )); - -extern void register_int13_drive ( struct int13_drive *drive ); -extern void unregister_int13_drive ( struct int13_drive *drive ); -extern int int13_boot ( unsigned int drive ); - -#endif /* INT13_H */ diff --git a/gpxe/src/arch/i386/include/kir.h b/gpxe/src/arch/i386/include/kir.h deleted file mode 100644 index 84633d26..00000000 --- a/gpxe/src/arch/i386/include/kir.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef KIR_H -#define KIR_H - -#ifndef KEEP_IT_REAL -#error "kir.h can be used only with -DKEEP_IT_REAL" -#endif - -#ifdef ASSEMBLY - -#define code32 code16gcc - -#else /* ASSEMBLY */ - -__asm__ ( ".code16gcc" ); - -#endif /* ASSEMBLY */ - -#endif /* KIR_H */ diff --git a/gpxe/src/arch/i386/include/libkir.h b/gpxe/src/arch/i386/include/libkir.h deleted file mode 100644 index 1f5b1350..00000000 --- a/gpxe/src/arch/i386/include/libkir.h +++ /dev/null @@ -1,233 +0,0 @@ -#ifndef LIBKIR_H -#define LIBKIR_H - -#include "realmode.h" - -#ifndef ASSEMBLY - -/* - * Full API documentation for these functions is in realmode.h. - * - */ - -/* Access to variables in .data16 and .text16 in a way compatible with librm */ -#define __data16( variable ) variable -#define __data16_array( variable, array ) variable array -#define __bss16( variable ) variable -#define __bss16_array( variable, array ) variable array -#define __text16( variable ) variable -#define __text16_array( variable,array ) variable array -#define __use_data16( variable ) variable -#define __use_text16( variable ) variable -#define __from_data16( pointer ) pointer -#define __from_text16( pointer ) pointer - -/* Real-mode data and code segments */ -static inline __attribute__ (( always_inline )) unsigned int _rm_cs ( void ) { - uint16_t cs; - __asm__ __volatile__ ( "movw %%cs, %w0" : "=r" ( cs ) ); - return cs; -} - -static inline __attribute__ (( always_inline )) unsigned int _rm_ds ( void ) { - uint16_t ds; - __asm__ __volatile__ ( "movw %%ds, %w0" : "=r" ( ds ) ); - return ds; -} - -#define rm_cs ( _rm_cs() ) -#define rm_ds ( _rm_ds() ) - -/* Copy to/from base memory */ - -static inline void copy_to_real_libkir ( unsigned int dest_seg, - unsigned int dest_off, - const void *src, size_t n ) { - unsigned int discard_D, discard_S, discard_c; - - __asm__ __volatile__ ( "pushw %%es\n\t" - "movw %3, %%es\n\t" - "rep movsb\n\t" - "popw %%es\n\t" - : "=D" ( discard_D ), "=S" ( discard_S ), - "=c" ( discard_c ) - : "r" ( dest_seg ), "D" ( dest_off ), - "S" ( src ), - "c" ( n ) - : "memory" ); -} - -static inline void copy_from_real_libkir ( void *dest, - unsigned int src_seg, - unsigned int src_off, - size_t n ) { - unsigned int discard_D, discard_S, discard_c; - - __asm__ __volatile__ ( "pushw %%ds\n\t" - "movw %4, %%ds\n\t" - "rep movsb\n\t" - "popw %%ds\n\t" - : "=D" ( discard_D ), "=S" ( discard_S ), - "=c" ( discard_c ) - : "D" ( dest ), - "r" ( src_seg ), "S" ( src_off ), - "c" ( n ) - : "memory" ); -} - -#define copy_to_real copy_to_real_libkir -#define copy_from_real copy_from_real_libkir - -/* - * Transfer individual values to/from base memory. There may well be - * a neater way to do this. We have two versions: one for constant - * offsets (where the mov instruction must be of the form "mov - * %es:123, %xx") and one for non-constant offsets (where the mov - * instruction must be of the form "mov %es:(%xx), %yx". If it's - * possible to incorporate both forms into one __asm__ instruction, I - * don't know how to do it. - * - * Ideally, the mov instruction should be "mov%z0"; the "%z0" is meant - * to expand to either "b", "w" or "l" depending on the size of - * operand 0. This would remove the (minor) ambiguity in the mov - * instruction. However, gcc on at least my system barfs with an - * "internal compiler error" when confronted with %z0. - * - */ - -#define put_real_kir_const_off( var, seg, off ) \ - __asm__ ( "movw %w1, %%es\n\t" \ - "mov %0, %%es:%c2\n\t" \ - "pushw %%ds\n\t" /* restore %es */ \ - "popw %%es\n\t" \ - : \ - : "r,r" ( var ), "rm,rm" ( seg ), "i,!r" ( off ) \ - ) - -#define put_real_kir_nonconst_off( var, seg, off ) \ - __asm__ ( "movw %w1, %%es\n\t" \ - "mov %0, %%es:(%2)\n\t" \ - "pushw %%ds\n\t" /* restore %es */ \ - "popw %%es\n\t" \ - : \ - : "r" ( var ), "rm" ( seg ), "r" ( off ) \ - ) - -#define put_real_kir( var, seg, off ) \ - do { \ - if ( __builtin_constant_p ( off ) ) \ - put_real_kir_const_off ( var, seg, off ); \ - else \ - put_real_kir_nonconst_off ( var, seg, off ); \ - } while ( 0 ) - -#define get_real_kir_const_off( var, seg, off ) \ - __asm__ ( "movw %w1, %%es\n\t" \ - "mov %%es:%c2, %0\n\t" \ - "pushw %%ds\n\t" /* restore %es */ \ - "popw %%es\n\t" \ - : "=r,r" ( var ) \ - : "rm,rm" ( seg ), "i,!r" ( off ) \ - ) - -#define get_real_kir_nonconst_off( var, seg, off ) \ - __asm__ ( "movw %w1, %%es\n\t" \ - "mov %%es:(%2), %0\n\t" \ - "pushw %%ds\n\t" /* restore %es */ \ - "popw %%es\n\t" \ - : "=r" ( var ) \ - : "rm" ( seg ), "r" ( off ) \ - ) - -#define get_real_kir( var, seg, off ) \ - do { \ - if ( __builtin_constant_p ( off ) ) \ - get_real_kir_const_off ( var, seg, off ); \ - else \ - get_real_kir_nonconst_off ( var, seg, off ); \ - } while ( 0 ) - -#define put_real put_real_kir -#define get_real get_real_kir - -/** - * A pointer to a user buffer - * - * This is actually a struct segoff, but encoded as a uint32_t to - * ensure that gcc passes it around efficiently. - */ -typedef uint32_t userptr_t; - -/** - * Copy data to user buffer - * - * @v buffer User buffer - * @v offset Offset within user buffer - * @v src Source - * @v len Length - */ -static inline __attribute__ (( always_inline )) void -copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) { - copy_to_real ( ( buffer >> 16 ), ( ( buffer & 0xffff ) + offset ), - src, len ); -} - -/** - * Copy data from user buffer - * - * @v dest Destination - * @v buffer User buffer - * @v offset Offset within user buffer - * @v len Length - */ -static inline __attribute__ (( always_inline )) void -copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) { - copy_from_real ( dest, ( buffer >> 16 ), - ( ( buffer & 0xffff ) + offset ), len ); -} - -/** - * Convert segment:offset address to user buffer - * - * @v segment Real-mode segment - * @v offset Real-mode offset - * @ret buffer User buffer - */ -static inline __attribute__ (( always_inline )) userptr_t -real_to_user ( unsigned int segment, unsigned int offset ) { - return ( ( segment << 16 ) | offset ); -} - -/** - * Convert virtual address to user buffer - * - * @v virtual Virtual address - * @ret buffer User buffer - * - * This constructs a user buffer from an ordinary pointer. Use it - * when you need to pass a pointer to an internal buffer to a function - * that expects a @c userptr_t. - */ -static inline __attribute__ (( always_inline )) userptr_t -virt_to_user ( void * virtual ) { - return real_to_user ( rm_ds, ( intptr_t ) virtual ); -} - -/* TEXT16_CODE: declare a fragment of code that resides in .text16 */ -#define TEXT16_CODE( asm_code_str ) \ - ".section \".text16\", \"ax\", @progbits\n\t" \ - ".code16\n\t" \ - ".arch i386\n\t" \ - asm_code_str "\n\t" \ - ".code16gcc\n\t" \ - ".previous\n\t" - -/* REAL_CODE: declare a fragment of code that executes in real mode */ -#define REAL_CODE( asm_code_str ) \ - ".code16\n\t" \ - asm_code_str "\n\t" \ - ".code16gcc\n\t" - -#endif /* ASSEMBLY */ - -#endif /* LIBKIR_H */ diff --git a/gpxe/src/arch/i386/include/librm.h b/gpxe/src/arch/i386/include/librm.h deleted file mode 100644 index f193f5e3..00000000 --- a/gpxe/src/arch/i386/include/librm.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef LIBRM_H -#define LIBRM_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* Segment selectors as used in our protected-mode GDTs. - * - * Don't change these unless you really know what you're doing. - */ - -#define VIRTUAL_CS 0x08 -#define VIRTUAL_DS 0x10 -#define PHYSICAL_CS 0x18 -#define PHYSICAL_DS 0x20 -#define REAL_CS 0x28 -#define REAL_DS 0x30 -#if 0 -#define LONG_CS 0x38 -#define LONG_DS 0x40 -#endif - -#ifndef ASSEMBLY - -#ifdef UACCESS_LIBRM -#define UACCESS_PREFIX_librm -#else -#define UACCESS_PREFIX_librm __librm_ -#endif - -/* Variables in librm.S */ -extern unsigned long virt_offset; - -/** - * Convert physical address to user pointer - * - * @v phys_addr Physical address - * @ret userptr User pointer - */ -static inline __always_inline userptr_t -UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) { - return ( phys_addr - virt_offset ); -} - -/** - * Convert user buffer to physical address - * - * @v userptr User pointer - * @v offset Offset from user pointer - * @ret phys_addr Physical address - */ -static inline __always_inline unsigned long -UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) { - return ( userptr + offset + virt_offset ); -} - -static inline __always_inline userptr_t -UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) { - return trivial_virt_to_user ( addr ); -} - -static inline __always_inline void * -UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) { - return trivial_user_to_virt ( userptr, offset ); -} - -static inline __always_inline userptr_t -UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) { - return trivial_userptr_add ( userptr, offset ); -} - -static inline __always_inline void -UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off, - userptr_t src, off_t src_off, - size_t len ) { - trivial_memcpy_user ( dest, dest_off, src, src_off, len ); -} - -static inline __always_inline void -UACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off, - userptr_t src, off_t src_off, - size_t len ) { - trivial_memmove_user ( dest, dest_off, src, src_off, len ); -} - -static inline __always_inline void -UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset, - int c, size_t len ) { - trivial_memset_user ( buffer, offset, c, len ); -} - -static inline __always_inline size_t -UACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) { - return trivial_strlen_user ( buffer, offset ); -} - -static inline __always_inline off_t -UACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset, - int c, size_t len ) { - return trivial_memchr_user ( buffer, offset, c, len ); -} - - -/****************************************************************************** - * - * Access to variables in .data16 and .text16 - * - */ - -extern char *data16; -extern char *text16; - -#define __data16( variable ) \ - __attribute__ (( section ( ".data16" ) )) \ - _data16_ ## variable __asm__ ( #variable ) - -#define __data16_array( variable, array ) \ - __attribute__ (( section ( ".data16" ) )) \ - _data16_ ## variable array __asm__ ( #variable ) - -#define __bss16( variable ) \ - __attribute__ (( section ( ".bss16" ) )) \ - _data16_ ## variable __asm__ ( #variable ) - -#define __bss16_array( variable, array ) \ - __attribute__ (( section ( ".bss16" ) )) \ - _data16_ ## variable array __asm__ ( #variable ) - -#define __text16( variable ) \ - __attribute__ (( section ( ".text16.data" ) )) \ - _text16_ ## variable __asm__ ( #variable ) - -#define __text16_array( variable, array ) \ - __attribute__ (( section ( ".text16.data" ) )) \ - _text16_ ## variable array __asm__ ( #variable ) - -#define __use_data16( variable ) \ - ( * ( ( typeof ( _data16_ ## variable ) * ) \ - & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) ) - -#define __use_text16( variable ) \ - ( * ( ( typeof ( _text16_ ## variable ) * ) \ - & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) ) - -#define __from_data16( pointer ) \ - ( ( unsigned int ) \ - ( ( ( void * ) (pointer) ) - ( ( void * ) data16 ) ) ) - -#define __from_text16( pointer ) \ - ( ( unsigned int ) \ - ( ( ( void * ) (pointer) ) - ( ( void * ) text16 ) ) ) - -/* Variables in librm.S, present in the normal data segment */ -extern uint16_t rm_sp; -extern uint16_t rm_ss; -extern uint16_t __data16 ( rm_cs ); -#define rm_cs __use_data16 ( rm_cs ) -extern uint16_t __text16 ( rm_ds ); -#define rm_ds __use_text16 ( rm_ds ) - -/* Functions that librm expects to be able to link to. Included here - * so that the compiler will catch prototype mismatches. - */ -extern void gateA20_set ( void ); - -/** - * Convert segment:offset address to user buffer - * - * @v segment Real-mode segment - * @v offset Real-mode offset - * @ret buffer User buffer - */ -static inline __always_inline userptr_t -real_to_user ( unsigned int segment, unsigned int offset ) { - return ( phys_to_user ( ( segment << 4 ) + offset ) ); -} - -extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ); -extern void remove_user_from_rm_stack ( userptr_t data, size_t size ); - -/* TEXT16_CODE: declare a fragment of code that resides in .text16 */ -#define TEXT16_CODE( asm_code_str ) \ - ".section \".text16\", \"ax\", @progbits\n\t" \ - ".code16\n\t" \ - asm_code_str "\n\t" \ - ".code32\n\t" \ - ".previous\n\t" - -/* REAL_CODE: declare a fragment of code that executes in real mode */ -#define REAL_CODE( asm_code_str ) \ - "pushl $1f\n\t" \ - "call real_call\n\t" \ - "addl $4, %%esp\n\t" \ - TEXT16_CODE ( "\n1:\n\t" \ - asm_code_str \ - "\n\t" \ - "ret\n\t" ) - -/* PHYS_CODE: declare a fragment of code that executes in flat physical mode */ -#define PHYS_CODE( asm_code_str ) \ - "call _virt_to_phys\n\t" \ - asm_code_str \ - "call _phys_to_virt\n\t" - -#endif /* ASSEMBLY */ - -#endif /* LIBRM_H */ diff --git a/gpxe/src/arch/i386/include/limits.h b/gpxe/src/arch/i386/include/limits.h deleted file mode 100644 index 031b6c57..00000000 --- a/gpxe/src/arch/i386/include/limits.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef LIMITS_H -#define LIMITS_H 1 - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* Number of bits in a `char' */ -#define CHAR_BIT 8 - -/* Minimum and maximum values a `signed char' can hold */ -#define SCHAR_MIN (-128) -#define SCHAR_MAX 127 - -/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ -#define UCHAR_MAX 255 - -/* Minimum and maximum values a `char' can hold */ -#define CHAR_MIN SCHAR_MIN -#define CHAR_MAX SCHAR_MAX - -/* Minimum and maximum values a `signed short int' can hold */ -#define SHRT_MIN (-32768) -#define SHRT_MAX 32767 - -/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */ -#define USHRT_MAX 65535 - - -/* Minimum and maximum values a `signed int' can hold */ -#define INT_MIN (-INT_MAX - 1) -#define INT_MAX 2147483647 - -/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ -#define UINT_MAX 4294967295U - - -/* Minimum and maximum values a `signed int' can hold */ -#define INT_MAX 2147483647 -#define INT_MIN (-INT_MAX - 1) - - -/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ -#define UINT_MAX 4294967295U - - -/* Minimum and maximum values a `signed long' can hold */ -#define LONG_MAX 2147483647 -#define LONG_MIN (-LONG_MAX - 1L) - -/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */ -#define ULONG_MAX 4294967295UL - -/* Minimum and maximum values a `signed long long' can hold */ -#define LLONG_MAX 9223372036854775807LL -#define LLONG_MIN (-LONG_MAX - 1LL) - - -/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */ -#define ULLONG_MAX 18446744073709551615ULL - - -#endif /* LIMITS_H */ diff --git a/gpxe/src/arch/i386/include/memsizes.h b/gpxe/src/arch/i386/include/memsizes.h deleted file mode 100644 index 7b217494..00000000 --- a/gpxe/src/arch/i386/include/memsizes.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _MEMSIZES_H -#define _MEMSIZES_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <basemem.h> - -/** - * Get size of base memory from BIOS free base memory counter - * - * @ret basemem Base memory size, in kB - */ -static inline unsigned int basememsize ( void ) { - return get_fbms(); -} - -extern unsigned int extmemsize ( void ); - -#endif /* _MEMSIZES_H */ diff --git a/gpxe/src/arch/i386/include/multiboot.h b/gpxe/src/arch/i386/include/multiboot.h deleted file mode 100644 index 44614c73..00000000 --- a/gpxe/src/arch/i386/include/multiboot.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef _MULTIBOOT_H -#define _MULTIBOOT_H - -/** - * @file - * - * Multiboot operating systems - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> - -/** The magic number for the Multiboot header */ -#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 - -/** Boot modules must be page aligned */ -#define MB_FLAG_PGALIGN 0x00000001 - -/** Memory map must be provided */ -#define MB_FLAG_MEMMAP 0x00000002 - -/** Video mode information must be provided */ -#define MB_FLAG_VIDMODE 0x00000004 - -/** Image is a raw multiboot image (not ELF) */ -#define MB_FLAG_RAW 0x00010000 - -/** - * The magic number passed by a Multiboot-compliant boot loader - * - * Must be passed in register %eax when jumping to the Multiboot OS - * image. - */ -#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 - -/** Multiboot information structure mem_* fields are valid */ -#define MBI_FLAG_MEM 0x00000001 - -/** Multiboot information structure boot_device field is valid */ -#define MBI_FLAG_BOOTDEV 0x00000002 - -/** Multiboot information structure cmdline field is valid */ -#define MBI_FLAG_CMDLINE 0x00000004 - -/** Multiboot information structure module fields are valid */ -#define MBI_FLAG_MODS 0x00000008 - -/** Multiboot information structure a.out symbol table is valid */ -#define MBI_FLAG_AOUT 0x00000010 - -/** Multiboot information struture ELF section header table is valid */ -#define MBI_FLAG_ELF 0x00000020 - -/** Multiboot information structure memory map is valid */ -#define MBI_FLAG_MMAP 0x00000040 - -/** Multiboot information structure drive list is valid */ -#define MBI_FLAG_DRIVES 0x00000080 - -/** Multiboot information structure ROM configuration field is valid */ -#define MBI_FLAG_CFGTBL 0x00000100 - -/** Multiboot information structure boot loader name field is valid */ -#define MBI_FLAG_LOADER 0x00000200 - -/** Multiboot information structure APM table is valid */ -#define MBI_FLAG_APM 0x00000400 - -/** Multiboot information structure video information is valid */ -#define MBI_FLAG_VBE 0x00000800 - -/** A multiboot header */ -struct multiboot_header { - uint32_t magic; - uint32_t flags; - uint32_t checksum; - uint32_t header_addr; - uint32_t load_addr; - uint32_t load_end_addr; - uint32_t bss_end_addr; - uint32_t entry_addr; -} __attribute__ (( packed, may_alias )); - -/** A multiboot a.out symbol table */ -struct multiboot_aout_symbol_table { - uint32_t tabsize; - uint32_t strsize; - uint32_t addr; - uint32_t reserved; -} __attribute__ (( packed, may_alias )); - -/** A multiboot ELF section header table */ -struct multiboot_elf_section_header_table { - uint32_t num; - uint32_t size; - uint32_t addr; - uint32_t shndx; -} __attribute__ (( packed, may_alias )); - -/** A multiboot information structure */ -struct multiboot_info { - uint32_t flags; - uint32_t mem_lower; - uint32_t mem_upper; - uint32_t boot_device; - uint32_t cmdline; - uint32_t mods_count; - uint32_t mods_addr; - union { - struct multiboot_aout_symbol_table aout_syms; - struct multiboot_elf_section_header_table elf_sections; - } syms; - uint32_t mmap_length; - uint32_t mmap_addr; - uint32_t drives_length; - uint32_t drives_addr; - uint32_t config_table; - uint32_t boot_loader_name; - uint32_t apm_table; - uint32_t vbe_control_info; - uint32_t vbe_mode_info; - uint16_t vbe_mode; - uint16_t vbe_interface_seg; - uint16_t vbe_interface_off; - uint16_t vbe_interface_len; -} __attribute__ (( packed, may_alias )); - -/** A multiboot module structure */ -struct multiboot_module { - uint32_t mod_start; - uint32_t mod_end; - uint32_t string; - uint32_t reserved; -} __attribute__ (( packed, may_alias )); - -/** A multiboot memory map entry */ -struct multiboot_memory_map { - uint32_t size; - uint64_t base_addr; - uint64_t length; - uint32_t type; -} __attribute__ (( packed, may_alias )); - -/** Usable RAM */ -#define MBMEM_RAM 1 - -#endif /* _MULTIBOOT_H */ diff --git a/gpxe/src/arch/i386/include/pic8259.h b/gpxe/src/arch/i386/include/pic8259.h deleted file mode 100644 index f8e20c4c..00000000 --- a/gpxe/src/arch/i386/include/pic8259.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Basic support for controlling the 8259 Programmable Interrupt Controllers. - * - * Initially written by Michael Brown (mcb30). - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef PIC8259_H -#define PIC8259_H - -/* For segoff_t */ -#include "realmode.h" - -#define IRQ_PIC_CUTOFF 8 - -/* 8259 register locations */ -#define PIC1_ICW1 0x20 -#define PIC1_OCW2 0x20 -#define PIC1_OCW3 0x20 -#define PIC1_ICR 0x20 -#define PIC1_IRR 0x20 -#define PIC1_ISR 0x20 -#define PIC1_ICW2 0x21 -#define PIC1_ICW3 0x21 -#define PIC1_ICW4 0x21 -#define PIC1_IMR 0x21 -#define PIC2_ICW1 0xa0 -#define PIC2_OCW2 0xa0 -#define PIC2_OCW3 0xa0 -#define PIC2_ICR 0xa0 -#define PIC2_IRR 0xa0 -#define PIC2_ISR 0xa0 -#define PIC2_ICW2 0xa1 -#define PIC2_ICW3 0xa1 -#define PIC2_ICW4 0xa1 -#define PIC2_IMR 0xa1 - -/* Register command values */ -#define OCW3_ID 0x08 -#define OCW3_READ_IRR 0x03 -#define OCW3_READ_ISR 0x02 -#define ICR_EOI_NON_SPECIFIC 0x20 -#define ICR_EOI_NOP 0x40 -#define ICR_EOI_SPECIFIC 0x60 -#define ICR_EOI_SET_PRIORITY 0xc0 - -/* Macros to enable/disable IRQs */ -#define IMR_REG(x) ( (x) < IRQ_PIC_CUTOFF ? PIC1_IMR : PIC2_IMR ) -#define IMR_BIT(x) ( 1 << ( (x) % IRQ_PIC_CUTOFF ) ) -#define irq_enabled(x) ( ( inb ( IMR_REG(x) ) & IMR_BIT(x) ) == 0 ) -#define enable_irq(x) outb ( inb( IMR_REG(x) ) & ~IMR_BIT(x), IMR_REG(x) ) -#define disable_irq(x) outb ( inb( IMR_REG(x) ) | IMR_BIT(x), IMR_REG(x) ) - -/* Macros for acknowledging IRQs */ -#define ICR_REG( irq ) ( (irq) < IRQ_PIC_CUTOFF ? PIC1_ICR : PIC2_ICR ) -#define ICR_VALUE( irq ) ( (irq) % IRQ_PIC_CUTOFF ) -#define CHAINED_IRQ 2 - -/* Utility macros to convert IRQ numbers to INT numbers and INT vectors */ -#define IRQ_INT( irq ) ( ( ( (irq) - IRQ_PIC_CUTOFF ) ^ 0x70 ) & 0x7f ) - -/* Other constants */ -#define IRQ_MAX 15 -#define IRQ_NONE -1U - -/* Function prototypes - */ -void send_eoi ( unsigned int irq ); - -#endif /* PIC8259_H */ diff --git a/gpxe/src/arch/i386/include/pnpbios.h b/gpxe/src/arch/i386/include/pnpbios.h deleted file mode 100644 index 4c20e73e..00000000 --- a/gpxe/src/arch/i386/include/pnpbios.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _PNPBIOS_H -#define _PNPBIOS_H - -/** @file - * - * PnP BIOS - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* BIOS segment address */ -#define BIOS_SEG 0xf000 - -extern int find_pnp_bios ( void ); - -#endif /* _PNPBIOS_H */ diff --git a/gpxe/src/arch/i386/include/pxe.h b/gpxe/src/arch/i386/include/pxe.h deleted file mode 100644 index 041ee7ba..00000000 --- a/gpxe/src/arch/i386/include/pxe.h +++ /dev/null @@ -1,154 +0,0 @@ -#ifndef PXE_H -#define PXE_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "pxe_types.h" -#include "pxe_api.h" -#include <gpxe/device.h> - -/* Parameter block for pxenv_unknown() */ -struct s_PXENV_UNKNOWN { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNKNOWN PXENV_UNKNOWN_t; - -/* Union used for PXE API calls; we don't know the type of the - * structure until we interpret the opcode. Also, Status is available - * in the same location for any opcode, and it's convenient to have - * non-specific access to it. - */ -union u_PXENV_ANY { - /* Make it easy to read status for any operation */ - PXENV_STATUS_t Status; - struct s_PXENV_UNKNOWN unknown; - struct s_PXENV_UNLOAD_STACK unload_stack; - struct s_PXENV_GET_CACHED_INFO get_cached_info; - struct s_PXENV_TFTP_READ_FILE restart_tftp; - struct s_PXENV_START_UNDI start_undi; - struct s_PXENV_STOP_UNDI stop_undi; - struct s_PXENV_START_BASE start_base; - struct s_PXENV_STOP_BASE stop_base; - struct s_PXENV_TFTP_OPEN tftp_open; - struct s_PXENV_TFTP_CLOSE tftp_close; - struct s_PXENV_TFTP_READ tftp_read; - struct s_PXENV_TFTP_READ_FILE tftp_read_file; - struct s_PXENV_TFTP_GET_FSIZE tftp_get_fsize; - struct s_PXENV_UDP_OPEN udp_open; - struct s_PXENV_UDP_CLOSE udp_close; - struct s_PXENV_UDP_WRITE udp_write; - struct s_PXENV_UDP_READ udp_read; - struct s_PXENV_UNDI_STARTUP undi_startup; - struct s_PXENV_UNDI_CLEANUP undi_cleanup; - struct s_PXENV_UNDI_INITIALIZE undi_initialize; - struct s_PXENV_UNDI_RESET undi_reset_adapter; - struct s_PXENV_UNDI_SHUTDOWN undi_shutdown; - struct s_PXENV_UNDI_OPEN undi_open; - struct s_PXENV_UNDI_CLOSE undi_close; - struct s_PXENV_UNDI_TRANSMIT undi_transmit; - struct s_PXENV_UNDI_SET_MCAST_ADDRESS undi_set_mcast_address; - struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_station_address; - struct s_PXENV_UNDI_SET_PACKET_FILTER undi_set_packet_filter; - struct s_PXENV_UNDI_GET_INFORMATION undi_get_information; - struct s_PXENV_UNDI_GET_STATISTICS undi_get_statistics; - struct s_PXENV_UNDI_CLEAR_STATISTICS undi_clear_statistics; - struct s_PXENV_UNDI_INITIATE_DIAGS undi_initiate_diags; - struct s_PXENV_UNDI_FORCE_INTERRUPT undi_force_interrupt; - struct s_PXENV_UNDI_GET_MCAST_ADDRESS undi_get_mcast_address; - struct s_PXENV_UNDI_GET_NIC_TYPE undi_get_nic_type; - struct s_PXENV_UNDI_GET_IFACE_INFO undi_get_iface_info; - struct s_PXENV_UNDI_GET_STATE undi_get_state; - struct s_PXENV_UNDI_ISR undi_isr; - struct s_PXENV_FILE_OPEN file_open; - struct s_PXENV_FILE_CLOSE file_close; - struct s_PXENV_FILE_SELECT file_select; - struct s_PXENV_FILE_READ file_read; - struct s_PXENV_GET_FILE_SIZE get_file_size; - struct s_PXENV_FILE_EXEC file_exec; - struct s_PXENV_FILE_API_CHECK file_api_check; - struct s_PXENV_FILE_EXIT_HOOK file_exit_hook; -}; - -typedef union u_PXENV_ANY PXENV_ANY_t; - -/** An UNDI expansion ROM header */ -struct undi_rom_header { - /** Signature - * - * Must be equal to @c ROM_SIGNATURE - */ - UINT16_t Signature; - /** ROM length in 512-byte blocks */ - UINT8_t ROMLength; - /** Unused */ - UINT8_t unused[0x13]; - /** Offset of the PXE ROM ID structure */ - UINT16_t PXEROMID; - /** Offset of the PCI ROM structure */ - UINT16_t PCIRHeader; -} PACKED; - -/** Signature for an expansion ROM */ -#define ROM_SIGNATURE 0xaa55 - -/** An UNDI ROM ID structure */ -struct undi_rom_id { - /** Signature - * - * Must be equal to @c UNDI_ROM_ID_SIGNATURE - */ - UINT32_t Signature; - /** Length of structure */ - UINT8_t StructLength; - /** Checksum */ - UINT8_t StructCksum; - /** Structure revision - * - * Must be zero. - */ - UINT8_t StructRev; - /** UNDI revision - * - * Version 2.1.0 is encoded as the byte sequence 0x00, 0x01, 0x02. - */ - UINT8_t UNDIRev[3]; - /** Offset to UNDI loader */ - UINT16_t UNDILoader; - /** Minimum required stack segment size */ - UINT16_t StackSize; - /** Minimum required data segment size */ - UINT16_t DataSize; - /** Minimum required code segment size */ - UINT16_t CodeSize; -} PACKED; - -/** Signature for an UNDI ROM ID structure */ -#define UNDI_ROM_ID_SIGNATURE \ - ( ( 'U' << 0 ) + ( 'N' << 8 ) + ( 'D' << 16 ) + ( 'I' << 24 ) ) - -/** A PCI expansion header */ -struct pcir_header { - /** Signature - * - * Must be equal to @c PCIR_SIGNATURE - */ - uint32_t signature; - /** PCI vendor ID */ - uint16_t vendor_id; - /** PCI device ID */ - uint16_t device_id; -} PACKED; - -/** Signature for an UNDI ROM ID structure */ -#define PCIR_SIGNATURE \ - ( ( 'P' << 0 ) + ( 'C' << 8 ) + ( 'I' << 16 ) + ( 'R' << 24 ) ) - - -extern struct net_device *pxe_netdev; - -extern void pxe_set_netdev ( struct net_device *netdev ); - -extern void pxe_set_cached_filename ( const unsigned char *filename ); - -#endif /* PXE_H */ diff --git a/gpxe/src/arch/i386/include/pxe_api.h b/gpxe/src/arch/i386/include/pxe_api.h deleted file mode 100644 index 92f046f7..00000000 --- a/gpxe/src/arch/i386/include/pxe_api.h +++ /dev/null @@ -1,1909 +0,0 @@ -#ifndef PXE_API_H -#define PXE_API_H - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * As an alternative, at your option, you may use this file under the - * following terms, known as the "MIT license": - * - * Copyright (c) 2005-2009 Michael Brown <mbrown@fensystems.co.uk> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** @file - * - * Preboot eXecution Environment (PXE) API - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "pxe_types.h" - -/** @addtogroup pxe Preboot eXecution Environment (PXE) API - * @{ - */ - -/** @defgroup pxe_api_call PXE entry points - * - * PXE entry points and calling conventions - * - * @{ - */ - -/** The PXENV+ structure */ -struct s_PXENV { - /** Signature - * - * Contains the bytes 'P', 'X', 'E', 'N', 'V', '+'. - */ - UINT8_t Signature[6]; - /** PXE API version - * - * MSB is major version number, LSB is minor version number. - * If the API version number is 0x0201 or greater, the !PXE - * structure pointed to by #PXEPtr should be used instead of - * this data structure. - */ - UINT16_t Version; - UINT8_t Length; /**< Length of this structure */ - /** Checksum - * - * The byte checksum of this structure (using the length in - * #Length) must be zero. - */ - UINT8_t Checksum; - SEGOFF16_t RMEntry; /**< Real-mode PXENV+ entry point */ - /** Protected-mode PXENV+ entry point offset - * - * PXE 2.1 deprecates this entry point. For protected-mode - * API calls, use the !PXE structure pointed to by #PXEPtr - * instead. - */ - UINT32_t PMOffset; - /** Protected-mode PXENV+ entry point segment selector - * - * PXE 2.1 deprecates this entry point. For protected-mode - * API calls, use the !PXE structure pointed to by #PXEPtr - * instead. - */ - SEGSEL_t PMSelector; - SEGSEL_t StackSeg; /**< Stack segment selector */ - UINT16_t StackSize; /**< Stack segment size */ - SEGSEL_t BC_CodeSeg; /**< Base-code code segment selector */ - UINT16_t BC_CodeSize; /**< Base-code code segment size */ - SEGSEL_t BC_DataSeg; /**< Base-code data segment selector */ - UINT16_t BC_DataSize; /**< Base-code data segment size */ - SEGSEL_t UNDIDataSeg; /**< UNDI data segment selector */ - UINT16_t UNDIDataSize; /**< UNDI data segment size */ - SEGSEL_t UNDICodeSeg; /**< UNDI code segment selector */ - UINT16_t UNDICodeSize; /**< UNDI code segment size */ - /** Address of the !PXE structure - * - * This field is present only if #Version is 0x0201 or - * greater. If present, it points to a struct s_PXE. - */ - SEGOFF16_t PXEPtr; -} PACKED; - -typedef struct s_PXENV PXENV_t; - -/** The !PXE structure */ -struct s_PXE { - /** Signature - * - * Contains the bytes '!', 'P', 'X', 'E'. - */ - UINT8_t Signature[4]; - UINT8_t StructLength; /**< Length of this structure */ - /** Checksum - * - * The byte checksum of this structure (using the length in - * #StructLength) must be zero. - */ - UINT8_t StructCksum; - /** Revision of this structure - * - * For PXE version 2.1, this field must be zero. - */ - UINT8_t StructRev; - UINT8_t reserved_1; /**< Must be zero */ - /** Address of the UNDI ROM ID structure - * - * This is a pointer to a struct s_UNDI_ROM_ID. - */ - SEGOFF16_t UNDIROMID; - /** Address of the Base Code ROM ID structure - * - * This is a pointer to a struct s_BC_ROM_ID. - */ - SEGOFF16_t BaseROMID; - /** 16-bit !PXE entry point - * - * This is the entry point for either real mode, or protected - * mode with a 16-bit stack segment. - */ - SEGOFF16_t EntryPointSP; - /** 32-bit !PXE entry point - * - * This is the entry point for protected mode with a 32-bit - * stack segment. - */ - SEGOFF16_t EntryPointESP; - /** Status call-out function - * - * @v 0 (if in a time-out loop) - * @v n Number of a received TFTP packet - * @ret 0 Continue operation - * @ret 1 Cancel operation - * - * This function will be called whenever the PXE stack is in - * protected mode, is waiting for an event (e.g. a DHCP reply) - * and wishes to allow the user to cancel the operation. - * Parameters are passed in register %ax; the return value - * must also be placed in register %ax. All other registers - * and flags @b must be preserved. - * - * In real mode, an internal function (that checks for a - * keypress) will be used. - * - * If this field is set to -1, no status call-out function - * will be used and consequently the user will not be allowed - * to interrupt operations. - * - * @note The PXE specification version 2.1 defines the - * StatusCallout field, mentions it 11 times, but nowhere - * defines what it actually does or how it gets called. - * Fortunately, the WfM specification version 1.1a deigns to - * inform us of such petty details. - */ - SEGOFF16_t StatusCallout; - UINT8_t reserved_2; /**< Must be zero */ - /** Number of segment descriptors - * - * If this number is greater than 7, the remaining descriptors - * follow immediately after #BC_CodeWrite. - */ - UINT8_t SegDescCnt; - /** First protected-mode selector - * - * This is the segment selector value for the first segment - * assigned to PXE. Protected-mode selectors must be - * consecutive, according to the PXE 2.1 specification, though - * no reason is given. Each #SEGDESC_t includes a field for - * the segment selector, so this information is entirely - * redundant. - */ - SEGSEL_t FirstSelector; - /** Stack segment descriptor */ - SEGDESC_t Stack; - /** UNDI data segment descriptor */ - SEGDESC_t UNDIData; - /** UNDI code segment descriptor */ - SEGDESC_t UNDICode; - /** UNDI writable code segment descriptor */ - SEGDESC_t UNDICodeWrite; - /** Base-code data segment descriptor */ - SEGDESC_t BC_Data; - /** Base-code code segment descriptor */ - SEGDESC_t BC_Code; - /** Base-code writable code segment descriptor */ - SEGDESC_t BC_CodeWrite; -} PACKED; - -typedef struct s_PXE PXE_t; - -/** @} */ /* pxe_api_call */ - -/** @defgroup pxe_preboot_api PXE Preboot API - * - * General high-level functions: #PXENV_UNLOAD_STACK, #PXENV_START_UNDI etc. - * - * @{ - */ - -/** @defgroup pxenv_unload_stack PXENV_UNLOAD_STACK - * - * UNLOAD BASE CODE STACK - * - * @{ - */ - -/** PXE API function code for pxenv_unload_stack() */ -#define PXENV_UNLOAD_STACK 0x0070 - -/** Parameter block for pxenv_unload_stack() */ -struct s_PXENV_UNLOAD_STACK { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT8_t reserved[10]; /**< Must be zero */ -} PACKED; - -typedef struct s_PXENV_UNLOAD_STACK PXENV_UNLOAD_STACK_t; - -extern PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK - *unload_stack ); - -/** @} */ /* pxenv_unload_stack */ - -/** @defgroup pxenv_get_cached_info PXENV_GET_CACHED_INFO - * - * GET CACHED INFO - * - * @{ - */ - -/** PXE API function code for pxenv_get_cached_info() */ -#define PXENV_GET_CACHED_INFO 0x0071 - -/** The client's DHCPDISCOVER packet */ -#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 - -/** The DHCP server's DHCPACK packet */ -#define PXENV_PACKET_TYPE_DHCP_ACK 2 - -/** The Boot Server's Discover Reply packet - * - * This packet contains DHCP option 60 set to "PXEClient", a valid - * boot file name, and may or may not contain MTFTP options. - */ -#define PXENV_PACKET_TYPE_CACHED_REPLY 3 - -/** Parameter block for pxenv_get_cached_info() */ -struct s_PXENV_GET_CACHED_INFO { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Packet type. - * - * Valid values are #PXENV_PACKET_TYPE_DHCP_DISCOVER, - * #PXENV_PACKET_TYPE_DHCP_ACK or #PXENV_PACKET_TYPE_CACHED_REPLY - */ - UINT16_t PacketType; - UINT16_t BufferSize; /**< Buffer size */ - SEGOFF16_t Buffer; /**< Buffer address */ - UINT16_t BufferLimit; /**< Maximum buffer size */ -} PACKED; - -typedef struct s_PXENV_GET_CACHED_INFO PXENV_GET_CACHED_INFO_t; - -#define BOOTP_REQ 1 /**< A BOOTP request packet */ -#define BOOTP_REP 2 /**< A BOOTP reply packet */ - -/** DHCP broadcast flag - * - * Request a broadcast response (DHCPOFFER or DHCPACK) from the DHCP - * server. - */ -#define BOOTP_BCAST 0x8000 - -#define VM_RFC1048 0x63825363L /**< DHCP magic cookie */ - -/** Maximum length of DHCP options */ -#define BOOTP_DHCPVEND 1024 - -/** Format of buffer filled in by pxenv_get_cached_info() - * - * This somewhat convoluted data structure simply describes the layout - * of a DHCP packet. Refer to RFC2131 section 2 for a full - * description. - */ -struct bootph { - /** Message opcode. - * - * Valid values are #BOOTP_REQ and #BOOTP_REP. - */ - UINT8_t opcode; - /** NIC hardware type. - * - * Valid values are as for s_PXENV_UNDI_GET_INFORMATION::HwType. - */ - UINT8_t Hardware; - UINT8_t Hardlen; /**< MAC address length */ - /** Gateway hops - * - * Zero in packets sent by the client. May be non-zero in - * replies from the DHCP server, if the reply comes via a DHCP - * relay agent. - */ - UINT8_t Gatehops; - UINT32_t ident; /**< DHCP transaction id (xid) */ - /** Elapsed time - * - * Number of seconds since the client began the DHCP - * transaction. - */ - UINT16_t seconds; - /** Flags - * - * This is the bitwise-OR of any of the following values: - * #BOOTP_BCAST. - */ - UINT16_t Flags; - /** Client IP address - * - * Set only if the client already has an IP address. - */ - IP4_t cip; - /** Your IP address - * - * This is the IP address that the server assigns to the - * client. - */ - IP4_t yip; - /** Server IP address - * - * This is the IP address of the BOOTP/DHCP server. - */ - IP4_t sip; - /** Gateway IP address - * - * This is the IP address of the BOOTP/DHCP relay agent, if - * any. It is @b not (necessarily) the address of the default - * gateway for routing purposes. - */ - IP4_t gip; - MAC_ADDR_t CAddr; /**< Client MAC address */ - UINT8_t Sname[64]; /**< Server host name */ - UINT8_t bootfile[128]; /**< Boot file name */ - /** DHCP options - * - * Don't ask. Just laugh. Then burn a copy of the PXE - * specification and send Intel an e-mail asking them if - * they've figured out what a "union" does in C yet. - */ - union bootph_vendor { - UINT8_t d[BOOTP_DHCPVEND]; /**< DHCP options */ - /** DHCP options */ - struct bootph_vendor_v { - /** DHCP magic cookie - * - * Should have the value #VM_RFC1048. - */ - UINT8_t magic[4]; - UINT32_t flags; /**< BOOTP flags/opcodes */ - /** "End of BOOTP vendor extensions" - * - * Abandon hope, all ye who consider the - * purpose of this field. - */ - UINT8_t pad[56]; - } v; - } vendor; -} PACKED; - -typedef struct bootph BOOTPLAYER_t; - -extern PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO - *get_cached_info ); - -/** @} */ /* pxenv_get_cached_info */ - -/** @defgroup pxenv_restart_tftp PXENV_RESTART_TFTP - * - * RESTART TFTP - * - * @{ - */ - -/** PXE API function code for pxenv_restart_tftp() */ -#define PXENV_RESTART_TFTP 0x0073 - -/** Parameter block for pxenv_restart_tftp() */ -struct s_PXENV_TFTP_READ_FILE; - -typedef struct s_PXENV_RESTART_TFTP PXENV_RESTART_TFTP_t; - -extern PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE - *restart_tftp ); - -/** @} */ /* pxenv_restart_tftp */ - -/** @defgroup pxenv_start_undi PXENV_START_UNDI - * - * START UNDI - * - * @{ - */ - -/** PXE API function code for pxenv_start_undi() */ -#define PXENV_START_UNDI 0x0000 - -/** Parameter block for pxenv_start_undi() */ -struct s_PXENV_START_UNDI { - PXENV_STATUS_t Status; /**< PXE status code */ - /** %ax register as passed to the Option ROM initialisation routine. - * - * For a PCI device, this should contain the bus:dev:fn value - * that uniquely identifies the PCI device in the system. For - * a non-PCI device, this field is not defined. - */ - UINT16_t AX; - /** %bx register as passed to the Option ROM initialisation routine. - * - * For an ISAPnP device, this should contain the Card Select - * Number assigned to the ISAPnP card. For non-ISAPnP - * devices, this should contain 0xffff. - */ - UINT16_t BX; - /** %dx register as passed to the Option ROM initialisation routine. - * - * For an ISAPnP device, this should contain the ISAPnP Read - * Port address as currently set in all ISAPnP cards. If - * there are no ISAPnP cards, this should contain 0xffff. (If - * this is a non-ISAPnP device, but there are ISAPnP cards in - * the system, this value is not well defined.) - */ - UINT16_t DX; - /** %di register as passed to the Option ROM initialisation routine. - * - * This contains the #OFF16_t portion of a struct #s_SEGOFF16 - * that points to the System BIOS Plug and Play Installation - * Check Structure. (Refer to section 4.4 of the Plug and - * Play BIOS specification for a description of this - * structure.) - * - * @note The PXE specification defines the type of this field - * as #UINT16_t. For x86, #OFF16_t and #UINT16_t are - * equivalent anyway; for other architectures #OFF16_t makes - * more sense. - */ - OFF16_t DI; - /** %es register as passed to the Option ROM initialisation routine. - * - * This contains the #SEGSEL_t portion of a struct #s_SEGOFF16 - * that points to the System BIOS Plug and Play Installation - * Check Structure. (Refer to section 4.4 of the Plug and - * Play BIOS specification for a description of this - * structure.) - * - * @note The PXE specification defines the type of this field - * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are - * equivalent anyway; for other architectures #SEGSEL_t makes - * more sense. - */ - SEGSEL_t ES; -} PACKED; - -typedef struct s_PXENV_START_UNDI PXENV_START_UNDI_t; - -extern PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ); - -/** @} */ /* pxenv_start_undi */ - -/** @defgroup pxenv_stop_undi PXENV_STOP_UNDI - * - * STOP UNDI - * - * @{ - */ - -/** PXE API function code for pxenv_stop_undi() */ -#define PXENV_STOP_UNDI 0x0015 - -/** Parameter block for pxenv_stop_undi() */ -struct s_PXENV_STOP_UNDI { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_STOP_UNDI PXENV_STOP_UNDI_t; - -extern PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ); - -/** @} */ /* pxenv_stop_undi */ - -/** @defgroup pxenv_start_base PXENV_START_BASE - * - * START BASE - * - * @{ - */ - -/** PXE API function code for pxenv_start_base() */ -#define PXENV_START_BASE 0x0075 - -/** Parameter block for pxenv_start_base() */ -struct s_PXENV_START_BASE { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_START_BASE PXENV_START_BASE_t; - -extern PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ); - -/** @} */ /* pxenv_start_base */ - -/** @defgroup pxenv_stop_base PXENV_STOP_BASE - * - * STOP BASE - * - * @{ - */ - -/** PXE API function code for pxenv_stop_base() */ -#define PXENV_STOP_BASE 0x0076 - -/** Parameter block for pxenv_stop_base() */ -struct s_PXENV_STOP_BASE { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_STOP_BASE PXENV_STOP_BASE_t; - -extern PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ); - -/** @} */ /* pxenv_stop_base */ - -/** @} */ /* pxe_preboot_api */ - -/** @defgroup pxe_tftp_api PXE TFTP API - * - * Download files via TFTP or MTFTP - * - * @{ - */ - -/** @defgroup pxenv_tftp_open PXENV_TFTP_OPEN - * - * TFTP OPEN - * - * @{ - */ - -/** PXE API function code for pxenv_tftp_open() */ -#define PXENV_TFTP_OPEN 0x0020 - -/** Parameter block for pxenv_tftp_open() */ -struct s_PXENV_TFTP_OPEN { - PXENV_STATUS_t Status; /**< PXE status code */ - IP4_t ServerIPAddress; /**< TFTP server IP address */ - IP4_t GatewayIPAddress; /**< Relay agent IP address */ - UINT8_t FileName[128]; /**< File name */ - UDP_PORT_t TFTPPort; /**< TFTP server UDP port */ - /** Requested size of TFTP packets - * - * This is the TFTP "blksize" option. This must be at least - * 512, since servers that do not support TFTP options cannot - * negotiate blocksizes smaller than this. - */ - UINT16_t PacketSize; -} PACKED; - -typedef struct s_PXENV_TFTP_OPEN PXENV_TFTP_OPEN_t; - -extern PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ); - -/** @} */ /* pxenv_tftp_open */ - -/** @defgroup pxenv_tftp_close PXENV_TFTP_CLOSE - * - * TFTP CLOSE - * - * @{ - */ - -/** PXE API function code for pxenv_tftp_close() */ -#define PXENV_TFTP_CLOSE 0x0021 - -/** Parameter block for pxenv_tftp_close() */ -struct s_PXENV_TFTP_CLOSE { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_TFTP_CLOSE PXENV_TFTP_CLOSE_t; - -extern PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ); - -/** @} */ /* pxenv_tftp_close */ - -/** @defgroup pxenv_tftp_read PXENV_TFTP_READ - * - * TFTP READ - * - * @{ - */ - -/** PXE API function code for pxenv_tftp_read() */ -#define PXENV_TFTP_READ 0x0022 - -/** Parameter block for pxenv_tftp_read() */ -struct s_PXENV_TFTP_READ { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t PacketNumber; /**< TFTP packet number */ - UINT16_t BufferSize; /**< Size of data buffer */ - SEGOFF16_t Buffer; /**< Address of data buffer */ -} PACKED; - -typedef struct s_PXENV_TFTP_READ PXENV_TFTP_READ_t; - -extern PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ); - -/** @} */ /* pxenv_tftp_read */ - -/** @defgroup pxenv_tftp_read_file PXENV_TFTP_READ_FILE - * - * TFTP/MTFTP READ FILE - * - * @{ - */ - -/** PXE API function code for pxenv_tftp_read_file() */ -#define PXENV_TFTP_READ_FILE 0x0023 - -/** Parameter block for pxenv_tftp_read_file() */ -struct s_PXENV_TFTP_READ_FILE { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT8_t FileName[128]; /**< File name */ - UINT32_t BufferSize; /**< Size of data buffer */ - ADDR32_t Buffer; /**< Address of data buffer */ - IP4_t ServerIPAddress; /**< TFTP server IP address */ - IP4_t GatewayIPAddress; /**< Relay agent IP address */ - /** File multicast IP address */ - IP4_t McastIPAddress; - /** Client multicast listening port */ - UDP_PORT_t TFTPClntPort; - /** Server multicast listening port */ - UDP_PORT_t TFTPSrvPort; - /** TFTP open timeout. - * - * This is the timeout for receiving the first DATA or ACK - * packets during the MTFTP Listen phase. - */ - UINT16_t TFTPOpenTimeOut; - /** TFTP reopen timeout. - * - * This is the timeout for receiving an ACK packet while in - * the MTFTP Listen phase (when at least one ACK packet has - * already been seen). - */ - UINT16_t TFTPReopenDelay; -} PACKED; - -typedef struct s_PXENV_TFTP_READ_FILE PXENV_TFTP_READ_FILE_t; - -extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE - *tftp_read_file ); - -/** @} */ /* pxenv_tftp_read_file */ - -/** @defgroup pxenv_tftp_get_fsize PXENV_TFTP_GET_FSIZE - * - * TFTP GET FILE SIZE - * - * @{ - */ - -/** PXE API function code for pxenv_tftp_get_fsize() */ -#define PXENV_TFTP_GET_FSIZE 0x0025 - -/** Parameter block for pxenv_tftp_get_fsize() */ -struct s_PXENV_TFTP_GET_FSIZE { - PXENV_STATUS_t Status; /**< PXE status code */ - IP4_t ServerIPAddress; /**< TFTP server IP address */ - IP4_t GatewayIPAddress; /**< Relay agent IP address */ - UINT8_t FileName[128]; /**< File name */ - UINT32_t FileSize; /**< Size of the file */ -} PACKED; - -typedef struct s_PXENV_TFTP_GET_FSIZE PXENV_TFTP_GET_FSIZE_t; - -extern PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE - *get_fsize ); - -/** @} */ /* pxenv_tftp_get_fsize */ - -/** @} */ /* pxe_tftp_api */ - -/** @defgroup pxe_udp_api PXE UDP API - * - * Transmit and receive UDP packets - * - * @{ - */ - -/** @defgroup pxenv_udp_open PXENV_UDP_OPEN - * - * UDP OPEN - * - * @{ - */ - -/** PXE API function code for pxenv_udp_open() */ -#define PXENV_UDP_OPEN 0x0030 - -/** Parameter block for pxenv_udp_open() */ -struct s_PXENV_UDP_OPEN { - PXENV_STATUS_t Status; /**< PXE status code */ - IP4_t src_ip; /**< IP address of this station */ -} PACKED; - -typedef struct s_PXENV_UDP_OPEN PXENV_UDP_OPEN_t; - -extern PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *udp_open ); - -/** @} */ /* pxenv_udp_open */ - -/** @defgroup pxenv_udp_close PXENV_UDP_CLOSE - * - * UDP CLOSE - * - * @{ - */ - -/** PXE API function code for pxenv_udp_close() */ -#define PXENV_UDP_CLOSE 0x0031 - -/** Parameter block for pxenv_udp_close() */ -struct s_PXENV_UDP_CLOSE { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UDP_CLOSE PXENV_UDP_CLOSE_t; - -extern PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *udp_close ); - -/** @} */ /* pxenv_udp_close */ - -/** @defgroup pxenv_udp_write PXENV_UDP_WRITE - * - * UDP WRITE - * - * @{ - */ - -/** PXE API function code for pxenv_udp_write() */ -#define PXENV_UDP_WRITE 0x0033 - -/** Parameter block for pxenv_udp_write() */ -struct s_PXENV_UDP_WRITE { - PXENV_STATUS_t Status; /**< PXE status code */ - IP4_t ip; /**< Destination IP address */ - IP4_t gw; /**< Relay agent IP address */ - UDP_PORT_t src_port; /**< Source UDP port */ - UDP_PORT_t dst_port; /**< Destination UDP port */ - UINT16_t buffer_size; /**< UDP payload buffer size */ - SEGOFF16_t buffer; /**< UDP payload buffer address */ -} PACKED; - -typedef struct s_PXENV_UDP_WRITE PXENV_UDP_WRITE_t; - -extern PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *udp_write ); - -/** @} */ /* pxenv_udp_write */ - -/** @defgroup pxenv_udp_read PXENV_UDP_READ - * - * UDP READ - * - * @{ - */ - -/** PXE API function code for pxenv_udp_read() */ -#define PXENV_UDP_READ 0x0032 - -/** Parameter block for pxenv_udp_read() */ -struct s_PXENV_UDP_READ { - PXENV_STATUS_t Status; /**< PXE status code */ - IP4_t src_ip; /**< Source IP address */ - IP4_t dest_ip; /**< Destination IP address */ - UDP_PORT_t s_port; /**< Source UDP port */ - UDP_PORT_t d_port; /**< Destination UDP port */ - UINT16_t buffer_size; /**< UDP payload buffer size */ - SEGOFF16_t buffer; /**< UDP payload buffer address */ -} PACKED; - -typedef struct s_PXENV_UDP_READ PXENV_UDP_READ_t; - -extern PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *udp_read ); - -/** @} */ /* pxenv_udp_read */ - -/** @} */ /* pxe_udp_api */ - -/** @defgroup pxe_undi_api PXE UNDI API - * - * Direct control of the network interface card - * - * @{ - */ - -/** @defgroup pxenv_undi_startup PXENV_UNDI_STARTUP - * - * UNDI STARTUP - * - * @{ - */ - -/** PXE API function code for pxenv_undi_startup() */ -#define PXENV_UNDI_STARTUP 0x0001 - -#define PXENV_BUS_ISA 0 /**< ISA bus type */ -#define PXENV_BUS_EISA 1 /**< EISA bus type */ -#define PXENV_BUS_MCA 2 /**< MCA bus type */ -#define PXENV_BUS_PCI 3 /**< PCI bus type */ -#define PXENV_BUS_VESA 4 /**< VESA bus type */ -#define PXENV_BUS_PCMCIA 5 /**< PCMCIA bus type */ - -/** Parameter block for pxenv_undi_startup() */ -struct s_PXENV_UNDI_STARTUP { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNDI_STARTUP PXENV_UNDI_STARTUP_t; - -extern PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP - *undi_startup ); - -/** @} */ /* pxenv_undi_startup */ - -/** @defgroup pxenv_undi_cleanup PXENV_UNDI_CLEANUP - * - * UNDI CLEANUP - * - * @{ - */ - -/** PXE API function code for pxenv_undi_cleanup() */ -#define PXENV_UNDI_CLEANUP 0x0002 - -/** Parameter block for pxenv_undi_cleanup() */ -struct s_PXENV_UNDI_CLEANUP { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNDI_CLEANUP PXENV_UNDI_CLEANUP_t; - -extern PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP - *undi_cleanup ); - -/** @} */ /* pxenv_undi_cleanup */ - -/** @defgroup pxenv_undi_initialize PXENV_UNDI_INITIALIZE - * - * UNDI INITIALIZE - * - * @{ - */ - -/** PXE API function code for pxenv_undi_initialize() */ -#define PXENV_UNDI_INITIALIZE 0x0003 - -/** Parameter block for pxenv_undi_initialize() */ -struct s_PXENV_UNDI_INITIALIZE { - PXENV_STATUS_t Status; /**< PXE status code */ - /** NDIS 2.0 configuration information, or NULL - * - * This is a pointer to the data structure returned by the - * NDIS 2.0 GetProtocolManagerInfo() API call. The data - * structure is documented, in a rather haphazard way, in - * section 4-17 of the NDIS 2.0 specification. - */ - ADDR32_t ProtocolIni; - UINT8_t reserved[8]; /**< Must be zero */ -} PACKED; - -typedef struct s_PXENV_UNDI_INITIALIZE PXENV_UNDI_INITIALIZE_t; - -extern PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE - *undi_initialize ); - -/** @} */ /* pxenv_undi_initialize */ - -/** @defgroup pxenv_undi_reset_adapter PXENV_UNDI_RESET_ADAPTER - * - * UNDI RESET ADAPTER - * - * @{ - */ - -/** PXE API function code for pxenv_undi_reset_adapter() */ -#define PXENV_UNDI_RESET_ADAPTER 0x0004 - -/** Maximum number of multicast MAC addresses */ -#define MAXNUM_MCADDR 8 - -/** List of multicast MAC addresses */ -struct s_PXENV_UNDI_MCAST_ADDRESS { - /** Number of multicast MAC addresses */ - UINT16_t MCastAddrCount; - /** List of up to #MAXNUM_MCADDR multicast MAC addresses */ - MAC_ADDR_t McastAddr[MAXNUM_MCADDR]; -} PACKED; - -typedef struct s_PXENV_UNDI_MCAST_ADDRESS PXENV_UNDI_MCAST_ADDRESS_t; - -/** Parameter block for pxenv_undi_reset_adapter() */ -struct s_PXENV_UNDI_RESET { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Multicast MAC addresses */ - struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} PACKED; - -typedef struct s_PXENV_UNDI_RESET PXENV_UNDI_RESET_t; - -extern PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET - *undi_reset_adapter ); - -/** @} */ /* pxenv_undi_reset_adapter */ - -/** @defgroup pxenv_undi_shutdown PXENV_UNDI_SHUTDOWN - * - * UNDI SHUTDOWN - * - * @{ - */ - -/** PXE API function code for pxenv_undi_shutdown() */ -#define PXENV_UNDI_SHUTDOWN 0x0005 - -/** Parameter block for pxenv_undi_shutdown() */ -struct s_PXENV_UNDI_SHUTDOWN { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNDI_SHUTDOWN PXENV_UNDI_SHUTDOWN_t; - -extern PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN - *undi_shutdown ); - -/** @} */ /* pxenv_undi_shutdown */ - -/** @defgroup pxenv_undi_open PXENV_UNDI_OPEN - * - * UNDI OPEN - * - * @{ - */ - -/** PXE API function code for pxenv_undi_open() */ -#define PXENV_UNDI_OPEN 0x0006 - -/** Accept "directed" packets - * - * These are packets addresses to either this adapter's MAC address or - * to any of the configured multicast MAC addresses (see - * #s_PXENV_UNDI_MCAST_ADDRESS). - */ -#define FLTR_DIRECTED 0x0001 -/** Accept broadcast packets */ -#define FLTR_BRDCST 0x0002 -/** Accept all packets; listen in promiscuous mode */ -#define FLTR_PRMSCS 0x0004 -/** Accept source-routed packets */ -#define FLTR_SRC_RTG 0x0008 - -/** Parameter block for pxenv_undi_open() */ -struct s_PXENV_UNDI_OPEN { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Open flags as defined in NDIS 2.0 - * - * This is the OpenOptions field as passed to the NDIS 2.0 - * OpenAdapter() API call. It is defined to be "adapter - * specific", though 0 is guaranteed to be a valid value. - */ - UINT16_t OpenFlag; - /** Receive packet filter - * - * This is the bitwise-OR of any of the following flags: - * #FLTR_DIRECTED, #FLTR_BRDCST, #FLTR_PRMSCS and - * #FLTR_SRC_RTG. - */ - UINT16_t PktFilter; - /** Multicast MAC addresses */ - struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} PACKED; - -typedef struct s_PXENV_UNDI_OPEN PXENV_UNDI_OPEN_t; - -extern PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ); - -/** @} */ /* pxenv_undi_open */ - -/** @defgroup pxenv_undi_close PXENV_UNDI_CLOSE - * - * UNDI CLOSE - * - * @{ - */ - -/** PXE API function code for pxenv_undi_close() */ -#define PXENV_UNDI_CLOSE 0x0007 - -/** Parameter block for pxenv_undi_close() */ -struct s_PXENV_UNDI_CLOSE { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNDI_CLOSE PXENV_UNDI_CLOSE_t; - -extern PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ); - -/** @} */ /* pxenv_undi_close */ - -/** @defgroup pxenv_undi_transmit PXENV_UNDI_TRANSMIT - * - * UNDI TRANSMIT PACKET - * - * @{ - */ - -/** PXE API function code for pxenv_undi_transmit() */ -#define PXENV_UNDI_TRANSMIT 0x0008 - -#define P_UNKNOWN 0 /**< Media header already filled in */ -#define P_IP 1 /**< IP protocol */ -#define P_ARP 2 /**< ARP protocol */ -#define P_RARP 3 /**< RARP protocol */ -#define P_OTHER 4 /**< Other protocol */ - -#define XMT_DESTADDR 0x0000 /**< Unicast packet */ -#define XMT_BROADCAST 0x0001 /**< Broadcast packet */ - -/** Maximum number of data blocks in a transmit buffer descriptor */ -#define MAX_DATA_BLKS 8 - -/** A transmit buffer descriptor, as pointed to by s_PXENV_UNDI_TRANSMIT::TBD - */ -struct s_PXENV_UNDI_TBD { - UINT16_t ImmedLength; /**< Length of the transmit buffer */ - SEGOFF16_t Xmit; /**< Address of the transmit buffer */ - UINT16_t DataBlkCount; - /** Array of up to #MAX_DATA_BLKS additional transmit buffers */ - struct DataBlk { - /** Always 1 - * - * A value of 0 would indicate that #TDDataPtr were an - * #ADDR32_t rather than a #SEGOFF16_t. The PXE - * specification version 2.1 explicitly states that - * this is not supported; #TDDataPtr will always be a - * #SEGOFF16_t. - */ - UINT8_t TDPtrType; - UINT8_t TDRsvdByte; /**< Must be zero */ - UINT16_t TDDataLen; /**< Length of this transmit buffer */ - SEGOFF16_t TDDataPtr; /**< Address of this transmit buffer */ - } DataBlock[MAX_DATA_BLKS]; -} PACKED; - -typedef struct s_PXENV_UNDI_TBD PXENV_UNDI_TBD_t; - -/** Parameter block for pxenv_undi_transmit() */ -struct s_PXENV_UNDI_TRANSMIT { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Protocol - * - * Valid values are #P_UNKNOWN, #P_IP, #P_ARP or #P_RARP. If - * the caller has already filled in the media header, this - * field must be set to #P_UNKNOWN. - */ - UINT8_t Protocol; - /** Unicast/broadcast flag - * - * Valid values are #XMT_DESTADDR or #XMT_BROADCAST. - */ - UINT8_t XmitFlag; - SEGOFF16_t DestAddr; /**< Destination MAC address */ - /** Address of the Transmit Buffer Descriptor - * - * This is a pointer to a struct s_PXENV_UNDI_TBD. - */ - SEGOFF16_t TBD; - UINT32_t Reserved[2]; /**< Must be zero */ -} PACKED; - -typedef struct s_PXENV_UNDI_TRANSMIT PXENV_UNDI_TRANSMIT_t; - -extern PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT - *undi_transmit ); - -/** @} */ /* pxenv_undi_transmit */ - -/** @defgroup pxenv_undi_set_mcast_address PXENV_UNDI_SET_MCAST_ADDRESS - * - * UNDI SET MULTICAST ADDRESS - * - * @{ - */ - -/** PXE API function code for pxenv_undi_set_mcast_address() */ -#define PXENV_UNDI_SET_MCAST_ADDRESS 0x0009 - -/** Parameter block for pxenv_undi_set_mcast_address() */ -struct s_PXENV_UNDI_SET_MCAST_ADDRESS { - PXENV_STATUS_t Status; /**< PXE status code */ - /** List of multicast addresses */ - struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} PACKED; - -typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS PXENV_UNDI_SET_MCAST_ADDRESS_t; - -extern PXENV_EXIT_t pxenv_undi_set_mcast_address ( - struct s_PXENV_UNDI_SET_MCAST_ADDRESS *undi_set_mcast_address ); - -/** @} */ /* pxenv_undi_set_mcast_address */ - -/** @defgroup pxenv_undi_set_station_address PXENV_UNDI_SET_STATION_ADDRESS - * - * UNDI SET STATION ADDRESS - * - * @{ - */ - -/** PXE API function code for pxenv_undi_set_station_address() */ -#define PXENV_UNDI_SET_STATION_ADDRESS 0x000a - -/** Parameter block for pxenv_undi_set_station_address() */ -struct s_PXENV_UNDI_SET_STATION_ADDRESS { - PXENV_STATUS_t Status; /**< PXE status code */ - MAC_ADDR_t StationAddress; /**< Station MAC address */ -} PACKED; - -typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS PXENV_UNDI_SET_STATION_ADDRESS_t; - -extern PXENV_EXIT_t pxenv_undi_set_station_address ( - struct s_PXENV_UNDI_SET_STATION_ADDRESS *undi_set_station_address ); - -/** @} */ /* pxenv_undi_set_station_address */ - -/** @defgroup pxenv_undi_set_packet_filter PXENV_UNDI_SET_PACKET_FILTER - * - * UNDI SET PACKET FILTER - * - * @{ - */ - -/** PXE API function code for pxenv_undi_set_packet_filter() */ -#define PXENV_UNDI_SET_PACKET_FILTER 0x000b - -/** Parameter block for pxenv_undi_set_packet_filter() */ -struct s_PXENV_UNDI_SET_PACKET_FILTER { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Receive packet filter - * - * This field takes the same values as - * s_PXENV_UNDI_OPEN::PktFilter. - * - * @note Yes, this field is a different size to - * s_PXENV_UNDI_OPEN::PktFilter. Blame "the managers at Intel - * who apparently let a consultant come up with the spec - * without any kind of adult supervision" (quote from hpa). - */ - UINT8_t filter; -} PACKED; - -typedef struct s_PXENV_UNDI_SET_PACKET_FILTER PXENV_UNDI_SET_PACKET_FILTER_t; - -extern PXENV_EXIT_t pxenv_undi_set_packet_filter ( - struct s_PXENV_UNDI_SET_PACKET_FILTER *undi_set_packet_filter ); - -/** @} */ /* pxenv_undi_set_packet_filter */ - -/** @defgroup pxenv_undi_get_information PXENV_UNDI_GET_INFORMATION - * - * UNDI GET INFORMATION - * - * @{ - */ - -/** PXE API function code for pxenv_undi_get_information() */ -#define PXENV_UNDI_GET_INFORMATION 0x000c - -#define ETHER_TYPE 1 /**< Ethernet (10Mb) */ -#define EXP_ETHER_TYPE 2 /**< Experimental Ethernet (3Mb) */ -#define AX25_TYPE 3 /**< Amateur Radio AX.25 */ -#define TOKEN_RING_TYPE 4 /**< Proteon ProNET Token Ring */ -#define CHAOS_TYPE 5 /**< Chaos */ -#define IEEE_TYPE 6 /**< IEEE 802 Networks */ -#define ARCNET_TYPE 7 /**< ARCNET */ - -/** Parameter block for pxenv_undi_get_information() */ -struct s_PXENV_UNDI_GET_INFORMATION { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t BaseIo; /**< I/O base address */ - UINT16_t IntNumber; /**< IRQ number */ - UINT16_t MaxTranUnit; /**< Adapter MTU */ - /** Hardware type - * - * Valid values are defined in RFC1010 ("Assigned numbers"), - * and are #ETHER_TYPE, #EXP_ETHER_TYPE, #AX25_TYPE, - * #TOKEN_RING_TYPE, #CHAOS_TYPE, #IEEE_TYPE or #ARCNET_TYPE. - */ - UINT16_t HwType; - UINT16_t HwAddrLen; /**< MAC address length */ - MAC_ADDR_t CurrentNodeAddress; /**< Current MAC address */ - MAC_ADDR_t PermNodeAddress; /**< Permanent (EEPROM) MAC address */ - SEGSEL_t ROMAddress; /**< Real-mode ROM segment address */ - UINT16_t RxBufCt; /**< Receive queue length */ - UINT16_t TxBufCt; /**< Transmit queue length */ -} PACKED; - -typedef struct s_PXENV_UNDI_GET_INFORMATION PXENV_UNDI_GET_INFORMATION_t; - -extern PXENV_EXIT_t pxenv_undi_get_information ( - struct s_PXENV_UNDI_GET_INFORMATION *undi_get_information ); - -/** @} */ /* pxenv_undi_get_information */ - -/** @defgroup pxenv_undi_get_statistics PXENV_UNDI_GET_STATISTICS - * - * UNDI GET STATISTICS - * - * @{ - */ - -/** PXE API function code for pxenv_undi_get_statistics() */ -#define PXENV_UNDI_GET_STATISTICS 0x000d - -/** Parameter block for pxenv_undi_get_statistics() */ -struct s_PXENV_UNDI_GET_STATISTICS { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT32_t XmtGoodFrames; /**< Successful transmission count */ - UINT32_t RcvGoodFrames; /**< Successful reception count */ - UINT32_t RcvCRCErrors; /**< Receive CRC error count */ - UINT32_t RcvResourceErrors; /**< Receive queue overflow count */ -} PACKED; - -typedef struct s_PXENV_UNDI_GET_STATISTICS PXENV_UNDI_GET_STATISTICS_t; - -extern PXENV_EXIT_t pxenv_undi_get_statistics ( - struct s_PXENV_UNDI_GET_STATISTICS *undi_get_statistics ); - -/** @} */ /* pxenv_undi_get_statistics */ - -/** @defgroup pxenv_undi_clear_statistics PXENV_UNDI_CLEAR_STATISTICS - * - * UNDI CLEAR STATISTICS - * - * @{ - */ - -/** PXE API function code for pxenv_undi_clear_statistics() */ -#define PXENV_UNDI_CLEAR_STATISTICS 0x000e - -/** Parameter block for pxenv_undi_clear_statistics() */ -struct s_PXENV_UNDI_CLEAR_STATISTICS { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNDI_CLEAR_STATISTICS PXENV_UNDI_CLEAR_STATISTICS_t; - -extern PXENV_EXIT_t pxenv_undi_clear_statistics ( - struct s_PXENV_UNDI_CLEAR_STATISTICS *undi_clear_statistics ); - -/** @} */ /* pxenv_undi_clear_statistics */ - -/** @defgroup pxenv_undi_initiate_diags PXENV_UNDI_INITIATE_DIAGS - * - * UNDI INITIATE DIAGS - * - * @{ - */ - -/** PXE API function code for pxenv_undi_initiate_diags() */ -#define PXENV_UNDI_INITIATE_DIAGS 0x000f - -/** Parameter block for pxenv_undi_initiate_diags() */ -struct s_PXENV_UNDI_INITIATE_DIAGS { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNDI_INITIATE_DIAGS PXENV_UNDI_INITIATE_DIAGS_t; - -extern PXENV_EXIT_t pxenv_undi_initiate_diags ( - struct s_PXENV_UNDI_INITIATE_DIAGS *undi_initiate_diags ); - -/** @} */ /* pxenv_undi_initiate_diags */ - -/** @defgroup pxenv_undi_force_interrupt PXENV_UNDI_FORCE_INTERRUPT - * - * UNDI FORCE INTERRUPT - * - * @{ - */ - -/** PXE API function code for pxenv_undi_force_interrupt() */ -#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 - -/** Parameter block for pxenv_undi_force_interrupt() */ -struct s_PXENV_UNDI_FORCE_INTERRUPT { - PXENV_STATUS_t Status; /**< PXE status code */ -} PACKED; - -typedef struct s_PXENV_UNDI_FORCE_INTERRUPT PXENV_UNDI_FORCE_INTERRUPT_t; - -extern PXENV_EXIT_t pxenv_undi_force_interrupt ( - struct s_PXENV_UNDI_FORCE_INTERRUPT *undi_force_interrupt ); - -/** @} */ /* pxenv_undi_force_interrupt */ - -/** @defgroup pxenv_undi_get_mcast_address PXENV_UNDI_GET_MCAST_ADDRESS - * - * UNDI GET MULTICAST ADDRESS - * - * @{ - */ - -/** PXE API function code for pxenv_undi_get_mcast_address() */ -#define PXENV_UNDI_GET_MCAST_ADDRESS 0x0011 - -/** Parameter block for pxenv_undi_get_mcast_address() */ -struct s_PXENV_UNDI_GET_MCAST_ADDRESS { - PXENV_STATUS_t Status; /**< PXE status code */ - IP4_t InetAddr; /**< Multicast IP address */ - MAC_ADDR_t MediaAddr; /**< Multicast MAC address */ -} PACKED; - -typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS PXENV_UNDI_GET_MCAST_ADDRESS_t; - -extern PXENV_EXIT_t pxenv_undi_get_mcast_address ( - struct s_PXENV_UNDI_GET_MCAST_ADDRESS *undi_get_mcast_address ); - -/** @} */ /* pxenv_undi_get_mcast_address */ - -/** @defgroup pxenv_undi_get_nic_type PXENV_UNDI_GET_NIC_TYPE - * - * UNDI GET NIC TYPE - * - * @{ - */ - -/** PXE API function code for pxenv_undi_get_nic_type() */ -#define PXENV_UNDI_GET_NIC_TYPE 0x0012 - -#define PCI_NIC 2 /**< PCI network card */ -#define PnP_NIC 3 /**< ISAPnP network card */ -#define CardBus_NIC 4 /**< CardBus network card */ - -/** Information for a PCI or equivalent NIC */ -struct pci_nic_info { - UINT16_t Vendor_ID; /**< PCI vendor ID */ - UINT16_t Dev_ID; /**< PCI device ID */ - UINT8_t Base_Class; /**< PCI base class */ - UINT8_t Sub_Class; /**< PCI sub class */ - UINT8_t Prog_Intf; /**< PCI programming interface */ - UINT8_t Rev; /**< PCI revision */ - UINT16_t BusDevFunc; /**< PCI bus:dev:fn address */ - UINT16_t SubVendor_ID; /**< PCI subvendor ID */ - UINT16_t SubDevice_ID; /**< PCI subdevice ID */ -} PACKED; - -/** Information for an ISAPnP or equivalent NIC */ -struct pnp_nic_info { - UINT32_t EISA_Dev_ID; /**< EISA device ID */ - UINT8_t Base_Class; /**< Base class */ - UINT8_t Sub_Class; /**< Sub class */ - UINT8_t Prog_Intf; /**< Programming interface */ - /** Card Select Number assigned to card */ - UINT16_t CardSelNum; -} PACKED; - -/** Parameter block for pxenv_undi_get_nic_type() */ -struct s_PXENV_UNDI_GET_NIC_TYPE { - PXENV_STATUS_t Status; /**< PXE status code */ - /** NIC type - * - * Valid values are #PCI_NIC, #PnP_NIC or #CardBus_NIC. - */ - UINT8_t NicType; - /** NIC information */ - union nic_type_info { - /** NIC information (if #NicType==#PCI_NIC) */ - struct pci_nic_info pci; - /** NIC information (if #NicType==#CardBus_NIC) */ - struct pci_nic_info cardbus; - /** NIC information (if #NicType==#PnP_NIC) */ - struct pnp_nic_info pnp; - } info; -} PACKED; - -typedef struct s_PXENV_UNDI_GET_NIC_TYPE PXENV_UNDI_GET_NIC_TYPE_t; - -extern PXENV_EXIT_t pxenv_undi_get_nic_type ( - struct s_PXENV_UNDI_GET_NIC_TYPE *undi_get_nic_type ); - -/** @} */ /* pxenv_undi_get_nic_type */ - -/** @defgroup pxenv_undi_get_iface_info PXENV_UNDI_GET_IFACE_INFO - * - * UNDI GET IFACE INFO - * - * @{ - */ - -/** PXE API function code for pxenv_undi_get_iface_info() */ -#define PXENV_UNDI_GET_IFACE_INFO 0x0013 - -/** Broadcast supported */ -#define SUPPORTED_BROADCAST 0x0001 -/** Multicast supported */ -#define SUPPORTED_MULTICAST 0x0002 -/** Functional/group addressing supported */ -#define SUPPORTED_GROUP 0x0004 -/** Promiscuous mode supported */ -#define SUPPORTED_PROMISCUOUS 0x0008 -/** Software settable station address */ -#define SUPPORTED_SET_STATION_ADDRESS 0x0010 -/** InitiateDiagnostics supported */ -#define SUPPORTED_DIAGNOSTICS 0x0040 -/** Reset MAC supported */ -#define SUPPORTED_RESET 0x0400 -/** Open / Close Adapter supported */ -#define SUPPORTED_OPEN_CLOSE 0x0800 -/** Interrupt Request supported */ -#define SUPPORTED_IRQ 0x1000 - -/** Parameter block for pxenv_undi_get_iface_info() */ -struct s_PXENV_UNDI_GET_IFACE_INFO { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Interface type - * - * This is defined in the NDIS 2.0 specification to be one of - * the strings "802.3", "802.4", "802.5", "802.6", "DIX", - * "DIX+802.3", "APPLETALK", "ARCNET", "FDDI", "SDLC", "BSC", - * "HDLC", or "ISDN". - * - * "Normal" Ethernet, for various historical reasons, is - * "DIX+802.3". - */ - UINT8_t IfaceType[16]; - UINT32_t LinkSpeed; /**< Link speed, in bits per second */ - /** Service flags - * - * These are the "service flags" defined in the "MAC - * Service-Specific Characteristics" table in the NDIS 2.0 - * specification. Almost all of them are irrelevant to PXE. - */ - UINT32_t ServiceFlags; - UINT32_t Reserved[4]; /**< Must be zero */ -} PACKED; - -typedef struct s_PXENV_UNDI_GET_IFACE_INFO PXENV_UNDI_GET_IFACE_INFO_t; - -extern PXENV_EXIT_t pxenv_undi_get_iface_info ( - struct s_PXENV_UNDI_GET_IFACE_INFO *undi_get_iface_info ); - -/** @} */ /* pxenv_undi_get_iface_info */ - -/** @defgroup pxenv_undi_get_state PXENV_UNDI_GET_STATE - * - * UNDI GET STATE - * - * @{ - */ - -/** PXE API function code for pxenv_undi_get_state() */ -#define PXENV_UNDI_GET_STATE 0x0015 - -/** pxenv_start_undi() has been called */ -#define PXE_UNDI_GET_STATE_STARTED 1 -/** pxenv_undi_initialize() has been called */ -#define PXE_UNDI_GET_STATE_INITIALIZED 2 -/** pxenv_undi_open() has been called */ -#define PXE_UNDI_GET_STATE_OPENED 3 - -/** Parameter block for pxenv_undi_get_state() */ -struct s_PXENV_UNDI_GET_STATE { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Current state of the UNDI driver - * - * Valid values are #PXE_UNDI_GET_STATE_STARTED, - * #PXE_UNDI_GET_STATE_INITIALIZED or - * #PXE_UNDI_GET_STATE_OPENED. - */ - UINT8_t UNDIstate; -} PACKED; - -typedef struct s_PXENV_UNDI_GET_STATE PXENV_UNDI_GET_STATE_t; - -extern PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE - *undi_get_state ); - -/** @} */ /* pxenv_undi_get_state */ - -/** @defgroup pxenv_undi_isr PXENV_UNDI_ISR - * - * UNDI ISR - * - * @{ - */ - -/** PXE API function code for pxenv_undi_isr() */ -#define PXENV_UNDI_ISR 0x0014 - -/** Determine whether or not this is our interrupt */ -#define PXENV_UNDI_ISR_IN_START 1 -/** Start processing interrupt */ -#define PXENV_UNDI_ISR_IN_PROCESS 2 -/** Continue processing interrupt */ -#define PXENV_UNDI_ISR_IN_GET_NEXT 3 -/** This interrupt was ours */ -#define PXENV_UNDI_ISR_OUT_OURS 0 -/** This interrupt was not ours */ -#define PXENV_UNDI_ISR_OUT_NOT_OURS 1 -/** Finished processing interrupt */ -#define PXENV_UNDI_ISR_OUT_DONE 0 -/** A packet transmission has completed */ -#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 -/** A packet has been received */ -#define PXENV_UNDI_ISR_OUT_RECEIVE 3 -/** We are already in the middle of processing an interrupt */ -#define PXENV_UNDI_ISR_OUT_BUSY 4 - -/** Unicast packet (or packet captured in promiscuous mode) */ -#define P_DIRECTED 0 -/** Broadcast packet */ -#define P_BROADCAST 1 -/** Multicast packet */ -#define P_MULTICAST 2 - -/** Parameter block for pxenv_undi_isr() */ -struct s_PXENV_UNDI_ISR { - PXENV_STATUS_t Status; /**< PXE status code */ - /** Function flag - * - * Valid values are #PXENV_UNDI_ISR_IN_START, - * #PXENV_UNDI_ISR_IN_PROCESS, #PXENV_UNDI_ISR_IN_GET_NEXT, - * #PXENV_UNDI_ISR_OUT_OURS, #PXENV_UNDI_ISR_OUT_NOT_OURS, - * #PXENV_UNDI_ISR_OUT_DONE, #PXENV_UNDI_ISR_OUT_TRANSMIT, - * #PXENV_UNDI_ISR_OUT_RECEIVE or #PXENV_UNDI_ISR_OUT_BUSY. - */ - UINT16_t FuncFlag; - UINT16_t BufferLength; /**< Data buffer length */ - UINT16_t FrameLength; /**< Total frame length */ - UINT16_t FrameHeaderLength; /**< Frame header length */ - SEGOFF16_t Frame; /**< Data buffer address */ - /** Protocol type - * - * Valid values are #P_IP, #P_ARP, #P_RARP or #P_OTHER. - */ - UINT8_t ProtType; - /** Packet type - * - * Valid values are #P_DIRECTED, #P_BROADCAST or #P_MULTICAST. - */ - UINT8_t PktType; -} PACKED; - -typedef struct s_PXENV_UNDI_ISR PXENV_UNDI_ISR_t; - -extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ); - -/** @} */ /* pxenv_undi_isr */ - -/** @} */ /* pxe_undi_api */ - -/** @defgroup pxe_file_api PXE FILE API - * - * POSIX-like file operations - * - * @{ - */ - -/** @defgroup pxenv_file_open PXENV_FILE_OPEN - * - * FILE OPEN - * - * @{ - */ - -/** PXE API function code for pxenv_file_open() */ -#define PXENV_FILE_OPEN 0x00e0 - -/** Parameter block for pxenv_file_open() */ -struct s_PXENV_FILE_OPEN { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t FileHandle; /**< File handle */ - SEGOFF16_t FileName; /**< File URL */ - UINT32_t Reserved; /**< Reserved */ -} PACKED; - -typedef struct s_PXENV_FILE_OPEN PXENV_FILE_OPEN_t; - -extern PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ); - -/** @} */ /* pxenv_file_open */ - -/** @defgroup pxenv_file_close PXENV_FILE_CLOSE - * - * FILE CLOSE - * - * @{ - */ - -/** PXE API function code for pxenv_file_close() */ -#define PXENV_FILE_CLOSE 0x00e1 - -/** Parameter block for pxenv_file_close() */ -struct s_PXENV_FILE_CLOSE { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t FileHandle; /**< File handle */ -} PACKED; - -typedef struct s_PXENV_FILE_CLOSE PXENV_FILE_CLOSE_t; - -extern PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE - *file_close ); - -/** @} */ /* pxenv_file_close */ - -/** @defgroup pxenv_file_select PXENV_FILE_SELECT - * - * FILE SELECT - * - * @{ - */ - -/** PXE API function code for pxenv_file_select() */ -#define PXENV_FILE_SELECT 0x00e2 - -/** File is ready for reading */ -#define RDY_READ 0x0001 - -/** Parameter block for pxenv_file_select() */ -struct s_PXENV_FILE_SELECT { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t FileHandle; /**< File handle */ - UINT16_t Ready; /**< Indication of readiness */ -} PACKED; - -typedef struct s_PXENV_FILE_SELECT PXENV_FILE_SELECT_t; - -extern PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT - *file_select ); - -/** @} */ /* pxenv_file_select */ - -/** @defgroup pxenv_file_read PXENV_FILE_READ - * - * FILE READ - * - * @{ - */ - -/** PXE API function code for pxenv_file_read() */ -#define PXENV_FILE_READ 0x00e3 - -/** Parameter block for pxenv_file_read() */ -struct s_PXENV_FILE_READ { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t FileHandle; /**< File handle */ - UINT16_t BufferSize; /**< Data buffer size */ - SEGOFF16_t Buffer; /**< Data buffer */ -} PACKED; - -typedef struct s_PXENV_FILE_READ PXENV_FILE_READ_t; - -extern PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ); - -/** @} */ /* pxenv_file_read */ - -/** @defgroup pxenv_get_file_size PXENV_GET_FILE_SIZE - * - * GET FILE SIZE - * - * @{ - */ - -/** PXE API function code for pxenv_get_file_size() */ -#define PXENV_GET_FILE_SIZE 0x00e4 - -/** Parameter block for pxenv_get_file_size() */ -struct s_PXENV_GET_FILE_SIZE { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t FileHandle; /**< File handle */ - UINT32_t FileSize; /**< File size */ -} PACKED; - -typedef struct s_PXENV_GET_FILE_SIZE PXENV_GET_FILE_SIZE_t; - -extern PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE - *get_file_size ); - -/** @} */ /* pxenv_get_file_size */ - -/** @defgroup pxenv_file_exec PXENV_FILE_EXEC - * - * FILE EXEC - * - * @{ - */ - -/** PXE API function code for pxenv_file_exec() */ -#define PXENV_FILE_EXEC 0x00e5 - -/** Parameter block for pxenv_file_exec() */ -struct s_PXENV_FILE_EXEC { - PXENV_STATUS_t Status; /**< PXE status code */ - SEGOFF16_t Command; /**< Command to execute */ -} PACKED; - -typedef struct s_PXENV_FILE_EXEC PXENV_FILE_EXEC_t; - -extern PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ); - -/** @} */ /* pxenv_file_exec */ - -/** @defgroup pxenv_file_api_check PXENV_FILE_API_CHECK - * - * FILE API CHECK - * - * @{ - */ - -/** PXE API function code for pxenv_file_api_check() */ -#define PXENV_FILE_API_CHECK 0x00e6 - -/** Parameter block for pxenv_file_api_check() */ -struct s_PXENV_FILE_API_CHECK { - PXENV_STATUS_t Status; /**< PXE status code */ - UINT16_t Size; /**< Size of structure */ - UINT32_t Magic; /**< Magic number */ - UINT32_t Provider; /**< Implementation identifier */ - UINT32_t APIMask; /**< Supported API functions */ - UINT32_t Flags; /**< Reserved for the future */ -} PACKED; - -typedef struct s_PXENV_FILE_API_CHECK PXENV_FILE_API_CHECK_t; - -extern PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ); - -/** @} */ /* pxenv_file_api_check */ - -/** @defgroup pxenv_file_exit_hook PXENV_FILE_EXIT_HOOK - * - * FILE EXIT HOOK - * - * @{ - */ - -/** PXE API function code for pxenv_file_exit_hook() */ -#define PXENV_FILE_EXIT_HOOK 0x00e7 - -/** Parameter block for pxenv_file_exit_hook() */ -struct s_PXENV_FILE_EXIT_HOOK { - PXENV_STATUS_t Status; /**< PXE status code */ - SEGOFF16_t Hook; /**< SEG16:OFF16 to jump to */ -} PACKED; - -typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t; - -extern PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook ); - -/** @} */ /* pxenv_file_exit_hook */ - -/** @} */ /* pxe_file_api */ - -/** @defgroup pxe_loader_api PXE Loader API - * - * The UNDI ROM loader API - * - * @{ - */ - -/** Parameter block for undi_loader() */ -struct s_UNDI_LOADER { - /** PXE status code */ - PXENV_STATUS_t Status; - /** %ax register as for PXENV_START_UNDI */ - UINT16_t AX; - /** %bx register as for PXENV_START_UNDI */ - UINT16_t BX; - /** %dx register as for PXENV_START_UNDI */ - UINT16_t DX; - /** %di register as for PXENV_START_UNDI */ - OFF16_t DI; - /** %es register as for PXENV_START_UNDI */ - SEGSEL_t ES; - /** UNDI data segment - * - * @note The PXE specification defines the type of this field - * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are - * equivalent anyway; for other architectures #SEGSEL_t makes - * more sense. - */ - SEGSEL_t UNDI_DS; - /** UNDI code segment - * - * @note The PXE specification defines the type of this field - * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are - * equivalent anyway; for other architectures #SEGSEL_t makes - * more sense. - */ - SEGSEL_t UNDI_CS; - /** Address of the !PXE structure (a struct s_PXE) */ - SEGOFF16_t PXEptr; - /** Address of the PXENV+ structure (a struct s_PXENV) */ - SEGOFF16_t PXENVptr; -} PACKED; - -typedef struct s_UNDI_LOADER UNDI_LOADER_t; - -extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ); - -/** @} */ /* pxe_loader_api */ - -/** @} */ /* pxe */ - -/** @page pxe_notes Etherboot PXE implementation notes - -@section pxe_routing IP routing - -Several PXE API calls (e.g. pxenv_tftp_open() and pxenv_udp_write()) -allow for the caller to specify a "relay agent IP address", often in a -field called "gateway" or similar. The PXE specification states that -"The IP layer should provide space for a minimum of four routing -entries obtained from the default router and static route DHCP option -tags in the DHCPACK message, plus any non-zero giaddr field from the -DHCPOFFER message(s) accepted by the client". - -The DHCP static route option ("option static-routes" in dhcpd.conf) -works only for classed IP routing (i.e. it provides no way to specify -a subnet mask). Since virtually everything now uses classless IP -routing, the DHCP static route option is almost totally useless, and -is (according to the dhcp-options man page) not implemented by any of -the popular DHCP clients. - -This leaves the caller-specified "relay agent IP address", the giaddr -field from the DHCPOFFER message(s) and the default gateway(s) -provided via the routers option ("option routers" in dhcpd.conf) in -the DHCPACK message. Each of these is a default gateway address. -It's a fair bet that the routers option should take priority over the -giaddr field, since the routers option has to be explicitly specified -by the DHCP server operator. Similarly, it's fair to assume that the -caller-specified "relay agent IP address", if present, should take -priority over any other routing table entries. - -@bug Etherboot currently ignores all potential sources of routing -information other than the first router provided to it by a DHCP -routers option. - -@section pxe_x86_modes x86 processor mode restrictions - -On the x86 platform, different PXE API calls have different -restrictions on the processor modes (real or protected) that can be -used. See the individual API call descriptions for the restrictions -that apply to any particular call. - -@subsection pxe_x86_pmode16 Real mode, or protected-mode with 16-bit stack - -The PXE specification states that the API function can be called in -protected mode only if the s_PXE::StatusCallout field is set to a -non-zero value, and that the API function cannot be called with a -32-bit stack segment. - -Etherboot does not enforce either of these restrictions; they seem (as -with so much of the PXE specification) to be artifacts of the Intel -implementation. - -*/ - -#endif /* PXE_API_H */ diff --git a/gpxe/src/arch/i386/include/pxe_call.h b/gpxe/src/arch/i386/include/pxe_call.h deleted file mode 100644 index 4d245616..00000000 --- a/gpxe/src/arch/i386/include/pxe_call.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _PXE_CALL_H -#define _PXE_CALL_H - -/** @file - * - * PXE API entry point - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <pxe_api.h> -#include <realmode.h> - -struct net_device; - -/** PXE load address segment */ -#define PXE_LOAD_SEGMENT 0 - -/** PXE load address offset */ -#define PXE_LOAD_OFFSET 0x7c00 - -/** PXE physical load address */ -#define PXE_LOAD_PHYS ( ( PXE_LOAD_SEGMENT << 4 ) + PXE_LOAD_OFFSET ) - -/** !PXE structure */ -extern struct s_PXE __text16 ( ppxe ); -#define ppxe __use_text16 ( ppxe ) - -/** PXENV+ structure */ -extern struct s_PXENV __text16 ( pxenv ); -#define pxenv __use_text16 ( pxenv ) - -extern void pxe_activate ( struct net_device *netdev ); -extern int pxe_deactivate ( void ); -extern int pxe_start_nbp ( void ); -extern __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ); -extern int _pxe_api_call_weak ( struct i386_all_regs *ix86 ) - __attribute__ (( weak )); - -/** - * Dispatch PXE API call weakly - * - * @v ix86 Registers for PXE call - * @ret present Zero if the PXE stack is present, nonzero if not - * - * A successful return only indicates that the PXE stack was available - * for dispatching the call; it says nothing about the success of - * whatever the call asked for. - */ -static inline int pxe_api_call_weak ( struct i386_all_regs *ix86 ) -{ - if ( _pxe_api_call_weak != NULL ) - return _pxe_api_call_weak ( ix86 ); - return -1; -} - -#endif /* _PXE_CALL_H */ diff --git a/gpxe/src/arch/i386/include/pxe_types.h b/gpxe/src/arch/i386/include/pxe_types.h deleted file mode 100644 index a6516d25..00000000 --- a/gpxe/src/arch/i386/include/pxe_types.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef PXE_TYPES_H -#define PXE_TYPES_H - -/** @file - * - * PXE data types - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <errno.h> /* PXE status codes */ - -/** @addtogroup pxe Preboot eXecution Environment (PXE) API - * @{ - */ - -/** @defgroup pxe_types PXE data types - * - * Basic PXE data types such as #UINT16_t, #ADDR32_t, #SEGSEL_t etc. - * - * These definitions are based on Table 1-1 ("Data Type Definitions") - * in the Intel PXE specification version 2.1. They have been - * generalised to non-x86 architectures where possible. - * - * @{ - */ - -/** An 8-bit unsigned integer */ -typedef uint8_t UINT8_t; - -/** A 16-bit unsigned integer */ -typedef uint16_t UINT16_t; - -/** A 32-bit unsigned integer */ -typedef uint32_t UINT32_t; - -/** A PXE exit code. - * - * Permitted values are #PXENV_EXIT_SUCCESS and #PXENV_EXIT_FAILURE. - * - */ -typedef UINT16_t PXENV_EXIT_t; -#define PXENV_EXIT_SUCCESS 0x0000 /**< No error occurred */ -#define PXENV_EXIT_FAILURE 0x0001 /**< An error occurred */ - -/** A PXE status code. - * - * Status codes are defined in errno.h. - * - */ -typedef UINT16_t PXENV_STATUS_t; - -/** An IPv4 address. - * - * @note This data type is in network (big-endian) byte order. - * - */ -typedef UINT32_t IP4_t; - -/** A UDP port. - * - * @note This data type is in network (big-endian) byte order. - * - */ -typedef UINT16_t UDP_PORT_t; - -/** Maximum length of a MAC address */ -#define MAC_ADDR_LEN 16 - -/** A MAC address */ -typedef UINT8_t MAC_ADDR_t[MAC_ADDR_LEN]; - -#ifndef HAVE_ARCH_ADDR32 -/** A physical address. - * - * For x86, this is a 32-bit physical address, and is therefore - * limited to the low 4GB. - * - */ -typedef UINT32_t ADDR32_t; -#endif - -#ifndef HAVE_ARCH_SEGSEL -/** A segment selector. - * - * For x86, this is a real mode segment (0x0000-0xffff), or a - * protected-mode segment selector, such as could be loaded into a - * segment register. - * - */ -typedef UINT16_t SEGSEL_t; -#endif - -#ifndef HAVE_ARCH_OFF16 -/** An offset within a segment identified by #SEGSEL - * - * For x86, this is a 16-bit offset. - * - */ -typedef UINT16_t OFF16_t; -#endif - -/** A segment:offset address - * - * For x86, this is a 16-bit real-mode or protected-mode - * segment:offset address. - * - */ -typedef struct s_SEGOFF16 { - OFF16_t offset; /**< Offset within the segment */ - SEGSEL_t segment; /**< Segment selector */ -} PACKED SEGOFF16_t; - -/** A segment descriptor */ -typedef struct s_SEGDESC { - SEGSEL_t segment_address; /**< Segment selector */ - ADDR32_t Physical_address; /**< Segment base address */ - OFF16_t Seg_size; /**< Size of the segment */ -} PACKED SEGDESC_t; - -/** @} */ /* pxe_types */ - -/** @} */ /* pxe */ - -#endif /* PXE_TYPES_H */ diff --git a/gpxe/src/arch/i386/include/pxeparent.h b/gpxe/src/arch/i386/include/pxeparent.h deleted file mode 100644 index b31e24a7..00000000 --- a/gpxe/src/arch/i386/include/pxeparent.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef PXEPARENT_H -#define PXEPARENT_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <pxe_types.h> - -extern int pxeparent_call ( SEGOFF16_t entry, unsigned int function, - void *params, size_t params_len ); - -#endif diff --git a/gpxe/src/arch/i386/include/realmode.h b/gpxe/src/arch/i386/include/realmode.h deleted file mode 100644 index a0a830b9..00000000 --- a/gpxe/src/arch/i386/include/realmode.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef REALMODE_H -#define REALMODE_H - -#include <stdint.h> -#include <registers.h> -#include <gpxe/uaccess.h> - -/* - * Data structures and type definitions - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * Declaration of variables in .data16 - * - * To place a variable in the .data16 segment, declare it using the - * pattern: - * - * int __data16 ( foo ); - * #define foo __use_data16 ( foo ); - * - * extern uint32_t __data16 ( bar ); - * #define bar __use_data16 ( bar ); - * - * static long __data16 ( baz ) = 0xff000000UL; - * #define baz __use_data16 ( baz ); - * - * i.e. take a normal declaration, add __data16() around the variable - * name, and add a line saying "#define <name> __use_data16 ( <name> ) - * - * You can then access them just like any other variable, for example - * - * int x = foo + bar; - * - * This magic is achieved at a cost of only around 7 extra bytes per - * group of accesses to .data16 variables. When using KEEP_IT_REAL, - * there is no extra cost. - * - * You should place variables in .data16 when they need to be accessed - * by real-mode code. Real-mode assembly (e.g. as created by - * REAL_CODE()) can access these variables via the usual data segment. - * You can therefore write something like - * - * static uint16_t __data16 ( foo ); - * #define foo __use_data16 ( foo ) - * - * int bar ( void ) { - * __asm__ __volatile__ ( REAL_CODE ( "int $0xff\n\t" - * "movw %ax, foo" ) - * : : ); - * return foo; - * } - * - * Variables may also be placed in .text16 using __text16 and - * __use_text16. Some variables (e.g. chained interrupt vectors) fit - * most naturally in .text16; most should be in .data16. - * - * If you have only a pointer to a magic symbol within .data16 or - * .text16, rather than the symbol itself, you can attempt to extract - * the underlying symbol name using __from_data16() or - * __from_text16(). This is not for the faint-hearted; check the - * assembler output to make sure that it's doing the right thing. - */ - -/** - * Copy data to base memory - * - * @v dest_seg Destination segment - * @v dest_off Destination offset - * @v src Source - * @v len Length - */ -static inline __always_inline void -copy_to_real ( unsigned int dest_seg, unsigned int dest_off, - void *src, size_t n ) { - copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n ); -} - -/** - * Copy data to base memory - * - * @v dest Destination - * @v src_seg Source segment - * @v src_off Source offset - * @v len Length - */ -static inline __always_inline void -copy_from_real ( void *dest, unsigned int src_seg, - unsigned int src_off, size_t n ) { - copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n ); -} - -/** - * Write a single variable to base memory - * - * @v var Variable to write - * @v dest_seg Destination segment - * @v dest_off Destination offset - */ -#define put_real( var, dest_seg, dest_off ) \ - copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) ) - -/** - * Read a single variable from base memory - * - * @v var Variable to read - * @v src_seg Source segment - * @v src_off Source offset - */ -#define get_real( var, src_seg, src_off ) \ - copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) ) - -/* - * REAL_CODE ( asm_code_str ) - * - * This can be used in inline assembly to create a fragment of code - * that will execute in real mode. For example: to write a character - * to the BIOS console using INT 10, you would do something like: - * - * __asm__ __volatile__ ( REAL_CODE ( "int $0x16" ) - * : "=a" ( character ) : "a" ( 0x0000 ) ); - * - */ - -#endif /* REALMODE_H */ diff --git a/gpxe/src/arch/i386/include/registers.h b/gpxe/src/arch/i386/include/registers.h deleted file mode 100644 index 2839e2bd..00000000 --- a/gpxe/src/arch/i386/include/registers.h +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef REGISTERS_H -#define REGISTERS_H - -/** @file - * - * i386 registers. - * - * This file defines data structures that allow easy access to i386 - * register dumps. - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> - -/** - * A 16-bit general register. - * - * This type encapsulates a 16-bit register such as %ax, %bx, %cx, - * %dx, %si, %di, %bp or %sp. - * - */ -typedef union { - struct { - union { - uint8_t l; - uint8_t byte; - }; - uint8_t h; - } PACKED; - uint16_t word; -} PACKED reg16_t; - -/** - * A 32-bit general register. - * - * This type encapsulates a 32-bit register such as %eax, %ebx, %ecx, - * %edx, %esi, %edi, %ebp or %esp. - * - */ -typedef union { - struct { - union { - uint8_t l; - uint8_t byte; - }; - uint8_t h; - } PACKED; - uint16_t word; - uint32_t dword; -} PACKED reg32_t; - -/** - * A 32-bit general register dump. - * - * This is the data structure that is created on the stack by the @c - * pushal instruction, and can be read back using the @c popal - * instruction. - * - */ -struct i386_regs { - union { - uint16_t di; - uint32_t edi; - }; - union { - uint16_t si; - uint32_t esi; - }; - union { - uint16_t bp; - uint32_t ebp; - }; - union { - uint16_t sp; - uint32_t esp; - }; - union { - struct { - uint8_t bl; - uint8_t bh; - } PACKED; - uint16_t bx; - uint32_t ebx; - }; - union { - struct { - uint8_t dl; - uint8_t dh; - } PACKED; - uint16_t dx; - uint32_t edx; - }; - union { - struct { - uint8_t cl; - uint8_t ch; - } PACKED; - uint16_t cx; - uint32_t ecx; - }; - union { - struct { - uint8_t al; - uint8_t ah; - } PACKED; - uint16_t ax; - uint32_t eax; - }; -} PACKED; - -/** - * A segment register dump. - * - * The i386 has no equivalent of the @c pushal or @c popal - * instructions for the segment registers. We adopt the convention of - * always using the sequences - * - * @code - * - * pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs - * - * @endcode - * - * and - * - * @code - * - * addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs - * - * @endcode - * - * This is the data structure that is created and read back by these - * instruction sequences. - * - */ -struct i386_seg_regs { - uint16_t cs; - uint16_t ss; - uint16_t ds; - uint16_t es; - uint16_t fs; - uint16_t gs; -} PACKED; - -/** - * A full register dump. - * - * This data structure is created by the instructions - * - * @code - * - * pushfl - * pushal - * pushw %gs ; pushw %fs ; pushw %es ; pushw %ds ; pushw %ss ; pushw %cs - * - * @endcode - * - * and can be read back using the instructions - * - * @code - * - * addw $4, %sp ; popw %ds ; popw %es ; popw %fs ; popw %gs - * popal - * popfl - * - * @endcode - * - * prot_call() and kir_call() create this data structure on the stack - * and pass in a pointer to this structure. - * - */ -struct i386_all_regs { - struct i386_seg_regs segs; - struct i386_regs regs; - uint32_t flags; -} PACKED; - -/* Flags */ -#define CF ( 1 << 0 ) -#define PF ( 1 << 2 ) -#define AF ( 1 << 4 ) -#define ZF ( 1 << 6 ) -#define SF ( 1 << 7 ) -#define OF ( 1 << 11 ) - -/* Segment:offset structure. Note that the order within the structure - * is offset:segment. - */ -struct segoff { - uint16_t offset; - uint16_t segment; -} PACKED; - -typedef struct segoff segoff_t; - -#endif /* REGISTERS_H */ diff --git a/gpxe/src/arch/i386/include/setjmp.h b/gpxe/src/arch/i386/include/setjmp.h deleted file mode 100644 index 5d3c11b6..00000000 --- a/gpxe/src/arch/i386/include/setjmp.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef ETHERBOOT_SETJMP_H -#define ETHERBOOT_SETJMP_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <realmode.h> - -/** A jump buffer */ -typedef struct { - uint32_t retaddr; - uint32_t ebx; - uint32_t esp; - uint32_t ebp; - uint32_t esi; - uint32_t edi; -} jmp_buf[1]; - -/** A real-mode-extended jump buffer */ -typedef struct { - jmp_buf env; - uint16_t rm_ss; - uint16_t rm_sp; -} rmjmp_buf[1]; - -extern int __asmcall setjmp ( jmp_buf env ); -extern void __asmcall longjmp ( jmp_buf env, int val ); - -#define rmsetjmp( _env ) ( { \ - (_env)->rm_ss = rm_ss; \ - (_env)->rm_sp = rm_sp; \ - setjmp ( (_env)->env ); } ) \ - -#define rmlongjmp( _env, _val ) do { \ - rm_ss = (_env)->rm_ss; \ - rm_sp = (_env)->rm_sp; \ - longjmp ( (_env)->env, (_val) ); \ - } while ( 0 ) - -#endif /* ETHERBOOT_SETJMP_H */ diff --git a/gpxe/src/arch/i386/include/undi.h b/gpxe/src/arch/i386/include/undi.h deleted file mode 100644 index de6925b6..00000000 --- a/gpxe/src/arch/i386/include/undi.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef _UNDI_H -#define _UNDI_H - -/** @file - * - * UNDI driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef ASSEMBLY - -#include <gpxe/device.h> -#include <pxe_types.h> - -/** An UNDI device - * - * This structure is used by assembly code as well as C; do not alter - * this structure without editing pxeprefix.S to match. - */ -struct undi_device { - /** PXENV+ structure address */ - SEGOFF16_t pxenv; - /** !PXE structure address */ - SEGOFF16_t ppxe; - /** Entry point */ - SEGOFF16_t entry; - /** Free base memory after load */ - UINT16_t fbms; - /** Free base memory prior to load */ - UINT16_t restore_fbms; - /** PCI bus:dev.fn, or @c UNDI_NO_PCI_BUSDEVFN */ - UINT16_t pci_busdevfn; - /** ISAPnP card select number, or @c UNDI_NO_ISAPNP_CSN */ - UINT16_t isapnp_csn; - /** ISAPnP read port, or @c UNDI_NO_ISAPNP_READ_PORT */ - UINT16_t isapnp_read_port; - /** PCI vendor ID - * - * Filled in only for the preloaded UNDI device by pxeprefix.S - */ - UINT16_t pci_vendor; - /** PCI device ID - * - * Filled in only for the preloaded UNDI device by pxeprefix.S - */ - UINT16_t pci_device; - /** Flags - * - * This is the bitwise OR of zero or more UNDI_FL_XXX - * constants. - */ - UINT16_t flags; - - /** Generic device */ - struct device dev; - /** Driver-private data - * - * Use undi_set_drvdata() and undi_get_drvdata() to access this - * field. - */ - void *priv; -} __attribute__ (( packed )); - -/** - * Set UNDI driver-private data - * - * @v undi UNDI device - * @v priv Private data - */ -static inline void undi_set_drvdata ( struct undi_device *undi, void *priv ) { - undi->priv = priv; -} - -/** - * Get UNDI driver-private data - * - * @v undi UNDI device - * @ret priv Private data - */ -static inline void * undi_get_drvdata ( struct undi_device *undi ) { - return undi->priv; -} - -#endif /* ASSEMBLY */ - -/** PCI bus:dev.fn field is invalid */ -#define UNDI_NO_PCI_BUSDEVFN 0xffff - -/** ISAPnP card select number field is invalid */ -#define UNDI_NO_ISAPNP_CSN 0xffff - -/** ISAPnP read port field is invalid */ -#define UNDI_NO_ISAPNP_READ_PORT 0xffff - -/** UNDI flag: START_UNDI has been called */ -#define UNDI_FL_STARTED 0x0001 - -/** UNDI flag: UNDI_STARTUP and UNDI_INITIALIZE have been called */ -#define UNDI_FL_INITIALIZED 0x0002 - -/** UNDI flag: keep stack resident */ -#define UNDI_FL_KEEP_ALL 0x0004 - -#endif /* _UNDI_H */ diff --git a/gpxe/src/arch/i386/include/undiload.h b/gpxe/src/arch/i386/include/undiload.h deleted file mode 100644 index 426830e8..00000000 --- a/gpxe/src/arch/i386/include/undiload.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _UNDILOAD_H -#define _UNDILOAD_H - -/** @file - * - * UNDI load/unload - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -struct undi_device; -struct undi_rom; - -extern int undi_load ( struct undi_device *undi, struct undi_rom *undirom ); -extern int undi_unload ( struct undi_device *undi ); - -/** - * Call UNDI loader to create a pixie - * - * @v undi UNDI device - * @v undirom UNDI ROM - * @v pci_busdevfn PCI bus:dev.fn - * @ret rc Return status code - */ -static inline int undi_load_pci ( struct undi_device *undi, - struct undi_rom *undirom, - unsigned int pci_busdevfn ) { - undi->pci_busdevfn = pci_busdevfn; - undi->isapnp_csn = UNDI_NO_ISAPNP_CSN; - undi->isapnp_read_port = UNDI_NO_ISAPNP_READ_PORT; - return undi_load ( undi, undirom ); -} - -#endif /* _UNDILOAD_H */ diff --git a/gpxe/src/arch/i386/include/undinet.h b/gpxe/src/arch/i386/include/undinet.h deleted file mode 100644 index c3c17c11..00000000 --- a/gpxe/src/arch/i386/include/undinet.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _UNDINET_H -#define _UNDINET_H - -/** @file - * - * UNDI network device driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -struct undi_device; - -extern int undinet_probe ( struct undi_device *undi ); -extern void undinet_remove ( struct undi_device *undi ); - -#endif /* _UNDINET_H */ diff --git a/gpxe/src/arch/i386/include/undipreload.h b/gpxe/src/arch/i386/include/undipreload.h deleted file mode 100644 index de9b8fb5..00000000 --- a/gpxe/src/arch/i386/include/undipreload.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _UNDIPRELOAD_H -#define _UNDIPRELOAD_H - -/** @file - * - * Preloaded UNDI stack - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <realmode.h> -#include <undi.h> - -extern struct undi_device __data16 ( preloaded_undi ); -#define preloaded_undi __use_data16 ( preloaded_undi ) - -#endif /* _UNDIPRELOAD_H */ diff --git a/gpxe/src/arch/i386/include/undirom.h b/gpxe/src/arch/i386/include/undirom.h deleted file mode 100644 index 86d7077b..00000000 --- a/gpxe/src/arch/i386/include/undirom.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _UNDIROM_H -#define _UNDIROM_H - -/** @file - * - * UNDI expansion ROMs - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <pxe_types.h> - -/** An UNDI PCI device ID */ -struct undi_pci_device_id { - /** PCI vendor ID */ - unsigned int vendor_id; - /** PCI device ID */ - unsigned int device_id; -}; - -/** An UNDI device ID */ -union undi_device_id { - /** PCI device ID */ - struct undi_pci_device_id pci; -}; - -/** An UNDI ROM */ -struct undi_rom { - /** List of UNDI ROMs */ - struct list_head list; - /** ROM segment address */ - unsigned int rom_segment; - /** UNDI loader entry point */ - SEGOFF16_t loader_entry; - /** Code segment size */ - size_t code_size; - /** Data segment size */ - size_t data_size; - /** Bus type - * - * Values are as used by @c PXENV_UNDI_GET_NIC_TYPE - */ - unsigned int bus_type; - /** Device ID */ - union undi_device_id bus_id; -}; - -extern struct undi_rom * undirom_find_pci ( unsigned int vendor_id, - unsigned int device_id, - unsigned int rombase ); - -#endif /* _UNDIROM_H */ diff --git a/gpxe/src/arch/i386/include/vga.h b/gpxe/src/arch/i386/include/vga.h deleted file mode 100644 index 01fc39d8..00000000 --- a/gpxe/src/arch/i386/include/vga.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * - * modified - * by Steve M. Gehlbach <steve@kesa.com> - * - * Originally from linux/drivers/video/vga16.c by - * Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> - * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> - * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm - * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> - * - */ - -#ifndef VGA_H_INCL -#define VGA_H_INCL 1 - -//#include <cpu/p5/io.h> - -#define u8 unsigned char -#define u16 unsigned short -#define u32 unsigned int -#define __u32 u32 - -#define VERROR -1 -#define CHAR_HEIGHT 16 -#define LINES 25 -#define COLS 80 - -// macros for writing to vga regs -#define write_crtc(data,addr) outb(addr,CRT_IC); outb(data,CRT_DC) -#define write_att(data,addr) inb(IS1_RC); inb(0x80); outb(addr,ATT_IW); inb(0x80); outb(data,ATT_IW); inb(0x80) -#define write_seq(data,addr) outb(addr,SEQ_I); outb(data,SEQ_D) -#define write_gra(data,addr) outb(addr,GRA_I); outb(data,GRA_D) -u8 read_seq_b(u16 addr); -u8 read_gra_b(u16 addr); -u8 read_crtc_b(u16 addr); -u8 read_att_b(u16 addr); - - -#ifdef VGA_HARDWARE_FIXUP -void vga_hardware_fixup(void); -#else -#define vga_hardware_fixup() do{} while(0) -#endif - -#define SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ -#define SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ -#define SYNC_EXT 4 /* external sync */ -#define SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ -#define SYNC_BROADCAST 16 /* broadcast video timings */ - /* vtotal = 144d/288n/576i => PAL */ - /* vtotal = 121d/242n/484i => NTSC */ - -#define SYNC_ON_GREEN 32 /* sync on green */ - -#define VMODE_NONINTERLACED 0 /* non interlaced */ -#define VMODE_INTERLACED 1 /* interlaced */ -#define VMODE_DOUBLE 2 /* double scan */ -#define VMODE_MASK 255 - -#define VMODE_YWRAP 256 /* ywrap instead of panning */ -#define VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ -#define VMODE_CONUPDATE 512 /* don't update x/yoffset */ - -/* VGA data register ports */ -#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ -#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ -#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ -#define GRA_D 0x3CF /* Graphics Controller Data Register */ -#define SEQ_D 0x3C5 /* Sequencer Data Register */ - -#define MIS_R 0x3CC // Misc Output Read Register -#define MIS_W 0x3C2 // Misc Output Write Register - -#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ -#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ -#define PEL_D 0x3C9 /* PEL Data Register */ -#define PEL_MSK 0x3C6 /* PEL mask register */ - -/* EGA-specific registers */ -#define GRA_E0 0x3CC /* Graphics enable processor 0 */ -#define GRA_E1 0x3CA /* Graphics enable processor 1 */ - - -/* VGA index register ports */ -#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ -#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ -#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ -#define GRA_I 0x3CE /* Graphics Controller Index */ -#define SEQ_I 0x3C4 /* Sequencer Index */ -#define PEL_IW 0x3C8 /* PEL Write Index */ -#define PEL_IR 0x3C7 /* PEL Read Index */ - -/* standard VGA indexes max counts */ -#define CRTC_C 25 /* 25 CRT Controller Registers sequentially set*/ - // the remainder are not in the par array -#define ATT_C 21 /* 21 Attribute Controller Registers */ -#define GRA_C 9 /* 9 Graphics Controller Registers */ -#define SEQ_C 5 /* 5 Sequencer Registers */ -#define MIS_C 1 /* 1 Misc Output Register */ - -#define CRTC_H_TOTAL 0 -#define CRTC_H_DISP 1 -#define CRTC_H_BLANK_START 2 -#define CRTC_H_BLANK_END 3 -#define CRTC_H_SYNC_START 4 -#define CRTC_H_SYNC_END 5 -#define CRTC_V_TOTAL 6 -#define CRTC_OVERFLOW 7 -#define CRTC_PRESET_ROW 8 -#define CRTC_MAX_SCAN 9 -#define CRTC_CURSOR_START 0x0A -#define CRTC_CURSOR_END 0x0B -#define CRTC_START_HI 0x0C -#define CRTC_START_LO 0x0D -#define CRTC_CURSOR_HI 0x0E -#define CRTC_CURSOR_LO 0x0F -#define CRTC_V_SYNC_START 0x10 -#define CRTC_V_SYNC_END 0x11 -#define CRTC_V_DISP_END 0x12 -#define CRTC_OFFSET 0x13 -#define CRTC_UNDERLINE 0x14 -#define CRTC_V_BLANK_START 0x15 -#define CRTC_V_BLANK_END 0x16 -#define CRTC_MODE 0x17 -#define CRTC_LINE_COMPARE 0x18 - -#define ATC_MODE 0x10 -#define ATC_OVERSCAN 0x11 -#define ATC_PLANE_ENABLE 0x12 -#define ATC_PEL 0x13 -#define ATC_COLOR_PAGE 0x14 - -#define SEQ_CLOCK_MODE 0x01 -#define SEQ_PLANE_WRITE 0x02 -#define SEQ_CHARACTER_MAP 0x03 -#define SEQ_MEMORY_MODE 0x04 - -#define GDC_SR_VALUE 0x00 -#define GDC_SR_ENABLE 0x01 -#define GDC_COMPARE_VALUE 0x02 -#define GDC_DATA_ROTATE 0x03 -#define GDC_PLANE_READ 0x04 -#define GDC_MODE 0x05 -#define GDC_MISC 0x06 -#define GDC_COMPARE_MASK 0x07 -#define GDC_BIT_MASK 0x08 - -// text attributes -#define VGA_ATTR_CLR_RED 0x4 -#define VGA_ATTR_CLR_GRN 0x2 -#define VGA_ATTR_CLR_BLU 0x1 -#define VGA_ATTR_CLR_YEL (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN) -#define VGA_ATTR_CLR_CYN (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) -#define VGA_ATTR_CLR_MAG (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED) -#define VGA_ATTR_CLR_BLK 0 -#define VGA_ATTR_CLR_WHT (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) -#define VGA_ATTR_BNK 0x80 -#define VGA_ATTR_ITN 0x08 - -/* - * vga register parameters - * these are copied to the - * registers. - * - */ -struct vga_par { - u8 crtc[CRTC_C]; - u8 atc[ATT_C]; - u8 gdc[GRA_C]; - u8 seq[SEQ_C]; - u8 misc; // the misc register, MIS_W - u8 vss; -}; - - -/* Interpretation of offset for color fields: All offsets are from the right, - * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you - * can use the offset as right argument to <<). A pixel afterwards is a bit - * stream and is written to video memory as that unmodified. This implies - * big-endian byte order if bits_per_pixel is greater than 8. - */ -struct fb_bitfield { - __u32 offset; /* beginning of bitfield */ - __u32 length; /* length of bitfield */ - __u32 msb_right; /* != 0 : Most significant bit is */ - /* right */ -}; - -struct screeninfo { - __u32 xres; /* visible resolution */ - __u32 yres; - __u32 xres_virtual; /* virtual resolution */ - __u32 yres_virtual; - __u32 xoffset; /* offset from virtual to visible */ - __u32 yoffset; /* resolution */ - - __u32 bits_per_pixel; /* guess what */ - __u32 grayscale; /* != 0 Graylevels instead of colors */ - - struct fb_bitfield red; /* bitfield in fb mem if true color, */ - struct fb_bitfield green; /* else only length is significant */ - struct fb_bitfield blue; - struct fb_bitfield transp; /* transparency */ - - __u32 nonstd; /* != 0 Non standard pixel format */ - - __u32 activate; /* see FB_ACTIVATE_* */ - - __u32 height; /* height of picture in mm */ - __u32 width; /* width of picture in mm */ - - __u32 accel_flags; /* acceleration flags (hints) */ - - /* Timing: All values in pixclocks, except pixclock (of course) */ - __u32 pixclock; /* pixel clock in ps (pico seconds) */ - __u32 left_margin; /* time from sync to picture */ - __u32 right_margin; /* time from picture to sync */ - __u32 upper_margin; /* time from sync to picture */ - __u32 lower_margin; - __u32 hsync_len; /* length of horizontal sync */ - __u32 vsync_len; /* length of vertical sync */ - __u32 sync; /* sync polarity */ - __u32 vmode; /* interlaced etc */ - __u32 reserved[6]; /* Reserved for future compatibility */ -}; - -#endif diff --git a/gpxe/src/arch/i386/interface/pcbios/abft.c b/gpxe/src/arch/i386/interface/pcbios/abft.c deleted file mode 100644 index 86941728..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/abft.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <realmode.h> -#include <gpxe/aoe.h> -#include <gpxe/netdevice.h> -#include <gpxe/abft.h> - -/** @file - * - * AoE Boot Firmware Table - * - */ - -#define abftab __use_data16 ( abftab ) -/** The aBFT used by gPXE */ -struct abft_table __data16 ( abftab ) __attribute__ (( aligned ( 16 ) )) = { - /* ACPI header */ - .acpi = { - .signature = ABFT_SIG, - .length = sizeof ( abftab ), - .revision = 1, - .oem_id = "FENSYS", - .oem_table_id = "gPXE", - }, -}; - -/** - * Fill in all variable portions of aBFT - * - * @v aoe AoE session - */ -void abft_fill_data ( struct aoe_session *aoe ) { - - /* Fill in boot parameters */ - abftab.shelf = aoe->major; - abftab.slot = aoe->minor; - memcpy ( abftab.mac, aoe->netdev->ll_addr, sizeof ( abftab.mac ) ); - - /* Update checksum */ - acpi_fix_checksum ( &abftab.acpi ); - - DBG ( "AoE boot firmware table:\n" ); - DBG_HD ( &abftab, sizeof ( abftab ) ); -} diff --git a/gpxe/src/arch/i386/interface/pcbios/aoeboot.c b/gpxe/src/arch/i386/interface/pcbios/aoeboot.c deleted file mode 100644 index 2670b15d..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/aoeboot.c +++ /dev/null @@ -1,78 +0,0 @@ -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <gpxe/aoe.h> -#include <gpxe/ata.h> -#include <gpxe/netdevice.h> -#include <gpxe/sanboot.h> -#include <gpxe/abft.h> -#include <int13.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -static int aoeboot ( const char *root_path ) { - struct ata_device *ata; - struct int13_drive *drive; - int rc; - - ata = zalloc ( sizeof ( *ata ) ); - if ( ! ata ) { - rc = -ENOMEM; - goto err_alloc_ata; - } - drive = zalloc ( sizeof ( *drive ) ); - if ( ! drive ) { - rc = -ENOMEM; - goto err_alloc_drive; - } - - /* FIXME: ugly, ugly hack */ - struct net_device *netdev = last_opened_netdev(); - - if ( ( rc = aoe_attach ( ata, netdev, root_path ) ) != 0 ) { - printf ( "Could not attach AoE device: %s\n", - strerror ( rc ) ); - goto err_attach; - } - if ( ( rc = init_atadev ( ata ) ) != 0 ) { - printf ( "Could not initialise AoE device: %s\n", - strerror ( rc ) ); - goto err_init; - } - - /* FIXME: ugly, ugly hack */ - struct aoe_session *aoe = - container_of ( ata->backend, struct aoe_session, refcnt ); - abft_fill_data ( aoe ); - - drive->blockdev = &ata->blockdev; - - register_int13_drive ( drive ); - printf ( "Registered as BIOS drive %#02x\n", drive->drive ); - printf ( "Booting from BIOS drive %#02x\n", drive->drive ); - rc = int13_boot ( drive->drive ); - printf ( "Boot failed\n" ); - - /* Leave drive registered, if instructed to do so */ - if ( keep_san() ) - return rc; - - printf ( "Unregistering BIOS drive %#02x\n", drive->drive ); - unregister_int13_drive ( drive ); - - err_init: - aoe_detach ( ata ); - err_attach: - free ( drive ); - err_alloc_drive: - free ( ata ); - err_alloc_ata: - return rc; -} - -struct sanboot_protocol aoe_sanboot_protocol __sanboot_protocol = { - .prefix = "aoe:", - .boot = aoeboot, -}; diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_nap.c b/gpxe/src/arch/i386/interface/pcbios/bios_nap.c deleted file mode 100644 index e38cac7a..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/bios_nap.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <gpxe/nap.h> -#include <realmode.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * Save power by halting the CPU until the next interrupt - * - */ -static void bios_cpu_nap ( void ) { - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - "hlt\n\t" - "cli\n\t" ) : : ); -} - -PROVIDE_NAP ( pcbios, cpu_nap, bios_cpu_nap ); diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c b/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c deleted file mode 100644 index 094214bd..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <gpxe/uaccess.h> -#include <gpxe/smbios.h> -#include <realmode.h> -#include <pnpbios.h> - -/** @file - * - * System Management BIOS - * - */ - -/** - * Find SMBIOS - * - * @v smbios SMBIOS entry point descriptor structure to fill in - * @ret rc Return status code - */ -static int bios_find_smbios ( struct smbios *smbios ) { - union { - struct smbios_entry entry; - uint8_t bytes[256]; /* 256 is maximum length possible */ - } u; - static unsigned int offset = 0; - size_t len; - unsigned int i; - uint8_t sum; - - /* Try to find SMBIOS */ - for ( ; offset < 0x10000 ; offset += 0x10 ) { - - /* Read start of header and verify signature */ - copy_from_real ( &u.entry, BIOS_SEG, offset, - sizeof ( u.entry )); - if ( u.entry.signature != SMBIOS_SIGNATURE ) - continue; - - /* Read whole header and verify checksum */ - len = u.entry.len; - copy_from_real ( &u.bytes, BIOS_SEG, offset, len ); - for ( i = 0 , sum = 0 ; i < len ; i++ ) { - sum += u.bytes[i]; - } - if ( sum != 0 ) { - DBG ( "SMBIOS at %04x:%04x has bad checksum %02x\n", - BIOS_SEG, offset, sum ); - continue; - } - - /* Fill result structure */ - DBG ( "Found SMBIOS v%d.%d entry point at %04x:%04x\n", - u.entry.major, u.entry.minor, BIOS_SEG, offset ); - smbios->address = phys_to_user ( u.entry.smbios_address ); - smbios->len = u.entry.smbios_len; - smbios->count = u.entry.smbios_count; - return 0; - } - - DBG ( "No SMBIOS found\n" ); - return -ENODEV; -} - -PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios ); diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_timer.c b/gpxe/src/arch/i386/interface/pcbios/bios_timer.c deleted file mode 100644 index 8ecf7c12..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/bios_timer.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** @file - * - * BIOS timer - * - */ - -#include <gpxe/timer.h> -#include <realmode.h> -#include <bios.h> - -/** - * Get current system time in ticks - * - * @ret ticks Current time, in ticks - * - * Use direct memory access to BIOS variables, longword 0040:006C - * (ticks today) and byte 0040:0070 (midnight crossover flag) instead - * of calling timeofday BIOS interrupt. - */ -static unsigned long bios_currticks ( void ) { - static int days = 0; - uint32_t ticks; - uint8_t midnight; - - /* Re-enable interrupts so that the timer interrupt can occur */ - __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" - "nop\n\t" - "nop\n\t" - "cli\n\t" ) : : ); - - get_real ( ticks, BDA_SEG, 0x006c ); - get_real ( midnight, BDA_SEG, 0x0070 ); - - if ( midnight ) { - midnight = 0; - put_real ( midnight, BDA_SEG, 0x0070 ); - days += 0x1800b0; - } - - return ( days + ticks ); -} - -PROVIDE_TIMER_INLINE ( pcbios, udelay ); -PROVIDE_TIMER ( pcbios, currticks, bios_currticks ); -PROVIDE_TIMER_INLINE ( pcbios, ticks_per_sec ); diff --git a/gpxe/src/arch/i386/interface/pcbios/biosint.c b/gpxe/src/arch/i386/interface/pcbios/biosint.c deleted file mode 100644 index a193defa..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/biosint.c +++ /dev/null @@ -1,92 +0,0 @@ -#include <errno.h> -#include <realmode.h> -#include <biosint.h> - -/** - * @file BIOS interrupts - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * Hook INT vector - * - * @v interrupt INT number - * @v handler Offset within .text16 to interrupt handler - * @v chain_vector Vector for chaining to previous handler - * - * Hooks in an i386 INT handler. The handler itself must reside - * within the .text16 segment. @c chain_vector will be filled in with - * the address of the previously-installed handler for this interrupt; - * the handler should probably exit by ljmping via this vector. - */ -void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler, - struct segoff *chain_vector ) { - struct segoff vector = { - .segment = rm_cs, - .offset = handler, - }; - - DBG ( "Hooking INT %#02x to %04x:%04x\n", - interrupt, rm_cs, handler ); - - if ( ( chain_vector->segment != 0 ) || - ( chain_vector->offset != 0 ) ) { - /* Already hooked; do nothing */ - DBG ( "...already hooked\n" ); - return; - } - - copy_from_real ( chain_vector, 0, ( interrupt * 4 ), - sizeof ( *chain_vector ) ); - DBG ( "...chaining to %04x:%04x\n", - chain_vector->segment, chain_vector->offset ); - if ( DBG_LOG ) { - char code[64]; - copy_from_real ( code, chain_vector->segment, - chain_vector->offset, sizeof ( code ) ); - DBG_HDA ( *chain_vector, code, sizeof ( code ) ); - } - - copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) ); - hooked_bios_interrupts++; -} - -/** - * Unhook INT vector - * - * @v interrupt INT number - * @v handler Offset within .text16 to interrupt handler - * @v chain_vector Vector containing address of previous handler - * - * Unhooks an i386 interrupt handler hooked by hook_i386_vector(). - * Note that this operation may fail, if some external code has hooked - * the vector since we hooked in our handler. If it fails, it means - * that it is not possible to unhook our handler, and we must leave it - * (and its chaining vector) resident in memory. - */ -int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler, - struct segoff *chain_vector ) { - struct segoff vector; - - DBG ( "Unhooking INT %#02x from %04x:%04x\n", - interrupt, rm_cs, handler ); - - copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) ); - if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) ) { - DBG ( "...cannot unhook; vector points to %04x:%04x\n", - vector.segment, vector.offset ); - return -EBUSY; - } - - DBG ( "...restoring to %04x:%04x\n", - chain_vector->segment, chain_vector->offset ); - copy_to_real ( 0, ( interrupt * 4 ), chain_vector, - sizeof ( *chain_vector ) ); - - chain_vector->segment = 0; - chain_vector->offset = 0; - hooked_bios_interrupts--; - return 0; -} diff --git a/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c b/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c deleted file mode 100644 index b1cbc337..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c +++ /dev/null @@ -1,73 +0,0 @@ -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <gpxe/sanboot.h> -#include <int13.h> -#include <gpxe/srp.h> -#include <gpxe/sbft.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -static int ib_srpboot ( const char *root_path ) { - struct scsi_device *scsi; - struct int13_drive *drive; - int rc; - - scsi = zalloc ( sizeof ( *scsi ) ); - if ( ! scsi ) { - rc = -ENOMEM; - goto err_alloc_scsi; - } - drive = zalloc ( sizeof ( *drive ) ); - if ( ! drive ) { - rc = -ENOMEM; - goto err_alloc_drive; - } - - if ( ( rc = srp_attach ( scsi, root_path ) ) != 0 ) { - printf ( "Could not attach IB_SRP device: %s\n", - strerror ( rc ) ); - goto err_attach; - } - if ( ( rc = init_scsidev ( scsi ) ) != 0 ) { - printf ( "Could not initialise IB_SRP device: %s\n", - strerror ( rc ) ); - goto err_init; - } - - drive->blockdev = &scsi->blockdev; - - /* FIXME: ugly, ugly hack */ - struct srp_device *srp = - container_of ( scsi->backend, struct srp_device, refcnt ); - sbft_fill_data ( srp ); - - register_int13_drive ( drive ); - printf ( "Registered as BIOS drive %#02x\n", drive->drive ); - printf ( "Booting from BIOS drive %#02x\n", drive->drive ); - rc = int13_boot ( drive->drive ); - printf ( "Boot failed\n" ); - - /* Leave drive registered, if instructed to do so */ - if ( keep_san() ) - return rc; - - printf ( "Unregistering BIOS drive %#02x\n", drive->drive ); - unregister_int13_drive ( drive ); - - err_init: - srp_detach ( scsi ); - err_attach: - free ( drive ); - err_alloc_drive: - free ( scsi ); - err_alloc_scsi: - return rc; -} - -struct sanboot_protocol ib_srp_sanboot_protocol __sanboot_protocol = { - .prefix = "ib_srp:", - .boot = ib_srpboot, -}; diff --git a/gpxe/src/arch/i386/interface/pcbios/ibft.c b/gpxe/src/arch/i386/interface/pcbios/ibft.c deleted file mode 100644 index adf8e6b9..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/ibft.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright Fen Systems Ltd. 2007. Portions of this code are derived - * from IBM Corporation Sample Programs. Copyright IBM Corporation - * 2004, 2007. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -FILE_LICENCE ( BSD2 ); - -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <byteswap.h> -#include <realmode.h> -#include <gpxe/pci.h> -#include <gpxe/acpi.h> -#include <gpxe/in.h> -#include <gpxe/netdevice.h> -#include <gpxe/ethernet.h> -#include <gpxe/dhcp.h> -#include <gpxe/iscsi.h> -#include <gpxe/ibft.h> - -/** @file - * - * iSCSI boot firmware table - * - * The information in this file is derived from the document "iSCSI - * Boot Firmware Table (iBFT)" as published by IBM at - * - * ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf - * - */ - -#define ibftab __use_data16 ( ibftab ) -/** The iBFT used by gPXE */ -struct gpxe_ibft __data16 ( ibftab ) = { - /* Table header */ - .table = { - /* ACPI header */ - .acpi = { - .signature = IBFT_SIG, - .length = sizeof ( ibftab ), - .revision = 1, - .oem_id = "FENSYS", - .oem_table_id = "gPXE", - }, - /* Control block */ - .control = { - .header = { - .structure_id = IBFT_STRUCTURE_ID_CONTROL, - .version = 1, - .length = sizeof ( ibftab.table.control ), - .flags = 0, - }, - .initiator = offsetof ( typeof ( ibftab ), initiator ), - .nic_0 = offsetof ( typeof ( ibftab ), nic ), - .target_0 = offsetof ( typeof ( ibftab ), target ), - }, - }, - /* iSCSI initiator information */ - .initiator = { - .header = { - .structure_id = IBFT_STRUCTURE_ID_INITIATOR, - .version = 1, - .length = sizeof ( ibftab.initiator ), - .flags = ( IBFT_FL_INITIATOR_BLOCK_VALID | - IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED ), - }, - }, - /* NIC information */ - .nic = { - .header = { - .structure_id = IBFT_STRUCTURE_ID_NIC, - .version = 1, - .length = sizeof ( ibftab.nic ), - .flags = ( IBFT_FL_NIC_BLOCK_VALID | - IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED ), - }, - }, - /* iSCSI target information */ - .target = { - .header = { - .structure_id = IBFT_STRUCTURE_ID_TARGET, - .version = 1, - .length = sizeof ( ibftab.target ), - .flags = ( IBFT_FL_TARGET_BLOCK_VALID | - IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED ), - }, - }, -}; - -/** - * Fill in an IP address field within iBFT - * - * @v ipaddr IP address field - * @v in IPv4 address - */ -static void ibft_set_ipaddr ( struct ibft_ipaddr *ipaddr, struct in_addr in ) { - memset ( ipaddr, 0, sizeof ( ipaddr ) ); - if ( in.s_addr ) { - ipaddr->in = in; - ipaddr->ones = 0xffff; - } -} - -/** - * Fill in an IP address within iBFT from configuration setting - * - * @v ipaddr IP address field - * @v setting Configuration setting - * @v tag DHCP option tag - */ -static void ibft_set_ipaddr_option ( struct ibft_ipaddr *ipaddr, - struct setting *setting ) { - struct in_addr in = { 0 }; - fetch_ipv4_setting ( NULL, setting, &in ); - ibft_set_ipaddr ( ipaddr, in ); -} - -/** - * Read IP address from iBFT (for debugging) - * - * @v strings iBFT string block descriptor - * @v string String field - * @ret ipaddr IP address string - */ -static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) { - return inet_ntoa ( ipaddr->in ); -} - -/** - * Allocate a string within iBFT - * - * @v strings iBFT string block descriptor - * @v string String field to fill in - * @v len Length of string to allocate (excluding NUL) - * @ret rc Return status code - */ -static int ibft_alloc_string ( struct ibft_string_block *strings, - struct ibft_string *string, size_t len ) { - char *dest; - unsigned int remaining; - - dest = ( ( ( char * ) strings->table ) + strings->offset ); - remaining = ( strings->table->acpi.length - strings->offset ); - if ( len >= remaining ) - return -ENOMEM; - - string->offset = strings->offset; - string->length = len; - strings->offset += ( len + 1 ); - return 0; -} - -/** - * Fill in a string field within iBFT - * - * @v strings iBFT string block descriptor - * @v string String field - * @v data String to fill in, or NULL - * @ret rc Return status code - */ -static int ibft_set_string ( struct ibft_string_block *strings, - struct ibft_string *string, const char *data ) { - char *dest; - int rc; - - if ( ! data ) - return 0; - - if ( ( rc = ibft_alloc_string ( strings, string, - strlen ( data ) ) ) != 0 ) - return rc; - dest = ( ( ( char * ) strings->table ) + string->offset ); - strcpy ( dest, data ); - - return 0; -} - -/** - * Fill in a string field within iBFT from configuration setting - * - * @v strings iBFT string block descriptor - * @v string String field - * @v setting Configuration setting - * @ret rc Return status code - */ -static int ibft_set_string_option ( struct ibft_string_block *strings, - struct ibft_string *string, - struct setting *setting ) { - int len; - char *dest; - int rc; - - len = fetch_setting_len ( NULL, setting ); - if ( len < 0 ) { - string->offset = 0; - string->length = 0; - return 0; - } - - if ( ( rc = ibft_alloc_string ( strings, string, len ) ) != 0 ) - return rc; - dest = ( ( ( char * ) strings->table ) + string->offset ); - fetch_string_setting ( NULL, setting, dest, ( len + 1 ) ); - return 0; -} - -/** - * Read string from iBFT (for debugging) - * - * @v strings iBFT string block descriptor - * @v string String field - * @ret data String content (or "<empty>") - */ -static const char * ibft_string ( struct ibft_string_block *strings, - struct ibft_string *string ) { - return ( string->offset ? - ( ( ( char * ) strings->table ) + string->offset ) : NULL ); -} - -/** - * Fill in NIC portion of iBFT - * - * @v nic NIC portion of iBFT - * @v strings iBFT string block descriptor - * @v netdev Network device - * @ret rc Return status code - */ -static int ibft_fill_nic ( struct ibft_nic *nic, - struct ibft_string_block *strings, - struct net_device *netdev ) { - struct ll_protocol *ll_protocol = netdev->ll_protocol; - struct in_addr netmask_addr = { 0 }; - unsigned int netmask_count = 0; - int rc; - - /* Extract values from DHCP configuration */ - ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting ); - DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) ); - ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting ); - DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) ); - ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting ); - DBG ( "iBFT NIC DNS = %s\n", ibft_ipaddr ( &nic->dns[0] ) ); - if ( ( rc = ibft_set_string_option ( strings, &nic->hostname, - &hostname_setting ) ) != 0 ) - return rc; - DBG ( "iBFT NIC hostname = %s\n", - ibft_string ( strings, &nic->hostname ) ); - - /* Derive subnet mask prefix from subnet mask */ - fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr ); - while ( netmask_addr.s_addr ) { - if ( netmask_addr.s_addr & 0x1 ) - netmask_count++; - netmask_addr.s_addr >>= 1; - } - nic->subnet_mask_prefix = netmask_count; - DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix ); - - /* Extract values from net-device configuration */ - if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr, - nic->mac_address ) ) != 0 ) { - DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) ); - return rc; - } - DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) ); - nic->pci_bus_dev_func = netdev->dev->desc.location; - DBG ( "iBFT NIC PCI = %04x\n", nic->pci_bus_dev_func ); - - return 0; -} - -/** - * Fill in Initiator portion of iBFT - * - * @v initiator Initiator portion of iBFT - * @v strings iBFT string block descriptor - * @ret rc Return status code - */ -static int ibft_fill_initiator ( struct ibft_initiator *initiator, - struct ibft_string_block *strings ) { - const char *initiator_iqn = iscsi_initiator_iqn(); - int rc; - - if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name, - initiator_iqn ) ) != 0 ) - return rc; - DBG ( "iBFT initiator hostname = %s\n", - ibft_string ( strings, &initiator->initiator_name ) ); - - return 0; -} - -/** - * Fill in Target CHAP portion of iBFT - * - * @v target Target portion of iBFT - * @v strings iBFT string block descriptor - * @v iscsi iSCSI session - * @ret rc Return status code - */ -static int ibft_fill_target_chap ( struct ibft_target *target, - struct ibft_string_block *strings, - struct iscsi_session *iscsi ) { - int rc; - - if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) ) - return 0; - - assert ( iscsi->initiator_username ); - assert ( iscsi->initiator_password ); - - target->chap_type = IBFT_CHAP_ONE_WAY; - if ( ( rc = ibft_set_string ( strings, &target->chap_name, - iscsi->initiator_username ) ) != 0 ) - return rc; - DBG ( "iBFT target username = %s\n", - ibft_string ( strings, &target->chap_name ) ); - if ( ( rc = ibft_set_string ( strings, &target->chap_secret, - iscsi->initiator_password ) ) != 0 ) - return rc; - DBG ( "iBFT target password = <redacted>\n" ); - - return 0; -} - -/** - * Fill in Target Reverse CHAP portion of iBFT - * - * @v target Target portion of iBFT - * @v strings iBFT string block descriptor - * @v iscsi iSCSI session - * @ret rc Return status code - */ -static int ibft_fill_target_reverse_chap ( struct ibft_target *target, - struct ibft_string_block *strings, - struct iscsi_session *iscsi ) { - int rc; - - if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) ) - return 0; - - assert ( iscsi->initiator_username ); - assert ( iscsi->initiator_password ); - assert ( iscsi->target_username ); - assert ( iscsi->target_password ); - - target->chap_type = IBFT_CHAP_MUTUAL; - if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name, - iscsi->target_username ) ) != 0 ) - return rc; - DBG ( "iBFT target reverse username = %s\n", - ibft_string ( strings, &target->chap_name ) ); - if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret, - iscsi->target_password ) ) != 0 ) - return rc; - DBG ( "iBFT target reverse password = <redacted>\n" ); - - return 0; -} - -/** - * Fill in Target portion of iBFT - * - * @v target Target portion of iBFT - * @v strings iBFT string block descriptor - * @v iscsi iSCSI session - * @ret rc Return status code - */ -static int ibft_fill_target ( struct ibft_target *target, - struct ibft_string_block *strings, - struct iscsi_session *iscsi ) { - struct sockaddr_in *sin_target = - ( struct sockaddr_in * ) &iscsi->target_sockaddr; - int rc; - - /* Fill in Target values */ - ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr ); - DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) ); - target->socket = ntohs ( sin_target->sin_port ); - DBG ( "iBFT target port = %d\n", target->socket ); - if ( ( rc = ibft_set_string ( strings, &target->target_name, - iscsi->target_iqn ) ) != 0 ) - return rc; - DBG ( "iBFT target name = %s\n", - ibft_string ( strings, &target->target_name ) ); - if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 ) - return rc; - if ( ( rc = ibft_fill_target_reverse_chap ( target, strings, - iscsi ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Fill in all variable portions of iBFT - * - * @v netdev Network device - * @v initiator_iqn Initiator IQN - * @v st_target Target socket address - * @v target_iqn Target IQN - * @ret rc Return status code - * - */ -int ibft_fill_data ( struct net_device *netdev, - struct iscsi_session *iscsi ) { - struct ibft_string_block strings = { - .table = &ibftab.table, - .offset = offsetof ( typeof ( ibftab ), strings ), - }; - int rc; - - /* Fill in NIC, Initiator and Target portions */ - if ( ( rc = ibft_fill_nic ( &ibftab.nic, &strings, netdev ) ) != 0 ) - return rc; - if ( ( rc = ibft_fill_initiator ( &ibftab.initiator, - &strings ) ) != 0 ) - return rc; - if ( ( rc = ibft_fill_target ( &ibftab.target, &strings, - iscsi ) ) != 0 ) - return rc; - - /* Update checksum */ - acpi_fix_checksum ( &ibftab.table.acpi ); - - return 0; -} diff --git a/gpxe/src/arch/i386/interface/pcbios/int13.c b/gpxe/src/arch/i386/interface/pcbios/int13.c deleted file mode 100644 index 87b613a8..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/int13.c +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <limits.h> -#include <byteswap.h> -#include <errno.h> -#include <assert.h> -#include <gpxe/list.h> -#include <gpxe/blockdev.h> -#include <gpxe/memmap.h> -#include <realmode.h> -#include <bios.h> -#include <biosint.h> -#include <bootsector.h> -#include <int13.h> - -/** @file - * - * INT 13 emulation - * - * This module provides a mechanism for exporting block devices via - * the BIOS INT 13 disk interrupt interface. - * - */ - -/** Vector for chaining to other INT 13 handlers */ -static struct segoff __text16 ( int13_vector ); -#define int13_vector __use_text16 ( int13_vector ) - -/** Assembly wrapper */ -extern void int13_wrapper ( void ); - -/** List of registered emulated drives */ -static LIST_HEAD ( drives ); - -/** - * Number of BIOS drives - * - * Note that this is the number of drives in the system as a whole - * (i.e. a mirror of the counter at 40:75), rather than a count of the - * number of emulated drives. - */ -static uint8_t num_drives; - -/** - * Update BIOS drive count - */ -static void int13_set_num_drives ( void ) { - struct int13_drive *drive; - - /* Get current drive count */ - get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES ); - - /* Ensure count is large enough to cover all of our emulated drives */ - list_for_each_entry ( drive, &drives, list ) { - if ( num_drives <= ( drive->drive & 0x7f ) ) - num_drives = ( ( drive->drive & 0x7f ) + 1 ); - } - - /* Update current drive count */ - put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES ); -} - -/** - * Check number of drives - */ -static void int13_check_num_drives ( void ) { - uint8_t check_num_drives; - - get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES ); - if ( check_num_drives != num_drives ) { - int13_set_num_drives(); - DBG ( "INT13 fixing up number of drives from %d to %d\n", - check_num_drives, num_drives ); - } -} - -/** - * INT 13, 00 - Reset disk system - * - * @v drive Emulated drive - * @ret status Status code - */ -static int int13_reset ( struct int13_drive *drive __unused, - struct i386_all_regs *ix86 __unused ) { - DBG ( "Reset drive\n" ); - return 0; -} - -/** - * INT 13, 01 - Get status of last operation - * - * @v drive Emulated drive - * @ret status Status code - */ -static int int13_get_last_status ( struct int13_drive *drive, - struct i386_all_regs *ix86 __unused ) { - DBG ( "Get status of last operation\n" ); - return drive->last_status; -} - -/** - * Read / write sectors - * - * @v drive Emulated drive - * @v al Number of sectors to read or write (must be nonzero) - * @v ch Low bits of cylinder number - * @v cl (bits 7:6) High bits of cylinder number - * @v cl (bits 5:0) Sector number - * @v dh Head number - * @v es:bx Data buffer - * @v io Read / write method - * @ret status Status code - * @ret al Number of sectors read or written - */ -static int int13_rw_sectors ( struct int13_drive *drive, - struct i386_all_regs *ix86, - int ( * io ) ( struct block_device *blockdev, - uint64_t block, - unsigned long count, - userptr_t buffer ) ) { - struct block_device *blockdev = drive->blockdev; - unsigned int cylinder, head, sector; - unsigned long lba; - unsigned int count; - userptr_t buffer; - int rc; - - /* Validate blocksize */ - if ( blockdev->blksize != INT13_BLKSIZE ) { - DBG ( "Invalid blocksize (%zd) for non-extended read/write\n", - blockdev->blksize ); - return -INT13_STATUS_INVALID; - } - - /* Calculate parameters */ - cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch ); - assert ( cylinder < drive->cylinders ); - head = ix86->regs.dh; - assert ( head < drive->heads ); - sector = ( ix86->regs.cl & 0x3f ); - assert ( ( sector >= 1 ) && ( sector <= drive->sectors_per_track ) ); - lba = ( ( ( ( cylinder * drive->heads ) + head ) - * drive->sectors_per_track ) + sector - 1 ); - count = ix86->regs.al; - buffer = real_to_user ( ix86->segs.es, ix86->regs.bx ); - - DBG ( "C/H/S %d/%d/%d = LBA %#lx <-> %04x:%04x (count %d)\n", cylinder, - head, sector, lba, ix86->segs.es, ix86->regs.bx, count ); - - /* Read from / write to block device */ - if ( ( rc = io ( blockdev, lba, count, buffer ) ) != 0 ) { - DBG ( "INT 13 failed: %s\n", strerror ( rc ) ); - return -INT13_STATUS_READ_ERROR; - } - - return 0; -} - -/** - * INT 13, 02 - Read sectors - * - * @v drive Emulated drive - * @v al Number of sectors to read (must be nonzero) - * @v ch Low bits of cylinder number - * @v cl (bits 7:6) High bits of cylinder number - * @v cl (bits 5:0) Sector number - * @v dh Head number - * @v es:bx Data buffer - * @ret status Status code - * @ret al Number of sectors read - */ -static int int13_read_sectors ( struct int13_drive *drive, - struct i386_all_regs *ix86 ) { - DBG ( "Read: " ); - return int13_rw_sectors ( drive, ix86, drive->blockdev->op->read ); -} - -/** - * INT 13, 03 - Write sectors - * - * @v drive Emulated drive - * @v al Number of sectors to write (must be nonzero) - * @v ch Low bits of cylinder number - * @v cl (bits 7:6) High bits of cylinder number - * @v cl (bits 5:0) Sector number - * @v dh Head number - * @v es:bx Data buffer - * @ret status Status code - * @ret al Number of sectors written - */ -static int int13_write_sectors ( struct int13_drive *drive, - struct i386_all_regs *ix86 ) { - DBG ( "Write: " ); - return int13_rw_sectors ( drive, ix86, drive->blockdev->op->write ); -} - -/** - * INT 13, 08 - Get drive parameters - * - * @v drive Emulated drive - * @ret status Status code - * @ret ch Low bits of maximum cylinder number - * @ret cl (bits 7:6) High bits of maximum cylinder number - * @ret cl (bits 5:0) Maximum sector number - * @ret dh Maximum head number - * @ret dl Number of drives - */ -static int int13_get_parameters ( struct int13_drive *drive, - struct i386_all_regs *ix86 ) { - unsigned int max_cylinder = drive->cylinders - 1; - unsigned int max_head = drive->heads - 1; - unsigned int max_sector = drive->sectors_per_track; /* sic */ - - DBG ( "Get drive parameters\n" ); - - ix86->regs.ch = ( max_cylinder & 0xff ); - ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector ); - ix86->regs.dh = max_head; - get_real ( ix86->regs.dl, BDA_SEG, BDA_NUM_DRIVES ); - return 0; -} - -/** - * INT 13, 15 - Get disk type - * - * @v drive Emulated drive - * @ret ah Type code - * @ret cx:dx Sector count - * @ret status Status code / disk type - */ -static int int13_get_disk_type ( struct int13_drive *drive, - struct i386_all_regs *ix86 ) { - uint32_t blocks; - - DBG ( "Get disk type\n" ); - blocks = ( ( drive->blockdev->blocks <= 0xffffffffUL ) ? - drive->blockdev->blocks : 0xffffffffUL ); - ix86->regs.cx = ( blocks >> 16 ); - ix86->regs.dx = ( blocks & 0xffff ); - return INT13_DISK_TYPE_HDD; -} - -/** - * INT 13, 41 - Extensions installation check - * - * @v drive Emulated drive - * @v bx 0x55aa - * @ret bx 0xaa55 - * @ret cx Extensions API support bitmap - * @ret status Status code / API version - */ -static int int13_extension_check ( struct int13_drive *drive __unused, - struct i386_all_regs *ix86 ) { - if ( ix86->regs.bx == 0x55aa ) { - DBG ( "INT 13 extensions installation check\n" ); - ix86->regs.bx = 0xaa55; - ix86->regs.cx = INT13_EXTENSION_LINEAR; - return INT13_EXTENSION_VER_1_X; - } else { - return -INT13_STATUS_INVALID; - } -} - -/** - * Extended read / write - * - * @v drive Emulated drive - * @v ds:si Disk address packet - * @v io Read / write method - * @ret status Status code - */ -static int int13_extended_rw ( struct int13_drive *drive, - struct i386_all_regs *ix86, - int ( * io ) ( struct block_device *blockdev, - uint64_t block, - unsigned long count, - userptr_t buffer ) ) { - struct block_device *blockdev = drive->blockdev; - struct int13_disk_address addr; - uint64_t lba; - unsigned long count; - userptr_t buffer; - int rc; - - /* Read parameters from disk address structure */ - copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, sizeof ( addr )); - lba = addr.lba; - count = addr.count; - buffer = real_to_user ( addr.buffer.segment, addr.buffer.offset ); - - DBG ( "LBA %#llx <-> %04x:%04x (count %ld)\n", (unsigned long long)lba, - addr.buffer.segment, addr.buffer.offset, count ); - - /* Read from / write to block device */ - if ( ( rc = io ( blockdev, lba, count, buffer ) ) != 0 ) { - DBG ( "INT 13 failed: %s\n", strerror ( rc ) ); - return -INT13_STATUS_READ_ERROR; - } - - return 0; -} - -/** - * INT 13, 42 - Extended read - * - * @v drive Emulated drive - * @v ds:si Disk address packet - * @ret status Status code - */ -static int int13_extended_read ( struct int13_drive *drive, - struct i386_all_regs *ix86 ) { - DBG ( "Extended read: " ); - return int13_extended_rw ( drive, ix86, drive->blockdev->op->read ); -} - -/** - * INT 13, 43 - Extended write - * - * @v drive Emulated drive - * @v ds:si Disk address packet - * @ret status Status code - */ -static int int13_extended_write ( struct int13_drive *drive, - struct i386_all_regs *ix86 ) { - DBG ( "Extended write: " ); - return int13_extended_rw ( drive, ix86, drive->blockdev->op->write ); -} - -/** - * INT 13, 48 - Get extended parameters - * - * @v drive Emulated drive - * @v ds:si Drive parameter table - * @ret status Status code - */ -static int int13_get_extended_parameters ( struct int13_drive *drive, - struct i386_all_regs *ix86 ) { - struct int13_disk_parameters params = { - .bufsize = sizeof ( params ), - .flags = INT13_FL_DMA_TRANSPARENT, - .cylinders = drive->cylinders, - .heads = drive->heads, - .sectors_per_track = drive->sectors_per_track, - .sectors = drive->blockdev->blocks, - .sector_size = drive->blockdev->blksize, - }; - - DBG ( "Get extended drive parameters to %04x:%04x\n", - ix86->segs.ds, ix86->regs.si ); - - copy_to_real ( ix86->segs.ds, ix86->regs.si, ¶ms, - sizeof ( params ) ); - return 0; -} - -/** - * INT 13 handler - * - */ -static __asmcall void int13 ( struct i386_all_regs *ix86 ) { - int command = ix86->regs.ah; - unsigned int bios_drive = ix86->regs.dl; - struct int13_drive *drive; - int status; - - /* Check BIOS hasn't killed off our drive */ - int13_check_num_drives(); - - list_for_each_entry ( drive, &drives, list ) { - - if ( bios_drive != drive->drive ) { - /* Remap any accesses to this drive's natural number */ - if ( bios_drive == drive->natural_drive ) { - DBG ( "INT 13,%04x (%02x) remapped to " - "(%02x)\n", ix86->regs.ax, - bios_drive, drive->drive ); - ix86->regs.dl = drive->drive; - return; - } - continue; - } - - DBG ( "INT 13,%04x (%02x): ", ix86->regs.ax, drive->drive ); - - switch ( command ) { - case INT13_RESET: - status = int13_reset ( drive, ix86 ); - break; - case INT13_GET_LAST_STATUS: - status = int13_get_last_status ( drive, ix86 ); - break; - case INT13_READ_SECTORS: - status = int13_read_sectors ( drive, ix86 ); - break; - case INT13_WRITE_SECTORS: - status = int13_write_sectors ( drive, ix86 ); - break; - case INT13_GET_PARAMETERS: - status = int13_get_parameters ( drive, ix86 ); - break; - case INT13_GET_DISK_TYPE: - status = int13_get_disk_type ( drive, ix86 ); - break; - case INT13_EXTENSION_CHECK: - status = int13_extension_check ( drive, ix86 ); - break; - case INT13_EXTENDED_READ: - status = int13_extended_read ( drive, ix86 ); - break; - case INT13_EXTENDED_WRITE: - status = int13_extended_write ( drive, ix86 ); - break; - case INT13_GET_EXTENDED_PARAMETERS: - status = int13_get_extended_parameters ( drive, ix86 ); - break; - default: - DBG ( "*** Unrecognised INT 13 ***\n" ); - status = -INT13_STATUS_INVALID; - break; - } - - /* Store status for INT 13,01 */ - drive->last_status = status; - - /* Negative status indicates an error */ - if ( status < 0 ) { - status = -status; - DBG ( "INT 13 returning failure status %x\n", status ); - } else { - ix86->flags &= ~CF; - } - ix86->regs.ah = status; - - /* Set OF to indicate to wrapper not to chain this call */ - ix86->flags |= OF; - - return; - } -} - -/** - * Hook INT 13 handler - * - */ -static void hook_int13 ( void ) { - /* Assembly wrapper to call int13(). int13() sets OF if we - * should not chain to the previous handler. (The wrapper - * clears CF and OF before calling int13()). - */ - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint13_wrapper:\n\t" - /* Preserve %ax and %dx for future reference */ - "pushw %%bp\n\t" - "movw %%sp, %%bp\n\t" - "pushw %%ax\n\t" - "pushw %%dx\n\t" - /* Clear OF, set CF, call int13() */ - "orb $0, %%al\n\t" - "stc\n\t" - "pushl %0\n\t" - "pushw %%cs\n\t" - "call prot_call\n\t" - /* Chain if OF not set */ - "jo 1f\n\t" - "pushfw\n\t" - "lcall *%%cs:int13_vector\n\t" - "\n1:\n\t" - /* Overwrite flags for iret */ - "pushfw\n\t" - "popw 6(%%bp)\n\t" - /* Fix up %dl: - * - * INT 13,15 : do nothing - * INT 13,08 : load with number of drives - * all others: restore original value - */ - "cmpb $0x15, -1(%%bp)\n\t" - "je 2f\n\t" - "movb -4(%%bp), %%dl\n\t" - "cmpb $0x08, -1(%%bp)\n\t" - "jne 2f\n\t" - "pushw %%ds\n\t" - "pushw %1\n\t" - "popw %%ds\n\t" - "movb %c2, %%dl\n\t" - "popw %%ds\n\t" - /* Return */ - "\n2:\n\t" - "movw %%bp, %%sp\n\t" - "popw %%bp\n\t" - "iret\n\t" ) - : : "i" ( int13 ), "i" ( BDA_SEG ), "i" ( BDA_NUM_DRIVES ) ); - - hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper, - &int13_vector ); -} - -/** - * Unhook INT 13 handler - */ -static void unhook_int13 ( void ) { - unhook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper, - &int13_vector ); -} - -/** - * Guess INT 13 drive geometry - * - * @v drive Emulated drive - * - * Guesses the drive geometry by inspecting the partition table. - */ -static void guess_int13_geometry ( struct int13_drive *drive ) { - struct master_boot_record mbr; - struct partition_table_entry *partition; - unsigned int guessed_heads = 255; - unsigned int guessed_sectors_per_track = 63; - unsigned long blocks; - unsigned long blocks_per_cyl; - unsigned int i; - - /* Don't even try when the blksize is invalid for C/H/S access */ - if ( drive->blockdev->blksize != INT13_BLKSIZE ) - return; - - /* Scan through partition table and modify guesses for heads - * and sectors_per_track if we find any used partitions. - */ - if ( drive->blockdev->op->read ( drive->blockdev, 0, 1, - virt_to_user ( &mbr ) ) == 0 ) { - for ( i = 0 ; i < 4 ; i++ ) { - partition = &mbr.partitions[i]; - if ( ! partition->type ) - continue; - guessed_heads = - ( PART_HEAD ( partition->chs_end ) + 1 ); - guessed_sectors_per_track = - PART_SECTOR ( partition->chs_end ); - DBG ( "Guessing C/H/S xx/%d/%d based on partition " - "%d\n", guessed_heads, - guessed_sectors_per_track, ( i + 1 ) ); - } - } else { - DBG ( "Could not read partition table to guess geometry\n" ); - } - - /* Apply guesses if no geometry already specified */ - if ( ! drive->heads ) - drive->heads = guessed_heads; - if ( ! drive->sectors_per_track ) - drive->sectors_per_track = guessed_sectors_per_track; - if ( ! drive->cylinders ) { - /* Avoid attempting a 64-bit divide on a 32-bit system */ - blocks = ( ( drive->blockdev->blocks <= ULONG_MAX ) ? - drive->blockdev->blocks : ULONG_MAX ); - blocks_per_cyl = ( drive->heads * drive->sectors_per_track ); - assert ( blocks_per_cyl != 0 ); - drive->cylinders = ( blocks / blocks_per_cyl ); - if ( drive->cylinders > 1024 ) - drive->cylinders = 1024; - } -} - -/** - * Register INT 13 emulated drive - * - * @v drive Emulated drive - * - * Registers the drive with the INT 13 emulation subsystem, and hooks - * the INT 13 interrupt vector (if not already hooked). - * - * The underlying block device must be valid. A drive number and - * geometry will be assigned if left blank. - */ -void register_int13_drive ( struct int13_drive *drive ) { - uint8_t num_drives; - - /* Give drive a default geometry if none specified */ - guess_int13_geometry ( drive ); - - /* Assign natural drive number */ - get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES ); - drive->natural_drive = ( num_drives | 0x80 ); - - /* Assign drive number */ - if ( ( drive->drive & 0xff ) == 0xff ) { - /* Drive number == -1 => use natural drive number */ - drive->drive = drive->natural_drive; - } else { - /* Use specified drive number (+0x80 if necessary) */ - drive->drive |= 0x80; - } - - DBG ( "Registered INT13 drive %02x (naturally %02x) with C/H/S " - "geometry %d/%d/%d\n", drive->drive, drive->natural_drive, - drive->cylinders, drive->heads, drive->sectors_per_track ); - - /* Hook INT 13 vector if not already hooked */ - if ( list_empty ( &drives ) ) - hook_int13(); - - /* Add to list of emulated drives */ - list_add ( &drive->list, &drives ); - - /* Update BIOS drive count */ - int13_set_num_drives(); -} - -/** - * Unregister INT 13 emulated drive - * - * @v drive Emulated drive - * - * Unregisters the drive from the INT 13 emulation subsystem. If this - * is the last emulated drive, the INT 13 vector is unhooked (if - * possible). - */ -void unregister_int13_drive ( struct int13_drive *drive ) { - /* Remove from list of emulated drives */ - list_del ( &drive->list ); - - /* Should adjust BIOS drive count, but it's difficult to do so - * reliably. - */ - - DBG ( "Unregistered INT13 drive %02x\n", drive->drive ); - - /* Unhook INT 13 vector if no more drives */ - if ( list_empty ( &drives ) ) - unhook_int13(); -} - -/** - * Attempt to boot from an INT 13 drive - * - * @v drive Drive number - * @ret rc Return status code - * - * This boots from the specified INT 13 drive by loading the Master - * Boot Record to 0000:7c00 and jumping to it. INT 18 is hooked to - * capture an attempt by the MBR to boot the next device. (This is - * the closest thing to a return path from an MBR). - * - * Note that this function can never return success, by definition. - */ -int int13_boot ( unsigned int drive ) { - struct memory_map memmap; - int status, signature; - int discard_c, discard_d; - int rc; - - DBG ( "Booting from INT 13 drive %02x\n", drive ); - - /* Use INT 13 to read the boot sector */ - __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t" - "pushw $0\n\t" - "popw %%es\n\t" - "stc\n\t" - "sti\n\t" - "int $0x13\n\t" - "sti\n\t" /* BIOS bugs */ - "jc 1f\n\t" - "xorl %%eax, %%eax\n\t" - "\n1:\n\t" - "movzwl %%es:0x7dfe, %%ebx\n\t" - "popw %%es\n\t" ) - : "=a" ( status ), "=b" ( signature ), - "=c" ( discard_c ), "=d" ( discard_d ) - : "a" ( 0x0201 ), "b" ( 0x7c00 ), - "c" ( 1 ), "d" ( drive ) ); - if ( status ) - return -EIO; - - /* Check signature is correct */ - if ( signature != be16_to_cpu ( 0x55aa ) ) { - DBG ( "Invalid disk signature %#04x (should be 0x55aa)\n", - cpu_to_be16 ( signature ) ); - return -ENOEXEC; - } - - /* Dump out memory map prior to boot, if memmap debugging is - * enabled. Not required for program flow, but we have so - * many problems that turn out to be memory-map related that - * it's worth doing. - */ - get_memmap ( &memmap ); - - /* Jump to boot sector */ - if ( ( rc = call_bootsector ( 0x0, 0x7c00, drive ) ) != 0 ) { - DBG ( "INT 13 drive %02x boot returned: %s\n", - drive, strerror ( rc ) ); - return rc; - } - - return -ECANCELED; /* -EIMPOSSIBLE */ -} diff --git a/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c b/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c deleted file mode 100644 index 00efd8ff..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c +++ /dev/null @@ -1,75 +0,0 @@ -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <gpxe/iscsi.h> -#include <gpxe/netdevice.h> -#include <gpxe/ibft.h> -#include <gpxe/sanboot.h> -#include <int13.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -static int iscsiboot ( const char *root_path ) { - struct scsi_device *scsi; - struct int13_drive *drive; - int rc; - - scsi = zalloc ( sizeof ( *scsi ) ); - if ( ! scsi ) { - rc = -ENOMEM; - goto err_alloc_scsi; - } - drive = zalloc ( sizeof ( *drive ) ); - if ( ! drive ) { - rc = -ENOMEM; - goto err_alloc_drive; - } - - if ( ( rc = iscsi_attach ( scsi, root_path ) ) != 0 ) { - printf ( "Could not attach iSCSI device: %s\n", - strerror ( rc ) ); - goto err_attach; - } - if ( ( rc = init_scsidev ( scsi ) ) != 0 ) { - printf ( "Could not initialise iSCSI device: %s\n", - strerror ( rc ) ); - goto err_init; - } - - drive->blockdev = &scsi->blockdev; - - /* FIXME: ugly, ugly hack */ - struct net_device *netdev = last_opened_netdev(); - struct iscsi_session *iscsi = - container_of ( scsi->backend, struct iscsi_session, refcnt ); - ibft_fill_data ( netdev, iscsi ); - - register_int13_drive ( drive ); - printf ( "Registered as BIOS drive %#02x\n", drive->drive ); - printf ( "Booting from BIOS drive %#02x\n", drive->drive ); - rc = int13_boot ( drive->drive ); - printf ( "Boot failed\n" ); - - /* Leave drive registered, if instructed to do so */ - if ( keep_san() ) - return rc; - - printf ( "Unregistering BIOS drive %#02x\n", drive->drive ); - unregister_int13_drive ( drive ); - - err_init: - iscsi_detach ( scsi ); - err_attach: - free ( drive ); - err_alloc_drive: - free ( scsi ); - err_alloc_scsi: - return rc; -} - -struct sanboot_protocol iscsi_sanboot_protocol __sanboot_protocol = { - .prefix = "iscsi:", - .boot = iscsiboot, -}; diff --git a/gpxe/src/arch/i386/interface/pcbios/keepsan.c b/gpxe/src/arch/i386/interface/pcbios/keepsan.c deleted file mode 100644 index 904e017d..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/keepsan.c +++ /dev/null @@ -1,26 +0,0 @@ -#include <stdint.h> -#include <stdio.h> -#include <gpxe/settings.h> -#include <gpxe/dhcp.h> -#include <gpxe/init.h> -#include <gpxe/sanboot.h> -#include <usr/autoboot.h> - -struct setting keep_san_setting __setting = { - .name = "keep-san", - .description = "Preserve SAN connection", - .tag = DHCP_EB_KEEP_SAN, - .type = &setting_type_int8, -}; - -int keep_san ( void ) { - int keep_san; - - keep_san = fetch_intz_setting ( NULL, &keep_san_setting ); - if ( ! keep_san ) - return 0; - - printf ( "Preserving connection to SAN disk\n" ); - shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES; - return 1; -} diff --git a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c deleted file mode 100644 index 0645fe63..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * External memory allocation - * - */ - -#include <limits.h> -#include <errno.h> -#include <gpxe/uaccess.h> -#include <gpxe/hidemem.h> -#include <gpxe/memmap.h> -#include <gpxe/umalloc.h> - -/** Alignment of external allocated memory */ -#define EM_ALIGN ( 4 * 1024 ) - -/** Equivalent of NOWHERE for user pointers */ -#define UNOWHERE ( ~UNULL ) - -/** An external memory block */ -struct external_memory { - /** Size of this memory block (excluding this header) */ - size_t size; - /** Block is currently in use */ - int used; -}; - -/** Top of heap */ -static userptr_t top = UNULL; - -/** Bottom of heap (current lowest allocated block) */ -static userptr_t bottom = UNULL; - -/** - * Initialise external heap - * - * @ret rc Return status code - */ -static int init_eheap ( void ) { - struct memory_map memmap; - unsigned long heap_size = 0; - unsigned int i; - - DBG ( "Allocating external heap\n" ); - - get_memmap ( &memmap ); - 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; - } - - DBG ( "External heap grows downwards from %lx\n", - user_to_phys ( top, 0 ) ); - return 0; -} - -/** - * Collect free blocks - * - */ -static void ecollect_free ( void ) { - struct external_memory extmem; - - /* Walk the free list and collect empty blocks */ - while ( bottom != top ) { - copy_from_user ( &extmem, bottom, -sizeof ( extmem ), - sizeof ( extmem ) ); - if ( extmem.used ) - break; - DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ), - user_to_phys ( bottom, extmem.size ) ); - bottom = userptr_add ( bottom, - ( extmem.size + sizeof ( extmem ) ) ); - } -} - -/** - * Reallocate external memory - * - * @v old_ptr Memory previously allocated by umalloc(), or UNULL - * @v new_size Requested size - * @ret new_ptr Allocated memory, or UNULL - * - * Calling realloc() with a new size of zero is a valid way to free a - * memory block. - */ -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; - } - - /* Get block properties into extmem */ - if ( ptr && ( ptr != UNOWHERE ) ) { - /* Determine old size */ - copy_from_user ( &extmem, ptr, -sizeof ( extmem ), - sizeof ( extmem ) ); - } else { - /* Create a zero-length block */ - ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) ); - DBG ( "EXTMEM allocating [%lx,%lx)\n", - user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) ); - extmem.size = 0; - } - extmem.used = ( new_size > 0 ); - - /* Expand/shrink block if possible */ - if ( ptr == bottom ) { - /* Update block */ - new = userptr_add ( ptr, - ( new_size - extmem.size ) ); - align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) ); - new_size += align; - new = userptr_add ( new, -align ); - DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n", - user_to_phys ( ptr, 0 ), - user_to_phys ( ptr, extmem.size ), - user_to_phys ( new, 0 ), - user_to_phys ( new, new_size )); - memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ? - extmem.size : new_size ) ); - extmem.size = new_size; - bottom = new; - } else { - /* Cannot expand; can only pretend to shrink */ - if ( new_size > extmem.size ) { - /* Refuse to expand */ - DBG ( "EXTMEM cannot expand [%lx,%lx)\n", - user_to_phys ( ptr, 0 ), - user_to_phys ( ptr, extmem.size ) ); - return UNULL; - } - } - - /* Write back block properties */ - copy_to_user ( new, -sizeof ( extmem ), &extmem, - sizeof ( extmem ) ); - - /* Collect any free blocks and update hidden memory region */ - ecollect_free(); - hide_umalloc ( user_to_phys ( bottom, -sizeof ( extmem ) ), - user_to_phys ( top, 0 ) ); - - return ( new_size ? new : UNOWHERE ); -} - -PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc ); diff --git a/gpxe/src/arch/i386/interface/pcbios/pcibios.c b/gpxe/src/arch/i386/interface/pcbios/pcibios.c deleted file mode 100644 index f2c3880c..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/pcibios.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <gpxe/pci.h> -#include <realmode.h> - -/** @file - * - * PCI configuration space access via PCI BIOS - * - */ - -/** - * Determine maximum PCI bus number within system - * - * @ret max_bus Maximum bus number - */ -static int pcibios_max_bus ( void ) { - int discard_a, discard_D; - uint8_t max_bus; - - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" - "int $0x1a\n\t" - "jnc 1f\n\t" - "xorw %%cx, %%cx\n\t" - "\n1:\n\t" ) - : "=c" ( max_bus ), "=a" ( discard_a ), - "=D" ( discard_D ) - : "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 ), - "D" ( 0 ) - : "ebx", "edx" ); - - return max_bus; -} - -/** - * Read configuration space via PCI BIOS - * - * @v pci PCI device - * @v command PCI BIOS command - * @v value Value read - * @ret rc Return status code - */ -int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){ - int discard_b, discard_D; - int status; - - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" - "int $0x1a\n\t" - "jnc 1f\n\t" - "xorl %%eax, %%eax\n\t" - "decl %%eax\n\t" - "movl %%eax, %%ecx\n\t" - "\n1:\n\t" ) - : "=a" ( status ), "=b" ( discard_b ), - "=c" ( *value ), "=D" ( discard_D ) - : "a" ( command >> 16 ), "D" ( command ), - "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ) - : "edx" ); - - return ( ( status >> 8 ) & 0xff ); -} - -/** - * Write configuration space via PCI BIOS - * - * @v pci PCI device - * @v command PCI BIOS command - * @v value Value to be written - * @ret rc Return status code - */ -int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){ - int discard_b, discard_c, discard_D; - int status; - - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" - "int $0x1a\n\t" - "jnc 1f\n\t" - "movb $0xff, %%ah\n\t" - "\n1:\n\t" ) - : "=a" ( status ), "=b" ( discard_b ), - "=c" ( discard_c ), "=D" ( discard_D ) - : "a" ( command >> 16 ), "D" ( command ), - "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ), - "c" ( value ) - : "edx" ); - - return ( ( status >> 8 ) & 0xff ); -} - -PROVIDE_PCIAPI ( pcbios, pci_max_bus, pcibios_max_bus ); -PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte ); -PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word ); -PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_dword ); -PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte ); -PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word ); -PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword ); diff --git a/gpxe/src/arch/i386/interface/pcbios/sbft.c b/gpxe/src/arch/i386/interface/pcbios/sbft.c deleted file mode 100644 index 12927c77..00000000 --- a/gpxe/src/arch/i386/interface/pcbios/sbft.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -FILE_LICENCE ( BSD2 ); - -/** @file - * - * SRP boot firmware table - * - */ - -#include <assert.h> -#include <realmode.h> -#include <gpxe/srp.h> -#include <gpxe/ib_srp.h> -#include <gpxe/acpi.h> -#include <gpxe/sbft.h> - -#define sbftab __use_data16 ( sbftab ) -/** The sBFT used by gPXE */ -struct gpxe_sbft __data16 ( sbftab ) = { - /* Table header */ - .table = { - /* ACPI header */ - .acpi = { - .signature = SBFT_SIG, - .length = sizeof ( sbftab ), - .revision = 1, - .oem_id = "FENSYS", - .oem_table_id = "gPXE", - }, - .scsi_offset = offsetof ( typeof ( sbftab ), scsi ), - .srp_offset = offsetof ( typeof ( sbftab ), srp ), - .ib_offset = offsetof ( typeof ( sbftab ), ib ), - }, -}; - -/** - * Fill in all variable portions of sBFT - * - * @v srp SRP device - * @ret rc Return status code - */ -int sbft_fill_data ( struct srp_device *srp ) { - struct sbft_scsi_subtable *sbft_scsi = &sbftab.scsi; - struct sbft_srp_subtable *sbft_srp = &sbftab.srp; - struct sbft_ib_subtable *sbft_ib = &sbftab.ib; - struct ib_srp_parameters *ib_params; - struct segoff rm_sbftab = { - .segment = rm_ds, - .offset = __from_data16 ( &sbftab ), - }; - - /* Fill in the SCSI subtable */ - memcpy ( &sbft_scsi->lun, &srp->lun, sizeof ( sbft_scsi->lun ) ); - - /* Fill in the SRP subtable */ - memcpy ( &sbft_srp->port_ids, &srp->port_ids, - sizeof ( sbft_srp->port_ids ) ); - - /* Fill in the IB subtable */ - assert ( srp->transport == &ib_srp_transport ); - ib_params = ib_srp_params ( srp ); - memcpy ( &sbft_ib->sgid, &ib_params->sgid, sizeof ( sbft_ib->sgid ) ); - memcpy ( &sbft_ib->dgid, &ib_params->dgid, sizeof ( sbft_ib->dgid ) ); - memcpy ( &sbft_ib->service_id, &ib_params->service_id, - sizeof ( sbft_ib->service_id ) ); - sbft_ib->pkey = ib_params->pkey; - - /* Update checksum */ - acpi_fix_checksum ( &sbftab.table.acpi ); - - DBGC ( &sbftab, "SRP Boot Firmware Table at %04x:%04x:\n", - rm_sbftab.segment, rm_sbftab.offset ); - DBGC_HDA ( &sbftab, rm_sbftab, &sbftab, sizeof ( sbftab ) ); - - return 0; -} diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_call.c b/gpxe/src/arch/i386/interface/pxe/pxe_call.c deleted file mode 100644 index 66a9b1e2..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_call.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/uaccess.h> -#include <gpxe/init.h> -#include <registers.h> -#include <biosint.h> -#include <pxe.h> -#include <pxe_call.h> - -/** @file - * - * PXE API entry point - */ - -/** Vector for chaining INT 1A */ -extern struct segoff __text16 ( pxe_int_1a_vector ); -#define pxe_int_1a_vector __use_text16 ( pxe_int_1a_vector ) - -/** INT 1A handler */ -extern void pxe_int_1a ( void ); - -/** INT 1A hooked flag */ -static int int_1a_hooked = 0; - -/** A function pointer to hold any PXE API call - * - * Used by pxe_api_call() to avoid large swathes of duplicated code. - */ -union pxenv_call { - PXENV_EXIT_t ( * any ) ( union u_PXENV_ANY * ); - PXENV_EXIT_t ( * unknown ) ( struct s_PXENV_UNKNOWN * ); - PXENV_EXIT_t ( * unload_stack ) ( struct s_PXENV_UNLOAD_STACK * ); - PXENV_EXIT_t ( * get_cached_info ) - ( struct s_PXENV_GET_CACHED_INFO * ); - PXENV_EXIT_t ( * restart_tftp ) ( struct s_PXENV_TFTP_READ_FILE * ); - PXENV_EXIT_t ( * start_undi ) ( struct s_PXENV_START_UNDI * ); - PXENV_EXIT_t ( * stop_undi ) ( struct s_PXENV_STOP_UNDI * ); - PXENV_EXIT_t ( * start_base ) ( struct s_PXENV_START_BASE * ); - PXENV_EXIT_t ( * stop_base ) ( struct s_PXENV_STOP_BASE * ); - PXENV_EXIT_t ( * tftp_open ) ( struct s_PXENV_TFTP_OPEN * ); - PXENV_EXIT_t ( * tftp_close ) ( struct s_PXENV_TFTP_CLOSE * ); - PXENV_EXIT_t ( * tftp_read ) ( struct s_PXENV_TFTP_READ * ); - PXENV_EXIT_t ( * tftp_read_file ) ( struct s_PXENV_TFTP_READ_FILE * ); - PXENV_EXIT_t ( * tftp_get_fsize ) ( struct s_PXENV_TFTP_GET_FSIZE * ); - PXENV_EXIT_t ( * udp_open ) ( struct s_PXENV_UDP_OPEN * ); - PXENV_EXIT_t ( * udp_close ) ( struct s_PXENV_UDP_CLOSE * ); - PXENV_EXIT_t ( * udp_write ) ( struct s_PXENV_UDP_WRITE * ); - PXENV_EXIT_t ( * udp_read ) ( struct s_PXENV_UDP_READ * ); - PXENV_EXIT_t ( * undi_startup ) ( struct s_PXENV_UNDI_STARTUP * ); - PXENV_EXIT_t ( * undi_cleanup ) ( struct s_PXENV_UNDI_CLEANUP * ); - PXENV_EXIT_t ( * undi_initialize ) - ( struct s_PXENV_UNDI_INITIALIZE * ); - PXENV_EXIT_t ( * undi_reset_adapter ) ( struct s_PXENV_UNDI_RESET * ); - PXENV_EXIT_t ( * undi_shutdown ) ( struct s_PXENV_UNDI_SHUTDOWN * ); - PXENV_EXIT_t ( * undi_open ) ( struct s_PXENV_UNDI_OPEN * ); - PXENV_EXIT_t ( * undi_close ) ( struct s_PXENV_UNDI_CLOSE * ); - PXENV_EXIT_t ( * undi_transmit ) ( struct s_PXENV_UNDI_TRANSMIT * ); - PXENV_EXIT_t ( * undi_set_mcast_address ) - ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS * ); - PXENV_EXIT_t ( * undi_set_station_address ) - ( struct s_PXENV_UNDI_SET_STATION_ADDRESS * ); - PXENV_EXIT_t ( * undi_set_packet_filter ) - ( struct s_PXENV_UNDI_SET_PACKET_FILTER * ); - PXENV_EXIT_t ( * undi_get_information ) - ( struct s_PXENV_UNDI_GET_INFORMATION * ); - PXENV_EXIT_t ( * undi_get_statistics ) - ( struct s_PXENV_UNDI_GET_STATISTICS * ); - PXENV_EXIT_t ( * undi_clear_statistics ) - ( struct s_PXENV_UNDI_CLEAR_STATISTICS * ); - PXENV_EXIT_t ( * undi_initiate_diags ) - ( struct s_PXENV_UNDI_INITIATE_DIAGS * ); - PXENV_EXIT_t ( * undi_force_interrupt ) - ( struct s_PXENV_UNDI_FORCE_INTERRUPT * ); - PXENV_EXIT_t ( * undi_get_mcast_address ) - ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS * ); - PXENV_EXIT_t ( * undi_get_nic_type ) - ( struct s_PXENV_UNDI_GET_NIC_TYPE * ); - PXENV_EXIT_t ( * undi_get_iface_info ) - ( struct s_PXENV_UNDI_GET_IFACE_INFO * ); - PXENV_EXIT_t ( * undi_get_state ) ( struct s_PXENV_UNDI_GET_STATE * ); - PXENV_EXIT_t ( * undi_isr ) ( struct s_PXENV_UNDI_ISR * ); - PXENV_EXIT_t ( * file_open ) ( struct s_PXENV_FILE_OPEN * ); - PXENV_EXIT_t ( * file_close ) ( struct s_PXENV_FILE_CLOSE * ); - PXENV_EXIT_t ( * file_select ) ( struct s_PXENV_FILE_SELECT * ); - PXENV_EXIT_t ( * file_read ) ( struct s_PXENV_FILE_READ * ); - PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * ); - PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * ); - PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * ); - PXENV_EXIT_t ( * file_exit_hook ) ( struct s_PXENV_FILE_EXIT_HOOK * ); -}; - -/** - * Handle an unknown PXE API call - * - * @v pxenv_unknown Pointer to a struct s_PXENV_UNKNOWN - * @ret #PXENV_EXIT_FAILURE Always - * @err #PXENV_STATUS_UNSUPPORTED Always - */ -static PXENV_EXIT_t pxenv_unknown ( struct s_PXENV_UNKNOWN *pxenv_unknown ) { - pxenv_unknown->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -} - -/** - * Dispatch PXE API call - * - * @v bx PXE opcode - * @v es:di Address of PXE parameter block - * @ret ax PXE exit code - */ -__asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) { - int opcode = ix86->regs.bx; - userptr_t parameters = real_to_user ( ix86->segs.es, ix86->regs.di ); - size_t param_len; - union u_PXENV_ANY pxenv_any; - union pxenv_call pxenv_call; - PXENV_EXIT_t ret; - - switch ( opcode ) { - case PXENV_UNLOAD_STACK: - pxenv_call.unload_stack = pxenv_unload_stack; - param_len = sizeof ( pxenv_any.unload_stack ); - break; - case PXENV_GET_CACHED_INFO: - pxenv_call.get_cached_info = pxenv_get_cached_info; - param_len = sizeof ( pxenv_any.get_cached_info ); - break; - case PXENV_RESTART_TFTP: - pxenv_call.restart_tftp = pxenv_restart_tftp; - param_len = sizeof ( pxenv_any.restart_tftp ); - break; - case PXENV_START_UNDI: - pxenv_call.start_undi = pxenv_start_undi; - param_len = sizeof ( pxenv_any.start_undi ); - break; - case PXENV_STOP_UNDI: - pxenv_call.stop_undi = pxenv_stop_undi; - param_len = sizeof ( pxenv_any.stop_undi ); - break; - case PXENV_START_BASE: - pxenv_call.start_base = pxenv_start_base; - param_len = sizeof ( pxenv_any.start_base ); - break; - case PXENV_STOP_BASE: - pxenv_call.stop_base = pxenv_stop_base; - param_len = sizeof ( pxenv_any.stop_base ); - break; - case PXENV_TFTP_OPEN: - pxenv_call.tftp_open = pxenv_tftp_open; - param_len = sizeof ( pxenv_any.tftp_open ); - break; - case PXENV_TFTP_CLOSE: - pxenv_call.tftp_close = pxenv_tftp_close; - param_len = sizeof ( pxenv_any.tftp_close ); - break; - case PXENV_TFTP_READ: - pxenv_call.tftp_read = pxenv_tftp_read; - param_len = sizeof ( pxenv_any.tftp_read ); - break; - case PXENV_TFTP_READ_FILE: - pxenv_call.tftp_read_file = pxenv_tftp_read_file; - param_len = sizeof ( pxenv_any.tftp_read_file ); - break; - case PXENV_TFTP_GET_FSIZE: - pxenv_call.tftp_get_fsize = pxenv_tftp_get_fsize; - param_len = sizeof ( pxenv_any.tftp_get_fsize ); - break; - case PXENV_UDP_OPEN: - pxenv_call.udp_open = pxenv_udp_open; - param_len = sizeof ( pxenv_any.udp_open ); - break; - case PXENV_UDP_CLOSE: - pxenv_call.udp_close = pxenv_udp_close; - param_len = sizeof ( pxenv_any.udp_close ); - break; - case PXENV_UDP_WRITE: - pxenv_call.udp_write = pxenv_udp_write; - param_len = sizeof ( pxenv_any.udp_write ); - break; - case PXENV_UDP_READ: - pxenv_call.udp_read = pxenv_udp_read; - param_len = sizeof ( pxenv_any.udp_read ); - break; - case PXENV_UNDI_STARTUP: - pxenv_call.undi_startup = pxenv_undi_startup; - param_len = sizeof ( pxenv_any.undi_startup ); - break; - case PXENV_UNDI_CLEANUP: - pxenv_call.undi_cleanup = pxenv_undi_cleanup; - param_len = sizeof ( pxenv_any.undi_cleanup ); - break; - case PXENV_UNDI_INITIALIZE: - pxenv_call.undi_initialize = pxenv_undi_initialize; - param_len = sizeof ( pxenv_any.undi_initialize ); - break; - case PXENV_UNDI_RESET_ADAPTER: - pxenv_call.undi_reset_adapter = pxenv_undi_reset_adapter; - param_len = sizeof ( pxenv_any.undi_reset_adapter ); - break; - case PXENV_UNDI_SHUTDOWN: - pxenv_call.undi_shutdown = pxenv_undi_shutdown; - param_len = sizeof ( pxenv_any.undi_shutdown ); - break; - case PXENV_UNDI_OPEN: - pxenv_call.undi_open = pxenv_undi_open; - param_len = sizeof ( pxenv_any.undi_open ); - break; - case PXENV_UNDI_CLOSE: - pxenv_call.undi_close = pxenv_undi_close; - param_len = sizeof ( pxenv_any.undi_close ); - break; - case PXENV_UNDI_TRANSMIT: - pxenv_call.undi_transmit = pxenv_undi_transmit; - param_len = sizeof ( pxenv_any.undi_transmit ); - break; - case PXENV_UNDI_SET_MCAST_ADDRESS: - pxenv_call.undi_set_mcast_address = - pxenv_undi_set_mcast_address; - param_len = sizeof ( pxenv_any.undi_set_mcast_address ); - break; - case PXENV_UNDI_SET_STATION_ADDRESS: - pxenv_call.undi_set_station_address = - pxenv_undi_set_station_address; - param_len = sizeof ( pxenv_any.undi_set_station_address ); - break; - case PXENV_UNDI_SET_PACKET_FILTER: - pxenv_call.undi_set_packet_filter = - pxenv_undi_set_packet_filter; - param_len = sizeof ( pxenv_any.undi_set_packet_filter ); - break; - case PXENV_UNDI_GET_INFORMATION: - pxenv_call.undi_get_information = pxenv_undi_get_information; - param_len = sizeof ( pxenv_any.undi_get_information ); - break; - case PXENV_UNDI_GET_STATISTICS: - pxenv_call.undi_get_statistics = pxenv_undi_get_statistics; - param_len = sizeof ( pxenv_any.undi_get_statistics ); - break; - case PXENV_UNDI_CLEAR_STATISTICS: - pxenv_call.undi_clear_statistics = pxenv_undi_clear_statistics; - param_len = sizeof ( pxenv_any.undi_clear_statistics ); - break; - case PXENV_UNDI_INITIATE_DIAGS: - pxenv_call.undi_initiate_diags = pxenv_undi_initiate_diags; - param_len = sizeof ( pxenv_any.undi_initiate_diags ); - break; - case PXENV_UNDI_FORCE_INTERRUPT: - pxenv_call.undi_force_interrupt = pxenv_undi_force_interrupt; - param_len = sizeof ( pxenv_any.undi_force_interrupt ); - break; - case PXENV_UNDI_GET_MCAST_ADDRESS: - pxenv_call.undi_get_mcast_address = - pxenv_undi_get_mcast_address; - param_len = sizeof ( pxenv_any.undi_get_mcast_address ); - break; - case PXENV_UNDI_GET_NIC_TYPE: - pxenv_call.undi_get_nic_type = pxenv_undi_get_nic_type; - param_len = sizeof ( pxenv_any.undi_get_nic_type ); - break; - case PXENV_UNDI_GET_IFACE_INFO: - pxenv_call.undi_get_iface_info = pxenv_undi_get_iface_info; - param_len = sizeof ( pxenv_any.undi_get_iface_info ); - break; - case PXENV_UNDI_ISR: - pxenv_call.undi_isr = pxenv_undi_isr; - param_len = sizeof ( pxenv_any.undi_isr ); - break; - case PXENV_FILE_OPEN: - pxenv_call.file_open = pxenv_file_open; - param_len = sizeof ( pxenv_any.file_open ); - break; - case PXENV_FILE_CLOSE: - pxenv_call.file_close = pxenv_file_close; - param_len = sizeof ( pxenv_any.file_close ); - break; - case PXENV_FILE_SELECT: - pxenv_call.file_select = pxenv_file_select; - param_len = sizeof ( pxenv_any.file_select ); - break; - case PXENV_FILE_READ: - pxenv_call.file_read = pxenv_file_read; - param_len = sizeof ( pxenv_any.file_read ); - break; - case PXENV_GET_FILE_SIZE: - pxenv_call.get_file_size = pxenv_get_file_size; - param_len = sizeof ( pxenv_any.get_file_size ); - break; - case PXENV_FILE_EXEC: - pxenv_call.file_exec = pxenv_file_exec; - param_len = sizeof ( pxenv_any.file_exec ); - break; - case PXENV_FILE_API_CHECK: - pxenv_call.file_api_check = pxenv_file_api_check; - param_len = sizeof ( pxenv_any.file_api_check ); - break; - case PXENV_FILE_EXIT_HOOK: - pxenv_call.file_exit_hook = pxenv_file_exit_hook; - param_len = sizeof ( pxenv_any.file_exit_hook ); - break; - default: - DBG ( "PXENV_UNKNOWN_%hx", opcode ); - pxenv_call.unknown = pxenv_unknown; - param_len = sizeof ( pxenv_any.unknown ); - break; - } - - /* Copy parameter block from caller */ - copy_from_user ( &pxenv_any, parameters, 0, param_len ); - - /* Set default status in case child routine fails to do so */ - pxenv_any.Status = PXENV_STATUS_FAILURE; - - /* Hand off to relevant API routine */ - DBG ( "[" ); - ret = pxenv_call.any ( &pxenv_any ); - if ( pxenv_any.Status != PXENV_STATUS_SUCCESS ) { - DBG ( " %02x", pxenv_any.Status ); - } - if ( ret != PXENV_EXIT_SUCCESS ) { - DBG ( ret == PXENV_EXIT_FAILURE ? " err" : " ??" ); - } - DBG ( "]" ); - - /* Copy modified parameter block back to caller and return */ - copy_to_user ( parameters, 0, &pxenv_any, param_len ); - ix86->regs.ax = ret; -} - -/** - * Dispatch weak PXE API call with PXE stack available - * - * @v ix86 Registers for PXE call - * @ret present Zero (PXE stack present) - */ -int _pxe_api_call_weak ( struct i386_all_regs *ix86 ) -{ - pxe_api_call ( ix86 ); - return 0; -} - -/** - * Dispatch PXE loader call - * - * @v es:di Address of PXE parameter block - * @ret ax PXE exit code - */ -__asmcall void pxe_loader_call ( struct i386_all_regs *ix86 ) { - userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di ); - struct s_UNDI_LOADER params; - PXENV_EXIT_t ret; - - /* Copy parameter block from caller */ - copy_from_user ( ¶ms, uparams, 0, sizeof ( params ) ); - - /* Fill in ROM segment address */ - ppxe.UNDIROMID.segment = ix86->segs.ds; - - /* Set default status in case child routine fails to do so */ - params.Status = PXENV_STATUS_FAILURE; - - /* Call UNDI loader */ - ret = undi_loader ( ¶ms ); - - /* Copy modified parameter block back to caller and return */ - copy_to_user ( uparams, 0, ¶ms, sizeof ( params ) ); - ix86->regs.ax = ret; -} - -/** - * Calculate byte checksum as used by PXE - * - * @v data Data - * @v size Length of data - * @ret sum Checksum - */ -static uint8_t pxe_checksum ( void *data, size_t size ) { - uint8_t *bytes = data; - uint8_t sum = 0; - - while ( size-- ) { - sum += *bytes++; - } - return sum; -} - -/** - * Initialise !PXE and PXENV+ structures - * - */ -static void pxe_init_structures ( void ) { - uint32_t rm_cs_phys = ( rm_cs << 4 ); - uint32_t rm_ds_phys = ( rm_ds << 4 ); - - /* Fill in missing segment fields */ - ppxe.EntryPointSP.segment = rm_cs; - ppxe.EntryPointESP.segment = rm_cs; - ppxe.Stack.segment_address = rm_ds; - ppxe.Stack.Physical_address = rm_ds_phys; - ppxe.UNDIData.segment_address = rm_ds; - ppxe.UNDIData.Physical_address = rm_ds_phys; - ppxe.UNDICode.segment_address = rm_cs; - ppxe.UNDICode.Physical_address = rm_cs_phys; - ppxe.UNDICodeWrite.segment_address = rm_cs; - ppxe.UNDICodeWrite.Physical_address = rm_cs_phys; - pxenv.RMEntry.segment = rm_cs; - pxenv.StackSeg = rm_ds; - pxenv.UNDIDataSeg = rm_ds; - pxenv.UNDICodeSeg = rm_cs; - pxenv.PXEPtr.segment = rm_cs; - - /* Update checksums */ - ppxe.StructCksum -= pxe_checksum ( &ppxe, sizeof ( ppxe ) ); - pxenv.Checksum -= pxe_checksum ( &pxenv, sizeof ( pxenv ) ); -} - -/** PXE structure initialiser */ -struct init_fn pxe_init_fn __init_fn ( INIT_NORMAL ) = { - .initialise = pxe_init_structures, -}; - -/** - * Activate PXE stack - * - * @v netdev Net device to use as PXE net device - */ -void pxe_activate ( struct net_device *netdev ) { - - /* Ensure INT 1A is hooked */ - if ( ! int_1a_hooked ) { - hook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a, - &pxe_int_1a_vector ); - int_1a_hooked = 1; - } - - /* Set PXE network device */ - pxe_set_netdev ( netdev ); -} - -/** - * Deactivate PXE stack - * - * @ret rc Return status code - */ -int pxe_deactivate ( void ) { - int rc; - - /* Clear PXE network device */ - pxe_set_netdev ( NULL ); - - /* Ensure INT 1A is unhooked, if possible */ - if ( int_1a_hooked ) { - if ( ( rc = unhook_bios_interrupt ( 0x1a, - (unsigned int) pxe_int_1a, - &pxe_int_1a_vector ))!= 0){ - DBG ( "Could not unhook INT 1A: %s\n", - strerror ( rc ) ); - return rc; - } - int_1a_hooked = 0; - } - - return 0; -} - -/** - * Start PXE NBP at 0000:7c00 - * - * @ret rc Return status code - */ -int pxe_start_nbp ( void ) { - int discard_b, discard_c, discard_d, discard_D; - uint16_t rc; - - /* Far call to PXE NBP */ - __asm__ __volatile__ ( REAL_CODE ( "movw %%cx, %%es\n\t" - "pushw %%es\n\t" - "pushw %%di\n\t" - "sti\n\t" - "lcall $0, $0x7c00\n\t" - "addw $4, %%sp\n\t" ) - : "=a" ( rc ), "=b" ( discard_b ), - "=c" ( discard_c ), "=d" ( discard_d ), - "=D" ( discard_D ) - : "a" ( 0 ), "b" ( __from_text16 ( &pxenv ) ), - "c" ( rm_cs ), - "d" ( virt_to_phys ( &pxenv ) ), - "D" ( __from_text16 ( &ppxe ) ) - : "esi", "ebp", "memory" ); - - return rc; -} diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S b/gpxe/src/arch/i386/interface/pxe/pxe_entry.S deleted file mode 100644 index 0d3a57cd..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - - .arch i386 - -/**************************************************************************** - * !PXE structure - **************************************************************************** - */ - .section ".text16.data", "aw", @progbits - .globl ppxe - .align 16 -ppxe: - .ascii "!PXE" /* Signature */ - .byte pxe_length /* StructLength */ - .byte 0 /* StructCksum */ - .byte 0 /* StructRev */ - .byte 0 /* reserved_1 */ - .word undiheader, 0 /* UNDIROMID */ - .word 0, 0 /* BaseROMID */ - .word pxe_entry_sp, 0 /* EntryPointSP */ - .word pxe_entry_esp, 0 /* EntryPointESP */ - .word -1, -1 /* StatusCallout */ - .byte 0 /* reserved_2 */ - .byte SegDescCnt /* SegDescCnt */ - .word 0 /* FirstSelector */ -pxe_segments: - .word 0, 0, 0, _data16_memsz /* Stack */ - .word 0, 0, 0, _data16_memsz /* UNDIData */ - .word 0, 0, 0, _text16_memsz /* UNDICode */ - .word 0, 0, 0, _text16_memsz /* UNDICodeWrite */ - .word 0, 0, 0, 0 /* BC_Data */ - .word 0, 0, 0, 0 /* BC_Code */ - .word 0, 0, 0, 0 /* BC_CodeWrite */ - .equ SegDescCnt, ( ( . - pxe_segments ) / 8 ) - .equ pxe_length, . - ppxe - .size ppxe, . - ppxe - - /* Define undiheader=0 as a weak symbol for non-ROM builds */ - .section ".weak", "a", @nobits - .weak undiheader -undiheader: - -/**************************************************************************** - * PXENV+ structure - **************************************************************************** - */ - .section ".text16.data", "aw", @progbits - .globl pxenv - .align 16 -pxenv: - .ascii "PXENV+" /* Signature */ - .word 0x0201 /* Version */ - .byte pxenv_length /* Length */ - .byte 0 /* Checksum */ - .word pxenv_entry, 0 /* RMEntry */ - .long 0 /* PMEntry */ - .word 0 /* PMSelector */ - .word 0 /* StackSeg */ - .word _data16_memsz /* StackSize */ - .word 0 /* BC_CodeSeg */ - .word 0 /* BC_CodeSize */ - .word 0 /* BC_DataSeg */ - .word 0 /* BC_DataSize */ - .word 0 /* UNDIDataSeg */ - .word _data16_memsz /* UNDIDataSize */ - .word 0 /* UNDICodeSeg */ - .word _text16_memsz /* UNDICodeSize */ - .word ppxe, 0 /* PXEPtr */ - .equ pxenv_length, . - pxenv - .size pxenv, . - pxenv - -/**************************************************************************** - * pxenv_entry (16-bit far call) - * - * PXE API call PXENV+ entry point - * - * Parameters: - * %es:di : Far pointer to PXE parameter structure - * %bx : PXE API call - * Returns: - * %ax : PXE exit status - * Corrupts: - * none - **************************************************************************** - */ - /* Wyse Streaming Manager server (WLDRM13.BIN) assumes that - * the PXENV+ entry point is at UNDI_CS:0000; apparently, - * somebody at Wyse has difficulty distinguishing between the - * words "may" and "must"... - */ - .section ".text16.null", "ax", @progbits - .code16 -pxenv_null_entry: - jmp pxenv_entry - - .section ".text16", "ax", @progbits - .code16 -pxenv_entry: - pushl $pxe_api_call - pushw %cs - call prot_call - addl $4, %esp - lret - .size pxenv_entry, . - pxenv_entry - -/**************************************************************************** - * pxe_entry - * - * PXE API call !PXE entry point - * - * Parameters: - * stack : Far pointer to PXE parameter structure - * stack : PXE API call - * Returns: - * %ax : PXE exit status - * Corrupts: - * none - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 -pxe_entry: -pxe_entry_sp: - /* Preserve original %esp */ - pushl %esp - /* Zero high word of %esp to allow use of common code */ - movzwl %sp, %esp - jmp pxe_entry_common -pxe_entry_esp: - /* Preserve %esp to match behaviour of pxe_entry_sp */ - pushl %esp -pxe_entry_common: - /* Save PXENV+ API call registers */ - pushw %es - pushw %di - pushw %bx - /* Load !PXE parameters from stack into PXENV+ registers */ - addr32 movw 18(%esp), %bx - movw %bx, %es - addr32 movw 16(%esp), %di - addr32 movw 14(%esp), %bx - /* Make call as for PXENV+ */ - pushw %cs - call pxenv_entry - /* Restore PXENV+ registers */ - popw %bx - popw %di - popw %es - /* Restore original %esp and return */ - popl %esp - lret - .size pxe_entry, . - pxe_entry - -/**************************************************************************** - * pxe_int_1a - * - * PXE INT 1A handler - * - * Parameters: - * %ax : 0x5650 - * Returns: - * %ax : 0x564e - * %es:bx : Far pointer to the PXENV+ structure - * %edx : Physical address of the PXENV+ structure - * CF cleared - * Corrupts: - * none - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 - .globl pxe_int_1a -pxe_int_1a: - pushfw - cmpw $0x5650, %ax - jne 1f - /* INT 1A,5650 - PXE installation check */ - xorl %edx, %edx - movw %cs, %dx - movw %dx, %es - movw $pxenv, %bx - shll $4, %edx - addl $pxenv, %edx - movw $0x564e, %ax - pushw %bp - movw %sp, %bp - andb $~0x01, 8(%bp) /* Clear CF on return */ - popw %bp - popfw - iret -1: /* INT 1A,other - pass through */ - popfw - ljmp *%cs:pxe_int_1a_vector - - .section ".text16.data", "aw", @progbits - .globl pxe_int_1a_vector -pxe_int_1a_vector: .long 0 diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_errors.c b/gpxe/src/arch/i386/interface/pxe/pxe_errors.c deleted file mode 100644 index f884ef8a..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_errors.c +++ /dev/null @@ -1,103 +0,0 @@ -#include <errno.h> -#include <gpxe/errortab.h> - -/* - * This table was generated from the relevant section of errno.h using - * - * perl -ne 'if ( /(PXENV_STATUS_(\S+))/ ) { - * $code = $1; $msg = $2; - * $msg =~ s/_/ /g; $msg = ucfirst lc $msg; - * $msg =~ s/(tftp|udp|arp|undi|bis|binl|pxenv|pxe|dhcp)/uc $1/ieg; - * print "\t{ $code, \"$msg\" },\n"; - * }' - * - * followed by a little manual tweaking. - * - */ -struct errortab pxe_errortab[] __errortab = { - { PXENV_STATUS_SUCCESS, "Success" }, - { PXENV_STATUS_FAILURE, "Failure" }, - { PXENV_STATUS_BAD_FUNC, "Bad function" }, - { PXENV_STATUS_UNSUPPORTED, "Unsupported function" }, - { PXENV_STATUS_KEEP_UNDI, "Keep UNDI" }, - { PXENV_STATUS_KEEP_ALL, "Keep all" }, - { PXENV_STATUS_OUT_OF_RESOURCES, "Out of resources" }, - { PXENV_STATUS_ARP_TIMEOUT, "ARP timeout" }, - { PXENV_STATUS_UDP_CLOSED, "UDP closed" }, - { PXENV_STATUS_UDP_OPEN, "UDP open" }, - { PXENV_STATUS_TFTP_CLOSED, "TFTP closed" }, - { PXENV_STATUS_TFTP_OPEN, "TFTP open" }, - { PXENV_STATUS_MCOPY_PROBLEM, "Memory copy problem" }, - { PXENV_STATUS_BIS_INTEGRITY_FAILURE, "BIS integrity failure" }, - { PXENV_STATUS_BIS_VALIDATE_FAILURE, "BIS validation failure" }, - { PXENV_STATUS_BIS_INIT_FAILURE, "BIS init failure" }, - { PXENV_STATUS_BIS_SHUTDOWN_FAILURE, "BIS shutdown failure" }, - { PXENV_STATUS_BIS_GBOA_FAILURE, "BIS GBOA failure" }, - { PXENV_STATUS_BIS_FREE_FAILURE, "BIS free failure" }, - { PXENV_STATUS_BIS_GSI_FAILURE, "BIS GSI failure" }, - { PXENV_STATUS_BIS_BAD_CKSUM, "BIS bad checksum" }, - { PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS, "TFTP cannot ARP address" }, - { PXENV_STATUS_TFTP_OPEN_TIMEOUT, "TFTP open timeout" }, - { PXENV_STATUS_TFTP_UNKNOWN_OPCODE, "TFTP unknown opcode" }, - { PXENV_STATUS_TFTP_READ_TIMEOUT, "TFTP read timeout" }, - { PXENV_STATUS_TFTP_ERROR_OPCODE, "TFTP error opcode" }, - { PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION, - "TFTP cannot open connection" }, - { PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, - "TFTP cannot read from connection" }, - { PXENV_STATUS_TFTP_TOO_MANY_PACKAGES, "TFTP too many packages" }, - { PXENV_STATUS_TFTP_FILE_NOT_FOUND, "TFTP file not found" }, - { PXENV_STATUS_TFTP_ACCESS_VIOLATION, "TFTP access violation" }, - { PXENV_STATUS_TFTP_NO_MCAST_ADDRESS, "TFTP no mcast address" }, - { PXENV_STATUS_TFTP_NO_FILESIZE, "TFTP no filesize" }, - { PXENV_STATUS_TFTP_INVALID_PACKET_SIZE, "TFTP invalid packet size" }, - { PXENV_STATUS_DHCP_TIMEOUT, "DHCP timeout" }, - { PXENV_STATUS_DHCP_NO_IP_ADDRESS, "DHCP no ip address" }, - { PXENV_STATUS_DHCP_NO_BOOTFILE_NAME, "DHCP no bootfile name" }, - { PXENV_STATUS_DHCP_BAD_IP_ADDRESS, "DHCP bad ip address" }, - { PXENV_STATUS_UNDI_INVALID_FUNCTION, "UNDI invalid function" }, - { PXENV_STATUS_UNDI_MEDIATEST_FAILED, "UNDI mediatest failed" }, - { PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST, - "UNDI cannot initialise NIC for multicast" }, - { PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC, - "UNDI cannot initialise NIC" }, - { PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY, - "UNDI cannot initialise PHY" }, - { PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA, - "UNDI cannot read config data" }, - { PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA, - "UNDI cannot read init data" }, - { PXENV_STATUS_UNDI_BAD_MAC_ADDRESS, "UNDI bad MAC address" }, - { PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM, "UNDI bad EEPROM checksum" }, - { PXENV_STATUS_UNDI_ERROR_SETTING_ISR, "UNDI error setting ISR" }, - { PXENV_STATUS_UNDI_INVALID_STATE, "UNDI invalid state" }, - { PXENV_STATUS_UNDI_TRANSMIT_ERROR, "UNDI transmit error" }, - { PXENV_STATUS_UNDI_INVALID_PARAMETER, "UNDI invalid parameter" }, - { PXENV_STATUS_BSTRAP_PROMPT_MENU, "Bootstrap prompt menu" }, - { PXENV_STATUS_BSTRAP_MCAST_ADDR, "Bootstrap mcast addr" }, - { PXENV_STATUS_BSTRAP_MISSING_LIST, "Bootstrap missing list" }, - { PXENV_STATUS_BSTRAP_NO_RESPONSE, "Bootstrap no response" }, - { PXENV_STATUS_BSTRAP_FILE_TOO_BIG, "Bootstrap file too big" }, - { PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE, - "BINL canceled by keystroke" }, - { PXENV_STATUS_BINL_NO_PXE_SERVER, "BINL no PXE server" }, - { PXENV_STATUS_NOT_AVAILABLE_IN_PMODE, - "Not available in protected mode" }, - { PXENV_STATUS_NOT_AVAILABLE_IN_RMODE, "Not available in real mode" }, - { PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED, - "BUSD device not supported" }, - { PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY, - "Loader no free base memory" }, - { PXENV_STATUS_LOADER_NO_BC_ROMID, "Loader no Base Code ROM ID" }, - { PXENV_STATUS_LOADER_BAD_BC_ROMID, "Loader bad Base Code ROM ID" }, - { PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE, - "Loader bad Base Code runtime image" }, - { PXENV_STATUS_LOADER_NO_UNDI_ROMID, "Loader no UNDI ROM ID" }, - { PXENV_STATUS_LOADER_BAD_UNDI_ROMID, "Loader bad UNDI ROM ID" }, - { PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE, - "Loader bad UNDI driver image" }, - { PXENV_STATUS_LOADER_NO_PXE_STRUCT, "Loader no !PXE struct" }, - { PXENV_STATUS_LOADER_NO_PXENV_STRUCT, "Loader no PXENV+ struct" }, - { PXENV_STATUS_LOADER_UNDI_START, "Loader UNDI start" }, - { PXENV_STATUS_LOADER_BC_START, "Loader Base Code start" }, -}; diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_file.c b/gpxe/src/arch/i386/interface/pxe/pxe_file.c deleted file mode 100644 index 8d832123..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_file.c +++ /dev/null @@ -1,306 +0,0 @@ -/** @file - * - * PXE FILE API - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <byteswap.h> -#include <gpxe/uaccess.h> -#include <gpxe/posix_io.h> -#include <gpxe/features.h> -#include <pxe.h> -#include <realmode.h> - -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * Portions (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>. - * [PXE exit hook logic] - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 ); - -/** - * FILE OPEN - * - * @v file_open Pointer to a struct s_PXENV_FILE_OPEN - * @v s_PXENV_FILE_OPEN::FileName URL of file to open - * @ret #PXENV_EXIT_SUCCESS File was opened - * @ret #PXENV_EXIT_FAILURE File was not opened - * @ret s_PXENV_FILE_OPEN::Status PXE status code - * @ret s_PXENV_FILE_OPEN::FileHandle Handle of opened file - * - */ -PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) { - userptr_t filename; - size_t filename_len; - int fd; - - DBG ( "PXENV_FILE_OPEN" ); - - /* Copy name from external program, and open it */ - filename = real_to_user ( file_open->FileName.segment, - file_open->FileName.offset ); - filename_len = strlen_user ( filename, 0 ); - { - char uri_string[ filename_len + 1 ]; - - copy_from_user ( uri_string, filename, 0, - sizeof ( uri_string ) ); - DBG ( " %s", uri_string ); - fd = open ( uri_string ); - } - - if ( fd < 0 ) { - file_open->Status = PXENV_STATUS ( fd ); - return PXENV_EXIT_FAILURE; - } - - DBG ( " as file %d", fd ); - - file_open->FileHandle = fd; - file_open->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * FILE CLOSE - * - * @v file_close Pointer to a struct s_PXENV_FILE_CLOSE - * @v s_PXENV_FILE_CLOSE::FileHandle File handle - * @ret #PXENV_EXIT_SUCCESS File was closed - * @ret #PXENV_EXIT_FAILURE File was not closed - * @ret s_PXENV_FILE_CLOSE::Status PXE status code - * - */ -PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) { - - DBG ( "PXENV_FILE_CLOSE %d", file_close->FileHandle ); - - close ( file_close->FileHandle ); - file_close->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * FILE SELECT - * - * @v file_select Pointer to a struct s_PXENV_FILE_SELECT - * @v s_PXENV_FILE_SELECT::FileHandle File handle - * @ret #PXENV_EXIT_SUCCESS File has been checked for readiness - * @ret #PXENV_EXIT_FAILURE File has not been checked for readiness - * @ret s_PXENV_FILE_SELECT::Status PXE status code - * @ret s_PXENV_FILE_SELECT::Ready Indication of readiness - * - */ -PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) { - fd_set fdset; - int ready; - - DBG ( "PXENV_FILE_SELECT %d", file_select->FileHandle ); - - FD_ZERO ( &fdset ); - FD_SET ( file_select->FileHandle, &fdset ); - if ( ( ready = select ( &fdset, 0 ) ) < 0 ) { - file_select->Status = PXENV_STATUS ( ready ); - return PXENV_EXIT_FAILURE; - } - - file_select->Ready = ( ready ? RDY_READ : 0 ); - file_select->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * FILE READ - * - * @v file_read Pointer to a struct s_PXENV_FILE_READ - * @v s_PXENV_FILE_READ::FileHandle File handle - * @v s_PXENV_FILE_READ::BufferSize Size of data buffer - * @v s_PXENV_FILE_READ::Buffer Data buffer - * @ret #PXENV_EXIT_SUCCESS Data has been read from file - * @ret #PXENV_EXIT_FAILURE Data has not been read from file - * @ret s_PXENV_FILE_READ::Status PXE status code - * @ret s_PXENV_FILE_READ::Ready Indication of readiness - * @ret s_PXENV_FILE_READ::BufferSize Length of data read - * - */ -PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) { - userptr_t buffer; - ssize_t len; - - DBG ( "PXENV_FILE_READ %d to %04x:%04x+%04x", file_read->FileHandle, - file_read->Buffer.segment, file_read->Buffer.offset, - file_read->BufferSize ); - - buffer = real_to_user ( file_read->Buffer.segment, - file_read->Buffer.offset ); - if ( ( len = read_user ( file_read->FileHandle, buffer, 0, - file_read->BufferSize ) ) < 0 ) { - file_read->Status = PXENV_STATUS ( len ); - return PXENV_EXIT_FAILURE; - } - - DBG ( " read %04zx", ( ( size_t ) len ) ); - - file_read->BufferSize = len; - file_read->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * GET FILE SIZE - * - * @v get_file_size Pointer to a struct s_PXENV_GET_FILE_SIZE - * @v s_PXENV_GET_FILE_SIZE::FileHandle File handle - * @ret #PXENV_EXIT_SUCCESS File size has been determined - * @ret #PXENV_EXIT_FAILURE File size has not been determined - * @ret s_PXENV_GET_FILE_SIZE::Status PXE status code - * @ret s_PXENV_GET_FILE_SIZE::FileSize Size of file - */ -PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE - *get_file_size ) { - ssize_t filesize; - - DBG ( "PXENV_GET_FILE_SIZE %d", get_file_size->FileHandle ); - - filesize = fsize ( get_file_size->FileHandle ); - if ( filesize < 0 ) { - get_file_size->Status = PXENV_STATUS ( filesize ); - return PXENV_EXIT_FAILURE; - } - - DBG ( " is %zd", ( ( size_t ) filesize ) ); - - get_file_size->FileSize = filesize; - get_file_size->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * FILE EXEC - * - * @v file_exec Pointer to a struct s_PXENV_FILE_EXEC - * @v s_PXENV_FILE_EXEC::Command Command to execute - * @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 - * - */ -PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) { - userptr_t command; - size_t command_len; - int rc; - - DBG ( "PXENV_FILE_EXEC" ); - - /* Copy name from external program, and exec it */ - command = real_to_user ( file_exec->Command.segment, - file_exec->Command.offset ); - command_len = strlen_user ( command, 0 ); - { - char command_string[ command_len + 1 ]; - - copy_from_user ( command_string, command, 0, - sizeof ( command_string ) ); - DBG ( " %s", command_string ); - - if ( ( rc = system ( command_string ) ) != 0 ) { - file_exec->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - } - - file_exec->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 }; -#define pxe_exit_hook __use_data16 ( pxe_exit_hook ) - -/** - * FILE API CHECK - * - * @v file_exec Pointer to a struct s_PXENV_FILE_API_CHECK - * @v s_PXENV_FILE_API_CHECK::Magic Inbound magic number (0x91d447b2) - * @ret #PXENV_EXIT_SUCCESS Command was executed successfully - * @ret #PXENV_EXIT_FAILURE Command was not executed successfully - * @ret s_PXENV_FILE_API_CHECK::Status PXE status code - * @ret s_PXENV_FILE_API_CHECK::Magic Outbound magic number (0xe9c17b20) - * @ret s_PXENV_FILE_API_CHECK::Provider "gPXE" (0x45585067) - * @ret s_PXENV_FILE_API_CHECK::APIMask API function bitmask - * @ret s_PXENV_FILE_API_CHECK::Flags Reserved - * - */ -PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ) { - DBG ( "PXENV_FILE_API_CHECK" ); - - if ( file_api_check->Magic != 0x91d447b2 ) { - file_api_check->Status = PXENV_STATUS_BAD_FUNC; - return PXENV_EXIT_FAILURE; - } else if ( file_api_check->Size < - sizeof(struct s_PXENV_FILE_API_CHECK) ) { - file_api_check->Status = PXENV_STATUS_OUT_OF_RESOURCES; - return PXENV_EXIT_FAILURE; - } else { - file_api_check->Status = PXENV_STATUS_SUCCESS; - file_api_check->Size = sizeof(struct s_PXENV_FILE_API_CHECK); - file_api_check->Magic = 0xe9c17b20; - file_api_check->Provider = 0x45585067; /* "gPXE" */ - file_api_check->APIMask = 0x0000007f; /* Functions e0-e6 */ - /* Check to see if we have a PXE exit hook */ - if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) - /* Function e7, also */ - file_api_check->APIMask |= 0x00000080; - file_api_check->Flags = 0; /* None defined */ - return PXENV_EXIT_SUCCESS; - } -} - -/** - * FILE EXIT HOOK - * - * @v file_exit_hook Pointer to a struct - * s_PXENV_FILE_EXIT_HOOK - * @v s_PXENV_FILE_EXIT_HOOK::Hook SEG16:OFF16 to jump to - * @ret #PXENV_EXIT_SUCCESS Successfully set hook - * @ret #PXENV_EXIT_FAILURE We're not an NBP build - * @ret s_PXENV_FILE_EXIT_HOOK::Status PXE status code - * - */ -PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK - *file_exit_hook ) { - DBG ( "PXENV_FILE_EXIT_HOOK" ); - - /* Check to see if we have a PXE exit hook */ - if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) { - /* We'll jump to the specified SEG16:OFF16 during exit */ - pxe_exit_hook.segment = file_exit_hook->Hook.segment; - pxe_exit_hook.offset = file_exit_hook->Hook.offset; - file_exit_hook->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; - } - - DBG ( " not NBP" ); - file_exit_hook->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -} - diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_loader.c b/gpxe/src/arch/i386/interface/pxe/pxe_loader.c deleted file mode 100644 index b35caf77..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_loader.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/init.h> -#include "pxe.h" -#include "pxe_call.h" - -/** @file - * - * PXE UNDI loader - * - */ - -/* PXENV_UNDI_LOADER - * - */ -PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ) { - - /* Perform one-time initialisation (e.g. heap) */ - initialise(); - - DBG ( "[PXENV_UNDI_LOADER to CS %04x DS %04x]", - undi_loader->UNDI_CS, undi_loader->UNDI_DS ); - - /* Fill in UNDI loader structure */ - undi_loader->PXEptr.segment = rm_cs; - undi_loader->PXEptr.offset = __from_text16 ( &ppxe ); - undi_loader->PXENVptr.segment = rm_cs; - undi_loader->PXENVptr.offset = __from_text16 ( &pxenv ); - - undi_loader->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c b/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c deleted file mode 100644 index 3939c7bf..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c +++ /dev/null @@ -1,357 +0,0 @@ -/** @file - * - * PXE Preboot API - * - */ - -/* PXE API interface for Etherboot. - * - * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <gpxe/uaccess.h> -#include <gpxe/dhcp.h> -#include <gpxe/fakedhcp.h> -#include <gpxe/device.h> -#include <gpxe/netdevice.h> -#include <gpxe/isapnp.h> -#include <gpxe/init.h> -#include <gpxe/if_ether.h> -#include <basemem_packet.h> -#include <biosint.h> -#include "pxe.h" -#include "pxe_call.h" - -/* Avoid dragging in isapnp.o unnecessarily */ -uint16_t isapnp_read_port; - -/** Zero-based versions of PXENV_GET_CACHED_INFO::PacketType */ -enum pxe_cached_info_indices { - CACHED_INFO_DHCPDISCOVER = ( PXENV_PACKET_TYPE_DHCP_DISCOVER - 1 ), - CACHED_INFO_DHCPACK = ( PXENV_PACKET_TYPE_DHCP_ACK - 1 ), - CACHED_INFO_BINL = ( PXENV_PACKET_TYPE_CACHED_REPLY - 1 ), - NUM_CACHED_INFOS -}; - -/** A cached DHCP packet */ -union pxe_cached_info { - struct dhcphdr dhcphdr; - /* This buffer must be *exactly* the size of a BOOTPLAYER_t - * structure, otherwise WinPE will die horribly. It takes the - * size of *our* buffer and feeds it in to us as the size of - * one of *its* buffers. If our buffer is larger than it - * expects, we therefore end up overwriting part of its data - * segment, since it tells us to do so. (D'oh!) - * - * Note that a BOOTPLAYER_t is not necessarily large enough to - * hold a DHCP packet; this is a flaw in the PXE spec. - */ - BOOTPLAYER_t packet; -} __attribute__ (( packed )); - -/** A PXE DHCP packet creator */ -struct pxe_dhcp_packet_creator { - /** Create DHCP packet - * - * @v netdev Network device - * @v data Buffer for DHCP packet - * @v max_len Size of DHCP packet buffer - * @ret rc Return status code - */ - int ( * create ) ( struct net_device *netdev, void *data, - size_t max_len ); -}; - -/** PXE DHCP packet creators */ -static struct pxe_dhcp_packet_creator pxe_dhcp_packet_creators[] = { - [CACHED_INFO_DHCPDISCOVER] = { create_fakedhcpdiscover }, - [CACHED_INFO_DHCPACK] = { create_fakedhcpack }, - [CACHED_INFO_BINL] = { create_fakepxebsack }, -}; - -/* The case in which the caller doesn't supply a buffer is really - * awkward to support given that we have multiple sources of options, - * and that we don't actually store the DHCP packets. (We may not - * even have performed DHCP; we may have obtained all configuration - * from non-volatile stored options or from the command line.) - * - * Some NBPs rely on the buffers we provide being persistent, so we - * can't just use the temporary packet buffer. 4.5kB of base memory - * always wasted just because some clients are too lazy to provide - * their own buffers... - */ -static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] ); -#define cached_info __use_data16 ( cached_info ) - -/** - * Set PXE cached TFTP filename - * - * @v filename TFTP filename - * - * This is a bug-for-bug compatibility hack needed in order to work - * with Microsoft Remote Installation Services (RIS). The filename - * used in a call to PXENV_RESTART_TFTP or PXENV_TFTP_READ_FILE must - * be returned as the DHCP filename in subsequent calls to - * PXENV_GET_CACHED_INFO. - */ -void pxe_set_cached_filename ( const unsigned char *filename ) { - memcpy ( cached_info[CACHED_INFO_DHCPACK].dhcphdr.file, filename, - sizeof ( cached_info[CACHED_INFO_DHCPACK].dhcphdr.file ) ); - memcpy ( cached_info[CACHED_INFO_BINL].dhcphdr.file, filename, - sizeof ( cached_info[CACHED_INFO_BINL].dhcphdr.file ) ); -} - -/** - * UNLOAD BASE CODE STACK - * - * @v None - - * @ret ... - * - */ -PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) { - DBG ( "PXENV_UNLOAD_STACK" ); - - unload_stack->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_GET_CACHED_INFO - * - * Status: working - */ -PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO - *get_cached_info ) { - struct pxe_dhcp_packet_creator *creator; - union pxe_cached_info *info; - unsigned int idx; - size_t len; - userptr_t buffer; - int rc; - - DBG ( "PXENV_GET_CACHED_INFO %d", get_cached_info->PacketType ); - - DBG ( " to %04x:%04x+%x", get_cached_info->Buffer.segment, - get_cached_info->Buffer.offset, get_cached_info->BufferSize ); - - /* Sanity check */ - idx = ( get_cached_info->PacketType - 1 ); - if ( idx >= NUM_CACHED_INFOS ) { - DBG ( " bad PacketType" ); - goto err; - } - info = &cached_info[idx]; - - /* Construct cached version of packet, if not already constructed. */ - if ( ! info->dhcphdr.op ) { - /* Construct DHCP packet */ - creator = &pxe_dhcp_packet_creators[idx]; - if ( ( rc = creator->create ( pxe_netdev, info, - sizeof ( *info ) ) ) != 0 ) { - DBG ( " failed to build packet" ); - goto err; - } - } - - len = get_cached_info->BufferSize; - if ( len == 0 ) { - /* Point client at our cached buffer. - * - * To add to the fun, Intel decided at some point in - * the evolution of the PXE specification to add the - * BufferLimit field, which we are meant to fill in - * with the length of our packet buffer, so that the - * caller can safely modify the boot server reply - * packet stored therein. However, this field was not - * present in earlier versions of the PXE spec, and - * there is at least one PXE NBP (Altiris) which - * allocates only exactly enough space for this - * earlier, shorter version of the structure. If we - * actually fill in the BufferLimit field, we - * therefore risk trashing random areas of the - * caller's memory. If we *don't* fill it in, then - * the caller is at liberty to assume that whatever - * random value happened to be in that location - * represents the length of the buffer we've just - * passed back to it. - * - * Since older PXE stacks won't fill this field in - * anyway, it's probably safe to assume that no - * callers actually rely on it, so we choose to not - * fill it in. - */ - get_cached_info->Buffer.segment = rm_ds; - get_cached_info->Buffer.offset = __from_data16 ( info ); - get_cached_info->BufferSize = sizeof ( *info ); - DBG ( " returning %04x:%04x+%04x['%x']", - get_cached_info->Buffer.segment, - get_cached_info->Buffer.offset, - get_cached_info->BufferSize, - get_cached_info->BufferLimit ); - } else { - /* Copy packet to client buffer */ - if ( len > sizeof ( *info ) ) - len = sizeof ( *info ); - if ( len < sizeof ( *info ) ) - DBG ( " buffer may be too short" ); - buffer = real_to_user ( get_cached_info->Buffer.segment, - get_cached_info->Buffer.offset ); - copy_to_user ( buffer, 0, info, len ); - get_cached_info->BufferSize = len; - } - - get_cached_info->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; - - err: - get_cached_info->Status = PXENV_STATUS_OUT_OF_RESOURCES; - return PXENV_EXIT_FAILURE; -} - -/* PXENV_RESTART_TFTP - * - * Status: working - */ -PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE - *restart_tftp ) { - PXENV_EXIT_t tftp_exit; - - DBG ( "PXENV_RESTART_TFTP " ); - - /* Intel bug-for-bug hack */ - pxe_set_cached_filename ( restart_tftp->FileName ); - - /* Words cannot describe the complete mismatch between the PXE - * specification and any possible version of reality... - */ - restart_tftp->Buffer = PXE_LOAD_PHYS; /* Fixed by spec, apparently */ - restart_tftp->BufferSize = ( 0xa0000 - PXE_LOAD_PHYS ); /* Near enough */ - tftp_exit = pxenv_tftp_read_file ( restart_tftp ); - if ( tftp_exit != PXENV_EXIT_SUCCESS ) - return tftp_exit; - - /* Fire up the new NBP */ - restart_tftp->Status = pxe_start_nbp(); - - /* Not sure what "SUCCESS" actually means, since we can only - * return if the new NBP failed to boot... - */ - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_START_UNDI - * - * Status: working - */ -PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { - unsigned int bus_type; - unsigned int location; - struct net_device *netdev; - - DBG ( "PXENV_START_UNDI %04x:%04x:%04x", - start_undi->AX, start_undi->BX, start_undi->DX ); - - /* Determine bus type and location. Use a heuristic to decide - * whether we are PCI or ISAPnP - */ - if ( ( start_undi->DX >= ISAPNP_READ_PORT_MIN ) && - ( start_undi->DX <= ISAPNP_READ_PORT_MAX ) && - ( start_undi->BX >= ISAPNP_CSN_MIN ) && - ( start_undi->BX <= ISAPNP_CSN_MAX ) ) { - bus_type = BUS_TYPE_ISAPNP; - location = start_undi->BX; - /* Record ISAPnP read port for use by isapnp.c */ - isapnp_read_port = start_undi->DX; - } else { - bus_type = BUS_TYPE_PCI; - location = start_undi->AX; - } - - /* Probe for devices, etc. */ - startup(); - - /* Look for a matching net device */ - netdev = find_netdev_by_location ( bus_type, location ); - if ( ! netdev ) { - DBG ( " no net device found" ); - start_undi->Status = PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC; - return PXENV_EXIT_FAILURE; - } - DBG ( " using netdev %s", netdev->name ); - - /* Activate PXE */ - pxe_activate ( netdev ); - - start_undi->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_STOP_UNDI - * - * Status: working - */ -PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) { - DBG ( "PXENV_STOP_UNDI" ); - - /* Deactivate PXE */ - pxe_deactivate(); - - /* Prepare for unload */ - shutdown ( SHUTDOWN_BOOT ); - - /* Check to see if we still have any hooked interrupts */ - if ( hooked_bios_interrupts != 0 ) { - DBG ( "PXENV_STOP_UNDI failed: %d interrupts still hooked\n", - hooked_bios_interrupts ); - stop_undi->Status = PXENV_STATUS_KEEP_UNDI; - return PXENV_EXIT_FAILURE; - } - - stop_undi->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_START_BASE - * - * Status: won't implement (requires major structural changes) - */ -PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ) { - DBG ( "PXENV_START_BASE" ); - - start_base->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -} - -/* PXENV_STOP_BASE - * - * Status: working - */ -PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ) { - DBG ( "PXENV_STOP_BASE" ); - - /* The only time we will be called is when the NBP is trying - * to shut down the PXE stack. There's nothing we need to do - * in this call. - */ - - stop_base->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c b/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c deleted file mode 100644 index 0e3ca3c5..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c +++ /dev/null @@ -1,586 +0,0 @@ -/** @file - * - * PXE TFTP API - * - */ - -/* - * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <byteswap.h> -#include <gpxe/uaccess.h> -#include <gpxe/in.h> -#include <gpxe/tftp.h> -#include <gpxe/xfer.h> -#include <gpxe/open.h> -#include <gpxe/process.h> -#include <pxe.h> - -/** A PXE TFTP connection */ -struct pxe_tftp_connection { - /** Data transfer interface */ - struct xfer_interface xfer; - /** Data buffer */ - userptr_t buffer; - /** Size of data buffer */ - size_t size; - /** Starting offset of data buffer */ - size_t start; - /** File position */ - size_t offset; - /** Maximum file position */ - size_t max_offset; - /** Block size */ - size_t blksize; - /** Block index */ - unsigned int blkidx; - /** Overall return status code */ - int rc; -}; - -/** The PXE TFTP connection */ -static struct pxe_tftp_connection pxe_tftp = { - .xfer = XFER_INIT ( &null_xfer_ops ), -}; - -/** - * Close PXE TFTP connection - * - * @v rc Final status code - */ -static void pxe_tftp_close ( int rc ) { - xfer_nullify ( &pxe_tftp.xfer ); - xfer_close ( &pxe_tftp.xfer, rc ); - pxe_tftp.rc = rc; -} - -/** - * Receive new data - * - * @v xfer Data transfer interface - * @v iobuf I/O buffer - * @v meta Transfer metadata - * @ret rc Return status code - */ -static int pxe_tftp_xfer_deliver_iob ( struct xfer_interface *xfer __unused, - struct io_buffer *iobuf, - struct xfer_metadata *meta ) { - size_t len = iob_len ( iobuf ); - int rc = 0; - - /* Calculate new buffer position */ - if ( meta->whence != SEEK_CUR ) - pxe_tftp.offset = 0; - pxe_tftp.offset += meta->offset; - - /* Copy data block to buffer */ - if ( len == 0 ) { - /* No data (pure seek); treat as success */ - } else if ( pxe_tftp.offset < pxe_tftp.start ) { - DBG ( " buffer underrun at %zx (min %zx)", - pxe_tftp.offset, pxe_tftp.start ); - rc = -ENOBUFS; - } else if ( ( pxe_tftp.offset + len ) > - ( pxe_tftp.start + pxe_tftp.size ) ) { - DBG ( " buffer overrun at %zx (max %zx)", - ( pxe_tftp.offset + len ), - ( pxe_tftp.start + pxe_tftp.size ) ); - rc = -ENOBUFS; - } else { - copy_to_user ( pxe_tftp.buffer, - ( pxe_tftp.offset - pxe_tftp.start ), - iobuf->data, len ); - } - - /* Calculate new buffer position */ - pxe_tftp.offset += len; - - /* Record maximum offset as the file size */ - if ( pxe_tftp.max_offset < pxe_tftp.offset ) - pxe_tftp.max_offset = pxe_tftp.offset; - - /* Terminate transfer on error */ - if ( rc != 0 ) - pxe_tftp_close ( rc ); - - free_iob ( iobuf ); - return rc; -} - -/** - * Handle close() event - * - * @v xfer Data transfer interface - * @v rc Reason for close - */ -static void pxe_tftp_xfer_close ( struct xfer_interface *xfer __unused, - int rc ) { - pxe_tftp_close ( rc ); -} - -static struct xfer_interface_operations pxe_tftp_xfer_ops = { - .close = pxe_tftp_xfer_close, - .vredirect = xfer_vreopen, - .window = unlimited_xfer_window, - .alloc_iob = default_xfer_alloc_iob, - .deliver_iob = pxe_tftp_xfer_deliver_iob, - .deliver_raw = xfer_deliver_as_iob, -}; - -/** - * Maximum length of a PXE TFTP URI - * - * The PXE TFTP API provides 128 characters for the filename; the - * extra 128 bytes allow for the remainder of the URI. - */ -#define PXE_TFTP_URI_LEN 256 - -/** - * Open PXE TFTP connection - * - * @v ipaddress IP address - * @v port TFTP server port - * @v filename File name - * @v blksize Requested block size - * @ret rc Return status code - */ -static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port, - const unsigned char *filename, size_t blksize, - int sizeonly ) { - char uri_string[PXE_TFTP_URI_LEN]; - struct in_addr address; - int rc; - - /* Intel bug-for-bug hack */ - pxe_set_cached_filename ( filename ); - - /* Reset PXE TFTP connection structure */ - memset ( &pxe_tftp, 0, sizeof ( pxe_tftp ) ); - xfer_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_ops, NULL ); - 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 ); - DBG ( " %s", uri_string ); - - /* Open PXE TFTP connection */ - if ( ( rc = xfer_open_uri_string ( &pxe_tftp.xfer, - uri_string ) ) != 0 ) { - DBG ( " could not open (%s)\n", strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * TFTP OPEN - * - * @v tftp_open Pointer to a struct s_PXENV_TFTP_OPEN - * @v s_PXENV_TFTP_OPEN::ServerIPAddress TFTP server IP address - * @v s_PXENV_TFTP_OPEN::GatewayIPAddress Relay agent IP address, or 0.0.0.0 - * @v s_PXENV_TFTP_OPEN::FileName Name of file to open - * @v s_PXENV_TFTP_OPEN::TFTPPort TFTP server UDP port - * @v s_PXENV_TFTP_OPEN::PacketSize TFTP blksize option to request - * @ret #PXENV_EXIT_SUCCESS File was opened - * @ret #PXENV_EXIT_FAILURE File was not opened - * @ret s_PXENV_TFTP_OPEN::Status PXE status code - * @ret s_PXENV_TFTP_OPEN::PacketSize Negotiated blksize - * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Requested blksize too small - * - * Opens a TFTP connection for downloading a file a block at a time - * using pxenv_tftp_read(). - * - * If s_PXENV_TFTP_OPEN::GatewayIPAddress is 0.0.0.0, normal IP - * routing will take place. See the relevant - * @ref pxe_routing "implementation note" for more details. - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - * - * @note According to the PXE specification version 2.1, this call - * "opens a file for reading/writing", though how writing is to be - * achieved without the existence of an API call %pxenv_tftp_write() - * is not made clear. - * - * @note Despite the existence of the numerous statements within the - * PXE specification of the form "...if a TFTP/MTFTP or UDP connection - * is active...", you cannot use pxenv_tftp_open() and - * pxenv_tftp_read() to read a file via MTFTP; only via plain old - * TFTP. If you want to use MTFTP, use pxenv_tftp_read_file() - * instead. Astute readers will note that, since - * pxenv_tftp_read_file() is an atomic operation from the point of - * view of the PXE API, it is conceptually impossible to issue any - * other PXE API call "if an MTFTP connection is active". - */ -PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) { - int rc; - - DBG ( "PXENV_TFTP_OPEN" ); - - /* Guard against callers that fail to close before re-opening */ - pxe_tftp_close ( 0 ); - - /* Open connection */ - if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress, - tftp_open->TFTPPort, - tftp_open->FileName, - tftp_open->PacketSize, - 0) ) != 0 ) { - tftp_open->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - /* Wait for OACK to arrive so that we have the block size */ - while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) && - ( pxe_tftp.max_offset == 0 ) ) { - step(); - } - pxe_tftp.blksize = xfer_window ( &pxe_tftp.xfer ); - tftp_open->PacketSize = pxe_tftp.blksize; - DBG ( " blksize=%d", tftp_open->PacketSize ); - - /* EINPROGRESS is normal; we don't wait for the whole transfer */ - if ( rc == -EINPROGRESS ) - rc = 0; - - tftp_open->Status = PXENV_STATUS ( rc ); - return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS ); -} - -/** - * TFTP CLOSE - * - * @v tftp_close Pointer to a struct s_PXENV_TFTP_CLOSE - * @ret #PXENV_EXIT_SUCCESS File was closed successfully - * @ret #PXENV_EXIT_FAILURE File was not closed - * @ret s_PXENV_TFTP_CLOSE::Status PXE status code - * @err None - - * - * Close a connection previously opened with pxenv_tftp_open(). You - * must have previously opened a connection with pxenv_tftp_open(). - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - */ -PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) { - DBG ( "PXENV_TFTP_CLOSE" ); - - pxe_tftp_close ( 0 ); - tftp_close->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * TFTP READ - * - * @v tftp_read Pointer to a struct s_PXENV_TFTP_READ - * @v s_PXENV_TFTP_READ::Buffer Address of data buffer - * @ret #PXENV_EXIT_SUCCESS Data was read successfully - * @ret #PXENV_EXIT_FAILURE Data was not read - * @ret s_PXENV_TFTP_READ::Status PXE status code - * @ret s_PXENV_TFTP_READ::PacketNumber TFTP packet number - * @ret s_PXENV_TFTP_READ::BufferSize Length of data written into buffer - * - * Reads a single packet from a connection previously opened with - * pxenv_tftp_open() into the data buffer pointed to by - * s_PXENV_TFTP_READ::Buffer. You must have previously opened a - * connection with pxenv_tftp_open(). The data written into - * s_PXENV_TFTP_READ::Buffer is just the file data; the various - * network headers have already been removed. - * - * The buffer must be large enough to contain a packet of the size - * negotiated via the s_PXENV_TFTP_OPEN::PacketSize field in the - * pxenv_tftp_open() call. It is worth noting that the PXE - * specification does @b not require the caller to fill in - * s_PXENV_TFTP_READ::BufferSize before calling pxenv_tftp_read(), so - * the PXE stack is free to ignore whatever value the caller might - * place there and just assume that the buffer is large enough. That - * said, it may be worth the caller always filling in - * s_PXENV_TFTP_READ::BufferSize to guard against PXE stacks that - * mistake it for an input parameter. - * - * The length of the TFTP data packet will be returned via - * s_PXENV_TFTP_READ::BufferSize. If this length is less than the - * blksize negotiated via s_PXENV_TFTP_OPEN::PacketSize in the call to - * pxenv_tftp_open(), this indicates that the block is the last block - * in the file. Note that zero is a valid length for - * s_PXENV_TFTP_READ::BufferSize, and will occur when the length of - * the file is a multiple of the blksize. - * - * The PXE specification doesn't actually state that calls to - * pxenv_tftp_read() will return the data packets in strict sequential - * order, though most PXE stacks will probably do so. The sequence - * number of the packet will be returned in - * s_PXENV_TFTP_READ::PacketNumber. The first packet in the file has - * a sequence number of one, not zero. - * - * To guard against flawed PXE stacks, the caller should probably set - * s_PXENV_TFTP_READ::PacketNumber to one less than the expected - * returned value (i.e. set it to zero for the first call to - * pxenv_tftp_read() and then re-use the returned s_PXENV_TFTP_READ - * parameter block for subsequent calls without modifying - * s_PXENV_TFTP_READ::PacketNumber between calls). The caller should - * also guard against potential problems caused by flawed - * implementations returning the occasional duplicate packet, by - * checking that the value returned in s_PXENV_TFTP_READ::PacketNumber - * is as expected (i.e. one greater than that returned from the - * previous call to pxenv_tftp_read()). - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - */ -PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) { - int rc; - - DBG ( "PXENV_TFTP_READ to %04x:%04x", - tftp_read->Buffer.segment, tftp_read->Buffer.offset ); - - /* Read single block into buffer */ - pxe_tftp.buffer = real_to_user ( tftp_read->Buffer.segment, - tftp_read->Buffer.offset ); - pxe_tftp.size = pxe_tftp.blksize; - pxe_tftp.start = pxe_tftp.offset; - while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) && - ( pxe_tftp.offset == pxe_tftp.start ) ) - step(); - pxe_tftp.buffer = UNULL; - tftp_read->BufferSize = ( pxe_tftp.offset - pxe_tftp.start ); - tftp_read->PacketNumber = ++pxe_tftp.blkidx; - - /* EINPROGRESS is normal if we haven't reached EOF yet */ - if ( rc == -EINPROGRESS ) - rc = 0; - - tftp_read->Status = PXENV_STATUS ( rc ); - return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS ); -} - -/** - * TFTP/MTFTP read file - * - * @v tftp_read_file Pointer to a struct s_PXENV_TFTP_READ_FILE - * @v s_PXENV_TFTP_READ_FILE::FileName File name - * @v s_PXENV_TFTP_READ_FILE::BufferSize Size of the receive buffer - * @v s_PXENV_TFTP_READ_FILE::Buffer Address of the receive buffer - * @v s_PXENV_TFTP_READ_FILE::ServerIPAddress TFTP server IP address - * @v s_PXENV_TFTP_READ_FILE::GatewayIPAddress Relay agent IP address - * @v s_PXENV_TFTP_READ_FILE::McastIPAddress File's multicast IP address - * @v s_PXENV_TFTP_READ_FILE::TFTPClntPort Client multicast UDP port - * @v s_PXENV_TFTP_READ_FILE::TFTPSrvPort Server multicast UDP port - * @v s_PXENV_TFTP_READ_FILE::TFTPOpenTimeOut Time to wait for first packet - * @v s_PXENV_TFTP_READ_FILE::TFTPReopenDelay MTFTP inactivity timeout - * @ret #PXENV_EXIT_SUCCESS File downloaded successfully - * @ret #PXENV_EXIT_FAILURE File not downloaded - * @ret s_PXENV_TFTP_READ_FILE::Status PXE status code - * @ret s_PXENV_TFTP_READ_FILE::BufferSize Length of downloaded file - * - * Downloads an entire file via either TFTP or MTFTP into the buffer - * pointed to by s_PXENV_TFTP_READ_FILE::Buffer. - * - * The PXE specification does not make it clear how the caller - * requests that MTFTP be used rather than TFTP (or vice versa). One - * reasonable guess is that setting - * s_PXENV_TFTP_READ_FILE::McastIPAddress to 0.0.0.0 would cause TFTP - * to be used instead of MTFTP, though it is conceivable that some PXE - * stacks would interpret that as "use the DHCP-provided multicast IP - * address" instead. Some PXE stacks will not implement MTFTP at all, - * and will always use TFTP. - * - * It is not specified whether or not - * s_PXENV_TFTP_READ_FILE::TFTPSrvPort will be used as the TFTP server - * port for TFTP (rather than MTFTP) downloads. Callers should assume - * that the only way to access a TFTP server on a non-standard port is - * to use pxenv_tftp_open() and pxenv_tftp_read(). - * - * If s_PXENV_TFTP_READ_FILE::GatewayIPAddress is 0.0.0.0, normal IP - * routing will take place. See the relevant - * @ref pxe_routing "implementation note" for more details. - * - * It is interesting to note that s_PXENV_TFTP_READ_FILE::Buffer is an - * #ADDR32_t type, i.e. nominally a flat physical address. Some PXE - * NBPs (e.g. NTLDR) are known to call pxenv_tftp_read_file() in real - * mode with s_PXENV_TFTP_READ_FILE::Buffer set to an address above - * 1MB. This means that PXE stacks must be prepared to write to areas - * outside base memory. Exactly how this is to be achieved is not - * specified, though using INT 15,87 is as close to a standard method - * as any, and should probably be used. Switching to protected-mode - * in order to access high memory will fail if pxenv_tftp_read_file() - * is called in V86 mode; it is reasonably to expect that a V86 - * monitor would intercept the relatively well-defined INT 15,87 if it - * wants the PXE stack to be able to write to high memory. - * - * Things get even more interesting if pxenv_tftp_read_file() is - * called in protected mode, because there is then absolutely no way - * for the PXE stack to write to an absolute physical address. You - * can't even get around the problem by creating a special "access - * everything" segment in the s_PXE data structure, because the - * #SEGDESC_t descriptors are limited to 64kB in size. - * - * Previous versions of the PXE specification (e.g. WfM 1.1a) provide - * a separate API call, %pxenv_tftp_read_file_pmode(), specifically to - * work around this problem. The s_PXENV_TFTP_READ_FILE_PMODE - * parameter block splits s_PXENV_TFTP_READ_FILE::Buffer into - * s_PXENV_TFTP_READ_FILE_PMODE::BufferSelector and - * s_PXENV_TFTP_READ_FILE_PMODE::BufferOffset, i.e. it provides a - * protected-mode segment:offset address for the data buffer. This - * API call is no longer present in version 2.1 of the PXE - * specification. - * - * Etherboot makes the assumption that s_PXENV_TFTP_READ_FILE::Buffer - * is an offset relative to the caller's data segment, when - * pxenv_tftp_read_file() is called in protected mode. - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - * - * @note Microsoft's NTLDR assumes that the filename passed in via - * s_PXENV_TFTP_READ_FILE::FileName will be stored in the "file" field - * of the stored DHCPACK packet, whence it will be returned via any - * subsequent calls to pxenv_get_cached_info(). Though this is - * essentially a bug in the Intel PXE implementation (not, for once, - * in the specification!), it is a bug that Microsoft relies upon, and - * so we implement this bug-for-bug compatibility by overwriting the - * filename stored DHCPACK packet with the filename passed in - * s_PXENV_TFTP_READ_FILE::FileName. - * - */ -PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE - *tftp_read_file ) { - int rc; - - DBG ( "PXENV_TFTP_READ_FILE to %08x+%x", tftp_read_file->Buffer, - tftp_read_file->BufferSize ); - - /* Open TFTP file */ - if ( ( rc = pxe_tftp_open ( tftp_read_file->ServerIPAddress, 0, - tftp_read_file->FileName, 0, 0 ) ) != 0 ) { - tftp_read_file->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - /* Read entire file */ - pxe_tftp.buffer = phys_to_user ( tftp_read_file->Buffer ); - pxe_tftp.size = tftp_read_file->BufferSize; - while ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) - step(); - pxe_tftp.buffer = UNULL; - tftp_read_file->BufferSize = pxe_tftp.max_offset; - - /* Close TFTP file */ - pxe_tftp_close ( rc ); - - tftp_read_file->Status = PXENV_STATUS ( rc ); - return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS ); -} - -/** - * TFTP GET FILE SIZE - * - * @v tftp_get_fsize Pointer to a struct s_PXENV_TFTP_GET_FSIZE - * @v s_PXENV_TFTP_GET_FSIZE::ServerIPAddress TFTP server IP address - * @v s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress Relay agent IP address - * @v s_PXENV_TFTP_GET_FSIZE::FileName File name - * @ret #PXENV_EXIT_SUCCESS File size was determined successfully - * @ret #PXENV_EXIT_FAILURE File size was not determined - * @ret s_PXENV_TFTP_GET_FSIZE::Status PXE status code - * @ret s_PXENV_TFTP_GET_FSIZE::FileSize File size - * - * Determine the size of a file on a TFTP server. This uses the - * "tsize" TFTP option, and so will not work with a TFTP server that - * does not support TFTP options, or that does not support the "tsize" - * option. - * - * The PXE specification states that this API call will @b not open a - * TFTP connection for subsequent use with pxenv_tftp_read(). (This - * is somewhat daft, since the only way to obtain the file size via - * the "tsize" option involves issuing a TFTP open request, but that's - * life.) - * - * You cannot call pxenv_tftp_get_fsize() while a TFTP or UDP - * connection is open. - * - * If s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress is 0.0.0.0, normal IP - * routing will take place. See the relevant - * @ref pxe_routing "implementation note" for more details. - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - * - * @note There is no way to specify the TFTP server port with this API - * call. Though you can open a file using a non-standard TFTP server - * port (via s_PXENV_TFTP_OPEN::TFTPPort or, potentially, - * s_PXENV_TFTP_READ_FILE::TFTPSrvPort), you can only get the size of - * a file from a TFTP server listening on the standard TFTP port. - * "Consistency" is not a word in Intel's vocabulary. - */ -PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE - *tftp_get_fsize ) { - int rc; - - DBG ( "PXENV_TFTP_GET_FSIZE" ); - - /* Open TFTP file */ - if ( ( rc = pxe_tftp_open ( tftp_get_fsize->ServerIPAddress, 0, - tftp_get_fsize->FileName, 0, 1 ) ) != 0 ) { - tftp_get_fsize->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - /* Wait for initial seek to arrive, and record size */ - while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) && - ( pxe_tftp.max_offset == 0 ) ) { - step(); - } - tftp_get_fsize->FileSize = pxe_tftp.max_offset; - DBG ( " fsize=%d", tftp_get_fsize->FileSize ); - - /* EINPROGRESS is normal; we don't wait for the whole transfer */ - if ( rc == -EINPROGRESS ) - rc = 0; - - /* Close TFTP file */ - pxe_tftp_close ( rc ); - - tftp_get_fsize->Status = PXENV_STATUS ( rc ); - return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS ); -} diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_udp.c b/gpxe/src/arch/i386/interface/pxe/pxe_udp.c deleted file mode 100644 index f4702201..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_udp.c +++ /dev/null @@ -1,405 +0,0 @@ -/** @file - * - * PXE UDP API - * - */ - -#include <string.h> -#include <byteswap.h> -#include <gpxe/xfer.h> -#include <gpxe/udp.h> -#include <gpxe/uaccess.h> -#include <gpxe/process.h> -#include <pxe.h> - -/* - * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/** A PXE UDP connection */ -struct pxe_udp_connection { - /** Data transfer interface to UDP stack */ - struct xfer_interface xfer; - /** Local address */ - struct sockaddr_in local; - /** Current PXENV_UDP_READ parameter block */ - struct s_PXENV_UDP_READ *pxenv_udp_read; -}; - -/** - * Receive PXE UDP data - * - * @v xfer Data transfer interface - * @v iobuf I/O buffer - * @v meta Data transfer metadata - * @ret rc Return status code - * - * Receives a packet as part of the current pxenv_udp_read() - * operation. - */ -static int pxe_udp_deliver_iob ( struct xfer_interface *xfer, - struct io_buffer *iobuf, - struct xfer_metadata *meta ) { - struct pxe_udp_connection *pxe_udp = - container_of ( xfer, struct pxe_udp_connection, xfer ); - struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read; - struct sockaddr_in *sin_src; - struct sockaddr_in *sin_dest; - userptr_t buffer; - size_t len; - int rc = 0; - - if ( ! pxenv_udp_read ) { - DBG ( "PXE discarded UDP packet\n" ); - rc = -ENOBUFS; - goto done; - } - - /* Copy packet to buffer and record length */ - buffer = real_to_user ( pxenv_udp_read->buffer.segment, - pxenv_udp_read->buffer.offset ); - len = iob_len ( iobuf ); - if ( len > pxenv_udp_read->buffer_size ) - len = pxenv_udp_read->buffer_size; - copy_to_user ( buffer, 0, iobuf->data, len ); - pxenv_udp_read->buffer_size = len; - - /* Fill in source/dest information */ - assert ( meta ); - sin_src = ( struct sockaddr_in * ) meta->src; - assert ( sin_src ); - assert ( sin_src->sin_family == AF_INET ); - pxenv_udp_read->src_ip = sin_src->sin_addr.s_addr; - pxenv_udp_read->s_port = sin_src->sin_port; - sin_dest = ( struct sockaddr_in * ) meta->dest; - assert ( sin_dest ); - assert ( sin_dest->sin_family == AF_INET ); - pxenv_udp_read->dest_ip = sin_dest->sin_addr.s_addr; - pxenv_udp_read->d_port = sin_dest->sin_port; - - /* Mark as received */ - pxe_udp->pxenv_udp_read = NULL; - - done: - free_iob ( iobuf ); - return rc; -} - -/** PXE UDP data transfer interface operations */ -static struct xfer_interface_operations pxe_udp_xfer_operations = { - .close = ignore_xfer_close, - .vredirect = ignore_xfer_vredirect, - .window = unlimited_xfer_window, - .alloc_iob = default_xfer_alloc_iob, - .deliver_iob = pxe_udp_deliver_iob, - .deliver_raw = xfer_deliver_as_iob, -}; - -/** The PXE UDP connection */ -static struct pxe_udp_connection pxe_udp = { - .xfer = XFER_INIT ( &pxe_udp_xfer_operations ), - .local = { - .sin_family = AF_INET, - }, -}; - -/** - * UDP OPEN - * - * @v pxenv_udp_open Pointer to a struct s_PXENV_UDP_OPEN - * @v s_PXENV_UDP_OPEN::src_ip IP address of this station, or 0.0.0.0 - * @ret #PXENV_EXIT_SUCCESS Always - * @ret s_PXENV_UDP_OPEN::Status PXE status code - * @err #PXENV_STATUS_UDP_OPEN UDP connection already open - * @err #PXENV_STATUS_OUT_OF_RESOURCES Could not open connection - * - * Prepares the PXE stack for communication using pxenv_udp_write() - * and pxenv_udp_read(). - * - * The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be - * recorded and used as the local station's IP address for all further - * communication, including communication by means other than - * pxenv_udp_write() and pxenv_udp_read(). (If - * s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address - * will remain unchanged.) - * - * You can only have one open UDP connection at a time. This is not a - * meaningful restriction, since pxenv_udp_write() and - * pxenv_udp_read() allow you to specify arbitrary local and remote - * ports and an arbitrary remote address for each packet. According - * to the PXE specifiation, you cannot have a UDP connection open at - * the same time as a TFTP connection; this restriction does not apply - * to Etherboot. - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - * - * @note The PXE specification does not make it clear whether the IP - * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only - * for this UDP connection, or retained for all future communication. - * The latter seems more consistent with typical PXE stack behaviour. - * - * @note Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip - * parameter. - * - */ -PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) { - int rc; - - DBG ( "PXENV_UDP_OPEN" ); - - /* Record source IP address */ - pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip; - DBG ( " %s", inet_ntoa ( pxe_udp.local.sin_addr ) ); - - /* Open promiscuous UDP connection */ - xfer_close ( &pxe_udp.xfer, 0 ); - if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) { - pxenv_udp_open->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - pxenv_udp_open->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * UDP CLOSE - * - * @v pxenv_udp_close Pointer to a struct s_PXENV_UDP_CLOSE - * @ret #PXENV_EXIT_SUCCESS Always - * @ret s_PXENV_UDP_CLOSE::Status PXE status code - * @err None - - * - * Closes a UDP connection opened with pxenv_udp_open(). - * - * You can only have one open UDP connection at a time. You cannot - * have a UDP connection open at the same time as a TFTP connection. - * You cannot use pxenv_udp_close() to close a TFTP connection; use - * pxenv_tftp_close() instead. - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - * - */ -PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) { - DBG ( "PXENV_UDP_CLOSE" ); - - /* Close UDP connection */ - xfer_close ( &pxe_udp.xfer, 0 ); - - pxenv_udp_close->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * UDP WRITE - * - * @v pxenv_udp_write Pointer to a struct s_PXENV_UDP_WRITE - * @v s_PXENV_UDP_WRITE::ip Destination IP address - * @v s_PXENV_UDP_WRITE::gw Relay agent IP address, or 0.0.0.0 - * @v s_PXENV_UDP_WRITE::src_port Source UDP port, or 0 - * @v s_PXENV_UDP_WRITE::dst_port Destination UDP port - * @v s_PXENV_UDP_WRITE::buffer_size Length of the UDP payload - * @v s_PXENV_UDP_WRITE::buffer Address of the UDP payload - * @ret #PXENV_EXIT_SUCCESS Packet was transmitted successfully - * @ret #PXENV_EXIT_FAILURE Packet could not be transmitted - * @ret s_PXENV_UDP_WRITE::Status PXE status code - * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open - * @err #PXENV_STATUS_UNDI_TRANSMIT_ERROR Could not transmit packet - * - * Transmits a single UDP packet. A valid IP and UDP header will be - * prepended to the payload in s_PXENV_UDP_WRITE::buffer; the buffer - * should not contain precomputed IP and UDP headers, nor should it - * contain space allocated for these headers. The first byte of the - * buffer will be transmitted as the first byte following the UDP - * header. - * - * If s_PXENV_UDP_WRITE::gw is 0.0.0.0, normal IP routing will take - * place. See the relevant @ref pxe_routing "implementation note" for - * more details. - * - * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used. - * - * You must have opened a UDP connection with pxenv_udp_open() before - * calling pxenv_udp_write(). - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - * - * @note Etherboot currently ignores the s_PXENV_UDP_WRITE::gw - * parameter. - * - */ -PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) { - struct sockaddr_in dest; - struct xfer_metadata meta = { - .src = ( struct sockaddr * ) &pxe_udp.local, - .dest = ( struct sockaddr * ) &dest, - .netdev = pxe_netdev, - }; - size_t len; - struct io_buffer *iobuf; - userptr_t buffer; - int rc; - - DBG ( "PXENV_UDP_WRITE" ); - - /* Construct destination socket address */ - memset ( &dest, 0, sizeof ( dest ) ); - dest.sin_family = AF_INET; - dest.sin_addr.s_addr = pxenv_udp_write->ip; - dest.sin_port = pxenv_udp_write->dst_port; - - /* Set local (source) port. PXE spec says source port is 2069 - * if not specified. Really, this ought to be set at UDP open - * time but hey, we didn't design this API. - */ - pxe_udp.local.sin_port = pxenv_udp_write->src_port; - if ( ! pxe_udp.local.sin_port ) - pxe_udp.local.sin_port = htons ( 2069 ); - - /* FIXME: we ignore the gateway specified, since we're - * confident of being able to do our own routing. We should - * probably allow for multiple gateways. - */ - - /* Allocate and fill data buffer */ - len = pxenv_udp_write->buffer_size; - iobuf = xfer_alloc_iob ( &pxe_udp.xfer, len ); - if ( ! iobuf ) { - pxenv_udp_write->Status = PXENV_STATUS_OUT_OF_RESOURCES; - return PXENV_EXIT_FAILURE; - } - buffer = real_to_user ( pxenv_udp_write->buffer.segment, - pxenv_udp_write->buffer.offset ); - copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len ); - - DBG ( " %04x:%04x+%x %d->%s:%d", pxenv_udp_write->buffer.segment, - pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size, - ntohs ( pxenv_udp_write->src_port ), - inet_ntoa ( dest.sin_addr ), - ntohs ( pxenv_udp_write->dst_port ) ); - - /* Transmit packet */ - if ( ( rc = xfer_deliver_iob_meta ( &pxe_udp.xfer, iobuf, - &meta ) ) != 0 ) { - pxenv_udp_write->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - pxenv_udp_write->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** - * UDP READ - * - * @v pxenv_udp_read Pointer to a struct s_PXENV_UDP_READ - * @v s_PXENV_UDP_READ::dest_ip Destination IP address, or 0.0.0.0 - * @v s_PXENV_UDP_READ::d_port Destination UDP port, or 0 - * @v s_PXENV_UDP_READ::buffer_size Size of the UDP payload buffer - * @v s_PXENV_UDP_READ::buffer Address of the UDP payload buffer - * @ret #PXENV_EXIT_SUCCESS A packet has been received - * @ret #PXENV_EXIT_FAILURE No packet has been received - * @ret s_PXENV_UDP_READ::Status PXE status code - * @ret s_PXENV_UDP_READ::src_ip Source IP address - * @ret s_PXENV_UDP_READ::dest_ip Destination IP address - * @ret s_PXENV_UDP_READ::s_port Source UDP port - * @ret s_PXENV_UDP_READ::d_port Destination UDP port - * @ret s_PXENV_UDP_READ::buffer_size Length of UDP payload - * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open - * @err #PXENV_STATUS_FAILURE No packet was ready to read - * - * Receive a single UDP packet. This is a non-blocking call; if no - * packet is ready to read, the call will return instantly with - * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE. - * - * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to - * any IP address will be accepted and may be returned to the caller. - * - * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP - * port will be accepted and may be returned to the caller. - * - * You must have opened a UDP connection with pxenv_udp_open() before - * calling pxenv_udp_read(). - * - * On x86, you must set the s_PXE::StatusCallout field to a nonzero - * value before calling this function in protected mode. You cannot - * call this function with a 32-bit stack segment. (See the relevant - * @ref pxe_x86_pmode16 "implementation note" for more details.) - * - * @note The PXE specification (version 2.1) does not state that we - * should fill in s_PXENV_UDP_READ::dest_ip and - * s_PXENV_UDP_READ::d_port, but Microsoft Windows' NTLDR program - * expects us to do so, and will fail if we don't. - * - */ -PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) { - struct in_addr dest_ip_wanted = { .s_addr = pxenv_udp_read->dest_ip }; - struct in_addr dest_ip; - uint16_t d_port_wanted = pxenv_udp_read->d_port; - uint16_t d_port; - - DBG ( "PXENV_UDP_READ" ); - - /* Try receiving a packet */ - pxe_udp.pxenv_udp_read = pxenv_udp_read; - step(); - if ( pxe_udp.pxenv_udp_read ) { - /* No packet received */ - pxe_udp.pxenv_udp_read = NULL; - goto no_packet; - } - dest_ip.s_addr = pxenv_udp_read->dest_ip; - d_port = pxenv_udp_read->d_port; - - /* Filter on destination address and/or port */ - if ( dest_ip_wanted.s_addr && - ( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) { - DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) ); - DBG ( " (wanted %s)", inet_ntoa ( dest_ip_wanted ) ); - goto no_packet; - } - if ( d_port_wanted && ( d_port_wanted != d_port ) ) { - DBG ( " wrong port %d ", htons ( d_port ) ); - DBG ( " (wanted %d)", htons ( d_port_wanted ) ); - goto no_packet; - } - - DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment, - pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size, - inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) )); - DBG ( "%d<-%s:%d", ntohs ( pxenv_udp_read->s_port ), - inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ), - ntohs ( pxenv_udp_read->d_port ) ); - - pxenv_udp_read->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; - - no_packet: - pxenv_udp_read->Status = PXENV_STATUS_FAILURE; - return PXENV_EXIT_FAILURE; -} diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_undi.c b/gpxe/src/arch/i386/interface/pxe/pxe_undi.c deleted file mode 100644 index c9b67c06..00000000 --- a/gpxe/src/arch/i386/interface/pxe/pxe_undi.c +++ /dev/null @@ -1,791 +0,0 @@ -/** @file - * - * PXE UNDI API - * - */ - -/* - * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <byteswap.h> -#include <basemem_packet.h> -#include <gpxe/netdevice.h> -#include <gpxe/iobuf.h> -#include <gpxe/device.h> -#include <gpxe/pci.h> -#include <gpxe/if_ether.h> -#include <gpxe/ip.h> -#include <gpxe/arp.h> -#include <gpxe/rarp.h> -#include "pxe.h" - -/** - * Count of outstanding transmitted packets - * - * This is incremented each time PXENV_UNDI_TRANSMIT is called, and - * decremented each time that PXENV_UNDI_ISR is called with the TX - * queue empty, stopping when the count reaches zero. This allows us - * to provide a pessimistic approximation of TX completion events to - * the PXE NBP simply by monitoring the netdev's TX queue. - */ -static int undi_tx_count = 0; - -struct net_device *pxe_netdev = NULL; - -/** - * Set network device as current PXE network device - * - * @v netdev Network device, or NULL - */ -void pxe_set_netdev ( struct net_device *netdev ) { - if ( pxe_netdev ) - netdev_put ( pxe_netdev ); - pxe_netdev = NULL; - if ( netdev ) - pxe_netdev = netdev_get ( netdev ); -} - -/** - * Open PXE network device - * - * @ret rc Return status code - */ -static int pxe_netdev_open ( void ) { - int rc; - - if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 ) - return rc; - - netdev_irq ( pxe_netdev, 1 ); - return 0; -} - -/** - * Close PXE network device - * - */ -static void pxe_netdev_close ( void ) { - netdev_irq ( pxe_netdev, 0 ); - netdev_close ( pxe_netdev ); - undi_tx_count = 0; -} - -/** - * Dump multicast address list - * - * @v mcast PXE multicast address list - */ -static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) { - struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; - unsigned int i; - - for ( i = 0 ; i < mcast->MCastAddrCount ; i++ ) { - DBG ( " %s", ll_protocol->ntoa ( mcast->McastAddr[i] ) ); - } -} - -/* PXENV_UNDI_STARTUP - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) { - DBG ( "PXENV_UNDI_STARTUP\n" ); - - undi_startup->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_CLEANUP - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) { - DBG ( "PXENV_UNDI_CLEANUP\n" ); - - pxe_netdev_close(); - - undi_cleanup->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_INITIALIZE - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE - *undi_initialize ) { - DBG ( "PXENV_UNDI_INITIALIZE protocolini %08x\n", - undi_initialize->ProtocolIni ); - - undi_initialize->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_RESET_ADAPTER - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET - *undi_reset_adapter ) { - int rc; - - DBG ( "PXENV_UNDI_RESET_ADAPTER" ); - pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf ); - DBG ( "\n" ); - - pxe_netdev_close(); - if ( ( rc = pxe_netdev_open() ) != 0 ) { - DBG ( "PXENV_UNDI_RESET_ADAPTER could not reopen %s: %s\n", - pxe_netdev->name, strerror ( rc ) ); - undi_reset_adapter->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - undi_reset_adapter->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SHUTDOWN - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN - *undi_shutdown ) { - DBG ( "PXENV_UNDI_SHUTDOWN\n" ); - - pxe_netdev_close(); - - undi_shutdown->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_OPEN - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) { - int rc; - - DBG ( "PXENV_UNDI_OPEN flag %04x filter %04x", - undi_open->OpenFlag, undi_open->PktFilter ); - pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf ); - DBG ( "\n" ); - - if ( ( rc = pxe_netdev_open() ) != 0 ) { - DBG ( "PXENV_UNDI_OPEN could not open %s: %s\n", - pxe_netdev->name, strerror ( rc ) ); - undi_open->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - undi_open->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_CLOSE - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) { - DBG ( "PXENV_UNDI_CLOSE\n" ); - - pxe_netdev_close(); - - undi_close->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_TRANSMIT - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT - *undi_transmit ) { - struct s_PXENV_UNDI_TBD tbd; - struct DataBlk *datablk; - struct io_buffer *iobuf; - struct net_protocol *net_protocol; - struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; - char destaddr[MAX_LL_ADDR_LEN]; - const void *ll_dest; - size_t ll_hlen = ll_protocol->ll_header_len; - size_t len; - unsigned int i; - int rc; - - DBG2 ( "PXENV_UNDI_TRANSMIT" ); - - /* Forcibly enable interrupts at this point, to work around - * callers that never call PXENV_UNDI_OPEN before attempting - * to use the UNDI API. - */ - netdev_irq ( pxe_netdev, 1 ); - - /* Identify network-layer protocol */ - switch ( undi_transmit->Protocol ) { - case P_IP: net_protocol = &ipv4_protocol; break; - case P_ARP: net_protocol = &arp_protocol; break; - case P_RARP: net_protocol = &rarp_protocol; break; - case P_UNKNOWN: - net_protocol = NULL; - ll_hlen = 0; - break; - default: - DBG2 ( " %02x invalid protocol\n", undi_transmit->Protocol ); - undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER; - return PXENV_EXIT_FAILURE; - } - DBG2 ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) ); - - /* Calculate total packet length */ - copy_from_real ( &tbd, undi_transmit->TBD.segment, - undi_transmit->TBD.offset, sizeof ( tbd ) ); - len = tbd.ImmedLength; - DBG2 ( " %04x:%04x+%x", tbd.Xmit.segment, tbd.Xmit.offset, - tbd.ImmedLength ); - for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) { - datablk = &tbd.DataBlock[i]; - len += datablk->TDDataLen; - DBG2 ( " %04x:%04x+%x", datablk->TDDataPtr.segment, - datablk->TDDataPtr.offset, datablk->TDDataLen ); - } - - /* Allocate and fill I/O buffer */ - iobuf = alloc_iob ( ll_hlen + len ); - if ( ! iobuf ) { - DBG2 ( " could not allocate iobuf\n" ); - undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES; - return PXENV_EXIT_FAILURE; - } - iob_reserve ( iobuf, ll_hlen ); - copy_from_real ( iob_put ( iobuf, tbd.ImmedLength ), tbd.Xmit.segment, - tbd.Xmit.offset, tbd.ImmedLength ); - for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) { - datablk = &tbd.DataBlock[i]; - copy_from_real ( iob_put ( iobuf, datablk->TDDataLen ), - datablk->TDDataPtr.segment, - datablk->TDDataPtr.offset, - datablk->TDDataLen ); - } - - /* Add link-layer header, if required to do so */ - if ( net_protocol != NULL ) { - - /* Calculate destination address */ - if ( undi_transmit->XmitFlag == XMT_DESTADDR ) { - copy_from_real ( destaddr, - undi_transmit->DestAddr.segment, - undi_transmit->DestAddr.offset, - ll_protocol->ll_addr_len ); - ll_dest = destaddr; - DBG2 ( " DEST %s", ll_protocol->ntoa ( ll_dest ) ); - } else { - ll_dest = pxe_netdev->ll_broadcast; - DBG2 ( " BCAST" ); - } - - /* Add link-layer header */ - if ( ( rc = ll_protocol->push ( pxe_netdev, iobuf, ll_dest, - pxe_netdev->ll_addr, - net_protocol->net_proto ))!=0){ - DBG2 ( " could not add link-layer header: %s\n", - strerror ( rc ) ); - free_iob ( iobuf ); - undi_transmit->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - } - - /* Flag transmission as in-progress. Do this before starting - * to transmit the packet, because the ISR may trigger before - * we return from netdev_tx(). - */ - undi_tx_count++; - - /* Transmit packet */ - DBG2 ( "\n" ); - if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) { - DBG2 ( "PXENV_UNDI_TRANSMIT could not transmit: %s\n", - strerror ( rc ) ); - undi_tx_count--; - undi_transmit->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - undi_transmit->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SET_MCAST_ADDRESS - * - * Status: working (for NICs that support receive-all-multicast) - */ -PXENV_EXIT_t -pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS - *undi_set_mcast_address ) { - DBG ( "PXENV_UNDI_SET_MCAST_ADDRESS" ); - pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf ); - DBG ( "\n" ); - - undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SET_STATION_ADDRESS - * - * Status: working - */ -PXENV_EXIT_t -pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS - *undi_set_station_address ) { - struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; - - DBG ( "PXENV_UNDI_SET_STATION_ADDRESS %s", - ll_protocol->ntoa ( undi_set_station_address->StationAddress ) ); - - /* If adapter is open, the change will have no effect; return - * an error - */ - if ( pxe_netdev->state & NETDEV_OPEN ) { - DBG ( " failed: netdev is open\n" ); - undi_set_station_address->Status = - PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Update MAC address */ - memcpy ( pxe_netdev->ll_addr, - &undi_set_station_address->StationAddress, - ll_protocol->ll_addr_len ); - - DBG ( "\n" ); - undi_set_station_address->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SET_PACKET_FILTER - * - * Status: won't implement (would require driver API changes for no - * real benefit) - */ -PXENV_EXIT_t -pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER - *undi_set_packet_filter ) { - - DBG ( "PXENV_UNDI_SET_PACKET_FILTER %02x\n", - undi_set_packet_filter->filter ); - - /* Pretend that we succeeded, otherwise the 3Com DOS UNDI - * driver refuses to load. (We ignore the filter value in the - * PXENV_UNDI_OPEN call anyway.) - */ - undi_set_packet_filter->Status = PXENV_STATUS_SUCCESS; - - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_INFORMATION - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION - *undi_get_information ) { - struct device *dev = pxe_netdev->dev; - struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; - size_t ll_addr_len = ll_protocol->ll_addr_len; - - DBG ( "PXENV_UNDI_GET_INFORMATION" ); - - undi_get_information->BaseIo = dev->desc.ioaddr; - undi_get_information->IntNumber = dev->desc.irq; - /* Cheat: assume all cards can cope with this */ - undi_get_information->MaxTranUnit = ETH_MAX_MTU; - undi_get_information->HwType = ntohs ( ll_protocol->ll_proto ); - undi_get_information->HwAddrLen = ll_addr_len; - assert ( ll_addr_len <= - sizeof ( undi_get_information->CurrentNodeAddress ) ); - memcpy ( &undi_get_information->CurrentNodeAddress, - pxe_netdev->ll_addr, - sizeof ( undi_get_information->CurrentNodeAddress ) ); - ll_protocol->init_addr ( pxe_netdev->hw_addr, - &undi_get_information->PermNodeAddress ); - undi_get_information->ROMAddress = 0; - /* nic.rom_info->rom_segment; */ - /* We only provide the ability to receive or transmit a single - * packet at a time. This is a bootloader, not an OS. - */ - undi_get_information->RxBufCt = 1; - undi_get_information->TxBufCt = 1; - - DBG ( " io %04x irq %d mtu %d %s %s\n", - undi_get_information->BaseIo, undi_get_information->IntNumber, - undi_get_information->MaxTranUnit, ll_protocol->name, - ll_protocol->ntoa ( &undi_get_information->CurrentNodeAddress )); - undi_get_information->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_STATISTICS - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS - *undi_get_statistics ) { - DBG ( "PXENV_UNDI_GET_STATISTICS" ); - - undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good; - undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good; - undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad; - undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad; - - DBG ( " txok %d rxok %d rxcrc %d rxrsrc %d\n", - undi_get_statistics->XmtGoodFrames, - undi_get_statistics->RcvGoodFrames, - undi_get_statistics->RcvCRCErrors, - undi_get_statistics->RcvResourceErrors ); - undi_get_statistics->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_CLEAR_STATISTICS - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS - *undi_clear_statistics ) { - DBG ( "PXENV_UNDI_CLEAR_STATISTICS\n" ); - - memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) ); - memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) ); - - undi_clear_statistics->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_INITIATE_DIAGS - * - * Status: won't implement (would require driver API changes for no - * real benefit) - */ -PXENV_EXIT_t pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS - *undi_initiate_diags ) { - DBG ( "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" ); - - undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -} - -/* PXENV_UNDI_FORCE_INTERRUPT - * - * Status: won't implement (would require driver API changes for no - * perceptible benefit) - */ -PXENV_EXIT_t pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT - *undi_force_interrupt ) { - DBG ( "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" ); - - undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -} - -/* PXENV_UNDI_GET_MCAST_ADDRESS - * - * Status: working - */ -PXENV_EXIT_t -pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS - *undi_get_mcast_address ) { - struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; - struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr }; - int rc; - - DBG ( "PXENV_UNDI_GET_MCAST_ADDRESS %s", inet_ntoa ( ip ) ); - - if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip, - undi_get_mcast_address->MediaAddr ))!=0){ - DBG ( " failed: %s\n", strerror ( rc ) ); - undi_get_mcast_address->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - DBG ( "=>%s\n", - ll_protocol->ntoa ( undi_get_mcast_address->MediaAddr ) ); - - undi_get_mcast_address->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_NIC_TYPE - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE - *undi_get_nic_type ) { - struct device *dev = pxe_netdev->dev; - - DBG ( "PXENV_UNDI_GET_NIC_TYPE" ); - - memset ( &undi_get_nic_type->info, 0, - sizeof ( undi_get_nic_type->info ) ); - - switch ( dev->desc.bus_type ) { - case BUS_TYPE_PCI: { - struct pci_nic_info *info = &undi_get_nic_type->info.pci; - - undi_get_nic_type->NicType = PCI_NIC; - info->Vendor_ID = dev->desc.vendor; - info->Dev_ID = dev->desc.device; - info->Base_Class = PCI_BASE_CLASS ( dev->desc.class ); - info->Sub_Class = PCI_SUB_CLASS ( dev->desc.class ); - info->Prog_Intf = PCI_PROG_INTF ( dev->desc.class ); - info->BusDevFunc = dev->desc.location; - /* Cheat: remaining fields are probably unnecessary, - * and would require adding extra code to pci.c. - */ - undi_get_nic_type->info.pci.SubVendor_ID = 0xffff; - undi_get_nic_type->info.pci.SubDevice_ID = 0xffff; - DBG ( " PCI %02x:%02x.%x %04x:%04x (%04x:%04x) %02x%02x%02x " - "rev %02x\n", PCI_BUS ( info->BusDevFunc ), - PCI_SLOT ( info->BusDevFunc ), - PCI_FUNC ( info->BusDevFunc ), info->Vendor_ID, - info->Dev_ID, info->SubVendor_ID, info->SubDevice_ID, - info->Base_Class, info->Sub_Class, info->Prog_Intf, - info->Rev ); - break; } - case BUS_TYPE_ISAPNP: { - struct pnp_nic_info *info = &undi_get_nic_type->info.pnp; - - undi_get_nic_type->NicType = PnP_NIC; - info->EISA_Dev_ID = ( ( dev->desc.vendor << 16 ) | - dev->desc.device ); - info->CardSelNum = dev->desc.location; - /* Cheat: remaining fields are probably unnecessary, - * and would require adding extra code to isapnp.c. - */ - DBG ( " ISAPnP CSN %04x %08x %02x%02x%02x\n", - info->CardSelNum, info->EISA_Dev_ID, - info->Base_Class, info->Sub_Class, info->Prog_Intf ); - break; } - default: - DBG ( " failed: unknown bus type\n" ); - undi_get_nic_type->Status = PXENV_STATUS_FAILURE; - return PXENV_EXIT_FAILURE; - } - - undi_get_nic_type->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_IFACE_INFO - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO - *undi_get_iface_info ) { - DBG ( "PXENV_UNDI_GET_IFACE_INFO" ); - - /* Just hand back some info, doesn't really matter what it is. - * Most PXE stacks seem to take this approach. - */ - snprintf ( ( char * ) undi_get_iface_info->IfaceType, - sizeof ( undi_get_iface_info->IfaceType ), "DIX+802.3" ); - undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */ - undi_get_iface_info->ServiceFlags = - ( SUPPORTED_BROADCAST | SUPPORTED_MULTICAST | - SUPPORTED_SET_STATION_ADDRESS | SUPPORTED_RESET | - SUPPORTED_OPEN_CLOSE | SUPPORTED_IRQ ); - memset ( undi_get_iface_info->Reserved, 0, - sizeof(undi_get_iface_info->Reserved) ); - - DBG ( " %s %dbps flags %08x\n", undi_get_iface_info->IfaceType, - undi_get_iface_info->LinkSpeed, - undi_get_iface_info->ServiceFlags ); - undi_get_iface_info->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_STATE - * - * Status: impossible - */ -PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE - *undi_get_state ) { - DBG ( "PXENV_UNDI_GET_STATE failed: unsupported\n" ); - - undi_get_state->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -}; - -/* PXENV_UNDI_ISR - * - * Status: working - */ -PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { - struct io_buffer *iobuf; - size_t len; - struct ll_protocol *ll_protocol; - const void *ll_dest; - const void *ll_source; - uint16_t net_proto; - size_t ll_hlen; - struct net_protocol *net_protocol; - unsigned int prottype; - int rc; - - /* Use coloured debug, since UNDI ISR messages are likely to - * be interspersed amongst other UNDI messages. - */ - DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" ); - - /* Just in case some idiot actually looks at these fields when - * we weren't meant to fill them in... - */ - undi_isr->BufferLength = 0; - undi_isr->FrameLength = 0; - undi_isr->FrameHeaderLength = 0; - undi_isr->ProtType = 0; - undi_isr->PktType = 0; - - switch ( undi_isr->FuncFlag ) { - case PXENV_UNDI_ISR_IN_START : - DBGC2 ( &pxenv_undi_isr, " START" ); - - /* Call poll(). This should acknowledge the device - * interrupt and queue up any received packet. - */ - netdev_poll ( pxe_netdev ); - - /* Disable interrupts to avoid interrupt storm */ - netdev_irq ( pxe_netdev, 0 ); - - /* Always say it was ours for the sake of simplicity */ - DBGC2 ( &pxenv_undi_isr, " OURS" ); - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS; - break; - case PXENV_UNDI_ISR_IN_PROCESS : - case PXENV_UNDI_ISR_IN_GET_NEXT : - DBGC2 ( &pxenv_undi_isr, " %s", - ( ( undi_isr->FuncFlag == PXENV_UNDI_ISR_IN_PROCESS ) ? - "PROCESS" : "GET_NEXT" ) ); - - /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call - * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START; - * they just sit in a tight polling loop merrily - * violating the PXE spec with repeated calls to - * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to - * cope with these out-of-spec clients. - */ - netdev_poll ( pxe_netdev ); - - /* If we have not yet marked a TX as complete, and the - * netdev TX queue is empty, report the TX completion. - */ - if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) { - DBGC2 ( &pxenv_undi_isr, " TXC" ); - undi_tx_count--; - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT; - break; - } - - /* Remove first packet from netdev RX queue */ - iobuf = netdev_rx_dequeue ( pxe_netdev ); - if ( ! iobuf ) { - DBGC2 ( &pxenv_undi_isr, " DONE" ); - /* No more packets remaining */ - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE; - /* Re-enable interrupts */ - netdev_irq ( pxe_netdev, 1 ); - break; - } - - /* Copy packet to base memory buffer */ - len = iob_len ( iobuf ); - DBGC2 ( &pxenv_undi_isr, " RX" ); - if ( len > sizeof ( basemem_packet ) ) { - /* Should never happen */ - DBGC2 ( &pxenv_undi_isr, " overlength (%zx)", len ); - len = sizeof ( basemem_packet ); - } - memcpy ( basemem_packet, iobuf->data, len ); - - /* Strip link-layer header */ - ll_protocol = pxe_netdev->ll_protocol; - if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest, - &ll_source, &net_proto )) !=0){ - /* Assume unknown net_proto and no ll_source */ - net_proto = 0; - ll_source = NULL; - } - ll_hlen = ( len - iob_len ( iobuf ) ); - - /* Determine network-layer protocol */ - switch ( net_proto ) { - case htons ( ETH_P_IP ): - net_protocol = &ipv4_protocol; - prottype = P_IP; - break; - case htons ( ETH_P_ARP ): - net_protocol = &arp_protocol; - prottype = P_ARP; - break; - case htons ( ETH_P_RARP ): - net_protocol = &rarp_protocol; - prottype = P_RARP; - break; - default: - net_protocol = NULL; - prottype = P_UNKNOWN; - break; - } - - /* Fill in UNDI_ISR structure */ - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE; - undi_isr->BufferLength = len; - undi_isr->FrameLength = len; - undi_isr->FrameHeaderLength = ll_hlen; - undi_isr->Frame.segment = rm_ds; - undi_isr->Frame.offset = __from_data16 ( basemem_packet ); - undi_isr->ProtType = prottype; - undi_isr->PktType = XMT_DESTADDR; - DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d", - undi_isr->Frame.segment, undi_isr->Frame.offset, - undi_isr->BufferLength, undi_isr->FrameLength, - ( net_protocol ? net_protocol->name : "RAW" ), - undi_isr->FrameHeaderLength ); - - /* Free packet */ - free_iob ( iobuf ); - break; - default : - DBGC2 ( &pxenv_undi_isr, " INVALID(%04x)\n", - undi_isr->FuncFlag ); - - /* Should never happen */ - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE; - undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER; - return PXENV_EXIT_FAILURE; - } - - DBGC2 ( &pxenv_undi_isr, "\n" ); - undi_isr->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} diff --git a/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c b/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c deleted file mode 100644 index 582db5d2..00000000 --- a/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/dhcp.h> -#include <pxeparent.h> -#include <pxe_api.h> -#include <pxe_types.h> -#include <pxe.h> - -/** @file - * - * Call interface to parent PXE stack - * - */ - -/** - * Name PXE API call - * - * @v function API call number - * @ret name API call name - */ -static inline __attribute__ (( always_inline )) const char * -pxeparent_function_name ( unsigned int function ) { - switch ( function ) { - case PXENV_START_UNDI: - return "PXENV_START_UNDI"; - case PXENV_STOP_UNDI: - return "PXENV_STOP_UNDI"; - case PXENV_UNDI_STARTUP: - return "PXENV_UNDI_STARTUP"; - case PXENV_UNDI_CLEANUP: - return "PXENV_UNDI_CLEANUP"; - case PXENV_UNDI_INITIALIZE: - return "PXENV_UNDI_INITIALIZE"; - case PXENV_UNDI_RESET_ADAPTER: - return "PXENV_UNDI_RESET_ADAPTER"; - case PXENV_UNDI_SHUTDOWN: - return "PXENV_UNDI_SHUTDOWN"; - case PXENV_UNDI_OPEN: - return "PXENV_UNDI_OPEN"; - case PXENV_UNDI_CLOSE: - return "PXENV_UNDI_CLOSE"; - case PXENV_UNDI_TRANSMIT: - return "PXENV_UNDI_TRANSMIT"; - case PXENV_UNDI_SET_MCAST_ADDRESS: - return "PXENV_UNDI_SET_MCAST_ADDRESS"; - case PXENV_UNDI_SET_STATION_ADDRESS: - return "PXENV_UNDI_SET_STATION_ADDRESS"; - case PXENV_UNDI_SET_PACKET_FILTER: - return "PXENV_UNDI_SET_PACKET_FILTER"; - case PXENV_UNDI_GET_INFORMATION: - return "PXENV_UNDI_GET_INFORMATION"; - case PXENV_UNDI_GET_STATISTICS: - return "PXENV_UNDI_GET_STATISTICS"; - case PXENV_UNDI_CLEAR_STATISTICS: - return "PXENV_UNDI_CLEAR_STATISTICS"; - case PXENV_UNDI_INITIATE_DIAGS: - return "PXENV_UNDI_INITIATE_DIAGS"; - case PXENV_UNDI_FORCE_INTERRUPT: - return "PXENV_UNDI_FORCE_INTERRUPT"; - case PXENV_UNDI_GET_MCAST_ADDRESS: - return "PXENV_UNDI_GET_MCAST_ADDRESS"; - case PXENV_UNDI_GET_NIC_TYPE: - return "PXENV_UNDI_GET_NIC_TYPE"; - case PXENV_UNDI_GET_IFACE_INFO: - return "PXENV_UNDI_GET_IFACE_INFO"; - /* - * Duplicate case value; this is a bug in the PXE specification. - * - * case PXENV_UNDI_GET_STATE: - * return "PXENV_UNDI_GET_STATE"; - */ - case PXENV_UNDI_ISR: - return "PXENV_UNDI_ISR"; - case PXENV_GET_CACHED_INFO: - return "PXENV_GET_CACHED_INFO"; - default: - return "UNKNOWN API CALL"; - } -} - -/** - * PXE parent parameter block - * - * Used as the paramter block for all parent PXE API calls. Resides in base - * memory. - */ -static union u_PXENV_ANY __bss16 ( pxeparent_params ); -#define pxeparent_params __use_data16 ( pxeparent_params ) - -/** PXE parent entry point - * - * Used as the indirection vector for all parent PXE API calls. Resides in - * base memory. - */ -SEGOFF16_t __bss16 ( pxeparent_entry_point ); -#define pxeparent_entry_point __use_data16 ( pxeparent_entry_point ) - -/** - * Issue parent PXE API call - * - * @v entry Parent PXE stack entry point - * @v function API call number - * @v params PXE parameter block - * @v params_len Length of PXE parameter block - * @ret rc Return status code - */ -int pxeparent_call ( SEGOFF16_t entry, unsigned int function, - void *params, size_t params_len ) { - PXENV_EXIT_t exit; - int discard_b, discard_D; - int rc; - - /* Copy parameter block and entry point */ - assert ( params_len <= sizeof ( pxeparent_params ) ); - memcpy ( &pxeparent_params, params, params_len ); - memcpy ( &pxeparent_entry_point, &entry, sizeof ( entry ) ); - - /* Call real-mode entry point. This calling convention will - * work with both the !PXE and the PXENV+ entry points. - */ - __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t" - "pushw %%di\n\t" - "pushw %%bx\n\t" - "lcall *pxeparent_entry_point\n\t" - "addw $6, %%sp\n\t" ) - : "=a" ( exit ), "=b" ( discard_b ), - "=D" ( discard_D ) - : "b" ( function ), - "D" ( __from_data16 ( &pxeparent_params ) ) - : "ecx", "edx", "esi", "ebp" ); - - /* PXE API calls may rudely change the status of A20 and not - * bother to restore it afterwards. Intel is known to be - * guilty of this. - * - * Note that we will return to this point even if A20 gets - * screwed up by the parent PXE stack, because Etherboot always - * resides in an even megabyte of RAM. - */ - gateA20_set(); - - /* Determine return status code based on PXENV_EXIT and - * PXENV_STATUS - */ - if ( exit == PXENV_EXIT_SUCCESS ) { - rc = 0; - } else { - rc = -pxeparent_params.Status; - /* Paranoia; don't return success for the combination - * of PXENV_EXIT_FAILURE but PXENV_STATUS_SUCCESS - */ - if ( rc == 0 ) - rc = -EIO; - } - - /* If anything goes wrong, print as much debug information as - * it's possible to give. - */ - if ( rc != 0 ) { - SEGOFF16_t rm_params = { - .segment = rm_ds, - .offset = __from_data16 ( &pxeparent_params ), - }; - - DBG ( "PXEPARENT %s failed: %s\n", - pxeparent_function_name ( function ), strerror ( rc ) ); - DBG ( "PXEPARENT parameters at %04x:%04x length " - "%#02zx, entry point at %04x:%04x\n", - rm_params.segment, rm_params.offset, params_len, - pxeparent_entry_point.segment, - pxeparent_entry_point.offset ); - DBG ( "PXEPARENT parameters provided:\n" ); - DBG_HDA ( rm_params, params, params_len ); - DBG ( "PXEPARENT parameters returned:\n" ); - DBG_HDA ( rm_params, &pxeparent_params, params_len ); - } - - /* Copy parameter block back */ - memcpy ( params, &pxeparent_params, params_len ); - - return rc; -} - diff --git a/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c b/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c deleted file mode 100644 index 66059437..00000000 --- a/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <string.h> -#include <gpxe/dhcp.h> -#include <gpxe/netdevice.h> -#include <undipreload.h> -#include <pxeparent.h> -#include <realmode.h> -#include <pxe_api.h> - -/** - * Present cached DHCP packet if it exists - */ -void __weak_impl ( get_cached_dhcpack ) ( void ) { - struct undi_device *undi; - struct s_PXENV_GET_CACHED_INFO get_cached_info; - int rc; - - /* Use preloaded UNDI device to get at PXE entry point */ - undi = &preloaded_undi; - if ( ! undi->entry.segment ) { - DBG ( "PXEDHCP no preloaded UNDI device found\n" ); - return; - } - - /* Check that stack is available to get cached info */ - if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) { - DBG ( "PXEDHCP stack was unloaded, no cache available\n" ); - return; - } - - /* Obtain cached DHCP packet */ - memset ( &get_cached_info, 0, sizeof ( get_cached_info ) ); - get_cached_info.PacketType = PXENV_PACKET_TYPE_DHCP_ACK; - - if ( ( rc = pxeparent_call ( undi->entry, PXENV_GET_CACHED_INFO, - &get_cached_info, - sizeof ( get_cached_info ) ) ) != 0 ) { - DBG ( "PXEDHCP GET_CACHED_INFO failed: %s\n", strerror ( rc ) ); - return; - } - - DBG ( "PXEDHCP got cached info at %04x:%04x length %d\n", - get_cached_info.Buffer.segment, get_cached_info.Buffer.offset, - get_cached_info.BufferSize ); - - /* Present cached DHCP packet */ - store_cached_dhcpack ( real_to_user ( get_cached_info.Buffer.segment, - get_cached_info.Buffer.offset ), - get_cached_info.BufferSize ); -} diff --git a/gpxe/src/arch/i386/interface/syslinux/com32_call.c b/gpxe/src/arch/i386/interface/syslinux/com32_call.c deleted file mode 100644 index d2c3f918..00000000 --- a/gpxe/src/arch/i386/interface/syslinux/com32_call.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * @file SYSLINUX COM32 helpers - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <realmode.h> -#include <comboot.h> -#include <assert.h> -#include <gpxe/uaccess.h> - -static com32sys_t __bss16 ( com32_regs ); -#define com32_regs __use_data16 ( com32_regs ) - -static uint8_t __bss16 ( com32_int_vector ); -#define com32_int_vector __use_data16 ( com32_int_vector ) - -static uint32_t __bss16 ( com32_farcall_proc ); -#define com32_farcall_proc __use_data16 ( com32_farcall_proc ) - -uint16_t __bss16 ( com32_saved_sp ); - -/** - * Interrupt call helper - */ -void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) { - - memcpy_user ( virt_to_user( &com32_regs ), 0, - phys_to_user ( inregs_phys ), 0, - sizeof(com32sys_t) ); - - com32_int_vector = interrupt; - - __asm__ __volatile__ ( - REAL_CODE ( /* Save all registers */ - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - /* Mask off unsafe flags */ - "movl (com32_regs + 40), %%eax\n\t" - "andl $0x200cd7, %%eax\n\t" - "movl %%eax, (com32_regs + 40)\n\t" - /* Load com32_regs into the actual registers */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $com32_regs, %%sp\n\t" - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t" - "popfl\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* patch INT instruction */ - "pushw %%ax\n\t" - "movb %%ss:(com32_int_vector), %%al\n\t" - "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t" - /* perform a jump to avoid problems with cache - * consistency in self-modifying code on some CPUs (486) - */ - "jmp 1f\n" - "1:\n\t" - "popw %%ax\n\t" - "com32_intcall_instr:\n\t" - /* INT instruction to be patched */ - "int $0xFF\n\t" - /* Copy regs back to com32_regs */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $(com32_regs + 44), %%sp\n\t" - "pushfl\n\t" - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* Restore registers */ - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t") - : : ); - - if ( outregs_phys ) { - memcpy_user ( phys_to_user ( outregs_phys ), 0, - virt_to_user( &com32_regs ), 0, - sizeof(com32sys_t) ); - } -} - -/** - * Farcall helper - */ -void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) { - - memcpy_user ( virt_to_user( &com32_regs ), 0, - phys_to_user ( inregs_phys ), 0, - sizeof(com32sys_t) ); - - com32_farcall_proc = proc; - - __asm__ __volatile__ ( - REAL_CODE ( /* Save all registers */ - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - /* Mask off unsafe flags */ - "movl (com32_regs + 40), %%eax\n\t" - "andl $0x200cd7, %%eax\n\t" - "movl %%eax, (com32_regs + 40)\n\t" - /* Load com32_regs into the actual registers */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $com32_regs, %%sp\n\t" - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t" - "popfl\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* Call procedure */ - "lcall *%%ss:(com32_farcall_proc)\n\t" - /* Copy regs back to com32_regs */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $(com32_regs + 44), %%sp\n\t" - "pushfl\n\t" - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* Restore registers */ - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t") - : : ); - - if ( outregs_phys ) { - memcpy_user ( phys_to_user ( outregs_phys ), 0, - virt_to_user( &com32_regs ), 0, - sizeof(com32sys_t) ); - } -} - -/** - * CDECL farcall helper - */ -int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) { - int32_t eax; - - copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz ); - com32_farcall_proc = proc; - - __asm__ __volatile__ ( - REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" ) - : "=a" (eax) - : - : "ecx", "edx" ); - - remove_user_from_rm_stack ( 0, stacksz ); - - return eax; -} diff --git a/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S b/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S deleted file mode 100644 index 5c5bd139..00000000 --- a/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - - .text - .arch i386 - .code32 - - .globl com32_farcall_wrapper -com32_farcall_wrapper: - - movl $com32_farcall, %eax - jmp com32_wrapper - - - .globl com32_cfarcall_wrapper -com32_cfarcall_wrapper: - - movl $com32_cfarcall, %eax - jmp com32_wrapper - - - .globl com32_intcall_wrapper -com32_intcall_wrapper: - - movl $com32_intcall, %eax - /*jmp com32_wrapper*/ /* fall through */ - -com32_wrapper: - - /* Switch to internal virtual address space */ - call _phys_to_virt - - mov %eax, (com32_helper_function) - - /* Save external COM32 stack pointer */ - movl %esp, (com32_external_esp) - - /* Copy arguments to caller-save registers */ - movl 12(%esp), %eax - movl 8(%esp), %ecx - movl 4(%esp), %edx - - /* Switch to internal stack */ - movl (com32_internal_esp), %esp - - /* Copy arguments to internal stack */ - pushl %eax - pushl %ecx - pushl %edx - - call *(com32_helper_function) - - /* Clean up stack */ - addl $12, %esp - - /* Save internal stack pointer and restore external stack pointer */ - movl %esp, (com32_internal_esp) - movl (com32_external_esp), %esp - - /* Switch to external flat physical address space */ - call _virt_to_phys - - ret - - - .data - -/* Internal gPXE virtual address space %esp */ -.globl com32_internal_esp -.lcomm com32_internal_esp, 4 - -/* External flat physical address space %esp */ -.globl com32_external_esp -.lcomm com32_external_esp, 4 - -/* Function pointer of helper to call */ -.lcomm com32_helper_function, 4 diff --git a/gpxe/src/arch/i386/interface/syslinux/comboot_call.c b/gpxe/src/arch/i386/interface/syslinux/comboot_call.c deleted file mode 100644 index 0a17bf13..00000000 --- a/gpxe/src/arch/i386/interface/syslinux/comboot_call.c +++ /dev/null @@ -1,716 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * @file SYSLINUX COMBOOT API - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <errno.h> -#include <realmode.h> -#include <biosint.h> -#include <console.h> -#include <stdlib.h> -#include <comboot.h> -#include <bzimage.h> -#include <pxe_call.h> -#include <setjmp.h> -#include <string.h> -#include <gpxe/posix_io.h> -#include <gpxe/process.h> -#include <gpxe/serial.h> -#include <gpxe/init.h> -#include <gpxe/image.h> -#include <usr/imgmgmt.h> -#include "config/console.h" -#include "config/serial.h" - -/** The "SYSLINUX" version string */ -static char __data16_array ( syslinux_version, [] ) = "gPXE " VERSION; -#define syslinux_version __use_data16 ( syslinux_version ) - -/** The "SYSLINUX" copyright string */ -static char __data16_array ( syslinux_copyright, [] ) = "http://etherboot.org"; -#define syslinux_copyright __use_data16 ( syslinux_copyright ) - -static char __data16_array ( syslinux_configuration_file, [] ) = ""; -#define syslinux_configuration_file __use_data16 ( syslinux_configuration_file ) - -/** Feature flags */ -static uint8_t __data16 ( comboot_feature_flags ) = COMBOOT_FEATURE_IDLE_LOOP; -#define comboot_feature_flags __use_data16 ( comboot_feature_flags ) - -typedef union { - syslinux_pm_regs pm; syslinux_rm_regs rm; -} syslinux_regs; - -/** Initial register values for INT 22h AX=1Ah and 1Bh */ -static syslinux_regs __text16 ( comboot_initial_regs ); -#define comboot_initial_regs __use_text16 ( comboot_initial_regs ) - -static struct segoff __text16 ( int20_vector ); -#define int20_vector __use_text16 ( int20_vector ) - -static struct segoff __text16 ( int21_vector ); -#define int21_vector __use_text16 ( int21_vector ) - -static struct segoff __text16 ( int22_vector ); -#define int22_vector __use_text16 ( int22_vector ) - -extern void int20_wrapper ( void ); -extern void int21_wrapper ( void ); -extern void int22_wrapper ( void ); - -/* setjmp/longjmp context buffer used to return after loading an image */ -rmjmp_buf comboot_return; - -/* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */ -struct image *comboot_replacement_image; - -/* Mode flags set by INT 22h AX=0017h */ -static uint16_t comboot_graphics_mode = 0; - - -/** - * Print a string with a particular terminator - */ -static void print_user_string ( unsigned int segment, unsigned int offset, char terminator ) { - int i = 0; - char c; - userptr_t str = real_to_user ( segment, offset ); - for ( ; ; ) { - copy_from_user ( &c, str, i, 1 ); - if ( c == terminator ) break; - putchar ( c ); - i++; - } -} - - -/** - * Perform a series of memory copies from a list in low memory - */ -static void shuffle ( unsigned int list_segment, unsigned int list_offset, unsigned int count ) -{ - comboot_shuffle_descriptor shuf[COMBOOT_MAX_SHUFFLE_DESCRIPTORS]; - unsigned int i; - - /* Copy shuffle descriptor list so it doesn't get overwritten */ - copy_from_user ( shuf, real_to_user ( list_segment, list_offset ), 0, - count * sizeof( comboot_shuffle_descriptor ) ); - - /* Do the copies */ - for ( i = 0; i < count; i++ ) { - userptr_t src_u = phys_to_user ( shuf[ i ].src ); - userptr_t dest_u = phys_to_user ( shuf[ i ].dest ); - - if ( shuf[ i ].src == 0xFFFFFFFF ) { - /* Fill with 0 instead of copying */ - memset_user ( dest_u, 0, 0, shuf[ i ].len ); - } else if ( shuf[ i ].dest == 0xFFFFFFFF ) { - /* Copy new list of descriptors */ - count = shuf[ i ].len / sizeof( comboot_shuffle_descriptor ); - assert ( count <= COMBOOT_MAX_SHUFFLE_DESCRIPTORS ); - copy_from_user ( shuf, src_u, 0, shuf[ i ].len ); - i = -1; - } else { - /* Regular copy */ - memmove_user ( dest_u, 0, src_u, 0, shuf[ i ].len ); - } - } -} - - -/** - * Set default text mode - */ -void comboot_force_text_mode ( void ) { - if ( comboot_graphics_mode & COMBOOT_VIDEO_VESA ) { - /* Set VGA mode 3 via VESA VBE mode set */ - __asm__ __volatile__ ( - REAL_CODE ( - "mov $0x4F02, %%ax\n\t" - "mov $0x03, %%bx\n\t" - "int $0x10\n\t" - ) - : : ); - } else if ( comboot_graphics_mode & COMBOOT_VIDEO_GRAPHICS ) { - /* Set VGA mode 3 via standard VGA mode set */ - __asm__ __volatile__ ( - REAL_CODE ( - "mov $0x03, %%ax\n\t" - "int $0x10\n\t" - ) - : : ); - } - - comboot_graphics_mode = 0; -} - - -/** - * Fetch kernel and optional initrd - */ -static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) { - struct image *kernel = NULL; - struct image *initrd = NULL; - char *initrd_file; - int rc; - - /* Find initrd= parameter, if any */ - if ( ( initrd_file = strstr ( cmdline, "initrd=" ) ) != NULL ) { - char *initrd_end; - - /* skip "initrd=" */ - initrd_file += 7; - - /* Find terminating space, if any, and replace with NUL */ - initrd_end = strchr ( initrd_file, ' ' ); - if ( initrd_end ) - *initrd_end = '\0'; - - DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file ); - - /* Allocate and fetch initrd */ - initrd = alloc_image(); - if ( ! initrd ) { - DBG ( "COMBOOT: could not allocate initrd\n" ); - rc = -ENOMEM; - goto out; - } - if ( ( rc = imgfetch ( initrd, initrd_file, - register_image ) ) != 0 ) { - DBG ( "COMBOOT: could not fetch initrd: %s\n", - strerror ( rc ) ); - goto out; - } - - /* Restore space after initrd name, if applicable */ - if ( initrd_end ) - *initrd_end = ' '; - } - - DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file ); - - /* Allocate and fetch kernel */ - kernel = alloc_image(); - if ( ! kernel ) { - DBG ( "COMBOOT: could not allocate kernel\n" ); - rc = -ENOMEM; - goto out; - } - if ( ( rc = imgfetch ( kernel, kernel_file, - register_image ) ) != 0 ) { - DBG ( "COMBOOT: could not fetch kernel: %s\n", - strerror ( rc ) ); - goto out; - } - if ( ( rc = image_set_cmdline ( kernel, cmdline ) ) != 0 ) { - DBG ( "COMBOOT: could not set kernel command line: %s\n", - strerror ( rc ) ); - goto out; - } - - /* Store kernel as replacement image */ - assert ( comboot_replacement_image == NULL ); - comboot_replacement_image = image_get ( kernel ); - - out: - /* Drop image references unconditionally; either we want to - * discard them, or they have been registered and we should - * drop out local reference. - */ - image_put ( kernel ); - image_put ( initrd ); - return rc; -} - - -/** - * Terminate program interrupt handler - */ -static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) { - rmlongjmp ( comboot_return, COMBOOT_EXIT ); -} - - -/** - * DOS-compatible API - */ -static __asmcall void int21 ( struct i386_all_regs *ix86 ) { - ix86->flags |= CF; - - switch ( ix86->regs.ah ) { - case 0x00: - case 0x4C: /* Terminate program */ - rmlongjmp ( comboot_return, COMBOOT_EXIT ); - break; - - case 0x01: /* Get Key with Echo */ - case 0x08: /* Get Key without Echo */ - /* TODO: handle extended characters? */ - ix86->regs.al = getchar( ); - - /* Enter */ - if ( ix86->regs.al == 0x0A ) - ix86->regs.al = 0x0D; - - if ( ix86->regs.ah == 0x01 ) - putchar ( ix86->regs.al ); - - ix86->flags &= ~CF; - break; - - case 0x02: /* Write Character */ - putchar ( ix86->regs.dl ); - ix86->flags &= ~CF; - break; - - case 0x04: /* Write Character to Serial Port */ - serial_putc ( ix86->regs.dl ); - ix86->flags &= ~CF; - break; - - case 0x09: /* Write DOS String to Console */ - print_user_string ( ix86->segs.ds, ix86->regs.dx, '$' ); - ix86->flags &= ~CF; - break; - - case 0x0B: /* Check Keyboard */ - if ( iskey() ) - ix86->regs.al = 0xFF; - else - ix86->regs.al = 0x00; - - ix86->flags &= ~CF; - break; - - case 0x30: /* Check DOS Version */ - /* Bottom halves all 0; top halves spell "SYSLINUX" */ - ix86->regs.eax = 0x59530000; - ix86->regs.ebx = 0x4C530000; - ix86->regs.ecx = 0x4E490000; - ix86->regs.edx = 0x58550000; - ix86->flags &= ~CF; - break; - - default: - DBG ( "COMBOOT unknown int21 function %02x\n", ix86->regs.ah ); - break; - } -} - - -/** - * SYSLINUX API - */ -static __asmcall void int22 ( struct i386_all_regs *ix86 ) { - ix86->flags |= CF; - - switch ( ix86->regs.ax ) { - case 0x0001: /* Get Version */ - - /* Number of INT 22h API functions available */ - ix86->regs.ax = 0x001D; - - /* SYSLINUX version number */ - ix86->regs.ch = 0; /* major */ - ix86->regs.cl = 0; /* minor */ - - /* SYSLINUX derivative ID */ - ix86->regs.dl = BZI_LOADER_TYPE_GPXE; - - /* SYSLINUX version and copyright strings */ - ix86->segs.es = rm_ds; - ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) ); - ix86->regs.di = ( ( unsigned ) __from_data16 ( syslinux_copyright ) ); - - ix86->flags &= ~CF; - break; - - case 0x0002: /* Write String */ - print_user_string ( ix86->segs.es, ix86->regs.bx, '\0' ); - ix86->flags &= ~CF; - break; - - case 0x0003: /* Run command */ - { - userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx ); - int len = strlen_user ( cmd_u, 0 ); - char cmd[len + 1]; - copy_from_user ( cmd, cmd_u, 0, len + 1 ); - DBG ( "COMBOOT: executing command '%s'\n", cmd ); - system ( cmd ); - DBG ( "COMBOOT: exiting after executing command...\n" ); - rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND ); - } - break; - - case 0x0004: /* Run default command */ - /* FIXME: just exit for now */ - rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND ); - break; - - case 0x0005: /* Force text mode */ - comboot_force_text_mode ( ); - ix86->flags &= ~CF; - break; - - case 0x0006: /* Open file */ - { - int fd; - userptr_t file_u = real_to_user ( ix86->segs.es, ix86->regs.si ); - int len = strlen_user ( file_u, 0 ); - char file[len + 1]; - - copy_from_user ( file, file_u, 0, len + 1 ); - - if ( file[0] == '\0' ) { - DBG ( "COMBOOT: attempted open with empty file name\n" ); - break; - } - - DBG ( "COMBOOT: opening file '%s'\n", file ); - - fd = open ( file ); - - if ( fd < 0 ) { - DBG ( "COMBOOT: error opening file %s\n", file ); - break; - } - - /* This relies on the fact that a gPXE POSIX fd will - * always fit in 16 bits. - */ -#if (POSIX_FD_MAX > 65535) -#error POSIX_FD_MAX too large -#endif - ix86->regs.si = (uint16_t) fd; - - ix86->regs.cx = COMBOOT_FILE_BLOCKSZ; - ix86->regs.eax = fsize ( fd ); - ix86->flags &= ~CF; - } - break; - - case 0x0007: /* Read file */ - { - int fd = ix86->regs.si; - int len = ix86->regs.cx * COMBOOT_FILE_BLOCKSZ; - int rc; - fd_set fds; - userptr_t buf = real_to_user ( ix86->segs.es, ix86->regs.bx ); - - /* Wait for data ready to read */ - FD_ZERO ( &fds ); - FD_SET ( fd, &fds ); - - select ( &fds, 1 ); - - rc = read_user ( fd, buf, 0, len ); - if ( rc < 0 ) { - DBG ( "COMBOOT: read failed\n" ); - ix86->regs.si = 0; - break; - } - - ix86->regs.ecx = rc; - ix86->flags &= ~CF; - } - break; - - case 0x0008: /* Close file */ - { - int fd = ix86->regs.si; - close ( fd ); - ix86->flags &= ~CF; - } - break; - - case 0x0009: /* Call PXE Stack */ - if ( pxe_api_call_weak ( ix86 ) != 0 ) - ix86->flags |= CF; - else - ix86->flags &= ~CF; - break; - - case 0x000A: /* Get Derivative-Specific Information */ - - /* gPXE has its own derivative ID, so there is no defined - * output here; just return AL for now */ - ix86->regs.al = BZI_LOADER_TYPE_GPXE; - ix86->flags &= ~CF; - break; - - case 0x000B: /* Get Serial Console Configuration */ -#if defined(CONSOLE_SERIAL) && !defined(COMPRESERVE) - ix86->regs.dx = COMCONSOLE; - ix86->regs.cx = 115200 / COMSPEED; - ix86->regs.bx = 0; -#else - ix86->regs.dx = 0; -#endif - - ix86->flags &= ~CF; - break; - - case 0x000E: /* Get configuration file name */ - /* FIXME: stub */ - ix86->segs.es = rm_ds; - ix86->regs.bx = ( ( unsigned ) __from_data16 ( syslinux_configuration_file ) ); - ix86->flags &= ~CF; - break; - - case 0x000F: /* Get IPAPPEND strings */ - /* FIXME: stub */ - ix86->regs.cx = 0; - ix86->segs.es = 0; - ix86->regs.bx = 0; - ix86->flags &= ~CF; - break; - - case 0x0010: /* Resolve hostname */ - { - userptr_t hostname_u = real_to_user ( ix86->segs.es, ix86->regs.bx ); - int len = strlen_user ( hostname_u, 0 ); - char hostname[len]; - struct in_addr addr; - - copy_from_user ( hostname, hostname_u, 0, len + 1 ); - - /* TODO: - * "If the hostname does not contain a dot (.), the - * local domain name is automatically appended." - */ - - comboot_resolv ( hostname, &addr ); - - ix86->regs.eax = addr.s_addr; - ix86->flags &= ~CF; - } - break; - - case 0x0011: /* Maximum number of shuffle descriptors */ - ix86->regs.cx = COMBOOT_MAX_SHUFFLE_DESCRIPTORS; - ix86->flags &= ~CF; - break; - - case 0x0012: /* Cleanup, shuffle and boot */ - if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS ) - break; - - /* Perform final cleanup */ - shutdown ( SHUTDOWN_BOOT ); - - /* Perform sequence of copies */ - shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx ); - - /* Jump to real-mode entry point */ - __asm__ __volatile__ ( - REAL_CODE ( - "pushw %0\n\t" - "popw %%ds\n\t" - "pushl %1\n\t" - "lret\n\t" - ) - : - : "r" ( ix86->segs.ds ), - "r" ( ix86->regs.ebp ), - "d" ( ix86->regs.ebx ), - "S" ( ix86->regs.esi ) ); - - assert ( 0 ); /* Execution should never reach this point */ - - break; - - case 0x0013: /* Idle loop call */ - step ( ); - ix86->flags &= ~CF; - break; - - case 0x0015: /* Get feature flags */ - ix86->segs.es = rm_ds; - ix86->regs.bx = ( ( unsigned ) __from_data16 ( &comboot_feature_flags ) ); - ix86->regs.cx = 1; /* Number of feature flag bytes */ - ix86->flags &= ~CF; - break; - - case 0x0016: /* Run kernel image */ - { - userptr_t file_u = real_to_user ( ix86->segs.ds, ix86->regs.si ); - userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx ); - int file_len = strlen_user ( file_u, 0 ); - int cmd_len = strlen_user ( cmd_u, 0 ); - char file[file_len + 1]; - char cmd[cmd_len + 1]; - - copy_from_user ( file, file_u, 0, file_len + 1 ); - copy_from_user ( cmd, cmd_u, 0, cmd_len + 1 ); - - DBG ( "COMBOOT: run kernel %s %s\n", file, cmd ); - comboot_fetch_kernel ( file, cmd ); - /* Technically, we should return if we - * couldn't load the kernel, but it's not safe - * to do that since we have just overwritten - * part of the COMBOOT program's memory space. - */ - DBG ( "COMBOOT: exiting to run kernel...\n" ); - rmlongjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL ); - } - break; - - case 0x0017: /* Report video mode change */ - comboot_graphics_mode = ix86->regs.bx; - ix86->flags &= ~CF; - break; - - case 0x0018: /* Query custom font */ - /* FIXME: stub */ - ix86->regs.al = 0; - ix86->segs.es = 0; - ix86->regs.bx = 0; - ix86->flags &= ~CF; - break; - - case 0x001B: /* Cleanup, shuffle and boot to real mode */ - if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS ) - break; - - /* Perform final cleanup */ - shutdown ( SHUTDOWN_BOOT ); - - /* Perform sequence of copies */ - shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx ); - - /* Copy initial register values to .text16 */ - memcpy_user ( real_to_user ( rm_cs, (unsigned) __from_text16 ( &comboot_initial_regs ) ), 0, - real_to_user ( ix86->segs.ds, ix86->regs.si ), 0, - sizeof(syslinux_rm_regs) ); - - /* Load initial register values */ - __asm__ __volatile__ ( - REAL_CODE ( - /* Point SS:SP at the register value structure */ - "pushw %%cs\n\t" - "popw %%ss\n\t" - "movw $comboot_initial_regs, %%sp\n\t" - - /* Segment registers */ - "popw %%es\n\t" - "popw %%ax\n\t" /* Skip CS */ - "popw %%ds\n\t" - "popw %%ax\n\t" /* Skip SS for now */ - "popw %%fs\n\t" - "popw %%gs\n\t" - - /* GP registers */ - "popl %%eax\n\t" - "popl %%ecx\n\t" - "popl %%edx\n\t" - "popl %%ebx\n\t" - "popl %%ebp\n\t" /* Skip ESP for now */ - "popl %%ebp\n\t" - "popl %%esi\n\t" - "popl %%edi\n\t" - - /* Load correct SS:ESP */ - "movw $(comboot_initial_regs + 6), %%sp\n\t" - "popw %%ss\n\t" - "movl %%cs:(comboot_initial_regs + 28), %%esp\n\t" - - "ljmp *%%cs:(comboot_initial_regs + 44)\n\t" - ) - : : ); - - break; - - case 0x001C: /* Get pointer to auxilliary data vector */ - /* FIXME: stub */ - ix86->regs.cx = 0; /* Size of the ADV */ - ix86->flags &= ~CF; - break; - - case 0x001D: /* Write auxilliary data vector */ - /* FIXME: stub */ - ix86->flags &= ~CF; - break; - - default: - DBG ( "COMBOOT unknown int22 function %04x\n", ix86->regs.ax ); - break; - } -} - -/** - * Hook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h) - */ -void hook_comboot_interrupts ( ) { - - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint20_wrapper:\n\t" - "pushl %0\n\t" - "pushw %%cs\n\t" - "call prot_call\n\t" - "addw $4, %%sp\n\t" - "iret\n\t" ) - : : "i" ( int20 ) ); - - hook_bios_interrupt ( 0x20, ( unsigned int ) int20_wrapper, - &int20_vector ); - - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint21_wrapper:\n\t" - "pushl %0\n\t" - "pushw %%cs\n\t" - "call prot_call\n\t" - "addw $4, %%sp\n\t" - "iret\n\t" ) - : : "i" ( int21 ) ); - - hook_bios_interrupt ( 0x21, ( unsigned int ) int21_wrapper, - &int21_vector ); - - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint22_wrapper:\n\t" - "pushl %0\n\t" - "pushw %%cs\n\t" - "call prot_call\n\t" - "addw $4, %%sp\n\t" - "iret\n\t" ) - : : "i" ( int22) ); - - hook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper, - &int22_vector ); -} - -/** - * Unhook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h) - */ -void unhook_comboot_interrupts ( ) { - - unhook_bios_interrupt ( 0x20, ( unsigned int ) int20_wrapper, - &int20_vector ); - - unhook_bios_interrupt ( 0x21, ( unsigned int ) int21_wrapper, - &int21_vector ); - - unhook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper, - &int22_vector ); -} diff --git a/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c b/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c deleted file mode 100644 index 30ac502e..00000000 --- a/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c +++ /dev/null @@ -1,60 +0,0 @@ -#include <errno.h> -#include <comboot.h> -#include <gpxe/in.h> -#include <gpxe/list.h> -#include <gpxe/process.h> -#include <gpxe/resolv.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -static int comboot_resolv_rc; -static struct in_addr comboot_resolv_addr; - -static void comboot_resolv_done ( struct resolv_interface *resolv, - struct sockaddr *sa, int rc ) { - struct sockaddr_in *sin; - - resolv_unplug ( resolv ); - - if ( rc != 0 ) { - comboot_resolv_rc = rc; - return; - } - - if ( sa->sa_family != AF_INET ) { - comboot_resolv_rc = -EAFNOSUPPORT; - return; - } - - sin = ( ( struct sockaddr_in * ) sa ); - comboot_resolv_addr = sin->sin_addr; - - comboot_resolv_rc = 0; -} - -static struct resolv_interface_operations comboot_resolv_ops = { - .done = comboot_resolv_done, -}; - -static struct resolv_interface comboot_resolver = { - .intf = { - .dest = &null_resolv.intf, - .refcnt = NULL, - }, - .op = &comboot_resolv_ops, -}; - -int comboot_resolv ( const char *name, struct in_addr *address ) { - int rc; - - comboot_resolv_rc = -EINPROGRESS; - - if ( ( rc = resolv ( &comboot_resolver, name, NULL ) ) != 0 ) - return rc; - - while ( comboot_resolv_rc == -EINPROGRESS ) - step(); - - *address = comboot_resolv_addr; - return comboot_resolv_rc; -} diff --git a/gpxe/src/arch/i386/kir-Makefile b/gpxe/src/arch/i386/kir-Makefile deleted file mode 100644 index bbfc1a3a..00000000 --- a/gpxe/src/arch/i386/kir-Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# Makefile to build a KEEP_IT_REAL flavour -# -# KEEP_IT_REAL, by its nature, requires a different build of every -# single object file, since the inclusion of ".code16gcc" will -# generate different machine code from the assembly. Unlike the other -# config options, there is no way that this global dependency can ever -# be reduced, so it makes sense to be able to build both the normal -# and the KIR versions without having to force a full rebuild each -# time. - -# Add this Makefile to MAKEDEPS -# -MAKEDEPS += arch/i386/kir-Makefile - -# Place binaries in bin-kir -# -BIN = bin-kir - -# Compile with -DKEEP_IT_REAL, forcibly include kir.h at the start of -# each file to drag in ".code16gcc" -# -CFLAGS += -DKEEP_IT_REAL -include kir.h - -include Makefile - -LDSCRIPT = arch/i386/scripts/i386-kir.lds diff --git a/gpxe/src/arch/i386/prefix/bootpart.S b/gpxe/src/arch/i386/prefix/bootpart.S deleted file mode 100644 index 968da1a3..00000000 --- a/gpxe/src/arch/i386/prefix/bootpart.S +++ /dev/null @@ -1,218 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ) - -#define BOOT_SEG 0x07c0 -#define EXEC_SEG 0x0100 -#define STACK_SEG 0x0200 -#define STACK_SIZE 0x2000 - - .text - .arch i386 - .section ".prefix", "awx", @progbits - .code16 - -/* - * Find active partition - * - * Parameters: - * %dl : BIOS drive number - * %bp : Active partition handler routine - */ -find_active_partition: - /* Set up stack at STACK_SEG:STACK_SIZE */ - movw $STACK_SEG, %ax - movw %ax, %ss - movw $STACK_SIZE, %sp - - /* Relocate self to EXEC_SEG */ - pushw $BOOT_SEG - popw %ds - pushw $EXEC_SEG - popw %es - xorw %si, %si - xorw %di, %di - movw $0x200, %cx - rep movsb - ljmp $EXEC_SEG, $1f -1: pushw %ds - popw %es - pushw %cs - popw %ds - - /* Check for LBA extensions */ - movb $0x41, %ah - movw $0x55aa, %bx - stc - int $0x13 - jc 1f - cmpw $0xaa55, %bx - jne 1f - movw $read_lba, read_sectors -1: - /* Read and process root partition table */ - xorb %dh, %dh - movw $0x0001, %cx - xorl %esi, %esi - xorl %edi, %edi - call process_table - - /* Print failure message */ - movw $10f, %si - jmp boot_error -10: .asciz "Could not locate active partition\r\n" - -/* - * Print failure message and boot next device - * - * Parameters: - * %si : Failure string - */ -boot_error: - cld - movw $0x0007, %bx - movb $0x0e, %ah -1: lodsb - testb %al, %al - je 99f - int $0x10 - jmp 1b -99: /* Boot next device */ - int $0x18 - -/* - * Process partition table - * - * Parameters: - * %dl : BIOS drive number - * %dh : Head - * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7) - * %ch : Low eight bits of cylinder - * %esi:%edi : LBA address - * %bp : Active partition handler routine - * - * Returns: - * CF set on error - */ -process_table: - pushal - call read_boot_sector - jc 99f - movw $446, %bx -1: call process_partition - addw $16, %bx - cmpw $510, %bx - jne 1b -99: popal - ret - -/* - * Process partition - * - * Parameters: - * %dl : BIOS drive number - * %dh : Head - * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7) - * %ch : Low eight bits of cylinder - * %esi:%edi : LBA address - * %bx : Offset within partition table - * %bp : Active partition handler routine - */ -process_partition: - pushal - /* Load C/H/S values from partition entry */ - movb %es:1(%bx), %dh - movw %es:2(%bx), %cx - /* Update LBA address from partition entry */ - addl %es:8(%bx), %edi - adcl $0, %esi - /* Check active flag */ - testb $0x80, %es:(%bx) - jz 1f - call read_boot_sector - jc 99f - jmp *%bp -1: /* Check for extended partition */ - movb %es:4(%bx), %al - cmpb $0x05, %al - je 2f - cmpb $0x0f, %al - je 2f - cmpb $0x85, %al - jne 99f -2: call process_table -99: popal - /* Reload original partition table */ - call read_boot_sector - ret - -/* - * Read single sector to %es:0000 and verify 0x55aa signature - * - * Parameters: - * %dl : BIOS drive number - * %dh : Head - * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7) - * %ch : Low eight bits of cylinder - * %esi:%edi : LBA address - * - * Returns: - * CF set on error - */ -read_boot_sector: - pushw %ax - movw $1, %ax - call *read_sectors - jc 99f - cmpw $0xaa55, %es:(510) - je 99f - stc -99: popw %ax - ret - -/* - * Read sectors to %es:0000 - * - * Parameters: - * %dl : BIOS drive number - * %dh : Head - * %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7) - * %ch : Low eight bits of cylinder - * %esi:%edi : LBA address - * %ax : Number of sectors (max 127) - * - * Returns: - * CF set on error - */ -read_sectors: .word read_chs - -read_chs: - /* Read sectors using C/H/S address */ - pushal - xorw %bx, %bx - movb $0x02, %ah - stc - int $0x13 - sti - popal - ret - -read_lba: - /* Read sectors using LBA address */ - pushal - movw %ax, (lba_desc + 2) - pushw %es - popw (lba_desc + 6) - movl %edi, (lba_desc + 8) - movl %esi, (lba_desc + 12) - movw $lba_desc, %si - movb $0x42, %ah - int $0x13 - popal - ret - -lba_desc: - .byte 0x10 - .byte 0 - .word 1 - .word 0x0000 - .word 0x0000 - .long 0, 0 diff --git a/gpxe/src/arch/i386/prefix/dskprefix.S b/gpxe/src/arch/i386/prefix/dskprefix.S deleted file mode 100644 index 60d351f7..00000000 --- a/gpxe/src/arch/i386/prefix/dskprefix.S +++ /dev/null @@ -1,381 +0,0 @@ -/* NOTE: this boot sector contains instructions that need at least an 80186. - * Yes, as86 has a bug somewhere in the valid instruction set checks. - * - */ - -/* floppyload.S Copyright (C) 1991, 1992 Linus Torvalds - * modified by Drew Eckhardt - * modified by Bruce Evans (bde) - * - * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines. - * - * It then loads the system at SYSSEG<<4, using BIOS interrupts. - * - * The loader has been made as simple as possible, and continuous read errors - * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by - * getting whole tracks at a time whenever possible. - */ - -FILE_LICENCE ( GPL2_ONLY ) - -.equ BOOTSEG, 0x07C0 /* original address of boot-sector */ - -.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */ - - .org 0 - .arch i386 - .text - .section ".prefix", "ax", @progbits - .code16 - - jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */ -go: - movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */ - /* of bootsect + room for stack + 12 for */ - /* saved disk parm block */ - - movw $BOOTSEG, %ax - movw %ax,%ds - movw %ax,%es - movw %ax,%ss /* put stack at BOOTSEG:0x4000-12. */ - movw %di,%sp - -/* Many BIOS's default disk parameter tables will not recognize multi-sector - * reads beyond the maximum sector number specified in the default diskette - * parameter tables - this may mean 7 sectors in some cases. - * - * Since single sector reads are slow and out of the question, we must take care - * of this by creating new parameter tables (for the first disk) in RAM. We - * will set the maximum sector count to 36 - the most we will encounter on an - * ED 2.88. High doesn't hurt. Low does. - * - * Segments are as follows: ds=es=ss=cs - BOOTSEG - */ - - xorw %cx,%cx - movw %cx,%es /* access segment 0 */ - movw $0x78, %bx /* 0:bx is parameter table address */ - pushw %ds /* save ds */ -/* 0:bx is parameter table address */ - ldsw %es:(%bx),%si /* loads ds and si */ - - movw %ax,%es /* ax is BOOTSECT (loaded above) */ - movb $6, %cl /* copy 12 bytes */ - cld - pushw %di /* keep a copy for later */ - rep - movsw /* ds:si is source, es:di is dest */ - popw %di - - movb $36,%es:4(%di) - - movw %cx,%ds /* access segment 0 */ - xchgw %di,(%bx) - movw %es,%si - xchgw %si,2(%bx) - popw %ds /* restore ds */ - movw %di, dpoff /* save old parameters */ - movw %si, dpseg /* to restore just before finishing */ - pushw %ds - popw %es /* reload es */ - -/* Note that es is already set up. Also cx is 0 from rep movsw above. */ - - xorb %ah,%ah /* reset FDC */ - xorb %dl,%dl - int $0x13 - -/* Get disk drive parameters, specifically number of sectors/track. - * - * It seems that there is no BIOS call to get the number of sectors. Guess - * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, - * 15 if sector 15 can be read. Otherwise guess 9. - */ - - movw $disksizes, %si /* table of sizes to try */ - -probe_loop: - lodsb - cbtw /* extend to word */ - movw %ax, sectors - cmpw $disksizes+4, %si - jae got_sectors /* if all else fails, try 9 */ - xchgw %cx,%ax /* cx = track and sector */ - xorw %dx,%dx /* drive 0, head 0 */ - movw $0x0200, %bx /* address after boot sector */ - /* (512 bytes from origin, es = cs) */ - movw $0x0201, %ax /* service 2, 1 sector */ - int $0x13 - jc probe_loop /* try next value */ - -got_sectors: - movw $msg1end-msg1, %cx - movw $msg1, %si - call print_str - -/* ok, we've written the Loading... message, now we want to load the system */ - - movw $SYSSEG, %ax - movw %ax,%es /* segment of SYSSEG<<4 */ - pushw %es - call read_it - -/* This turns off the floppy drive motor, so that we enter the kernel in a - * known state, and don't have to worry about it later. - */ - movw $0x3f2, %dx - xorb %al,%al - outb %al,%dx - - call print_nl - pop %es /* = SYSSEG */ - -/* Restore original disk parameters */ - movw $0x78, %bx - movw dpoff, %di - movw dpseg, %si - xorw %ax,%ax - movw %ax,%ds - movw %di,(%bx) - movw %si,2(%bx) - - /* Everything now loaded. %es = SYSSEG, so %es:0000 points to - * start of loaded image. - */ - - /* Jump to loaded copy */ - ljmp $SYSSEG, $start_runtime - -endseg: .word SYSSEG - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDW" - .long endseg - .long 16 - .long 0 - .previous - -/* This routine loads the system at address SYSSEG<<4, making sure no 64kB - * boundaries are crossed. We try to load it as fast as possible, loading whole - * tracks whenever we can. - * - * in: es - starting address segment (normally SYSSEG) - */ -read_it: - movw $0,sread /* load whole image including prefix */ - movw %es,%ax - testw $0x0fff, %ax -die: jne die /* es must be at 64kB boundary */ - xorw %bx,%bx /* bx is starting address within segment */ -rp_read: - movw %es,%ax - movw %bx,%dx - movb $4, %cl - shrw %cl,%dx /* bx is always divisible by 16 */ - addw %dx,%ax - cmpw endseg, %ax /* have we loaded all yet? */ - jb ok1_read - ret -ok1_read: - movw sectors, %ax - subw sread, %ax - movw %ax,%cx - shlw $9, %cx - addw %bx,%cx - jnc ok2_read - je ok2_read - xorw %ax,%ax - subw %bx,%ax - shrw $9, %ax -ok2_read: - call read_track - movw %ax,%cx - addw sread, %ax - cmpw sectors, %ax - jne ok3_read - movw $1, %ax - subw head, %ax - jne ok4_read - incw track -ok4_read: - movw %ax, head - xorw %ax,%ax -ok3_read: - movw %ax, sread - shlw $9, %cx - addw %cx,%bx - jnc rp_read - movw %es,%ax - addb $0x10, %ah - movw %ax,%es - xorw %bx,%bx - jmp rp_read - -read_track: - pusha - pushw %ax - pushw %bx - pushw %bp /* just in case the BIOS is buggy */ - movw $0x0e2e, %ax /* 0x2e = . */ - movw $0x0007, %bx - int $0x10 - popw %bp - popw %bx - popw %ax - - movw track, %dx - movw sread, %cx - incw %cx - movb %dl,%ch - movw head, %dx - movb %dl,%dh - andw $0x0100, %dx - movb $2, %ah - - pushw %dx /* save for error dump */ - pushw %cx - pushw %bx - pushw %ax - - int $0x13 - jc bad_rt - addw $8, %sp - popa - ret - -bad_rt: pushw %ax /* save error code */ - call print_all /* ah = error, al = read */ - - xorb %ah,%ah - xorb %dl,%dl - int $0x13 - - addw $10, %sp - popa - jmp read_track - -/* print_all is for debugging purposes. It will print out all of the registers. - * The assumption is that this is called from a routine, with a stack frame like - * dx - * cx - * bx - * ax - * error - * ret <- sp - */ - -print_all: - call print_nl /* nl for readability */ - movw $5, %cx /* error code + 4 registers */ - movw %sp,%bp - -print_loop: - pushw %cx /* save count left */ - - cmpb $5, %cl - jae no_reg /* see if register name is needed */ - - movw $0x0007, %bx /* page 0, attribute 7 (normal) */ - movw $0xe05+0x41-1, %ax - subb %cl,%al - int $0x10 - - movb $0x58, %al /* 'X' */ - int $0x10 - - movb $0x3A, %al /* ':' */ - int $0x10 - -no_reg: - addw $2, %bp /* next register */ - call print_hex /* print it */ - movb $0x20, %al /* print a space */ - int $0x10 - popw %cx - loop print_loop - call print_nl /* nl for readability */ - ret - -print_str: - movw $0x0007, %bx /* page 0, attribute 7 (normal) */ - movb $0x0e, %ah /* write char, tty mode */ -prloop: - lodsb - int $0x10 - loop prloop - ret - -print_nl: - movw $0x0007, %bx /* page 0, attribute 7 (normal) */ - movw $0xe0d, %ax /* CR */ - int $0x10 - movb $0xa, %al /* LF */ - int $0x10 - ret - -/* print_hex prints the word pointed to by ss:bp in hexadecimal. */ - -print_hex: - movw (%bp),%dx /* load word into dx */ - movb $4, %cl - movb $0x0e, %ah /* write char, tty mode */ - movw $0x0007, %bx /* page 0, attribute 7 (normal) */ - call print_digit - call print_digit - call print_digit -/* fall through */ -print_digit: - rol %cl,%dx /* rotate so that lowest 4 bits are used */ - movb $0x0f, %al /* mask for nybble */ - andb %dl,%al - addb $0x90, %al /* convert al to ascii hex (four instructions) */ - daa - adcb $0x40, %al - daa - int $0x10 - ret - -sread: .word 0 /* sectors read of current track */ -head: .word 0 /* current head */ -track: .word 0 /* current track */ - -sectors: - .word 0 - -dpseg: .word 0 -dpoff: .word 0 - -disksizes: - .byte 36,18,15,9 - -msg1: - .ascii "Loading ROM image" -msg1end: - - .org 510, 0 - .word 0xAA55 - -start_runtime: - /* Install gPXE */ - call install - - /* Set up real-mode stack */ - movw %bx, %ss - movw $_estack16, %sp - - /* Jump to .text16 segment */ - pushw %ax - pushw $1f - lret - .section ".text16", "awx", @progbits -1: - pushl $main - pushw %cs - call prot_call - popl %ecx /* discard */ - - /* Uninstall gPXE */ - call uninstall - - /* Boot next device */ - int $0x18 - diff --git a/gpxe/src/arch/i386/prefix/hdprefix.S b/gpxe/src/arch/i386/prefix/hdprefix.S deleted file mode 100644 index 05767567..00000000 --- a/gpxe/src/arch/i386/prefix/hdprefix.S +++ /dev/null @@ -1,109 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ) - - .text - .arch i386 - .section ".prefix", "awx", @progbits - .code16 - .org 0 - - movw $load_image, %bp - jmp find_active_partition - -#include "bootpart.S" - -load_image: - /* Get disk geometry */ - pushal - pushw %es - movb $0x08, %ah - int $0x13 - jc load_failed - movb %cl, max_sector - movb %dh, max_head - popw %es - popal - -1: /* Read to end of current track */ - movb %cl, %al - negb %al - addb max_sector, %al - incb %al - andb $0x3f, %al - movzbl %al, %eax - call *read_sectors - jc load_failed - - /* Update %es */ - movw %es, %bx - shll $5, %eax - addw %ax, %bx - movw %bx, %es - shrl $5, %eax - - /* Update LBA address */ - addl %eax, %edi - adcl $0, %esi - - /* Update CHS address */ - andb $0xc0, %cl - orb $0x01, %cl - incb %dh - cmpb max_head, %dh - jbe 2f - xorb %dh, %dh - incb %ch - jnc 2f - addb $0xc0, %cl -2: - /* Loop until whole image is read */ - subl %eax, load_length - ja 1b - ljmp $BOOT_SEG, $start_image - -max_sector: - .byte 0 -max_head: - .byte 0 -load_length: - .long 0 - - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDL" - .long load_length - .long 512 - .long 0 - .previous - - -load_failed: - movw $10f, %si - jmp boot_error -10: .asciz "Could not load gPXE\r\n" - - .org 510 - .byte 0x55, 0xaa - -start_image: - /* Install gPXE */ - call install - - /* Set up real-mode stack */ - movw %bx, %ss - movw $_estack16, %sp - - /* Jump to .text16 segment */ - pushw %ax - pushw $1f - lret - .section ".text16", "awx", @progbits -1: - pushl $main - pushw %cs - call prot_call - popl %ecx /* discard */ - - /* Uninstall gPXE */ - call uninstall - - /* Boot next device */ - int $0x18 diff --git a/gpxe/src/arch/i386/prefix/hromprefix.S b/gpxe/src/arch/i386/prefix/hromprefix.S deleted file mode 100644 index 03acf1e2..00000000 --- a/gpxe/src/arch/i386/prefix/hromprefix.S +++ /dev/null @@ -1,12 +0,0 @@ -/***************************************************************************** - * ROM prefix that relocates to HIGHMEM_LOADPOINT during POST if PMM allocation - * fails. Intended to be used, with caution, on BIOSes that support PCI3.00 but - * have limited PMM support, such as most AMI BIOSes. - ***************************************************************************** - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -#define SHRINK_WITHOUT_PMM - -#include "romprefix.S" diff --git a/gpxe/src/arch/i386/prefix/kkpxeprefix.S b/gpxe/src/arch/i386/prefix/kkpxeprefix.S deleted file mode 100644 index 02cc6fee..00000000 --- a/gpxe/src/arch/i386/prefix/kkpxeprefix.S +++ /dev/null @@ -1,13 +0,0 @@ -/***************************************************************************** - * PXE prefix that keeps the whole PXE stack present - ***************************************************************************** - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -/* Since we have the whole stack, we can use cached DHCP information */ -REQUEST_OBJECT ( pxeparent_dhcp ) - -#define PXELOADER_KEEP_UNDI -#define PXELOADER_KEEP_PXE -#include "pxeprefix.S" diff --git a/gpxe/src/arch/i386/prefix/kpxeprefix.S b/gpxe/src/arch/i386/prefix/kpxeprefix.S deleted file mode 100644 index 923faccc..00000000 --- a/gpxe/src/arch/i386/prefix/kpxeprefix.S +++ /dev/null @@ -1,9 +0,0 @@ -/***************************************************************************** - * PXE prefix that keep the UNDI portion of the PXE stack present - ***************************************************************************** - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -#define PXELOADER_KEEP_UNDI -#include "pxeprefix.S" diff --git a/gpxe/src/arch/i386/prefix/libprefix.S b/gpxe/src/arch/i386/prefix/libprefix.S deleted file mode 100644 index 9e6ba6f0..00000000 --- a/gpxe/src/arch/i386/prefix/libprefix.S +++ /dev/null @@ -1,819 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - - .arch i386 - -/** - * High memory temporary load address - * - * Temporary buffer into which to copy (or decompress) our runtime - * image, prior to calling get_memmap() and relocate(). We don't - * actually leave anything here once install() has returned. - * - * We use the start of an even megabyte so that we don't have to worry - * about the current state of the A20 line. - * - * We use 4MB rather than 2MB because some PXE stack / PMM BIOS - * combinations are known to place data required by other UNDI ROMs - * loader around the 2MB mark. - */ - .globl HIGHMEM_LOADPOINT - .equ HIGHMEM_LOADPOINT, ( 4 << 20 ) - -/* Image compression enabled */ -#define COMPRESS 1 - -#define CR0_PE 1 - -/***************************************************************************** - * Utility function: print character (with LF -> LF,CR translation) - * - * Parameters: - * %al : character to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_character -print_character: - /* Preserve registers */ - pushw %ax - pushw %bx - pushw %bp - /* If %di is non-zero, write character to buffer and exit */ - testw %di, %di - jz 1f - movb %al, %ds:(%di) - incw %di - jmp 3f -1: /* Print character */ - movw $0x0007, %bx /* page 0, attribute 7 (normal) */ - movb $0x0e, %ah /* write char, tty mode */ - cmpb $0x0a, %al /* '\n'? */ - jne 2f - int $0x10 - movb $0x0d, %al -2: int $0x10 - /* Restore registers and return */ -3: popw %bp - popw %bx - popw %ax - ret - .size print_character, . - print_character - -/***************************************************************************** - * Utility function: print a NUL-terminated string - * - * Parameters: - * %ds:si : string to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:si : character after terminating NUL - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_message -print_message: - /* Preserve registers */ - pushw %ax - /* Print string */ -1: lodsb - testb %al, %al - je 2f - call print_character - jmp 1b -2: /* Restore registers and return */ - popw %ax - ret - .size print_message, . - print_message - -/***************************************************************************** - * Utility functions: print hex digit/byte/word/dword - * - * Parameters: - * %al (low nibble) : digit to print - * %al : byte to print - * %ax : word to print - * %eax : dword to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_hex_dword -print_hex_dword: - rorl $16, %eax - call print_hex_word - rorl $16, %eax - /* Fall through */ - .size print_hex_dword, . - print_hex_dword - .globl print_hex_word -print_hex_word: - xchgb %al, %ah - call print_hex_byte - xchgb %al, %ah - /* Fall through */ - .size print_hex_word, . - print_hex_word - .globl print_hex_byte -print_hex_byte: - rorb $4, %al - call print_hex_nibble - rorb $4, %al - /* Fall through */ - .size print_hex_byte, . - print_hex_byte - .globl print_hex_nibble -print_hex_nibble: - /* Preserve registers */ - pushw %ax - /* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */ - andb $0x0f, %al - cmpb $10, %al - sbbb $0x69, %al - das - call print_character - /* Restore registers and return */ - popw %ax - ret - .size print_hex_nibble, . - print_hex_nibble - -/***************************************************************************** - * Utility function: print PCI bus:dev.fn - * - * Parameters: - * %ax : PCI bus:dev.fn to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_pci_busdevfn -print_pci_busdevfn: - /* Preserve registers */ - pushw %ax - /* Print bus */ - xchgb %al, %ah - call print_hex_byte - /* Print ":" */ - movb $( ':' ), %al - call print_character - /* Print device */ - movb %ah, %al - shrb $3, %al - call print_hex_byte - /* Print "." */ - movb $( '.' ), %al - call print_character - /* Print function */ - movb %ah, %al - andb $0x07, %al - call print_hex_nibble - /* Restore registers and return */ - popw %ax - ret - .size print_pci_busdevfn, . - print_pci_busdevfn - -/***************************************************************************** - * Utility function: clear current line - * - * Parameters: - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl print_kill_line -print_kill_line: - /* Preserve registers */ - pushw %ax - pushw %cx - /* Print CR */ - movb $( '\r' ), %al - call print_character - /* Print 79 spaces */ - movb $( ' ' ), %al - movw $79, %cx -1: call print_character - loop 1b - /* Print CR */ - movb $( '\r' ), %al - call print_character - /* Restore registers and return */ - popw %cx - popw %ax - ret - .size print_kill_line, . - print_kill_line - -/**************************************************************************** - * pm_call (real-mode near call) - * - * Call routine in 16-bit protected mode for access to extended memory - * - * Parameters: - * %ax : address of routine to call in 16-bit protected mode - * Returns: - * none - * Corrupts: - * %ax - * - * The specified routine is called in 16-bit protected mode, with: - * - * %cs : 16-bit code segment with base matching real-mode %cs - * %ss : 16-bit data segment with base matching real-mode %ss - * %ds,%es,%fs,%gs : 32-bit data segment with zero base and 4GB limit - * - **************************************************************************** - */ - -#ifndef KEEP_IT_REAL - - /* GDT for protected-mode calls */ - .section ".prefix.lib", "awx", @progbits - .align 16 -pm_call_vars: -gdt: -gdt_limit: .word gdt_length - 1 -gdt_base: .long 0 - .word 0 /* padding */ -pm_cs: /* 16-bit protected-mode code segment */ - .equ PM_CS, pm_cs - gdt - .word 0xffff, 0 - .byte 0, 0x9b, 0x00, 0 -pm_ss: /* 16-bit protected-mode stack segment */ - .equ PM_SS, pm_ss - gdt - .word 0xffff, 0 - .byte 0, 0x93, 0x00, 0 -pm_ds: /* 32-bit protected-mode flat data segment */ - .equ PM_DS, pm_ds - gdt - .word 0xffff, 0 - .byte 0, 0x93, 0xcf, 0 -gdt_end: - .equ gdt_length, . - gdt - .size gdt, . - gdt - - .section ".prefix.lib", "awx", @progbits - .align 16 -pm_saved_gdt: - .long 0, 0 - .size pm_saved_gdt, . - pm_saved_gdt - - .equ pm_call_vars_size, . - pm_call_vars -#define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) ) - - .section ".prefix.lib", "awx", @progbits - .code16 -pm_call: - /* Preserve registers, flags, and RM return point */ - pushw %bp - movw %sp, %bp - subw $pm_call_vars_size, %sp - andw $0xfff0, %sp - pushfl - pushw %gs - pushw %fs - pushw %es - pushw %ds - pushw %ss - pushw %cs - pushw $99f - - /* Set up local variable block, and preserve GDT */ - pushw %cx - pushw %si - pushw %di - pushw %ss - popw %es - movw $pm_call_vars, %si - leaw PM_CALL_VAR(pm_call_vars)(%bp), %di - movw $pm_call_vars_size, %cx - cs rep movsb - popw %di - popw %si - popw %cx - sgdt PM_CALL_VAR(pm_saved_gdt)(%bp) - - /* Set up GDT bases */ - pushl %eax - pushl %edi - xorl %eax, %eax - movw %ss, %ax - shll $4, %eax - movzwl %bp, %edi - addr32 leal PM_CALL_VAR(gdt)(%eax, %edi), %eax - movl %eax, PM_CALL_VAR(gdt_base)(%bp) - movw %cs, %ax - movw $PM_CALL_VAR(pm_cs), %di - call set_seg_base - movw %ss, %ax - movw $PM_CALL_VAR(pm_ss), %di - call set_seg_base - popl %edi - popl %eax - - /* Switch CPU to protected mode and load up segment registers */ - pushl %eax - cli - data32 lgdt PM_CALL_VAR(gdt)(%bp) - movl %cr0, %eax - orb $CR0_PE, %al - movl %eax, %cr0 - ljmp $PM_CS, $1f -1: movw $PM_SS, %ax - movw %ax, %ss - movw $PM_DS, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - popl %eax - - /* Call PM routine */ - call *%ax - - /* Set real-mode segment limits on %ds, %es, %fs and %gs */ - movw %ss, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - - /* Return CPU to real mode */ - movl %cr0, %eax - andb $0!CR0_PE, %al - movl %eax, %cr0 - - /* Restore registers and flags */ - lret /* will ljmp to 99f */ -99: popw %ss - popw %ds - popw %es - popw %fs - popw %gs - data32 lgdt PM_CALL_VAR(pm_saved_gdt)(%bp) - popfl - movw %bp, %sp - popw %bp - ret - .size pm_call, . - pm_call - -set_seg_base: - rolw $4, %ax - movw %ax, 2(%bp,%di) - andw $0xfff0, 2(%bp,%di) - movb %al, 4(%bp,%di) - andb $0x0f, 4(%bp,%di) - ret - .size set_seg_base, . - set_seg_base - -#endif /* KEEP_IT_REAL */ - -/**************************************************************************** - * copy_bytes (real-mode or 16-bit protected-mode near call) - * - * Copy bytes - * - * Parameters: - * %ds:esi : source address - * %es:edi : destination address - * %ecx : length - * Returns: - * %ds:esi : next source address - * %es:edi : next destination address - * Corrupts: - * None - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 -copy_bytes: - pushl %ecx - rep addr32 movsb - popl %ecx - ret - .size copy_bytes, . - copy_bytes - -/**************************************************************************** - * install_block (real-mode near call) - * - * Install block to specified address - * - * Parameters: - * %esi : source physical address (must be a multiple of 16) - * %edi : destination physical address (must be a multiple of 16) - * %ecx : length of (decompressed) data - * %edx : total length of block (including any uninitialised data portion) - * Returns: - * %esi : next source physical address (will be a multiple of 16) - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 -install_block: - -#ifdef KEEP_IT_REAL - - /* Preserve registers */ - pushw %ds - pushw %es - pushl %ecx - pushl %edi - - /* Convert %esi and %edi to segment registers */ - shrl $4, %esi - movw %si, %ds - xorw %si, %si - shrl $4, %edi - movw %di, %es - xorw %di, %di - -#else /* KEEP_IT_REAL */ - - /* Call self in protected mode */ - pushw %ax - movw $1f, %ax - call pm_call - popw %ax - ret -1: - /* Preserve registers */ - pushl %ecx - pushl %edi - -#endif /* KEEP_IT_REAL */ - - -#if COMPRESS - /* Decompress source to destination */ - call decompress16 -#else - /* Copy source to destination */ - call copy_bytes -#endif - - /* Zero .bss portion */ - negl %ecx - addl %edx, %ecx - pushw %ax - xorw %ax, %ax - rep addr32 stosb - popw %ax - - /* Round up %esi to start of next source block */ - addl $0xf, %esi - andl $~0xf, %esi - - -#ifdef KEEP_IT_REAL - - /* Convert %ds:esi back to a physical address */ - movzwl %ds, %cx - shll $4, %ecx - addl %ecx, %esi - - /* Restore registers */ - popl %edi - popl %ecx - popw %es - popw %ds - -#else /* KEEP_IT_REAL */ - - /* Restore registers */ - popl %edi - popl %ecx - -#endif - - ret - .size install_block, . - install_block - -/**************************************************************************** - * alloc_basemem (real-mode near call) - * - * Allocate space for .text16 and .data16 from top of base memory. - * Memory is allocated using the BIOS free base memory counter at - * 0x40:13. - * - * Parameters: - * none - * Returns: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl alloc_basemem -alloc_basemem: - /* Preserve registers */ - pushw %fs - - /* FBMS => %ax as segment address */ - pushw $0x40 - popw %fs - movw %fs:0x13, %ax - shlw $6, %ax - - /* Calculate .data16 segment address */ - subw $_data16_memsz_pgh, %ax - pushw %ax - - /* Calculate .text16 segment address */ - subw $_text16_memsz_pgh, %ax - pushw %ax - - /* Update FBMS */ - shrw $6, %ax - movw %ax, %fs:0x13 - - /* Retrieve .text16 and .data16 segment addresses */ - popw %ax - popw %bx - - /* Restore registers and return */ - popw %fs - ret - .size alloc_basemem, . - alloc_basemem - -/**************************************************************************** - * free_basemem (real-mode near call) - * - * Free space allocated with alloc_basemem. - * - * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Returns: - * %ax : 0 if successfully freed - * Corrupts: - * none - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 - .globl free_basemem -free_basemem: - /* Preserve registers */ - pushw %fs - - /* Check FBMS counter */ - pushw %ax - shrw $6, %ax - pushw $0x40 - popw %fs - cmpw %ax, %fs:0x13 - popw %ax - jne 1f - - /* Check hooked interrupt count */ - cmpw $0, %cs:hooked_bios_interrupts - jne 1f - - /* OK to free memory */ - addw $_text16_memsz_pgh, %ax - addw $_data16_memsz_pgh, %ax - shrw $6, %ax - movw %ax, %fs:0x13 - xorw %ax, %ax - -1: /* Restore registers and return */ - popw %fs - ret - .size free_basemem, . - free_basemem - - .section ".text16.data", "aw", @progbits - .globl hooked_bios_interrupts -hooked_bios_interrupts: - .word 0 - .size hooked_bios_interrupts, . - hooked_bios_interrupts - -/**************************************************************************** - * install (real-mode near call) - * - * Install all text and data segments. - * - * Parameters: - * none - * Returns: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl install -install: - /* Preserve registers */ - pushl %esi - pushl %edi - /* Allocate space for .text16 and .data16 */ - call alloc_basemem - /* Image source = %cs:0000 */ - xorl %esi, %esi - /* Image destination = HIGHMEM_LOADPOINT */ - movl $HIGHMEM_LOADPOINT, %edi - /* Install text and data segments */ - call install_prealloc - /* Restore registers and return */ - popl %edi - popl %esi - ret - .size install, . - install - -/**************************************************************************** - * install_prealloc (real-mode near call) - * - * Install all text and data segments. - * - * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address - * %esi : Image source physical address (or zero for %cs:0000) - * %edi : Decompression temporary area physical address - * Corrupts: - * none - **************************************************************************** - */ - .section ".prefix.lib", "awx", @progbits - .code16 - .globl install_prealloc -install_prealloc: - /* Save registers */ - pushal - pushw %ds - pushw %es - - /* Sanity: clear the direction flag asap */ - cld - - /* Calculate physical address of payload (i.e. first source) */ - testl %esi, %esi - jnz 1f - movw %cs, %si - shll $4, %esi -1: addl $_payload_lma, %esi - - /* Install .text16 and .data16 */ - pushl %edi - movzwl %ax, %edi - shll $4, %edi - movl $_text16_memsz, %ecx - movl %ecx, %edx - call install_block /* .text16 */ - movzwl %bx, %edi - shll $4, %edi - movl $_data16_filesz, %ecx - movl $_data16_memsz, %edx - call install_block /* .data16 */ - popl %edi - - /* Set up %ds for access to .data16 */ - movw %bx, %ds - -#ifdef KEEP_IT_REAL - /* Initialise libkir */ - movw %ax, (init_libkir_vector+2) - lcall *init_libkir_vector -#else - /* Install .text and .data to temporary area in high memory, - * prior to reading the E820 memory map and relocating - * properly. - */ - movl $_textdata_filesz, %ecx - movl $_textdata_memsz, %edx - call install_block - - /* Initialise librm at current location */ - movw %ax, (init_librm_vector+2) - lcall *init_librm_vector - - /* 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. - */ - movw %ax, (prot_call_vector+2) - pushl $relocate - lcall *prot_call_vector - popl %edx /* discard */ - - /* Copy code to new location */ - pushl %edi - pushw %ax - movw $copy_bytes, %ax - call pm_call - popw %ax - popl %edi - - /* Initialise librm at new location */ - lcall *init_librm_vector - -#endif - /* Restore registers */ - popw %es - popw %ds - popal - ret - .size install_prealloc, . - install_prealloc - - /* Vectors for far calls to .text16 functions */ - .section ".data16", "aw", @progbits -#ifdef KEEP_IT_REAL -init_libkir_vector: - .word init_libkir - .word 0 - .size init_libkir_vector, . - init_libkir_vector -#else -init_librm_vector: - .word init_librm - .word 0 - .size init_librm_vector, . - init_librm_vector -prot_call_vector: - .word prot_call - .word 0 - .size prot_call_vector, . - prot_call_vector -#endif - -/**************************************************************************** - * uninstall (real-mode near call) - * - * Uninstall all text and data segments. - * - * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address - * Returns: - * none - * Corrupts: - * none - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 - .globl uninstall -uninstall: - call free_basemem - ret - .size uninstall, . - uninstall - - - - /* File split information for the compressor */ -#if COMPRESS - .section ".zinfo", "a", @progbits - .ascii "COPY" - .long _prefix_lma - .long _prefix_filesz - .long _max_align - .ascii "PACK" - .long _text16_lma - .long _text16_filesz - .long _max_align - .ascii "PACK" - .long _data16_lma - .long _data16_filesz - .long _max_align - .ascii "PACK" - .long _textdata_lma - .long _textdata_filesz - .long _max_align -#else /* COMPRESS */ - .section ".zinfo", "a", @progbits - .ascii "COPY" - .long _prefix_lma - .long _filesz - .long _max_align -#endif /* COMPRESS */ diff --git a/gpxe/src/arch/i386/prefix/lkrnprefix.S b/gpxe/src/arch/i386/prefix/lkrnprefix.S deleted file mode 100644 index 101d0388..00000000 --- a/gpxe/src/arch/i386/prefix/lkrnprefix.S +++ /dev/null @@ -1,216 +0,0 @@ -/* - Copyright (C) 2000, Entity Cyber, Inc. - - Authors: Gary Byers (gb@thinguin.org) - Marty Connor (mdc@thinguin.org) - - This software may be used and distributed according to the terms - of the GNU Public License (GPL), incorporated herein by reference. - - Description: - - This is just a little bit of code and data that can get prepended - to a ROM image in order to allow bootloaders to load the result - as if it were a Linux kernel image. - - A real Linux kernel image consists of a one-sector boot loader - (to load the image from a floppy disk), followed a few sectors - of setup code, followed by the kernel code itself. There's - a table in the first sector (starting at offset 497) that indicates - how many sectors of setup code follow the first sector and which - contains some other parameters that aren't interesting in this - case. - - When a bootloader loads the sectors that comprise a kernel image, - it doesn't execute the code in the first sector (since that code - would try to load the image from a floppy disk.) The code in the - first sector below doesn't expect to get executed (and prints an - error message if it ever -is- executed.) - - We don't require much in the way of setup code. Historically, the - Linux kernel required at least 4 sectors of setup code. - Therefore, at least 4 sectors must be present even though we don't - use them. - -*/ - -FILE_LICENCE ( GPL_ANY ) - -#define SETUPSECS 4 /* Minimal nr of setup-sectors */ -#define PREFIXSIZE ((SETUPSECS+1)*512) -#define PREFIXPGH (PREFIXSIZE / 16 ) -#define BOOTSEG 0x07C0 /* original address of boot-sector */ -#define INITSEG 0x9000 /* we move boot here - out of the way */ -#define SETUPSEG 0x9020 /* setup starts here */ -#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */ - - .text - .code16 - .arch i386 - .org 0 - .section ".prefix", "ax", @progbits -/* - This is a minimal boot sector. If anyone tries to execute it (e.g., if - a .lilo file is dd'ed to a floppy), print an error message. -*/ - -bootsector: - jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */ -1: - movw $0x2000, %di /* 0x2000 is arbitrary value >= length - of bootsect + room for stack */ - - movw $BOOTSEG, %ax - movw %ax,%ds - movw %ax,%es - - cli - movw %ax, %ss /* put stack at BOOTSEG:0x2000. */ - movw %di,%sp - sti - - movw $why_end-why, %cx - movw $why, %si - - movw $0x0007, %bx /* page 0, attribute 7 (normal) */ - movb $0x0e, %ah /* write char, tty mode */ -prloop: - lodsb - int $0x10 - loop prloop -freeze: jmp freeze - -why: .ascii "This image cannot be loaded from a floppy disk.\r\n" -why_end: - - -/* - The following header is documented in the Linux source code at - Documentation/i386/boot.txt -*/ - .org 497 -setup_sects: - .byte SETUPSECS -root_flags: - .word 0 -syssize: - .long -PREFIXPGH - - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDL" - .long syssize - .long 16 - .long 0 - .previous - -ram_size: - .word 0 -vid_mode: - .word 0 -root_dev: - .word 0 -boot_flag: - .word 0xAA55 -jump: - /* Manually specify a two-byte jmp instruction here rather - * than leaving it up to the assembler. */ - .byte 0xeb - .byte setup_code - header -header: - .byte 'H', 'd', 'r', 'S' -version: - .word 0x0207 /* 2.07 */ -realmode_swtch: - .long 0 -start_sys: - .word 0 -kernel_version: - .word 0 -type_of_loader: - .byte 0 -loadflags: - .byte 0 -setup_move_size: - .word 0 -code32_start: - .long 0 -ramdisk_image: - .long 0 -ramdisk_size: - .long 0 -bootsect_kludge: - .long 0 -heap_end_ptr: - .word 0 -pad1: - .word 0 -cmd_line_ptr: - .long 0 -initrd_addr_max: - /* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have - * been known to require this field. Set the value to 2 GB. This - * value is also used by the Linux kernel. */ - .long 0x7fffffff -kernel_alignment: - .long 0 -relocatable_kernel: - .byte 0 -pad2: - .byte 0, 0, 0 -cmdline_size: - .long 0 -hardware_subarch: - .long 0 -hardware_subarch_data: - .byte 0, 0, 0, 0, 0, 0, 0, 0 - -/* - We don't need to do too much setup. - - This code gets loaded at SETUPSEG:0. It wants to start - executing the image that's loaded at SYSSEG:0 and - whose entry point is SYSSEG:0. -*/ -setup_code: - /* We expect to be contiguous in memory once loaded. The Linux image - * boot process requires that setup code is loaded separately from - * "non-real code". Since we don't need any information that's left - * in the prefix, it doesn't matter: we just have to ensure that - * %cs:0000 is where the start of the image *would* be. - */ - ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_gpxe - - - .org PREFIXSIZE -/* - We're now at the beginning of the kernel proper. - */ -run_gpxe: - /* Set up stack just below 0x7c00 */ - xorw %ax, %ax - movw %ax, %ss - movw $0x7c00, %sp - - /* Install gPXE */ - call install - - /* Set up real-mode stack */ - movw %bx, %ss - movw $_estack16, %sp - - /* Jump to .text16 segment */ - pushw %ax - pushw $1f - lret - .section ".text16", "awx", @progbits -1: - pushl $main - pushw %cs - call prot_call - popl %ecx /* discard */ - - /* Uninstall gPXE */ - call uninstall - - /* Boot next device */ - int $0x18 diff --git a/gpxe/src/arch/i386/prefix/mbr.S b/gpxe/src/arch/i386/prefix/mbr.S deleted file mode 100644 index adfe2041..00000000 --- a/gpxe/src/arch/i386/prefix/mbr.S +++ /dev/null @@ -1,13 +0,0 @@ - .text - .arch i386 - .section ".prefix", "awx", @progbits - .code16 - .org 0 - -mbr: - movw $exec_sector, %bp - jmp find_active_partition -exec_sector: - ljmp $0x0000, $0x7c00 - -#include "bootpart.S" diff --git a/gpxe/src/arch/i386/prefix/nbiprefix.S b/gpxe/src/arch/i386/prefix/nbiprefix.S deleted file mode 100644 index 607d80fb..00000000 --- a/gpxe/src/arch/i386/prefix/nbiprefix.S +++ /dev/null @@ -1,77 +0,0 @@ - .text - .arch i386 - .code16 - .section ".prefix", "ax", @progbits - .org 0 - -nbi_header: - -/***************************************************************************** - * NBI file header - ***************************************************************************** - */ -file_header: - .long 0x1b031336 /* Signature */ - .byte 0x04 /* 16 bytes header, no vendor info */ - .byte 0 - .byte 0 - .byte 0 /* No flags */ - .word 0x0000, 0x07c0 /* Load header to 0x07c0:0x0000 */ - .word entry, 0x07c0 /* Start execution at 0x07c0:entry */ - .size file_header, . - file_header - -/***************************************************************************** - * NBI segment header - ***************************************************************************** - */ -segment_header: - .byte 0x04 /* 16 bytes header, no vendor info */ - .byte 0 - .byte 0 - .byte 0x04 /* Last segment */ - .long 0x00007e00 -imglen: .long -512 -memlen: .long -512 - .size segment_header, . - segment_header - - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDL" - .long imglen - .long 1 - .long 0 - .ascii "ADDL" - .long memlen - .long 1 - .long 0 - .previous - -/***************************************************************************** - * NBI entry point - ***************************************************************************** - */ -entry: - /* Install gPXE */ - call install - - /* Jump to .text16 segment */ - pushw %ax - pushw $1f - lret - .section ".text16", "awx", @progbits -1: - pushl $main - pushw %cs - call prot_call - popl %ecx /* discard */ - - /* Uninstall gPXE */ - call uninstall - - /* Reboot system */ - int $0x19 - - .previous - .size entry, . - entry - -nbi_header_end: - .org 512 diff --git a/gpxe/src/arch/i386/prefix/nullprefix.S b/gpxe/src/arch/i386/prefix/nullprefix.S deleted file mode 100644 index 032d41e0..00000000 --- a/gpxe/src/arch/i386/prefix/nullprefix.S +++ /dev/null @@ -1,13 +0,0 @@ - .org 0 - .text - .arch i386 - - .section ".prefix", "ax", @progbits - .code16 -_prefix: - - .section ".text16", "ax", @progbits -prefix_exit: - -prefix_exit_end: - .previous diff --git a/gpxe/src/arch/i386/prefix/pxeprefix.S b/gpxe/src/arch/i386/prefix/pxeprefix.S deleted file mode 100644 index e728c482..00000000 --- a/gpxe/src/arch/i386/prefix/pxeprefix.S +++ /dev/null @@ -1,761 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ) - -#define PXENV_UNDI_SHUTDOWN 0x0005 -#define PXENV_UNDI_GET_NIC_TYPE 0x0012 -#define PXENV_UNDI_GET_IFACE_INFO 0x0013 -#define PXENV_STOP_UNDI 0x0015 -#define PXENV_UNLOAD_STACK 0x0070 - -#define PXE_HACK_EB54 0x0001 - - .text - .arch i386 - .org 0 - .code16 - -#include <undi.h> - -#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) ) -#define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) ) -#define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) ) - -/***************************************************************************** - * Entry point: set operating context, print welcome message - ***************************************************************************** - */ - .section ".prefix", "ax", @progbits - jmp $0x7c0, $1f -1: - /* Preserve registers for possible return to PXE */ - pushfl - pushal - pushw %gs - pushw %fs - pushw %es - pushw %ds - - /* Store magic word on PXE stack and remember PXE %ss:esp */ - pushl $STACK_MAGIC - movw %ss, %cs:pxe_ss - movl %esp, %cs:pxe_esp - - /* Set up segments */ - movw %cs, %ax - movw %ax, %ds - movw $0x40, %ax /* BIOS data segment access */ - movw %ax, %fs - /* Set up stack just below 0x7c00 */ - xorw %ax, %ax - movw %ax, %ss - movl $0x7c00, %esp - /* Clear direction flag, for the sake of sanity */ - cld - /* Print welcome message */ - movw $10f, %si - xorw %di, %di - call print_message - .section ".prefix.data", "aw", @progbits -10: .asciz "PXE->EB:" - .previous - -/***************************************************************************** - * Find us a usable !PXE or PXENV+ entry point - ***************************************************************************** - */ -detect_pxe: - /* Plan A: !PXE pointer from the stack */ - lgsl pxe_esp, %ebp /* %gs:%bp -> original stack */ - lesw %gs:52(%bp), %bx - call is_valid_ppxe - je have_ppxe - - /* Plan B: PXENV+ pointer from initial ES:BX */ - movw %gs:32(%bp),%bx - movw %gs:8(%bp),%es - call is_valid_pxenv - je have_pxenv - - /* Plan C: PXENV+ structure via INT 1Ah */ - movw $0x5650, %ax - int $0x1a - jc 1f - cmpw $0x564e, %ax - jne 1f - call is_valid_pxenv - je have_pxenv -1: - /* Plan D: scan base memory for !PXE */ - call memory_scan_ppxe - je have_ppxe - - /* Plan E: scan base memory for PXENV+ */ - call memory_scan_pxenv - jne stack_not_found - -have_pxenv: - movw %bx, pxenv_offset - movw %es, pxenv_segment - - cmpw $0x201, %es:6(%bx) /* API version >= 2.01 */ - jb 1f - cmpb $0x2c, %es:8(%bx) /* ... and structure long enough */ - jb 2f - - lesw %es:0x28(%bx), %bx /* Find !PXE from PXENV+ */ - call is_valid_ppxe - je have_ppxe -2: - call memory_scan_ppxe /* We are *supposed* to have !PXE... */ - je have_ppxe -1: - lesw pxenv_segoff, %bx /* Nope, we're stuck with PXENV+ */ - - /* Record entry point and UNDI segments */ - pushl %es:0x0a(%bx) /* Entry point */ - pushw %es:0x24(%bx) /* UNDI code segment */ - pushw %es:0x26(%bx) /* UNDI code size */ - pushw %es:0x20(%bx) /* UNDI data segment */ - pushw %es:0x22(%bx) /* UNDI data size */ - - /* Print "PXENV+ at <address>" */ - movw $10f, %si - jmp check_have_stack - .section ".prefix.data", "aw", @progbits -10: .asciz " PXENV+ at " - .previous - -have_ppxe: - movw %bx, ppxe_offset - movw %es, ppxe_segment - - pushl %es:0x10(%bx) /* Entry point */ - pushw %es:0x30(%bx) /* UNDI code segment */ - pushw %es:0x36(%bx) /* UNDI code size */ - pushw %es:0x28(%bx) /* UNDI data segment */ - pushw %es:0x2e(%bx) /* UNDI data size */ - - /* Print "!PXE at <address>" */ - movw $10f, %si - jmp check_have_stack - .section ".prefix.data", "aw", @progbits -10: .asciz " !PXE at " - .previous - -is_valid_ppxe: - cmpl $0x45585021, %es:(%bx) - jne 1f - movzbw %es:4(%bx), %cx - cmpw $0x58, %cx - jae is_valid_checksum -1: - ret - -is_valid_pxenv: - cmpl $0x4e455850, %es:(%bx) - jne 1b - cmpw $0x2b56, %es:4(%bx) - jne 1b - movzbw %es:8(%bx), %cx - cmpw $0x28, %cx - jb 1b - -is_valid_checksum: - pushw %ax - movw %bx, %si - xorw %ax, %ax -2: - es lodsb - addb %al, %ah - loopw 2b - popw %ax - ret - -memory_scan_ppxe: - movw $is_valid_ppxe, %dx - jmp memory_scan_common - -memory_scan_pxenv: - movw $is_valid_pxenv, %dx - -memory_scan_common: - movw %fs:(0x13), %ax - shlw $6, %ax - decw %ax -1: incw %ax - cmpw $( 0xa000 - 1 ), %ax - ja 2f - movw %ax, %es - xorw %bx, %bx - call *%dx - jne 1b -2: ret - -/***************************************************************************** - * Sanity check: we must have an entry point - ***************************************************************************** - */ -check_have_stack: - /* Save common values pushed onto the stack */ - popl undi_data_segoff - popl undi_code_segoff - popl entry_segoff - - /* Print have !PXE/PXENV+ message; structure pointer in %es:%bx */ - call print_message - call print_segoff - movb $( ',' ), %al - call print_character - - /* Check for entry point */ - movl entry_segoff, %eax - testl %eax, %eax - jnz 99f - /* No entry point: print message and skip everything else */ -stack_not_found: - movw $10f, %si - call print_message - jmp finished - .section ".prefix.data", "aw", @progbits -10: .asciz " No PXE stack found!\n" - .previous -99: - -/***************************************************************************** - * Calculate base memory usage by UNDI - ***************************************************************************** - */ -find_undi_basemem_usage: - movw undi_code_segment, %ax - movw undi_code_size, %bx - movw undi_data_segment, %cx - movw undi_data_size, %dx - cmpw %ax, %cx - ja 1f - xchgw %ax, %cx - xchgw %bx, %dx -1: /* %ax:%bx now describes the lower region, %cx:%dx the higher */ - shrw $6, %ax /* Round down to nearest kB */ - movw %ax, undi_fbms_start - addw $0x0f, %dx /* Round up to next segment */ - shrw $4, %dx - addw %dx, %cx - addw $((1024 / 16) - 1), %cx /* Round up to next kB */ - shrw $6, %cx - movw %cx, undi_fbms_end - -/***************************************************************************** - * Print information about detected PXE stack - ***************************************************************************** - */ -print_structure_information: - /* Print entry point */ - movw $10f, %si - call print_message - les entry_segoff, %bx - call print_segoff - .section ".prefix.data", "aw", @progbits -10: .asciz " entry point at " - .previous - /* Print UNDI code segment */ - movw $10f, %si - call print_message - les undi_code_segoff, %bx - call print_segoff - .section ".prefix.data", "aw", @progbits -10: .asciz "\n UNDI code segment " - .previous - /* Print UNDI data segment */ - movw $10f, %si - call print_message - les undi_data_segoff, %bx - call print_segoff - .section ".prefix.data", "aw", @progbits -10: .asciz ", data segment " - .previous - /* Print UNDI memory usage */ - movw $10f, %si - call print_message - movw undi_fbms_start, %ax - call print_word - movb $( '-' ), %al - call print_character - movw undi_fbms_end, %ax - call print_word - movw $20f, %si - call print_message - .section ".prefix.data", "aw", @progbits -10: .asciz " (" -20: .asciz "kB)\n" - .previous - -/***************************************************************************** - * Determine physical device - ***************************************************************************** - */ -get_physical_device: - /* Issue PXENV_UNDI_GET_NIC_TYPE */ - movw $PXENV_UNDI_GET_NIC_TYPE, %bx - call pxe_call - jnc 1f - call print_pxe_error - jmp no_physical_device -1: /* Determine physical device type */ - movb ( pxe_parameter_structure + 0x02 ), %al - cmpb $2, %al - je pci_physical_device - jmp no_physical_device - -pci_physical_device: - /* Record PCI bus:dev.fn and vendor/device IDs */ - movl ( pxe_parameter_structure + 0x03 ), %eax - movl %eax, pci_vendor - movw ( pxe_parameter_structure + 0x0b ), %ax - movw %ax, pci_busdevfn - movw $10f, %si - call print_message - call print_pci_busdevfn - jmp 99f - .section ".prefix.data", "aw", @progbits -10: .asciz " UNDI device is PCI " - .previous - -no_physical_device: - /* No device found, or device type not understood */ - movw $10f, %si - call print_message - .section ".prefix.data", "aw", @progbits -10: .asciz " Unable to determine UNDI physical device" - .previous - -99: - -/***************************************************************************** - * Determine interface type - ***************************************************************************** - */ -get_iface_type: - /* Issue PXENV_UNDI_GET_IFACE_INFO */ - movw $PXENV_UNDI_GET_IFACE_INFO, %bx - call pxe_call - jnc 1f - call print_pxe_error - jmp 99f -1: /* Print interface type */ - movw $10f, %si - call print_message - leaw ( pxe_parameter_structure + 0x02 ), %si - call print_message - .section ".prefix.data", "aw", @progbits -10: .asciz ", type " - .previous - /* Check for "Etherboot" interface type */ - cmpl $EB_MAGIC_1, ( pxe_parameter_structure + 0x02 ) - jne 99f - cmpl $EB_MAGIC_2, ( pxe_parameter_structure + 0x06 ) - jne 99f - movw $10f, %si - call print_message - .section ".prefix.data", "aw", @progbits -10: .asciz " (workaround enabled)" - .previous - /* Flag Etherboot workarounds as required */ - orw $PXE_HACK_EB54, pxe_hacks - -99: movb $0x0a, %al - call print_character - -/***************************************************************************** - * Leave NIC in a safe state - ***************************************************************************** - */ -#ifndef PXELOADER_KEEP_PXE -shutdown_nic: - /* Issue PXENV_UNDI_SHUTDOWN */ - movw $PXENV_UNDI_SHUTDOWN, %bx - call pxe_call - jnc 1f - call print_pxe_error -1: -unload_base_code: - /* Etherboot treats PXENV_UNLOAD_STACK as PXENV_STOP_UNDI, so - * we must not issue this call if the underlying stack is - * Etherboot and we were not intending to issue a PXENV_STOP_UNDI. - */ -#ifdef PXELOADER_KEEP_UNDI - testw $PXE_HACK_EB54, pxe_hacks - jnz 99f -#endif /* PXELOADER_KEEP_UNDI */ - /* Issue PXENV_UNLOAD_STACK */ - movw $PXENV_UNLOAD_STACK, %bx - call pxe_call - jnc 1f - call print_pxe_error - jmp 99f -1: /* Free base memory used by PXE base code */ - movw undi_fbms_start, %ax - movw %fs:(0x13), %bx - call free_basemem -99: - andw $~( UNDI_FL_INITIALIZED | UNDI_FL_KEEP_ALL ), flags -#endif /* PXELOADER_KEEP_PXE */ - -/***************************************************************************** - * Unload UNDI driver - ***************************************************************************** - */ -#ifndef PXELOADER_KEEP_UNDI -unload_undi: - /* Issue PXENV_STOP_UNDI */ - movw $PXENV_STOP_UNDI, %bx - call pxe_call - jnc 1f - call print_pxe_error - jmp 99f -1: /* Free base memory used by UNDI */ - movw undi_fbms_end, %ax - movw undi_fbms_start, %bx - call free_basemem - /* Clear UNDI_FL_STARTED */ - andw $~UNDI_FL_STARTED, flags -99: -#endif /* PXELOADER_KEEP_UNDI */ - -/***************************************************************************** - * Print remaining free base memory - ***************************************************************************** - */ -print_free_basemem: - movw $10f, %si - call print_message - movw %fs:(0x13), %ax - call print_word - movw $20f, %si - call print_message - .section ".prefix.data", "aw", @progbits -10: .asciz " " -20: .asciz "kB free base memory after PXE unload\n" - .previous - -/***************************************************************************** - * Exit point - ***************************************************************************** - */ -finished: - jmp run_gpxe - -/***************************************************************************** - * Subroutine: print segment:offset address - * - * Parameters: - * %es:%bx : segment:offset address to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ -print_segoff: - /* Preserve registers */ - pushw %ax - /* Print "<segment>:offset" */ - movw %es, %ax - call print_hex_word - movb $( ':' ), %al - call print_character - movw %bx, %ax - call print_hex_word - /* Restore registers and return */ - popw %ax - ret - -/***************************************************************************** - * Subroutine: print decimal word - * - * Parameters: - * %ax : word to print - * %ds:di : output buffer (or %di=0 to print to console) - * Returns: - * %ds:di : next character in output buffer (if applicable) - ***************************************************************************** - */ -print_word: - /* Preserve registers */ - pushw %ax - pushw %bx - pushw %cx - pushw %dx - /* Build up digit sequence on stack */ - movw $10, %bx - xorw %cx, %cx -1: xorw %dx, %dx - divw %bx, %ax - pushw %dx - incw %cx - testw %ax, %ax - jnz 1b - /* Print digit sequence */ -1: popw %ax - call print_hex_nibble - loop 1b - /* Restore registers and return */ - popw %dx - popw %cx - popw %bx - popw %ax - ret - -/***************************************************************************** - * Subroutine: zero 1kB block of base memory - * - * Parameters: - * %bx : block to zero (in kB) - * Returns: - * Nothing - ***************************************************************************** - */ -zero_kb: - /* Preserve registers */ - pushw %ax - pushw %cx - pushw %di - pushw %es - /* Zero block */ - movw %bx, %ax - shlw $6, %ax - movw %ax, %es - movw $0x400, %cx - xorw %di, %di - xorw %ax, %ax - rep stosb - /* Restore registers and return */ - popw %es - popw %di - popw %cx - popw %ax - ret - -/***************************************************************************** - * Subroutine: free and zero base memory - * - * Parameters: - * %ax : Desired new free base memory counter (in kB) - * %bx : Expected current free base memory counter (in kB) - * %fs : BIOS data segment (0x40) - * Returns: - * None - * - * The base memory from %bx kB to %ax kB is unconditionally zeroed. - * It will be freed if and only if the expected current free base - * memory counter (%bx) matches the actual current free base memory - * counter in 0x40:0x13; if this does not match then the memory will - * be leaked. - ***************************************************************************** - */ -free_basemem: - /* Zero base memory */ - pushw %bx -1: cmpw %bx, %ax - je 2f - call zero_kb - incw %bx - jmp 1b -2: popw %bx - /* Free base memory */ - cmpw %fs:(0x13), %bx /* Update FBMS only if "old" value */ - jne 1f /* is correct */ -1: movw %ax, %fs:(0x13) - ret - -/***************************************************************************** - * Subroutine: make a PXE API call. Works with either !PXE or PXENV+ API. - * - * Parameters: - * %bx : PXE API call number - * %ds:pxe_parameter_structure : Parameters for PXE API call - * Returns: - * %ax : PXE status code (not exit code) - * CF set if %ax is non-zero - ***************************************************************************** - */ -pxe_call: - /* Preserve registers */ - pushw %di - pushw %es - /* Set up registers for PXENV+ API. %bx already set up */ - pushw %ds - popw %es - movw $pxe_parameter_structure, %di - /* Set up stack for !PXE API */ - pushw %es - pushw %di - pushw %bx - /* Make the API call */ - lcall *entry_segoff - /* Reset the stack */ - addw $6, %sp - movw pxe_parameter_structure, %ax - clc - testw %ax, %ax - jz 1f - stc -1: /* Clear direction flag, for the sake of sanity */ - cld - /* Restore registers and return */ - popw %es - popw %di - ret - -/***************************************************************************** - * Subroutine: print PXE API call error message - * - * Parameters: - * %ax : PXE status code - * %bx : PXE API call number - * Returns: - * Nothing - ***************************************************************************** - */ -print_pxe_error: - pushw %si - movw $10f, %si - call print_message - xchgw %ax, %bx - call print_hex_word - movw $20f, %si - call print_message - xchgw %ax, %bx - call print_hex_word - movw $30f, %si - call print_message - popw %si - ret - .section ".prefix.data", "aw", @progbits -10: .asciz " UNDI API call " -20: .asciz " failed: status code " -30: .asciz "\n" - .previous - -/***************************************************************************** - * PXE data structures - ***************************************************************************** - */ - .section ".prefix.data" - -pxe_esp: .long 0 -pxe_ss: .word 0 - -pxe_parameter_structure: .fill 64 - -undi_code_segoff: -undi_code_size: .word 0 -undi_code_segment: .word 0 - -undi_data_segoff: -undi_data_size: .word 0 -undi_data_segment: .word 0 - -pxe_hacks: .word 0 - -/* The following fields are part of a struct undi_device */ - -undi_device: - -pxenv_segoff: -pxenv_offset: .word 0 -pxenv_segment: .word 0 - -ppxe_segoff: -ppxe_offset: .word 0 -ppxe_segment: .word 0 - -entry_segoff: -entry_offset: .word 0 -entry_segment: .word 0 - -undi_fbms_start: .word 0 -undi_fbms_end: .word 0 - -pci_busdevfn: .word UNDI_NO_PCI_BUSDEVFN -isapnp_csn: .word UNDI_NO_ISAPNP_CSN -isapnp_read_port: .word UNDI_NO_ISAPNP_READ_PORT - -pci_vendor: .word 0 -pci_device: .word 0 -flags: - .word ( UNDI_FL_INITIALIZED | UNDI_FL_STARTED | UNDI_FL_KEEP_ALL ) - - .equ undi_device_size, ( . - undi_device ) - -/***************************************************************************** - * Run gPXE main code - ***************************************************************************** - */ - .section ".prefix" -run_gpxe: - /* Install gPXE */ - call install - - /* Set up real-mode stack */ - movw %bx, %ss - movw $_estack16, %sp - -#ifdef PXELOADER_KEEP_UNDI - /* Copy our undi_device structure to the preloaded_undi variable */ - movw %bx, %es - movw $preloaded_undi, %di - movw $undi_device, %si - movw $undi_device_size, %cx - rep movsb -#endif - - /* Retrieve PXE %ss:esp */ - movw pxe_ss, %di - movl pxe_esp, %ebp - - /* Jump to .text16 segment with %ds pointing to .data16 */ - movw %bx, %ds - pushw %ax - pushw $1f - lret - .section ".text16", "ax", @progbits -1: - /* Update the exit hook */ - movw %cs,pxe_exit_hook+2 - push %ax - mov $2f,%ax - mov %ax,pxe_exit_hook - pop %ax - - /* Run main program */ - pushl $main - pushw %cs - call prot_call - popl %ecx /* discard */ - - /* Uninstall gPXE */ - call uninstall - - /* Restore PXE stack */ - movw %di, %ss - movl %ebp, %esp - - /* Jump to hook if applicable */ - ljmpw *pxe_exit_hook - -2: /* Check PXE stack magic */ - popl %eax - cmpl $STACK_MAGIC, %eax - jne 1f - - /* PXE stack OK: return to caller */ - popw %ds - popw %es - popw %fs - popw %gs - popal - popfl - xorw %ax, %ax /* Return success */ - lret - -1: /* PXE stack corrupt or removed: use INT 18 */ - int $0x18 - .previous diff --git a/gpxe/src/arch/i386/prefix/romprefix.S b/gpxe/src/arch/i386/prefix/romprefix.S deleted file mode 100644 index 02e54976..00000000 --- a/gpxe/src/arch/i386/prefix/romprefix.S +++ /dev/null @@ -1,1079 +0,0 @@ -/* At entry, the processor is in 16 bit real mode and the code is being - * executed from an address it was not linked to. Code must be pic and - * 32 bit sensitive until things are fixed up. - * - * Also be very careful as the stack is at the rear end of the interrupt - * table so using a noticeable amount of stack space is a no-no. - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -#include <config/general.h> - -#define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) ) -#define PMM_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'M' << 16 ) + ( 'M' << 24 ) ) -#define PCI_SIGNATURE ( 'P' + ( 'C' << 8 ) + ( 'I' << 16 ) + ( ' ' << 24 ) ) -#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) ) -#define PNP_GET_BBS_VERSION 0x60 -#define PMM_ALLOCATE 0x0000 -#define PMM_DEALLOCATE 0x0002 - -/* ROM banner timeout. Based on the configurable BANNER_TIMEOUT in - * config.h, but converted to a number of (18Hz) timer ticks, and - * doubled to allow for BIOSes that switch video modes immediately - * beforehand, so rendering the message almost invisible to the user. - */ -#define ROM_BANNER_TIMEOUT ( 2 * ( 18 * BANNER_TIMEOUT ) / 10 ) - -/* We can load a ROM in two ways: have the BIOS load all of it (.rom prefix) - * or have the BIOS load a stub that loads the rest using PCI (.xrom prefix). - * The latter is not as widely supported, but allows the use of large ROMs - * on some systems with crowded option ROM space. - */ - -#ifdef LOAD_ROM_FROM_PCI -#define ROM_SIZE_VALUE _prefix_filesz_sect /* Amount to load in BIOS */ -#else -#define ROM_SIZE_VALUE 0 /* Load amount (before compr. fixup) */ -#endif - - - .text - .code16 - .arch i386 - .section ".prefix", "ax", @progbits - - .org 0x00 -romheader: - .word 0xAA55 /* BIOS extension signature */ -romheader_size: .byte ROM_SIZE_VALUE /* Size in 512-byte blocks */ - jmp init /* Initialisation vector */ -checksum: - .byte 0, 0 -real_size: - .word 0 - .org 0x16 - .word undiheader - .org 0x18 - .word pciheader - .org 0x1a - .word pnpheader - .size romheader, . - romheader - - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ -#ifndef LOAD_ROM_FROM_PCI - .ascii "ADDB" - .long romheader_size - .long 512 - .long 0 -#endif - .ascii "ADDB" - .long real_size - .long 512 - .long 0 - .previous - -pciheader: - .ascii "PCIR" /* Signature */ - .word pci_vendor_id /* Vendor identification */ - .word pci_device_id /* Device identification */ - .word 0x0000 /* Device list pointer */ - .word pciheader_len /* PCI data structure length */ - .byte 0x03 /* PCI data structure revision */ - .byte 0x02, 0x00, 0x00 /* Class code */ -pciheader_image_length: - .word ROM_SIZE_VALUE /* Image length */ - .word 0x0001 /* Revision level */ - .byte 0x00 /* Code type */ - .byte 0x80 /* Last image indicator */ -pciheader_runtime_length: - .word ROM_SIZE_VALUE /* Maximum run-time image length */ - .word 0x0000 /* Configuration utility code header */ - .word 0x0000 /* DMTF CLP entry point */ - .equ pciheader_len, . - pciheader - .size pciheader, . - pciheader - -#ifndef LOAD_ROM_FROM_PCI - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDW" - .long pciheader_image_length - .long 512 - .long 0 - .ascii "ADDW" - .long pciheader_runtime_length - .long 512 - .long 0 - .previous -#endif - -pnpheader: - .ascii "$PnP" /* Signature */ - .byte 0x01 /* Structure revision */ - .byte ( pnpheader_len / 16 ) /* Length (in 16 byte increments) */ - .word 0x0000 /* Offset of next header */ - .byte 0x00 /* Reserved */ - .byte 0x00 /* Checksum */ - .long 0x00000000 /* Device identifier */ - .word mfgstr /* Manufacturer string */ - .word prodstr /* Product name */ - .byte 0x02 /* Device base type code */ - .byte 0x00 /* Device sub-type code */ - .byte 0x00 /* Device interface type code */ - .byte 0xf4 /* Device indicator */ - .word 0x0000 /* Boot connection vector */ - .word 0x0000 /* Disconnect vector */ - .word bev_entry /* Boot execution vector */ - .word 0x0000 /* Reserved */ - .word 0x0000 /* Static resource information vector*/ - .equ pnpheader_len, . - pnpheader - .size pnpheader, . - pnpheader - -/* Manufacturer string */ -mfgstr: - .asciz "http://etherboot.org" - .size mfgstr, . - mfgstr - -/* Product string - * - * Defaults to PRODUCT_SHORT_NAME. If the ROM image is writable at - * initialisation time, it will be filled in to include the PCI - * bus:dev.fn number of the card as well. - */ -prodstr: - .ascii PRODUCT_SHORT_NAME -prodstr_separator: - .byte 0 - .ascii "(PCI " -prodstr_pci_id: - .asciz "xx:xx.x)" /* Filled in by init code */ - .size prodstr, . - prodstr - - .globl undiheader - .weak undiloader -undiheader: - .ascii "UNDI" /* Signature */ - .byte undiheader_len /* Length of structure */ - .byte 0 /* Checksum */ - .byte 0 /* Structure revision */ - .byte 0,1,2 /* PXE version: 2.1.0 */ - .word undiloader /* Offset to loader routine */ - .word _data16_memsz /* Stack segment size */ - .word _data16_memsz /* Data segment size */ - .word _text16_memsz /* Code segment size */ - .ascii "PCIR" /* Bus type */ - .equ undiheader_len, . - undiheader - .size undiheader, . - undiheader - -/* Initialisation (called once during POST) - * - * Determine whether or not this is a PnP system via a signature - * check. If it is PnP, return to the PnP BIOS indicating that we are - * a boot-capable device; the BIOS will call our boot execution vector - * if it wants to boot us. If it is not PnP, hook INT 19. - */ -init: - /* Preserve registers, clear direction flag, set %ds=%cs */ - pushaw - pushw %ds - pushw %es - pushw %fs - pushw %gs - cld - pushw %cs - popw %ds - - /* Shuffle some registers around. We need %di available for - * the print_xxx functions, and in a register that's - * addressable from %es, so shuffle as follows: - * - * %di (pointer to PnP structure) => %bx - * %bx (runtime segment address, for PCI 3.0) => %gs - */ - movw %bx, %gs - movw %di, %bx - - /* Print message as early as possible */ - movw $init_message, %si - xorw %di, %di - call print_message - call print_pci_busdevfn - -#ifdef LOAD_ROM_FROM_PCI - /* Save PCI bus:dev.fn for later use */ - movw %ax, pci_busdevfn -#endif - - /* Fill in product name string, if possible */ - movw $prodstr_pci_id, %di - call print_pci_busdevfn - movb $( ' ' ), prodstr_separator - - /* Print segment address */ - movb $( ' ' ), %al - xorw %di, %di - call print_character - movw %cs, %ax - call print_hex_word - - /* Check for PCI BIOS version */ - pushl %ebx - pushl %edx - pushl %edi - stc - movw $0xb101, %ax - int $0x1a - jc no_pci3 - cmpl $PCI_SIGNATURE, %edx - jne no_pci3 - testb %ah, %ah - jnz no_pci3 -#ifdef LOAD_ROM_FROM_PCI - incb pcibios_present -#endif - movw $init_message_pci, %si - xorw %di, %di - call print_message - movb %bh, %al - call print_hex_nibble - movb $( '.' ), %al - call print_character - movb %bl, %al - call print_hex_byte - cmpb $3, %bh - jb no_pci3 - /* PCI >=3.0: leave %gs as-is if sane */ - movw %gs, %ax - cmpw $0xa000, %ax /* Insane if %gs < 0xa000 */ - jb pci3_insane - movw %cs, %bx /* Sane if %cs == %gs */ - cmpw %bx, %ax - je 1f - movzbw romheader_size, %cx /* Sane if %cs+len <= %gs */ - shlw $5, %cx - addw %cx, %bx - cmpw %bx, %ax - jae 1f - movw %cs, %bx /* Sane if %gs+len <= %cs */ - addw %cx, %ax - cmpw %bx, %ax - jbe 1f -pci3_insane: /* PCI 3.0 with insane %gs value: print error and ignore %gs */ - movb $( '!' ), %al - call print_character - movw %gs, %ax - call print_hex_word -no_pci3: - /* PCI <3.0: set %gs (runtime segment) = %cs (init-time segment) */ - pushw %cs - popw %gs -1: popl %edi - popl %edx - popl %ebx - - /* Check for PnP BIOS. Although %es:di should point to the - * PnP BIOS signature on entry, some BIOSes fail to do this. - */ - movw $( 0xf000 - 1 ), %bx -pnp_scan: - incw %bx - jz no_pnp - movw %bx, %es - cmpl $PNP_SIGNATURE, %es:0 - jne pnp_scan - xorw %dx, %dx - xorw %si, %si - movzbw %es:5, %cx -1: es lodsb - addb %al, %dl - loop 1b - jnz pnp_scan - /* Is PnP: print PnP message */ - movw $init_message_pnp, %si - xorw %di, %di - call print_message - /* Check for BBS */ - pushw %es:0x1b /* Real-mode data segment */ - pushw %ds /* &(bbs_version) */ - pushw $bbs_version - pushw $PNP_GET_BBS_VERSION - lcall *%es:0xd - addw $8, %sp - testw %ax, %ax - je got_bbs -no_pnp: /* Not PnP-compliant - therefore cannot be BBS-compliant */ -no_bbs: /* Not BBS-compliant - must hook INT 19 */ - movw $init_message_int19, %si - xorw %di, %di - call print_message - xorw %ax, %ax - movw %ax, %es - pushl %es:( 0x19 * 4 ) - popl orig_int19 - pushw %gs /* %gs contains runtime %cs */ - pushw $int19_entry - popl %es:( 0x19 * 4 ) - jmp bbs_done -got_bbs: /* BBS compliant - no need to hook INT 19 */ - movw $init_message_bbs, %si - xorw %di, %di - call print_message -bbs_done: - - /* Check for PMM */ - movw $( 0xe000 - 1 ), %bx -pmm_scan: - incw %bx - jz no_pmm - movw %bx, %es - cmpl $PMM_SIGNATURE, %es:0 - jne pmm_scan - xorw %dx, %dx - xorw %si, %si - movzbw %es:5, %cx -1: es lodsb - addb %al, %dl - loop 1b - jnz pmm_scan - /* PMM found: print PMM message */ - movw $init_message_pmm, %si - xorw %di, %di - call print_message - /* We have PMM and so a 1kB stack: preserve upper register halves */ - pushal - /* Calculate required allocation size in %esi */ - movzwl real_size, %eax - shll $9, %eax - addl $_textdata_memsz, %eax - orw $0xffff, %ax /* Ensure allocation size is at least 64kB */ - bsrl %eax, %ecx - subw $15, %cx /* Round up and convert to 64kB count */ - movw $1, %si - shlw %cl, %si -pmm_loop: - /* Try to allocate block via PMM */ - pushw $0x0006 /* Aligned, extended memory */ - pushl $0xffffffff /* No handle */ - movzwl %si, %eax - shll $12, %eax - pushl %eax /* Allocation size in paragraphs */ - pushw $PMM_ALLOCATE - lcall *%es:7 - addw $12, %sp - /* Abort if allocation fails */ - testw %dx, %dx /* %ax==0 even on success, since align>=64kB */ - jz pmm_fail - /* If block has A20==1, free block and try again with twice - * the allocation size (and hence alignment). - */ - testw $0x0010, %dx - jz got_pmm - pushw %dx - pushw $0 - pushw $PMM_DEALLOCATE - lcall *%es:7 - addw $6, %sp - addw %si, %si - jmp pmm_loop -got_pmm: /* PMM allocation succeeded */ - movw %dx, ( image_source + 2 ) - movw %dx, %ax - xorw %di, %di - call print_hex_word - movb $( '@' ), %al - call print_character - movw %si, %ax - call print_hex_byte -pmm_copy: - /* Copy ROM to PMM block */ - xorw %ax, %ax - movw %ax, %es - movl image_source, %edi - xorl %esi, %esi - movzbl romheader_size, %ecx - shll $9, %ecx - addr32 rep movsb /* PMM presence implies flat real mode */ - movl %edi, decompress_to - /* Shrink ROM */ - movb $_prefix_memsz_sect, romheader_size -#if defined(SHRINK_WITHOUT_PMM) || defined(LOAD_ROM_FROM_PCI) - jmp pmm_done -pmm_fail: - /* Print marker and copy ourselves to high memory */ - movl $HIGHMEM_LOADPOINT, image_source - xorw %di, %di - movb $( '!' ), %al - call print_character - jmp pmm_copy -pmm_done: -#else -pmm_fail: -#endif - /* Restore upper register halves */ - popal -#if defined(LOAD_ROM_FROM_PCI) - call load_from_pci - jc load_err - jmp load_ok -no_pmm: - /* Cannot continue without PMM - print error message */ - xorw %di, %di - movw $init_message_no_pmm, %si - call print_message -load_err: - /* Wait for five seconds to let user see message */ - movw $90, %cx -1: call wait_for_tick - loop 1b - /* Mark environment as invalid and return */ - movl $0, decompress_to - jmp out - -load_ok: -#else -no_pmm: -#endif - /* Update checksum */ - xorw %bx, %bx - xorw %si, %si - movzbw romheader_size, %cx - shlw $9, %cx -1: lodsb - addb %al, %bl - loop 1b - subb %bl, checksum - - /* Copy self to option ROM space. Required for PCI3.0, which - * loads us to a temporary location in low memory. Will be a - * no-op for lower PCI versions. - */ - movb $( ' ' ), %al - xorw %di, %di - call print_character - movw %gs, %ax - call print_hex_word - movzbw romheader_size, %cx - shlw $9, %cx - movw %ax, %es - xorw %si, %si - xorw %di, %di - cs rep movsb - - /* Prompt for POST-time shell */ - movw $init_message_prompt, %si - xorw %di, %di - call print_message - movw $prodstr, %si - call print_message - movw $init_message_dots, %si - call print_message - /* Wait for Ctrl-B */ - movw $0xff02, %bx - call wait_for_key - /* Clear prompt */ - pushf - xorw %di, %di - call print_kill_line - movw $init_message_done, %si - call print_message - popf - jnz out - /* Ctrl-B was pressed: invoke gPXE. The keypress will be - * picked up by the initial shell prompt, and we will drop - * into a shell. - */ - pushw %cs - call exec -out: - /* Restore registers */ - popw %gs - popw %fs - popw %es - popw %ds - popaw - - /* Indicate boot capability to PnP BIOS, if present */ - movw $0x20, %ax - lret - .size init, . - init - -/* - * Note to hardware vendors: - * - * If you wish to brand this boot ROM, please do so by defining the - * strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/general.h. - * - * While nothing in the GPL prevents you from removing all references - * to gPXE or http://etherboot.org, we prefer you not to do so. - * - * If you have an OEM-mandated branding requirement that cannot be - * satisfied simply by defining PRODUCT_NAME and PRODUCT_SHORT_NAME, - * please contact us. - * - * [ Including an ASCII NUL in PRODUCT_NAME is considered to be - * bypassing the spirit of this request! ] - */ -init_message: - .ascii "\n" - .ascii PRODUCT_NAME - .ascii "\n" - .asciz "gPXE (http://etherboot.org) - " - .size init_message, . - init_message -init_message_pci: - .asciz " PCI" - .size init_message_pci, . - init_message_pci -init_message_pnp: - .asciz " PnP" - .size init_message_pnp, . - init_message_pnp -init_message_bbs: - .asciz " BBS" - .size init_message_bbs, . - init_message_bbs -init_message_pmm: - .asciz " PMM" - .size init_message_pmm, . - init_message_pmm -#ifdef LOAD_ROM_FROM_PCI -init_message_no_pmm: - .asciz "\nPMM required but not present!\n" - .size init_message_no_pmm, . - init_message_no_pmm -#endif -init_message_int19: - .asciz " INT19" - .size init_message_int19, . - init_message_int19 -init_message_prompt: - .asciz "\nPress Ctrl-B to configure " - .size init_message_prompt, . - init_message_prompt -init_message_dots: - .asciz "..." - .size init_message_dots, . - init_message_dots -init_message_done: - .asciz "\n\n" - .size init_message_done, . - init_message_done - -/* ROM image location - * - * May be either within option ROM space, or within PMM-allocated block. - */ - .globl image_source -image_source: - .long 0 - .size image_source, . - image_source - -/* Temporary decompression area - * - * May be either at HIGHMEM_LOADPOINT, or within PMM-allocated block. - * If a PCI ROM load fails, this will be set to zero. - */ - .globl decompress_to -decompress_to: - .long HIGHMEM_LOADPOINT - .size decompress_to, . - decompress_to - -#ifdef LOAD_ROM_FROM_PCI - -/* Set if the PCI BIOS is present, even <3.0 */ -pcibios_present: - .byte 0 - .byte 0 /* for alignment */ - .size pcibios_present, . - pcibios_present - -/* PCI bus:device.function word - * - * Filled in by init in the .xrom case, so the remainder of the ROM - * can be located. - */ -pci_busdevfn: - .word 0 - .size pci_busdevfn, . - pci_busdevfn - -#endif - -/* BBS version - * - * Filled in by BBS BIOS. We ignore the value. - */ -bbs_version: - .word 0 - .size bbs_version, . - bbs_version - -/* Boot Execution Vector entry point - * - * Called by the PnP BIOS when it wants to boot us. - */ -bev_entry: - pushw %cs - call exec - lret - .size bev_entry, . - bev_entry - - -#ifdef LOAD_ROM_FROM_PCI - -#define PCI_ROM_ADDRESS 0x30 /* Bits 31:11 address, 10:1 reserved */ -#define PCI_ROM_ADDRESS_ENABLE 0x00000001 -#define PCI_ROM_ADDRESS_MASK 0xfffff800 - -#define PCIBIOS_READ_WORD 0xb109 -#define PCIBIOS_READ_DWORD 0xb10a -#define PCIBIOS_WRITE_WORD 0xb10c -#define PCIBIOS_WRITE_DWORD 0xb10d - -/* Determine size of PCI BAR - * - * %bx : PCI bus:dev.fn to probe - * %di : Address of BAR to find size of - * %edx : Mask of address bits within BAR - * - * %ecx : Size for a memory resource, - * 1 for an I/O resource (bit 0 set). - * CF : Set on error or nonexistent device (all-ones read) - * - * All other registers saved. - */ -pci_bar_size: - /* Save registers */ - pushw %ax - pushl %esi - pushl %edx - - /* Read current BAR value */ - movw $PCIBIOS_READ_DWORD, %ax - int $0x1a - - /* Check for device existence and save it */ - testb $1, %cl /* I/O bit? */ - jz 1f - andl $1, %ecx /* If so, exit with %ecx = 1 */ - jmp 99f -1: notl %ecx - testl %ecx, %ecx /* Set ZF iff %ecx was all-ones */ - notl %ecx - jnz 1f - stc /* All ones - exit with CF set */ - jmp 99f -1: movl %ecx, %esi /* Save in %esi */ - - /* Write all ones to BAR */ - movl %edx, %ecx - movw $PCIBIOS_WRITE_DWORD, %ax - int $0x1a - - /* Read back BAR */ - movw $PCIBIOS_READ_DWORD, %ax - int $0x1a - - /* Find decode size from least set bit in mask BAR */ - bsfl %ecx, %ecx /* Find least set bit, log2(decode size) */ - jz 1f /* Mask BAR should not be zero */ - xorl %edx, %edx - incl %edx - shll %cl, %edx /* %edx = decode size */ - jmp 2f -1: xorl %edx, %edx /* Return zero size for mask BAR zero */ - - /* Restore old BAR value */ -2: movl %esi, %ecx - movw $PCIBIOS_WRITE_DWORD, %ax - int $0x1a - - movl %edx, %ecx /* Return size in %ecx */ - - /* Restore registers and return */ -99: popl %edx - popl %esi - popw %ax - ret - - .size pci_bar_size, . - pci_bar_size - -/* PCI ROM loader - * - * Called from init in the .xrom case to load the non-prefix code - * using the PCI ROM BAR. - * - * Returns with carry flag set on error. All registers saved. - */ -load_from_pci: - /* - * Use PCI BIOS access to config space. The calls take - * - * %ah : 0xb1 %al : function - * %bx : bus/dev/fn - * %di : config space address - * %ecx : value to write (for writes) - * - * %ecx : value read (for reads) - * %ah : return code - * CF : error indication - * - * All registers not used for return are preserved. - */ - - /* Save registers and set up %es for big real mode */ - pushal - pushw %es - xorw %ax, %ax - movw %ax, %es - - /* Check PCI BIOS presence */ - cmpb $0, pcibios_present - jz err_pcibios - - /* Load existing PCI ROM BAR */ - movw $PCIBIOS_READ_DWORD, %ax - movw pci_busdevfn, %bx - movw $PCI_ROM_ADDRESS, %di - int $0x1a - - /* Maybe it's already enabled? */ - testb $PCI_ROM_ADDRESS_ENABLE, %cl - jz 1f - movb $1, %dl /* Flag indicating no deinit required */ - movl %ecx, %ebp - jmp check_rom - - /* Determine PCI BAR decode size */ -1: movl $PCI_ROM_ADDRESS_MASK, %edx - call pci_bar_size /* Returns decode size in %ecx */ - jc err_size_insane /* CF => no ROM BAR, %ecx == ffffffff */ - - /* Check sanity of decode size */ - xorl %eax, %eax - movw real_size, %ax - shll $9, %eax /* %eax = ROM size */ - cmpl %ecx, %eax - ja err_size_insane /* Insane if decode size < ROM size */ - cmpl $0x100000, %ecx - jae err_size_insane /* Insane if decode size >= 1MB */ - - /* Find a place to map the BAR - * In theory we should examine e820 and all PCI BARs to find a - * free region. However, we run at POST when e820 may not be - * available, and memory reads of an unmapped location are - * de facto standardized to return all-ones. Thus, we can get - * away with searching high memory (0xf0000000 and up) on - * multiples of the ROM BAR decode size for a sufficiently - * large all-ones region. - */ - movl %ecx, %edx /* Save ROM BAR size in %edx */ - movl $0xf0000000, %ebp - xorl %eax, %eax - notl %eax /* %eax = all ones */ -bar_search: - movl %ebp, %edi - movl %edx, %ecx - shrl $2, %ecx - addr32 repe scasl /* Scan %es:edi for anything not all-ones */ - jz bar_found - addl %edx, %ebp - testl $0x80000000, %ebp - jz err_no_bar - jmp bar_search - -bar_found: - movl %edi, %ebp - /* Save current BAR value on stack to restore later */ - movw $PCIBIOS_READ_DWORD, %ax - movw $PCI_ROM_ADDRESS, %di - int $0x1a - pushl %ecx - - /* Map the ROM */ - movw $PCIBIOS_WRITE_DWORD, %ax - movl %ebp, %ecx - orb $PCI_ROM_ADDRESS_ENABLE, %cl - int $0x1a - - xorb %dl, %dl /* %dl = 0 : ROM was not already mapped */ -check_rom: - /* Check and copy ROM - enter with %dl set to skip unmapping, - * %ebp set to mapped ROM BAR address. - * We check up to prodstr_separator for equality, since anything past - * that may have been modified. Since our check includes the checksum - * byte over the whole ROM stub, that should be sufficient. - */ - xorb %dh, %dh /* %dh = 0 : ROM did not fail integrity check */ - - /* Verify ROM integrity */ - xorl %esi, %esi - movl %ebp, %edi - movl $prodstr_separator, %ecx - addr32 repe cmpsb - jz copy_rom - incb %dh /* ROM failed integrity check */ - movl %ecx, %ebp /* Save number of bytes left */ - jmp skip_load - -copy_rom: - /* Print BAR address and indicate whether we mapped it ourselves */ - movb $( ' ' ), %al - xorw %di, %di - call print_character - movl %ebp, %eax - call print_hex_dword - movb $( '-' ), %al /* '-' for self-mapped */ - subb %dl, %al - subb %dl, %al /* '+' = '-' - 2 for BIOS-mapped */ - call print_character - - /* Copy ROM at %ebp to PMM or highmem block */ - movl %ebp, %esi - movl image_source, %edi - movzwl real_size, %ecx - shll $9, %ecx - addr32 es rep movsb - movl %edi, decompress_to -skip_load: - testb %dl, %dl /* Was ROM already mapped? */ - jnz skip_unmap - - /* Unmap the ROM by restoring old ROM BAR */ - movw $PCIBIOS_WRITE_DWORD, %ax - movw $PCI_ROM_ADDRESS, %di - popl %ecx - int $0x1a - -skip_unmap: - /* Error handling */ - testb %dh, %dh - jnz err_rom_invalid - clc - jmp 99f - -err_pcibios: /* No PCI BIOS available */ - movw $load_message_no_pcibios, %si - xorl %eax, %eax /* "error code" is zero */ - jmp 1f -err_size_insane: /* BAR has size (%ecx) that is insane */ - movw $load_message_size_insane, %si - movl %ecx, %eax - jmp 1f -err_no_bar: /* No space of sufficient size (%edx) found */ - movw $load_message_no_bar, %si - movl %edx, %eax - jmp 1f -err_rom_invalid: /* Loaded ROM does not match (%ebp bytes left) */ - movw $load_message_rom_invalid, %si - movzbl romheader_size, %eax - shll $9, %eax - subl %ebp, %eax - decl %eax /* %eax is now byte index of failure */ - -1: /* Error handler - print message at %si and dword in %eax */ - xorw %di, %di - call print_message - call print_hex_dword - stc -99: popw %es - popal - ret - - .size load_from_pci, . - load_from_pci - -load_message_no_pcibios: - .asciz "\nNo PCI BIOS found! " - .size load_message_no_pcibios, . - load_message_no_pcibios - -load_message_size_insane: - .asciz "\nROM resource has invalid size " - .size load_message_size_insane, . - load_message_size_insane - -load_message_no_bar: - .asciz "\nNo memory hole of sufficient size " - .size load_message_no_bar, . - load_message_no_bar - -load_message_rom_invalid: - .asciz "\nLoaded ROM is invalid at " - .size load_message_rom_invalid, . - load_message_rom_invalid - -#endif /* LOAD_ROM_FROM_PCI */ - - -/* INT19 entry point - * - * Called via the hooked INT 19 if we detected a non-PnP BIOS. We - * attempt to return via the original INT 19 vector (if we were able - * to store it). - */ -int19_entry: - pushw %cs - popw %ds - /* Prompt user to press B to boot */ - movw $int19_message_prompt, %si - xorw %di, %di - call print_message - movw $prodstr, %si - call print_message - movw $int19_message_dots, %si - call print_message - movw $0xdf4e, %bx - call wait_for_key - pushf - xorw %di, %di - call print_kill_line - movw $int19_message_done, %si - call print_message - popf - jz 1f - /* Leave keypress in buffer and start gPXE. The keypress will - * cause the usual initial Ctrl-B prompt to be skipped. - */ - pushw %cs - call exec -1: /* Try to call original INT 19 vector */ - movl %cs:orig_int19, %eax - testl %eax, %eax - je 2f - ljmp *%cs:orig_int19 -2: /* No chained vector: issue INT 18 as a last resort */ - int $0x18 - .size int19_entry, . - int19_entry -orig_int19: - .long 0 - .size orig_int19, . - orig_int19 - -int19_message_prompt: - .asciz "Press N to skip booting from " - .size int19_message_prompt, . - int19_message_prompt -int19_message_dots: - .asciz "..." - .size int19_message_dots, . - int19_message_dots -int19_message_done: - .asciz "\n\n" - .size int19_message_done, . - int19_message_done - -/* Execute as a boot device - * - */ -exec: /* Set %ds = %cs */ - pushw %cs - popw %ds - -#ifdef LOAD_ROM_FROM_PCI - /* Don't execute if load was invalid */ - cmpl $0, decompress_to - jne 1f - lret -1: -#endif - - /* Print message as soon as possible */ - movw $prodstr, %si - xorw %di, %di - call print_message - movw $exec_message, %si - call print_message - - /* Store magic word on BIOS stack and remember BIOS %ss:sp */ - pushl $STACK_MAGIC - movw %ss, %dx - movw %sp, %bp - - /* Obtain a reasonably-sized temporary stack */ - xorw %ax, %ax - movw %ax, %ss - movw $0x7c00, %sp - - /* Install gPXE */ - movl image_source, %esi - movl decompress_to, %edi - call alloc_basemem - call install_prealloc - - /* Set up real-mode stack */ - movw %bx, %ss - movw $_estack16, %sp - - /* Jump to .text16 segment */ - pushw %ax - pushw $1f - lret - .section ".text16", "awx", @progbits -1: /* Call main() */ - pushl $main - pushw %cs - call prot_call - popl %ecx /* discard */ - - /* Uninstall gPXE */ - call uninstall - - /* Restore BIOS stack */ - movw %dx, %ss - movw %bp, %sp - - /* Check magic word on BIOS stack */ - popl %eax - cmpl $STACK_MAGIC, %eax - jne 1f - /* BIOS stack OK: return to caller */ - lret -1: /* BIOS stack corrupt: use INT 18 */ - int $0x18 - .previous - -exec_message: - .asciz " starting execution\n" - .size exec_message, . - exec_message - -/* Wait for key press specified by %bl (masked by %bh) - * - * Used by init and INT19 code when prompting user. If the specified - * key is pressed, it is left in the keyboard buffer. - * - * Returns with ZF set iff specified key is pressed. - */ -wait_for_key: - /* Preserve registers */ - pushw %cx - pushw %ax -1: /* Empty the keyboard buffer before waiting for input */ - movb $0x01, %ah - int $0x16 - jz 2f - xorw %ax, %ax - int $0x16 - jmp 1b -2: /* Wait for a key press */ - movw $ROM_BANNER_TIMEOUT, %cx -3: decw %cx - js 99f /* Exit with ZF clear */ - /* Wait for timer tick to be updated */ - call wait_for_tick - /* Check to see if a key was pressed */ - movb $0x01, %ah - int $0x16 - jz 3b - /* Check to see if key was the specified key */ - andb %bh, %al - cmpb %al, %bl - je 99f /* Exit with ZF set */ - /* Not the specified key: remove from buffer and stop waiting */ - pushfw - xorw %ax, %ax - int $0x16 - popfw /* Exit with ZF clear */ -99: /* Restore registers and return */ - popw %ax - popw %cx - ret - .size wait_for_key, . - wait_for_key - -/* Wait for timer tick - * - * Used by wait_for_key - */ -wait_for_tick: - pushl %eax - pushw %fs - movw $0x40, %ax - movw %ax, %fs - movl %fs:(0x6c), %eax -1: pushf - sti - hlt - popf - cmpl %fs:(0x6c), %eax - je 1b - popw %fs - popl %eax - ret - .size wait_for_tick, . - wait_for_tick diff --git a/gpxe/src/arch/i386/prefix/undiloader.S b/gpxe/src/arch/i386/prefix/undiloader.S deleted file mode 100644 index 36c1bef3..00000000 --- a/gpxe/src/arch/i386/prefix/undiloader.S +++ /dev/null @@ -1,49 +0,0 @@ - .text - .code16 - .arch i386 - .section ".prefix", "ax", @progbits - -/* UNDI loader - * - * Called by an external program to load our PXE stack. - */ - .globl undiloader -undiloader: - /* Save registers */ - pushl %esi - pushl %edi - pushw %ds - pushw %es - pushw %bx - /* ROM segment address to %ds */ - pushw %cs - popw %ds - /* UNDI loader parameter structure address into %es:%di */ - movw %sp, %bx - movw %ss:18(%bx), %di - movw %ss:20(%bx), %es - /* Install to specified real-mode addresses */ - pushw %di - movw %es:12(%di), %bx - movw %es:14(%di), %ax - movl image_source, %esi - movl decompress_to, %edi - call install_prealloc - popw %di - /* Call UNDI loader C code */ - pushl $pxe_loader_call - pushw %cs - pushw $1f - pushw %ax - pushw $prot_call - lret -1: popw %bx /* discard */ - popw %bx /* discard */ - /* Restore registers and return */ - popw %bx - popw %es - popw %ds - popl %edi - popl %esi - lret - .size undiloader, . - undiloader diff --git a/gpxe/src/arch/i386/prefix/unnrv2b.S b/gpxe/src/arch/i386/prefix/unnrv2b.S deleted file mode 100644 index f5724c13..00000000 --- a/gpxe/src/arch/i386/prefix/unnrv2b.S +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer - * - * This file 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. - * - * Originally this code was part of ucl the data compression library - * for upx the ``Ultimate Packer of eXecutables''. - * - * - Converted to gas assembly, and refitted to work with etherboot. - * Eric Biederman 20 Aug 2002 - * - * - Structure modified to be a subroutine call rather than an - * executable prefix. - * Michael Brown 30 Mar 2004 - * - * - Modified to be compilable as either 16-bit or 32-bit code. - * Michael Brown 9 Mar 2005 - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -/**************************************************************************** - * This file provides the decompress() and decompress16() functions - * which can be called in order to decompress an image compressed with - * the nrv2b utility in src/util. - * - * These functions are designed to be called by the prefix. They are - * position-independent code. - * - * The same basic assembly code is used to compile both - * decompress() and decompress16(). - **************************************************************************** - */ - - .text - .arch i386 - .section ".prefix.lib", "ax", @progbits - -#ifdef CODE16 -/**************************************************************************** - * decompress16 (real-mode near call, position independent) - * - * Decompress data in 16-bit mode - * - * Parameters (passed via registers): - * %ds:%esi - Start of compressed input data - * %es:%edi - Start of output buffer - * Returns: - * %ds:%esi - End of compressed input data - * %es:%edi - End of decompressed output data - * All other registers are preserved - * - * NOTE: It would be possible to build a smaller version of the - * decompression code for -DKEEP_IT_REAL by using - * #define REG(x) x - * to use 16-bit registers where possible. This would impose limits - * that the compressed data size must be in the range [1,65533-%si] - * and the uncompressed data size must be in the range [1,65536-%di] - * (where %si and %di are the input values for those registers). Note - * particularly that the lower limit is 1, not 0, and that the upper - * limit on the input (compressed) data really is 65533, since the - * algorithm may read up to three bytes beyond the end of the input - * data, since it reads dwords. - **************************************************************************** - */ - -#define REG(x) e ## x -#define ADDR32 addr32 - - .code16 - .globl decompress16 -decompress16: - -#else /* CODE16 */ - -/**************************************************************************** - * decompress (32-bit protected-mode near call, position independent) - * - * Parameters (passed via registers): - * %ds:%esi - Start of compressed input data - * %es:%edi - Start of output buffer - * Returns: - * %ds:%esi - End of compressed input data - * %es:%edi - End of decompressed output data - * All other registers are preserved - **************************************************************************** - */ - -#define REG(x) e ## x -#define ADDR32 - - .code32 - .globl decompress -decompress: - -#endif /* CODE16 */ - -#define xAX REG(ax) -#define xCX REG(cx) -#define xBP REG(bp) -#define xSI REG(si) -#define xDI REG(di) - - /* Save registers */ - push %xAX - pushl %ebx - push %xCX - push %xBP - /* Do the decompression */ - cld - xor %xBP, %xBP - dec %xBP /* last_m_off = -1 */ - jmp dcl1_n2b - -decompr_literals_n2b: - ADDR32 movsb -decompr_loop_n2b: - addl %ebx, %ebx - jnz dcl2_n2b -dcl1_n2b: - call getbit32 -dcl2_n2b: - jc decompr_literals_n2b - xor %xAX, %xAX - inc %xAX /* m_off = 1 */ -loop1_n2b: - call getbit1 - adc %xAX, %xAX /* m_off = m_off*2 + getbit() */ - call getbit1 - jnc loop1_n2b /* while(!getbit()) */ - sub $3, %xAX - jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */ - shl $8, %xAX - ADDR32 movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */ - inc %xSI - xor $-1, %xAX - jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */ - mov %xAX, %xBP /* last_m_off = m_off ?*/ -decompr_ebpeax_n2b: - xor %xCX, %xCX - call getbit1 - adc %xCX, %xCX /* m_len = getbit() */ - call getbit1 - adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */ - jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */ - inc %xCX /* m_len++ */ -loop2_n2b: - call getbit1 - adc %xCX, %xCX /* m_len = m_len*2 + getbit() */ - call getbit1 - jnc loop2_n2b /* while(!getbit()) */ - inc %xCX - inc %xCX /* m_len += 2 */ -decompr_got_mlen_n2b: - cmp $-0xd00, %xBP - adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */ - push %xSI - ADDR32 lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */ - rep - es ADDR32 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */ - pop %xSI - jmp decompr_loop_n2b - - -getbit1: - addl %ebx, %ebx - jnz 1f -getbit32: - ADDR32 movl (%xSI), %ebx - sub $-4, %xSI /* sets carry flag */ - adcl %ebx, %ebx -1: - ret - -decompr_end_n2b: - /* Restore registers and return */ - pop %xBP - pop %xCX - popl %ebx - pop %xAX - ret diff --git a/gpxe/src/arch/i386/prefix/unnrv2b16.S b/gpxe/src/arch/i386/prefix/unnrv2b16.S deleted file mode 100644 index b24c2846..00000000 --- a/gpxe/src/arch/i386/prefix/unnrv2b16.S +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 16-bit version of the decompressor - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -#define CODE16 -#include "unnrv2b.S" diff --git a/gpxe/src/arch/i386/prefix/usbdisk.S b/gpxe/src/arch/i386/prefix/usbdisk.S deleted file mode 100644 index fa7d1956..00000000 --- a/gpxe/src/arch/i386/prefix/usbdisk.S +++ /dev/null @@ -1,23 +0,0 @@ - .text - .arch i386 - .section ".prefix", "awx", @progbits - .code16 - .org 0 - -#include "mbr.S" - -/* Partition table: ZIP-compatible partition 4, 64 heads, 32 sectors/track */ - .org 446 - .space 16 - .space 16 - .space 16 - .byte 0x80, 0x01, 0x01, 0x00 - .byte 0xeb, 0x3f, 0x20, 0x01 - .long 0x00000020 - .long 0x00000fe0 - - .org 510 - .byte 0x55, 0xaa - -/* Skip to start of partition */ - .org 32 * 512 diff --git a/gpxe/src/arch/i386/prefix/xromprefix.S b/gpxe/src/arch/i386/prefix/xromprefix.S deleted file mode 100644 index d7c861f5..00000000 --- a/gpxe/src/arch/i386/prefix/xromprefix.S +++ /dev/null @@ -1,9 +0,0 @@ -/* - * ROM prefix that loads the bulk of the ROM using direct PCI accesses, - * so as not to take up much option ROM space on PCI <3.0 systems. - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -#define LOAD_ROM_FROM_PCI -#include "romprefix.S" diff --git a/gpxe/src/arch/i386/scripts/i386-kir.lds b/gpxe/src/arch/i386/scripts/i386-kir.lds deleted file mode 100644 index c19480f0..00000000 --- a/gpxe/src/arch/i386/scripts/i386-kir.lds +++ /dev/null @@ -1,197 +0,0 @@ -/* -*- sh -*- */ - -/* - * Linker script for i386 images - * - */ - -OUTPUT_FORMAT ( "elf32-i386", "elf32-i386", "elf32-i386" ) -OUTPUT_ARCH ( i386 ) -ENTRY ( _entry ) - -SECTIONS { - - /* All sections in the resulting file have consecutive load - * addresses, but may have individual link addresses depending on - * the memory model being used. - * - * The linker symbols _prefix_link_addr, load_addr, and - * _max_align may be specified explicitly. If not specified, they - * will default to: - * - * _prefix_link_addr = 0 - * _load_addr = 0 - * _max_align = 16 - * - * We guarantee alignment of virtual addresses to any alignment - * specified by the constituent object files (e.g. via - * __attribute__((aligned(x)))). Load addresses are guaranteed - * only up to _max_align. Provided that all loader and relocation - * code honours _max_align, this means that physical addresses are - * also guaranteed up to _max_align. - * - * Note that when using -DKEEP_IT_REAL, the UNDI segments are only - * guaranteed to be loaded on a paragraph boundary (i.e. 16-byte - * alignment). Using _max_align>16 will therefore not guarantee - * >16-byte alignment of physical addresses when -DKEEP_IT_REAL is - * used (though virtual addresses will still be fully aligned). - * - */ - - /* - * The prefix - */ - - _prefix_link_addr = DEFINED ( _prefix_link_addr ) ? _prefix_link_addr : 0; - . = _prefix_link_addr; - _prefix = .; - - .prefix : AT ( _prefix_load_offset + __prefix ) { - __prefix = .; - _entry = .; - *(.prefix) - *(.prefix.*) - _eprefix_progbits = .; - } - - _eprefix = .; - - /* - * The 16-bit sections - */ - - _text16_link_addr = 0; - . = _text16_link_addr; - _text16 = .; - - . += 1; /* Prevent NULL being valid */ - - .text16 : AT ( _text16_load_offset + __text16 ) { - __text16 = .; - *(.text.null_trap) - *(.text16) - *(.text16.*) - *(.text) - *(.text.*) - _etext16_progbits = .; - } = 0x9090 - - _etext16 = .; - - _data16_link_addr = 0; - . = _data16_link_addr; - _data16 = .; - - . += 1; /* Prevent NULL being valid */ - - .rodata16 : AT ( _data16_load_offset + __rodata16 ) { - __rodata16 = .; - *(.rodata16) - *(.rodata16.*) - *(.rodata) - *(.rodata.*) - } - .data16 : AT ( _data16_load_offset + __data16 ) { - __data16 = .; - *(.data16) - *(.data16.*) - *(.data) - *(.data.*) - *(SORT(.tbl.*)) /* Various tables. See include/tables.h */ - _edata16_progbits = .; - } - .bss16 : AT ( _data16_load_offset + __bss16 ) { - __bss16 = .; - _bss16 = .; - *(.bss16) - *(.bss16.*) - *(.bss) - *(.bss.*) - *(COMMON) - _ebss16 = .; - } - .stack16 : AT ( _data16_load_offset + __stack16 ) { - __stack16 = .; - *(.stack16) - *(.stack16.*) - *(.stack) - *(.stack.*) - } - - _edata16 = .; - - _end = .; - - /* - * Dispose of the comment and note sections to make the link map - * easier to read - */ - - /DISCARD/ : { - *(.comment) - *(.note) - *(.discard) - } - - /* - * Load address calculations. The slightly obscure nature of the - * calculations is because ALIGN(x) can only operate on the - * location counter. - */ - - _max_align = DEFINED ( _max_align ) ? _max_align : 16; - _load_addr = DEFINED ( _load_addr ) ? _load_addr : 0; - - . = _load_addr; - - . -= _prefix_link_addr; - _prefix_load_offset = ALIGN ( _max_align ); - _prefix_load_addr = _prefix_link_addr + _prefix_load_offset; - _prefix_size = _eprefix - _prefix; - _prefix_progbits_size = _eprefix_progbits - _prefix; - . = _prefix_load_addr + _prefix_progbits_size; - - . -= _text16_link_addr; - _text16_load_offset = ALIGN ( _max_align ); - _text16_load_addr = _text16_link_addr + _text16_load_offset; - _text16_size = _etext16 - _text16; - _text16_progbits_size = _etext16_progbits - _text16; - . = _text16_load_addr + _text16_progbits_size; - - . -= _data16_link_addr; - _data16_load_offset = ALIGN ( _max_align ); - _data16_load_addr = _data16_link_addr + _data16_load_offset; - _data16_size = _edata16 - _data16; - _data16_progbits_size = _edata16_progbits - _data16; - . = _data16_load_addr + _data16_progbits_size; - - . = ALIGN ( _max_align ); - - _load_size = . - _load_addr; - - /* - * Alignment checks. ALIGN() can only operate on the location - * counter, so we set the location counter to each value we want - * to check. - */ - - . = _prefix_load_addr - _prefix_link_addr; - _assert = ASSERT ( ( . == ALIGN ( _max_align ) ), - "_prefix is badly aligned" ); - - . = _text16_load_addr - _text16_link_addr; - _assert = ASSERT ( ( . == ALIGN ( _max_align ) ), - "_text16 is badly aligned" ); - - . = _data16_load_addr - _data16_link_addr; - _assert = ASSERT ( ( . == ALIGN ( _max_align ) ), - "_data16 is badly aligned" ); - - /* - * Values calculated to save code from doing it - */ - _text16_size_pgh = ( ( _text16_size + 15 ) / 16 ); - _data16_size_pgh = ( ( _data16_size + 15 ) / 16 ); - _load_size_pgh = ( ( _load_size + 15 ) / 16 ); - _load_size_sect = ( ( _load_size + 511 ) / 512 ); -} diff --git a/gpxe/src/arch/i386/scripts/i386.lds b/gpxe/src/arch/i386/scripts/i386.lds deleted file mode 100644 index 33c75f90..00000000 --- a/gpxe/src/arch/i386/scripts/i386.lds +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- sh -*- */ - -/* - * Linker script for i386 images - * - */ - -SECTIONS { - - /* Each section starts at a virtual address of zero. - * - * We guarantee alignment of virtual addresses to any alignment - * specified by the constituent object files (e.g. via - * __attribute__((aligned(x)))). Load addresses are guaranteed - * only up to _max_align. Provided that all loader and relocation - * code honours _max_align, this means that physical addresses are - * also guaranteed up to _max_align. - * - * Note that when using -DKEEP_IT_REAL, the UNDI segments are only - * guaranteed to be loaded on a paragraph boundary (i.e. 16-byte - * alignment). Using _max_align>16 will therefore not guarantee - * >16-byte alignment of physical addresses when -DKEEP_IT_REAL is - * used (though virtual addresses will still be fully aligned). - * - */ - - /* - * The prefix - * - */ - - .prefix 0x0 : AT ( _prefix_lma ) { - _prefix = .; - *(.prefix) - *(.prefix.*) - _mprefix = .; - } .bss.prefix (NOLOAD) : AT ( _end_lma ) { - _eprefix = .; - } - _prefix_filesz = ABSOLUTE ( _mprefix - _prefix ); - _prefix_memsz = ABSOLUTE ( _eprefix - _prefix ); - - /* - * The 16-bit (real-mode) code section - * - */ - - .text16 0x0 : AT ( _text16_lma ) { - _text16 = .; - *(.text16.null) - . += 1; /* Prevent NULL being valid */ - *(.text16) - *(.text16.*) - _mtext16 = .; - } .bss.text16 (NOLOAD) : AT ( _end_lma ) { - _etext16 = .; - } - _text16_filesz = ABSOLUTE ( _mtext16 - _text16 ); - _text16_memsz = ABSOLUTE ( _etext16 - _text16 ); - - /* - * The 16-bit (real-mode) data section - * - */ - - .data16 0x0 : AT ( _data16_lma ) { - _data16 = .; - . += 1; /* Prevent NULL being valid */ - *(.rodata16) - *(.rodata16.*) - *(.data16) - *(.data16.*) - _mdata16 = .; - } .bss.data16 (NOLOAD) : AT ( _end_lma ) { - *(.bss16) - *(.bss16.*) - *(.stack16) - *(.stack16.*) - _edata16 = .; - } - _data16_filesz = ABSOLUTE ( _mdata16 - _data16 ); - _data16_memsz = ABSOLUTE ( _edata16 - _data16 ); - - /* - * The 32-bit sections - * - */ - - .textdata 0x0 : AT ( _textdata_lma ) { - _textdata = .; - *(.text.null_trap) - . += 1; /* Prevent NULL being valid */ - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.data) - *(.data.*) - *(SORT(.tbl.*)) /* Various tables. See include/tables.h */ - _mtextdata = .; - } .bss.textdata (NOLOAD) : AT ( _end_lma ) { - *(.bss) - *(.bss.*) - *(COMMON) - *(.stack) - *(.stack.*) - _etextdata = .; - } - _textdata_filesz = ABSOLUTE ( _mtextdata - _textdata ); - _textdata_memsz = ABSOLUTE ( _etextdata - _textdata ); - - /* - * Compressor information block - * - */ - - .zinfo 0x0 : AT ( _zinfo_lma ) { - _zinfo = .; - *(.zinfo) - *(.zinfo.*) - _mzinfo = .; - } .bss.zinfo (NOLOAD) : AT ( _end_lma ) { - _ezinfo = .; - } - _zinfo_filesz = ABSOLUTE ( _mzinfo - _zinfo ); - _zinfo_memsz = ABSOLUTE ( _ezinfo - _zinfo ); - - /* - * Weak symbols that need zero values if not otherwise defined - * - */ - - .weak 0x0 : AT ( _end_lma ) { - _weak = .; - *(.weak) - _eweak = .; - } - _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" ); - - /* - * Dispose of the comment and note sections to make the link map - * easier to read - * - */ - - /DISCARD/ : { - *(.comment) - *(.comment.*) - *(.note) - *(.note.*) - *(.eh_frame) - *(.eh_frame.*) - *(.rel) - *(.rel.*) - *(.discard) - } - - /* - * Load address calculations. In older versions of ld, ALIGN() - * can operate only on the location counter, so we use that. - * - */ - - PROVIDE ( _max_align = 16 ); - . = 0; - - . = ALIGN ( _max_align ); - _prefix_lma = .; - . += _prefix_filesz; - - . = ALIGN ( _max_align ); - _payload_lma = .; - _text16_lma = .; - . += _text16_filesz; - - . = ALIGN ( _max_align ); - _data16_lma = .; - . += _data16_filesz; - - . = ALIGN ( _max_align ); - _textdata_lma = .; - . += _textdata_filesz; - - _filesz = .; /* Do not include zinfo block in file size */ - - . = ALIGN ( _max_align ); - _zinfo_lma = .; - . += _zinfo_filesz; - - . = ALIGN ( _max_align ); - _end_lma = .; - - /* - * Values calculated to save code from doing it - * - */ - _prefix_filesz_sect = ( ( _prefix_filesz + 511 ) / 512 ); - _prefix_memsz_pgh = ( ( _prefix_memsz + 15 ) / 16 ); - _prefix_memsz_sect = ( ( _prefix_memsz + 511 ) / 512 ); - _text16_memsz_pgh = ( ( _text16_memsz + 15 ) / 16 ); - _data16_memsz_pgh = ( ( _data16_memsz + 15 ) / 16 ); -} diff --git a/gpxe/src/arch/i386/transitions/libkir.S b/gpxe/src/arch/i386/transitions/libkir.S deleted file mode 100644 index 1176fcce..00000000 --- a/gpxe/src/arch/i386/transitions/libkir.S +++ /dev/null @@ -1,256 +0,0 @@ -/* - * libkir: a transition library for -DKEEP_IT_REAL - * - * Michael Brown <mbrown@fensystems.co.uk> - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -/**************************************************************************** - * This file defines libkir: an interface between external and - * internal environments when -DKEEP_IT_REAL is used, so that both - * internal and external environments are in real mode. It deals with - * switching data segments and the stack. It provides the following - * functions: - * - * ext_to_kir & switch between external and internal (kir) - * kir_to_ext environments, preserving all non-segment - * registers - * - * kir_call issue a call to an internal routine from external - * code - * - * libkir is written to avoid assuming that segments are anything - * other than opaque data types, and also avoids assuming that the - * stack pointer is 16-bit. This should enable it to run just as well - * in 16:16 or 16:32 protected mode as in real mode. - **************************************************************************** - */ - -/* Breakpoint for when debugging under bochs */ -#define BOCHSBP xchgw %bx, %bx - - .text - .arch i386 - .section ".text16", "awx", @progbits - .code16 - -/**************************************************************************** - * init_libkir (real-mode or 16:xx protected-mode far call) - * - * Initialise libkir ready for transitions to the kir environment - * - * Parameters: - * %cs : .text16 segment - * %ds : .data16 segment - **************************************************************************** - */ - .globl init_libkir -init_libkir: - /* Record segment registers */ - pushw %ds - popw %cs:kir_ds - lret - -/**************************************************************************** - * ext_to_kir (real-mode or 16:xx protected-mode near call) - * - * Switch from external stack and segment registers to internal stack - * and segment registers. %ss:sp is restored from the saved kir_ds - * and kir_sp. %ds, %es, %fs and %gs are all restored from the saved - * kir_ds. All other registers are preserved. - * - * %cs:0000 must point to the start of the runtime image code segment - * on entry. - * - * Parameters: none - **************************************************************************** - */ - - .globl ext_to_kir -ext_to_kir: - /* Record external segment registers */ - movw %ds, %cs:ext_ds - pushw %cs - popw %ds /* Set %ds = %cs for easier access to variables */ - movw %es, %ds:ext_es - movw %fs, %ds:ext_fs - movw %gs, %ds:ext_fs - - /* Preserve registers */ - movw %ax, %ds:save_ax - - /* Extract near return address from stack */ - popw %ds:save_retaddr - - /* Record external %ss:esp */ - movw %ss, %ds:ext_ss - movl %esp, %ds:ext_esp - - /* Load internal segment registers and stack pointer */ - movw %ds:kir_ds, %ax - movw %ax, %ss - movzwl %ds:kir_sp, %esp - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs -1: - - /* Place return address on new stack */ - pushw %cs:save_retaddr - - /* Restore registers and return */ - movw %cs:save_ax, %ax - ret - -/**************************************************************************** - * kir_to_ext (real-mode or 16:xx protected-mode near call) - * - * Switch from internal stack and segment registers to external stack - * and segment registers. %ss:%esp is restored from the saved ext_ss - * and ext_esp. Other segment registers are restored from the - * corresponding locations. All other registers are preserved. - * - * Note that it is actually %ss that is recorded as kir_ds, on the - * assumption that %ss == %ds when kir_to_ext is called. - * - * Parameters: none - **************************************************************************** - */ - - .globl kir_to_ext -kir_to_ext: - /* Record near return address */ - pushw %cs - popw %ds /* Set %ds = %cs for easier access to variables */ - popw %ds:save_retaddr - - /* Record internal segment registers and %sp */ - movw %ss, %ds:kir_ds - movw %sp, %ds:kir_sp - - /* Load external segment registers and stack pointer */ - movw %ds:ext_ss, %ss - movl %ds:ext_esp, %esp - movw %ds:ext_gs, %gs - movw %ds:ext_fs, %fs - movw %ds:ext_es, %es - movw %ds:ext_ds, %ds - - /* Return */ - pushw %cs:save_retaddr - ret - -/**************************************************************************** - * kir_call (real-mode or 16:xx protected-mode far call) - * - * Call a specific C function in the internal code. The prototype of - * the C function must be - * void function ( struct i386_all_resg *ix86 ); - * ix86 will point to a struct containing the real-mode registers - * at entry to kir_call. - * - * All registers will be preserved across kir_call(), unless the C - * function explicitly overwrites values in ix86. Interrupt status - * will also be preserved. - * - * Parameters: - * function : (32-bit) virtual address of C function to call - * - * Example usage: - * pushl $pxe_api_call - * lcall $UNDI_CS, $kir_call - * addw $4, %sp - * to call in to the C function - * void pxe_api_call ( struct i386_all_regs *ix86 ); - **************************************************************************** - */ - - .globl kir_call -kir_call: - /* Preserve flags. Must do this before any operation that may - * affect flags. - */ - pushfl - popl %cs:save_flags - - /* Disable interrupts. We do funny things with the stack, and - * we're not re-entrant. - */ - cli - - /* Extract address of internal routine from stack. We must do - * this without using (%bp), because we may be called with - * either a 16-bit or a 32-bit stack segment. - */ - popl %cs:save_retaddr /* Scratch location */ - popl %cs:save_function - subl $8, %esp /* Restore %esp */ - - /* Switch to internal stack. Note that the external stack is - * inaccessible once we're running internally (since we have - * no concept of 48-bit far pointers) - */ - call ext_to_kir - - /* Store external registers on internal stack */ - pushl %cs:save_flags - pushal - pushl %cs:ext_fs_and_gs - pushl %cs:ext_ds_and_es - pushl %cs:ext_cs_and_ss - - /* Push &ix86 on stack and call function */ - sti - pushl %esp - data32 call *%cs:save_function - popl %eax /* discard */ - - /* Restore external registers from internal stack */ - popl %cs:ext_cs_and_ss - popl %cs:ext_ds_and_es - popl %cs:ext_fs_and_gs - popal - popl %cs:save_flags - - /* Switch to external stack */ - call kir_to_ext - - /* Restore flags */ - pushl %cs:save_flags - popfl - - /* Return */ - lret - -/**************************************************************************** - * Stored internal and external stack and segment registers - **************************************************************************** - */ - -ext_cs_and_ss: -ext_cs: .word 0 -ext_ss: .word 0 -ext_ds_and_es: -ext_ds: .word 0 -ext_es: .word 0 -ext_fs_and_gs: -ext_fs: .word 0 -ext_gs: .word 0 -ext_esp: .long 0 - - .globl kir_ds -kir_ds: .word 0 - .globl kir_sp -kir_sp: .word _estack - -/**************************************************************************** - * Temporary variables - **************************************************************************** - */ -save_ax: .word 0 -save_retaddr: .long 0 -save_flags: .long 0 -save_function: .long 0 diff --git a/gpxe/src/arch/i386/transitions/libpm.S b/gpxe/src/arch/i386/transitions/libpm.S deleted file mode 100644 index e69de29b..00000000 --- a/gpxe/src/arch/i386/transitions/libpm.S +++ /dev/null diff --git a/gpxe/src/arch/i386/transitions/librm.S b/gpxe/src/arch/i386/transitions/librm.S deleted file mode 100644 index cb27ef35..00000000 --- a/gpxe/src/arch/i386/transitions/librm.S +++ /dev/null @@ -1,581 +0,0 @@ -/* - * librm: a library for interfacing to real-mode code - * - * Michael Brown <mbrown@fensystems.co.uk> - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ) - -/* Drag in local definitions */ -#include "librm.h" - -/* For switches to/from protected mode */ -#define CR0_PE 1 - -/* Size of various C data structures */ -#define SIZEOF_I386_SEG_REGS 12 -#define SIZEOF_I386_REGS 32 -#define SIZEOF_REAL_MODE_REGS ( SIZEOF_I386_SEG_REGS + SIZEOF_I386_REGS ) -#define SIZEOF_I386_FLAGS 4 -#define SIZEOF_I386_ALL_REGS ( SIZEOF_REAL_MODE_REGS + SIZEOF_I386_FLAGS ) - - .arch i386 - -/**************************************************************************** - * Global descriptor table - * - * Call init_librm to set up the GDT before attempting to use any - * protected-mode code. - * - * Define FLATTEN_REAL_MODE if you want to use so-called "flat real - * mode" with 4GB limits instead. - * - * NOTE: This must be located before prot_to_real, otherwise gas - * throws a "can't handle non absolute segment in `ljmp'" error due to - * not knowing the value of REAL_CS when the ljmp is encountered. - * - * Note also that putting ".word gdt_end - gdt - 1" directly into - * gdt_limit, rather than going via gdt_length, will also produce the - * "non absolute segment" error. This is most probably a bug in gas. - **************************************************************************** - */ - -#ifdef FLATTEN_REAL_MODE -#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x8f -#else -#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00 -#endif - .section ".data16", "aw", @progbits - .align 16 -gdt: -gdtr: /* The first GDT entry is unused, the GDTR can fit here. */ -gdt_limit: .word gdt_length - 1 -gdt_base: .long 0 - .word 0 /* padding */ - - .org gdt + VIRTUAL_CS, 0 -virtual_cs: /* 32 bit protected mode code segment, virtual addresses */ - .word 0xffff, 0 - .byte 0, 0x9f, 0xcf, 0 - - .org gdt + VIRTUAL_DS, 0 -virtual_ds: /* 32 bit protected mode data segment, virtual addresses */ - .word 0xffff, 0 - .byte 0, 0x93, 0xcf, 0 - - .org gdt + PHYSICAL_CS, 0 -physical_cs: /* 32 bit protected mode code segment, physical addresses */ - .word 0xffff, 0 - .byte 0, 0x9f, 0xcf, 0 - - .org gdt + PHYSICAL_DS, 0 -physical_ds: /* 32 bit protected mode data segment, physical addresses */ - .word 0xffff, 0 - .byte 0, 0x93, 0xcf, 0 - - .org gdt + REAL_CS, 0 -real_cs: /* 16 bit real mode code segment */ - .word 0xffff, 0 - .byte 0, 0x9b, RM_LIMIT_16_19__AVL__SIZE__GRANULARITY, 0 - - .org gdt + REAL_DS -real_ds: /* 16 bit real mode data segment */ - .word 0xffff, 0 - .byte 0, 0x93, RM_LIMIT_16_19__AVL__SIZE__GRANULARITY, 0 - -gdt_end: - .equ gdt_length, gdt_end - gdt - -/**************************************************************************** - * init_librm (real-mode far call, 16-bit real-mode far return address) - * - * Initialise the GDT ready for transitions to protected mode. - * - * Parameters: - * %cs : .text16 segment - * %ds : .data16 segment - * %edi : Physical base of protected-mode code (virt_offset) - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 - .globl init_librm -init_librm: - /* Preserve registers */ - pushl %eax - pushl %ebx - - /* Store _virt_offset and set up virtual_cs and virtual_ds segments */ - movl %edi, %eax - movw $virtual_cs, %bx - call set_seg_base - movw $virtual_ds, %bx - call set_seg_base - movl %edi, _virt_offset - - /* Negate virt_offset */ - negl %edi - - /* Store rm_cs and _text16, set up real_cs segment */ - xorl %eax, %eax - movw %cs, %ax - movw %ax, rm_cs - shll $4, %eax - movw $real_cs, %bx - call set_seg_base - addr32 leal (%eax, %edi), %ebx - movl %ebx, _text16 - - /* Store rm_ds and _data16, set up real_ds segment */ - xorl %eax, %eax - movw %ds, %ax - movw %ax, %cs:rm_ds - shll $4, %eax - movw $real_ds, %bx - call set_seg_base - addr32 leal (%eax, %edi), %ebx - movl %ebx, _data16 - - /* Set GDT and IDT base */ - movl %eax, gdt_base - addl $gdt, gdt_base - call idt_init - - /* Restore registers */ - negl %edi - popl %ebx - popl %eax - lret - - .section ".text16", "ax", @progbits - .code16 - .weak idt_init -set_seg_base: -1: movw %ax, 2(%bx) - rorl $16, %eax - movb %al, 4(%bx) - movb %ah, 7(%bx) - roll $16, %eax -idt_init: /* Reuse the return opcode here */ - ret - -/**************************************************************************** - * real_to_prot (real-mode near call, 32-bit virtual return address) - * - * Switch from 16-bit real-mode to 32-bit protected mode with virtual - * addresses. The real-mode %ss:sp is stored in rm_ss and rm_sp, and - * the protected-mode %esp is restored from the saved pm_esp. - * Interrupts are disabled. All other registers may be destroyed. - * - * The return address for this function should be a 32-bit virtual - * address. - * - * Parameters: - * %ecx : number of bytes to move from RM stack to PM stack - * - **************************************************************************** - */ - .section ".text16", "ax", @progbits - .code16 -real_to_prot: - /* Make sure we have our data segment available */ - movw %cs:rm_ds, %ax - movw %ax, %ds - - /* Add _virt_offset, _text16 and _data16 to stack to be - * copied, and also copy the return address. - */ - pushl _virt_offset - pushl _text16 - pushl _data16 - addw $16, %cx /* %ecx must be less than 64kB anyway */ - - /* Real-mode %ss:%sp => %ebp:%edx and virtual address => %esi */ - xorl %ebp, %ebp - movw %ss, %bp - movzwl %sp, %edx - movl %ebp, %eax - shll $4, %eax - addr32 leal (%eax,%edx), %esi - subl _virt_offset, %esi - - /* Switch to protected mode */ - cli - data32 lgdt gdtr - data32 lidt idtr - movl %cr0, %eax - orb $CR0_PE, %al - movl %eax, %cr0 - data32 ljmp $VIRTUAL_CS, $1f - .section ".text", "ax", @progbits - .code32 -1: - /* Set up protected-mode data segments and stack pointer */ - movw $VIRTUAL_DS, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - movl pm_esp, %esp - - /* Record real-mode %ss:sp (after removal of data) */ - movw %bp, rm_ss - addl %ecx, %edx - movw %dx, rm_sp - - /* Move data from RM stack to PM stack */ - subl %ecx, %esp - movl %esp, %edi - rep movsb - - /* Publish virt_offset, text16 and data16 for PM code to use */ - popl data16 - popl text16 - popl virt_offset - - /* Return to virtual address */ - ret - - /* Default IDTR with no interrupts */ - .section ".data16", "aw", @progbits - .weak idtr -idtr: -rm_idtr: - .word 0xffff /* limit */ - .long 0 /* base */ - -/**************************************************************************** - * prot_to_real (protected-mode near call, 32-bit real-mode return address) - * - * Switch from 32-bit protected mode with virtual addresses to 16-bit - * real mode. The protected-mode %esp is stored in pm_esp and the - * real-mode %ss:sp is restored from the saved rm_ss and rm_sp. The - * high word of the real-mode %esp is set to zero. All real-mode data - * segment registers are loaded from the saved rm_ds. Interrupts are - * *not* enabled, since we want to be able to use prot_to_real in an - * ISR. All other registers may be destroyed. - * - * The return address for this function should be a 32-bit (sic) - * real-mode offset within .code16. - * - * Parameters: - * %ecx : number of bytes to move from PM stack to RM stack - * - **************************************************************************** - */ - .section ".text", "ax", @progbits - .code32 -prot_to_real: - /* Add return address to data to be moved to RM stack */ - addl $4, %ecx - - /* Real-mode %ss:sp => %ebp:edx and virtual address => %edi */ - movzwl rm_ss, %ebp - movzwl rm_sp, %edx - subl %ecx, %edx - movl %ebp, %eax - shll $4, %eax - leal (%eax,%edx), %edi - subl virt_offset, %edi - - /* Move data from PM stack to RM stack */ - movl %esp, %esi - rep movsb - - /* Record protected-mode %esp (after removal of data) */ - movl %esi, pm_esp - - /* Load real-mode segment limits */ - movw $REAL_DS, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - ljmp $REAL_CS, $1f - .section ".text16", "ax", @progbits - .code16 -1: - /* Switch to real mode */ - movl %cr0, %eax - andb $0!CR0_PE, %al - movl %eax, %cr0 - ljmp *p2r_jump_vector -p2r_jump_target: - - /* Set up real-mode data segments and stack pointer */ - movw %cs:rm_ds, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %bp, %ss - movl %edx, %esp - - /* Reset IDTR to the real-mode defaults */ - data32 lidt rm_idtr - - /* Return to real-mode address */ - data32 ret - - - /* Real-mode code and data segments. Assigned by the call to - * init_librm. rm_cs doubles as the segment part of the jump - * vector used by prot_to_real. rm_ds is located in .text16 - * rather than .data16 because code needs to be able to locate - * the data segment. - */ - .section ".data16", "aw", @progbits -p2r_jump_vector: - .word p2r_jump_target - .globl rm_cs -rm_cs: .word 0 - .globl rm_ds - .section ".text16.data", "aw", @progbits -rm_ds: .word 0 - -/**************************************************************************** - * prot_call (real-mode far call, 16-bit real-mode far return address) - * - * Call a specific C function in the protected-mode code. The - * prototype of the C function must be - * void function ( struct i386_all_regs *ix86 ); - * ix86 will point to a struct containing the real-mode registers - * at entry to prot_call. - * - * All registers will be preserved across prot_call(), unless the C - * function explicitly overwrites values in ix86. Interrupt status - * and GDT will also be preserved. Gate A20 will be enabled. - * - * Note that prot_call() does not rely on the real-mode stack - * remaining intact in order to return, since everything relevant is - * copied to the protected-mode stack for the duration of the call. - * In particular, this means that a real-mode prefix can make a call - * to main() which will return correctly even if the prefix's stack - * gets vapourised during the Etherboot run. (The prefix cannot rely - * on anything else on the stack being preserved, so should move any - * critical data to registers before calling main()). - * - * Parameters: - * function : virtual address of protected-mode function to call - * - * Example usage: - * pushl $pxe_api_call - * call prot_call - * addw $4, %sp - * to call in to the C function - * void pxe_api_call ( struct i386_all_regs *ix86 ); - **************************************************************************** - */ - -#define PC_OFFSET_GDT ( 0 ) -#define PC_OFFSET_IDT ( PC_OFFSET_GDT + 8 /* pad to 8 to keep alignment */ ) -#define PC_OFFSET_IX86 ( PC_OFFSET_IDT + 8 /* pad to 8 to keep alignment */ ) -#define PC_OFFSET_RETADDR ( PC_OFFSET_IX86 + SIZEOF_I386_ALL_REGS ) -#define PC_OFFSET_FUNCTION ( PC_OFFSET_RETADDR + 4 ) -#define PC_OFFSET_END ( PC_OFFSET_FUNCTION + 4 ) - - .section ".text16", "ax", @progbits - .code16 - .globl prot_call -prot_call: - /* Preserve registers, flags and GDT on external RM stack */ - pushfl - pushal - pushw %gs - pushw %fs - pushw %es - pushw %ds - pushw %ss - pushw %cs - subw $16, %sp - movw %sp, %bp - sidt 8(%bp) - sgdt (%bp) - - /* For sanity's sake, clear the direction flag as soon as possible */ - cld - - /* Switch to protected mode and move register dump to PM stack */ - movl $PC_OFFSET_END, %ecx - pushl $1f - jmp real_to_prot - .section ".text", "ax", @progbits - .code32 -1: - /* Set up environment expected by C code */ - call gateA20_set - - /* Call function */ - leal PC_OFFSET_IX86(%esp), %eax - pushl %eax - call *(PC_OFFSET_FUNCTION+4)(%esp) - popl %eax /* discard */ - - /* Switch to real mode and move register dump back to RM stack */ - movl $PC_OFFSET_END, %ecx - pushl $1f - jmp prot_to_real - .section ".text16", "ax", @progbits - .code16 -1: - /* Reload GDT and IDT, restore registers and flags and return */ - movw %sp, %bp - data32 lgdt (%bp) - data32 lidt 8(%bp) - addw $20, %sp /* also skip %cs and %ss */ - popw %ds - popw %es - popw %fs - popw %gs - popal - /* popal skips %esp. We therefore want to do "movl -20(%sp), - * %esp", but -20(%sp) is not a valid 80386 expression. - * Fortunately, prot_to_real() zeroes the high word of %esp, so - * we can just use -20(%esp) instead. - */ - addr32 movl -20(%esp), %esp - popfl - lret - -/**************************************************************************** - * real_call (protected-mode near call, 32-bit virtual return address) - * - * Call a real-mode function from protected-mode code. - * - * The non-segment register values will be passed directly to the - * real-mode code. The segment registers will be set as per - * prot_to_real. The non-segment register values set by the real-mode - * function will be passed back to the protected-mode caller. A - * result of this is that this routine cannot be called directly from - * C code, since it clobbers registers that the C ABI expects the - * callee to preserve. Gate A20 will *not* be automatically - * re-enabled. Since we always run from an even megabyte of memory, - * we are guaranteed to return successfully to the protected-mode - * code, which should then call gateA20_set() if it suspects that gate - * A20 may have been disabled. Note that enabling gate A20 is a - * potentially slow operation that may also cause keyboard input to be - * lost; this is why it is not done automatically. - * - * librm.h defines a convenient macro REAL_CODE() for using real_call. - * See librm.h and realmode.h for details and examples. - * - * Parameters: - * (32-bit) near pointer to real-mode function to call - * - * Returns: none - **************************************************************************** - */ - -#define RC_OFFSET_PRESERVE_REGS ( 0 ) -#define RC_OFFSET_RETADDR ( RC_OFFSET_PRESERVE_REGS + SIZEOF_I386_REGS ) -#define RC_OFFSET_FUNCTION ( RC_OFFSET_RETADDR + 4 ) -#define RC_OFFSET_END ( RC_OFFSET_FUNCTION + 4 ) - - .section ".text", "ax", @progbits - .code32 - .globl real_call -real_call: - /* Create register dump and function pointer copy on PM stack */ - pushal - pushl RC_OFFSET_FUNCTION(%esp) - - /* Switch to real mode and move register dump to RM stack */ - movl $( RC_OFFSET_RETADDR + 4 /* function pointer copy */ ), %ecx - pushl $1f - jmp prot_to_real - .section ".text16", "ax", @progbits - .code16 -1: - /* Call real-mode function */ - popl rc_function - popal - call *rc_function - pushal - - /* For sanity's sake, clear the direction flag as soon as possible */ - cld - - /* Switch to protected mode and move register dump back to PM stack */ - movl $RC_OFFSET_RETADDR, %ecx - pushl $1f - jmp real_to_prot - .section ".text", "ax", @progbits - .code32 -1: - /* Restore registers and return */ - popal - ret - - - /* Function vector, used because "call xx(%sp)" is not a valid - * 16-bit expression. - */ - .section ".data16", "aw", @progbits -rc_function: .word 0, 0 - -/**************************************************************************** - * Stored real-mode and protected-mode stack pointers - * - * The real-mode stack pointer is stored here whenever real_to_prot - * is called and restored whenever prot_to_real is called. The - * converse happens for the protected-mode stack pointer. - * - * Despite initial appearances this scheme is, in fact re-entrant, - * because program flow dictates that we always return via the point - * we left by. For example: - * PXE API call entry - * 1 real => prot - * ... - * Print a text string - * ... - * 2 prot => real - * INT 10 - * 3 real => prot - * ... - * ... - * 4 prot => real - * PXE API call exit - * - * At point 1, the RM mode stack value, say RPXE, is stored in - * rm_ss,sp. We want this value to still be present in rm_ss,sp when - * we reach point 4. - * - * At point 2, the RM stack value is restored from RPXE. At point 3, - * the RM stack value is again stored in rm_ss,sp. This *does* - * overwrite the RPXE that we have stored there, but it's the same - * value, since the code between points 2 and 3 has managed to return - * to us. - **************************************************************************** - */ - .section ".data", "aw", @progbits - .globl rm_sp -rm_sp: .word 0 - .globl rm_ss -rm_ss: .word 0 -pm_esp: .long _estack - -/**************************************************************************** - * Virtual address offsets - * - * These are used by the protected-mode code to map between virtual - * and physical addresses, and to access variables in the .text16 or - * .data16 segments. - **************************************************************************** - */ - /* Internal copies, created by init_librm (which runs in real mode) */ - .section ".data16", "aw", @progbits -_virt_offset: .long 0 -_text16: .long 0 -_data16: .long 0 - - /* Externally-visible copies, created by real_to_prot */ - .section ".data", "aw", @progbits - .globl virt_offset -virt_offset: .long 0 - .globl text16 -text16: .long 0 - .globl data16 -data16: .long 0 diff --git a/gpxe/src/arch/i386/transitions/librm_mgmt.c b/gpxe/src/arch/i386/transitions/librm_mgmt.c deleted file mode 100644 index f00be811..00000000 --- a/gpxe/src/arch/i386/transitions/librm_mgmt.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * librm: a library for interfacing to real-mode code - * - * Michael Brown <mbrown@fensystems.co.uk> - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <realmode.h> - -/* - * This file provides functions for managing librm. - * - */ - -/** - * Allocate space on the real-mode stack and copy data there from a - * user buffer - * - * @v data User buffer - * @v size Size of stack data - * @ret sp New value of real-mode stack pointer - */ -uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) { - userptr_t rm_stack; - rm_sp -= size; - rm_stack = real_to_user ( rm_ss, rm_sp ); - memcpy_user ( rm_stack, 0, data, 0, size ); - return rm_sp; -}; - -/** - * Deallocate space on the real-mode stack, optionally copying back - * data to a user buffer. - * - * @v data User buffer - * @v size Size of stack data - */ -void remove_user_from_rm_stack ( userptr_t data, size_t size ) { - if ( data ) { - userptr_t rm_stack = real_to_user ( rm_ss, rm_sp ); - memcpy_user ( rm_stack, 0, data, 0, size ); - } - rm_sp += size; -}; - -PROVIDE_UACCESS_INLINE ( librm, phys_to_user ); -PROVIDE_UACCESS_INLINE ( librm, user_to_phys ); -PROVIDE_UACCESS_INLINE ( librm, virt_to_user ); -PROVIDE_UACCESS_INLINE ( librm, user_to_virt ); -PROVIDE_UACCESS_INLINE ( librm, userptr_add ); -PROVIDE_UACCESS_INLINE ( librm, memcpy_user ); -PROVIDE_UACCESS_INLINE ( librm, memmove_user ); -PROVIDE_UACCESS_INLINE ( librm, memset_user ); -PROVIDE_UACCESS_INLINE ( librm, strlen_user ); -PROVIDE_UACCESS_INLINE ( librm, memchr_user ); diff --git a/gpxe/src/arch/x86/Makefile b/gpxe/src/arch/x86/Makefile deleted file mode 100644 index f5f67ac7..00000000 --- a/gpxe/src/arch/x86/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Include common x86 headers -# -INCDIRS += arch/x86/include - -# x86-specific directories containing source files -# -SRCDIRS += arch/x86/core -SRCDIRS += arch/x86/interface/efi -SRCDIRS += arch/x86/prefix diff --git a/gpxe/src/arch/x86/Makefile.efi b/gpxe/src/arch/x86/Makefile.efi deleted file mode 100644 index bef8d59d..00000000 --- a/gpxe/src/arch/x86/Makefile.efi +++ /dev/null @@ -1,28 +0,0 @@ -# -*- makefile -*- : Force emacs to use Makefile mode - -# The EFI linker script -# -LDSCRIPT = arch/x86/scripts/efi.lds - -# Retain relocation information for elf2efi -# -LDFLAGS += -q -S - -# Media types. -# -NON_AUTO_MEDIA += efi -NON_AUTO_MEDIA += efidrv - -# Rules for building EFI files -# -$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI) - $(QM)$(ECHO) " [FINISH] $@" - $(Q)$(ELF2EFI) --subsystem=10 $< $@ - -$(BIN)/%.efidrv : $(BIN)/%.efidrv.tmp $(ELF2EFI) - $(QM)$(ECHO) " [FINISH] $@" - $(Q)$(ELF2EFI) --subsystem=11 $< $@ - -$(BIN)/%.efirom : $(BIN)/%.efidrv $(EFIROM) - $(QM)$(ECHO) " [FINISH] $@" - $(Q)$(EFIROM) -v $(TGT_PCI_VENDOR) -d $(TGT_PCI_DEVICE) $< $@ diff --git a/gpxe/src/arch/x86/core/pcidirect.c b/gpxe/src/arch/x86/core/pcidirect.c deleted file mode 100644 index 2c61d9ca..00000000 --- a/gpxe/src/arch/x86/core/pcidirect.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/io.h> -#include <gpxe/pci.h> - -/** @file - * - * PCI configuration space access via Type 1 accesses - * - */ - -/** - * Prepare for Type 1 PCI configuration space access - * - * @v pci PCI device - * @v where Location within PCI configuration space - */ -void pcidirect_prepare ( struct pci_device *pci, int where ) { - outl ( ( 0x80000000 | ( pci->bus << 16 ) | ( pci->devfn << 8 ) | - ( where & ~3 ) ), PCIDIRECT_CONFIG_ADDRESS ); -} - -PROVIDE_PCIAPI_INLINE ( direct, pci_max_bus ); -PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte ); -PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word ); -PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_dword ); -PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte ); -PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word ); -PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword ); diff --git a/gpxe/src/arch/x86/core/x86_string.c b/gpxe/src/arch/x86/core/x86_string.c deleted file mode 100644 index 5838ebac..00000000 --- a/gpxe/src/arch/x86/core/x86_string.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** @file - * - * Optimised string operations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <string.h> - -/** - * Copy memory area - * - * @v dest Destination address - * @v src Source address - * @v len Length - * @ret dest Destination address - */ -void * __memcpy ( void *dest, const void *src, size_t len ) { - void *edi = dest; - const void *esi = src; - int discard_ecx; - - /* We often do large dword-aligned and dword-length block - * 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" ); - } - return dest; -} diff --git a/gpxe/src/arch/x86/include/bits/pci_io.h b/gpxe/src/arch/x86/include/bits/pci_io.h deleted file mode 100644 index f6efcdac..00000000 --- a/gpxe/src/arch/x86/include/bits/pci_io.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _BITS_PCI_IO_H -#define _BITS_PCI_IO_H - -/** @file - * - * i386-specific PCI I/O API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/pcibios.h> -#include <gpxe/pcidirect.h> - -#endif /* _BITS_PCI_IO_H */ diff --git a/gpxe/src/arch/x86/include/bits/string.h b/gpxe/src/arch/x86/include/bits/string.h deleted file mode 100644 index a68868ac..00000000 --- a/gpxe/src/arch/x86/include/bits/string.h +++ /dev/null @@ -1,252 +0,0 @@ -#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). - */ - -/* - * 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 :-) - * - * NO Copyright (C) 1991, 1992 Linus Torvalds, - * consider these trivial functions to be PD. - */ - -FILE_LICENCE ( PUBLIC_DOMAIN ); - -#define __HAVE_ARCH_MEMCPY - -extern void * __memcpy ( 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 - -static inline __attribute__ (( always_inline )) void * -__constant_memcpy ( void *dest, const void *src, size_t len ) { - union { - uint32_t u32[2]; - uint16_t u16[4]; - uint8_t u8[8]; - } __attribute__ (( __may_alias__ )) *dest_u = dest; - const union { - uint32_t u32[2]; - uint16_t u16[4]; - uint8_t u8[8]; - } __attribute__ (( __may_alias__ )) *src_u = src; - const void *esi; - void *edi; - - switch ( len ) { - case 0 : /* 0 bytes */ - return dest; - /* - * Single-register moves; these are always better than a - * string operation. We can clobber an arbitrary two - * registers (data, source, dest can re-use source register) - * instead of being restricted to esi and edi. There's also a - * much greater potential for optimising with nearby code. - * - */ - case 1 : /* 4 bytes */ - dest_u->u8[0] = src_u->u8[0]; - return dest; - case 2 : /* 6 bytes */ - dest_u->u16[0] = src_u->u16[0]; - return dest; - case 4 : /* 4 bytes */ - dest_u->u32[0] = src_u->u32[0]; - return dest; - /* - * Double-register moves; these are probably still a win. - * - */ - case 3 : /* 12 bytes */ - dest_u->u16[0] = src_u->u16[0]; - dest_u->u8[2] = src_u->u8[2]; - return dest; - case 5 : /* 10 bytes */ - dest_u->u32[0] = src_u->u32[0]; - dest_u->u8[4] = src_u->u8[4]; - return dest; - case 6 : /* 12 bytes */ - dest_u->u32[0] = src_u->u32[0]; - dest_u->u16[2] = src_u->u16[2]; - return dest; - case 8 : /* 10 bytes */ - dest_u->u32[0] = src_u->u32[0]; - dest_u->u32[1] = src_u->u32[1]; - return dest; - } - - /* Even if we have to load up esi and edi ready for a string - * operation, we can sometimes save space by using multiple - * single-byte "movs" operations instead of loading up ecx and - * using "rep movsb". - * - * "load ecx, rep movsb" is 7 bytes, plus an average of 1 byte - * to allow for saving/restoring ecx 50% of the time. - * - * "movsl" and "movsb" are 1 byte each, "movsw" is two bytes. - * (In 16-bit mode, "movsl" is 2 bytes and "movsw" is 1 byte, - * but "movsl" moves twice as much data, so it balances out). - * - * The cutoff point therefore occurs around 26 bytes; the byte - * requirements for each method are: - * - * len 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - * #bytes (ecx) 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 - * #bytes (no ecx) 4 5 6 7 5 6 7 8 6 7 8 9 7 8 9 10 - */ - - esi = src; - edi = dest; - - if ( len >= 26 ) - return __memcpy ( dest, src, len ); - - if ( len >= 6*4 ) - __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - if ( len >= 5*4 ) - __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - if ( len >= 4*4 ) - __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - if ( len >= 3*4 ) - __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - if ( len >= 2*4 ) - __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - if ( len >= 1*4 ) - __asm__ __volatile__ ( "movsl" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - if ( ( len % 4 ) >= 2 ) - __asm__ __volatile__ ( "movsw" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - if ( ( len % 2 ) >= 1 ) - __asm__ __volatile__ ( "movsb" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - - return dest; -} - -#define memcpy( dest, src, len ) \ - ( __builtin_constant_p ( (len) ) ? \ - __constant_memcpy ( (dest), (src), (len) ) : \ - __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; -} - -#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; -} - -#define __HAVE_ARCH_MEMSWAP -static inline void * memswap(void *dest, void *src, size_t n) -{ -int d0, d1, d2, d3; -__asm__ __volatile__( - "\n1:\t" - "movb (%%edi),%%al\n\t" - "xchgb (%%esi),%%al\n\t" - "incl %%esi\n\t" - "stosb\n\t" - "loop 1b" - : "=&c" (d0), "=&S" (d1), "=&D" (d2), "=&a" (d3) - : "0" (n), "1" (src), "2" (dest) - : "memory" ); -return dest; -} - -#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; -} - -#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 */ diff --git a/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h b/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h deleted file mode 100644 index 833c922c..00000000 --- a/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _GPXE_EFIX86_NAP_H -#define _GPXE_EFIX86_NAP_H - -/** @file - * - * EFI CPU sleeping - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef NAP_EFIX86 -#define NAP_PREFIX_efix86 -#else -#define NAP_PREFIX_efix86 __efix86_ -#endif - -#endif /* _GPXE_EFIX86_NAP_H */ diff --git a/gpxe/src/arch/x86/include/gpxe/pcibios.h b/gpxe/src/arch/x86/include/gpxe/pcibios.h deleted file mode 100644 index 93a6eb8a..00000000 --- a/gpxe/src/arch/x86/include/gpxe/pcibios.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef _GPXE_PCIBIOS_H -#define _GPXE_PCIBIOS_H - -#include <stdint.h> - -/** @file - * - * PCI configuration space access via PCI BIOS - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef PCIAPI_PCBIOS -#define PCIAPI_PREFIX_pcbios -#else -#define PCIAPI_PREFIX_pcbios __pcbios_ -#endif - -struct pci_device; - -#define PCIBIOS_INSTALLATION_CHECK 0xb1010000 -#define PCIBIOS_READ_CONFIG_BYTE 0xb1080000 -#define PCIBIOS_READ_CONFIG_WORD 0xb1090000 -#define PCIBIOS_READ_CONFIG_DWORD 0xb10a0000 -#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b0000 -#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c0000 -#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d0000 - -extern int pcibios_read ( struct pci_device *pci, uint32_t command, - uint32_t *value ); -extern int pcibios_write ( struct pci_device *pci, uint32_t command, - uint32_t value ); - -/** - * Read byte from PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( pcbios, pci_read_config_byte ) ( struct pci_device *pci, - unsigned int where, - uint8_t *value ) { - uint32_t tmp; - int rc; - - rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_BYTE | where, &tmp ); - *value = tmp; - return rc; -} - -/** - * Read word from PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( pcbios, pci_read_config_word ) ( struct pci_device *pci, - unsigned int where, - uint16_t *value ) { - uint32_t tmp; - int rc; - - rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_WORD | where, &tmp ); - *value = tmp; - return rc; -} - -/** - * Read dword from PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( pcbios, pci_read_config_dword ) ( struct pci_device *pci, - unsigned int where, - uint32_t *value ) { - return pcibios_read ( pci, PCIBIOS_READ_CONFIG_DWORD | where, value ); -} - -/** - * Write byte to PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( pcbios, pci_write_config_byte ) ( struct pci_device *pci, - unsigned int where, - uint8_t value ) { - return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value ); -} - -/** - * Write word to PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( pcbios, pci_write_config_word ) ( struct pci_device *pci, - unsigned int where, - uint16_t value ) { - return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_WORD | where, value ); -} - -/** - * Write dword to PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( pcbios, pci_write_config_dword ) ( struct pci_device *pci, - unsigned int where, - uint32_t value ) { - return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_DWORD | where, value); -} - -#endif /* _GPXE_PCIBIOS_H */ diff --git a/gpxe/src/arch/x86/include/gpxe/pcidirect.h b/gpxe/src/arch/x86/include/gpxe/pcidirect.h deleted file mode 100644 index 8b705fb2..00000000 --- a/gpxe/src/arch/x86/include/gpxe/pcidirect.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef _PCIDIRECT_H -#define _PCIDIRECT_H - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <gpxe/io.h> - -#ifdef PCIAPI_DIRECT -#define PCIAPI_PREFIX_direct -#else -#define PCIAPI_PREFIX_direct __direct_ -#endif - -/** @file - * - * PCI configuration space access via Type 1 accesses - * - */ - -#define PCIDIRECT_CONFIG_ADDRESS 0xcf8 -#define PCIDIRECT_CONFIG_DATA 0xcfc - -struct pci_device; - -extern void pcidirect_prepare ( struct pci_device *pci, int where ); - -/** - * Determine maximum PCI bus number within system - * - * @ret max_bus Maximum bus number - */ -static inline __always_inline int -PCIAPI_INLINE ( direct, pci_max_bus ) ( void ) { - /* No way to work this out via Type 1 accesses */ - return 0xff; -} - -/** - * Read byte from PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( direct, pci_read_config_byte ) ( struct pci_device *pci, - unsigned int where, - uint8_t *value ) { - pcidirect_prepare ( pci, where ); - *value = inb ( PCIDIRECT_CONFIG_DATA + ( where & 3 ) ); - return 0; -} - -/** - * Read word from PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( direct, pci_read_config_word ) ( struct pci_device *pci, - unsigned int where, - uint16_t *value ) { - pcidirect_prepare ( pci, where ); - *value = inw ( PCIDIRECT_CONFIG_DATA + ( where & 2 ) ); - return 0; -} - -/** - * Read dword from PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( direct, pci_read_config_dword ) ( struct pci_device *pci, - unsigned int where, - uint32_t *value ) { - pcidirect_prepare ( pci, where ); - *value = inl ( PCIDIRECT_CONFIG_DATA ); - return 0; -} - -/** - * Write byte to PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( direct, pci_write_config_byte ) ( struct pci_device *pci, - unsigned int where, - uint8_t value ) { - pcidirect_prepare ( pci, where ); - outb ( value, PCIDIRECT_CONFIG_DATA + ( where & 3 ) ); - return 0; -} - -/** - * Write word to PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( direct, pci_write_config_word ) ( struct pci_device *pci, - unsigned int where, - uint16_t value ) { - pcidirect_prepare ( pci, where ); - outw ( value, PCIDIRECT_CONFIG_DATA + ( where & 2 ) ); - return 0; -} - -/** - * Write dword to PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __always_inline int -PCIAPI_INLINE ( direct, pci_write_config_dword ) ( struct pci_device *pci, - unsigned int where, - uint32_t value ) { - pcidirect_prepare ( pci, where ); - outl ( value, PCIDIRECT_CONFIG_DATA ); - return 0; -} - -#endif /* _PCIDIRECT_H */ diff --git a/gpxe/src/arch/x86/interface/efi/efix86_nap.c b/gpxe/src/arch/x86/interface/efi/efix86_nap.c deleted file mode 100644 index 89a4e3ba..00000000 --- a/gpxe/src/arch/x86/interface/efi/efix86_nap.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <gpxe/nap.h> -#include <gpxe/efi/efi.h> - -/** @file - * - * gPXE CPU sleeping API for EFI - * - */ - -/** - * Sleep until next interrupt - * - */ -static void efix86_cpu_nap ( void ) { - /* - * I can't find any EFI API that allows us to put the CPU to - * sleep. The CpuSleep() function is defined in CpuLib.h, but - * isn't part of any exposed protocol so we have no way to - * call it. - * - * The EFI shell doesn't seem to bother sleeping the CPU; it - * just sits there idly burning power. - * - */ - __asm__ __volatile__ ( "hlt" ); -} - -PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap ); diff --git a/gpxe/src/arch/x86/prefix/efidrvprefix.c b/gpxe/src/arch/x86/prefix/efidrvprefix.c deleted file mode 100644 index 36d56508..00000000 --- a/gpxe/src/arch/x86/prefix/efidrvprefix.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdlib.h> -#include <gpxe/init.h> -#include <gpxe/efi/efi.h> - -/** - * EFI entry point - * - * @v image_handle Image handle - * @v systab System table - * @ret efirc EFI return status code - */ -EFI_STATUS EFIAPI _start ( EFI_HANDLE image_handle, - EFI_SYSTEM_TABLE *systab ) { - EFI_STATUS efirc; - - /* Initialise EFI environment */ - if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 ) - return efirc; - - /* Initialise gPXE environment */ - initialise(); - startup(); - - /* Install SNP driver and return */ - return RC_TO_EFIRC ( efi_snp_install () ); -} diff --git a/gpxe/src/arch/x86/prefix/efiprefix.c b/gpxe/src/arch/x86/prefix/efiprefix.c deleted file mode 100644 index 4cc9e04a..00000000 --- a/gpxe/src/arch/x86/prefix/efiprefix.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdlib.h> -#include <gpxe/efi/efi.h> - -/** - * EFI entry point - * - * @v image_handle Image handle - * @v systab System table - * @ret efirc EFI return status code - */ -EFI_STATUS EFIAPI _start ( EFI_HANDLE image_handle, - EFI_SYSTEM_TABLE *systab ) { - EFI_STATUS efirc; - - /* Initialise EFI environment */ - if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 ) - return efirc; - - /* Call to main() */ - return RC_TO_EFIRC ( main () ); -} diff --git a/gpxe/src/arch/x86/scripts/efi.lds b/gpxe/src/arch/x86/scripts/efi.lds deleted file mode 100644 index 7525b81b..00000000 --- a/gpxe/src/arch/x86/scripts/efi.lds +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- sh -*- */ - -/* - * Linker script for EFI images - * - */ - -ENTRY ( _start ) - -SECTIONS { - - /* The file starts at a virtual address of zero, and sections are - * contiguous. Each section is aligned to at least _max_align, - * which defaults to 32. Load addresses are equal to virtual - * addresses. - */ - - _max_align = 32; - - /* Allow plenty of space for file headers */ - . = 0x1000; - - /* - * The text section - * - */ - - . = ALIGN ( _max_align ); - .text : { - _text = .; - *(.text) - *(.text.*) - _etext = .; - } - - /* - * The rodata section - * - */ - - . = ALIGN ( _max_align ); - .rodata : { - _rodata = .; - *(.rodata) - *(.rodata.*) - _erodata = .; - } - - /* - * The data section - * - */ - - . = ALIGN ( _max_align ); - .data : { - _data = .; - *(.data) - *(.data.*) - *(SORT(.tbl.*)) /* Various tables. See include/tables.h */ - _edata = .; - } - - /* - * The bss section - * - */ - - . = ALIGN ( _max_align ); - .bss : { - _bss = .; - *(.bss) - *(.bss.*) - *(COMMON) - _ebss = .; - } - - /* - * Weak symbols that need zero values if not otherwise defined - * - */ - - .weak 0x0 : { - _weak = .; - *(.weak) - _eweak = .; - } - _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" ); - - /* - * Dispose of the comment and note sections to make the link map - * easier to read - * - */ - - /DISCARD/ : { - *(.comment) - *(.comment.*) - *(.note) - *(.note.*) - *(.eh_frame) - *(.eh_frame.*) - *(.rel) - *(.rel.*) - *(.discard) - } -} diff --git a/gpxe/src/arch/x86_64/Makefile b/gpxe/src/arch/x86_64/Makefile deleted file mode 100644 index d2c2ff53..00000000 --- a/gpxe/src/arch/x86_64/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# Code size reduction. -# -CFLAGS += -fstrength-reduce -fomit-frame-pointer - -# Code size reduction. gcc3 needs a different syntax to gcc2 if you -# want to avoid spurious warnings. -# -CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1 - -# Use %rip-relative addressing wherever possible. -# -CFLAGS += -fpie - -# Force 64-bit code -# -CFLAGS += -m64 -ASFLAGS += --64 -LDFLAGS += -m elf_x86_64 - -# EFI requires -fshort-wchar, and nothing else currently uses wchar_t -# -CFLAGS += -fshort-wchar - -# We need to undefine the default macro "i386" when compiling .S -# files, otherwise ".arch i386" translates to ".arch 1"... -# -CFLAGS += -Ui386 - -# x86_64-specific directories containing source files -# -SRCDIRS += arch/x86_64/prefix - -# Include common x86 Makefile -# -MAKEDEPS += arch/x86/Makefile -include arch/x86/Makefile - -# Include platform-specific Makefile -# -MAKEDEPS += arch/x86_64/Makefile.$(PLATFORM) -include arch/x86_64/Makefile.$(PLATFORM) diff --git a/gpxe/src/arch/x86_64/Makefile.efi b/gpxe/src/arch/x86_64/Makefile.efi deleted file mode 100644 index 26b71278..00000000 --- a/gpxe/src/arch/x86_64/Makefile.efi +++ /dev/null @@ -1,14 +0,0 @@ -# -*- makefile -*- : Force emacs to use Makefile mode - -# EFI probably doesn't guarantee us a red zone, so let's not rely on it. -# -CFLAGS += -mno-red-zone - -# Specify EFI image builder -# -ELF2EFI = $(ELF2EFI64) - -# Include generic EFI Makefile -# -MAKEDEPS += arch/x86/Makefile.efi -include arch/x86/Makefile.efi diff --git a/gpxe/src/arch/x86_64/include/bits/byteswap.h b/gpxe/src/arch/x86_64/include/bits/byteswap.h deleted file mode 100644 index 9ed85e8f..00000000 --- a/gpxe/src/arch/x86_64/include/bits/byteswap.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _BITS_BYTESWAP_H -#define _BITS_BYTESWAP_H - -static inline __attribute__ (( always_inline, const )) uint16_t -__bswap_variable_16 ( uint16_t x ) { - __asm__ ( "xchgb %b0,%h0" : "=Q" ( x ) : "0" ( x ) ); - return x; -} - -static inline __attribute__ (( always_inline, const )) uint32_t -__bswap_variable_32 ( uint32_t x ) { - __asm__ ( "bswapl %k0" : "=r" ( x ) : "0" ( x ) ); - return x; -} - -static inline __attribute__ (( always_inline, const )) uint64_t -__bswap_variable_64 ( uint64_t x ) { - __asm__ ( "bswapq %q0" : "=r" ( x ) : "0" ( x ) ); - return x; -} - -#endif /* _BITS_BYTESWAP_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/compiler.h b/gpxe/src/arch/x86_64/include/bits/compiler.h deleted file mode 100644 index 51a7eaae..00000000 --- a/gpxe/src/arch/x86_64/include/bits/compiler.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BITS_COMPILER_H -#define _BITS_COMPILER_H - -#ifndef ASSEMBLY - -/** Declare a function with standard calling conventions */ -#define __asmcall __attribute__ (( regparm(0) )) - -/** Declare a function with libgcc implicit linkage */ -#define __libgcc - -#endif /* ASSEMBLY */ - -#endif /* _BITS_COMPILER_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/endian.h b/gpxe/src/arch/x86_64/include/bits/endian.h deleted file mode 100644 index 413e702d..00000000 --- a/gpxe/src/arch/x86_64/include/bits/endian.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ETHERBOOT_BITS_ENDIAN_H -#define ETHERBOOT_BITS_ENDIAN_H - -#define __BYTE_ORDER __LITTLE_ENDIAN - -#endif /* ETHERBOOT_BITS_ENDIAN_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/errfile.h b/gpxe/src/arch/x86_64/include/bits/errfile.h deleted file mode 100644 index dcda26ba..00000000 --- a/gpxe/src/arch/x86_64/include/bits/errfile.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _BITS_ERRFILE_H -#define _BITS_ERRFILE_H - -/** - * @addtogroup errfile Error file identifiers - * @{ - */ - -/** @} */ - -#endif /* _BITS_ERRFILE_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/io.h b/gpxe/src/arch/x86_64/include/bits/io.h deleted file mode 100644 index 921fdcc0..00000000 --- a/gpxe/src/arch/x86_64/include/bits/io.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _BITS_IO_H -#define _BITS_IO_H - -/** @file - * - * x86_64-specific I/O API implementations - * - */ - -#endif /* _BITS_IO_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/nap.h b/gpxe/src/arch/x86_64/include/bits/nap.h deleted file mode 100644 index 0a0c8a24..00000000 --- a/gpxe/src/arch/x86_64/include/bits/nap.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BITS_NAP_H -#define _BITS_NAP_H - -/** @file - * - * x86_64-specific CPU sleeping API implementations - * - */ - -#include <gpxe/efi/efix86_nap.h> - -#endif /* _BITS_MAP_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/smbios.h b/gpxe/src/arch/x86_64/include/bits/smbios.h deleted file mode 100644 index 2f0118d0..00000000 --- a/gpxe/src/arch/x86_64/include/bits/smbios.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _BITS_SMBIOS_H -#define _BITS_SMBIOS_H - -/** @file - * - * i386-specific SMBIOS API implementations - * - */ - -#endif /* _BITS_SMBIOS_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/stdint.h b/gpxe/src/arch/x86_64/include/bits/stdint.h deleted file mode 100644 index 9eb72e9c..00000000 --- a/gpxe/src/arch/x86_64/include/bits/stdint.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _BITS_STDINT_H -#define _BITS_STDINT_H - -typedef __SIZE_TYPE__ size_t; -typedef signed long ssize_t; -typedef signed long off_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef signed long long int64_t; - -typedef unsigned long physaddr_t; -typedef unsigned long intptr_t; - -#endif /* _BITS_STDINT_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/timer.h b/gpxe/src/arch/x86_64/include/bits/timer.h deleted file mode 100644 index dfa6c270..00000000 --- a/gpxe/src/arch/x86_64/include/bits/timer.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _BITS_TIMER_H -#define _BITS_TIMER_H - -/** @file - * - * x86_64-specific timer API implementations - * - */ - -#endif /* _BITS_TIMER_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/uaccess.h b/gpxe/src/arch/x86_64/include/bits/uaccess.h deleted file mode 100644 index 45582924..00000000 --- a/gpxe/src/arch/x86_64/include/bits/uaccess.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _BITS_UACCESS_H -#define _BITS_UACCESS_H - -/** @file - * - * x86_64-specific user access API implementations - * - */ - -#endif /* _BITS_UACCESS_H */ diff --git a/gpxe/src/arch/x86_64/include/bits/umalloc.h b/gpxe/src/arch/x86_64/include/bits/umalloc.h deleted file mode 100644 index 12bf949d..00000000 --- a/gpxe/src/arch/x86_64/include/bits/umalloc.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _BITS_UMALLOC_H -#define _BITS_UMALLOC_H - -/** @file - * - * x86_64-specific user memory allocation API implementations - * - */ - -#endif /* _BITS_UMALLOC_H */ diff --git a/gpxe/src/arch/x86_64/include/gdbmach.h b/gpxe/src/arch/x86_64/include/gdbmach.h deleted file mode 100644 index fcf8e94e..00000000 --- a/gpxe/src/arch/x86_64/include/gdbmach.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef GDBMACH_H -#define GDBMACH_H - -/** @file - * - * GDB architecture specifics - * - * This file declares functions for manipulating the machine state and - * debugging context. - * - */ - -#include <stdint.h> - -typedef unsigned long gdbreg_t; - -/* The register snapshot, this must be in sync with interrupt handler and the - * GDB protocol. */ -enum { - // STUB: don't expect this to work! - GDBMACH_EIP, - GDBMACH_EFLAGS, - GDBMACH_NREGS, - GDBMACH_SIZEOF_REGS = GDBMACH_NREGS * sizeof ( gdbreg_t ) -}; - -/* Breakpoint types */ -enum { - GDBMACH_BPMEM, - GDBMACH_BPHW, - GDBMACH_WATCH, - GDBMACH_RWATCH, - GDBMACH_AWATCH, -}; - -static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) { - regs [ GDBMACH_EIP ] = pc; -} - -static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) { - regs [ GDBMACH_EFLAGS ] &= ~( 1 << 8 ); /* Trace Flag (TF) */ - regs [ GDBMACH_EFLAGS ] |= ( step << 8 ); -} - -static inline void gdbmach_breakpoint ( void ) { - __asm__ __volatile__ ( "int $3\n" ); -} - -extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ); - -#endif /* GDBMACH_H */ diff --git a/gpxe/src/arch/x86_64/include/limits.h b/gpxe/src/arch/x86_64/include/limits.h deleted file mode 100644 index 8cf87b47..00000000 --- a/gpxe/src/arch/x86_64/include/limits.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef LIMITS_H -#define LIMITS_H 1 - -/* Number of bits in a `char' */ -#define CHAR_BIT 8 - -/* Minimum and maximum values a `signed char' can hold */ -#define SCHAR_MIN (-128) -#define SCHAR_MAX 127 - -/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ -#define UCHAR_MAX 255 - -/* Minimum and maximum values a `char' can hold */ -#define CHAR_MIN SCHAR_MIN -#define CHAR_MAX SCHAR_MAX - -/* Minimum and maximum values a `signed short int' can hold */ -#define SHRT_MIN (-32768) -#define SHRT_MAX 32767 - -/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */ -#define USHRT_MAX 65535 - - -/* Minimum and maximum values a `signed int' can hold */ -#define INT_MIN (-INT_MAX - 1) -#define INT_MAX 2147483647 - -/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ -#define UINT_MAX 4294967295U - - -/* Minimum and maximum values a `signed int' can hold */ -#define INT_MAX 2147483647 -#define INT_MIN (-INT_MAX - 1) - - -/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ -#define UINT_MAX 4294967295U - - -/* Minimum and maximum values a `signed long' can hold */ -#define LONG_MAX 9223372036854775807L -#define LONG_MIN (-LONG_MAX - 1L) - -/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */ -#define ULONG_MAX 18446744073709551615UL - -/* Minimum and maximum values a `signed long long' can hold */ -#define LLONG_MAX 9223372036854775807LL -#define LLONG_MIN (-LONG_MAX - 1LL) - - -/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */ -#define ULLONG_MAX 18446744073709551615ULL - - -#endif /* LIMITS_H */ |