patch-2.1.48 linux/arch/m68k/boot/amiga/linuxboot.c
Next file: linux/arch/m68k/boot/amiga/linuxboot.h
Previous file: linux/arch/m68k/boot/amiga/bootstrap.h
Back to the patch index
Back to the overall index
- Lines: 1693
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.1.47/linux/arch/m68k/boot/amiga/linuxboot.c
- Orig date:
Mon Jul 7 08:18:53 1997
diff -u --recursive --new-file v2.1.47/linux/arch/m68k/boot/amiga/linuxboot.c linux/arch/m68k/boot/amiga/linuxboot.c
@@ -1,1692 +0,0 @@
-/*
- * linux/arch/m68k/boot/amiga/linuxboot.c -- Generic routine to boot Linux/m68k
- * on Amiga, used by both Amiboot and
- * Amiga-Lilo.
- *
- * Created 1996 by Geert Uytterhoeven
- *
- *
- * This file is based on the original bootstrap code (bootstrap.c):
- *
- * Copyright (C) 1993, 1994 Hamish Macdonald
- * Greg Harp
- *
- * with work by Michael Rausch
- * Geert Uytterhoeven
- * Frank Neumann
- * Andreas Schwab
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- * History:
- * 11 Jun 1997 Fix for unpadded gzipped ramdisks with bootinfo interface
- * version 1.0
- * 27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo
- * interface version 1.0 (Geert)
- * 3 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
- * code for ataboot)
- * 30 Dec 1996 Reverted the CPU detection to the old scheme
- * New boot parameter override scheme (Geert)
- * 27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
- * 9 Sep 1996 Rewritten option parsing
- * New parameter passing to linuxboot() (linuxboot_args)
- * (Geert)
- * 18 Aug 1996 Updated for the new boot information structure (Geert)
- * 10 Jan 1996 The real Linux/m68k boot code moved to linuxboot.[ch]
- * (Geert)
- * 11 Jul 1995 Support for ELF kernel (untested!) (Andreas)
- * 7 Mar 1995 Memory block sizes are rounded to a multiple of 256K
- * instead of 1M (Geert)
- * 31 May 1994 Memory thrash problem solved (Geert)
- * 11 May 1994 A3640 MapROM check (Geert)
- */
-
-
-#ifndef __GNUC__
-#error GNU CC is required to compile this program
-#endif /* __GNUC__ */
-
-
-#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
-/* support compressed kernels? */
-#define ZKERNEL
-
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-
-#include <linux/a.out.h>
-#include <linux/elf.h>
-#include <linux/linkage.h>
-#include <asm/bootinfo.h>
-#include <asm/amigahw.h>
-#include <asm/page.h>
-
-#include "linuxboot.h"
-
-
-#undef custom
-#define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
-
-/* a.out linkage conventions */
-#undef SYMBOL_NAME_STR
-#define SYMBOL_NAME_STR(X) "_"#X
-
-/* temporary stack size */
-#define TEMP_STACKSIZE (256)
-
-#define DEFAULT_BAUD (9600)
-
-extern char copyall, copyallend;
-
-static struct exec kexec;
-static Elf32_Ehdr kexec_elf;
-static const struct linuxboot_args *linuxboot_args;
-
-/* Bootinfo */
-struct amiga_bootinfo bi;
-
-#ifdef BOOTINFO_COMPAT_1_0
-static struct compat_bootinfo compat_bootinfo;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
-#define MAX_BI_SIZE (4096)
-static u_long bi_size;
-static union {
- struct bi_record record;
- u_char fake[MAX_BI_SIZE];
-} bi_union;
-
-#define kernelname linuxboot_args->kernelname
-#define ramdiskname linuxboot_args->ramdiskname
-#define debugflag linuxboot_args->debugflag
-#define keep_video linuxboot_args->keep_video
-#define reset_boards linuxboot_args->reset_boards
-#define baud linuxboot_args->baud
-
-#define Puts linuxboot_args->puts
-#define GetChar linuxboot_args->getchar
-#define PutChar linuxboot_args->putchar
-#define Printf linuxboot_args->printf
-#define Open linuxboot_args->open
-#define Seek linuxboot_args->seek
-#define Read linuxboot_args->read
-#define Close linuxboot_args->close
-#define FileSize linuxboot_args->filesize
-#define Sleep linuxboot_args->sleep
-
- /*
- * Function Prototypes
- */
-
-static u_long get_chipset(void);
-static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu);
-static u_long get_model(u_long chipset);
-static int probe_resident(const char *name);
-static int probe_resource(const char *name);
-static int create_bootinfo(void);
-#ifdef BOOTINFO_COMPAT_1_0
-static int create_compat_bootinfo(void);
-#endif /* BOOTINFO_COMPAT_1_0 */
-static int add_bi_record(u_short tag, u_short size, const void *data);
-static int add_bi_string(u_short tag, const u_char *s);
-static int check_bootinfo_version(const char *memptr);
-static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
- u_long start_mem, u_long kernel_size, u_long rd_dest,
- u_long rd_size) __attribute__ ((noreturn));
-asmlinkage u_long maprommed(void);
-#ifdef ZKERNEL
-static int load_zkernel(int fd);
-static int KRead(int fd, void *buf, int cnt);
-static int KSeek(int fd, int offset);
-static int KClose(int fd);
-#else
-#define KRead Read
-#define KSeek Seek
-#define KClose Close
-#endif
-
-
- /*
- * Reset functions for nasty Zorro boards
- */
-
-static void reset_rb3(const struct ConfigDev *cd);
-static void reset_piccolo(const struct ConfigDev *cd);
-static void reset_sd64(const struct ConfigDev *cd);
-static void reset_ariadne(const struct ConfigDev *cd);
-static void reset_hydra(const struct ConfigDev *cd);
-#if 0
-static void reset_a2060(const struct ConfigDev *cd);
-#endif
-
-struct boardreset {
- u_short manuf;
- u_short prod;
- const char *name;
- void (*reset)(const struct ConfigDev *cd);
-};
-
-static struct boardreset boardresetdb[] = {
- { MANUF_HELFRICH1, PROD_RAINBOW3, "Rainbow 3", reset_rb3 },
- { MANUF_HELFRICH2, PROD_PICCOLO_REG, "Piccolo", reset_piccolo },
- { MANUF_HELFRICH2, PROD_SD64_REG, "SD64", reset_sd64 },
- { MANUF_VILLAGE_TRONIC, PROD_ARIADNE, "Ariadne", reset_ariadne },
- { MANUF_HYDRA_SYSTEMS, PROD_AMIGANET, "Hydra", reset_hydra },
-#if 0
- { MANUF_COMMODORE, PROD_A2060, "A2060", reset_a2060 },
-#endif
-};
-#define NUM_BOARDRESET sizeof(boardresetdb)/sizeof(*boardresetdb)
-
-static void (*boardresetfuncs[ZORRO_NUM_AUTO])(const struct ConfigDev *cd);
-
-
-const char *amiga_models[] = {
- "Amiga 500", "Amiga 500+", "Amiga 600", "Amiga 1000", "Amiga 1200",
- "Amiga 2000", "Amiga 2500", "Amiga 3000", "Amiga 3000T", "Amiga 3000+",
- "Amiga 4000", "Amiga 4000T", "CDTV", "CD32", "Draco"
-};
-const u_long first_amiga_model = AMI_500;
-const u_long last_amiga_model = AMI_DRACO;
-
-
-#define MASK(model) (1<<AMI_##model)
-
-#define CLASS_A3000 (MASK(3000) | MASK(3000T))
-#define CLASS_A4000 (MASK(4000) | MASK(4000T))
-#define CLASS_ZKICK (MASK(500) | MASK(1000) | MASK(2000) | MASK(2500))
-
-
- /*
- * Boot the Linux/m68k Operating System
- */
-
-u_long linuxboot(const struct linuxboot_args *args)
-{
- int kfd = -1, rfd = -1, elf_kernel = 0, do_fast, do_chip;
- int i, j;
- const struct MemHeader *mnp;
- struct ConfigDev *cdp = NULL;
- char *memptr = NULL;
- u_long *stack = NULL;
- u_long fast_total, model_mask, startcodesize, start_mem, mem_size, rd_size;
- u_long kernel_size;
- u_int realbaud;
- u_long memreq = 0, text_offset = 0;
- Elf32_Phdr *kernel_phdrs = NULL;
- void (*startfunc)(void);
- u_short manuf;
- u_char prod;
- void *bi_ptr;
-
- linuxboot_args = args;
-
- /* print the greet message */
- Puts("\nLinux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n");
- Puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n\n");
-
- /* Note: Initial values in bi override detected values */
- bi = args->bi;
-
- /* machine is Amiga */
- bi.machtype = MACH_AMIGA;
-
- /* determine chipset */
- if (!bi.chipset)
- bi.chipset = get_chipset();
-
- /* determine CPU, FPU and MMU type */
- if (!bi.cputype)
- get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
-
- /* determine Amiga model */
- if (!bi.model)
- bi.model = get_model(bi.chipset);
- model_mask = (bi.model != AMI_UNKNOWN) ? 1<<bi.model : 0;
-
- /* Memory & AutoConfig based on 'unix_boot.c' by C= */
-
- /* find all of the autoconfig boards in the system */
- if (!bi.num_autocon)
- for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1)); i++)
- if (bi.num_autocon < ZORRO_NUM_AUTO)
- /* copy the contents of each structure into our boot info and
- count this device */
- memcpy(&bi.autocon[bi.num_autocon++], cdp,
- sizeof(struct ConfigDev));
- else
- Printf("Warning: too many AutoConfig devices. Ignoring device at "
- "0x%08lx\n", cdp->cd_BoardAddr);
-
- do_fast = bi.num_memory ? 0 : 1;
- do_chip = bi.chip_size ? 0 : 1;
- /* find out the memory in the system */
- for (mnp = (struct MemHeader *)SysBase->MemList.lh_Head;
- mnp->mh_Node.ln_Succ;
- mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ) {
- struct MemHeader mh;
-
- /* copy the information */
- mh = *mnp;
-
- /* skip virtual memory */
- if (!(mh.mh_Attributes & MEMF_PUBLIC))
- continue;
-
- /* if we suspect that Kickstart is shadowed in an A3000,
- modify the entry to show 512K more at the top of RAM
- Check first for a MapROMmed A3640 board: overwriting the
- Kickstart image causes an infinite lock-up on reboot! */
- if ((mh.mh_Upper == (void *)0x07f80000) &&
- (model_mask & (CLASS_A3000 | CLASS_A4000)))
- if ((bi.cputype & CPU_68040) && Supervisor(maprommed))
- Puts("A3640 MapROM detected.\n");
- else if (model_mask & CLASS_A3000) {
- mh.mh_Upper = (void *)0x08000000;
- Puts("A3000 shadowed Kickstart detected.\n");
- }
-
- /* if we suspect that Kickstart is zkicked,
- modify the entry to show 512K more at the botton of RAM */
- if ((mh.mh_Lower == (void *)0x00280020) &&
- (model_mask & CLASS_ZKICK)) {
- mh.mh_Lower = (void *)0x00200000;
- Puts("ZKick detected.\n");
- }
-
- /* mask the memory limit values */
- mh.mh_Upper = (void *)((u_long)mh.mh_Upper & 0xfffff000);
- mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
-
- /* if fast memory */
- if (do_fast && mh.mh_Attributes & MEMF_FAST) {
- /* set the size value to the size of this block and mask off to a
- 256K increment */
- u_long size = ((u_long)mh.mh_Upper-(u_long)mh.mh_Lower)&0xfffc0000;
- if (size > 0)
- if (bi.num_memory < NUM_MEMINFO) {
- /* record the start and size */
- bi.memory[bi.num_memory].addr = (u_long)mh.mh_Lower;
- bi.memory[bi.num_memory].size = size;
- /* count this block */
- bi.num_memory++;
- } else
- Printf("Warning: too many memory blocks. Ignoring block "
- "of %ldK at 0x%08x\n", size>>10,
- (u_long)mh.mh_Lower);
- } else if (do_chip && mh.mh_Attributes & MEMF_CHIP)
- /* if CHIP memory, record the size */
- bi.chip_size = (u_long)mh.mh_Upper;
- }
-
- /* get info from ExecBase */
- if (!bi.vblank)
- bi.vblank = SysBase->VBlankFrequency;
- if (!bi.psfreq)
- bi.psfreq = SysBase->PowerSupplyFrequency;
- if (!bi.eclock)
- bi.eclock = SysBase->ex_EClockFrequency;
-
- /* serial port */
- if (!bi.serper) {
- realbaud = baud ? baud : DEFAULT_BAUD;
- bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
- }
-
- /* display Amiga model */
- if (bi.model >= first_amiga_model && bi.model <= last_amiga_model)
- Printf("%s ", amiga_models[bi.model-first_amiga_model]);
- else
- Puts("Amiga ");
-
- /* display the CPU type */
- Puts("CPU: ");
- switch (bi.cputype) {
- case CPU_68020:
- Puts("68020 (Do you have an MMU?)");
- break;
- case CPU_68030:
- Puts("68030");
- break;
- case CPU_68040:
- Puts("68040");
- break;
- case CPU_68060:
- Puts("68060");
- break;
- default:
- Puts("Insufficient for Linux. Aborting...\n");
- Printf("SysBase->AttnFlags = 0x%08lx\n", SysBase->AttnFlags);
- goto Fail;
- }
- switch (bi.fputype) {
- case FPU_68881:
- Puts(" with 68881 FPU");
- break;
- case FPU_68882:
- Puts(" with 68882 FPU");
- break;
- case FPU_68040:
- case FPU_68060:
- Puts(" with internal FPU");
- break;
- default:
- Puts(" without FPU");
- break;
- }
-
- /* display the chipset */
- switch (bi.chipset) {
- case CS_STONEAGE:
- Puts(", old or unknown chipset");
- break;
- case CS_OCS:
- Puts(", OCS");
- break;
- case CS_ECS:
- Puts(", ECS");
- break;
- case CS_AGA:
- Puts(", AGA chipset");
- break;
- }
-
- Puts("\n\n");
-
- /* display the command line */
- Printf("Command line is '%s'\n", bi.command_line);
-
- /* display the clock statistics */
- Printf("Vertical Blank Frequency: %ldHz\n", bi.vblank);
- Printf("Power Supply Frequency: %ldHz\n", bi.psfreq);
- Printf("EClock Frequency: %ldHz\n\n", bi.eclock);
-
- /* display autoconfig devices */
- if (bi.num_autocon) {
- Printf("Found %ld AutoConfig Device%s\n", bi.num_autocon,
- bi.num_autocon > 1 ? "s" : "");
- for (i = 0; i < bi.num_autocon; i++) {
- Printf("Device %ld: addr = 0x%08lx", i,
- (u_long)bi.autocon[i].cd_BoardAddr);
- boardresetfuncs[i] = NULL;
- if (reset_boards) {
- manuf = bi.autocon[i].cd_Rom.er_Manufacturer;
- prod = bi.autocon[i].cd_Rom.er_Product;
- for (j = 0; j < NUM_BOARDRESET; j++)
- if ((manuf == boardresetdb[j].manuf) &&
- (prod == boardresetdb[j].prod)) {
- Printf(" [%s - will be reset at kernel boot time]",
- boardresetdb[j].name);
- boardresetfuncs[i] = boardresetdb[j].reset;
- break;
- }
- }
- PutChar('\n');
- }
- } else
- Puts("No AutoConfig Devices Found\n");
-
- /* display memory */
- if (bi.num_memory) {
- Printf("\nFound %ld Block%sof Memory\n", bi.num_memory,
- bi.num_memory > 1 ? "s " : " ");
- for (i = 0; i < bi.num_memory; i++)
- Printf("Block %ld: 0x%08lx to 0x%08lx (%ldK)\n", i,
- bi.memory[i].addr, bi.memory[i].addr+bi.memory[i].size,
- bi.memory[i].size>>10);
- } else {
- Puts("No memory found?! Aborting...\n");
- goto Fail;
- }
-
- /* display chip memory size */
- Printf("%ldK of CHIP memory\n", bi.chip_size>>10);
-
- start_mem = bi.memory[0].addr;
- mem_size = bi.memory[0].size;
-
- /* tell us where the kernel will go */
- Printf("\nThe kernel will be located at 0x%08lx\n", start_mem);
-
- /* verify that there is enough Chip RAM */
- if (bi.chip_size < 512*1024) {
- Puts("Not enough Chip RAM in this system. Aborting...\n");
- goto Fail;
- }
-
- /* verify that there is enough Fast RAM */
- for (fast_total = 0, i = 0; i < bi.num_memory; i++)
- fast_total += bi.memory[i].size;
- if (fast_total < 2*1024*1024) {
- Puts("Not enough Fast RAM in this system. Aborting...\n");
- goto Fail;
- }
-
- /* support for ramdisk */
- if (ramdiskname) {
- int size;
-
- if ((size = FileSize(ramdiskname)) == -1) {
- Printf("Unable to find size of ramdisk file `%s'\n", ramdiskname);
- goto Fail;
- }
- /* record ramdisk size */
- bi.ramdisk.size = size;
- } else
- bi.ramdisk.size = 0;
- rd_size = bi.ramdisk.size;
- bi.ramdisk.addr = (u_long)start_mem+mem_size-rd_size;
-
- /* create the bootinfo structure */
- if (!create_bootinfo())
- goto Fail;
-
- /* open kernel executable and read exec header */
- if ((kfd = Open(kernelname)) == -1) {
- Printf("Unable to open kernel file `%s'\n", kernelname);
- goto Fail;
- }
- if (KRead(kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
- Puts("Unable to read exec header from kernel file\n");
- goto Fail;
- }
-
-#ifdef ZKERNEL
- if (((unsigned char *)&kexec)[0] == 037 &&
- (((unsigned char *)&kexec)[1] == 0213 ||
- ((unsigned char *)&kexec)[1] == 0236)) {
- /* That's a compressed kernel */
- Puts("Kernel is compressed\n");
- if (load_zkernel(kfd)) {
- Puts("Decompression error -- aborting\n");
- goto Fail;
- }
- }
-#endif
-
- switch (N_MAGIC(kexec)) {
- case ZMAGIC:
- if (debugflag)
- Puts("\nLoading a.out (ZMAGIC) Linux/m68k kernel...\n");
- text_offset = N_TXTOFF(kexec);
- break;
-
- case QMAGIC:
- if (debugflag)
- Puts("\nLoading a.out (QMAGIC) Linux/m68k kernel...\n");
- text_offset = sizeof(kexec);
- /* the text size includes the exec header; remove this */
- kexec.a_text -= sizeof(kexec);
- break;
-
- default:
- /* Try to parse it as an ELF header */
- KSeek(kfd, 0);
- if ((KRead(kfd, (void *)&kexec_elf, sizeof(kexec_elf)) ==
- sizeof(kexec_elf)) &&
- (memcmp(&kexec_elf.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0)) {
- elf_kernel = 1;
- if (debugflag)
- Puts("\nLoading ELF Linux/m68k kernel...\n");
- /* A few plausibility checks */
- if ((kexec_elf.e_type != ET_EXEC) ||
- (kexec_elf.e_machine != EM_68K) ||
- (kexec_elf.e_version != EV_CURRENT)) {
- Puts("Invalid ELF header contents in kernel\n");
- goto Fail;
- }
- /* Load the program headers */
- if (!(kernel_phdrs =
- (Elf32_Phdr *)AllocMem(kexec_elf.e_phnum*sizeof(Elf32_Phdr),
- MEMF_FAST | MEMF_PUBLIC |
- MEMF_CLEAR))) {
- Puts("Unable to allocate memory for program headers\n");
- goto Fail;
- }
- KSeek(kfd, kexec_elf.e_phoff);
- if (KRead(kfd, (void *)kernel_phdrs,
- kexec_elf.e_phnum*sizeof(*kernel_phdrs)) !=
- kexec_elf.e_phnum*sizeof(*kernel_phdrs)) {
- Puts("Unable to read program headers from kernel file\n");
- goto Fail;
- }
- break;
- }
- Printf("Wrong magic number 0x%08lx in kernel header\n",
- N_MAGIC(kexec));
- goto Fail;
- }
-
- /* Load the kernel at one page after start of mem */
- start_mem += PAGE_SIZE;
- mem_size -= PAGE_SIZE;
- /* Align bss size to multiple of four */
- if (!elf_kernel)
- kexec.a_bss = (kexec.a_bss+3) & ~3;
-
- /* calculate the total required amount of memory */
- if (elf_kernel) {
- u_long min_addr = 0xffffffff, max_addr = 0;
- for (i = 0; i < kexec_elf.e_phnum; i++) {
- if (min_addr > kernel_phdrs[i].p_vaddr)
- min_addr = kernel_phdrs[i].p_vaddr;
- if (max_addr < kernel_phdrs[i].p_vaddr+kernel_phdrs[i].p_memsz)
- max_addr = kernel_phdrs[i].p_vaddr+kernel_phdrs[i].p_memsz;
- }
- /* This is needed for newer linkers that include the header in
- the first segment. */
- if (min_addr == 0) {
- min_addr = PAGE_SIZE;
- kernel_phdrs[0].p_vaddr += PAGE_SIZE;
- kernel_phdrs[0].p_offset += PAGE_SIZE;
- kernel_phdrs[0].p_filesz -= PAGE_SIZE;
- kernel_phdrs[0].p_memsz -= PAGE_SIZE;
- }
- kernel_size = max_addr-min_addr;
- } else
- kernel_size = kexec.a_text+kexec.a_data+kexec.a_bss;
- memreq = kernel_size+bi_size+rd_size;
-#ifdef BOOTINFO_COMPAT_1_0
- if (sizeof(compat_bootinfo) > bi_size)
- memreq = kernel_size+sizeof(compat_bootinfo)+rd_size;
-#endif /* BOOTINFO_COMPAT_1_0 */
- if (!(memptr = (char *)AllocMem(memreq, MEMF_FAST | MEMF_PUBLIC |
- MEMF_CLEAR))) {
- Puts("Unable to allocate memory\n");
- goto Fail;
- }
-
- /* read the text and data segments from the kernel image */
- if (elf_kernel)
- for (i = 0; i < kexec_elf.e_phnum; i++) {
- if (KSeek(kfd, kernel_phdrs[i].p_offset) == -1) {
- Printf("Failed to seek to segment %ld\n", i);
- goto Fail;
- }
- if (KRead(kfd, memptr+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
- kernel_phdrs[i].p_filesz) != kernel_phdrs[i].p_filesz) {
- Printf("Failed to read segment %ld\n", i);
- goto Fail;
- }
- }
- else {
- if (KSeek(kfd, text_offset) == -1) {
- Puts("Failed to seek to text\n");
- goto Fail;
- }
- if (KRead(kfd, memptr, kexec.a_text) != kexec.a_text) {
- Puts("Failed to read text\n");
- goto Fail;
- }
- /* data follows immediately after text */
- if (KRead(kfd, memptr+kexec.a_text, kexec.a_data) != kexec.a_data) {
- Puts("Failed to read data\n");
- goto Fail;
- }
- }
- KClose(kfd);
- kfd = -1;
-
- /* Check kernel's bootinfo version */
- switch (check_bootinfo_version(memptr)) {
- case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
- bi_ptr = &bi_union.record;
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
- if (!create_compat_bootinfo())
- goto Fail;
- bi_ptr = &compat_bootinfo;
- bi_size = sizeof(compat_bootinfo);
- break;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
- default:
- goto Fail;
- }
-
- /* copy the bootinfo to the end of the kernel image */
- memcpy((void *)(memptr+kernel_size), bi_ptr, bi_size);
-
- if (ramdiskname) {
- if ((rfd = Open(ramdiskname)) == -1) {
- Printf("Unable to open ramdisk file `%s'\n", ramdiskname);
- goto Fail;
- }
- if (Read(rfd, memptr+kernel_size+bi_size, rd_size) != rd_size) {
- Puts("Failed to read ramdisk file\n");
- goto Fail;
- }
- Close(rfd);
- rfd = -1;
- }
-
- /* allocate temporary chip ram stack */
- if (!(stack = (u_long *)AllocMem(TEMP_STACKSIZE, MEMF_CHIP | MEMF_CLEAR))) {
- Puts("Unable to allocate memory for stack\n");
- goto Fail;
- }
-
- /* allocate chip ram for copy of startup code */
- startcodesize = ©allend-©all;
- if (!(startfunc = (void (*)(void))AllocMem(startcodesize,
- MEMF_CHIP | MEMF_CLEAR))) {
- Puts("Unable to allocate memory for startcode\n");
- goto Fail;
- }
-
- /* copy startup code to CHIP RAM */
- memcpy(startfunc, ©all, startcodesize);
-
- if (debugflag) {
- if (bi.ramdisk.size)
- Printf("RAM disk at 0x%08lx, size is %ldK\n",
- (u_long)memptr+kernel_size+bi_size, bi.ramdisk.size>>10);
-
- if (elf_kernel) {
- PutChar('\n');
- for (i = 0; i < kexec_elf.e_phnum; i++)
- Printf("Kernel segment %ld at 0x%08lx, size %ld\n", i,
- start_mem+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
- kernel_phdrs[i].p_memsz);
- Printf("Boot info at 0x%08lx\n", start_mem+kernel_size);
- } else {
- Printf("\nKernel text at 0x%08lx, code size 0x%08lx\n", start_mem,
- kexec.a_text);
- Printf("Kernel data at 0x%08lx, data size 0x%08lx\n",
- start_mem+kexec.a_text, kexec.a_data);
- Printf("Kernel bss at 0x%08lx, bss size 0x%08lx\n",
- start_mem+kexec.a_text+kexec.a_data, kexec.a_bss);
- Printf("Boot info at 0x%08lx\n", start_mem+kernel_size);
- }
- Printf("\nKernel entry is 0x%08lx\n", elf_kernel ? kexec_elf.e_entry :
- kexec.a_entry);
-
- Printf("ramdisk dest is 0x%08lx\n", bi.ramdisk.addr);
- Printf("ramdisk lower limit is 0x%08lx\n",
- (u_long)memptr+kernel_size+bi_size);
- Printf("ramdisk src top is 0x%08lx\n",
- (u_long)memptr+kernel_size+bi_size+rd_size);
-
- Puts("\nType a key to continue the Linux/m68k boot...");
- GetChar();
- PutChar('\n');
- }
-
- /* wait for things to settle down */
- Sleep(1000000);
-
- if (!keep_video)
- /* set graphics mode to a nice normal one */
- LoadView(NULL);
-
- Disable();
-
- /* reset nasty Zorro boards */
- if (reset_boards)
- for (i = 0; i < bi.num_autocon; i++)
- if (boardresetfuncs[i])
- boardresetfuncs[i](&bi.autocon[i]);
-
- /* Turn off all DMA */
- custom.dmacon = DMAF_ALL | DMAF_MASTER;
-
- /* turn off caches */
- CacheControl(0, ~0);
-
- /* Go into supervisor state */
- SuperState();
-
- /* turn off any mmu translation */
- disable_mmu();
-
- /* execute the copy-and-go code (from CHIP RAM) */
- start_kernel(startfunc, (char *)stack+TEMP_STACKSIZE, memptr, start_mem,
- kernel_size, bi.ramdisk.addr, rd_size);
-
- /* Clean up and exit in case of a failure */
-Fail:
- if (kfd != -1)
- KClose(kfd);
- if (rfd != -1)
- Close(rfd);
- if (memptr)
- FreeMem((void *)memptr, memreq);
- if (stack)
- FreeMem((void *)stack, TEMP_STACKSIZE);
- if (kernel_phdrs)
- FreeMem((void *)kernel_phdrs, kexec_elf.e_phnum*sizeof(Elf32_Phdr));
- return(FALSE);
-}
-
-
- /*
- * Determine the Chipset
- */
-
-static u_long get_chipset(void)
-{
- u_char cs;
- u_long chipset;
-
- if (GfxBase->Version >= 39)
- cs = SetChipRev(SETCHIPREV_BEST);
- else
- cs = GfxBase->ChipRevBits0;
- if ((cs & GFXG_AGA) == GFXG_AGA)
- chipset = CS_AGA;
- else if ((cs & GFXG_ECS) == GFXG_ECS)
- chipset = CS_ECS;
- else if ((cs & GFXG_OCS) == GFXG_OCS)
- chipset = CS_OCS;
- else
- chipset = CS_STONEAGE;
- return(chipset);
-}
-
-
- /*
- * Determine the CPU Type
- */
-
-static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu)
-{
- *cpu = *fpu = 0;
-
- if (SysBase->AttnFlags & AFF_68060)
- *cpu = CPU_68060;
- else if (SysBase->AttnFlags & AFF_68040)
- *cpu = CPU_68040;
- else if (SysBase->AttnFlags & AFF_68030)
- *cpu = CPU_68030;
- else if (SysBase->AttnFlags & AFF_68020)
- *cpu = CPU_68020;
-
- if (*cpu == CPU_68040 || *cpu == CPU_68060) {
- if (SysBase->AttnFlags & AFF_FPU40)
- *fpu = *cpu;
- } else if (SysBase->AttnFlags & AFF_68882)
- *fpu = FPU_68882;
- else if (SysBase->AttnFlags & AFF_68881)
- *fpu = FPU_68881;
-
- *mmu = *cpu;
-}
-
- /*
- * Determine the Amiga Model
- */
-
-static u_long get_model(u_long chipset)
-{
- u_long model = AMI_UNKNOWN;
-
- if (debugflag)
- Puts("Amiga model identification:\n");
- if (probe_resource("draco.resource"))
- model = AMI_DRACO;
- else {
- if (debugflag)
- Puts(" Chipset: ");
- switch (chipset) {
- case CS_STONEAGE:
- if (debugflag)
- Puts("Old or unknown\n");
- goto OCS;
- break;
-
- case CS_OCS:
- if (debugflag)
- Puts("OCS\n");
-OCS: if (probe_resident("cd.device"))
- model = AMI_CDTV;
- else
- /* let's call it an A2000 (may be A500, A1000, A2500) */
- model = AMI_2000;
- break;
-
- case CS_ECS:
- if (debugflag)
- Puts("ECS\n");
- if (probe_resident("Magic 36.7") ||
- probe_resident("kickad 36.57") ||
- probe_resident("A3000 Bonus") ||
- probe_resident("A3000 bonus"))
- /* let's call it an A3000 (may be A3000T) */
- model = AMI_3000;
- else if (probe_resource("card.resource"))
- model = AMI_600;
- else
- /* let's call it an A2000 (may be A500[+], A1000, A2500) */
- model = AMI_2000;
- break;
-
- case CS_AGA:
- if (debugflag)
- Puts("AGA\n");
- if (probe_resident("A1000 Bonus") ||
- probe_resident("A4000 bonus"))
- model = probe_resident("NCR scsi.device") ? AMI_4000T :
- AMI_4000;
- else if (probe_resource("card.resource"))
- model = AMI_1200;
- else if (probe_resident("cd.device"))
- model = AMI_CD32;
- else
- model = AMI_3000PLUS;
- break;
- }
- }
- if (debugflag) {
- Puts("\nType a key to continue...");
- GetChar();
- Puts("\n\n");
- }
- return(model);
-}
-
-
- /*
- * Probe for a Resident Modules
- */
-
-static int probe_resident(const char *name)
-{
- const struct Resident *res;
-
- if (debugflag)
- Printf(" Module `%s': ", name);
- res = FindResident(name);
- if (debugflag)
- if (res)
- Printf("0x%08lx\n", res);
- else
- Puts("not present\n");
- return(res ? TRUE : FALSE);
-}
-
-
- /*
- * Probe for an available Resource
- */
-
-static int probe_resource(const char *name)
-{
- const void *res;
-
- if (debugflag)
- Printf(" Resource `%s': ", name);
- res = OpenResource(name);
- if (debugflag)
- if (res)
- Printf("0x%08lx\n", res);
- else
- Puts("not present\n");
- return(res ? TRUE : FALSE);
-}
-
-
- /*
- * Create the Bootinfo structure
- */
-
-static int create_bootinfo(void)
-{
- int i;
- struct bi_record *record;
-
- /* Initialization */
- bi_size = 0;
-
- /* Generic tags */
- if (!add_bi_record(BI_MACHTYPE, sizeof(bi.machtype), &bi.machtype))
- return(0);
- if (!add_bi_record(BI_CPUTYPE, sizeof(bi.cputype), &bi.cputype))
- return(0);
- if (!add_bi_record(BI_FPUTYPE, sizeof(bi.fputype), &bi.fputype))
- return(0);
- if (!add_bi_record(BI_MMUTYPE, sizeof(bi.mmutype), &bi.mmutype))
- return(0);
- for (i = 0; i < bi.num_memory; i++)
- if (!add_bi_record(BI_MEMCHUNK, sizeof(bi.memory[i]), &bi.memory[i]))
- return(0);
- if (bi.ramdisk.size)
- if (!add_bi_record(BI_RAMDISK, sizeof(bi.ramdisk), &bi.ramdisk))
- return(0);
- if (!add_bi_string(BI_COMMAND_LINE, bi.command_line))
- return(0);
-
- /* Amiga tags */
- if (!add_bi_record(BI_AMIGA_MODEL, sizeof(bi.model), &bi.model))
- return(0);
- for (i = 0; i < bi.num_autocon; i++)
- if (!add_bi_record(BI_AMIGA_AUTOCON, sizeof(bi.autocon[i]),
- &bi.autocon[i]))
- return(0);
- if (!add_bi_record(BI_AMIGA_CHIP_SIZE, sizeof(bi.chip_size), &bi.chip_size))
- return(0);
- if (!add_bi_record(BI_AMIGA_VBLANK, sizeof(bi.vblank), &bi.vblank))
- return(0);
- if (!add_bi_record(BI_AMIGA_PSFREQ, sizeof(bi.psfreq), &bi.psfreq))
- return(0);
- if (!add_bi_record(BI_AMIGA_ECLOCK, sizeof(bi.eclock), &bi.eclock))
- return(0);
- if (!add_bi_record(BI_AMIGA_CHIPSET, sizeof(bi.chipset), &bi.chipset))
- return(0);
- if (!add_bi_record(BI_AMIGA_SERPER, sizeof(bi.serper), &bi.serper))
- return(0);
-
- /* Trailer */
- record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
- record->tag = BI_LAST;
- bi_size += sizeof(bi_union.record.tag);
-
- return(1);
-}
-
-
- /*
- * Add a Record to the Bootinfo Structure
- */
-
-static int add_bi_record(u_short tag, u_short size, const void *data)
-{
- struct bi_record *record;
- u_int size2;
-
- size2 = (sizeof(struct bi_record)+size+3)&-4;
- if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
- Puts("Can't add bootinfo record. Ask a wizard to enlarge me.\n");
- return(0);
- }
- record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
- record->tag = tag;
- record->size = size2;
- memcpy(record->data, data, size);
- bi_size += size2;
- return(1);
-}
-
-
- /*
- * Add a String Record to the Bootinfo Structure
- */
-
-static int add_bi_string(u_short tag, const u_char *s)
-{
- return(add_bi_record(tag, strlen(s)+1, (void *)s));
-}
-
-
-#ifdef BOOTINFO_COMPAT_1_0
-
- /*
- * Create the Bootinfo structure for backwards compatibility mode
- */
-
-static int create_compat_bootinfo(void)
-{
- u_int i;
-
- compat_bootinfo.machtype = bi.machtype;
- if (bi.cputype & CPU_68020)
- compat_bootinfo.cputype = COMPAT_CPU_68020;
- else if (bi.cputype & CPU_68030)
- compat_bootinfo.cputype = COMPAT_CPU_68030;
- else if (bi.cputype & CPU_68040)
- compat_bootinfo.cputype = COMPAT_CPU_68040;
- else if (bi.cputype & CPU_68060)
- compat_bootinfo.cputype = COMPAT_CPU_68060;
- else {
- Printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
- return(0);
- }
- if (bi.fputype & FPU_68881)
- compat_bootinfo.cputype |= COMPAT_FPU_68881;
- else if (bi.fputype & FPU_68882)
- compat_bootinfo.cputype |= COMPAT_FPU_68882;
- else if (bi.fputype & FPU_68040)
- compat_bootinfo.cputype |= COMPAT_FPU_68040;
- else if (bi.fputype & FPU_68060)
- compat_bootinfo.cputype |= COMPAT_FPU_68060;
- else if (bi.fputype) {
- Printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
- return(0);
- }
- compat_bootinfo.num_memory = bi.num_memory;
- if (compat_bootinfo.num_memory > COMPAT_NUM_MEMINFO) {
- Printf("Warning: using only %ld blocks of memory\n",
- COMPAT_NUM_MEMINFO);
- compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
- }
- for (i = 0; i < compat_bootinfo.num_memory; i++) {
- compat_bootinfo.memory[i].addr = bi.memory[i].addr;
- compat_bootinfo.memory[i].size = bi.memory[i].size;
- }
- if (bi.ramdisk.size) {
- bi.ramdisk.addr &= 0xfffffc00;
- compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
- compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
- } else {
- compat_bootinfo.ramdisk_size = 0;
- compat_bootinfo.ramdisk_addr = 0;
- }
- strncpy(compat_bootinfo.command_line, bi.command_line, COMPAT_CL_SIZE);
- compat_bootinfo.command_line[COMPAT_CL_SIZE-1] = '\0';
-
- compat_bootinfo.bi_amiga.model = bi.model;
- compat_bootinfo.bi_amiga.num_autocon = bi.num_autocon;
- if (compat_bootinfo.bi_amiga.num_autocon > COMPAT_NUM_AUTO) {
- Printf("Warning: using only %ld AutoConfig devices\n",
- COMPAT_NUM_AUTO);
- compat_bootinfo.bi_amiga.num_autocon = COMPAT_NUM_AUTO;
- }
- for (i = 0; i < compat_bootinfo.bi_amiga.num_autocon; i++)
- compat_bootinfo.bi_amiga.autocon[i] = bi.autocon[i];
- compat_bootinfo.bi_amiga.chip_size = bi.chip_size;
- compat_bootinfo.bi_amiga.vblank = bi.vblank;
- compat_bootinfo.bi_amiga.psfreq = bi.psfreq;
- compat_bootinfo.bi_amiga.eclock = bi.eclock;
- compat_bootinfo.bi_amiga.chipset = bi.chipset;
- compat_bootinfo.bi_amiga.hw_present = 0;
- return(1);
-}
-#endif /* BOOTINFO_COMPAT_1_0 */
-
-
- /*
- * Compare the Bootstrap and Kernel Versions
- */
-
-static int check_bootinfo_version(const char *memptr)
-{
- const struct bootversion *bv = (struct bootversion *)memptr;
- unsigned long version = 0;
- int i, kernel_major, kernel_minor, boots_major, boots_minor;
-
- if (bv->magic == BOOTINFOV_MAGIC)
- for (i = 0; bv->machversions[i].machtype != 0; ++i)
- if (bv->machversions[i].machtype == MACH_AMIGA) {
- version = bv->machversions[i].version;
- break;
- }
- if (!version)
- Puts("Kernel has no bootinfo version info, assuming 0.0\n");
-
- kernel_major = BI_VERSION_MAJOR(version);
- kernel_minor = BI_VERSION_MINOR(version);
- boots_major = BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION);
- boots_minor = BI_VERSION_MINOR(AMIGA_BOOTI_VERSION);
- Printf("Bootstrap's bootinfo version: %ld.%ld\n", boots_major,
- boots_minor);
- Printf("Kernel's bootinfo version : %ld.%ld\n", kernel_major,
- kernel_minor);
-
- switch (kernel_major) {
- case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
- if (kernel_minor > boots_minor) {
- Puts("Warning: Bootinfo version of bootstrap and kernel "
- "differ!\n");
- Puts(" Certain features may not work.\n");
- }
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
- Puts("(using backwards compatibility mode)\n");
- break;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
- default:
- Printf("\nThis bootstrap is too %s for this kernel!\n",
- boots_major < kernel_major ? "old" : "new");
- return(0);
- }
- return(kernel_major);
-}
-
-
- /*
- * Call the copy-and-go-code
- */
-
-static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
- u_long start_mem, u_long kernel_size, u_long rd_dest,
- u_long rd_size)
-{
- register void (*a0)() __asm("a0") = startfunc;
- register char *a2 __asm("a2") = stackp;
- register char *a3 __asm("a3") = memptr;
- register u_long a4 __asm("a4") = start_mem;
- register u_long d0 __asm("d0") = rd_dest;
- register u_long d1 __asm("d1") = rd_size;
- register u_long d2 __asm("d2") = kernel_size;
- register u_long d3 __asm("d3") = bi_size;
-
- __asm __volatile ("movel a2,sp;"
- "jmp a0@"
- : /* no outputs */
- : "r" (a0), "r" (a2), "r" (a3), "r" (a4), "r" (d0),
- "r" (d1), "r" (d2), "r" (d3)
- /* no return */);
- /* fake a noreturn */
- for (;;);
-}
-
-
- /*
- * This assembler code is copied to chip ram, and then executed.
- * It copies the kernel to it's final resting place.
- *
- * It is called with:
- *
- * a3 = memptr
- * a4 = start_mem
- * d0 = rd_dest
- * d1 = rd_size
- * d2 = kernel_size
- * d3 = bi_size
- */
-
-asm(".text\n"
-ALIGN_STR "\n"
-SYMBOL_NAME_STR(copyall) ":
- | /* copy kernel text and data */
- movel a3,a0 | src = (u_long *)memptr;
- movel a0,a2 | limit = (u_long *)(memptr+kernel_size);
- addl d2,a2
- movel a4,a1 | dest = (u_long *)start_mem;
-1: cmpl a0,a2
- jeq 2f | while (src < limit)
- moveb a0@+,a1@+ | *dest++ = *src++;
- jra 1b
-2:
- | /* copy bootinfo to end of bss */
- movel a3,a0 | src = (u_long *)(memptr+kernel_size);
- addl d2,a0 | dest = end of bss (already in a1)
- movel d3,d7 | count = bi_size
- subql #1,d7
-1: moveb a0@+,a1@+ | while (--count > -1)
- dbra d7,1b | *dest++ = *src++
-
- | /* copy the ramdisk to the top of memory */
- movel a3,a0 | src = (u_long *)(memptr+kernel_size+bi_size);
- addl d2,a0
- addl d3,a0
- movel d0,a1 | dest = (u_long *)rd_dest;
- movel a0,a2 | limit = (u_long *)(memptr+kernel_size+
- addl d1,a2 | bi_size+rd_size);
-1: cmpl a0,a2
- jeq 2f | while (src > limit)
- moveb a0@+,a1@+ | *dest++ = *src++;
- jra 1b
-2:
- | /* jump to start of kernel */
- movel a4,a0 | jump_to (start_mem);
- jmp a0@
-"
-SYMBOL_NAME_STR(copyallend) ":
-");
-
-
- /*
- * Test for a MapROMmed A3640 Board
- */
-
-asm(".text\n"
-ALIGN_STR "\n"
-SYMBOL_NAME_STR(maprommed) ":
- oriw #0x0700,sr
- moveml #0x3f20,sp@-
- | /* Save cache settings */
- .long 0x4e7a1002 | movec cacr,d1 */
- | /* Save MMU settings */
- .long 0x4e7a2003 | movec tc,d2
- .long 0x4e7a3004 | movec itt0,d3
- .long 0x4e7a4005 | movec itt1,d4
- .long 0x4e7a5006 | movec dtt0,d5
- .long 0x4e7a6007 | movec dtt1,d6
- moveq #0,d0
- movel d0,a2
- | /* Disable caches */
- .long 0x4e7b0002 | movec d0,cacr
- | /* Disable MMU */
- .long 0x4e7b0003 | movec d0,tc
- .long 0x4e7b0004 | movec d0,itt0
- .long 0x4e7b0005 | movec d0,itt1
- .long 0x4e7b0006 | movec d0,dtt0
- .long 0x4e7b0007 | movec d0,dtt1
- lea 0x07f80000,a0
- lea 0x00f80000,a1
- movel a0@,d7
- cmpl a1@,d7
- jne 1f
- movel d7,d0
- notl d0
- movel d0,a0@
- nop | /* Thanks to Jörg Mayer! */
- cmpl a1@,d0
- jne 1f
- moveq #-1,d0 | /* MapROMmed A3640 present */
- movel d0,a2
-1: movel d7,a0@
- | /* Restore MMU settings */
- .long 0x4e7b2003 | movec d2,tc
- .long 0x4e7b3004 | movec d3,itt0
- .long 0x4e7b4005 | movec d4,itt1
- .long 0x4e7b5006 | movec d5,dtt0
- .long 0x4e7b6007 | movec d6,dtt1
- | /* Restore cache settings */
- .long 0x4e7b1002 | movec d1,cacr
- movel a2,d0
- moveml sp@+,#0x04fc
- rte
-");
-
-
- /*
- * Reset functions for nasty Zorro boards
- */
-
-static void reset_rb3(const struct ConfigDev *cd)
-{
- volatile u_char *rb3_reg = (u_char *)(cd->cd_BoardAddr+0x01002000);
-
- /* FN: If a Rainbow III board is present, reset it to disable */
- /* its (possibly activated) vertical blank interrupts as the */
- /* kernel is not yet prepared to handle them (level 6). */
-
- /* set RESET bit in special function register */
- *rb3_reg = 0x01;
- /* actually, only a few cycles delay are required... */
- Sleep(1000000);
- /* clear reset bit */
- *rb3_reg = 0x00;
-}
-
-static void reset_piccolo(const struct ConfigDev *cd)
-{
- volatile u_char *piccolo_reg = (u_char *)(cd->cd_BoardAddr+0x8000);
-
- /* FN: the same stuff as above, for the Piccolo board. */
- /* this also has the side effect of resetting the board's */
- /* output selection logic to use the Amiga's display in single */
- /* monitor systems - which is currently what we want. */
-
- /* set RESET bit in special function register */
- *piccolo_reg = 0x01;
- /* actually, only a few cycles delay are required... */
- Sleep(1000000);
- /* clear reset bit */
- *piccolo_reg = 0x51;
-}
-
-static void reset_sd64(const struct ConfigDev *cd)
-{
- volatile u_char *sd64_reg = (u_char *)(cd->cd_BoardAddr+0x8000);
-
- /* FN: the same stuff as above, for the SD64 board. */
- /* just as on the Piccolo, this also resets the monitor switch */
-
- /* set RESET bit in special function register */
- *sd64_reg = 0x1f;
- /* actually, only a few cycles delay are required... */
- Sleep(1000000);
- /* clear reset bit AND switch monitor bit (0x20) */
- *sd64_reg = 0x4f;
-}
-
-static void reset_ariadne(const struct ConfigDev *cd)
-{
- volatile u_short *lance_rdp = (u_short *)(cd->cd_BoardAddr+0x0370);
- volatile u_short *lance_rap = (u_short *)(cd->cd_BoardAddr+0x0372);
- volatile u_short *lance_reset = (u_short *)(cd->cd_BoardAddr+0x0374);
-
- volatile u_char *pit_paddr = (u_char *)(cd->cd_BoardAddr+0x1004);
- volatile u_char *pit_pbddr = (u_char *)(cd->cd_BoardAddr+0x1006);
- volatile u_char *pit_pacr = (u_char *)(cd->cd_BoardAddr+0x100b);
- volatile u_char *pit_pbcr = (u_char *)(cd->cd_BoardAddr+0x100e);
- volatile u_char *pit_psr = (u_char *)(cd->cd_BoardAddr+0x101a);
-
- u_short in;
-
- Disable();
-
- /*
- * Reset the Ethernet part (Am79C960 PCnet-ISA)
- */
-
- in = *lance_reset; /* Reset Chip on Read Access */
- *lance_rap = 0x0000; /* PCnet-ISA Controller Status (CSR0) */
- *lance_rdp = 0x0400; /* STOP */
-
- /*
- * Reset the Parallel part (MC68230 PI/T)
- */
-
- *pit_pacr &= 0xfd; /* Port A Control Register */
- *pit_pbcr &= 0xfd; /* Port B Control Register */
- *pit_psr = 0x05; /* Port Status Register */
- *pit_paddr = 0x00; /* Port A Data Direction Register */
- *pit_pbddr = 0x00; /* Port B Data Direction Register */
-
- Enable();
-}
-
-static void reset_hydra(const struct ConfigDev *cd)
-{
- volatile u_char *nic_cr = (u_char *)(cd->cd_BoardAddr+0xffe1);
- volatile u_char *nic_isr = (u_char *)(cd->cd_BoardAddr+0xffe1 + 14);
- int n = 5000;
-
- Disable();
-
- *nic_cr = 0x21; /* nic command register: software reset etc. */
- while (((*nic_isr & 0x80) == 0) && --n) /* wait for reset to complete */
- ;
-
- Enable();
-}
-
-#if 0
-static void reset_a2060(const struct ConfigDev *cd)
-{
-#error reset_a2060: not yet implemented
-}
-#endif
-
-
-#ifdef ZKERNEL
-
-#define ZFILE_CHUNK_BITS 16 /* chunk is 64 KB */
-#define ZFILE_CHUNK_SIZE (1 << ZFILE_CHUNK_BITS)
-#define ZFILE_CHUNK_MASK (ZFILE_CHUNK_SIZE-1)
-#define ZFILE_N_CHUNKS (2*1024*1024/ZFILE_CHUNK_SIZE)
-
-/* variables for storing the uncompressed data */
-static char *ZFile[ZFILE_N_CHUNKS];
-static int ZFileSize = 0;
-static int ZFpos = 0;
-static int Zwpos = 0;
-
-static int Zinfd = 0; /* fd of compressed file */
-
-/*
- * gzip declarations
- */
-
-#define OF(args) args
-
-#define memzero(s, n) memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define INBUFSIZ 4096
-#define WSIZE 0x8000 /* window size--must be a power of two, and */
- /* at least 32K for zip's deflate method */
-
-static uch *inbuf;
-static uch *window;
-
-static unsigned insize = 0; /* valid bytes in inbuf */
-static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0; /* bytes in output buffer */
-static int exit_code = 0;
-static long bytes_out = 0;
-
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions (stubbed out) */
-#define Assert(cond,msg)
-#define Trace(x)
-#define Tracev(x)
-#define Tracevv(x)
-#define Tracec(c,x)
-#define Tracecv(c,x)
-
-#define STATIC static
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
-
-#define malloc(x) AllocVec(x, MEMF_FAST | MEMF_PUBLIC)
-#define free(x) FreeVec(x)
-
-#ifdef LILO
-#include "inflate.c"
-#else
-#include "../../../../lib/inflate.c"
-#endif
-
-static void gzip_mark(void **ptr)
-{
-}
-
-static void gzip_release(void **ptr)
-{
-}
-
-
-/*
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
- if (exit_code)
- return -1;
-
- insize = Read(Zinfd, inbuf, INBUFSIZ);
- if (insize <= 0)
- return -1;
-
- inptr = 1;
- return(inbuf[0]);
-}
-
-/*
- * 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, ch;
- int chunk = Zwpos >> ZFILE_CHUNK_BITS;
-
- if (exit_code)
- return;
-
- if (chunk >= ZFILE_N_CHUNKS) {
- error("Compressed image too large! Aborting.\n");
- return;
- }
- if (!ZFile[chunk]) {
- if (!(ZFile[chunk] = (char *)AllocMem(ZFILE_CHUNK_SIZE,
- MEMF_FAST | MEMF_PUBLIC))) {
- error("Out of memory for decompresing kernel image\n");
- return;
- }
- }
- memcpy(ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt);
- Zwpos += outcnt;
-
-#define DISPLAY_BITS 10
- if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0)
- PutChar('.');
-
- in = window;
- for (n = 0; n < outcnt; n++) {
- ch = *in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- outcnt = 0;
-}
-
-static void error(char *x)
-{
- Printf("\n%s", x);
- exit_code = 1;
-}
-
-static inline int call_sub(int (*func)(void), void *stackp)
-{
- register int _res __asm("d0");
- register int (*a0)(void) __asm("a0") = func;
- register int (*a1)(void) __asm("a1") = stackp;
-
- __asm __volatile ("movel sp,a2;"
- "movel a1,sp;"
- "jsr a0@;"
- "movel a2,sp"
- : "=r" (_res)
- : "r" (a0), "r" (a1)
- : "a0", "a1", "a2", "d0", "d1", "memory");
- return(_res);
-}
-
-static int load_zkernel(int fd)
-{
- int i, err = -1;
-#define ZSTACKSIZE (16384)
- u_long *zstack;
-
- for (i = 0; i < ZFILE_N_CHUNKS; ++i)
- ZFile[i] = NULL;
- Zinfd = fd;
- Seek(fd, 0);
-
- if (!(inbuf = (uch *)AllocMem(INBUFSIZ, MEMF_FAST | MEMF_PUBLIC)))
- Puts("Couldn't allocate gunzip buffer\n");
- else {
- if (!(window = (uch *)AllocMem(WSIZE, MEMF_FAST | MEMF_PUBLIC)))
- Puts("Couldn't allocate gunzip window\n");
- else {
- if (!(zstack = (u_long *)AllocMem(ZSTACKSIZE,
- MEMF_FAST | MEMF_PUBLIC)))
- Puts("Couldn't allocate gunzip stack\n");
- else {
- Puts("Uncompressing kernel image ");
- makecrc();
- if (!(err = call_sub(gunzip, (char *)zstack+ZSTACKSIZE)))
- Puts("done\n");
- ZFileSize = Zwpos;
- FreeMem(zstack, ZSTACKSIZE);
- }
- FreeMem(window, WSIZE);
- window = NULL;
- }
- FreeMem(inbuf, INBUFSIZ);
- inbuf = NULL;
- }
- Close(Zinfd); /* input file not needed anymore */
- return(err);
-}
-
-
-/* Note about the read/lseek wrapper and its memory management: It assumes
- * that all seeks are only forward, and thus data already read or skipped can
- * be freed. This is true for current organization of bootstrap and kernels.
- * Little exception: The struct kexec at the start of the file. After reading
- * it, there may be a seek back to the end of the file. But this currently
- * doesn't hurt. (Roman)
- */
-
-static int KRead(int fd, void *buf, int cnt)
-{
- unsigned done = 0;
-
- if (!ZFileSize)
- return(Read(fd, buf, cnt));
-
- if (ZFpos + cnt > ZFileSize)
- cnt = ZFileSize - ZFpos;
-
- while (cnt > 0) {
- unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
- unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
- unsigned n = cnt;
-
- if (ZFpos + n > endchunk)
- n = endchunk - ZFpos;
- memcpy(buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n);
- cnt -= n;
- buf += n;
- done += n;
- ZFpos += n;
-
- if (ZFpos == endchunk) {
- FreeMem(ZFile[chunk], ZFILE_CHUNK_SIZE);
- ZFile[chunk] = NULL;
- }
- }
-
- return(done);
-}
-
-
-static int KSeek(int fd, int offset)
-{
- unsigned oldpos, oldchunk, newchunk;
-
- if (!ZFileSize)
- return(Seek(fd, offset));
-
- oldpos = ZFpos;
- ZFpos = offset;
- if (ZFpos < 0) {
- ZFpos = 0;
- return(-1);
- } else if (ZFpos > ZFileSize) {
- ZFpos = ZFileSize;
- return(-1);
- }
-
- /* free memory of skipped-over data */
- oldchunk = oldpos >> ZFILE_CHUNK_BITS;
- newchunk = ZFpos >> ZFILE_CHUNK_BITS;
- while(oldchunk < newchunk) {
- if (ZFile[oldchunk]) {
- FreeMem(ZFile[oldchunk], ZFILE_CHUNK_SIZE);
- ZFile[oldchunk] = NULL;
- }
- ++oldchunk;
- }
- return(ZFpos);
-}
-
-
-static void free_zfile(void)
-{
- int i;
-
- for (i = 0; i < ZFILE_N_CHUNKS; ++i)
- if (ZFile[i]) {
- FreeMem(ZFile[i], ZFILE_CHUNK_SIZE);
- ZFile[i] = NULL;
- }
-}
-
-static int KClose(int fd)
-{
- if (ZFileSize) {
- free_zfile();
- ZFileSize = 0;
- } else
- Close(fd);
- return(0);
-}
-#endif /* ZKERNEL */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov