diff options
Diffstat (limited to 'contrib/baremetal')
-rw-r--r-- | contrib/baremetal/Makefile | 475 | ||||
-rw-r--r-- | contrib/baremetal/main.c | 1119 | ||||
-rw-r--r-- | contrib/baremetal/marini.txt | 52 | ||||
-rw-r--r-- | contrib/baremetal/misc.c | 351 | ||||
-rw-r--r-- | contrib/baremetal/startmpcc.S | 756 |
5 files changed, 0 insertions, 2753 deletions
diff --git a/contrib/baremetal/Makefile b/contrib/baremetal/Makefile deleted file mode 100644 index df4de762..00000000 --- a/contrib/baremetal/Makefile +++ /dev/null @@ -1,475 +0,0 @@ -# -# Makefile for Etherboot -# -# Most of the time you should edit Config -# -# Common options: -# VERSION=v - Set the version string -# -# NS8390 options: -# -DINCLUDE_NE - Include NE1000/NE2000 support -# -DNE_SCAN=list - Probe for NE base address using list of -# comma separated hex addresses -# -DINCLUDE_3C503 - Include 3c503 support -# -DT503_SHMEM - Use 3c503 shared memory mode (off by default) -# -DINCLUDE_WD - Include Western Digital/SMC support -# -DWD_DEFAULT_MEM- Default memory location for WD/SMC cards -# -DCOMPEX_RL2000_FIX -# -# If you have a Compex RL2000 PCI 32-bit (11F6:1401), -# and the bootrom hangs in "Probing...[NE*000/PCI]", -# try enabling this fix... it worked for me :). -# In the first packet write somehow it somehow doesn't -# get back the expected data so it is stuck in a loop. -# I didn't bother to investigate what or why because it works -# when I interrupt the loop if it takes more then COMPEX_RL2000_TRIES. -# The code will notify if it does a abort. -# SomniOne - somnione@gmx.net -# -# 3C509 option: -# -DINCLUDE_3C509 - Include 3c509 support -# -# 3C90X options: -# -DINCLUDE_3C90X - Include 3c90x support -# -DCFG_3C90X_PRESERVE_XCVR - Reset the transceiver type to the value it -# had initially just before the loaded code is started. -# -DCFG_3C90X_XCVR - Hardcode the tranceiver type Etherboot uses. -# -DCFG_3C90X_BOOTROM_FIX - If you have a 3c905B with buggy ROM -# interface, setting this option might "fix" it. Use -# with caution and read the docs in 3c90x.txt! -# -# See the documentation file 3c90x.txt for more details. -# -# CS89X0 (optional) options: -# -DINCLUDE_CS89X0- Include CS89x0 support -# -DCS_SCAN=list - Probe for CS89x0 base address using list of -# comma separated hex addresses; increasing the -# address by one (0x300 -> 0x301) will force a -# more aggressive probing algorithm. This might -# be neccessary after a soft-reset of the NIC. -# -# LANCE options: -# -DINCLUDE_NE2100- Include NE2100 support -# -DINCLUDE_NI6510- Include NI6510 support -# -# SK_G16 options: -# -DINCLUDE_SK_G16- Include SK_G16 support -# -# I82586 options: -# -DINCLUDE_3C507 - Include 3c507 support -# -DINCLUDE_NI5210- Include NI5210 support -# -DINCLUDE_EXOS205-Include EXOS205 support -# -# SMC9000 options: -# -DINCLUDE_SMC9000 - Include SMC9000 driver -# -DSMC9000_SCAN=list - List of I/O addresses to probe -# -# TIARA (Fujitsu Etherstar) options: -# -DINCLUDE_TIARA - Include Tiara support -# -# NI5010 options: -# -DINCLUDE_NI5010 - Include NI5010 support -# -# TULIP options: -# -DINCLUDE_TULIP - Include Tulip support -# -DUSE_INTERNAL_BUFFER - receuve and transmit buffers within program -# space, not below 0x10000, in case that region is used -# -# RTL8139 options: -# -DINCLUDE_RTL8139 - Include RTL8139 support -# -DUSE_INTERNAL_BUFFER - 8 kB receive buffer within program space, -# not at 0x10000 - 8kB, in case that region is used -# - -include Config - -GCC= gcc -CPP= gcc -E -VERSION= 4.6.12 -CFLAGS16+= -DVERSION=\"$(VERSION)\" -DRELOC=$(RELOCADDR) -CFLAGS32+= -DVERSION=\"$(VERSION)\" -DRELOC=$(RELOCADDR) $(OLDGAS) -LCONFIG+= -DRELOC=$(RELOCADDR) - -IDENT16= 'Etherboot/16 $(VERSION) (GPL) $(@F)' -IDENT32= 'Etherboot/32 $(VERSION) (GPL) $(@F)' - -# Find out if we're using binutils 2.9.1 which uses a different syntax in some -# places (most prominently in the opcode prefix area). -OLDGAS:= $(shell $(AS) --version | grep -q '2\.9\.1' && echo -DGAS291) - -# Check the requested type of build (32, 16 or both families) -ifeq ($(ETHERBOOT),16) -BUILD_LIBS= $(BLIB16) -BUILD_BINS= $(BINS16) -endif -ifeq ($(ETHERBOOT),32) -BUILD_LIBS= $(BLIB32) -BUILD_BINS= $(BINS32) -endif -ifeq ($(ETHERBOOT),both) -BUILD_LIBS= $(BLIB16) $(BLIB32) -BUILD_BINS= $(BINS16) $(BINS32) -endif - -3C503FLAGS= -DINCLUDE_3C503 # -DT503_SHMEM -# Note that the suffix to MAKEROM_ is the (mixed case) basename of the ROM file -MAKEROM_3c503= -3 -3C507FLAGS= -DINCLUDE_3C507 -3C509FLAGS= -DINCLUDE_3C509 -3C529FLAGS= -DINCLUDE_3C529 -3C595FLAGS= -DINCLUDE_3C595 -3C90XFLAGS= -DINCLUDE_3C90X -CS89X0FLAGS= -DINCLUDE_CS89X0 -EEPROFLAGS= -DINCLUDE_EEPRO -EEPRO100FLAGS= -DINCLUDE_EEPRO100 -EPIC100FLAGS= -DINCLUDE_EPIC100 -EXOS205FLAGS= -DINCLUDE_EXOS205 -LANCEFLAGS= -DINCLUDE_LANCE # Lance/PCI! -NE2100FLAGS= -DINCLUDE_NE2100 -NEFLAGS= -DINCLUDE_NE -DNE_SCAN=0x300,0x280,0x320,0x340,0x380 -NS8390FLAGS= -DINCLUDE_NS8390 # NE2000/PCI! -NI5010FLAGS= -DINCLUDE_NI5010 -NI5210FLAGS= -DINCLUDE_NI5210 -NI6510FLAGS= -DINCLUDE_NI6510 -RTL8139FLAGS= -DINCLUDE_RTL8139 -SK_G16FLAGS= -DINCLUDE_SK_G16 -SMC9000FLAGS= -DINCLUDE_SMC9000 -TIARAFLAGS= -DINCLUDE_TIARA -DEPCAFLAGS= -DINCLUDE_DEPCA # -DDEPCA_MODEL=DEPCA -DDEPCA_RAM_BASE=0xd0000 -TULIPFLAGS= -DINCLUDE_TULIP -OTULIPFLAGS= -DINCLUDE_OTULIP -VIA_RHINEFLAGS= -DINCLUDE_VIA_RHINE -WDFLAGS= -DINCLUDE_WD -DWD_DEFAULT_MEM=0xCC000 -W89C840FLAGS= -DINCLUDE_W89C840 - -# If you have not made any changes to the *.S files, AS86 need not be set. -# (most people) -# If you have made changes to the *.S files and you want to rebuild *loader.bin -# and {floppy,com}load.bin and you have as86 from the ELKS Dev86 package (not -# the one that normally comes with Linux) (not most people) -#AS86= as86 -# If you have made changes to the *.S files and you want to rebuild *loader.bin -# and {floppy,com}load.bin and you have nasm (not most people) -#AS86= nasm - -# if your as has trouble with the data32 directive, uncomment this -# but note that the premade start*.o will be larger than necessary because it -# contains some routines which may not be used -#AS_PSEUDOS= n - -SRCS= floppyload.S comload.S liloprefix.S loader.S start16.S start32.S serial.S startmpcc.S -SRCS+= main.c pci.c osloader.c nfs.c misc.c ansiesc.c bootmenu.c config.c -SRCS+= md5.c floppy.c - -# ROM loaders: LZ version (prefix Z), PCI header version (prefix P) -ifndef AS86 -RLOADER= rloader.bin.pre -PRLOADER= prloader.bin.pre -RZLOADER= rzloader.bin.pre -PRZLOADER= przloader.bin.pre -FLOPPYLOAD= floppyload.bin.pre -COMLOAD= comload.bin.pre -LILOPREFIX= liloprefix.bin.pre -else -RLOADER= bin/rloader.bin -PRLOADER= bin/prloader.bin -RZLOADER= bin/rzloader.bin -PRZLOADER= bin/przloader.bin -FLOPPYLOAD= bin/floppyload.bin -COMLOAD= bin/comload.bin -LILOPREFIX= bin/liloprefix.bin -endif - -ifeq ($(AS86),as86) -LCPPFLAGS+= -DUSE_AS86 -LASFLAGS+= $(AS86FLAGS) -0 -LASBINARY:= -b -endif -ifeq ($(AS86),nasm) -LCPPFLAGS+= -DUSE_NASM -LASFLAGS+= $(NASMFLAGS) -fbin -LASBINARY:= -o -endif - -ifeq ($(AS_PSEUDOS),n) -START16= start16.o.pre -START32= start32.o.pre -else -START16= bin16/start16.o -START32= bin32/startmpcc.o -endif - -BOBJS16= bin16/main.o bin16/osloader.o bin16/misc.o bin16/bootmenu.o -BOBJS16+= bin16/floppy.o bin16/timer.o -BOBJS32= bin32/main.o bin32/osloader.o bin32/nfs.o bin32/misc.o -BOBJS32+= bin32/ansiesc.o bin32/bootmenu.o bin32/md5.o bin32/floppy.o -BOBJS32+= bin32/serial.o bin32/timer.o -BLIB16= bin16/bootlib.a -BLIB32= bin32/bootlib.a -LIBS16= $(BLIB16) $(LIBC16) -LIBS32= $(BLIB32) $(LIBC32) /usr/lib/gcc-lib/i386-redhat-linux/2.96/libgcc.a -UTIL_LZHUF:= $(shell if [ -d ../contrib/compressor ]; then echo bin/lzhuf; fi) -UTILS+= bin/makerom $(UTIL_LZHUF) bin/organon -STDDEPS16= $(START16) $(BLIB16) $(UTILS) -STDDEPS32= $(START32) $(BLIB32) $(UTILS) -MAKEDEPS= Makefile Config Roms - -CHECKSIZE= { read d1; read d1 d2 d3 size d4; [ $$size -gt $(ROMLIMIT) ] &&\ - { $(RM) $@; echo "ERROR: code size exceeds limit!"; exit 1; }; exit 0; } - -# Make sure that the relocation address is acceptable for all ROM sizes. -# Setting it to 0x98000 leaves about 29kB of space for the Etherboot program. -# The check is done based running 'size' on the binary, not ROM size, but -# roughly this means a ROM of 16kB or a partially used ROM of 32kB, -# remembering to compressed ROM images into account. -# You may also set RELOCADDR to 0x88000 to avoid using 0x98000 -# because of other drivers (e.g. Disk On Chip). In that case, you may -# only load 512kB of OS, or load in memory above 1MB. -# Don't forget to choose an assembler because the loaders have to be rebuilt. -ifndef RELOCADDR -RELOCADDR=0x98000 -#RELOCADDR=0xe0000 -endif - -# Evaluate ROMLIMIT only once - it is constant during the make run. -# Note that the 3K safety margin below is for the 1K extended BIOS data area -# and for the Etherboot runtime stack. Under normal situations, 2K of stack -# are rarely needed. If you experience strange behaviour in functions that use -# many local variables or that call functions that do, check for stack overrun! -# Make sure that the normal case needs no perl interpreter - if someone uses a -# different RELOCADDR, then he has perl installed anyways (the shell cannot -# deal with hex numbers, as test/eval don't support non-decimal integers). -ifeq ($(RELOCADDR),0x98000) -ROMLIMIT=29696 -else -ROMLIMIT:=$(shell perl -e 'print 0x10000 - 3072 - ($(RELOCADDR) & 0xFFFF), "\n";') -endif - -# Start of targets - -all: $(UTILS) $(BUILD_LIBS) allbins - -include Roms - -# We need allbins because $(BINS16) and $(BINS32) are not defined until -# the Makefile fragment "Roms" is read. - -allbins: $(BUILD_BINS) - -# Common files - -$(BLIB16): $(BOBJS16) - $(AR16) rv $@ $(BOBJS16) - $(RANLIB16) $@ - -$(BLIB32): $(BOBJS32) - $(AR32) rv $@ $(BOBJS32) - $(RANLIB32) $@ - -bin16/main.o: main.c etherboot.h osdep.h nic.h -bin32/main.o: main.c etherboot.h osdep.h nic.h - -bin16/osloader.o: osloader.c etherboot.h osdep.h -bin32/osloader.o: osloader.c etherboot.h osdep.h - -# NFS currently makes no sense for Etherboot/16 -bin32/nfs.o: nfs.c etherboot.h osdep.h nic.h - -bin16/misc.o: misc.c etherboot.h osdep.h -bin32/misc.o: misc.c etherboot.h osdep.h - -# ANSIESC is not supported for Etherboot/16 -bin32/ansiesc.o: ansiesc.c etherboot.h osdep.h - -bin16/bootmenu.o: bootmenu.c etherboot.h osdep.h -bin32/bootmenu.o: bootmenu.c etherboot.h osdep.h - -# Password support is not available for Etherboot/16 -bin32/md5.o: md5.c etherboot.h osdep.h - -bin16/floppy.o: floppy.c etherboot.h osdep.h -bin32/floppy.o: floppy.c etherboot.h osdep.h - -bin16/timer.o: timer.c timer.h etherboot.h osdep.h -bin32/timer.o: timer.c timer.h etherboot.h osdep.h - -bin32/inthw.o: inthw.c - -# PCI support code (common to all PCI drivers) - -bin32/pci.o: pci.c pci.h - -# Do not add driver specific dependencies here unless it's something the -# genrules.pl script *can't* deal with, i.e. if it is not C code. - -# Prepended loaders - -#ifndef AS86 -#$(RLOADER) $(RZLOADER) $(PRLOADER) $(PRZLOADER): $(MAKEDEPS) -# @if [ $(RELOCADDR) != 0x98000 ]; then echo Non-standard RELOCADDR, must assemble $@; exit 1; fi -# $(TOUCH) $@ -#else -#bin/rloader.s: loader.S $(MAKEDEPS) -# $(CPP) $(LCPPFLAGS) $(LCONFIG) -o $@ $< -# -#bin/rzloader.s: loader.S $(MAKEDEPS) -# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DZLOADER -o $@ $< -# -#bin/prloader.s: loader.S $(MAKEDEPS) -# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DPCI_PNP_HEADER -o $@ $< -# -#bin/przloader.s: loader.S $(MAKEDEPS) -# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DPCI_PNP_HEADER -DZLOADER -o $@ $< -#endif - -# Floppy loader - -ifdef AS86 -bin/floppyload.s: floppyload.S $(MAKEDEPS) - $(CPP) $(LCPPFLAGS) -o $@ $< -endif - -# COM loader - -ifdef AS86 -bin/comload.s: comload.S $(MAKEDEPS) - $(CPP) $(LCPPFLAGS) -o $@ $< -endif - -# LILO prefix: - -ifdef AS86 -bin/liloprefix.s: liloprefix.S $(MAKEDEPS) - $(CPP) $(LCPPFLAGS) -o $@ $< -endif - -# Utilities - -bin/makerom: makerom.c - $(GCC) -O2 -o $@ makerom.c - -bin/organon: organon.c - $(GCC) -o $@ organon.c - -bin/lzhuf: ../contrib/compressor/lzhuf.c - $(GCC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -o $@ $< - -# Roms file - -Roms: NIC genrules.pl - @chmod +x genrules.pl - ./genrules.pl NIC > $@ - -# Pattern Rules - -# general rules for compiling/assembling source files -bin16/%.o: %.c $(MAKEDEPS) - $(CC16) $(CFLAGS16) -o $@ -c $< - -bin32/%.o: %.c $(MAKEDEPS) - $(CC32) $(CFLAGS32) -o $@ -c $< - -bin16/%.o: %.S $(MAKEDEPS) - $(CC16) $(CFLAGS16) $(ASFLAGS16) -c -o $@ $< - -bin32/%.o: %.S $(MAKEDEPS) - $(CPP) $(CFLAGS32) $< | $(AS) $(ASFLAGS32) -o $@ - -# general rule for .bin (plain binary loader code), may be overridden -ifdef AS86 -bin/%.bin: bin/%.s - $(AS86) $(LASFLAGS) $(LASBINARY) $@ $< -endif - -# general rule for .huf (compressed binary code), may be overridden -%.huf: %.img - bin/lzhuf e $< $@ - -# general rules for normal/compressed ROM images, may be overridden -bin16/%.rom: bin16/%.img $(RLOADER) - cat $(RLOADER) $< > $@ - bin/makerom $(MAKEROM_$*) -i$(IDENT16) $@ - -bin32/%.rom: bin32/%.img $(RLOADER) - cat $(RLOADER) $< > $@ - bin/makerom $(MAKEROM_$*) -i$(IDENT32) $@ - -bin16/%.lzrom: bin16/%.huf $(RZLOADER) - cat $(RZLOADER) $< > $@ - bin/makerom $(MAKEROM_$*) -i$(IDENT16) $@ - -bin32/%.lzrom: bin32/%.huf $(RZLOADER) - cat $(RZLOADER) $< > $@ - bin/makerom $(MAKEROM_$*) -i$(IDENT32) $@ - -# rules to write the .rom/.lzrom image onto a blank floppy -# You must give the directory name, e.g. use bin32/rtl8139.lzfd0 as the target. -%.fd0: %.rom $(FLOPPYLOAD) - cat $(FLOPPYLOAD) $< > /dev/fd0 - -%.lzfd0: %.lzrom $(FLOPPYLOAD) - cat $(FLOPPYLOAD) $< > /dev/fd0 - -# rules to generate a .com executable -# You must give the directory name, e.g. use bin32/rtl8139.com as the target. -%.com: %.lzrom $(COMLOAD) - cat $(COMLOAD) $< > $@ - -# rules to make a floppy image (padding to fill an even number of cylinders). -# VMware reports floppy image read errors if it cannot read ahead 36 sectors, -# probably because the floppyload.S code reads up to that number of sectors in -# a single request. Not that 18k matters much these days... -# You must give the directory name, e.g. use bin32/rtl8139.fdimg as the target. -%.fdimg: %.rom $(FLOPPYLOAD) - cat $(FLOPPYLOAD) $< > $@.x - dd if=$@.x of=$@ bs=36k conv=sync 2> /dev/null - $(RM) $@.x - -%.lzfdimg: %.lzrom $(FLOPPYLOAD) - cat $(FLOPPYLOAD) $< > $@.x - dd if=$@.x of=$@ bs=36k conv=sync 2> /dev/null - $(RM) $@.x - -# rules to make a LILO-bootable image -%.lilo: %.rom $(LILOPREFIX) - cat $(LILOPREFIX) $< /dev/zero | head -c 64k > $@ - -%.lzlilo: %.lzrom $(LILOPREFIX) - cat $(LILOPREFIX) $< /dev/zero | head -c 64k > $@ - -# Housekeeping - -# To make sure that this actually builds a start32.o.pre with all options set, -# you have to make sure that -DFLOPPY -DANSIESC -DCONSOLE_DUAL are in CFLAGS32. -precompiled: bin/rloader.bin bin/rzloader.bin bin/prloader.bin bin/przloader.bin bin/floppyload.bin bin/comload.bin bin16/start16.o bin32/start32.o bin/liloprefix.bin - cp -p bin/rloader.bin rloader.bin.pre - cp -p bin/rzloader.bin rzloader.bin.pre - cp -p bin/prloader.bin prloader.bin.pre - cp -p bin/przloader.bin przloader.bin.pre - cp -p bin/floppyload.bin floppyload.bin.pre - cp -p bin/comload.bin comload.bin.pre - cp -p bin16/start16.o start16.o.pre - cp -p bin32/start32.o start32.o.pre - cp -p bin/liloprefix.bin liloprefix.bin.pre - -clean: - $(RM) $(UTILS) bin/*.s bin/*.bin - $(RM) $(BLIB16) $(BLIB32) - $(RM) bin16/*.o bin32/*.o bin16/*.tmp bin32/*.tmp - $(RM) bin16/*.img bin32/*.img bin16/*.huf bin32/*.huf - $(RM) bin16/*.rom bin32/*.rom bin16/*.lzrom bin32/*.lzrom - $(RM) bin16/*.com bin32/*.com - $(RM) bin16/*.fdimg bin32/*.fdimg bin16/*.lzfdimg bin32/*.lzfdimg - $(RM) bin16/*.lilo bin32/*.lilo bin16/*.lzlilo bin32/*.lzlilo - $(RM) bin32/*.hex - $(RM) bin32/*.asm - $(RM) bin32/*.map - -tarball: - (echo -n $(VERSION) ''; date -u +'%Y-%m-%d') > ../VERSION - (cd ..; tar cf /tmp/mpccboot-$(VERSION).tar --exclude CVS mpccboot) - bzip2 -9 < /tmp/mpccboot-$(VERSION).tar > /tmp/mpccboot-$(VERSION).tar.bz2 - gzip -9 < /tmp/mpccboot-$(VERSION).tar > /tmp/mpccboot-$(VERSION).tar.gz - -version: - @echo $(VERSION) diff --git a/contrib/baremetal/main.c b/contrib/baremetal/main.c deleted file mode 100644 index 7b0de44c..00000000 --- a/contrib/baremetal/main.c +++ /dev/null @@ -1,1119 +0,0 @@ -/************************************************************************** -ETHERBOOT - BOOTP/TFTP Bootstrap Program - -Author: Martin Renters - Date: Dec/93 - -Literature dealing with the network protocols: - ARP - RFC826 - RARP - RFC903 - UDP - RFC768 - BOOTP - RFC951, RFC2132 (vendor extensions) - DHCP - RFC2131, RFC2132 (options) - TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize) - RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper) - NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented) - -**************************************************************************/ - -/* #define MDEBUG */ - -#include "etherboot.h" -#include "nic.h" - -int jmp_bootmenu[10]; - -struct arptable_t arptable[MAX_ARP]; - -const char *kernel; -char kernel_buf[128]; -struct rom_info rom; - -#ifdef IMAGE_MENU -static char *imagelist[RFC1533_VENDOR_NUMOFIMG]; -static int useimagemenu; -int menutmo,menudefault; -unsigned char *defparams = NULL; -int defparams_max = 0; -#endif -#ifdef MOTD -char *motd[RFC1533_VENDOR_NUMOFMOTD]; -#endif -#ifdef IMAGE_FREEBSD -int freebsd_howto = 0; -#endif -int vendorext_isvalid; -char config_buffer[TFTP_MAX_PACKET+1]; /* +1 for null byte */ -unsigned long netmask; -char *hostname = ""; -int hostnamelen = 0; -#if defined(ETHERBOOT16) || defined(INTERNAL_BOOTP_DATA) -struct bootpd_t bootp_data; -#endif -unsigned long xid; -unsigned char *end_of_rfc1533 = NULL; -#ifndef NO_DHCP_SUPPORT -int dhcp_reply; -in_addr dhcp_server = { 0L }; -in_addr dhcp_addr = { 0L }; -#endif /* NO_DHCP_SUPPORT */ - -unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */ -#ifdef NO_DHCP_SUPPORT -char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END }; -#else -char rfc1533_cookie[] = { RFC1533_COOKIE}; -char rfc1533_end[]={RFC1533_END }; -static const char dhcpdiscover[]={ - RFC2132_MSG_TYPE,1,DHCPDISCOVER, - RFC2132_MAX_SIZE,2, /* request as much as we can */ - sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256, - RFC2132_PARAM_LIST,4,RFC1533_NETMASK,RFC1533_GATEWAY, - RFC1533_HOSTNAME - }; -static const char dhcprequest []={ - RFC2132_MSG_TYPE,1,DHCPREQUEST, - RFC2132_SRV_ID,4,0,0,0,0, - RFC2132_REQ_ADDR,4,0,0,0,0, - RFC2132_MAX_SIZE,2, /* request as much as we can */ - sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256, - /* request parameters */ - RFC2132_PARAM_LIST, -#ifdef IMAGE_FREEBSD - /* 4 standard + 6 vendortags + 8 motd + 16 menu items */ - 4 + 6 + 8 + 16, -#else - /* 4 standard + 5 vendortags + 8 motd + 16 menu items */ - 4 + 5 + 8 + 16, -#endif - /* Standard parameters */ - RFC1533_NETMASK, RFC1533_GATEWAY, - RFC1533_HOSTNAME, - RFC1533_ROOTPATH, /* only passed to the booted image */ - /* Etherboot vendortags */ - RFC1533_VENDOR_MAGIC, - RFC1533_VENDOR_ADDPARM, - RFC1533_VENDOR_ETHDEV, -#ifdef IMAGE_FREEBSD - RFC1533_VENDOR_HOWTO, -#endif - RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION, - /* 8 MOTD entries */ - RFC1533_VENDOR_MOTD, - RFC1533_VENDOR_MOTD+1, - RFC1533_VENDOR_MOTD+2, - RFC1533_VENDOR_MOTD+3, - RFC1533_VENDOR_MOTD+4, - RFC1533_VENDOR_MOTD+5, - RFC1533_VENDOR_MOTD+6, - RFC1533_VENDOR_MOTD+7, - /* 16 image entries */ - RFC1533_VENDOR_IMG, - RFC1533_VENDOR_IMG+1, - RFC1533_VENDOR_IMG+2, - RFC1533_VENDOR_IMG+3, - RFC1533_VENDOR_IMG+4, - RFC1533_VENDOR_IMG+5, - RFC1533_VENDOR_IMG+6, - RFC1533_VENDOR_IMG+7, - RFC1533_VENDOR_IMG+8, - RFC1533_VENDOR_IMG+9, - RFC1533_VENDOR_IMG+10, - RFC1533_VENDOR_IMG+11, - RFC1533_VENDOR_IMG+12, - RFC1533_VENDOR_IMG+13, - RFC1533_VENDOR_IMG+14, - RFC1533_VENDOR_IMG+15, - }; - -#endif /* NO_DHCP_SUPPORT */ -static const char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - -/************************************************************************** -MAIN - Kick off routine -**************************************************************************/ -int main(void) -{ - char *p; - static int card_retries = 0; - int i; - - for (p=_edata; p<_end; p++) - *p = 0; /* Zero BSS */ - -#ifdef CONSOLE_SERIAL - (void)serial_init(); -#endif - -#ifdef DELIMITERLINES - for (i=0; i<80; i++) putchar('='); -#endif - -#ifdef ETHERBOOT32 - rom = *(struct rom_info *)ROM_INFO_LOCATION; - printf("ROM segment %#x length %#x reloc %#x\n", rom.rom_segment, - rom.rom_length << 1, ((unsigned long)_start) >> 4); -#endif -#ifdef ETHERBOOT16 - fmemcpy(&rom, (Address)ROM_INFO_LOCATION, sizeof(rom)); - printf("ROM segment %#x length %#x\n", rom.rom_segment, - rom.rom_length << 1); -#endif -#ifdef ASK_BOOT - while (1) { - int c; - unsigned long time; - printf(ASK_PROMPT); -#if ASK_BOOT > 0 - for (time = currticks() + ASK_BOOT*TICKS_PER_SEC; !iskey(); ) - if (currticks() > time) { - c = ANS_DEFAULT; - goto done; - } -#endif - c = getchar(); - if ((c >= 'a') && (c <= 'z')) c &= 0x5F; - if (c == '\n') c = ANS_DEFAULT; -done: - if ((c >= ' ') && (c <= '~')) putchar(c); - putchar('\n'); - if (c == ANS_LOCAL) - exit(0); - if (c == ANS_NETWORK) - break; - } -#endif -#if (TRY_FLOPPY_FIRST > 0) && defined(FLOPPY) - disk_init(); - printf("Trying floppy"); - for (i = TRY_FLOPPY_FIRST; i-- > 0; ) { - putchar('.'); - if (disk_read(0, 0, 0, 0, ((char *) FLOPPY_BOOT_LOCATION)) != 0x8000) { - printf("using floppy\n"); - exit(0); - } - } - printf("no floppy\n"); -#endif /* TRY_FLOPPY_FIRST && FLOPPY */ - print_config(); - gateA20_set(); -#ifdef EMERGENCYDISKBOOT - if (!eth_probe()) { - printf("No adapter found\n"); - exit(0); - } -#else - while (!eth_probe()) { - printf("No adapter found"); - if (!setjmp(jmp_bootmenu)) - rfc951_sleep(++card_retries); - } -#endif - kernel = DEFAULT_BOOTFILE; - while (1) { - if ((i = setjmp(jmp_bootmenu)) != 0) { -#if defined(ANSIESC) && defined(CONSOLE_CRT) - ansi_reset(); -#endif - bootmenu(--i); - } else { - load(); - } -#if defined(ANSIESC) && defined(CONSOLE_CRT) - ansi_reset(); -#endif - } -} - -/************************************************************************** -LOADKERNEL - Try to load kernel image -**************************************************************************/ -#ifndef FLOPPY -#define loadkernel(s) download((s),downloadkernel) -#else -static int loadkernel(const char *fname) -{ - if (!memcmp(fname,"/dev/",5) && fname[6] == 'd') { - int dev, part = 0; - if (fname[5] == 'f') { - if ((dev = fname[7] - '0') < 0 || dev > 3) - goto nodisk; } - else if (fname[5] == 'h' || fname[5] == 's') { - if ((dev = 0x80 + fname[7] - 'a') < 0x80 || dev > 0x83) - goto nodisk; - if (fname[8]) { - part = fname[8] - '0'; - if (fname[9]) - part = 10*part + fname[9] - '0'; } - /* bootdisk cannot cope with more than eight partitions */ - if (part < 0 || part > 8) - goto nodisk; } - else - goto nodisk; - return(bootdisk(dev,part)); } -nodisk: - return download(fname, downloadkernel); -} -#endif - -/************************************************************************** -LOAD - Try to get booted -**************************************************************************/ -void load() -{ - static int bootp_completed = 0; - - /* Find a server to get BOOTP reply from */ - if (!bootp_completed || - !arptable[ARP_CLIENT].ipaddr.s_addr || !arptable[ARP_SERVER].ipaddr.s_addr) { -retry: - bootp_completed = 0; -#ifdef RARP_NOT_BOOTP - printf("Searching for server (RARP)...\n"); -#else -#ifndef NO_DHCP_SUPPORT - printf("Searching for server (DHCP)...\n"); -#else - printf("Searching for server (BOOTP)...\n"); -#endif -#endif - -#ifdef RARP_NOT_BOOTP - if (!rarp()) { -#else - if (!bootp()) { -#endif - printf("No Server found\n"); -#ifdef EMERGENCYDISKBOOT - exit(0); -#else - goto retry; -#endif - } - bootp_completed++; - } - printf("Me: %I, Server: %I", - arptable[ARP_CLIENT].ipaddr.s_addr, - arptable[ARP_SERVER].ipaddr.s_addr); - if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr) - printf(", Relay: %I", - BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr); - if (arptable[ARP_GATEWAY].ipaddr.s_addr) - printf(", Gateway %I", arptable[ARP_GATEWAY].ipaddr.s_addr); - putchar('\n'); - -#ifdef MDEBUG - printf("\n=>>"); getchar(); -#endif - -#ifdef MOTD - if (vendorext_isvalid) - show_motd(); -#endif - /* Now use TFTP to load file */ -#ifdef IMAGE_MENU - if (vendorext_isvalid && useimagemenu) { - selectImage(imagelist); - bootp_completed = 0; - } -#endif -#ifdef DOWNLOAD_PROTO_NFS - rpc_init(); -#endif - for (;;) { - printf("Loading %s ",kernel); - while (!loadkernel(kernel)) { - printf("Unable to load file.\n"); - sleep(2); /* lay off server for a while */ - } - } -} - -/************************************************************************** -DEFAULT_NETMASK - Return default netmask for IP address -**************************************************************************/ -static inline unsigned long default_netmask(void) -{ - int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24; - if (net <= 127) - return(htonl(0xff000000)); - else if (net < 192) - return(htonl(0xffff0000)); - else - return(htonl(0xffffff00)); -} - -/************************************************************************** -UDP_TRANSMIT - Send a UDP datagram -**************************************************************************/ -int udp_transmit(unsigned long destip, unsigned int srcsock, - unsigned int destsock, int len, const void *buf) -{ - struct iphdr *ip; - struct udphdr *udp; - struct arprequest arpreq; - int arpentry, i; - int retry; - - ip = (struct iphdr *)buf; - udp = (struct udphdr *)((long)buf + sizeof(struct iphdr)); - ip->verhdrlen = 0x45; - ip->service = 0; - ip->len = htons(len); - ip->ident = 0; - ip->frags = 0; - ip->ttl = 60; - ip->protocol = IP_UDP; - ip->chksum = 0; - ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr; - ip->dest.s_addr = destip; - ip->chksum = ipchksum((unsigned short *)buf, sizeof(struct iphdr)); - udp->src = htons(srcsock); - udp->dest = htons(destsock); - udp->len = htons(len - sizeof(struct iphdr)); - udp->chksum = 0; - if (destip == IP_BROADCAST) { - eth_transmit(broadcast, IP, len, buf); - } else { - if (((destip & netmask) != - (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) && - arptable[ARP_GATEWAY].ipaddr.s_addr) - destip = arptable[ARP_GATEWAY].ipaddr.s_addr; - for(arpentry = 0; arpentry<MAX_ARP; arpentry++) - if (arptable[arpentry].ipaddr.s_addr == destip) break; - if (arpentry == MAX_ARP) { - printf("%I is not in my arp table!\n", destip); - return(0); - } - for (i = 0; i<ETHER_ADDR_SIZE; i++) - if (arptable[arpentry].node[i]) break; - if (i == ETHER_ADDR_SIZE) { /* Need to do arp request */ - arpreq.hwtype = htons(1); - arpreq.protocol = htons(IP); - arpreq.hwlen = ETHER_ADDR_SIZE; - arpreq.protolen = 4; - arpreq.opcode = htons(ARP_REQUEST); - memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); - memset(arpreq.thwaddr, 0, ETHER_ADDR_SIZE); - memcpy(arpreq.tipaddr, &destip, sizeof(in_addr)); - for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) { - eth_transmit(broadcast, ARP, sizeof(arpreq), - &arpreq); - if (await_reply(AWAIT_ARP, arpentry, - arpreq.tipaddr, TIMEOUT)) goto xmit; - rfc951_sleep(retry); - /* We have slept for a while - the packet may - * have arrived by now. If not, we have at - * least some room in the Rx buffer for the - * next reply. */ - if (await_reply(AWAIT_ARP, arpentry, - arpreq.tipaddr, 0)) goto xmit; - } - return(0); - } -xmit: - eth_transmit(arptable[arpentry].node, IP, len, buf); - } - return(1); -} - -/************************************************************************** -DOWNLOADKERNEL - Try to load file -**************************************************************************/ -int downloadkernel(data, block, len, eof) - unsigned char *data; - int block, len, eof; -{ -#ifdef SIZEINDICATOR - static int rlen = 0; - - if (!(block % 4) || eof) { - int size; - size = ((block-1) * rlen + len) / 1024; - - putchar('\b'); - putchar('\b'); - putchar('\b'); - putchar('\b'); - - putchar('0' + (size/1000)%10); - putchar('0' + (size/100)%10); - putchar('0' + (size/10)%10); - putchar('0' + (size/1)%10); - } -#endif - if (block == 1) - { -#ifdef SIZEINDICATOR - rlen=len; -#endif - if (!eof && ( -#ifdef TAGGED_IMAGE - *((unsigned long *)data) == 0x1B031336L || -#endif -#ifdef ELF_IMAGE - *((unsigned long *)data) == 0x464C457FL || -#endif -#ifdef AOUT_IMAGE - *((unsigned short *)data) == 0x010BL || -#endif - ((unsigned short *)data)[255] == 0xAA55)) - { - ; - } - else if (eof) - { - memcpy(config_buffer, data, len); - config_buffer[len] = 0; - return (1); /* done */ - } - else - { - printf("error: not a tagged image\n"); - return(0); /* error */ - } - } - if (len != 0) { - if (!os_download(block, data, len)) - return(0); /* error */ - } - if (eof) { - os_download(block+1, data, 0); /* does not return */ - return(0); /* error */ - } - return(-1); /* there is more data */ -} - -#ifdef DOWNLOAD_PROTO_TFTP -/************************************************************************** -TFTP - Download extended BOOTP data, or kernel image -**************************************************************************/ -int tftp(const char *name, int (*fnc)(unsigned char *, int, int, int)) -{ - int retry = 0; - static unsigned short iport = 2000; - unsigned short oport; - unsigned short len, block = 0, prevblock = 0; - int bcounter = 0; - struct tftp_t *tr; - struct tftp_t tp; - int rc; - int packetsize = TFTP_DEFAULTSIZE_PACKET; - - /* Clear out the Rx queue first. It contains nothing of interest, - * except possibly ARP requests from the DHCP/TFTP server. We use - * polling throughout Etherboot, so some time may have passed since we - * last polled the receive queue, which may now be filled with - * broadcast packets. This will cause the reply to the packets we are - * about to send to be lost immediately. Not very clever. */ - await_reply(AWAIT_QDRAIN, 0, NULL, 0); - - tp.opcode = htons(TFTP_RRQ); - len = (sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d", - name, 0, 0, 0, TFTP_MAX_PACKET) - ((char *)&tp)) + 1; - if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport, - TFTP_PORT, len, &tp)) - return (0); - for (;;) - { -#ifdef CONGESTED - if (!await_reply(AWAIT_TFTP, iport, NULL, (block ? TFTP_REXMT : TIMEOUT))) -#else - if (!await_reply(AWAIT_TFTP, iport, NULL, TIMEOUT)) -#endif - { - if (!block && retry++ < MAX_TFTP_RETRIES) - { /* maybe initial request was lost */ - rfc951_sleep(retry); - if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, - ++iport, TFTP_PORT, len, &tp)) - return (0); - continue; - } -#ifdef CONGESTED - if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT)) - { /* we resend our last ack */ -#ifdef MDEBUG - printf("<REXMT>\n"); -#endif - udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, - iport, oport, - TFTP_MIN_PACKET, &tp); - continue; - } -#endif - break; /* timeout */ - } - tr = (struct tftp_t *)&nic.packet[ETHER_HDR_SIZE]; - if (tr->opcode == ntohs(TFTP_ERROR)) - { - printf("TFTP error %d (%s)\n", - ntohs(tr->u.err.errcode), - tr->u.err.errmsg); - break; - } - - if (tr->opcode == ntohs(TFTP_OACK)) { - char *p = tr->u.oack.data, *e; - - if (prevblock) /* shouldn't happen */ - continue; /* ignore it */ - len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 2; - if (len > TFTP_MAX_PACKET) - goto noak; - e = p + len; - while (*p != '\000' && p < e) { - if (!strcasecmp("blksize", p)) { - p += 8; - if ((packetsize = getdec(&p)) < - TFTP_DEFAULTSIZE_PACKET) - goto noak; - while (p < e && *p) p++; - if (p < e) - p++; - } - else { - noak: - tp.opcode = htons(TFTP_ERROR); - tp.u.err.errcode = 8; - len = (sprintf((char *)tp.u.err.errmsg, - "RFC1782 error") - - ((char *)&tp)) + 1; - udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, - iport, ntohs(tr->udp.src), - len, &tp); - return (0); - } - } - if (p > e) - goto noak; - block = tp.u.ack.block = 0; /* this ensures, that */ - /* the packet does not get */ - /* processed as data! */ - } - else if (tr->opcode == ntohs(TFTP_DATA)) { - len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4; - if (len > packetsize) /* shouldn't happen */ - continue; /* ignore it */ - block = ntohs(tp.u.ack.block = tr->u.data.block); } - else /* neither TFTP_OACK nor TFTP_DATA */ - break; - - if ((block || bcounter) && (block != prevblock+1)) { - /* Block order should be continuous */ - tp.u.ack.block = htons(block = prevblock); - } - tp.opcode = htons(TFTP_ACK); - oport = ntohs(tr->udp.src); - udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport, - oport, TFTP_MIN_PACKET, &tp); /* ack */ - if ((unsigned short)(block-prevblock) != 1) { - /* Retransmission or OACK, don't process via callback - * and don't change the value of prevblock. */ - continue; - } - prevblock = block; - retry = 0; /* It's the right place to zero the timer? */ - if ((rc = fnc(tr->u.data.download, - ++bcounter, len, len < packetsize)) >= 0) - return(rc); - if (len < packetsize) /* End of data */ - return (1); - } - return (0); -} -#endif /* DOWNLOAD_PROTO_TFTP */ - -#ifdef RARP_NOT_BOOTP -/************************************************************************** -RARP - Get my IP address and load information -**************************************************************************/ -int rarp() -{ - int retry; - - /* arp and rarp requests share the same packet structure. */ - struct arprequest rarpreq; - - memset(&rarpreq, 0, sizeof(rarpreq)); - - rarpreq.hwtype = htons(1); - rarpreq.protocol = htons(IP); - rarpreq.hwlen = ETHER_ADDR_SIZE; - rarpreq.protolen = 4; - rarpreq.opcode = htons(RARP_REQUEST); - memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - /* sipaddr is already zeroed out */ - memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - /* tipaddr is already zeroed out */ - - for (retry = 0; retry < MAX_ARP_RETRIES; rfc951_sleep(++retry)) { - eth_transmit(broadcast, RARP, sizeof(rarpreq), &rarpreq); - - if (await_reply(AWAIT_RARP, 0, rarpreq.shwaddr, TIMEOUT)) - break; - } - - if (retry < MAX_ARP_RETRIES) { - sprintf(kernel = kernel_buf, "/tftpboot/kernel.%I", arptable[ARP_CLIENT].ipaddr); - - return (1); - } - return (0); -} - -#else - -/************************************************************************** -BOOTP - Get my IP address and load information -**************************************************************************/ -int bootp() -{ - int retry; -#ifndef NO_DHCP_SUPPORT - int retry1; -#endif /* NO_DHCP_SUPPORT */ - struct bootp_t bp; - unsigned long starttime; -#ifdef T509HACK - int flag; - - flag = 1; -#endif - memset(&bp, 0, sizeof(struct bootp_t)); - bp.bp_op = BOOTP_REQUEST; - bp.bp_htype = 1; - bp.bp_hlen = ETHER_ADDR_SIZE; - bp.bp_xid = xid = starttime = currticks(); - memcpy(bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); -#ifdef NO_DHCP_SUPPORT - memcpy(bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */ -#else - memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */ - memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover); - memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end); -#endif /* NO_DHCP_SUPPORT */ - - for (retry = 0; retry < MAX_BOOTP_RETRIES; ) { - - /* Clear out the Rx queue first. It contains nothing of - * interest, except possibly ARP requests from the DHCP/TFTP - * server. We use polling throughout Etherboot, so some time - * may have passed since we last polled the receive queue, - * which may now be filled with broadcast packets. This will - * cause the reply to the packets we are about to send to be - * lost immediately. Not very clever. */ - await_reply(AWAIT_QDRAIN, 0, NULL, 0); - - udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, - sizeof(struct bootp_t), &bp); -#ifdef T509HACK - if (flag) { - flag--; - } else { - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) - return(1); - rfc951_sleep(++retry); - - } -#else -#ifdef NO_DHCP_SUPPORT - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) -#else - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)){ - if (dhcp_reply==DHCPOFFER){ - dhcp_reply=0; - memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); - memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest); - memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end); - memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr)); - memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr)); - for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) { - udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, - sizeof(struct bootp_t), &bp); - dhcp_reply=0; - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) - if (dhcp_reply==DHCPACK) - return(1); - rfc951_sleep(++retry1); - } - } else -#endif /* NO_DHCP_SUPPORT */ - return(1); -#ifndef NO_DHCP_SUPPORT - } - rfc951_sleep(++retry); - -#endif /* NO_DHCP_SUPPORT */ -#endif - bp.bp_secs = htons((currticks()-starttime)/20); - } - return(0); -} -#endif /* RARP_NOT_BOOTP */ - -/************************************************************************** -AWAIT_REPLY - Wait until we get a response for our request -**************************************************************************/ -int await_reply(int type, int ival, void *ptr, int timeout) -{ - unsigned long time; - struct iphdr *ip; - struct udphdr *udp; - struct arprequest *arpreply; - struct bootp_t *bootpreply; - struct rpc_t *rpc; - unsigned short ptype; - - unsigned int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) + - sizeof(struct udphdr); - time = timeout + currticks(); - /* The timeout check is done below. The timeout is only checked if - * there is no packet in the Rx queue. This assumes that eth_poll() - * needs a negligible amount of time. */ - for (;;) { - if (eth_poll()) { /* We have something! */ - /* Check for ARP - No IP hdr */ - if (nic.packetlen >= ETHER_HDR_SIZE) { - ptype = ((unsigned short) nic.packet[12]) << 8 - | ((unsigned short) nic.packet[13]); - } else continue; /* what else could we do with it? */ - if ((nic.packetlen >= ETHER_HDR_SIZE + - sizeof(struct arprequest)) && - (ptype == ARP) ) { - unsigned long tmp; - - arpreply = (struct arprequest *) - &nic.packet[ETHER_HDR_SIZE]; - if ((arpreply->opcode == ntohs(ARP_REPLY)) && - !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) && - (type == AWAIT_ARP)) { - memcpy(arptable[ival].node, arpreply->shwaddr, ETHER_ADDR_SIZE); - return(1); - } - memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); - if ((arpreply->opcode == ntohs(ARP_REQUEST)) && - (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) { - arpreply->opcode = htons(ARP_REPLY); - memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr)); - memcpy(arpreply->thwaddr, arpreply->shwaddr, ETHER_ADDR_SIZE); - memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); - memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - eth_transmit(arpreply->thwaddr, ARP, - sizeof(struct arprequest), - arpreply); -#ifdef MDEBUG - memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); - printf("Sent ARP reply to: %I\n",tmp); -#endif MDEBUG - } - continue; - } - - if (type == AWAIT_QDRAIN) { - continue; - } - - /* Check for RARP - No IP hdr */ - if ((type == AWAIT_RARP) && - (nic.packetlen >= ETHER_HDR_SIZE + - sizeof(struct arprequest)) && - (ptype == RARP)) { - arpreply = (struct arprequest *) - &nic.packet[ETHER_HDR_SIZE]; - if ((arpreply->opcode == ntohs(RARP_REPLY)) && - !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) { - memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETHER_ADDR_SIZE); - memcpy(& arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr)); - memcpy(& arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr)); - return(1); - } - continue; - } - - /* Anything else has IP header */ - if ((nic.packetlen < protohdrlen) || - (ptype != IP) ) continue; - ip = (struct iphdr *)&nic.packet[ETHER_HDR_SIZE]; - if ((ip->verhdrlen != 0x45) || - ipchksum((unsigned short *)ip, sizeof(struct iphdr)) || - (ip->protocol != IP_UDP)) continue; - udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE + - sizeof(struct iphdr)]; - - /* BOOTP ? */ - bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE]; - if ((type == AWAIT_BOOTP) && - (nic.packetlen >= (ETHER_HDR_SIZE + -#ifdef NO_DHCP_SUPPORT - sizeof(struct bootp_t))) && -#else - sizeof(struct bootp_t))-DHCP_OPT_LEN) && -#endif /* NO_DHCP_SUPPORT */ - (ntohs(udp->dest) == BOOTP_CLIENT) && - (bootpreply->bp_op == BOOTP_REPLY) && - (bootpreply->bp_xid == xid)) { - arptable[ARP_CLIENT].ipaddr.s_addr = - bootpreply->bp_yiaddr.s_addr; -#ifndef NO_DHCP_SUPPORT - dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr; -#endif /* NO_DHCP_SUPPORT */ - netmask = default_netmask(); - arptable[ARP_SERVER].ipaddr.s_addr = - bootpreply->bp_siaddr.s_addr; - memset(arptable[ARP_SERVER].node, 0, ETHER_ADDR_SIZE); /* Kill arp */ - arptable[ARP_GATEWAY].ipaddr.s_addr = - bootpreply->bp_giaddr.s_addr; - memset(arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE); /* Kill arp */ - if (bootpreply->bp_file[0]) { - memcpy(kernel_buf, bootpreply->bp_file, 128); - kernel = kernel_buf; - } - memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t)); - decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, -#ifdef NO_DHCP_SUPPORT - 0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1); -#else - 0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1); -#endif /* NO_DHCP_SUPPORT */ - return(1); - } - -#ifdef DOWNLOAD_PROTO_TFTP - /* TFTP ? */ - if ((type == AWAIT_TFTP) && - (ntohs(udp->dest) == ival)) return(1); -#endif /* DOWNLOAD_PROTO_TFTP */ - -#ifdef DOWNLOAD_PROTO_NFS - /* RPC ? */ - rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE]; - if ((type == AWAIT_RPC) && - (ntohs(udp->dest) == ival) && - (*(unsigned long *)ptr == ntohl(rpc->u.reply.id)) && - (ntohl(rpc->u.reply.type) == MSG_REPLY)) { - return (1); - } -#endif /* DOWNLOAD_PROTO_NFS */ - - } else { - /* Check for abort key only if the Rx queue is empty - - * as long as we have something to process, don't - * assume that something failed. It is unlikely that - * we have no processing time left between packets. */ - if (iskey() && (getchar() == ESC)) -#ifdef EMERGENCYDISKBOOT - exit(0); -#else - longjmp(jmp_bootmenu,1); -#endif - /* Do the timeout after at least a full queue walk. */ - if ((timeout == 0) || (currticks() > time)) { - break; - } - } - } - return(0); -} - -/************************************************************************** -DECODE_RFC1533 - Decodes RFC1533 header -**************************************************************************/ -int decode_rfc1533(p, block, len, eof) - register unsigned char *p; - int block, len, eof; -{ - static unsigned char *extdata = NULL, *extend = NULL; - unsigned char *extpath = NULL; - unsigned char *endp; - - if (block == 0) { -#ifdef IMAGE_MENU - memset(imagelist, 0, sizeof(imagelist)); - menudefault = useimagemenu = 0; - menutmo = -1; -#endif -#ifdef MOTD - memset(motd, 0, sizeof(motd)); -#endif - end_of_rfc1533 = NULL; - vendorext_isvalid = 0; - if (memcmp(p, rfc1533_cookie, 4)) - return(0); /* no RFC 1533 header found */ - p += 4; - endp = p + len; } - else { - if (block == 1) { - if (memcmp(p, rfc1533_cookie, 4)) - return(0); /* no RFC 1533 header found */ - p += 4; - len -= 4; } - if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) { - memcpy(extend, p, len); - extend += len; - } else { - printf("Overflow in vendor data buffer! Aborting...\n"); - *extdata = RFC1533_END; - return(0); - } - p = extdata; endp = extend; - } - if (eof) { - while(p < endp) { - unsigned char c = *p; - if (c == RFC1533_PAD) {p++; continue;} - else if (c == RFC1533_END) { - end_of_rfc1533 = endp = p; continue; } - else if (c == RFC1533_NETMASK) {memcpy(&netmask, p+2, sizeof(in_addr));} - - else if (c == RFC1533_GATEWAY) { - /* This is a little simplistic, but it will - usually be sufficient. - Take only the first entry */ - if (TAG_LEN(p) >= sizeof(in_addr)) - memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr)); - } - else if (c == RFC1533_EXTENSIONPATH) - extpath = p; -#ifndef NO_DHCP_SUPPORT - else if (c == RFC2132_MSG_TYPE) - { dhcp_reply=*(p+2); - } - else if (c == RFC2132_SRV_ID) - { - memcpy(&dhcp_server, p+2, sizeof(in_addr)); - } -#endif /* NO_DHCP_SUPPORT */ - else if (c == RFC1533_HOSTNAME) - { - hostname = p + 2; - hostnamelen = *(p + 1); - } - else if (c == RFC1533_VENDOR_MAGIC -#ifndef IMAGE_FREEBSD /* since FreeBSD uses tag 128 for swap definition */ - && TAG_LEN(p) >= 6 && - !memcmp(p+2,vendorext_magic,4) && - p[6] == RFC1533_VENDOR_MAJOR -#endif - ) - vendorext_isvalid++; -#ifdef IMAGE_FREEBSD - else if (c == RFC1533_VENDOR_HOWTO) { - freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5]; - } -#endif -#ifdef IMAGE_MENU - else if (c == RFC1533_VENDOR_MNUOPTS) { - parse_menuopts(p+2, TAG_LEN(p)); - } - else if (c >= RFC1533_VENDOR_IMG && - c<RFC1533_VENDOR_IMG+RFC1533_VENDOR_NUMOFIMG){ - imagelist[c - RFC1533_VENDOR_IMG] = p; - useimagemenu++; - } -#endif -#ifdef MOTD - else if (c >= RFC1533_VENDOR_MOTD && - c < RFC1533_VENDOR_MOTD + - RFC1533_VENDOR_NUMOFMOTD) - motd[c - RFC1533_VENDOR_MOTD] = p; -#endif - else { -#if 0 - unsigned char *q; - printf("Unknown RFC1533-tag "); - for(q=p;q<p+2+TAG_LEN(p);q++) - printf("%x ",*q); - putchar('\n'); -#endif - } - p += TAG_LEN(p) + 2; - } - extdata = extend = endp; - if (block == 0 && extpath != NULL) { - char fname[64]; - memcpy(fname, extpath+2, TAG_LEN(extpath)); - fname[(int)TAG_LEN(extpath)] = '\000'; - printf("Loading BOOTP-extension file: %s\n",fname); - download(fname,decode_rfc1533); - } - } - return(-1); /* proceed with next block */ -} - -/************************************************************************** -IPCHKSUM - Checksum IP Header -**************************************************************************/ -unsigned short ipchksum(ip, len) - register unsigned short *ip; - register int len; -{ - unsigned long sum = 0; - len >>= 1; - while (len--) { - sum += *(ip++); - if (sum > 0xFFFF) - sum -= 0xFFFF; - } - return((~sum) & 0x0000FFFF); -} - -/************************************************************************** -RFC951_SLEEP - sleep for expotentially longer times -**************************************************************************/ -void rfc951_sleep(exp) - int exp; -{ - static long seed = 0; - long q; - unsigned long tmo; - -#ifdef BACKOFF_LIMIT - if (exp > BACKOFF_LIMIT) - exp = BACKOFF_LIMIT; -#endif - if (!seed) /* Initialize linear congruential generator */ - seed = currticks() + *(long *)&arptable[ARP_CLIENT].node - + ((short *)arptable[ARP_CLIENT].node)[2]; - /* simplified version of the LCG given in Bruce Scheier's - "Applied Cryptography" */ - q = seed/53668; - if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563l; - /* compute mask */ - for (tmo = 63; tmo <= 60*TICKS_PER_SEC && --exp > 0; tmo = 2*tmo+1); - /* sleep */ - printf("<sleep>\n"); - - for (tmo = (tmo&seed)+currticks(); currticks() < tmo; ) - if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1); - return; -} - -/************************************************************************** -CLEANUP_NET - shut down networking -**************************************************************************/ -void cleanup_net(void) -{ -#ifdef DOWNLOAD_PROTO_NFS - nfs_umountall(ARP_SERVER); -#endif - eth_disable(); - eth_reset(); -} - -/************************************************************************** -CLEANUP - shut down etherboot so that the OS may be called right away -**************************************************************************/ -void cleanup(void) -{ -#if defined(ANSIESC) && defined(CONSOLE_CRT) - ansi_reset(); -#endif -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/contrib/baremetal/marini.txt b/contrib/baremetal/marini.txt deleted file mode 100644 index 464f1488..00000000 --- a/contrib/baremetal/marini.txt +++ /dev/null @@ -1,52 +0,0 @@ -From: "Paolo Marini" <paolom@prisma-eng.it> -Subject: Etherboot on bare metal -Date: Tue, 10 Apr 2001 23:19:19 +0200 -Organization: Prisma Engineering srl - -Hi Ken, -I have ported Etherboot on an embedded, biosless platform and would like -to contribute the code. - -Essentially, the hardware I was running Etherboot is a Pentium based -embedded system, with an Intel Chipset, *but* without serial, VGA, -keyboard etc., only an 82559 Intel (custom) Ethernet controller (I debug -it with the etheral Ethernet packet analyser and an emulator). - -What I did was: - - a.. integrate the init.s file within the firmware, with GDT -(re)initialisation (a simple and single entry point taking control of -the boot process) - b.. provide some stupid BIOS stubs in order to let the OS boot and -still belive that an INT10 call goes to the BIOS - c.. provide some basic functions to Etherboot, like timer (I used the -Pentium TSC internal counter) - d.. hardwire in the code information about the RAM size -The BIOS stubs are enough to boot Linux, pSOS and QNX with bootp. QNX is -somewhat difficult to load, because the i82559 driver tries to find the -component using the BIOS32 calls, so I had to patch it. - -what i I got from the original firmware is the PCI initialisation and -resource (I/O, interrupts, memory) allocation. - -I send you what I changed, that is, the initialisation code and the -misc.c file containing the timer, and the makefile (I don't remember -exactly the options I used to compile all). - -Of course, it is only a good starting point for anyone wanting to -implement a bootp client on a biosless platform; some integration work -still needs to be done. - -Ciao -Paolo - -And in a subsequent email: - -I worked with version 4.6.12, but the real modifications involve the -init.S file, which I think is quite sstable between releases. I forgot -to say that my entry point (symbol _start in init.s) assumes the -processor is already in protected mode. - -[The only difference between main.c and misc.c from those in Etherboot -4.6.12 seems to be the deletion of eth_reset(). This may be of use to -others trying to make these changes work on more recent releases. Ken] diff --git a/contrib/baremetal/misc.c b/contrib/baremetal/misc.c deleted file mode 100644 index 924ccd6d..00000000 --- a/contrib/baremetal/misc.c +++ /dev/null @@ -1,351 +0,0 @@ -/************************************************************************** -MISC Support Routines -**************************************************************************/ - -#include "etherboot.h" - -/************************************************************************** -SLEEP -**************************************************************************/ -void sleep(int secs) -{ - unsigned long tmo; - - for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; ) - /* Nothing */; -} - -/************************************************************************** -TWIDDLE -**************************************************************************/ -void twiddle() -{ - static unsigned long lastticks = 0; - static int count=0; - static const char tiddles[]="-\\|/"; - unsigned long ticks; - if ((ticks = currticks()) == lastticks) - return; - lastticks = ticks; - putchar(tiddles[(count++)&3]); - putchar('\b'); -} - -/************************************************************************** -STRCASECMP (not entirely correct, but this will do for our purposes) -**************************************************************************/ -int strcasecmp(a,b) - char *a, *b; -{ - while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; } - return((*a & ~0x20) - (*b & ~0x20)); -} - -/************************************************************************** -PRINTF and friends - - Formats: - %[#]X - 4 bytes long (8 hex digits) - %[#]x - 2 bytes int (4 hex digits) - - optional # prefixes 0x - %b - 1 byte int (2 hex digits) - %d - decimal int - %c - char - %s - string - %I - Internet address in x.x.x.x notation - Note: width specification not supported -**************************************************************************/ -static char *do_printf(char *buf, const char *fmt, const int *dp) -{ - register char *p; - int alt; - char tmp[16]; - static const char hex[]="0123456789ABCDEF"; - - while (*fmt) { - if (*fmt == '%') { /* switch() uses more space */ - alt = 0; - fmt++; - if (*fmt == '#') { - alt = 1; - fmt++; - } - if (*fmt == 'X') { - const long *lp = (const long *)dp; - register long h = *lp++; - dp = (const int *)lp; - if (alt) { - *buf++ = '0'; - *buf++ = 'x'; - } - *(buf++) = hex[(h>>28)& 0x0F]; - *(buf++) = hex[(h>>24)& 0x0F]; - *(buf++) = hex[(h>>20)& 0x0F]; - *(buf++) = hex[(h>>16)& 0x0F]; - *(buf++) = hex[(h>>12)& 0x0F]; - *(buf++) = hex[(h>>8)& 0x0F]; - *(buf++) = hex[(h>>4)& 0x0F]; - *(buf++) = hex[h& 0x0F]; - } - if (*fmt == 'x') { - register int h = *(dp++); - if (alt) { - *buf++ = '0'; - *buf++ = 'x'; - } - *(buf++) = hex[(h>>12)& 0x0F]; - *(buf++) = hex[(h>>8)& 0x0F]; - *(buf++) = hex[(h>>4)& 0x0F]; - *(buf++) = hex[h& 0x0F]; - } - if (*fmt == 'b') { - register int h = *(dp++); - *(buf++) = hex[(h>>4)& 0x0F]; - *(buf++) = hex[h& 0x0F]; - } - if (*fmt == 'd') { - register int dec = *(dp++); - p = tmp; - if (dec < 0) { - *(buf++) = '-'; - dec = -dec; - } - do { - *(p++) = '0' + (dec%10); - dec = dec/10; - } while(dec); - while ((--p) >= tmp) *(buf++) = *p; - } - if (*fmt == 'I') { - union { - long l; - unsigned char c[4]; - } u; - const long *lp = (const long *)dp; - u.l = *lp++; - dp = (const int *)lp; - buf = sprintf(buf,"%d.%d.%d.%d", - u.c[0], u.c[1], u.c[2], u.c[3]); - } - if (*fmt == 'c') - *(buf++) = *(dp++); - if (*fmt == 's') { - p = (char *)*dp++; - while (*p) *(buf++) = *p++; - } - } else *(buf++) = *fmt; - fmt++; - } - *buf = '\0'; - return(buf); -} - -char *sprintf(char *buf, const char *fmt, ...) -{ - return do_printf(buf, fmt, ((const int *)&fmt)+1); -} - -void printf(const char *fmt, ...) -{ - char buf[120], *p; - - p = buf; - do_printf(buf, fmt, ((const int *)&fmt)+1); - while (*p) putchar(*p++); -} - -#ifdef IMAGE_MENU -/************************************************************************** -INET_ATON - Convert an ascii x.x.x.x to binary form -**************************************************************************/ -int inet_aton(char *p, in_addr *i) -{ - unsigned long ip = 0; - int val; - if (((val = getdec(&p)) < 0) || (val > 255)) return(0); - if (*p != '.') return(0); - p++; - ip = val; - if (((val = getdec(&p)) < 0) || (val > 255)) return(0); - if (*p != '.') return(0); - p++; - ip = (ip << 8) | val; - if (((val = getdec(&p)) < 0) || (val > 255)) return(0); - if (*p != '.') return(0); - p++; - ip = (ip << 8) | val; - if (((val = getdec(&p)) < 0) || (val > 255)) return(0); - i->s_addr = htonl((ip << 8) | val); - return(1); -} - -#endif /* IMAGE_MENU */ - -int getdec(char **ptr) -{ - char *p = *ptr; - int ret=0; - if ((*p < '0') || (*p > '9')) return(-1); - while ((*p >= '0') && (*p <= '9')) { - ret = ret*10 + (*p - '0'); - p++; - } - *ptr = p; - return(ret); -} - -#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 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 */ -#ifndef IBM_L40 -static void empty_8042(void) -{ - unsigned long time; - char st; - - time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */ - while ((((st = inb(K_CMD)) & K_OBUF_FUL) || - (st & K_IBUF_FUL)) && - currticks() < time) - inb(K_RDWR); -} -#endif IBM_L40 - -/* - * Gate A20 for high memory - */ -void gateA20_set(void) -{ -#ifdef IBM_L40 - outb(0x2, 0x92); -#else /* IBM_L40 */ - empty_8042(); - outb(KC_CMD_WOUT, K_CMD); - empty_8042(); - outb(KB_SET_A20, K_RDWR); - empty_8042(); -#endif /* IBM_L40 */ -} - -#ifdef TAGGED_IMAGE -/* - * Unset Gate A20 for high memory - some operating systems (mainly old 16 bit - * ones) don't expect it to be set by the boot loader. - */ -void gateA20_unset(void) -{ -#ifdef IBM_L40 - outb(0x0, 0x92); -#else /* IBM_L40 */ - empty_8042(); - outb(KC_CMD_WOUT, K_CMD); - empty_8042(); - outb(KB_UNSET_A20, K_RDWR); - empty_8042(); -#endif /* IBM_L40 */ -} -#endif - -#ifdef ETHERBOOT32 -/* Serial console is only implemented in ETHERBOOT32 for now */ -void -putchar(int c) -{ -#ifndef ANSIESC - if (c == '\n') - putchar('\r'); -#endif - -#ifdef CONSOLE_CRT -#ifdef ANSIESC - handleansi(c); -#else - putc(c); -#endif -#endif -#ifdef CONSOLE_SERIAL -#ifdef ANSIESC - if (c == '\n') - serial_putc('\r'); -#endif - serial_putc(c); -#endif -} - -/************************************************************************** -GETCHAR - Read the next character from the console WITHOUT ECHO -**************************************************************************/ -int -getchar(void) -{ - int c = 256; - -#if defined CONSOLE_CRT || defined CONSOLE_SERIAL - do { -#ifdef CONSOLE_CRT - if (ischar()) - c = getc(); -#endif -#ifdef CONSOLE_SERIAL - if (serial_ischar()) - c = serial_getc(); -#endif - } while (c==256); - if (c == '\r') - c = '\n'; -#endif - return c; -} - -int -iskey(void) -{ -#ifdef CONSOLE_CRT - if (ischar()) - return 1; -#endif -#ifdef CONSOLE_SERIAL - if (serial_ischar()) - return 1; -#endif - return 0; -} -#endif /* ETHERBOOT32 */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ - -#include <asm/msr.h> - -#define CPUCLOCK 166 - -unsigned long currticks(void) -{ - register unsigned long l, h; - long long unsigned p; - long long unsigned hh,ll; - - rdtsc(l, h); - ll = l, hh = h; - - p = (ll + hh * 0x100000000LL) * 182 / (CPUCLOCK * 100000LL); - return (unsigned)p; -} - diff --git a/contrib/baremetal/startmpcc.S b/contrib/baremetal/startmpcc.S deleted file mode 100644 index 07486ce5..00000000 --- a/contrib/baremetal/startmpcc.S +++ /dev/null @@ -1,756 +0,0 @@ -/* #defines because ljmp wants a number, probably gas bug */ -/* .equ KERN_CODE_SEG,_pmcs-_gdt */ -#define KERN_CODE_SEG 0x08 - .equ KERN_DATA_SEG,_pmds-_gdt -/* .equ REAL_CODE_SEG,_rmcs-_gdt */ -#define REAL_CODE_SEG 0x18 - .equ REAL_DATA_SEG,_rmds-_gdt - .equ CR0_PE,1 - -#ifdef GAS291 -#define DATA32 data32; -#define ADDR32 addr32; -#define LJMPI(x) ljmp x -#else -#define DATA32 data32 -#define ADDR32 addr32 -/* newer GAS295 require #define LJMPI(x) ljmp *x */ -#define LJMPI(x) ljmp x -#endif - -#define PIC1_VBS 0x08 /* PIC1 interrupts start at vector 64 */ -#define PIC2_VBS 0x70 /* PIC1 interrupts start at vector 112 */ - -/* - * NOTE: if you write a subroutine that is called from C code (gcc/egcs), - * then you only have to take care of %ebx, %esi, %edi and %ebp. These - * registers must not be altered under any circumstance. All other registers - * may be clobbered without any negative side effects. If you don't follow - * this rule then you'll run into strange effects that only occur on some - * gcc versions (because the register allocator may use different registers). - * - * All the data32 prefixes for the ljmp instructions are necessary, because - * the assembler emits code with a relocation address of 0. This means that - * all destinations are initially negative, which the assembler doesn't grok, - * because for some reason negative numbers don't fit into 16 bits. The addr32 - * prefixes are there for the same reasons, because otherwise the memory - * references are only 16 bit wide. Theoretically they are all superfluous. - * One last note about prefixes: the data32 prefixes on all call _real_to_prot - * instructions could be removed if the _real_to_prot function is changed to - * deal correctly with 16 bit return addresses. I tried it, but failed. - */ - -/************************************************************************** -START - Where all the fun begins.... -**************************************************************************/ -/* this must be the first thing in the file because we enter from the top */ - .global _start - .code32 -_start: - cli - - /* load new IDT and GDT */ - lgdt gdtarg - lidt Idt_Reg - /* flush prefetch queue, and reload %cs:%eip */ - ljmp $KERN_CODE_SEG,$1f -1: - - /* reload other segment registers */ - movl $KERN_DATA_SEG,%eax - movl %eax,%ds - movl %eax,%es - movl %eax,%ss - movl $stktop,%esp - - /* program the PITs in order to stop them */ - mov $0x30,%al - out %al,$0x43 - out %al,$0x40 - mov $0x70,%al - out %al,$0x43 - out %al,$0x41 - mov $0xf0,%al - out %al,$0x43 - out %al,$0x42 - - call main - /* fall through */ - - .globl exit -exit: -2: - ljmp $KERN_CODE_SEG,$2b - -/************************************************************************** -MEMSIZE - Determine size of extended memory -**************************************************************************/ - .globl memsize -memsize: -#if 0 - pushl %ebx - pushl %esi - pushl %edi - call _prot_to_real - .code16 - movw $0xe801,%ax - stc - int $0x15 - jc 1f - andl $0xffff,%eax - andl $0xffff,%ebx - shll $6,%ebx - addl %ebx,%eax - jmp 2f -1: - movw $0x8800,%ax - int $0x15 - andl $0xffff,%eax -2: - movl %eax,%esi - DATA32 call _real_to_prot - .code32 - movl %esi,%eax - popl %edi - popl %esi - popl %ebx -#else - mov $32768,%eax -#endif - ret - -/************************************************************************** -XSTART - Transfer control to the kernel just loaded -**************************************************************************/ - .code16 - - .globl _int08_handler -_int08_handler: - movb $0x20, %al - outb %al, $0x20 - iret - - .globl _int10_handler -_int10_handler: - cmp $0x3, %ah - jnz _int10_04 - mov $0x0, %dx - mov $0x0, %cx - iret -_int10_04: - cmp $0x4, %ah - jnz _int10_05 - mov $0x0, %ah - iret -_int10_05: - cmp $0x5, %ah - jnz _int10_08 - mov $0x0, %al - iret -_int10_08: - cmp $0x8, %ah - jnz _int10_0D - mov $0x20, %al - mov $0x7, %ah - iret -_int10_0D: - cmp $0xD, %ah - jnz _int10_0F - mov $0x0, %al - iret -_int10_0F: - cmp $0xF, %ah - jnz _int10_XX - mov $0xb, %al - mov $80, %ah - mov $0, %bh -_int10_XX: - iret - - .globl _int11_handler -_int11_handler: - mov $0x22, %ax - iret - - .globl _int12_handler -_int12_handler: - mov $640, %ax - iret - - .globl _int13_handler -_int13_handler: - clc - mov $0, %ah - iret - - .globl _int14_handler -_int14_handler: - iret - - .globl _int15_handler -_int15_handler: - cmp $0xe801,%ax - jz _int15_008 - cmp $0x0, %ah - jz _int15_000 - cmp $0x1, %ah - jz _int15_000 - cmp $0x2, %ah - jz _int15_000 - cmp $0x3, %ah - jz _int15_000 - cmp $0xf, %ah - jz _int15_000 - cmp $0x21, %ah - jz _int15_000 - cmp $0x40, %ah - jz _int15_000 - cmp $0x41, %ah - jz _int15_000 - cmp $0x42, %ah - jz _int15_000 - cmp $0x43, %ah - jz _int15_000 - cmp $0x44, %ah - jz _int15_000 - cmp $0x80, %ah - jz _int15_001 - cmp $0x81, %ah - jz _int15_001 - cmp $0x82, %ah - jz _int15_002 - cmp $0x83, %ah - jz _int15_003 - cmp $0x84, %ah - jz _int15_000 - cmp $0x85, %ah - jz _int15_004 - cmp $0x86, %ah - jz _int15_003 - cmp $0x87, %ah - jz _int15_005 - cmp $0x88, %ah - jz _int15_006 - cmp $0x89, %ah - jz _int15_005 - cmp $0x90, %ah - jz _int15_007 - cmp $0xc0, %ah - jz _int15_000 - cmp $0xc1, %ah - jz _int15_000 - cmp $0xc2, %ah - jz _int15_000 - cmp $0xc3, %ah - jz _int15_000 - cmp $0xc4, %ah - jz _int15_000 - iret - -_int15_000: - mov $0x86, %ah - stc - iret - -_int15_001: - mov $0, %bx - mov $0, %cx - iret - -_int15_002: - mov $0, %bx - iret - -_int15_003: - clc - iret - -_int15_004: - mov $0, %al - iret - -_int15_005: - mov $0, %ah - clc - cmp $0, %ah - iret - -_int15_006: - mov $0xf000, %ax - iret - -_int15_007: - stc - iret - -_int15_008: - clc - mov $1024, %dx /* dx -> extended memory size (in 64K chuncks) */ - mov $640, %cx /* cx -> conventional memory size (in 1 Kbytes chuncks) */ - iret - - .globl _int16_handler -_int16_handler: - cmp $0x0, %ah - jnz _int16_01 - mov $0x20, %al - mov $0x39, %ah - iret -_int16_01: - cmp $0x1, %ah - jnz _int16_02 - iret -_int16_02: - cmp $0x2, %ah - jnz _int16_05 - mov $0, %al - iret -_int16_05: - cmp $0x5, %ah - jnz _int16_10 - mov $0, %al - iret -_int16_10: - cmp $0x10, %ah - jnz _int16_11 - mov $0x20, %al - mov $0x39, %ah - iret -_int16_11: - cmp $0x11, %ah - jnz _int16_12 - iret -_int16_12: - cmp $0x12, %ah - jnz _int16_XX - mov $0, %ax - iret -_int16_XX: - iret - - .globl _int17_handler -_int17_handler: - mov $0xd0, %ah - iret - - .globl _int19_handler -_int19_handler: - hlt - iret - - .globl _int1A_handler -_int1A_handler: - stc - iret - - .code32 - .globl xstart -xstart: - /* reprogram the PICs so that interrupt are masked */ - movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/ - outb %al,$0x20 - movb $PIC1_VBS, %al - outb %al,$0x21 - movb $0x4,%al - outb %al,$0x21 - movb $0x1,%al - outb %al,$0x21 - movb $0xff,%al - outb %al,$0x21 - - movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/ - outb %al,$0xa0 - movb $PIC2_VBS, %al - outb %al,$0xa1 - movb $0x2,%al - outb %al,$0xa1 - movb $0x1,%al - outb %al,$0xa1 - movb $0xff,%al - outb %al,$0xa1 - - pushl %ebp - movl %esp,%ebp - pushl %ebx - pushl %esi - pushl %edi - movl 8(%ebp),%eax - movl %eax,_execaddr - movl 12(%ebp),%ebx - movl 16(%ebp),%ecx /* bootp record (32bit pointer) */ - addl $28,%ecx /* ip, udp header */ - shll $12,%ecx - shrw $12,%cx - call _prot_to_real - .code16 -/* MP: add int10 handler */ - push %eax - push %ebx - push %es - mov $0,%ax - mov %ax,%es - mov %cs,%ax - shl $16,%eax - - ADDR32 mov $(_int08_handler-_start),%ax - mov $0x20,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int10_handler-_start),%ax - mov $0x40,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int11_handler-_start),%ax - mov $0x44,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int12_handler-_start),%ax - mov $0x48,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int13_handler-_start),%ax - mov $0x4c,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int14_handler-_start),%ax - mov $0x50,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int15_handler-_start),%ax - mov $0x54,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int16_handler-_start),%ax - mov $0x58,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int17_handler-_start),%ax - mov $0x5c,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int19_handler-_start),%ax - mov $0x64,%ebx - mov %eax,%es:(%bx) - - ADDR32 mov $(_int1A_handler-_start),%ax - mov $0x68,%ebx - mov %eax,%es:(%bx) - - pop %es - pop %ebx - pop %eax -/* */ - pushl %ecx /* bootp record */ - pushl %ebx /* file header */ - movl $((RELOC<<12)+(1f-RELOC)),%eax - pushl %eax - ADDR32 LJMPI(_execaddr-_start) -1: - addw $8,%sp /* XXX or is this 10 in case of a 16bit "ret" */ - DATA32 call _real_to_prot - .code32 - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - -_execaddr: - .long 0 - -#ifdef IMAGE_MULTIBOOT -/************************************************************************** -XEND - Restart Etherboot from the beginning (from protected mode) -**************************************************************************/ - - .globl xend -xend: - cs - lidt idtarg_realmode-_start+RELOC - cs - lgdt gdtarg-_start+RELOC -#ifdef GAS291 - ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */ -#else - ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */ -#endif /* GAS291 */ -1: - .code16 - movw $REAL_DATA_SEG,%ax - movw %ax,%ds - movw %ax,%ss - movw %ax,%es - - /* clear the PE bit of CR0 */ - movl %cr0,%eax - andl $0!CR0_PE,%eax - movl %eax,%cr0 - - /* make intersegment jmp to flush the processor pipeline - * and reload %cs:%eip (to clear upper 16 bits of %eip). - */ - DATA32 ljmp $(RELOC)>>4,$2f-_start -2: - /* we are in real mode now - * set up the real mode segment registers : %ds, %ss, %es - */ - movw %cs,%ax - movw %ax,%ds - movw %ax,%es - movw %ax,%ss - xorl %esp,%esp - ADDR32 movw initsp-RELOC,%sp - - movw $0,%ax - movw %ax,%fs - movw %ax,%gs - - sti - jmp _start - - .code32 -#endif /* IMAGE_MULTIBOOT */ - -.global get_cs -get_cs: - xorl %eax,%eax - movw %cs,%ax - ret - -.global get_ds -get_ds: - xorl %eax,%eax - movw %ds,%ax - ret - -.global getsp -getsp: - movl %esp,%eax /* GET STACK POINTER */ - subl $4, %eax /* ACCOUNT FOR RETURN ADDRESS ON */ - ret - -.global get_gdtbase -get_gdtbase: - sub $8,%esp /* ALLOCATE ROOM ON THE STACK */ - sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */ - mov 2(%esp),%eax /* READ GDT BASE ADDRESS */ - mov $KERN_DATA_SEG,%dx /* ASSUME UNIVERSAL DS. */ - add $8,%esp /* RESTORE STACK */ - ret /* DONE */ - -.global get_gdtsize -get_gdtsize: - sub $8,%esp /* ALLOCATE ROOM ON THE STACK */ - sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */ - xor %eax,%eax - mov 2(%esp),%eax /* READ GDT BASE ADDRESS */ - mov (%ESP),%ax - shr $3,%ax - add $8,%esp /* RESTORE STACK */ - ret /* DONE */ - -.global get_idtbase -get_idtbase: - sub $8,%esp - sidt (%esp,1) /* STORE IIDT REGISTER ON STACK */ - mov 2(%esp),%eax - mov $KERN_DATA_SEG,%dx - add $8,%esp - ret - -.global get_lw -get_lw: - xor %edx,%edx - mov 8(%esp),%eax - mov 4(%esp),%dx - ret - -/************************************************************************** -SETJMP - Save stack context for non-local goto -**************************************************************************/ - .globl setjmp -setjmp: - mov 4(%esp),%ecx - mov 0(%esp),%edx - mov %edx,0(%ecx) - mov %ebx,4(%ecx) - mov %esp,8(%ecx) - mov %ebp,12(%ecx) - mov %esi,16(%ecx) - mov %edi,20(%ecx) - mov %eax,24(%ecx) - mov $0,%eax - ret - -/************************************************************************** -LONGJMP - Non-local jump to a saved stack context -**************************************************************************/ - .globl longjmp -longjmp: - mov 4(%esp),%edx - mov 8(%esp),%eax - mov 0(%edx),%ecx - mov 4(%edx),%ebx - mov 8(%edx),%esp - mov 12(%edx),%ebp - mov 16(%edx),%esi - mov 20(%edx),%edi - cmp $0,%eax - jne 1f - mov $1,%eax -1: mov %ecx,0(%esp) - ret - -/************************************************************************** -_REAL_TO_PROT - Go from REAL mode to Protected Mode -**************************************************************************/ - .globl _real_to_prot -_real_to_prot: - .code16 - cli - cs - ADDR32 lgdt gdtarg-_start - movl %cr0,%eax - orl $CR0_PE,%eax - movl %eax,%cr0 /* turn on protected mode */ - - /* flush prefetch queue, and reload %cs:%eip */ - DATA32 ljmp $KERN_CODE_SEG,$1f -1: - .code32 - /* reload other segment registers */ - movl $KERN_DATA_SEG,%eax - movl %eax,%ds - movl %eax,%es - movl %eax,%ss - addl $RELOC,%esp /* Fix up stack pointer */ - xorl %eax,%eax - movl %eax,%fs - movl %eax,%gs - popl %eax /* Fix up return address */ - addl $RELOC,%eax - pushl %eax - ret - -/************************************************************************** -_PROT_TO_REAL - Go from Protected Mode to REAL Mode -**************************************************************************/ - .globl _prot_to_real -_prot_to_real: - .code32 - popl %eax - subl $RELOC,%eax /* Adjust return address */ - pushl %eax - subl $RELOC,%esp /* Adjust stack pointer */ -#ifdef GAS291 - ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */ -#else - ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */ -#endif /* GAS291 */ -1: - .code16 - movw $REAL_DATA_SEG,%ax - movw %ax,%ds - movw %ax,%ss - movw %ax,%es - movw %ax,%fs - movw %ax,%gs - cli - - /* clear the PE bit of CR0 */ - movl %cr0,%eax - andl $0!CR0_PE,%eax - movl %eax,%cr0 - - /* make intersegment jmp to flush the processor pipeline - * and reload %cs:%eip (to clear upper 16 bits of %eip). - */ - DATA32 ljmp $(RELOC)>>4,$2f-_start -2: - /* we are in real mode now - * set up the real mode segment registers : %ds, $ss, %es - */ - movw %cs,%ax - movw %ax,%ds - movw %ax,%es - movw %ax,%ss -#if 0 - sti -#endif - DATA32 ret /* There is a 32 bit return address on the stack */ - .code32 - -/************************************************************************** -GLOBAL DESCRIPTOR TABLE -**************************************************************************/ - .align 4 -Idt_Reg: - .word 0x3ff - .long 0 - - .align 4 -_gdt: -gdtarg: -Gdt_Table: - .word 0x27 /* limit */ - .long _gdt /* addr */ - .word 0 -_pmcs: - /* 32 bit protected mode code segment */ - .word 0xffff,0 - .byte 0,0x9f,0xcf,0 - -_pmds: - /* 32 bit protected mode data segment */ - .word 0xffff,0 - .byte 0,0x93,0xcf,0 - -_rmcs: - /* 16 bit real mode code segment */ - .word 0xffff,(RELOC&0xffff) - .byte (RELOC>>16),0x9b,0x00,(RELOC>>24) - -_rmds: - /* 16 bit real mode data segment */ - .word 0xffff,(RELOC&0xffff) - .byte (RELOC>>16),0x93,0x00,(RELOC>>24) - - .align 4 -RUN_GDT: /* POINTER TO GDT IN RAM */ - .byte 0x7f,0 /* [BSP_GDT_NUM*8]-1 */ - .long Gdt_Table - - .align 4 - - .section ".rodata" -err_not386: - .ascii "Etherboot/32 requires 386+" - .byte 0x0d, 0x0a -err_not386_end: - -days: .long 0 -irq_num: .long - - .data - .align 4 - .org 2048 -.global stktop -stktop: - .long - -.section ".armando" -/* 1:::::::::2:::::::::3:::::::3 */ -/* 12345678901234567890123456789012345678 */ -/* v----+----v----+----v----+----v----+--- */ - -.global EtherbootString -EtherbootString: -.ascii "EtherBoot MPCC " /* fw identifier */ - -.byte 0, 0 /* mandatory hole */ - -.long _start /* entry point */ -.word 0 -.byte 'E' /* type */ -.byte 0 /* selector */ -.word 0 /* CRC */ |