mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
Add a first bit of a framework. Builds the following parts, in
accordance to the newboot document: * reset vector (16 bytes) * vpd (240bytes) * boot block (8k - 256b) * lar archive (256-8 k) The boot block is kind of simple, still. It enables pmode, car, and starts looking for an initram module in the lar archive. Note: This doesnt do much at the moment, as gas seems to produce buggy code in init.S. Take this as a suggestion of how it might work and please provide patches fixing it and bringing it into shape. Signed-off-by: Stefan Reinauer <stepan@coresystems.de> Acked-by: Ronald G. Minnich <rminnich@gmail.com> git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@62 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
parent
e388149797
commit
c275218a89
25 changed files with 1627 additions and 496 deletions
2
Makefile
2
Makefile
|
@ -418,7 +418,7 @@ include $(srctree)/arch/$(ARCH)/Makefile
|
|||
export KBUILD_DEFCONFIG
|
||||
|
||||
config %config: scripts_basic outputmakefile FORCE
|
||||
$(Q)mkdir -p include/linux
|
||||
$(Q)mkdir -p include/linuxbios
|
||||
$(Q)$(MAKE) $(build)=scripts/kconfig $@
|
||||
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
|
||||
|
||||
|
|
|
@ -24,11 +24,15 @@
|
|||
# might want to read
|
||||
#
|
||||
|
||||
CFLAGS :=
|
||||
|
||||
linuxbios.jump: FORCE
|
||||
$(Q)echo "Building jump vector"
|
||||
$(Q)dd if=/dev/zero of=$(objtree)/linuxbios.jump bs=16 count=1 # 0x10
|
||||
touch $(objtree)/linuxbios.jump
|
||||
|
||||
$(Q)$(CC) -E $(srctree)/arch/x86/reset.S -o $(objtree)/reset.s -DBOOTBLK=0x1f00 -DRESRVED=0xf0 -DDATE=\"`date +%Y/%m/%d`\"
|
||||
$(Q)$(AS) $(objtree)/reset.s -o $(objtree)/reset.o
|
||||
$(Q)$(LD) -Ttext 0xfffffff0 -s --oformat binary $(objtree)/reset.o -o $(objtree)/linuxbios.jump
|
||||
$(Q)chmod 644 $(objtree)/linuxbios.jump
|
||||
$(Q)echo "Len: `wc -c < linuxbios.jump`"
|
||||
|
||||
#
|
||||
# This part takes care of compression. It should build the compression modules
|
||||
|
@ -68,35 +72,53 @@ linuxbios_ram: statictree.o
|
|||
payload:
|
||||
$(Q)echo "building payload"
|
||||
|
||||
|
||||
#
|
||||
# build the lar archive
|
||||
#
|
||||
|
||||
|
||||
linuxbios.lar: lzma initram linuxbios_ram payload
|
||||
$(Q)echo lar c $(objdir)/linuxbios.lar $^
|
||||
$(Q)dd if=/dev/zero of=$(objtree)/linuxbios.lar bs=57088 count=1
|
||||
|
||||
linuxbios.lar: $(objtree)/lar lzma linuxbios.initram linuxbios_ram payload
|
||||
$(Q)echo "Building LinuxBIOS archive..."
|
||||
$(Q)mkdir $(objtree)/lar.tmp
|
||||
$(Q)mkdir $(objtree)/lar.tmp/normal
|
||||
$(Q)cp $(objtree)/linuxbios.initram $(objtree)/lar.tmp/normal/initram
|
||||
$(Q)cd $(objtree)/lar.tmp && ../lar c ../linuxbios.lar.pre normal/initram
|
||||
# TODO: dynamically pad the lar archive. bs is image size - bootblock size (8k)
|
||||
$(Q)dd if=$(objtree)/linuxbios.lar.pre of=$(objtree)/linuxbios.lar bs=253952 count=1 conv=sync
|
||||
|
||||
#
|
||||
# this is going to be the enable car code, lar parser and such:
|
||||
#
|
||||
|
||||
INITCFLAGS=-I$(srctree)/include/cpu/generic/x86 -I$(srctree)/include -fno-builtin -Os
|
||||
|
||||
linuxbios.init:
|
||||
$(Q)echo Building init from $^
|
||||
$(Q)dd if=/dev/zero of=$(objtree)/linuxbios.init bs=8192 count=1
|
||||
$(Q)echo Building linuxbios.init
|
||||
#
|
||||
# asm stub
|
||||
$(Q)$(CC) -E $(srctree)/arch/x86/init.S -o $(objtree)/init.s
|
||||
$(Q)$(AS) $(objtree)/init.s -o $(objtree)/init.o
|
||||
#
|
||||
# main
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/arch/x86/cachemain.c -o cachemain.o
|
||||
#
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/lib/lar.c -o lar.o
|
||||
#
|
||||
# console lib
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/arch/x86/console.c -o console.o
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/arch/x86/serial.c -o serial.o
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/console/vtxprintf.c -o vtxprintf.o
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/lib/uart8250.c -o uart8250.o
|
||||
|
||||
#
|
||||
# VPD or SIP ROM or ... how does nvidia call it?
|
||||
# Some space to cope with dirty southbridge tricks.
|
||||
# Do we want to put our own stuff there, too?
|
||||
#
|
||||
# TODO: dynamic start address 4G - 0x2000 (bootblock size)
|
||||
$(Q)$(LD) -Ttext 0xffffe000 -s --oformat binary init.o cachemain.o console.o uart8250.o \
|
||||
serial.o vtxprintf.o lar.o -o linuxbios.init.pre
|
||||
|
||||
#linuxbios.vpd:
|
||||
# $(Q)printf "Building dummy VPD ..."
|
||||
# $(Q)dd if=/dev/zero of=$(objtree)/linuxbios.vpd bs=240 count=1 # 0xf0
|
||||
# $(Q)printf "ok.\n"
|
||||
# Pad boot block to 0x2000 - 0x100
|
||||
$(Q)dd if=linuxbios.init.pre of=linuxbios.init bs=7936 conv=sync
|
||||
$(Q)echo "Len: `wc -c < linuxbios.init.pre`"
|
||||
#
|
||||
$(Q)test `wc -c < linuxbios.init.pre` -gt 7936 && echo "Error. Bootblock got too big" || true
|
||||
|
||||
#
|
||||
# Compose the image:
|
||||
|
@ -107,18 +129,9 @@ linuxbios.rom: linuxbios.lar linuxbios.init linuxbios.vpd linuxbios.jump
|
|||
$(objtree)/linuxbios.vpd $(objtree)/linuxbios.jump > \
|
||||
$(objtree)/linuxbios.rom
|
||||
|
||||
# miscellaneous important targets.
|
||||
$(objtree)/mainboard.o: $(objtree)/statictree.o
|
||||
|
||||
$(objtree)/statictree.o: $(objtree)/statictree.c
|
||||
$(CC) $(CFLAGS) $(LINUXBIOSINCLUDE) -c -o $(objtree)/statictree.o $(objtree)/statictree.c
|
||||
|
||||
$(objtree)/statictree.c: mainboard/$(MAINBOARDDIR)/dts $(objtree)/dtc
|
||||
$(objtree)/dtc -O lb mainboard/$(MAINBOARDDIR)/dts >$(objtree)/statictree.c
|
||||
|
||||
$(objtree)/dtc:
|
||||
$(MAKE) -C $(srctree)/util/dtc/
|
||||
cp $(srctree)/util/dtc/dtc $(objtree)
|
||||
$(objtree)/lar:
|
||||
$(MAKE) -C $(srctree)/util/lar
|
||||
cp $(srctree)/util/lar/lar $(objtree)
|
||||
|
||||
|
||||
.PHONY: linuxbios.rom
|
||||
|
|
259
arch/x86/cache_as_ram.S
Normal file
259
arch/x86/cache_as_ram.S
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* Copyright (C) 2005 Eswar Nallusamy, LANL
|
||||
* Copyright (C) 2005 Yinghai Lu, Tyan Corp.
|
||||
* Copyright (C) 2007 Stefan Reinauer, coresystems GmbH
|
||||
|
||||
/* We will use 4Kbytes only for cache as ram. This is
|
||||
* enough to fit in our stack.
|
||||
*
|
||||
* disable HyperThreading is done by eswar
|
||||
* the other is very similar to the AMD CAR, except remove amd specific msr
|
||||
*/
|
||||
|
||||
#define CacheSize 4096
|
||||
#define CacheBase (0xd0000 - CacheSize)
|
||||
|
||||
#define ASSEMBLY
|
||||
#include "mtrr.h"
|
||||
|
||||
/* Save the BIST result */
|
||||
movl %eax, %ebp
|
||||
|
||||
CacheAsRam:
|
||||
/* Check whether the processor has HT capability */
|
||||
movl $01, %eax
|
||||
cpuid
|
||||
btl $28, %edx
|
||||
jnc NotHtProcessor
|
||||
bswapl %ebx
|
||||
cmpb $01, %bh
|
||||
jbe NotHtProcessor
|
||||
|
||||
/* It is a HT processor; Send SIPI to the other logical processor
|
||||
* within this processor so that the CAR related common system
|
||||
* registers are programmed accordingly
|
||||
*/
|
||||
|
||||
/* Use some register that is common to both logical processors
|
||||
* as semaphore. Refer Appendix B, Vol.3
|
||||
*/
|
||||
|
||||
xorl %eax, %eax
|
||||
xorl %edx, %edx
|
||||
movl $0x250, %ecx
|
||||
wrmsr
|
||||
|
||||
/* Figure out the logical AP's APIC ID; the following logic will work
|
||||
* only for processors with 2 threads.
|
||||
*
|
||||
* Refer to Vol 3. Table 7-1 for details about this logic
|
||||
*/
|
||||
movl $0xFEE00020, %esi
|
||||
movl (%esi), %ebx
|
||||
andl $0xFF000000, %ebx
|
||||
bswapl %ebx
|
||||
btl $0, %ebx
|
||||
jnc LogicalAP0
|
||||
andb $0xFE, %bl
|
||||
jmp SendSIPI
|
||||
LogicalAP0:
|
||||
orb $0x01, %bl
|
||||
SendSIPI:
|
||||
bswapl %ebx /* ebx - logical AP's APIC ID */
|
||||
|
||||
/* Fill up the IPI command registers in the Local APIC mapped to
|
||||
* default address and issue SIPI to the other logical processor
|
||||
* within this processor die.
|
||||
*/
|
||||
|
||||
RetrySIPI:
|
||||
movl %ebx, %eax
|
||||
movl $0xFEE00310, %esi
|
||||
movl %eax, (%esi)
|
||||
|
||||
/* SIPI vector - F900:0000 */
|
||||
movl $0x000006F9, %eax
|
||||
movl $0xFEE00300, %esi
|
||||
movl %eax, (%esi)
|
||||
|
||||
movl $0x30, %ecx
|
||||
SIPIDelay:
|
||||
pause
|
||||
decl %ecx
|
||||
jnz SIPIDelay
|
||||
|
||||
movl (%esi), %eax
|
||||
andl $0x00001000, %eax
|
||||
jnz RetrySIPI
|
||||
|
||||
/* Wait for the Logical AP to complete initialization */
|
||||
LogicalAPSIPINotdone:
|
||||
movl $0x250, %ecx
|
||||
rdmsr
|
||||
orl %eax, %eax
|
||||
jz LogicalAPSIPINotdone
|
||||
|
||||
|
||||
|
||||
NotHtProcessor:
|
||||
/* Set the default memory type and enable fixed and variable MTRRs */
|
||||
movl $MTRRdefType_MSR, %ecx
|
||||
xorl %edx, %edx
|
||||
/* Enable Variable and Fixed MTRRs */
|
||||
movl $0x00000c00, %eax
|
||||
wrmsr
|
||||
|
||||
/*Clear all MTRRs */
|
||||
xorl %edx, %edx
|
||||
movl $fixed_mtrr_msr, %esi
|
||||
clear_fixed_var_mtrr:
|
||||
lodsl (%esi), %eax
|
||||
testl %eax, %eax
|
||||
jz clear_fixed_var_mtrr_out
|
||||
|
||||
movl %eax, %ecx
|
||||
xorl %eax, %eax
|
||||
wrmsr
|
||||
|
||||
jmp clear_fixed_var_mtrr
|
||||
clear_fixed_var_mtrr_out:
|
||||
|
||||
#if CacheSize == 0x10000
|
||||
/* enable caching for 64K using fixed mtrr */
|
||||
movl $0x268, %ecx /* fix4k_c0000*/
|
||||
movl $0x06060606, %eax /* WB IO type */
|
||||
movl %eax, %edx
|
||||
wrmsr
|
||||
movl $0x269, %ecx
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
#if CacheSize == 0x8000
|
||||
/* enable caching for 32K using fixed mtrr */
|
||||
movl $0x269, %ecx /* fix4k_c8000*/
|
||||
movl $0x06060606, %eax /* WB IO type */
|
||||
movl %eax, %edx
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
/* enable caching for 16K/8K/4K using fixed mtrr */
|
||||
movl $0x269, %ecx /* fix4k_cc000*/
|
||||
#if CacheSize == 0x4000
|
||||
movl $0x06060606, %edx /* WB IO type */
|
||||
#endif
|
||||
#if CacheSize == 0x2000
|
||||
movl $0x06060000, %edx /* WB IO type */
|
||||
#endif
|
||||
#if CacheSize == 0x1000
|
||||
movl $0x06000000, %edx /* WB IO type */
|
||||
#endif
|
||||
xorl %eax, %eax
|
||||
wrmsr
|
||||
|
||||
#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
|
||||
/* enable write base caching so we can do execute in place
|
||||
* on the flash rom.
|
||||
*/
|
||||
movl $0x202, %ecx
|
||||
xorl %edx, %edx
|
||||
movl $(XIP_ROM_BASE | MTRR_TYPE_WRBACK), %eax
|
||||
wrmsr
|
||||
|
||||
movl $0x203, %ecx
|
||||
movl $0x0000000f, %edx
|
||||
movl $(~(XIP_ROM_SIZE - 1) | 0x800), %eax
|
||||
wrmsr
|
||||
#endif /* XIP_ROM_SIZE && XIP_ROM_BASE */
|
||||
|
||||
/* enable cache */
|
||||
movl %cr0, %eax
|
||||
andl $0x9fffffff,%eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Read the range with lodsl*/
|
||||
movl $CacheBase, %esi
|
||||
cld
|
||||
movl $(CacheSize>>2), %ecx
|
||||
rep lodsl
|
||||
|
||||
/* Clear the range */
|
||||
movl $CacheBase, %edi
|
||||
movl $(CacheSize>>2), %ecx
|
||||
xorl %eax, %eax
|
||||
rep stosl
|
||||
|
||||
|
||||
#if 0
|
||||
/* check the cache as ram */
|
||||
movl $CacheBase, %esi
|
||||
movl $(CacheSize>>2), %ecx
|
||||
.xin1:
|
||||
movl %esi, %eax
|
||||
movl %eax, (%esi)
|
||||
decl %ecx
|
||||
je .xout1
|
||||
add $4, %esi
|
||||
jmp .xin1
|
||||
.xout1:
|
||||
|
||||
movl $CacheBase, %esi
|
||||
// movl $(CacheSize>>2), %ecx
|
||||
movl $4, %ecx
|
||||
.xin1x:
|
||||
movl %esi, %eax
|
||||
|
||||
movl $0x4000, %edx
|
||||
movb %ah, %al
|
||||
.testx1:
|
||||
outb %al, $0x80
|
||||
decl %edx
|
||||
jnz .testx1
|
||||
|
||||
movl (%esi), %eax
|
||||
cmpb 0xff, %al
|
||||
je .xin2 /* dont show */
|
||||
|
||||
movl $0x4000, %edx
|
||||
.testx2:
|
||||
outb %al, $0x80
|
||||
decl %edx
|
||||
jnz .testx2
|
||||
|
||||
.xin2: decl %ecx
|
||||
je .xout1x
|
||||
add $4, %esi
|
||||
jmp .xin1x
|
||||
.xout1x:
|
||||
|
||||
#endif
|
||||
|
||||
movl $(CacheBase+CacheSize-4), %eax
|
||||
movl %eax, %esp
|
||||
|
||||
/* Load a different set of data segments */
|
||||
movw $CACHE_RAM_DATA_SEG, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
|
||||
lout:
|
||||
|
||||
/* Restore the BIST result */
|
||||
movl %ebp, %eax
|
||||
/* We need to set ebp ? No need */
|
||||
movl %esp, %ebp
|
||||
pushl %eax /* bist */
|
||||
call stage1_main
|
||||
/* We will not go back */
|
||||
|
||||
fixed_mtrr_msr:
|
||||
.long 0x250, 0x258, 0x259
|
||||
.long 0x268, 0x269, 0x26A
|
||||
.long 0x26B, 0x26C, 0x26D
|
||||
.long 0x26E, 0x26F
|
||||
var_mtrr_msr:
|
||||
.long 0x200, 0x201, 0x202, 0x203
|
||||
.long 0x204, 0x205, 0x206, 0x207
|
||||
.long 0x208, 0x209, 0x20A, 0x20B
|
||||
.long 0x20C, 0x20D, 0x20E, 0x20F
|
||||
.long 0x000 /* NULL, end of table */
|
||||
|
92
arch/x86/cachemain.c
Normal file
92
arch/x86/cachemain.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* GPLv2.
|
||||
*
|
||||
* Copyright (C) 2007 Stefan Reinauer <stepan@coresystems.de>, coresystems GmbH
|
||||
*/
|
||||
|
||||
#include <arch/types.h>
|
||||
#include <arch/io.h>
|
||||
#include <console/loglevel.h>
|
||||
#include <lar.h>
|
||||
#include "config.h"
|
||||
|
||||
static void post_code(u8 value)
|
||||
{
|
||||
outb(value, 0x80);
|
||||
}
|
||||
|
||||
static void stop_ap(void)
|
||||
{
|
||||
// nothing yet
|
||||
post_code(0xf0);
|
||||
}
|
||||
|
||||
static void enable_superio(void)
|
||||
{
|
||||
// nothing yet
|
||||
post_code(0xf1);
|
||||
}
|
||||
|
||||
static void enable_rom(void)
|
||||
{
|
||||
// nothing here yet
|
||||
post_code(0xf2);
|
||||
}
|
||||
|
||||
void stage1_main(u32 bist)
|
||||
{
|
||||
int ret;
|
||||
struct mem_file archive, result;
|
||||
|
||||
post_code(0x02);
|
||||
|
||||
// before we do anything, we want to stop if we dont run
|
||||
// on the bootstrap processor.
|
||||
if (bist==0) {
|
||||
// stop secondaries
|
||||
stop_ap();
|
||||
}
|
||||
|
||||
// We have cache as ram running and can start executing code in C.
|
||||
//
|
||||
|
||||
enable_superio();
|
||||
|
||||
//
|
||||
uart_init(); // initialize serial port
|
||||
console_init(); // print banner
|
||||
|
||||
if (bist!=0) {
|
||||
die("BIST FAILED: %08x", bist);
|
||||
}
|
||||
|
||||
// enable rom
|
||||
enable_rom();
|
||||
|
||||
// location and size of image.
|
||||
|
||||
// FIXME this should be defined in the VPD area
|
||||
// but NOT IN THE CODE.
|
||||
|
||||
archive.len=LINUXBIOS_ROMSIZE_KB*1024;
|
||||
archive.start=(void *)(0UL-archive.len);
|
||||
|
||||
// FIXME check integrity
|
||||
|
||||
|
||||
// fixme: choose an initram image (normal/fallback)
|
||||
// find first initram
|
||||
ret=find_file(&archive, "normal/initram", &result);
|
||||
if(!ret) {
|
||||
void (*initram)(void);
|
||||
initram=(result.start);
|
||||
printk(BIOS_INFO, "Jumping to RAM init code at 0x%08x\n",
|
||||
result.start);
|
||||
initram();
|
||||
|
||||
}
|
||||
|
||||
die ("FATAL: No initram module found\n");
|
||||
|
||||
}
|
||||
|
||||
|
8
arch/x86/config.h
Normal file
8
arch/x86/config.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* This config file is a place holder and will be created dynamically soon */
|
||||
|
||||
#define LINUXBIOS_VERSION "3.0.0-wth"
|
||||
#define LINUXBIOS_BUILD "Fri Jan 19 15:24:28 CET 2007"
|
||||
|
||||
#define LINUXBIOS_ROMSIZE_KB 512
|
||||
|
||||
#define TTYS0_BASE 0x3f8
|
70
arch/x86/console.c
Normal file
70
arch/x86/console.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <arch/types.h>
|
||||
#include <arch/hlt.h>
|
||||
#include <console/loglevel.h>
|
||||
#include "config.h"
|
||||
|
||||
// FIXME: we need this for varargs
|
||||
#include <stdarg.h>
|
||||
|
||||
#if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_DEBUG
|
||||
#define debug(msg_level, fmt, arg...) printk(msg_level, fmt, ##arg)
|
||||
#endif
|
||||
|
||||
#ifndef LINUXBIOS_EXTRA_VERSION
|
||||
#define LINUXBIOS_EXTRA_VERSION ""
|
||||
#endif
|
||||
|
||||
/* printk's without a loglevel use this.. */
|
||||
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* BIOS_WARNING */
|
||||
|
||||
extern int vtxprintf(void (*)(unsigned char), const char *, va_list);
|
||||
extern void uart8250_tx_byte(unsigned, unsigned char);
|
||||
|
||||
int console_loglevel()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
void console_tx_byte(unsigned char byte)
|
||||
{
|
||||
if (byte == '\n')
|
||||
uart8250_tx_byte(TTYS0_BASE, '\r');
|
||||
uart8250_tx_byte(TTYS0_BASE, byte);
|
||||
}
|
||||
|
||||
int printk(int msg_level, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
if (msg_level >= console_loglevel()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vtxprintf(console_tx_byte, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void console_init(void)
|
||||
{
|
||||
static const char console_test[] =
|
||||
"\n\nLinuxBIOS-"
|
||||
LINUXBIOS_VERSION
|
||||
LINUXBIOS_EXTRA_VERSION
|
||||
" "
|
||||
LINUXBIOS_BUILD
|
||||
" starting...\n";
|
||||
|
||||
printk(BIOS_INFO, console_test);
|
||||
}
|
||||
|
||||
void die(const char *str)
|
||||
{
|
||||
printk(BIOS_EMERG,str);
|
||||
do {
|
||||
hlt();
|
||||
} while(1);
|
||||
}
|
148
arch/x86/init.S
Normal file
148
arch/x86/init.S
Normal file
|
@ -0,0 +1,148 @@
|
|||
# init code - switch cpu to pmode and enable cache as ram.
|
||||
#
|
||||
# Copyright (C) 2000 Ron Minnich, Advanced Computing Lab, LANL
|
||||
# Copyright (C) 2007 Stefan Reinauer, coresystems GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
|
||||
#
|
||||
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
#define ROM_CODE_SEG 0x08
|
||||
#define ROM_DATA_SEG 0x10
|
||||
|
||||
#define CACHE_RAM_CODE_SEG 0x18
|
||||
#define CACHE_RAM_DATA_SEG 0x20
|
||||
|
||||
.code16
|
||||
.globl _start
|
||||
_start:
|
||||
cli
|
||||
|
||||
/* save the BIST result */
|
||||
movl %eax, %ebp;
|
||||
|
||||
/* thanks to kmliu@sis.tw.com for this TBL fix */
|
||||
/* IMMEDIATELY invalidate the translation lookaside buffer before
|
||||
* executing any further code. Even though paging is disabled we
|
||||
* could still get false address translations due to the TLB if we
|
||||
* didn't invalidate it.
|
||||
*/
|
||||
|
||||
xorl %eax, %eax
|
||||
movl %eax, %cr3 /* Invalidate TLB */
|
||||
|
||||
/* switch to protected mode */
|
||||
|
||||
movw %cs, %ax
|
||||
shlw $4, %ax
|
||||
movw $gdt16 + 0xe000, %bx
|
||||
subw %ax, %bx
|
||||
data32 lgdt %cs:(%bx)
|
||||
|
||||
movl %cr0, %eax
|
||||
andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
|
||||
orl $0x60000001, %eax /* CD, NW, PE = 1 */
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Restore BIST result */
|
||||
movl %ebp, %eax
|
||||
|
||||
|
||||
// port80_post (0x23) /* post 0x01 */
|
||||
/* Now we are in protected mode. Jump to a 32 bit code segment. */
|
||||
//data32 ljmp $ROM_CODE_SEG, $__protected_start
|
||||
data32 ljmp $ROM_CODE_SEG, $0xe058
|
||||
|
||||
.align 4
|
||||
.globl gdt16
|
||||
gdt16 = . - _start
|
||||
.word gdt_end - gdt -1 /* compute the table limit */
|
||||
.long gdt /* we know the offset */
|
||||
|
||||
|
||||
/* From now on we are 32bit */
|
||||
|
||||
.code32
|
||||
|
||||
|
||||
/* This is the gdt for ROMCC/ASM part of LinuxBIOS. It
|
||||
* is different from the gdt in GCC part of LinuxBIOS.
|
||||
*
|
||||
* That on was defined in c_start.S in LinuxBIOS v2. TODO
|
||||
*/
|
||||
|
||||
.align 4
|
||||
.globl gdtptr
|
||||
gdt:
|
||||
gdtptr:
|
||||
.word gdt_end - gdt -1 /* compute the table limit */
|
||||
.long gdt /* we know the offset */
|
||||
.word 0
|
||||
|
||||
/* selgdt 0x08, flat code segment */
|
||||
.word 0xffff, 0x0000
|
||||
.byte 0x00, 0x9b, 0xcf, 0x00
|
||||
|
||||
/* selgdt 0x10,flat data segment */
|
||||
.word 0xffff, 0x0000
|
||||
.byte 0x00, 0x93, 0xcf, 0x00
|
||||
gdt_end:
|
||||
|
||||
/*
|
||||
* When we come here we are in protected mode. We expand
|
||||
* the stack and copies the data segment from ROM to the
|
||||
* memory.
|
||||
*
|
||||
* After that, we call the chipset bootstrap routine that
|
||||
* does what is left of the chipset initialization.
|
||||
*
|
||||
* NOTE aligned to 4 so that we are sure that the prefetch
|
||||
* cache will be reloaded.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
#if 0
|
||||
//This code was used by v2. TODO
|
||||
.globl protected_start
|
||||
protected_start:
|
||||
|
||||
lgdt %cs:gdtptr
|
||||
ljmp $ROM_CODE_SEG, $__protected_start
|
||||
#endif
|
||||
|
||||
.globl __protected_start
|
||||
__protected_start:
|
||||
/* Save the BIST value */
|
||||
movl %eax, %ebp
|
||||
|
||||
port80_post (0x01) /* post 0x01 */
|
||||
|
||||
movw $ROM_DATA_SEG, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
/* Restore the BIST value to %eax */
|
||||
movl %ebp, %eax
|
||||
|
||||
#define CONFIG_CPUTYPE_INTEL 1
|
||||
#ifdef CONFIG_CPUTYPE_INTEL
|
||||
#include "cache_as_ram.S"
|
||||
#endif
|
||||
|
||||
.align 4
|
|
@ -1,22 +0,0 @@
|
|||
##
|
||||
## This file is part of the LinuxBIOS project.
|
||||
##
|
||||
## Copyright (C) 2006 coresystems GmbH
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
head-y += init.o
|
||||
|
|
@ -1,436 +0,0 @@
|
|||
// mainboardinit cpu/x86/16bit/entry16.inc
|
||||
|
||||
/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
|
||||
* rminnich@lanl.gov
|
||||
*/
|
||||
|
||||
/* Start code to put an i386 or later processor into 32-bit
|
||||
* protected mode.
|
||||
*/
|
||||
|
||||
/* .section ".rom.text" */
|
||||
#include <arch/rom_segs.h>
|
||||
.code16
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
|
||||
_start:
|
||||
cli
|
||||
/* Save the BIST result */
|
||||
movl %eax, %ebp
|
||||
|
||||
/* thanks to kmliu@sis.tw.com for this TBL fix ... */
|
||||
|
||||
/* IMMEDIATELY invalidate the translation lookaside buffer before executing*/
|
||||
/* any further code. Even though paging is disabled we could still get*/
|
||||
/*false address translations due to the TLB if we didn't invalidate it.*/
|
||||
|
||||
xorl %eax, %eax
|
||||
movl %eax, %cr3 /* Invalidate TLB*/
|
||||
|
||||
/* Invalidating the cache here seems to be a bad idea on
|
||||
* modern processors. Don't.
|
||||
* If we are hyperthreaded or we have multiple cores it is bad,
|
||||
* for SMP startup. On Opterons it causes a 5 second delay.
|
||||
* Invalidating the cache was pure paranoia in any event.
|
||||
* If you cpu needs it you can write a cpu dependent version of
|
||||
* entry16.inc.
|
||||
*/
|
||||
|
||||
/* Note: gas handles memory addresses in 16 bit code very poorly.
|
||||
* In particular it doesn't appear to have a directive allowing you
|
||||
* associate a section or even an absolute offset with a segment register.
|
||||
*
|
||||
* This means that anything except cs:ip relative offsets are
|
||||
* a real pain in 16 bit mode. And explains why it is almost
|
||||
* imposible to get gas to do lgdt correctly.
|
||||
*
|
||||
* One way to work around this is to have the linker do the
|
||||
* math instead of the assembler. This solves the very
|
||||
* pratical problem of being able to write code that can
|
||||
* be relocated.
|
||||
*
|
||||
* An lgdt call before we have memory enabled cannot be
|
||||
* position independent, as we cannot execute a call
|
||||
* instruction to get our current instruction pointer.
|
||||
* So while this code is relocateable it isn't arbitrarily
|
||||
* relocatable.
|
||||
*
|
||||
* The criteria for relocation have been relaxed to their
|
||||
* utmost, so that we can use the same code for both
|
||||
* our initial entry point and startup of the second cpu.
|
||||
* The code assumes when executing at _start that:
|
||||
* (((cs & 0xfff) == 0) and (ip == _start & 0xffff))
|
||||
* or
|
||||
* ((cs == anything) and (ip == 0)).
|
||||
*
|
||||
* The restrictions in reset16.inc mean that _start initially
|
||||
* must be loaded at or above 0xffff0000 or below 0x100000.
|
||||
*
|
||||
* The linker scripts computs gdtptr16_offset by simply returning
|
||||
* the low 16 bits. This means that the intial segment used
|
||||
* when start is called must be 64K aligned. This should not
|
||||
* restrict the address as the ip address can be anything.
|
||||
*/
|
||||
|
||||
movw %cs, %ax
|
||||
shlw $4, %ax
|
||||
movw $gdtptr16_offset, %bx
|
||||
subw %ax, %bx
|
||||
data32 lgdt %cs:(%bx)
|
||||
|
||||
movl %cr0, %eax
|
||||
andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
|
||||
orl $0x60000001, %eax /* CD, NW, PE = 1 */
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Restore BIST to %eax */
|
||||
movl %ebp, %eax
|
||||
|
||||
/* Now that we are in protected mode jump to a 32 bit code segment. */
|
||||
data32 ljmp $ROM_CODE_SEG, $__protected_start
|
||||
|
||||
/**
|
||||
* The gdt is defined in entry32.inc, it has a 4 Gb code segment
|
||||
* at 0x08, and a 4 GB data segment at 0x10;
|
||||
*/
|
||||
.align 4
|
||||
.globl gdtptr16
|
||||
gdtptr16:
|
||||
.word gdt_end - gdt -1 /* compute the table limit */
|
||||
.long gdt /* we know the offset */
|
||||
|
||||
.globl _estart
|
||||
_estart:
|
||||
.code32
|
||||
|
||||
|
||||
/* For starting linuxBIOS in protected mode */
|
||||
|
||||
#include <arch/rom_segs.h>
|
||||
|
||||
/* .section ".rom.text" */
|
||||
.code32
|
||||
|
||||
.align 4
|
||||
.globl gdtptr
|
||||
|
||||
/* This is the gdt for ROMCC/ASM part of LinuxBIOS.
|
||||
* It is different from the gdt in GCC part of LinuxBIOS
|
||||
* which is defined in c_start.S */
|
||||
gdt:
|
||||
gdtptr:
|
||||
.word gdt_end - gdt -1 /* compute the table limit */
|
||||
.long gdt /* we know the offset */
|
||||
.word 0
|
||||
|
||||
/* selgdt 0x08, flat code segment */
|
||||
.word 0xffff, 0x0000
|
||||
.byte 0x00, 0x9b, 0xcf, 0x00
|
||||
|
||||
/* selgdt 0x10,flat data segment */
|
||||
.word 0xffff, 0x0000
|
||||
.byte 0x00, 0x93, 0xcf, 0x00
|
||||
|
||||
gdt_end:
|
||||
|
||||
|
||||
|
||||
// mainboardinit cpu/x86/32bit/entry32.inc
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* When we come here we are in protected mode. We expand
|
||||
* the stack and copies the data segment from ROM to the
|
||||
* memory.
|
||||
*
|
||||
* After that, we call the chipset bootstrap routine that
|
||||
* does what is left of the chipset initialization.
|
||||
*
|
||||
* NOTE aligned to 4 so that we are sure that the prefetch
|
||||
* cache will be reloaded.
|
||||
*/
|
||||
.align 4
|
||||
.globl protected_start
|
||||
protected_start:
|
||||
|
||||
lgdt %cs:gdtptr
|
||||
ljmp $ROM_CODE_SEG, $__protected_start
|
||||
|
||||
__protected_start:
|
||||
/* Save the BIST value */
|
||||
movl %eax, %ebp
|
||||
|
||||
intel_chip_post_macro(0x10) /* post 10 */
|
||||
|
||||
movw $ROM_DATA_SEG, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
/* Restore the BIST value to %eax */
|
||||
movl %ebp, %eax
|
||||
|
||||
|
||||
|
||||
|
||||
// mainboardinit cpu/x86/16bit/reset16.inc
|
||||
|
||||
|
||||
.section ".reset"
|
||||
.code16
|
||||
.globl reset_vector
|
||||
reset_vector:
|
||||
.byte 0xe9
|
||||
.int _start - ( . + 2 )
|
||||
/* Note: The above jump is hand coded to work around bugs in binutils.
|
||||
* 5 byte are used for a 3 byte instruction. This works because x86
|
||||
* is little endian and allows us to use supported 32bit relocations
|
||||
* instead of the weird 16 bit relocations that binutils does not
|
||||
* handle consistenly between versions because they are used so rarely.
|
||||
*/
|
||||
. = 0x8;
|
||||
.code32
|
||||
jmp protected_start
|
||||
.previous
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// mainboardinit arch/i386/lib/cpu_reset.inc
|
||||
|
||||
jmp cpu_reset_out
|
||||
|
||||
__cpu_reset:
|
||||
/* set the boot_complete flag */
|
||||
movl $0xffffffff, %ebp
|
||||
jmp __main
|
||||
|
||||
cpu_reset_out:
|
||||
|
||||
|
||||
// mainboardinit arch/i386/lib/id.inc
|
||||
|
||||
.section ".id", "a", @progbits
|
||||
|
||||
.globl __id_start
|
||||
__id_start:
|
||||
vendor:
|
||||
.asciz MAINBOARD_VENDOR
|
||||
part:
|
||||
.asciz MAINBOARD_PART_NUMBER
|
||||
.long __id_end + 0x10 - vendor /* Reverse offset to the vendor id */
|
||||
.long __id_end + 0x10 - part /* Reverse offset to the part number */
|
||||
.long PAYLOAD_SIZE + ROM_IMAGE_SIZE /* Size of this romimage */
|
||||
.globl __id_end
|
||||
|
||||
__id_end:
|
||||
.previous
|
||||
|
||||
|
||||
// mainboardinit ./failover.inc
|
||||
// mainboardinit ./auto.inc
|
||||
//
|
||||
|
||||
/* by yhlu 6.2005 */
|
||||
/* yhlu 2005.12 make it support HDT Memory Debuggers with Disassmbly, please select the PCI Bus mem for Phys Type*/
|
||||
/* yhlu 2006.3 copy data from cache to ram and reserve 0x1000 for global variables */
|
||||
#define CacheSize DCACHE_RAM_SIZE
|
||||
#define CacheBase (0xd0000 - CacheSize)
|
||||
/* leave some space for global variable to pass to RAM stage */
|
||||
#define GlobalVarSize DCACHE_RAM_GLOBAL_VAR_SIZE
|
||||
|
||||
#include <cpu/x86/mtrr.h>
|
||||
#include <cpu/amd/mtrr.h>
|
||||
|
||||
/* Save the BIST result */
|
||||
movl %eax, %ebp
|
||||
|
||||
/*for normal part %ebx already contain cpu_init_detected from fallback call */
|
||||
|
||||
cache_as_ram_setup:
|
||||
|
||||
/* hope we can skip the double set for normal part */
|
||||
#if ((HAVE_FAILOVER_BOOT==1) && (USE_FAILOVER_IMAGE==1)) || ((HAVE_FAILOVER_BOOT==0) && (USE_FALLBACK_IMAGE==1))
|
||||
/* check if cpu_init_detected */
|
||||
movl $MTRRdefType_MSR, %ecx
|
||||
rdmsr
|
||||
andl $0x00000800, %eax
|
||||
movl %eax, %ebx /* We store the status */
|
||||
|
||||
/* Set MtrrFixDramModEn for clear fixed mtrr */
|
||||
enable_fixed_mtrr_dram_modify:
|
||||
movl $SYSCFG_MSR, %ecx
|
||||
rdmsr
|
||||
andl $(~(SYSCFG_MSR_MtrrFixDramEn|SYSCFG_MSR_MtrrVarDramEn)), %eax
|
||||
orl $SYSCFG_MSR_MtrrFixDramModEn, %eax
|
||||
wrmsr
|
||||
|
||||
/*Clear all MTRRs */
|
||||
|
||||
xorl %edx, %edx
|
||||
movl $fixed_mtrr_msr, %esi
|
||||
clear_fixed_var_mtrr:
|
||||
lodsl (%esi), %eax
|
||||
testl %eax, %eax
|
||||
jz clear_fixed_var_mtrr_out
|
||||
|
||||
movl %eax, %ecx
|
||||
xorl %eax, %eax
|
||||
wrmsr
|
||||
|
||||
jmp clear_fixed_var_mtrr
|
||||
clear_fixed_var_mtrr_out:
|
||||
|
||||
#if CacheSize == 0x10000
|
||||
/* enable caching for 64K using fixed mtrr */
|
||||
movl $0x268, %ecx /* fix4k_c0000*/
|
||||
movl $0x06060606, %eax /* WB IO type */
|
||||
movl %eax, %edx
|
||||
wrmsr
|
||||
movl $0x269, %ecx
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
#if CacheSize == 0xc000
|
||||
/* enable caching for 16K using fixed mtrr */
|
||||
movl $0x268, %ecx /* fix4k_c4000*/
|
||||
movl $0x06060606, %edx /* WB IO type */
|
||||
xorl %eax, %eax
|
||||
wrmsr
|
||||
/* enable caching for 32K using fixed mtrr */
|
||||
movl $0x269, %ecx /* fix4k_c8000*/
|
||||
movl $0x06060606, %eax /* WB IO type */
|
||||
movl %eax, %edx
|
||||
wrmsr
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if CacheSize == 0x8000
|
||||
/* enable caching for 32K using fixed mtrr */
|
||||
movl $0x269, %ecx /* fix4k_c8000*/
|
||||
movl $0x06060606, %eax /* WB IO type */
|
||||
movl %eax, %edx
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
#if CacheSize < 0x8000
|
||||
/* enable caching for 16K/8K/4K using fixed mtrr */
|
||||
movl $0x269, %ecx /* fix4k_cc000*/
|
||||
#if CacheSize == 0x4000
|
||||
movl $0x06060606, %edx /* WB IO type */
|
||||
#endif
|
||||
#if CacheSize == 0x2000
|
||||
movl $0x06060000, %edx /* WB IO type */
|
||||
#endif
|
||||
#if CacheSize == 0x1000
|
||||
movl $0x06000000, %edx /* WB IO type */
|
||||
#endif
|
||||
xorl %eax, %eax
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
/* enable memory access for first MBs using top_mem */
|
||||
movl $TOP_MEM, %ecx
|
||||
xorl %edx, %edx
|
||||
movl $(((CONFIG_LB_MEM_TOPK << 10) + TOP_MEM_MASK) & ~TOP_MEM_MASK) , %eax
|
||||
wrmsr
|
||||
#endif /* USE_FAILOVER_IMAGE == 1*/
|
||||
|
||||
|
||||
#if ((HAVE_FAILOVER_BOOT==1) && (USE_FAILOVER_IMAGE == 0)) || ((HAVE_FAILOVER_BOOT==0) && (USE_FALLBACK_IMAGE==0))
|
||||
/* disable cache */
|
||||
movl %cr0, %eax
|
||||
orl $(0x1<<30),%eax
|
||||
movl %eax, %cr0
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
|
||||
/* enable write base caching so we can do execute in place
|
||||
* on the flash rom.
|
||||
*/
|
||||
movl $0x202, %ecx
|
||||
xorl %edx, %edx
|
||||
movl $(XIP_ROM_BASE | MTRR_TYPE_WRBACK), %eax
|
||||
wrmsr
|
||||
|
||||
movl $0x203, %ecx
|
||||
movl $((1<<(CPU_ADDR_BITS-32))-1), %edx /* AMD 40 bit */
|
||||
movl $(~(XIP_ROM_SIZE - 1) | 0x800), %eax
|
||||
wrmsr
|
||||
#endif /* XIP_ROM_SIZE && XIP_ROM_BASE */
|
||||
|
||||
#if ((HAVE_FAILOVER_BOOT==1) && (USE_FAILOVER_IMAGE==1)) || ((HAVE_FAILOVER_BOOT==0) && (USE_FALLBACK_IMAGE==1))
|
||||
/* Set the default memory type and enable fixed and variable MTRRs */
|
||||
movl $MTRRdefType_MSR, %ecx
|
||||
xorl %edx, %edx
|
||||
/* Enable Variable and Fixed MTRRs */
|
||||
movl $0x00000c00, %eax
|
||||
wrmsr
|
||||
|
||||
/* Enable the MTRRs and IORRs in SYSCFG */
|
||||
movl $SYSCFG_MSR, %ecx
|
||||
rdmsr
|
||||
orl $(SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn), %eax
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
/* enable cache */
|
||||
movl %cr0, %eax
|
||||
andl $0x9fffffff,%eax
|
||||
movl %eax, %cr0
|
||||
|
||||
#if ((HAVE_FAILOVER_BOOT==1) && (USE_FAILOVER_IMAGE==1)) || ((HAVE_FAILOVER_BOOT==0) && (USE_FALLBACK_IMAGE==1))
|
||||
|
||||
/* Read the range with lodsl*/
|
||||
cld
|
||||
movl $CacheBase, %esi
|
||||
movl $(CacheSize>>2), %ecx
|
||||
rep
|
||||
lodsl
|
||||
/* Clear the range */
|
||||
movl $CacheBase, %edi
|
||||
movl $(CacheSize>>2), %ecx
|
||||
xorl %eax, %eax
|
||||
rep
|
||||
stosl
|
||||
|
||||
#endif /*USE_FAILOVER_IMAGE == 1*/
|
||||
|
||||
/* set up the stack pointer */
|
||||
movl $(CacheBase+CacheSize - GlobalVarSize), %eax
|
||||
movl %eax, %esp
|
||||
|
||||
/* Restore the BIST result */
|
||||
movl %ebp, %eax
|
||||
/* We need to set ebp ? No need */
|
||||
movl %esp, %ebp
|
||||
pushl %ebx /* init detected */
|
||||
pushl %eax /* bist */
|
||||
call cache_as_ram_main
|
||||
/* We will not go back */
|
||||
|
||||
fixed_mtrr_msr:
|
||||
.long 0x250, 0x258, 0x259
|
||||
.long 0x268, 0x269, 0x26A
|
||||
.long 0x26B, 0x26C, 0x26D
|
||||
.long 0x26E, 0x26F
|
||||
var_mtrr_msr:
|
||||
.long 0x200, 0x201, 0x202, 0x203
|
||||
.long 0x204, 0x205, 0x206, 0x207
|
||||
.long 0x208, 0x209, 0x20A, 0x20B
|
||||
.long 0x20C, 0x20D, 0x20E, 0x20F
|
||||
var_iorr_msr:
|
||||
.long 0xC0010016, 0xC0010017, 0xC0010018, 0xC0010019
|
||||
mem_top:
|
||||
.long 0xC001001A, 0xC001001D
|
||||
.long 0x000 /* NULL, end of table */
|
||||
cache_as_ram_setup_out:
|
||||
|
14
arch/x86/macros.h
Normal file
14
arch/x86/macros.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Ron Minnich, Advanced Computing Lab, LANL
|
||||
* Copyright (C) 2007 Stefan Reinauer, coresystems GmbH
|
||||
*/
|
||||
|
||||
#ifndef X86_MACROS_H
|
||||
#define X86_MACROS_H 1
|
||||
|
||||
|
||||
#define port80_post(value) \
|
||||
movb $value, %al; \
|
||||
outb %al, $0x80
|
||||
|
||||
#endif
|
45
arch/x86/mtrr.h
Normal file
45
arch/x86/mtrr.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef CPU_X86_MTRR_H
|
||||
#define CPU_X86_MTRR_H
|
||||
|
||||
|
||||
/* These are the region types */
|
||||
#define MTRR_TYPE_UNCACHEABLE 0
|
||||
#define MTRR_TYPE_WRCOMB 1
|
||||
/*#define MTRR_TYPE_ 2*/
|
||||
/*#define MTRR_TYPE_ 3*/
|
||||
#define MTRR_TYPE_WRTHROUGH 4
|
||||
#define MTRR_TYPE_WRPROT 5
|
||||
#define MTRR_TYPE_WRBACK 6
|
||||
#define MTRR_NUM_TYPES 7
|
||||
|
||||
#define MTRRcap_MSR 0x0fe
|
||||
#define MTRRdefType_MSR 0x2ff
|
||||
|
||||
#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
|
||||
#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
|
||||
|
||||
#define NUM_FIXED_RANGES 88
|
||||
#define MTRRfix64K_00000_MSR 0x250
|
||||
#define MTRRfix16K_80000_MSR 0x258
|
||||
#define MTRRfix16K_A0000_MSR 0x259
|
||||
#define MTRRfix4K_C0000_MSR 0x268
|
||||
#define MTRRfix4K_C8000_MSR 0x269
|
||||
#define MTRRfix4K_D0000_MSR 0x26a
|
||||
#define MTRRfix4K_D8000_MSR 0x26b
|
||||
#define MTRRfix4K_E0000_MSR 0x26c
|
||||
#define MTRRfix4K_E8000_MSR 0x26d
|
||||
#define MTRRfix4K_F0000_MSR 0x26e
|
||||
#define MTRRfix4K_F8000_MSR 0x26f
|
||||
|
||||
|
||||
#if !defined(__ROMCC__) && !defined (ASSEMBLY)
|
||||
|
||||
|
||||
void x86_setup_var_mtrrs(unsigned address_bits);
|
||||
void x86_setup_mtrrs(unsigned address_bits);
|
||||
int x86_mtrr_check(void);
|
||||
|
||||
#endif /* __ROMCC__ */
|
||||
|
||||
|
||||
#endif /* CPU_X86_MTRR_H */
|
26
arch/x86/reset.S
Normal file
26
arch/x86/reset.S
Normal file
|
@ -0,0 +1,26 @@
|
|||
# reset vector
|
||||
#
|
||||
# (C) 2007 coresystems GmbH
|
||||
|
||||
# RVECTOR: size of reset vector, default is 0x10
|
||||
# RESRVED: size of vpd code, default is 0xf0
|
||||
#
|
||||
# BOOTBLK: size of bootblock code, default is 0x1f00 (8k-256b)
|
||||
#
|
||||
|
||||
SEGMENT_SIZE = 0x10000
|
||||
RVECTOR = 0x00010
|
||||
|
||||
.code16
|
||||
.globl _start
|
||||
_start:
|
||||
jmp SEGMENT_SIZE-(BOOTBLK+RESRVED+RVECTOR)
|
||||
|
||||
.byte 0
|
||||
|
||||
# date? idstring? we might want to put something else in here.
|
||||
.ascii DATE
|
||||
|
||||
# checksum
|
||||
.word 0
|
||||
|
110
arch/x86/serial.c
Normal file
110
arch/x86/serial.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
#include <arch/io.h>
|
||||
#include <fallback.h>
|
||||
|
||||
/* Base Address */
|
||||
#ifndef TTYS0_BASE
|
||||
#define TTYS0_BASE 0x3f8
|
||||
#endif
|
||||
|
||||
#ifndef TTYS0_BAUD
|
||||
#define TTYS0_BAUD 115200
|
||||
#endif
|
||||
|
||||
#if ((115200%TTYS0_BAUD) != 0)
|
||||
#error Bad ttys0 baud rate
|
||||
#endif
|
||||
|
||||
#define TTYS0_DIV (115200/TTYS0_BAUD)
|
||||
|
||||
/* Line Control Settings */
|
||||
#ifndef TTYS0_LCS
|
||||
/* Set 8bit, 1 stop bit, no parity */
|
||||
#define TTYS0_LCS 0x3
|
||||
#endif
|
||||
|
||||
#define UART_LCS TTYS0_LCS
|
||||
|
||||
|
||||
#if CONFIG_USE_INIT == 0
|
||||
|
||||
/* Data */
|
||||
#define UART_RBR 0x00
|
||||
#define UART_TBR 0x00
|
||||
|
||||
/* Control */
|
||||
#define UART_IER 0x01
|
||||
#define UART_IIR 0x02
|
||||
#define UART_FCR 0x02
|
||||
#define UART_LCR 0x03
|
||||
#define UART_MCR 0x04
|
||||
#define UART_DLL 0x00
|
||||
#define UART_DLM 0x01
|
||||
|
||||
/* Status */
|
||||
#define UART_LSR 0x05
|
||||
#define UART_MSR 0x06
|
||||
#define UART_SCR 0x07
|
||||
|
||||
static int uart_can_tx_byte(void)
|
||||
{
|
||||
return inb(TTYS0_BASE + UART_LSR) & 0x20;
|
||||
}
|
||||
|
||||
static void uart_wait_to_tx_byte(void)
|
||||
{
|
||||
while(!uart_can_tx_byte())
|
||||
;
|
||||
}
|
||||
|
||||
static void uart_wait_until_sent(void)
|
||||
{
|
||||
while(!(inb(TTYS0_BASE + UART_LSR) & 0x40))
|
||||
;
|
||||
}
|
||||
|
||||
static void uart_tx_byte(unsigned char data)
|
||||
{
|
||||
uart_wait_to_tx_byte();
|
||||
outb(data, TTYS0_BASE + UART_TBR);
|
||||
/* Make certain the data clears the fifos */
|
||||
uart_wait_until_sent();
|
||||
}
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
/* disable interrupts */
|
||||
outb(0x0, TTYS0_BASE + UART_IER);
|
||||
/* enable fifo's */
|
||||
outb(0x01, TTYS0_BASE + UART_FCR);
|
||||
/* Set Baud Rate Divisor to 12 ==> 115200 Baud */
|
||||
outb(0x80 | UART_LCS, TTYS0_BASE + UART_LCR);
|
||||
#if USE_OPTION_TABLE == 1
|
||||
static const unsigned char divisor[] = { 1,2,3,6,12,24,48,96 };
|
||||
unsigned ttys0_div, ttys0_index;
|
||||
ttys0_index = read_option(CMOS_VSTART_baud_rate, CMOS_VLEN_baud_rate, 0);
|
||||
ttys0_index &= 7;
|
||||
ttys0_div = divisor[ttys0_index];
|
||||
outb(ttys0_div & 0xff, TTYS0_BASE + UART_DLL);
|
||||
outb(0, TTYS0_BASE + UART_DLM);
|
||||
#else
|
||||
outb(TTYS0_DIV & 0xFF, TTYS0_BASE + UART_DLL);
|
||||
outb((TTYS0_DIV >> 8) & 0xFF, TTYS0_BASE + UART_DLM);
|
||||
#endif
|
||||
outb(UART_LCS, TTYS0_BASE + UART_LCR);
|
||||
}
|
||||
#else
|
||||
extern void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs);
|
||||
void uart_init(void)
|
||||
{
|
||||
#if USE_OPTION_TABLE == 1
|
||||
static const unsigned char divisor[] = { 1,2,3,6,12,24,48,96 };
|
||||
unsigned ttys0_div, ttys0_index;
|
||||
ttys0_index = read_option(CMOS_VSTART_baud_rate, CMOS_VLEN_baud_rate, 0);
|
||||
ttys0_index &= 7;
|
||||
ttys0_div = divisor[ttys0_index];
|
||||
uart8250_init(TTYS0_BASE, ttys0_div, UART_LCS);
|
||||
#else
|
||||
uart8250_init(TTYS0_BASE, TTYS0_DIV, UART_LCS);
|
||||
#endif
|
||||
}
|
||||
#endif
|
309
console/vtxprintf.c
Normal file
309
console/vtxprintf.c
Normal file
|
@ -0,0 +1,309 @@
|
|||
/* vtxprintf.c, from
|
||||
* linux/lib/vsprintf.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <div64.h>
|
||||
|
||||
/* haha, don't need ctype.c */
|
||||
#define isdigit(c) ((c) >= '0' && (c) <= '9')
|
||||
#define is_digit isdigit
|
||||
#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
|
||||
|
||||
static unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
|
||||
{
|
||||
unsigned long result = 0,value;
|
||||
|
||||
if (!base) {
|
||||
base = 10;
|
||||
if (*cp == '0') {
|
||||
base = 8;
|
||||
cp++;
|
||||
if ((*cp == 'x') && isxdigit(cp[1])) {
|
||||
cp++;
|
||||
base = 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
|
||||
? toupper(*cp) : *cp)-'A'+10) < base) {
|
||||
result = result*base + value;
|
||||
cp++;
|
||||
}
|
||||
if (endp)
|
||||
*endp = (char *)cp;
|
||||
return result;
|
||||
}
|
||||
|
||||
static long simple_strtol(const char *cp,char **endp,unsigned int base)
|
||||
{
|
||||
if(*cp=='-')
|
||||
return -simple_strtoul(cp+1,endp,base);
|
||||
return simple_strtoul(cp,endp,base);
|
||||
}
|
||||
|
||||
|
||||
static int skip_atoi(const char **s)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (is_digit(**s))
|
||||
i = i*10 + *((*s)++) - '0';
|
||||
return i;
|
||||
}
|
||||
|
||||
#define ZEROPAD 1 /* pad with zero */
|
||||
#define SIGN 2 /* unsigned/signed long */
|
||||
#define PLUS 4 /* show plus */
|
||||
#define SPACE 8 /* space if plus */
|
||||
#define LEFT 16 /* left justified */
|
||||
#define SPECIAL 32 /* 0x */
|
||||
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
|
||||
|
||||
static int number(void (*tx_byte)(unsigned char byte),
|
||||
unsigned long long num, int base, int size, int precision, int type)
|
||||
{
|
||||
char c,sign,tmp[66];
|
||||
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
int i;
|
||||
int count = 0;
|
||||
|
||||
if (type & LARGE)
|
||||
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
if (type & LEFT)
|
||||
type &= ~ZEROPAD;
|
||||
if (base < 2 || base > 36)
|
||||
return 0;
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (type & SIGN) {
|
||||
if ((signed long long)num < 0) {
|
||||
sign = '-';
|
||||
num = -num;
|
||||
size--;
|
||||
} else if (type & PLUS) {
|
||||
sign = '+';
|
||||
size--;
|
||||
} else if (type & SPACE) {
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
}
|
||||
if (type & SPECIAL) {
|
||||
if (base == 16)
|
||||
size -= 2;
|
||||
else if (base == 8)
|
||||
size--;
|
||||
}
|
||||
i = 0;
|
||||
if (num == 0)
|
||||
tmp[i++]='0';
|
||||
else while (num != 0)
|
||||
tmp[i++] = digits[do_div(num,base)];
|
||||
if (i > precision)
|
||||
precision = i;
|
||||
size -= precision;
|
||||
if (!(type&(ZEROPAD+LEFT)))
|
||||
while(size-->0)
|
||||
tx_byte(' '), count++;
|
||||
if (sign)
|
||||
tx_byte(sign), count++;
|
||||
if (type & SPECIAL) {
|
||||
if (base==8)
|
||||
tx_byte('0'), count++;
|
||||
else if (base==16) {
|
||||
tx_byte('0'), count++;
|
||||
tx_byte(digits[33]), count++;
|
||||
}
|
||||
}
|
||||
if (!(type & LEFT))
|
||||
while (size-- > 0)
|
||||
tx_byte(c), count++;
|
||||
while (i < precision--)
|
||||
tx_byte('0'), count++;
|
||||
while (i-- > 0)
|
||||
tx_byte(tmp[i]), count++;
|
||||
while (size-- > 0)
|
||||
tx_byte(' '), count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
unsigned long long num;
|
||||
int i, base;
|
||||
const char *s;
|
||||
|
||||
int flags; /* flags to number() */
|
||||
|
||||
int field_width; /* width of output field */
|
||||
int precision; /* min. # of digits for integers; max
|
||||
number of chars for from string */
|
||||
int qualifier; /* 'h', 'l', or 'L' for integer fields */
|
||||
|
||||
int count;
|
||||
|
||||
for (count=0; *fmt ; ++fmt) {
|
||||
if (*fmt != '%') {
|
||||
tx_byte(*fmt), count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* process flags */
|
||||
flags = 0;
|
||||
repeat:
|
||||
++fmt; /* this also skips first '%' */
|
||||
switch (*fmt) {
|
||||
case '-': flags |= LEFT; goto repeat;
|
||||
case '+': flags |= PLUS; goto repeat;
|
||||
case ' ': flags |= SPACE; goto repeat;
|
||||
case '#': flags |= SPECIAL; goto repeat;
|
||||
case '0': flags |= ZEROPAD; goto repeat;
|
||||
}
|
||||
|
||||
/* get field width */
|
||||
field_width = -1;
|
||||
if (is_digit(*fmt))
|
||||
field_width = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
field_width = va_arg(args, int);
|
||||
if (field_width < 0) {
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the precision */
|
||||
precision = -1;
|
||||
if (*fmt == '.') {
|
||||
++fmt;
|
||||
if (is_digit(*fmt))
|
||||
precision = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
precision = va_arg(args, int);
|
||||
}
|
||||
if (precision < 0)
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
/* get the conversion qualifier */
|
||||
qualifier = -1;
|
||||
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
|
||||
qualifier = *fmt;
|
||||
++fmt;
|
||||
if (*fmt == 'l') {
|
||||
qualifier = 'L';
|
||||
++fmt;
|
||||
}
|
||||
}
|
||||
|
||||
/* default base */
|
||||
base = 10;
|
||||
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
if (!(flags & LEFT))
|
||||
while (--field_width > 0)
|
||||
tx_byte(' '), count++;
|
||||
tx_byte((unsigned char) va_arg(args, int)), count++;
|
||||
while (--field_width > 0)
|
||||
tx_byte(' '), count++;
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
if (!s)
|
||||
s = "<NULL>";
|
||||
|
||||
len = strnlen(s, precision);
|
||||
|
||||
if (!(flags & LEFT))
|
||||
while (len < field_width--)
|
||||
tx_byte(' '), count++;
|
||||
for (i = 0; i < len; ++i)
|
||||
tx_byte(*s++), count++;
|
||||
while (len < field_width--)
|
||||
tx_byte(' '), count++;
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
if (field_width == -1) {
|
||||
field_width = 2*sizeof(void *);
|
||||
flags |= ZEROPAD;
|
||||
}
|
||||
count += number(tx_byte,
|
||||
(unsigned long) va_arg(args, void *), 16,
|
||||
field_width, precision, flags);
|
||||
continue;
|
||||
|
||||
|
||||
case 'n':
|
||||
if (qualifier == 'L') {
|
||||
long long *ip = va_arg(args, long long *);
|
||||
*ip = count;
|
||||
} else if (qualifier == 'l') {
|
||||
long * ip = va_arg(args, long *);
|
||||
*ip = count;
|
||||
} else {
|
||||
int * ip = va_arg(args, int *);
|
||||
*ip = count;
|
||||
}
|
||||
continue;
|
||||
|
||||
case '%':
|
||||
tx_byte('%'), count++;
|
||||
continue;
|
||||
|
||||
/* integer number formats - set up the flags and "break" */
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
flags |= LARGE;
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
default:
|
||||
tx_byte('%'), count++;
|
||||
if (*fmt)
|
||||
tx_byte(*fmt), count++;
|
||||
else
|
||||
--fmt;
|
||||
continue;
|
||||
}
|
||||
if (qualifier == 'L') {
|
||||
num = va_arg(args, unsigned long long);
|
||||
} else if (qualifier == 'l') {
|
||||
num = va_arg(args, unsigned long);
|
||||
} else if (qualifier == 'h') {
|
||||
num = (unsigned short) va_arg(args, int);
|
||||
if (flags & SIGN)
|
||||
num = (short) num;
|
||||
} else if (flags & SIGN) {
|
||||
num = va_arg(args, int);
|
||||
} else {
|
||||
num = va_arg(args, unsigned int);
|
||||
}
|
||||
count += number(tx_byte, num, base, field_width, precision, flags);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
9
include/cpu/generic/x86/arch/hlt.h
Normal file
9
include/cpu/generic/x86/arch/hlt.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef ARCH_HLT_H
|
||||
#define ARCH_HLT_H
|
||||
|
||||
static inline __attribute__((always_inline)) void hlt(void)
|
||||
{
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
#endif
|
48
include/cpu/generic/x86/div64.h
Normal file
48
include/cpu/generic/x86/div64.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef __I386_DIV64
|
||||
#define __I386_DIV64
|
||||
|
||||
/*
|
||||
* do_div() is NOT a C function. It wants to return
|
||||
* two values (the quotient and the remainder), but
|
||||
* since that doesn't work very well in C, what it
|
||||
* does is:
|
||||
*
|
||||
* - modifies the 64-bit dividend _in_place_
|
||||
* - returns the 32-bit remainder
|
||||
*
|
||||
* This ends up being the most efficient "calling
|
||||
* convention" on x86.
|
||||
*/
|
||||
#define do_div(n,base) ({ \
|
||||
unsigned long __upper, __low, __high, __mod, __base; \
|
||||
__base = (base); \
|
||||
asm("":"=a" (__low), "=d" (__high):"A" (n)); \
|
||||
__upper = __high; \
|
||||
if (__high) { \
|
||||
__upper = __high % (__base); \
|
||||
__high = __high / (__base); \
|
||||
} \
|
||||
asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \
|
||||
asm("":"=A" (n):"a" (__low),"d" (__high)); \
|
||||
__mod; \
|
||||
})
|
||||
|
||||
/*
|
||||
* (long)X = ((long long)divs) / (long)div
|
||||
* (long)rem = ((long long)divs) % (long)div
|
||||
*
|
||||
* Warning, this will do an exception if X overflows.
|
||||
*/
|
||||
#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)
|
||||
|
||||
extern inline long
|
||||
div_ll_X_l_rem(long long divs, long div, long *rem)
|
||||
{
|
||||
long dum2;
|
||||
__asm__("divl %2":"=a"(dum2), "=d"(*rem)
|
||||
: "rm"(div), "A"(divs));
|
||||
|
||||
return dum2;
|
||||
|
||||
}
|
||||
#endif
|
18
include/fallback.h
Normal file
18
include/fallback.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef PART_FALLBACK_BOOT_H
|
||||
#define PART_FALLBACK_BOOT_H
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#if HAVE_FALLBACK_BOOT == 1
|
||||
void set_boot_successful(void);
|
||||
#else
|
||||
#define set_boot_successful()
|
||||
#endif
|
||||
|
||||
void boot_successful(void);
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#define RTC_BOOT_BYTE 48
|
||||
|
||||
#endif /* PART_FALLBACK_BOOT_H */
|
39
include/lar.h
Normal file
39
include/lar.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* lar - LinuxBIOS archiver
|
||||
*
|
||||
* Copright (C) 2006 coresystems GmbH
|
||||
* Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
|
||||
*
|
||||
* This file may be dual licensed with the new BSD license.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAGIC "LARCHIVE"
|
||||
#define MAX_PATHLEN 1024
|
||||
|
||||
struct lar_header {
|
||||
char magic[8];
|
||||
u32 len;
|
||||
u32 checksum;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
struct mem_file {
|
||||
void *start;
|
||||
int len;
|
||||
};
|
||||
|
130
include/string.h
Normal file
130
include/string.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern void *memcpy(void *dest, const void *src, size_t n);
|
||||
extern void *memmove(void *dest, const void *src, size_t n);
|
||||
extern void *memset(void *s, int c, size_t n);
|
||||
extern int memcmp(const void *s1, const void *s2, size_t n);
|
||||
|
||||
extern int sprintf(char * buf, const char *fmt, ...);
|
||||
|
||||
// yes, linux has fancy ones. We don't care. This stuff gets used
|
||||
// hardly at all. And the pain of including those files is just too high.
|
||||
|
||||
//extern inline void strcpy(char *dst, char *src) {while (*src) *dst++ = *src++;}
|
||||
|
||||
//extern inline int strlen(char *src) { int i = 0; while (*src++) i++; return i;}
|
||||
|
||||
static inline size_t strnlen(const char *src, size_t max)
|
||||
{
|
||||
size_t i = 0;
|
||||
while((*src++) && (i < max)) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline size_t strlen(const char *src)
|
||||
{
|
||||
size_t i = 0;
|
||||
while(*src++) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline char *strchr(const char *s, int c)
|
||||
{
|
||||
for (; *s; s++) {
|
||||
if (*s == c)
|
||||
return (char *) s;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char *strdup(const char *s)
|
||||
{
|
||||
size_t sz = strlen(s) + 1;
|
||||
char *d = malloc(sz);
|
||||
memcpy(d, s, sz);
|
||||
return d;
|
||||
}
|
||||
|
||||
static inline char *strncpy(char *to, const char *from, int count)
|
||||
{
|
||||
register char *ret = to;
|
||||
|
||||
while (count > 0) {
|
||||
count--;
|
||||
if ((*to++ = *from++) == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
count--;
|
||||
*to++ = '\0';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
int r;
|
||||
|
||||
while ((r = (*s1 - *s2)) == 0 && *s1) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int isspace(int c)
|
||||
{
|
||||
switch (c) {
|
||||
case ' ': case '\f': case '\n':
|
||||
case '\r': case '\t': case '\v':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int isdigit(int c)
|
||||
{
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
static inline int isxdigit(int c)
|
||||
{
|
||||
return ((c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'f') ||
|
||||
(c >= 'A' && c <= 'F'));
|
||||
}
|
||||
|
||||
static inline int isupper(int c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
static inline int islower(int c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
static inline int toupper(int c)
|
||||
{
|
||||
if (islower(c))
|
||||
c -= 'a'-'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline int tolower(int c)
|
||||
{
|
||||
if (isupper(c))
|
||||
c -= 'A'-'a';
|
||||
return c;
|
||||
}
|
||||
#endif /* STRING_H */
|
15
include/uart8250.h
Normal file
15
include/uart8250.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef UART8250_H
|
||||
#define UART8250_H
|
||||
|
||||
struct uart8250 {
|
||||
unsigned int baud;
|
||||
/* Do I need an lcs parameter here? */
|
||||
};
|
||||
|
||||
unsigned char uart8250_rx_byte(unsigned base_port);
|
||||
int uart8250_can_rx_byte(unsigned base_port);
|
||||
void uart8250_tx_byte(unsigned base_port, unsigned char data);
|
||||
void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs);
|
||||
void init_uart8250(unsigned base_port, struct uart8250 *uart);
|
||||
|
||||
#endif /* UART8250_H */
|
63
lib/lar.c
Normal file
63
lib/lar.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* lar - LinuxBIOS archiver
|
||||
*
|
||||
* Copright (C) 2006-2007 coresystems GmbH
|
||||
* Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <arch/types.h>
|
||||
#include <string.h>
|
||||
#include <lar.h>
|
||||
|
||||
#ifndef CONFIG_BIG_ENDIAN
|
||||
#define ntohl(x) ( ((x&0xff)<<24) | ((x&0xff00)<<8) | \
|
||||
((x&0xff0000) >> 8) | ((x&0xff000000) >> 24) )
|
||||
#else
|
||||
#define ntohl(x) (x)
|
||||
#endif
|
||||
|
||||
int find_file(struct mem_file *archive, char *filename, struct mem_file *result)
|
||||
{
|
||||
char * walk, *fullname;
|
||||
struct lar_header * header;
|
||||
|
||||
for (walk = archive->start; walk < (char *)archive->start +
|
||||
archive->len; walk+=16) {
|
||||
|
||||
if(strcmp(walk, MAGIC)!=0)
|
||||
continue;
|
||||
|
||||
header=(struct lar_header *)walk;
|
||||
fullname=walk+sizeof(struct lar_header);
|
||||
|
||||
// FIXME: check checksum
|
||||
|
||||
if(strcmp(fullname, filename)!=0) {
|
||||
result->start=walk + ntohl(header->offset);
|
||||
result->len=ntohl(header->len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip file
|
||||
walk += ( ntohl(header->offset) + ntohl(header->len)
|
||||
+ 15 ) & 0xfffffff0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
91
lib/uart8250.c
Normal file
91
lib/uart8250.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* Should support 8250, 16450, 16550, 16550A type uarts */
|
||||
#include <arch/io.h>
|
||||
#include <uart8250.h>
|
||||
#include "../arch/x86/config.h" // for ttyS0 base FIXME!
|
||||
|
||||
/* Data */
|
||||
#define UART_RBR 0x00
|
||||
#define UART_TBR 0x00
|
||||
|
||||
/* Control */
|
||||
#define UART_IER 0x01
|
||||
#define UART_IIR 0x02
|
||||
#define UART_FCR 0x02
|
||||
#define UART_LCR 0x03
|
||||
#define UART_MCR 0x04
|
||||
#define UART_DLL 0x00
|
||||
#define UART_DLM 0x01
|
||||
|
||||
/* Status */
|
||||
#define UART_LSR 0x05
|
||||
#define UART_MSR 0x06
|
||||
#define UART_SCR 0x07
|
||||
|
||||
static inline int uart8250_can_tx_byte(unsigned base_port)
|
||||
{
|
||||
return inb(base_port + UART_LSR) & 0x20;
|
||||
}
|
||||
|
||||
static inline void uart8250_wait_to_tx_byte(unsigned base_port)
|
||||
{
|
||||
while(!uart8250_can_tx_byte(base_port))
|
||||
;
|
||||
}
|
||||
|
||||
static inline void uart8250_wait_until_sent(unsigned base_port)
|
||||
{
|
||||
while(!(inb(base_port + UART_LSR) & 0x40))
|
||||
;
|
||||
}
|
||||
|
||||
void uart8250_tx_byte(unsigned base_port, unsigned char data)
|
||||
{
|
||||
uart8250_wait_to_tx_byte(base_port);
|
||||
outb(data, base_port + UART_TBR);
|
||||
/* Make certain the data clears the fifos */
|
||||
uart8250_wait_until_sent(base_port);
|
||||
}
|
||||
|
||||
int uart8250_can_rx_byte(unsigned base_port)
|
||||
{
|
||||
return inb(base_port + UART_LSR) & 0x01;
|
||||
}
|
||||
|
||||
unsigned char uart8250_rx_byte(unsigned base_port)
|
||||
{
|
||||
while(!uart8250_can_rx_byte(base_port))
|
||||
;
|
||||
return inb(base_port + UART_RBR);
|
||||
}
|
||||
|
||||
void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs)
|
||||
{
|
||||
lcs &= 0x7f;
|
||||
/* disable interrupts */
|
||||
outb(0x0, base_port + UART_IER);
|
||||
/* enable fifo's */
|
||||
outb(0x01, base_port + UART_FCR);
|
||||
/* assert DTR and RTS so the other end is happy */
|
||||
outb(0x03, base_port + UART_MCR);
|
||||
/* Set Baud Rate Divisor to 12 ==> 115200 Baud */
|
||||
outb(0x80 | lcs, base_port + UART_LCR);
|
||||
outb(divisor & 0xFF, base_port + UART_DLL);
|
||||
outb((divisor >> 8) & 0xFF, base_port + UART_DLM);
|
||||
outb(lcs, base_port + UART_LCR);
|
||||
}
|
||||
|
||||
/* Initialize a generic uart */
|
||||
void init_uart8250(unsigned base_port, struct uart8250 *uart)
|
||||
{
|
||||
int divisor;
|
||||
int lcs;
|
||||
divisor = 115200/(uart->baud ? uart->baud: 1);
|
||||
lcs = 3;
|
||||
if (base_port == TTYS0_BASE) {
|
||||
/* Don't reinitialize the console serial port,
|
||||
* This is espeically nasty in SMP.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
uart8250_init(base_port, divisor, lcs);
|
||||
}
|
|
@ -1,7 +1,28 @@
|
|||
##
|
||||
## This file is part of the LinuxBIOS project.
|
||||
##
|
||||
## Copyright (C) 2006 coresystems GmbH
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
|
||||
#
|
||||
# This is duplicate in arch/x86/ where it does not belong.
|
||||
# How can we cross reference?
|
||||
# VPD or SIP ROM or ... how does nvidia call it?
|
||||
# Some space to cope with dirty southbridge tricks.
|
||||
# Do we want to put our own stuff there, too?
|
||||
#
|
||||
|
||||
linuxbios.vpd:
|
||||
|
@ -10,3 +31,40 @@ linuxbios.vpd:
|
|||
$(Q)printf "ok.\n"
|
||||
|
||||
|
||||
#
|
||||
# this is going to be the enable car code, lar parser and such:
|
||||
#
|
||||
|
||||
INITCFLAGS=-I$(srctree)/include/cpu/generic/x86 -I$(srctree)/include -fno-builtin -Os -fPIC
|
||||
|
||||
linuxbios.initram:
|
||||
$(Q)echo Building linuxbios.initram
|
||||
#
|
||||
# main
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/mainboard/$(MAINBOARDDIR)/initram.c -o initram.o
|
||||
#
|
||||
# console lib
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/arch/x86/console.c -o console.o
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/arch/x86/serial.c -o serial.o
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/console/vtxprintf.c -o vtxprintf.o
|
||||
$(Q)$(CC) $(INITCFLAGS) -c $(srctree)/lib/uart8250.c -o uart8250.o
|
||||
|
||||
$(Q)$(LD) -Ttext 0x00000000 -s --oformat binary initram.o console.o uart8250.o \
|
||||
serial.o vtxprintf.o -o $(objtree)/linuxbios.initram
|
||||
|
||||
$(Q)chmod 644 $(objtree)/linuxbios.initram
|
||||
|
||||
|
||||
# miscellaneous important targets.
|
||||
$(objtree)/mainboard.o: $(objtree)/statictree.o
|
||||
|
||||
$(objtree)/statictree.o: $(objtree)/statictree.c
|
||||
$(CC) $(CFLAGS) $(LINUXBIOSINCLUDE) -c -o $(objtree)/statictree.o $(objtree)/statictree.c
|
||||
|
||||
$(objtree)/statictree.c: mainboard/$(MAINBOARDDIR)/dts $(objtree)/dtc
|
||||
$(objtree)/dtc -O lb mainboard/$(MAINBOARDDIR)/dts >$(objtree)/statictree.c
|
||||
|
||||
$(objtree)/dtc:
|
||||
$(MAKE) -C $(srctree)/util/dtc/
|
||||
cp $(srctree)/util/dtc/dtc $(objtree)
|
||||
|
||||
|
|
24
mainboard/emulation/qemu-i386/initram.c
Normal file
24
mainboard/emulation/qemu-i386/initram.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* GPLv2.
|
||||
*
|
||||
* Copyright (C) 2007 Stefan Reinauer <stepan@coresystems.de>, coresystems GmbH
|
||||
*/
|
||||
|
||||
#include <arch/types.h>
|
||||
#include <arch/io.h>
|
||||
#include <console/loglevel.h>
|
||||
|
||||
static void post_code(u8 value)
|
||||
{
|
||||
outb(value, 0x80);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printk(BIOS_INFO, "RAM init code started\n");
|
||||
|
||||
die ("Nothing to do.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ int list_lar(int argc, char *argv[])
|
|||
|
||||
printf(" %s ", walk+sizeof(struct lar_header));
|
||||
|
||||
printf("(%d bytes @0x%lx)\n", ntohl(header->len),
|
||||
printf("(%d bytes @0x%x)\n", ntohl(header->len),
|
||||
(walk-inmap)+ntohl(header->offset));
|
||||
}
|
||||
munmap(inmap, statbuf.st_size);
|
||||
|
|
Loading…
Add table
Reference in a new issue