diff options
author | Stefan Reinauer <stepan@openbios.org> | 2003-09-18 14:16:08 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2003-09-18 14:16:08 +0000 |
commit | dcdbdfb46e7075515fef5be386e14c42463f7a5e (patch) | |
tree | ca43f548ddcb695d4843fe8a69a55e68ba325ca8 /util/extensions/legacybios/arch/x86 | |
parent | 59549598c08d5bdcee01bfb91dd9d147edf9fee7 (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/Makefile | 64 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/boot.S | 39 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/builtin.c | 27 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/console.c | 395 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/include/io.h | 55 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/include/multiboot.h | 96 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/mboot.S | 57 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/multiboot.c | 92 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/pci.c | 126 | ||||
-rw-r--r-- | util/extensions/legacybios/arch/x86/plainboot.c | 21 |
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(¤t, PCI_VENDOR_ID, &vendor); + pci_read_config_word(¤t, 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; +} |