--- /dev/null
+bin
+gcccheck
--- /dev/null
+#
+# Config for Etherboot/32
+#
+# Do not delete the tag OptionDescription and /OptionDescription
+# It is used to automatically generate the documentation.
+#
+# @OptionDescription@
+# User interaction options:
+#
+# -DASK_BOOT=n
+# Ask "Boot from (N)etwork ... or (Q)uit? "
+# at startup, timeout after n seconds (0 = no timeout).
+# If unset or negative, don't ask and boot immediately
+# using the default.
+# -DBOOT_FIRST
+# -DBOOT_SECOND
+# -DBOOT_THIRD
+# On timeout or Return key from previous
+# question, selects the order to try to boot from
+# various devices.
+# (alternatives: BOOT_NIC, BOOT_DISK,
+# BOOT_FLOPPY, BOOT_NOTHING)
+# See etherboot.h for prompt and answer strings.
+# BOOT_DISK and BOOT_FLOPPY work only where a driver
+# exists, e.g. in LinuxBIOS.
+# They have no effect on PCBIOS.
+# -DBOOT_INDEX The device to boot from 0 == any device.
+# 1 == The first nic found.
+# 2 == The second nic found
+# ...
+# BOOT_INDEX only applies to the BOOT_FIRST. BOOT_SECOND
+# and BOOT_THIRD search through all of the boot devices.
+# -DBAR_PROGRESS
+# Use rotating bar instead of sequential dots
+# to indicate an IP packet transmitted.
+#
+# Boot order options:
+#
+# -DBOOT_CLASS_FIRST
+# -DBOOT_CLASS_SECOND
+# -DBOOT_CLASS_THIRD
+# Select the priority of the boot classes
+# Valid values are:
+# BOOT_NIC
+# BOOT_DISK
+# BOOT_FLOPPY
+# BOOT_DISK and BOOT_FLOPPY work only where a driver exists,
+# e.g. in LinuxBIOS. They have no effect on PCBIOS.
+#
+# Boot autoconfiguration protocol options:
+#
+# -DALTERNATE_DHCP_PORTS_1067_1068
+# Use ports 1067 and 1068 for DHCP instead of 67 and 68.
+# As these ports are non-standard, you need to configure
+# your DHCP server to use them. This option gets around
+# existing DHCP servers which cannot be touched, for
+# one reason or another, at the cost of non-standard
+# boot images.
+# -DNO_DHCP_SUPPORT
+# Use BOOTP instead of DHCP.
+# -DRARP_NOT_BOOTP
+# Use RARP instead of BOOTP/DHCP.
+# -DREQUIRE_VCI_ETHERBOOT
+# Require an encapsulated Vendor Class Identifier
+# of "Etherboot" in the DHCP reply
+# Requires DHCP support.
+# -DDHCP_CLIENT_ID=\"Identifier\"
+# -DDHCP_CLIENT_ID_LEN=<Client ID length in octets>
+# -DDHCP_CLIENT_ID_TYPE=<Client ID type>
+# Specify a RFC2132 Client Identifier option, length and type.
+# Requires DHCP support.
+# -DDHCP_USER_CLASS=\"UserClass\"
+# -DDHCP_USER_CLASS_LEN=<User Class length in octets>
+# Specify a RFC3004 User Class option and length. Use this
+# option to set a UC (or multiple UCs) rather than munge the
+# client Vendor Class ID.
+# Requires DHCP support.
+# -DALLOW_ONLY_ENCAPSULATED
+# Ignore Etherboot-specific options that are not within
+# the Etherboot encapsulated options field. This option
+# should be enabled unless you have a legacy DHCP server
+# configuration from the bad old days before the use of
+# encapsulated Etherboot options.
+# -DDEFAULT_BOOTFILE=\"default_bootfile_name\"
+# Define a default bootfile for the case where your DHCP
+# server does not provide the information. Example:
+# -DDEFAULT_BOOTFILE="tftp:///tftpboot/kernel"
+# If you do not specify this option, then DHCP offers that
+# do not specify bootfiles will be ignored.
+#
+# NIC tuning parameters:
+#
+# -DALLMULTI
+# Turns on multicast reception in the NICs.
+#
+# Boot tuning parameters:
+#
+# -DCONGESTED
+# Turns on packet retransmission. Use it on a
+# congested network, where the normal operation
+# can't boot the image.
+# -DBACKOFF_LIMIT
+# Sets the maximum RFC951 backoff exponent to n.
+# Do not set this unreasonably low, because on networks
+# with many machines they can saturate the link
+# (the delay corresponding to the exponent is a random
+# time in the range 0..3.5*2^n seconds). Use 5 for a
+# VERY small network (max. 2 minutes delay), 7 for a
+# medium sized network (max. 7.5 minutes delay) or 10
+# for a really huge network with many clients, frequent
+# congestions (max. 1 hour delay). On average the
+# delay time will be half the maximum value. If in
+# doubt about the consequences, use a larger value.
+# Also keep in mind that the number of retransmissions
+# is not changed by this setting, so the default of 20
+# may no longer be appropriate. You might need to set
+# MAX_ARP_RETRIES, MAX_BOOTP_RETRIES, MAX_TFTP_RETRIES
+# and MAX_RPC_RETRIES to a larger value.
+# -DTIMEOUT=n
+# Use with care!! See above.
+# Sets the base of RFC2131 sleep interval to n.
+# This can be used with -DBACKOFF_LIMIT=0 to get a small
+# and constant (predictable) retry interval for embedded
+# devices. This is to achieve short boot delays if both
+# the DHCP Server and the embedded device will be powered
+# on the same time. Otherwise if the DHCP server is ready
+# the client could sleep the next exponentially timeout,
+# e.g. 70 seconds or more. This is not what you want.
+# n should be a multiple of TICKS_PER_SEC (18).
+#
+# Boot device options:
+#
+# -DTRY_FLOPPY_FIRST
+# If > 0, tries that many times to read the boot
+# sector from a floppy drive before booting from
+# ROM. If successful, does a local boot.
+# It assumes the floppy is bootable.
+# -DEXIT_IF_NO_OFFER
+# If no IP offer is obtained, exit and
+# let the BIOS continue.
+# The accessibility of the TFTP server has no effect,
+# so configure your DHCP/BOOTP server properly.
+# You should probably reduce MAX_BOOTP_RETRIES
+# to a small number like 3.
+#
+# Boot image options:
+#
+# -DTAGGED_IMAGE
+# Add tagged image kernel boot support (recommended).
+# -DAOUT_IMAGE
+# Add a.out kernel boot support (generic).
+# -DELF_IMAGE
+# Add generic ELF kernel boot support (recommended).
+# -DEL64F_IMAGE
+# Add generic ELF64 kernel boot support (useful for > 4GB disks).
+# -DWINCE_IMAGE
+# Add the ability to boot WINCE.... now only sis630 OK!
+# -DPXE_IMAGE
+# Add the ability to boot PXE NBPs. Requires
+# PXE_EXPORT. Currently not supported on
+# anything other than i386
+# -DFREEBSD_PXEEMU
+# Add the ability to boot PXE images... only FreeBSD supported
+# -DIMAGE_MULTIBOOT
+# Add Multiboot image support (currently only
+# for ELF images).
+# Without this, generic ELF support is selected.
+# -DIMAGE_FREEBSD
+# Add FreeBSD image loading support (requires at least
+# -DAOUT_IMAGE and/or -DELF_IMAGE).
+# -DFREEBSD_KERNEL_ENV
+# Pass in FreeBSD kernel environment
+# -DAOUT_LYNX_KDI
+# Add Lynx a.out KDI support
+# -DMULTICAST_LEVEL1
+# Support for sending multicast packets
+# -DMULTICAST_LEVEL2
+# Support for receiving multicast packets
+# -DDNS_RESOLVER
+# Support for resolving hostnames in bootfile name (experimental)
+# -DDOWNLOAD_PROTO_TFTP
+# If defined, includes TFTP support (recommended).
+# -DDOWNLOAD_PROTO_NFS
+# If defined, includes NFS support.
+# -DDEFAULT_PROTO_NFS
+# If defined, makes NFS the default protocol instead
+# of TFTP. Requires DOWNLOAD_PROTO_NFS.
+# -DDOWNLOAD_PROTO_SLAM
+# If defined, includes Scalable Local Area Multicast
+# support.
+# -DDOWNLOAD_PROTO_TFTM
+# If defined, includes TFTP Multicast mode support.
+# -DDOWNLOAD_PROTO_HTTP
+# If defined, includes HTTP support.
+#
+# Console options:
+#
+# -DCONSOLE_FIRMWARE
+# Set for firmware/BIOS provided (default if nothing else is set).
+# Normally this is shows up on your CRT.
+# -DCONSOLE_SERIAL
+# Set for serial console.
+# -DCONSOLE_DUAL
+# Both of the above
+# -DCONSOLE_DIRECT_VGA
+# Set for direct VGA console (only for x86).
+# -DCOMCONSOLE
+# Set port, e.g. 0x3F8.
+# -DCONSPEED
+# Set speed, e.g. 57600.
+# -DCOMPARM
+# Set Line Control Register value for data bits, stop
+# bits and parity. See a National Semiconditor 8250/
+# 16450/16550 data sheet for bit meanings.
+# If undefined, defaults to 0x03 = 8N1.
+# -DCOMPRESERVE
+# Ignore COMSPEED and COMPARAM and instead preserve
+# the com port parameters from the previous user
+# of the com port. Examples of previous user are a BIOS
+# that implements console redirection, lilo and LinuxBIOS.
+# This makes it trivial to keep the serial port
+# speed setting in sync between multiple users.
+# You set the speed in the first user and the
+# rest follow along.
+#
+# Interface export options:
+#
+# -DPXE_EXPORT
+# Export a PXE API interface. This is work in
+# progress. Note that you won't be able to load
+# PXE NBPs unless you also use -DPXE_IMAGE.
+# -DPXE_STRICT
+# Strict(er) compliance with the PXE
+# specification as published by Intel. This may
+# or may not be a good thing depending on your
+# view of the spec...
+# -DPXE_DHCP_STRICT
+# Strict compliance of the DHCP request packets
+# with the PXE specification as published by
+# Intel. This may or may not be a good thing
+# depending on your view of whether requesting
+# vendor options which don't actually exist is
+# pointless or not. You probably want this
+# option if you intend to use Windows RIS or
+# similar.
+#
+# Obscure options you probably don't need to touch:
+#
+# -DPOWERSAVE
+# Halt the processor when waiting for keyboard input
+# which saves power while waiting for user interaction.
+# Good for compute clusters and VMware emulation.
+# But may not work for all CPUs.
+# -DBUILD_SERIAL
+# Include an auto-incrementing build number in
+# the Etherboot welcome message. Useful when
+# developing, to be sure that the file you
+# compiled is the one you're currently testing.
+# -DBUILD_ID
+# Include a build ID string in the Etherboot
+# welcome message. Useful when developing, if
+# you have multiple builds with different
+# configurations and want to check you're
+# running the one you think you are. Requires
+# -DBUILD_SERIAL.
+#
+# BUS options:
+#
+# -DCONFIG_PCI
+# Include support for devices using the pci bus.
+# -DCONFIG_ISA
+# Include support for devices using isa bus.
+# -DCONFIG_PCMCIA
+# Include support for PCMCIA in general *development*
+# @/OptionDescription@
+
+# These default settings compile Etherboot with a small number of options.
+# You may wish to enable more of the features if the size of your ROM allows.
+
+
+# Select which buses etherboot should support
+CFLAGS+= -DCONFIG_PCI -DCONFIG_ISA
+# CFLAGS+= -DCONFIG_PCMCIA
+
+# For prompting and default on timeout
+CFLAGS+= -DASK_BOOT=3 -DBOOT_FIRST=BOOT_NIC
+# If you would like to attempt to boot from other devices as well as the network.
+# CFLAGS+= -DBOOT_SECOND=BOOT_FLOPPY
+# CFLAGS+= -DBOOT_THIRD=BOOT_DISK
+# CFLAGS+= -DBOOT_INDEX=0
+
+# If you prefer the old style rotating bar progress display
+# CFLAGS+= -DBAR_PROGRESS
+
+# Show size indicator
+# CFLAGS+= -DSIZEINDICATOR
+
+# Enabling this creates non-standard images which use ports 1067 and 1068
+# for DHCP/BOOTP
+# CFLAGS+= -DALTERNATE_DHCP_PORTS_1067_1068
+
+# Enabling this makes the boot ROM require a Vendor Class Identifier
+# of "Etherboot" in the Vendor Encapsulated Options
+# This can be used to reject replies from servers other than the one
+# we want to give out addresses to us, but it will prevent Etherboot
+# from getting an IP lease until you have configured DHCPD correctly
+# CFLAGS+= -DREQUIRE_VCI_ETHERBOOT
+
+# EXPERIMENTAL! Set DHCP_CLIENT_ID to create a Client Identifier (DHCP
+# option 61, see RFC2132 section 9.14) when Etherboot sends the DHCP
+# DISCOVER and REQUEST packets. This ID must UNIQUELY identify each
+# client on your local network. Set DHCP_CLIENT_ID_TYPE to the
+# appropriate hardware type as described in RFC2132 / RFC1700; this
+# almost certainly means using '1' if the Client ID is an Ethernet MAC
+# address and '0' otherwise. Set DHCP_CLIENT_ID_LEN to the length of
+# the Client ID in octets (this is not a null terminated C string, do
+# NOT add 1 for a terminator and do NOT add an extra 1 for the
+# hardware type octet). Note that to identify your client using the
+# normal default MAC address of your NIC, you do NOT need to set this
+# option, as the MAC address is automatically used in the
+# hwtype/chaddr field; note also that this field only sets the DHCP
+# option: it does NOT change the MAC address used by the client.
+
+# CFLAGS+= -DDHCP_CLIENT_ID="'C','L','I','E','N','T','0','0','1'" \
+# -DDHCP_CLIENT_ID_LEN=9 -DDHCP_CLIENT_ID_TYPE=0
+
+# CFLAGS+= -DDHCP_CLIENT_ID="0xDE,0xAD,0xBE,0xEF,0xDE,0xAD" \
+# -DDHCP_CLIENT_ID_LEN=6 -DDHCP_CLIENT_ID_TYPE=1
+
+# EXPERIMENTAL! Set DHCP_USER_CLASS to create a User Class option (see
+# RFC3004) when Etherboot sends the DHCP DISCOVER and REQUEST packets.
+# This can be used for classification of clients, typically so that a
+# DHCP server can send an appropriately tailored reply. Normally, a
+# string identifies a class of to which this client instance belongs
+# which is useful in your network, such as a department ('FINANCE' or
+# 'MARKETING') or hardware type ('THINCLIENT' or 'KIOSK'). Set
+# DHCP_USER_CLASS_LEN to the length of DHCP_USER_CLASS in octets.
+# This is NOT a null terminated C string, do NOT add 1 for a
+# terminator. RFC3004 advises how to lay out multiple User Class
+# options by using an octet for the length of each string, as in this
+# example. It is, of course, up to the server to parse this.
+
+# CFLAGS+= -DDHCP_USER_CLASS="'T','E','S','T','C','L','A','S','S'" \
+# -DDHCP_USER_CLASS_LEN=9
+
+# CFLAGS+= -DDHCP_USER_CLASS="5,'A','L','P','H','A',4,'B','E','T','A'" \
+# -DDHCP_USER_CLASS_LEN=11
+
+# for btext console support
+# CFLAGS+= -DCONSOLE_BTEXT
+# for direct PC kbd support
+# CFLAGS+= -DCONSOLE_PC_KBD
+# Set to enable FILO support
+# for FILO support it will make main call pci_init
+# INCLUDE_FILO=y
+ifdef INCLUDE_FILO
+CFLAGS+= -DCONFIG_FILO
+endif
+
+# Enabling this causes Etherboot to ignore Etherboot-specific options
+# that are not within an Etherboot encapsulated options field.
+# This option should be enabled unless you have a legacy DHCP server
+# configuration from the bad old days before the use of
+# encapsulated Etherboot options.
+CFLAGS+= -DALLOW_ONLY_ENCAPSULATED
+
+# Disable DHCP support
+# CFLAGS+= -DNO_DHCP_SUPPORT
+
+# Specify a default bootfile to be used if the DHCP server does not
+# provide the information. If you do not specify this option, then
+# DHCP offers that do not contain bootfiles will be ignored.
+# CFLAGS+= -DDEFAULT_BOOTFILE=\"tftp:///tftpboot/kernel\"
+
+# Limit the delay on packet loss/congestion to a more bearable value. See
+# description above. If unset, do not limit the delay between resend.
+CFLAGS+= -DBACKOFF_LIMIT=7 -DCONGESTED
+
+# More optional features
+# CFLAGS+= -DTRY_FLOPPY_FIRST=4
+# CFLAGS+= -DEXIT_IF_NO_OFFER
+
+# For a serial console, which can run in parallel with FIRMWARE console
+# CFLAGS+= -DCONSOLE_DUAL -DCOMCONSOLE=0x3F8 -DCONSPEED=9600
+
+# Enable tagged image, generic ELF, Multiboot ELF
+# or FreeBSD ELF/a.out boot image support
+CFLAGS+= -DTAGGED_IMAGE -DELF_IMAGE
+# CFLAGS+= -DAOUT_IMAGE -DIMAGE_MULTIBOOT -DIMAGE_FREEBSD
+# CFLAGS+= -DAOUT_IMAGE -DAOUT_LYNX_KDI
+# CFLAGS+= -DCOFF_IMAGE
+# CFLAGS+= -DRAW_IMAGE
+
+# Download files via TFTP
+CFLAGS+= -DDOWNLOAD_PROTO_TFTP
+# Change download protocol to NFS, default is TFTP
+# CFLAGS+= -DDOWNLOAD_PROTO_NFS
+# Change download protocol to HTTP, default is TFTP
+# CFLAGS+= -DDOWNLOAD_PROTO_HTTP
+# Change default protocol to NFS
+# CFLAGS+= -DDEFAULT_PROTO_NFS
+# Support to resolve hostnames in boot filename
+# CFLAGS+= -DDNS_RESOLVER
+
+# Multicast Support
+# CFLAGS+= -DALLMULTI -DMULTICAST_LEVEL1 -DMULTICAST_LEVEL2 -DDOWNLOAD_PROTO_TFTM
+
+# Etherboot as a PXE network protocol ROM
+CFLAGS+= -DPXE_IMAGE -DPXE_EXPORT
+# Etherboot stricter as a PXE network protocol ROM
+# CFLAGS+= -DPXE_DHCP_STRICT
+
+# Support for PXE emulation. Works only with FreeBSD to load the kernel
+# via pxeboot, use only with DOWNLOAD_PROTO_NFS
+# CFLAGS+= -DFREEBSD_PXEEMU
+
+# Include an auto-incrementing build serial number and optional build
+# ID string
+# CFLAGS+= -DBUILD_SERIAL
+# CFLAGS+= -DBUILD_SERIAL -DBUILD_ID=\"testing\"
+
+# Do not relocate
+# core/relocate.c should really be moved to an arch specific directory
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
+ifndef ARCH
+ARCH:=$(shell uname -m | sed -e s,i[3456789]86,i386,)
+endif
+MAKEDEPS:=
+SUFFIXES:=
+
+include Config
+include arch/$(ARCH)/Config
+include Makefile.main
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+#
+# 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:
+
+
+# Utilities
+
+$(BIN)/lzhuf: util/lzhuf.c
+ $(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -o $@ $<
+
+# 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)
--- /dev/null
+This file documents the driver changes needed to support use as part
+of a PXE stack.
+
+PROPER WAY
+==========
+
+1. The probe() routine.
+
+There are three additional fields that need to be filled in the nic
+structure: ioaddr, irqno and irq.
+
+ ioaddr is the base I/O address and seems to be for information only;
+ no use will be made of this value other than displaying it on the
+ screen.
+
+ irqno must be the IRQ number for the NIC. For PCI NICs this can
+ simply be copied from pci->irq.
+
+ irq is a function pointer, like poll and transmit. It must point to
+ the driver's irq() function.
+
+2. The poll() routine.
+
+This must take an additional parameter: "int retrieve". Calling
+poll() with retrieve!=0 should function exactly as before. Calling
+poll() with retrieve==0 indicates that poll() should check for the
+presence of a packet to read, but must *not* read the packet. The
+packet will be read by a subsequent call to poll() with retrieve!=0.
+
+The easiest way to implement this is to insert the line
+ if ( ! retrieve ) return 1;
+between the "is there a packet ready" and the "fetch packet" parts of
+the existing poll() routine.
+
+Care must be taken that a call to poll() with retrieve==0 does not
+clear the NIC's "packet ready" status indicator, otherwise the
+subsequent call to poll() with retrieve!=0 will fail because it will
+think that there is no packet to read.
+
+poll() should also acknowledge and clear the NIC's "packet received"
+interrupt. It does not need to worry about enabling/disabling
+interrupts; this is taken care of by calls to the driver's irq()
+routine.
+
+Etherboot will forcibly regenerate an interrupt if a packet remains
+pending after all interrupts have been acknowledged. You can
+therefore get away with having poll() just acknolwedge and clear all
+NIC interrupts, without particularly worrying about exactly when this
+should be done.
+
+3. The irq() routine.
+
+This is a new routine, with prototype
+ void DRIVER_irq ( struct nic *nic, irq_action_t action );
+"action" takes one of three possible values: ENABLE, DISABLE or FORCE.
+ENABLE and DISABLE mean to enable/disable the NIC's "packet received"
+interrupt. FORCE means that the NIC should be forced to generate a
+fake "packet received" interrupt.
+
+If you are unable to implement FORCE, your NIC will not work when
+being driven via the UNDI interface under heavy network traffic
+conditions. Since Etherboot's UNDI driver (make bin/undi.zpxe) is the
+only program known to use this interface, it probably doesn't really
+matter.
+
+
+QUICK AND DIRTY WAY
+===================
+
+It is possible to use the system timer interrupt (IRQ 0) rather than a
+genuine NIC interrupt. Since there is a constant stream of timer
+interrupts, the net upshot is a whole load of spurious "NIC"
+interrupts that have no effect other than to cause unnecessary PXE API
+calls. It's inefficient but it works.
+
+To achieve this, simply set nic->irqno=0 in probe() and point nic->irq
+to a dummy routine that does nothing. Add the line
+ if ( ! retrieve ) return 1;
+at the beginning of poll(), to prevent the packet being read (and
+discarded) when poll() is called with retrieve==0;
+
+
+UNCONVERTED DRIVERS
+===================
+
+Drivers that have not yet been converted should continue to function
+when not used as part of a PXE stack, although there will be a
+harmless compile-time warning about assignment from an incompatible
+pointer type in the probe() function, since the prototype for the
+poll() function is missing the "int retrieve" parameter.
--- /dev/null
+# Config for armnommu Etherboot
+#
+
+# For a clean compilation, switch in global Config
+# off: -DCONFIG_PCI, -DTAGGED_IMAGE, -DELF_IMAGE, -DPXE*, -DRELOCATE and INCLUDE_FILO
+# on : -DRAW_IMAGE
+
+# Serial line settings
+CFLAGS+= -DCONSOLE_SERIAL -DCONSPEED=57600
+
+# System Frequency
+CFLAGS+= -DSYSCLK=73728000
+
+# Image Download Address
+CFLAGS+= -DRAWADDR=0x40100000
+
+# NIC Debug Outputs
+#CFLAGS+= -DDEBUG_NIC
+
+# Fixed MAC address
+# p2001_eth has no flash and fixed mac address
+#CFLAGS+= -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
+CFLAGS+= -DMAC_HW_ADDR_DRV="0x00,0x09,0x4F,0x00,0x00,0x02"
--- /dev/null
+ARCH_FORMAT= armnommu
+
+ROMLIMIT= 20480
+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)/start.o
+
+SRCS+= arch/armnommu/core/arm_timer.c
+SRCS+= arch/armnommu/core/start.S
+SRCS+= arch/armnommu/core/serial.c
+SRCS+= arch/armnommu/core/mem.c
+SRCS+= arch/armnommu/core/setjmp.S
+SRCS+= arch/armnommu/drivers/net/p2001_eth.c
+
+# not greater than 100kB
+ROMLIMIT:=1024000
+
+include $(BIN)/Roms
+
+ROMS= $(BIN)/p2001_eth.rom
+IMGS= $(BIN)/p2001_eth.img
+
+
+allfiles: $(ROMS)
+
+BOBJS+= $(BIN)/arm_timer.o
+BOBJS+= $(BIN)/serial.o
+BOBJS+= $(BIN)/mem.o
+BOBJS+= $(BIN)/setjmp.o
+BOBJS+= $(BIN)/lib1funcs.o
+
+# Utilities
+
+$(BIN)/nrv2b: util/nrv2b.c
+ $(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
+
+# Pattern Rules
+# General for compiling/assembly source files
+$(BIN)/%.o: arch/armnommu/core/%.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+$(BIN)/%.o: arch/armnommu/drivers/net/%.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+$(BIN)/%.S: arch/armnommu/core/%.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) -S -o $@ -c $<
+
+$(BIN)/%.o: arch/armnommu/core/%.S $(MAKEDEPS)
+ $(CPP) $(CFLAGS) -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
+
+# general ruls for generating .img files
+$(BIN)/%.tmp: $(BIN)/%.o $(START) $(BIN)/config.o arch/$(ARCH)/core/etherboot.lds $(LIBS) $(STDDEPS) $(MAKEDEPS)
+ $(LD) $(LDFLAGS) -T arch/$(ARCH)/core/etherboot.lds -o $@ $(START) $(BIN)/config.o $< $(LIBS)
+ @$(SIZE) $@ | $(CHECKSIZE)
+
+$(BIN)/%.img: $(BIN)/%.tmp $(MAKEDEPS)
+ $(OBJCOPY) -O binary $< $@
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "etherboot.h"
+#include "timer.h"
+#include "latch.h"
+#include "hardware.h"
+
+
+/* get timer returns the contents of the timer */
+static unsigned long get_timer(void)
+{
+ return P2001_TIMER->Freerun_Timer;
+}
+
+/* ------ Calibrate the TSC -------
+ * Time how long it takes to excute a loop that runs in known time.
+ * And find the convertion needed to get to CLOCK_TICK_RATE
+ */
+
+static unsigned long configure_timer(void)
+{
+ return (1);
+}
+
+static unsigned long clocks_per_tick = 1;
+
+void setup_timers(void)
+{
+ if (!clocks_per_tick) {
+ clocks_per_tick = configure_timer();
+ }
+}
+
+unsigned long currticks(void)
+{
+ return get_timer(); /* /clocks_per_tick */
+}
+
+static unsigned long timer_timeout;
+static int __timer_running(void)
+{
+ return get_timer() < timer_timeout;
+}
+
+void udelay(unsigned int usecs)
+{
+ unsigned long now;
+ now = get_timer();
+ timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
+ while(__timer_running());
+}
+void ndelay(unsigned int nsecs)
+{
+ unsigned long now;
+ now = get_timer();
+ timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
+ while(__timer_running());
+}
+
+void load_timer2(unsigned int timer2_ticks)
+{
+ unsigned long now;
+ unsigned long clocks;
+ now = get_timer();
+ clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
+ timer_timeout = now + clocks;
+}
+
+int timer2_running(void)
+{
+ return __timer_running();
+}
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ /*. = 0x00000000;*/ /* PIC */
+ /*. = 0x00000400;*/ /* ROM Bootloader */
+ . = 0x40000000; /* SDRAM */
+
+ . = ALIGN(4);
+ _text = . ;
+ .text :
+ {
+ _start = .;
+ _virt_start = .;
+ bin/start.o (.text)
+ *(.text)
+
+ . = ALIGN(16);
+ isa_drivers = . ;
+ *(.drivers.isa);
+ isa_drivers_end = . ;
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ . = ALIGN(4);
+ _bss = . ;
+ .bss : { *(.bss) }
+
+ . = ALIGN(4);
+ _ebss = .;
+ _end = .;
+
+ . = ALIGN(16);
+ .text :
+ {
+ *(.dma.desc);
+ *(.dma.buffer);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+/*
+ * from gcc/config/udivmodsi4.c
+ */
+unsigned long
+udivmodsi4(unsigned long num, unsigned long den, int modwanted)
+{
+ unsigned long bit = 1;
+ unsigned long res = 0;
+
+ while (den < num && bit && !(den & (1L<<31)))
+ {
+ den <<=1;
+ bit <<=1;
+ }
+ while (bit)
+ {
+ if (num >= den)
+ {
+ num -= den;
+ res |= bit;
+ }
+ bit >>=1;
+ den >>=1;
+ }
+ if (modwanted) return num;
+ return res;
+}
+
+
+/*
+ * from gcc/config/udivmod.c
+ */
+long
+__udivsi3 (long a, long b)
+{
+ return udivmodsi4 (a, b, 0);
+}
+
+long
+__umodsi3 (long a, long b)
+{
+ return udivmodsi4 (a, b, 1);
+}
+
+
+/*
+ * from gcc/config/divmod.c
+ */
+long
+__divsi3 (long a, long b)
+{
+ int neg = 0;
+ long res;
+
+ if (a < 0)
+ {
+ a = -a;
+ neg = !neg;
+ }
+
+ if (b < 0)
+ {
+ b = -b;
+ neg = !neg;
+ }
+
+ res = udivmodsi4 (a, b, 0);
+
+ if (neg)
+ res = -res;
+
+ return res;
+}
+
+long
+__modsi3 (long a, long b)
+{
+ int neg = 0;
+ long res;
+
+ if (a < 0)
+ {
+ a = -a;
+ neg = 1;
+ }
+
+ if (b < 0)
+ b = -b;
+
+ res = udivmodsi4 (a, b, 1);
+
+ if (neg)
+ res = -res;
+
+ return res;
+}
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "hooks.h"
+#include "io.h"
+#include "etherboot.h"
+
+struct meminfo meminfo;
+void get_memsizes(void)
+{
+/* We initialize the meminfo structure
+ * according to our development board's specs
+ * We do not have a way to automatically probe the
+ * memspace instead we initialize it manually
+ */
+ meminfo.basememsize = 0x00000000;
+ meminfo.memsize = 0x00008000;
+ meminfo.map_count = 1;
+
+ meminfo.map[0].addr = 0x40000000;
+ meminfo.map[0].size = 0x01000000;
+ meminfo.map[0].type = E820_RAM;
+}
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifdef RAW_IMAGE
+static unsigned long raw_load_addr;
+
+int mach_boot(register unsigned long entry_point)
+{
+ void (*fnc)(void) = (void *) entry_point;
+ // r0 = 0
+ // r1 = 625 (machine nr. MACH_TYPE_P2001)
+ (*fnc)();
+
+ return 0; /* We should never reach this point ! */
+}
+
+static sector_t raw_download(unsigned char *data, unsigned int len, int eof)
+{
+ memcpy(phys_to_virt(raw_load_addr), data, len);
+ raw_load_addr += len;
+ if (!eof)
+ return 0;
+
+ done(1);
+ printf("Starting program.\n");
+ mach_boot(RAWADDR);
+ printf("Bootsector returned?");
+ longjmp(restart_etherboot, -2);
+ return 1;
+}
+
+static os_download_t raw_probe(unsigned char *data __unused, unsigned int len __unused)
+{
+ printf("(RAW");
+ // probe something here...
+ printf(")... \n");
+
+ //raw_load_addr = phys_to_virt(_end);
+ raw_load_addr = RAWADDR;
+ printf("Writing image to 0x%x\n", raw_load_addr);
+ return raw_download;
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "etherboot.h"
+#include "hardware.h"
+#ifdef CONSOLE_SERIAL
+
+/*
+ * void serial_putc(int ch);
+ * Write character `ch' to port UART_BASE.
+ */
+void serial_putc(int ch)
+{
+ /* wait for room in the 32 byte tx FIFO */
+ while ((P2001_UART->r.STATUS & 0x3f) > /* 30 */ 0) ;
+ P2001_UART->w.TX1 = ch & 0xff;
+}
+
+/*
+ * int serial_getc(void);
+ * Read a character from port UART_BASE.
+ */
+int serial_getc(void)
+{
+ while (((P2001_UART->r.STATUS >> 6) & 0x3f) == 0) ;
+ return P2001_UART->r.RX1 & 0xff;
+}
+
+/*
+ * int serial_ischar(void);
+ * If there is a character in the input buffer of port UART_BASE,
+ * return nonzero; otherwise return 0.
+ */
+int serial_ischar(void)
+{
+ return (P2001_UART->r.STATUS >> 6) & 0x3f;
+}
+
+/*
+ * int serial_init(void);
+ * Initialize port to speed 57.600, line settings 8N1.
+ */
+int serial_init(void)
+{
+ static unsigned int N;
+ // const M=3
+ P2001_UART->w.Clear = 0; // clear
+ N = ((SYSCLK/8)*3)/CONSPEED;
+ P2001_UART->w.Baudrate = (N<<16)+3; // set 57.600 BAUD
+ P2001_UART->w.Config = 0xcc100; // set 8N1, *water = 12
+ return 1;
+}
+
+/*
+ * void serial_fini(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)
+{
+}
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+.text
+
+.global sigsetjmp;
+.type sigsetjmp,%function
+.align 4;
+sigsetjmp:
+ /* Save registers */
+ stmia r0, {v1-v6, sl, fp, sp, lr}
+
+ mov r0, #0
+ bx lr
+.size sigsetjmp,.-sigsetjmp;
+
+
+
+.global longjmp;
+.type longjmp,%function
+.align 4;
+longjmp:
+ mov ip, r0 /* save jmp_buf pointer */
+
+ movs r0, r1 /* get the return value in place */
+ moveq r0, #1 /* can't let setjmp() return zero! */
+
+ ldmia ip, {v1-v6, sl, fp, sp, pc}
+.size longjmp,.-longjmp;
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+.global _start
+
+/* Mode definitions */
+#define Mode_USR 0x10
+#define Mode_FIQ 0x11
+#define Mode_IRQ 0x12
+#define Mode_SVC 0x13
+#define Mode_ABT 0x17
+#define Mode_UNDEF 0x1B
+#define Mode_SYS 0x1F // only available on ARM Arch. v4
+#define I_Bit 0x80
+#define F_Bit 0x40
+
+/* LPEC register definitions */
+#define Adr_SYS_BASE 0x00100000
+#define REL_Adr_SDRAM_Ctrl 0x10
+#define REL_Adr_ExtMem_Ctrl 0x14
+#define REL_Adr_WaitState_Ext 0x18
+#define REL_Adr_WaitState_Asic 0x1c
+#define Adr_TIMER_BASE 0x00110000
+#define REL_Adr_Timer12_PreDiv 0x0c
+#define REL_Adr_PLL_12000_config 0x30
+#define REL_Adr_PLL_12288_config 0x34
+#define REL_Adr_DIV_12288_config 0x38
+#define REL_Adr_FSC_CONFIG 0x44
+#define Adr_GPIO_BASE 0x00120000
+#define REL_Adr_NRES_OUT 0x2c
+
+
+
+/* Define entry point */
+.arm // Next instruction will be ARM
+_start:
+
+/*
+ * Initialize memory system
+ */
+
+
+/*
+ * Initialize stack pointer registers
+ */
+
+/* Enter SVC mode and set up the SVC stack pointer */
+ mov r0, #(Mode_SVC|I_Bit|F_Bit)
+ msr cpsr_c, r0
+ ldr sp, SP_SVC
+
+
+/*
+ * Initialize critical IO devices
+ */
+
+ /* watchdog off */
+ mov r0, #Adr_TIMER_BASE
+ ldr r1, Timer12_PreDiv
+ str r1, [r0, #REL_Adr_Timer12_PreDiv]
+
+ /* NRES=1 */
+ mov r0, #Adr_GPIO_BASE
+ ldr r1, NRES_OUT
+ str r1, [r0, #REL_Adr_NRES_OUT]
+
+ /* ExtMem */
+ mov r0, #Adr_SYS_BASE
+ ldr r1, ExtMem_Ctrl
+ str r1, [r0, #REL_Adr_ExtMem_Ctrl]
+
+ /* SDRAM */
+ mov r0, #Adr_SYS_BASE
+ ldr r1, SDRAM_Ctrl
+ str r1, [r0, #REL_Adr_SDRAM_Ctrl]
+/*
+_wait_sdram_ctrl:
+ ldr r1, [r0]
+ tst r1, #0x20000
+ beq _wait_sdram_ctrl
+*/
+
+ /* WaitState_Ext */
+ ldr r1, WaitState_Ext
+ str r1, [r0, #REL_Adr_WaitState_Ext]
+ /* WaitState_Asic */
+ ldr r1, WaitState_Asic
+ str r1, [r0, #REL_Adr_WaitState_Asic]
+
+ /* PLL_12288 */
+ mov r0, #Adr_TIMER_BASE
+ ldr r1, PLL_12288_config
+ str r1, [r0, #REL_Adr_PLL_12288_config]
+ /* DIV_12288 */
+ ldr r1, DIV_12288_config
+ str r1, [r0, #REL_Adr_DIV_12288_config]
+ /* PLL_12200 */
+ ldr r1, PLL_12000_config
+ str r1, [r0, #REL_Adr_PLL_12000_config]
+
+ /* FSC_CONFIG */
+ ldr r1, [r0, #REL_Adr_FSC_CONFIG]
+ bic r1, r1, #0x07
+ ldr r2, FSC_CONFIG
+ orr r1, r1, r2
+ str r1, [r0, #REL_Adr_FSC_CONFIG]
+
+
+/*
+ * Initialize interrupt system variables here
+ */
+
+
+/*
+ * Initialize memory required by main C code
+ */
+
+
+/* jump to main program */
+ mov r0, #0
+ b main
+
+
+Timer12_PreDiv:
+ .word 0x40bb0000 /* watchdog off */
+NRES_OUT:
+ .word 0x00000003 /* NRES_OUT_DRV=1, NRES_OUT_DAT=1 */
+
+#if SYSCLK == 73728000
+ExtMem_Ctrl:
+ .word 0x000000e8 /* fuer FPGA 32 Bit konfiguriert */
+SDRAM_Ctrl:
+// .word 0x28fc0037 /* default */
+ .word 0xaef40027 /* p2001_bit_compact */
+WaitState_Ext:
+ .word 0xa0001245 /* fuer 73 MHz */
+// .word 0x0000fff3 /* rom bootloader */
+WaitState_Asic:
+ .word 0x00ff8a5f /* fuer 85 MHz */
+// .word 0x00000203 /* rom bootloader */
+PLL_12288_config:
+ .word 0x00000004 /* fuer 73 MHz */
+DIV_12288_config:
+ .word 0x00010601 /* fuer 73 MHz */
+PLL_12000_config:
+ .word 0x10004e75 /* fuer 85 MHz */
+FSC_CONFIG:
+ .word 0xc0000005 /* fuer 73 MHz */
+#else
+#error "Please define proper timings and wait states for that sysclk."
+#endif
+
+SP_SVC:
+ .word 0x40fffffc
+
+
+
+#ifndef NORELOCATE
+/**************************************************************************
+RELOCATE_TO - relocate etherboot to the specified address
+**************************************************************************/
+ .global relocate_to
+
+relocate_to:
+ ldr r1, =_start
+ ldr r2, =_end
+
+ /* while (r1 < r2) { *(r0++) = *(r1++) } */
+_relocate_loop:
+ cmp r1, r2
+ ldrcc r3, [r1], #4
+ strcc r3, [r0], #4
+ bcc _relocate_loop
+ mov pc, lr
+#endif
+
+
+.global __gccmain
+__gccmain:
+ mov pc, lr /* return from subroutine */
--- /dev/null
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+P2001 NIC driver for Etherboot
+***************************************************************************/
+
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the ISA support functions, if this is an ISA NIC */
+#include "isa.h"
+
+#include "hardware.h"
+#include "lxt971a.h"
+#include "timer.h"
+
+
+/* NIC specific static variables go here */
+static unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV};
+
+/* DMA descriptors and buffers */
+#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
+#define DMA_BUF_SIZE 2048 /* Buffer size */
+static DMA_DSC txd __attribute__ ((__section__(".dma.desc")));
+static DMA_DSC rxd[NUM_RX_DESC] __attribute__ ((__section__(".dma.desc")));
+static unsigned char rxb[NUM_RX_DESC * DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
+static unsigned char txb[ DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
+static unsigned int cur_rx;
+
+/* Device selectors */
+static unsigned int cur_channel; // DMA channel : 0..3
+static unsigned int cur_phy; // PHY Address : 0..31
+static P2001_ETH_regs_ptr EU; // Ethernet Unit : 0x0018_000 with _=0..3
+static P2001_ETH_regs_ptr MU; // Management Unit: 0x00180000
+
+#define MDIO_MAXCOUNT 1000 /* mdio abort */
+static unsigned int mdio_error; /* mdio error */
+
+/* Function prototypes */
+static void p2001_eth_mdio_init ();
+static void p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data);
+static unsigned int p2001_eth_mdio_read (unsigned int phyadr, unsigned int regadr);
+extern unsigned int p2001_eth_mdio_error;
+
+static int p2001_eth_poll (struct nic *nic, int retrieve);
+static void p2001_eth_transmit (struct nic *nic, const char *d,
+ unsigned int t, unsigned int s, const char *p);
+
+static void p2001_eth_irq (struct nic *nic, irq_action_t action);
+
+static void p2001_eth_init ();
+static void p2001_eth_disable (struct dev *dev);
+
+static int p2001_eth_check_link(unsigned int phy);
+static int p2001_eth_probe (struct dev *dev, unsigned short *probe_addrs __unused);
+
+
+/**************************************************************************
+PHY MANAGEMENT UNIT - Read/write
+***************************************************************************/
+static void p2001_eth_mdio_init()
+{
+ /* reset ethernet PHYs */
+ printf("Resetting PHYs...\n");
+
+ /* GPIO24/25: TX_ER2/TX_ER0 */
+ /* GPIO26/27: PHY_RESET/TX_ER1 */
+ P2001_GPIO->PIN_MUX |= 0x0018;
+ // 31-16: 0000 1111 0000 0000
+ P2001_GPIO->GPIO2_En |= 0x0400;
+
+ P2001_GPIO->GPIO2_Out |= 0x04000000;
+ P2001_GPIO->GPIO2_Out &= ~0x0400;
+ mdelay(500);
+ P2001_GPIO->GPIO2_Out |= 0x0400;
+
+ /* set management unit clock divisor */
+ // max. MDIO CLK = 2.048 MHz (EU.doc)
+ // max. MDIO CLK = 8.000 MHz (LXT971A)
+ // sysclk/(2*(n+1)) = MDIO CLK <= 2.048 MHz
+ // n >= sysclk/4.096 MHz - 1
+#if SYSCLK == 73728000
+ P2001_MU->MU_DIV = 17; // 73.728 MHZ =17=> 2.020 MHz
+#else
+ //MU->MU_DIV = (SYSCLK/4.096)-1;
+#error "Please define a proper MDIO CLK divisor for that sysclk."
+#endif
+ asm("nop \n nop");
+}
+
+static void p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data)
+{
+ static unsigned int count;
+ count = 0;
+
+ /* Warten bis Hardware inaktiv (MIU = "0") */
+ while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
+ count++;
+
+ /* Schreiben MU_DATA */
+ MU->MU_DATA = data;
+
+ /* Schreiben MU_CNTL */
+ MU->MU_CNTL = regadr + (phyadr<<5) + (1<<10);
+
+ /* Warten bis Hardware aktiv (MIU = "1") */
+ while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
+ count++;
+ //asm("nop \r\n nop");
+
+ /* Warten bis Hardware inaktiv (MIU = "0") */
+ while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
+ count++;
+
+ mdio_error = (count >= MDIO_MAXCOUNT);
+}
+
+static unsigned int p2001_eth_mdio_read(unsigned int phyadr, unsigned int regadr)
+{
+ static unsigned int count;
+ count = 0;
+
+ do {
+ /* Warten bis Hardware inaktiv (MIU = "0") */
+ while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
+ count++;
+
+ /* Schreiben MU_CNTL */
+ MU->MU_CNTL = regadr + (phyadr<<5) + (2<<10);
+
+ /* Warten bis Hardware aktiv (MIU = "1") */
+ while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
+ count++;
+ //asm("nop \r\n nop");
+
+ /* Warten bis Hardware inaktiv (MIU = "0") */
+ while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
+ count++;
+
+ /* Fehler, wenn MDIO Read Error (MRE = "1") */
+ } while ((MU->MU_CNTL & 0x4000) && (count < MDIO_MAXCOUNT));
+
+ /* Lesen MU_DATA */
+ mdio_error = (count >= MDIO_MAXCOUNT);
+ return MU->MU_DATA;
+}
+
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+/* Function: p2001_eth_poll
+ *
+ * Description: checks for a received packet and returns it if found.
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: 1 if a packet was received.
+ * 0 if no pacet was received.
+ *
+ * Side effects:
+ * Returns (copies) the packet to the array nic->packet.
+ * Returns the length of the packet in nic->packetlen.
+ */
+static int p2001_eth_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+
+ int retstat = 0;
+
+ if (rxd[cur_rx].stat & (1<<31)) // OWN
+ return retstat;
+
+ if (!retrieve)
+ return 1;
+
+ nic->packetlen = rxd[cur_rx].cntl & 0xffff;
+
+ if (rxd[cur_rx].stat & ((1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22))) {
+ /* corrupted packet received */
+ printf("p2001_eth_poll: Corrupted packet received, stat = %X\n",
+ rxd[cur_rx].stat);
+ retstat = 0;
+ } else {
+ /* give packet to higher routine */
+ memcpy(nic->packet, (rxb + cur_rx*DMA_BUF_SIZE), nic->packetlen);
+ retstat = 1;
+ }
+
+#ifdef DEBUG_NIC
+ printf("p2001_eth_poll: packet from %! to %! received\n",
+ (rxb+cur_rx*DMA_BUF_SIZE)+ETH_ALEN,
+ (rxb+cur_rx*DMA_BUF_SIZE));
+#endif
+
+ /* disable receiver */
+ // FIXME: is that ok? it can produce grave errors.
+ EU->RMAC_DMA_EN = 0; /* clear run bit */
+
+ /* return the descriptor and buffer to receive ring */
+ rxd[cur_rx].stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
+ rxd[cur_rx].cntl = (1<<23); // DSC1 RECEIVE
+ rxd[cur_rx].cntl |= cur_channel << 16; // DSC1 CHANNEL
+ rxd[cur_rx].cntl |= DMA_BUF_SIZE; // DSC1 LEN
+
+ if (++cur_rx == NUM_RX_DESC)
+ cur_rx = 0;
+
+ /* enable receiver */
+ if (!(EU->RMAC_DMA_EN & 0x01))
+ EU->RMAC_DMA_EN = 0x01; /* set run bit */
+
+#ifdef DEBUG_NIC
+ printf("RMAC_MIB0..5: %d:%d:%d:%d:%d:%d\n",
+ EU->RMAC_MIB0, EU->RMAC_MIB1,
+ EU->RMAC_MIB2, EU->RMAC_MIB3,
+ EU->RMAC_MIB4, EU->RMAC_MIB5);
+#endif
+
+ return retstat; /* initially as this is called to flush the input */
+}
+
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+/* Function: p2001_eth_transmit
+ *
+ * Description: transmits a packet and waits for completion or timeout.
+ *
+ * Arguments: char d[6]: destination ethernet address.
+ * unsigned short t: ethernet protocol type.
+ * unsigned short s: size of the data-part of the packet.
+ * char *p: the data for the packet.
+ *
+ * Returns: void.
+ */
+static void p2001_eth_transmit(
+ struct nic *nic __unused,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ unsigned int nstype;
+#ifdef DEBUG_NIC
+ unsigned int status;
+#endif
+
+ /* assemble packet */
+ memcpy(txb, d, ETH_ALEN); // destination
+ memcpy(txb+ETH_ALEN, nic->node_addr, ETH_ALEN); // source
+ nstype = htons(t);
+ memcpy(txb+2*ETH_ALEN, (char*)&nstype, 2); // type
+ memcpy(txb+ETH_HLEN, p, s); // packet
+ s += ETH_HLEN;
+
+ /* pad to minimum packet size */
+// while (s<ETH_ZLEN)
+// txb[s++] = '\0';
+ // TMAC_CNTL.ATP does the same
+
+#ifdef DEBUG_NIC
+ printf("p2001_eth_transmit: packet from %! to %! sent\n", txb+ETH_ALEN, txb);
+#endif
+
+ /* configure descriptor */
+ txd.stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
+ txd.cntl = cur_channel << 16; // DSC1 CHANNEL
+ txd.cntl |= s; // DSC1 LEN
+
+ /* restart the transmitter */
+ EU->TMAC_DMA_EN = 0x01; /* set run bit */
+ while(EU->TMAC_DMA_EN & 0x01) ; /* wait */
+
+#ifdef DEBUG_NIC
+ /* check status */
+ status = EU->TMAC_DMA_STAT;
+ if (status & ~(0x40))
+ printf("p2001_eth_transmit: dma status=0x%hx\n", status);
+
+ printf("TMAC_MIB6..7: %d:%d\n", EU->TMAC_MIB6, EU->TMAC_MIB7);
+#endif
+}
+
+
+/**************************************************************************
+IRQ - Enable, Disable or Force Interrupts
+***************************************************************************/
+/* Function: p2001_eth_irq
+ *
+ * Description: Enable, Disable, or Force, interrupts
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ * irq_action_t action: Requested action
+ *
+ * Returns: void.
+ */
+
+static void
+p2001_eth_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+
+/**************************************************************************
+INIT - Initialize device
+***************************************************************************/
+/* Function: p2001_init
+ *
+ * Description: resets the ethernet controller chip and various
+ * data structures required for sending and receiving packets.
+ *
+ * returns: void.
+ */
+static void p2001_eth_init()
+{
+ static int i;
+
+ /* disable transceiver */
+// EU->TMAC_DMA_EN = 0; /* clear run bit */
+// EU->RMAC_DMA_EN = 0; /* clear run bit */
+
+ /* set rx filter (physical mac addresses) */
+ EU->RMAC_PHYU =
+ (MAC_HW_ADDR[0]<< 8) +
+ (MAC_HW_ADDR[1]<< 0);
+ EU->RMAC_PHYL =
+ (MAC_HW_ADDR[2]<<24) +
+ (MAC_HW_ADDR[3]<<16) +
+ (MAC_HW_ADDR[4]<<8 ) +
+ (MAC_HW_ADDR[5]<<0 );
+
+ /* initialize the tx descriptor ring */
+// txd.stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
+// txd.cntl = cur_channel << 16; // DSC1 CHANNEL
+// txd.cntl |= DMA_BUF_SIZE; // DSC1 LEN
+ txd.buf = &txb; // DSC2 BUFFER
+ txd.next = &txd; // DSC3 NEXTDSC @self
+ EU->TMAC_DMA_DESC = &txd;
+
+ /* initialize the rx descriptor ring */
+ cur_rx = 0;
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ rxd[i].stat = (1<<31) | (1<<30) | (1<<29); // DSC0 OWN|START|END
+ rxd[i].cntl = (1<<23); // DSC1 RECEIVE
+ rxd[i].cntl |= cur_channel << 16; // DSC1 CHANNEL
+ rxd[i].cntl |= DMA_BUF_SIZE; // DSC1 LEN
+ rxd[i].buf = &rxb[i*DMA_BUF_SIZE]; // DSC2 BUFFER (EU-RX data)
+ rxd[i].next = &rxd[i+1]; // DSC3 NEXTDSC @next
+ }
+ rxd[NUM_RX_DESC-1].next = &rxd[0]; // DSC3 NEXTDSC @first
+ EU->RMAC_DMA_DESC = &rxd[0];
+
+ /* set transmitter mode */
+ EU->TMAC_CNTL = (1<<4) | /* COI: Collision ignore */
+ //(1<<3) | /* CSI: Carrier Sense ignore */
+ (1<<2); /* ATP: Automatic Transmit Padding */
+
+ /* set receive mode */
+ EU->RMAC_CNTL = (1<<3) | /* BROAD: Broadcast packets */
+ (1<<1); /* PHY : Packets to out MAC address */
+
+ /* enable receiver */
+ EU->RMAC_DMA_EN = 1; /* set run bit */
+}
+
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void p2001_eth_disable(struct dev *dev __unused)
+{
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ */
+
+ /* disable transmitter */
+ EU->TMAC_DMA_EN = 0; /* clear run bit */
+
+ /* disable receiver */
+ EU->RMAC_DMA_EN = 0; /* clear run bit */
+}
+
+
+/**************************************************************************
+LINK - Check for valid link
+***************************************************************************/
+static int p2001_eth_check_link(unsigned int phy)
+{
+ static int status;
+ static unsigned int count;
+ count = 0;
+
+ /* Use 0x3300 for restarting NWay */
+ printf("Starting auto-negotiation... ");
+ p2001_eth_mdio_write(phy, Adr_LXT971A_Control, 0x3300);
+ if (mdio_error)
+ goto failed;
+
+ /* Bits 1.5 and 17.7 are set to 1 once the Auto-Negotiation process to completed. */
+ do {
+ mdelay(500);
+ status = p2001_eth_mdio_read(phy, Adr_LXT971A_Status1);
+ if (mdio_error || (count++ > 6)) // 6*500ms = 3s timeout
+ goto failed;
+ } while (!(status & 0x20));
+
+ /* Bits 1.2 and 17.10 are set to 1 once the link is established. */
+ if (p2001_eth_mdio_read(phy, Adr_LXT971A_Status1) & 0x04) {
+ /* Bits 17.14 and 17.9 can be used to determine the link operation conditions (speed and duplex). */
+ printf("Valid link, operating at: %sMb-%s\n",
+ (p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x4000) ? "100" : "10",
+ (p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x0200) ? "FD" : "HD");
+ return 1;
+ }
+
+failed:
+ if (mdio_error)
+ printf("Failed\n");
+ else
+ printf("No valid link\n");
+ return 0;
+}
+
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int p2001_eth_probe(struct dev *dev, unsigned short *probe_addrs __unused)
+{
+ struct nic *nic = (struct nic *)dev;
+ /* if probe_addrs is 0, then routine can use a hardwired default */
+ static int board_found;
+ static int valid_link;
+
+ /* reset phys and configure mdio clk */
+ p2001_eth_mdio_init();
+
+ /* find the correct PHY/DMA/MAC combination */
+ MU = P2001_MU; // MU for all PHYs is only in EU0
+ printf("Searching for P2001 NICs...\n");
+ for (cur_channel=0; cur_channel<4; cur_channel++) {
+ switch(cur_channel) {
+ case 0:
+ EU = P2001_EU0;
+ cur_phy = 0;
+ break;
+ case 1:
+ EU = P2001_EU1;
+ cur_phy = 1;
+ break;
+ case 2:
+ EU = P2001_EU2;
+ cur_phy = 2;
+ break;
+ case 3:
+ EU = P2001_EU3;
+ cur_phy = 3;
+ break;
+ }
+
+ /* first a non destructive test for initial value RMAC_TLEN=1518 */
+ board_found = (EU->RMAC_TLEN == 1518);
+ if (board_found) {
+ printf("Checking EU%d...\n", cur_channel);
+
+ valid_link = p2001_eth_check_link(cur_phy);
+ if (valid_link) {
+ /* initialize device */
+ p2001_eth_init(nic);
+
+ /* set node address */
+ printf("Setting MAC address to %!\n", MAC_HW_ADDR);
+ memcpy(nic->node_addr, MAC_HW_ADDR, 6);
+
+ /* point to NIC specific routines */
+ dev->disable = p2001_eth_disable;
+ nic->poll = p2001_eth_poll;
+ nic->transmit = p2001_eth_transmit;
+ nic->irq = p2001_eth_irq;
+
+ /* Report the ISA pnp id of the board */
+ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
+ dev->devid.vendor_id = htons(0x1234);
+ return 1;
+ }
+ }
+ }
+ /* else */
+ return 0;
+}
+
+ISA_ROM("p2001_eth", "P2001 Ethernet Driver")
+static struct isa_driver p2001_eth_driver __isa_driver = {
+ .type = NIC_DRIVER,
+ .name = "P2001 Ethernet Driver",
+ .probe = p2001_eth_probe,
+ .ioaddrs = 0,
+};
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ETHERBOOT_BITS_BYTESWAP_H
+#define ETHERBOOT_BITS_BYTESWAP_H
+
+/* We do not have byte swap functions ... We are
+ * RISC processor ...
+ */
+
+static inline unsigned short __swap16(volatile unsigned short v)
+{
+ return ((v << 8) | (v >> 8));
+}
+
+static inline unsigned int __swap32(volatile unsigned long v)
+{
+ return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
+}
+
+#define __bswap_constant_16(x) \
+ ((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
+ (((uint16_t)(x) & 0xff00) >> 8)))
+
+#define __bswap_constant_32(x) \
+ ((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \
+ (((uint32_t)(x) & 0x0000ff00U) << 8) | \
+ (((uint32_t)(x) & 0x00ff0000U) >> 8) | \
+ (((uint32_t)(x) & 0xff000000U) >> 24)))
+
+# define __bswap_16(x) \
+ (__extension__ \
+ ({ unsigned short int __bsx = (x); \
+ ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); }))
+
+
+# define __bswap_32(x) \
+ (__extension__ \
+ ({ unsigned int __bsx = (x); \
+ ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | \
+ (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); }))
+
+#endif /* ETHERBOOT_BITS_BYTESWAP_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARM_BITS_CPU_H
+#define ARM_BITS_CPU_H
+
+#define cpu_setup() do {} while(0)
+
+#endif /* ARM_BITS_CPU_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARM_BITS_ELF_H
+#define ARM_BITS_ELF_H
+
+/* ELF Defines for the current architecture */
+#define EM_CURRENT EM_ARM
+#define ELFDATA_CURRENT ELFDATA2LSB
+
+#define ELF_CHECK_ARCH(x) \
+ ((x).e_machine == EM_CURRENT)
+
+#endif /* ARM_BITS_ELF_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ETHERBOOT_BITS_ENDIAN_H
+#define ETHERBOOT_BITS_ENDIAN_H
+
+#ifdef __ARMEB__
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+#endif /* ETHERBOOT_BITS_ENDIAN_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ETHERBOOT_BITS_STRING_H
+#define ETHERBOOT_BITS_STRING_H
+
+#endif /* ETHERBOOT_BITS_STRING_H */
--- /dev/null
+/* empty file */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Architecture: ARM9TDMI
+ * Processor : P2001
+ */
+
+#ifndef ARCH_HARDWARE_H
+#define ARCH_HARDWARE_H
+
+#ifndef __ASSEMBLY__
+
+/* DMA descriptor */
+typedef struct {
+ unsigned int stat; /* status: own, start, end, offset, status */
+ unsigned int cntl; /* control: loop, int, type, channel, length */
+ char *buf; /* buffer */
+ void *next; /* nextdsc */
+} DMA_DSC;
+
+
+/* The address definitions are from asic_bf.h */
+typedef struct { // 0x00100000U
+ volatile unsigned int reserved1[0x3];
+ volatile unsigned int ArmDmaPri; // 0x0000000CU
+ volatile unsigned int SDRAM_Ctrl; // 0x00000010U
+ volatile unsigned int ExtMem_Ctrl; // 0x00000014U
+ volatile unsigned int WaitState_Ext; // 0x00000018U
+ volatile unsigned int WaitState_Asic; // 0x0000001CU
+ volatile unsigned int TOP; // 0x00000020U
+ volatile unsigned int reserved2[0x3];
+ volatile unsigned int Adr1_EQ_30Bit; // 0x00000030U
+ volatile unsigned int Adr2_EQ_30Bit; // 0x00000034U
+ volatile unsigned int Adr3_EQ_30Bit; // 0x00000038U
+ volatile unsigned int Dat3_EQ_32Bit; // 0x0000003CU
+ volatile unsigned int Adr4_HE_20Bit; // 0x00000040U
+ volatile unsigned int Adr4_LT_20Bit; // 0x00000044U
+ volatile unsigned int Adr5_HE_20Bit; // 0x00000048U
+ volatile unsigned int Adr5_LT_20Bit; // 0x0000004CU
+ volatile unsigned int Adr_Control; // 0x00000050U
+ volatile unsigned int ABORT_IA_32Bit; // 0x00000054U
+} *P2001_SYS_regs_ptr;
+#define P2001_SYS ((volatile P2001_SYS_regs_ptr) 0x00100000)
+
+typedef struct { // 0x00110000U
+ volatile unsigned int Timer1; // 0x00000000U
+ volatile unsigned int Timer2; // 0x00000004U
+ volatile unsigned int TIMER_PRELOAD; // 0x00000008U
+ volatile unsigned int Timer12_PreDiv; // 0x0000000CU
+ volatile unsigned int TIMER_INT; // 0x00000010U
+ volatile unsigned int Freerun_Timer; // 0x00000014U
+ volatile unsigned int WatchDog_Timer; // 0x00000018U
+ volatile unsigned int PWM_CNT; // 0x00000020U
+ volatile unsigned int PWM_CNT2; // 0x00000024U
+ volatile unsigned int PLL_12000_config; // 0x00000030U
+ volatile unsigned int PLL_12288_config; // 0x00000034U
+ volatile unsigned int DIV_12288_config; // 0x00000038U
+ volatile unsigned int MOD_CNT_768; // 0x0000003CU
+ volatile unsigned int FSC_IRQ_STATUS; // 0x00000040U
+ volatile unsigned int FSC_CONFIG; // 0x00000044U
+ volatile unsigned int FSC_CONSTRUCT; // 0x00000048U
+ volatile unsigned int FSC_base_clk_reg; // 0x0000004CU
+ volatile unsigned int SYSCLK_SHAPE; // 0x00000050U
+ volatile unsigned int SDRAMCLK_SHAPE; // 0x00000054U
+ volatile unsigned int RING_OSZI; // 0x00000058U
+} *P2001_TIMER_regs_ptr;
+#define P2001_TIMER ((volatile P2001_TIMER_regs_ptr) 0x00110000)
+
+typedef struct { // 0x00120000U
+ volatile unsigned int reserved1[0x5];
+ volatile unsigned int GPIO_Config; // 0x00000014U
+ volatile unsigned int GPIO_INT; // 0x00000018U
+ volatile unsigned int GPIO_Out; // 0x0000001CU
+ volatile unsigned int GPIO_IN; // 0x00000020U
+ volatile unsigned int GPIO_En; // 0x00000024U
+ volatile unsigned int PIN_MUX; // 0x00000028U
+ volatile unsigned int NRES_OUT; // 0x0000002CU
+ volatile unsigned int GPIO2_Out; // 0x00000030U
+ volatile unsigned int GPIO2_IN; // 0x00000034U
+ volatile unsigned int GPIO2_En; // 0x00000038U
+ volatile unsigned int GPIO_INT_SEL; // 0x0000003CU
+ volatile unsigned int GPI3_IN; // 0x00000040U
+ volatile unsigned int GPO4_OUT; // 0x00000044U
+} *P2001_GPIO_regs_ptr;
+#define P2001_GPIO ((volatile P2001_GPIO_regs_ptr) 0x00120000)
+
+typedef struct { // 0x00130000U
+ volatile unsigned int Main_NFIQ_Int_Ctrl; // 0x00000000U
+ volatile unsigned int Main_NIRQ_Int_Ctrl; // 0x00000004U
+ volatile unsigned int Status_NFIQ; // 0x00000008U
+ volatile unsigned int Status_NIRQ; // 0x0000000CU
+} *P2001_INT_CTRL_regs_ptr;
+#define P2001_INT_CTRL ((volatile P2001_INT_CTRL_regs_ptr) 0x00130000)
+
+typedef union { // 0x00140000U
+ struct { // write
+ volatile unsigned int TX1; // 0x00000000U
+ volatile unsigned int TX2; // 0x00000004U
+ volatile unsigned int TX3; // 0x00000008U
+ volatile unsigned int TX4; // 0x0000000CU
+ volatile unsigned int Baudrate; // 0x00000010U
+ volatile unsigned int reserved1[0x3];
+ volatile unsigned int Config; // 0x00000020U
+ volatile unsigned int Clear; // 0x00000024U
+ volatile unsigned int Echo_EN; // 0x00000028U
+ volatile unsigned int IRQ_Status; // 0x0000002CU
+ } w; // write
+
+ struct { // read
+ volatile unsigned int RX1; // 0x00000000U
+ volatile unsigned int RX2; // 0x00000004U
+ volatile unsigned int RX3; // 0x00000008U
+ volatile unsigned int RX4; // 0x0000000CU
+ volatile unsigned int reserved1[0x4];
+ volatile unsigned int PRE_STATUS; // 0x00000020U
+ volatile unsigned int STATUS; // 0x00000024U
+ volatile unsigned int reserved2[0x1];
+ volatile unsigned int IRQ_Status; // 0x0000002CU
+ } r; // read
+} *P2001_UART_regs_ptr;
+#define P2001_UART ((volatile P2001_UART_regs_ptr) 0x00140000)
+
+typedef struct { // 0x0018_000U _=0,1,2,3
+ volatile DMA_DSC * RMAC_DMA_DESC; // 0x00000000U
+ volatile unsigned int RMAC_DMA_CNTL; // 0x00000004U
+ volatile unsigned int RMAC_DMA_STAT; // 0x00000008U
+ volatile unsigned int RMAC_DMA_EN; // 0x0000000CU
+ volatile unsigned int RMAC_CNTL; // 0x00000010U
+ volatile unsigned int RMAC_TLEN; // 0x00000014U
+ volatile unsigned int RMAC_PHYU; // 0x00000018U
+ volatile unsigned int RMAC_PHYL; // 0x0000001CU
+ volatile unsigned int RMAC_PFM0; // 0x00000020U
+ volatile unsigned int RMAC_PFM1; // 0x00000024U
+ volatile unsigned int RMAC_PFM2; // 0x00000028U
+ volatile unsigned int RMAC_PFM3; // 0x0000002CU
+ volatile unsigned int RMAC_PFM4; // 0x00000030U
+ volatile unsigned int RMAC_PFM5; // 0x00000034U
+ volatile unsigned int RMAC_PFM6; // 0x00000038U
+ volatile unsigned int RMAC_PFM7; // 0x0000003CU
+ volatile unsigned int RMAC_MIB0; // 0x00000040U
+ volatile unsigned int RMAC_MIB1; // 0x00000044U
+ volatile unsigned int RMAC_MIB2; // 0x00000048U
+ volatile unsigned int RMAC_MIB3; // 0x0000004CU
+ volatile unsigned int RMAC_MIB4; // 0x00000050U
+ volatile unsigned int RMAC_MIB5; // 0x00000054U
+ volatile unsigned int reserved1[0x1e8];
+ volatile unsigned int RMAC_DMA_DATA; // 0x000007F8U
+ volatile unsigned int RMAC_DMA_ADR; // 0x000007FCU
+ volatile DMA_DSC * TMAC_DMA_DESC; // 0x00000800U
+ volatile unsigned int TMAC_DMA_CNTL; // 0x00000804U
+ volatile unsigned int TMAC_DMA_STAT; // 0x00000808U
+ volatile unsigned int TMAC_DMA_EN; // 0x0000080CU
+ volatile unsigned int TMAC_CNTL; // 0x00000810U
+ volatile unsigned int TMAC_MIB6; // 0x00000814U
+ volatile unsigned int TMAC_MIB7; // 0x00000818U
+ volatile unsigned int reserved2[0x1];
+ volatile unsigned int MU_CNTL; // 0x00000820U
+ volatile unsigned int MU_DATA; // 0x00000824U
+ volatile unsigned int MU_DIV; // 0x00000828U
+ volatile unsigned int CONF_RMII; // 0x0000082CU
+ volatile unsigned int reserved3[0x1f2];
+ volatile unsigned int TMAC_DMA_DATA; // 0x00000FF8U
+ volatile unsigned int TMAC_DMA_ADR; // 0x00000FFCU
+} *P2001_ETH_regs_ptr;
+#define P2001_EU0 ((volatile P2001_ETH_regs_ptr) 0x00180000)
+#define P2001_EU1 ((volatile P2001_ETH_regs_ptr) 0x00181000)
+#define P2001_EU2 ((volatile P2001_ETH_regs_ptr) 0x00182000)
+#define P2001_EU3 ((volatile P2001_ETH_regs_ptr) 0x00183000)
+#define P2001_MU P2001_EU0
+
+#endif
+
+#endif /* ARCH_HARDWARE_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ETHERBOOT_ARM_HOOKS_H
+#define ETHERBOOT_ARM_HOOKS_H
+
+struct Elf_Bhdr;
+
+#define arch_main(data, params) do {} while(0)
+//void arch_main(in_call_data_t *data, va_list params);
+
+#define arch_on_exit(status) do {} while(0)
+//void arch_on_exit(int status);
+
+#define arch_relocate_to(addr) do {} while(0)
+//void arch_relocate_to(unsigned long addr);
+
+#define arch_relocated_from(old_addr) do {} while(0)
+//void arch_relocate_from(unsigned long old_addr);
+
+#endif /* ETHERBOOT_ARM_HOOKS_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ETHERBOOT_IO_H
+#define ETHERBOOT_IO_H
+
+#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
+#define phys_to_virt(vaddr) ((void *) (vaddr))
+
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+#define iounmap(addr) ((void)0)
+#define ioremap(physaddr, size) (physaddr)
+
+extern unsigned char inb (unsigned long int port);
+extern unsigned short int inw (unsigned long int port);
+extern unsigned long int inl (unsigned long int port);
+extern void outb (unsigned char value, unsigned long int port);
+extern void outw (unsigned short value, unsigned long int port);
+extern void outl (unsigned long value, unsigned long int port);
+
+#endif /* ETHERBOOT_IO_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef LATCH_H
+#define LATCH_H
+
+// Freerun_Timer is always at 12.288 MHZ
+#define TICKS_PER_SEC (12288000UL)
+//#define TICKS_PER_SEC (73728000UL)
+
+#endif /* LATCH_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LIMITS_H
+#define __LIMITS_H 1
+
+#define MB_LEN_MAX 16
+
+#define CHAR_BIT 8
+
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+#define UCHAR_MAX 255
+
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+#define USHRT_MAX 65535
+
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+#define UINT_MAX 4294967295U
+
+#define LONG_MAX 2147483647L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+#define ULONG_MAX 4294967295UL
+
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LLONG_MAX - 1LL)
+
+#define ULLONG_MAX 18446744073709551615ULL
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Intel LXT971ALE (MII-compatible PHY)
+ */
+
+#define Adr_LXT971A_Control 0 /* Control Register */
+#define Adr_LXT971A_Status1 1 /* MII Status Register #1 */
+#define Adr_LXT971A_PHY_ID1 2 /* PHY Identification Register 1 */
+#define Adr_LXT971A_PHY_ID2 3 /* PHY Identification Register 2 */
+#define Adr_LXT971A_AN_Advertise 4 /* Auto Negotiation Advertisement Register */
+#define Adr_LXT971A_AN_Link_Ability 5 /* Auto Negotiation Link Partner Base Page Ability Register */
+#define Adr_LXT971A_AN_Expansion 6 /* Auto Negotiation Expansion */
+#define Adr_LXT971A_AN_Next_Page_Txmit 7 /* Auto Negotiation Next Page Transmit Register */
+#define Adr_LXT971A_AN_Link_Next_Page 8 /* Auto Negotiation Link Partner Next Page Receive Register */
+#define Adr_LXT971A_Fast_Control 9 /* Not Implemented */
+#define Adr_LXT971A_Fast_Status 10 /* Not Implemented */
+#define Adr_LXT971A_Extended_Status 15 /* Not Implemented */
+#define Adr_LXT971A_Port_Config 16 /* Configuration Register */
+#define Adr_LXT971A_Status2 17 /* Status Register #2 */
+#define Adr_LXT971A_Interrupt_Enable 18 /* Interrupt Enable Register */
+#define Adr_LXT971A_Interrupt_Status 19 /* Interrupt Status Register */
+#define Adr_LXT971A_LED_Config 20 /* LED Configuration Register */
+#define Adr_LXT971A_Transmit_Control 30 /* Transmit Control Register */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ETHERBOOT_SETJMP_H
+#define ETHERBOOT_SETJMP_H
+
+#ifndef __ASSEMBLER__
+/* Jump buffer contains v1-v6, sl, fp, sp and pc. Other registers are not
+ saved. */
+//typedef int jmp_buf[22];
+typedef int jmp_buf[10];
+#endif
+
+extern int sigsetjmp(jmp_buf __env, int __savemask);
+extern void longjmp(jmp_buf __env, int __val) __attribute__((__noreturn__));
+
+#define setjmp(env) sigsetjmp(env,0)
+
+#endif /* ETHERBOOT_SETJMP_H */
--- /dev/null
+/*
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+#endif /* STDINT_H */
--- /dev/null
+# Config for e1 Etherboot
+#
+
+CFLAGS+= -mgnu-param -DCONSOLE_SERIAL -DCOMCONSOLE=0x01C00000 -DCONSPEED=28800
+CFLAGS+= -DSIZEINDICATOR -DNO_DHCP_SUPPORT -DBAR_PROGRESS
+#CFLAGS+= -DEMBEDDED -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
+
--- /dev/null
+ARCH_FORMAT= coff-e1
+
+BUILD_ROMS= $(ROMS)
+BUILD_COFFS= $(patsubst %img, %coff, $(IMGS))
+SUFFIXES+= rom zrom coff
+
+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
+
+# DMAC_HW_ADDR_DRV holds the ethernet's MAC address. It is passed as
+# flag to the low level driver instead of reading it from an
+# external EEPROM, which we do not have!
+EXTRA_CFLAGS = -DEMBEDDED -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
+
+START= $(BIN)/start.o
+START16= $(BIN)/start.o
+
+SRCS+= arch/e1/core/e132_xs.c
+SRCS+= arch/e1/core/e1_timer.c
+SRCS+= arch/e1/core/longjmp.c
+SRCS+= arch/e1/core/memcmp.S
+SRCS+= arch/e1/core/memcpy.S
+SRCS+= arch/e1/core/memset.S
+SRCS+= arch/e1/core/setjmp.c
+SRCS+= arch/e1/core/strcmp.S
+SRCS+= arch/e1/core/start.S
+
+ROMLIMIT:=3276800
+
+include $(BIN)/Roms
+
+ROMS= $(BIN)/cs89x0.rom
+IMGS= $(BIN)/cs89x0.img
+
+#allfiles: $(BUILD_ROMS)
+all: $(BUILD_COFFS)
+
+BOBJS+= $(BIN)/e1_timer.o
+BOBJS+= $(BIN)/memcmp.o $(BIN)/memcpy.o $(BIN)/memset.o
+BOBJS+= $(BIN)/setjmp.o $(BIN)/longjmp.o
+BOBJS+= $(BIN)/e132_xs.o
+
+# Utilities
+
+$(BIN)/nrv2b: util/nrv2b.c
+ $(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
+
+# Pattern Rules
+# General for compiling/assembly source files
+$(BIN)/cs89x0.o: drivers/net/cs89x0.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
+# With the current tools we have problem with the compilation
+# of the vsprintf file when the -O2 is selected. So we compile
+# the aforemntioned file with -O1 !!!
+$(BIN)/vsprintf.o: core/vsprintf.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) -O1 -o $@ -c $<
+
+$(BIN)/%.o: arch/e1/core/%.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+$(BIN)/%.o: arch/e1/core/%.S $(MAKEDEPS)
+ $(CPP) $(CFLAGS) -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
+
+$(BIN)/%.coff: $(BIN)/%.tmp $(MAKEDEPS)
+ mv $< $(BIN)/etherboot.coff
--- /dev/null
+ARCH_FORMAT= coff-e1
+
+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
+
+EXTRA_CFLAGS = -DEMBEDDED -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
+
+BUILD_ROMS= $(ROMS)
+BUILD_COFFS= $(BIN)/cs89x0.coff
+#BUILD_COFFS= $(patsubst %img, %coff, $(IMGS))
+
+START= $(BIN)/start.o
+START16= $(BIN)/start.o
+
+#SRCS+= arch/e1/core/coff_loader.c
+SRCS+= arch/e1/core/e132_xs.c
+SRCS+= arch/e1/core/e1_timer.c
+SRCS+= arch/e1/core/longjmp.c
+SRCS+= arch/e1/core/memcmp.S
+SRCS+= arch/e1/core/memcpy.S
+SRCS+= arch/e1/core/memset.S
+SRCS+= arch/e1/core/setjmp.c
+SRCS+= arch/e1/core/strcmp.S
+SRCS+= arch/e1/core/start.S
+
+ROMLIMIT:=3276800
+
+include $(BIN)/Roms
+
+hyperstone: $(BUILD_COFFS)
+coff: $(BUILD_COFFS)
+
+BOBJS+= $(BIN)/e1_timer.o
+BOBJS+= $(BIN)/memcmp.o $(BIN)/memcpy.o $(BIN)/memset.o
+BOBJS+= $(BIN)/setjmp.o $(BIN)/longjmp.o
+BOBJS+= $(BIN)/e132_xs.o
+
+# Utilities
+
+$(BIN)/nrv2b: util/nrv2b.c
+ $(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 -o $@ $<
+
+# Pattern Rules
+# General for compiling/assembly source files
+
+$(BIN)/cs89x0.o: drivers/net/cs89x0.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
+# With the current tools we have problem with the compilation
+# of the vsprintf file when the -O2 is selected. So we compile
+# the aforemntioned file with -O1 !!!
+$(BIN)/vsprintf.o: core/vsprintf.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) -O1 -o $@ -c $<
+
+$(BIN)/%.o: arch/e1/core/%.c $(MAKEDEPS)
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+$(BIN)/%.o: arch/e1/core/%.S $(MAKEDEPS)
+ $(CPP) $(CFLAGS) -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
+
+$(BIN)/%.coff: $(BIN)/%.tmp $(MAKEDEPS)
+ mv $< $(BIN)/etherboot.coff
+
--- /dev/null
+Introduction
+---------------------
+This README file provides guideliness to compile successfully the
+Etherboot for Hyperstone.
+This directory (src/arch/e1) contains the files that depend on
+Hyperstone's architecture. The header files that include the
+configuration of the system are based on Hyperstone's E132-XS
+development board. The can be very easily modified to support
+anyother configuration environment.
+
+Software Perquisites:
+---------------------
+The build environment requires a C compiler for the E1-32XS
+processor. Normally you can simply install a cross-compiling tool
+chain based on the GNU tools (that is binutils and gcc). If you
+are running a Linux system on a x86 CPU then you can just download
+the toolchain as a binary from Hyperstone's official web-site. The
+binary distribution will untar the tools in the /usr/local/e1-coff
+directory. On any other system you will need to build the tool
+chain from the sources.
+
+To compile successfully the following tools should be available:
+ - GNU toolchain:
+ - GCC ver 2.95.2 20030110 (release) e1-coff-gcc -v
+ - LD ver 2.12.90 20020726 e1-coff-ld -V
+
+Hardware Perquisites:
+---------------------
+The etherboot has been successfully tested in the E1-32XS
+development board. A second serial device is initialized
+to act as a console. The standard messages
+are redirected to the console. Nevertheless, if one wants not
+to use the serial console he may omit the corresponding switches
+from the Config file located under "src/arch/e1/" directory.
+
+On the E1-32XS board that was used, a daughter-board was employed
+to connect a second HyIce to the development board. Since the HyIce
+embeds a standard 16550 device, the Etherboot's standard device
+driver is used.
+
+The position of the jumpers of the development board in order to
+initialize both the second HyIce and the Ethernet device is
+depicted in the following table:
+
+Jumper: Position
+------:--------------
+J3 1-2 (default)
+J4 1-2 (default)
+J13 5-6
+J5 1-2 (default)
+J6 1-2 & 3-4
+J7 3-4
+J9 1-2 (default)
+J10 1-2
+J11 3-4
+
+Compilation
+---------------------
+In order to compile Etherboot for Hyperstone, the following steps should be followed:
+1) Edit the main Makefile (located under "src" directory") and comment-out
+the ARCH variable (by putting a "#" in front of it). Append the following line:
+ARCH:=e1
+2) Edit the Config file (the one located under "src" directory) and make sure that
+the CFLAGS variable will contain *only* the following swithces:
+CFLAGS+= -DCONFIG_ISA
+CFLAGS+= -DBOOT_FIRST=BOOT_NIC
+CFLAGS+= -DALLOW_ONLY_ENCAPSULATED
+CFLAGS+= -DBACKOFF_LIMIT=7 -DCONGESTED
+CFLAGS+= -DCOFF_IMAGE
+CFLAGS+= -DDOWNLOAD_PROTO_TFTP
+Please note that extra or any other switches may cause failure of compilation!
+3) type "make hyperstone" or "make coff"
+4) the generated file will be located under the "src/bin" directory and will be called :
+ "etherboot.coff". Now you may download it with usual way using e1-coff-gdb ..
+
+Have Fun
+
+Yannis Mitsos, George Thanos
+{gmitsos,gthanos}@telecom.ntua.gr
+
--- /dev/null
+/*
+ * Copyright 2003 Yannis Mitsos and George Thanos
+ * {gmitsos@gthanos}@telecom.ntua.gr
+ * Released under GPL2, see the file COPYING in the top directory
+ * COFF loader is based on the source code of the ELF loader.
+ *
+ */
+#include "coff.h"
+
+#define COFF_DEBUG 0
+
+typedef struct {
+ COFF_filehdr coff32;
+ COFF_opthdr opthdr32;
+ union {
+ COFF_scnhdr scnhdr32[1];
+ unsigned char dummy[1024];
+ } p;
+ unsigned long curaddr;
+ signed int segment; /* current segment number, -1 for none */
+ unsigned int loc; /* start offset of current block */
+ unsigned int skip; /* padding to be skipped to current segment */
+ unsigned long toread; /* remaining data to be read in the segment */
+}coff_state;
+
+coff_state cstate;
+
+static sector_t coff32_download(unsigned char *data, unsigned int len, int eof);
+static inline os_download_t coff_probe(unsigned char *data, unsigned int len)
+{
+ unsigned long phdr_size;
+
+ if (len < (sizeof(cstate.coff32)+ sizeof(cstate.opthdr32))) {
+ return 0;
+ }
+ memcpy(&cstate.coff32, data, (sizeof(cstate.coff32)+sizeof(cstate.opthdr32)));
+
+ if ((cstate.coff32.f_magic != EM_E1) ||
+ (cstate.opthdr32.magic != O_MAGIC)){
+ return 0;
+ }
+ printf("(COFF");
+ printf(")... \n");
+
+ if (cstate.coff32.f_opthdr == 0){
+ printf("No optional header in COFF file, cannot find the entry point\n");
+ return dead_download;
+ }
+
+ phdr_size = cstate.coff32.f_nscns * sizeof(cstate.p.scnhdr32);
+ if (sizeof(cstate.coff32) + cstate.coff32.f_opthdr + phdr_size > len) {
+ printf("COFF header outside first block\n");
+ return dead_download;
+ }
+
+ memcpy(&cstate.p.scnhdr32, data + (sizeof(cstate.coff32) + cstate.coff32.f_opthdr), phdr_size);
+
+ /* Check for Etherboot related limitations. Memory
+ * between _text and _end is not allowed.
+ * Reasons: the Etherboot code/data area.
+ */
+ for (cstate.segment = 0; cstate.segment < cstate.coff32.f_nscns; cstate.segment++) {
+ unsigned long start, mid, end, istart, iend;
+
+ if ((cstate.p.scnhdr32[cstate.segment].s_flags != S_TYPE_TEXT) &&
+ (cstate.p.scnhdr32[cstate.segment].s_flags != S_TYPE_DATA) &&
+ (cstate.p.scnhdr32[cstate.segment].s_flags != S_TYPE_BSS)){ /* Do we realy need to check the BSS section ? */
+#ifdef COFF_DEBUG
+ printf("Section <%s> in not a loadable section \n",cstate.p.scnhdr32[cstate.segment].s_name);
+#endif
+ continue;
+ }
+
+ start = cstate.p.scnhdr32[cstate.segment].s_paddr;
+ mid = start + cstate.p.scnhdr32[cstate.segment].s_size;
+ end = start + cstate.p.scnhdr32[cstate.segment].s_size;
+
+ /* Do we need the following variables ? */
+ istart = 0x8000;
+ iend = 0x8000;
+
+ if (!prep_segment(start, mid, end, istart, iend)) {
+ return dead_download;
+ }
+}
+ cstate.segment = -1;
+ cstate.loc = 0;
+ cstate.skip = 0;
+ cstate.toread = 0;
+ return coff32_download;
+}
+
+extern int mach_boot(unsigned long entry_point);
+static sector_t coff32_download(unsigned char *data, unsigned int len, int eof)
+{
+ unsigned long skip_sectors = 0;
+ unsigned int offset; /* working offset in the current data block */
+ int i;
+
+ offset = 0;
+ do {
+ if (cstate.segment != -1) {
+ if (cstate.skip) {
+ if (cstate.skip >= len - offset) {
+ cstate.skip -= len - offset;
+ break;
+ }
+ offset += cstate.skip;
+ cstate.skip = 0;
+ }
+
+ if (cstate.toread) {
+ unsigned int cplen;
+ cplen = len - offset;
+ if (cplen >= cstate.toread) {
+ cplen = cstate.toread;
+ }
+ memcpy(phys_to_virt(cstate.curaddr), data+offset, cplen);
+ cstate.curaddr += cplen;
+ cstate.toread -= cplen;
+ offset += cplen;
+ if (cstate.toread)
+ break;
+ }
+ }
+
+ /* Data left, but current segment finished - look for the next
+ * segment (in file offset order) that needs to be loaded.
+ * We can only seek forward, so select the program headers,
+ * in the correct order.
+ */
+ cstate.segment = -1;
+ for (i = 0; i < cstate.coff32.f_nscns; i++) {
+
+ if ((cstate.p.scnhdr32[i].s_flags != S_TYPE_TEXT) &&
+ (cstate.p.scnhdr32[i].s_flags != S_TYPE_DATA))
+ continue;
+ if (cstate.p.scnhdr32[i].s_size == 0)
+ continue;
+ if (cstate.p.scnhdr32[i].s_scnptr < cstate.loc + offset)
+ continue; /* can't go backwards */
+ if ((cstate.segment != -1) &&
+ (cstate.p.scnhdr32[i].s_scnptr >= cstate.p.scnhdr32[cstate.segment].s_scnptr))
+ continue; /* search minimum file offset */
+ cstate.segment = i;
+ }
+
+ if (cstate.segment == -1) {
+ /* No more segments to be loaded, so just start the
+ * kernel. This saves a lot of network bandwidth if
+ * debug info is in the kernel but not loaded. */
+ goto coff_startkernel;
+ break;
+ }
+ cstate.curaddr = cstate.p.scnhdr32[cstate.segment].s_paddr;
+ cstate.skip = cstate.p.scnhdr32[cstate.segment].s_scnptr - (cstate.loc + offset);
+ cstate.toread = cstate.p.scnhdr32[cstate.segment].s_size;
+#if COFF_DEBUG
+ printf("PHDR %d, size %#lX, curaddr %#lX\n",
+ cstate.segment, cstate.toread, cstate.curaddr);
+#endif
+ } while (offset < len);
+
+ cstate.loc += len + (cstate.skip & ~0x1ff);
+ skip_sectors = cstate.skip >> 9;
+ cstate.skip &= 0x1ff;
+
+ if (eof) {
+ unsigned long entry;
+coff_startkernel:
+ entry = cstate.opthdr32.entry;
+ done();
+ mach_boot(entry);
+ }
+ return skip_sectors;
+}
--- /dev/null
+/*
+ * Copyright 2003 Yannis Mitsos and George Thanos
+ * {gmitsos@gthanos}@telecom.ntua.gr
+ * Released under GPL2, see the file COPYING in the top directory
+ *
+ */
+#include "hooks.h"
+#include "io.h"
+#include "etherboot.h"
+#include "e132_xs_board.h"
+
+unsigned int io_periph[NR_CS] = {[0 ... NR_CS-1] = 0 };
+
+/*
+void arch_main(struct Elf_Bhdr *ptr __unused)
+{
+
+}
+*/
+
+void init_peripherals(void)
+{
+ int i;
+
+ for(i=0; i< NR_CS; i++){
+ io_periph[i]= (SLOW_IO_ACCESS | i << 22);
+ }
+
+ io_periph[ETHERNET_CS] = (io_periph[ETHERNET_CS] | 1 << IOWait);
+
+ asm volatile("
+ ori SR, 0x20
+ movi FCR, 0x66ffFFFF"
+ :
+ :);
+}
+
+struct meminfo meminfo;
+void get_memsizes(void)
+{
+/* We initialize the meminfo structure
+ * according to our development board's specs
+ * We do not have a way to automatically probe the
+ * memspace instead we initialize it manually
+ */
+ meminfo.basememsize = BASEMEM;
+ meminfo.memsize = SDRAM_SIZE;
+ meminfo.map_count = NR_MEMORY_REGNS;
+
+ meminfo.map[0].addr = SDRAM_BASEMEM;
+ meminfo.map[0].size = SDRAM_SIZE;
+ meminfo.map[0].type = E820_RAM;
+ meminfo.map[1].addr = SRAM_BASEMEM;
+ meminfo.map[1].size = SRAM_SIZE;
+ meminfo.map[1].type = E820_RAM;
+ meminfo.map[2].addr = IRAM_BASEMEM;
+ meminfo.map[2].size = IRAM_SIZE;
+ meminfo.map[2].type = E820_RAM;
+}
+
+int mach_boot(register unsigned long entry_point)
+{
+ asm volatile(
+ "mov PC, %0"
+ : /* no outputs */
+ : "l" (entry_point) );
+ return 0; /* We should never reach this point ! */
+
+}
+
--- /dev/null
+/*
+ * Copyright 2003 Yannis Mitsos and George Thanos
+ * {gmitsos@gthanos}@telecom.ntua.gr
+ * Released under GPL2, see the file COPYING in the top directory
+ *
+ */
+#include "etherboot.h"
+#include "timer.h"
+#include "e132_xs_board.h"
+
+/* get timer returns the contents of the timer */
+static inline unsigned long get_timer(void)
+{
+ unsigned long result;
+ __asm__ __volatile__("
+ ORI SR, 0x20
+ mov %0, TR"
+ : "=l"(result));
+ return result;
+}
+
+/* ------ Calibrate the TSC -------
+ * Time how long it takes to excute a loop that runs in known time.
+ * And find the convertion needed to get to CLOCK_TICK_RATE
+ */
+
+static unsigned long configure_timer(void)
+{
+ unsigned long TPR_value; /* Timer Prescalar Value */
+
+ TPR_value = 0x000C00000;
+
+ asm volatile ("
+ FETCH 4
+ ORI SR, 0x20
+ MOV TPR, %0
+ ORI SR, 0x20
+ MOVI TR, 0x0"
+ : /* no outputs */
+ : "l" (TPR_value)
+ );
+
+ printf("The time prescaler register is set to: <%#x>\n",TPR_value);
+ return (1);
+}
+
+static unsigned long clocks_per_tick;
+
+void setup_timers(void)
+{
+ if (!clocks_per_tick) {
+ clocks_per_tick = configure_timer();
+ }
+}
+
+unsigned long currticks(void)
+{
+ return get_timer()/clocks_per_tick;
+}
+
+static unsigned long timer_timeout;
+static int __timer_running(void)
+{
+ return get_timer() < timer_timeout;
+}
+
+void udelay(unsigned int usecs)
+{
+ unsigned long now;
+ now = get_timer();
+ timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
+ while(__timer_running());
+}
+void ndelay(unsigned int nsecs)
+{
+ unsigned long now;
+ now = get_timer();
+ timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
+ while(__timer_running());
+}
+
+void load_timer2(unsigned int timer2_ticks)
+{
+ unsigned long now;
+ unsigned long clocks;
+ now = get_timer();
+ clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
+ timer_timeout = now + clocks;
+}
+
+int timer2_running(void)
+{
+ return __timer_running();
+}
--- /dev/null
+/* Default linker script, for normal executables */
+OUTPUT_FORMAT("coff-e1-big")
+MEMORY
+ {
+ romvec : ORIGIN = 0x2000000, LENGTH = 0x0000400
+ flash : ORIGIN = 0xE0000000, LENGTH = 0x20000
+ eflash : ORIGIN = 0x2200000, LENGTH = 0x20000
+ ram : ORIGIN = 0x00000000, LENGTH = 0x1000000
+ eram16MB : ORIGIN = 0x01000000, LENGTH = 0
+ sram : ORIGIN = 0x40000000, LENGTH = 0x40000
+ iram : ORIGIN = 0xC0000000, LENGTH = 0x4000
+ }
+
+SEARCH_DIR("/usr/local/e1-coff/lib");
+ENTRY(Main)
+MEM0start = 0x00000000;
+MEM0size = 0x40000000;
+MEM1start = 0x40000000;
+MEM1size = 0x40000000;
+MEM2start = 0x80000000;
+MEM2size = 0x40000000;
+IRAMstart = 0xC0000000;
+IRAMsize = 0x20000000;
+MEM3start = 0xE0000000;
+MEM3size = 0x20000000;
+Stack1Reserve = 560;
+_Stack1Size = DEFINED(_Stack1Size)? _Stack1Size : 1*1024;
+_Stack2Size = DEFINED(_Stack2Size)? _Stack2Size : 16*1024;
+_Stack1Base = DEFINED(_Stack1Base)? _Stack1Base : __bss_end__;
+_Stack2Base = DEFINED(_Stack2Base)? _Stack2Base : __bss_end__ + _Stack1Size + Stack1Reserve;
+_Mem0HeapBase = DEFINED(_Mem0HeapBase)? _Mem0HeapBase : _Stack2Base + _Stack2Size;
+_Mem1HeapBase = DEFINED(_Mem1HeapBase)? _Mem1HeapBase : 0;
+Priority = DEFINED(Priority) ? Priority : 31;
+TextBase = DEFINED(TextBase) ? TextBase : 0xa00000;
+SECTIONS
+{
+ .G6 (DEFINED(G6Base) ? G6Base : 0x9000) : {
+ *(.G6)
+ }
+ .G7 (DEFINED(G7Base) ? G7Base : 0x40001000) : {
+ *(.G7)
+ }
+ .G8 (DEFINED(G8Base) ? G8Base : 0xC0000000) : {
+ *(.G8)
+ }
+ .G9 (DEFINED(G9Base) ? G9Base : 0) : {
+ *(.G9)
+ }
+ .G10 (DEFINED(G10Base) ? G10Base : 0) : {
+ *(.G10)
+ }
+ .G11 (DEFINED(G11Base) ? G11Base : 0) : {
+ *(.G11)
+ }
+ .G12 (DEFINED(G12Base) ? G12Base : 0) : {
+ *(.G12)
+ }
+ .G13 (DEFINED(G13Base) ? G13Base : 0) : {
+ *(.G13)
+ }
+
+ .text TextBase : {
+ __virt_start = .;
+ __text = . ;
+ *(.text)
+ *(.fini)
+ . = ALIGN(16);
+ _isa_drivers = . ;
+ *(.drivisa);
+ _isa_drivers_end = . ;
+ . = ALIGN(16);
+
+ *(.init)
+ _etext = . ;
+ /* _init = DEFINED(_init) ? _init : 0; */
+ /* _fini = DEFINED(_fini) ? _fini : 0; */
+ /* _argc = DEFINED(_argc) ? _argc : 0; */
+ /* _argv = DEFINED(_argv) ? _argv : 0; */
+ /* _envp = DEFINED(_envp) ? _envp : 0; */
+ /* _hwinit = DEFINED(_hwinit) ? _hwinit : 0; */
+ /* _atexit = DEFINED(_atexit) ? _atexit : 0; */
+ G6Size = SIZEOF(.G6);
+ G7Size = SIZEOF(.G7);
+ G8Size = SIZEOF(.G8);
+ G9Size = SIZEOF(.G9);
+ G10Size = SIZEOF(.G10);
+ G11Size = SIZEOF(.G11);
+ G12Size = SIZEOF(.G12);
+ G13Size = SIZEOF(.G13);
+
+}
+
+ .data SIZEOF(.text) + ADDR(.text) : {
+ *(.data)
+ _edata = . ;
+}
+
+ .bss SIZEOF(.data) + ADDR(.data) :
+ {
+ __bss_start__ = ALIGN( 0x10 ) ;
+ __bss = . ;
+ *(.bss)
+ *(COMMON)
+ __end = . ;
+ __bss_end__ = ALIGN( 0x10 ) ;
+ __ebss = . ;
+ }
+
+.eram16MB :
+ {
+ ___ramend = . - 0x7000;
+ } > eram16MB
+
+ .stab 0 (NOLOAD) :
+ {
+ [ .stab ]
+ }
+ .stabstr 0 (NOLOAD) :
+ {
+ [ .stabstr ]
+ }
+ _GOT_ 0 (NOLOAD) :
+ {
+ [ _GOT_ ]
+ }
+}
--- /dev/null
+/*
+ * Copyright 2003 Yannis Mitsos and George Thanos
+ * {gmitsos@gthanos}@telecom.ntua.gr
+ * Released under GPL2, see the file COPYING in the top directory
+ *
+ */
+#include "setjmp.h"
+
+unsigned long jmpbuf_ptr;
+
+void longjmp(jmp_buf state, int value )
+{
+ if(!value)
+ state->__jmpbuf->ReturnValue = 1;
+ else
+ state->__jmpbuf->ReturnValue = value;
+
+ jmpbuf_ptr = (unsigned long)state;
+
+#define _state_ ((struct __jmp_buf_tag*)jmpbuf_ptr)
+ asm volatile("mov L0, %0\n\t"
+ "mov L1, %1\n\t"
+ "mov L2, %2\n\t"
+ "mov G3, %3\n\t"
+ "mov G4, %4\n\t"
+ "ret PC, L1\n\t"
+ :/*no output*/
+ :"l"(_state_->__jmpbuf->ReturnValue),
+ "l"(_state_->__jmpbuf->SavedPC),
+ "l"(_state_->__jmpbuf->SavedSR),
+ "l"(_state_->__jmpbuf->G3),
+ "l"(_state_->__jmpbuf->G4)
+ :"%G3", "%G4", "%L0", "%L1" );
+#undef _state_
+}
--- /dev/null
+/*
+ * Derived from the Hyperstone's library source code.
+ * Modefied src in order to apply the -mgnu-param compiler option.
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
+ * George Thanos <gthanos@telecom.ntua.gr>
+ */
+ .text
+ .align 2
+ .global _memcmp
+
+;ENTRY (_memcmp)
+_memcmp:
+ FRAME L9, L3 # get incoming parameters
+ CMPBI L2,3 # check word alignment
+ BNZ byte_compare
+ CMPBI L1,3 # check word alignment
+ BNZ byte_compare
+
+double_compare:
+ ADDI L0, -8
+ BLT is_equal
+ LDD.P L1, L5
+ LDD.P L2, L7
+ SUB L5, L7
+ DBNZ corr_8
+ SUB L6, L8
+ BZ double_compare
+ ADDI L0, 4
+ ADDI L2, -4
+ ADDI L1, -4
+ BR byte_compare
+
+corr_8: ADDI L0, 8
+ ADDI L2, -8
+ ADDI L1, -8
+byte_compare:
+ ADDI L0, -1
+ BLT equal
+ LDBU.N L2, L5, 1 # Load and compare bytes
+ LDBU.N L1, L6, 1
+ SUB L5, L6
+ BZ byte_compare
+ MOV L2, L5
+ RET PC, L3
+
+is_equal: CMPI L0, -8
+ DBNE byte_compare
+ ADDI L0, 8
+equal:
+ MOVI L2, 0
+ RET PC, L3
+
+ .END
+
--- /dev/null
+/*
+ * Derived from the Hyperstone's library source code.
+ * Modefied src in order to apply the -mgnu-param compiler option.
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
+ * George Thanos <gthanos@telecom.ntua.gr>
+ */
+ .text
+ .align 2
+ .global _memcpy
+;ENTRY(_memcpy)
+_memcpy:
+ FRAME L8, L3
+ MOV L7, L2 # Save for return
+
+#*****************************
+# Perform byte copy if both
+# not on a word alignment
+#*****************************
+ CMPBI L2, 3 # check word alignment
+ BNZ mem_except
+ CMPBI L1, 3 # check word alignment
+ BNZ mem_except
+
+#*****************************
+# Copy Double,Word,Halfword,
+# then byte
+#*****************************
+DBL_LOOP:
+ CMPI L0, 8 # Copy Doubles
+ BLT DO_WORD
+ LDD.P L1, L5
+ ADDI L0, -8
+ DBR DBL_LOOP
+ STD.P L2, L5
+
+DO_WORD:
+ CMPI L0, 4 # Copy leftover word
+ BLT DO_HALF
+ LDW.P L1, L5
+ ADDI L0, -4
+ DBZ DONE # Done if L0 is 0
+ STW.P L2, L5
+
+DO_HALF:
+ CMPI L0, 2 # Copy leftover byte
+ BLT DO_BYTE
+ LDHU.N L1, L5, 2
+ ADDI L0, -2
+ DBZ DONE # Done if L0 is 0
+ STHU.N L2, L5, 2
+
+DO_BYTE:
+ CMPI L0, 1 # Copy leftover byte
+ BLT DONE
+ LDBU.D L1, L5, 0
+ STBU.D L2, L5, 0
+
+DONE: # Copy done
+ MOV L2, L7 # Return pointer
+ RET PC, L3
+
+#****************************
+# Byte memcpy
+#****************************
+mem_except:
+ DBR L_5
+ MOVI L6,0
+L_3:
+ LDBS.D L1, L5, 0 # Transfer the byte
+ ADDI L6, 1
+ STBS.D L2, L5, 0
+ ADDI L2, 1
+ ADDI L1, 1
+L_5: # Loop test
+ CMP L6, L0
+ BST L_3
+ MOV L2, L7 # Return pointer
+ RET PC, L3
+ .END
--- /dev/null
+/*
+ * Derived from the Hyperstone's library source code.
+ * Modefied src in order to apply the -mgnu-param compiler option.
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
+ * George Thanos <gthanos@telecom.ntua.gr>
+ */
+ .text
+ .align 2
+ .global _memset
+
+;ENTRY(_memset)
+_memset: FRAME L9, L3
+ MASK L5, L1, 0xFF
+ MOV L8, L2
+ CMPI L0, 0 # if n = 0 then return
+ BE retour
+
+loop0: CMPBI L8, 0x3
+ BZ word_bound
+ ADDI L0, -1
+ DBNZ loop0
+ STBU.N L8, L5, 1
+retour: RET PC, L3
+
+word_bound:
+ CMPI L0, 8
+ DBLT loop2
+ MOV L7, L5
+ SHLI L7, 8
+ OR L5, L7
+ MOV L7, L5
+ SHLI L7, 16
+ OR L5, L7
+ MOV L6, L5
+loop1: ADDI L0, -8
+ CMPI L0, 8
+ DBGE loop1
+ STD.P L8, L5
+ CMPI L0, 0
+ DBNZ loop2
+ ANDNI L5, ~ 0xFF
+ RET PC, L3
+
+loop2: ADDI L0, -1
+ DBNZ loop2
+ STBU.N L8, L5, 1
+ RET PC, L3
--- /dev/null
+/*
+ * Copyright 2003 Yannis Mitsos and George Thanos
+ * {gmitsos@gthanos}@telecom.ntua.gr
+ * Released under GPL2, see the file COPYING in the top directory
+ *
+ */
+#include "setjmp.h"
+
+int setjmp( jmp_buf state)
+{
+ asm volatile( "mov %0, G3\n\t"
+ "mov %1, G4\n\t"
+ :"=l"(state->__jmpbuf->G3),
+ "=l"(state->__jmpbuf->G4)
+ :/*no input*/
+ :"%G3", "%G4" );
+
+ asm volatile( "setadr %0\n\t"
+ "mov %1, L1\n\t"
+ "mov %2, L2\n\t"
+ :"=l"(state->__jmpbuf->SavedSP),
+ "=l"(state->__jmpbuf->SavedPC),
+ "=l"(state->__jmpbuf->SavedSR)
+ :/*no input*/);
+ return 0;
+}
--- /dev/null
+/*
+ * Derived from the Hyperstone's library source code.
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
+ * George Thanos <gthanos@telecom.ntua.gr>
+ */
+ .global Priority ; Task-Priority
+ .global _Stack1Size ; Size of hardware stack
+ .global _Stack2Size ; Size of aggregate stack
+ .global _Stack1Base ; Base of hardware stack
+ .global _Stack2Base ; Base of aggregate stack
+ .global _Mem0HeapBase ; Base of Heap in Mem0
+ .global _Mem1HeapBase ; Base of Heap in Mem1
+
+ .global _init_peripherals
+ .global _main
+ .global Main
+
+ .global __exit
+ .global __fmode
+ .global __MaxArgCount
+
+ .text
+BasePtrs:
+ .weak G6Base,G7Base,G8Base,G9Base,G10Base,G11Base,G12Base,G13Base
+ .long G6Base,G7Base,G8Base,G9Base,G10Base,G11Base,G12Base,G13Base
+BasePtrsEnd:
+HeapPtrs:
+ .long _Mem0HeapBase
+ .long _Mem1HeapBase
+HeapPtrsEnd:
+
+__MaxArgCount:
+ .long 32
+__StandAloneMode:
+ .long 0 ; 0 indicate stand alone mode
+
+;============================================================================;
+; Startup-Code ;
+;============================================================================;
+ .data
+
+; do not change the order of: __argc,..
+__argc:
+ .long 0
+__argv:
+ .long 0
+__IsShell:
+ .long 1
+ErrorLevel:
+ .long 0
+__lab:
+ .long 0
+__fmode:
+ .long 0x4000 ; O_TEXT attribute
+
+_isa_drivers:
+ .long 0
+
+_isa_drivers_end:
+ .long 0
+
+
+ .text
+Main:
+StartUp:
+ FRAME L5, L0
+ MOVI L2, __bss_start__ ; clear the .bss segment
+0: CMPI L2, __bss_end__
+ BHE 0f
+ DBR 0b
+ STW.P L2, 0
+0: SUM L2, PC, BasePtrs-$ ; Load BasePtrs G6-G13
+ LDD.P L2, G6
+ LDD.P L2, G8
+; LDD.P L2, G10
+ LDD.P L2, G12
+ MOVI L2, 1
+ SUM L3, PC, __StandAloneMode-$
+ STW.R L3, L2
+
+ ;----------------------------------------------------------------;
+ ; Call main C function ;
+ ;----------------------------------------------------------------;
+2: LDW.D PC, L2, __argc - $ ; pass count of arguments to main
+ LDW.D PC, L3, __argv - $ ; pass pointer array to main
+ CALL L4, PC, _init_peripherals - $
+ CALL L4, PC, _main - $ ; --> Call Main-Program
+ CHK PC, PC ; trap if execution arrives here
+
+__exit:
+ FRAME L5, L1
+ STW.D PC, L0, ErrorLevel - $ ; Store ERRORLEVEL
+
+ CHK PC, PC
+ RET PC, L1
+
+ .global ___main
+___main:
+ FRAME L4, L1
+ MOVI L3, 2
+ STW.D PC, L3, __StandAloneMode-$
+ RET PC, L1 ; does not return
+
+ .section _GOT_
+ .long Main+4 ; OnCreate
+ .long Main+8 ; OnError
+ .long BasePtrs ; G6
+ .long BasePtrs+4 ; G7
+ .long BasePtrs+8 ; G8
+
+ .END
--- /dev/null
+/*
+ * Derived from the Hyperstone's library source code.
+ * Modefied src in order to apply the -mgnu-param compiler option.
+ * Copyright (C) 2002-2003 GDT, Yannis Mitsos <gmitsos@telecom.ntua.gr>
+ * George Thanos <gthanos@telecom.ntua.gr>
+ */
+ .text
+ .align 2
+ .global _strcmp
+;ENTRY(_strcmp)
+_strcmp:
+ FRAME L8,L2
+ CMPBI L1, 3 # check for word alignment
+ BNZ str_except
+ CMPBI L0, 3 # check for word alignment
+ BNZ str_except
+
+start:
+ LDD.P L1, L4 # post inc mode
+ LDD.P L0, L6 # post inc mode
+ CMPBI L4, ANYBZ
+ BE correct1
+ CMP L4, L6
+ BNE correct1
+ CMP L5, L7
+ BNE correct
+ CMPBI L5, ANYBZ
+ BE correct
+ CMPBI L6, ANYBZ
+ BE correct1
+ CMPBI L7, ANYBZ
+ BNE start
+
+correct: MASK L4, L5, 0xff000000
+ MASK L6, L7, 0xff000000
+ CMP L4, L6
+ BNE Exit
+ SHLI L5, 8
+ CMPI L4, 0
+ DBNE correct
+ SHLI L7, 8
+ MOV L1, L4
+ RET PC, L2
+
+Exit: SUB L4, L6 # Subtract chars
+ SARI L4, 24
+ MOV L1, L4
+ RET PC, L2
+
+correct1: MASK L5, L4, 0xff000000
+ MASK L7, L6, 0xff000000
+ CMP L5, L7
+ BNE Exit1
+ SHLI L4, 8
+ CMPI L5, 0
+ DBNE correct1
+ SHLI L6, 8
+ MOV L1, L5
+ RET PC, L2
+Exit1: SUB L5, L7 # Subtract chars
+ SARI L5, 24
+ MOV L1, L5
+ RET PC, L2
+
+testzero: CMPI L4, 0
+ BE L_5
+str_except:
+ LDBU.N L1, L4, 1 # Load *s1, compare bytes
+ LDBU.N L0, L5, 1 # Load *s2, compare bytes
+ CMP L4, L5
+ BE testzero
+ SUB L4, L5 # Subtract chars
+L_5: MOV L1, L4
+ RET PC, L2
+ .END
+
--- /dev/null
+#ifndef ETHERBOOT_BITS_BYTESWAP_H
+#define ETHERBOOT_BITS_BYTESWAP_H
+
+/* We do not have byte swap functions ... We are
+ * RISC processor ...
+ */
+
+static inline unsigned short __swap16(volatile unsigned short v)
+{
+ return ((v << 8) | (v >> 8));
+}
+
+static inline unsigned int __swap32(volatile unsigned long v)
+{
+ return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
+}
+
+#define __bswap_constant_16(x) \
+ ((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
+ (((uint16_t)(x) & 0xff00) >> 8)))
+
+#define __bswap_constant_32(x) \
+ ((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \
+ (((uint32_t)(x) & 0x0000ff00U) << 8) | \
+ (((uint32_t)(x) & 0x00ff0000U) >> 8) | \
+ (((uint32_t)(x) & 0xff000000U) >> 24)))
+
+#define __bswap_16(x) \
+ (__builtin_constant_p(x) ? \
+ __bswap_constant_16(x) : \
+ __swap16(x))
+
+
+#define __bswap_32(x) \
+ (__builtin_constant_p(x) ? \
+ __bswap_constant_32(x) : \
+ __swap32(x))
+
+#endif /* ETHERBOOT_BITS_BYTESWAP_H */
--- /dev/null
+#ifndef E1_BITS_CPU_H
+#define E1_BITS_CPU_H
+
+#define cpu_setup() do {} while(0)
+
+#endif /* E1_BITS_CPU_H */
--- /dev/null
+#ifndef E1_BITS_ELF_H
+#define E1_BITS_ELF_H
+
+/* dummy file, needed for the compilation of core/nic.c */
+
+#endif /* E1_BITS_ELF_H */
--- /dev/null
+#ifndef ETHERBOOT_BITS_ENDIAN_H
+#define ETHERBOOT_BITS_ENDIAN_H
+
+#define __BYTE_ORDER __BIG_ENDIAN
+
+#endif /* ETHERBOOT_BITS_ENDIAN_H */
--- /dev/null
+#ifndef ETHERBOOT_BITS_STRING_H
+#define ETHERBOOT_BITS_STRING_H
+
+/* define inline optimized string functions here */
+
+#define __HAVE_ARCH_MEMCPY
+//extern void * memcpy(const void *d, const void *s, size_t count);
+
+#define __HAVE_ARCH_MEMCMP
+//extern int memcmp(const void * s ,const void * d ,size_t );
+
+#define __HAVE_ARCH_MEMSET
+//extern void * memset(const void * s, int c, size_t count);
+
+#define __HAVE_ARCH_MEMMOVE
+static inline void *memmove(void *s1, const void *s2, size_t n) {
+
+ unsigned int i;
+ char *tmp = s1;
+ char *cs2 = (char *) s2;
+
+ if (tmp < cs2) {
+ for(i=0; i<n; ++i, ++tmp, ++cs2)
+ *tmp = *cs2;
+ }
+ else {
+ tmp += n - 1;
+ cs2 += n - 1;
+ for(i=0; i<n; ++i, --tmp, --cs2)
+ *tmp = *cs2;
+ }
+ return(s1);
+}
+
+#endif /* ETHERBOOT_BITS_STRING_H */
--- /dev/null
+#ifndef __E132_XS_BOARD_H
+#define __E132_XS_BOARD_H
+
+#define CONFIG_HYPERSTONE_OSC_FREQ_MHZ 15
+
+#define NR_MEMORY_REGNS 3
+#define BASEMEM 0x0
+
+/* SDRAM mapping */
+#define SDRAM_SIZE 0x01000000
+#define SDRAM_BASEMEM BASEMEM
+
+/* SRAM mapping */
+#define SRAM_BASEMEM 0x40000000
+#define SRAM_SIZE 0x0003FFFF
+
+/* IRAM mapping */
+#define IRAM_BASEMEM 0xC0000000
+#define IRAM_SIZE 0x00003FFF
+
+
+#endif /* __E132_XS_BOARD_H */
--- /dev/null
+#ifndef ETHERBOOT_E1_HOOKS_H
+#define ETHERBOOT_E1_HOOKS_H
+
+#define arch_main(data,params) do {} while(0)
+#define arch_on_exit(status) do {} while(0)
+#define arch_relocate_to(addr) do {} while(0)
+#define arch_relocated_from(old_addr) do {} while(0)
+
+#endif /* ETHERBOOT_E1_HOOKS_H */
--- /dev/null
+#ifndef ETHERBOOT_IO_H
+#define ETHERBOOT_IO_H
+
+/* Don't require identity mapped physical memory,
+ * osloader.c is the only valid user at the moment.
+ */
+#if 0
+static inline unsigned long virt_to_phys(volatile const void *virt_addr)
+{
+ return ((unsigned long)virt_addr);
+}
+#else
+#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
+#endif
+
+#if 0
+static inline void *phys_to_virt(unsigned long phys_addr)
+{
+ return (void *)(phys_addr);
+}
+#else
+#define phys_to_virt(vaddr) ((void *) (vaddr))
+#endif
+
+/* virt_to_bus converts an addresss inside of etherboot [_start, _end]
+ * into a memory address cards can use.
+ */
+#define virt_to_bus virt_to_phys
+
+/* bus_to_virt reverses virt_to_bus, the address must be output
+ * from virt_to_bus to be valid. This function does not work on
+ * all bus addresses.
+ */
+#define bus_to_virt phys_to_virt
+
+#define iounmap(addr) ((void)0)
+#define ioremap(physaddr, size) (physaddr)
+
+#define IORegAddress 13
+#define IOWait 11
+#define IOSetupTime 8
+#define IOAccessTime 5
+#define IOHoldTime 3
+
+#define SLOW_IO_ACCESS ( 0x3 << IOSetupTime | 0x0 << IOWait | 7 << IOAccessTime | 3 << IOHoldTime )
+
+/* The development board can generate up to 15 Chip selects */
+#define NR_CS 16
+
+extern unsigned int io_periph[NR_CS];
+#define ETHERNET_CS 4
+
+static inline unsigned short _swapw(volatile unsigned short v)
+{
+ return ((v << 8) | (v >> 8));
+}
+
+static inline unsigned int _swapl(volatile unsigned long v)
+{
+ return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
+}
+
+#define hy_inpw(addr) \
+ ({ register unsigned long dummy, dummy1; \
+ dummy = addr; \
+ asm volatile ("LDW.IOD %1, %0, 0" \
+ : "=l" (dummy1) \
+ : "l" (dummy)); dummy1; })
+
+
+#define hy_outpw(x, addr) \
+ ({ register unsigned long dummy0,dummy1; \
+ dummy0 = addr; \
+ dummy1 = x; \
+ asm volatile ("STW.IOD %1, %0, 0" \
+ : "=l" (dummy1) \
+ : "l"(dummy0), "l" (dummy1)); dummy1; })
+
+#define readb(addr) ({ unsigned char __v = inregb(addr); __v; })
+#define readw(addr) ({ unsigned short __v = inregw(addr); __v; })
+#define readl(addr) ({ unsigned long __v = inregl(addr); __v; })
+
+#define writeb(b,addr) (void)(outreg(b, addr))
+#define writew(b,addr) (void)(outreg(b, addr))
+#define writel(b,addr) (void)(outreg(b, addr))
+
+static inline unsigned long common_io_access(unsigned long addr)
+{
+ return io_periph[(addr & 0x03C00000) >> 22];
+}
+
+static inline volatile unsigned char inregb(volatile unsigned long reg)
+{
+ unsigned char val;
+
+ val = hy_inpw(common_io_access(reg) | ((0xf & reg) << IORegAddress));
+ return val;
+}
+
+static inline volatile unsigned short inregw(volatile unsigned long reg)
+{
+ unsigned short val;
+
+ val = hy_inpw(common_io_access(reg) | ((0xf & reg) << IORegAddress));
+ return val;
+}
+
+static inline volatile unsigned long inregl(volatile unsigned long reg)
+{
+ unsigned long val;
+
+ val = hy_inpw(common_io_access(reg) | ((0xf & reg) << IORegAddress));
+ return val;
+}
+
+static inline void outreg(volatile unsigned long val, volatile unsigned long reg)
+{
+
+ hy_outpw(val, (common_io_access(reg) | ((0xf & reg) << IORegAddress)));
+}
+
+static inline void io_outsb(unsigned int addr, void *buf, int len)
+{
+ unsigned long tmp;
+ unsigned char *bp = (unsigned char *) buf;
+
+ tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
+
+ while (len--){
+ hy_outpw(_swapw(*bp++), tmp);
+ }
+}
+
+static inline void io_outsw(volatile unsigned int addr, void *buf, int len)
+{
+ unsigned long tmp;
+ unsigned short *bp = (unsigned short *) buf;
+
+ tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
+
+ while (len--){
+ hy_outpw(_swapw(*bp++), tmp);
+ }
+}
+
+static inline void io_outsl(volatile unsigned int addr, void *buf, int len)
+{
+ unsigned long tmp;
+ unsigned int *bp = (unsigned int *) buf;
+
+ tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
+
+ while (len--){
+ hy_outpw(_swapl(*bp++), tmp);
+ }
+}
+
+static inline void io_insb(volatile unsigned int addr, void *buf, int len)
+{
+ unsigned long tmp;
+ unsigned char *bp = (unsigned char *) buf;
+
+ tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
+
+ while (len--)
+ *bp++ = hy_inpw((unsigned char) tmp);
+
+}
+
+static inline void io_insw(unsigned int addr, void *buf, int len)
+{
+ unsigned long tmp;
+ unsigned short *bp = (unsigned short *) buf;
+
+ tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
+
+ while (len--)
+ *bp++ = _swapw((unsigned short)hy_inpw(tmp));
+
+}
+
+static inline void io_insl(unsigned int addr, void *buf, int len)
+{
+ unsigned long tmp;
+ unsigned int *bp = (unsigned int *) buf;
+
+ tmp = (common_io_access(addr)) | ((0xf & addr) << IORegAddress);
+
+ while (len--)
+ *bp++ = _swapl((unsigned int)hy_inpw(tmp));
+}
+
+#define inb(addr) readb(addr)
+#define inw(addr) readw(addr)
+#define inl(addr) readl(addr)
+#define outb(x,addr) ((void) writeb(x,addr))
+#define outw(x,addr) ((void) writew(x,addr))
+#define outl(x,addr) ((void) writel(x,addr))
+
+#define insb(a,b,l) io_insb(a,b,l)
+#define insw(a,b,l) io_insw(a,b,l)
+#define insl(a,b,l) io_insl(a,b,l)
+#define outsb(a,b,l) io_outsb(a,b,l)
+#define outsw(a,b,l) io_outsw(a,b,l)
+#define outsl(a,b,l) io_outsl(a,b,l)
+
+#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
+
+#endif /* ETHERBOOT_IO_H */
--- /dev/null
+#ifndef LATCH_H
+#define LATCH_H
+
+//#define TICKS_PER_SEC (1000000UL)
+#define TICKS_PER_SEC (625000UL)
+
+/* Fixed timer interval used for calibrating a more precise timer */
+//#define LATCHES_PER_SEC 10
+
+void sleep_latch(void);
+
+#endif /* LATCH_H */
--- /dev/null
+/*--------------------------------------------------------------------------*/
+/* Project: ANSI C Standard Header Files */
+/* File: LIMITS.H */
+/* Edited by: hyperstone electronics GmbH */
+/* Am Seerhein 8 */
+/* D-78467 Konstanz, Germany */
+/* Date: January 30, 1996 */
+/*--------------------------------------------------------------------------*/
+/* Purpose: */
+/* The header file <limits.h> defines limits of ordinal types */
+/* (char, short, int, long) */
+/*--------------------------------------------------------------------------*/
+
+#ifndef __LIMITS_H
+#define __LIMITS_H 1
+
+#define MB_LEN_MAX 1
+#define CHAR_BIT 8
+#define SCHAR_MIN -128L
+#define SCHAR_MAX 127L
+#define UCHAR_MAX 255
+#define CHAR_MIN 0
+#define CHAR_MAX UCHAR_MAX
+#define SHRT_MIN -32768
+#define SHRT_MAX 32767
+#define USHRT_MAX 65535
+#define INT_MIN 0x80000000
+#define INT_MAX 0x7FFFFFFF
+#define UINT_MAX 0xFFFFFFFFL
+#define LONG_MIN INT_MIN
+#define LONG_MAX INT_MAX
+#define ULONG_MAX UINT_MAX
+
+#endif
--- /dev/null
+#ifndef _SETJMP_H
+#define _SETJMP_H
+
+
+typedef struct {
+ unsigned long G3;
+ unsigned long G4;
+ unsigned long SavedSP;
+ unsigned long SavedPC;
+ unsigned long SavedSR;
+ unsigned long ReturnValue;
+} __jmp_buf[1];
+
+typedef struct __jmp_buf_tag /* C++ doesn't like tagless structs. */
+ {
+ __jmp_buf __jmpbuf; /* Calling environment. */
+ int __mask_was_saved; /* Saved the signal mask? */
+ } jmp_buf[1];
+
+void longjmp(jmp_buf state, int value );
+int setjmp( jmp_buf state);
+
+#endif
--- /dev/null
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+#endif /* STDINT_H */
--- /dev/null
+# Config for i386 Etherboot
+#
+# Do not delete the tag OptionDescription and /OptionDescription
+# It is used to automatically generate the documentation.
+#
+# @OptionDescrition@
+#
+# BIOS interface options:
+#
+# -DPCBIOS
+# Compile in support for the normal pcbios
+# -DLINUXBIOS
+# Compile in support for LinuxBIOS
+# -DBBS_BUT_NOT_PNP_COMPLIANT
+# Some BIOSes claim to be PNP but they don't conform
+# to the BBS spec which specifies that ES:DI must
+# point to the string $PnP on entry. This option
+# works around those. This option must be added to
+# LCONFIG.
+# -DNO_DELAYED_INT
+# Take control as soon as BIOS detects the ROM.
+# Normally hooks onto INT18H or INT19H. Use only if you
+# have a very non-conformant BIOS as it bypasses
+# BIOS initialisation of devices. This only works for
+# legacy ROMs, i.e. PCI_PNP_HEADER not defined.
+# This option was formerly called NOINT19H.
+# -DBOOT_INT18H
+# Etherboot normally hooks onto INT19H for legacy ROMs.
+# You can choose to hook onto INT18H (BASIC interpreter
+# entry point) instead. This entry point is used when
+# all boot devices have been exhausted. This option must
+# be added to LCONFIG.
+# -DCONFIG_PCI_DIRECT
+# Define this for PCI BIOSes that do not implement
+# BIOS32 or not correctly. Normally not needed.
+# Only works for BIOSes of a certain era.
+# -DCONFIG_TSC_CURRTICKS
+# Uses the processor time stamp counter instead of reading
+# the BIOS time counter. This allows Etherboot to work
+# even without a BIOS. This only works on late model
+# 486s and above.
+# -DCONFIG_NO_TIMER2
+# Some systems do not have timer2 implemented.
+# If you have a RTC this will allow you to roughly calibrate
+# it using outb instructions.
+# -DIBM_L40
+# This option uses the 0x92 method of controlling
+# A20 instead of the traditional method of using the
+# keyboard controller. An explanation of A20 is here:
+# http://www.win.tue.nl/~aeb/linux/kbd/A20.html
+# This occurs on MCA, EISA and some embedded boards,
+# and sometimes with the Fast Gate A20 option on some
+# BIOSes.
+# Enable this only if you are sure of what you are doing.
+#
+# Extended cpu options
+
+# -DCONFIG_X86_64
+# Compile in support for booting x86_64 64bit binaries.
+#
+# PXE loader options:
+#
+# -DPXELOADER_KEEP_ALL
+# Prevent PXE loader (prefix) from unloading the
+# PXE stack. You will want to use this if, for
+# example, you are booting via PXE-on-floppy.
+# You may want to use it under certain
+# circumstances when using the Etherboot UNDI
+# driver; these are complex and best practice is
+# not yet established.
+#
+# Obscure options you probably don't need to touch:
+#
+# -DIGNORE_E820_MAP
+# Ignore the memory map returned by the E820 BIOS
+# call. May be necessary on some buggy BIOSes.
+# -DT503_AUI
+# Use AUI by default on 3c503 cards.
+# -DFLATTEN_REAL_MODE
+# Use 4GB segment limits when calling out to or
+# returning to real-mode code. This is necessary to
+# work around some buggy code (e.g. OpenBSD's pxeboot)
+# that uses flat real-mode without being sufficiently
+# paranoid about the volatility of its segment limits.
+
+#
+# @/OptionDescription@
+
+# BIOS select don't change unless you know what you are doing
+CFLAGS+= -DPCBIOS
+
+# Compile in k8/hammer support
+# CFLAGS+= -DCONFIG_X86_64
+
+# Options to make a version of Etherboot that will work under linuxBIOS.
+# CFLAGS+= -DLINUXBIOS -DCONFIG_TSC_CURRTICKS -DCONSOLE_SERIAL -DCOMCONSOLE=0x3f8 -DCOMPRESERVE -DCONFIG_PCI_DIRECT -DELF_IMAGE
+
+# These options affect the loader that is prepended to the Etherboot image
+# LCONFIG+= -DBBS_BUT_NOT_PNP_COMPLIANT
+# LCONFIG+= -DBOOT_INT18H
+
+# Produce code that will work inside the Bochs emulator. The pnic
+# driver is probably the best one to try.
+# CFLAGS+= -DCONFIG_PCI_DIRECT
+
+# Produce code that will work with OpenBSD's pxeboot
+# CFLAGS+= -DFLATTEN_REAL_MODE
+
+CFLAGS+= -fstrength-reduce -fomit-frame-pointer -march=i386
+# Squeeze the code in as little space as possible.
+# gcc3 needs a different syntax to gcc2 if you want to avoid spurious warnings.
+GCC_VERSION = $(subst ., ,$(shell $(CC) -dumpversion))
+GCC_MAJORVERSION = $(firstword $(GCC_VERSION))
+ifeq ($(GCC_MAJORVERSION),2)
+CFLAGS+= -malign-jumps=1 -malign-loops=1 -malign-functions=1
+else
+CFLAGS+= -falign-jumps=1 -falign-loops=1 -falign-functions=1
+endif
+GCC_MINORVERSION = $(word 2, $(GCC_VERSION))
+ifneq ($(GCC_MINORVERSION),4)
+CFLAGS+= -mcpu=i386
+endif
+
+LDFLAGS+= -N
+
+ifeq "$(shell uname -s)" "FreeBSD"
+CFLAGS+= -DIMAGE_FREEBSD -DELF_IMAGE -DAOUT_IMAGE
+endif
+
+# An alternate location for isolinux.bin can be set here
+# ISOLINUX_BIN=/path/to/isolinux.bin
--- /dev/null
+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/unhuf.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 -D ASSEMBLY $< | $(AS) $(ASFLAGS) -o $@
+
+$(BIN)/%.o: arch/i386/prefix/%.S $(MAKEDEPS)
+ $(CPP) $(CFLAGS) -Ui386 -D ASSEMBLY $< | $(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
+ 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
+
+# rule to make a floppy emulation ISO boot image
+SUFFIXES += liso
+%.liso: util/genliso %.zlilo
+ bash util/genliso $*.liso $*.zlilo
+
--- /dev/null
+/* a.out */
+struct exec {
+ unsigned long a_midmag; /* flags<<26 | mid<<16 | magic */
+ unsigned long a_text; /* text segment size */
+ unsigned long a_data; /* initialized data size */
+ unsigned long a_bss; /* uninitialized data size */
+ unsigned long a_syms; /* symbol table size */
+ unsigned long a_entry; /* entry point */
+ unsigned long a_trsize; /* text relocation size */
+ unsigned long a_drsize; /* data relocation size */
+};
+
+struct aout_state {
+ struct exec head;
+ unsigned long curaddr;
+ int segment; /* current segment number, -1 for none */
+ unsigned long loc; /* start offset of current block */
+ unsigned long skip; /* padding to be skipped to current segment */
+ unsigned long toread; /* remaining data to be read in the segment */
+};
+
+static struct aout_state astate;
+
+static sector_t aout_download(unsigned char *data, unsigned int len, int eof);
+static inline os_download_t aout_probe(unsigned char *data, unsigned int len)
+{
+ unsigned long start, mid, end, istart, iend;
+ if (len < sizeof(astate.head)) {
+ return 0;
+ }
+ memcpy(&astate.head, data, sizeof(astate.head));
+ if ((astate.head.a_midmag & 0xffff) != 0x010BL) {
+ return 0;
+ }
+
+ printf("(a.out");
+ aout_freebsd_probe();
+ printf(")... ");
+ /* Check the aout image */
+ start = astate.head.a_entry;
+ mid = (((start + astate.head.a_text) + 4095) & ~4095) + astate.head.a_data;
+ end = ((mid + 4095) & ~4095) + astate.head.a_bss;
+ istart = 4096;
+ iend = istart + (mid - start);
+ if (!prep_segment(start, mid, end, istart, iend))
+ return dead_download;
+ astate.segment = -1;
+ astate.loc = 0;
+ astate.skip = 0;
+ astate.toread = 0;
+ return aout_download;
+}
+
+static sector_t aout_download(unsigned char *data, unsigned int len, int eof)
+{
+ unsigned int offset; /* working offset in the current data block */
+
+ offset = 0;
+
+#ifdef AOUT_LYNX_KDI
+ astate.segment++;
+ if (astate.segment == 0) {
+ astate.curaddr = 0x100000;
+ astate.head.a_entry = astate.curaddr + 0x20;
+ }
+ memcpy(phys_to_virt(astate.curaddr), data, len);
+ astate.curaddr += len;
+ return 0;
+#endif
+
+ do {
+ if (astate.segment != -1) {
+ if (astate.skip) {
+ if (astate.skip >= len - offset) {
+ astate.skip -= len - offset;
+ break;
+ }
+ offset += astate.skip;
+ astate.skip = 0;
+ }
+
+ if (astate.toread) {
+ if (astate.toread >= len - offset) {
+ memcpy(phys_to_virt(astate.curaddr), data+offset,
+ len - offset);
+ astate.curaddr += len - offset;
+ astate.toread -= len - offset;
+ break;
+ }
+ memcpy(phys_to_virt(astate.curaddr), data+offset, astate.toread);
+ offset += astate.toread;
+ astate.toread = 0;
+ }
+ }
+
+ /* Data left, but current segment finished - look for the next
+ * segment. This is quite simple for a.out files. */
+ astate.segment++;
+ switch (astate.segment) {
+ case 0:
+ /* read text */
+ astate.curaddr = astate.head.a_entry;
+ astate.skip = 4096;
+ astate.toread = astate.head.a_text;
+ break;
+ case 1:
+ /* read data */
+ /* skip and curaddr may be wrong, but I couldn't find
+ * examples where this failed. There is no reasonable
+ * documentation for a.out available. */
+ astate.skip = ((astate.curaddr + 4095) & ~4095) - astate.curaddr;
+ astate.curaddr = (astate.curaddr + 4095) & ~4095;
+ astate.toread = astate.head.a_data;
+ break;
+ case 2:
+ /* initialize bss and start kernel */
+ astate.curaddr = (astate.curaddr + 4095) & ~4095;
+ astate.skip = 0;
+ astate.toread = 0;
+ memset(phys_to_virt(astate.curaddr), '\0', astate.head.a_bss);
+ goto aout_startkernel;
+ default:
+ break;
+ }
+ } while (offset < len);
+
+ astate.loc += len;
+
+ if (eof) {
+ unsigned long entry;
+
+aout_startkernel:
+ entry = astate.head.a_entry;
+ done(1);
+
+ aout_freebsd_boot();
+#ifdef AOUT_LYNX_KDI
+ xstart32(entry);
+#endif
+ printf("unexpected a.out variant\n");
+ longjmp(restart_etherboot, -2);
+ }
+ return 0;
+}
--- /dev/null
+/* Callout/callback interface for Etherboot
+ *
+ * This file provides the mechanisms for making calls from Etherboot
+ * to external programs and vice-versa.
+ *
+ * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
+ */
+
+#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
+ * to its exit routine
+ */
+#define MAX_PREFIX_STACK_DATA 16
+
+/* Prefix exit routine is defined in prefix object */
+extern void prefix_exit ( void );
+extern void prefix_exit_end ( void );
+
+/*****************************************************************************
+ *
+ * IN_CALL INTERFACE
+ *
+ *****************************************************************************
+ */
+
+/* in_call(): entry point for calls in to Etherboot from external code.
+ *
+ * Parameters: some set up by assembly code _in_call(), others as
+ * passed from external code.
+ */
+uint32_t i386_in_call ( va_list ap, i386_pm_in_call_data_t pm_data,
+ uint32_t opcode ) {
+ uint32_t ret;
+ i386_rm_in_call_data_t rm_data;
+ in_call_data_t in_call_data = { &pm_data, NULL };
+ struct {
+ int data[MAX_PREFIX_STACK_DATA/4];
+ } in_stack;
+
+ /* Fill out rm_data if we were called from real mode */
+ if ( opcode & EB_CALL_FROM_REAL_MODE ) {
+ in_call_data.rm = &rm_data;
+ rm_data = va_arg ( ap, typeof(rm_data) );
+ /* Null return address indicates to use the special
+ * prefix exit mechanism, and that there are
+ * parameters on the stack that the prefix wants
+ * handed to its exit routine.
+ */
+ if ( rm_data.ret_addr.offset == 0 ) {
+ int n = va_arg ( ap, int ) / 4;
+ int i;
+ for ( i = 0; i < n; i++ ) {
+ in_stack.data[i] = va_arg ( ap, int );
+ }
+ }
+ }
+
+ /* Hand off to main in_call() routine */
+ ret = in_call ( &in_call_data, opcode, ap );
+
+ /* If real-mode return address is null, it means that we
+ * should exit via the prefix's exit path, which is part of
+ * our image. (This arrangement is necessary since the prefix
+ * code itself may have been vapourised by the time we want to
+ * return.)
+ */
+ if ( ( opcode & EB_CALL_FROM_REAL_MODE ) &&
+ ( rm_data.ret_addr.offset == 0 ) ) {
+ real_call ( prefix_exit, &in_stack, NULL );
+ /* Should never return */
+ }
+
+ return ret;
+}
+
+#ifdef CODE16
+
+/* install_rm_callback_interface(): install real-mode callback
+ * interface at specified address.
+ *
+ * Real-mode code may then call to this address (or lcall to this
+ * address plus RM_IN_CALL_FAR) in order to make an in_call() to
+ * Etherboot.
+ *
+ * Returns the size of the installed code, or 0 if the code could not
+ * be installed.
+ */
+int install_rm_callback_interface ( void *address, size_t available ) {
+ if ( available &&
+ ( available < rm_callback_interface_size ) ) return 0;
+
+ /* Inform RM code where to find Etherboot */
+ rm_etherboot_location = virt_to_phys(_text);
+
+ /* Install callback interface */
+ memcpy ( address, &rm_callback_interface,
+ rm_callback_interface_size );
+
+ return rm_callback_interface_size;
+}
+
+#endif /* CODE16 */
--- /dev/null
+#ifdef CONFIG_X86_64
+#include "stdint.h"
+#include "string.h"
+#include "bits/cpu.h"
+
+
+/* Standard macro to see if a specific flag is changeable */
+static inline int flag_is_changeable_p(uint32_t flag)
+{
+ uint32_t f1, f2;
+
+ asm("pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl %2,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl\n\t"
+ : "=&r" (f1), "=&r" (f2)
+ : "ir" (flag));
+
+ return ((f1^f2) & flag) != 0;
+}
+
+
+/* Probe for the CPUID instruction */
+static inline int have_cpuid_p(void)
+{
+ return flag_is_changeable_p(X86_EFLAGS_ID);
+}
+
+static void identify_cpu(struct cpuinfo_x86 *c)
+{
+ unsigned xlvl;
+
+ c->cpuid_level = -1; /* CPUID not detected */
+ c->x86_model = c->x86_mask = 0; /* So far unknown... */
+ c->x86_vendor_id[0] = '\0'; /* Unset */
+ memset(&c->x86_capability, 0, sizeof c->x86_capability);
+
+ if (!have_cpuid_p()) {
+ /* CPU doesn'thave CPUID */
+
+ /* If there are any capabilities, they'r vendor-specific */
+ /* enable_cpuid() would have set c->x86 for us. */
+ }
+ else {
+ /* CPU does have CPUID */
+
+ /* Get vendor name */
+ cpuid(0x00000000, &c->cpuid_level,
+ (int *)&c->x86_vendor_id[0],
+ (int *)&c->x86_vendor_id[8],
+ (int *)&c->x86_vendor_id[4]);
+
+ /* Initialize the standard set of capabilities */
+ /* Note that the vendor-specific code below might override */
+
+ /* Intel-defined flags: level 0x00000001 */
+ if ( c->cpuid_level >= 0x00000001 ) {
+ unsigned tfms, junk;
+ cpuid(0x00000001, &tfms, &junk, &junk,
+ &c->x86_capability[0]);
+ c->x86 = (tfms >> 8) & 15;
+ c->x86_model = (tfms >> 4) & 15;
+ c->x86_mask = tfms & 15;
+ }
+
+ /* AMD-defined flags: level 0x80000001 */
+ xlvl = cpuid_eax(0x80000000);
+ if ( (xlvl & 0xffff0000) == 0x80000000 ) {
+ if ( xlvl >= 0x80000001 )
+ c->x86_capability[1] = cpuid_edx(0x80000001);
+ }
+ }
+}
+
+struct cpuinfo_x86 cpu_info;
+void cpu_setup(void)
+{
+ identify_cpu(&cpu_info);
+}
+#endif /* CONFIG_X86_64 */
--- /dev/null
+#include "etherboot.h"
+#include "elf.h"
+
+
+#define NAME "Etherboot"
+
+#if defined(PCBIOS)
+#define FIRMWARE "PCBIOS"
+#endif
+#if defined(LINUXBIOS)
+#define FIRMWARE "LinuxBIOS"
+#endif
+#if !defined(FIRMWARE)
+#error "No BIOS selected"
+#endif
+
+#define SZ(X) ((sizeof(X)+3) & ~3)
+#define CP(D,S) (memcpy(&(D), &(S), sizeof(S)))
+
+struct elf_notes {
+ /* The note header */
+ struct Elf_Bhdr hdr;
+
+ /* First the Fixed sized entries that must be well aligned */
+
+ /* Pointer to bootp data */
+ Elf_Nhdr nf1;
+ char nf1_name[SZ(EB_PARAM_NOTE)];
+ uint32_t nf1_bootp_data;
+
+ /* Pointer to ELF header */
+ Elf_Nhdr nf2;
+ char nf2_name[SZ(EB_PARAM_NOTE)];
+ uint32_t nf2_header;
+
+ /* A copy of the i386 memory map */
+ Elf_Nhdr nf3;
+ char nf3_name[SZ(EB_PARAM_NOTE)];
+ struct meminfo nf3_meminfo;
+
+ /* Then the variable sized data string data where alignment does not matter */
+
+ /* The bootloader name */
+ Elf_Nhdr nv1;
+ char nv1_desc[SZ(NAME)];
+ /* The bootloader version */
+ Elf_Nhdr nv2;
+ char nv2_desc[SZ(VERSION)];
+ /* The firmware type */
+ Elf_Nhdr nv3;
+ char nv3_desc[SZ(FIRMWARE)];
+ /* Name of the loaded image */
+ Elf_Nhdr nv4;
+ char nv4_loaded_image[128];
+ /* An empty command line */
+ Elf_Nhdr nv5;
+ char nv5_cmdline[SZ("")];
+};
+
+#define ELF_NOTE_COUNT (3 + 5)
+
+static struct elf_notes notes;
+struct Elf_Bhdr *prepare_boot_params(void *header)
+{
+ memset(¬es, 0, sizeof(notes));
+ notes.hdr.b_signature = ELF_BHDR_MAGIC;
+ notes.hdr.b_size = sizeof(notes);
+ notes.hdr.b_checksum = 0;
+ notes.hdr.b_records = ELF_NOTE_COUNT;
+
+ /* Initialize the fixed length entries. */
+ notes.nf1.n_namesz = sizeof(EB_PARAM_NOTE);
+ notes.nf1.n_descsz = sizeof(notes.nf1_bootp_data);
+ notes.nf1.n_type = EB_BOOTP_DATA;
+ CP(notes.nf1_name, EB_PARAM_NOTE);
+ notes.nf1_bootp_data = virt_to_phys(BOOTP_DATA_ADDR);
+
+ notes.nf2.n_namesz = sizeof(EB_PARAM_NOTE);
+ notes.nf2.n_descsz = sizeof(notes.nf2_header);
+ notes.nf2.n_type = EB_HEADER;
+ CP(notes.nf2_name, EB_PARAM_NOTE);
+ notes.nf2_header = virt_to_phys(header);
+
+ notes.nf3.n_namesz = sizeof(EB_PARAM_NOTE);
+ notes.nf3.n_descsz = sizeof(notes.nf3_meminfo);
+ notes.nf3.n_type = EB_I386_MEMMAP;
+ CP(notes.nf3_name, EB_PARAM_NOTE);
+ memcpy(¬es.nf3_meminfo, &meminfo, sizeof(meminfo));
+
+ /* Initialize the variable length entries */
+ notes.nv1.n_namesz = 0;
+ notes.nv1.n_descsz = sizeof(NAME);
+ notes.nv1.n_type = EBN_BOOTLOADER_NAME;
+ CP(notes.nv1_desc, NAME);
+
+ notes.nv2.n_namesz = 0;
+ notes.nv2.n_descsz = sizeof(VERSION);
+ notes.nv2.n_type = EBN_BOOTLOADER_VERSION;
+ CP(notes.nv2_desc, VERSION);
+
+ notes.nv3.n_namesz = 0;
+ notes.nv3.n_descsz = sizeof(FIRMWARE);
+ notes.nv3.n_type = EBN_FIRMWARE_TYPE;
+ CP(notes.nv3_desc, FIRMWARE);
+
+ /* Attempt to pass the name of the loaded image */
+ notes.nv4.n_namesz = 0;
+ notes.nv4.n_descsz = sizeof(notes.nv4_loaded_image);
+ notes.nv4.n_type = EBN_LOADED_IMAGE;
+ memcpy(¬es.nv4_loaded_image, KERNEL_BUF, sizeof(notes.nv4_loaded_image));
+
+ /* Pass an empty command line for now */
+ notes.nv5.n_namesz = 0;
+ notes.nv5.n_descsz = sizeof("");
+ notes.nv5.n_type = EBN_COMMAND_LINE;
+ CP(notes.nv5_cmdline, "");
+
+
+ notes.hdr.b_checksum = ipchksum(¬es, sizeof(notes));
+ /* Like UDP invert a 0 checksum to show that a checksum is present */
+ if (notes.hdr.b_checksum == 0) {
+ notes.hdr.b_checksum = 0xffff;
+ }
+ return ¬es.hdr;
+}
+
+int elf_start(unsigned long machine __unused_i386, unsigned long entry, unsigned long params)
+{
+#if defined(CONFIG_X86_64)
+ if (machine == EM_X86_64) {
+ return xstart_lm(entry, params);
+ }
+#endif
+ return xstart32(entry, params);
+}
--- /dev/null
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+
+ENTRY(_text)
+SECTIONS {
+ . = ALIGN(16);
+ /* Start address of Etherboot in the virtual address space */
+ _virt_start = 0;
+ _text = . ;
+ .text.nocompress : {
+ *(.text*.nocompress)
+ . = ALIGN(16);
+ } = 0x9090
+
+ .text16 : {
+ _text16 = .;
+ *(.text16)
+ *(.text16.*)
+ _etext16 = . ;
+ }
+ .text.compress : {
+ *(.text)
+ *(.text.*)
+ } = 0x9090
+ .rodata : {
+ . = ALIGN(4);
+ *(.rodata)
+ *(.rodata.*)
+ }
+ . = ALIGN(4);
+ .drivers.pci : {
+ pci_drivers = . ;
+ *(.drivers.pci);
+ pci_drivers_end = . ;
+ }
+ . = ALIGN(4);
+ .drivers.isa : {
+ isa_drivers = . ;
+ *(.drivers.isa);
+ isa_drivers_end = .;
+ }
+ _etext = . ;
+ _data = . ;
+ .data : {
+ *(.data)
+ *(.data.*)
+ }
+ _edata = . ;
+ _uncompressed_verbatim_end = . ;
+ . = ALIGN(16);
+ .bss.preserve : {
+ *(.bss.preserve)
+ *(.bss.preserve.*)
+ }
+ _bss = . ;
+ .bss : {
+ *(.bss)
+ *(.bss.*)
+ }
+ . = ALIGN(16);
+ _ebss = .;
+ _stack = . ;
+ .stack : {
+ _stack_start = . ;
+ *(.stack)
+ *(.stack.*)
+ _stack_end = . ;
+ }
+ _bss_size = _ebss - _bss;
+ _stack_offset = _stack - _text ;
+ _stack_offset_pgh = _stack_offset / 16 ;
+ _stack_size = _stack_end - _stack_start ;
+ . = ALIGN(16);
+ _end = . ;
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.note)
+ }
+
+ /* PXE-specific symbol calculations. The results of these are
+ * needed in romprefix.S, which is why they must be calculated
+ * here.
+ */
+ _pxe_stack_size = _pxe_stack_t_size
+ + _pxe_callback_interface_size
+ + _rm_callback_interface_size
+ + _e820mangler_size + 15 ;
+
+}
--- /dev/null
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+
+ENTRY(_prefix_start)
+SECTIONS {
+ /* Prefix */
+ .prefix : {
+ _verbatim_start = . ;
+ _prefix_start = . ;
+ *(.prefix)
+ . = ALIGN(16);
+ _prefix_end = . ;
+ } = 0x9090
+ _prefix_size = _prefix_end - _prefix_start;
+
+ .text.nocompress : {
+ *(.prefix.udata)
+ } = 0x9090
+
+ decompress_to = . ;
+ .prefix.zdata : {
+ _compressed = . ;
+ *(.prefix.zdata)
+ _compressed_end = . ;
+ }
+ _compressed_size = _compressed_end - _compressed;
+
+ . = ALIGN(16);
+ _verbatim_end = . ;
+
+
+ /* Size of the core of etherboot in memory */
+ _base_size = _end - _text;
+
+ /* _prefix_size is the length of the non-core etherboot prefix */
+ _prefix_size = _prefix_end - _prefix_start;
+
+ /* _verbatim_size is the actual amount that has to be copied to base memory */
+ _verbatim_size = _verbatim_end - _verbatim_start;
+
+ /* _image_size is the amount of base memory needed to run */
+ _image_size = _base_size + _prefix_size;
+
+ /* Standard sizes rounded up to paragraphs */
+ _prefix_size_pgh = (_prefix_size + 15) / 16;
+ _verbatim_size_pgh = (_verbatim_size + 15) / 16;
+ _image_size_pgh = (_image_size + 15) / 16 ;
+
+ /* Standard sizes in sectors */
+ _prefix_size_sct = (_prefix_size + 511) / 512;
+ _verbatim_size_sct = (_verbatim_size + 511) / 512;
+ _image_size_sct = (_image_size + 511) / 512;
+
+ /* Symbol offsets and sizes for the exe prefix */
+ _exe_hdr_size = 32;
+ _exe_size = _verbatim_size; /* Should this be - 32 to exclude the header? */
+ _exe_size_tail = (_exe_size) % 512;
+ _exe_size_pages = ((_exe_size) + 511) / 512;
+ _exe_bss_size = ((_image_size - _verbatim_size) + 15) / 16;
+ _exe_ss_offset = (_stack_offset + _prefix_size - _exe_hdr_size + 15) / 16 ;
+
+ /* This is where we copy the compressed image before decompression.
+ * Prepare to decompress in place. The end mark is about 8.25 bytes long,
+ * and the worst case symbol is about 16.5 bytes long. Therefore
+ * We need to reserve at least 25 bytes of slack here.
+ * Currently I reserve 2048 bytes of just slack to be safe :)
+ * 2048 bytes easily falls within the BSS (the defualt stack is 4096 bytes)
+ * so we really are decompressing in place.
+ *
+ * Hmm. I missed a trick. In the very worst case (no compression)
+ * the encoded data is 9/8 the size as it started out so to be completely
+ * safe I need to be 1/8 of the uncompressed code size past the end.
+ * This will still fit compfortably into our bss in any conceivable scenario.
+ */
+ _compressed_copy = _edata + _prefix_size - _compressed_size +
+ /* The amount to overflow _edata */
+ MAX( ((_edata - _text + 7) / 8) , 2016 ) + 32;
+ _assert = ASSERT( ( _compressed_copy - _prefix_size ) < _ebss , "Cannot decompress in place" ) ;
+
+ decompress = DEFINED(decompress) ? decompress : 0;
+ /DISCARD/ : {
+ *(.comment)
+ *(.note)
+ }
+
+ /* Symbols used by the prefixes whose addresses are inconvinient
+ * to compute, at runtime in the code.
+ */
+ image_basemem_size = DEFINED(image_basemem_size)? image_basemem_size : 65536;
+ image_basemem = DEFINED(image_basemem)? image_basemem : 65536;
+ _prefix_real_to_prot = _real_to_prot + _prefix_size ;
+ _prefix_prot_to_real = _prot_to_real + _prefix_size ;
+ _prefix_image_basemem_size = image_basemem_size + _prefix_size ;
+ _prefix_image_basemem = image_basemem + _prefix_size ;
+ _prefix_rm_in_call = _rm_in_call + _prefix_size ;
+ _prefix_in_call = _in_call + _prefix_size ;
+ _prefix_rom = rom + _prefix_size ;
+ _prefix_rm_etherboot_location = rm_etherboot_location + _prefix_size ;
+ _prefix_stack_end = _stack_end + _prefix_size ;
+}
--- /dev/null
+/* bootinfo */
+#define BOOTINFO_VERSION 1
+#define NODEV (-1) /* non-existent device */
+#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */
+#define PAGE_SIZE (1<<PAGE_SHIFT) /* bytes/page */
+#define PAGE_MASK (PAGE_SIZE-1)
+#define N_BIOS_GEOM 8
+
+struct bootinfo {
+ unsigned int bi_version;
+ const unsigned char *bi_kernelname;
+ struct nfs_diskless *bi_nfs_diskless;
+ /* End of fields that are always present. */
+#define bi_endcommon bi_n_bios_used
+ unsigned int bi_n_bios_used;
+ unsigned long bi_bios_geom[N_BIOS_GEOM];
+ unsigned int bi_size;
+ unsigned char bi_memsizes_valid;
+ unsigned char bi_pad[3];
+ unsigned long bi_basemem;
+ unsigned long bi_extmem;
+ unsigned long bi_symtab;
+ unsigned long bi_esymtab;
+ /* Note that these are in the FreeBSD headers but were not here... */
+ unsigned long bi_kernend; /* end of kernel space */
+ unsigned long bi_envp; /* environment */
+ unsigned long bi_modulep; /* preloaded modules */
+};
+
+static struct bootinfo bsdinfo;
+
+#ifdef ELF_IMAGE
+static Elf32_Shdr *shdr; /* To support the FreeBSD kludge! */
+static Address symtab_load;
+static Address symstr_load;
+static int symtabindex;
+static int symstrindex;
+#endif
+
+static enum {
+ Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD,
+} image_type = Unknown;
+
+static unsigned int off;
+
+
+#ifdef ELF_IMAGE
+static void elf_freebsd_probe(void)
+{
+ image_type = Elf;
+ if ( (estate.e.elf32.e_entry & 0xf0000000) &&
+ (estate.e.elf32.e_type == ET_EXEC))
+ {
+ image_type = Elf_FreeBSD;
+ printf("/FreeBSD");
+ off = -(estate.e.elf32.e_entry & 0xff000000);
+ estate.e.elf32.e_entry += off;
+ }
+ /* Make sure we have a null to start with... */
+ shdr = 0;
+
+ /* Clear the symbol index values... */
+ symtabindex = -1;
+ symstrindex = -1;
+
+ /* ...and the load addresses of the symbols */
+ symtab_load = 0;
+ symstr_load = 0;
+}
+
+static void elf_freebsd_fixup_segment(void)
+{
+ if (image_type == Elf_FreeBSD) {
+ estate.p.phdr32[estate.segment].p_paddr += off;
+ }
+}
+
+static void elf_freebsd_find_segment_end(void)
+{
+ /* Count the bytes read even for the last block
+ * as we will need to know where the last block
+ * ends in order to load the symbols correctly.
+ * (plus it could be useful elsewhere...)
+ * Note that we need to count the actual size,
+ * not just the end of the disk image size.
+ */
+ estate.curaddr +=
+ (estate.p.phdr32[estate.segment].p_memsz -
+ estate.p.phdr32[estate.segment].p_filesz);
+}
+
+static int elf_freebsd_debug_loader(unsigned int offset)
+{
+ /* No more segments to be loaded - time to start the
+ * nasty state machine to support the loading of
+ * FreeBSD debug symbols due to the fact that FreeBSD
+ * uses/exports the kernel's debug symbols in order
+ * to make much of the system work! Amazing (arg!)
+ *
+ * We depend on the fact that for the FreeBSD kernel,
+ * there is only one section of debug symbols and that
+ * the section is after all of the loaded sections in
+ * the file. This assumes a lot but is somewhat required
+ * to make this code not be too annoying. (Where do you
+ * load symbols when the code has not loaded yet?)
+ * Since this function is actually just a callback from
+ * the network data transfer code, we need to be able to
+ * work with the data as it comes in. There is no chance
+ * for doing a seek other than forwards.
+ *
+ * The process we use is to first load the section
+ * headers. Once they are loaded (shdr != 0) we then
+ * look for where the symbol table and symbol table
+ * strings are and setup some state that we found
+ * them and fall into processing the first one (which
+ * is the symbol table) and after that has been loaded,
+ * we try the symbol strings. Note that the order is
+ * actually required as the memory image depends on
+ * the symbol strings being loaded starting at the
+ * end of the symbol table. The kernel assumes this
+ * layout of the image.
+ *
+ * At any point, if we get to the end of the load file
+ * or the section requested is earlier in the file than
+ * the current file pointer, we just end up falling
+ * out of this and booting the kernel without this
+ * information.
+ */
+
+ /* Make sure that the next address is long aligned... */
+ /* Assumes size of long is a power of 2... */
+ estate.curaddr = (estate.curaddr + sizeof(long) - 1) & ~(sizeof(long) - 1);
+
+ /* If we have not yet gotten the shdr loaded, try that */
+ if (shdr == 0)
+ {
+ estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize;
+ estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset);
+ if (estate.toread)
+ {
+#if ELF_DEBUG
+ printf("shdr *, size %lX, curaddr %lX\n",
+ estate.toread, estate.curaddr);
+#endif
+
+ /* Start reading at the curaddr and make that the shdr */
+ shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr);
+
+ /* Start to read... */
+ return 1;
+ }
+ }
+ else
+ {
+ /* We have the shdr loaded, check if we have found
+ * the indexs where the symbols are supposed to be */
+ if ((symtabindex == -1) && (symstrindex == -1))
+ {
+ int i;
+ /* Make sure that the address is page aligned... */
+ /* Symbols need to start in their own page(s)... */
+ estate.curaddr = (estate.curaddr + 4095) & ~4095;
+
+ /* Need to make new indexes... */
+ for (i=0; i < estate.e.elf32.e_shnum; i++)
+ {
+ if (shdr[i].sh_type == SHT_SYMTAB)
+ {
+ int j;
+ for (j=0; j < estate.e.elf32.e_phnum; j++)
+ {
+ /* Check only for loaded sections */
+ if ((estate.p.phdr32[j].p_type | 0x80) == (PT_LOAD | 0x80))
+ {
+ /* Only the extra symbols */
+ if ((shdr[i].sh_offset >= estate.p.phdr32[j].p_offset) &&
+ ((shdr[i].sh_offset + shdr[i].sh_size) <=
+ (estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz)))
+ {
+ shdr[i].sh_offset=0;
+ shdr[i].sh_size=0;
+ break;
+ }
+ }
+ }
+ if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0))
+ {
+ symtabindex = i;
+ symstrindex = shdr[i].sh_link;
+ }
+ }
+ }
+ }
+
+ /* Check if we have a symbol table index and have not loaded it */
+ if ((symtab_load == 0) && (symtabindex >= 0))
+ {
+ /* No symbol table yet? Load it first... */
+
+ /* This happens to work out in a strange way.
+ * If we are past the point in the file already,
+ * we will skip a *large* number of bytes which
+ * ends up bringing us to the end of the file and
+ * an old (default) boot. Less code and lets
+ * the state machine work in a cleaner way but this
+ * is a nasty side-effect trick... */
+ estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset);
+
+ /* And we need to read this many bytes... */
+ estate.toread = shdr[symtabindex].sh_size;
+
+ if (estate.toread)
+ {
+#if ELF_DEBUG
+ printf("db sym, size %lX, curaddr %lX\n",
+ estate.toread, estate.curaddr);
+#endif
+ /* Save where we are loading this... */
+ symtab_load = phys_to_virt(estate.curaddr);
+
+ *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
+ estate.curaddr += sizeof(long);
+
+ /* Start to read... */
+ return 1;
+ }
+ }
+ else if ((symstr_load == 0) && (symstrindex >= 0))
+ {
+ /* We have already loaded the symbol table, so
+ * now on to the symbol strings... */
+
+
+ /* Same nasty trick as above... */
+ estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset);
+
+ /* And we need to read this many bytes... */
+ estate.toread = shdr[symstrindex].sh_size;
+
+ if (estate.toread)
+ {
+#if ELF_DEBUG
+ printf("db str, size %lX, curaddr %lX\n",
+ estate.toread, estate.curaddr);
+#endif
+ /* Save where we are loading this... */
+ symstr_load = phys_to_virt(estate.curaddr);
+
+ *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
+ estate.curaddr += sizeof(long);
+
+ /* Start to read... */
+ return 1;
+ }
+ }
+ }
+ /* all done */
+ return 0;
+}
+
+static void elf_freebsd_boot(unsigned long entry)
+{
+ if (image_type != Elf_FreeBSD)
+ return;
+
+ memset(&bsdinfo, 0, sizeof(bsdinfo));
+ bsdinfo.bi_basemem = meminfo.basememsize;
+ bsdinfo.bi_extmem = meminfo.memsize;
+ bsdinfo.bi_memsizes_valid = 1;
+ bsdinfo.bi_version = BOOTINFO_VERSION;
+ bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
+ bsdinfo.bi_nfs_diskless = NULL;
+ bsdinfo.bi_size = sizeof(bsdinfo);
+#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
+ if(freebsd_kernel_env[0] != '\0'){
+ freebsd_howto |= RB_BOOTINFO;
+ bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env;
+ }
+
+ /* Check if we have symbols loaded, and if so,
+ * made the meta_data needed to pass those to
+ * the kernel. */
+ if ((symtab_load !=0) && (symstr_load != 0))
+ {
+ unsigned long *t;
+
+ bsdinfo.bi_symtab = symtab_load;
+
+ /* End of symbols (long aligned...) */
+ /* Assumes size of long is a power of 2... */
+ bsdinfo.bi_esymtab = (symstr_load +
+ sizeof(long) +
+ *((long *)symstr_load) +
+ sizeof(long) - 1) & ~(sizeof(long) - 1);
+
+ /* Where we will build the meta data... */
+ t = phys_to_virt(bsdinfo.bi_esymtab);
+
+#if ELF_DEBUG
+ printf("Metadata at %lX\n",t);
+#endif
+
+ /* Set up the pointer to the memory... */
+ bsdinfo.bi_modulep = virt_to_phys(t);
+
+ /* The metadata structure is an array of 32-bit
+ * words where we store some information about the
+ * system. This is critical, as FreeBSD now looks
+ * only for the metadata for the extended symbol
+ * information rather than in the bootinfo.
+ */
+ /* First, do the kernel name and the kernel type */
+ /* Note that this assumed x86 byte order... */
+
+ /* 'kernel\0\0' */
+ *t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65;
+
+ /* 'elf kernel\0\0' */
+ *t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65;
+
+ /* Now the symbol start/end - note that they are
+ * here in local/physical address - the Kernel
+ * boot process will relocate the addresses. */
+ *t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab;
+ *t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab;
+
+ *t++=MODINFO_END; *t++=0; /* end of metadata */
+
+ /* Since we have symbols we need to make
+ * sure that the kernel knows its own end
+ * of memory... It is not _end but after
+ * the symbols and the metadata... */
+ bsdinfo.bi_kernend = virt_to_phys(t);
+
+ /* Signal locore.s that we have a valid bootinfo
+ * structure that was completely filled in. */
+ freebsd_howto |= 0x80000000;
+ }
+
+ xstart32(entry, freebsd_howto, NODEV, 0, 0, 0,
+ virt_to_phys(&bsdinfo), 0, 0, 0);
+ longjmp(restart_etherboot, -2);
+}
+#endif
+
+#ifdef AOUT_IMAGE
+static void aout_freebsd_probe(void)
+{
+ image_type = Aout;
+ if (((astate.head.a_midmag >> 16) & 0xffff) == 0) {
+ /* Some other a.out variants have a different
+ * value, and use other alignments (e.g. 1K),
+ * not the 4K used by FreeBSD. */
+ image_type = Aout_FreeBSD;
+ printf("/FreeBSD");
+ off = -(astate.head.a_entry & 0xff000000);
+ astate.head.a_entry += off;
+ }
+}
+
+static void aout_freebsd_boot(void)
+{
+ if (image_type == Aout_FreeBSD) {
+ memset(&bsdinfo, 0, sizeof(bsdinfo));
+ bsdinfo.bi_basemem = meminfo.basememsize;
+ bsdinfo.bi_extmem = meminfo.memsize;
+ bsdinfo.bi_memsizes_valid = 1;
+ bsdinfo.bi_version = BOOTINFO_VERSION;
+ bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
+ bsdinfo.bi_nfs_diskless = NULL;
+ bsdinfo.bi_size = sizeof(bsdinfo);
+ xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0,
+ virt_to_phys(&bsdinfo), 0, 0, 0);
+ longjmp(restart_etherboot, -2);
+ }
+}
+#endif
--- /dev/null
+#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();
+#endif
+
+}
+
+void arch_relocated_from (unsigned long old_addr )
+{
+
+#ifdef PCBIOS
+ /* Deallocate base memory used for the Etherboot runtime,
+ * if applicable
+ */
+ forget_runtime_base_memory( old_addr );
+#endif
+
+}
+
+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.
+ */
+ forget_real_mode_stack();
+#endif
+}
--- /dev/null
+/* A couple of routines to implement a low-overhead timer for drivers */
+
+ /*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+#include "etherboot.h"
+#include "timer.h"
+#include "latch.h"
+
+void __load_timer2(unsigned int ticks)
+{
+ /*
+ * Now let's take care of PPC channel 2
+ *
+ * Set the Gate high, program PPC channel 2 for mode 0,
+ * (interrupt on terminal count mode), binary count,
+ * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+ *
+ * Note some implementations have a bug where the high bits byte
+ * of channel 2 is ignored.
+ */
+ /* Set up the timer gate, turn off the speaker */
+ /* Set the Gate high, disable speaker */
+ outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
+ /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
+ /* LSB of ticks */
+ outb(ticks & 0xFF, TIMER2_PORT);
+ /* MSB of ticks */
+ outb(ticks >> 8, TIMER2_PORT);
+}
+
+static int __timer2_running(void)
+{
+ return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
+}
+
+#if !defined(CONFIG_TSC_CURRTICKS)
+void setup_timers(void)
+{
+ return;
+}
+
+void load_timer2(unsigned int ticks)
+{
+ return __load_timer2(ticks);
+}
+
+int timer2_running(void)
+{
+ return __timer2_running();
+}
+
+void ndelay(unsigned int nsecs)
+{
+ waiton_timer2((nsecs * CLOCK_TICK_RATE)/1000000000);
+}
+void udelay(unsigned int usecs)
+{
+ waiton_timer2((usecs * TICKS_PER_MS)/1000);
+}
+#endif /* !defined(CONFIG_TSC_CURRTICKS) */
+
+#if defined(CONFIG_TSC_CURRTICKS)
+
+#define rdtsc(low,high) \
+ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
+
+#define rdtscll(val) \
+ __asm__ __volatile__ ("rdtsc" : "=A" (val))
+
+
+/* Number of clock ticks to time with the rtc */
+#define LATCH 0xFF
+
+#define LATCHES_PER_SEC ((CLOCK_TICK_RATE + (LATCH/2))/LATCH)
+#define TICKS_PER_LATCH ((LATCHES_PER_SEC + (TICKS_PER_SEC/2))/TICKS_PER_SEC)
+
+static void sleep_latch(void)
+{
+ __load_timer2(LATCH);
+ while(__timer2_running());
+}
+
+/* ------ Calibrate the TSC -------
+ * Time how long it takes to excute a loop that runs in known time.
+ * And find the convertion needed to get to CLOCK_TICK_RATE
+ */
+
+
+static unsigned long long calibrate_tsc(void)
+{
+ unsigned long startlow, starthigh;
+ unsigned long endlow, endhigh;
+
+ rdtsc(startlow,starthigh);
+ sleep_latch();
+ rdtsc(endlow,endhigh);
+
+ /* 64-bit subtract - gcc just messes up with long longs */
+ __asm__("subl %2,%0\n\t"
+ "sbbl %3,%1"
+ :"=a" (endlow), "=d" (endhigh)
+ :"g" (startlow), "g" (starthigh),
+ "0" (endlow), "1" (endhigh));
+
+ /* Error: ECPUTOOFAST */
+ if (endhigh)
+ goto bad_ctc;
+
+ endlow *= TICKS_PER_LATCH;
+ return endlow;
+
+ /*
+ * The CTC wasn't reliable: we got a hit on the very first read,
+ * or the CPU was so fast/slow that the quotient wouldn't fit in
+ * 32 bits..
+ */
+bad_ctc:
+ printf("bad_ctc\n");
+ return 0;
+}
+
+static unsigned long clocks_per_tick;
+void setup_timers(void)
+{
+ if (!clocks_per_tick) {
+ clocks_per_tick = calibrate_tsc();
+ /* Display the CPU Mhz to easily test if the calibration was bad */
+ printf("CPU %ld Mhz\n", (clocks_per_tick/1000 * TICKS_PER_SEC)/1000);
+ }
+}
+
+unsigned long currticks(void)
+{
+ unsigned long clocks_high, clocks_low;
+ unsigned long currticks;
+ /* Read the Time Stamp Counter */
+ rdtsc(clocks_low, clocks_high);
+
+ /* currticks = clocks / clocks_per_tick; */
+ __asm__("divl %1"
+ :"=a" (currticks)
+ :"r" (clocks_per_tick), "0" (clocks_low), "d" (clocks_high));
+
+
+ return currticks;
+}
+
+static unsigned long long timer_timeout;
+static int __timer_running(void)
+{
+ unsigned long long now;
+ rdtscll(now);
+ return now < timer_timeout;
+}
+
+void udelay(unsigned int usecs)
+{
+ unsigned long long now;
+ rdtscll(now);
+ timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
+ while(__timer_running());
+}
+void ndelay(unsigned int nsecs)
+{
+ unsigned long long now;
+ rdtscll(now);
+ timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
+ while(__timer_running());
+}
+
+void load_timer2(unsigned int timer2_ticks)
+{
+ unsigned long long now;
+ unsigned long clocks;
+ rdtscll(now);
+ clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
+ timer_timeout = now + clocks;
+}
+
+int timer2_running(void)
+{
+ return __timer_running();
+}
+
+#endif /* RTC_CURRTICKS */
--- /dev/null
+#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 */
--- /dev/null
+/* Multiboot support
+ *
+ * 2003-07-02 mmap fix and header probe by SONE Takeshi
+ */
+
+struct multiboot_mods {
+ unsigned mod_start;
+ unsigned mod_end;
+ unsigned char *string;
+ unsigned reserved;
+};
+
+struct multiboot_mmap {
+ unsigned int size;
+ unsigned int base_addr_low;
+ unsigned int base_addr_high;
+ unsigned int length_low;
+ unsigned int length_high;
+ unsigned int type;
+};
+
+/* The structure of a Multiboot 0.6 parameter block. */
+struct multiboot_info {
+ unsigned int flags;
+#define MULTIBOOT_MEM_VALID 0x01
+#define MULTIBOOT_BOOT_DEV_VALID 0x02
+#define MULTIBOOT_CMDLINE_VALID 0x04
+#define MULTIBOOT_MODS_VALID 0x08
+#define MULTIBOOT_AOUT_SYMS_VALID 0x10
+#define MULTIBOOT_ELF_SYMS_VALID 0x20
+#define MULTIBOOT_MMAP_VALID 0x40
+ unsigned int memlower;
+ unsigned int memupper;
+ unsigned int bootdev;
+ unsigned int cmdline; /* physical address of the command line */
+ unsigned mods_count;
+ struct multiboot_mods *mods_addr;
+ unsigned syms_num;
+ unsigned syms_size;
+ unsigned syms_addr;
+ unsigned syms_shndx;
+ unsigned mmap_length;
+ unsigned mmap_addr;
+ /* The structure actually ends here, so I might as well put
+ * the ugly e820 parameters here...
+ */
+ struct multiboot_mmap mmap[E820MAX];
+};
+
+/* Multiboot image header (minimal part) */
+struct multiboot_header {
+ unsigned int magic;
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+ unsigned int flags;
+ unsigned int checksum;
+};
+
+static struct multiboot_header *mbheader;
+
+static struct multiboot_info mbinfo;
+
+static void multiboot_probe(unsigned char *data, int len)
+{
+ int offset;
+ struct multiboot_header *h;
+
+ /* Multiboot spec requires the header to be in first 8KB of the image */
+ if (len > 8192)
+ len = 8192;
+
+ for (offset = 0; offset < len; offset += 4) {
+ h = (struct multiboot_header *) (data + offset);
+ if (h->magic == MULTIBOOT_HEADER_MAGIC
+ && h->magic + h->flags + h->checksum == 0) {
+ printf("/Multiboot");
+ mbheader = h;
+ return;
+ }
+ }
+ mbheader = 0;
+}
+
+static inline void multiboot_boot(unsigned long entry)
+{
+ unsigned char cmdline[512], *c;
+ int i;
+ if (!mbheader)
+ return;
+ /* Etherboot limits the command line to the kernel name,
+ &nbs