diff --git a/src/arch/i386/config/crt0.base b/src/arch/i386/config/crt0.base new file mode 100644 index 0000000000..24fb673e4a --- /dev/null +++ b/src/arch/i386/config/crt0.base @@ -0,0 +1,109 @@ +/* + * $ $ + * + */ + +#include +#include + +#include +/* + * 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 + +#include + +CRT0_PARAMETERS + +/* Turn on mtrr for faster boot */ +#include + +/* + * 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" diff --git a/src/arch/i386/config/ldscript.base b/src/arch/i386/config/ldscript.base new file mode 100644 index 0000000000..c0376ff77e --- /dev/null +++ b/src/arch/i386/config/ldscript.base @@ -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 */ diff --git a/src/arch/i386/config/make.base b/src/arch/i386/config/make.base new file mode 100644 index 0000000000..436d544cdb --- /dev/null +++ b/src/arch/i386/config/make.base @@ -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 diff --git a/src/arch/i386/include/arch/io.h b/src/arch/i386/include/arch/io.h new file mode 100644 index 0000000000..e3d0ea770d --- /dev/null +++ b/src/arch/i386/include/arch/io.h @@ -0,0 +1 @@ +#include diff --git a/src/arch/i386/lib/Config b/src/arch/i386/lib/Config new file mode 100644 index 0000000000..9c1b74211b --- /dev/null +++ b/src/arch/i386/lib/Config @@ -0,0 +1,3 @@ +object i386_subr.o +object params.o +object hardwaremain.o diff --git a/src/arch/i386/lib/hardwaremain.c b/src/arch/i386/lib/hardwaremain.c new file mode 100644 index 0000000000..3e8ba8102c --- /dev/null +++ b/src/arch/i386/lib/hardwaremain.c @@ -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 +#include +#include +#include +#include +#include +#include + +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 */ +} diff --git a/src/arch/i386/lib/i386_subr.c b/src/arch/i386/lib/i386_subr.c new file mode 100644 index 0000000000..ff4bd15b61 --- /dev/null +++ b/src/arch/i386/lib/i386_subr.c @@ -0,0 +1,163 @@ +#include +#include +#include + +#include +#include +#include +#include + +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; isize; 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 +} + diff --git a/src/arch/i386/lib/params.c b/src/arch/i386/lib/params.c new file mode 100644 index 0000000000..8e26098ff3 --- /dev/null +++ b/src/arch/i386/lib/params.c @@ -0,0 +1,166 @@ +#include + +/* +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; +} diff --git a/src/include/boot/elf.h b/src/include/boot/elf.h index abc17b2bd5..6884fe91fe 100644 --- a/src/include/boot/elf.h +++ b/src/include/boot/elf.h @@ -4,6 +4,7 @@ /* Standard ELF types. */ #include +#include #include /* 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 */ diff --git a/src/include/rom/fill_inbuf.h b/src/include/rom/fill_inbuf.h new file mode 100644 index 0000000000..16f76b7ecb --- /dev/null +++ b/src/include/rom/fill_inbuf.h @@ -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 */ diff --git a/src/include/stdlib.h b/src/include/stdlib.h index c86a981f28..eb67d20fe7 100644 --- a/src/include/stdlib.h +++ b/src/include/stdlib.h @@ -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 */ diff --git a/src/include/string.h b/src/include/string.h index 63be07241d..dbaa1ecd17 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -1,3 +1,8 @@ +#ifndef STRING_H +#define STRING_H + +#include + // 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 */ diff --git a/src/lib/do_inflate.c b/src/lib/do_inflate.c new file mode 100644 index 0000000000..8f1c76545f --- /dev/null +++ b/src/lib/do_inflate.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#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(); +} diff --git a/src/lib/do_inflate.h b/src/lib/do_inflate.h new file mode 100644 index 0000000000..693a00a7da --- /dev/null +++ b/src/lib/do_inflate.h @@ -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 */ diff --git a/src/lib/elfboot.c b/src/lib/elfboot.c new file mode 100644 index 0000000000..9921d49e8e --- /dev/null +++ b/src/lib/elfboot.c @@ -0,0 +1,144 @@ +#if USE_ELF_BOOT +#include +#include +#include +#include +#include +#include + +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 */ diff --git a/src/lib/inflate.c b/src/lib/inflate.c index 6f691c297f..337de31df4 100644 --- a/src/lib/inflate.c +++ b/src/lib/inflate.c @@ -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 , 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 #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(" 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(" 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 */ diff --git a/src/lib/malloc.c b/src/lib/malloc.c new file mode 100644 index 0000000000..e954e3889c --- /dev/null +++ b/src/lib/malloc.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#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 */ +} diff --git a/src/mainboard/intel/l440gx/Config b/src/mainboard/intel/l440gx/Config new file mode 100644 index 0000000000..e18cb22ddf --- /dev/null +++ b/src/mainboard/intel/l440gx/Config @@ -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? diff --git a/src/mainboard/intel/l440gx/crt0.S b/src/mainboard/intel/l440gx/crt0.S index 1c249cfb64..4de7fdc5f4 100644 --- a/src/mainboard/intel/l440gx/crt0.S +++ b/src/mainboard/intel/l440gx/crt0.S @@ -26,7 +26,7 @@ #include -#include +#include #include diff --git a/src/mainboard/intel/l440gx/mainboard.c b/src/mainboard/intel/l440gx/mainboard.c index 63d63f08fb..3d5d8c98c4 100644 --- a/src/mainboard/intel/l440gx/mainboard.c +++ b/src/mainboard/intel/l440gx/mainboard.c @@ -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); diff --git a/src/northbridge/alpha/tsunami/Config b/src/northbridge/alpha/tsunami/Config new file mode 100644 index 0000000000..1facaaf1be --- /dev/null +++ b/src/northbridge/alpha/tsunami/Config @@ -0,0 +1,3 @@ +cpu ev6 +option USE_CPU_EV6=1 +option USE_CORE_TSUNAMI=1 diff --git a/src/northbridge/intel/440gx/Config b/src/northbridge/intel/440gx/Config new file mode 100644 index 0000000000..36065836d1 --- /dev/null +++ b/src/northbridge/intel/440gx/Config @@ -0,0 +1,4 @@ +raminit northbridge/intel/440gx/raminit.inc +raminit sdram/generic_sdram.inc + +object northbridge.o diff --git a/src/rom/Config b/src/rom/Config new file mode 100644 index 0000000000..7a2ab811f0 --- /dev/null +++ b/src/rom/Config @@ -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 diff --git a/src/rom/docmil_fill_inbuf.c b/src/rom/docmil_fill_inbuf.c new file mode 100644 index 0000000000..4a5a89037f --- /dev/null +++ b/src/rom/docmil_fill_inbuf.c @@ -0,0 +1,120 @@ +#ifdef USE_DOC_MIL + +#include +#include +#include +#include +#include +#include + +#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 */ diff --git a/src/rom/fill_inbuf.c b/src/rom/fill_inbuf.c new file mode 100644 index 0000000000..396ab0df90 --- /dev/null +++ b/src/rom/fill_inbuf.c @@ -0,0 +1,7 @@ +#include + +unsigned char *inbuf /* = 0 */; +unsigned int insize /* = 0 */; +unsigned int inptr /* = 0 */; + + diff --git a/src/rom/rom_fill_inbuf.c b/src/rom/rom_fill_inbuf.c new file mode 100644 index 0000000000..52590fb1f2 --- /dev/null +++ b/src/rom/rom_fill_inbuf.c @@ -0,0 +1,117 @@ +#ifdef USE_GENERIC_ROM + +#include +#include +#include +#include +#include + +#include + +#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 */ diff --git a/src/rom/tsunami_tigbus_rom_fill_inbuf.c b/src/rom/tsunami_tigbus_rom_fill_inbuf.c new file mode 100644 index 0000000000..8ac5af5e3a --- /dev/null +++ b/src/rom/tsunami_tigbus_rom_fill_inbuf.c @@ -0,0 +1,98 @@ +#ifdef USE_TSUNAMI_TIGBUS_ROM + +#include +#include +#include +#include +#include + +#include +#include + +#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 */ diff --git a/src/superio/NSC/pc87309/setup_serial.inc b/src/superio/NSC/pc87309/setup_serial.inc new file mode 100644 index 0000000000..c9ce936d86 --- /dev/null +++ b/src/superio/NSC/pc87309/setup_serial.inc @@ -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) +