Next in my series of cleanups form the alpha port nothing should break yet...

This commit is contained in:
Eric W. Biederman 2001-03-23 21:03:13 +00:00
commit 24fe8d03aa
28 changed files with 1672 additions and 143 deletions

View file

@ -0,0 +1,109 @@
/*
* $ $
*
*/
#include <asm.h>
#include <intel.h>
#include <pciconf.h>
/*
* This is the entry code (the mkrom(8) utility makes a jumpvector
* to this adddess.
*
* When we get here we are in x86 real mode.
*
* %cs = 0xf000 %ip = 0x0000
* %ds = 0x0000 %es = 0x0000
* %dx = 0x0yxx (y = 3 for i386, 5 for pentium, 6 for P6,
* where x is undefined)
* %fl = 0x0002
*/
.text
.code16
#include <cpu/p5/start32.inc>
#include <pc80/i8259.inc>
CRT0_PARAMETERS
/* Turn on mtrr for faster boot */
#include <cpu/p6/earlymtrr.inc>
/*
* Copy data into RAM and clear the BSS. Since these segments
* isn\'t really that big we just copy/clear using bytes, not
* double words.
*/
intel_chip_post_macro(0x11) /* post 11 */
#ifdef SERIAL_CONSOLE
TTYS0_TX_STRING($str_after_ram)
#endif /* SERIAL_CONSOLE */
cld /* clear direction flag */
/* copy data segment from FLASH ROM to RAM */
leal EXT(_ldata), %esi
leal EXT(_data), %edi
movl $EXT(_eldata), %ecx
subl %esi, %ecx
jz .Lnodata /* should not happen */
rep
movsb
.Lnodata:
intel_chip_post_macro(0x12) /* post 12 */
#ifdef SERIAL_CONSOLE
TTYS0_TX_STRING($str_after_ram)
#endif /* SERIAL_CONSOLE */
/** clear stack */
leal EXT(_stack), %edi
movl $EXT(_estack), %ecx
subl %edi, %ecx
xorl %eax, %eax
rep
stosb
/** clear bss */
leal EXT(_bss), %edi
movl $EXT(_ebss), %ecx
subl %edi, %ecx
jz .Lnobss
xorl %eax, %eax
rep
stosb
.Lnobss:
/*
* Now we are finished. Memory is up, data is copied and
* bss is cleared. Now we call the main routine and
* let it do the rest.
*/
intel_chip_post_macro(0xfe) /* post fe */
#ifdef SERIAL_CONSOLE
TTYS0_TX_STRING($str_pre_main)
#endif /* SERIAL_CONSOLE */
/* memory is up. Let\'s do the rest in C -- much easier. */
/* set new stack */
movl $_estack, %esp
intel_chip_post_macro(0xfd) /* post fe */
call EXT(intel_main)
/*NOTREACHED*/
.Lhlt:
intel_chip_post_macro(0xee) /* post fe */
hlt
jmp .Lhlt
ttyS0_test: .string "\r\n\r\nHello world!!\r\n"
str_after_ram: .string "Ram Initialize?\r\n"
str_after_copy: .string "after copy?\r\n"
str_pre_main: .string "before main\r\n"
newline: .string "\r\n"

View file

@ -0,0 +1,116 @@
/*
* Memory map:
*
* _RAMBASE
* : data segment
* : bss segment
* : heap
* : stack
* _ROMBASE
* : linuxbios text
* : readonly text
*/
/*
* Bootstrap code for the STPC Consumer
* Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
*
* $Id$
*
*/
/*
* Written by Johan Rydberg, based on work by Daniel Kahlin.
* Rewritten by Eric Biederman
*/
/*
* We use ELF as output format. So that we can
* debug the code in some form.
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
/* oh, barf. This wont work if all you use is .o's. -- RGM */
/* These are now set by the config tool
_RAMBASE = 0x04000;
_ROMBASE = 0x80000;
*/
/*
* Entry point is not really nececary, since the mkrom(8)
* tool creates a entry point that jumps to $0xc000:0x0000.
*/
/* baloney, but ... RGM*/
ENTRY(_start)
SECTIONS
{
/*
* First we place the code and read only data (typically const declared).
* This get placed in rom.
*/
.text _ROMBASE : {
_text = .;
*(.text);
_etext = .;
}
.rodata (.) : {
_rodata = .;
*(.rodata);
_erodata = .;
}
. = _RAMBASE;
/*
* After the code we place initialized data (typically initialized
* global variables). This gets copied into ram by startup code.
* __data_start and __data_end shows where in ram this should be placed,
* whereas __data_loadstart and __data_loadend shows where in rom to
* copy from.
*/
.data (.): AT (_erodata) {
_data = .;
*(.data)
*(.sdata)
*(.sdata2)
*(.got)
_edata = .;
}
_ldata = LOADADDR(.data);
_eldata = LOADADDR(.data) + SIZEOF(.data);
/*
* bss does not contain data, it is just a space that should be zero
* initialized on startup. (typically uninitialized global variables)
* crt0.S fills between _bss and _ebss with zeroes.
*/
.bss (.): {
_bss = .;
*(.bss)
*(.sbss)
*(COMMON)
_ebss = .;
}
_end = .;
.heap (.): {
_heap = .;
/* Reserve 64K for the heap */
. = . + 0x10000;
_eheap = .;
}
.stack (.) : {
_stack = .;
/* Resever 64k for the stack */
. = . + 0x10000;
_estack = .;
}
}
/*
* This provides the start and end address for the whole image
*/
_image = LOADADDR(.text);
_eimage = LOADADDR(.data) + SIZEOF(.data);
/* EOF */

View file

@ -0,0 +1,41 @@
biosbase 0xf0000
rambase 0x4000
makedefine LINK = ld -T ldscript.ld -o $@ crt0.o linuxbios.a
makedefine CPPFLAGS= -I$(TOP)/src/include -I$(TOP)/src/arch/$(ARCH)/include $(CPUFLAGS)
makedefine CFLAGS= $(CPU_OPT) $(CPPFLAGS) -O2 -nostdinc -nostdlib -fno-builtin -Wall
makedefine CC=cc
makerule all : romimage ;
makerule floppy : all ; mcopy -o romimage a:
makerule romimage : linuxbios.rom vmlinux.bin.gz.block ; cat vmlinux.bin.gz.block linuxbios.rom > romimage
makerule linuxbios.rom: linuxbios.strip mkrom ; ./mkrom -s 64 -f -o linuxbios.rom linuxbios.strip
makerule linuxbios.strip: linuxbios ; objcopy -O binary -R .note -R .comment -S linuxbios linuxbios.strip
makerule linuxbios: linuxbios.a vmlinux.bin.gz ; @rm -f biosobject
addaction linuxbios $(LINK)
addaction linuxbios nm -n linuxbios > linuxbios.map
makerule linuxbios.a : $(OBJECTS) ; rm -f linuxbios.a
addaction linuxbios.a ar cr linuxbios.a $(OBJECTS)
makerule crt0.s: crt0.S ; $(CC) $(CPPFLAGS) -I$(TOP)/src -E $< > crt0.s
makerule crt0.o : crt0.s; $(CC) $(CPU_OPT) -c crt0.s
makerule mkrom: $(TOP)/mkrom/mkrom.c ; $(CC) -o mkrom $<
makerule clean : ; rm -f linuxbios.* vmlinux.* *.o mkrom xa? *~
addaction clean rm -f linuxbios romimage crt0.s
addaction clean rm -f a.out *.s *.l
addaction clean rm -f TAGS tags
addaction clean rm -f docipl
makerule vmlinux.bin.gz.block : vmlinux.bin.gz ; dd conv=sync bs=448k if=vmlinux.bin.gz of=vmlinux.bin.gz.block
makerule vmlinux.bin.gz: vmlinux.bin ;gzip -f -3 vmlinux.bin
makerule vmlinux.bin: $(LINUX)/vmlinux ; objcopy -O binary -R .note -R .comment -S $< vmlinux.bin
# do standard config files that the user need not specify
# for now, this is just 'lib', but it may be more later.
dir /src/arch/i386
dir /src/lib
dir /src/boot
dir /src/rom

View file

@ -0,0 +1 @@
#include <cpu/p5/io.h>

3
src/arch/i386/lib/Config Normal file
View file

@ -0,0 +1,3 @@
object i386_subr.o
object params.o
object hardwaremain.o

View file

@ -0,0 +1,197 @@
/*
This software and ancillary information (herein called SOFTWARE )
called LinuxBIOS is made available under the terms described
here. The SOFTWARE has been approved for release with associated
LA-CC Number 00-34 . Unless otherwise indicated, this SOFTWARE has
been authored by an employee or employees of the University of
California, operator of the Los Alamos National Laboratory under
Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
U.S. Government has rights to use, reproduce, and distribute this
SOFTWARE. The public may copy, distribute, prepare derivative works
and publicly display this SOFTWARE without charge, provided that this
Notice and any statement of authorship are reproduced on all copies.
Neither the Government nor the University makes any warranty, express
or implied, or assumes any liability or responsibility for the use of
this SOFTWARE. If SOFTWARE is modified to produce derivative works,
such modified SOFTWARE should be clearly marked, so as not to confuse
it with the version available from LANL.
*/
/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
* rminnich@lanl.gov
*/
/*
* C Bootstrap code for the INTEL
* $Id$
*
*/
#define LINUXBIOS
#ifndef lint
static char rcsid[] = "$Id$";
#endif
#include <cpu/p5/io.h>
#include <intel.h>
#include <pciconf.h>
#include <cpu/p5/cpuid.h>
#include <cpu/p6/ioapic.h>
#include <subr.h>
#include <printk.h>
void intel_main()
{
// These are only used here, so don't bother putting them in a .h
void mainboard_fixup(void);
void nvram_on(void);
void keyboard_on(void);
void framebuffer_on(void);
void intel_copy_irq_routing_table(void);
#ifdef FINAL_MAINBOARD_FIXUP
void final_mainboard_fixup(void);
#endif /* FINAL_MAINBOARD_FIXUP */
#ifdef CONFIGURE_L2_CACHE
int intel_l2_configure();
#endif /* CONFIGURE_L2_CACHE */
#ifdef UPDATE_MICROCODE
void intel_display_cpuid_microcode(void);
#endif /* UPDATE_MICROCODE */
/* the order here is a bit tricky. We don't want to do much of
* anything that uses config registers until after PciAllocateResources
* since that function also figures out what kind of config strategy
* to use (type 1 or type 2).
* so we turn on cache, then worry about PCI setup, then do other
* things, so that the other work can use the PciRead* and PciWrite*
* functions.
*/
unsigned long totalram = 0;
extern void linuxbiosmain(unsigned long membase, unsigned long totalram);
/* displayinit MUST PRECEDE ALL PRINTK! */
displayinit();
post_code(0x39);
printk(KERN_INFO "Reached intel_main().\n");
post_code(0x40);
#ifdef UPDATE_MICROCODE
post_code(0x41);
printk(KERN_INFO "Updating microcode\n");
intel_display_cpuid_microcode();
#endif /* UPDATE_MICROCODE */
post_code(0x42);
// pick how to scan the bus. This is first so we can get at memory size.
printk(KERN_INFO "Finding PCI confiuration type...\n");
pci_set_method();
post_code(0x5f);
printk(KERN_INFO "Scanning PCI bus...");
pci_enumerate();
post_code(0x66);
printk(KERN_INFO "done\n");
// The framebuffer can change how much memory you have.
// So you really need to run this before you size ram.
#ifdef HAVE_FRAMEBUFFER
framebuffer_on();
#endif /* HAVE_FRAMEBUFFER */
totalram = sizeram();
post_code(0x70);
printk(KERN_INFO "totalram: %ldM\n", totalram/1024);
// can't size just yet ...
// mainboard totalram sizing may not be up yet. If it is not ready,
// take a default of 64M
if (!totalram)
totalram = 64 * 1024;
// Turn on cache before configuring the bus.
printk(KERN_INFO "Enabling cache...");
intel_cache_on(0, totalram);
post_code(0x80);
printk(KERN_INFO "done.\n");
printk(KERN_INFO "Allocating PCI resources...");
// Now do the real bus
// we round the total ram up a lot for thing like the SISFB, which
// shares high memory with the CPU.
pci_configure();
post_code(0x88);
pci_enable();
post_code(0x90);
printk(KERN_INFO "done.\n");
/* set up the IO-APIC for the clock interrupt. */
post_code(0x92);
setup_ioapic();
// generic mainboard fixup
mainboard_fixup();
#ifndef MAINBOARD_FIXUP_IN_CHARGE
nvram_on();
intel_display_cpuid();
intel_mtrr_check();
#ifndef NO_KEYBOARD
keyboard_on();
#endif /* NO_KEYBOARD */
#ifdef MUST_ENABLE_FLOPPY
enable_floppy();
post_code(0x95);
#endif /* MUST_ENABLE_FLOPPY */
#ifdef SMP
/* copy the smp block to address 0 */
intel_smpblock((void *)16);
post_code(0x96);
#endif /* SMP */
intel_zero_irq_settings();
intel_check_irq_routing_table();
intel_copy_irq_routing_table();
post_code(0x9a);
/* to do: intel_serial_on(); */
intel_interrupts_on();
#ifdef FINAL_MAINBOARD_FIXUP
printk(KERN_INFO "Final mainboard fixup for ");
post_code(0xec);
final_mainboard_fixup();
printk(KERN_INFO "done.\n");
#endif /* FINAL_MAINBOARD_FIXUP */
#ifdef CONFIGURE_L2_CACHE
/* now that everything is really up, enable the l2 cache if desired.
* The enable can wait until this point, because linuxbios and it's
* data areas are tiny, easily fitting into the L1 cache.
*/
printk(KERN_INFO "Configuring L2 cache...");
intel_l2_configure();
printk(KERN_INFO "done.\n");
#endif /* CONFIGURE_L2_CACHE */
#endif /* MAINBOARD_FIXUP_IN_CHARGE */
#ifdef LINUXBIOS
printk(KERN_INFO "Jumping to linuxbiosmain()...\n");
// we could go to argc, argv, for main but it seems like overkill.
post_code(0xed);
linuxbiosmain(0, totalram);
#endif /* LINUXBIOS */
}

View file

@ -0,0 +1,163 @@
#include <cpu/p5/io.h>
#include <cpu/p5/macros.h>
#include <cpu/p6/msr.h>
#include <printk.h>
#include <pci.h>
#include <subr.h>
#include <string.h>
void intel_cache_on(unsigned long base, unsigned long totalram)
{
post_code(0x60);
/* we need an #ifdef i586 here at some point ... */
__asm__ __volatile__("mov %cr0, %eax\n\t"
"and $0x9fffffff,%eax\n\t"
"mov %eax, %cr0\n\t");
/* turns out cache isn't really on until you set MTRR registers on
* 686 and later.
* NOTHING FANCY. Linux does a much better job anyway.
* so absolute minimum needed to get it going.
*/
/* OK, linux it turns out does nothing. We have to do it ... */
#ifdef i686
// totalram here is in linux sizing, i.e. units of KB.
// set_mtrr is responsible for getting it into the right units!
intel_set_mtrr(base, totalram);
#endif
post_code(0x6A);
}
void intel_interrupts_on()
{
/* this is so interrupts work. This is very limited scope --
* linux will do better later, we hope ...
*/
/* this is the first way we learned to do it. It fails on real SMP
* stuff. So we have to do things differently ...
* see the Intel mp1.4 spec, page A-3
*/
#ifdef SMP
unsigned long reg, *regp;
#define SVR 0xfee000f0
#define LVT1 0xfee00350
#define LVT2 0xfee00360
#define APIC_ENABLED 0x100
printk(KERN_INFO "Enabling interrupts...");
regp = (unsigned long *) SVR;
reg = *regp;
reg &= (~0xf0);
reg |= APIC_ENABLED;
*regp = reg;
regp = (unsigned long *) LVT1;
reg = *regp;
reg &= 0xfffe00ff;
reg |= 0x5700;
*regp = reg;
regp = (unsigned long *) LVT2;
reg = *regp;
reg &= 0xfffe00ff;
reg |= 0x5400;
*regp = reg;
#else
unsigned long low, high;
printk(KERN_INFO "Enabling interrupts...");
rdmsr(0x1b, low, high);
low &= ~0x800;
wrmsr(0x1b, low, high);
#endif
printk(KERN_INFO "done.\n");
post_code(0x9b);
}
/* These functions should be chip-set independent -tds */
void intel_zero_irq_settings(void)
{
struct pci_dev *pcidev;
unsigned char line;
printk(KERN_INFO "Zeroing IRQ settings...");
pcidev = pci_devices;
while (pcidev) {
pci_read_config_byte(pcidev, 0x3d, &line);
if (line) {
pci_write_config_byte(pcidev, 0x3c, 0);
}
pcidev = pcidev->next;
}
printk(KERN_INFO "done.\n");
}
void intel_check_irq_routing_table(void)
{
#ifdef HAVE_PIRQ_TABLE
const u8 *addr;
const struct irq_routing_table *rt;
int i;
u8 sum;
printk(KERN_INFO "Checking IRQ routing tables...");
rt = &intel_irq_routing_table;
addr = (u8 *)rt;
sum = 0;
for (i = 0; i < rt->size; i++)
sum += addr[i];
DBG("%s:%6d:%s() - irq_routing_table located at: 0x%p\n",
__FILE__, __LINE__, __FUNCTION__, addr);
sum = (unsigned char)(rt->checksum-sum);
if (sum != rt->checksum) {
printk(KERN_WARNING "%s:%6d:%s() - "
"checksum is: 0x%02x but should be: 0x%02x\n",
__FILE__, __LINE__, __FUNCTION__, rt->checksum, sum);
}
if (rt->signature != PIRQ_SIGNATURE || rt->version != PIRQ_VERSION ||
rt->size % 16 || rt->size < sizeof(struct irq_routing_table)) {
printk(KERN_WARNING "%s:%6d:%s() - "
"Interrupt Routing Table not valid\n",
__FILE__, __LINE__, __FUNCTION__);
return;
}
sum = 0;
for (i=0; i<rt->size; i++)
sum += addr[i];
if (sum) {
printk(KERN_WARNING "%s:%6d:%s() - "
"checksum error in irq routing table\n",
__FILE__, __LINE__, __FUNCTION__);
}
printk(KERN_INFO "done.\n");
#endif /* #ifdef HAVE_PIRQ_TABLE */
}
#define RTABLE_DEST 0xf0000
void intel_copy_irq_routing_table(void)
{
#ifdef HAVE_PIRQ_TABLE
printk(KERN_INFO "Copying IRQ routing tables...");
memcpy((char *) RTABLE_DEST, &intel_irq_routing_table, intel_irq_routing_table.size);
printk(KERN_INFO "done.\n");
#endif
}

166
src/arch/i386/lib/params.c Normal file
View file

@ -0,0 +1,166 @@
#include <string.h>
/*
This software and ancillary information (herein called SOFTWARE )
called LinuxBIOS is made available under the terms described
here. The SOFTWARE has been approved for release with associated
LA-CC Number 00-34 . Unless otherwise indicated, this SOFTWARE has
been authored by an employee or employees of the University of
California, operator of the Los Alamos National Laboratory under
Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
U.S. Government has rights to use, reproduce, and distribute this
SOFTWARE. The public may copy, distribute, prepare derivative works
and publicly display this SOFTWARE without charge, provided that this
Notice and any statement of authorship are reproduced on all copies.
Neither the Government nor the University makes any warranty, express
or implied, or assumes any liability or responsibility for the use of
this SOFTWARE. If SOFTWARE is modified to produce derivative works,
such modified SOFTWARE should be clearly marked, so as not to confuse
it with the version available from LANL.
*/
/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
* rminnich@lanl.gov
*/
#ifndef lint
static char rcsid[] = "$Id$";
#endif
struct screen_info {
unsigned char orig_x; /* 0x00 */
unsigned char orig_y; /* 0x01 */
unsigned short dontuse1; /* 0x02 -- EXT_MEM_K sits here */
unsigned short orig_video_page; /* 0x04 */
unsigned char orig_video_mode; /* 0x06 */
unsigned char orig_video_cols; /* 0x07 */
unsigned short unused2; /* 0x08 */
unsigned short orig_video_ega_bx; /* 0x0a */
unsigned short unused3; /* 0x0c */
unsigned char orig_video_lines; /* 0x0e */
unsigned char orig_video_isVGA; /* 0x0f */
unsigned short orig_video_points; /* 0x10 */
/* VESA graphic mode -- linear frame buffer */
unsigned short lfb_width; /* 0x12 */
unsigned short lfb_height; /* 0x14 */
unsigned short lfb_depth; /* 0x16 */
unsigned long lfb_base; /* 0x18 */
unsigned long lfb_size; /* 0x1c */
unsigned short dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
unsigned short lfb_linelength; /* 0x24 */
unsigned char red_size; /* 0x26 */
unsigned char red_pos; /* 0x27 */
unsigned char green_size; /* 0x28 */
unsigned char green_pos; /* 0x29 */
unsigned char blue_size; /* 0x2a */
unsigned char blue_pos; /* 0x2b */
unsigned char rsvd_size; /* 0x2c */
unsigned char rsvd_pos; /* 0x2d */
unsigned short vesapm_seg; /* 0x2e */
unsigned short vesapm_off; /* 0x30 */
unsigned short pages; /* 0x32 */
/* 0x34 -- 0x3f reserved for future expansion */
};
#define E820MAP 0x2d0 /* our map */
#define E820MAX 32 /* number of entries in E820MAP */
#define E820NR 0x1e8 /* # entries in E820MAP */
/* sigh, this is not a struct or include file thing. */
#ifdef i386
/* from linux 2.2.13 */
/*
* This is set up by the setup-routine at boot-time
*/
#define PARAM ((unsigned char *)empty_zero_page)
#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
#define E820_MAP_NR (*(char*) (PARAM+E820NR))
#define E820_MAP ((unsigned long *) (PARAM+E820MAP))
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
#define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
#define COMMAND_LINE ((char *) (PARAM+2048))
#define COMMAND_LINE_SIZE 256
#endif
/* this is support for passing parameters to the linux kernel.
* you can pass memory size, command lines, and so on.
*/
void
init_params(unsigned char *empty_zero_page)
{
memset(PARAM, 0, 4096 /*XXXXXXXXXXXXXXXXX */ );
}
void
set_memory_size(unsigned char *empty_zero_page, unsigned long ext_memory_size,
unsigned long alt_memory_size)
{
/* for now, we do not have an 820 map (who cares, 8x0 chipsets are dead! */
E820_MAP_NR = 0;
EXT_MEM_K = ext_memory_size;
ALT_MEM_K = alt_memory_size;
}
void
set_root_rdonly(unsigned char *empty_zero_page)
{
MOUNT_ROOT_RDONLY = 1;
}
/* see the lilo doc */
void
set_command_line(unsigned char *empty_zero_page, unsigned char *cmdline)
{
int i;
/* no strncpy ...
strncpy(COMMAND_LINE, cmdline, COMMAND_LINE_SIZE);
*/
for (i = 0; (i < COMMAND_LINE_SIZE) && (cmdline[i]); i++)
COMMAND_LINE[i] = cmdline[i];
*(unsigned short *) 0x90020 = 0xa33f;
*(unsigned short *) 0x90022 = 2048;
}
unsigned char *
get_empty_zero_page()
{
/* gosh, I thought we had to do get at empty_zero_page, and we don't.
* silly me. We just have to get to 0x90000
*/
/* we'll leave this hook in for now. We may need it someday */
// unsigned long l = *(unsigned long *) 0xffffc;
return (unsigned char *) 0x90000;
}
/* I am pretty sure we only need to set rows and cols for now.
* All the rest is BIOS stuff. If it gets worse we'll have to make this a
* screen_info * as the param
*/
void
set_display(unsigned char *empty_zero_page, int rows, int cols)
{
struct screen_info *sc = &SCREEN_INFO;
sc->orig_video_cols = cols;
sc->orig_video_lines = rows;
}
void
set_initrd(unsigned char *empty_zero_page, unsigned long start, unsigned long size)
{
INITRD_START = start;
INITRD_SIZE = size;
LOADER_TYPE = 1;
}

View file

@ -4,6 +4,7 @@
/* Standard ELF types. */
#include <stdint.h>
#include <stddef.h>
#include <arch/boot/boot.h>
/* Type for a 16-bit quantity. */
@ -390,4 +391,5 @@ typedef Elf64_Phdr Elf_phdr;
extern int elf_check_arch(Elf_ehdr *ehdr);
extern void jmp_to_elf_entry(void *entry, void *ube);
extern int elfboot(size_t totalram);
#endif /* elf.h */

View file

@ -0,0 +1,13 @@
#ifndef ROM_FILL_INBUF_H
#define ROM_FILL_INBUF_H
extern unsigned char *inbuf; /* input buffer */
extern unsigned int insize; /* valid bytes in inbuf */
extern unsigned int inptr; /* index of next byte to be processed in inbuf */
extern int fill_inbuf(void);
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
#endif /* ROM_FILL_INBUF_H */

View file

@ -6,4 +6,9 @@
extern void *malloc(size_t size);
void free(void *ptr);
/* Extensions to malloc... */
typedef size_t malloc_mark_t;
void malloc_mark(malloc_mark_t *place);
void malloc_release(malloc_mark_t *place);
#endif /* STDLIB_H */

View file

@ -1,3 +1,8 @@
#ifndef STRING_H
#define STRING_H
#include <stddef.h>
// 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.
@ -5,8 +10,7 @@
//extern inline int strlen(char *src) { int i = 0; while (*src++) i++; return i;}
#if 1
extern inline int strnlen(const char *src, int max) {
static inline size_t strnlen(const char *src, size_t max) {
int i = 0;
if (max<0) {
while (*src++)
@ -19,23 +23,9 @@ extern inline int strnlen(const char *src, int max) {
return i;
}
}
#else
static inline size_t strnlen(const char * s, size_t count)
{
int d0;
register int __res;
__asm__ __volatile__(
"movl %2,%0\n\t"
"jmp 2f\n"
"1:\tcmpb $0,(%0)\n\t"
"je 3f\n\t"
"incl %0\n"
"2:\tdecl %1\n\t"
"cmpl $-1,%1\n\t"
"jne 1b\n"
"3:\tsubl %2,%0"
:"=a" (__res), "=&d" (d0)
:"c" (s),"1" (count));
return __res;
}
#endif
extern void *memcpy(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);
#endif /* STRING_H */

101
src/lib/do_inflate.c Normal file
View file

@ -0,0 +1,101 @@
#include <printk.h>
#include <string.h>
#include <stdlib.h>
#include <rom/fill_inbuf.h>
#include <subr.h>
#include "definitions.h"
#include "do_inflate.h"
#define MALLOC_WINDOW 1
/*
* gzip support routine declartions..
* =========================================================
*/
static void flush_window(void);
static long bytes_out; /* total bytes compressed */
static unsigned outcnt; /* bytes in output buffer */
#define WSIZE 0x8000 /* Window size must be at least 32k, and a power of two */
#if !MALLOC_WINDOW
static unsigned char window[WSIZE]; /* Sliding window buffer */
#else
static unsigned char *window; /* Sliding window buffer */
#endif
/*
* gzip declarations
*/
#define OF(args) args
#define STATIC static
#define memzero(s, n) memset ((s), 0, (n))
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
#ifdef TRACEV
# define Trace(x) printk(KERN_DDEBUG x)
# define Tracev(x) {if (verbose) printk(KERN_DDEBUG x);}
# define Tracevv(x) {if (verbose>1) printk(KERN_DDEBUG x);}
# define Tracec(c,x) {if (verbose && (c)) printk(KERN_DDEBUG x);}
# define Tracecv(c,x) {if (verbose>1 && (c)) printk(KERN_DDEBUG x);}
#else
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
#include "inflate.c"
/* Variables that gunzip doesn't need to see... */
static unsigned char *output_data;
static unsigned long output_ptr;
/* ===========================================================================
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
* (Used for the decompressed data only.)
*/
static void flush_window(void)
{
ulg c = crc; /* temporary variable */
unsigned n;
uch *in, *out, ch;
in = window;
out = &output_data[output_ptr];
DBG("flush 0x%08x count 0x%08x\n", (unsigned long) out, outcnt);
for (n = 0; n < outcnt; n++) {
ch = *out++ = *in++;
c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
}
crc = c;
bytes_out += (ulg) outcnt;
output_ptr += (ulg) outcnt;
outcnt = 0;
}
void gunzip_setup(void)
{
/* common globals -- don't rely on init! */
outcnt = 0;
bytes_out = 0;
output_ptr = 0;
#if MALLOC_WINDOW
window = malloc(WSIZE);
#endif
output_data = (char *) KERNEL_START;
DBG("output data is 0x%08x\n", (unsigned long) output_data);
makecrc();
}

6
src/lib/do_inflate.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef DO_INFLATE_H
#define DO_INFLATE_H
extern void gunzip_setup(void);
extern int gunzip(void);
#endif /* DO_INFLATE_H */

144
src/lib/elfboot.c Normal file
View file

@ -0,0 +1,144 @@
#if USE_ELF_BOOT
#include <printk.h>
#include <boot/elf.h>
#include <boot/uniform_boot.h>
#include <rom/fill_inbuf.h>
#include <string.h>
#include <subr.h>
int elfboot(size_t totalram)
{
static unsigned char header[ELF_HEAD_SIZE];
unsigned long offset;
Elf_ehdr *ehdr;
Elf_phdr *phdr;
void *ptr, *entry;
int i;
printk("\n");
printk("Welcome to elfboot, the open sourced starter.\n");
printk("Febuary 2001, Eric Biederman.\n");
printk("Version 0.99\n");
printk("\n");
ptr = get_ube_pointer(totalram);
post_code(0xf8);
/* Read in the initial 512 bytes */
for(offset = 0; offset < 512; offset++) {
header[offset] = get_byte();
}
ehdr = (Elf_ehdr *)(&header[0]);
entry = (void *)(ehdr->e_entry);
/* Sanity check the elf header */
if ((memcmp(ehdr->e_ident, ELFMAG, 4) != 0) ||
(ehdr->e_type != ET_EXEC) ||
(!elf_check_arch(ehdr)) ||
(ehdr->e_ident[EI_VERSION] != EV_CURRENT) ||
(ehdr->e_version != EV_CURRENT) ||
(ehdr->e_phoff > ELF_HEAD_SIZE) ||
(ehdr->e_phentsize != sizeof(Elf_phdr)) ||
((ehdr->e_phoff + (ehdr->e_phentsize * ehdr->e_phnum)) >
ELF_HEAD_SIZE)) {
goto out;
}
phdr = (Elf_phdr *)&header[ehdr->e_phoff];
offset = 0;
while(1) {
Elf_phdr *cur_phdr = 0;
int i,len;
unsigned long start_offset;
unsigned char *dest, *middle, *end;
/* Find the program header that descibes the current piece
* of the file.
*/
for(i = 0; i < ehdr->e_phnum; i++) {
if (phdr[i].p_type != PT_LOAD) {
continue;
}
if (phdr[i].p_filesz > phdr[i].p_memsz) {
continue;
}
if (phdr[i].p_offset >= offset) {
if (!cur_phdr ||
(cur_phdr->p_offset > phdr[i].p_offset)) {
cur_phdr = &phdr[i];
}
}
}
/* If we are out of sections we are done */
if (!cur_phdr) {
break;
}
printk("Loading Section: addr: 0x%08x memsz: 0x%08x filesz: 0x%08x\n",
cur_phdr->p_paddr, cur_phdr->p_memsz, cur_phdr->p_filesz);
/* Compute the boundaries of the section */
dest = (unsigned char *)(cur_phdr->p_paddr);
end = dest + cur_phdr->p_memsz;
len = cur_phdr->p_filesz;
if (len > cur_phdr->p_memsz) {
len = cur_phdr->p_memsz;
}
middle = dest + len;
start_offset = cur_phdr->p_offset;
/* Skip intial buffer unused bytes */
if (offset < ELF_HEAD_SIZE) {
if (start_offset < ELF_HEAD_SIZE) {
offset = start_offset;
} else {
offset = ELF_HEAD_SIZE;
}
}
/* Skip the unused bytes */
while(offset < start_offset) {
offset++;
get_byte();
}
/* Copy data from the initial buffer */
if (offset < ELF_HEAD_SIZE) {
size_t len;
if ((cur_phdr->p_filesz + start_offset) > ELF_HEAD_SIZE) {
len = ELF_HEAD_SIZE - start_offset;
}
else {
len = cur_phdr->p_filesz;
}
memcpy(dest, &header[start_offset], len);
dest += len;
}
/* Read the section into memory */
while(dest < middle) {
*(dest++) = get_byte();
}
offset += cur_phdr->p_filesz;
/* Zero the extra bytes */
while(dest < end) {
*(dest++) = 0;
}
}
DBG("Jumping to boot code\n");
post_code(0xfe);
/* Jump to kernel */
jmp_to_elf_entry(entry, ptr);
out:
printk("Bad ELF Image\n");
for(i = 0; i < sizeof(*ehdr); i++) {
if ((i & 0xf) == 0) {
printk("\n");
}
printk("%02x ", header[i]);
}
printk("\n");
return 0;
}
#endif /* USE_ELF_BOOT */

View file

@ -1,8 +1,5 @@
#define DEBG(x)
#define DEBGINT(x)
#define DEBG1(x)
#define DEBGH(x)
#define DEBGDYN(x)
/* Taken from /usr/src/linux/lib/inflate.c [unmodified]
Used for start32, 1/11/2000
James Hendricks, Dale Webster */
@ -13,6 +10,12 @@
/*
* Adapted for booting Linux by Hannu Savolainen 1993
* based on gzip-1.0.3
*
* Nicolas Pitre <nico@cam.org>, 1999/04/14 :
* Little mods for all variable to reside either into rodata or bss segments
* by marking constant variables with 'const' and initializing all the others
* at run-time only. This allows for the kernel uncompressor to run
* directly from Flash or ROM memory on embeded systems.
*/
/*
@ -115,7 +118,6 @@ static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #";
# include <stdlib.h>
#endif
#include "gzip.h"
#define STATIC
#endif /* !STATIC */
@ -140,8 +142,8 @@ struct huft {
/* Function prototypes */
STATIC int huft_build OF((unsigned *, unsigned, unsigned, const ush *,
const ush *, struct huft **, int *));
STATIC int huft_build OF((unsigned *, unsigned, unsigned,
const ush *, const ush *, struct huft **, int *));
STATIC int huft_free OF((struct huft *));
STATIC int inflate_codes OF((struct huft *, struct huft *, int, int));
STATIC int inflate_stored OF((void));
@ -164,20 +166,20 @@ STATIC int inflate OF((void));
#define flush_output(w) (wp=(w),flush_window())
/* Tables for deflate from PKZIP's appnote.txt. */
const unsigned border[] = { /* Order of the bit length code lengths */
static const unsigned border[] = { /* Order of the bit length code lengths */
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
const ush cplens[] = { /* Copy lengths for literal codes 257..285 */
static const ush cplens[] = { /* Copy lengths for literal codes 257..285 */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
/* note: see note #13 above about the 258 in this list. */
const ush cplext[] = { /* Extra bits for literal codes 257..285 */
static const ush cplext[] = { /* Extra bits for literal codes 257..285 */
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
const ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
static const ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
const ush cpdext[] = { /* Extra bits for distance codes */
static const ush cpdext[] = { /* Extra bits for distance codes */
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
@ -217,7 +219,7 @@ const ush cpdext[] = { /* Extra bits for distance codes */
STATIC ulg bb; /* bit buffer */
STATIC unsigned bk; /* bits in bit buffer */
const ush mask_bits[] = {
STATIC const ush mask_bits[] = {
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
@ -261,8 +263,8 @@ const ush mask_bits[] = {
*/
STATIC int lbits ; /* bits in base literal/length lookup table */
STATIC int dbits ; /* bits in base distance lookup table */
STATIC const int lbits = 9; /* bits in base literal/length lookup table */
STATIC const int dbits = 6; /* bits in base distance lookup table */
/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
@ -273,14 +275,14 @@ STATIC int dbits ; /* bits in base distance lookup table */
STATIC unsigned hufts; /* track memory usage */
STATIC int huft_build(
unsigned *b, /* code lengths in bits (all assumed <= BMAX) */
unsigned n, /* number of codes (assumed <= N_MAX) */
unsigned s, /* number of simple-valued codes (0..s-1) */
const ush *d, /* list of base values for non-simple codes */
const ush *e, /* list of extra bits for non-simple codes */
struct huft **t, /* result: starting table */
int *m) /* maximum lookup bits, returns actual */
STATIC int huft_build(b, n, s, d, e, t, m)
unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
unsigned n; /* number of codes (assumed <= N_MAX) */
unsigned s; /* number of simple-valued codes (0..s-1) */
const ush *d; /* list of base values for non-simple codes */
const ush *e; /* list of extra bits for non-simple codes */
struct huft **t; /* result: starting table */
int *m; /* maximum lookup bits, returns actual */
/* Given a list of code lengths and a maximum table size, make a set of
tables to decode that set of codes. Return zero on success, one if
the given code set is incomplete (the tables are still built in this
@ -307,7 +309,7 @@ STATIC int huft_build(
int y; /* number of dummy codes added */
unsigned z; /* number of entries in current table */
DEBGH("huft1 ");
DEBG("huft1 ");
/* Generate counts for each bit length */
memzero(c, sizeof(c));
@ -320,12 +322,12 @@ DEBGH("huft1 ");
} while (--i);
if (c[0] == n) /* null input--all zero length codes */
{
*t = 0;
*t = (struct huft *)NULL;
*m = 0;
return 0;
}
DEBGH("huft2 ");
DEBG("huft2 ");
/* Find minimum and maximum length, bound *m by those */
l = *m;
@ -343,7 +345,7 @@ DEBGH("huft2 ");
l = i;
*m = l;
DEBGH("huft3 ");
DEBG("huft3 ");
/* Adjust last length count to fill out codes, if needed */
for (y = 1 << j; j < i; j++, y <<= 1)
@ -353,7 +355,7 @@ DEBGH("huft3 ");
return 2;
c[i] += y;
DEBGH("huft4 ");
DEBG("huft4 ");
/* Generate starting offsets into the value table for each length */
x[1] = j = 0;
@ -362,7 +364,7 @@ DEBGH("huft4 ");
*xp++ = (j += *p++);
}
DEBGH("huft5 ");
DEBG("huft5 ");
/* Make a table of values in order of bit lengths */
p = b; i = 0;
@ -371,26 +373,26 @@ DEBGH("huft5 ");
v[x[j]++] = i;
} while (++i < n);
DEBGH("h6 ");
DEBG("h6 ");
/* Generate the Huffman codes and for each, make the table entries */
x[0] = i = 0; /* first Huffman code is zero */
p = v; /* grab values in bit order */
h = -1; /* no tables yet--level -1 */
w = -l; /* bits decoded == (l * h) */
u[0] = 0; /* just to keep compilers happy */
q = (struct huft *)0; /* ditto */
u[0] = (struct huft *)NULL; /* just to keep compilers happy */
q = (struct huft *)NULL; /* ditto */
z = 0; /* ditto */
DEBGH("h6a ");
DEBG("h6a ");
/* go through the bit lengths (k already is bits in shortest code) */
for (; k <= g; k++)
{
DEBGH("h6b ");
DEBG("h6b ");
a = c[k];
while (a--)
{
DEBGH("h6b1 ");
DEBG("h6b1 ");
/* here i is the Huffman code of length k bits for value *p */
/* make tables up to required level */
while (k > w + l)
@ -417,7 +419,8 @@ DEBG1("3 ");
z = 1 << j; /* table entries for j-bit table */
/* allocate and link in new table */
if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == 0)
if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
(struct huft *)NULL)
{
if (h)
huft_free(u[0]);
@ -426,7 +429,7 @@ DEBG1("3 ");
DEBG1("4 ");
hufts += z + 1; /* track memory usage */
*t = q + 1; /* link to list for huft_free() */
*(t = &(q->v.t)) = 0;
*(t = &(q->v.t)) = (struct huft *)NULL;
u[h] = ++q; /* table starts after link */
DEBG1("5 ");
@ -442,7 +445,7 @@ DEBG1("5 ");
}
DEBG1("6 ");
}
DEBGH("h6c ");
DEBG("h6c ");
/* set up table entry in r */
r.b = (uch)(k - w);
@ -459,7 +462,7 @@ DEBGH("h6c ");
r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
r.v.n = d[*p++ - s];
}
DEBGH("h6d ");
DEBG("h6d ");
/* fill code-like entries with r */
f = 1 << (k - w);
@ -477,12 +480,12 @@ DEBGH("h6d ");
h--; /* don't need to update q */
w -= l;
}
DEBGH("h6e ");
DEBG("h6e ");
}
DEBGH("h6f ");
DEBG("h6f ");
}
DEBGH("huft7 ");
DEBG("huft7 ");
/* Return true (1) if we were given an incomplete table */
return y != 0 && g != 1;
@ -490,8 +493,8 @@ DEBGH("huft7 ");
STATIC int huft_free(
struct huft *t) /* table to free */
STATIC int huft_free(t)
struct huft *t; /* table to free */
/* Free the malloc'ed tables built by huft_build(), which makes a linked
list of the tables it made, with the links in a dummy first entry of
each table. */
@ -501,7 +504,7 @@ struct huft *t) /* table to free */
/* Go through linked list, freeing from the malloced (t[-1]) address. */
p = t;
while (p != 0)
while (p != (struct huft *)NULL)
{
q = (--p)->v.t;
free((char*)p);
@ -511,11 +514,9 @@ struct huft *t) /* table to free */
}
STATIC int inflate_codes(
struct huft *tl,
struct huft *td, /* literal/length and distance decoder tables */
int bl,
int bd) /* number of bits decoded by tl[] and td[] */
STATIC int inflate_codes(tl, td, bl, bd)
struct huft *tl, *td; /* literal/length and distance decoder tables */
int bl, bd; /* number of bits decoded by tl[] and td[] */
/* inflate (decompress) the codes in a deflated (compressed) block.
Return an error code or zero if it all goes ok. */
{
@ -550,9 +551,6 @@ STATIC int inflate_codes(
DUMPBITS(t->b)
if (e == 16) /* then it's a literal */
{
/*
DEBG("l");
*/
slide[w++] = (uch)t->v.n;
Tracevv((stderr, "%c", slide[w-1]));
if (w == WSIZE)
@ -587,18 +585,10 @@ STATIC int inflate_codes(
d = w - t->v.n - ((unsigned)b & mask_bits[e]);
DUMPBITS(e)
Tracevv((stderr,"\\[%d,%d]", w-d, n));
/*
DEBG("D");printint(w-d);printint(n);
*/
/* do the copy */
do {
n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
#if 0
DEBG("memcpy %d to %d size %d"); printint(d); printint(w);
printint(e);
DEBG("\n");
#endif
#if !defined(NOMEMCPY) && !defined(DEBUG)
if (w - d >= e) /* (this test assumes unsigned comparison) */
{
@ -633,7 +623,7 @@ STATIC int inflate_codes(
STATIC int inflate_stored(void)
STATIC int inflate_stored()
/* "decompress" an inflated type 0 (stored) block. */
{
unsigned n; /* number of bytes in block */
@ -689,7 +679,7 @@ DEBG("<stor");
STATIC int inflate_fixed(void)
STATIC int inflate_fixed()
/* decompress an inflated type 1 (fixed Huffman codes) block. We should
either replace this with a custom decoder, or at least precompute the
Huffman tables. */
@ -743,7 +733,7 @@ DEBG("<fix");
STATIC int inflate_dynamic(void)
STATIC int inflate_dynamic()
/* decompress an inflated type 2 (dynamic Huffman codes) block. */
{
int i; /* temporary variables */
@ -766,14 +756,6 @@ STATIC int inflate_dynamic(void)
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
#if 0
for(i = 0; i < 288+32; i++)
if (ll[i]) {
display("non-zero ll index at ");
printint(i);
}
#endif
DEBG("<dyn");
/* make local bit buffer */
@ -797,8 +779,8 @@ DEBG("<dyn");
if (nl > 286 || nd > 30)
#endif
return 1; /* bad lengths */
DEBGINT(nl); DEBGINT(nd); DEBGINT(nb);
DEBGDYN("dyn1 ");
DEBG("dyn1 ");
/* read in bit-length-code lengths */
for (j = 0; j < nb; j++)
@ -810,17 +792,18 @@ DEBGDYN("dyn1 ");
for (; j < 19; j++)
ll[border[j]] = 0;
DEBG("dyn2 ");
/* build decoding table for trees--single level, 7 bit lookup */
bl = 7;
if ((i = huft_build(ll, 19, 19, 0, 0, &tl, &bl)) != 0)
if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
{
if (i == 1)
huft_free(tl);
return i; /* incomplete code set */
}
DEBGDYN("dyn3 freemem now "); DEBGINT(free_mem_ptr);
DEBG("dyn3 ");
/* read in literal and distance code lengths */
n = nl + nd;
@ -832,9 +815,6 @@ DEBGDYN("dyn3 freemem now "); DEBGINT(free_mem_ptr);
j = (td = tl + ((unsigned)b & m))->b;
DUMPBITS(j)
j = td->v.n;
/*
DEBGDYN("j is now"); DEBGINT(j);
*/
if (j < 16) /* length of code in bits (0..15) */
ll[i++] = l = j; /* save last length in l */
else if (j == 16) /* repeat last length 3 to 6 times */
@ -842,9 +822,6 @@ DEBGDYN("dyn3 freemem now "); DEBGINT(free_mem_ptr);
NEEDBITS(2)
j = 3 + ((unsigned)b & 3);
DUMPBITS(2)
/*
DEBGDYN("j second is now"); DEBGINT(j);
*/
if ((unsigned)i + j > n)
return 1;
while (j--)
@ -855,9 +832,6 @@ DEBGDYN("dyn3 freemem now "); DEBGINT(free_mem_ptr);
NEEDBITS(3)
j = 3 + ((unsigned)b & 7);
DUMPBITS(3)
/*
DEBGDYN("j three is now"); DEBGINT(j);
*/
if ((unsigned)i + j > n)
return 1;
while (j--)
@ -869,9 +843,6 @@ DEBGDYN("dyn3 freemem now "); DEBGINT(free_mem_ptr);
NEEDBITS(7)
j = 11 + ((unsigned)b & 0x7f);
DUMPBITS(7)
/*
DEBGDYN("j four is now"); DEBGINT(j);
*/
if ((unsigned)i + j > n)
return 1;
while (j--)
@ -880,35 +851,35 @@ DEBGDYN("dyn3 freemem now "); DEBGINT(free_mem_ptr);
}
}
DEBGDYN("dyn4 ");
DEBG("dyn4 ");
/* free decoding table for trees */
huft_free(tl);
DEBGDYN("dyn5 free mem is now");DEBGINT(free_mem_ptr);
DEBG("dyn5 ");
/* restore the global bit buffer */
bb = b;
bk = k;
DEBGDYN("dyn5a ");
DEBG("dyn5a ");
/* build the decoding tables for literal/length and distance codes */
bl = lbits;
if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
{
DEBGDYN("dyn5b ");
DEBG("dyn5b ");
if (i == 1) {
error(" incomplete literal tree\n");
huft_free(tl);
}
return i; /* incomplete code set */
}
DEBGDYN("dyn5c ");
DEBG("dyn5c ");
bd = dbits;
if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
{
DEBGDYN("dyn5d ");
DEBG("dyn5d ");
if (i == 1) {
error(" incomplete distance tree\n");
#ifdef PKZIP_BUG_WORKAROUND
@ -922,15 +893,13 @@ DEBGDYN("dyn5d ");
#endif
}
DEBGDYN("dyn6 free_mem_ptr ");DEBGINT(free_mem_ptr);
DEBG("dyn6 ");
/* decompress until an end-of-block code */
DEBG("inflate_codes inptr is "); DEBGINT(inptr);
if (inflate_codes(tl, td, bl, bd))
return 1;
DEBG("AFTER inflate_codes inptr is "); DEBGINT(inptr);
DEBGDYN("dyn7 ");
DEBG("dyn7 ");
/* free the decoding tables, return */
huft_free(tl);
@ -942,18 +911,16 @@ DEBGDYN("dyn7 ");
STATIC int inflate_block(
int *e) /* last block flag */
STATIC int inflate_block(e)
int *e; /* last block flag */
/* decompress an inflated block */
{
unsigned t; /* block type */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
DEBG("<blk(");
DEBGINT(inptr);
DEBG(")");
DEBG("<blk");
/* make local bit buffer */
b = bb;
k = bk;
@ -991,13 +958,13 @@ int *e) /* last block flag */
STATIC int inflate(void)
STATIC int inflate()
/* decompress an inflated entry */
{
int e; /* last block flag */
int r; /* result code */
unsigned h; /* maximum struct huft's malloc'ed */
void *ptr;
malloc_mark_t mark;
/* initialize window, bit buffer */
wp = 0;
@ -1009,12 +976,12 @@ STATIC int inflate(void)
h = 0;
do {
hufts = 0;
gzip_mark(&ptr);
malloc_mark(&mark);
if ((r = inflate_block(&e)) != 0) {
gzip_release(&ptr);
malloc_release(&mark);
return r;
}
gzip_release(&ptr);
malloc_release(&mark);
if (hufts > h)
h = hufts;
} while (!e);
@ -1043,9 +1010,7 @@ STATIC int inflate(void)
**********************************************************************/
static ulg crc_32_tab[256];
/* note that this fails for NVRAM! */
/* do assign below in makecrc */
static ulg crc ; /*= (ulg)0xffffffffL; shift register contents */
static ulg crc; /* initialized in makecrc() so it'll reside in bss */
#define CRC_VALUE (crc ^ 0xffffffffL)
/*
@ -1064,12 +1029,8 @@ makecrc(void)
int k; /* byte being shifted into crc apparatus */
/* terms of polynomial defining this crc (except x^32): */
const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* move init of the lbits and dbits here, I know this is hokey -- rgm */
lbits = 9; /* bits in base literal/length lookup table */
dbits = 6; /* bits in base distance lookup table */
crc = (ulg)0xffffffffL; /* shift register contents */
/* Make exclusive-or pattern from polynomial */
e = 0;
for (i = 0; i < sizeof(p)/sizeof(int); i++)
@ -1088,6 +1049,9 @@ makecrc(void)
}
crc_32_tab[i] = c;
}
/* this is initialized here so this code could reside in ROM */
crc = (ulg)0xffffffffL; /* shift register contents */
}
/* gzip flag byte */
@ -1102,7 +1066,7 @@ makecrc(void)
/*
* Do the uncompression!
*/
static int gunzip(void)
int gunzip(void)
{
uch flags;
unsigned char magic[2]; /* magic header */

52
src/lib/malloc.c Normal file
View file

@ -0,0 +1,52 @@
#include <stdlib.h>
#include <printk.h>
#include <subr.h>
#if 1
#define MALLOCDBG(x)
#else
#define MALLOCDBG(x) printk x
#endif
extern unsigned char _heap, _eheap;
static size_t free_mem_ptr = (size_t)&_heap; /* Start of heap */
static size_t free_mem_end_ptr = (size_t)&_eheap; /* End of heap */
void malloc_mark(malloc_mark_t *place)
{
*place = free_mem_ptr;
DBG("malloc_mark 0x%08lx\n", (unsigned long)free_mem_ptr);
}
void malloc_release(malloc_mark_t *ptr)
{
free_mem_ptr = *ptr;
DBG("malloc_release 0x%08lx\n", (unsigned long)free_mem_ptr);
}
void *malloc(size_t size)
{
void *p;
if (size < 0)
error("Error! malloc: Size < 0");
if (free_mem_ptr <= 0)
error("Error! malloc: Free_mem_ptr <= 0");
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
p = (void *) free_mem_ptr;
free_mem_ptr += size;
if (free_mem_ptr >= free_mem_end_ptr)
error("Error! malloc: Free_mem_ptr >= free_mem_end_ptr");
MALLOCDBG(("malloc 0x%08lx\n", (unsigned long)p));
return p;
}
void free(void *where)
{
/* Don't care */
}

View file

@ -0,0 +1,56 @@
northbridge intel/440gx
southbridge intel/piix4e
superio NSC/pc87309
option ENABLE_FIXED_AND_VARIABLE_MTRRS
option PIIX4_DEVFN=0x90
option NO_KEYBOARD
option ZKERNEL_START=0xfff40000
option ZKERNEL_MASK=0x3ed
option L440GX
option SMP
object mainboard.o
cpu p6
cpu p5
makerule phlash_floppy: phlash ; mcopy -o /tmp/$(PHLASH_BASE_NAME).bi? a:
makerule phlash: $(BOOT_IMAGE) linuxbios.rom headers ; rm -f xa?
addaction phlash split -b 64k $(BOOT_IMAGE)
addaction phlash # Now just touch them if we have a really
addaction phlash # small kernel!
addaction phlash touch xaa xab xac xad xae xaf xag xah
addaction phlash # this is starting at bank 4, and proceeding on. Unused banks are dups
addaction phlash # the nvram is odd, all of the banks are interleaved
addaction phlash cat $(PHLASH_BASE_NAME).bi1.header xaa > $(PHLASH_BASE_NAME).bi1 #4
addaction phlash cat $(PHLASH_BASE_NAME).bi3.header xab > $(PHLASH_BASE_NAME).bi3 #6
addaction phlash cat $(PHLASH_BASE_NAME).bi2.header xac > $(PHLASH_BASE_NAME).bi2 #7
addaction phlash cat $(PHLASH_BASE_NAME).bi4.header xad > $(PHLASH_BASE_NAME).bi4 #9
addaction phlash cat $(PHLASH_BASE_NAME).bi7.header xae > $(PHLASH_BASE_NAME).bi7 #a
addaction phlash cat $(PHLASH_BASE_NAME).bi6.header xaf > $(PHLASH_BASE_NAME).bi6 #b
addaction phlash cat $(PHLASH_BASE_NAME).bi9.header xag > $(PHLASH_BASE_NAME).bi9 #c
addaction phlash cat $(PHLASH_BASE_NAME).bi8.header xah > $(PHLASH_BASE_NAME).bi8 #d
addaction phlash cat $(PHLASH_BASE_NAME).bia.header linuxbios.rom > $(PHLASH_BASE_NAME).bia
addaction phlash # Part o & 5 seem not to be written reliably for some reason...
addaction phlash cat $(PHLASH_BASE_NAME).bio.header /dev/null > $(PHLASH_BASE_NAME).bio
addaction phlash cat $(PHLASH_BASE_NAME).bi5.header /dev/null > $(PHLASH_BASE_NAME).bi5
addaction phlash sh -x $(TOP)/src/mainboard/intel/l440gx/BUILD_PHLASH_FILES $(PHLASH_BASE_NAME)
makerule headers : $(PHLASH_BASE_NAME).bi1.header $(PHLASH_BASE_NAME).bi2.header $(PHLASH_BASE_NAME).bi3.header $(PHLASH_BASE_NAME).bi4.header $(PHLASH_BASE_NAME).bi5.header $(PHLASH_BASE_NAME).bi6.header $(PHLASH_BASE_NAME).bi7.header $(PHLASH_BASE_NAME).bi8.header $(PHLASH_BASE_NAME).bi9.header $(PHLASH_BASE_NAME).bia.header $(PHLASH_BASE_NAME).bio.header ;
makerule $(PHLASH_BASE_NAME).bi1.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi1 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi2.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi2 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi3.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi3 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi4.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi4 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi5.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi5 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi6.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi6 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi7.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi7 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi8.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi8 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bi9.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bi9 ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bia.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bia ; dd if=$< of=$@ bs=1 count=160
makerule $(PHLASH_BASE_NAME).bio.header: $(TOP)/../intel_flash_disk/$(PHLASH_BASE_NAME).bio ; dd if=$< of=$@ bs=1 count=160
addaction clean rm -f $(PHLASH_BASE_NAME)* xa?

View file

@ -26,7 +26,7 @@
#include <pc80/i8259.inc>
#include <superio/NSC/pc87309/superio.inc>
#include <superio/NSC/pc87309/setup_serial.inc>
#include <pc80/serial.inc>

View file

@ -23,9 +23,9 @@ void mainboard_fixup()
#endif
#if 1
{
unsigned char byte;
unsigned short word;
unsigned long dword;
u8 byte;
u16 word;
u32 dword;
for(i = 0; i < 8; i++) {
pci_read_config_byte(host_bridge_pcidev, 0x60 +i, &byte);
printk("DRB[i] = 0x%02x\n", byte);

View file

@ -0,0 +1,3 @@
cpu ev6
option USE_CPU_EV6=1
option USE_CORE_TSUNAMI=1

View file

@ -0,0 +1,4 @@
raminit northbridge/intel/440gx/raminit.inc
raminit sdram/generic_sdram.inc
object northbridge.o

4
src/rom/Config Normal file
View file

@ -0,0 +1,4 @@
object fill_inbuf.o
object rom_fill_inbuf.o
object docmil_fill_inbuf.o
object tsunami_tigbus_rom_fill_inbuf.o

120
src/rom/docmil_fill_inbuf.c Normal file
View file

@ -0,0 +1,120 @@
#ifdef USE_DOC_MIL
#include <cpu/p5/io.h>
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/fill_inbuf.h>
#ifndef DOC_KERNEL_START
#define DOC_KERNEL_START 65536
#endif
static unsigned char *nvram;
static int block_count;
static int firstfill = 1;
void memcpy_from_doc_mil(void *dest, const void *src, size_t n);
unsigned char *doc_mil = (unsigned char *) 0xffffe000;
#ifdef CHECK_DOC_MIL
unsigned char *checkbuf;
#endif /* CHECK_DOC_MIL */
static unsigned char *ram;
#define K64 (64 * 1024)
int fill_inbuf(void)
{
if (firstfill) {
if ((ram = malloc(K64)) == NULL) {
printk(KERN_EMERG "%6d:%s() - ram malloc failed\n",
__LINE__, __FUNCTION__);
return (0);
}
#ifdef CHECK_DOC_MIL
if ((checkbuf = malloc(K64)) == NULL) {
printk(KERN_EMERG "%6d:%s() - checkbuf malloc failed\n",
__LINE__, __FUNCTION__);
printk(KERN_EMERG "Checking disabled\n");
}
#endif
DBG("%6d:%s() - ram buffer:0x%p\n",
__LINE__, __FUNCTION__, ram);
block_count = 0;
firstfill = 0;
nvram = (unsigned char *) DOC_KERNEL_START;
}
memcpy_from_doc_mil(ram, nvram, K64);
#ifdef CHECK_DOC_MIL
if (checkbuf) {
memcpy_from_doc_mil(checkbuf, nvram, K64);
if (memcmp(checkbuf, ram, K64)) {
printk("CHECKBUF FAILS for doc mil!\n");
printk(KERN_EMERG "address 0x%x\n", nvram);
}
}
{
int i;
printk(KERN_INFO "First 16 bytes of block: ");
for(i = 0; i < 16; i++)
printk("0x%x ", ram[i]);
printk(KERN_INFO "\n");
}
#endif
DBG("%6d:%s() - nvram:0x%p block_count:%d\n",
__LINE__, __FUNCTION__, nvram, block_count);
nvram += K64;
inbuf = ram;
insize = K64;
inptr = 1;
post_code(0xd0 + block_count);
block_count++;
return inbuf[0];
}
void memcpy_from_doc_mil(void *dest, const void *src, size_t n)
{
int i;
unsigned long address = (unsigned long) src;
for (i = n; i >= 0; i -= 0x200) {
unsigned short c = 0x1000;
volatile unsigned char dummy;
/* issue Read00 flash command */
*(unsigned char *) (doc_mil + 0x1004) = 0x03;
*(unsigned char *) (doc_mil + 0x800) = 0x00;
*(unsigned char *) (doc_mil + 0x101e) = 0x00;
*(unsigned char *) (doc_mil + 0x1004) = 0x01;
/* issue Address to flash */
*(unsigned char *) (doc_mil + 0x1004) = 0x05;
*(unsigned char *) (doc_mil + 0x800) = address & 0xff;
*(unsigned char *) (doc_mil + 0x800) = (address >> 9) & 0xff;
*(unsigned char *) (doc_mil + 0x800) = (address >> 17) & 0xff;
*(unsigned char *) (doc_mil + 0x101e) = 0x00;
*(unsigned char *) (doc_mil + 0x1004) = 0x01;
/* We are using the "side effect" of the assignment to force GCC reload
* *(doc_mil + 0x1004) on each iteration */
while (!((dummy = *(unsigned char *) (doc_mil + 0x1004)) & 0x80) && --c)
/* wait for chip response */;
/* copy 512 bytes of data from CDSN_IO registers */
dummy = *(unsigned char *) (doc_mil + 0x101d);
memcpy(dest, doc_mil + 0x800, 0x200);
dest += 0x200;
address += 0x200;
}
}
#endif /* USE_DOC_MIL */

7
src/rom/fill_inbuf.c Normal file
View file

@ -0,0 +1,7 @@
#include <rom/fill_inbuf.h>
unsigned char *inbuf /* = 0 */;
unsigned int insize /* = 0 */;
unsigned int inptr /* = 0 */;

117
src/rom/rom_fill_inbuf.c Normal file
View file

@ -0,0 +1,117 @@
#ifdef USE_GENERIC_ROM
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/fill_inbuf.h>
#include <string.h>
#ifndef ZKERNEL_START
#define ZKERNEL_START 0xfff80000
#endif
#ifndef ZKERNEL_MASK
#define ZKERNEL_MASK 0x0000ffff
#endif
static unsigned char *zkernel_start = (unsigned char *)ZKERNEL_START;
static unsigned long zkernel_mask = ZKERNEL_MASK;
static unsigned char *nvram;
static int block_count;
static int firstfill = 1;
#if defined(INBUF_COPY)
static unsigned char *ram;
#endif
#define K64 (64 * 1024)
int fill_inbuf(void)
{
extern unsigned char *inbuf;
extern unsigned int insize;
extern unsigned int inptr;
if (firstfill) {
block_count = 0;
firstfill = 0;
#ifdef INBUF_COPY
ram = malloc(K64);
#endif
}
if (block_count > 31) {
printk(KERN_EMERG "%6d:%s() - overflowed source buffer\n",
__LINE__, __FUNCTION__);
inbuf = zkernel_start;
inptr = 0;
insize = 0;
return (0);
}
if (!block_count) {
nvram = zkernel_start;
#ifdef INBUF_COPY
if (!ram) {
printk(KERN_EMERG "%6d:%s() - "
"ram malloc failed\n",
__LINE__, __FUNCTION__);
inbuf = zkernel_start;
inptr = 0;
insize = 0;
return (0);
}
DBG("%6d:%s() - ram buffer:0x%08x\n",
__LINE__, __FUNCTION__, ram);
#endif
DBG("%6d:%s() - zkernel_start:0x%08x "
"zkernel_mask:0x%08x\n",
__LINE__, __FUNCTION__,
zkernel_start, zkernel_mask);
} else {
nvram += K64;
while (!(zkernel_mask & (1 << block_count))) {
DBG("%6d:%s() - skipping block %d\n",
__LINE__, __FUNCTION__, block_count);
block_count++;
nvram += K64;
if (block_count > 31) {
printk(KERN_EMERG "%6d:%s() - "
"overflowed source buffer\n",
__LINE__, __FUNCTION__);
inbuf = zkernel_start;
inptr = 0;
insize = 1;
return (0);
}
}
}
#ifdef INBUF_COPY
memcpy(ram, nvram, K64);
#endif
DBG("%6d:%s() - nvram:0x%p block_count:%d\n",
__LINE__, __FUNCTION__, nvram, block_count);
#ifdef INBUF_COPY
inbuf = ram;
#else
inbuf = nvram;
#endif
insize = K64;
inptr = 1;
post_code(0xd0 + block_count);
block_count++;
return inbuf[0];
}
#endif /* USE_GENERIC_ROM */

View file

@ -0,0 +1,98 @@
#ifdef USE_TSUNAMI_TIGBUS_ROM
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/fill_inbuf.h>
#include <arch/io.h>
#include <northbridge/alpha/tsunami/core_tsunami.h>
#ifndef TIG_KERNEL_START
#define TIG_KERNEL_START 0x20000
#endif
static unsigned long nvram;
static int block_count;
static int firstfill = 1;
static unsigned char *ram;
#define K64 (64 * 1024)
#define MAX_TIG_FLASH_SIZE (16*1024*1024)
static void tsunami_flash_copy_from(void *addr, unsigned long offset, long len)
{
unsigned char *dest;
dest = addr;
while(len && (offset < MAX_TIG_FLASH_SIZE)) {
*dest = tsunami_tig_readb(offset);
offset++;
dest++;
len--;
}
}
int fill_inbuf(void)
{
extern unsigned char *inbuf;
extern unsigned int insize;
extern unsigned int inptr;
if (firstfill) {
block_count = 0;
firstfill = 0;
ram = malloc(K64);
if (!ram) {
printk(KERN_EMERG "%6d:%s() - "
"ram malloc failed\n",
__LINE__, __FUNCTION__);
return 0;
}
}
if (block_count > 31) {
printk(KERN_EMERG "%6d:%s() - overflowed source buffer\n",
__LINE__, __FUNCTION__);
insize = 0;
return (0);
}
if (!block_count) {
nvram = TIG_KERNEL_START;
DBG("%6d:%s() - ram buffer:0x%08x\n",
__LINE__, __FUNCTION__, ram);
DBG("%6d:%s() - TIG_KERNEL_START:0x%08x\n",
__LINE__, __FUNCTION__,
TIG_KERNEL_START);
}
tsunami_flash_copy_from(ram, nvram, K64);
DBG("\n%6d:%s() - nvram:0x%lx block_count:%d\n",
__LINE__, __FUNCTION__, nvram, block_count);
#if 0
{
int i;
for(i = 0; i < K64; i+= 16) {
printk("%05x: %02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
(block_count << 16)+i,
ram[i+0], ram[i+1], ram[i+2], ram[i+3],
ram[i+4], ram[i+5], ram[i+6], ram[i+7],
ram[i+8], ram[i+9], ram[i+10], ram[i+11],
ram[i+12], ram[i+13], ram[i+14],ram[i+15]);
}
}
#endif
nvram += K64;
inbuf = ram;
insize = K64;
inptr = 1;
post_code(0xd0 + block_count);
block_count++;
return inbuf[0];
}
#endif /* USE_TSUNAMI_TIGBUS_ROM */

View file

@ -0,0 +1,47 @@
/*
* Enable the peripheral devices on the NSC Super IO chip PC87309
* For now this is specific to the L440GX motherboard.
*/
/* The base address is 0x15c, 0x2e, depending on config bytes */
#define SIO_BASE $0x2e
#define SIO_INDEX SIO_BASE
#define SIO_DATA SIO_BASE+1
#define SIO_READ(ldn, index) \
mov SIO_BASE, %dx ; \
mov $0x07, %al ; \
outb %al, %dx ; \
inc %dx ; \
mov ldn, %al ; \
outb %al, %dx ; \
dec %dx ; \
mov index, %al ; \
outb %al, %dx ; \
inc %dx ; \
inb %dx, %al ;
#define SIO_WRITE(ldn, index, data) \
mov SIO_BASE, %dx ; \
mov $0x07, %al ; \
outb %al, %dx ; \
inc %dx ; \
mov ldn, %al ; \
outb %al, %dx ; \
dec %dx ; \
mov index, %al ; \
outb %al, %dx ; \
inc %dx ; \
mov data, %al ; \
outb %al, %dx ;
/* At boot up the chip is in configure mode so don't worry
* about getting it there just configure some peripherals.
*/
/* enable serial 1 */
SIO_WRITE($0x03, $0x30, $0x01)