Initial revision

This commit is contained in:
Michael Brown
2005-05-17 16:44:57 +00:00
parent 75a5374d79
commit 1097cf8685
164 changed files with 24592 additions and 0 deletions

475
contrib/baremetal/Makefile Normal file
View File

@@ -0,0 +1,475 @@
#
# Makefile for Etherboot
#
# Most of the time you should edit Config
#
# Common options:
# VERSION=v - Set the version string
#
# NS8390 options:
# -DINCLUDE_NE - Include NE1000/NE2000 support
# -DNE_SCAN=list - Probe for NE base address using list of
# comma separated hex addresses
# -DINCLUDE_3C503 - Include 3c503 support
# -DT503_SHMEM - Use 3c503 shared memory mode (off by default)
# -DINCLUDE_WD - Include Western Digital/SMC support
# -DWD_DEFAULT_MEM- Default memory location for WD/SMC cards
# -DCOMPEX_RL2000_FIX
#
# If you have a Compex RL2000 PCI 32-bit (11F6:1401),
# and the bootrom hangs in "Probing...[NE*000/PCI]",
# try enabling this fix... it worked for me :).
# In the first packet write somehow it somehow doesn't
# get back the expected data so it is stuck in a loop.
# I didn't bother to investigate what or why because it works
# when I interrupt the loop if it takes more then COMPEX_RL2000_TRIES.
# The code will notify if it does a abort.
# SomniOne - somnione@gmx.net
#
# 3C509 option:
# -DINCLUDE_3C509 - Include 3c509 support
#
# 3C90X options:
# -DINCLUDE_3C90X - Include 3c90x support
# -DCFG_3C90X_PRESERVE_XCVR - Reset the transceiver type to the value it
# had initially just before the loaded code is started.
# -DCFG_3C90X_XCVR - Hardcode the tranceiver type Etherboot uses.
# -DCFG_3C90X_BOOTROM_FIX - If you have a 3c905B with buggy ROM
# interface, setting this option might "fix" it. Use
# with caution and read the docs in 3c90x.txt!
#
# See the documentation file 3c90x.txt for more details.
#
# CS89X0 (optional) options:
# -DINCLUDE_CS89X0- Include CS89x0 support
# -DCS_SCAN=list - Probe for CS89x0 base address using list of
# comma separated hex addresses; increasing the
# address by one (0x300 -> 0x301) will force a
# more aggressive probing algorithm. This might
# be neccessary after a soft-reset of the NIC.
#
# LANCE options:
# -DINCLUDE_NE2100- Include NE2100 support
# -DINCLUDE_NI6510- Include NI6510 support
#
# SK_G16 options:
# -DINCLUDE_SK_G16- Include SK_G16 support
#
# I82586 options:
# -DINCLUDE_3C507 - Include 3c507 support
# -DINCLUDE_NI5210- Include NI5210 support
# -DINCLUDE_EXOS205-Include EXOS205 support
#
# SMC9000 options:
# -DINCLUDE_SMC9000 - Include SMC9000 driver
# -DSMC9000_SCAN=list - List of I/O addresses to probe
#
# TIARA (Fujitsu Etherstar) options:
# -DINCLUDE_TIARA - Include Tiara support
#
# NI5010 options:
# -DINCLUDE_NI5010 - Include NI5010 support
#
# TULIP options:
# -DINCLUDE_TULIP - Include Tulip support
# -DUSE_INTERNAL_BUFFER - receuve and transmit buffers within program
# space, not below 0x10000, in case that region is used
#
# RTL8139 options:
# -DINCLUDE_RTL8139 - Include RTL8139 support
# -DUSE_INTERNAL_BUFFER - 8 kB receive buffer within program space,
# not at 0x10000 - 8kB, in case that region is used
#
include Config
GCC= gcc
CPP= gcc -E
VERSION= 4.6.12
CFLAGS16+= -DVERSION=\"$(VERSION)\" -DRELOC=$(RELOCADDR)
CFLAGS32+= -DVERSION=\"$(VERSION)\" -DRELOC=$(RELOCADDR) $(OLDGAS)
LCONFIG+= -DRELOC=$(RELOCADDR)
IDENT16= 'Etherboot/16 $(VERSION) (GPL) $(@F)'
IDENT32= 'Etherboot/32 $(VERSION) (GPL) $(@F)'
# Find out if we're using binutils 2.9.1 which uses a different syntax in some
# places (most prominently in the opcode prefix area).
OLDGAS:= $(shell $(AS) --version | grep -q '2\.9\.1' && echo -DGAS291)
# Check the requested type of build (32, 16 or both families)
ifeq ($(ETHERBOOT),16)
BUILD_LIBS= $(BLIB16)
BUILD_BINS= $(BINS16)
endif
ifeq ($(ETHERBOOT),32)
BUILD_LIBS= $(BLIB32)
BUILD_BINS= $(BINS32)
endif
ifeq ($(ETHERBOOT),both)
BUILD_LIBS= $(BLIB16) $(BLIB32)
BUILD_BINS= $(BINS16) $(BINS32)
endif
3C503FLAGS= -DINCLUDE_3C503 # -DT503_SHMEM
# Note that the suffix to MAKEROM_ is the (mixed case) basename of the ROM file
MAKEROM_3c503= -3
3C507FLAGS= -DINCLUDE_3C507
3C509FLAGS= -DINCLUDE_3C509
3C529FLAGS= -DINCLUDE_3C529
3C595FLAGS= -DINCLUDE_3C595
3C90XFLAGS= -DINCLUDE_3C90X
CS89X0FLAGS= -DINCLUDE_CS89X0
EEPROFLAGS= -DINCLUDE_EEPRO
EEPRO100FLAGS= -DINCLUDE_EEPRO100
EPIC100FLAGS= -DINCLUDE_EPIC100
EXOS205FLAGS= -DINCLUDE_EXOS205
LANCEFLAGS= -DINCLUDE_LANCE # Lance/PCI!
NE2100FLAGS= -DINCLUDE_NE2100
NEFLAGS= -DINCLUDE_NE -DNE_SCAN=0x300,0x280,0x320,0x340,0x380
NS8390FLAGS= -DINCLUDE_NS8390 # NE2000/PCI!
NI5010FLAGS= -DINCLUDE_NI5010
NI5210FLAGS= -DINCLUDE_NI5210
NI6510FLAGS= -DINCLUDE_NI6510
RTL8139FLAGS= -DINCLUDE_RTL8139
SK_G16FLAGS= -DINCLUDE_SK_G16
SMC9000FLAGS= -DINCLUDE_SMC9000
TIARAFLAGS= -DINCLUDE_TIARA
DEPCAFLAGS= -DINCLUDE_DEPCA # -DDEPCA_MODEL=DEPCA -DDEPCA_RAM_BASE=0xd0000
TULIPFLAGS= -DINCLUDE_TULIP
OTULIPFLAGS= -DINCLUDE_OTULIP
VIA_RHINEFLAGS= -DINCLUDE_VIA_RHINE
WDFLAGS= -DINCLUDE_WD -DWD_DEFAULT_MEM=0xCC000
W89C840FLAGS= -DINCLUDE_W89C840
# If you have not made any changes to the *.S files, AS86 need not be set.
# (most people)
# If you have made changes to the *.S files and you want to rebuild *loader.bin
# and {floppy,com}load.bin and you have as86 from the ELKS Dev86 package (not
# the one that normally comes with Linux) (not most people)
#AS86= as86
# If you have made changes to the *.S files and you want to rebuild *loader.bin
# and {floppy,com}load.bin and you have nasm (not most people)
#AS86= nasm
# if your as has trouble with the data32 directive, uncomment this
# but note that the premade start*.o will be larger than necessary because it
# contains some routines which may not be used
#AS_PSEUDOS= n
SRCS= floppyload.S comload.S liloprefix.S loader.S start16.S start32.S serial.S startmpcc.S
SRCS+= main.c pci.c osloader.c nfs.c misc.c ansiesc.c bootmenu.c config.c
SRCS+= md5.c floppy.c
# ROM loaders: LZ version (prefix Z), PCI header version (prefix P)
ifndef AS86
RLOADER= rloader.bin.pre
PRLOADER= prloader.bin.pre
RZLOADER= rzloader.bin.pre
PRZLOADER= przloader.bin.pre
FLOPPYLOAD= floppyload.bin.pre
COMLOAD= comload.bin.pre
LILOPREFIX= liloprefix.bin.pre
else
RLOADER= bin/rloader.bin
PRLOADER= bin/prloader.bin
RZLOADER= bin/rzloader.bin
PRZLOADER= bin/przloader.bin
FLOPPYLOAD= bin/floppyload.bin
COMLOAD= bin/comload.bin
LILOPREFIX= bin/liloprefix.bin
endif
ifeq ($(AS86),as86)
LCPPFLAGS+= -DUSE_AS86
LASFLAGS+= $(AS86FLAGS) -0
LASBINARY:= -b
endif
ifeq ($(AS86),nasm)
LCPPFLAGS+= -DUSE_NASM
LASFLAGS+= $(NASMFLAGS) -fbin
LASBINARY:= -o
endif
ifeq ($(AS_PSEUDOS),n)
START16= start16.o.pre
START32= start32.o.pre
else
START16= bin16/start16.o
START32= bin32/startmpcc.o
endif
BOBJS16= bin16/main.o bin16/osloader.o bin16/misc.o bin16/bootmenu.o
BOBJS16+= bin16/floppy.o bin16/timer.o
BOBJS32= bin32/main.o bin32/osloader.o bin32/nfs.o bin32/misc.o
BOBJS32+= bin32/ansiesc.o bin32/bootmenu.o bin32/md5.o bin32/floppy.o
BOBJS32+= bin32/serial.o bin32/timer.o
BLIB16= bin16/bootlib.a
BLIB32= bin32/bootlib.a
LIBS16= $(BLIB16) $(LIBC16)
LIBS32= $(BLIB32) $(LIBC32) /usr/lib/gcc-lib/i386-redhat-linux/2.96/libgcc.a
UTIL_LZHUF:= $(shell if [ -d ../contrib/compressor ]; then echo bin/lzhuf; fi)
UTILS+= bin/makerom $(UTIL_LZHUF) bin/organon
STDDEPS16= $(START16) $(BLIB16) $(UTILS)
STDDEPS32= $(START32) $(BLIB32) $(UTILS)
MAKEDEPS= Makefile Config Roms
CHECKSIZE= { read d1; read d1 d2 d3 size d4; [ $$size -gt $(ROMLIMIT) ] &&\
{ $(RM) $@; echo "ERROR: code size exceeds limit!"; exit 1; }; exit 0; }
# Make sure that the relocation address is acceptable for all ROM sizes.
# Setting it to 0x98000 leaves about 29kB of space for the Etherboot program.
# The check is done based running 'size' on the binary, not ROM size, but
# roughly this means a ROM of 16kB or a partially used ROM of 32kB,
# remembering to compressed ROM images into account.
# You may also set RELOCADDR to 0x88000 to avoid using 0x98000
# because of other drivers (e.g. Disk On Chip). In that case, you may
# only load 512kB of OS, or load in memory above 1MB.
# Don't forget to choose an assembler because the loaders have to be rebuilt.
ifndef RELOCADDR
RELOCADDR=0x98000
#RELOCADDR=0xe0000
endif
# Evaluate ROMLIMIT only once - it is constant during the make run.
# Note that the 3K safety margin below is for the 1K extended BIOS data area
# and for the Etherboot runtime stack. Under normal situations, 2K of stack
# are rarely needed. If you experience strange behaviour in functions that use
# many local variables or that call functions that do, check for stack overrun!
# Make sure that the normal case needs no perl interpreter - if someone uses a
# different RELOCADDR, then he has perl installed anyways (the shell cannot
# deal with hex numbers, as test/eval don't support non-decimal integers).
ifeq ($(RELOCADDR),0x98000)
ROMLIMIT=29696
else
ROMLIMIT:=$(shell perl -e 'print 0x10000 - 3072 - ($(RELOCADDR) & 0xFFFF), "\n";')
endif
# Start of targets
all: $(UTILS) $(BUILD_LIBS) allbins
include Roms
# We need allbins because $(BINS16) and $(BINS32) are not defined until
# the Makefile fragment "Roms" is read.
allbins: $(BUILD_BINS)
# Common files
$(BLIB16): $(BOBJS16)
$(AR16) rv $@ $(BOBJS16)
$(RANLIB16) $@
$(BLIB32): $(BOBJS32)
$(AR32) rv $@ $(BOBJS32)
$(RANLIB32) $@
bin16/main.o: main.c etherboot.h osdep.h nic.h
bin32/main.o: main.c etherboot.h osdep.h nic.h
bin16/osloader.o: osloader.c etherboot.h osdep.h
bin32/osloader.o: osloader.c etherboot.h osdep.h
# NFS currently makes no sense for Etherboot/16
bin32/nfs.o: nfs.c etherboot.h osdep.h nic.h
bin16/misc.o: misc.c etherboot.h osdep.h
bin32/misc.o: misc.c etherboot.h osdep.h
# ANSIESC is not supported for Etherboot/16
bin32/ansiesc.o: ansiesc.c etherboot.h osdep.h
bin16/bootmenu.o: bootmenu.c etherboot.h osdep.h
bin32/bootmenu.o: bootmenu.c etherboot.h osdep.h
# Password support is not available for Etherboot/16
bin32/md5.o: md5.c etherboot.h osdep.h
bin16/floppy.o: floppy.c etherboot.h osdep.h
bin32/floppy.o: floppy.c etherboot.h osdep.h
bin16/timer.o: timer.c timer.h etherboot.h osdep.h
bin32/timer.o: timer.c timer.h etherboot.h osdep.h
bin32/inthw.o: inthw.c
# PCI support code (common to all PCI drivers)
bin32/pci.o: pci.c pci.h
# Do not add driver specific dependencies here unless it's something the
# genrules.pl script *can't* deal with, i.e. if it is not C code.
# Prepended loaders
#ifndef AS86
#$(RLOADER) $(RZLOADER) $(PRLOADER) $(PRZLOADER): $(MAKEDEPS)
# @if [ $(RELOCADDR) != 0x98000 ]; then echo Non-standard RELOCADDR, must assemble $@; exit 1; fi
# $(TOUCH) $@
#else
#bin/rloader.s: loader.S $(MAKEDEPS)
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -o $@ $<
#
#bin/rzloader.s: loader.S $(MAKEDEPS)
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DZLOADER -o $@ $<
#
#bin/prloader.s: loader.S $(MAKEDEPS)
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DPCI_PNP_HEADER -o $@ $<
#
#bin/przloader.s: loader.S $(MAKEDEPS)
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DPCI_PNP_HEADER -DZLOADER -o $@ $<
#endif
# Floppy loader
ifdef AS86
bin/floppyload.s: floppyload.S $(MAKEDEPS)
$(CPP) $(LCPPFLAGS) -o $@ $<
endif
# COM loader
ifdef AS86
bin/comload.s: comload.S $(MAKEDEPS)
$(CPP) $(LCPPFLAGS) -o $@ $<
endif
# LILO prefix:
ifdef AS86
bin/liloprefix.s: liloprefix.S $(MAKEDEPS)
$(CPP) $(LCPPFLAGS) -o $@ $<
endif
# Utilities
bin/makerom: makerom.c
$(GCC) -O2 -o $@ makerom.c
bin/organon: organon.c
$(GCC) -o $@ organon.c
bin/lzhuf: ../contrib/compressor/lzhuf.c
$(GCC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -o $@ $<
# Roms file
Roms: NIC genrules.pl
@chmod +x genrules.pl
./genrules.pl NIC > $@
# Pattern Rules
# general rules for compiling/assembling source files
bin16/%.o: %.c $(MAKEDEPS)
$(CC16) $(CFLAGS16) -o $@ -c $<
bin32/%.o: %.c $(MAKEDEPS)
$(CC32) $(CFLAGS32) -o $@ -c $<
bin16/%.o: %.S $(MAKEDEPS)
$(CC16) $(CFLAGS16) $(ASFLAGS16) -c -o $@ $<
bin32/%.o: %.S $(MAKEDEPS)
$(CPP) $(CFLAGS32) $< | $(AS) $(ASFLAGS32) -o $@
# general rule for .bin (plain binary loader code), may be overridden
ifdef AS86
bin/%.bin: bin/%.s
$(AS86) $(LASFLAGS) $(LASBINARY) $@ $<
endif
# general rule for .huf (compressed binary code), may be overridden
%.huf: %.img
bin/lzhuf e $< $@
# general rules for normal/compressed ROM images, may be overridden
bin16/%.rom: bin16/%.img $(RLOADER)
cat $(RLOADER) $< > $@
bin/makerom $(MAKEROM_$*) -i$(IDENT16) $@
bin32/%.rom: bin32/%.img $(RLOADER)
cat $(RLOADER) $< > $@
bin/makerom $(MAKEROM_$*) -i$(IDENT32) $@
bin16/%.lzrom: bin16/%.huf $(RZLOADER)
cat $(RZLOADER) $< > $@
bin/makerom $(MAKEROM_$*) -i$(IDENT16) $@
bin32/%.lzrom: bin32/%.huf $(RZLOADER)
cat $(RZLOADER) $< > $@
bin/makerom $(MAKEROM_$*) -i$(IDENT32) $@
# rules to write the .rom/.lzrom image onto a blank floppy
# You must give the directory name, e.g. use bin32/rtl8139.lzfd0 as the target.
%.fd0: %.rom $(FLOPPYLOAD)
cat $(FLOPPYLOAD) $< > /dev/fd0
%.lzfd0: %.lzrom $(FLOPPYLOAD)
cat $(FLOPPYLOAD) $< > /dev/fd0
# rules to generate a .com executable
# You must give the directory name, e.g. use bin32/rtl8139.com as the target.
%.com: %.lzrom $(COMLOAD)
cat $(COMLOAD) $< > $@
# rules to make a floppy image (padding to fill an even number of cylinders).
# VMware reports floppy image read errors if it cannot read ahead 36 sectors,
# probably because the floppyload.S code reads up to that number of sectors in
# a single request. Not that 18k matters much these days...
# You must give the directory name, e.g. use bin32/rtl8139.fdimg as the target.
%.fdimg: %.rom $(FLOPPYLOAD)
cat $(FLOPPYLOAD) $< > $@.x
dd if=$@.x of=$@ bs=36k conv=sync 2> /dev/null
$(RM) $@.x
%.lzfdimg: %.lzrom $(FLOPPYLOAD)
cat $(FLOPPYLOAD) $< > $@.x
dd if=$@.x of=$@ bs=36k conv=sync 2> /dev/null
$(RM) $@.x
# rules to make a LILO-bootable image
%.lilo: %.rom $(LILOPREFIX)
cat $(LILOPREFIX) $< /dev/zero | head -c 64k > $@
%.lzlilo: %.lzrom $(LILOPREFIX)
cat $(LILOPREFIX) $< /dev/zero | head -c 64k > $@
# Housekeeping
# To make sure that this actually builds a start32.o.pre with all options set,
# you have to make sure that -DFLOPPY -DANSIESC -DCONSOLE_DUAL are in CFLAGS32.
precompiled: bin/rloader.bin bin/rzloader.bin bin/prloader.bin bin/przloader.bin bin/floppyload.bin bin/comload.bin bin16/start16.o bin32/start32.o bin/liloprefix.bin
cp -p bin/rloader.bin rloader.bin.pre
cp -p bin/rzloader.bin rzloader.bin.pre
cp -p bin/prloader.bin prloader.bin.pre
cp -p bin/przloader.bin przloader.bin.pre
cp -p bin/floppyload.bin floppyload.bin.pre
cp -p bin/comload.bin comload.bin.pre
cp -p bin16/start16.o start16.o.pre
cp -p bin32/start32.o start32.o.pre
cp -p bin/liloprefix.bin liloprefix.bin.pre
clean:
$(RM) $(UTILS) bin/*.s bin/*.bin
$(RM) $(BLIB16) $(BLIB32)
$(RM) bin16/*.o bin32/*.o bin16/*.tmp bin32/*.tmp
$(RM) bin16/*.img bin32/*.img bin16/*.huf bin32/*.huf
$(RM) bin16/*.rom bin32/*.rom bin16/*.lzrom bin32/*.lzrom
$(RM) bin16/*.com bin32/*.com
$(RM) bin16/*.fdimg bin32/*.fdimg bin16/*.lzfdimg bin32/*.lzfdimg
$(RM) bin16/*.lilo bin32/*.lilo bin16/*.lzlilo bin32/*.lzlilo
$(RM) bin32/*.hex
$(RM) bin32/*.asm
$(RM) bin32/*.map
tarball:
(echo -n $(VERSION) ''; date -u +'%Y-%m-%d') > ../VERSION
(cd ..; tar cf /tmp/mpccboot-$(VERSION).tar --exclude CVS mpccboot)
bzip2 -9 < /tmp/mpccboot-$(VERSION).tar > /tmp/mpccboot-$(VERSION).tar.bz2
gzip -9 < /tmp/mpccboot-$(VERSION).tar > /tmp/mpccboot-$(VERSION).tar.gz
version:
@echo $(VERSION)

1119
contrib/baremetal/main.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
From: "Paolo Marini" <paolom@prisma-eng.it>
Subject: Etherboot on bare metal
Date: Tue, 10 Apr 2001 23:19:19 +0200
Organization: Prisma Engineering srl
Hi Ken,
I have ported Etherboot on an embedded, biosless platform and would like
to contribute the code.
Essentially, the hardware I was running Etherboot is a Pentium based
embedded system, with an Intel Chipset, *but* without serial, VGA,
keyboard etc., only an 82559 Intel (custom) Ethernet controller (I debug
it with the etheral Ethernet packet analyser and an emulator).
What I did was:
a.. integrate the init.s file within the firmware, with GDT
(re)initialisation (a simple and single entry point taking control of
the boot process)
b.. provide some stupid BIOS stubs in order to let the OS boot and
still belive that an INT10 call goes to the BIOS
c.. provide some basic functions to Etherboot, like timer (I used the
Pentium TSC internal counter)
d.. hardwire in the code information about the RAM size
The BIOS stubs are enough to boot Linux, pSOS and QNX with bootp. QNX is
somewhat difficult to load, because the i82559 driver tries to find the
component using the BIOS32 calls, so I had to patch it.
what i I got from the original firmware is the PCI initialisation and
resource (I/O, interrupts, memory) allocation.
I send you what I changed, that is, the initialisation code and the
misc.c file containing the timer, and the makefile (I don't remember
exactly the options I used to compile all).
Of course, it is only a good starting point for anyone wanting to
implement a bootp client on a biosless platform; some integration work
still needs to be done.
Ciao
Paolo
And in a subsequent email:
I worked with version 4.6.12, but the real modifications involve the
init.S file, which I think is quite sstable between releases. I forgot
to say that my entry point (symbol _start in init.s) assumes the
processor is already in protected mode.
[The only difference between main.c and misc.c from those in Etherboot
4.6.12 seems to be the deletion of eth_reset(). This may be of use to
others trying to make these changes work on more recent releases. Ken]

351
contrib/baremetal/misc.c Normal file
View File

@@ -0,0 +1,351 @@
/**************************************************************************
MISC Support Routines
**************************************************************************/
#include "etherboot.h"
/**************************************************************************
SLEEP
**************************************************************************/
void sleep(int secs)
{
unsigned long tmo;
for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; )
/* Nothing */;
}
/**************************************************************************
TWIDDLE
**************************************************************************/
void twiddle()
{
static unsigned long lastticks = 0;
static int count=0;
static const char tiddles[]="-\\|/";
unsigned long ticks;
if ((ticks = currticks()) == lastticks)
return;
lastticks = ticks;
putchar(tiddles[(count++)&3]);
putchar('\b');
}
/**************************************************************************
STRCASECMP (not entirely correct, but this will do for our purposes)
**************************************************************************/
int strcasecmp(a,b)
char *a, *b;
{
while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
return((*a & ~0x20) - (*b & ~0x20));
}
/**************************************************************************
PRINTF and friends
Formats:
%[#]X - 4 bytes long (8 hex digits)
%[#]x - 2 bytes int (4 hex digits)
- optional # prefixes 0x
%b - 1 byte int (2 hex digits)
%d - decimal int
%c - char
%s - string
%I - Internet address in x.x.x.x notation
Note: width specification not supported
**************************************************************************/
static char *do_printf(char *buf, const char *fmt, const int *dp)
{
register char *p;
int alt;
char tmp[16];
static const char hex[]="0123456789ABCDEF";
while (*fmt) {
if (*fmt == '%') { /* switch() uses more space */
alt = 0;
fmt++;
if (*fmt == '#') {
alt = 1;
fmt++;
}
if (*fmt == 'X') {
const long *lp = (const long *)dp;
register long h = *lp++;
dp = (const int *)lp;
if (alt) {
*buf++ = '0';
*buf++ = 'x';
}
*(buf++) = hex[(h>>28)& 0x0F];
*(buf++) = hex[(h>>24)& 0x0F];
*(buf++) = hex[(h>>20)& 0x0F];
*(buf++) = hex[(h>>16)& 0x0F];
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'x') {
register int h = *(dp++);
if (alt) {
*buf++ = '0';
*buf++ = 'x';
}
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'b') {
register int h = *(dp++);
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'd') {
register int dec = *(dp++);
p = tmp;
if (dec < 0) {
*(buf++) = '-';
dec = -dec;
}
do {
*(p++) = '0' + (dec%10);
dec = dec/10;
} while(dec);
while ((--p) >= tmp) *(buf++) = *p;
}
if (*fmt == 'I') {
union {
long l;
unsigned char c[4];
} u;
const long *lp = (const long *)dp;
u.l = *lp++;
dp = (const int *)lp;
buf = sprintf(buf,"%d.%d.%d.%d",
u.c[0], u.c[1], u.c[2], u.c[3]);
}
if (*fmt == 'c')
*(buf++) = *(dp++);
if (*fmt == 's') {
p = (char *)*dp++;
while (*p) *(buf++) = *p++;
}
} else *(buf++) = *fmt;
fmt++;
}
*buf = '\0';
return(buf);
}
char *sprintf(char *buf, const char *fmt, ...)
{
return do_printf(buf, fmt, ((const int *)&fmt)+1);
}
void printf(const char *fmt, ...)
{
char buf[120], *p;
p = buf;
do_printf(buf, fmt, ((const int *)&fmt)+1);
while (*p) putchar(*p++);
}
#ifdef IMAGE_MENU
/**************************************************************************
INET_ATON - Convert an ascii x.x.x.x to binary form
**************************************************************************/
int inet_aton(char *p, in_addr *i)
{
unsigned long ip = 0;
int val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = (ip << 8) | val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = (ip << 8) | val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
i->s_addr = htonl((ip << 8) | val);
return(1);
}
#endif /* IMAGE_MENU */
int getdec(char **ptr)
{
char *p = *ptr;
int ret=0;
if ((*p < '0') || (*p > '9')) return(-1);
while ((*p >= '0') && (*p <= '9')) {
ret = ret*10 + (*p - '0');
p++;
}
*ptr = p;
return(ret);
}
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keyboard status */
#define K_CMD 0x64 /* keybd ctlr command (write-only) */
#define K_OBUF_FUL 0x01 /* output buffer full */
#define K_IBUF_FUL 0x02 /* input buffer full */
#define KC_CMD_WIN 0xd0 /* read output port */
#define KC_CMD_WOUT 0xd1 /* write output port */
#define KB_SET_A20 0xdf /* enable A20,
enable output buffer full interrupt
enable data line
disable clock line */
#define KB_UNSET_A20 0xdd /* enable A20,
enable output buffer full interrupt
enable data line
disable clock line */
#ifndef IBM_L40
static void empty_8042(void)
{
unsigned long time;
char st;
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
(st & K_IBUF_FUL)) &&
currticks() < time)
inb(K_RDWR);
}
#endif IBM_L40
/*
* Gate A20 for high memory
*/
void gateA20_set(void)
{
#ifdef IBM_L40
outb(0x2, 0x92);
#else /* IBM_L40 */
empty_8042();
outb(KC_CMD_WOUT, K_CMD);
empty_8042();
outb(KB_SET_A20, K_RDWR);
empty_8042();
#endif /* IBM_L40 */
}
#ifdef TAGGED_IMAGE
/*
* Unset Gate A20 for high memory - some operating systems (mainly old 16 bit
* ones) don't expect it to be set by the boot loader.
*/
void gateA20_unset(void)
{
#ifdef IBM_L40
outb(0x0, 0x92);
#else /* IBM_L40 */
empty_8042();
outb(KC_CMD_WOUT, K_CMD);
empty_8042();
outb(KB_UNSET_A20, K_RDWR);
empty_8042();
#endif /* IBM_L40 */
}
#endif
#ifdef ETHERBOOT32
/* Serial console is only implemented in ETHERBOOT32 for now */
void
putchar(int c)
{
#ifndef ANSIESC
if (c == '\n')
putchar('\r');
#endif
#ifdef CONSOLE_CRT
#ifdef ANSIESC
handleansi(c);
#else
putc(c);
#endif
#endif
#ifdef CONSOLE_SERIAL
#ifdef ANSIESC
if (c == '\n')
serial_putc('\r');
#endif
serial_putc(c);
#endif
}
/**************************************************************************
GETCHAR - Read the next character from the console WITHOUT ECHO
**************************************************************************/
int
getchar(void)
{
int c = 256;
#if defined CONSOLE_CRT || defined CONSOLE_SERIAL
do {
#ifdef CONSOLE_CRT
if (ischar())
c = getc();
#endif
#ifdef CONSOLE_SERIAL
if (serial_ischar())
c = serial_getc();
#endif
} while (c==256);
if (c == '\r')
c = '\n';
#endif
return c;
}
int
iskey(void)
{
#ifdef CONSOLE_CRT
if (ischar())
return 1;
#endif
#ifdef CONSOLE_SERIAL
if (serial_ischar())
return 1;
#endif
return 0;
}
#endif /* ETHERBOOT32 */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
#include <asm/msr.h>
#define CPUCLOCK 166
unsigned long currticks(void)
{
register unsigned long l, h;
long long unsigned p;
long long unsigned hh,ll;
rdtsc(l, h);
ll = l, hh = h;
p = (ll + hh * 0x100000000LL) * 182 / (CPUCLOCK * 100000LL);
return (unsigned)p;
}

View File

@@ -0,0 +1,756 @@
/* #defines because ljmp wants a number, probably gas bug */
/* .equ KERN_CODE_SEG,_pmcs-_gdt */
#define KERN_CODE_SEG 0x08
.equ KERN_DATA_SEG,_pmds-_gdt
/* .equ REAL_CODE_SEG,_rmcs-_gdt */
#define REAL_CODE_SEG 0x18
.equ REAL_DATA_SEG,_rmds-_gdt
.equ CR0_PE,1
#ifdef GAS291
#define DATA32 data32;
#define ADDR32 addr32;
#define LJMPI(x) ljmp x
#else
#define DATA32 data32
#define ADDR32 addr32
/* newer GAS295 require #define LJMPI(x) ljmp *x */
#define LJMPI(x) ljmp x
#endif
#define PIC1_VBS 0x08 /* PIC1 interrupts start at vector 64 */
#define PIC2_VBS 0x70 /* PIC1 interrupts start at vector 112 */
/*
* NOTE: if you write a subroutine that is called from C code (gcc/egcs),
* then you only have to take care of %ebx, %esi, %edi and %ebp. These
* registers must not be altered under any circumstance. All other registers
* may be clobbered without any negative side effects. If you don't follow
* this rule then you'll run into strange effects that only occur on some
* gcc versions (because the register allocator may use different registers).
*
* All the data32 prefixes for the ljmp instructions are necessary, because
* the assembler emits code with a relocation address of 0. This means that
* all destinations are initially negative, which the assembler doesn't grok,
* because for some reason negative numbers don't fit into 16 bits. The addr32
* prefixes are there for the same reasons, because otherwise the memory
* references are only 16 bit wide. Theoretically they are all superfluous.
* One last note about prefixes: the data32 prefixes on all call _real_to_prot
* instructions could be removed if the _real_to_prot function is changed to
* deal correctly with 16 bit return addresses. I tried it, but failed.
*/
/**************************************************************************
START - Where all the fun begins....
**************************************************************************/
/* this must be the first thing in the file because we enter from the top */
.global _start
.code32
_start:
cli
/* load new IDT and GDT */
lgdt gdtarg
lidt Idt_Reg
/* flush prefetch queue, and reload %cs:%eip */
ljmp $KERN_CODE_SEG,$1f
1:
/* reload other segment registers */
movl $KERN_DATA_SEG,%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%ss
movl $stktop,%esp
/* program the PITs in order to stop them */
mov $0x30,%al
out %al,$0x43
out %al,$0x40
mov $0x70,%al
out %al,$0x43
out %al,$0x41
mov $0xf0,%al
out %al,$0x43
out %al,$0x42
call main
/* fall through */
.globl exit
exit:
2:
ljmp $KERN_CODE_SEG,$2b
/**************************************************************************
MEMSIZE - Determine size of extended memory
**************************************************************************/
.globl memsize
memsize:
#if 0
pushl %ebx
pushl %esi
pushl %edi
call _prot_to_real
.code16
movw $0xe801,%ax
stc
int $0x15
jc 1f
andl $0xffff,%eax
andl $0xffff,%ebx
shll $6,%ebx
addl %ebx,%eax
jmp 2f
1:
movw $0x8800,%ax
int $0x15
andl $0xffff,%eax
2:
movl %eax,%esi
DATA32 call _real_to_prot
.code32
movl %esi,%eax
popl %edi
popl %esi
popl %ebx
#else
mov $32768,%eax
#endif
ret
/**************************************************************************
XSTART - Transfer control to the kernel just loaded
**************************************************************************/
.code16
.globl _int08_handler
_int08_handler:
movb $0x20, %al
outb %al, $0x20
iret
.globl _int10_handler
_int10_handler:
cmp $0x3, %ah
jnz _int10_04
mov $0x0, %dx
mov $0x0, %cx
iret
_int10_04:
cmp $0x4, %ah
jnz _int10_05
mov $0x0, %ah
iret
_int10_05:
cmp $0x5, %ah
jnz _int10_08
mov $0x0, %al
iret
_int10_08:
cmp $0x8, %ah
jnz _int10_0D
mov $0x20, %al
mov $0x7, %ah
iret
_int10_0D:
cmp $0xD, %ah
jnz _int10_0F
mov $0x0, %al
iret
_int10_0F:
cmp $0xF, %ah
jnz _int10_XX
mov $0xb, %al
mov $80, %ah
mov $0, %bh
_int10_XX:
iret
.globl _int11_handler
_int11_handler:
mov $0x22, %ax
iret
.globl _int12_handler
_int12_handler:
mov $640, %ax
iret
.globl _int13_handler
_int13_handler:
clc
mov $0, %ah
iret
.globl _int14_handler
_int14_handler:
iret
.globl _int15_handler
_int15_handler:
cmp $0xe801,%ax
jz _int15_008
cmp $0x0, %ah
jz _int15_000
cmp $0x1, %ah
jz _int15_000
cmp $0x2, %ah
jz _int15_000
cmp $0x3, %ah
jz _int15_000
cmp $0xf, %ah
jz _int15_000
cmp $0x21, %ah
jz _int15_000
cmp $0x40, %ah
jz _int15_000
cmp $0x41, %ah
jz _int15_000
cmp $0x42, %ah
jz _int15_000
cmp $0x43, %ah
jz _int15_000
cmp $0x44, %ah
jz _int15_000
cmp $0x80, %ah
jz _int15_001
cmp $0x81, %ah
jz _int15_001
cmp $0x82, %ah
jz _int15_002
cmp $0x83, %ah
jz _int15_003
cmp $0x84, %ah
jz _int15_000
cmp $0x85, %ah
jz _int15_004
cmp $0x86, %ah
jz _int15_003
cmp $0x87, %ah
jz _int15_005
cmp $0x88, %ah
jz _int15_006
cmp $0x89, %ah
jz _int15_005
cmp $0x90, %ah
jz _int15_007
cmp $0xc0, %ah
jz _int15_000
cmp $0xc1, %ah
jz _int15_000
cmp $0xc2, %ah
jz _int15_000
cmp $0xc3, %ah
jz _int15_000
cmp $0xc4, %ah
jz _int15_000
iret
_int15_000:
mov $0x86, %ah
stc
iret
_int15_001:
mov $0, %bx
mov $0, %cx
iret
_int15_002:
mov $0, %bx
iret
_int15_003:
clc
iret
_int15_004:
mov $0, %al
iret
_int15_005:
mov $0, %ah
clc
cmp $0, %ah
iret
_int15_006:
mov $0xf000, %ax
iret
_int15_007:
stc
iret
_int15_008:
clc
mov $1024, %dx /* dx -> extended memory size (in 64K chuncks) */
mov $640, %cx /* cx -> conventional memory size (in 1 Kbytes chuncks) */
iret
.globl _int16_handler
_int16_handler:
cmp $0x0, %ah
jnz _int16_01
mov $0x20, %al
mov $0x39, %ah
iret
_int16_01:
cmp $0x1, %ah
jnz _int16_02
iret
_int16_02:
cmp $0x2, %ah
jnz _int16_05
mov $0, %al
iret
_int16_05:
cmp $0x5, %ah
jnz _int16_10
mov $0, %al
iret
_int16_10:
cmp $0x10, %ah
jnz _int16_11
mov $0x20, %al
mov $0x39, %ah
iret
_int16_11:
cmp $0x11, %ah
jnz _int16_12
iret
_int16_12:
cmp $0x12, %ah
jnz _int16_XX
mov $0, %ax
iret
_int16_XX:
iret
.globl _int17_handler
_int17_handler:
mov $0xd0, %ah
iret
.globl _int19_handler
_int19_handler:
hlt
iret
.globl _int1A_handler
_int1A_handler:
stc
iret
.code32
.globl xstart
xstart:
/* reprogram the PICs so that interrupt are masked */
movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/
outb %al,$0x20
movb $PIC1_VBS, %al
outb %al,$0x21
movb $0x4,%al
outb %al,$0x21
movb $0x1,%al
outb %al,$0x21
movb $0xff,%al
outb %al,$0x21
movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/
outb %al,$0xa0
movb $PIC2_VBS, %al
outb %al,$0xa1
movb $0x2,%al
outb %al,$0xa1
movb $0x1,%al
outb %al,$0xa1
movb $0xff,%al
outb %al,$0xa1
pushl %ebp
movl %esp,%ebp
pushl %ebx
pushl %esi
pushl %edi
movl 8(%ebp),%eax
movl %eax,_execaddr
movl 12(%ebp),%ebx
movl 16(%ebp),%ecx /* bootp record (32bit pointer) */
addl $28,%ecx /* ip, udp header */
shll $12,%ecx
shrw $12,%cx
call _prot_to_real
.code16
/* MP: add int10 handler */
push %eax
push %ebx
push %es
mov $0,%ax
mov %ax,%es
mov %cs,%ax
shl $16,%eax
ADDR32 mov $(_int08_handler-_start),%ax
mov $0x20,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int10_handler-_start),%ax
mov $0x40,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int11_handler-_start),%ax
mov $0x44,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int12_handler-_start),%ax
mov $0x48,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int13_handler-_start),%ax
mov $0x4c,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int14_handler-_start),%ax
mov $0x50,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int15_handler-_start),%ax
mov $0x54,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int16_handler-_start),%ax
mov $0x58,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int17_handler-_start),%ax
mov $0x5c,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int19_handler-_start),%ax
mov $0x64,%ebx
mov %eax,%es:(%bx)
ADDR32 mov $(_int1A_handler-_start),%ax
mov $0x68,%ebx
mov %eax,%es:(%bx)
pop %es
pop %ebx
pop %eax
/* */
pushl %ecx /* bootp record */
pushl %ebx /* file header */
movl $((RELOC<<12)+(1f-RELOC)),%eax
pushl %eax
ADDR32 LJMPI(_execaddr-_start)
1:
addw $8,%sp /* XXX or is this 10 in case of a 16bit "ret" */
DATA32 call _real_to_prot
.code32
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
_execaddr:
.long 0
#ifdef IMAGE_MULTIBOOT
/**************************************************************************
XEND - Restart Etherboot from the beginning (from protected mode)
**************************************************************************/
.globl xend
xend:
cs
lidt idtarg_realmode-_start+RELOC
cs
lgdt gdtarg-_start+RELOC
#ifdef GAS291
ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */
#else
ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */
#endif /* GAS291 */
1:
.code16
movw $REAL_DATA_SEG,%ax
movw %ax,%ds
movw %ax,%ss
movw %ax,%es
/* clear the PE bit of CR0 */
movl %cr0,%eax
andl $0!CR0_PE,%eax
movl %eax,%cr0
/* make intersegment jmp to flush the processor pipeline
* and reload %cs:%eip (to clear upper 16 bits of %eip).
*/
DATA32 ljmp $(RELOC)>>4,$2f-_start
2:
/* we are in real mode now
* set up the real mode segment registers : %ds, %ss, %es
*/
movw %cs,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%ss
xorl %esp,%esp
ADDR32 movw initsp-RELOC,%sp
movw $0,%ax
movw %ax,%fs
movw %ax,%gs
sti
jmp _start
.code32
#endif /* IMAGE_MULTIBOOT */
.global get_cs
get_cs:
xorl %eax,%eax
movw %cs,%ax
ret
.global get_ds
get_ds:
xorl %eax,%eax
movw %ds,%ax
ret
.global getsp
getsp:
movl %esp,%eax /* GET STACK POINTER */
subl $4, %eax /* ACCOUNT FOR RETURN ADDRESS ON */
ret
.global get_gdtbase
get_gdtbase:
sub $8,%esp /* ALLOCATE ROOM ON THE STACK */
sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */
mov 2(%esp),%eax /* READ GDT BASE ADDRESS */
mov $KERN_DATA_SEG,%dx /* ASSUME UNIVERSAL DS. */
add $8,%esp /* RESTORE STACK */
ret /* DONE */
.global get_gdtsize
get_gdtsize:
sub $8,%esp /* ALLOCATE ROOM ON THE STACK */
sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */
xor %eax,%eax
mov 2(%esp),%eax /* READ GDT BASE ADDRESS */
mov (%ESP),%ax
shr $3,%ax
add $8,%esp /* RESTORE STACK */
ret /* DONE */
.global get_idtbase
get_idtbase:
sub $8,%esp
sidt (%esp,1) /* STORE IIDT REGISTER ON STACK */
mov 2(%esp),%eax
mov $KERN_DATA_SEG,%dx
add $8,%esp
ret
.global get_lw
get_lw:
xor %edx,%edx
mov 8(%esp),%eax
mov 4(%esp),%dx
ret
/**************************************************************************
SETJMP - Save stack context for non-local goto
**************************************************************************/
.globl setjmp
setjmp:
mov 4(%esp),%ecx
mov 0(%esp),%edx
mov %edx,0(%ecx)
mov %ebx,4(%ecx)
mov %esp,8(%ecx)
mov %ebp,12(%ecx)
mov %esi,16(%ecx)
mov %edi,20(%ecx)
mov %eax,24(%ecx)
mov $0,%eax
ret
/**************************************************************************
LONGJMP - Non-local jump to a saved stack context
**************************************************************************/
.globl longjmp
longjmp:
mov 4(%esp),%edx
mov 8(%esp),%eax
mov 0(%edx),%ecx
mov 4(%edx),%ebx
mov 8(%edx),%esp
mov 12(%edx),%ebp
mov 16(%edx),%esi
mov 20(%edx),%edi
cmp $0,%eax
jne 1f
mov $1,%eax
1: mov %ecx,0(%esp)
ret
/**************************************************************************
_REAL_TO_PROT - Go from REAL mode to Protected Mode
**************************************************************************/
.globl _real_to_prot
_real_to_prot:
.code16
cli
cs
ADDR32 lgdt gdtarg-_start
movl %cr0,%eax
orl $CR0_PE,%eax
movl %eax,%cr0 /* turn on protected mode */
/* flush prefetch queue, and reload %cs:%eip */
DATA32 ljmp $KERN_CODE_SEG,$1f
1:
.code32
/* reload other segment registers */
movl $KERN_DATA_SEG,%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%ss
addl $RELOC,%esp /* Fix up stack pointer */
xorl %eax,%eax
movl %eax,%fs
movl %eax,%gs
popl %eax /* Fix up return address */
addl $RELOC,%eax
pushl %eax
ret
/**************************************************************************
_PROT_TO_REAL - Go from Protected Mode to REAL Mode
**************************************************************************/
.globl _prot_to_real
_prot_to_real:
.code32
popl %eax
subl $RELOC,%eax /* Adjust return address */
pushl %eax
subl $RELOC,%esp /* Adjust stack pointer */
#ifdef GAS291
ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */
#else
ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */
#endif /* GAS291 */
1:
.code16
movw $REAL_DATA_SEG,%ax
movw %ax,%ds
movw %ax,%ss
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
cli
/* clear the PE bit of CR0 */
movl %cr0,%eax
andl $0!CR0_PE,%eax
movl %eax,%cr0
/* make intersegment jmp to flush the processor pipeline
* and reload %cs:%eip (to clear upper 16 bits of %eip).
*/
DATA32 ljmp $(RELOC)>>4,$2f-_start
2:
/* we are in real mode now
* set up the real mode segment registers : %ds, $ss, %es
*/
movw %cs,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%ss
#if 0
sti
#endif
DATA32 ret /* There is a 32 bit return address on the stack */
.code32
/**************************************************************************
GLOBAL DESCRIPTOR TABLE
**************************************************************************/
.align 4
Idt_Reg:
.word 0x3ff
.long 0
.align 4
_gdt:
gdtarg:
Gdt_Table:
.word 0x27 /* limit */
.long _gdt /* addr */
.word 0
_pmcs:
/* 32 bit protected mode code segment */
.word 0xffff,0
.byte 0,0x9f,0xcf,0
_pmds:
/* 32 bit protected mode data segment */
.word 0xffff,0
.byte 0,0x93,0xcf,0
_rmcs:
/* 16 bit real mode code segment */
.word 0xffff,(RELOC&0xffff)
.byte (RELOC>>16),0x9b,0x00,(RELOC>>24)
_rmds:
/* 16 bit real mode data segment */
.word 0xffff,(RELOC&0xffff)
.byte (RELOC>>16),0x93,0x00,(RELOC>>24)
.align 4
RUN_GDT: /* POINTER TO GDT IN RAM */
.byte 0x7f,0 /* [BSP_GDT_NUM*8]-1 */
.long Gdt_Table
.align 4
.section ".rodata"
err_not386:
.ascii "Etherboot/32 requires 386+"
.byte 0x0d, 0x0a
err_not386_end:
days: .long 0
irq_num: .long
.data
.align 4
.org 2048
.global stktop
stktop:
.long
.section ".armando"
/* <20> <20> <20> <20> <20> <20> <20> <20>1:::::::::2:::::::::3:::::::3 */
/* <20> <20> <20> <20>12345678901234567890123456789012345678 */
/* <20> <20> <20> v----+----v----+----v----+----v----+--- */
.global EtherbootString
EtherbootString:
.ascii "EtherBoot MPCC " /* fw identifier */
.byte 0, 0 /* mandatory hole */
.long _start /* entry point */
.word 0
.byte 'E' /* type */
.byte 0 /* selector */
.word 0 /* CRC */