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
This commit is contained in:
64
util/extensions/legacybios/arch/x86/Makefile
Normal file
64
util/extensions/legacybios/arch/x86/Makefile
Normal file
@@ -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
|
39
util/extensions/legacybios/arch/x86/boot.S
Normal file
39
util/extensions/legacybios/arch/x86/boot.S
Normal file
@@ -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. */
|
27
util/extensions/legacybios/arch/x86/builtin.c
Normal file
27
util/extensions/legacybios/arch/x86/builtin.c
Normal file
@@ -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;
|
||||
}
|
395
util/extensions/legacybios/arch/x86/console.c
Normal file
395
util/extensions/legacybios/arch/x86/console.c
Normal file
@@ -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
|
55
util/extensions/legacybios/arch/x86/include/io.h
Normal file
55
util/extensions/legacybios/arch/x86/include/io.h
Normal file
@@ -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 */
|
96
util/extensions/legacybios/arch/x86/include/multiboot.h
Normal file
96
util/extensions/legacybios/arch/x86/include/multiboot.h
Normal file
@@ -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 */
|
57
util/extensions/legacybios/arch/x86/mboot.S
Normal file
57
util/extensions/legacybios/arch/x86/mboot.S
Normal file
@@ -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. */
|
92
util/extensions/legacybios/arch/x86/multiboot.c
Normal file
92
util/extensions/legacybios/arch/x86/multiboot.c
Normal file
@@ -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;
|
||||
}
|
126
util/extensions/legacybios/arch/x86/pci.c
Normal file
126
util/extensions/legacybios/arch/x86/pci.c
Normal file
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
21
util/extensions/legacybios/arch/x86/plainboot.c
Normal file
21
util/extensions/legacybios/arch/x86/plainboot.c
Normal file
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user