]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
Merged mcb30-realmode-redesign back to HEAD
authorMichael Brown <mcb30@etherboot.org>
Fri, 8 Apr 2005 15:01:17 +0000 (15:01 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 8 Apr 2005 15:01:17 +0000 (15:01 +0000)
100 files changed:
src/.cvsignore
src/Config
src/Families [deleted file]
src/Makefile
src/Makefile-armnommu [deleted file]
src/Makefile-e1 [deleted file]
src/Makefile-i386 [deleted file]
src/Makefile-ia64 [deleted file]
src/Makefile.housekeeping [new file with mode: 0644]
src/Makefile.main [deleted file]
src/arch/armnommu/core/arm_timer.c
src/arch/e1/core/e1_timer.c
src/arch/i386/Config
src/arch/i386/Makefile
src/arch/i386/README.i386 [new file with mode: 0644]
src/arch/i386/core/callbacks.c
src/arch/i386/core/cpu.c
src/arch/i386/core/elf.c
src/arch/i386/core/hooks.c
src/arch/i386/core/i386_timer.c
src/arch/i386/core/init.S [deleted file]
src/arch/i386/core/pxe_callbacks.c
src/arch/i386/core/realmode.c
src/arch/i386/core/realmode_asm.S
src/arch/i386/core/setjmp.S [new file with mode: 0644]
src/arch/i386/core/setup.S [new file with mode: 0644]
src/arch/i386/core/start16.S [deleted file]
src/arch/i386/core/start32.S
src/arch/i386/core/tagged_loader.c
src/arch/i386/core/video_subr.c
src/arch/i386/core/virtaddr.S [new file with mode: 0644]
src/arch/i386/drivers/net/undi.c
src/arch/i386/firmware/pcbios/bios.c
src/arch/i386/firmware/pcbios/bios_console.c [new file with mode: 0644]
src/arch/i386/firmware/pcbios/console.c [deleted file]
src/arch/i386/firmware/pcbios/gateA20.c [new file with mode: 0644]
src/arch/i386/firmware/pcbios/memsizes.c
src/arch/i386/include/bios.h [new file with mode: 0644]
src/arch/i386/include/bochs.h [new file with mode: 0644]
src/arch/i386/include/hidemem.h
src/arch/i386/include/hooks.h
src/arch/i386/include/io.h
src/arch/i386/include/kir.h [new file with mode: 0644]
src/arch/i386/include/libkir.h [new file with mode: 0644]
src/arch/i386/include/librm.h [new file with mode: 0644]
src/arch/i386/include/memsizes.h [new file with mode: 0644]
src/arch/i386/include/pic8259.h
src/arch/i386/include/pxe_callbacks.h
src/arch/i386/include/pxe_types.h
src/arch/i386/include/realmode.h
src/arch/i386/include/registers.h [new file with mode: 0644]
src/arch/i386/include/segoff.h [deleted file]
src/arch/i386/include/virtaddr.h [new file with mode: 0644]
src/arch/i386/kir-Makefile [new file with mode: 0644]
src/arch/i386/prefix/dskprefix.S [moved from src/arch/i386/prefix/floppyprefix.S with 88% similarity]
src/arch/i386/prefix/int19exit.c [new file with mode: 0644]
src/arch/i386/prefix/unnrv2b.S
src/arch/i386/scripts/i386.lds [new file with mode: 0644]
src/arch/i386/transitions/libkir.S [new file with mode: 0644]
src/arch/i386/transitions/libpm.S [new file with mode: 0644]
src/arch/i386/transitions/librm.S [new file with mode: 0644]
src/arch/i386/transitions/librm_mgmt.c [new file with mode: 0644]
src/arch/ia64/core/ia64_timer.c
src/bin/.cvsignore [new file with mode: 0644]
src/core/btext.c
src/core/config.c
src/core/console.c [new file with mode: 0644]
src/core/heap.c
src/core/init.c [new file with mode: 0644]
src/core/main.c
src/core/misc.c
src/core/osloader.c
src/core/pc_kbd.c
src/core/pcmcia.c
src/core/pxe_export.c
src/core/relocate.c
src/core/serial.c
src/drivers/disk/ide_disk.c
src/drivers/net/3c509.c
src/drivers/net/3c515.c
src/drivers/net/cs89x0.c
src/drivers/net/depca.c
src/drivers/net/eepro.c
src/drivers/net/ns83820.c
src/drivers/net/ns8390.c
src/drivers/net/prism2_pci.c
src/drivers/net/sk_g16.c
src/drivers/net/smc9000.c
src/genrules.pl [deleted file]
src/include/btext.h
src/include/compiler.h [new file with mode: 0644]
src/include/console.h [new file with mode: 0644]
src/include/etherboot.h
src/include/init.h [new file with mode: 0644]
src/include/main.h [new file with mode: 0644]
src/include/osdep.h
src/include/stddef.h [new file with mode: 0644]
src/include/timer.h
src/util/parserom.pl [new file with mode: 0644]
src/util/zfilelen.pl [deleted file]

index 2e0d941a6dc6f4f848ca44310c94037a2a89f498..ef29930b6c1fac7297adb27f40f786dca7896321 100644 (file)
@@ -1,2 +1,3 @@
-bin
-gcccheck
+.toolcheck
+TAGS*
+bin*
index 7be549b1ab7c1e847530d8367ddd5a51c4ae563c..b1c72a05f803ea6fe40a16b3940f0cc705e622b2 100644 (file)
@@ -424,27 +424,134 @@ CFLAGS+= -DPXE_IMAGE -DPXE_EXPORT
 # but this is here for archs that don't support relocation
 # CFLAGS+=     -DNORELOCATE
 
-# you should normally not need to change these
-HOST_CC=       gcc
-CPP=           gcc -E -Wp,-Wall
-RM=            rm -f
-TOUCH=         touch
-PERL=          /usr/bin/perl
-CC=            gcc
-AS=            as
-LD=            ld
-SIZE=          size
-AR=            ar
-RANLIB=                ranlib
-OBJCOPY=       objcopy
-
-CFLAGS+=       -Os -ffreestanding
-CFLAGS+=       -Wall -W -Wno-format
-CFLAGS+=       $(EXTRA_CFLAGS)
-ASFLAGS+=      $(EXTRA_ASFLAGS)
-LDFLAGS+=      $(EXTRA_LDFLAGS)
-# For debugging
-# LDFLAGS+=    -Map $@.map
-
-# Location to place generated binaries, and files
-BIN=bin
+
+
+
+# Garbage from Makefile.main temporarily placed here until a home can
+# be found for it.
+
+# 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
+#      -DWD_790_PIO    - Read/write to WD/SMC 790 cards in PIO mode (default
+#                        is to use shared memory) Try this if you get "Bogus
+#                        packet, ignoring" messages, common on ISA/PCI hybrid
+#                        systems.
+#      -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
+#
+#      Warning Warning Warning
+#      If you use any of the XCVR options below, please do not complain about
+#      the behaviour with Linux drivers to the kernel developers. You are
+#      on your own if you do this. Please read 3c90x.txt to understand
+#      what they do. If you don't understand them, ask for help on the
+#      Etherboot mailing list. And please document what you did to the NIC
+#      on the NIC so that people after you won't get nasty surprises.
+#
+#      -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
+#
+# RTL8139 options:
+#      -DINCLUDE_RTL8139 - Include RTL8139 support
+#
+# SIS900 options:
+#      -DINCLUDE_SIS900 - Include SIS900 support
+#
+# NATSEMI options:
+#      -DINCLUDE_NATSEMI - Include NATSEMI support
+#
+
+CFLAGS_3c503   = -DINCLUDE_3C503 # -DT503_SHMEM
+MAKEROM_FLAGS_3c503=   -3
+CFLAGS_3c507   = -DINCLUDE_3C507
+CFLAGS_3c509   = -DINCLUDE_3C509
+CFLAGS_3c529   = -DINCLUDE_3C529
+CFLAGS_3c595   = -DINCLUDE_3C595
+CFLAGS_3c90x   = -DINCLUDE_3C90X
+CFLAGS_cs89x0  = -DINCLUDE_CS89X0
+CFLAGS_eepro   = -DINCLUDE_EEPRO
+CFLAGS_eepro100        = -DINCLUDE_EEPRO100
+CFLAGS_e1000   = -DINCLUDE_E1000
+CFLAGS_epic100 = -DINCLUDE_EPIC100
+CFLAGS_exos205 = -DINCLUDE_EXOS205
+CFLAGS_lance   = -DINCLUDE_LANCE               # Lance/PCI!
+CFLAGS_ne2100  = -DINCLUDE_NE2100
+CFLAGS_ne      = -DINCLUDE_NE -DNE_SCAN=0x300,0x280,0x320,0x340,0x380
+CFLAGS_ns8390  = -DINCLUDE_NS8390      # NE2000/PCI!
+CFLAGS_ni5010  = -DINCLUDE_NI5010
+CFLAGS_ni5210  = -DINCLUDE_NI5210
+CFLAGS_ni6510  = -DINCLUDE_NI6510
+CFLAGS_rtl8139 = -DINCLUDE_RTL8139
+CFLAGS_sk_g16  = -DINCLUDE_SK_G16
+CFLAGS_sis900   = -DINCLUDE_SIS900
+CFLAGS_natsemi  = -DINCLUDE_NATSEMI
+CFLAGS_smc9000  = -DINCLUDE_SMC9000
+CFLAGS_sundance        = -DINCLUDE_SUNDANCE
+CFLAGS_tlan    = -DINCLUDE_TLAN
+CFLAGS_tiara   = -DINCLUDE_TIARA
+CFLAGS_depca   = -DINCLUDE_DEPCA       
+# CFLAGS_depca += -DDEPCA_MODEL=DEPCA -DDEPCA_RAM_BASE=0xd0000
+CFLAGS_tulip   = -DINCLUDE_TULIP
+CFLAGS_otulip  = -DINCLUDE_OTULIP
+CFLAGS_via_rhine = -DINCLUDE_VIA_RHINE
+CFLAGS_wd      = -DINCLUDE_WD -DWD_DEFAULT_MEM=0xCC000
+CFLAGS_w89c840 = -DINCLUDE_W89C840
diff --git a/src/Families b/src/Families
deleted file mode 100644 (file)
index 8a2af71..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-# This is the config file for creating Makefile rules for Etherboot ROMs
-#
-# To make a ROM for a supported NIC locate the appropriate family
-# and add a line of the form
-#
-# ROM          PCI-IDs         Comment
-#
-# ROM is the desired output name for both .rom and .lzrom images.
-# PCI IDs are the PCI vendor and device IDs of the PCI NIC
-# For ISA NICs put -
-#
-# All PCI ROMs that share a single driver are only built once (because they
-# only have different PCI-IDs, but identical code).  ISA ROMS are built for
-# each ROM type, because different vendors used a different logic around the
-# basic chip.  The most popular example is the NS8390, which some cards use
-# in PIO mode, some in DMA mode.  Two chips currently don't fit into this nice
-# black-and-white scheme (the Lance and the NS8390).  Their driver deals
-# with both PCI and ISA cards.  These drivers will be treated similarly to
-# ISA only drivers by genrules.pl and are compiled for each ROM type that is
-# ISA, and additionally compiled for the PCI card type.
-#
-# Then do: make clean, make Roms and make
-#
-# Please send additions to this file to <kenUNDERSCOREyap AT users PERIOD sourceforge PERIOD net>
-
-# Start of configuration
-
-family         drivers/net/skel
-
-family         arch/ia64/drivers/net/undi_nii
-undi_nii       -
-
-# 3c59x cards (Vortex) and 3c900 cards
-# If your 3c900 NIC detects but fails to work, e.g. no link light, with
-# the 3c90x driver, try using the 3c595 driver. I have one report that the
-# 3c595 driver handles these NICs properly. (The 595 driver uses the
-# programmed I/O mode of operation, whereas the 90x driver uses the bus
-# mastering mode. These NICs are capable of either mode.) When it comes to
-# making a ROM, as usual, you must choose the correct image, the one that
-# contains the same PCI IDs as your NIC.
-family         drivers/net/3c595
-
-# 3Com 3c90x cards
-family         drivers/net/3c90x
-
-# Intel Etherexpress Pro/100
-family         drivers/net/eepro100
-
-#Intel Etherexpress Pro/1000
-family         drivers/net/e1000
-
-#Broadcom Tigon 3
-family         drivers/net/tg3
-
-family         drivers/net/pcnet32
-
-# National Semiconductor ns83820 (Gigabit) family
-family         drivers/net/ns83820
-
-family         drivers/net/tulip
-
-family         drivers/net/davicom
-
-family         drivers/net/rtl8139
-
-family         drivers/net/r8169
-
-family         drivers/net/via-rhine
-
-family         drivers/net/w89c840
-
-family         drivers/net/sis900
-
-family         drivers/net/natsemi
-
-family         drivers/net/prism2_plx
-
-family         drivers/net/prism2_pci
-# Various Prism2.5 (PCI) devices that manifest themselves as Harris Semiconductor devices
-# (with the actual vendor appearing as the vendor of the first subsystem)
-hwp01170       0x1260,0x3873   ActionTec HWP01170
-dwl520         0x1260,0x3873   DLink DWL-520
-
-family         drivers/net/ns8390
-wd             -               WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)
-ne             -               NE1000/2000 and clones
-3c503          -               3Com503, Etherlink II[/16]
-
-family         drivers/net/epic100
-
-family         drivers/net/3c509
-3c509          -               3c509, ISA/EISA
-3c529          -               3c529 == MCA 3c509
-
-family         drivers/net/3c515
-3c515          -               3c515, Fast EtherLink ISA
-
-family         drivers/net/eepro
-eepro          -               Intel Etherexpress Pro/10
-
-family         drivers/net/cs89x0
-cs89x0         -               Crystal Semiconductor CS89x0
-
-family         drivers/net/depca
-depca          -               Digital DE100 and DE200
-
-family          drivers/net/forcedeth
-
-family         drivers/net/sk_g16
-sk_g16         -               Schneider and Koch G16
-
-family         drivers/net/smc9000
-smc9000                -               SMC9000
-
-family         drivers/net/sundance
-
-family         drivers/net/tlan
-
-family         drivers/disk/ide_disk
-ide_disk       0x0000,0x0000   Generic IDE disk support
-
-family         drivers/disk/pc_floppy
-
-family         arch/i386/drivers/net/undi
-undi           0x0000,0x0000   UNDI driver support
-
-family         drivers/net/pnic
-
-family         arch/armnommu/drivers/net/p2001_eth
-
-family         drivers/net/mtd80x
-
-family         drivers/net/dmfe
index afb1618eb6da4e00c3086fd651b2a125a67c5c16..7d7d76d4306495cd10417f8b5cd4b591d1abe4e3 100644 (file)
-# Override ARCH here or on the command line
-# ARCH=i386
-# Additionally you can supply extra compilation arguments, e.g. for x86_64
-# EXTRA_CFLAGS=-m32
-# EXTRA_ASFLAGS=--32
-# EXTRA_LDFLAGS=-m elf_i386
+# Initialise variables that get added to throughout the various Makefiles
+#
+MAKEDEPS       := Makefile .toolcheck
+SRCDIRS                :=
+SRCS           :=
+NON_AUTO_SRCS  :=
+DRIVERS                :=
+ROMS           :=
+MEDIA          :=
+NON_AUTO_MEDIA :=
+
+# Grab the central Config file.
+#
+MAKEDEPS       += Config
+include Config
+
+# If no architecture is specified in Config or on the command-line,
+# use that of the build machine.
+#
 ifndef ARCH
-ARCH:=$(shell uname -m | sed -e s,i[3456789]86,i386,)
+ARCH           := $(shell uname -m | sed -e s,i[3456789]86,i386,)
 endif
-MAKEDEPS:=
-SUFFIXES:=
 
-include Config
+# Drag in architecture-specific Config
+#
+MAKEDEPS       += arch/$(ARCH)/Config
 include arch/$(ARCH)/Config
-include Makefile.main
+
+# If invoked with no build target, print out a helpfully suggestive
+# message.
+#
+noargs : blib
+       @echo '===================================================='
+       @echo 'No target specified. To specify a target, do: '
+       @echo
+       @echo '    $(MAKE) bin/<rom-name>.<output-format> '
+       @echo
+       @echo 'where <output-format> is one of [z]{$(MEDIA) }'
+       @echo
+       @echo 'or: '
+       @echo
+       @echo '    $(MAKE) all<output-format>s'
+       @echo
+       @echo 'to generate all possible images of format <output-format>'
+       @echo
+       @echo 'For example, '
+       @echo
+       @echo '    make allzroms '
+       @echo
+       @echo 'will generate all possible .zrom (rom burnable) images, and'
+       @echo
+       @echo '    make allzdsks'
+       @echo
+       @echo 'will generate all possible .zdsk (bootable floppy) images, or'
+       @echo
+       @echo '===================================================='
+       @exit 1
+
+# Locations of utilities
+#
+HOST_CC                ?= gcc
+CPP            ?= gcc -E -Wp,-Wall
+RM             ?= rm -f
+TOUCH          ?= touch
+MKDIR          ?= mkdir
+PERL           ?= /usr/bin/perl
+CC             ?= $(CROSS_COMPILE)gcc
+AS             ?= $(CROSS_COMPILE)as
+LD             ?= $(CROSS_COMPILE)ld
+SIZE           ?= $(CROSS_COMPILE)size
+AR             ?= $(CROSS_COMPILE)ar
+RANLIB         ?= $(CROSS_COMPILE)ranlib
+OBJCOPY                ?= $(CROSS_COMPILE)objcopy
+PARSEROM       ?= $(PERL) ./util/parserom.pl
+MAKEROM                ?= $(PERL) ./util/makerom.pl
+NRV2B          ?= ./util/nrv2b
+
+# Location to place generated files
+#
+BIN            ?= bin
+
+# Library containing all compiled objects
+BLIB   = $(BIN)/blib.a
+
+# Common flags
+#
+CFLAGS         += -I include -I arch/$(ARCH)/include -DARCH=$(ARCH)
+CFLAGS         += -Os -ffreestanding
+CFLAGS         += -Wall -W -Wno-format
+CFLAGS         += $(EXTRA_CFLAGS)
+ASFLAGS                += $(EXTRA_ASFLAGS)
+LDFLAGS                += $(EXTRA_LDFLAGS)
+
+# CFLAGS for specific object types
+#
+CFLAGS_c       += 
+CFLAGS_S       += -DASSEMBLY
+
+# CFLAGS for specific object files.  You can define
+# e.g. CFLAGS_rtl8139, and have those flags automatically used when
+# compiling bin/rtl8139.o.
+#
+OBJ_CFLAGS     = $(CFLAGS_$(basename $(@F))) \
+                 -DOBJECT=$(subst -,_,$(basename $(@F)))
+$(BIN)/%.flags :
+       @echo $(OBJ_CFLAGS)
+
+# Rules for specific object types.
+#
+COMPILE_c      = $(CC) $(CFLAGS) $(CFLAGS_c) $(OBJ_CFLAGS)
+RULE_c         = $(COMPILE_c) -c $< -o $@
+RULE_c_to_s    = $(COMPILE_c) -S -c $< -o $@ 
+RULE_c_to_c    = $(COMPILE_c) -E -c $< > $@
+
+PREPROCESS_S   = $(CPP) $(CFLAGS) $(CFLAGS_S) $(OBJ_CFLAGS)
+ASSEMBLE_S     = $(AS) $(ASFLAGS)
+RULE_S         = $(PREPROCESS_S) $< | $(ASSEMBLE_S) -o $@
+RULE_S_to_s    = $(PREPROCESS_S) $< > $@
+
+DEBUG_TARGETS  += c s
+
+# SRCDIRS lists all directories containing source files.
+#
+SRCDIRS                += core drivers/net drivers/disk
+
+# NON_AUTO_SRCS lists files that are excluded from the normal
+# automatic build system.
+#
+NON_AUTO_SRCS  += core/elf_loader.c
+
+# Rules for finalising files.  TGT_MAKEROM_FLAGS is defined as part of
+# the automatic build system and varies by target; it includes the
+# "-p 0x1234,0x5678" string to set the PCI IDs.
+#
+FINALISE_rom = $(MAKEROM) $(MAKEROM_FLAGS) $(TGT_MAKEROM_FLAGS) \
+              -i$(IDENT) $@
+
+# Drag in architecture-specific Makefile
+#
+MAKEDEPS       += arch/$(ARCH)/Makefile
+include arch/$(ARCH)/Makefile
+
+# Drag in the automatic build system and other housekeeping functions
+MAKEDEPS       += Makefile.housekeeping
+include Makefile.housekeeping
diff --git a/src/Makefile-armnommu b/src/Makefile-armnommu
deleted file mode 100644 (file)
index 04c4002..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-ARCH:=armnommu
-MAKEDEPS:=
-
-include Config
-include arch/$(ARCH)/Config
-
-CC=            $(CROSS_COMPILE)gcc
-AS=            $(CROSS_COMPILE)as
-LD=            $(CROSS_COMPILE)ld
-SIZE=          $(CROSS_COMPILE)size
-AR=            $(CROSS_COMPILE)ar
-RANLIB=                $(CROSS_COMPILE)ranlib
-OBJCOPY=       $(CROSS_COMPILE)objcopy
-
-MAKEDEPS+=Makefile-armnommu
-BIN=bin
-
-include Makefile.main
diff --git a/src/Makefile-e1 b/src/Makefile-e1
deleted file mode 100644 (file)
index bdd4917..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-ARCH:=e1
-MAKEDEPS:=
-
-include arch/$(ARCH)/Config
-include Config
-
-CC=            e1-coff-gcc
-AS=            e1-coff-as
-LD=            e1-coff-ld
-SIZE=  e1-coff-size
-AR=            e1-coff-ar
-RANLIB=        e1-coff-ranlib
-OBJCOPY=e1-coff-objcopy
-
-MAKEDEPS+=Makefile-e1
-BIN=bin-e1
-
-include Makefile.main
diff --git a/src/Makefile-i386 b/src/Makefile-i386
deleted file mode 100644 (file)
index d626852..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-ARCH:=i386
-MAKEDEPS:=
-
-include arch/$(ARCH)/Config
-include Config
-
-CC=            i386-linux-gcc
-AS=            i386-linux-as
-LD=            i386-linux-ld
-SIZE=          i386-linux-size
-AR=            i386-linux-ar
-RANLIB=                i386-linux-ranlib
-OBJCOPY=       i386-linux-objcopy
-
-MAKEDEPS+=Makefile-i386
-BIN=bin-i386
-
-include Makefile.main
diff --git a/src/Makefile-ia64 b/src/Makefile-ia64
deleted file mode 100644 (file)
index 503f7e0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-ARCH:=ia64
-MAKEDEPS:=
-
-include arch/$(ARCH)/Config
-include Config
-
-CC=            ia64-linux-gcc
-AS=            ia64-linux-as
-LD=            ia64-linux-ld
-SIZE=          ia64-linux-size
-AR=            ia64-linux-ar
-RANLIB=                ia64-linux-ranlib
-OBJCOPY=       ia64-linux-objcopy
-
-MAKEDEPS+=Makefile-ia64
-BIN=bin-ia64
-
-include Makefile.main
diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping
new file mode 100644 (file)
index 0000000..57538be
--- /dev/null
@@ -0,0 +1,375 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# This file contains various boring housekeeping functions that would
+# otherwise seriously clutter up the main Makefile.
+
+# Objects to be removed by "make clean"
+#
+CLEANUP        := $(BIN)/*.* # *.* to avoid catching the "CVS" directory
+
+# Version number calculations 
+#
+VERSION_MAJOR  = 5
+VERSION_MINOR  = 3
+VERSION_PATCH  = 14
+EXTRAVERSION   =       
+MM_VERSION     = $(VERSION_MAJOR).$(VERSION_MINOR)
+VERSION                = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION)
+CFLAGS         += -DVERSION_MAJOR=$(VERSION_MAJOR) \
+                  -DVERSION_MINOR=$(VERSION_MINOR) \
+                  -DVERSION=\"$(VERSION)\"
+IDENT          = '$(@F) $(VERSION) (GPL) etherboot.org'
+version :
+       @echo $(VERSION)
+
+# Check for tools that can cause failed builds
+#
+.toolcheck : Makefile Config
+       @if $(CC) -v 2>&1 | grep -is 'gcc version 2\.96' > /dev/null; then \
+               echo 'gcc 2.96 is unsuitable for compiling Etherboot'; \
+               echo 'Use gcc 2.95 or gcc 3.x instead'; \
+               exit 1; \
+       fi
+       @if [ `perl -e 'use bytes; print chr(255)' | wc -c` = 2 ]; then \
+               echo 'Your Perl version has a Unicode handling bug'; \
+               echo 'Execute this command before compiling Etherboot:'; \
+               echo 'export LANG=$${LANG%.UTF-8}'; \
+               exit 1; \
+       fi
+       @$(TOUCH) $@
+VERYCLEANUP    += .toolcheck
+
+# Check for an old version of gas (binutils 2.9.1)
+#
+OLDGAS := $(shell $(AS) --version | grep -q '2\.9\.1' && echo -DGAS291)
+CFLAGS += $(OLDGAS)
+oldgas :
+       @echo $(oldgas)
+
+# SRCDIRS lists all directories containing source files.
+srcdirs :
+       @echo $(SRCDIRS)
+
+# SRCS lists all .c or .S files found in any SRCDIR
+#
+SRCS   += $(wildcard $(patsubst %,%/*.c,$(SRCDIRS)))
+SRCS   += $(wildcard $(patsubst %,%/*.S,$(SRCDIRS)))
+srcs :
+       @echo $(SRCS)
+
+# AUTO_SRCS lists all files in SRCS that are not mentioned in
+# NON_AUTO_SRCS.  Files should be added to NON_AUTO_SRCS if they
+# cannot be built using the standard build template.
+#
+AUTO_SRCS = $(filter-out $(NON_AUTO_SRCS),$(SRCS))
+autosrcs :
+       @echo $(AUTO_SRCS)
+
+# We automatically generate rules for any file mentioned in AUTO_SRCS
+# using the following set of templates.  It would be cleaner to use
+# $(eval ...), but this function exists only in GNU make >= 3.80.
+
+# src_template : generate Makefile rules for a given source file
+#
+# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c")
+# $(2) is the full path to the .d file (e.g. "bin/deps/drivers/net/rtl8139.d")
+# $(3) is the source type (e.g. "c")
+# $(4) is the source base name (e.g. "rtl8139")
+#
+define src_template
+
+       @echo "Generating Makefile rules for $(1)"
+       @$(MKDIR) -p $(dir $(2))
+       @$(RM) $(2)
+       @$(TOUCH) $(2)
+       $(foreach OBJ,$(if $(OBJS_$(4)),$(OBJS_$(4)),$(4)), \
+               $(call obj_template,$(1),$(2),$(3),$(OBJ)))
+       @$(PARSEROM) $(1) >> $(2)
+
+endef
+
+# obj_template : generate Makefile rules for a given resultant object
+# of a particular source file.  (We can have multiple objects per
+# source file via the OBJS_xxx list.)
+#
+# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c")
+# $(2) is the full path to the .d file (e.g. "bin/deps/drivers/net/rtl8139.d")
+# $(3) is the source type (e.g. "c")
+# $(4) is the object name (e.g. "rtl8139")
+#
+define obj_template
+
+       @$(CPP) $(CFLAGS) $(CFLAGS_$(3)) $(CFLAGS_$(4)) \
+               -M $(1) -MT "$(4)_DEPS" | tr : = >> $(2)
+       @echo -e '\n$$(BIN)/$(4).o : $(1) $$(MAKEDEPS) $$($(4)_DEPS)' \
+                '\n\t$$(RULE_$(3))\n' \
+                '\nBOBJS += $$(BIN)/$(4).o\n' \
+                $(foreach TGT,$(DEBUG_TARGETS), \
+                   $(if $(RULE_$(3)_to_$(TGT)), \
+                   '\n$$(BIN)/$(4).$(TGT) : $(1) $$(MAKEDEPS) $$($(4)_DEPS)' \
+                   '\n\t$$(RULE_$(3)_to_$(TGT))\n' ) ) \
+                '\n$(2) : $$($(4)_DEPS)\n' \
+                '\nTAGS : $$($(4)_DEPS)\n' \
+               >> $(2)
+
+endef
+
+# Rule to generate the Makefile rules files to be included
+#
+$(BIN)/deps/%.d : % $(MAKEDEPS) $(PARSEROM)
+       $(if $(filter $(AUTO_SRCS),$<),$(call src_template,$<,$@,$(subst .,,$(suffix $<)),$(basename $(notdir $<))),@echo 'ERROR: $< is not an AUTO_SRC' ; exit 1)
+
+# Calculate and include the list of Makefile rules files
+#
+AUTO_DEPS      = $(patsubst %,$(BIN)/deps/%.d,$(AUTO_SRCS))
+include $(AUTO_DEPS)
+autodeps :
+       @echo $(AUTO_DEPS)
+VERYCLEANUP    += $(BIN)/deps
+
+# The following variables are created by the Makefile rules files
+#
+bobjs :
+       @echo $(BOBJS)
+drivers :
+       @echo $(DRIVERS)
+.PHONY : drivers
+roms :
+       @echo $(ROMS)
+
+# Generate the NIC file from the parsed source files.  The NIC file is
+# only for rom-o-matic.
+#
+$(BIN)/NIC : $(AUTO_DEPS)
+       @echo '# This is an automatically generated file, do not edit' > $@
+       @echo '# It does not affect anything in the build, ' \
+            'it is only for rom-o-matic' >> $@
+       @echo >> $@
+       @perl -ne 'chomp; print "$$1\n" if /\# NIC\t(.*)$$/' $^ >> $@
+CLEANUP                += $(BIN)/NIC
+
+# Library of all objects
+#
+$(BLIB) : $(BOBJS)
+       $(AR) r $@ $(BOBJS)
+       $(RANLIB) $@
+blib : $(BLIB)
+
+# Analyse a target name (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and
+# derive the variables:
+# 
+# TGT_ELEMENTS : the elements of the target (e.g. "dfe538 prism2_pci")
+# TGT_PREFIX   : the prefix type (e.g. "zrom")
+# TGT_DRIVERS  : the driver for each element (e.g. "rtl8139 prism2_pci")
+# TGT_ROM_NAME : the ROM name (e.g. "dfe538")
+# TGT_MEDIA    : the media type (e.g. "rom")
+#
+TGT_ELEMENTS   = $(subst --, ,$(firstword $(subst ., ,$(notdir $@))))
+TGT_PREFIX     = $(word 2,$(subst ., ,$(notdir $@)))
+TGT_DRIVERS    = $(strip $(foreach TGT_ELEMENT,$(TGT_ELEMENTS), \
+                  $(firstword $(DRIVER_$(TGT_ELEMENT)) $(TGT_ELEMENT))))
+TGT_ROM_NAME   = $(firstword $(TGT_ELEMENTS))
+TGT_MEDIA      = $(subst z,,$(TGT_PREFIX))
+
+# Look up ROM type and IDs for the current target
+# (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and derive the variables:
+#
+# TGT_ROM_TYPE   : PCI/ISA indicator (e.g. "pci")
+# TGT_PCI_VENDOR : the PCI vendor ID (e.g. "0x1186")
+# TGT_PCI_DEVICE : the PCI device ID (e.g. "0x1300")
+#
+TGT_ROM_TYPE   = $(ROM_TYPE_$(TGT_ROM_NAME))
+TGT_PCI_VENDOR = $(PCI_VENDOR_$(TGT_ROM_NAME))
+TGT_PCI_DEVICE = $(PCI_DEVICE_$(TGT_ROM_NAME))
+
+# Calculate link-time options for the current target
+# (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and derive the variables:
+#
+# TGT_LD_DRIVERS : symbols to require in order to drag in the relevant drivers
+#                 (e.g. "obj_rtl8139 obj_prism2_pci")
+# TGT_LD_PREFIX  : symbols to require in order to drag in the relevant prefix
+#                 (e.g. "obj_zpciprefix")
+# TGT_LD_IDS :     symbols to define in order to fill in ID structures in the
+#                 ROM header (e.g. "pci_vendor=0x1186 pci_device=0x1300")
+#
+TGT_LD_DRIVERS = $(subst -,_,$(patsubst %,obj_%,$(TGT_DRIVERS)))
+TGT_LD_PREFIX  = obj_$(subst rom,$(TGT_ROM_TYPE),$(TGT_PREFIX))prefix
+TGT_LD_IDS     = $(if $(TGT_PCI_VENDOR),pci_vendor=$(TGT_PCI_VENDOR)) \
+                 $(if $(TGT_PCI_DEVICE),pci_device=$(TGT_PCI_DEVICE))
+
+# Calculate linker flags based on link-time options for the current
+# target type (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and derive the
+# variables:
+#
+# TGT_LD_FLAGS : target-specific flags to pass to linker (e.g.
+#               "-u obj_zpciprefix -u obj_rtl8139 -u obj_prism2_pci
+#                --defsym pci_vendor=0x1186 --defsym pci_device=0x1300")
+#
+TGT_LD_FLAGS   = $(foreach SYM,$(TGT_LD_PREFIX) $(TGT_LD_DRIVERS) obj_config,\
+                   -u $(SYM) --defsym check_$(SYM)=$(SYM) ) \
+                 $(patsubst %,--defsym %,$(TGT_LD_IDS))
+
+# Calculate makerom flags for the specific target
+# (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and derive the variables:
+#
+# TGT_MAKEROM_FLAGS : target-specific flags for makerom (e.g.
+#                    "-p 0x1186,0x1300")
+#
+TGT_MAKEROM_FLAGS = $(strip $(MAKEROM_FLAGS_$(TGT_ROM_NAME)) \
+       $(if $(TGT_PCI_VENDOR),$(strip -p $(TGT_PCI_VENDOR),$(TGT_PCI_DEVICE))))
+
+# Print out all derived information for a given target.
+#
+$(BIN)/%.info :
+       @echo 'Elements             : $(TGT_ELEMENTS)'
+       @echo 'Prefix               : $(TGT_PREFIX)'
+       @echo 'Drivers              : $(TGT_DRIVERS)'
+       @echo 'ROM name             : $(TGT_ROM_NAME)'
+       @echo 'Media                : $(TGT_MEDIA)'
+       @echo
+       @echo 'ROM type             : $(TGT_ROM_TYPE)'
+       @echo 'PCI vendor           : $(TGT_PCI_VENDOR)'
+       @echo 'PCI device           : $(TGT_PCI_DEVICE)'
+       @echo
+       @echo 'LD driver symbols    : $(TGT_LD_DRIVERS)'
+       @echo 'LD prefix symbols    : $(TGT_LD_PREFIX)'
+       @echo 'LD ID symbols        : $(TGT_LD_IDS)'
+       @echo
+       @echo 'LD target flags      : $(TGT_LD_FLAGS)'
+       @echo
+       @echo 'makerom target flags : $(TGT_MAKEROM_FLAGS)'
+
+# Build an intermediate object file from the objects required for the
+# specified target.
+#
+$(BIN)/%.tmp : $(BLIB) $(MAKEDEPS) $(LDSCRIPT)
+       $(LD) $(LDFLAGS) -T $(LDSCRIPT) $(TGT_LD_FLAGS) $< -o $@ \
+               -Map $(BIN)/$*.tmp.map
+
+# Show a linker map for the specified target
+#
+$(BIN)/%.map : $(BIN)/%.tmp
+       @less $(BIN)/$*.tmp.map
+
+# Rules for each media format.  These are generated and placed in an
+# external Makefile fragment.  We could do this via $(eval ...), but
+# that would require make >= 3.80.
+# 
+# Note that there's an alternative way to generate most .rom images:
+# they can be copied from their 'master' ROM image using cp and
+# reprocessed with makerom to add the PCI IDs and ident string.  The
+# relevant rule would look something like:
+#
+#   $(BIN)/dfe538%rom : $(BIN)/rtl8139%rom
+#      cat $< $@
+#      $(FINALISE_rom)
+# 
+# You can derive the ROM/driver relationships using the variables
+# DRIVER_<rom> and/or ROMS_<driver>.
+# 
+# We don't currently do this, because (a) it would require generating
+# yet more Makefile fragments (since you need a rule for each ROM in
+# ROMS), and (b) the linker is so fast that it probably wouldn't make
+# much difference to the overall build time.
+
+media :
+       @echo $(MEDIA)
+
+AUTO_MEDIA     = $(filter-out $(NON_AUTO_MEDIA),$(MEDIA))
+automedia :
+       @echo $(AUTO_MEDIA)
+
+# media_template : create Makefile rules for specified media
+#
+# $(1) is the media name (e.g. "rom")
+# $(2) is the full path to the .d file (e.g. "bin/deps/rom.media.d")
+#
+define media_template
+
+       @echo "Generating Makefile rules for $(1) media"
+       @$(MKDIR) -p $(dir $(2))
+       @$(RM) $(2)
+       @$(TOUCH) $(2)
+       @echo -e '$$(BIN)/%$(1) : $$(BIN)/%$(1).tmp' \
+                 '\n\t$$(OBJCOPY) -O binary $$< $$@' \
+                 '\n\t$$(FINALISE_$(1))' \
+               > $(2)
+
+endef
+
+# Rule to generate the Makefile rules to be included
+#
+$(BIN)/deps/%.media.d : $(MAKEDEPS)
+       $(if $(filter $(AUTO_MEDIA),$*), \
+               $(call media_template,$*,$@), \
+               @echo 'ERROR: $* is not an AUTO_MEDIA' ; exit 1)
+
+# Calculate and include the list of Makefile rules files
+#
+MEDIA_DEPS             = $(patsubst %,$(BIN)/deps/%.media.d,$(AUTO_MEDIA))
+mediadeps :
+       @echo $(MEDIA_DEPS)
+include $(MEDIA_DEPS)
+
+# The "allXXXs" targets for each suffix
+#
+allroms allzroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%)
+all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%)
+
+# The compressor utility
+#
+$(NRV2B) : util/nrv2b.c $(MAKEDEPS)
+       $(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \
+                      -DBITSIZE=32 -DENDIAN=0 -o $@ $<
+CLEANUP        += $(NRV2B)
+
+# Auto-incrementing build serial number.  Append "bs" to your list of
+# build targets to get a serial number printed at the end of the
+# build.  Enable -DBUILD_SERIAL in order to see it when the code runs.
+#
+BUILDSERIAL_H = include/.buildserial.h
+
+$(BUILDSERIAL_H) :
+       @if [ ! -s $@ ]; then echo '#define BUILD_SERIAL_NUM 0' > $@; fi
+       @perl -pi -e 's/(BUILD_SERIAL_NUM)\s+(\d+)/"$${1} ".($${2}+1)/e' $@
+
+bs : $(BUILDSERIAL_H)
+       @perl -n -e '/BUILD_SERIAL_NUM\s+(\d+)/ && ' \
+               -e 'print "Build serial number is $$1\n";' $<
+
+ifeq ($(filter bs,$(MAKECMDGOALS)),bs)
+.PHONY : $(BUILDSERIAL_H)
+endif
+
+# Ensure that include/.buildserial.h always exists, to solve the
+# problem of bootstrapping a BUILD_SERIAL-enabled build.
+#
+ifeq ($(wildcard $(BUILDSERIAL_H)),)
+$(shell $(TOUCH) $(BUILDSERIAL_H))
+endif
+
+# List of available architectures
+#
+ARCHS  = $(filter-out CVS,$(patsubst arch/%,%,$(wildcard arch/*)))
+archs :
+       @echo $(ARCHS)
+
+OTHER_ARCHS    = $(filter-out $(ARCH),$(ARCHS))
+otherarchs :
+       @echo $(OTHER_ARCHS)
+
+# Build the TAGS file for emacs
+#
+TAGS : TAGS.$(ARCH)
+
+TAGS.$(ARCH) : 
+       ctags -e -R -f $@ $(foreach ARCH,$(OTHER_ARCHS),--exclude=arch/$(ARCH))
+CLEANUP        += TAGS*
+
+# Clean-up
+#
+clean :
+       $(RM) $(CLEANUP)
+
+veryclean : clean
+       $(RM) -r $(VERYCLEANUP)
diff --git a/src/Makefile.main b/src/Makefile.main
deleted file mode 100644 (file)
index 1c7b6e5..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-#
-# Makefile for Etherboot
-#
-# Most of the time you should edit Config
-#
-# Common options:
-#      VERSION_*=v     - Set the major and minor version numbers
-#
-# 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
-#      -DWD_790_PIO    - Read/write to WD/SMC 790 cards in PIO mode (default
-#                        is to use shared memory) Try this if you get "Bogus
-#                        packet, ignoring" messages, common on ISA/PCI hybrid
-#                        systems.
-#      -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
-#
-#      Warning Warning Warning
-#      If you use any of the XCVR options below, please do not complain about
-#      the behaviour with Linux drivers to the kernel developers. You are
-#      on your own if you do this. Please read 3c90x.txt to understand
-#      what they do. If you don't understand them, ask for help on the
-#      Etherboot mailing list. And please document what you did to the NIC
-#      on the NIC so that people after you won't get nasty surprises.
-#
-#      -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
-#
-# RTL8139 options:
-#      -DINCLUDE_RTL8139 - Include RTL8139 support
-#
-# SIS900 options:
-#      -DINCLUDE_SIS900 - Include SIS900 support
-#
-# NATSEMI options:
-#      -DINCLUDE_NATSEMI - Include NATSEMI support
-#
-
-SRCS:=
-BOBJS:=
-
-MAKEROM=       $(PERL) ./util/makerom.pl
-VERSION_MAJOR= 5
-VERSION_MINOR= 3
-VERSION_PATCH= 14
-EXTRAVERSION=  
-VERSION=       $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)$(EXTRAVERSION)
-MM_VERSION=    $(VERSION_MAJOR).$(VERSION_MINOR)
-CFLAGS+=       -DVERSION_MAJOR=$(VERSION_MAJOR) \
-               -DVERSION_MINOR=$(VERSION_MINOR) \
-               -DVERSION=\"$(VERSION)\" $(OLDGAS) \
-               -I include -I arch/$(ARCH)/include \
-               -DARCH=$(ARCH)
-FILO=filo
-FILO_PROGRAM_NAME = FILO
-FILO_PROGRAM_VERSION = 0.4.1
-FILO_BUILD_INFO = ($(shell whoami)@$(shell hostname)) $(shell LANG=C date)
-
-GCCINCDIR = $(shell $(CC) -print-search-dirs | head -n 1 | cut -d' ' -f2)include
-CPPFLAGS = -nostdinc -imacros filo/config.h 
-#-Ifilo/include -I$(GCCINCDIR) -MD
-ASFLAGS_X = -D__ASSEMBLY__
-
-IDENT=         '$(@F) $(VERSION) (GPL) etherboot.org'
-
-# 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)
-
-BUILD_LIBS=    $(BLIB)
-BUILD_IMGS=    $(IMGS)
-
-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
-E1000FLAGS=    -DINCLUDE_E1000
-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
-SIS900FLAGS=           -DINCLUDE_SIS900
-NATSEMIFLAGS=          -DINCLUDE_NATSEMI
-SMC9000FLAGS=   -DINCLUDE_SMC9000
-SUNDANCEFLAGS= -DINCLUDE_SUNDANCE
-TLANFLAGS=     -DINCLUDE_TLAN
-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
-
-SRCS+= core/serial.c
-
-SRCS+= core/btext.c core/pc_kbd.c
-
-SRCS+= core/main.c core/pci.c core/osloader.c core/nfs.c
-SRCS+= core/misc.c core/config.c core/isa_probe.c core/pci_probe.c
-SRCS+= core/relocate.c core/heap.c
-SRCS+= drivers/disk/floppy.c core/nic.c core/disk.c core/timer.c
-SRCS+= core/proto_eth_slow.c
-SRCS+= core/proto_slam.c core/proto_tftm.c core/proto_http.c
-SRCS+= core/isapnp.c
-SRCS+= core/pcmcia.c core/i82365.c
-SRCS+= core/pxe_export.c core/dns_resolver.c
-
-FILO_SRCS+=    $(FILO)/drivers/ide_x.c  
-FILO_SRCS+=    $(FILO)/fs/blockdev.c $(FILO)/fs/eltorito.c $(FILO)/fs/fsys_ext2fs.c $(FILO)/fs/fsys_fat.c $(FILO)/fs/fsys_iso9660.c
-FILO_SRCS+=    $(FILO)/fs/fsys_reiserfs.c $(FILO)/fs/vfs.c $(FILO)/fs/fsys_jfs.c $(FILO)/fs/fsys_minix.c $(FILO)/fs/fsys_xfs.c  
-FILO_SRCS+=    $(FILO)/main/elfload.c $(FILO)/main/elfnote.c $(FILO)/main/filo_x.c $(FILO)/main/lib.c $(FILO)/main/linuxbios_x.c 
-FILO_SRCS+=    $(FILO)/main/pci_x.c $(FILO)/main/malloc_x.c $(FILO)/main/printf_x.c $(FILO)/main/console_x.c 
-FILO_SRCS+=    $(FILO)/$(ARCH)/context.c $(FILO)/$(ARCH)/linux_load.c $(FILO)/$(ARCH)/segment.c $(FILO)/$(ARCH)/sys_info.c 
-FILO_SRCS+=    $(FILO)/$(ARCH)/switch.S $(FILO)/usb/debug_x.c $(FILO)/usb/scsi_cmds.c $(FILO)/usb/uhci.c $(FILO)/usb/usb.c 
-FILO_SRCS+=    $(FILO)/usb/ohci.c $(FILO)/usb/usb_scsi_low.c  $(FILO)/usb/usb_x.c
-
-
-BOBJS+=                $(BIN)/main.o $(BIN)/osloader.o $(BIN)/nfs.o $(BIN)/misc.o
-BOBJS+=                $(BIN)/proto_slam.o $(BIN)/proto_tftm.o $(BIN)/proto_http.o
-BOBJS+=                $(BIN)/floppy.o
-BOBJS+=                $(BIN)/serial.o $(BIN)/timer.o  $(BIN)/relocate.o $(BIN)/heap.o
-BOBJS+=                $(BIN)/btext.o $(BIN)/pc_kbd.o
-BOBJS+=                $(BIN)/nic.o $(BIN)/disk.o
-BOBJS+=                $(BIN)/isapnp.o
-BOBJS+=                $(BIN)/pci.o $(BIN)/isa_probe.o $(BIN)/pci_probe.o
-BOBJS+=                $(BIN)/vsprintf.o $(BIN)/string.o
-BOBJS+=                $(BIN)/pcmcia.o $(BIN)/i82365.o
-BOBJS+=                $(BIN)/pxe_export.o $(BIN)/dns_resolver.o
-
-FILO_OBJS+=            $(BIN)/ide_x.o $(BIN)/pci_x.o
-FILO_OBJS+=            $(BIN)/blockdev.o $(BIN)/eltorito.o $(BIN)/fsys_ext2fs.o $(BIN)/fsys_fat.o $(BIN)/fsys_iso9660.o $(BIN)/fsys_reiserfs.o $(BIN)/vfs.o
-FILO_OBJS+=            $(BIN)/fsys_jfs.o $(BIN)/fsys_minix.o $(BIN)/fsys_xfs.o  
-FILO_OBJS+=            $(BIN)/elfload.o  $(BIN)/elfnote.o  $(BIN)/filo_x.o $(BIN)/lib.o $(BIN)/linuxbios_x.o $(BIN)/malloc_x.o $(BIN)/printf_x.o $(BIN)/console_x.o   
-FILO_OBJS+=            $(BIN)/context.o  $(BIN)/linux_load.o  $(BIN)/segment.o  $(BIN)/sys_info.o $(BIN)/switch.o
-FILO_OBJS+=            $(BIN)/debug_x.o  $(BIN)/scsi_cmds.o $(BIN)/uhci.o $(BIN)/usb.o $(BIN)/ohci.o $(BIN)/usb_scsi_low.o $(BIN)/usb_x.o
-
-BLIB=          $(BIN)/bootlib.a 
-FILOLIB=       $(BIN)/filolib.a
-LIBS=          $(BLIB)
-ifdef  INCLUDE_FILO
-LIBS+=         $(FILOLIB)
-endif
-UTILS+=                $(BIN)/nrv2b
-STDDEPS=       $(START) $(UTILS)
-# MAKEDEPS is the one target that is depended by all ROMs, so we check gcc here
-# If you are confident that gcc 2.96 works for you, you can remove the lines
-# that check gcc in the toolcheck rule
-MAKEDEPS+=     Makefile Makefile.main Config genrules.pl Families
-MAKEDEPS+=     $(BIN)/toolcheck
-MAKEDEPS+=     arch/$(ARCH)/Makefile arch/$(ARCH)/Config
-
-# Start of targets
-
-.PHONY:        noargs
-noargs:        $(BIN)/toolcheck
-       @echo '===================================================='
-       @echo 'No target specified. To specify a target, do: '
-       @echo
-       @echo '    $(MAKE) bin/<rom-name>.<output-format> '
-       @echo
-       @echo 'where <output-format> is one of {zdsk, zrom, iso, liso, zlilo, zpxe, elf, com}'
-       @echo
-       @echo 'or: '
-       @echo
-       @echo '    $(MAKE) all<output-format>s'
-       @echo
-       @echo 'to generate all possible images of format <output-format>'
-       @echo
-       @echo 'For example, '
-       @echo
-       @echo '    make allzroms '
-       @echo
-       @echo 'will generate all possible .zrom (rom burnable) images, and'
-       @echo
-       @echo '    make allzdsks'
-       @echo
-       @echo 'will generate all possible .zdsk (bootable floppy) images, or'
-       @echo
-       @echo '===================================================='
-       @exit 1
-
-$(BIN)/toolcheck:      Makefile Config
-       @if $(CC) -v 2>&1 | grep -is 'gcc version 2\.96' > /dev/null; \
-       then \
-               echo 'gcc 2.96 is unsuitable for compiling Etherboot'; \
-               echo 'Use gcc 2.95 or gcc 3.x instead'; \
-               exit 1; \
-       else \
-               touch $(BIN)/toolcheck; \
-       fi; \
-       if [ `perl -e 'use bytes; print chr(255)' | wc -c` = 2 ]; \
-       then \
-               echo 'Your Perl version has a Unicode handling bug'; \
-               echo 'To workaround, execute this before compiling Etherboot:'; \
-               echo 'export LANG=$${LANG%.UTF-8}'; \
-               exit 1; \
-       fi
-
-include                arch/$(ARCH)/Makefile
-
-# Common files
-
-$(BLIB):       $(BOBJS)
-       $(AR) r $@ $(BOBJS)
-       $(RANLIB) $@
-
-$(FILOLIB):    $(FILO_OBJS)
-       $(AR) r $@ $(FILO_OBJS)
-       $(RANLIB) $@
-
-# LinuxBIOS support code
-$(BIN)/linuxbios.o:    firmware/linuxbios/linuxbios.c include/etherboot.h include/dev.h firmware/linuxbios/linuxbios_tables.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.
-
-$(FILO)/config.h: $(FILO)/Config
-       /bin/echo -e '/* GENERATED FILE, DO NOT EDIT */\n' >$@
-       sed -e 's/#.*//' -e '/=/!d' -e 's/\([^[:space:]]*\)[[:space:]]*=[[:space:]]*\(.*\).*/#define \1 \2/' -e 's/^#define \([^ ]*\) 0$$/#undef \1/' $^ >>$@
-
-filo_version: $(FILO)/main/version.h
-
-$(FILO)/main/version.h: FORCE
-       echo '#define PROGRAM_NAME "$(FILO_PROGRAM_NAME)"' > $@
-       echo '#define PROGRAM_VERSION "$(FILO_PROGRAM_VERSION) $(FILO_BUILD_INFO)"' >> $@
-
-FORCE:
-
-
-# Roms file
-# Builds almost silently because this rule is triggered for just about
-# every modification to sources.
-
-$(BIN)/Roms $(BIN)/NIC:        genrules.pl Families $(SRCS)
-       @mkdir -p $(@D)
-       @echo Scanning for ROMs and dependencies...
-       @$(PERL) ./genrules.pl Families $(BIN)/NIC $(ARCH) $(SRCS) > $(BIN)/Roms
-
-# Pattern Rules
-
-# general rules for compiling/assembling source files
-$(BIN)/%.o:    core/%.c $(MAKEDEPS)
-       $(CC) $(CFLAGS) -o $@ -c $<
-
-$(BIN)/%.s:    core/%.c $(MAKEDEPS)
-       $(CC) $(CFLAGS) -S -o $@ -c $<
-
-$(BIN)/%.o:    drivers/disk/%.c $(MAKEDEPS)
-       $(CC) $(CFLAGS) -o $@ -c $<
-
-$(BIN)/%.o:    drivers/net/%.c $(MAKEDEPS)
-       $(CC) $(CFLAGS) -o $@ -c $<
-
-$(BIN)/%.o:    firmware/linuxbios/%.c $(MAKEDEPS)
-       $(CC) $(CFLAGS) -o $@ -c $<
-
-$(BIN)/%.o:     $(FILO)/drivers/%.c $(MAKEDEPS) $(FILO)/config.h
-       $(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
-
-$(BIN)/%.o:     $(FILO)/fs/%.c $(MAKEDEPS) $(FILO)/config.h
-       $(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
-
-$(BIN)/%.o:     $(FILO)/$(ARCH)/%.c $(MAKEDEPS) $(FILO)/config.h
-       $(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
-
-$(BIN)/%.o:     $(FILO)/$(ARCH)/%.S $(MAKEDEPS) $(FILO)/config.h
-       $(CC) $(ASFLAGS_X) $(CPPFLAGS) -c $< -o $@
-
-$(BIN)/%.o:     $(FILO)/main/%.c $(MAKEDEPS) $(FILO)/config.h filo_version
-       $(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
-
-$(BIN)/%.o:     $(FILO)/usb/%.c $(MAKEDEPS) $(FILO)/config.h
-       $(CC) $(CFLAGS) -imacros $(FILO)/config.h -o $@ -c $<
-
-# Rule for the super etherboot image.
-$(BIN)/etherboot.o: $(DOBJS)
-       $(LD) $(LDFLAGS) -r $(DOBJS) -o $@
-
-$(BIN)/etherboot-pci.o: $(PCIOBJS)
-       $(LD) $(LDFLAGS) -r $(PCIOBJS) -o $@
-
-# General rules for generating runtime (rt) files
-$(BIN)/%.rt.o:  $(BIN)/%.o $(START) $(BIN)/config.o $(LIBS) $(STDDEPS) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -r $(START) $(BIN)/config.o $< $(LIBS) -o $@
-
-#   Rule for $(BIN)/%.FORMAT.rt is architecture and target-format specific
-
-$(BIN)/%.rt.bin: $(BIN)/%.rt $(MAKEDEPS)
-       $(OBJCOPY) -O binary -R .prefix $< $@
-
-$(BIN)/%.rt1.bin: $(BIN)/%.rt $(MAKEDEPS)
-       $(OBJCOPY) -O binary -j .text.nocompress $< $@
-
-$(BIN)/%.rt2.bin: $(BIN)/%.rt $(MAKEDEPS)
-       $(OBJCOPY) -O binary -R .prefix -R .text.nocompress $< $@
-
-# Rules for generating prefix binary files
-
-#   Rule for $(BIN)/%.FORMAT.prf is architecture and target-format specific
-$(BIN)/%.prf.bin: $(BIN)/%.prf $(MAKEDEPS)
-       $(OBJCOPY) -j .prefix -O binary $< $@
-
-# general rule for .z (compressed binary code), may be overridden
-$(BIN)/%.zbin: $(BIN)/%.bin $(BIN)/nrv2b $(MAKEDEPS)
-       $(BIN)/nrv2b e $< $@
-
-# Housekeeping
-
-clean:
-       $(RM) $(BIN)/*
-       $(RM) $(FILO)/config.h $(FILO)/main/version.h
-
-../index.html: ../index.xhtml
-       (cd ..; m4 -P -DHOSTSITE=SOURCEFORGE index.xhtml > index.html)
-
-../index-berlios.html: ../index.xhtml
-       (cd ..; m4 -P -DHOSTSITE=BERLIOS index.xhtml > index-berlios.html)
-
-tarball: ../index.html ../index-berlios.html
-       (echo -n $(VERSION) ''; date -u +'%Y-%m-%d') > ../VERSION
-       (cd ../..; tar cf /tmp/etherboot-$(VERSION).tar --exclude CVS --exclude doc etherboot-$(VERSION))
-       bzip2 -9 < /tmp/etherboot-$(VERSION).tar > /tmp/etherboot-$(VERSION).tar.bz2
-       gzip -9 < /tmp/etherboot-$(VERSION).tar > /tmp/etherboot-$(VERSION).tar.gz
-
-# Auto-incrementing build serial number.  Is auto-incremented for each
-# make run that specifies a final image file (e.g. bin/undi.zpxe) as a
-# target, or a target of the form "all*".  Enable via -DBUILD_SERIAL
-# in Config.
-
-ifneq ($(findstring -DBUILD_SERIAL,$(CFLAGS)),)
-
-# If no make goals are specified, it means "make all"
-REALGOALS = $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all)
-
-# Filter to see if there are any targets to trigger an auto-increment
-BUILDGOALS = $(filter all,$(REALGOALS)) $(filter all%,$(REALGOALS)) \
-            $(foreach SUFFIX,$(SUFFIXES),$(filter %.$(SUFFIX),$(REALGOALS)))
-
-ifneq ($(strip $(BUILDGOALS)),)
-# This is an auto-incrementing build.  Forcibly rebuild .buildserial.h
-# and mark config.o as depending on it to force its rebuilding.
-bin/config.o : include/.buildserial.h
-.PHONY : include/.buildserial.h
-endif # BUILDGOALS
-
-include/.buildserial.h :
-       @if [ ! -f $@ ]; then   echo '#define BUILD_SERIAL_NUM 0' > $@; fi
-       @perl -pi -e 's/(BUILD_SERIAL_NUM)\s+(\d+)/"$${1} ".($${2}+1)/e' $@
-
-buildserial : include/.buildserial.h
-       @perl -n -e '/BUILD_SERIAL_NUM\s+(\d+)/ && ' \
-               -e 'print "Build serial number is $$1\n";' $<
-
-else # -DBUILD_SERIAL
-
-buildserial : 
-       @echo Build serial number is disabled. Enable -DBUILD_SERIAL in Config.
-
-endif # -DBUILD_SERIAL
-
-bs : buildserial
-
-version:
-       @echo $(VERSION)
-
-romlimit:
-       @echo $(ROMLIMIT)
-
-sources:
-       @echo $(SRCS)
index b858ca8d29799f5afd2b6455cc494bea8c5eeabe..fef20e7bad412c87ca1e4941cb5d06f23775124f 100644 (file)
@@ -9,7 +9,7 @@
 #include "timer.h"
 #include "latch.h"
 #include "hardware.h"
-
+#include "init.h"
 
 /* get timer returns the contents of the timer */
 static unsigned long get_timer(void)
@@ -29,7 +29,7 @@ static unsigned long configure_timer(void)
 
 static unsigned long clocks_per_tick = 1;
 
-void setup_timers(void)
+static void setup_timers(void)
 {
        if (!clocks_per_tick) {
                clocks_per_tick = configure_timer();
@@ -75,3 +75,5 @@ int timer2_running(void)
 {
        return __timer_running();
 }
+
+INIT_FN ( INIT_TIMERS, setup_timers, NULL, NULL );
index d3ddb6443780199f6a336d80765ebaf9324ea6e5..4ed9a0fbcf95be4ebe378f3c99e54ce2439b3702 100644 (file)
@@ -7,6 +7,7 @@
 #include "etherboot.h"
 #include "timer.h"
 #include "e132_xs_board.h"
+#include "init.h"
 
 /* get timer returns the contents of the timer */
 static inline unsigned long get_timer(void)
@@ -46,7 +47,7 @@ static unsigned long configure_timer(void)
 
 static unsigned long clocks_per_tick;
 
-void setup_timers(void)
+static void setup_timers(void)
 {
        if (!clocks_per_tick) {
                clocks_per_tick = configure_timer();
@@ -92,3 +93,5 @@ int timer2_running(void)
 {
        return __timer_running();
 }
+
+INIT_FN ( INIT_TIMERS, setup_timers, NULL, NULL );
index e8ac91b8e7b24754af556067c6522a655fd3315c..a212652791ba279d4f3c3ea76a1ab3c711938c55 100644 (file)
@@ -129,3 +129,8 @@ endif
 
 # An alternate location for isolinux.bin can be set here
 # ISOLINUX_BIN=/path/to/isolinux.bin
+
+# These seem to have some relevance to compiling on x86_64
+# EXTRA_CFLAGS=-m32
+# EXTRA_ASFLAGS=--32
+# EXTRA_LDFLAGS=-m elf_i386
index 0a80ff94653f51ebf0c26beaebe904e6c1ed374f..a4139e74b6bf04e4a8ca2f7f10008daa49240204 100644 (file)
-ARCH_FORMAT=   elf32-i386
-
-# For debugging, don't delete intermediates
-#.SECONDARY:
-
-LDSCRIPT=      arch/i386/core/etherboot.lds
-PLDSCRIPT=     arch/i386/core/etherboot.prefix.lds
-
-LCONFIG+=      -Ui386
-
-ROMLIMIT=      524288
-CHECKSIZE=     { read d1; read d1 d2 d3 size d4; [ $$size -gt $(ROMLIMIT) ] &&\
-       { $(RM) $@; echo "ERROR: code size exceeds limit!"; exit 1; }; exit 0; }
-
-START= $(BIN)/start32.o $(BIN)/linuxbios.o \
-       $(BIN)/bios.o $(BIN)/console.o $(BIN)/memsizes.o $(BIN)/basemem.o \
-       $(BIN)/hidemem.o $(BIN)/e820mangler.o \
-       $(BIN)/realmode.o $(BIN)/realmode_asm.o \
-       $(BIN)/callbacks.o $(BIN)/pxe_callbacks.o
-
-SRCS+= arch/i386/prefix/floppyprefix.S
-SRCS+= arch/i386/prefix/unnrv2b.S
-SRCS+= arch/i386/firmware/pcbios/bios.c
-SRCS+= arch/i386/firmware/pcbios/console.c
-SRCS+= arch/i386/firmware/pcbios/memsizes.c
-SRCS+= arch/i386/firmware/pcbios/basemem.c
-SRCS+= arch/i386/firmware/pcbios/hidemem.c
-SRCS+= arch/i386/firmware/pcbios/e820mangler.S
-SRCS+= arch/i386/prefix/liloprefix.S
-SRCS+= arch/i386/prefix/elfprefix.S
-SRCS+= arch/i386/prefix/lmelf_prefix.S
-SRCS+= arch/i386/prefix/elf_dprefix.S
-SRCS+= arch/i386/prefix/lmelf_dprefix.S
-SRCS+= arch/i386/prefix/comprefix.S
-SRCS+= arch/i386/prefix/exeprefix.S
-SRCS+= arch/i386/prefix/pxeprefix.S
-SRCS+= arch/i386/prefix/romprefix.S
-
-SRCS+= arch/i386/core/init.S
-SRCS+= arch/i386/core/start32.S
-SRCS+= arch/i386/core/pci_io.c
-SRCS+= arch/i386/core/i386_timer.c
-SRCS+= arch/i386/core/elf.c
-SRCS+= arch/i386/core/cpu.c
-SRCS+= arch/i386/core/video_subr.c
-SRCS+= arch/i386/core/pic8259.c
-SRCS+= arch/i386/core/hooks.c
-SRCS+= arch/i386/core/callbacks.c
-SRCS+= arch/i386/core/realmode.c
-SRCS+= arch/i386/core/realmode_asm.S
-SRCS+= arch/i386/core/pxe_callbacks.c
-
-# ROM loaders: ISA and PCI versions
-ISAPREFIX=     $(BIN)/isaprefix.o
-ISAENTRY=      $(BIN)/isaprefix.entry.o
-ISAEXIT=       $(BIN)/isaprefix.exit.o
-PCIPREFIX=     $(BIN)/pciprefix.o
-PCIENTRY=      $(BIN)/pciprefix.entry.o
-PCIEXIT=       $(BIN)/pciprefix.exit.o
-# Variables xxx_ROMTYPE are defined by genrules.pl.  ROMENTRY and
-# ROMEXIT will evaluate to give the correct objects to use.
-TARGETBASE=$(patsubst $(BIN)/%,%,$(firstword $(subst ., ,$@)))
-ROMCARD=$(firstword $(subst --, ,$(TARGETBASE)))
-ROMTYPE=$(firstword $(ROMTYPE_$(ROMCARD)) ISA)
-romENTRY=$($(ROMTYPE)ENTRY)
-romEXIT=$($(ROMTYPE)EXIT)
-
-# Target type for generic prf rules
-TARGETTYPE=$(patsubst .%,%, $(suffix $(basename $@)))
-TARGETENTRY=$($(TARGETTYPE)ENTRY)
-TARGETEXIT=$($(TARGETTYPE)EXIT)
-
-# Other real-mode entry loaders
-dskPREFIX=     $(BIN)/floppyprefix.o
-dskENTRY=      $(BIN)/floppyprefix.entry.o
-dskEXIT=       $(BIN)/floppyprefix.exit.o
-comPREFIX=     $(BIN)/comprefix.o
-comENTRY=      $(BIN)/comprefix.entry.o
-comEXIT=       $(BIN)/comprefix.exit.o
-exePREFIX=     $(BIN)/exeprefix.o
-exeENTRY=      $(BIN)/exeprefix.entry.o
-exeEXIT=       $(BIN)/exeprefix.exit.o
-liloPREFIX=    $(BIN)/liloprefix.o
-liloENTRY=     $(BIN)/liloprefix.entry.o
-liloEXIT=      $(BIN)/liloprefix.exit.o
-bImagePREFIX=  $(BIN)/bImageprefix.o
-bImageENTRY=   $(BIN)/bImageprefix.entry.o
-bImageEXIT=    $(BIN)/bImageprefix.exit.o
-pxePREFIX=     $(BIN)/pxeprefix.o
-pxeENTRY=      $(BIN)/pxeprefix.entry.o
-pxeEXIT=       $(BIN)/pxeprefix.exit.o
-rawPREFIX=     $(BIN)/nullprefix.o
-rawENTRY=      $(BIN)/nullprefix.entry.o
-rawEXIT=       $(BIN)/nullprefix.exit.o
-
-# Protected mode entry loaders
-elfPREFIX=     $(BIN)/elfprefix.o
-elfENTRY=      $(BIN)/elfprefix.entry.o
-elfEXIT=       $(BIN)/elfprefix.exit.o
-lmelfPREFIX=   $(BIN)/lmelf_prefix.o
-lmelfENTRY=    $(BIN)/lmelf_prefix.entry.o
-lmelfEXIT=     $(BIN)/lmelf_prefix.exit.o
-elfdPREFIX=    $(BIN)/elf_dprefix.o
-elfdENTRY=     $(BIN)/elf_dprefix.entry.o
-elfdEXIT=      $(BIN)/elf_dprefix.exit.o
-lmelfdPREFIX=  $(BIN)/lmelf_dprefix.o
-lmelfdENTRY=   $(BIN)/lmelf_dprefix.entry.o
-lmelfdEXIT=    $(BIN)/lmelf_dprefix.exit.o
-
-include                $(BIN)/Roms
-
-all:           $(ROMS)
-allroms:       $(ROMS)
-allzroms:      $(ROMS)
-alldsks:       $(EB_DSKS)
-allzdsks:      $(EB_ZDSKS)
-alllilos:      $(EB_LILOS)
-allzlilos:     $(EB_ZLILOS)
-allbImages:    $(EB_BIMAGES)
-allbzImages:   $(EB_BZIMAGES)
-allpxes:       $(EB_PXES)
-allzpxes:      $(EB_ZPXES)
-allelfs:       $(EB_ELFS)
-allzelfs:      $(EB_ZELFS)
-alllmelfs:     $(EB_LMELFS)
-allzlmelfs:    $(EB_ZLMELFS)
-allelfds:      $(EB_ELFDS)
-allzelfds:     $(EB_ZELFDS)
-alllmelfds:    $(EB_LMELFDS)
-allzlmelfds:   $(EB_ZLMELFDS)
-allcoms:       $(EB_COMS)
-allexes:       $(EB_EXES)
-allisos:       $(EB_ISOS)
-alllisos:      $(EB_LISOS)
-
-BOBJS+=                $(BIN)/pci_io.o $(BIN)/i386_timer.o
-BOBJS+=                $(BIN)/elf.o $(BIN)/cpu.o $(BIN)/video_subr.o
-BOBJS+=                $(BIN)/pic8259.o $(BIN)/hooks.o
-
-# ROM loaders
-
-$(ISAPREFIX):  arch/i386/prefix/romprefix.S $(MAKEDEPS)
-       $(CPP) $(CFLAGS) $(LCONFIG) -Ui386 -D ASSEMBLY $< \
-               | $(AS) $(ASFLAGS) -o $@ 
-
-$(PCIPREFIX):  arch/i386/prefix/romprefix.S $(MAKEDEPS)
-       $(CPP) -DPCI_PNP_HEADER $(CFLAGS) $(LCONFIG) -Ui386 -D ASSEMBLY $< \
-               | $(AS) $(ASFLAGS) -o $@ 
-
-# Prefix splitters
-$(BIN)/%prefix.entry.o: $(BIN)/%prefix.o $(MAKEDEPS)
-       $(OBJCOPY) -R .text16 $< $@
-
-$(BIN)/%prefix.exit.o: $(BIN)/%prefix.o $(MAKEDEPS)
-       $(OBJCOPY) -R .prefix $< $@
-
-# Generic prefix objects
-PREFIXOBJS = $(BIN)/init.o
-ZPREFIXOBJS = $(BIN)/init.o $(BIN)/unnrv2b.o
-
-# Utilities
-$(BIN)/nrv2b:  util/nrv2b.c
-       $(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
-
-ZFILELEN = perl util/zfilelen.pl
-
-# Pattern Rules
-
-# General for compiling/assembly source files
-
-$(BIN)/%.o:    arch/i386/core/%.c $(MAKEDEPS)
-       $(CC) $(CFLAGS) -o $@ -c $<
-
-$(BIN)/%.o:    arch/i386/core/%.S $(MAKEDEPS)
-       $(CPP) $(CFLAGS) -Ui386 -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
-
-$(BIN)/%.o:    arch/i386/firmware/pcbios/%.c $(MAKEDEPS)
-       $(CC) $(CFLAGS) -o $@ -c $<
-
-$(BIN)/%.o:    arch/i386/firmware/pcbios/%.S $(MAKEDEPS)
-       $(CPP) $(CFLAGS) -Ui386 -DASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
-
-$(BIN)/%.o:    arch/i386/prefix/%.S $(MAKEDEPS)
-       $(CPP) $(CFLAGS) -Ui386 -DASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
-
-$(BIN)/%16.o:  arch/i386/prefix/%.S $(MAKEDEPS)
-       $(CPP) $(CFLAGS) -Ui386 -DASSEMBLY -DCODE16 $< | $(AS) $(ASFLAGS) -o $@
-
-# general rule for 16bit .o, may be overridden
-$(BIN)/%.o:    $(BIN)/%.s
-       $(AS) $(ASFLAGS) -o $@ $<
-
-# general rule for .bin (plain binary loader code), may be overridden
-$(BIN)/%.bin:  $(BIN)/%.o
-       $(OBJCOPY) -O binary $< $@
-
-# general rule for .z (compressed binary code), may be overridden
-# rule for .z is in top level Makefile
-# Give the directory name, e.g. use $(BIN)/rtl8139.com as the target.
-
-$(BIN)/%.zo:   $(BIN)/%.zbin arch/i386/core/prefixzdata.lds $(MAKEDEPS)
-       $(LD) -T arch/i386/core/prefixzdata.lds -b binary $< -o $@
-
-$(BIN)/%.uo:   $(BIN)/%.bin arch/i386/core/prefixudata.lds $(MAKEDEPS)
-       $(LD) -T arch/i386/core/prefixudata.lds -b binary $< -o $@
-
-# Intermediate prf rules
-
-%.prf:  %.rt $(PREFIXOBJS) %.rt1.uo %.rt2.uo $(MAKEDEPS)
-       $(MAKE) $(TARGETENTRY)
-       $(LD) $(LDFLAGS) -T $(PLDSCRIPT) $(TARGETENTRY) -R $(subst $(MAKEDEPS),,$^)  -o $@ 
-
-%.zprf:  %.rt $(ZPREFIXOBJS) %.rt1.uo %.rt2.zo $(MAKEDEPS)
-       $(MAKE) $(TARGETENTRY)
-       $(LD) $(LDFLAGS) -T $(PLDSCRIPT) $(TARGETENTRY) -R $(subst $(MAKEDEPS),,$^)  -o $@ 
-
-# general rules for normal/compressed ROM images, may be overridden
-SUFFIXES +=    rom zrom
-
-$(BIN)/%.rom.rt: $(BIN)/%.rt.o  $(ISAENTRY) $(PCIENTRY) $(ISAEXIT) $(PCIEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(romEXIT) $<
-       @$(SIZE) $@ | $(CHECKSIZE)
-
-$(BIN)/%.rom: $(BIN)/%.rom.prf
-       $(OBJCOPY) -O binary $< $@
-       $(MAKEROM) $(MAKEROM_FLAGS) $(MAKEROM_$(ROMCARD)) $(MAKEROM_ID_$(ROMCARD)) -i$(IDENT) $@
-
-$(BIN)/%.zrom: $(BIN)/%.rom.zprf
-       $(OBJCOPY) -O binary $< $@
-       $(MAKEROM) $(MAKEROM_FLAGS) $(MAKEROM_$(ROMCARD)) $(MAKEROM_ID_$(ROMCARD)) -i$(IDENT) $@
-
-# general rules for ELF images
-SUFFIXES +=    elf zelf
-$(BIN)/%.elf.rt:  $(BIN)/%.rt.o $(elfENTRY) $(elfEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(elfEXIT)  $< 
-
-$(BIN)/%.elf: $(BIN)/%.elf.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zelf: $(BIN)/%.elf.zprf 
-       $(OBJCOPY) -O binary $< $@
-
-# general rules for Long Mode ELF images
-SUFFIXES +=    lmelf zlmelf
-$(BIN)/%.lmelf.rt: $(BIN)/%.rt.o $(lmelfENTRY) $(lmelfEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(lmelfEXIT) $<
-
-$(BIN)/%.lmelf: $(BIN)/%.lmelf.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zlmelf: $(BIN)/%.lmelf.zprf
-       $(OBJCOPY) -O binary $< $@
-
-# general rules for ELF dynamic images
-SUFFIXES +=    elfd zelfd
-$(BIN)/%.elfd.rt: $(BIN)/%.rt.o $(elfdENTRY) $(elfdEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(elfdEXIT) $<
-
-$(BIN)/%.elfd: $(BIN)/%.elfd.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zelfd: $(BIN)/%.elfd.zprf
-       $(OBJCOPY) -O binary $< $@
-
-# general rules for Long Mode ELF dynamic images
-SUFFIXES +=    lmelfd zlmelfd
-$(BIN)/%.lmelfd.rt: $(BIN)/%.rt.o $(lmelfdENTRY) $(lmelfdEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $(lmelfdEXIT) $<
-
-$(BIN)/%.lmelfd: $(BIN)/%.lmelfd.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zlmelfd: $(BIN)/%.lmelfd.zprf
-       $(OBJCOPY) -O binary $< $@
-
-# rules to generate a DOS loadable .com executable
-SUFFIXES +=    com
-$(BIN)/%.com.rt: $(BIN)/%.rt.o $(comENTRY) $(comEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(comEXIT)
-
-$(BIN)/%.com: $(BIN)/%.com.zprf
-       $(OBJCOPY) -O binary $< $@
-
-# rules to generate a DOS loadable .exe executable
-SUFFIXES +=    exe
-$(BIN)/%.exe.rt: $(BIN)/%.rt.o $(exeENTRY) $(exeEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(exeEXIT)
-       @$(SIZE) $@ | $(CHECKSIZE)
-
-$(BIN)/%.exe: $(BIN)/%.exe.prf
-       $(OBJCOPY) -O binary $< $@
-
-# rules to make a LILO loadable image
-SUFFIXES +=    lilo zlilo
-
-$(BIN)/%.lilo.rt: $(BIN)/%.rt.o $(liloENTRY) $(liloEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(liloEXIT)
-       @$(SIZE) $@ | $(CHECKSIZE)
-
-$(BIN)/%.lilo: $(BIN)/%.lilo.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zlilo: $(BIN)/%.lilo.zprf
-       $(OBJCOPY) -O binary $< $@
-
-# rules to make big linux boot protocol image
-SUFFIXES +=    bImage bzImage
-
-$(BIN)/%.bImage.rt: $(BIN)/%.rt.o $(bImageENTRY) $(bImageEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(bImageEXIT)
-
-$(BIN)/%.bImage: $(BIN)/%.bImage.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.bzImage: $(BIN)/%.bImage.zprf
-       $(OBJCOPY) -O binary $< $@
-
-
-# rules to generate a PXE loadable image
-SUFFIXES +=    pxe zpxe
-
-$(BIN)/%.pxe.rt: $(BIN)/%.rt.o $(pxeENTRY) $(pxeEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(pxeEXIT)
-       @$(SIZE) $@ | $(CHECKSIZE)
-
-$(BIN)/%.pxe: $(BIN)/%.pxe.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zpxe: $(BIN)/%.pxe.zprf
-       $(OBJCOPY) -O binary $< $@
-
-# rules to generate the .dsk/.zdsk floppy images
-SUFFIXES +=    dsk zdsk
-
-$(BIN)/%.dsk.rt: $(BIN)/%.rt.o $(dskENTRY) $(dskEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(dskEXIT)
-       @$(SIZE) $@ | $(CHECKSIZE)
-
-$(BIN)/%.dsk: $(BIN)/%.dsk.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zdsk: $(BIN)/%.dsk.zprf
-       $(OBJCOPY) -O binary $< $@
-
-# rules to write the .dsk/.zdsk image onto a blank floppy
-SUFFIXES +=    fd0 zfd0
-%.fd0: %.dsk
-       dd if=$< bs=512 conv=sync of=/dev/fd0
-       sync
-
-%.zfd0:        %.zdsk
+# i386-specific directories containing source files
+#
+SRCDIRS                += arch/i386/core arch/i386/transitions arch/i386/prefix
+SRCDIRS                += arch/i386/firmware/pcbios arch/i386/firmware/linuxbios
+SRCDIRS                += arch/i386/drivers/net
+
+# The various xxx_loader.c files are #included into core/loader.c and
+# should not be compiled directly.
+#
+NON_AUTO_SRCS  += arch/i386/core/aout_loader.c
+NON_AUTO_SRCS  += arch/i386/core/freebsd_loader.c
+NON_AUTO_SRCS  += arch/i386/core/multiboot_loader.c
+NON_AUTO_SRCS  += arch/i386/core/tagged_loader.c
+NON_AUTO_SRCS  += arch/i386/core/wince_loader.c
+
+# setup.S and unnrv2b.S are both used to generate 16-bit as well as
+# 32-bit objects.
+#
+OBJS_setup             = setup setup16
+CFLAGS_setup16         = -DCODE16
+OBJS_unnrv2b           = unnrv2b unnrv2b16
+CFLAGS_unnrv2b16       = -DCODE16
+
+# hooks.c is used to generate hooks.o and hooks_rm.o
+#
+OBJS_hooks             = hooks hooks_rm
+CFLAGS_hooks_rm                = -DREALMODE
+
+# We need to undefine the default macro "i386" when compiling .S
+# files, otherwise ".arch i386" translates to ".arch 1"...
+#
+CFLAGS_S               += -Ui386
+
+# The i386 linker script
+#
+LDSCRIPT               = arch/i386/scripts/i386.lds
+
+# Media types.
+# 
+# It's ugly that we have to define these repetitive combinations by
+# hand.  Unforunately, $(eval ...) is available only in make >= 3.80,
+# and using an external Makefile fragment doesn't work because
+# OBJS_xxx need to be defined *before* the external Makefile fragments
+# for the source files are generated...
+
+CFLAGS_ZPREFIX         = -DCOMPRESS
+
+MEDIA                  += rom
+OBJS_romprefix         = isaprefix zisaprefix pciprefix zpciprefix
+CFLAGS_isaprefix       =
+CFLAGS_zisaprefix      = $(CFLAGS_ZPREFIX)
+CFLAGS_pciprefix       = -DPCI_PNP_HEADER
+CFLAGS_zpciprefix      = $(CFLAGS_pciprefix) $(CFLAGS_ZPREFIX)
+
+MEDIA                  += pxe
+OBJS_pxeprefix         = pxeprefix zpxeprefix
+CFLAGS_zpxeprefix      = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += elf
+OBJS_elfprefix         = elfprefix zelfprefix
+CFLAGS_zelfprefix      = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += elfd
+OBJS_elfdprefix                = elfdprefix zelfdprefix
+CFLAGS_zelfdprefix     = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += lmelf
+OBJS_lmelfprefix       = lmelfprefix zlmelfprefix
+CFLAGS_zlmelfprefix    = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += lmelfd
+OBJS_lmelfdprefix      = lmelfdprefix zlmelfdprefix
+CFLAGS_zlmelfdprefix   = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += lilo
+OBJS_liloprefix                = liloprefix zliloprefix
+CFLAGS_zliloprefix     = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += bImage
+OBJS_bImageprefix      = bImageprefix zbImageprefix
+CFLAGS_zbImageprefix   = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += dsk
+OBJS_dskprefix         = dskprefix zdskprefix
+CFLAGS_zdskprefix      = $(CFLAGS_ZPREFIX)
+
+MEDIA                  += raw
+OBJS_rawprefix         = rawprefix zrawprefix
+CFLAGS_zrawprefix      = $(CFLAGS_ZPREFIX)
+
+# These media cannot handle compressed payloads
+
+MEDIA                  += com
+
+MEDIA                  += exe
+
+# Some suffixes (e.g. %.zfd0) are generated directly from other
+# finished files (e.g. %.zdsk), rather than having their own prefix.
+
+# rule to write disk images to /dev/fd0
+NON_AUTO_MEDIA         += fd0
+%fd0 : %dsk
        dd if=$< bs=512 conv=sync of=/dev/fd0
        sync
 
-# rules to create raw executable images
-SUFFIXES +=    raw zraw
-$(BIN)/%.raw.rt: $(BIN)/%.rt.o $(rawENTRY) $(rawEXIT) $(LDSCRIPT) $(MAKEDEPS)
-       $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $@ $< $(rawEXIT)
-
-$(BIN)/%.raw: $(BIN)/%.raw.prf
-       $(OBJCOPY) -O binary $< $@
-
-$(BIN)/%.zraw: $(BIN)/%.raw.zprf
-       $(OBJCOPY) -O binary $< $@
-
 # rule to make a non-emulation ISO boot image
-SUFFIXES +=    iso
-%.iso: util/geniso %.zlilo
-       ISOLINUX_BIN=${ISOLINUX_BIN} bash util/geniso $*.iso $*.zlilo
+NON_AUTO_MEDIA         += iso
+%iso:  %lilo util/geniso
+       ISOLINUX_BIN=$(ISOLINUX_BIN) bash util/geniso $@ $<
 
 # rule to make a floppy emulation ISO boot image
-SUFFIXES +=    liso
-%.liso:        util/genliso %.zlilo
-       bash util/genliso $*.liso $*.zlilo
-
+NON_AUTO_MEDIA         += liso
+%liso: %lilo util/genliso
+       bash util/genliso $@ $<
+
+# Add NON_AUTO_MEDIA to the media list, so that they show up in the
+# output of "make"
+#
+MEDIA          += $(NON_AUTO_MEDIA)
+
+# Shortcut to allow typing just
+#   make bin-kir/%
+# rather than
+#   make -f arch/i386/kir-Makefile bin-kir/%
+# for building a KEEP_IT_REAL flavour.
+#
+$(BIN)-kir/% : kir-target
+       $(MAKE) -f arch/i386/kir-Makefile $(MAKECMDGOALS)
+
+.PHONY : kir-target
diff --git a/src/arch/i386/README.i386 b/src/arch/i386/README.i386
new file mode 100644 (file)
index 0000000..b9b79cc
--- /dev/null
@@ -0,0 +1,197 @@
+Etherboot/NILO i386 initialisation path and external call interface
+===================================================================
+
+1. Background
+
+GCC compiles 32-bit code.  It is capable of producing
+position-independent code, but the resulting binary is about 25%
+bigger than the corresponding fixed-position code.  Since one main use
+of Etherboot is as firmware to be burned into an EPROM, code size must
+be kept as small as possible.
+
+This means that we want to compile fixed-position code with GCC, and
+link it to have a predetermined start address.  The problem then is
+that we must know the address that the code will be loaded to when it
+runs.  There are several ways to solve this:
+
+1. Pick an address, link the code with this start address, then make
+   sure that the code gets loaded at that location.  This is
+   problematic, because we may pick an address that we later end up
+   wanting to use to load the operating system that we're booting.
+
+2. Pick an address, link the code with this start address, then set up
+   virtual addressing so that the virtual addresses match the
+   link-time addresses regardless of the real physical address that
+   the code is loaded to.  This enables us to relocate Etherboot to
+   the top of high memory, where it will be out of the way of any
+   loading operating system.
+
+3. Link the code with a text start address of zero and a data start
+   address also of zero.  Use 16-bit real mode and the
+   quasi-position-independence it gives you via segment addressing.
+   Doing this requires that we generate 16-bit code, rather than
+   32-bit code, and restricts us to a maximum of 64kB in each segment.
+
+There are other possible approaches (e.g. including a relocation table
+and code that performs standard dynamic relocation), but the three
+options listed above are probably the best available.
+
+Etherboot can be invoked in a variety of ways (ROM, floppy, as a PXE
+NBP, etc).  Several of these ways involve control being passed to
+Etherboot with the CPU in 16-bit real mode.  Some will involve the CPU
+being in 32-bit protected mode, and there's an outside chance that
+some may involve the CPU being in 16-bit protected mode.  We will
+almost certainly have to effect a CPU mode change in order to reach
+the mode we want to be in to execute the C code.
+
+Additionally, Etherboot may wish to call external routines, such as
+BIOS interrupts, which must be called in 16-bit real mode.  When
+providing a PXE API, Etherboot must provide a mechanism for external
+code to call it from 16-bit real mode.
+
+Not all i386 builds of Etherboot will want to make real-mode calls.
+For example, when built for LinuxBIOS rather than the standard PCBIOS,
+no real-mode calls are necessary.
+
+For the ultimate in PXE compatibility, we may want to build Etherboot
+to run permanently in real mode.
+
+There is a wide variety of potential combinations of mode switches
+that we may wish to implement.  There are additional complications,
+such as the inability to access a high-memory stack when running in
+real mode.
+
+2. Transition libraries
+
+To handle all these various combinations of mode switches, we have
+several "transition" libraries in Etherboot.  We also have the concept
+of an "internal" and an "external" environment.  The internal
+environment is the environment within which we can execute C code.
+The external environment is the environment of whatever external code
+we're trying to interface to, such as the system BIOS or a PXE NBP.
+
+As well as having a separate addressing scheme, the internal
+environment also has a separate stack.
+
+The transition libraries are:
+
+a) librm
+
+librm handles transitions between an external 16-bit real-mode
+environment and an internal 32-bit protected-mode environment with
+virtual addresses.
+
+b) libkir
+
+libkir handles transitions between an external 16-bit real-mode (or
+16:16 or 16:32 protected-mode) environment and an internal 16-bit
+real-mode (or 16:16 protected-mode) environment.
+
+c) libpm
+
+libpm handles transitions between an external 32-bit protected-mode
+environment with flat physical addresses and an internal 32-bit
+protected-mode environment with virtual addresses.
+
+The transition libraries handle the transitions required when
+Etherboot is started up for the first time, the transitions required
+to execute any external code, and the transitions required when
+Etherboot exits (if it exits).  When Etherboot provides a PXE API,
+they also handle the transitions required when a PXE client makes a
+PXE API call to Etherboot.
+
+Etherboot may use multiple transition libraries.  For example, an
+Etherboot ELF image does not require librm for its initial transitions
+from prefix to runtime, but may require librm for calling external
+real-mode functions.
+
+3. Setup and initialisation
+
+Etherboot is conceptually divided into the prefix, the decompressor,
+and the runtime image.  (For non-compressed images, the decompressor
+is a no-op.)  The complete image comprises all three parts and is
+distinct from the runtime image, which exclude the prefix and the
+decompressor.
+
+The prefix does several tasks:
+
+  Load the complete image into memory.  (For example, the floppy
+  prefix issues BIOS calls to load the remainder of the complete image
+  from the floppy disk into RAM, and the ISA ROM prefix copies the ROM
+  contents into RAM for faster access.)
+
+  Call the decompressor, if the runtime image is compressed.  This
+  decompresses the runtime image.
+
+  Call the runtime image's setup() routine.  This is a routine
+  implemented in assembly code which sets up the internal environment
+  so that C code can execute.
+
+  Call the runtime image's arch_initialise() routine.  This is a
+  routine implemented in C which does some basic startup tasks, such
+  as initialising the console device, obtaining a memory map and
+  relocating the runtime image to high memory.
+
+  Call the runtime image's arch_main() routine.  This records the exit
+  mechanism requested by the prefix and calls main().  (The prefix
+  needs to register an exit mechanism because by the time main()
+  returns, the memory occupied by the prefix has most likely been
+  overwritten.)
+
+When acting as a PXE ROM, the ROM prefix contains an UNDI loader
+routine in addition to its usual code.  The UNDI loader performs a
+similar sequence of steps:
+
+  Load the complete image into memory.
+
+  Call the decompressor.
+
+  Call the runtime image's setup() routine.
+
+  Call the runtime image's arch_initialise() routine.
+
+  Call the runtime image's install_pxe_stack() routine.
+
+  Return to caller.
+
+The runtime image's setup() routine will perform the following steps:
+
+  Switch to the internal environment using an appropriate transition
+  library.  This will record the parameters of the external
+  environment.
+
+  Set up the internal environment: load a stack, and set up a GDT for
+  virtual addressing if virtual addressing is to be used.
+
+  Switch back to the external environment using the transition
+  library.  This will record the parameters of the internal
+  environment.
+
+Once the setup() routine has returned, the internal environment has been
+set up ready for C code to run.  The prefix can call C routines using
+a function from the transition library.
+
+The runtime image's arch_initialise() routine will perform the
+following steps:
+
+  Zero the bss
+
+  Initialise the console device(s) and print a welcome message.
+
+  Obtain a memory map via the INT 15,E820 BIOS call or suitable
+  fallback mechanism. [not done if libkir is being used]
+
+  Relocate the runtime image to the top of high memory. [not done if
+  libkir is being used]
+
+  Install librm to base memory. [done only if librm is being used]
+
+  Call initialise().
+
+  Return to the prefix, setting registers to indicate to the prefix
+  the new location of the transition library, if applicable.  Which
+  registers these are is specific to the transition library being
+  used.
+
+Once the arch_initialise() routine has returned, the prefix will
+probably call arch_main().
index d45e63e221806f2e0d78297f48ab0d96ead437b3..8818e146b369f90b42f2bee829c299015fc82688 100644 (file)
@@ -9,7 +9,6 @@
 #include "etherboot.h"
 #include "callbacks.h"
 #include "realmode.h"
-#include "segoff.h"
 #include <stdarg.h>
 
 /* Maximum amount of stack data that prefix may request to be passed
index 8a0f73337e59fd027732e4ed0a8d54d46b4681ac..7b2533f46c09cc4e14215dde09963aad37923617 100644 (file)
@@ -2,6 +2,7 @@
 #include "stdint.h"
 #include "string.h"
 #include "bits/cpu.h"
+#include "init.h"
 
 
 /* Standard macro to see if a specific flag is changeable */
@@ -83,4 +84,7 @@ void cpu_setup(void)
 {
        identify_cpu(&cpu_info);
 }
+
+INIT_FN ( INIT_CPU, cpu_setup, NULL, NULL );
+
 #endif /* CONFIG_X86_64 */
index 6ef78c7142d715fd7aef4d7afd14dfa639ba139d..40a18a1f04ce232fcd07b3fa243cdc5493ca3008 100644 (file)
@@ -1,5 +1,6 @@
 #include "etherboot.h"
 #include "elf.h"
+#include "memsizes.h"
 
 
 #define NAME "Etherboot"
index 9ca6f480cb781d17db353d55269a0f76b792debf..32a137b1c70f037a8755f1be3a8b9e028d088ac8 100644 (file)
@@ -1,35 +1,93 @@
-#include "etherboot.h"
-#include "callbacks.h"
-#include <stdarg.h>
-
-void arch_main ( in_call_data_t *data __unused, va_list params __unused )
-{
-#ifdef PCBIOS
-       /* Deallocate base memory used for the prefix, if applicable
-        */
-       forget_prefix_base_memory();
+#include "stdint.h"
+#include "stddef.h"
+#include "registers.h"
+#include "string.h"
+#include "hooks.h"
+#include "init.h"
+#include "main.h"
+#ifdef REALMODE
+#include "realmode.h"
 #endif
 
-}
+/* Symbols defined by the linker */
+extern char _bss[], _ebss[];
+
+/*
+ * This file provides the basic entry points from assembly code.  See
+ * README.i386 for a description of the entry code path.
+ *
+ * This file is compiled to two different object files: hooks.o and
+ * hooks_rm.o.  REALMODE is defined when compiling hooks_rm.o
+ *
+ */
 
-void arch_relocated_from (unsigned long old_addr )
+/*
+ * arch_initialise(): perform any required initialisation such as
+ * setting up the console device and relocating to high memory.  Note
+ * that if we relocate to high memory and the prefix is in base
+ * memory, then we will need to install a copy of librm in base memory
+ * and adjust retaddr so that we return to the installed copy.
+ *
+ */
+#ifdef REALMODE
+void arch_rm_initialise ( struct i386_all_regs *regs,
+                         void (*retaddr) (void) )
+#else /* REALMODE */
+void arch_initialise ( struct i386_all_regs *regs,
+                      void (*retaddr) (void) __unused )
+#endif /* REALMODE */
 {
+       /* Zero the BSS */
+       memset ( _bss, 0, _ebss - _bss );
 
-#ifdef PCBIOS
-       /* Deallocate base memory used for the Etherboot runtime,
-        * if applicable
+       /* Call all registered initialisation functions.
         */
-       forget_runtime_base_memory( old_addr );
-#endif
-
+       call_init_fns ();
 }
 
-void arch_on_exit ( int exit_status __unused ) 
-{
-#ifdef PCBIOS
-       /* Deallocate the real-mode stack now.  We will reallocate
-        * the stack if are going to use it after this point.
+#ifdef REALMODE
+
+/*
+ * arch_rm_main() : call main() and then exit via whatever exit mechanism
+ * the prefix requested.
+ *
+ */
+void arch_rm_main ( struct i386_all_regs *regs ) {
+       struct i386_all_regs regs_copy;
+       void (*exit_fn) ( struct i386_all_regs *regs );
+
+       /* Take a copy of the registers, because the memory holding
+        * them will probably be trashed by the time main() returns.
         */
-       forget_real_mode_stack();
-#endif
+       regs_copy = *regs;
+       exit_fn = ( typeof ( exit_fn ) ) regs_copy.eax;
+
+       /* Call to main() */
+       regs_copy.eax = main();
+
+       /* Call registered per-object exit functions */
+       call_exit_fns ();
+
+       if ( exit_fn ) {
+               /* Prefix requested that we use a particular function
+                * as the exit path, so we call this function, which
+                * must not return.
+                */
+               exit_fn ( &regs_copy );
+       }
 }
+
+#else /* REALMODE */
+
+/*
+ * arch_main() : call main() and return
+ *
+ */
+void arch_main ( struct i386_all_regs *regs ) {
+       regs->eax = main();
+
+       /* Call registered per-object exit functions */
+       call_exit_fns ();
+};
+
+#endif /* REALMODE */
index 531183d4cdacef80ec25d853a0f399543a801afe..c9aa406f9482d17715ab365d6826a4613469ace0 100644 (file)
@@ -10,6 +10,7 @@
 #include       "etherboot.h"
 #include       "timer.h"
 #include       "latch.h"
+#include       "init.h"
 
 void __load_timer2(unsigned int ticks)
 {
@@ -40,7 +41,7 @@ static int __timer2_running(void)
 }
 
 #if !defined(CONFIG_TSC_CURRTICKS)
-void setup_timers(void)
+static void setup_timers(void)
 {
        return;
 }
@@ -126,7 +127,7 @@ bad_ctc:
 }
 
 static unsigned long clocks_per_tick;
-void setup_timers(void)
+static void setup_timers(void)
 {
        if (!clocks_per_tick) {
                clocks_per_tick = calibrate_tsc();
@@ -189,3 +190,5 @@ int timer2_running(void)
 }
 
 #endif /* RTC_CURRTICKS */
+
+INIT_FN ( INIT_TIMERS, setup_timers, NULL, NULL );
diff --git a/src/arch/i386/core/init.S b/src/arch/i386/core/init.S
deleted file mode 100644 (file)
index 71717c2..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-#include "callbacks.h"
-       .equ CR0_PE, 1
-       
-       .text
-       .arch i386
-       .section ".prefix", "ax", @progbits
-
-#undef CODE16
-#if defined(PCBIOS)
-#define        CODE16
-#endif
-
-/* We have two entry points: "conventional" (at the start of the file)
- * and "callback" (at _entry, 2 bytes in).  The "callback" entry
- * should be used if the caller wishes to provide a specific opcode.
- * It is equivalent to a call to in_call.  Using the "conventional"
- * entry point is equivalent to using the "callback" entry point with
- * an opcode of EB_OPCODE_MAIN.
- *
- * Both entry points can be called in either 16-bit real or 32-bit
- * protected mode with flat physical addresses.  We detect which mode
- * the processor is in and call either in_call or rm_in_call as
- * appropriate.  Note that the mode detection code must therefore be
- * capable of doing the same thing in either mode, even though the
- * machine code instructions will be interpreted differently.
- *
- * The decompressor will be invoked if necessary to decompress
- * Etherboot before attempting to jump to it.
- */
-
-/******************************************************************************
- * Entry points and mode detection code
- ******************************************************************************
- */
-
-       .code32
-/* "Conventional" entry point: caller provides no opcode */
-       .globl  _start
-_start:
-       /* Set flag to indicate conventional entry point used */
-       pushl   $0                      /* "pushw $0" in 16-bit code */
-       /* Fall through to "callback" entry point */
-       
-/* "Callback" entry point */
-       .globl  _entry
-_entry:
-       
-#ifdef CODE16
-       /* CPU mode detection code */
-       pushl   %eax                    /* "pushw %ax" in 16-bit code */
-       pushw   %ax                     /* "pushl %eax" in 16-bit code */
-       movl    %cr0, %eax              /* Test protected mode bit */
-       testb   $CR0_PE, %al
-       popw    %ax                     /* "popl %eax" in 16-bit code */
-       popl    %eax                    /* "popw %eax" in 16-bit code */
-       jz      rmode
-#endif /* CODE16 */
-
-/******************************************************************************
- * Entered in protected mode
- ******************************************************************************
- */
-               
-       .code32
-pmode:
-       cmpl    $0, 0(%esp)             /* Conventional entry point used? */
-       jne     1f
-       /* Entered via conventional entry point: set up stack */
-       xchgl   %eax, 4(%esp)           /* %eax = return addr, store %eax */
-       movl    %eax, 0(%esp)           /* 0(%esp) = return address */
-       movl    $(EB_OPCODE_MAIN|EB_USE_INTERNAL_STACK|EB_SKIP_OPCODE), %eax
-       xchgl   %eax, 4(%esp)           /* 4(%esp) = opcode, restore %eax */
-1:
-       /* Run decompressor if necessary */
-       pushl   %eax
-       movl    $decompress, %eax
-       testl   %eax, %eax
-       jz      1f
-       call    decompress
-1:     popl    %eax
-
-       /* Make in_call to Etherboot */
-       jmp     _prefix_in_call
-
-/******************************************************************************
- * Entered in real mode
- ******************************************************************************
- */
-       
-#ifdef CODE16
-       .code16
-rmode:
-       pushw   %ax                     /* Padding */
-       pushw   %bp
-       movw    %sp, %bp
-       cmpw    $0, 6(%bp)              /* Conventional entry point used? */
-       jne     1f
-       /* Entered via conventional entry point: set up stack */
-       pushw   %ax
-       movw    6(%bp), %ax
-       movw    %ax, 2(%bp)             /* Move return address down */
-       movl    $(EB_OPCODE_MAIN|EB_USE_INTERNAL_STACK|EB_SKIP_OPCODE), 4(%bp)
-       popw    %ax
-       popw    %bp
-       jmp     2f
-1:     /* Entered via callback entry point: do nothing */
-       popw    %bp
-       popw    %ax
-2:
-       /* Preserve registers */
-       pushw   %ds
-       pushl   %eax
-       
-       /* Run decompressor if necessary.  Decompressor is 32-bit
-        * code, so we must switch to pmode first.  Save and restore
-        * GDT over transition to pmode.
-        */
-       movl    $decompress, %eax
-       testl   %eax, %eax
-       jz      1f
-       pushw   %ds
-       pushw   %es
-       pushw   %fs
-       pushw   %gs
-       subw    $8, %sp
-       pushw   %bp
-       movw    %sp, %bp
-       sgdt    2(%bp)
-       pushw   %ss                     /* Store params for _prot_to_real */
-       pushw   %cs
-       call    _prefix_real_to_prot
-       .code32
-       call    decompress
-       call    _prefix_prot_to_real
-       .code16
-       popw    %ax                     /* skip */
-       popw    %ax                     /* skip */
-       lgdt    2(%bp)
-       popw    %bp
-       addw    $8, %sp
-       popw    %gs
-       popw    %fs
-       popw    %es
-       popw    %ds
-1:
-
-       /* Set rm_etherboot_location */
-       xorl    %eax, %eax
-       movw    %cs, %ax
-       movw    %ax, %ds
-       shll    $4, %eax
-       addl    $_prefix_size, %eax
-       movl    %eax, _prefix_rm_etherboot_location
-
-       /* Restore registers */
-       popl    %eax
-       popw    %ds
-
-       /* Make real-mode in_call to Etherboot */
-       jmp     _prefix_rm_in_call
-#endif /* CODE16 */
-
-/******************************************************************************
- * Utility routines that can be called by the "prefix".
- ******************************************************************************
- */
-
-#ifdef CODE16
-
-/* Prelocate code: either to an area at the top of free base memory.
- * Switch stacks to use the stack within the resulting
- * Etherboot image.
- *
- * On entry, %cs:0000 must be the start of the prefix: this is used to
- * locate the code to be copied.
- *
- * This routine takes a single word parameter: the number of bytes to
- * be transferred from the old stack to the new stack (excluding the
- * return address and this parameter itself, which will always be
- * copied).  If this value is negative, the stacks will not be
- * switched.
- *
- * Control will "return" to the appropriate point in the relocated
- * image.
- */
-
-#define PRELOC_PRESERVE ( 20 )
-#define PRELOC_OFFSET_RETADDR ( PRELOC_PRESERVE )
-#define PRELOC_OFFSET_RETADDR_E ( PRELOC_OFFSET_RETADDR + 4 )
-#define PRELOC_OFFSET_COPY ( PRELOC_OFFSET_RETADDR_E )
-#define PRELOC_OFFSET_COPY_E ( PRELOC_OFFSET_COPY + 2 )
-
-#define PRELOC_ALWAYS_COPY ( PRELOC_OFFSET_COPY_E )
-       
-       .code16
-       .globl  prelocate
-prelocate:
-       /* Pad to allow for expansion of return address */
-       pushw   %ax
-       
-       /* Preserve registers */
-       pushaw
-       pushw   %ds
-       pushw   %es
-       
-       /* Claim an area of base memory from the BIOS and put the
-        * payload there.
-        */
-       movw    $0x40, %bx
-       movw    %bx, %es
-       movw    %es:(0x13), %bx         /* FBMS in kb to %ax */
-       shlw    $6, %bx                 /* ... in paragraphs */
-       subw    $_image_size_pgh, %bx   /* Subtract space for image */
-       shrw    $6, %bx                 /* Round down to nearest kb */
-       movw    %bx, %es:(0x13)         /* ...and claim memory from BIOS */
-       shlw    $6, %bx
-
-       /* At this point %bx contains the segment address for the
-        * start of the image (image = prefix + runtime).
-        */
-
-       /* Switch stacks */
-       movw    %ss, %ax
-       movw    %ax, %ds
-       movw    %sp, %si                /* %ds:si = current %ss:sp */
-       movw    %ss:PRELOC_OFFSET_COPY(%si), %cx
-       testw   %cx, %cx
-       js      1f
-       leaw    _stack_offset_pgh(%bx), %ax /* %ax = new %ss */
-       movw    %ax, %es
-       movw    $_stack_size, %di
-       addw    $PRELOC_ALWAYS_COPY, %cx
-       subw    %cx, %di                /* %es:di = new %ss:sp */
-       movw    %ax, %ss                /* Set new %ss:sp */
-       movw    %di, %sp
-       cld
-       rep movsb                       /* Copy stack contents */
-1:     
-
-       /* Do the image copy backwards, since if there's overlap with
-        * a forward copy then it means we're going to get trashed
-        * during the copy anyway...
-        */
-       pushal                          /* Preserve 32-bit registers */
-       movw    %bx, %es                /* Destination base for copy */
-       pushw   %cs
-       popw    %ds                     /* Source base for copy */
-       movl    $_verbatim_size-1, %ecx /* Offset to last byte */
-       movl    %ecx, %esi
-       movl    %ecx, %edi
-       incl    %ecx                    /* Length */
-       std                             /* Backwards copy of binary */
-       ADDR32 rep movsb
-       cld
-       popal                           /* Restore 32-bit registers */
-
-       /* Store (%bx<<4) as image_basemem to be picked up by
-        * basemem.c.  Also store image_size, since there's no other
-        * way that we can later know how much memory we allocated.
-        * (_zfile_size is unavailable when rt2 is linked).
-        */
-       pushl   %eax
-       xorl    %eax, %eax
-       movw    %bx, %ax
-       shll    $4, %eax
-       movl    %eax, %es:_prefix_image_basemem
-       movl    $_image_size, %es:_prefix_image_basemem_size
-       popl    %eax
-
-       /* Expand original near return address into far return to new
-        * code location.
-        */
-       movw    %sp, %bp
-       xchgw   %bx, (PRELOC_OFFSET_RETADDR+2)(%bp)
-       movw    %bx, (PRELOC_OFFSET_RETADDR+0)(%bp)
-
-       /* Restore registers and return */
-       popw    %es
-       popw    %ds
-       popaw
-       lret                            /* Jump to relocated code */
-
-       /* Utility routine to free base memory allocated by prelocate.
-        * Ensure that said memory is not in use (e.g. for the CPU
-        * stack) before calling this routine.
-        */
-       .globl deprelocate
-deprelocate:   
-       /* Claim an area of base memory from the BIOS and put the
-        * payload there.
-        */
-       pushw   %ax
-       pushw   %es
-       movw    $0x40, %ax
-       movw    %ax, %es
-       movw    %es:(0x13), %ax         /* FBMS in kb to %ax */
-       shlw    $6, %ax                 /* ... in paragraphs */
-       addw    $_image_size_pgh+0x40-1, %ax /* Add space for image and... */
-       shrw    $6, %ax                 /* ...round up to nearest kb */
-       movw    %ax, %es:(0x13)         /* Give memory back to BIOS */
-       popw    %es
-       popw    %ax
-       ret
-       
-#endif /* CODE16 */
index 344d34fefc8c277afd64ed43ecb3c51e456dff6b..df52232923bee2f05a1b579a16f3b525987fb0f3 100644 (file)
@@ -3,6 +3,31 @@
  * an NBP to the PXE stack and for starting an NBP from the PXE stack.
  */
 
+#warning "pxe_callbacks.c is temporarily broken"
+
+void xstartpxe ( void ) {
+}
+
+void install_pxe_stack ( void ) {
+}
+
+void remove_pxe_stack ( void ) {
+}
+
+void hook_pxe_stack ( void ) {
+}
+
+void unhook_pxe_stack ( void ) {
+}
+
+void pxe_in_call ( void ) {
+}
+
+void use_undi_ds_for_rm_stack ( void ) {
+}
+
+#if 0
+
 #ifdef PXE_EXPORT
 
 #include "etherboot.h"
@@ -362,3 +387,5 @@ __asm__ ( ".globl _pxe_stack_t_size" );
 __asm__ ( ".equ _pxe_stack_t_size, 0" );
 
 #endif /* PXE_EXPORT */
+
+#endif /* 0 */
index ef4ede86c2d15853b144e3298ac6540dcbaaa9c3..32252bd3bca295629be04b868ac4923766d46eae 100644 (file)
  * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
  */
 
-#include "etherboot.h"
 #include "realmode.h"
-#include "segoff.h"
 
-#define RM_STACK_SIZE ( 0x1000 )
-
-/* gcc won't let us use extended asm outside a function (compiler
- * bug), ao we have to put these asm statements inside a dummy
- * function.
- */
-static void work_around_gcc_bug ( void ) __attribute__ ((used));
-static void work_around_gcc_bug ( void ) {
-       /* Export _real_mode_stack_size as absolute linker symbol */
-       __asm__ ( ".globl _real_mode_stack_size" );
-       __asm__ ( ".equ _real_mode_stack_size, %c0" : : "i" (RM_STACK_SIZE) );
-}
-
-/* While Etherboot remains in base memory the real-mode stack is
- * placed in the Etherboot main stack.  The first allocation or
- * deallocation of base memory will cause a 'proper' real-mode stack
- * to be allocated.  This will happen before Etherboot is relocated to
- * high memory.
- */
-uint32_t real_mode_stack = 0;
-size_t real_mode_stack_size = RM_STACK_SIZE;
-int lock_real_mode_stack = 0;  /* Set to make stack immobile */
-
-/* Make a call to a real-mode code block.
- */
-
-/* These is the structure that exists on the stack as the paramters
- * passed in to _real_call.  We pass a pointer to this struct to
- * prepare_real_call(), to save stack space.
+/*
+ * Copy data to/from base memory.
+ *
  */
-typedef struct {
-       void *fragment;
-       int fragment_len;
-       void *in_stack;
-       int in_stack_len;
-       void *out_stack;
-       int out_stack_len;
-} real_call_params_t;
 
-uint32_t prepare_real_call ( real_call_params_t *p,
-                            int local_stack_len, char *local_stack ) {
-       char *stack_base;
-       char *stack_end;
-       char *stack;
-       char *s;
-       prot_to_real_params_t *p2r_params;
-       real_to_prot_params_t *r2p_params;
+#ifdef KEEP_IT_REAL
 
-       /* Work out where we're putting the stack */
-       if ( virt_to_phys(local_stack) < 0xa0000 ) {
-               /* Current stack is in base memory.  We can therefore
-                * use it directly, with a constraint on the size that
-                * we don't know; assume that we can use up to
-                * real_mode_stack_size.  (Not a valid assumption, but
-                * it will do).
-                */
-               stack_end = local_stack + local_stack_len;
-               stack_base = stack_end - real_mode_stack_size;
-       } else {
-               if (!real_mode_stack) {
-                       allot_real_mode_stack();
-               }
-               /* Use the allocated real-mode stack in base memory.
-                * This has fixed start and end points.
-                */
-               stack_base = phys_to_virt(real_mode_stack);
-               stack_end = stack_base + real_mode_stack_size;
-       }
-       s = stack = stack_end - local_stack_len;
+void memcpy_to_real ( segoff_t dest, void *src, size_t n ) {
 
-       /* Compile input stack and trampoline code to stack */
-       if ( p->in_stack_len ) {
-               memcpy ( s, p->in_stack, p->in_stack_len );
-               s += p->in_stack_len;
-       }
-       memcpy ( s, _prot_to_real_prefix, prot_to_real_prefix_size );
-       s += prot_to_real_prefix_size;
-       p2r_params = (prot_to_real_params_t*) ( s - sizeof(*p2r_params) );
-       memcpy ( s, p->fragment, p->fragment_len );
-       s += p->fragment_len;
-       memcpy ( s, _real_to_prot_suffix, real_to_prot_suffix_size );
-       s += real_to_prot_suffix_size;
-       r2p_params = (real_to_prot_params_t*) ( s - sizeof(*r2p_params) );
+}
 
-       /* Set parameters within compiled stack */
-       p2r_params->ss = p2r_params->cs = SEGMENT ( stack_base );
-       p2r_params->esp = virt_to_phys ( stack );
-       p2r_params->r2p_params = virt_to_phys ( r2p_params );
-       r2p_params->out_stack = ( p->out_stack == NULL ) ?
-               0 : virt_to_phys ( p->out_stack );
-       r2p_params->out_stack_len = p->out_stack_len;
+void memcpy_from_real ( void *dest, segoff_t src, size_t n ) {
 
-       return virt_to_phys ( stack + p->in_stack_len );
 }
 
+#endif /* KEEP_IT_REAL */
 
-/* Parameters are not genuinely unused; they are passed to
- * prepare_real_call() as part of a real_call_params_t struct.
- */
-uint16_t _real_call ( void *fragment, int fragment_len,
-                     void *in_stack __unused, int in_stack_len,
-                     void *out_stack __unused, int out_stack_len __unused ) {
-       uint16_t retval;
 
-       /* This code is basically equivalent to
-        *
-        *      uint32_t trampoline;
-        *      char local_stack[ in_stack_len + prot_to_real_prefix_size +
-        *                        fragment_len + real_to_prot_suffix_size ];
-        *      trampoline = prepare_real_call ( &fragment, local_stack );
-        *      __asm__ ( "call _virt_to_phys\n\t"
-        *                "call %%eax\n\t"
-        *                "call _phys_to_virt\n\t"
-        *                : "=a" (retval) : "0" (trampoline) );
-        *
-        * but implemented in assembly to avoid problems with not
-        * being certain exactly how gcc handles %esp.
-        */
+#define RM_STACK_SIZE ( 0x1000 )
 
-       __asm__ ( "pushl %%ebp\n\t"
-                 "movl  %%esp, %%ebp\n\t"      /* %esp preserved via %ebp */
-                 "subl  %%ecx, %%esp\n\t"      /* space for inline RM stack */
-                 "pushl %%esp\n\t"             /* set up RM stack */
-                 "pushl %%ecx\n\t"
-                 "pushl %%eax\n\t"
-                 "call  prepare_real_call\n\t" /* %eax = trampoline addr */
-                 "addl  $12, %%esp\n\t"
-                 "call  _virt_to_phys\n\t"     /* switch to phys addr */
-                 "call  *%%eax\n\t"            /* call to trampoline */
-                 "call  _phys_to_virt\n\t"     /* switch to virt addr */
-                 "movl  %%ebp, %%esp\n\t"      /* restore %esp & %ebp */
-                 "popl  %%ebp\n\t"
-                 : "=a" ( retval )
-                 : "0" ( &fragment )
-                 , "c" ( ( ( in_stack_len + prot_to_real_prefix_size +
-                             fragment_len + real_to_prot_suffix_size )
-                           + 0x3 ) & ~0x3 ) );
-       return retval;
+/* gcc won't let us use extended asm outside a function (compiler
+ * bug), ao we have to put these asm statements inside a dummy
+ * function.
+ */
+static void work_around_gcc_bug ( void ) __attribute__ ((used));
+static void work_around_gcc_bug ( void ) {
+       /* Export _real_mode_stack_size as absolute linker symbol */
+       __asm__ ( ".globl real_mode_stack_size" );
+       __asm__ ( ".equ real_mode_stack_size, %c0" : : "i" (RM_STACK_SIZE) );
 }
+
+char *real_mode_stack;
+int lock_real_mode_stack;
index 28a5bfede190b421595ee0d54969cbce1b0a9775..db8bc22b4667e5b5243a259c138c8d685c33ee0c 100644 (file)
 #define        LJMPI(x)        ljmp    x
 #endif
 
-/****************************************************************************
- * REAL-MODE CALLBACK INTERFACE
- *
- * This must be copied down to base memory in order for external
- * programs to be able to make calls in to Etherboot.  Store the
- * current physical address of Etherboot (i.e. virt_to_phys(_text)) in
- * (uint32_t)rm_etherboot_location, then copy
- * (uint16_t)rm_callback_interface_size bytes starting at
- * &((void)rm_callback_interface).
- *
- * There are two defined entry points:
- *   Offset RM_IN_CALL     = 0         Near call entry point
- *   Offset RM_IN_CALL_FAR = 2         Far call entry point
- *
- * Note that the routines _prot_to_real and _real_to_prot double as
- * trampoline fragments for external calls (calls from Etherboot to
- * real-mode code).  _prot_to_real does not automatically re-enable
- * interrupts; this is to allow for the potential of using Etherboot
- * code as an ISR.  _real_to_prot does automatically disable
- * interrupts, since we don't have a protected-mode IDT.
- ****************************************************************************
- */
-
-       .globl  rm_callback_interface
-       .code16
-rm_callback_interface:
-       .globl  _rm_in_call
-_rm_in_call:
-       jmp     _real_in_call
-       .globl  _rm_in_call_far
-_rm_in_call_far:
-       jmp     _real_in_call_far
-
-/****************************************************************************
- * _real_in_call
- *
- * Parameters:
- *   16-bit real-mode near/far return address (implicit from [l]call
- *   to routine) Other parameters as for _in_call_far().
- *
- * This routine will convert the 16-bit real-mode far return address
- * to a 32-bit real-mode far return address, switch to protected mode
- * using _real_to_prot and call in to _in_call_far.
- ****************************************************************************
- */
-
-#define RIC_PRESERVE ( 8 )
-#define RIC_OFFSET_CALLADDR ( RIC_PRESERVE )
-#define RIC_OFFSET_CALLADDR_E ( RIC_OFFSET_CALLADDR + 4 )
-#define RIC_OFFSET_CONTADDR ( RIC_OFFSET_CALLADDR_E )
-#define RIC_OFFSET_CONTADDR_E ( RIC_OFFSET_CONTADDR + 4 )
-#define RIC_OFFSET_OPCODE ( RIC_OFFSET_CONTADDR_E )
-#define RIC_OFFSET_OPCODE_E ( RIC_OFFSET_OPCODE + 4 )
-#define RIC_OFFSET_SEG_REGS ( RIC_OFFSET_OPCODE_E )
-#define RIC_OFFSET_SEG_REGS_E ( RIC_OFFSET_SEG_REGS + ( NUM_SEG_REGS * 2 ) )
-#define RIC_OFFSET_PAD ( RIC_OFFSET_SEG_REGS_E )
-#define RIC_OFFSET_PAD_E ( RIC_OFFSET_PAD + 2 )
-#define RIC_OFFSET_FLAGS ( RIC_OFFSET_PAD_E )
-#define RIC_OFFSET_FLAGS_E ( RIC_OFFSET_FLAGS + 2 )
-#define RIC_OFFSET_RETADDR ( RIC_OFFSET_FLAGS_E )
-#define RIC_OFFSET_RETADDR_E ( RIC_OFFSET_RETADDR + 4 )
-#define RIC_OFFSET_ORIG_OPCODE ( RIC_OFFSET_RETADDR_E )
-#define RIC_INSERT_LENGTH ( RIC_OFFSET_OPCODE_E - RIC_OFFSET_CALLADDR )
-       
-       .code16
-_real_in_call:
-       /* Expand near return address to far return address
-        */
-       pushw   %ax             /* Extend stack, store %ax */
-       pushfw
-       pushw   %bp
-       movw    %sp, %bp
-       movw    %cs, %ax
-       xchgw   %ax, 6(%bp)
-       xchgw   %ax, 4(%bp)     /* also restores %ax */
-       popw    %bp
-       popfw
-       /* Fall through to _real_in_call_far */
-       
-_real_in_call_far:
-       /* Store flags and pad */
-       pushfw
-       pushw   %ax
-
-       /* Store segment registers.  Order matches that of seg_regs_t */
-       pushw   %gs
-       pushw   %fs
-       pushw   %es
-       pushw   %ds
-       pushw   %ss
-       pushw   %cs
-
-       /* Switch to protected mode */
-       call _real_to_prot
-       .code32
-
-       /* Allow space for expanded stack */
-       subl    $RIC_INSERT_LENGTH, %esp
-       
-       /* Store temporary registers */
-       pushl   %ebp
-       pushl   %eax
-
-       /* Copy opcode, set EB_CALL_FROM_REAL_MODE and EP_SKIP_OPCODE.
-        * Copy it because _in_call() and i386_in_call() expect it at
-        * a fixed position, not as part of the va_list.
-        */
-       movl    RIC_OFFSET_ORIG_OPCODE(%esp), %eax
-       orl     $(EB_CALL_FROM_REAL_MODE|EB_SKIP_OPCODE), %eax
-       movl    %eax, RIC_OFFSET_OPCODE(%esp)
-       
-       /* Set up call and return addresses */
-       call    1f
-1:     popl    %ebp
-       subl    $1b, %ebp                       /* %ebp = offset */
-       movl    rm_etherboot_location(%ebp), %eax  /* Etherboot phys addr */
-       subl    $_text, %eax
-       addl    $_in_call, %eax                 /* _in_call phys addr */
-       movl    %eax, RIC_OFFSET_CALLADDR(%esp)
-       leal    2f(%ebp), %eax                  /* continuation address */
-       movl    %eax, RIC_OFFSET_CONTADDR(%esp)
-       
-       /* Restore temporary registers */
-       popl    %eax
-       popl    %ebp
-
-       /* Call to _in_call */
-       ret
-       /* opcode will be popped automatically thanks to EB_SKIP_OPCODE */
-
-2:     /* Continuation point */
-       call    _prot_to_real                   /* Return to real mode */
-       /* Note: the first two words of our segment register store
-        * happens to be exactly what we need to pass as parameters to
-        * _prot_to_real.
-        */
-       .code16
-       popw    %ds                             /* Restore segment registers */
-       popw    %ds                             /* (skip cs&ss since these   */
-       popw    %ds                             /* have already been set by  */
-       popw    %es                             /* _prot_to_real             */
-       popw    %fs
-       popw    %gs
-       addw    $2, %sp                         /* skip pad */
-
-       /* Check for EB_SKIP_OPCODE */
-       pushw   %bp
-       movw    %sp, %bp
-       testl   $EB_SKIP_OPCODE, 6(%bp)
-       popw    %bp
-       jnz     1f
-       /* Normal return */
-       popfw                                   /* Restore interrupt status */
-       lret                                    /* Back to caller */
-1:     /* Return and skip opcode */
-       popfw
-       lret    $4
-
-/****************************************************************************
- * rm_etherboot_location: the current physical location of Etherboot.
- * Needed so that real-mode callback routines can locate Etherboot.
- ****************************************************************************
- */
-       .globl rm_etherboot_location
-rm_etherboot_location: .long 0
-               
-/****************************************************************************
- * _prot_to_real_prefix
- *
- * Trampoline fragment.  Switch from 32-bit protected mode with flat
- * physical addresses to 16-bit real mode.  Store registers in the
- * trampoline for restoration by _real_to_prot_suffix.  Switch to
- * stack in base memory.
- ****************************************************************************
- */
-       
-       .globl _prot_to_real_prefix
-       .code32
-_prot_to_real_prefix:
-       /* Registers to preserve */
-       pushl   %ebx
-       pushl   %esi
-       pushl   %edi
-       pushl   %ebp
-
-       /* Calculate offset */
-       call    1f
-1:     popl    %ebp
-       subl    $1b, %ebp               /* %ebp = offset for labels in p2r*/
-
-       /* Preserve registers and return address in r2p_params */
-       movl    p2r_r2p_params(%ebp), %ebx
-       subl    $r2p_params, %ebx       /* %ebx = offset for labels in r2p */
-       popl    r2p_ebp(%ebx)
-       popl    r2p_edi(%ebx)
-       popl    r2p_esi(%ebx)
-       popl    r2p_ebx(%ebx)
-       popl    r2p_ret_addr(%ebx)
-       movl    %esp, r2p_esp(%ebx)
-
-       /* Switch stacks */
-       movl    p2r_esp(%ebp), %esp
-
-       /* Switch to real mode */
-       pushl   p2r_segments(%ebp)
-       call    _prot_to_real
-       .code16
-       addw    $4, %sp
-               
-       /* Fall through to next trampoline fragment */
-       jmp     _prot_to_real_prefix_end
-       
-/****************************************************************************
- * _prot_to_real
- *
- * Switch from 32-bit protected mode with flat physical addresses to
- * 16-bit real mode.  Stack and code must be in base memory when
- * called.  %cs, %ss, %eip, %esp are changed to real-mode values,
- * other segment registers are destroyed, all other registers are
- * preserved.  Interrupts are *not* enabled.
- *
- * Parameters:
- *   %cs               Real-mode code segment (word)
- *   %ss               Real-mode stack segment (word)
- ****************************************************************************
- */
-
-#define P2R_PRESERVE ( 12 )
-#define P2R_OFFSET_RETADDR ( P2R_PRESERVE )
-#define P2R_OFFSET_RETADDR_E ( P2R_OFFSET_RETADDR + 4 )
-#define P2R_OFFSET_CS ( P2R_OFFSET_RETADDR_E )
-#define P2R_OFFSET_CS_E ( P2R_OFFSET_CS + 2 )
-#define P2R_OFFSET_SS ( P2R_OFFSET_CS_E )
-#define P2R_OFFSET_SS_E ( P2R_OFFSET_SS + 2 )
-
-       .globl _prot_to_real
-       .code32
-_prot_to_real:
-       /* Preserve registers */
-       pushl   %ebp
-       pushl   %ebx
-       pushl   %eax
-       
-       /* Calculate offset */
-       call    1f
-1:     popl    %ebp
-       subl    $1b, %ebp               /* %ebp = offset for labels in p2r*/
-
-       /* Set up GDT with real-mode limits and appropriate bases for
-        * real-mode %cs and %ss.  Set up protected-mode continuation
-        * point on stack.
-        */
-       /* Fixup GDT */
-       leal    p2r_gdt(%ebp), %eax
-       movl    %eax, p2r_gdt_addr(%ebp)
-
-       /* Calculate CS base address: set GDT code segment, adjust
-        * return address, set up continuation address on stack.
-        */
-       movzwl  P2R_OFFSET_CS(%esp), %eax
-       shll    $4, %eax
-       /* Change return address to real-mode far address */
-       subl    %eax, P2R_OFFSET_RETADDR(%esp)
-       movl    %eax, %ebx
-       shrl    $4, %ebx
-       movw    %bx, (P2R_OFFSET_RETADDR+2)(%esp)
-       /* First real mode address */
-       movl    %eax, %ebx
-       shrl    $4, %ebx
-       pushw   %bx
-       leal    3f(%ebp), %ebx
-       subl    %eax, %ebx
-       pushw   %bx
-       /* Continuation address */
-       pushl   $(p2r_rmcs - p2r_gdt)
-       leal    2f(%ebp), %ebx
-       subl    %eax, %ebx
-       pushl   %ebx
-       /* Code segment in GDT */
-       movw    %ax, (p2r_rmcs+2)(%ebp)
-       shrl    $16, %eax                       /* Remainder of cs base addr */
-       movb    %al, (p2r_rmcs+4)(%ebp)
-       movb    %ah, (p2r_rmcs+7)(%ebp)
-
-       /* Calculate SS base address: set GDT data segment, retain to
-        * use for adjusting %esp.
-        */
-       movzwl  (12+P2R_OFFSET_SS)(%esp), %eax  /* Set ss base address */
-       shll    $4, %eax
-       movw    %ax, (p2r_rmds+2)(%ebp)
-       movl    %eax, %ebx
-       shrl    $16, %ebx
-       movb    %bl, (p2r_rmds+4)(%ebp)
-       movb    %bh, (p2r_rmds+7)(%ebp)
-
-       /* Load GDT */
-       lgdt    p2r_gdt(%ebp)
-       /* Reload all segment registers and adjust %esp */
-       movw    $(p2r_rmds - p2r_gdt), %bx /* Pmode DS */
-       movw    %bx, %ss
-       subl    %eax, %esp              /* %esp now less than 0x10000 */
-       movw    %bx, %ds
-       movw    %bx, %es
-       movw    %bx, %fs
-       movw    %bx, %gs
-       lret                            /* %cs:eip */
-2:     /* Segment registers now have 16-bit limits. */
-       .code16
-
-       /* Switch to real mode */
-       movl    %cr0, %ebx
-       andb    $0!CR0_PE, %bl
-       movl    %ebx, %cr0
-
-       /* Make intersegment jmp to flush the processor pipeline
-        * and reload %cs:%eip (to clear upper 16 bits of %eip).
-        */
-       lret
-3:             
-       
-       /* Load real-mode segment value to %ss.  %sp already OK */
-       shrl    $4, %eax
-       movw    %ax, %ss
-
-       /* Restore registers */
-       popl    %eax
-       popl    %ebx
-       popl    %ebp
-
-       /* Return to caller in real-mode */
-       lret
-
-#ifdef FLATTEN_REAL_MODE
-#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x8f
-#else
-#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
-#endif
-
-p2r_gdt:
-p2r_gdtarg:
-p2r_gdt_limit:         .word p2r_gdt_end - p2r_gdt - 1
-p2r_gdt_addr:          .long 0
-p2r_gdt_padding:       .word 0
-p2r_rmcs:
-       /* 16 bit real mode code segment */
-       .word   0xffff,(0&0xffff)
-       .byte   (0>>16),0x9b,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
-p2r_rmds:
-       /* 16 bit real mode data segment */
-       .word   0xffff,(0&0xffff)
-       .byte   (0>>16),0x93,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
-p2r_gdt_end:
-
-       /* This is the end of the trampoline prefix code.  When used
-        * as a prefix, fall through to the following code in the
-        * trampoline.
-        */
-p2r_params: /* Structure must match prot_to_real_params_t in realmode.h */
-p2r_esp:       .long 0
-p2r_segments:
-p2r_cs:                .word 0
-p2r_ss:                .word 0
-p2r_r2p_params:        .long 0
-       .globl  _prot_to_real_prefix_end
-_prot_to_real_prefix_end:
-       
-       .globl  _prot_to_real_prefix_size
-       .equ    _prot_to_real_prefix_size, _prot_to_real_prefix_end - _prot_to_real_prefix
-       .globl  prot_to_real_prefix_size
-prot_to_real_prefix_size:      
-       .word   _prot_to_real_prefix_size
-       
-/****************************************************************************
- * _real_to_prot_suffix
- *
- * Trampoline fragment.  Switch from 16-bit real-mode to 32-bit
- * protected mode with flat physical addresses.  Copy returned stack
- * parameters to output_stack.  Restore registers preserved by
- * _prot_to_real_prefix.  Restore stack to previous location.
- ****************************************************************************
- */
-
-       .globl _real_to_prot_suffix
-       .code16
-_real_to_prot_suffix:
-
-       /* Switch to protected mode */
-       call    _real_to_prot
-       .code32
-
-       /* Calculate offset */
-       call    1f
-1:     popl    %ebp
-       subl    $1b, %ebp               /* %ebp = offset for labels in r2p */
-
-       /* Copy stack to out_stack */
-       movl    r2p_out_stack(%ebp), %edi
-       movl    r2p_out_stack_len(%ebp), %ecx
-       movl    %esp, %esi
-       cld
-       rep movsb
-
-       /* Switch back to original stack */
-       movl    r2p_esp(%ebp), %esp
-
-       /* Restore registers and return */
-       pushl   r2p_ret_addr(%ebp)      /* Set up return address on stack */
-       movl    r2p_ebx(%ebp), %ebx
-       movl    r2p_esi(%ebp), %esi
-       movl    r2p_edi(%ebp), %edi
-       movl    r2p_ebp(%ebp), %ebp
-       ret
-
-/****************************************************************************
- * _real_to_prot
- *
- * Switch from 16-bit real-mode to 32-bit protected mode with flat
- * physical addresses.  All segment registers are destroyed, %eip and
- * %esp are changed to flat physical values, all other registers are
- * preserved.  Interrupts are disabled.
- *
- * Parameters: none
- ****************************************************************************
- */
-
-#define R2P_PRESERVE ( 12 )
-#define R2P_OFFSET_RETADDR ( R2P_PRESERVE )
-#define R2P_OFFSET_ORIG_RETADDR ( R2P_OFFSET_RETADDR + 2 )
-
-       .globl _real_to_prot
-       .code16         
-_real_to_prot:
-       /* Disable interrupts */
-       cli
-       /* zero extend the return address */
-       pushw   $0
-
-       /* Preserve registers */
-       pushl   %ebp
-       pushl   %ebx
-       pushl   %eax
-
-       /* Convert 16-bit real-mode near return address to
-        * 32-bit pmode physical near return address
-        */
-       movw    %sp, %bp
-       xorl    %ebx, %ebx
-       push    %cs
-       popw    %bx
-       movw    %bx, %ds
-       shll    $4, %ebx
-       movzwl  %ss:R2P_OFFSET_ORIG_RETADDR(%bp), %eax
-       addl    %ebx, %eax
-       movl    %eax, %ss:(R2P_OFFSET_RETADDR)(%bp)
-
-       /* Store the code segment physical base address in %ebp */
-       movl    %ebx, %ebp
-
-       /* Find the offset within the code segment that I am running at */
-       xorl    %ebx, %ebx
-       call    1f
-1:     popw    %bx
-
-       /* Set up GDT */
-       leal    (r2p_gdt-1b)(%bx), %eax /* %ds:ebx = %ds:bx = &(r2p_gdt) */
-       addl    %ebp, %eax              /* %eax = &r2p_gdt (physical) */
-       movl    %eax, %ds:(r2p_gdt-1b+2)(%bx) /* Set phys. addr. in r2p_gdt */
-
-       /* Compute the first protected mode physical address */
-       leal    (2f-1b)(%bx), %eax
-       addl    %ebp, %eax
-       movl    %eax, %ds:(r2p_paddr-1b)(%bx)
-
-       /* Calculate new %esp */
-       xorl    %eax, %eax
-       push    %ss
-       popw    %ax
-       shll    $4, %eax
-       movzwl  %sp, %ebp
-       addl    %eax, %ebp              /* %ebp = new %esp */
-       
-       /* Load GDT */
-       DATA32 lgdt %ds:(r2p_gdt-1b)(%bx)       /* Load GDT */
-
-       /* Switch to protected mode */
-       movl    %cr0, %eax
-       orb     $CR0_PE, %al
-       movl    %eax, %cr0
-
-       /* flush prefetch queue, and reload %cs:%eip */
-       DATA32 ljmp %ds:(r2p_paddr-1b)(%bx)
-       .code32
-2:
-       
-       /* Load segment registers, adjust %esp */
-       movw    $(r2p_pmds-r2p_gdt), %ax
-       movw    %ax, %ss
-       movl    %ebp, %esp
-       movw    %ax, %ds
-       movw    %ax, %es
-       movw    %ax, %fs
-       movw    %ax, %gs
-
-       /* Restore registers */
-       popl    %eax
-       popl    %ebx
-       popl    %ebp
-
-       /* return to caller */
-       ret
-
-r2p_gdt:
-       .word   r2p_gdt_end - r2p_gdt - 1       /* limit */
-       .long 0                                 /* addr */
-       .word 0
-r2p_pmcs:
-       /* 32 bit protected mode code segment, physical addresses */
-       .word   0xffff, 0
-       .byte   0, 0x9f, 0xcf, 0
-r2p_pmds:
-       /* 32 bit protected mode data segment, physical addresses */
-       .word   0xffff,0
-       .byte   0,0x93,0xcf,0
-r2p_gdt_end:
-
-r2p_paddr:
-       .long 2b
-       .word r2p_pmcs - r2p_gdt, 0
-
-
-       /* This is the end of the trampoline suffix code.
-        */
-r2p_params: /* Structure must match real_to_prot_params_t in realmode.h */
-r2p_ret_addr:          .long 0
-r2p_esp:               .long 0
-r2p_ebx:               .long 0
-r2p_esi:               .long 0
-r2p_edi:               .long 0
-r2p_ebp:               .long 0
-r2p_out_stack:         .long 0
-r2p_out_stack_len:     .long 0
-       .globl  _real_to_prot_suffix_end
-_real_to_prot_suffix_end:
-
-       .globl  _real_to_prot_suffix_size
-       .equ    _real_to_prot_suffix_size, _real_to_prot_suffix_end - _real_to_prot_suffix
-       .globl  real_to_prot_suffix_size
-real_to_prot_suffix_size:
-       .word   _real_to_prot_suffix_size
-
-rm_callback_interface_end:
-
-       .globl  _rm_callback_interface_size
-       .equ    _rm_callback_interface_size, rm_callback_interface_end - rm_callback_interface
-       .globl  rm_callback_interface_size
-rm_callback_interface_size:
-       .word   _rm_callback_interface_size
-
-/****************************************************************************
- * END OF REAL-MODE CALLBACK INTERFACE
- ****************************************************************************
- */
-
-
 #ifdef PXE_EXPORT
 /****************************************************************************
  * PXE CALLBACK INTERFACE
diff --git a/src/arch/i386/core/setjmp.S b/src/arch/i386/core/setjmp.S
new file mode 100644 (file)
index 0000000..59a1b7c
--- /dev/null
@@ -0,0 +1,40 @@
+/* setjmp and longjmp. Use of these functions is deprecated. */
+
+       .text
+       .arch i386
+       .code32
+       
+/**************************************************************************
+SETJMP - Save stack context for non-local goto
+**************************************************************************/
+       .globl  setjmp
+setjmp:
+       movl    4(%esp),%ecx            /* jmpbuf */
+       movl    0(%esp),%edx            /* return address */
+       movl    %edx,0(%ecx)
+       movl    %ebx,4(%ecx)
+       movl    %esp,8(%ecx)
+       movl    %ebp,12(%ecx)
+       movl    %esi,16(%ecx)
+       movl    %edi,20(%ecx)
+       movl    $0,%eax
+       ret
+
+/**************************************************************************
+LONGJMP - Non-local jump to a saved stack context
+**************************************************************************/
+       .globl  longjmp
+longjmp:
+       movl    4(%esp),%edx            /* jumpbuf */
+       movl    8(%esp),%eax            /* result */
+       movl    0(%edx),%ecx
+       movl    4(%edx),%ebx
+       movl    8(%edx),%esp
+       movl    12(%edx),%ebp
+       movl    16(%edx),%esi
+       movl    20(%edx),%edi
+       cmpl    $0,%eax
+       jne     1f
+       movl    $1,%eax
+1:     movl    %ecx,0(%esp)
+       ret
diff --git a/src/arch/i386/core/setup.S b/src/arch/i386/core/setup.S
new file mode 100644 (file)
index 0000000..b2dd3b1
--- /dev/null
@@ -0,0 +1,158 @@
+/****************************************************************************
+ * This file provides the setup() and setup16() functions.  The
+ * purpose of these functions is to set up the internal environment so
+ * that C code can execute.  This includes setting up the internal
+ * stack and (where applicable) setting up a GDT for virtual
+ * addressing.
+ *
+ * These functions are designed to be called by the prefix.
+ *
+ * The same basic assembly code is used to compile both setup()
+ * and setup16().
+ ****************************************************************************
+ */
+
+       .text
+       .arch i386
+
+#ifdef CODE16
+/****************************************************************************
+ * setup16 (real-mode far call)
+ *
+ * This function can be called by a 16-bit prefix in order to set up
+ * the internal (either 16-bit or 32-bit) environment.
+ *
+ * Parameters: none
+ *
+ * %cs:0000, %ds:0000 and %es:0000 must point to the start of the
+ * (decompressed) runtime image.
+ *
+ * If KEEP_IT_REAL is defined, then %ds:0000 may instead point to the
+ * start of the (decompressed) data segment portion of the runtime
+ * image.  If %ds==%cs, then it will be assumed that the data segment
+ * follows immediately after the code segment.
+ ****************************************************************************
+ */
+
+#ifdef KEEP_IT_REAL
+
+#define ENTER_FROM_EXTERNAL call ext_to_kir
+#define RETURN_TO_EXTERNAL call kir_to_ext
+#define ENTRY_POINT kir_call
+
+#else /* KEEP_IT_REAL */
+
+#define ENTER_FROM_EXTERNAL \
+       pushw %cs ; \
+       call real_to_prot ; \
+       .code32
+#define RETURN_TO_EXTERNAL \
+       call prot_to_real ; \
+       .code16
+#define ENTRY_POINT _prot_call /* _prot_call = OFFSET ( prot_call ) in librm */
+
+#endif /* KEEP_IT_REAL */
+       
+#define ENTRY_POINT_REGISTER di
+        
+       .section ".text16"
+       .code16
+       .globl setup16
+setup16:
+       
+#else /* CODE16 */
+
+/****************************************************************************
+ * setup (32-bit protected-mode near call)
+ *
+ * This function can be called by a 32-bit prefix in order to set up
+ * the internal 32-bit environment.
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+
+#define ENTER_FROM_EXTERNAL call ext_to_int
+#define RETURN_TO_EXTERNAL call int_to_ext
+#define ENTRY_POINT int_call
+#define ENTRY_POINT_REGISTER edi
+       
+       .section ".text"
+       .code32
+       .globl setup
+setup:
+       
+#endif /* CODE16 */
+       
+       /* Preserve flags (including interrupt status) */
+       pushfl
+
+       /* Switch to (uninitialised) internal environment.  This will
+        * preserve the external environment for when we call
+        * RETURN_TO_EXTERNAL.
+        */
+       ENTER_FROM_EXTERNAL
+       /* NOTE: We may have only four bytes of stack at this point */
+
+#if defined(CODE16) && defined(KEEP_IT_REAL)
+       
+       /* If %ds == %cs, then the data segment is located immediately
+        * after the code segment.
+        */
+       pushw   %ax
+       pushw   %bx
+       movw    %cs, %ax
+       movw    %ds, %bx
+       cmpw    %ax, %bx
+       jne     1f
+       addw    $_text_load_size_pgh, %ax
+       movw    %ax, %ds
+1:     popw    %bx
+       popw    %ax
+               
+       /* Switch to internal stack */
+       pushw   %ds
+       popw    %ss
+       movl    $_estack, %esp
+
+#else /* CODE16 && KEEP_IT_REAL */
+
+       /* Work out where we're running */
+       call    1f
+1:     popl    %ebp
+
+       /* Switch to internal pmode stack */
+       leal    (_estack-1b)(%ebp), %esp
+
+       /* Set up GDT for virtual addressing */
+       call    run_here
+
+#endif /* CODE16 && KEEP_IT_REAL */
+       
+       /* Switch back to external environment.  This will preserve
+        * the internal environment ready for the next call.
+        */
+       RETURN_TO_EXTERNAL
+
+       /* Pass pointer to entry-point function back to prefix.  %es
+        * may, by now, have been destroyed, so we re-initialise it
+        * from %cs.
+        */
+       pushw   %cs
+       popw    %es
+       mov     $ENTRY_POINT, %ENTRY_POINT_REGISTER
+       
+       /* Restore flags (including interrupt status) */
+       popfl
+       
+       lret
+
+/****************************************************************************
+ * Internal stack
+ ****************************************************************************
+ */
+       .section ".stack"
+       .align 8
+_stack:
+       .space 4096
+_estack:
diff --git a/src/arch/i386/core/start16.S b/src/arch/i386/core/start16.S
deleted file mode 100644 (file)
index 72fcfbf..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*****************************************************************************
- *
- * THIS FILE IS NOW OBSOLETE.
- *
- * The functions of this file are now placed in init.S.
- *
- *****************************************************************************
- */
-       
-#ifndef PCBIOS
-#error "16bit code is only supported with the PCBIOS"
-#endif
-
-#define        CODE_SEG 0x08
-#define DATA_SEG 0x10
-
-#define EXEC_IN_SITU_MAGIC     0x45524548      /* 'HERE' */
-
-       .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
-
-/*****************************************************************************
- *
- * start16 : move payload to desired area of memory, set up for exit
- *          back to prefix, set up for 32-bit code.
- *
- * Enter (from prefix) with es:di = 0x4552:0x4548 if you want to
- * prevent start16 from moving the payload.  There are three
- * motivations for moving the payload:
- * 
- * 1. It may be in ROM, in which case we need to move it to RAM.
- * 2. Whatever loaded us probably didn't know about our memory usage
- *    beyond the end of the image file.  We should claim this memory
- *    before using it.
- *
- * Unless the prefix instructs us otherwise we will move the payload to:
- *
- *    An area of memory claimed from the BIOS via 40:13.
- *
- * We use the main Etherboot stack (within the image target) as our
- * stack; we don't rely on the prefix passing us a stack usable for
- * anything other than the prefix's return address.  The (first 512
- * bytes of the) prefix code segment is copied to a safe archive
- * location.
- *
- * When we return to the prefix (from start32), we copy this code back
- * to a new area of memory, restore the prefix's ss:sp and ljmp back
- * to the copy of the prefix.  The prefix will see a return from
- * start16 *but* may be executing at a new location.  Code following
- * the lcall to start16 must therefore be position-independent and
- * must also be within [cs:0000,cs:01ff].  We make absolutely no
- * guarantees about the stack contents when the prefix regains
- * control.
- * 
- * Trashes just about all registers, including all the segment
- * registers.
- *
- *****************************************************************************
- */
-
-       .text
-       .code16
-       .arch i386
-       .org 0
-       .globl _start16
-_start16:
-
-/*****************************************************************************
- * Work out where we are going to place our image (image = optional
- * decompressor + runtime).  Exit this stage with %ax containing the
- * runtime target address divided by 16 (i.e. a real-mode segment
- * address).
- *****************************************************************************
- */    
-       movw    %es, %ax
-       cmpw    $(EXEC_IN_SITU_MAGIC >> 16), %ax
-       jne     exec_moved
-       cmpw    $(EXEC_IN_SITU_MAGIC & 0xffff), %di
-       jne     exec_moved
-exec_in_situ: 
-       /* Prefix has warned us not to move the payload.  Simply
-        * calculate where the image is going to end up, so we can
-        * work out where to put our stack.
-        */
-       movw    %cs, %ax
-       addw    $((payload-_start16)/16), %ax
-       jmp     99f
-exec_moved:
-       /* Claim an area of base memory from the BIOS and put the
-        * payload there.  arch_relocated_to() will deal with freeing
-        * up this memory once we've relocated to high memory.
-        */
-       movw    $0x40, %ax
-       movw    %ax, %es
-       movw    %es:(0x13), %ax         /* FBMS in kb to %ax */
-       shlw    $6, %ax                 /* ... in paragraphs */
-       subw    $__image_size_pgh, %ax  /* Subtract space for image */
-       shrw    $6, %ax                 /* Round down to nearest kb */
-       movw    %ax, %es:(0x13)         /* ...and claim memory from BIOS */
-       shlw    $6, %ax
-99:
-       /* At this point %ax contains the segment address for the
-        * start of the image (image = optional decompressor + runtime).
-        */
-
-/*****************************************************************************
- * Set up stack in start32's stack space within the place we're going
- * to copy Etherboot to, reserve space for GDT, copy return address
- * from prefix stack, store prefix stack address
- *****************************************************************************
- */
-       popl    %esi                    /* Return address */
-       mov     %ss, %bx                /* %es:di = prefix stack address   */
-       mov     %bx, %es                /* (*after* pop of return address) */
-       movw    %sp, %di
-       movw    $__offset_stack_pgh, %bx        /* Set up Etherboot stack */
-       addw    %ax, %bx
-       movw    %bx, %ss
-       movw    $__stack_size, %sp
-       subw    $(_gdt_end - _gdt), %sp /* Reserve space for GDT */
-       movw    %sp, %bp                /* Record GDT location */       
-       /* Set up i386_rm_in_call_data_t structure on stack.  This is
-        * the same structure as is set up by rm_in_call.
-        */
-       pushl   $0                      /* Dummy opcode */
-       pushl   %esi                    /* Prefix return address */
-       pushfw                          /* Flags */
-       pushw   %di                     /* Prefix %sp */
-       pushw   %gs                     /* Segment registers */
-       pushw   %fs
-       pushw   %es
-       pushw   %ds
-       pushw   %es                     /* Prefix %ss */
-       pushw   %cs
-       /* Stack is now 32-bit aligned */
-       
-       /* %ax still contains image target segment address */
-
-/*****************************************************************************
- * Calculate image target and prefix code physical addresses, store on stack
- * for use in copy routine.
- *****************************************************************************
- */
-       movzwl  %es:-2(%di), %ebx       /* Prefix code segment */
-       shll    $4, %ebx
-       pushl   %ebx                    /* Prefix code physical address */
-       movzwl  %ax, %edi               /* Image target segment */
-       shll    $4, %edi
-       pushl   %edi                    /* Image target physical address */
-
-/*****************************************************************************
- * Transition to 32-bit protected mode.  Set up all segment
- * descriptors to use flat physical addresses.
- *****************************************************************************
- */
-       /* Copy gdt to area reserved on stack
-        */
-       push    %cs                     /* GDT source location -> %ds:%si */
-       pop     %ds
-       mov     $(_gdt - _start16), %si
-       push    %ss                     /* GDT target location -> %es:%di */
-       pop     %es
-       mov     %bp, %di
-       mov     $(_gdt_end - _gdt), %cx
-       cld
-       rep movsb                       /* Copy GDT to stack */
-       movl    %ss, %eax
-       shll    $4, %eax
-       movzwl  %bp, %ebx
-       addl    %eax, %ebx              /* Physical addr of GDT copy -> %ebx */
-       movl    %ebx, 2(%bp)            /* Fill in addr field in GDT */
-               
-       /* Compute the offset I am running at.
-        */
-       movl    %cs, %ebx 
-       shll    $4, %ebx                /* %ebx = offset for start16 symbols */
-
-       /* Switch to 32bit protected mode.
-        */
-       cli                             /* Disable interrupts */
-       lgdt    (%bp)                   /* Load GDT from stack */
-       movl    %cr0, %eax              /* Set protected mode bit */
-       orb     $CR0_PE, %al
-       movl    %eax, %cr0
-       movl    %ss, %eax               /* Convert stack pointer to 32bit */
-       shll    $4, %eax
-       movzwl  %sp, %esp
-       addl    %eax, %esp
-       movl    $DATA_SEG, %eax         /* Reload the segment registers */
-       movl    %eax, %ds
-       movl    %eax, %es
-       movl    %eax, %ss
-       movl    %eax, %fs
-       movl    %eax, %gs
-       /* Flush prefetch queue, and reload %cs:%eip by effectively ljmping
-        * to code32_start.  Do the jump via pushl and lret because the text
-        * may not be writable/
-        */
-       pushl   $CODE_SEG
-       ADDR32 leal (code32_start-_start16)(%ebx), %eax
-       pushl   %eax    
-       DATA32 lret /* DATA32 needed, because we're still in 16-bit mode */
-
-_gdt:
-gdtarg:
-       .word   _gdt_end - _gdt - 1     /* limit */
-       .long 0                         /* 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
-_gdt_end:
-
-       .code32
-code32_start:  
-       
-/*****************************************************************************
- * Copy payload to target location.  Do the copy backwards, since if
- * there's overlap with a forward copy then it means start16 is going
- * to get trashed during the copy anyway...
- *****************************************************************************
- */
-       popl    %edi            /* Image target physical address */
-       pushl   %edi
-       leal    (payload-_start16)(%ebx), %esi /* Image source physical addr */
-       movl    $__payload_size, %ecx /* Payload size (not image size) */
-       addl    %ecx, %edi      /* Start at last byte (length - 1) */
-       decl    %edi
-       addl    %ecx, %esi
-       decl    %esi
-       std                     /* Backward copy of image */
-       rep movsb
-       cld
-       popl    %edi            /* Restore image target physical address */
-       leal    __decompressor_uncompressed(%edi), %ebx
-       subl    $_text, %ebx /* %ebx = offset for runtime symbols */
-
-/*****************************************************************************
- * Copy prefix to storage area within Etherboot image.
- *****************************************************************************
- */
-       popl    %esi            /* Prefix source physical address */
-       pushl   %edi
-       leal    _prefix_copy(%ebx), %edi /* Prefix copy phys. addr. */
-       leal    _eprefix_copy(%ebx), %ecx
-       subl    %edi, %ecx      /* Prefix copy size */
-       rep movsb               /* Forward copy of prefix */
-       popl    %edi            /* Restore image target physical address */
-
-/*****************************************************************************
- * Record base memory used by Etherboot image
- *****************************************************************************
- */
-       movl    %edi, _prefix_image_basemem (%ebx)
-
-/*****************************************************************************
- * Jump to start of the image (i.e. the decompressor, or start32 if
- * non-compressed).
- *****************************************************************************
- */
-       pushl   $0              /* Inform start32 that exit path is 16-bit */
-       jmpl    *%edi           /* Jump to image */
-       
-       .balign 16
-       /* Etherboot needs to be 16byte aligned or data that
-        * is virtually aligned is no longer physically aligned
-        * which is just nasty in general.  16byte alignment 
-        * should be sufficient though.
-        */
-payload:
index 6dc3f20307f4d10e0e96b5e80a8aa9696dde345f..e82454bb7dcebff399508461b20fa087bd3e1a40 100644 (file)
@@ -1,18 +1,5 @@
-/* #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    FLAT_CODE_SEG,_pmcs2-_gdt
-       .equ    FLAT_DATA_SEG,_pmds2-_gdt
-       .equ    CR0_PE,1
-#ifdef CONFIG_X86_64
-       .equ    LM_CODE_SEG,  _lmcs-_gdt
-       .equ    LM_DATA_SEG,  _lmds-_gdt
-#endif
-
+#include "virtaddr.h"
+       
        .equ    MSR_K6_EFER,   0xC0000080
        .equ    EFER_LME,      0x00000100
        .equ    X86_CR4_PAE,   0x00000020
 #define        LJMPI(x)        ljmp    x
 #endif
 
-#define BOCHSBP xchgw %bx, %bx
-
-#include "callbacks.h"
-#define NUM_PUSHA_REGS (8)
-#define NUM_SEG_REGS (6)
-       
 /*
  * 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
  * deal correctly with 16 bit return addresses.  I tried it, but failed.
  */
 
-/**************************************************************************
- * START
- *
- * This file is no longer enterered from the top.  init.S will jump to
- * either _in_call or _rm_in_call, depending on the processor mode
- * when init.S was entered.
- **************************************************************************/
        .text
        .arch i386
        .code32
        
-/**************************************************************************
-_IN_CALL - make a call in to Etherboot.
-**************************************************************************/
-
-/* There are two 32-bit entry points: _in_call and _in_call_far, for
- * near calls and far calls respectively.  Both should be called with
- * flat physical addresses.  They will result in a call to the C
- * routine in_call(); see there for API details.
- *
- * Note that this routine makes fairly heavy use of the stack and no
- * use of fixed data areas.  This is because it must be re-entrant;
- * there may be more than one concurrent call in to Etherboot.
- */
-
-#define IC_OFFSET_VA_LIST_PTR ( 0 )
-#define IC_OFFSET_VA_LIST_PTR_E ( IC_OFFSET_VA_LIST_PTR + 4 )
-#define IC_OFFSET_REGISTERS ( IC_OFFSET_VA_LIST_PTR_E )
-#define IC_OFFSET_REGISTERS_E ( IC_OFFSET_REGISTERS + ( NUM_PUSHA_REGS * 4 ) )
-#define IC_OFFSET_SEG_REGS ( IC_OFFSET_REGISTERS_E )
-#define IC_OFFSET_SEG_REGS_E ( IC_OFFSET_SEG_REGS + ( NUM_SEG_REGS * 2 ) )
-#define IC_OFFSET_GDT ( IC_OFFSET_SEG_REGS_E )
-#define IC_OFFSET_GDT_E ( IC_OFFSET_GDT + 8 )
-#define IC_OFFSET_FLAGS ( IC_OFFSET_GDT_E )
-#define IC_OFFSET_FLAGS_E ( IC_OFFSET_FLAGS + 4 )
-#define IC_OFFSET_RETADDR ( IC_OFFSET_FLAGS_E )
-#define IC_OFFSET_RETADDR_E ( IC_OFFSET_RETADDR + 8 )
-#define IC_OFFSET_ORIG_STACK ( IC_OFFSET_RETADDR )
-#define IC_OFFSET_OPCODE ( IC_OFFSET_ORIG_STACK + 8 )
-#define IC_OFFSET_OPCODE_E ( IC_OFFSET_OPCODE + 4 )
-#define IC_OFFSET_VA_LIST ( IC_OFFSET_OPCODE_E )
-       
-       .code32
-       .globl _in_call
-       .globl _in_call_far
-_in_call:
-       /* Expand to far return address */
-       pushl   %eax                    /* Store %eax */
-       xorl    %eax, %eax
-       movw    %cs, %ax
-       xchgl   %eax, 4(%esp)           /* 4(%esp) = %cs, %eax = ret addr */
-       xchgl   %eax, 0(%esp)           /* 0(%esp) = ret addr, restore %eax */
-_in_call_far:
-       /* Store flags */
-       pushfl
-       /* Store the GDT */
-       subl    $8, %esp
-       sgdt    0(%esp)
-       /* Store segment register values */
-       pushw   %gs
-       pushw   %fs
-       pushw   %es
-       pushw   %ds
-       pushw   %ss
-       pushw   %cs
-       /* Store general-purpose register values */
-       pushal
-       /* Replace %esp in store with physical %esp value on entry */
-       leal    (IC_OFFSET_ORIG_STACK - IC_OFFSET_REGISTERS)(%esp), %eax
-       movl    %eax, (IC_OFFSET_REGISTERS - IC_OFFSET_REGISTERS + 12)(%esp)
-       /* Store va_list pointer (physical address) */
-       leal    (IC_OFFSET_VA_LIST - IC_OFFSET_VA_LIST_PTR_E)(%esp), %eax
-       pushl   %eax
-       /* IC_OFFSET_*(%esp) are now valid */
-
-       /* Switch to virtual addresses */
-       call    _phys_to_virt
-
-       /* Fixup the va_list pointer */
-       movl    virt_offset, %ebp
-       subl    %ebp, IC_OFFSET_VA_LIST_PTR(%esp)
-
-       /* Check opcode for EB_USE_INTERNAL_STACK flag */
-       movl    IC_OFFSET_OPCODE(%esp), %eax
-       testl   $EB_USE_INTERNAL_STACK, %eax
-       je      2f
-       /* Use internal stack flag set */
-       /* Check %esp is not already in internal stack range */
-       leal    _stack, %esi            /* %esi = bottom of internal stack */
-       leal    _estack, %edi           /* %edi = top of internal stack */
-       cmpl    %esi, %esp
-       jb      1f
-       cmpl    %edi, %esp
-       jbe     2f
-1:     /* %esp not currently in internal stack range */
-       movl    %esp, %esi              /* %esi = original stack */
-       movl    $IC_OFFSET_OPCODE_E, %ecx /* %ecx = length to transfer */
-       subl    %ecx, %edi              /* %edi = internal stack pos */
-       movl    %edi, %esp              /*  = new %esp */
-       rep movsb                       /* Copy data to internal stack */
-2:
-
-       /* Call to C code */
-       call    i386_in_call
-
-       /* Set %eax (return code from C) in registers structure on
-        * stack, so that we return it to the caller.
-        */
-       movl    %eax, (IC_OFFSET_REGISTERS + 28)(%esp)
-
-       /* Calculate physical continuation address */
-       movl    virt_offset, %ebp
-       movzwl  (IC_OFFSET_SEG_REGS + 0)(%esp), %eax    /* %cs */
-       movzwl  (IC_OFFSET_SEG_REGS + 2)(%esp), %ebx    /* %ss */
-       pushl   %eax                    /* Continuation segment */
-       leal    1f(%ebp), %eax
-       pushl   %eax                    /* Continuation offset */
-       
-       /* Restore caller's GDT */
-       cli                             /* Temporarily disable interrupts */
-       lgdt    (8+IC_OFFSET_GDT)(%esp)
-       /* Reset %ss and adjust %esp */
-       movw    %bx, %ss
-       addl    %ebp, %esp
-       lret                            /* Reload %cs:eip, flush prefetch */
-1:
-
-       /* Skip va_list ptr */
-       popl    %eax
-       /* Reload general-purpose registers to be returned */
-       popal
-       /* Reload segment registers as passed in from caller */
-       popw    %gs
-       popw    %fs
-       popw    %es
-       popw    %ds
-       addl    $(4+8), %esp    /* Skip %cs, %ss and GDT (already reloaded) */
-       /* Restore flags (including revert of interrupt status) */
-       popfl
-
-       /* Restore physical %esp from entry.  It will only be
-        * different if EB_USE_INTERNAL_STACK was specified.
-        */
-       movl    ( 12 + IC_OFFSET_REGISTERS - IC_OFFSET_RETADDR )(%esp), %esp
-               
-       /* Check for EB_SKIP_OPCODE */
-       pushfl
-       testl   $EB_SKIP_OPCODE, 12(%esp)
-       jnz     1f
-       /* Normal return */
-       popfl
-       lret
-1:     /* Return and skip opcode */
-       popfl
-       lret    $4
-       
-/**************************************************************************
-RELOCATE_TO - relocate etherboot to the specified address
-**************************************************************************/
-       .globl relocate_to
-relocate_to:
-       /* Save the callee save registers */
-       pushl   %ebp
-       pushl   %esi
-       pushl   %edi
-
-       /* Compute the virtual destination address */
-       movl    16(%esp), %edi  # dest
-       subl    virt_offset, %edi
-       
-
-       /* Compute the new value of virt_offset */
-       movl    16(%esp), %ebp  # virt_offset
-       subl    $_text, %ebp
-
-       /* Fixup the gdt */
-       pushl   $_pmcs
-       pushl   %ebp            # virt_offset
-       call    set_seg_base
-       addl    $8, %esp
-
-       /* Fixup gdtarg */
-       leal    _gdt(%ebp), %eax
-       movl    %eax, gdtarg +2
-
-       /* Fixup virt_offset */
-       movl    %ebp, virt_offset
-
-       /* Load the move parameters */
-       movl    $_text, %esi
-       movl    $_end, %ecx
-       subl    %esi, %ecx
-
-       /* Move etherboot uses %esi, %edi, %ecx */
-       rep 
-       movsb
-
-       /* Reload the gdt */
-       cs
-       lgdt    gdtarg
-
-       /* Reload %cs */
-       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    %eax,%fs
-       movl    %eax,%gs
-
-       /* Restore the callee save registers */
-       popl    %edi
-       popl    %esi
-       popl    %ebp
-
-       /* return */
-       ret
-
 /**************************************************************************
 XSTART32 - Transfer control to the kernel just loaded
 **************************************************************************/
@@ -301,7 +66,7 @@ xstart32:
        pushl   %ebx
 
        /* Store the destination address on the stack */
-       pushl   $FLAT_CODE_SEG
+       pushl   $PHYSICAL_CS
        pushl   %ecx
 
        /* Cache virt_offset */
@@ -536,218 +301,6 @@ end_lm:
        .arch i386
 #endif /* CONFIG_X86_64 */
 
-/**************************************************************************
-SETJMP - Save stack context for non-local goto
-**************************************************************************/
-       .globl  setjmp
-setjmp:
-       movl    4(%esp),%ecx            /* jmpbuf */
-       movl    0(%esp),%edx            /* return address */
-       movl    %edx,0(%ecx)
-       movl    %ebx,4(%ecx)
-       movl    %esp,8(%ecx)
-       movl    %ebp,12(%ecx)
-       movl    %esi,16(%ecx)
-       movl    %edi,20(%ecx)
-       movl    $0,%eax
-       ret
-
-/**************************************************************************
-LONGJMP - Non-local jump to a saved stack context
-**************************************************************************/
-       .globl  longjmp
-longjmp:
-       movl    4(%esp),%edx            /* jumpbuf */
-       movl    8(%esp),%eax            /* result */
-       movl    0(%edx),%ecx
-       movl    4(%edx),%ebx
-       movl    8(%edx),%esp
-       movl    12(%edx),%ebp
-       movl    16(%edx),%esi
-       movl    20(%edx),%edi
-       cmpl    $0,%eax
-       jne     1f
-       movl    $1,%eax
-1:     movl    %ecx,0(%esp)
-       ret
-
-/**************************************************************************
-_VIRT_TO_PHYS - Transition from virtual to physical addresses
-               Preserves all preservable registers and flags
-**************************************************************************/
-       .globl _virt_to_phys
-_virt_to_phys:
-       pushfl
-       pushl   %ebp
-       pushl   %eax
-       movl    virt_offset, %ebp       /* Load virt_offset */
-       addl    %ebp, 12(%esp)          /* Adjust the return address */
-
-       /* reload the code segment */
-       pushl   $FLAT_CODE_SEG
-       leal    1f(%ebp), %eax
-       pushl   %eax
-       lret
-
-1:
-       /* reload other segment registers */
-       movl    $FLAT_DATA_SEG, %eax
-       movl    %eax, %ds
-       movl    %eax, %es       
-       movl    %eax, %ss       
-       addl    %ebp, %esp              /* Adjust the stack pointer */
-       movl    %eax, %fs       
-       movl    %eax, %gs
-
-       popl    %eax
-       popl    %ebp
-       popfl
-       ret
-
-
-/**************************************************************************
-_PHYS_TO_VIRT - Transition from using physical to virtual addresses
-               Preserves all preservable registers and flags
-**************************************************************************/
-       .globl _phys_to_virt
-_phys_to_virt:
-       pushfl
-       pushl   %ebp
-       pushl   %eax
-
-       call    1f
-1:     popl    %ebp
-       subl    $1b, %ebp
-       movl    %ebp, virt_offset(%ebp)
-
-       /* Fixup the gdt */
-       leal    _pmcs(%ebp), %eax
-       pushl   %eax
-       pushl   %ebp
-       call    set_seg_base
-       addl    $8, %esp
-
-       /* Fixup gdtarg */
-       leal    _gdt(%ebp), %eax
-       movl    %eax, (gdtarg+2)(%ebp)
-
-       /* Load the global descriptor table */
-       cli
-       lgdt    %cs:gdtarg(%ebp)
-       ljmp    $KERN_CODE_SEG, $1f
-1:
-       /* reload other segment regsters */
-       movl    $KERN_DATA_SEG, %eax
-       movl    %eax, %ds
-       movl    %eax, %es       
-       movl    %eax, %ss       
-       subl    %ebp, %esp      /* Adjust the stack pointer */
-       movl    %eax, %fs       
-       movl    %eax, %gs
-
-       subl    %ebp, 12(%esp)  /* Adjust the return address */
-       popl    %eax
-       popl    %ebp
-       popfl
-       ret
-       
-
-/**************************************************************************
-SET_SEG_BASE - Set the base address of a segment register
-**************************************************************************/
-       .globl set_seg_base
-set_seg_base:
-       pushl   %eax
-       pushl   %ebx
-       movl    12(%esp), %eax          /* %eax = base address */
-       movl    16(%esp), %ebx          /* %ebx = &code_descriptor */
-       movw    %ax, (0+2)(%ebx)        /* CS base bits 0-15 */
-       movw    %ax, (8+2)(%ebx)        /* DS base bits 0-15 */
-       shrl    $16, %eax
-       movb    %al, (0+4)(%ebx)        /* CS base bits 16-23 */
-       movb    %al, (8+4)(%ebx)        /* DS base bits 16-23 */
-       movb    %ah, (0+7)(%ebx)        /* CS base bits 24-31 */
-       movb    %ah, (8+7)(%ebx)        /* DS base bits 24-31 */
-       popl    %ebx
-       popl    %eax
-       ret
-       
-/**************************************************************************
-GLOBAL DESCRIPTOR TABLE
-**************************************************************************/
-       .data
-       .align  4
-
-       .globl  _gdt
-       .globl  gdtarg
-_gdt:
-gdtarg:
-       .word   _gdt_end - _gdt - 1     /* limit */
-       .long   _gdt                    /* addr */
-       .word   0
-
-       .globl  _pmcs
-_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,(0&0xffff)
-       .byte   (0>>16),0x9b,0x00,(0>>24)
-
-_rmds:
-       /* 16 bit real mode data segment */
-       .word   0xffff,(0&0xffff)
-       .byte   (0>>16),0x93,0x00,(0>>24)
-
-_pmcs2:
-       /* 32 bit protected mode code segment, base 0 */
-       .word   0xffff,0
-       .byte   0,0x9f,0xcf,0
-
-_pmds2:
-       /* 32 bit protected mode data segment, base 0 */
-       .word   0xffff,0
-       .byte   0,0x93,0xcf,0
-
-#ifdef CONFIG_X86_64
-_lmcs:
-       /* 64bit long mode code segment, base 0 */
-       .word   0xffff, 0
-       .byte   0x00, 0x9f, 0xaf , 0x00
-_lmds:
-       /* 64bit long mode data segment, base 0 */
-       .word   0xffff, 0
-       .byte   0x00, 0x93, 0xcf, 0x00
-#endif
-_gdt_end:
-
-       /* The initial register contents */
-       .balign 4
-       .globl initial_regs
-initial_regs:
-       .fill 8, 4, 0
-
-       /* The virtual address offset  */       
-       .globl virt_offset
-virt_offset:
-       .long   0
-
-       .section ".stack"
-       .p2align 3
-       /* allocate a 4K stack in the stack segment */
-       .globl  _stack
-_stack:
-       .space 4096
-       .globl  _estack
-_estack:
 #ifdef CONFIG_X86_64
        .section ".bss"
        .p2align 12
index 9c6d6c25a27c3cc5beec0cc8b659638845350de2..8955b0f87af711b03b278cd5cdd843b386615164 100644 (file)
@@ -1,5 +1,4 @@
 #include "realmode.h"
-#include "segoff.h"
 
 struct segheader
 {
index dccdd97c2e4792be1e5b01626af1d4d1c7f41ea7..dbcfc73d880c6933b15c546e4ad3fc80f8636a7e 100644 (file)
@@ -5,10 +5,14 @@
  *
  */
 
-#ifdef CONSOLE_DIRECT_VGA
+#include "stddef.h"
+#include "string.h"
+#include "io.h"
+#include "console.h"
+#include "init.h"
+#include "vga.h"
 
-#include <etherboot.h>
-#include <vga.h>
+static struct console_driver vga_console;
 
 static char *vidmem;           /* The video buffer */
 static int video_line, video_col;
@@ -17,7 +21,7 @@ static int video_line, video_col;
 
 static void memsetw(void *s, int c, unsigned int n)
 {
-       int i;
+       unsigned int i;
        u16 *ss = (u16 *) s;
 
        for (i = 0; i < n; i++) {
@@ -25,7 +29,7 @@ static void memsetw(void *s, int c, unsigned int n)
        }
 }
 
-void video_init(void)
+static void video_init(void)
 {
        static int inited=0;
 
@@ -50,7 +54,7 @@ static void video_scroll(void)
                vidmem[i] = ' ';
 }
 
-void vga_putc(unsigned char byte)
+static void vga_putc(int byte)
 {
        if (byte == '\n') {
                video_line++;
@@ -90,5 +94,9 @@ void vga_putc(unsigned char byte)
        write_crtc((video_col + (video_line *COLS)) & 0x0ff, CRTC_CURSOR_LO);
 }
 
-#endif
+static struct console_driver vga_console __console_driver = {
+       .putchar = vga_putc,
+       .disabled = 1,
+};
 
+INIT_FN ( INIT_CONSOLE, video_init, NULL, NULL );
diff --git a/src/arch/i386/core/virtaddr.S b/src/arch/i386/core/virtaddr.S
new file mode 100644 (file)
index 0000000..ed495c3
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Functions to support the virtual addressing method of relocation
+ * that Etherboot uses.
+ *
+ */
+
+#include "virtaddr.h"
+               
+       .arch i386
+
+/****************************************************************************
+ * GDT for initial transition to protected mode
+ *
+ * The segment values, PHYSICAL_CS et al, are defined in an external
+ * header file virtaddr.h, since they need to be shared with librm.
+ ****************************************************************************
+ */
+       .data
+       .align 16
+
+gdt:
+gdt_limit:             .word gdt_length - 1
+gdt_addr:              .long 0
+                       .word 0 /* padding */
+       
+       .org    gdt + PHYSICAL_CS
+physical_cs:
+       /* 32 bit protected mode code segment, physical addresses */
+       .word   0xffff,0
+       .byte   0,0x9f,0xcf,0
+       
+       .org    gdt + PHYSICAL_DS
+physical_ds:
+       /* 32 bit protected mode data segment, physical addresses */
+       .word   0xffff,0
+       .byte   0,0x93,0xcf,0
+       
+       .org    gdt + VIRTUAL_CS
+virtual_cs:
+       /* 32 bit protected mode code segment, virtual addresses */
+       .word   0xffff,0
+       .byte   0,0x9f,0xcf,0
+
+       .org    gdt + VIRTUAL_DS
+virtual_ds:    
+       /* 32 bit protected mode data segment, virtual addresses */
+       .word   0xffff,0
+       .byte   0,0x93,0xcf,0
+
+#ifdef CONFIG_X86_64
+       
+       .org    gdt + LONG_CS
+long_cs:
+       /* 64bit long mode code segment, base 0 */
+       .word   0xffff, 0
+       .byte   0x00, 0x9f, 0xaf , 0x00
+
+       .org    gdt + LONG_DS
+long_ds:
+       /* 64bit long mode data segment, base 0 */
+       .word   0xffff, 0
+       .byte   0x00, 0x93, 0xcf, 0x00
+       
+#endif /* CONFIG_X86_64 */
+       
+gdt_end:               
+       .equ    gdt_length, gdt_end - gdt
+
+       /* The virtual address offset  */       
+       .globl virt_offset
+virt_offset:   .long   0
+               
+       .text
+       .code32
+       
+/****************************************************************************
+ * run_here (flat physical addressing, position-independent)
+ *
+ * Set up a GDT to run Etherboot at the current location with virtual
+ * addressing.  This call does not switch to virtual addresses or move
+ * the stack pointer.  The GDT will be located within the copy of
+ * Etherboot.  All registers are preserved.
+ *
+ * This gets called at startup and at any subsequent relocation of
+ * Etherboot.
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+       .globl  run_here
+run_here:
+       /* Preserve registers */
+       pushl   %eax
+       pushl   %ebp
+
+       /* Find out where we're running */
+       call    1f
+1:     popl    %ebp
+       subl    $1b, %ebp
+
+       /* Store as virt_offset */
+       movl    %ebp, virt_offset(%ebp)
+
+       /* Set segment base addresses in GDT */
+       leal    virtual_cs(%ebp), %eax
+       pushl   %eax
+       pushl   %ebp
+       call    set_seg_base
+       popl    %eax /* discard */
+       popl    %eax /* discard */
+
+       /* Set physical location of GDT */
+       leal    gdt(%ebp), %eax
+       movl    %eax, gdt_addr(%ebp)
+
+       /* Load the new GDT */
+       lgdt    gdt(%ebp)
+
+       /* Reload new flat physical segment registers */
+       movl    $PHYSICAL_DS, %eax
+       movl    %eax, %ds
+       movl    %eax, %es
+       movl    %eax, %fs
+       movl    %eax, %gs
+       movl    %eax, %ss
+
+       /* Restore registers, convert return address to far return
+        * address.
+        */
+       popl    %ebp
+       movl    $PHYSICAL_CS, %eax
+       xchgl   %eax, 4(%esp)   /* cs now on stack, ret offset now in eax */
+       xchgl   %eax, 0(%esp)   /* ret offset now on stack, eax restored */
+       
+       /* Return to caller, reloading %cs with new value */
+       lret
+
+/****************************************************************************
+ * set_seg_base (any addressing, position-independent)
+ *
+ * Set the base address of a pair of segments in the GDT.  This relies
+ * on the layout of the GDT being (CS,DS) pairs.
+ *
+ * Parameters:
+ *   uint32_t base_address
+ *   struct gdt_entry * code_segment
+ * Returns:
+ *   none
+ ****************************************************************************
+ */
+       .globl set_seg_base
+set_seg_base:
+       pushl   %eax
+       pushl   %ebx
+       movl    12(%esp), %eax          /* %eax = base address */
+       movl    16(%esp), %ebx          /* %ebx = &code_descriptor */
+       movw    %ax, (0+2)(%ebx)        /* CS base bits 0-15 */
+       movw    %ax, (8+2)(%ebx)        /* DS base bits 0-15 */
+       shrl    $16, %eax
+       movb    %al, (0+4)(%ebx)        /* CS base bits 16-23 */
+       movb    %al, (8+4)(%ebx)        /* DS base bits 16-23 */
+       movb    %ah, (0+7)(%ebx)        /* CS base bits 24-31 */
+       movb    %ah, (8+7)(%ebx)        /* DS base bits 24-31 */
+       popl    %ebx
+       popl    %eax
+       ret
+       
+/****************************************************************************
+ * _virt_to_phys (virtual addressing)
+ *
+ * Switch from virtual to flat physical addresses.  %esp is adjusted
+ * to a physical value.  Segment registers are set to flat physical
+ * selectors.  All other registers are preserved.  Flags are
+ * preserved.
+ *
+ * Parameters: none
+ * Returns: none
+ ****************************************************************************
+ */
+       .globl _virt_to_phys
+_virt_to_phys:
+       /* Preserve registers and flags */
+       pushfl
+       pushl   %eax
+       pushl   %ebp
+
+       /* Change return address to a physical address */
+       movl    virt_offset, %ebp
+       addl    %ebp, 12(%esp)
+
+       /* Switch to physical code segment */
+       pushl   $PHYSICAL_CS
+       leal    1f(%ebp), %eax
+       pushl   %eax
+       lret
+1:
+       /* Reload other segment registers and adjust %esp */
+       movl    $PHYSICAL_DS, %eax
+       movl    %eax, %ds
+       movl    %eax, %es       
+       movl    %eax, %fs       
+       movl    %eax, %gs
+       movl    %eax, %ss       
+       addl    %ebp, %esp
+
+       /* Restore registers and flags, and return */
+       popl    %ebp
+       popl    %eax
+       popfl
+       ret
+
+/****************************************************************************
+ * _phys_to_virt (flat physical addressing)
+ *
+ * Switch from flat physical to virtual addresses.  %esp is adjusted
+ * to a virtual value.  Segment registers are set to virtual
+ * selectors.  All other registers are preserved.  Flags are
+ * preserved.
+ *
+ * Note that this depends on the GDT already being correctly set up
+ * (e.g. by a call to run_here()).
+ *
+ * Parameters: none
+ * Returns: none
+ ****************************************************************************
+ */
+       .globl _phys_to_virt
+_phys_to_virt:
+       /* Preserve registers and flags */
+       pushfl
+       pushl   %eax
+       pushl   %ebp
+
+       /* Switch to virtual code segment */
+       ljmp    $VIRTUAL_CS, $1f
+1:     
+       /* Reload data segment registers */
+       movl    $VIRTUAL_DS, %eax
+       movl    %eax, %ds
+       movl    %eax, %es       
+       movl    %eax, %fs       
+       movl    %eax, %gs
+
+       /* Reload stack segment and adjust %esp */
+       movl    virt_offset, %ebp
+       movl    %eax, %ss       
+       subl    %ebp, %esp
+
+       /* Change the return address to a virtual address */
+       subl    %ebp, 12(%esp)
+
+       /* Restore registers and flags, and return */
+       popl    %ebp
+       popl    %eax
+       popfl
+       ret
+
+/****************************************************************************
+ * relocate_to (virtual addressing)
+ *
+ * Relocate Etherboot to the specified address.  The runtime image
+ * (excluding the prefix, decompressor and compressed image) is copied
+ * to a new location, and execution continues in the new copy.  This
+ * routine is designed to be called from C code.
+ *
+ * Parameters:
+ *     uint32_t new_phys_addr
+ ****************************************************************************
+ */
+       .globl relocate_to
+relocate_to:
+       /* Save the callee save registers */
+       pushl   %ebp
+       pushl   %esi
+       pushl   %edi
+
+       /* Compute the physical source address and data length */
+       movl    $_text, %esi
+       movl    $_end, %ecx
+       subl    %esi, %ecx
+       addl    virt_offset, %esi
+
+       /* Compute the physical destination address */
+       movl    16(%esp), %edi
+
+       /* Switch to flat physical addressing */
+       call    _virt_to_phys
+       
+       /* Do the copy */
+       cld
+       rep movsb
+
+       /* Calculate offset to new image */
+       subl    %esi, %edi
+
+       /* Switch to executing in new image */
+       call    1f
+1:     popl    %ebp
+       leal    (2f-1b)(%ebp,%edi), %eax
+       jmpl    *%eax
+2:
+       /* Switch to stack in new image */
+       addl    %edi, %esp
+       
+       /* Call run_here() to set up GDT */
+       call    run_here
+
+       /* Switch to virtual addressing */
+       call    _phys_to_virt
+       
+       /* Restore the callee save registers */
+       popl    %edi
+       popl    %esi
+       popl    %ebp
+
+       /* return */
+       ret
index 084fc18a1179ac88de83ad631affe060ffc81558..7e3e7df8d3aca27464cc62f13599d599a9547d14 100644 (file)
@@ -1436,7 +1436,7 @@ static int undi_isa_probe ( struct dev *dev,
  * this list.
  */
 static struct pci_id undi_nics[] = {
-       /* PCI_ROM(0x0000, 0x0000, "undi", "UNDI adaptor"), */
+       PCI_ROM(0x0000, 0x0000, "undi", "UNDI driver support"),
 };
 
 static struct pci_driver undi_driver __pci_driver = {
index 70f26703c9ea93c94b3e8d9b6b0fcba45eaa0ec2..fcbe7f3246c1c201fb0247b043750bf58f9cc8ed 100644 (file)
@@ -3,11 +3,11 @@
  * Body of routines taken from old pcbios.S
  */
 
-#ifdef PCBIOS
-
-#include "etherboot.h"
+#include "stdint.h"
 #include "realmode.h"
-#include "segoff.h"
+#include "compiler.h"
+
+#define BIOS_DATA_SEG 0x0040
 
 #define CF ( 1 << 0 )
 
@@ -23,133 +23,101 @@ timeofday BIOS interrupt.
 #define CONFIG_BIOS_CURRTICKS 1
 #endif
 #if defined(CONFIG_BIOS_CURRTICKS)
-unsigned long currticks (void) 
-{
+unsigned long currticks ( void ) {
        static uint32_t days = 0;
-       uint32_t *ticks = VIRTUAL(0x0040,0x006c);
-       uint8_t *midnight = VIRTUAL(0x0040,0x0070);
+       uint32_t ticks;
+       uint8_t midnight;
 
        /* Re-enable interrupts so that the timer interrupt can occur
         */
-       RM_FRAGMENT(rm_currticks,
-               "sti\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "cli\n\t"
-       );      
-
-       real_call ( rm_currticks, NULL, NULL );
-
-       if ( *midnight ) {
-               *midnight = 0;
+       REAL_EXEC ( rm_currticks,
+                   "sti\n\t"
+                   "nop\n\t"
+                   "nop\n\t"
+                   "cli\n\t",
+                   0,
+                   OUT_CONSTRAINTS (),
+                   IN_CONSTRAINTS (),
+                   CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
+
+       get_real ( ticks, BIOS_DATA_SEG, 0x006c );
+       get_real ( midnight, BIOS_DATA_SEG, 0x0070 );
+
+       if ( midnight ) {
+               midnight = 0;
+               put_real ( midnight, BIOS_DATA_SEG, 0x0070 );
                days += 0x1800b0;
        }
-       return ( days + *ticks );
+       return ( days + ticks );
 }
 #endif /* CONFIG_BIOS_CURRTICKS */
 
-/**************************************************************************
-INT15 - Call Interrupt 0x15
-**************************************************************************/
-int int15 ( int ax )
-{
-       struct {
-               reg16_t ax;
-       } PACKED in_stack;
-       struct {
-               reg16_t flags;
-       } PACKED out_stack;
-       reg16_t ret_ax;
-
-       RM_FRAGMENT(rm_int15,
-               "sti\n\t"
-               "popw %ax\n\t"
-               "stc\n\t"
-               "int $0x15\n\t"
-               "pushf\n\t"
-               "cli\n\t"
-       );
-
-       in_stack.ax.word = ax;
-       ret_ax.word = real_call ( rm_int15, &in_stack, &out_stack );
-
-       /* Carry flag clear indicates function not supported */
-       if ( ! ( out_stack.flags.word & CF ) ) return 0;
-       return ret_ax.h;
-}
-
-#ifdef POWERSAVE
 /**************************************************************************
 CPU_NAP - Save power by halting the CPU until the next interrupt
 **************************************************************************/
-void cpu_nap ( void )
-{
-       RM_FRAGMENT(rm_cpu_nap,
-               "sti\n\t"
-               "hlt\n\t"
-               "cli\n\t"
-       );      
-
-       real_call ( rm_cpu_nap, NULL, NULL );
+void cpu_nap ( void ) {
+       REAL_EXEC ( rm_cpu_nap,
+                   "sti\n\t"
+                   "hlt\n\t"
+                   "cli\n\t",
+                   0,
+                   OUT_CONSTRAINTS (),
+                   IN_CONSTRAINTS (),
+                   CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
 }
-#endif /* POWERSAVE */
 
 #if    (TRY_FLOPPY_FIRST > 0)
 /**************************************************************************
 DISK_INIT - Initialize the disk system
 **************************************************************************/
-void disk_init ( void )
-{
-       RM_FRAGMENT(rm_disk_init,
-               "sti\n\t"
-               "xorw %ax,%ax\n\t"
-               "movb $0x80,%dl\n\t"
-               "int $0x13\n\t"
-               "cli\n\t"
-       );
-       
-       real_call ( rm_disk_init, NULL, NULL );
+void disk_init ( void ) {
+       REAL_EXEC ( rm_disk_init,
+                   "sti\n\t"
+                   "xorw %ax,%ax\n\t"
+                   "movb $0x80,%dl\n\t"
+                   "int $0x13\n\t"
+                   "cli\n\t",
+                   0,
+                   OUT_CONSTRAINTS (),
+                   IN_CONSTRAINTS (),
+                   CLOBBER ( "eax", "ebx", "ecx", "edx",
+                             "ebp", "esi", "edi" ) );
 }
 
 /**************************************************************************
 DISK_READ - Read a sector from disk
 **************************************************************************/
 unsigned int pcbios_disk_read ( int drive, int cylinder, int head, int sector,
-                               char *buf ) {
-       struct {
-               reg16_t ax;
-               reg16_t cx;
-               reg16_t dx;
-               segoff_t buffer;
-       } PACKED in_stack;
-       struct {
-               reg16_t flags;
-       } PACKED out_stack;
-       reg16_t ret_ax;
+                               char *fixme_buf ) {
+       uint16_t ax, flags, discard_c, discard_d;
+       segoff_t buf = SEGOFF ( fixme_buf );
+
+       /* FIXME: buf should be passed in as a segoff_t rather than a
+        * char *
+        */
 
-       RM_FRAGMENT(rm_pcbios_disk_read,
-               "sti\n\t"
-               "popw %ax\n\t"
-               "popw %cx\n\t"
-               "popw %dx\n\t"
-               "popw %bx\n\t"
-               "popw %es\n\t"
-               "int $0x13\n\t"
-               "pushfw\n\t"
-               "cli\n\t"
+       REAL_EXEC ( rm_pcbios_disk_read,
+                   "sti\n\t"
+                   "pushl %%ebx\n\t"      /* Convert %ebx to %es:bx */
+                   "popl %%bx\n\t"
+                   "popl %%es\n\t"
+                   "movb $0x02, %%ah\n\t" /* INT 13,2 - Read disk sector */
+                   "movb $0x01, %%al\n\t" /* Read one sector */
+                   "int $0x13\n\t"
+                   "pushfw\n\t"
+                   "popw %%bx\n\t"
+                   "cli\n\t",
+                   4,
+                   OUT_CONSTRAINTS ( "=a" ( ax ), "=b" ( flags ),
+                                     "=c" ( discard_c ), "=d" ( discard_d ) ),
+                   IN_CONSTRAINTS ( "c" ( ( ( cylinder & 0xff ) << 8 ) |
+                                          ( ( cylinder >> 8 ) & 0x3 ) |
+                                          sector ),
+                                    "d" ( ( head << 8 ) | drive ),
+                                    "b" ( buf ) ),
+                   CLOBBER ( "ebp", "esi", "edi" ) );
        );
 
-       in_stack.ax.h = 2; /* INT 13,2 - Read disk sector */
-       in_stack.ax.l = 1; /* Read one sector */
-       in_stack.cx.h = cylinder & 0xff;
-       in_stack.cx.l = ( ( cylinder >> 8 ) & 0x3 ) | sector;
-       in_stack.dx.h = head;
-       in_stack.dx.l = drive;
-       in_stack.buffer.segment = SEGMENT ( buf );
-       in_stack.buffer.offset = OFFSET ( buf );
-       ret_ax.word = real_call ( rm_pcbios_disk_read, &in_stack, &out_stack );
-       return ( out_stack.flags.word & CF ) ? ret_ax.word : 0;
+       return ( flags & CF ) ? ax : 0;
 }
 #endif /* TRY_FLOPPY_FIRST */
-
-#endif /* PCBIOS */
diff --git a/src/arch/i386/firmware/pcbios/bios_console.c b/src/arch/i386/firmware/pcbios/bios_console.c
new file mode 100644 (file)
index 0000000..b0bee1a
--- /dev/null
@@ -0,0 +1,76 @@
+/* Etherboot routines for PCBIOS firmware.
+ *
+ * Body of routines taken from old pcbios.S
+ */
+
+#include "compiler.h"
+#include "realmode.h"
+#include "console.h"
+
+#define ZF ( 1 << 6 )
+
+/**************************************************************************
+bios_putchar - Print a character on console
+**************************************************************************/
+static void bios_putchar ( int character ) {
+       REAL_EXEC ( rm_console_putc,
+                   "sti\n\t"
+                   "movb $0x0e, %%ah\n\t"
+                   "movl $1, %%ebx\n\t"
+                   "int $0x10\n\t"
+                   "cli\n\t",
+                   1,
+                   OUT_CONSTRAINTS ( "=a" ( character ) ),
+                   IN_CONSTRAINTS ( "a" ( character ) ),
+                   CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
+
+       /* NOTE: %eax may be clobbered, so must be specified as an output
+        * parameter, even though we don't then do anything with it.
+        */
+}
+
+/**************************************************************************
+bios_getchar - Get a character from console
+**************************************************************************/
+static int bios_getchar ( void ) {
+       uint16_t character;
+       
+       REAL_EXEC ( rm_console_getc,
+                   "sti\n\t"
+                   "xorw %%ax, %%ax\n\t"
+                   "int $0x16\n\t"
+                   "cli\n\t",
+                   1,
+                   OUT_CONSTRAINTS ( "=a" ( character ) ),
+                   IN_CONSTRAINTS (),
+                   CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
+       
+       return ( character & 0xff );
+}
+
+/**************************************************************************
+bios_iskey - Check for keyboard interrupt
+**************************************************************************/
+static int bios_iskey ( void ) {
+       uint16_t flags;
+       
+       REAL_EXEC ( rm_console_ischar,
+                   "sti\n\t"
+                   "movb $1, %%ah\n\t"
+                   "int $0x16\n\t"
+                   "pushfw\n\t"
+                   "popw %%ax\n\t"
+                   "cli\n\t",
+                   1,
+                   OUT_CONSTRAINTS ( "=a" ( flags ) ),
+                   IN_CONSTRAINTS (),
+                   CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
+       
+       return ( ( flags & ZF ) == 0 );
+}
+
+static struct console_driver bios_console __console_driver = {
+       .putchar = bios_putchar,
+       .getchar = bios_getchar,
+       .iskey = bios_iskey,
+};
diff --git a/src/arch/i386/firmware/pcbios/console.c b/src/arch/i386/firmware/pcbios/console.c
deleted file mode 100644 (file)
index f994f06..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Etherboot routines for PCBIOS firmware.
- *
- * Body of routines taken from old pcbios.S
- */
-
-#ifdef PCBIOS
-
-#include "etherboot.h"
-#include "realmode.h"
-#include "segoff.h"
-
-#define ZF ( 1 << 6 )
-
-/**************************************************************************
-CONSOLE_PUTC - Print a character on console
-**************************************************************************/
-void console_putc ( int character )
-{
-       struct {
-               reg16_t ax;
-       } PACKED in_stack;
-
-       RM_FRAGMENT(rm_console_putc,
-               "sti\n\t"
-               "popw %ax\n\t"
-               "movb $0x0e, %ah\n\t"
-               "movl $1, %ebx\n\t"
-               "int $0x10\n\t"
-               "cli\n\t"
-       );
-
-       in_stack.ax.l = character;
-       real_call ( rm_console_putc, &in_stack, NULL );
-}
-
-/**************************************************************************
-CONSOLE_GETC - Get a character from console
-**************************************************************************/
-int console_getc ( void )
-{
-       RM_FRAGMENT(rm_console_getc,
-               "sti\n\t"
-               "xorw %ax, %ax\n\t"
-               "int $0x16\n\t"
-               "xorb %ah, %ah\n\t"
-               "cli\n\t"
-       );      
-
-       return real_call ( rm_console_getc, NULL, NULL );
-}
-
-/**************************************************************************
-CONSOLE_ISCHAR - Check for keyboard interrupt
-**************************************************************************/
-int console_ischar ( void )
-{
-       RM_FRAGMENT(rm_console_ischar,
-               "sti\n\t"
-               "movb $1, %ah\n\t"
-               "int $0x16\n\t"
-               "pushfw\n\t"
-               "popw %ax\n\t"
-               "cli\n\t"
-       );
-
-       return ( ( real_call ( rm_console_ischar, NULL, NULL ) & ZF ) == 0 );
-}
-
-/**************************************************************************
-GETSHIFT - Get keyboard shift state
-**************************************************************************/
-int getshift ( void )
-{
-       RM_FRAGMENT(rm_getshift,
-               "sti\n\t"
-               "movb $2, %ah\n\t"
-               "int $0x16\n\t"
-               "andw $0x3, %ax\n\t" 
-               "cli\n\t"
-       );
-
-       return real_call ( rm_getshift, NULL, NULL );
-}
-
-#endif /* PCBIOS */
diff --git a/src/arch/i386/firmware/pcbios/gateA20.c b/src/arch/i386/firmware/pcbios/gateA20.c
new file mode 100644 (file)
index 0000000..bbee376
--- /dev/null
@@ -0,0 +1,90 @@
+#include "realmode.h"
+#include "timer.h"
+#include "latch.h"
+#include "bios.h"
+
+#define K_RDWR         0x60            /* keyboard data & cmds (read/write) */
+#define K_STATUS       0x64            /* keyboard status */
+#define K_CMD          0x64            /* keybd ctlr command (write-only) */
+
+#define K_OBUF_FUL     0x01            /* output buffer full */
+#define K_IBUF_FUL     0x02            /* input buffer full */
+
+#define KC_CMD_WIN     0xd0            /* read  output port */
+#define KC_CMD_WOUT    0xd1            /* write output port */
+#define 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 */
+
+enum { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402,
+       Query_A20_Support = 0x2403 };
+
+#define CF ( 1 << 0 )
+
+#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
+ *
+ * Note that this function gets called as part of the return path from
+ * librm's real_call, which is used to make the int15 call if librm is
+ * being used.  To avoid an infinite recursion, we make gateA20_set
+ * return immediately if it is already part of the call stack.
+ */
+void gateA20_set ( void ) {
+       static char reentry_guard = 0;
+       uint16_t flags, status;
+
+       if ( reentry_guard )
+               return;
+       reentry_guard = 1;
+
+       REAL_EXEC ( rm_enableA20,
+                   "sti\n\t"
+                   "stc\n\t"
+                   "int $0x15\n\t"
+                   "pushfw\n\t"
+                   "popw %%bx\n\t"
+                   "cli\n\t",
+                   2,
+                   OUT_CONSTRAINTS ( "=a" ( status ), "=b" ( flags ) ),
+                   IN_CONSTRAINTS ( "a" ( Enable_A20 ) ),
+                   CLOBBER ( "ecx", "edx", "ebp", "esi", "edi" ) );
+
+       if ( ( flags & CF ) ||
+            ( ( status >> 8 ) & 0xff ) ) {
+               /* INT 15 method failed, try alternatives */
+#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 */
+       }
+       
+       reentry_guard = 0;
+}
+
+void gateA20_unset ( void ) {
+       /* Not currently implemented */
+}
index 18ae86dade2ced1bc3c4c0dfdf669e49b2a05813..3284e1efdd9c7fdd88c27deec4df22d9011f1d54 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef PCBIOS
-
-#include "etherboot.h"
+#include "stdint.h"
+#include "stddef.h"
 #include "realmode.h"
+#include "init.h"
+#include "memsizes.h"
 
 #define CF ( 1 << 0 )
 
@@ -16,109 +17,131 @@ struct meminfo meminfo;
 /**************************************************************************
 BASEMEMSIZE - Get size of the conventional (base) memory
 **************************************************************************/
-unsigned short basememsize ( void )
-{
-       RM_FRAGMENT(rm_basememsize,
-               "int $0x12\n\t"
-       );      
-       return real_call ( rm_basememsize, NULL, NULL );
+static unsigned short basememsize ( void ) {
+       uint16_t int12_basememsize, fbms_basememsize;
+
+       /* There are two methods for retrieving the base memory size:
+        * INT 12 and the BIOS FBMS counter at 40:13.  We read both
+        * and use the smaller value, to be paranoid.
+        */
+
+       REAL_EXEC ( rm_basememsize,
+                   "int $0x12\n\t",
+                   1,
+                   OUT_CONSTRAINTS ( "=a" ( int12_basememsize ) ),
+                   IN_CONSTRAINTS (),
+                   CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
+
+       get_real ( fbms_basememsize, 0x40, 0x13 );
+
+       return ( int12_basememsize < fbms_basememsize ?
+                int12_basememsize : fbms_basememsize );
 }
 
 /**************************************************************************
-MEMSIZE - Determine size of extended memory
+MEMSIZE - Determine size of extended memory, in kB
 **************************************************************************/
-unsigned int memsize ( void )
-{
-       struct {
-               reg16_t ax;
-       } PACKED in_stack;
-       struct {
-               reg16_t ax;
-               reg16_t bx;
-               reg16_t cx;
-               reg16_t dx;
-               reg16_t flags;
-       } PACKED out_stack;
+static unsigned int memsize ( void ) {
+       uint16_t extmem_1m_to_16m_k, extmem_16m_plus_64k;
+       uint16_t confmem_1m_to_16m_k, confmem_16m_plus_64k;
+       uint16_t flags;
        int memsize;
 
-       RM_FRAGMENT(rm_memsize,
-       /* Some buggy BIOSes don't clear/set carry on pass/error of
+       /* Try INT 15,e801 first
+        *
+        * Some buggy BIOSes don't clear/set carry on pass/error of
         * e801h memory size call or merely pass cx,dx through without
         * changing them, so we set carry and zero cx,dx before call.
         */
-               "stc\n\t"
-               "xorw %cx,%cx\n\t"
-               "xorw %dx,%dx\n\t"
-               "popw %ax\n\t"
-               "int $0x15\n\t"
-               "pushfw\n\t"
-               "pushw %dx\n\t"
-               "pushw %cx\n\t"
-               "pushw %bx\n\t"
-               "pushw %ax\n\t"
-       );
-
-       /* Try INT 15,e801 first */
-       in_stack.ax.word = 0xe801;
-       real_call ( rm_memsize, &in_stack, &out_stack );
-       if ( out_stack.flags.word & CF ) {
-               /* INT 15,e801 not supported: try INT 15,88 */
-               in_stack.ax.word = 0x8800;
-               memsize = real_call ( rm_memsize, &in_stack, &out_stack );
-       } else {
-               /* Some BIOSes report extended memory via ax,bx rather
-                * than cx,dx
-                */
-               if ( (out_stack.cx.word==0) && (out_stack.dx.word==0) ) {
-                       /* Use ax,bx */
-                       memsize = ( out_stack.bx.word<<6 ) + out_stack.ax.word;
+       REAL_EXEC ( rm_mem_e801,
+                   "stc\n\t"
+                   "int $0x15\n\t"
+                   "pushfw\n\t"        /* flags -> %di */
+                   "popw %%di\n\t",
+                   5,
+                   OUT_CONSTRAINTS ( "=a" ( extmem_1m_to_16m_k ),
+                                     "=b" ( extmem_16m_plus_64k ),
+                                     "=c" ( confmem_1m_to_16m_k ),
+                                     "=d" ( confmem_16m_plus_64k ),
+                                     "=D" ( flags ) ),
+                   IN_CONSTRAINTS ( "a" ( 0xe801 ),
+                                    "c" ( 0 ),
+                                    "d" ( 0 ) ),
+                   CLOBBER ( "ebp", "esi" ) );
+
+       if ( ! ( flags & CF ) ) {
+               /* INT 15,e801 succeeded */
+               if ( confmem_1m_to_16m_k || confmem_16m_plus_64k ) {
+                       /* Use confmem (cx,dx) values */
+                       memsize = confmem_1m_to_16m_k +
+                               ( confmem_16m_plus_64k << 6 );
                } else {
-                       /* Use cx,dx */
-                       memsize = ( out_stack.dx.word<<6 ) + out_stack.cx.word;
+                       /* Use extmem (ax,bx) values */
+                       memsize = extmem_1m_to_16m_k +
+                               ( extmem_16m_plus_64k << 6 );
                }
+       } else {
+               /* INT 15,e801 failed; fall back to INT 15,88
+                *
+                * CF is apparently unreliable and should be ignored.
+                */
+               REAL_EXEC ( rm_mem_88,
+                           "int $0x15\n\t",
+                           1,
+                           OUT_CONSTRAINTS ( "=a" ( extmem_1m_to_16m_k ) ),
+                           IN_CONSTRAINTS ( "a" ( 0x88 << 8 ) ),
+                           CLOBBER ( "ebx", "ecx", "edx",
+                                     "ebp", "esi", "edi" ) );
+               memsize = extmem_1m_to_16m_k;
        }
+
        return memsize;
 }
 
-#define SMAP ( 0x534d4150 )
-int meme820 ( struct e820entry *buf, int count )
-{
-       struct {
-               reg16_t flags;
-               reg32_t eax;
-               reg32_t ebx;
-               struct e820entry entry;
-       } PACKED stack;
-       int index = 0;
-
-       RM_FRAGMENT(rm_meme820,
-               "addw $6, %sp\n\t"      /* skip flags, eax */
-               "popl %ebx\n\t"
-               "pushw %ss\n\t" /* es:di = ss:sp */
-               "popw %es\n\t"
-               "movw %sp, %di\n\t"
-               "movl $0xe820, %eax\n\t"
-               "movl $" RM_STR(SMAP) ", %edx\n\t"
-               "movl $" RM_STR(E820ENTRY_SIZE) ", %ecx\n\t"
-               "int $0x15\n\t"
-               "pushl %ebx\n\t"
-               "pushl %eax\n\t"
-               "pushfw\n\t"
-       );
-
-       stack.ebx.dword = 0; /* 'EOF' marker */
-       while ( ( index < count ) &&
-               ( ( index == 0 ) || ( stack.ebx.dword != 0 ) ) ) {
-               real_call ( rm_meme820, &stack, &stack );
-               if ( stack.eax.dword != SMAP ) return 0;
-               if ( stack.flags.word & CF ) return 0;
-               buf[index++] = stack.entry;
-       }
+/**************************************************************************
+MEME820 - Retrieve the E820 BIOS memory map
+**************************************************************************/
+#define SMAP ( 0x534d4150 ) /* "SMAP" */
+static int meme820 ( struct e820entry *buf, int count ) {
+       int index;
+       uint16_t basemem_entry;
+       uint32_t smap, next;
+       uint16_t flags;
+       uint32_t discard_c, discard_d;
+
+       index = 0;
+       next = 0;
+       do {
+               basemem_entry = BASEMEM_PARAMETER_INIT ( buf[index] );
+               REAL_EXEC ( rm_mem_e820,
+                           "int $0x15\n\t"
+                           "pushfw\n\t"        /* flags -> %di */
+                           "popw %%di\n\t",
+                           5,
+                           OUT_CONSTRAINTS ( "=a" ( smap ),
+                                             "=b" ( next ),
+                                             "=c" ( discard_c ),
+                                             "=d" ( discard_d ),
+                                             "=D" ( flags ) ),
+                           IN_CONSTRAINTS ( "a" ( 0xe820 ),
+                                            "b" ( next ),
+                                            "c" ( sizeof (struct e820entry) ),
+                                            "d" ( SMAP ),
+                                            "D" ( basemem_entry ) ),
+                           CLOBBER ( "ebp", "esi" ) );
+               BASEMEM_PARAMETER_DONE ( buf[index] );
+               if ( smap != SMAP ) return 0;
+               if ( flags & CF ) break;
+               index++;
+       } while ( ( index < count ) && ( next != 0 ) );
+               
        return index;
 }
 
-void get_memsizes(void)
-{
+/**************************************************************************
+GET_MEMSIZES - Retrieve the system memory map via any available means
+**************************************************************************/
+void get_memsizes ( void ) {
        /* Ensure we don't stomp bios data structutres.
         * the interrupt table: 0x000 - 0x3ff
         * the bios data area:  0x400 - 0x502
@@ -127,16 +150,19 @@ void get_memsizes(void)
        static const unsigned min_addr = 0x600;
        unsigned i;
        unsigned basemem;
-       basemem = get_free_base_memory();
+
+       /* Retrieve memory information from the BIOS */
        meminfo.basememsize = basememsize();
+       basemem = meminfo.basememsize << 10;
        meminfo.memsize = memsize();
 #ifndef IGNORE_E820_MAP
-       meminfo.map_count = meme820(meminfo.map, E820MAX);
+       meminfo.map_count = meme820 ( meminfo.map, E820MAX );
 #else
        meminfo.map_count = 0;
 #endif
-       if (meminfo.map_count == 0) {
-               /* If we don't have an e820 memory map fake it */
+
+       /* If we don't have an e820 memory map fake it */
+       if ( meminfo.map_count == 0 ) {
                meminfo.map_count = 2;
                meminfo.map[0].addr = 0;
                meminfo.map[0].size = meminfo.basememsize << 10;
@@ -145,57 +171,56 @@ void get_memsizes(void)
                meminfo.map[1].size = meminfo.memsize << 10;
                meminfo.map[1].type = E820_RAM;
        }
+
        /* Scrub the e820 map */
-       for(i = 0; i < meminfo.map_count; i++) {
-               if (meminfo.map[i].type != E820_RAM) {
+       for ( i = 0; i < meminfo.map_count; i++ ) {
+               if ( meminfo.map[i].type != E820_RAM ) {
                        continue;
                }
+
                /* Reserve the bios data structures */
-               if (meminfo.map[i].addr < min_addr) {
+               if ( meminfo.map[i].addr < min_addr ) {
                        unsigned long delta;
                        delta = min_addr - meminfo.map[i].addr;
-                       if (delta > meminfo.map[i].size) {
+                       if ( delta > meminfo.map[i].size ) {
                                delta = meminfo.map[i].size;
                        }
                        meminfo.map[i].addr = min_addr;
                        meminfo.map[i].size -= delta;
                }
-               /* Ensure the returned e820 map is in sync 
-                * with the actual memory state 
+
+               /* Ensure the returned e820 map is in sync with the
+                * actual memory state
                 */
-               if ((meminfo.map[i].addr < 0xa0000) && 
-                       ((meminfo.map[i].addr + meminfo.map[i].size) > basemem))
-               {
-                       if (meminfo.map[i].addr <= basemem) {
-                               meminfo.map[i].size = basemem - meminfo.map[i].addr;
+               if ( ( meminfo.map[i].addr < 0xa0000 ) && 
+                    (( meminfo.map[i].addr+meminfo.map[i].size ) > basemem )){
+                       if ( meminfo.map[i].addr <= basemem ) {
+                               meminfo.map[i].size = basemem
+                                       - meminfo.map[i].addr;
                        } else {
                                meminfo.map[i].addr = basemem;
                                meminfo.map[i].size = 0;
                        }
                }
        }
+
 #if MEMSIZES_DEBUG
-{
-       int i;
-       printf("basememsize %d\n", meminfo.basememsize);
-       printf("memsize %d\n",     meminfo.memsize);
-       printf("Memory regions(%d):\n", meminfo.map_count);
-       for(i = 0; i < meminfo.map_count; i++) {
+       printf ( "basememsize %d\n", meminfo.basememsize );
+       printf ( "memsize %d\n",     meminfo.memsize );
+       printf ( "Memory regions(%d):\n", meminfo.map_count );
+       for ( i = 0; i < meminfo.map_count; i++ ) {
                unsigned long long r_start, r_end;
                r_start = meminfo.map[i].addr;
                r_end = r_start + meminfo.map[i].size;
-               printf("[%X%X, %X%X) type %d\n", 
-                       (unsigned long)(r_start >> 32),
-                       (unsigned long)r_start,
-                       (unsigned long)(r_end >> 32),
-                       (unsigned long)r_end,
-                       meminfo.map[i].type);
-#if defined(CONSOLE_FIRMWARE)
-               sleep(1); /* No way to see 32 entries on a standard 80x25 screen... */
-#endif
+               printf ( "[%X%X, %X%X) type %d\n", 
+                        ( unsigned long ) ( r_start >> 32 ),
+                        ( unsigned long ) r_start,
+                        ( unsigned long ) ( r_end >> 32 ),
+                        ( unsigned long ) r_end,
+                        meminfo.map[i].type );
        }
-}
 #endif
+
 }
 
-#endif /* PCBIOS */
+INIT_FN ( INIT_MEMSIZES, get_memsizes, NULL, NULL );
diff --git a/src/arch/i386/include/bios.h b/src/arch/i386/include/bios.h
new file mode 100644 (file)
index 0000000..afc648b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef BIOS_H
+#define BIOS_H
+
+extern unsigned long currticks ( void );
+extern void cpu_nap ( void );
+extern void disk_init ( void );
+extern unsigned int pcbios_disk_read ( int drive, int cylinder, int head,
+                                      int sector, char *fixme_buf );
+
+#endif /* BIOS_H */
diff --git a/src/arch/i386/include/bochs.h b/src/arch/i386/include/bochs.h
new file mode 100644 (file)
index 0000000..73f43c3
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef BOCHS_H
+#define BOCHS_H
+
+/*
+ * This file defines "bochsbp", the magic breakpoint instruction that
+ * is incredibly useful when debugging under bochs.
+ *
+ */
+
+#ifdef ASSEMBLY
+
+/* Breakpoint for when debugging under bochs */
+#define bochsbp xchgw %bx, %bx
+#define BOCHSBP bochsbp
+
+#else /* ASSEMBLY */
+
+/* Breakpoint for when debugging under bochs */
+static inline void bochsbp ( void ) {
+       __asm__ __volatile__ ( "xchgw %bx, %bx" );
+}
+
+#endif /* ASSEMBLY */
+
+#warning "bochs.h should not be included into production code"
+
+#endif /* BOCHS_H */
index 600a869233ded605af39c894564b6ccab8271577..71b0905ff7f33f342a6f3f72ed0c4142086f375d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef HIDEMEM_H
 #define HIDEMEM_H
 
-#include "segoff.h"
+#include "realmode.h"
 
 extern int install_e820mangler ( void *new_mangler );
 extern int hide_etherboot ( void );
index 0764edafac8aa7a0092d15bad7deb5d5d4fecf90..a4e4b397e126488c884ba1c2145e4ffcb4b7299b 100644 (file)
@@ -1,9 +1,14 @@
-#ifndef ETHERBOOT_I386_HOOKS_H
-#define ETHERBOOT_I386_HOOKS_H
+#ifndef HOOKS_H
+#define HOOKS_H
 
-void arch_main(in_call_data_t *data, va_list params);
-void arch_on_exit(int status);
-#define arch_relocate_to(addr)
-void arch_relocated_from ( uint32_t old_addr );
+/* in hooks.o */
+extern void arch_initialise ( struct i386_all_regs *regs,
+                             void (*retaddr) (void) );
+extern void arch_main ( struct i386_all_regs *regs );
 
-#endif /* ETHERBOOT_I386_HOOKS_H */
+/* in hooks_rm.o */
+extern void arch_rm_initialise ( struct i386_all_regs *regs,
+                                void (*retaddr) (void) );
+extern void arch_rm_main ( struct i386_all_regs *regs );
+
+#endif /* HOOKS_H */
index e351a0c103caabb8c9b377b2253f4930c1519aee..5b6a624354198502d66e9bb1df6f39c8f98d2de9 100644 (file)
@@ -1,22 +1,8 @@
 #ifndef        ETHERBOOT_IO_H
 #define ETHERBOOT_IO_H
 
-
-/* Amount of relocation etherboot is experiencing */
-extern unsigned long virt_offset;
-
-/* Don't require identity mapped physical memory,
- * osloader.c is the only valid user at the moment.
- */
-static inline unsigned long virt_to_phys(volatile const void *virt_addr)
-{
-       return ((unsigned long)virt_addr) + virt_offset;
-}
-
-static inline void *phys_to_virt(unsigned long phys_addr)
-{
-       return (void *)(phys_addr - virt_offset);
-}
+#include "compiler.h"
+#include "virtaddr.h"
 
 /* virt_to_bus converts an addresss inside of etherboot [_start, _end]
  * into a memory access cards can use.
diff --git a/src/arch/i386/include/kir.h b/src/arch/i386/include/kir.h
new file mode 100644 (file)
index 0000000..84633d2
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef KIR_H
+#define KIR_H
+
+#ifndef KEEP_IT_REAL
+#error "kir.h can be used only with -DKEEP_IT_REAL"
+#endif
+
+#ifdef ASSEMBLY
+
+#define code32 code16gcc
+
+#else /* ASSEMBLY */
+
+__asm__ ( ".code16gcc" );
+
+#endif /* ASSEMBLY */
+
+#endif /* KIR_H */
diff --git a/src/arch/i386/include/libkir.h b/src/arch/i386/include/libkir.h
new file mode 100644 (file)
index 0000000..5bac42d
--- /dev/null
@@ -0,0 +1,184 @@
+#ifndef LIBKIR_H
+#define LIBKIR_H
+
+#include "realmode.h"
+
+#ifndef ASSEMBLY
+
+/*
+ * Full API documentation for these functions is in realmode.h.
+ *
+ */
+
+/* Copy to/from base memory */
+
+static inline void copy_to_real_libkir ( uint16_t dest_seg, uint16_t dest_off,
+                                        void *src, size_t n ) {
+       __asm__ ( "movw %4, %%es\n\t"
+                 "cld\n\t"
+                 "rep movsb\n\t"
+                 "pushw %%ds\n\t" /* restore %es */
+                 "popw %%es\n\t"
+                 : "=S" ( src ), "=D" ( dest_off ), "=c" ( n ) /* clobbered */
+                 : "S" ( src ), "r" ( dest_seg ), "D" ( dest_off ), "c" ( n )
+                 : "memory"
+                 );
+}
+
+static inline void copy_from_real_libkir ( void *dest,
+                                          uint16_t src_seg, uint16_t src_off,
+                                          size_t n ) {
+       __asm__ ( "movw %%ax, %%ds\n\t"
+                 "cld\n\t"
+                 "rep movsb\n\t"
+                 "pushw %%es\n\t" /* restore %ds */
+                 "popw %%ds\n\t"
+                 : "=S" ( src_off ), "=D" ( dest ), "=c" ( n ) /* clobbered */
+                 : "a" ( src_seg ), "S" ( src_off ), "D" ( dest ), "c" ( n )
+                 : "memory"
+                 );
+}
+#define copy_to_real copy_to_real_libkir
+#define copy_from_real copy_from_real_libkir
+
+/*
+ * Transfer individual values to/from base memory.  There may well be
+ * a neater way to do this.  We have two versions: one for constant
+ * offsets (where the mov instruction must be of the form "mov
+ * %es:123, %xx") and one for non-constant offsets (where the mov
+ * instruction must be of the form "mov %es:(%xx), %yx".  If it's
+ * possible to incorporate both forms into one __asm__ instruction, I
+ * don't know how to do it.
+ *
+ * Ideally, the mov instruction should be "mov%z0"; the "%z0" is meant
+ * to expand to either "b", "w" or "l" depending on the size of
+ * operand 0.  This would remove the (minor) ambiguity in the mov
+ * instruction.  However, gcc on at least my system barfs with an
+ * "internal compiler error" when confronted with %z0.
+ *
+ */
+
+#define put_real_kir_const_off( var, seg, off )                                     \
+       __asm__ ( "movw %w1, %%es\n\t"                                       \
+                 "mov %0, %%es:%c2\n\t"                                     \
+                 "pushw %%ds\n\t" /* restore %es */                         \
+                 "popw %%es\n\t"                                            \
+                 :                                                          \
+                 : "r,r" ( var ), "rm,rm" ( seg ), "i,!r" ( off )           \
+                 )
+
+#define put_real_kir_nonconst_off( var, seg, off )                          \
+       __asm__ ( "movw %w1, %%es\n\t"                                       \
+                 "mov %0, %%es:(%2)\n\t"                                    \
+                 "pushw %%ds\n\t" /* restore %es */                         \
+                 "popw %%es\n\t"                                            \
+                 :                                                          \
+                 : "r" ( var ), "rm" ( seg ), "r" ( off )                   \
+                 )
+
+#define put_real_kir( var, seg, off )                                       \
+       do {                                                                 \
+         if ( __builtin_constant_p ( off ) )                                \
+                 put_real_kir_const_off ( var, seg, off );                  \
+         else                                                               \
+                 put_real_kir_nonconst_off ( var, seg, off );               \
+       } while ( 0 )
+
+#define get_real_kir_const_off( var, seg, off )                                     \
+       __asm__ ( "movw %w1, %%es\n\t"                                       \
+                 "mov %%es:%c2, %0\n\t"                                     \
+                 "pushw %%ds\n\t" /* restore %es */                         \
+                 "popw %%es\n\t"                                            \
+                 : "=r,r" ( var )                                           \
+                 : "rm,rm" ( seg ), "i,!r" ( off )                          \
+                 )
+
+#define get_real_kir_nonconst_off( var, seg, off )                          \
+       __asm__ ( "movw %w1, %%es\n\t"                                       \
+                 "mov %%es:(%2), %0\n\t"                                    \
+                 "pushw %%ds\n\t" /* restore %es */                         \
+                 "popw %%es\n\t"                                            \
+                 : "=r" ( var )                                             \
+                 : "rm" ( seg ), "r" ( off )                                \
+                 )
+
+#define get_real_kir( var, seg, off )                                       \
+       do {                                                                 \
+         if ( __builtin_constant_p ( off ) )                                \
+                 get_real_kir_const_off ( var, seg, off );                  \
+         else                                                               \
+                 get_real_kir_nonconst_off ( var, seg, off );               \
+       } while ( 0 )
+
+#define put_real put_real_kir
+#define get_real get_real_kir
+
+/* Place/remove parameter on real-mode stack in a way that's
+ * compatible with libkir
+ */
+#define BASEMEM_PARAMETER_INIT_LIBKIR( param ) \
+       ( ( uint16_t ) ( ( uint32_t ) & ( param ) ) )
+#define BASEMEM_PARAMETER_DONE_LIBKIR( param )
+#define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBKIR
+#define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBKIR
+
+/* REAL_CALL: call an external real-mode routine */
+#define OUT_CONSTRAINTS(...) __VA_ARGS__
+#define IN_CONSTRAINTS(...) "m" ( __routine ), ## __VA_ARGS__
+#define CLOBBER(...) __VA_ARGS__
+#define REAL_CALL( routine, num_out_constraints, out_constraints,           \
+                  in_constraints, clobber )                                 \
+       do {                                                                 \
+               segoff_t __routine = routine;                                \
+               __asm__ __volatile__ (                                       \
+                       "pushl %" #num_out_constraints "\n\t"                \
+                       ".code16\n\t"                                        \
+                       "pushw %%gs\n\t"        /* preserve segs */          \
+                       "pushw %%fs\n\t"                                     \
+                       "pushw %%es\n\t"                                     \
+                       "pushw %%ds\n\t"                                     \
+                       "pushw %%cs\n\t"        /* lcall to routine */       \
+                       "call 1f\n\t"                                        \
+                       "jmp 2f\n\t"                                         \
+                       "\n1:\n\t"                                           \
+                       "addr32 pushl 12(%%esp)\n\t"                         \
+                       "lret\n\t"                                           \
+                       "\n2:\n\t"                                           \
+                       "popw %%ds\n\t"         /* restore segs */           \
+                       "popw %%es\n\t"                                      \
+                       "popw %%fs\n\t"                                      \
+                       "popw %%gs\n\t"                                      \
+                       "addw $4, %%sp\n\t"                                  \
+                       ".code16gcc\n\t"                                     \
+                       : out_constraints : in_constraints : clobber         \
+               );                                                           \
+       } while ( 0 )
+
+/* REAL_EXEC: execute some inline assembly code in a way that matches
+ * the interface of librm
+ */
+
+#define IN_CONSTRAINTS_NO_ROUTINE( routine, ... ) __VA_ARGS__
+#define REAL_EXEC( name, asm_code_str, num_out_constraints, out_constraints, \
+                  in_constraints, clobber )                                 \
+       __asm__ __volatile__ (                                               \
+               ".code16\n\t"                                                \
+               "pushw %%gs\n\t"                                             \
+               "pushw %%fs\n\t"                                             \
+               "pushw %%es\n\t"                                             \
+               "pushw %%ds\n\t"                                             \
+               "\n" #name ":\n\t"                                           \
+               asm_code_str                                                 \
+               "popw %%ds\n\t"                                              \
+               "popw %%es\n\t"                                              \
+               "popw %%fs\n\t"                                              \
+               "popw %%gs\n\t"                                              \
+               ".code16gcc\n\t"                                             \
+               : out_constraints                                            \
+               : IN_CONSTRAINTS_NO_ROUTINE ( in_constraints )               \
+               : clobber                                                    \
+               );
+
+#endif /* ASSEMBLY */
+
+#endif /* LIBKIR_H */
diff --git a/src/arch/i386/include/librm.h b/src/arch/i386/include/librm.h
new file mode 100644 (file)
index 0000000..16bfc08
--- /dev/null
@@ -0,0 +1,186 @@
+#ifndef LIBRM_H
+#define LIBRM_H
+
+/* Drag in protected-mode segment selector values */
+#include "virtaddr.h"
+#include "realmode.h"
+
+#ifndef ASSEMBLY
+
+#include "stddef.h"
+#include "string.h"
+
+/*
+ * Data structures and type definitions
+ *
+ */
+
+/* Real-mode call parameter block, as passed to real_call */
+struct real_call_params {
+       struct i386_seg_regs;
+       struct i386_regs;
+       segoff_t rm_code;
+       segoff_t reserved;
+} PACKED;
+
+/* Current location of librm in base memory */
+extern char *installed_librm;
+
+/* Start and size of our source copy of librm (i.e. the one that we
+ * can install by copying it to base memory and setting
+ * installed_librm)
+ */
+extern char librm[];
+extern size_t _librm_size[];
+
+/* Linker symbols for offsets within librm.  Other symbols should
+ * almost certainly not be referred to from C code.
+ */
+extern void (*_real_to_prot[]) ( void );
+extern void (*_prot_to_real[]) ( void );
+extern void (*_prot_call[]) ( void );
+extern void (*_real_call[]) ( void );
+extern segoff_t _rm_stack[];
+extern uint32_t _pm_stack[];
+extern char _librm_ref_count[];
+
+/* Symbols within current installation of librm */
+#define LIBRM_VAR( sym ) \
+       ( * ( ( typeof ( * _ ## sym ) * ) \
+             & ( installed_librm [ (int) _ ## sym ] ) ) )
+#define LIBRM_FN( sym ) \
+        ( ( typeof ( * _ ## sym ) ) \
+             & ( installed_librm [ (int) _ ## sym ] ) )
+#define LIBRM_CONSTANT( sym ) \
+       ( ( typeof ( * _ ## sym ) ) ( _ ## sym ) )
+#define inst_real_to_prot      LIBRM_FN ( real_to_prot )
+#define inst_prot_to_real      LIBRM_FN ( prot_to_real )
+#define inst_prot_call         LIBRM_FN ( prot_call )
+#define inst_real_call         LIBRM_FN ( real_call )
+#define inst_rm_stack          LIBRM_VAR ( rm_stack )
+#define inst_pm_stack          LIBRM_VAR ( pm_stack )
+#define inst_librm_ref_count   LIBRM_VAR ( librm_ref_count )
+#define librm_size             LIBRM_CONSTANT ( librm_size )
+
+/* Functions that librm expects to be able to link to.  Included here
+ * so that the compiler will catch prototype mismatches.
+ */
+extern void _phys_to_virt ( void );
+extern void _virt_to_phys ( void );
+extern void gateA20_set ( void );
+
+/*
+ * librm_mgmt: functions for manipulating base memory and executing
+ * real-mode code.
+ *
+ * Full API documentation for these functions is in realmode.h.
+ *
+ */
+
+/* Macro for obtaining a physical address from a segment:offset pair. */
+#define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
+
+/* Copy to/from base memory */
+static inline void copy_to_real_librm ( uint16_t dest_seg, uint16_t dest_off,
+                                       void *src, size_t n ) {
+       memcpy ( VIRTUAL ( dest_seg, dest_off ), src, n );
+}
+static inline void copy_from_real_librm ( void *dest,
+                                         uint16_t src_seg, uint16_t src_off,
+                                         size_t n ) {
+       memcpy ( dest, VIRTUAL ( src_seg, src_off ), n );
+}
+#define put_real_librm( var, dest_seg, dest_off )                            \
+       do {                                                                  \
+               * ( ( typeof(var) * ) VIRTUAL ( dest_seg, dest_off ) ) = var; \
+       } while ( 0 )
+#define get_real_librm( var, src_seg, src_off )                                      \
+       do {                                                                  \
+               var = * ( ( typeof(var) * ) VIRTUAL ( src_seg, src_off ) ); \
+       } while ( 0 )
+#define copy_to_real copy_to_real_librm
+#define copy_from_real copy_from_real_librm
+#define put_real put_real_librm
+#define get_real get_real_librm
+
+/* Copy to/from real-mode stack */
+extern uint16_t copy_to_rm_stack ( void *data, size_t size );
+extern void remove_from_rm_stack ( void *data, size_t size );
+
+/* Place/remove parameter on real-mode stack in a way that's
+ * compatible with libkir
+ */
+#define BASEMEM_PARAMETER_INIT_LIBRM( param ) \
+       copy_to_rm_stack ( & ( param ), sizeof ( param ) )
+#define BASEMEM_PARAMETER_DONE_LIBRM( param ) \
+       remove_from_rm_stack ( & ( param ), sizeof ( param ) )
+#define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBRM
+#define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBRM
+
+/* REAL_FRAGMENT: Declare and define a real-mode code fragment in .text16 */
+#define        REAL_FRAGMENT( name, asm_code_str )                             \
+       extern void name ( void );                                      \
+       extern char name ## _size[];                                    \
+       __asm__ __volatile__ (                                          \
+               ".section \".text16\"\n\t"                              \
+               ".code16\n\t"                                           \
+               ".arch i386\n\t"                                        \
+               #name ":\n\t"                                           \
+               asm_code_str "\n\t"                                     \
+               "lret\n\t"                                              \
+               #name "_end:\n\t"                                       \
+               ".equ " #name "_size, " #name "_end - " #name "\n\t"    \
+               ".code32\n\t"                                           \
+               ".previous\n\t"                                         \
+               : :                                                     \
+       )
+#define FRAGMENT_SIZE( fragment ) ( (size_t) fragment ## _size )
+
+/* REAL_CALL: call a real-mode routine via librm */
+#define OUT_CONSTRAINTS(...) __VA_ARGS__
+#define IN_CONSTRAINTS(...) "m" ( __routine ), ## __VA_ARGS__
+#define CLOBBER(...) __VA_ARGS__
+#define REAL_CALL( routine, num_out_constraints, out_constraints,           \
+                  in_constraints, clobber )                                 \
+       do {                                                                 \
+               segoff_t __routine = routine;                                \
+               __asm__ __volatile__ (                                       \
+                                     "pushl %" #num_out_constraints "\n\t"  \
+                                     "call 1f\n\t"                          \
+                                     "jmp 2f\n\t"                           \
+                                     "\n1:\n\t"                             \
+                                     "pushl installed_librm\n\t"            \
+                                     "addl $_real_call, 0(%%esp)\n\t"       \
+                                     "ret\n\t"                              \
+                                     "\n2:\n\t"                             \
+                                     "addl $4, %%esp\n\t"                   \
+                                     : out_constraints                      \
+                                     : in_constraints                       \
+                                     : clobber                              \
+                                     );                                     \
+       } while ( 0 )
+
+/* REAL_EXEC: combine RM_FRAGMENT and REAL_CALL into one handy unit */
+#define PASSTHRU(...) __VA_ARGS__
+#define REAL_EXEC( name, asm_code_str, num_out_constraints, out_constraints, \
+                  in_constraints, clobber )                                 \
+       do {                                                                 \
+               segoff_t fragment;                                           \
+                                                                            \
+               REAL_FRAGMENT ( name, asm_code_str );                        \
+                                                                            \
+               fragment.segment = inst_rm_stack.segment;                    \
+               fragment.offset =                                            \
+                       copy_to_rm_stack ( name, FRAGMENT_SIZE ( name ) );   \
+                                                                            \
+               REAL_CALL ( fragment, num_out_constraints,                   \
+                           PASSTHRU ( out_constraints ),                    \
+                           PASSTHRU ( in_constraints ),                     \
+                           PASSTHRU ( clobber ) );                          \
+                                                                            \
+               remove_from_rm_stack ( NULL, FRAGMENT_SIZE ( name ) );       \
+       } while ( 0 )
+
+#endif /* ASSEMBLY */
+
+#endif /* LIBRM_H */
diff --git a/src/arch/i386/include/memsizes.h b/src/arch/i386/include/memsizes.h
new file mode 100644 (file)
index 0000000..a5bb3f2
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef MEMSIZES_H
+#define MEMSIZES_H
+
+/*
+ * These structures seem to be very i386 (and, in fact, PCBIOS)
+ * specific, so I've moved them out of etherboot.h.
+ *
+ */
+
+struct e820entry {
+       uint64_t addr;
+       uint64_t size;
+       uint32_t type;
+#define E820_RAM       1
+#define E820_RESERVED  2
+#define E820_ACPI      3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS       4
+} __attribute__ (( packed ));
+#define E820ENTRY_SIZE 20
+#define E820MAX 32
+
+struct meminfo {
+       uint16_t basememsize;
+       uint16_t pad;
+       uint32_t memsize;
+       uint32_t map_count;
+       struct e820entry map[E820MAX];
+} __attribute__ (( packed ));
+
+extern struct meminfo meminfo;
+
+extern void get_memsizes ( void );
+
+#endif /* MEMSIZES_H */
index 694e9d1379eb9131bdf5aef76c831a3477034c37..d3f9b87921c18587d677c76f6c17a5847a8b4914 100644 (file)
@@ -8,7 +8,7 @@
 #define PIC8259_H
 
 /* For segoff_t */
-#include "segoff.h"
+#include "realmode.h"
 
 #define IRQ_PIC_CUTOFF (8)
 
@@ -90,7 +90,7 @@ void dump_irq_status ( void );
  * handler code, so we put prototypes and the size macro here.
  */
 extern void _trivial_irq_handler ( void );
-extern void _trivial_irq_handler_end ( void );
+extern char _trivial_irq_handler_size[];
 #define TRIVIAL_IRQ_HANDLER_SIZE FRAGMENT_SIZE(_trivial_irq_handler)
 
 #endif /* PIC8259_H */
index 9b941931f0cf82ae7dd0789ed4cbdad79b89d340..cf5a7a8788dc4c30ebdbceead29f4c82c8d01fb4 100644 (file)
@@ -5,7 +5,6 @@
 #define PXE_CALLBACKS_H
 
 #include "etherboot.h"
-#include "segoff.h"
 #include "pxe.h"
 
 typedef struct {
index 7b093e6a578e15d0e08d7041f63eb8e4510928dc..45736a2bf24fc6739e76913998ca02b3bcdded75 100644 (file)
@@ -10,7 +10,7 @@
 
 /* SEGOFF16_t defined in separate header
  */
-#include "segoff.h"
+#include "realmode.h"
 typedef segoff_t I386_SEGOFF16_t;
 #define SEGOFF16_t I386_SEGOFF16_t
 
index eca92b9b50dd4b25069ea076a413079657d4a2dd..d641869f85f948ce1443d950bbf65f7e61d4999f 100644 (file)
-/* Real-mode interface
- */
+#ifndef REALMODE_H
+#define REALMODE_H
 
 #ifndef ASSEMBLY
 
-#include "etherboot.h"
-#include "segoff.h"
-
-typedef union {
-       struct {
-               union {
-                       uint8_t l;
-                       uint8_t byte;
-               };
-               uint8_t h;
-       } PACKED;
-       uint16_t word;
-} PACKED reg16_t;
-
-typedef union {
-       reg16_t w;
-       uint32_t dword;
-} PACKED reg32_t;
-
-/* Macros to help with defining inline real-mode trampoline fragments.
+#include "stdint.h"
+#include "compiler.h"
+#include "registers.h"
+#include "io.h"
+
+/*
+ * Data structures and type definitions
+ *
  */
-#define RM_XSTR(x) #x  /* Macro hackery needed to stringify       */
-#define RM_STR(x) RM_XSTR(x)
-#define        RM_FRAGMENT(name, asm_code_str)         \
-       extern void name ( void );              \
-       extern void name ## _end (void);        \
-       __asm__(                                \
-               ".section \".text16\"\n\t"      \
-               ".code16\n\t"                   \
-               ".arch i386\n\t"                \
-               ".globl " #name " \n\t"         \
-               #name ":\n\t"                   \
-               asm_code_str "\n\t"             \
-               ".globl " #name "_end\n\t"      \
-               #name "_end:\n\t"               \
-               ".code32\n\t"                   \
-               ".previous\n\t"                 \
-       )
-
-#define FRAGMENT_SIZE(fragment) ( (size_t) ( ( (void*) fragment ## _end )\
-                                            - ( (void*) (fragment) ) ) )
-
-/* Data structures in _prot_to_real and _real_to_prot.  These
- * structures are accessed by assembly code as well as C code.
+
+/* All i386 registers, as passed in by prot_call or kir_call */
+struct real_mode_regs {
+       struct i386_all_regs;
+} PACKED;
+
+/* Segment:offset structure.  Note that the order within the structure
+ * is offset:segment.
  */
 typedef struct {
-       uint32_t esp;
-       uint16_t cs;
-       uint16_t ss;
-       uint32_t r2p_params;
-} PACKED prot_to_real_params_t;
+       uint16_t offset;
+       uint16_t segment;
+} segoff_t PACKED;
 
-typedef struct {
-       uint32_t ret_addr;
-       uint32_t esp;
-       uint32_t ebx;
-       uint32_t esi;
-       uint32_t edi;
-       uint32_t ebp;
-       uint32_t out_stack;
-       uint32_t out_stack_len;
-} PACKED real_to_prot_params_t;
-
-/* Function prototypes: realmode.c
+/* Macro hackery needed to stringify bits of inline assembly */
+#define RM_XSTR(x) #x
+#define RM_STR(x) RM_XSTR(x)
+
+/* Drag in the selected real-mode transition library header */
+#ifdef KEEP_IT_REAL
+#include "libkir.h"
+#else
+#include "librm.h"
+#endif
+
+/*
+ * The API to some functions is identical between librm and libkir, so
+ * they are documented here, even though the prototypes are in librm.h
+ * and libkir.h.
+ *
  */
-#define real_call( fragment, in_stack, out_stack ) \
-       _real_call ( fragment, FRAGMENT_SIZE(fragment), \
-                    (void*)(in_stack), \
-                    ( (in_stack) == NULL ? 0 : sizeof(*(in_stack)) ), \
-                    (void*)(out_stack), \
-                    ( (out_stack) == NULL ? 0 : sizeof(*(out_stack)) ) )
-extern uint16_t _real_call ( void *fragment, int fragment_len,
-                            void *in_stack, int in_stack_len,
-                            void *out_stack, int out_stack_len );
-/* Function prototypes: realmode_asm.S
+
+/*
+ * void copy_to_real ( uint16_t dest_seg, uint16_t dest_off,
+ *                    void *src, size_t n )
+ * void copy_from_real ( void *dest, uint16_t src_seg, uint16_t src_off,
+ *                      size_t n )
+ *
+ * These functions can be used to copy data to and from arbitrary
+ * locations in base memory.
  */
-extern void rm_callback_interface;
-extern uint16_t rm_callback_interface_size;
-extern uint32_t rm_etherboot_location;
-extern void _rm_in_call ( void );
-extern void _rm_in_call_far ( void );
-
-extern void _prot_to_real_prefix ( void );
-extern void _prot_to_real_prefix_end ( void );
-extern uint16_t prot_to_real_prefix_size;
-
-extern void _real_to_prot_suffix ( void );
-extern void _real_to_prot_suffix_end ( void );
-extern uint16_t real_to_prot_suffix_size;
-
-/* PXE assembler bits */
-extern void pxe_callback_interface;
-extern uint16_t pxe_callback_interface_size;
-extern void _pxe_in_call_far ( void );
-extern void _pxenv_in_call_far ( void );
-extern void _pxe_intercept_int1a ( void );
-extern segoff_t _pxe_intercepted_int1a;
-extern segoff_t _pxe_pxenv_location;
-
-/* Global variables
+
+/*
+ * put_real ( variable, uint16_t dest_seg, uint16_t dest_off )
+ * get_real ( variable, uint16_t src_seg, uint16_t src_off )
+ *
+ * These macros can be used to read or write single variables to and
+ * from arbitrary locations in base memory.  "variable" must be a
+ * variable of either 1, 2 or 4 bytes in length.
  */
-extern uint32_t real_mode_stack;
-extern size_t real_mode_stack_size;
+
+/*
+ * REAL_CALL ( routine, num_out_constraints, out_constraints,
+ *            in_constraints, clobber )
+ * REAL_EXEC ( name, asm_code_str, num_out_constraints, out_constraints,
+ *            in_constraints, clobber )
+ *
+ * If you have a pre-existing real-mode routine that you want to make
+ * a far call to, use REAL_CALL.  If you have a code fragment that you
+ * want to copy down to base memory, execute, and then remove, use
+ * REAL_EXEC.
+ *
+ * out_constraints must be of the form OUT_CONSTRAINTS(constraints),
+ * and in_constraints must be of the form IN_CONSTRAINTS(constraints),
+ * where "constraints" is a constraints list as would be used in an
+ * inline __asm__()
+ *
+ * clobber must be of the form CLOBBER ( clobber_list ), where
+ * "clobber_list" is a clobber list as would be used in an inline
+ * __asm__().
+ *
+ * These are best illustrated by example.  To write a character to the
+ * console using INT 10, you would do something like:
+ *
+ *     REAL_EXEC ( rm_test_librm,
+ *                 "int $0x10",
+ *                 1,
+ *                 OUT_CONSTRAINTS ( "=a" ( discard ) ),
+ *                 IN_CONSTRAINTS ( "a" ( 0x0e00 + character ),
+ *                                  "b" ( 1 ) ),
+ *                 CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
+ *
+ * IMPORTANT: gcc does not automatically assume that input operands
+ * get clobbered.  The only way to specify that an input operand may
+ * be modified is to also specify it as an output operand; hence the
+ * "(discard)" in the above code.
+ */
+
+#warning "realmode.h contains placeholders for obsolete macros"
+
+
+/* Just for now */
+#define SEGMENT(x) ( virt_to_phys ( x ) >> 4 )
+#define OFFSET(x) ( virt_to_phys ( x ) & 0xf )
+#define SEGOFF(x) { OFFSET(x), SEGMENT(x) }
+
+/* To make basemem.c compile */
 extern int lock_real_mode_stack;
+extern char *real_mode_stack;
+extern char real_mode_stack_size[];
+
+#define RM_FRAGMENT(name,asm) \
+       void name ( void ) {} \
+       extern char name ## _size[];
 
 
-/* Function prototypes from basemem.c
- */
-#ifdef LINUXBIOS
-/* A silly hard code that let's the code compile and work. 
- * When this becomes a problem feel free to implement
- * something better.
- */
-static inline void allot_real_mode_stack(void) { real_mode_stack = 0x7c00; } 
-#else
-void allot_real_mode_stack(void);
-#endif
 
 #endif /* ASSEMBLY */
+
+#endif /* REALMODE_H */
diff --git a/src/arch/i386/include/registers.h b/src/arch/i386/include/registers.h
new file mode 100644 (file)
index 0000000..2e78d41
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef REGISTERS_H
+#define REGISTERS_H
+
+#include "stdint.h"
+#include "compiler.h"
+
+/* Basic 16-bit and 32-bit register types */
+typedef union {
+       struct {
+               union {
+                       uint8_t l;
+                       uint8_t byte;
+               };
+               uint8_t h;
+       } PACKED;
+       uint16_t word;
+} PACKED reg16_t;
+
+typedef union {
+       reg16_t;
+       uint32_t dword;
+} PACKED reg32_t;
+
+/* As created by pushal / read by popal */
+struct i386_regs {
+       union {
+               uint16_t di;
+               uint32_t edi;
+       };
+       union {
+               uint16_t si;
+               uint32_t esi;
+       };
+       union {
+               uint16_t bp;
+               uint32_t ebp;
+       };
+       union {
+               uint16_t sp;
+               uint32_t esp;
+       };
+       union {
+               struct {
+                       uint8_t bl;
+                       uint8_t bh;
+               } PACKED;
+               uint16_t bx;
+               uint32_t ebx;
+       };
+       union {
+               struct {
+                       uint8_t dl;
+                       uint8_t dh;
+               } PACKED;
+               uint16_t dx;
+               uint32_t edx;
+       };
+       union {
+               struct {
+                       uint8_t cl;
+                       uint8_t ch;
+               } PACKED;
+               uint16_t cx;
+               uint32_t ecx;
+       };
+       union {
+               struct {
+                       uint8_t al;
+                       uint8_t ah;
+               } PACKED;
+               uint16_t ax;
+               uint32_t eax;
+       };
+} PACKED;
+
+/* Our pushal/popal equivalent for segment registers */
+struct i386_seg_regs {
+       uint16_t cs;
+       uint16_t ss;
+       uint16_t ds;
+       uint16_t es;
+       uint16_t fs;
+       uint16_t gs;
+} PACKED;
+
+/* All i386 registers, as passed in by prot_call or kir_call */
+struct i386_all_regs {
+       struct i386_seg_regs;
+       struct i386_regs;
+       uint32_t i386_flags;
+} PACKED;
+
+#endif /* REGISTERS_H */
diff --git a/src/arch/i386/include/segoff.h b/src/arch/i386/include/segoff.h
deleted file mode 100644 (file)
index 822ddd3..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Segment:offset types and macros
- *
- * Initially written by Michael Brown (mcb30).
- */
-
-#ifndef SEGOFF_H
-#define SEGOFF_H
-
-#include <stdint.h>
-#include <osdep.h>
-#include <io.h>
-
-/* Segment:offset structure.  Note that the order within the structure
- * is offset:segment.
- */
-typedef struct {
-       uint16_t offset;
-       uint16_t segment;
-} segoff_t;
-
-/* Macros for converting from virtual to segment:offset addresses,
- * when we don't actually care which of the many isomorphic results we
- * get.
- */
-#ifdef DEBUG_SEGMENT
-uint16_t SEGMENT ( const void * const ptr ) {
-       uint32_t phys = virt_to_phys ( ptr );
-       if ( phys > 0xfffff ) {
-               printf ( "FATAL ERROR: segment address out of range\n" );
-       }
-       return phys >> 4;
-}
-#else
-#define SEGMENT(x) ( virt_to_phys ( x ) >> 4 )
-#endif
-#define OFFSET(x) ( virt_to_phys ( x ) & 0xf )
-#define SEGOFF(x) { OFFSET(x), SEGMENT(x) }
-#define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
-
-#endif /* SEGOFF_H */
diff --git a/src/arch/i386/include/virtaddr.h b/src/arch/i386/include/virtaddr.h
new file mode 100644 (file)
index 0000000..15fad1c
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef VIRTADDR_H
+#define VIRTADDR_H
+
+/* Segment selectors as used in our protected-mode GDTs.
+ *
+ * Don't change these unless you really know what you're doing.
+ */
+#define PHYSICAL_CS 0x08
+#define PHYSICAL_DS 0x10
+#define VIRTUAL_CS 0x18
+#define VIRTUAL_DS 0x20
+#define LONG_CS 0x28
+#define LONG_DS 0x30
+
+#ifndef ASSEMBLY
+
+#include "stdint.h"
+
+#ifndef KEEP_IT_REAL
+
+/*
+ * Without -DKEEP_IT_REAL, we are in 32-bit protected mode with a
+ * fixed link address but an unknown physical start address.  Our GDT
+ * sets up code and data segments with an offset of virt_offset, so
+ * that link-time addresses can still work.
+ *
+ */
+
+/* C-callable function prototypes */
+
+extern void relocate_to ( uint32_t new_phys_addr );
+
+/* Variables in virtaddr.S */
+extern unsigned long virt_offset;
+
+/*
+ * Convert between virtual and physical addresses
+ *
+ */
+static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
+       return ( ( unsigned long ) virt_addr ) + virt_offset;
+}
+
+static inline void * phys_to_virt ( unsigned long phys_addr ) {
+       return ( void * ) ( phys_addr - virt_offset );
+}
+
+#else /* KEEP_IT_REAL */
+
+/*
+ * With -DKEEP_IT_REAL, we are in 16-bit real mode with fixed link
+ * addresses and a segmented memory model.  We have separate code and
+ * data segments.
+ *
+ * Because we may be called in 16-bit protected mode (damn PXE spec),
+ * we cannot simply assume that physical = segment * 16 + offset.
+ * Instead, we have to look up the physical start address of the
+ * segment in the !PXE structure.  We have to assume that
+ * virt_to_phys() is called only on pointers within the data segment,
+ * because nothing passes segment information to us.
+ *
+ * We don't implement phys_to_virt at all, because there will be many
+ * addresses that simply cannot be reached via a virtual address when
+ * the virtual address space is limited to 64kB!
+ */
+
+static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
+       /* Cheat: just for now, do the segment*16+offset calculation */
+       uint16_t ds;
+
+       __asm__ ( "movw %%ds, %%ax" : "=a" ( ds ) : );
+       return ( 16 * ds + ( ( unsigned long ) virt_addr ) );
+}
+
+/* Define it as a deprecated function so that we get compile-time
+ * warnings, rather than just the link-time errors.
+ */
+extern void * phys_to_virt ( unsigned long phys_addr )
+     __attribute__ ((deprecated));
+
+#endif /* KEEP_IT_REAL */
+
+#endif /* ASSEMBLY */
+
+#endif /* VIRTADDR_H */
diff --git a/src/arch/i386/kir-Makefile b/src/arch/i386/kir-Makefile
new file mode 100644 (file)
index 0000000..cc37a91
--- /dev/null
@@ -0,0 +1,29 @@
+# Makefile to build a KEEP_IT_REAL flavour
+# 
+# KEEP_IT_REAL, by its nature, requires a different build of every
+# single object file, since the inclusion of ".code16gcc" will
+# generate different machine code from the assembly.  Unlike the other
+# config options, there is no way that this global dependency can ever
+# be reduced, so it makes sense to be able to build both the normal
+# and the KIR versions without having to force a full rebuild each
+# time.
+
+# Add this Makefile to MAKEDEPS
+#
+MAKEDEPS       += arch/i386/kir-Makefile
+
+# Place binaries in bin-kir
+#
+BIN            = bin-kir
+
+# Compile with -DKEEP_IT_REAL, forcibly include kir.h at the start of
+# each file to drag in ".code16gcc"
+#
+CFLAGS         += -DKEEP_IT_REAL -include kir.h
+
+# Link with _data_link_addr = 0; data symbols are relative to the data
+# segment.
+#
+LDFLAGS                += --defsym _data_link_addr=0
+
+include Makefile
similarity index 88%
rename from src/arch/i386/prefix/floppyprefix.S
rename to src/arch/i386/prefix/dskprefix.S
index 18bed4c8f89408b57f52e4b0e80eddac18a10987..d1f64e7aef4ea9cc3bdda2d908334fef96b4e7a7 100644 (file)
@@ -1,3 +1,5 @@
+#include "compiler.h"
+
 /* NOTE: this boot sector contains instructions that need at least an 80186.
  * Yes, as86 has a bug somewhere in the valid instruction set checks.
  *
@@ -115,7 +117,6 @@ got_sectors:
 
 /* ok, we've written the Loading... message, now we want to load the system */
 
-       pushw   %es                     /* = ds */
        movw    $SYSSEG, %ax
        movw    %ax,%es                 /* segment of SYSSEG<<4 */
        pushw   %es
@@ -130,8 +131,6 @@ got_sectors:
 
        call    print_nl
        pop     %es                     /* = SYSSEG */
-       pop     %es                     /* balance push/pop es */
-sigok: 
 
 /* Restore original disk parameters */
        movw    $0x78, %bx
@@ -142,20 +141,47 @@ sigok:
        movw    %di,(%bx)
        movw    %si,2(%bx)
 
-/* after that (everything loaded), we call to the .ROM file loaded. */
-
-       pushl   $0              /* No parameters to preserve for exit path */
-       pushw   $0              /* Use prefix exit path mechanism */
-       ljmp    $SYSSEG, $_start
-
-       .section ".text16", "ax", @progbits
-       .globl  prefix_exit
-prefix_exit:
-       xchgw   %bx, %bx
-       int     $0x19           /* should try to boot machine */
-       .globl  prefix_exit_end
-prefix_exit_end:
-       .previous
+       /* Everything now loaded.  %es = SYSSEG, so %es:0000 points to
+        * start of loaded image.
+        */
+
+start_runtime:
+
+#ifdef COMPRESS
+       /* Decompress runtime image.  %es:0000 points to decompressed
+        * image on exit.
+        */
+       lcall   $SYSSEG, $decompress16
+#endif
+       
+       /* Set up internal environment.  Address of entry-point
+        * function is returned in %es:di.
+        */
+       pushw   %es             /* setup16 says %ds:0000 must point to image */
+       popw    %ds
+       movw    $setup16, %di
+       pushw   %cs
+       call    ljmp_to_es_di
+
+       /* Call initialisation routine.  Relocation may be done.  New
+        * address of entry-point function is returned in %es:di.
+        */
+       pushl   $arch_rm_initialise
+       pushw   %cs             /* == lcall %es:di */
+       call    ljmp_to_es_di
+       
+       /* Call to arch_rm_main.  Register INT19 as an exit path.  This
+        * call will never return.
+        */
+       movl    $exit_via_int19, %eax
+       pushl   $arch_rm_main
+       pushl   %eax            /* Dummy return address */
+
+       /* Do the equivalent of ljmp *%es:di */
+ljmp_to_es_di: 
+       pushw   %es
+       pushw   %di
+       lret
 
 /* This routine loads the system at address SYSSEG<<4, making sure no 64kB
  * boundaries are crossed. We try to load it as fast as possible, loading whole
@@ -164,7 +190,7 @@ prefix_exit_end:
  * in: es - starting address segment (normally SYSSEG)
  */
 read_it: 
-       movw    $0,sread                /* read whole image incl boot sector */
+       movw    $1,sread                /* don't reload the prefix */
        movw    %es,%ax
        testw   $0x0fff, %ax
 die:   jne     die                     /* es must be at 64kB boundary */
diff --git a/src/arch/i386/prefix/int19exit.c b/src/arch/i386/prefix/int19exit.c
new file mode 100644 (file)
index 0000000..e7be062
--- /dev/null
@@ -0,0 +1,13 @@
+#include "bochs.h"
+#include "realmode.h"
+
+/*
+ * The "exit via INT 19" exit path.  INT 19 is the old (pre-BBS) "boot
+ * system" interrupt.
+ *
+ */
+
+void exit_via_int19 ( struct real_mode_regs *rm_regs ) {
+       bochsbp();
+       /* Placeholder */
+}
index 1836fa71569bc06cafd825c69c466809deacffbf..50776dc93a3ff70eb883be9b463f304241d59a3a 100644 (file)
  * - Structure modified to be a subroutine call rather than an
  *   executable prefix.
  *   Michael Brown 30 Mar 2004
+ *
+ * - Modified to be compilable as either 16-bit or 32-bit code.
+ *   Michael Brown 9 Mar 2005
  */
 
+/****************************************************************************
+ * This file provides the decompress_block() and decompress_block16()
+ * functions which can be called in order to decompress an image
+ * compressed with the nrv2b utility in src/util.
+ *
+ * These functions are designed to be called by the prefix.  They are
+ * position-independent code.
+ *
+ * The same basic assembly code is used to compile both
+ * decompress_block() and decompress_block16().
+ ****************************************************************************
+ */
 
        .text
        .arch i386
        .section ".prefix", "ax", @progbits
-       .code32
-       
-       .globl decompress
-decompress:
-       /* Save the initial register values */
-       pushal
 
-       /*
-        * See where I am running, and compute %ebp
-        * %ebp holds delta between physical and virtual addresses.
-        */
-       call    1f
-1:     popl    %ebp
-       subl    $1b, %ebp
+#ifdef CODE16
+/****************************************************************************
+ * decompress_block16 (real-mode near call, position independent)
+ *
+ * Parameters (passed via registers):
+ *   %ds:%si - Pointer to compressed input data
+ *   %es:%di - Pointer to output buffer
+ * Returns:
+ *   All registers are preserved
+ *
+ * NOTE: The compressed data size must be in the range [1,65533-%si]
+ * and the uncompressed data size must be in the range [1,65536-%di]
+ * (where %si and %di are the input values for those registers).  Note
+ * particularly that the lower limit is 1, not 0, and that the upper
+ * limit on the input (compressed) data really is 65533, since the
+ * algorithm may read up to three bytes beyond the end of the input
+ * data, since it reads dwords.
+ *
+ * Although splitting up the data into (almost) 64kB chunks for
+ * compression is awkward and worsens the compression ratio, it has
+ * little to no practical effect since our image size is currently
+ * <64kB for all single drivers.  Having a decompression routine that
+ * can run in real-mode avoids the need to duplicate RM-to-PM
+ * transition code from librm (or have part of librm kept
+ * uncompressed, which is itself awkward) and means that we don't need
+ * to set up the PM stack until we hit the setup routine itself.
+ ****************************************************************************
+ */
+
+#define REG(x) x
 
-       /* "compressed" and "decompress_to" defined by linker script */
-       /* move compressed image up to temporary area before decompressing */
-       std
-       movl    $_compressed_size, %ecx
-       leal    _compressed+4-1(%ebp, %ecx), %esi
-       leal    _compressed_copy-1(%ebp, %ecx), %edi
-       rep movsb
-       /* Setup to run the decompressor */
-       cld
-       leal    _compressed_copy(%ebp), %esi
-       leal    decompress_to(%ebp), %edi
-       movl    $-1, %ebp       /* last_m_off = -1 */
-       jmp     dcl1_n2b
+       .code16
+       .globl  decompress_block16
+decompress_block16:
+       
+#else /* CODE16 */
 
-/* ------------- DECOMPRESSION -------------
+/****************************************************************************
+ * decompress_block (32-bit protected-mode near call, position independent)
+ *
+ * Parameters (passed via registers):
+ *   %ds:%esi - Pointer to compressed input data
+ *   %es:%edi - Pointer to output buffer
+ * Returns:
+ *   All registers are preserved
+ ****************************************************************************
+ */
 
- Input:
-   %esi - source
-   %edi - dest
-   %ebp - -1
-   cld
+#define REG(x) e ## x
+       
+       .code32
+       .globl  decompress_block
+decompress_block:
 
- Output:
-   %eax - 0
-   %ecx - 0
-*/
+#endif /* CODE16 */
 
-.macro getbit bits
-.if    \bits == 1
-       addl    %ebx, %ebx
-       jnz     1f
-.endif
-       movl    (%esi), %ebx
-       subl    $-4, %esi       /* sets carry flag */
-       adcl    %ebx, %ebx
-1:
-.endm
+#define xAX    REG(ax)
+#define xCX    REG(cx)
+#define xBP    REG(bp)
+#define xSI    REG(si)
+#define xDI    REG(di)
 
+       /* Save registers */
+       pushal
+       /* Do the decompression */
+       cld
+       xor     %xBP, %xBP
+       dec     %xBP            /* last_m_off = -1 */
+       jmp     dcl1_n2b
+       
 decompr_literals_n2b:
        movsb
-
 decompr_loop_n2b:
        addl    %ebx, %ebx
        jnz     dcl2_n2b
 dcl1_n2b:
-       getbit  32
+       call    getbit32
 dcl2_n2b:
        jc      decompr_literals_n2b
-       xorl    %eax, %eax
-       incl    %eax            /* m_off = 1 */
+       xor     %xAX, %xAX
+       inc     %xAX            /* m_off = 1 */
 loop1_n2b:
-       getbit  1
-       adcl    %eax, %eax      /* m_off = m_off*2 + getbit() */
-       getbit  1
+       call    getbit1
+       adc     %xAX, %xAX      /* m_off = m_off*2 + getbit() */
+       call    getbit1
        jnc     loop1_n2b       /* while(!getbit()) */
-       xorl    %ecx, %ecx
-       subl    $3, %eax
+       sub     $3, %xAX
        jb      decompr_ebpeax_n2b      /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
-       shll    $8, %eax        
-       movb    (%esi), %al     /* m_off = (m_off - 3)*256 + src[ilen++] */
-       incl    %esi
-       xorl    $-1, %eax       
+       shl     $8, %xAX        
+       movb    (%xSI), %al     /* m_off = (m_off - 3)*256 + src[ilen++] */
+       inc     %xSI
+       not     %xAX    
        jz      decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
-       movl    %eax, %ebp      /* last_m_off = m_off ?*/
+       mov     %xAX, %xBP      /* last_m_off = m_off ?*/
 decompr_ebpeax_n2b:
-       getbit  1               
-       adcl    %ecx, %ecx      /* m_len = getbit() */
-       getbit  1
-       adcl    %ecx, %ecx      /* m_len = m_len*2 + getbit()) */
+       xor     %xCX, %xCX
+       call    getbit1
+       adc     %xCX, %xCX      /* m_len = getbit() */
+       call    getbit1
+       adc     %xCX, %xCX      /* m_len = m_len*2 + getbit()) */
        jnz     decompr_got_mlen_n2b    /* if (m_len == 0) goto decompr_got_mlen_n2b */
-       incl    %ecx            /* m_len++ */
+       inc     %xCX            /* m_len++ */
 loop2_n2b:
-       getbit  1       
-       adcl    %ecx, %ecx      /* m_len = m_len*2 + getbit() */
-       getbit  1
+       call    getbit1 
+       adc     %xCX, %xCX      /* m_len = m_len*2 + getbit() */
+       call    getbit1
        jnc     loop2_n2b       /* while(!getbit()) */
-       incl    %ecx
-       incl    %ecx            /* m_len += 2 */
+       inc     %xCX
+       inc     %xCX            /* m_len += 2 */
 decompr_got_mlen_n2b:
-       cmpl    $-0xd00, %ebp
-       adcl    $1, %ecx        /* m_len = m_len + 1 + (last_m_off > 0xd00) */
-       pushl   %esi
-       leal    (%edi,%ebp), %esi       /* m_pos = dst + olen + -m_off  */
+       cmp     $-0xd00, %xBP
+       adc     $1, %xCX        /* m_len = m_len + 1 + (last_m_off > 0xd00) */
+       push    %xSI
+       lea     (%xBP,%xDI), %xSI       /* m_pos = dst + olen + -m_off  */
        rep
-       movsb                   /* dst[olen++] = *m_pos++ while(m_len > 0) */
-       popl    %esi
+       es movsb                /* dst[olen++] = *m_pos++ while(m_len > 0) */
+       pop     %xSI
        jmp     decompr_loop_n2b
+
+
+getbit1:
+       addl    %ebx, %ebx
+       jnz     1f
+getbit32:
+       movl    (%xSI), %ebx
+       sub     $-4, %xSI       /* sets carry flag */
+       adcl    %ebx, %ebx
+1:
+       ret
+
 decompr_end_n2b:
-       /* Restore the initial register values */
+       /* Restore registers and return */
        popal
        ret
diff --git a/src/arch/i386/scripts/i386.lds b/src/arch/i386/scripts/i386.lds
new file mode 100644 (file)
index 0000000..4f9df56
--- /dev/null
@@ -0,0 +1,263 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for i386 images
+ *
+ */
+
+OUTPUT_FORMAT ( "elf32-i386", "elf32-i386", "elf32-i386" )
+OUTPUT_ARCH ( i386 )
+ENTRY ( _entry )
+
+SECTIONS {
+
+    /* All sections in the resulting file have consecutive load
+     * addresses, but may have individual link addresses depending on
+     * the memory model being used.
+     *
+     * The linker symbols {prefix,decompress,text,data}_link_addr,
+     * load_addr, and _max_align may be specified explicitly.  If not
+     * specified, they will default to:
+     *
+     *   _prefix_link_addr     = 0
+     *   _decompress_link_addr = 0
+     *   _text_link_addr       = 0
+     *   _data_link_addr       = _text_link_addr + sizeof ( text sections )
+     *   _load_addr            = 0
+     *   _max_align            = 16
+     * 
+     * We guarantee alignment of virtual addresses to any alignment
+     * specified by the constituent object files (e.g. via
+     * __attribute__((aligned(x)))).  Load addresses are guaranteed
+     * only up to _max_align.  Provided that all loader and relocation
+     * code honours _max_align, this means that physical addresses are
+     * also guaranteed up to _max_align.
+     *
+     * Note that when using -DKEEP_IT_REAL, the UNDI segments are only
+     * guaranteed to be loaded on a paragraph boundary (i.e. 16-byte
+     * alignment).  Using _max_align>16 will therefore not guarantee
+     * >16-byte alignment of physical addresses when -DKEEP_IT_REAL is
+     * used (though virtual addresses will still be fully aligned).
+     *
+     * The real-mode prefixes rely on _text_link_addr and
+     * _decompress_link_addr being 0, since they issue far calls into
+     * those sections, thus requiring that symbol_value ==
+     * symbol_offset therein.  Using the linker to calculate
+     * e.g. offset_setup16=setup16-_text will not work, since you then
+     * cannot use the reference from the prefix to setup16 to drag in
+     * setup16.o.  Life is hard.
+     *
+     * If librm is included, then it must go at offset 0 within the
+     * text section.  This is because librm is dual-usage: it is
+     * called from setup16 with %cs:0000 pointing to the start of the
+     * text section, and later it will be copied to base memory and
+     * called with %cs:0000 pointing to the start of librm.
+     *
+     * The decompressor is designed to decompress in-place.  After
+     * calling the decompressor, the image will look exactly the same
+     * as the uncompressed image; the compressed data and the
+     * decompressor code itself will have been overwritten.
+     */
+
+    /*
+     * The prefix
+     */
+
+    _prefix_link_addr = DEFINED ( _prefix_link_addr ) ? _prefix_link_addr : 0;
+    . = _prefix_link_addr;
+    _prefix = .;
+
+    .prefix : AT ( _prefix_load_offset + __prefix ) {
+       __prefix = .;
+       _entry = .;
+       *(.prefix)
+       *(.prefix.*)
+    }
+    
+    _eprefix = .;
+
+    /*
+     * The decompressor (may be absent)
+     */
+
+    _decompress_link_addr = DEFINED ( _decompress_link_addr ) ?
+                             _decompress_link_addr : 0;
+    . = _decompress_link_addr;
+    _decompress = .;
+
+    .decompress : AT ( _decompress_load_offset + __decompress ) {
+           __decompress = .;
+           *(.decompress)
+           *(.decompress.*)
+    }
+
+    _edecompress = .;
+
+    /*
+     * The text sections
+     */
+
+    _text_link_addr = DEFINED ( _text_link_addr ) ? _text_link_addr : 0;
+    . = _text_link_addr;
+    _text = .;
+
+    .text16 : AT ( _text_load_offset + __text16 ) {
+       __text16 = .;
+
+       /* librm is a special case; it must go at the start of the
+        * text section if it is included.
+        */
+       _assert = ASSERT ( ( . == _text_link_addr ), "librm cannot go first" );
+       *(.librm)
+
+       *(.text16)
+       *(.text16.*)
+    } = 0x9090
+
+    .text : AT ( _text_load_offset + __text ) {
+       __text = .;
+       *(.text)
+       *(.text.*)
+    } = 0x9090
+
+    _etext = .;
+
+    /*
+     * The data sections
+     */
+
+    _data_link_addr = DEFINED ( _data_link_addr ) ? _data_link_addr : .;
+    . = _data_link_addr;
+    _data = .;
+
+    .rodata : AT ( _data_load_offset + __rodata ) {
+       __rodata = .;
+       *(.rodata)
+       *(.rodata.*)
+    }
+
+    .data : AT ( _data_load_offset + __data ) {
+       __data = .;
+       *(.data)
+       *(.data.*)
+       pci_drivers = .;
+       *(.drivers.pci)
+       pci_drivers_end = .;
+       isa_drivers = .;
+       *(.drivers.isa)
+       isa_drivers_end = .;
+       console_drivers = .;
+       *(.drivers.console)
+       console_drivers_end = .;
+       init_fns = .;
+       *(SORT(.init_fns.*))
+       init_fns_end = .;
+
+       _progbits_end = .;
+    }
+
+    .bss : AT ( _data_load_offset + __bss ) {
+       __bss = .;
+       _bss = .;
+       *(.bss)
+       *(.bss.*)
+       *(COMMON)
+       _ebss = .;
+    }
+
+    .stack : AT ( _data_load_offset + __stack ) {
+       __stack = .;
+       *(.stack)
+       *(.stack.*)
+    }
+
+    _edata = .;
+
+    _end = .;
+
+    /*
+     * Dispose of the comment and note sections to make the link map
+     * easier to read
+     */
+
+    /DISCARD/ : {
+       *(.comment)
+       *(.note)
+    }
+
+    /*
+     * Load address calculations.  The slightly obscure nature of the
+     * calculations is because ALIGN(x) can only operate on the
+     * location counter.
+     */
+
+    _max_align             = DEFINED ( _max_align ) ? _max_align : 16;
+    _load_addr             = DEFINED ( _load_addr ) ? _load_addr : 0;
+
+    .                      = _load_addr;
+
+    .                     -= _prefix_link_addr;
+    _prefix_load_offset            = ALIGN ( _max_align );
+    _prefix_load_addr      = _prefix_link_addr + _prefix_load_offset;
+    _prefix_size           = _eprefix - _prefix;
+    .                      = _prefix_load_addr + _prefix_size;
+
+    .                     -= _decompress_link_addr;
+    _decompress_load_offset = ALIGN ( _max_align );
+    _decompress_load_addr   = _decompress_link_addr + _decompress_load_offset;
+    _decompress_size       = _edecompress - _decompress;
+    .                      = _decompress_load_addr + _decompress_size;
+
+    .                     -= _text_link_addr;
+    _text_load_offset      = ALIGN ( _max_align );
+    _text_load_addr        = _text_link_addr + _text_load_offset;
+    _text_size             = _etext - _text;
+    .                      = _text_load_addr + _text_size;
+
+    .                     -= _data_link_addr;
+    _data_load_offset      = ALIGN ( _max_align );
+    _data_load_addr        = _data_link_addr + _data_load_offset;
+    _data_size             = _edata - _data;
+    .                      = _data_load_addr + _data_size;
+
+    /*
+     * Alignment checks.  ALIGN() can only operate on the location
+     * counter, so we set the location counter to each value we want
+     * to check.
+     */
+
+    . = _prefix_load_addr - _prefix_link_addr;
+    _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+                      "_prefix is badly aligned" );
+
+    . = _decompress_load_addr - _prefix_link_addr;
+    _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+                      "_decompress is badly aligned" );
+
+    . = _text_load_addr - _text_link_addr;
+    _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+                      "_text is badly aligned" );
+
+    . = _data_load_addr - _data_link_addr;
+    _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+                      "_data is badly aligned" );
+
+    /*
+     * setup16 needs to know this when KEEP_IT_REAL is used.  There
+     * are no harmful side-effects of calculating it all the time.
+     */
+    _text_load_size_pgh = ( _data_load_addr - _text_load_addr ) / 16 ;
+
+    /*
+     * Useful-to-know values.
+     */
+
+    /* Size of the decompressed runtime image */
+    _runtime_size = _edata - _text;
+    /* Size of the initialised-contents portion of the runtime image */
+    _runtime_progbits_size = _progbits_end - _text;
+    /* Size of the (non-compressed) binary file */
+    _file_size = _prefix_size + _runtime_progbits_size;
+    /* Size of the non-compressed portion of the compressed binary file */
+    _zfile_noncompressed_size = _prefix_size + _decompress_size;
+}
diff --git a/src/arch/i386/transitions/libkir.S b/src/arch/i386/transitions/libkir.S
new file mode 100644 (file)
index 0000000..79a0aa0
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * libkir: a transition library for -DKEEP_IT_REAL
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+/****************************************************************************
+ * This file defines libkir: an interface between external and
+ * internal environments when -DKEEP_IT_REAL is used, so that both
+ * internal and external environments are in real mode.  It deals with
+ * switching data segments and the stack.  It provides the following
+ * functions:
+ *
+ * ext_to_kir &                switch between external and internal (kir)
+ * kir_to_ext          environments, preserving all non-segment
+ *                     registers
+ *
+ * kir_call            issue a call to an internal routine from external
+ *                     code
+ *
+ * libkir is written to avoid assuming that segments are anything
+ * other than opaque data types, and also avoids assuming that the
+ * stack pointer is 16-bit.  This should enable it to run just as well
+ * in 16:16 or 16:32 protected mode as in real mode.
+ ****************************************************************************
+ */
+
+/* Breakpoint for when debugging under bochs */
+#define BOCHSBP xchgw %bx, %bx
+
+       .text
+       .arch i386
+       .section ".text16", "awx", @progbits
+       .code16
+       
+/****************************************************************************
+ * ext_to_kir (real-mode or 16:xx protected-mode near call)
+ *
+ * Switch from external stack and segment registers to internal stack
+ * and segment registers.  %ss:sp is restored from the saved kir_ds
+ * and kir_sp.  %ds, %es, %fs and %gs are all restored from the saved
+ * kir_ds.  All other registers are preserved.
+ *
+ * %cs:0000 must point to the start of the runtime image code segment
+ * on entry.
+ *
+ * Note that this routine can be called *without* having first set up
+ * a stored kir_ds and kir_sp.  If you do this, ext_to_kir will return
+ * without altering the segment registers or stack pointer.
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+
+       .globl  ext_to_kir
+ext_to_kir:
+       /* Record external segment registers */
+       movw    %ds, %cs:ext_ds
+       pushw   %cs
+       popw    %ds     /* Set %ds = %cs for easier access to variables */
+       movw    %es, %ds:ext_es
+       movw    %fs, %ds:ext_fs
+       movw    %gs, %ds:ext_fs
+
+       /* Preserve registers */
+       movw    %ax, %ds:save_ax
+
+       /* Extract near return address from stack */
+       popw    %ds:save_retaddr
+
+       /* Record external %ss:esp */
+       movw    %ss, %ds:ext_ss
+       movl    %esp, %ds:ext_esp
+
+       /* Load internal segment registers and stack pointer, if available */
+       movw    %ds:kir_ds, %ax
+       testw   %ax, %ax
+       jz      1f
+       movw    %ax, %ss
+       movzwl  %ds:kir_sp, %esp
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+1:
+
+       /* Place return address on new stack */
+       pushw   %cs:save_retaddr
+       
+       /* Restore registers and return */
+       movw    %cs:save_ax, %ax
+       ret
+
+/****************************************************************************
+ * kir_to_ext (real-mode or 16:xx protected-mode near call)
+ *
+ * Switch from internal stack and segment registers to external stack
+ * and segment registers.  %ss:%esp is restored from the saved ext_ss
+ * and ext_esp.  Other segment registers are restored from the
+ * corresponding locations.  All other registers are preserved.
+ *
+ * Note that it is actually %ss that is recorded as kir_ds, on the
+ * assumption that %ss == %ds when kir_to_ext is called.
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+
+       .globl  kir_to_ext
+kir_to_ext:
+       /* Record near return address */
+       pushw   %cs
+       popw    %ds     /* Set %ds = %cs for easier access to variables */
+       popw    %ds:save_retaddr
+       
+       /* Record internal segment registers and %sp */
+       movw    %ss, %ds:kir_ds
+       movw    %sp, %ds:kir_sp
+
+       /* Load external segment registers and stack pointer */
+       movw    %ds:ext_ss, %ss
+       movl    %ds:ext_esp, %esp
+       movw    %ds:ext_gs, %gs
+       movw    %ds:ext_fs, %fs
+       movw    %ds:ext_es, %es
+       movw    %ds:ext_ds, %ds
+
+       /* Return */
+       pushw   %cs:save_retaddr
+       ret
+       
+/****************************************************************************
+ * kir_call (real-mode or 16:xx protected-mode far call)
+ *
+ * Call a specific C function in the internal code.  The prototype of
+ * the C function must be
+ *   void function ( struct real_mode_regs *rm_regs ); 
+ * rm_regs will point to a struct containing the real-mode registers
+ * at entry to kir_call.
+ *
+ * All registers will be preserved across kir_call(), unless the C
+ * function explicitly overwrites values in rm_regs.  Interrupt status
+ * will also be preserved.
+ *
+ * Parameters:
+ *   function : (16-bit) virtual address of protected-mode function to call
+ *
+ * Example usage:
+ *     pushw   $pxe_api_call
+ *     lcall   $UNDI_CS, $kir_call
+ *     addw    $2, %sp
+ * to call in to the C function
+ *      void pxe_api_call ( struct real_mode_regs *rm_regs );
+ ****************************************************************************
+ */
+
+       .globl  kir_call
+kir_call:
+
+       /* Preserve flags.  Must do this before any operation that may
+        * affect flags.
+        */
+       pushfl
+       popl    %cs:save_flags
+
+       /* Disable interrupts.  We do funny things with the stack, and
+        * we're not re-entrant.
+        */
+       cli
+               
+       /* Extract address of internal routine from stack.  We must do
+        * this without using (%bp), because we may be called with
+        * either a 16-bit or a 32-bit stack segment.
+        */
+       popl    %cs:save_retaddr        /* Scratch location */
+       popw    %cs:save_function
+       subl    $6, %esp                /* Restore %esp */
+       
+       /* Switch to internal stack.  Note that the external stack is
+        * inaccessible once we're running internally (since we have
+        * no concept of 48-bit far pointers)
+        */
+       call    ext_to_kir
+       
+       /* Store external registers on internal stack */
+       pushl   %cs:save_flags
+       pushal
+       pushl   %cs:ext_fs_and_gs
+       pushl   %cs:ext_ds_and_es
+       pushl   %cs:ext_cs_and_ss
+
+       /* Push &rm_regs on stack and call function */
+       pushl   %esp
+       data32 call *%cs:save_function
+       popl    %eax /* discard */
+       
+       /* Restore external registers from internal stack */
+       popl    %cs:ext_cs_and_ss
+       popl    %cs:ext_ds_and_es
+       popl    %cs:ext_fs_and_gs
+       popal
+       popl    %cs:save_flags
+
+       /* Switch to external stack */
+       call    kir_to_ext
+
+       /* Restore flags */
+       pushl   %cs:save_flags
+       popfl
+
+       /* Return */
+       lret
+
+/****************************************************************************
+ * Stored internal and external stack and segment registers
+ ****************************************************************************
+ */
+       
+ext_cs_and_ss: 
+ext_cs:                .word 0
+ext_ss:                .word 0
+ext_ds_and_es: 
+ext_ds:                .word 0
+ext_es:                .word 0
+ext_fs_and_gs: 
+ext_fs:                .word 0
+ext_gs:                .word 0
+ext_esp:       .long 0
+
+               .globl kir_ds
+kir_ds:                .word 0
+               .globl kir_sp
+kir_sp:                .word 0
+
+/****************************************************************************
+ * Temporary variables
+ ****************************************************************************
+ */
+save_ax:       .word 0
+save_retaddr:  .word 0
+save_flags:    .long 0
+save_function: .long 0
diff --git a/src/arch/i386/transitions/libpm.S b/src/arch/i386/transitions/libpm.S
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/arch/i386/transitions/librm.S b/src/arch/i386/transitions/librm.S
new file mode 100644 (file)
index 0000000..6dc6b4f
--- /dev/null
@@ -0,0 +1,691 @@
+/*
+ * librm: a library for interfacing to real-mode code
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+/* Drag in local definitions */
+#include "librm.h"
+
+/****************************************************************************
+ * This file defines librm: a block of code that is designed to reside
+ * permanently in base memory and provide the interface between
+ * real-mode code running in base memory and protected-mode code
+ * running in high memory.  It provides the following functions:
+ *
+ *   real_to_prot &    switch between real and protected mode 
+ *   prot_to_real      while running in base memory, preserving 
+ *                     all non-segment registers
+ *
+ *   real_call         issue a call to a real-mode routine from
+ *                     protected-mode code running in high memory
+ *
+ *   prot_call         issue a call to a protected-mode routine from
+ *                     real-mode code running in base memory
+ *
+ * librm requires the following functions to be present in the
+ * protected-mode code:
+ *
+ *   _phys_to_virt     Switch from physical to virtual addressing.  This
+ *                     routine must be position-independent and must
+ *                     *not* assume that it is genuinely running with
+ *                     flat physical addresses
+ *
+ *   _virt_to_phys     Switch from virtual to physical addresses.
+ *
+ *   gateA20_set       Enable the A20 line to permit access to the odd
+ *                     megabytes of RAM.  (This function will be called
+ *                     with virtual addresses set up).
+ *
+ * librm needs to be linked against the protected-mode binary so that
+ * it can import the symbols for these functions.
+ *
+ * librm requires that the protected-mode code set up the following
+ * segments:
+ *
+ *   PHYSICAL_CS       32-bit pmode code and data segments with flat
+ *   PHYSICAL_DS       physical addresses.
+ *
+ *   VIRTUAL_CS                32-bit pmode code segment with virtual
+ *                     addressing, such that a protected-mode routine
+ *                     can always be found at $VIRTUAL_CS:routine.
+ *
+ * These segments must be set as #define constants when compiling
+ * librm.  Edit librm.h to change the values.
+ *
+ * librm does not know the location of the code executing in high
+ * memory.  It relies on the code running in high memory setting up a
+ * GDT such that the high-memory code is accessible at virtual
+ * addresses fixed at compile-time.
+ *
+ * librm symbols are exported as absolute values and represent offsets
+ * into librm.  This is the most useful form of the symbols, since
+ * librm is basically a binary blob that you place somewhere in base
+ * memory.
+ *
+ * librm.h provides convenient ways to use these symbols: you simply
+ * set the pointer ( char * ) installed_librm to point to wherever
+ * librm is installed, and can then use e.g. inst_rm_stack just like
+ * any other variable and have it automatically refer to the value of
+ * rm_stack in the installed librm.  Macro trickery makes this
+ * completely transparent, and the resulting assembler code is
+ * amazingly efficient.
+ *
+ * Note that librm must be called in genuine real mode, not 16:16 or
+ * 16:32 protected mode.  It makes the assumption that
+ * physical_address = 16*segment+offset, and also that it can use
+ * OFFSET(%bp) to access stack variables.  The former assumption will
+ * break in either protected mode, the latter may break in 16:32
+ * protected mode.
+ ****************************************************************************
+ */
+
+/*
+ * Default values for pmode segments if not defined
+ */
+#ifndef PHYSICAL_CS
+#warning "Assuming PHYSICAL_CS = 0x08"
+#define PHYSICAL_CS 0x08
+#endif
+#ifndef PHYSICAL_DS
+#warning "Assuming PHYSICAL_DS = 0x10"
+#define PHYSICAL_DS 0x10
+#endif
+#ifndef VIRTUAL_CS
+#warning "Assuming VIRTUAL_CS = 0x18"
+#define VIRTUAL_CS 0x18
+#endif
+
+/* For switches to/from protected mode */
+#define CR0_PE 1
+
+/* Size of various C data structures */
+#define SIZEOF_I386_SEG_REGS   12
+#define SIZEOF_I386_REGS       32
+#define SIZEOF_I386_ALL_REGS   ( SIZEOF_I386_SEG_REGS + SIZEOF_I386_REGS )
+#define SIZEOF_I386_FLAGS      4
+#define SIZEOF_REAL_MODE_REGS   ( SIZEOF_I386_ALL_REGS + SIZEOF_I386_FLAGS )
+#define SIZEOF_SEGOFF_T                4
+#define SIZEOF_REAL_CALL_PARAMS ( SIZEOF_I386_ALL_REGS + 2 * SIZEOF_SEGOFF_T )
+       
+       .text
+       .arch i386
+       .section ".librm", "awx", @progbits
+       .align 16
+
+       .globl  librm
+librm:
+       
+_librm_start:
+
+#undef OFFSET
+#define OFFSET(sym) ( sym - _librm_start )
+
+#undef EXPORT
+#define EXPORT(sym) \
+       .globl sym ; \
+       .globl _ ## sym ;  \
+       .equ _ ## sym, OFFSET(sym) ; \
+       sym
+
+/****************************************************************************
+ * GDT for initial transition to protected mode
+ *
+ * PHYSICAL_CS and PHYSICAL_DS are defined in an external header file.
+ * We use only those selectors, and construct our GDT to match the
+ * selector values we're asked to use.  Use PHYSICAL_CS=0x08 and
+ * PHYSICAL_DS=0x10 to minimise the space occupied by this GDT.
+ *
+ * Note: pm_gdt is also used to store the location of the
+ * protected-mode GDT as recorded on entry to prot_to_real.
+ ****************************************************************************
+ */
+       .align 16
+pm_gdt:
+pm_gdt_limit:          .word pm_gdt_length - 1
+pm_gdt_addr:           .long 0
+                       .word 0 /* padding */
+       
+       .org    pm_gdt + PHYSICAL_CS
+pm_gdt_pm_cs:
+       /* 32 bit protected mode code segment, physical addresses */
+       .word   0xffff, 0
+       .byte   0, 0x9f, 0xcf, 0
+       
+       .org    pm_gdt + PHYSICAL_DS
+pm_gdt_pm_ds:
+       /* 32 bit protected mode data segment, physical addresses */
+       .word   0xffff,0
+       .byte   0,0x93,0xcf,0
+       
+pm_gdt_end:            
+       .equ    pm_gdt_length, pm_gdt_end - pm_gdt
+
+/****************************************************************************
+ * GDT for transition to real mode
+ *
+ * This is used primarily to set 64kB segment limits.  Define
+ * FLATTEN_REAL_MODE if you want to use so-called "flat real mode"
+ * with 4GB limits instead.  The base address of each of the segments
+ * will be adjusted at run-time.
+ *
+ * NOTE: This must be located before prot_to_real, otherwise gas
+ * throws a "can't handle non absolute segment in `ljmp'" error due to
+ * not knowing the value of RM_CS when the ljmp is encountered.
+ *
+ * Note also that putting ".word rm_gdt_end - rm_gdt - 1" directly
+ * into rm_gdt_limit, rather than going via rm_gdt_length, will also
+ * produce the "non absolute segment" error.  This is most probably a
+ * bug in gas.
+ ****************************************************************************
+ */
+       
+#ifdef FLATTEN_REAL_MODE
+#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x8f
+#else
+#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
+#endif
+       .align 16
+rm_gdt:
+rm_gdt_limit:          .word rm_gdt_length - 1
+rm_gdt_base:           .long 0
+                       .word 0 /* padding */
+       
+rm_gdt_rm_cs:  /* 16 bit real mode code segment */
+       .equ    RM_CS, rm_gdt_rm_cs - rm_gdt
+       .word   0xffff,(0&0xffff)
+       .byte   (0>>16),0x9b,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
+       
+rm_gdt_rm_ds:  /* 16 bit real mode data segment */
+       .equ    RM_DS, rm_gdt_rm_ds - rm_gdt
+       .word   0xffff,(0&0xffff)
+       .byte   (0>>16),0x93,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
+       
+rm_gdt_end:
+       .equ    rm_gdt_length, rm_gdt_end - rm_gdt
+
+/****************************************************************************
+ * real_to_prot (real-mode far call)
+ *
+ * Switch from 16-bit real-mode to 32-bit protected mode with flat
+ * physical addresses.  %esp is restored from the saved pm_esp.  All
+ * segment registers are set to flat physical-mode values.  All other
+ * registers are preserved.  Interrupts are disabled.
+ *
+ * Note that this routine can be called *without* having first set up
+ * a stored pm_esp or stored GDT.  If you do this, real_to_prot will
+ * return with a temporary stack that is only *FOUR BYTES* in size.
+ * This is just enough to enable you to do a "call 1f; popl %ebp"
+ * sequence in order to find out your physical address and then load a
+ * proper 32-bit protected-mode stack pointer.  Do *NOT* use more than
+ * four bytes since this will overwrite code in librm!
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+
+       .code16         
+EXPORT(real_to_prot):
+       /* Disable interrupts */
+       cli
+
+       /* Set %ds = %cs, for easier access to variables */
+       pushw   %cs
+       popw    %ds
+       
+       /* Preserve registers */
+       movl    %eax, %ds:OFFSET(save_eax)
+       movl    %ebx, %ds:OFFSET(save_ebx)
+
+       /* Extract real-mode far return address from stack */
+       popl    %ds:OFFSET(save_retaddr)
+
+       /* Record real-mode stack pointer */
+       movw    %sp, %ds:OFFSET(rm_sp)
+       pushw   %ss
+       popw    %ds:OFFSET(rm_ss)
+
+       /* Physical base address of librm to %ebx */
+       xorl    %ebx, %ebx
+       movw    %cs, %bx
+       shll    $4, %ebx
+               
+       /* Check base address of stored protected-mode GDT.  If it's
+        * zero, set it up to use our internal GDT (with physical
+        * segments only).
+        */
+       movl    %ds:OFFSET(pm_gdt_addr), %eax
+       testl   %eax, %eax
+       jnz     1f
+       /* Use internal GDT */
+       movl    %ebx, %eax
+       addl    $OFFSET(pm_gdt), %eax
+       movl    %eax, %ds:OFFSET(pm_gdt_addr)
+1:     
+       
+       /* Set up protected-mode continuation address on real-mode stack */
+       pushl   $PHYSICAL_CS
+       movl    %ebx, %eax
+       addl    $OFFSET(1f), %eax
+       pushl   %eax
+       
+       /* Restore protected-mode GDT */
+       lgdt    %ds:OFFSET(pm_gdt)
+
+       /* Switch to protected mode */
+       movl    %cr0, %eax
+       orb     $CR0_PE, %al
+       movl    %eax, %cr0
+
+       /* Flush prefetch queue and reload %cs:eip */
+       data32 lret
+1:     .code32
+
+       /* Set up protected-mode stack and data segments */
+       movw    $PHYSICAL_DS, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* Switch to saved protected-mode stack.  Note that there may
+        * not actually *be* a saved protected-mode stack.
+        */
+       movl    OFFSET(pm_esp)(%ebx), %esp
+       testl   %esp, %esp
+       jnz     1f
+       /* No stack - use save_retaddr as a 4-byte temporary stack */
+       leal    OFFSET(save_retaddr+4)(%ebx), %esp
+1:     
+       
+       /* Convert real-mode far return address to physical address
+        * and place on stack
+        */
+       pushl   OFFSET(save_retaddr)(%ebx)
+       xorl    %eax, %eax
+       xchgw   2(%esp), %ax
+       shll    $4, %eax
+       addl    %eax, 0(%esp)
+
+       /* Restore registers and return */
+       movl    OFFSET(save_eax)(%ebx), %eax
+       movl    OFFSET(save_ebx)(%ebx), %ebx
+       ret
+
+/****************************************************************************
+ * prot_to_real (protected-mode near call, physical addresses)
+ *
+ * Switch from 32-bit protected mode with flat physical addresses to
+ * 16-bit real mode.  %ss:sp is restored from the saved rm_ss and
+ * rm_sp.  %cs is set such that %cs:0000 is the start of librm.  All
+ * other segment registers are set to %ss.  All other registers are
+ * preserved.  Interrupts are *not* enabled, since we want to be able
+ * to use this routine inside an ISR.
+ *
+ * Note that since %cs:0000 points to the start of librm on exit, it
+ * follows that the code calling prot_to_real must be located within
+ * 64kB of the start of librm.
+ *
+ * Parameters: none
+ ****************************************************************************
+ */
+
+       .code32
+EXPORT(prot_to_real):
+       /* Calculate physical base address of librm in %ebx, preserve
+        * original %eax and %ebx in save_eax and save_ebx
+        */
+       pushl   %ebx
+       call    1f
+1:     popl    %ebx
+       subl    $OFFSET(1b), %ebx
+       popl    OFFSET(save_ebx)(%ebx)
+       movl    %eax, OFFSET(save_eax)(%ebx)
+
+       /* Extract return address from the stack, convert to offset
+        * within librm and save in save_retaddr
+        */
+       popl    %eax
+       subl    %ebx, %eax
+       movl    %eax, OFFSET(save_retaddr)(%ebx)
+
+       /* Record protected-mode stack pointer */
+       movl    %esp, OFFSET(pm_esp)(%ebx)
+
+       /* Record protected-mode GDT */
+       sgdt    OFFSET(pm_gdt)(%ebx)
+
+       /* Set up real-mode GDT */
+       leal    OFFSET(rm_gdt)(%ebx), %eax
+       movl    %eax, OFFSET(rm_gdt_base)(%ebx)
+       movl    %ebx, %eax
+       rorl    $16, %eax
+       movw    %bx, OFFSET(rm_gdt_rm_cs+2)(%ebx)
+       movb    %al, OFFSET(rm_gdt_rm_cs+4)(%ebx)
+       movw    %bx, OFFSET(rm_gdt_rm_ds+2)(%ebx)
+       movb    %al, OFFSET(rm_gdt_rm_ds+4)(%ebx)
+       
+       /* Switch to real-mode GDT and reload segment registers to get
+        * 64kB limits.  Stack is invalidated by this process.
+        */
+       lgdt    OFFSET(rm_gdt)(%ebx)
+       ljmp    $RM_CS, $1f
+1:     .code16
+       movw    $RM_DS, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* Calculate real-mode code segment in %ax and store in ljmp
+        * instruction
+        */
+       movl    %ebx, %eax
+       shrl    $4, %eax
+       movw    %ax, OFFSET(p2r_ljmp) + 3
+
+       /* Switch to real mode */
+       movl    %cr0, %ebx
+       andb    $0!CR0_PE, %bl
+       movl    %ebx, %cr0
+
+       /* Intersegment jump to flush prefetch queue and reload
+        * %cs:eip.  The segment gets filled in by the above code.  We
+        * can't just use lret to achieve this, because we have no
+        * stack at the moment.
+        */
+p2r_ljmp:
+       ljmp    $0, $OFFSET(1f)
+1:     
+
+       /* Set %ds to point to code segment for easier data access */
+       movw    %ax, %ds
+                       
+       /* Restore registers */
+       movl    OFFSET(save_eax), %eax
+       movl    OFFSET(save_ebx), %ebx
+
+       /* Set up real-mode data segments and stack */
+       movw    OFFSET(rm_ss), %ss
+       movw    OFFSET(rm_sp), %sp
+       pushw   %ss
+       pushw   %ss
+       pushw   %ss
+       pushw   %ss
+       popw    %ds
+       popw    %es
+       popw    %fs
+       popw    %gs
+
+       /* Set up return address on stack and return */
+       pushw   %cs:OFFSET(save_retaddr)
+       ret
+
+/****************************************************************************
+ * prot_call (real-mode far call)
+ *
+ * Call a specific C function in the protected-mode code.  The
+ * prototype of the C function must be
+ *   void function ( struct real_mode_regs *rm_regs,
+ *                  void (*retaddr) (void) ); 
+ * rm_regs will point to a struct containing the real-mode registers
+ * at entry to prot_call.  retaddr will point to the (virtual) return
+ * address from "function".  This return address will point into
+ * librm.  It is included so that "function" may, if desired, relocate
+ * librm and return via the new copy.  It must not be directly called
+ * as a function, i.e. you may not do "*retaddr()"; you must instead
+ * do something like:
+ *     *retaddr += ( new_librm_location - old_librm_location );
+ *     return;
+ *
+ * All registers will be preserved across prot_call(), unless the C
+ * function explicitly overwrites values in rm_regs.  Interrupt status
+ * will also be preserved.  Gate A20 will be enabled.
+ *
+ * Parameters:
+ *   function : virtual address of protected-mode function to call
+ *
+ * Example usage:
+ *     pushl   $pxe_api_call
+ *     lcall   $LIBRM_SEGMENT, $prot_call
+ *     addw    $4, %sp
+ * to call in to the C function
+ *      void pxe_api_call ( struct real_mode_regs *rm_regs );
+ ****************************************************************************
+ */
+
+#define PC_OFFSET_RM_REGS ( 0 )
+#define PC_OFFSET_RETADDR ( PC_OFFSET_RM_REGS + SIZEOF_REAL_MODE_REGS )
+#define PC_OFFSET_FUNCTION ( PC_OFFSET_RETADDR + 4 )
+       
+       .code16
+EXPORT(prot_call):
+       /* Preserve registers and flags on RM stack */
+       pushfl
+       pushal
+       pushw   %gs
+       pushw   %fs
+       pushw   %es
+       pushw   %ds
+       pushw   %ss
+       pushw   %cs     
+       
+       /* Record RM stack pointer */
+       xorl    %ebp, %ebp
+       movw    %sp, %bp
+       
+       /* Physical address of RM stack pointer to %esi */
+       xorl    %esi, %esi
+       pushw   %ss
+       popw    %si
+       shll    $4, %esi
+       addl    %ebp, %esi
+
+       /* Address of pmode function to %ebx */
+       movl    %ss:(PC_OFFSET_FUNCTION)(%bp), %ebx
+       
+       /* Switch to protected mode */
+       pushw   %cs
+       call    real_to_prot
+       .code32
+
+       /* Copy rm_regs from RM stack to PM stack */
+       movl    $SIZEOF_REAL_MODE_REGS, %ecx
+       subl    %ecx, %esp
+       movl    %esp, %edi
+       cld
+       rep     movsb
+       
+       /* Switch to virtual addresses. */
+       call    1f
+       jmp     2f
+1:     ljmp    $VIRTUAL_CS, $_phys_to_virt
+2:     
+
+       /* Enable A20 line */
+       pushal
+       lcall   $VIRTUAL_CS, $gateA20_set
+       popl    %eax    /* discard */
+       popal
+
+       /* Push &rm_regs and &retaddr on the stack, and call function */
+       movl    %esp, %ebp
+       pushl   %esp
+       subl    $12, 0(%esp)
+       pushl   %ebp
+       call    *%ebx
+       popl    %eax /* discard */
+       popl    %eax /* discard */
+
+       /* Switch to physical addresses, discard PM register store */
+       lcall   $VIRTUAL_CS, $_virt_to_phys
+       addl    $SIZEOF_REAL_MODE_REGS+4, %esp /* also discard lcall seg */
+
+       /* Switch to real mode */
+       call    prot_to_real
+       .code16
+
+       /* Restore registers and flags, and return */
+       popw    %ax     /* skip %cs */
+       popw    %ax     /* skip %ss */
+       popw    %ds
+       popw    %es
+       popw    %fs
+       popw    %gs
+       popal
+       popfl
+       lret
+
+/****************************************************************************
+ * real_call (protected-mode near call, virtual addresses)
+ *
+ * Call a real-mode function from protected-mode code.
+ *
+ * The non-segment register values will be passed directly to the
+ * real-mode code.  The segment registers will be set as per
+ * prot_to_real.  The non-segment register values set by the real-mode
+ * function will be passed back to the protected-mode caller.  A
+ * result of this is that this routine cannot be called directly from
+ * C code, since it clobbers registers that the C ABI expects the
+ * callee to preserve.  Gate A20 will be re-enabled in case the
+ * real-mode routine disabled it.
+ *
+ * librm.h defines two convenient macros for using real_call:
+ * REAL_CALL and REAL_EXEC.  See librm.h and realmode.h for details
+ * and examples.
+ *
+ * Parameters:
+ *   far pointer to real-mode function to call
+ *
+ * Returns: none
+ ****************************************************************************
+ */
+
+#define RC_OFFSET_PRESERVE_REGS ( 0 )
+#define RC_OFFSET_RETADDR ( RC_OFFSET_PRESERVE_REGS + 8 )
+#define RC_OFFSET_RM_FUNCTION ( RC_OFFSET_RETADDR + 4 )
+       
+       .code32
+EXPORT(real_call):
+       /* Preserve registers */
+       pushl   %ebp
+       pushl   %eax
+       
+       /* Switch to physical addresses */
+       lcall   $VIRTUAL_CS, $_virt_to_phys
+       addl    $4, %esp
+
+       /* Extract real-mode function address and store in ljmp instruction */
+       call    1f
+1:     popl    %ebp
+       movl    RC_OFFSET_RM_FUNCTION(%esp), %eax
+       movl    %eax, (rc_ljmp + 1 - 1b)(%ebp)
+
+       /* Restore registers */
+       popl    %eax
+       popl    %ebp
+
+       /* Switch to real mode, preserving non-segment registers */
+       call    prot_to_real
+       .code16
+
+       /* Far call to real-mode routine */
+       pushw   %cs
+       call    rc_ljmp
+       jmp     2f
+rc_ljmp:       
+       ljmp    $0, $0  /* address filled in by above code */
+2:     
+       
+       /* Switch to protected mode */
+       pushw   %cs
+       call    real_to_prot
+       .code32
+
+       /* Switch to virtual addresses */
+       call    1f
+       jmp     2f
+1:     ljmp    $VIRTUAL_CS, $_phys_to_virt
+2:     
+
+       /* Enable A20 line */
+       pushal
+       lcall   $VIRTUAL_CS, $gateA20_set
+       popl    %eax    /* discard */
+       popal
+
+       /* Return */
+       ret
+       
+/****************************************************************************
+ * Relocation lock counter
+ *
+ * librm may be moved in base memory only when this counter is zero.
+ * The counter gets incremented whenever a reference to librm is
+ * generated (e.g. a real_call is made, resulting in a return address
+ * pointing to librm being placed on the stack), and decremented when
+ * the reference goes out of scope (e.g. the real_call returns).
+ ****************************************************************************
+ */
+EXPORT(librm_ref_count):       .byte 0
+
+/****************************************************************************
+ * Stored real-mode and protected-mode stack pointers
+ *
+ * The real-mode stack pointer is stored here whenever real_to_prot
+ * is called and restored whenever prot_to_real is called.  The
+ * converse happens for the protected-mode stack pointer.
+ *
+ * Despite initial appearances this scheme is, in fact re-entrant,
+ * because program flow dictates that we always return via the point
+ * we left by.  For example:
+ *    PXE API call entry
+ *  1   real => prot
+ *        ...
+ *        Print a text string
+ *         ...
+ *  2       prot => real
+ *            INT 10
+ *  3       real => prot
+ *         ...
+ *        ...
+ *  4   prot => real
+ *    PXE API call exit
+ *
+ * At point 1, the RM mode stack value, say RPXE, is stored in
+ * rm_ss,sp.  We want this value to still be present in rm_ss,sp when
+ * we reach point 4.
+ *
+ * At point 2, the RM stack value is restored from RPXE.  At point 3,
+ * the RM stack value is again stored in rm_ss,sp.  This *does*
+ * overwrite the RPXE that we have stored there, but it's the same
+ * value, since the code between points 2 and 3 has managed to return
+ * to us.
+ ****************************************************************************
+ */
+
+EXPORT(rm_stack):      /* comprises rm_ss and rm_sp */
+rm_sp:         .word 0
+rm_ss:         .word 0
+
+EXPORT(pm_stack):
+pm_esp:                .long 0
+
+/****************************************************************************
+ * Temporary variables
+ ****************************************************************************
+ */
+save_eax:      .long 0
+save_ebx:      .long 0
+save_retaddr:  .long 0
+       
+/****************************************************************************
+ * End of librm
+ ****************************************************************************
+ */
+_librm_end:
+       .globl _librm_size
+       .equ _librm_size, _librm_end - _librm_start
diff --git a/src/arch/i386/transitions/librm_mgmt.c b/src/arch/i386/transitions/librm_mgmt.c
new file mode 100644 (file)
index 0000000..bfe963d
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * librm: a library for interfacing to real-mode code
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+#ifdef KEEP_IT_REAL
+/* Build a null object under -DKEEP_IT_REAL */
+#else
+
+#include "stdint.h"
+#include "stddef.h"
+#include "string.h"
+#include "librm.h"
+
+/*
+ * This file provides functions for managing librm.
+ *
+ */
+
+/* Current location of librm in base memory */
+char *installed_librm = librm;
+
+/*
+ * Install librm to base memory
+ *
+ */
+void install_librm ( void *addr ) {
+       memcpy ( addr, librm, librm_size );
+       installed_librm = addr;
+}
+
+/*
+ * Increment lock count of librm
+ *
+ */
+void lock_librm ( void ) {
+       inst_librm_ref_count++;
+}
+
+/*
+ * Decrement lock count of librm
+ *
+ */
+void unlock_librm ( void ) {
+#ifdef DEBUG_LIBRM
+       if ( inst_librm_ref_count == 0 ) {
+               printf ( "librm: ref count gone negative\n" );
+               lockup();
+       }
+#endif
+       inst_librm_ref_count--;
+}
+
+/*
+ * Allocate space on the real-mode stack and copy data there.
+ *
+ */
+uint16_t copy_to_rm_stack ( void *data, size_t size ) {
+#ifdef DEBUG_LIBRM
+       if ( inst_rm_stack.offset <= size ) {
+               printf ( "librm: out of space in RM stack\n" );
+               lockup();
+       }
+#endif
+       inst_rm_stack.offset -= size;
+       copy_to_real ( inst_rm_stack.segment, inst_rm_stack.offset,
+                      data, size );
+       return inst_rm_stack.offset;
+};
+
+/*
+ * Deallocate space on the real-mode stack, optionally copying back
+ * data.
+ *
+ */
+void remove_from_rm_stack ( void *data, size_t size ) {
+       if ( data ) {
+               copy_from_real ( data,
+                                inst_rm_stack.segment, inst_rm_stack.offset,
+                                size );
+       }
+       inst_rm_stack.offset += size;
+};
+
+#endif /* KEEP_IT_REAL */
index 3115714ab8dcde77a747dea6459070c08190d8e0..b7f5473932d51d01eaa399da9347343aa28157f8 100644 (file)
@@ -2,6 +2,7 @@
 #include "timer.h"
 #include "sal.h"
 #include "pal.h"
+#include "init.h"
 
 static inline unsigned long get_cycles(void)
 {
@@ -39,7 +40,7 @@ static unsigned long calibrate_cycles(void)
 }
 
 static unsigned long clocks_per_tick;
-void setup_timers(void)
+static void setup_timers(void)
 {
        if (!clocks_per_tick) {
                clocks_per_tick = calibrate_cycles();
@@ -87,3 +88,5 @@ int timer2_running(void)
 {
        return __timer_running();
 }
+
+INIT_FN ( INIT_TIMERS, setup_timers, NULL, NULL );
diff --git a/src/bin/.cvsignore b/src/bin/.cvsignore
new file mode 100644 (file)
index 0000000..72e8ffc
--- /dev/null
@@ -0,0 +1 @@
+*
index 12afb8d531d48f47f7fff9a82dd5058603ee5468..546b7be3b17fc0752486429e4c819dfc1bba53d9 100644 (file)
@@ -1,5 +1,3 @@
-#ifdef CONSOLE_BTEXT
-#ifdef CONFIG_PCI
 /*
  * Procedures for drawing on the screen early on in the boot process.
  *
@@ -10,6 +8,8 @@
  */
 
 #include "etherboot.h"
+#include "console.h"
+#include "init.h"
 #include "pci.h"
 
 #ifdef CONFIG_FILO
@@ -36,6 +36,8 @@ static void draw_byte_16(unsigned char *bits, u32 *base, u32 rb);
 #endif
 static void draw_byte_8(unsigned char *bits, u32 *base, u32 rb);
 
+static int pci_find_device_x(int vendorx, int devicex, int index, struct pci_device *dev);
+
 static u32 g_loc_X;
 static u32 g_loc_Y;
 static u32 g_max_loc_X;
@@ -62,7 +64,7 @@ boot_infos_t disp_bi;
 /* This function will enable the early boot text when doing OF booting. This
  * way, xmon output should work too
  */
-void
+static void
 btext_setup_display(u32 width, u32 height, u32 depth, u32 pitch,
                    unsigned long address)
 {
@@ -73,7 +75,7 @@ btext_setup_display(u32 width, u32 height, u32 depth, u32 pitch,
        g_max_loc_X = width / 8;
        g_max_loc_Y = height / 16;
 //     bi->logicalDisplayBase = (unsigned char *)address;
-       bi->dispDeviceBase = (unsigned char *)address;
+       bi->dispDeviceBase = address;
        bi->dispDeviceRowBytes = pitch;
        bi->dispDeviceDepth = depth;
        bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
@@ -93,7 +95,7 @@ btext_setup_display(u32 width, u32 height, u32 depth, u32 pitch,
  *    changes.
  */
 
-void 
+static void 
 map_boot_text(void)
 {
        boot_infos_t *bi = &disp_bi;
@@ -113,18 +115,19 @@ static unsigned char * BTEXT
 calc_base(boot_infos_t *bi, u32 x, u32 y)
 {
        unsigned char *base;
-#if 1
        base = bi->logicalDisplayBase;
+#if 0
+       /* Ummm... which moron wrote this? */
        if (base == 0)
-#endif
                base = bi->dispDeviceBase;
+#endif
        base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
        base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
        return base;
 }
 
 
-void BTEXT btext_clearscreen(void)
+static void BTEXT btext_clearscreen(void)
 {
        boot_infos_t* bi        = &disp_bi;
        u32 *base       = (u32 *)calc_base(bi, 0, 0);
@@ -147,7 +150,7 @@ __inline__ void dcbst(const void* addr)
        __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr));
 }
 
-void BTEXT btext_flushscreen(void)
+static void BTEXT btext_flushscreen(void)
 {
        boot_infos_t* bi        = &disp_bi;
        u32  *base      = (unsigned long *)calc_base(bi, 0, 0);
@@ -198,7 +201,7 @@ scrollscreen(void)
 }
 #endif /* ndef NO_SCROLL */
 
-void BTEXT btext_drawchar(char c)
+static void BTEXT btext_drawchar(char c)
 {
        u32 cline = 0;
 
@@ -246,7 +249,7 @@ void BTEXT btext_drawchar(char c)
 #endif
 }
 #if 0
-void BTEXT
+static void BTEXT
 btext_drawstring(const char *c)
 {
        if (!boot_text_mapped)
@@ -254,7 +257,7 @@ btext_drawstring(const char *c)
        while (*c)
                btext_drawchar(*c++);
 }
-void BTEXT
+static void BTEXT
 btext_drawhex(u32 v)
 {
        static char hex_table[] = "0123456789abcdef";
@@ -394,7 +397,7 @@ draw_byte_8(unsigned char *font, u32 *base, u32 rb)
 #endif
 
 
-void btext_init(void)
+static void btext_init(void)
 {
 #if 0
 // for debug
@@ -402,14 +405,16 @@ void btext_init(void)
 #else
     uint32_t frame_buffer;//  0xfc000000
 
-    struct pci_device *dev = 0;
-
 #if USE_FILO_PCI_FIND==0
+    struct pci_device dev;
+
     pci_find_device_x(0x1002, 0x4752, 0, &dev);
     if(dev.vendor==0) return; // no fb
 
     frame_buffer = (uint32_t)dev.membase;
 #else
+    struct pci_device *dev = 0;
+
     pci_init();
     dev = pci_find_device(0x1002, 0x4752, -1, -1, 0);
     if(!dev) {
@@ -422,21 +427,21 @@ void btext_init(void)
 #endif
 
        btext_setup_display(640, 480, 8, 640,frame_buffer);
-//     btext_clearscreen(); //move to main
-//     map_boot_text();  //move console_init
+       btext_clearscreen();
+       map_boot_text();
 }
-void btext_putc(int c)
+static void btext_putc(int c)
 {      
         btext_drawchar((unsigned char)c);
 }
-#if 0
-static struct console_driver btext_console __console = {
-        .init    = btext_init,
-        .tx_byte = btext_tx_byte,
-        .rx_byte = 0,
-        .tst_byte = 0,
+
+static struct console_driver btext_console __console_driver = {
+       .putchar = btext_putc,
+       .disabled = 1,
 };
-#endif
+
+INIT_FN ( INIT_CONSOLE, btext_init, NULL, NULL );
+
 #if USE_FILO_PCI_FIND==0
 int pci_find_device_x(int vendorx, int devicex, int index, struct pci_device *dev)
 {                       
@@ -445,7 +450,6 @@ int pci_find_device_x(int vendorx, int devicex, int index, struct pci_device *de
 #if 1
         unsigned char hdr_type = 0;
 #endif
-        uint32_t class; 
         uint16_t vendor, device;
         uint32_t l, membase;
 #if 0
@@ -5192,5 +5196,3 @@ static unsigned char vga_font[cmapsz] BTDATA = {
        0x00, /* 00000000 */
 #endif
 };
-#endif
-#endif
index 180b0669b32bd626096c16c9d87b9ff218bd8afc..d85ca242d73aa0704389cb005485332f837bc5d2 100644 (file)
@@ -7,6 +7,7 @@
 
 #include       "etherboot.h"
 #include       "nic.h"
+#include       "console.h"
 #ifdef BUILD_SERIAL
 #include       ".buildserial.h"
 #define xstr(s) str(s)
@@ -104,6 +105,9 @@ void print_config(void)
                "DNS "
 #endif
                "\n");
+#ifdef KEEP_IT_REAL
+       printf( "Keeping It Real [EXPERIMENTAL]\n" );
+#endif
 }
 
 static const char *driver_name[] = {
@@ -159,3 +163,48 @@ void disable(struct dev *dev)
                dev->disable = 0;
        }
 }
+
+
+/*
+ * Drag in all requested console types
+ *
+ * At least one of the CONSOLE_xxx has to be set.  CONSOLE_DUAL sets
+ * both CONSOLE_FIRMWARE and CONSOLE_SERIAL for legacy compatibility.
+ * If no CONSOLE_xxx is set, CONSOLE_FIRMWARE is assumed.
+ */
+
+#ifdef CONSOLE_CRT
+#define CONSOLE_FIRMWARE
+#endif
+
+#ifdef CONSOLE_DUAL
+#undef CONSOLE_FIRMWARE
+#define CONSOLE_FIRMWARE
+#undef CONSOLE_SERIAL
+#define CONSOLE_SERIAL
+#endif
+
+#if    !defined(CONSOLE_FIRMWARE) && !defined(CONSOLE_SERIAL)
+#define CONSOLE_FIRMWARE
+#endif
+
+#ifdef CONSOLE_FIRMWARE
+REQUIRE_OBJECT ( bios_console );
+#endif
+
+#ifdef CONSOLE_SERIAL
+REQUIRE_OBJECT ( serial );
+#endif
+
+#ifdef CONSOLE_DIRECT_VGA
+REQUIRE_OBJECT ( video_subr );
+#endif
+
+#ifdef CONSOLE_BTEXT
+REQUIRE_OBJECT ( btext );
+#endif
+
+#ifdef CONSOLE_PC_KBD
+REQUIRE_OBJECT ( pc_kbd );
+#endif
+
diff --git a/src/core/console.c b/src/core/console.c
new file mode 100644 (file)
index 0000000..6e92cb5
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Central console switch.  Various console devices can be selected
+ * via the build options CONSOLE_FIRMWARE, CONSOLE_SERIAL etc.
+ * config.c picks up on these definitions and drags in the relevant
+ * objects.  The linker compiles the console_drivers table for us; we
+ * simply delegate to each console_driver that we find in the table.
+ *
+ * Doing it this way allows for changing CONSOLE_XXX without
+ * rebuilding anything other than config.o.  This is extremely useful
+ * for rom-o-matic.
+ */
+
+#include "stddef.h"
+#include "console.h"
+
+/* FIXME: we need a cleaner way to pick up cpu_nap().  It makes a
+ * real-mode call, and so we don't want to use it with LinuxBIOS.
+ */
+#include "bios.h"
+
+extern struct console_driver console_drivers[];
+extern struct console_driver console_drivers_end[];
+
+/*****************************************************************************
+ * putchar : write a single character to each console
+ *****************************************************************************
+ */
+
+void putchar ( int character ) {
+       struct console_driver *console;
+
+       /* Automatic LF -> CR,LF translation */
+       if ( character == '\n' )
+               putchar ( '\r' );
+
+       for ( console = console_drivers; console < console_drivers_end ;
+             console++ ) {
+               if ( ( ! console->disabled ) && console->putchar )
+                       console->putchar ( character );
+       }
+}
+
+/*****************************************************************************
+ * has_input : check to see if any input is available on any console,
+ * and return a pointer to the console device if so
+ *****************************************************************************
+ */
+static struct console_driver * has_input ( void ) {
+       struct console_driver *console;
+
+       for ( console = console_drivers; console < console_drivers_end ;
+             console++ ) {
+               if ( ( ! console->disabled ) && console->iskey ) {
+                       if ( console->iskey () )
+                               return console;
+               }
+       }
+       return NULL;
+}
+
+/*****************************************************************************
+ * getchar : read a single character from any console
+ *
+ * NOTE : this function does not echo the character, and it does block
+ *****************************************************************************
+ */
+
+int getchar ( void ) {
+       struct console_driver *console;
+       int character = 256;
+
+       while ( character == 256 ) {
+               /* Doze for a while (until the next interrupt).  This works
+                * fine, because the keyboard is interrupt-driven, and the
+                * timer interrupt (approx. every 50msec) takes care of the
+                * serial port, which is read by polling.  This reduces the
+                * power dissipation of a modern CPU considerably, and also
+                * makes Etherboot waiting for user interaction waste a lot
+                * less CPU time in a VMware session.
+                */
+               cpu_nap();
+               
+               console = has_input();
+               if ( console && console->getchar )
+                       character = console->getchar ();
+       }
+
+       /* CR -> LF translation */
+       if ( character == '\r' )
+               character = '\n';
+
+       return character;
+}
+
+/*****************************************************************************
+ * iskey : check to see if any input is available on any console
+ *****************************************************************************
+ */
+
+int iskey ( void ) {
+       return has_input() ? 1 : 0;
+}
index 51ce47d7531592c9b7d23955205b1017ec174ad4..7f69829df588acf9d9cb21809002ef37efcbca27 100644 (file)
@@ -1,8 +1,12 @@
 #include "etherboot.h"
+#include "init.h"
+#include "memsizes.h"
 
 size_t heap_ptr, heap_top, heap_bot;
 
-void init_heap(void)
+#define _virt_start 0
+
+static void init_heap(void)
 {
        size_t size;
        size_t start, end;
@@ -82,6 +86,11 @@ void init_heap(void)
        heap_ptr = heap_bot;
 }
 
+static void reset_heap(void)
+{
+       heap_ptr = heap_bot;
+}
+
 void *allot(size_t size)
 {
        void *ptr;
@@ -166,3 +175,5 @@ void forget2(void *ptr)
         }
         heap_ptr = addr;
 }
+
+INIT_FN ( INIT_HEAP, init_heap, reset_heap, NULL );
diff --git a/src/core/init.c b/src/core/init.c
new file mode 100644 (file)
index 0000000..3dc8769
--- /dev/null
@@ -0,0 +1,44 @@
+/**************************************************************************
+ * call_{init,reset,exit}_fns ()
+ * 
+ * Call the various initialisation and exit functions.  We use a
+ * function table so that we don't end up dragging in an object just
+ * because we call its initialisation function.
+ **************************************************************************
+ */
+
+#include "init.h"
+
+extern struct init_fn init_fns[];
+extern struct init_fn init_fns_end[];
+
+void call_init_fns ( void ) {
+       struct init_fn *init_fn;
+
+       for ( init_fn = init_fns; init_fn < init_fns_end ; init_fn++ ) {
+               if ( init_fn->init )
+                       init_fn->init ();
+       }
+}
+
+void call_reset_fns ( void ) {
+       struct init_fn *init_fn;
+
+       for ( init_fn = init_fns; init_fn < init_fns_end ; init_fn++ ) {
+               if ( init_fn->reset )
+                       init_fn->reset ();
+       }
+}
+
+void call_exit_fns ( void ) {
+       struct init_fn *init_fn;
+
+       /* 
+        * Exit functions are called in reverse order to
+        * initialisation functions.
+        */
+       for ( init_fn = init_fns_end - 1; init_fn >= init_fns ; init_fn-- ) {
+               if ( init_fn->exit )
+                       init_fn->exit ();
+       }
+}
index e92d2929d07d4f31877c1ec342b7e594071554be..9cd89c228845557000cfcf70f13efb7ff69b12c6 100644 (file)
@@ -23,12 +23,10 @@ Literature dealing with the network protocols:
 #include "http.h"
 #include "timer.h"
 #include "cpu.h"
+#include "console.h"
+#include "init.h"
 #include <stdarg.h>
 
-#ifdef CONSOLE_BTEXT
-#include "btext.h"
-#endif
-
 #ifdef CONFIG_FILO
 #include <lib.h>
 #endif
@@ -43,51 +41,6 @@ int freebsd_howto = 0;
 char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE];
 #endif
 
-/* in_call(): the entry point to Etherboot.  Generally called from
- * arch_in_call(), which in turn will have been invoked from
- * platform-specific assembly code.
- */
-int in_call ( in_call_data_t *data, uint32_t opcode, va_list params ) {
-       int old_as_main_program = as_main_program;
-       int ret = 0;
-
-       /* Set flat to indicate that we are not running as the main
-        * program (i.e. we are something like a PXE stack).
-        */
-       as_main_program = 0;
-
-       /* NOTE: params will cease to be valid if we relocate, since
-        * it represents a virtual address
-        */
-       switch ( EB_OPCODE(opcode) ) {
-               
-       case EB_OPCODE_CHECK:
-               /* Installation check
-                */
-               ret = EB_CHECK_RESULT;
-               break;
-       case EB_OPCODE_MAIN:
-               /* Start up Etherboot as a standalone program. */
-               as_main_program = 1;
-               ret = main ( data, params );
-               break;
-#ifdef PXE_EXPORT
-       case EB_OPCODE_PXE:
-               /* !PXE API call */
-               ret = pxe_in_call ( data, params );
-               break;
-#endif
-       default:
-               printf ( "Unsupported API \"%c%c\"\n",
-                        EB_OPCODE(opcode) >> 8, EB_OPCODE(opcode) & 0xff );
-               ret = -1;
-               break;
-       }
-
-       as_main_program = old_as_main_program;
-       return ret;
-}
-
 static inline unsigned long ask_boot(unsigned *index)
 {
        unsigned long order = DEFAULT_BOOT_ORDER;
@@ -166,26 +119,6 @@ static inline void try_floppy_first(void)
 #endif /* TRY_FLOPPY_FIRST */  
 }
 
-void console_init(void)
-{
-#ifdef CONSOLE_SERIAL
-       (void)serial_init();
-#endif
-#ifdef         CONSOLE_DIRECT_VGA
-               video_init();
-#endif
-#ifdef CONSOLE_BTEXT
-       map_boot_text();
-#endif
-}
-
-static void console_fini(void)
-{
-#ifdef CONSOLE_SERIAL
-       (void)serial_fini();
-#endif
-}
-
 static struct class_operations {
        struct dev *dev;
        int (*probe)(struct dev *dev);
@@ -204,44 +137,16 @@ static int exit_ok;
 static int exit_status;
 static int initialized;
 
+
 /**************************************************************************
 MAIN - Kick off routine
 **************************************************************************/
-int main(in_call_data_t *data, va_list params)
-{
-       char *p;
+int main ( void ) {
        int state;
 
-       for (p = _bss; p < _ebss; p++)
-               *p = 0; /* Zero BSS */
-
-       console_init();
-       arch_main(data,params);
-
-#if 0
-#ifdef  CONSOLE_BTEXT
-        btext_init();
-        map_boot_text();
-        btext_clearscreen();
-#endif
-#endif 
-
-       if ( rom.rom_segment ) {
-               printf ( "ROM segment %#hx length %#hx reloc %#x\n",
-                        rom.rom_segment, rom.rom_length, _text );
-       }
-
-       cpu_setup();
-       setup_timers();
-       gateA20_set();
        print_config();
-       get_memsizes();
        cleanup();
 
-#ifdef CONFIG_PCMCIA
-       pcmcia_init_all();
-#endif
-
        /* -1:  timeout or ESC
           -2:  error return from loader
           -3:  finish the current run.
@@ -258,10 +163,7 @@ int main(in_call_data_t *data, va_list params)
        for(;state != 255;) {
                state = main_loop(state);
        }
-       arch_on_exit(exit_status);
-#ifdef CONFIG_PCMCIA
-       pcmcia_shutdown_all();
-#endif
+       /* arch_on_exit(exit_status) */
        return exit_status;
 }
 
@@ -283,13 +185,11 @@ static int main_loop(int state)
        static unsigned boot_index;
        static struct dev * dev = 0;
        static struct class_operations *ops;
-       static void *heap_base;
        static int type;
        static int i;
 
        if (!initialized) {
                initialized = 1;
-               console_init();
                if (dev && (state >= 1) && (state <= 2)) {
                        dev->how_probe = PROBE_AWAKE;
                        dev->how_probe = ops->probe(dev);
@@ -304,21 +204,8 @@ static int main_loop(int state)
                static int firsttime = 1;
                /* First time through */
                if (firsttime) {
-                       relocate();
+                       /* relocate(); */
                        cleanup();
-                       console_init();
-                       init_heap();
-#ifdef  CONSOLE_BTEXT
-                       //I need to all allot
-                       btext_init(); 
-                       map_boot_text();
-                       btext_clearscreen();
-#else
-       #ifdef CONFIG_FILO
-                       pci_init();
-       #endif
-#endif
-
                        firsttime = 0;
                } 
 #ifdef EXIT_IF_NO_OFFER
@@ -327,7 +214,6 @@ static int main_loop(int state)
                        exit(0);
                }
 #endif
-               heap_base = allot(0);
                i = -1;
                state = 4;
                dev = 0;
@@ -339,8 +225,7 @@ static int main_loop(int state)
        }
        case 4:
                cleanup();
-               console_init();
-               forget(heap_base);
+               call_reset_fns();
                /* Find a dev entry to probe with */
                if (!dev) {
                        int boot;
@@ -377,7 +262,12 @@ static int main_loop(int state)
                break;
        case 3:
                state = -1;
-               heap_base = allot(0);
+               /* Removed the following line because it was causing
+                * heap.o to be dragged in unnecessarily.  It's also
+                * slightly puzzling: by resetting heap_base, doesn't
+                * this mean that we permanently leak memory?
+                */
+               /* heap_base = allot(0); */
                dev->how_probe = ops->probe(dev);
                if (dev->how_probe == PROBE_FAILED) {
                        dev = 0;
@@ -518,7 +408,6 @@ void cleanup(void)
        /* Stop receiving packets */
        eth_disable();
        disk_disable();
-       console_fini();
        initialized = 0;
 }
 
index f5ce9d8f367e440246d6cddddf9c00085463cd7f..0fe6cb47d57fa3a792fe1fd2456dd916bcac6dcf 100644 (file)
@@ -3,13 +3,7 @@ MISC Support Routines
 **************************************************************************/
 
 #include "etherboot.h"
-#ifdef CONSOLE_BTEXT
-#include <btext.h>
-#endif
-#ifdef CONSOLE_PC_KBD
-#include <pc_kbd.h>
-#endif
-
+#include "console.h"
 
 /**************************************************************************
 IPCHKSUM - Checksum IP Header
@@ -170,7 +164,6 @@ int inet_aton(const char *start, in_addr *i)
        return p - start;
 }
 
-
 unsigned long strtoul(const char *p, const char **endp, int base)
 {
        unsigned long ret = 0;
@@ -185,140 +178,6 @@ unsigned long strtoul(const char *p, const char **endp, int base)
        
 }
 
-#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 */
-
-enum { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402,
-       Query_A20_Support = 0x2403 };
-
-#if defined(PCBIOS) && !defined(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 */
-
-#if defined(PCBIOS)
-/*
- * Gate A20 for high memory
- */
-void gateA20_set(void)
-{
-#warning "gateA20_set should test to see if it is already set"
-       if (int15(Enable_A20) == 0) {
-               return;
-       }
-#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 */
-}
-#endif
-
-
-int last_putchar; // From filo
-
-void
-putchar(int c)
-{
-       c &= 0xff;
-       last_putchar = c;
-
-       if (c == '\n')
-               putchar('\r');
-#ifdef CONSOLE_FIRMWARE
-       console_putc(c);
-#endif
-#ifdef CONSOLE_DIRECT_VGA
-       vga_putc(c);
-#endif
-#ifdef  CONSOLE_BTEXT
-        btext_putc(c);
-#endif
-#ifdef CONSOLE_SERIAL
-       serial_putc(c);
-#endif
-}
-
-/**************************************************************************
-GETCHAR - Read the next character from input device WITHOUT ECHO
-**************************************************************************/
-int getchar(void)
-{
-       int c = 256;
-
-       do {
-#if defined(PCBIOS) && defined(POWERSAVE)
-               /* Doze for a while (until the next interrupt).  This works
-                * fine, because the keyboard is interrupt-driven, and the
-                * timer interrupt (approx. every 50msec) takes care of the
-                * serial port, which is read by polling.  This reduces the
-                * power dissipation of a modern CPU considerably, and also
-                * makes Etherboot waiting for user interaction waste a lot
-                * less CPU time in a VMware session.  */
-               cpu_nap();
-#endif /* POWERSAVE */
-#ifdef CONSOLE_FIRMWARE
-               if (console_ischar())
-                       c = console_getc();
-#endif
-#ifdef CONSOLE_SERIAL
-               if (serial_ischar())
-                       c = serial_getc();
-#endif
-#ifdef CONSOLE_PC_KBD
-               if (kbd_ischar()) 
-                       c = kbd_getc();
-#endif
-       } while (c==256);
-       if (c == '\r')
-               c = '\n';
-       return c;
-}
-
-int iskey(void)
-{
-#ifdef CONSOLE_FIRMWARE
-       if (console_ischar())
-               return 1;
-#endif
-#ifdef CONSOLE_SERIAL
-       if (serial_ischar())
-               return 1;
-#endif
-#ifdef CONSOLE_PC_KBD
-        if (kbd_ischar())
-               return 1;
-#endif
-       return 0;
-}
 
 #if DEBUG_UTILS
 
index ae67b34da4000725c4f0a28b1933de58343cb062..f70aeacd443ba99ad3291668cbc7e70db955808c 100644 (file)
@@ -30,6 +30,22 @@ Modifications: Ken Yap (for Etherboot/16)
  */
 
 #include "etherboot.h"
+#include "memsizes.h"
+
+#ifdef KEEP_IT_REAL
+
+#warning "All download mechanisms are broken under KEEP_IT_REAL"
+
+os_download_t probe_image(unsigned char *data, unsigned int len) {
+       return 0;
+}
+
+int load_block(unsigned char *data, unsigned int block, unsigned int len, int eof) {
+       return 1;
+}
+
+#else /* KEEP_IT_REAL */
+
 
 struct os_entry_regs os_regs;
 
@@ -128,7 +144,7 @@ static void done(int do_cleanup)
         */
        if ( do_cleanup ) {
                cleanup();
-               arch_on_exit(0);
+               /* arch_on_exit(0); */
        }
 }
 
@@ -261,6 +277,7 @@ PROBE_IMAGE - Detect image file type
 os_download_t probe_image(unsigned char *data, unsigned int len)
 {
        os_download_t os_download = 0;
+
 #ifdef AOUT_IMAGE
        if (!os_download) os_download = aout_probe(data, len);
 #endif
@@ -286,6 +303,7 @@ os_download_t probe_image(unsigned char *data, unsigned int len)
 #ifdef RAW_IMAGE
        if (!os_download) os_download = raw_probe(data, len);
 #endif
+
        return os_download;
 }
 
@@ -363,3 +381,4 @@ int load_block(unsigned char *data, unsigned int block, unsigned int len, int eo
  * End:
  */
 
+#endif /* KEEP_IT_REAL */
index 9fe8292441780fb2f763b2613a67e4de2ae336b0..84a3c640c8fa5e3e5339c8bf9fcfd26967ede377 100644 (file)
@@ -9,8 +9,9 @@
  * 2004-04 moved by LYH From filo to Etherboot
  *             yhlu@tyan.com
  */
-#ifdef CONSOLE_PC_KBD
-#include "etherboot.h"
+
+#include "io.h"
+#include "console.h"
 
 static char key_map[][128] = {
     {
@@ -69,14 +70,14 @@ static int get_scancode(void)
     return scan;
 }
 
-int kbd_havekey(void)
+static int kbd_havekey(void)
 {
     if (!cur_scan)
        cur_scan = get_scancode();
     return cur_scan != 0;
 }
 
-int kbd_ischar(void)
+static int kbd_ischar(void)
 {
     if (!kbd_havekey())
        return 0;
@@ -87,7 +88,7 @@ int kbd_ischar(void)
     return 1;
 }
 
-int kbd_getc(void)
+static int kbd_getc(void)
 {
     int c;
 
@@ -105,4 +106,7 @@ int kbd_getc(void)
     cur_scan = 0;
     return c;
 }
-#endif
+
+static struct console_driver pc_kbd_console __console_driver = {
+       .getchar = kbd_getc,
+};
index 2a7cf2b876816c9a745042255bd6c50a3276a175..03a96de8e6b675b0759918a7ca6a2f5c655c48b8 100644 (file)
@@ -1,5 +1,3 @@
-#ifdef CONFIG_PCMCIA
-
 /*
  *     pcmcia.c
  *
  *     at some point. If there's anything obvious or better, not-so-obvious,
  *     please contact me by e-mail: anselm (AT) hoffmeister (DOT) be   *THANKS*
  */
-#include "../include/pcmcia.h"
-#include "../include/i82365.h"
+#include "pcmcia.h"
+#include "i82365.h"
 #define CODE_STATUS "alpha"
 #define        CODE_VERSION "0.1.3"
-
-#include "../include/pcmcia-opts.h"
-#include "../include/pcmcia.h"
+#include "pcmcia-opts.h"
+#include "console.h"
+#include "init.h"
 
 int    sockets; /* AHTODO: Phase this out! */
 u_int  pccsocks;
@@ -55,7 +53,7 @@ void  sleepticks(int numticks ) {
        return;
 }
 
-int    pcmcia_init_all(void) {
+static void pcmcia_init_all(void) {
        u_int i, j, k, l, m, n, ui, configs = 0;
        u_int multicard[8];
        u_char  *uc, upc;
@@ -253,17 +251,15 @@ int       pcmcia_init_all(void) {
                getchar();
        }
 
-       return 0;
 }
 
-int    pcmcia_shutdown_all(void) {
+static void    pcmcia_shutdown_all(void) {
        int i;
        //if ( PDEBUG > 2 ) {printf("<press key to continue>\n" ); getchar(); }
        for ( i = 0; i < pccsocks; ++i ) {
                driver[pccsock[i].drivernum].f(SHUTDOWN,pccsock[i].internalid,0,0,0);
        }
        printf("Shutdown of PCMCIA subsystem completed");
-       return 0;
 }
 
-#endif /* CONFIG_PCMCIA */
+INIT_FN ( INIT_PCMCIA, pcmcia_init_all, NULL, pcmcia_shutdown_all );
index 0199de287de207565f477c5f41c7a8079ab67214..b2ecee192147379a875f0766ac7c9085b3af2392 100644 (file)
@@ -1230,17 +1230,11 @@ PXENV_EXIT_t pxenv_undi_loader ( undi_loader_t *loader ) {
         * this, but it's currently split interestingly between main()
         * and main_loop()...
         */
-       console_init();
-       cpu_setup();
-       setup_timers();
-       gateA20_set();
        print_config();
        get_memsizes();
        cleanup();
        relocate();
        cleanup();
-       console_init();
-       init_heap();
 
        /* We have relocated; the loader pointer is now invalid */
        loader = phys_to_virt ( loader_phys );
index d20846a88b4751affe7f52807591c6a84ef77060..436432e5cc0fbb2571aebb11e4ea5e14fb3d7137 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef        NORELOCATE
 
 #include "etherboot.h"
+#include "memsizes.h"
 
 /* by Eric Biederman */
 
@@ -93,10 +94,10 @@ void relocate(void)
                printf("Relocating _text from: [%lx,%lx) to [%lx,%lx)\n",
                        old_addr, virt_to_phys(_end),
                        addr, eaddr);
-               arch_relocate_to(addr);
+               /* arch_relocate_to ( addr ) */
                cleanup();
                relocate_to(addr);
-               arch_relocated_from(old_addr);
+               /* arch_relocated_from ( addr ) */
        }
 }
 
index 72207e8d06901ac6aebfbe02e556dbfceee68c7f..2c18786014455f3296c3a801d40c25c58ad5fd72 100644 (file)
@@ -1,7 +1,3 @@
-#include "etherboot.h"
-#include "timer.h"
-#ifdef CONSOLE_SERIAL
-
 /*
  * The serial port interface routines implement a simple polled i/o
  * interface to a standard serial port.  Due to the space restrictions
  * parity, 1 stop bit (8N1).  This can be changed in init_serial().
  */
 
-static int found = 0;
+#include "stddef.h"
+#include "console.h"
+#include "init.h"
+#include "io.h"
+#include "timer.h"
+
+/* Set default values if none specified */
 
-#if defined(COMCONSOLE)
-#undef UART_BASE
-#define UART_BASE COMCONSOLE
+#ifndef COMCONSOLE
+#define COMCONSOLE ( 0x3f8 )
 #endif
 
-#ifndef UART_BASE
-#error UART_BASE not defined
+#ifndef CONSPEED
+#define CONSPEED ( 9600 )
 #endif
 
-#if defined(CONSPEED)
+#undef UART_BASE
+#define UART_BASE COMCONSOLE
+
 #undef UART_BAUD
 #define UART_BAUD CONSPEED
-#endif
-
-#ifndef UART_BAUD
-#define UART_BAUD 115200
-#endif
 
 #if ((115200%UART_BAUD) != 0)
 #error Bad ttys0 baud rate
@@ -83,18 +81,15 @@ static int found = 0;
 #define uart_writeb(val,addr) outb((val),(addr))
 #endif
 
+static struct console_driver serial_console;
+
 /*
  * void serial_putc(int ch);
  *     Write character `ch' to port UART_BASE.
  */
-void serial_putc(int ch)
-{
+static void serial_putc ( int ch ) {
        int i;
        int status;
-       if (!found) {
-               /* no serial interface */
-               return;
-       }
        i = 1000; /* timeout */
        while(--i > 0) {
                status = uart_readb(UART_BASE + UART_LSR);
@@ -111,8 +106,7 @@ void serial_putc(int ch)
  * int serial_getc(void);
  *     Read a character from port UART_BASE.
  */
-int serial_getc(void)
-{
+static int serial_getc ( void ) {
        int status;
        int ch;
        do {
@@ -131,11 +125,8 @@ int serial_getc(void)
  *       If there is a character in the input buffer of port UART_BASE,
  *       return nonzero; otherwise return 0.
  */
-int serial_ischar(void)
-{
+static int serial_ischar ( void ) {
        int status;
-       if (!found)
-               return 0;
        status = uart_readb(UART_BASE + UART_LSR);      /* line status reg; */
        return status & 1;              /* rx char available */
 }
@@ -144,15 +135,10 @@ int serial_ischar(void)
  * int serial_init(void);
  *     Initialize port UART_BASE to speed CONSPEED, line settings 8N1.
  */
-int serial_init(void)
-{
-       int initialized = 0;
+static void serial_init ( void ) {
        int status;
        int divisor, lcs;
 
-       if (found)
-               return 1;
-
        divisor = COMBRD;
        lcs = UART_LCS;
 
@@ -207,10 +193,9 @@ int serial_init(void)
                /* line status reg */
                status = uart_readb(UART_BASE + UART_LSR);
        } while(status & UART_LSR_DR);
-       initialized = 1;
+       serial_console.disabled = 0;
  out:
-       found = initialized;
-       return initialized;
+       return;
 }
 
 /*
@@ -218,10 +203,9 @@ int serial_init(void)
  *     Cleanup our use of the serial port, in particular flush the
  *     output buffer so we don't accidentially loose characters.
  */
-void serial_fini(void)
-{
+static void serial_fini ( void ) {
        int i, status;
-       if (!found) {
+       if (serial_console.disabled) {
                /* no serial interface */
                return;
        }
@@ -232,5 +216,15 @@ void serial_fini(void)
        do {
                status = uart_readb(UART_BASE + UART_LSR);
        } while((--i > 0) && !(status & UART_LSR_TEMPT));
+       /* Don't mark it as disabled; it's still usable */
 }
-#endif
+
+static struct console_driver serial_console __console_driver = {
+       .putchar = serial_putc,
+       .getchar = serial_getc,
+       .iskey = serial_ischar,
+       .disabled = 1,
+};
+
+INIT_FN ( INIT_CONSOLE, serial_init, NULL, serial_fini );
+
index be0fa310a37dddc6a0283d06311061e66a846e28..d7e62acacf33b96f081358d04bbfad384797cda8 100644 (file)
@@ -759,7 +759,8 @@ static int ide_pci_probe(struct dev *dev, struct pci_device *pci)
 }
 #define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b
 static struct pci_id ide_controllers[] = {
-{ PCI_VENDOR_ID_INTEL,       PCI_DEVICE_ID_INTEL_82801CA_11,    "PIIX4" },
+       PCI_ROM(0x0000, 0x0000, "ide_disk", "Generic IDE disk support"),
+/* { PCI_VENDOR_ID_INTEL,       PCI_DEVICE_ID_INTEL_82801CA_11,    "PIIX4" },*/
 #if 0  /* Currently I don't need any entries in this table so ignore it */
 { PCI_VENDOR_ID_INTEL,       PCI_DEVICE_ID_INTEL_82371FB_0,     "PIIX" },
 { PCI_VENDOR_ID_INTEL,       PCI_DEVICE_ID_INTEL_82371FB_1,     "PIIX" },
index 0a7187ed6f3bbf89edd501809bf9b4f5898fe7d2..6375e8c7c8aa872416e63f20a9bbe33723bf7a65 100644 (file)
@@ -653,6 +653,7 @@ static struct isa_driver t509_driver __isa_driver = {
        .probe   = t509_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("3c509","3c509, ISA/EISA");
 #endif
 
 #ifdef INCLUDE_3C529
@@ -662,6 +663,7 @@ static struct isa_driver t529_driver __isa_driver = {
        .probe   = t529_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("3c529","3c529 == MCA 3c509");
 #endif
 
 /*
index f185acefe10f9d8819d81538715f698a5f819301..7c21b45e700930fd016daa750ac037c278a8f7ff 100644 (file)
@@ -812,3 +812,4 @@ static struct isa_driver t515_driver __isa_driver = {
        .probe = t515_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("3c515","3c515, Fast EtherLink ISA");
index 42de1f2a3db972fe4c2eebd1d3db25578c2776e9..f418dc1bdc033823522b650d80c93a98b5a4023a 100644 (file)
@@ -711,6 +711,7 @@ static struct isa_driver cs89x0_driver __isa_driver = {
        .probe   = cs89x0_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("cs89x0","Crystal Semiconductor CS89x0");
 
 /*
  * Local variables:
index 29266b105a0471aed54ed8af6219c29026fdd797..ca456803bd5ae2907c9dc4ebeee1fdb9c5b13698 100644 (file)
@@ -792,3 +792,4 @@ static struct isa_driver depca_driver __isa_driver = {
        .probe   = depca_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("depca","Digital DE100 and DE200");
index b27c9f7f0dff786d9d1c15c9322b6fd963780767..a191a163f6edc0d1df463d93529e81842f925c86 100644 (file)
@@ -623,3 +623,4 @@ static struct isa_driver eepro_driver __isa_driver = {
        .probe   = eepro_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("eepro","Intel Etherexpress Pro/10");
index 16b41f8b3258219b74e1782e2f4e05193f6808f8..34f6f50d6645720a4394008ff7bb5df1d629c1c1 100755 (executable)
@@ -370,25 +370,6 @@ struct ring_desc {
 };
 #endif
 
-/* Define the TX Descriptor */
-static struct ring_desc tx_ring[NR_TX_DESC]
-    __attribute__ ((aligned(8)));
-
-/* Create a static buffer of size REAL_RX_BUF_SIZE for each
-TX Descriptor.  All descriptors point to a
-part of this buffer */
-static unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE];
-
-/* Define the TX Descriptor */
-static struct ring_desc rx_ring[NR_RX_DESC]
-    __attribute__ ((aligned(8)));
-
-/* Create a static buffer of size REAL_RX_BUF_SIZE for each
-RX Descriptor   All descriptors point to a
-part of this buffer */
-static unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE]
-    __attribute__ ((aligned(8)));
-
 /* Private Storage for the NIC */
 struct ns83820_private {
        u8 *base;
@@ -412,6 +393,25 @@ struct ns83820_private {
 } nsx;
 static struct ns83820_private *ns;
 
+/* Define the TX Descriptor */
+static struct ring_desc tx_ring[NR_TX_DESC]
+    __attribute__ ((aligned(8)));
+
+/* Create a static buffer of size REAL_RX_BUF_SIZE for each
+TX Descriptor.  All descriptors point to a
+part of this buffer */
+static unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE];
+
+/* Define the TX Descriptor */
+static struct ring_desc rx_ring[NR_RX_DESC]
+    __attribute__ ((aligned(8)));
+
+/* Create a static buffer of size REAL_RX_BUF_SIZE for each
+RX Descriptor   All descriptors point to a
+part of this buffer */
+static unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE]
+    __attribute__ ((aligned(8)));
+
 static void phy_intr(struct nic *nic __unused)
 {
        static char *speeds[] =
index dddc0819815c08efdad24589b6febacf982f53d4..5a18c8e6afc553b74b790dde91b38edba4e33482 100644 (file)
@@ -961,6 +961,7 @@ static struct isa_driver wd_driver __isa_driver = {
        .probe   = wd_probe,
        .ioaddrs = 0, 
 };
+ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
 #endif
 
 #ifdef INCLUDE_3C503
@@ -970,6 +971,7 @@ static struct isa_driver t503_driver __isa_driver = {
        .probe   = t503_probe,
        .ioaddrs = 0, 
 };
+ISA_ROM("3c503","3Com503, Etherlink II[/16]");
 #endif
 
 #ifdef INCLUDE_NE
@@ -979,6 +981,7 @@ static struct isa_driver ne_driver __isa_driver = {
        .probe   = ne_probe,
        .ioaddrs = 0, 
 };
+ISA_ROM("ne","NE1000/2000 and clones");
 #endif
 
 #ifdef INCLUDE_NS8390
@@ -1013,4 +1016,3 @@ static struct pci_driver nepci_driver __pci_driver = {
  *  c-basic-offset: 8
  * End:
  */
-
index be2b06ccd0c69c9ce84b08bea6673ee822c73326..4aafb4ff249a11e2d020d511a189a58dd6aeb8e9 100644 (file)
@@ -18,7 +18,9 @@ $Id$
 #include "prism2.c"
 
 static struct pci_id prism2_pci_nics[] = {
-PCI_ROM(0x1260, 0x3873, "prism2_pci", "Harris Semiconductor Prism2.5 clone"),  /* Generic Prism2.5 PCI device */
+PCI_ROM(0x1260, 0x3873, "prism2_pci",  "Harris Semiconductor Prism2.5 clone"),
+PCI_ROM(0x1260, 0x3873, "hwp01170",    "ActionTec HWP01170"),
+PCI_ROM(0x1260, 0x3873, "dwl520",      "DLink DWL-520"),
 };
 
 static struct pci_driver prism2_pci_driver __pci_driver = {
index 6591c020c0e1ea387f132b738ba8b986f288a9c8..f65118d7af1fa9867ff10477f8e8d558871af9de 100644 (file)
@@ -1187,3 +1187,4 @@ static struct isa_driver SK_driver __isa_driver = {
        .probe   = SK_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("sk_g16","Schneider and Koch G16");
index a05521e8c84fe1d505037203bfc7ea4200c1d3a3..6a935e35028d9c7e9f4b7c1a719e5fd274814f66 100644 (file)
@@ -542,3 +542,4 @@ static struct isa_driver smc9000_driver __isa_driver = {
        .probe   = smc9000_probe,
        .ioaddrs = 0,
 };
+ISA_ROM("smc9000","SMC9000");
diff --git a/src/genrules.pl b/src/genrules.pl
deleted file mode 100755 (executable)
index 0a129c8..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-#!/usr/bin/perl -w
-#
-#      Helper program to generate Makefile rules into file Rom from table in
-#      file NIC
-#
-#      GPL, Ken Yap 2001, with major contributions by Klaus Espenlaub
-#      Revised 2002
-#
-
-use strict;
-
-use bytes;
-
-use File::Basename;
-
-use vars qw($familyfile $nic @families $curfam %drivers %pcient %isaent %isalist %buildent $arch @srcs);
-
-sub __gendep ($$$)
-{
-       my ($file, $deps, $driver_dep) = @_;
-       foreach my $source (@$deps) {
-               my $inc;
-               my @collect_dep = ();
-               $inc = "arch/$arch/include/$source" unless ! -e "arch/$arch/include/$source";
-               $inc = "include/$source" unless ! -e "include/$source";
-               $inc = dirname($file) . "/$source" unless ! -e dirname($file) . "/$source";
-               unless (defined($inc)) {
-                       print STDERR "$source from $file not found (shouldn't happen)\n";
-                       next;
-               };
-               next if (exists ${$driver_dep}{$inc});
-               ${$driver_dep}{$inc} = $inc;
-# Warn about failure to open, then skip, rather than soldiering on with the read
-               unless (open(INFILE, "$inc")) {
-                       print STDERR "$inc: $! (shouldn't happen)\n";
-                       next;
-               };
-               while (<INFILE>) {
-                       chomp($_);
-# This code is not very smart: no C comments or CPP conditionals processing is
-# done.  This may cause unexpected (or incorrect) additional dependencies.
-# However, ignoring the CPP conditionals is in some sense correct: we need to
-# figure out a superset of all the headers for the driver source.  
-                       next unless (s/^\s*#include\s*"([^"]*)".*$/$1/);
-# Ignore system includes, like the ones in osdep.h
-                       next if ($_ =~ m:^/:);
-# Ignore "special" includes, like .buildserial.h
-                       next if /^\./;
-                       push(@collect_dep, $_);
-               }
-               close(INFILE);
-               if (@collect_dep) {
-                       &__gendep($inc, \@collect_dep, $driver_dep);
-               }
-       }
-}
-
-sub gendep ($) {
-       my ($driver) = @_;
-
-       # Automatically generate the dependencies for the driver sources.
-       my %driver_dep = ();
-       __gendep( "", [ $driver ], \%driver_dep);
-       return sort values %driver_dep
-}
-
-# Make sure that every rom name exists only once.
-# make will warn if it finds duplicate rules, but it is better to stop
-sub checkduplicate (\%$$) {
-       my ($anyent, $curfam, $romname) = @_;
-       foreach my $family (@families) {
-               if (exists($$anyent{$family})) {
-                       my $aref = $$anyent{$family};
-                       foreach my $entry (@$aref) {
-                               if ($entry->[0] eq $romname) {
-                                       print STDERR "\nROM name $romname defined twice. Please correct.\n";
-                                       exit 1;
-                               }
-                       }
-               }
-       }
-}
-
-sub genroms($) {
-       my ($driver) = @_;
-       
-       # Automatically discover the ROMS this driver can produce.
-       unless (open(INFILE, "$driver")) {
-               print STDERR "$driver: %! (shouldn't happen)\n";
-               next;
-       };
-       while (<INFILE>) {
-               chomp($_);
-               if ($_ =~ m/^\s*PCI_ROM\(\s*0x([0-9A-Fa-f]*)\s*,\s*0x([0-9A-Fa-f]*)\s*,\s*"([^"]*)"\s*,\s*"([^"]*)"\)/) {
-
-                       # We store a list of PCI IDs and comments for each PC target
-                       my ($vendor_id, $device_id, $rom, $comment) = (hex($1), hex($2), $3, $4);
-                       my $ids = sprintf("0x%04x,0x%04x", $vendor_id, $device_id);
-                       checkduplicate(%pcient, $curfam, $rom);
-                       push(@{$pcient{$curfam}}, [$rom, $ids, $comment]);
-               }
-               elsif($_ =~ m/^\s*ISA_ROM\(\s*"([^"]*)"\s*,\s*"([^"]*)"\)/) {
-                       my ($rom, $comment) = ($1, $2);
-                       # We store the base driver file for each ISA target
-                       $isalist{$rom} = $curfam;
-                       $buildent{$rom} = 1;
-                       checkduplicate(%isaent, $curfam, $rom);
-                       push(@{$isaent{$curfam}}, [$rom, $comment]);
-               }
-               elsif($_ =~ m/^\s*PCI_ROM/ or $_ =~ m/^\s*ISA_ROM/) {
-                       # Complain since we cannot parse this. Of course it would be nicer if we could parse...
-                       print STDERR "\nFound incomplete PCI_ROM or ISA_ROM macro in file $driver.\n";
-                       print STDERR "ROM macros spanning more than one line are not supported,\n";
-                       print STDERR "please adjust $driver accordingly.\n\n\n";
-                       exit 1;
-               }
-       }
-}
-
-sub addfam ($) {
-       my ($family) = @_;
-
-       push(@families, $family);
-       # We store the list of dependencies in the hash for each family
-       my @deps = &gendep("$family.c");
-       $drivers{$family} = join(' ', @deps);
-       $pcient{$family} = [];
-       genroms("$family.c");
-}
-
-sub addrom ($) {
-       my ($rom, $ids, $comment) = split(' ', $_[0], 3);
-
-       # defaults if missing
-       $ids = '-' unless ($ids);
-       $comment = $rom unless ($comment);
-       if ($ids ne '-') {
-               # We store a list of PCI IDs and comments for each PCI target
-               checkduplicate(%pcient, $curfam, $rom);
-               push(@{$pcient{$curfam}}, [$rom, $ids, $comment]);
-       } else {
-               # We store the base driver file for each ISA target
-               $isalist{$rom} = $curfam;
-               $buildent{$rom} = 1;
-               checkduplicate(%isaent, $curfam, $rom);
-               push(@{$isaent{$curfam}}, [$rom, $comment]);
-       }
-}
-
-# Return true if this driver is ISA only
-sub isaonly ($) {
-       my $aref = $pcient{$_[0]};
-
-       return ($#$aref < 0);
-}
-
-$#ARGV >= 1 or die "Usage: $0 Families bin/NIC arch sources...\n";
-$familyfile = shift(@ARGV);
-$nic  = shift(@ARGV);
-$arch = shift(@ARGV);
-@srcs = @ARGV;
-open FAM, "<$familyfile" or die "Could not open $familyfile: $!\n";
-
-$curfam = '';
-while ( <FAM> ) {
-       chomp($_);
-       next if (/^\s*(#.*)?$/);
-       my ($keyword) = split(' ', $_ , 2);
-       if ($keyword eq 'family') {
-               my ($keyword, $driver) = split(' ', $_, 2);
-               $curfam = '';
-               if (! -e "$driver.c") {
-                       print STDERR "Driver file $driver.c not found, skipping...\n";
-                       next;
-               }
-               if ($driver =~ "^arch" && $driver !~ "^arch/$arch") {
-# This warning just makes noise for most compilations.
-#                      print STDERR "Driver file $driver.c not for arch $arch, skipping...\n";
-                       next;
-               }
-               &addfam($curfam = $driver);
-       } else {
-               # skip until we have a valid family
-               next if ($curfam eq '');
-               &addrom($_);
-       }
-}
-close FAM;
-
-open(N,">$nic") or die "$nic: $!\n";
-print N <<EOF;
-# This is an automatically generated file, do not edit
-# It does not affect anything in the build, it's only for rom-o-matic
-
-EOF
-foreach my $family (@families) {
-       print N "family\t$family\n";
-       if (exists($pcient{$family})) {
-               my $aref = $pcient{$family};
-               foreach my $entry (@$aref) {
-                       my $rom = $entry->[0];
-                       my $ids = $entry->[1];
-                       my $comment = $entry->[2];
-                       print N "$rom\t$ids\t$comment\n";
-               }
-       }
-       if (exists($isaent{$family})) {
-               my $aref = $isaent{$family};
-               foreach my $entry (@$aref) {
-                       my $rom = $entry->[0];
-                       my $comment = $entry->[1];
-                       print N "$rom\t-\t$comment\n";
-               }
-       }
-       print N "\n";
-}
-close(N);
-
-# Generate the normal source dependencies
-print "# Core object file dependencies\n";
-foreach my $source (@srcs) {
-       next if ($source !~ '[.][cS]$');
-       my @deps = &gendep($source);
-       my $obj = $source;
-       $obj =~ s/^.*?([^\/]+)\.[cS]/bin\/$1.o/;
-       foreach my $dep (@deps) {
-               print "$obj: $dep\n";
-       }
-       print("\n");
-}
-
-# Generate the assignments to DOBJS and BINS
-print "# Driver object files and ROM image files\n";
-print "DOBJS\t:=\n";
-print "PCIOBJS\t:=\n";
-
-print "# Target formats\n";
-print "EB_ISOS\t:=\n";
-print "EB_LISOS\t:=\n";
-print "EB_COMS\t:=\n";
-print "EB_EXES\t:=\n";
-print "EB_LILOS\t:=\n";
-print "EB_ZLILOS\t:=\n";
-print "EB_PXES\t:=\n";
-print "EB_ZPXES\t:=\n";
-print "EB_DSKS\t:=\n";
-print "EB_ZDSKS\t:=\n";
-print "EB_ELFS\t:=\n";
-print "EB_ZELFS\t:=\n";
-print "EB_LMELFS\t:=\n";
-print "EB_ZLMELFS\t:=\n";
-print "EB_ELFDS\t:=\n";
-print "EB_ZELFDS\t:=\n";
-print "EB_LMELFDS\t:=\n";
-print "EB_ZLMELFDS\t:=\n";
-
-foreach my $pci (sort keys %pcient) {
-       my $img = basename($pci);
-
-       print "DOBJS\t+= \$(BIN)/$img.o\n";
-       print "PCIOBJS\t+= \$(BIN)/$img.o\n" unless isaonly($pci);
-
-# Output targets
-       print "EB_LILOS\t+= \$(BIN)/$img.lilo \nEB_ZLILOS\t+= \$(BIN)/$img.zlilo\n";
-       print "EB_PXES\t+= \$(BIN)/$img.pxe   \nEB_ZPXES\t+= \$(BIN)/$img.zpxe\n";
-       print "EB_DSKS\t+= \$(BIN)/$img.dsk   \nEB_ZDSKS\t+= \$(BIN)/$img.zdsk\n";
-       print "EB_ELFS\t+= \$(BIN)/$img.elf   \nEB_ZELFS\t+= \$(BIN)/$img.zelf\n";
-       print "EB_LMELFS\t+= \$(BIN)/$img.lmelf \nEB_ZLMELFS\t+= \$(BIN)/$img.zlmelf\n";
-       print "EB_ELFDS\t+= \$(BIN)/$img.elfd   \nEB_ZELFDS\t+= \$(BIN)/$img.zelfd\n";
-       print "EB_LMELFDS\t+= \$(BIN)/$img.lmelfd \nEB_ZLMELFDS\t+= \$(BIN)/$img.zlmelfd\n";
-       print "EB_BIMAGES\t+= \$(BIN)/$img.bImage \nEB_BZIMAGES\t+= \$(BIN)/$img.bzImage\n";
-       print "EB_ISOS\t+= \$(BIN)/$img.iso\n";
-       print "EB_LISOS\t+= \$(BIN)/$img.liso\n";
-       print "EB_COMS\t+= \$(BIN)/$img.com\n";
-       print "EB_EXES\t+= \$(BIN)/$img.exe\n";
-}
-
-foreach my $img (sort keys %buildent) {
-
-       print "DOBJS\t+= \$(BIN)/$img.o\n";
-
-# Output targets
-       print "EB_LILOS\t+= \$(BIN)/$img.lilo \nEB_ZLILOS\t+= \$(BIN)/$img.zlilo\n";
-       print "EB_PXES\t+= \$(BIN)/$img.pxe   \nEB_ZPXES\t+= \$(BIN)/$img.zpxe\n";
-       print "EB_DSKS\t+= \$(BIN)/$img.dsk   \nEB_ZDSKS\t+= \$(BIN)/$img.zdsk\n";
-       print "EB_ELFS\t+= \$(BIN)/$img.elf   \nEB_ZELFS\t+= \$(BIN)/$img.zelf\n";
-       print "EB_LMELFS\t+= \$(BIN)/$img.lmelf \nEB_ZLMELFS\t+= \$(BIN)/$img.zlmelf\n";
-       print "EB_ELFDS\t+= \$(BIN)/$img.elfd   \nEB_ZELFDS\t+= \$(BIN)/$img.zelfd\n";
-       print "EB_LMELFDS\t+= \$(BIN)/$img.lmelfd \nEB_ZLMELFDS\t+= \$(BIN)/$img.zlmelfd\n";
-       print "EB_BIMAGES\t+= \$(BIN)/$img.bImage \nEB_BZIMAGE\t+= \$(BIN)/$img.bzImage\n";
-       print "EB_ISOS\t+= \$(BIN)/$img.iso\n";
-       print "EB_LISOS\t+= \$(BIN)/$img.liso\n";
-       print "EB_COMS\t+= \$(BIN)/$img.com\n";
-       print "EB_EXES\t+= \$(BIN)/$img.exe\n";
-}
-
-print "ROMS\t:=\n";
-foreach my $family (sort keys %pcient) {
-       my $aref = $pcient{$family};
-       foreach my $entry (@$aref) {
-               my $rom = $entry->[0];
-               print "ROMS\t+= \$(BIN)/$rom.rom \$(BIN)/$rom.zrom\n";
-       }
-}
-foreach my $isa (sort keys %isalist) {
-       print "ROMS\t+= \$(BIN)/$isa.rom \$(BIN)/$isa.zrom\n";
-}
-
-# Generate the *.o rules
-print "\n# Rules to build the driver object files\n";
-foreach my $pci (sort keys %drivers) {
-       # For ISA the rule for .o will generated later
-       next if isaonly($pci);
-       # PCI drivers are compiled only once for all ROMs
-       (my $macro = basename($pci)) =~ tr/\-/_/;
-       my $obj = basename($pci);
-       my $deps = $drivers{$pci};
-       print <<EOF;
-
-\$(BIN)/$obj.o:        $pci.c \$(MAKEDEPS) $deps
-       \$(CC) \$(CFLAGS) \$(\U$macro\EFLAGS) -o \$@ -c \$<
-
-\$(BIN)/$obj--%.o:     \$(BIN)/%.o \$(BIN)/$obj.o \$(MAKEDEPS)
-       \$(LD) -r \$(BIN)/$obj.o \$< -o \$@
-
-EOF
-}
-
-# Do the ISA entries
-foreach my $isa (sort keys %isalist) {
-       (my $macro = $isa) =~ tr/\-/_/;
-       my $base = $isalist{$isa};
-       my $deps = $drivers{$base};
-       print <<EOF;
-\$(BIN)/$isa.o:        $base.c \$(MAKEDEPS) $deps
-       \$(CC) \$(CFLAGS) \$(\U$macro\EFLAGS) -o \$@ -c \$<
-
-\$(BIN)/$isa--%.o:     \$(BIN)/%.o \$(BIN)/$isa.o \$(MAKEDEPS)
-       \$(LD) -r \$(BIN)/$isa.o \$< -o \$@ 
-EOF
-}
-
-# Generate the Rom rules
-print "# Rules to build the ROM files\n";
-foreach my $family (sort keys %pcient) {
-       next if isaonly($family);
-       my $img = basename($family);
-       print <<EOF;
-ROMTYPE_$img = PCI
-EOF
-       my $aref = $pcient{$family};
-       foreach my $entry (@$aref) {
-               my ($rom, $ids, $comment) = @$entry;
-               next if ($ids eq '-');
-               print <<EOF;
-ROMTYPE_$rom = PCI
-MAKEROM_ID_$rom = -p $ids
-
-EOF
-               next if($rom eq $img);
-               print <<EOF;
-\$(BIN)/$rom\%rom: \$(BIN)/$img\%rom
-       cat \$< > \$@
-       \$(MAKEROM) \$(MAKEROM_FLAGS) \$(MAKEROM_\$(ROMCARD)) \$(MAKEROM_ID_\$(ROMCARD)) -i\$(IDENT) \$@
-
-EOF
-       }
-}
-
-# ISA ROMs are prepared from the matching code images
-# Think this can probably be removed, but not sure
-foreach my $isa (sort keys %isalist) {
-       print <<EOF;
-EOF
-}
-
index 15241cd39cade4bb7d8651b05cbea225d2611cab..1d3f9e59b36498b4b8c161bbf6e8307360e1bbaf 100644 (file)
@@ -32,7 +32,7 @@ typedef struct boot_infos
     /* Some infos about the current MacOS display */
     u32       dispDeviceRect[4];       /* left,top,right,bottom */
     u32       dispDeviceDepth;         /* (8, 16 or 32) */
-    u8*       dispDeviceBase;          /* base address (physical) */
+    u32       dispDeviceBase;          /* base address (physical) */
     u32       dispDeviceRowBytes;      /* rowbytes (in bytes) */
     u32       dispDeviceColorsOffset;  /* Colormap (8 bits only) or 0 (*) */
 
@@ -56,21 +56,7 @@ typedef struct boot_infos
  * Benjamin Herrenschmidt <benh@kernel.crashing.org>
  */
 
-extern void btext_clearscreen(void);
-
 extern boot_infos_t disp_bi;
 extern u32 boot_text_mapped;
 
-void btext_setup_display(u32 width, u32 height, u32 depth, u32 pitch,
-                        unsigned long address);
-void map_boot_text(void);
-
-void btext_drawchar(char c);
-void btext_drawstring(const char *str);
-void btext_drawhex(u32 v);
-
-void btext_putc(int c);
-
-void btext_init(void);
-
 #endif /* _BTEXT_H */
diff --git a/src/include/compiler.h b/src/include/compiler.h
new file mode 100644 (file)
index 0000000..401d4e4
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef COMPILER_H
+#define COMPILER_H
+
+/* We export the symbol obj_OBJECT (OBJECT is defined on command-line)
+ * as a global symbol, so that the linker can drag in selected object
+ * files from the library using -u obj_OBJECT.
+ *
+ * Not quite sure why cpp requires two levels of macro call in order
+ * to actually expand OBJECT...
+ */
+#undef _H1
+#define _H1( x, y ) x ## y
+#undef _H2
+#define _H2( x, y ) _H1 ( x, y )
+#define OBJECT_SYMBOL _H2 ( obj_, OBJECT )
+#undef _STR
+#define _STR(s) #s
+#undef _XSTR
+#define _XSTR(s) _STR(s)
+#define OBJECT_SYMBOL_STR _XSTR ( OBJECT_SYMBOL )
+
+#ifdef ASSEMBLY
+
+       .globl  OBJECT_SYMBOL
+       .equ    OBJECT_SYMBOL, 0
+
+#else /* ASSEMBLY */
+
+__asm__ ( ".globl\t" OBJECT_SYMBOL_STR );
+__asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" );
+
+#define REQUIRE_OBJECT(object) \
+       __asm__ ( ".equ\tneed_" #object ", obj_" #object );
+
+#define PACKED __attribute__((packed))
+#define __unused __attribute__((unused))
+#define __used __attribute__((used))
+
+#endif /* ASSEMBLY */
+
+#endif /* COMPILER_H */
diff --git a/src/include/console.h b/src/include/console.h
new file mode 100644 (file)
index 0000000..ce2e539
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef CONSOLE_H
+#define CONSOLE_H
+
+#include "stdint.h"
+
+/*
+ * Consoles that cannot be used before their INIT_FN() has completed
+ * should set disabled = 1 initially.  This allows other console
+ * devices to still be used to print out early debugging messages.
+ */
+
+struct console_driver {
+       int disabled;
+       void ( *putchar ) ( int character );
+       int ( *getchar ) ( void );
+       int ( *iskey ) ( void );
+};
+
+#define __console_driver \
+       __attribute__ (( used, __section__ ( ".drivers.console" ) ))
+
+/* Function prototypes */
+
+extern void putchar ( int character );
+extern int getchar ( void );
+extern int iskey ( void );
+
+#endif /* CONSOLE_H */
index 44ada53897b746e1ea353c752ea9457af13624a1..f4a4f12659f2bd4122ff486b4b16ee2ea4ac94e1 100644 (file)
 #define DEFAULT_BOOTFILE       PXENFSROOTPATH "/boot/pxeboot"
 #endif
 
-/* Clean up console settings... mainly CONSOLE_FIRMWARE and CONSOLE_SERIAL are used
- * in the sources (except start.S and serial.S which cannot include
- * etherboot.h).  At least one of the CONSOLE_xxx has to be set, and
- * CONSOLE_DUAL sets both CONSOLE_CRT and CONSOLE_SERIAL.  If none is set,
- * CONSOLE_CRT is assumed.  */
-#ifdef CONSOLE_CRT
-#define CONSOLE_FIRMWARE
-#endif
-#ifdef CONSOLE_DUAL
-#undef CONSOLE_FIRMWARE
-#define CONSOLE_FIRMWARE
-#undef CONSOLE_SERIAL
-#define CONSOLE_SERIAL
-#endif
-#if    defined(CONSOLE_FIRMWARE) && defined(CONSOLE_SERIAL)
-#undef CONSOLE_DUAL
-#define CONSOLE_DUAL
-#endif
-#if    !defined(CONSOLE_FIRMWARE) && !defined(CONSOLE_SERIAL)
-#define CONSOLE_FIRMWARE
-#endif
-
 #if    !defined(DOWNLOAD_PROTO_TFTP) && !defined(DOWNLOAD_PROTO_NFS) && !defined(DOWNLOAD_PROTO_SLAM) && !defined(DOWNLOAD_PROTO_TFTM) && !defined(DOWNLOAD_PROTO_DISK) && !defined(DOWNLOAD_PROTO_HTTP)
 #error No download protocol defined!
 #endif
@@ -204,7 +182,7 @@ External prototypes
 struct Elf_Bhdr;
 extern int in_call(in_call_data_t *data, uint32_t opcode, va_list params);
 extern void console_init(void); 
-extern int main(in_call_data_t *data, va_list params);
+extern int main();
 extern int loadkernel P((const char *fname));
 extern char as_main_program;
 /* nic.c */
@@ -287,26 +265,6 @@ extern unsigned long strtoul P((const char *p, const char **, int base));
 extern void printf P((const char *, ...));
 extern int sprintf P((char *, const char *, ...));
 extern int inet_aton P((const char *p, in_addr *i));
-#ifdef PCBIOS
-extern void gateA20_set P((void));
-#define gateA20_unset()
-#else
-#define gateA20_set()
-#define gateA20_unset()
-#endif
-extern void putchar P((int));
-extern int getchar P((void));
-extern int iskey P((void));
-
-/* pcbios.S */
-extern int console_getc P((void));
-extern void console_putc P((int));
-extern int console_ischar P((void));
-extern int getshift P((void));
-extern int int15 P((int));
-#ifdef POWERSAVE
-extern void cpu_nap P((void));
-#endif /* POWERSAVE */
 
 /* basemem.c */
 extern uint32_t get_free_base_memory ( void );
@@ -318,26 +276,6 @@ extern void free_unused_base_memory ( void );
 extern void forget_prefix_base_memory ( void );
 extern void forget_runtime_base_memory ( uint32_t old_addr );
 
-struct e820entry {
-       uint64_t addr;
-       uint64_t size;
-       uint32_t type;
-#define E820_RAM       1
-#define E820_RESERVED  2
-#define E820_ACPI      3 /* usable as RAM once ACPI tables have been read */
-#define E820_NVS       4
-} PACKED;
-#define E820ENTRY_SIZE 20
-#define E820MAX 32
-struct meminfo {
-       uint16_t basememsize;
-       uint16_t pad;
-       uint32_t memsize;
-       uint32_t map_count;
-       struct e820entry map[E820MAX];
-} PACKED;
-extern struct meminfo meminfo;
-extern void get_memsizes(void);
 extern unsigned long get_boot_order(unsigned long order, unsigned *index);
 #ifndef NORELOCATE
 extern void relocate(void);
diff --git a/src/include/init.h b/src/include/init.h
new file mode 100644 (file)
index 0000000..9ec9ded
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef INIT_H
+#define INIT_H
+
+/*
+ * In order to avoid having objects dragged in just because main()
+ * calls their initialisation function, we allow each object to
+ * specify that it has a function that must be called to initialise
+ * that object.  The function call_init_fns() will call all the
+ * included objects' initialisation functions.
+ *
+ * Objects that require initialisation should include init.h and
+ * register the initialisation function using INIT_FN().
+ *
+ * Objects may register up to three functions: init, reset and exit.
+ * init gets called only once, at the point that Etherboot is
+ * initialised (before the call to main()).  reset gets called between
+ * each boot attempt.  exit gets called only once, just before the
+ * loaded OS starts up (or just before Etherboot exits, if it exits,
+ * or when the PXE NBP calls UNDI_SHUTDOWN, if it's a PXE NBP).
+ *
+ * The syntax is:
+ *   INIT_FN ( init_order, init_function, reset_function, exit_function );
+ * where init_order is an ordering taken from the list below.  Any
+ * function may be left as NULL.
+ */
+
+/* An entry in the initialisation function table */
+
+struct init_fn {
+       void ( *init ) ( void );
+       void ( *reset ) ( void );
+       void ( *exit ) ( void );
+};
+
+/* Use double digits to avoid problems with "10" < "9" on alphabetic sort */
+#define INIT_CONSOLE   "00"
+#define        INIT_CPU        "01"
+#define        INIT_TIMERS     "02"
+#define        INIT_PCMCIA     "03"
+#define        INIT_MEMSIZES   "04"
+#define        INIT_HEAP       "05"
+
+/* Macro for creating an initialisation function table entry */
+#define INIT_FN( init_order, init_func, reset_func, exit_func )                      \
+       static struct init_fn init_ ## init_func ## _ ## exit_func            \
+           __attribute__ ((used,__section__(".init_fns." init_order))) = {  \
+               .init = init_func,                                            \
+               .reset = reset_func,                                          \
+               .exit = exit_func,                                            \
+       };
+
+/* Function prototypes */
+
+void call_init_fns ( void );
+void call_reset_fns ( void );
+void call_exit_fns ( void );
+
+#endif /* INIT_H */
diff --git a/src/include/main.h b/src/include/main.h
new file mode 100644 (file)
index 0000000..2b2a96c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+extern int main ( void );
+
+#endif /* MAIN_H */
index 1b03e5671ea4a7bdff72fc5a3c60547df2d56200..d7e1af477f2baddd067a44ef3b24997d48f303f0 100644 (file)
@@ -18,7 +18,6 @@
 #include "setjmp.h"
 #include "latch.h"
 #include "callbacks.h"
-#include "hooks.h"
 
 /* within 1MB of 4GB is too close. 
  * MAX_ADDR is the maximum address we can easily do DMA to.
diff --git a/src/include/stddef.h b/src/include/stddef.h
new file mode 100644 (file)
index 0000000..ee1f154
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef STDDEF_H
+#define STDDEF_H
+
+/* for size_t */
+#include "stdint.h"
+
+#undef NULL
+#define NULL   ((void *)0)
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* STDDEF_H */
index 6b68f5f38c1580d60a4b7e6a2c514aa030efe946..0044d0c070a3898845e00c29f12631583bf84350 100644 (file)
@@ -53,7 +53,6 @@ extern void load_timer2(unsigned int ticks);
 extern inline int timer2_running(void);
 extern void waiton_timer2(unsigned int ticks);
 
-extern void setup_timers(void);
 extern void ndelay(unsigned int nsecs);
 extern void udelay(unsigned int usecs);
 extern void mdelay(unsigned int msecs);
diff --git a/src/util/parserom.pl b/src/util/parserom.pl
new file mode 100644 (file)
index 0000000..56bb944
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/perl -w
+#
+# Parse PCI_ROM and ISA_ROM entries from a source file on stdin and
+# output the relevant Makefile variable definitions to stdout
+#
+# Based upon portions of Ken Yap's genrules.pl
+
+use strict;
+use warnings;
+
+die "Syntax: $0 driver_source.c" unless @ARGV == 1;
+my $source = shift;
+open DRV, "<$source" or die "Could not open $source: $!\n";
+
+( my $family, my $driver_name ) = ( $source =~ /^(.*?([^\/]+))\..$/ )
+    or die "Could not parse source file name \"$source\"\n";
+
+my $printed_family;
+
+sub rom {
+  ( my $type, my $image, my $desc, my $vendor, my $device ) = @_;
+  my $ids = $vendor ? "$vendor,$device" : "-";
+  unless ( $printed_family ) {
+    print "\n";
+    print "# NIC\t\n";
+    print "# NIC\tfamily\t$family\n";
+    print "DRIVERS += $driver_name\n";
+    $printed_family = 1;
+  }
+  print "\n";
+  print "# NIC\t$image\t$ids\t$desc\n";
+  print "DRIVER_$image = $driver_name\n";
+  print "ROM_TYPE_$image = $type\n";
+  print "ROM_DESCRIPTION_$image = \"$desc\"\n";
+  print "PCI_VENDOR_$image = $vendor\n" if $vendor;
+  print "PCI_DEVICE_$image = $device\n" if $device;
+  print "ROMS += $image\n";
+  print "ROMS_$driver_name += $image\n";
+}
+
+while ( <DRV> ) {
+  next unless /(PCI|ISA)_ROM\s*\(/;
+
+  if ( /^\s*PCI_ROM\s*\(
+         \s*(0x[0-9A-Fa-f]{4})\s*, # PCI vendor
+         \s*(0x[0-9A-Fa-f]{4})\s*, # PCI device
+         \s*\"([^\"]*)\"\s*,      # Image
+         \s*\"([^\"]*)\"\s*       # Description
+       \)/x ) {
+    ( my $vendor, my $device, my $image, my $desc ) = ( lc $1, lc $2, $3, $4 );
+    rom ( "pci", $image, $desc, $vendor, $device );
+  } elsif ( /^\s*ISA_ROM\s*\(
+             \s*\"([^\"]*)\"\s*,  # Image
+             \s*\"([^\"]*)\"\s*   # Description
+           \)/x ) {
+    ( my $image, my $desc ) = ( $1, $2 );
+    rom ( "isa", $image, $desc );
+  } else {
+    warn "Malformed PCI_ROM or ISA_ROM macro on line $. of $source\n";
+  }
+}
+
+close DRV;
diff --git a/src/util/zfilelen.pl b/src/util/zfilelen.pl
deleted file mode 100755 (executable)
index 1f58ff9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/perl -w
-
-use bytes;
-
-local $/;
-$_ = <>;
-print length($_);
-exit;