summaryrefslogtreecommitdiff
path: root/util/extensions/legacybios/arch/x86
diff options
context:
space:
mode:
authorStefan Reinauer <stepan@openbios.org>2003-09-18 14:16:08 +0000
committerStefan Reinauer <stepan@openbios.org>2003-09-18 14:16:08 +0000
commitdcdbdfb46e7075515fef5be386e14c42463f7a5e (patch)
treeca43f548ddcb695d4843fe8a69a55e68ba325ca8 /util/extensions/legacybios/arch/x86
parent59549598c08d5bdcee01bfb91dd9d147edf9fee7 (diff)
first shot of legacybios emulation.
does not work yet.. sorry :-( git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1119 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'util/extensions/legacybios/arch/x86')
-rw-r--r--util/extensions/legacybios/arch/x86/Makefile64
-rw-r--r--util/extensions/legacybios/arch/x86/boot.S39
-rw-r--r--util/extensions/legacybios/arch/x86/builtin.c27
-rw-r--r--util/extensions/legacybios/arch/x86/console.c395
-rw-r--r--util/extensions/legacybios/arch/x86/include/io.h55
-rw-r--r--util/extensions/legacybios/arch/x86/include/multiboot.h96
-rw-r--r--util/extensions/legacybios/arch/x86/mboot.S57
-rw-r--r--util/extensions/legacybios/arch/x86/multiboot.c92
-rw-r--r--util/extensions/legacybios/arch/x86/pci.c126
-rw-r--r--util/extensions/legacybios/arch/x86/plainboot.c21
10 files changed, 972 insertions, 0 deletions
diff --git a/util/extensions/legacybios/arch/x86/Makefile b/util/extensions/legacybios/arch/x86/Makefile
new file mode 100644
index 0000000000..bb168c5b5e
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/Makefile
@@ -0,0 +1,64 @@
+# Copyright (C) 2003 Stefan Reinauer
+#
+# See the file "COPYING" for further information about
+# the copyright and warranty status of this work.
+#
+
+VPATH := $(TOPDIR)/include:$(BUILDDIR):$(TOPDIR)/arch/$(ARCH)/include
+
+BINARIES := legacybios.multiboot legacybios legacybios.full
+
+
+all: core link $(BINARIES)
+
+LDFLAGS_OPENBIOS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,100000
+
+OBJS_GENERIC = lib.o legacybios.o console.o pcibios.o malloc.o pci.o libx86emu.a
+OBJS_MULTIBOOT = mboot.o multiboot.o
+OBJS_PLAIN = boot.o plainboot.o
+OBJS_BUILTIN = boot.o builtin.o
+
+INCLUDES := -Iinclude -I$(TOPDIR)/include -I$(BUILDDIR)
+
+include $(TOPDIR)/Rules.make
+
+core:
+ echo -e "\nCompiling $(ARCH) architecture specific binaries"
+
+link: $(OBJS_MULTIBOOT) $(OBJS_PLAIN) $(OBJS_BUILTIN) $(OBJS_GENERIC)
+ cd $(BUILDDIR) && if [ ! -r legacybios.multiboot -o ! -r legacybios \
+ -o ! -r legacybios.full ]; then echo -e "\nLinking:"; fi
+
+legacybios.multiboot: $(OBJS_MULTIBOOT) $(OBJS_GENERIC)
+ echo -ne " multiboot image for grub... "
+ cd $(BUILDDIR) && $(CC) $(LDFLAGS_OPENBIOS) -o $@.nostrip $^ -lgcc
+ echo -e "\tok"
+ cd $(BUILDDIR) && objcopy -O binary -R .note -R .comment $@.nostrip $@
+
+legacybios: $(OBJS_PLAIN) $(OBJS_GENERIC)
+ echo -n " elf image (for LinuxBIOS)... "
+ cd $(BUILDDIR) && $(CC) $(LDFLAGS_OPENBIOS) -o $@.nostrip $^ -lgcc
+ echo -e "\tok"
+ cd $(BUILDDIR) && objcopy -R .note -R .comment $@.nostrip $@ && strip -s $@
+
+
+rom.h: vgabios.rom
+ echo -n " generating linkable rom..."
+ cd $(BUILDDIR) && ./bin2hex < $^ > $@
+ echo -e "\tok"
+
+legacybios.full: $(OBJS_BUILTIN) $(OBJS_GENERIC)
+ echo -n " elf image with rom... "
+ cd $(BUILDDIR) && $(CC) $(LDFLAGS_OPENBIOS) -o $@.nostrip $(OBJS_BUILTIN) $(OBJS_GENERIC) -lgcc
+ echo -e "\tok"
+ cd $(BUILDDIR) && objcopy -R .note -R .comment $@.nostrip $@ && strip -s $@
+
+
+# dependencies. these are so small that we write them manually.
+
+multiboot.o: multiboot.c types.h config.h multiboot.h
+boot.o: boot.S multiboot.h
+mboot.o: mboot.S multiboot.h
+console.o: console.c types.h config.h
+plainboot.o: types.h config.h
+builtin.o: rom.h
diff --git a/util/extensions/legacybios/arch/x86/boot.S b/util/extensions/legacybios/arch/x86/boot.S
new file mode 100644
index 0000000000..90b2ec0df6
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/boot.S
@@ -0,0 +1,39 @@
+/* boot.S
+ * assembler bootstrap
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#define ASM 1
+#include <multiboot.h>
+
+ .text
+
+ .code32
+ .globl start, _start
+
+ /* unused */
+start:
+_start:
+ /* Initialize stack pointer. */
+ movl $(stack + STACK_SIZE), %esp
+
+ /* Reset EFLAGS. */
+ pushl $0
+ popf
+
+ /* parameter 2 */
+ pushl %ebx
+ /* parameter 1 */
+ pushl %eax
+
+ /* jump to C main function... */
+ call EXT_C(cmain)
+
+loop: hlt
+ jmp loop
+
+ .comm stack, STACK_SIZE /* stack area. */
diff --git a/util/extensions/legacybios/arch/x86/builtin.c b/util/extensions/legacybios/arch/x86/builtin.c
new file mode 100644
index 0000000000..10368ab630
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/builtin.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "types.h"
+
+
+/*
+ * wrap an array around the hex'ed dictionary file
+ */
+
+static char romimage[] = {
+#include "rom.h"
+};
+
+void legacybios(ucell romstart, ucell romend);
+
+void cmain(void)
+{
+ legacybios((ucell) romimage,
+ (ucell) romimage + sizeof(romimage));
+ return;
+}
diff --git a/util/extensions/legacybios/arch/x86/console.c b/util/extensions/legacybios/arch/x86/console.c
new file mode 100644
index 0000000000..3204922499
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/console.c
@@ -0,0 +1,395 @@
+/* small console implementation */
+/*
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include <string.h>
+
+#include <config.h>
+#include <types.h>
+#include <io.h>
+#ifdef DEBUG_CONSOLE
+
+/* ******************************************************************
+ * serial console functions
+ * ****************************************************************** */
+
+#ifdef DEBUG_CONSOLE_SERIAL
+
+#define RBR(x) x==2?0x2f8:0x3f8
+#define THR(x) x==2?0x2f8:0x3f8
+#define IER(x) x==2?0x2f9:0x3f9
+#define IIR(x) x==2?0x2fa:0x3fa
+#define LCR(x) x==2?0x2fb:0x3fb
+#define MCR(x) x==2?0x2fc:0x3fc
+#define LSR(x) x==2?0x2fd:0x3fd
+#define MSR(x) x==2?0x2fe:0x3fe
+#define SCR(x) x==2?0x2ff:0x3ff
+#define DLL(x) x==2?0x2f8:0x3f8
+#define DLM(x) x==2?0x2f9:0x3f9
+
+static int uart_charav(int port)
+{
+ if (!port)
+ return -1;
+ return ((inb(LSR(port)) & 1) != 0);
+}
+
+static char uart_getchar(int port)
+{
+ if (!port)
+ return -1;
+ while (!uart_charav(port));
+ return ((char) inb(RBR(port)) & 0177);
+}
+
+static void uart_putchar(int port, unsigned char c)
+{
+ if (!port)
+ return;
+ if (c == '\n')
+ uart_putchar(port, '\r');
+ while (!(inb(LSR(port)) & 0x20));
+ outb(THR(port), c);
+}
+
+static void uart_init_line(int port, unsigned long baud)
+{
+ int i, baudconst;
+
+ if (!port)
+ return;
+
+ switch (baud) {
+ case 115200:
+ baudconst = 1;
+ break;
+ case 57600:
+ baudconst = 2;
+ break;
+ case 38400:
+ baudconst = 3;
+ break;
+ case 19200:
+ baudconst = 6;
+ break;
+ case 9600:
+ default:
+ baudconst = 12;
+ break;
+ }
+
+ outb(LCR(port), 0x87);
+ outb(DLM(port), 0);
+ outb(DLL(port), baudconst);
+ outb(LCR(port), 0x07);
+ outb(MCR(port), 0x0f);
+
+ for (i = 10; i > 0; i--) {
+ if (inb(LSR(port)) == (unsigned int) 0)
+ break;
+ inb(RBR(port));
+ }
+}
+
+int uart_init(int port, unsigned long speed)
+{
+ if (port)
+ uart_init_line(port, speed);
+ return -1;
+}
+
+static void serial_putchar(int c)
+{
+ uart_putchar(SERIAL_PORT, (unsigned char) (c & 0xff));
+}
+
+static void serial_cls(void)
+{
+ serial_putchar(27);
+ serial_putchar('[');
+ serial_putchar('H');
+ serial_putchar(27);
+ serial_putchar('[');
+ serial_putchar('J');
+}
+
+#endif
+
+/* ******************************************************************
+ * simple polling video/keyboard console functions
+ * ****************************************************************** */
+
+#ifdef DEBUG_CONSOLE_VGA
+
+/* raw vga text mode */
+#define COLUMNS 80 /* The number of columns. */
+#define LINES 25 /* The number of lines. */
+#define ATTRIBUTE 7 /* The attribute of an character. */
+
+#define VGA_BASE 0xB8000 /* The video memory address. */
+
+/* VGA Index and Data Registers */
+#define VGA_REG_INDEX 0x03D4 /* VGA index register */
+#define VGA_REG_DATA 0x03D5 /* VGA data register */
+
+#define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */
+#define VGA_IDX_CURSTART 0x0A /* cursor start */
+#define VGA_IDX_CUREND 0x0B /* cursor end */
+#define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits)*/
+#define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */
+
+/* Save the X and Y position. */
+static int xpos, ypos;
+/* Point to the video memory. */
+static volatile unsigned char *const video = (unsigned char *) VGA_BASE;
+
+static void video_initcursor(void)
+{
+ u8 val;
+ outb(VGA_REG_INDEX, VGA_IDX_CURMSL);
+ val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */
+
+ outb(VGA_REG_INDEX, VGA_IDX_CURSTART);
+ outb(VGA_REG_DATA, 0);
+
+ outb(VGA_REG_INDEX, VGA_IDX_CUREND);
+ outb(VGA_REG_DATA, val);
+}
+
+
+
+static void video_poscursor(unsigned int x, unsigned int y)
+{
+ unsigned short pos;
+
+ /* Calculate new cursor position as a function of x and y */
+ pos = (y*COLUMNS) + x;
+
+ /* Output the new position to VGA card */
+ outb(VGA_REG_INDEX, VGA_IDX_CURLO); /* output low 8 bits */
+ outb(VGA_REG_DATA, (u8) (pos));
+ outb(VGA_REG_INDEX, VGA_IDX_CURHI); /* output high 8 bits */
+ outb(VGA_REG_DATA, (u8) (pos >> 8));
+
+};
+
+
+static void video_newline(void)
+{
+ xpos = 0;
+
+ if (ypos < LINES-1) {
+ ypos++;
+ } else {
+ int i;
+ memmove((void *)video, (void *)(video+2*COLUMNS), (LINES-1)*COLUMNS*2);
+
+ for(i=( (LINES-1) *2*COLUMNS ); i<2*COLUMNS*LINES;) {
+ video[i++]=0;
+ video[i++]=ATTRIBUTE;
+ }
+ }
+
+}
+
+/* Put the character C on the screen. */
+static void video_putchar(int c)
+{
+ if (c == '\n' || c == '\r') {
+ video_newline();
+ return;
+ }
+
+ if (xpos >= COLUMNS)
+ video_newline();
+
+ *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
+ *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
+
+ xpos++;
+
+ video_poscursor(xpos, ypos);
+}
+
+static void video_cls(void)
+{
+ int i;
+ for(i=0; i<2*COLUMNS*LINES;) {
+ video[i++]=0;
+ video[i++]=ATTRIBUTE;
+ }
+
+
+ xpos = 0; ypos = 0;
+
+ video_initcursor();
+ video_poscursor(xpos,ypos);
+}
+
+/*
+ * keyboard driver
+ */
+
+static char normal[] = {
+ 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
+ '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
+ 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j',
+ 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b',
+ 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f
+};
+
+static char shifted[] = {
+ 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
+ '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
+ 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J',
+ 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B',
+ 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8',
+ '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f
+};
+
+static int key_ext;
+static int key_lshift = 0, key_rshift = 0, key_caps = 0;
+
+static char last_key;
+
+static void keyboard_cmd(unsigned char cmd, unsigned char val)
+{
+ outb(0x60, cmd);
+ /* wait until keyboard controller accepts cmds: */
+ while (inb(0x64) & 2);
+ outb(0x60, val);
+ while (inb(0x64) & 2);
+}
+
+static char keyboard_poll(void)
+{
+ unsigned int c;
+ if (inb(0x64) & 1) {
+ c = inb(0x60);
+ switch (c) {
+ case 0xe0:
+ key_ext = 1;
+ return 0;
+ case 0x2a:
+ key_lshift = 1;
+ return 0;
+ case 0x36:
+ key_rshift = 1;
+ return 0;
+ case 0xaa:
+ key_lshift = 0;
+ return 0;
+ case 0xb6:
+ key_rshift = 0;
+ return 0;
+ case 0x3a:
+ if (key_caps) {
+ key_caps = 0;
+ keyboard_cmd(0xed, 0);
+ } else {
+ key_caps = 1;
+ keyboard_cmd(0xed, 4); /* set caps led */
+ }
+ return 0;
+ }
+
+ if (key_ext) {
+ void printk(const char *format, ...);
+ printk("extended keycode: %x\n", c);
+
+ key_ext = 0;
+ return 0;
+ }
+
+ if (c & 0x80) /* unhandled key release */
+ return 0;
+
+ if (key_lshift || key_rshift)
+ return key_caps ? normal[c] : shifted[c];
+ else
+ return key_caps ? shifted[c] : normal[c];
+ }
+ return 0;
+}
+
+static int keyboard_dataready(void)
+{
+ if (last_key)
+ return 1;
+
+ last_key = keyboard_poll();
+
+ return (last_key != 0);
+}
+
+static unsigned char keyboard_readdata(void)
+{
+ char tmp;
+ while (!keyboard_dataready());
+ tmp = last_key;
+ last_key = 0;
+ return tmp;
+}
+#endif
+
+
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+int putchar(int c)
+{
+#ifdef DEBUG_CONSOLE_SERIAL
+ serial_putchar(c);
+#endif
+#ifdef DEBUG_CONSOLE_VGA
+ video_putchar(c);
+#endif
+ return c;
+}
+
+int availchar(void)
+{
+#ifdef DEBUG_CONSOLE_SERIAL
+ if (uart_charav(SERIAL_PORT))
+ return 1;
+#endif
+#ifdef DEBUG_CONSOLE_VGA
+ if (keyboard_dataready())
+ return 1;
+#endif
+ return 0;
+}
+
+int getchar(void)
+{
+#ifdef DEBUG_CONSOLE_SERIAL
+ if (uart_charav(SERIAL_PORT))
+ return (uart_getchar(SERIAL_PORT));
+#endif
+#ifdef DEBUG_CONSOLE_VGA
+ if (keyboard_dataready())
+ return (keyboard_readdata());
+#endif
+ return 0;
+}
+
+void cls(void)
+{
+#ifdef DEBUG_CONSOLE_SERIAL
+ serial_cls();
+#endif
+#ifdef DEBUG_CONSOLE_VGA
+ video_cls();
+#endif
+}
+
+
+#endif // DEBUG_CONSOLE
diff --git a/util/extensions/legacybios/arch/x86/include/io.h b/util/extensions/legacybios/arch/x86/include/io.h
new file mode 100644
index 0000000000..fd78334a7a
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/include/io.h
@@ -0,0 +1,55 @@
+/* I/O implementation
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ *
+ * this code is inspired by the linux kernel
+ *
+ */
+
+#ifndef IO_H
+#define IO_H
+
+#include <types.h>
+
+#define __EXTERN__ extern
+
+__EXTERN__ inline u8 inb(u32 port)
+{
+ u8 result;
+ __asm__ __volatile__ ( "inb %w1,%0" :"=a" (result) :"Nd" (port));
+ return result;
+}
+
+__EXTERN__ inline u16 inw(u32 port)
+{
+ u16 result;
+ __asm__ __volatile__ ( "inw %w1,%0" :"=a" (result) :"Nd" (port));
+ return result;
+}
+
+__EXTERN__ inline u32 inl(u32 port)
+{
+ u32 result;
+ __asm__ __volatile__ ( "inl %w1,%0" :"=a" (result) :"Nd" (port));
+ return result;
+}
+
+__EXTERN__ inline void outb (u32 port, u8 value)
+{
+ __asm__ __volatile__ ( "outb %b0,%w1" : :"a" (value), "Nd" (port));
+}
+
+__EXTERN__ inline void outw (u32 port, u16 value)
+{
+ __asm__ __volatile__ ( "outw %w0,%w1" : :"a" (value), "Nd" (port));
+}
+
+__EXTERN__ inline void outl (u32 port, u32 value)
+{
+ __asm__ __volatile__ ( "outl %0,%w1" : :"a" (value), "Nd" (port));
+}
+
+#endif /* IO_H */
diff --git a/util/extensions/legacybios/arch/x86/include/multiboot.h b/util/extensions/legacybios/arch/x86/include/multiboot.h
new file mode 100644
index 0000000000..4027035793
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/include/multiboot.h
@@ -0,0 +1,96 @@
+/* multiboot.h
+ * header for multiboot
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+/* magic number for multiboot header */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* flags for multiboot header */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* magic number passed by multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (8KB). */
+#define STACK_SIZE 0x2000
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* We don't want these declarations in boot.S */
+
+/* multiboot header */
+typedef struct multiboot_header {
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* symbol table for a.out */
+typedef struct aout_symbol_table {
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* section header table for ELF */
+typedef struct elf_section_header_table {
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* multiboot information */
+typedef struct multiboot_info {
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+} multiboot_info_t;
+
+/* module structure */
+typedef struct module {
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map {
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+#endif /* ! ASM */
diff --git a/util/extensions/legacybios/arch/x86/mboot.S b/util/extensions/legacybios/arch/x86/mboot.S
new file mode 100644
index 0000000000..679bfcbc72
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/mboot.S
@@ -0,0 +1,57 @@
+/* mboot.S
+ * legacybios assembler bootstrap for multiboot
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#define ASM 1
+#include <multiboot.h>
+
+ .text
+
+ .code32
+ .globl start, _start
+
+ /* unused */
+start:
+_start:
+ jmp multiboot_entry
+
+ /* Align 32 bits boundary. */
+ .align 4
+
+ /* Multiboot header. */
+multiboot_header:
+ .long MULTIBOOT_HEADER_MAGIC /* magic */
+ .long MULTIBOOT_HEADER_FLAGS /* flags */
+ .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+ /* checksum */
+ .long multiboot_header /* header_addr */
+ .long _start /* load_addr */
+ .long _edata /* load_end_addr */
+ .long _end /* bss_end_addr */
+ .long multiboot_entry /* entry_addr */
+
+multiboot_entry:
+ /* Initialize stack pointer. */
+ movl $(stack + STACK_SIZE), %esp
+
+ /* Reset EFLAGS. */
+ pushl $0
+ popf
+
+ /* pointer to multiboot information structure. */
+ pushl %ebx
+ /* magic value. */
+ pushl %eax
+
+ /* jump to C main function... */
+ call EXT_C(cmain)
+
+loop: hlt
+ jmp loop
+
+ .comm stack, STACK_SIZE /* stack area. */
diff --git a/util/extensions/legacybios/arch/x86/multiboot.c b/util/extensions/legacybios/arch/x86/multiboot.c
new file mode 100644
index 0000000000..a1793cf425
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/multiboot.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "types.h"
+#include "multiboot.h"
+
+/* Multiboot: Check if the bit BIT in FLAGS is set. */
+#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
+
+#ifdef DEBUG_CONSOLE
+void cls(void);
+void printk(const char *fmt, ...);
+int uart_init(int port, unsigned long speed);
+#endif
+
+void legacybios(ucell romstart, ucell romend);
+
+/* Check if MAGIC is valid and print the Multiboot information structure
+ pointed by ADDR. */
+
+void cmain(unsigned long magic, unsigned long addr)
+{
+ multiboot_info_t *mbi;
+
+#ifdef DEBUG_CONSOLE
+ uart_init(SERIAL_PORT, SERIAL_SPEED);
+ /* Clear the screen. */
+ cls();
+#endif
+
+ /* Am I booted by a Multiboot-compliant boot loader? */
+ if (magic != MULTIBOOT_BOOTLOADER_MAGIC) {
+ printk("legacybios: loader not multiboot capable\n");
+ return;
+ }
+
+ /* Set MBI to the address of the Multiboot information structure. */
+ mbi = (multiboot_info_t *) addr;
+
+#ifdef DEBUG_BOOT
+ /* Print out the flags. */
+ printk("flags = 0x%x\n", mbi->flags);
+
+ /* Are mem_* valid? */
+ if (CHECK_FLAG(mbi->flags, 0))
+ printk("mem_lower = %dKB, mem_upper = %dKB\n",
+ mbi->mem_lower, mbi->mem_upper);
+
+ /* Is boot_device valid? */
+ if (CHECK_FLAG(mbi->flags, 1))
+ printk("boot_device = 0x%x\n", mbi->boot_device);
+
+ /* Is the command line passed? */
+ if (CHECK_FLAG(mbi->flags, 2))
+ printk("cmdline = %s\n", (char *) mbi->cmdline);
+#endif
+
+#ifdef DEBUG_BOOT
+ /* Bits 4 and 5 are mutually exclusive! */
+ if (CHECK_FLAG(mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5)) {
+ printk("panic: binary claims to be a.out and elf.\n");
+ return;
+ }
+#endif
+
+ /* Are mods_* valid? */
+ if (CHECK_FLAG(mbi->flags, 3)) {
+ module_t *mod;
+ unsigned int i;
+#ifdef DEBUG_BOOT
+ printk("mods_count = %d, mods_addr = 0x%x\n",
+ mbi->mods_count, mbi->mods_addr);
+#endif
+ for (i = 0, mod = (module_t *) mbi->mods_addr;
+ i < mbi->mods_count; i++, mod += sizeof(module_t)) {
+ legacybios(mod->mod_start, mod->mod_end);
+#ifdef DEBUG_BOOT
+ printk
+ (" mod_start = 0x%x, mod_end = 0x%x, string = %s\n",
+ mod->mod_start, mod->mod_end,
+ (char *) mod->string);
+#endif
+ }
+ }
+
+ return;
+}
diff --git a/util/extensions/legacybios/arch/x86/pci.c b/util/extensions/legacybios/arch/x86/pci.c
new file mode 100644
index 0000000000..3fff076564
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/pci.c
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <io.h>
+#include <pci.h>
+
+void *malloc(unsigned int size);
+void *memset(void *s, int c, size_t count);
+
+#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus << 16) | (dev->devfn << 8) | (where & ~3))
+
+static struct pci_dev *pcidevices = NULL;
+
+struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
+ struct pci_dev *from)
+{
+ struct pci_dev *curr = from ? from : pcidevices;
+
+ while (curr) {
+ if (curr->vendor == vendor && curr->device == device)
+ return curr;
+ curr = curr->next;
+ }
+ return NULL;
+}
+
+struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
+{
+ struct pci_dev *curr = pcidevices;
+
+ while (curr) {
+ if (curr->devfn == devfn && curr->bus == bus)
+ return curr;
+ curr = curr->next;
+ }
+ return NULL;
+}
+
+int pci_read_config_byte(struct pci_dev *dev, u8 where, u8 * val)
+{
+ outl(0xcf8, CONFIG_CMD(dev, where));
+ *val = inb(0xCFC + (where & 3));
+ return 0;
+}
+
+int pci_read_config_word(struct pci_dev *dev, u8 where, u16 * val)
+{
+ outl(0xcf8, CONFIG_CMD(dev, where));
+ *val = inb(0xCFC + (where & 2));
+ return 0;
+}
+
+int pci_read_config_dword(struct pci_dev *dev, u8 where, u32 * val)
+{
+ outl(0xcf8, CONFIG_CMD(dev, where));
+ *val = inb(0xCFC);
+ return 0;
+}
+
+int pci_write_config_byte(struct pci_dev *dev, u8 where, u8 val)
+{
+ outl(0xcf8, CONFIG_CMD(dev, where));
+ outb(0xCFC + (where & 3), val);
+ return 0;
+}
+
+int pci_write_config_word(struct pci_dev *dev, u8 where, u16 val)
+{
+ outl(0xcf8, CONFIG_CMD(dev, where));
+ outb(0xCFC + (where & 2), val);
+ return 0;
+}
+
+int pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val)
+{
+ outl(0xcf8, CONFIG_CMD(dev, where));
+ outb(0xCFC, where);
+ return 0;
+}
+
+#define FUNC(x) ((x) & 7)
+#define SLOT(x) ((x) >> 3)
+#define MAX_DEV (20 << 3)
+
+void pci_init(void)
+{
+ struct pci_dev *pdev, **p, current;
+ int dev, bus = 0, multi = 0;
+
+ pcidevices = NULL;
+
+ for (dev = 0; dev < MAX_DEV; dev++) {
+ u16 vendor, device;
+
+ if (!multi && FUNC(dev))
+ continue;
+
+ current.bus = bus; // FIXME
+ current.devfn = dev;
+
+ pci_read_config_word(&current, PCI_VENDOR_ID, &vendor);
+ pci_read_config_word(&current, PCI_DEVICE_ID, &device);
+
+ if (vendor == 0xffff || vendor == 0x0000 ||
+ device == 0xffff || device == 0x0000)
+ continue;
+
+ pdev = malloc(sizeof(*pdev));
+ memset(pdev, 0, sizeof(*pdev));
+
+ pdev->vendor = vendor;
+ pdev->device = device;
+ pdev->bus = current.bus;
+
+ pci_read_config_byte(pdev, PCI_HEADER_TYPE, &(pdev->header));
+ pci_read_config_word(pdev, PCI_COMMAND, &(pdev->command));
+ pci_read_config_byte(pdev, PCI_CLASS_PROG, &(pdev->progif));
+ pci_read_config_word(pdev, PCI_CLASS_DEVICE, &(pdev->class));
+ pdev->devfn = dev;
+
+ multi = pdev->header & 0x80;
+ for (p = &pcidevices; *p; p = &(*p)->next);
+ *p = pdev;
+
+ }
+
+
+}
diff --git a/util/extensions/legacybios/arch/x86/plainboot.c b/util/extensions/legacybios/arch/x86/plainboot.c
new file mode 100644
index 0000000000..b43cc720e2
--- /dev/null
+++ b/util/extensions/legacybios/arch/x86/plainboot.c
@@ -0,0 +1,21 @@
+/* tag: legacybios starter
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "types.h"
+
+#define FIXED_ROMSTART 0xc0000
+#define FIXED_ROMEND 0xcffff
+
+void legacybios(ucell romstart, ucell romend);
+
+void cmain(void)
+{
+ legacybios(FIXED_ROMSTART,FIXED_ROMEND);
+ return;
+}