mirror of
https://github.com/ipxe/ipxe
synced 2025-12-10 13:32:20 +03:00
Initial revision
This commit is contained in:
475
contrib/baremetal/Makefile
Normal file
475
contrib/baremetal/Makefile
Normal file
@@ -0,0 +1,475 @@
|
||||
#
|
||||
# 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)
|
||||
1119
contrib/baremetal/main.c
Normal file
1119
contrib/baremetal/main.c
Normal file
File diff suppressed because it is too large
Load Diff
52
contrib/baremetal/marini.txt
Normal file
52
contrib/baremetal/marini.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
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]
|
||||
351
contrib/baremetal/misc.c
Normal file
351
contrib/baremetal/misc.c
Normal file
@@ -0,0 +1,351 @@
|
||||
/**************************************************************************
|
||||
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;
|
||||
}
|
||||
|
||||
756
contrib/baremetal/startmpcc.S
Normal file
756
contrib/baremetal/startmpcc.S
Normal file
@@ -0,0 +1,756 @@
|
||||
/* #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"
|
||||
/* <20> <20> <20> <20> <20> <20> <20> <20>1:::::::::2:::::::::3:::::::3 */
|
||||
/* <20> <20> <20> <20>12345678901234567890123456789012345678 */
|
||||
/* <20> <20> <20> 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 */
|
||||
Reference in New Issue
Block a user