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:
Stefan Reinauer 2007-01-29 22:09:50 +00:00
parent e388149797
commit c275218a89
25 changed files with 1627 additions and 496 deletions

View file

@ -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

View file

@ -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
View 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
View 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
View 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
View 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
View 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

View file

@ -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

View file

@ -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
View 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
View 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
View 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
View 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
View 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;
}

View file

@ -0,0 +1,9 @@
#ifndef ARCH_HLT_H
#define ARCH_HLT_H
static inline __attribute__((always_inline)) void hlt(void)
{
asm("hlt");
}
#endif

View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

View file

@ -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)

View 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;
}

View file

@ -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);