home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ANews 2
/
AnewsCD2.iso
/
LinuxPPC
/
Amiga
/
linuxboot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-10-08
|
52KB
|
1,949 lines
/*
* 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
* Jesper Skov
*
*
* 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:
* 26 Feb 1998 Added support for booting APUS systems.
* 27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo
* interface version 1.0 (Geert)
* 03 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 <sys/types.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"
#define APUS
#ifdef APUS
#define INTUITION_CLASSES_H 1
#include <powerup/ppclib/interface.h>
/*#include <powerup/gcclib/powerup_protos.h>*/
#include <powerup/ppclib/message.h>
#include <powerup/ppclib/tasks.h>
#include <powerup/ppclib/object.h>
#include "ppcboot_elf.h"
#endif
#undef custom
#define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
/* temporary stack size */
#define TEMP_STACKSIZE (256)
#define DEFAULT_BAUD (9600)
extern char copyall, copyallend;
extern char getvbr, wedgie;
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 apus_boot linuxboot_args->apus_boot
#define checksum linuxboot_args->checksum
#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 mem_size, u_long rd_size,
u_long kernel_size) __attribute__ ((noreturn));
asmlinkage u_long probe_powerup(u_long);
asmlinkage u_long maprommed(void);
asmlinkage u_long check346(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_a2065(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_COMMODORE, PROD_A2065, "A2065", reset_a2065 },
{ 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;
unsigned long* info;
struct ConfigDev *zdevs[ZORRO_NUM_AUTO];
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,