home *** CD-ROM | disk | FTP | other *** search
/ ANews 2 / AnewsCD2.iso / LinuxPPC / Amiga / linuxboot.c < prev    next >
C/C++ Source or Header  |  1999-10-08  |  52KB  |  1,949 lines

  1. /*
  2.  *  linux/arch/m68k/boot/amiga/linuxboot.c -- Generic routine to boot Linux/m68k
  3.  *                          on Amiga, used by both Amiboot and
  4.  *                          Amiga-Lilo.
  5.  *
  6.  *    Created 1996 by Geert Uytterhoeven
  7.  *
  8.  *
  9.  *  This file is based on the original bootstrap code (bootstrap.c):
  10.  *
  11.  *    Copyright (C) 1993, 1994 Hamish Macdonald
  12.  *                 Greg Harp
  13.  *
  14.  *            with work by Michael Rausch
  15.  *                 Geert Uytterhoeven
  16.  *                 Frank Neumann
  17.  *                 Andreas Schwab
  18.  *                 Jesper Skov
  19.  *
  20.  *
  21.  *  This file is subject to the terms and conditions of the GNU General Public
  22.  *  License.  See the file COPYING in the main directory of this archive
  23.  *  for more details.
  24.  *
  25.  *  History:
  26.  *    26 Feb 1998 Added support for booting APUS systems.
  27.  *    27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo
  28.  *            interface version 1.0 (Geert)
  29.  *    03 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
  30.  *            code for ataboot)
  31.  *    30 Dec 1996 Reverted the CPU detection to the old scheme
  32.  *            New boot parameter override scheme (Geert)
  33.  *      27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
  34.  *       9 Sep 1996 Rewritten option parsing
  35.  *            New parameter passing to linuxboot() (linuxboot_args)
  36.  *            (Geert)
  37.  *    18 Aug 1996 Updated for the new boot information structure (Geert)
  38.  *    10 Jan 1996 The real Linux/m68k boot code moved to linuxboot.[ch]
  39.  *            (Geert)
  40.  *    11 Jul 1995 Support for ELF kernel (untested!) (Andreas)
  41.  *     7 Mar 1995 Memory block sizes are rounded to a multiple of 256K
  42.  *            instead of 1M (Geert)
  43.  *    31 May 1994 Memory thrash problem solved (Geert)
  44.  *    11 May 1994 A3640 MapROM check (Geert)
  45.  */
  46.  
  47.  
  48. #ifndef __GNUC__
  49. #error GNU CC is required to compile this program
  50. #endif /* __GNUC__ */
  51.  
  52.  
  53. #define BOOTINFO_COMPAT_1_0    /* bootinfo interface version 1.0 compatible */
  54. /* support compressed kernels? */
  55. #define ZKERNEL
  56.  
  57. #include <stddef.h>
  58. #include <string.h>
  59. #include <errno.h>
  60. #include <sys/types.h>
  61.  
  62. #include <linux/a.out.h>
  63. #include <linux/elf.h>
  64. #include <linux/linkage.h>
  65. #include <asm/bootinfo.h>
  66. #include <asm/amigahw.h>
  67. #include <asm/page.h>
  68.  
  69. #include "linuxboot.h"
  70.  
  71. #define APUS
  72. #ifdef APUS
  73.  
  74. #define INTUITION_CLASSES_H 1
  75.  
  76. #include <powerup/ppclib/interface.h>
  77. /*#include <powerup/gcclib/powerup_protos.h>*/
  78. #include <powerup/ppclib/message.h>
  79. #include <powerup/ppclib/tasks.h>
  80. #include <powerup/ppclib/object.h>
  81. #include "ppcboot_elf.h"
  82.  
  83. #endif
  84.  
  85. #undef custom
  86. #define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
  87.  
  88. /* temporary stack size */
  89. #define TEMP_STACKSIZE    (256)
  90.  
  91. #define DEFAULT_BAUD    (9600)
  92.  
  93. extern char copyall, copyallend;
  94.  
  95. extern char getvbr, wedgie;
  96.  
  97. static struct exec kexec;
  98. static Elf32_Ehdr kexec_elf;
  99. static const struct linuxboot_args *linuxboot_args;
  100.  
  101. /* Bootinfo */
  102. struct amiga_bootinfo bi;
  103.  
  104. #ifdef BOOTINFO_COMPAT_1_0
  105. static struct compat_bootinfo compat_bootinfo;
  106. #endif /* BOOTINFO_COMPAT_1_0 */
  107.  
  108. #define MAX_BI_SIZE    (4096)
  109. static u_long bi_size;
  110. static union {
  111.     struct bi_record record;
  112.     u_char fake[MAX_BI_SIZE];
  113. } bi_union;
  114.  
  115. #define kernelname    linuxboot_args->kernelname
  116. #define ramdiskname    linuxboot_args->ramdiskname
  117. #define debugflag    linuxboot_args->debugflag
  118. #define keep_video    linuxboot_args->keep_video
  119. #define reset_boards    linuxboot_args->reset_boards
  120. #define baud        linuxboot_args->baud
  121.  
  122. #define apus_boot    linuxboot_args->apus_boot
  123. #define checksum    linuxboot_args->checksum
  124.  
  125. #define Puts        linuxboot_args->puts
  126. #define GetChar        linuxboot_args->getchar
  127. #define PutChar        linuxboot_args->putchar
  128. #define Printf        linuxboot_args->printf
  129. #define Open        linuxboot_args->open
  130. #define Seek        linuxboot_args->seek
  131. #define Read        linuxboot_args->read
  132. #define Close        linuxboot_args->close
  133. #define FileSize    linuxboot_args->filesize
  134. #define Sleep        linuxboot_args->sleep
  135.  
  136.     /*
  137.      *  Function Prototypes
  138.      */
  139.  
  140. static u_long get_chipset(void);
  141. static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu);
  142. static u_long get_model(u_long chipset);
  143. static int probe_resident(const char *name);
  144. static int probe_resource(const char *name);
  145. static int create_bootinfo(void);
  146. #ifdef BOOTINFO_COMPAT_1_0
  147. static int create_compat_bootinfo(void);
  148. #endif /* BOOTINFO_COMPAT_1_0 */
  149. static int add_bi_record(u_short tag, u_short size, const void *data);
  150. static int add_bi_string(u_short tag, const u_char *s);
  151. static int check_bootinfo_version(const char *memptr);
  152. static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
  153.              u_long start_mem, u_long mem_size, u_long rd_size,
  154.              u_long kernel_size) __attribute__ ((noreturn));
  155. asmlinkage u_long probe_powerup(u_long);
  156. asmlinkage u_long maprommed(void);
  157. asmlinkage u_long check346(void);
  158. #ifdef ZKERNEL
  159. static int load_zkernel(int fd);
  160. static int KRead(int fd, void *buf, int cnt);
  161. static int KSeek(int fd, int offset);
  162. static int KClose(int fd);
  163. #else
  164. #define KRead        Read
  165. #define KSeek        Seek
  166. #define KClose        Close
  167. #endif
  168.  
  169.  
  170.     /*
  171.      *    Reset functions for nasty Zorro boards
  172.      */
  173.  
  174. static void reset_rb3(const struct ConfigDev *cd);
  175. static void reset_piccolo(const struct ConfigDev *cd);
  176. static void reset_sd64(const struct ConfigDev *cd);
  177. static void reset_a2065(const struct ConfigDev *cd);
  178. static void reset_ariadne(const struct ConfigDev *cd);
  179. static void reset_hydra(const struct ConfigDev *cd);
  180. #if 0
  181. static void reset_a2060(const struct ConfigDev *cd);
  182. #endif
  183.  
  184. struct boardreset {
  185.     u_short manuf;
  186.     u_short prod;
  187.     const char *name;
  188.     void (*reset)(const struct ConfigDev *cd);
  189. };
  190.  
  191. static struct boardreset boardresetdb[] = {
  192.     { MANUF_HELFRICH1, PROD_RAINBOW3, "Rainbow 3", reset_rb3 },
  193.     { MANUF_HELFRICH2, PROD_PICCOLO_REG, "Piccolo", reset_piccolo },
  194.     { MANUF_HELFRICH2, PROD_SD64_REG, "SD64", reset_sd64 },
  195.     { MANUF_COMMODORE, PROD_A2065, "A2065", reset_a2065 },
  196.     { MANUF_VILLAGE_TRONIC, PROD_ARIADNE, "Ariadne", reset_ariadne },
  197.     { MANUF_HYDRA_SYSTEMS, PROD_AMIGANET, "Hydra", reset_hydra },
  198. #if 0
  199.     { MANUF_COMMODORE, PROD_A2060, "A2060", reset_a2060 },
  200. #endif
  201. };
  202. #define NUM_BOARDRESET    sizeof(boardresetdb)/sizeof(*boardresetdb)
  203.  
  204. static void (*boardresetfuncs[ZORRO_NUM_AUTO])(const struct ConfigDev *cd);
  205.  
  206.  
  207. const char *amiga_models[] = {
  208.     "Amiga 500", "Amiga 500+", "Amiga 600", "Amiga 1000", "Amiga 1200",
  209.     "Amiga 2000", "Amiga 2500", "Amiga 3000", "Amiga 3000T", "Amiga 3000+",
  210.     "Amiga 4000", "Amiga 4000T", "CDTV", "CD32", "Draco"
  211. };
  212. const u_long first_amiga_model = AMI_500;
  213. const u_long last_amiga_model = AMI_DRACO;
  214.  
  215.  
  216. #define MASK(model)    (1<<AMI_##model)
  217.  
  218. #define CLASS_A3000    (MASK(3000) | MASK(3000T))
  219. #define CLASS_A4000    (MASK(4000) | MASK(4000T))
  220. #define CLASS_ZKICK    (MASK(500) | MASK(1000) | MASK(2000) | MASK(2500))
  221.  
  222.  
  223.     /*
  224.      *    Boot the Linux/m68k Operating System
  225.      */
  226.  
  227. u_long linuxboot(const struct linuxboot_args *args)
  228. {
  229.     int kfd = -1, rfd = -1, elf_kernel = 0, do_fast, do_chip;
  230.     int i, j;
  231.     const struct MemHeader *mnp;
  232.     struct ConfigDev *cdp = NULL;
  233.     char *memptr = NULL;
  234.     u_long *stack = NULL;
  235.     u_long fast_total, model_mask, startcodesize, start_mem, mem_size, rd_size;
  236.     u_long kernel_size;
  237.     u_int realbaud;
  238.     u_long memreq = 0, text_offset = 0;
  239.     Elf32_Phdr *kernel_phdrs = NULL;
  240.     void (*startfunc)(void);
  241.     u_short manuf;
  242.     u_char prod;
  243.     void *bi_ptr;
  244.     unsigned long* info;
  245.     struct ConfigDev *zdevs[ZORRO_NUM_AUTO];
  246.  
  247.     linuxboot_args = args;
  248.  
  249.     /* print the greet message */
  250.     Puts("\nLinux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n");
  251.     Puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n\n");
  252.  
  253.     /* Note: Initial values in bi override detected values */
  254.     bi = args->bi;
  255.  
  256.     /* machine is Amiga */
  257.     bi.machtype = MACH_AMIGA;
  258.  
  259.     /* determine chipset */
  260.     if (!bi.chipset)
  261.     bi.chipset = get_chipset();
  262.  
  263.     /* determine CPU, FPU and MMU type */
  264.     if (!bi.cputype)
  265.     get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
  266.  
  267.     /* determine Amiga model */
  268.     if (!bi.model)
  269.     bi.model = get_model(bi.chipset);
  270.     model_mask = (bi.model != AMI_UNKNOWN) ? 1<<bi.model : 0;
  271.  
  272.     /* Memory & AutoConfig based on 'unix_boot.c' by C= */
  273.  
  274.     /* find all of the autoconfig boards in the system */
  275.     if (!bi.num_autocon)
  276.     for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1,