patch-2.1.48 linux/arch/m68k/boot/atari/bootstrap.c
Next file: linux/arch/m68k/boot/atari/bootstrap.h
Previous file: linux/arch/m68k/boot/atari/bootp.h
Back to the patch index
Back to the overall index
- Lines: 1603
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.1.47/linux/arch/m68k/boot/atari/bootstrap.c
- Orig date:
Wed Apr 23 19:01:15 1997
diff -u --recursive --new-file v2.1.47/linux/arch/m68k/boot/atari/bootstrap.c linux/arch/m68k/boot/atari/bootstrap.c
@@ -1,1602 +0,0 @@
-/*
-** bootstrap.c -- Load and launch the Atari Linux kernel
-**
-** Copyright 1993 by Arjan Knor
-**
-** 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:
-** 01 Feb 1997 Implemented kernel decompression (Roman)
-** 28 Nov 1996 Fixed and tested previous change (James)
-** 27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
-** 12 Nov 1996 Fixed and tested previous change (Andreas)
-** 18 Aug 1996 Updated for the new boot information structure (untested!)
-** (Geert)
-** 10 Dec 1995 BOOTP/TFTP support (Roman)
-** 03 Oct 1995 Allow kernel to be loaded to TT ram again (Andreas)
-** 11 Jul 1995 Add support for ELF format kernel (Andreas)
-** 16 Jun 1995 Adapted to Linux 1.2: kernel always loaded into ST ram
-** (Andreas)
-** 14 Nov 1994 YANML (Yet Another New Memory Layout :-) kernel
-** start address is KSTART_ADDR + PAGE_SIZE, this
-** does not need the ugly kludge with
-** -fwritable-strings (++andreas)
-** 09 Sep 1994 Adapted to the new memory layout: All the boot_info entry
-** mentions all ST-Ram and the mover is located somewhere
-** in the middle of memory (roman)
-** Added the default arguments file known from the other
-** bootstrap version
-** 19 Feb 1994 Changed everything so that it works? (rdv)
-** 14 Mar 1994 New mini-copy routine used (rdv)
-*/
-
-
-#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
-/* support compressed kernels? */
-#define ZKERNEL
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stddef.h>
-#include <string.h>
-#include <ctype.h>
-#include "sysvars.h"
-#include <osbind.h>
-#include <sys/types.h>
-#include <sys/file.h>
-
-/* linux specific include files */
-#include <linux/a.out.h>
-#include <linux/elf.h>
-#include <asm/page.h>
-
-#define _LINUX_TYPES_H /* Hack to prevent including <linux/types.h> */
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-
-/* Atari bootstrap include file */
-#include "bootstrap.h"
-
-#define MIN_RAMSIZE (3) /* 3 MB */
-#define TEMP_STACKSIZE 256
-
-extern char *optarg;
-extern int optind;
-static void get_default_args( int *argc, char ***argv );
-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);
-/* This is missing in <unistd.h> */
-extern int sync (void);
-
-/* Bootinfo */
-static struct atari_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;
-
-u_long *cookiejar;
-u_long userstk;
-
-/* getcookie -- function to get the value of the given cookie. */
-static int getcookie(char *cookie, u_long *value)
-{
- int i = 0;
-
- while(cookiejar[i] != 0L) {
- if(cookiejar[i] == *(u_long *)cookie) {
- *value = cookiejar[i + 1];
- return 1;
- }
- i += 2;
- }
- return -1;
-}
-
-static void usage(void)
-{
- fprintf(stderr, "Usage:\n"
- "\tbootstrap [-dst] [-k kernel_executable] [-r ramdisk_file]"
- " [option...]\n");
- exit(EXIT_FAILURE);
-}
-
-/*
- * Copy the kernel and the ramdisk to their final resting places.
- *
- * I assume that the kernel data and the ramdisk reside somewhere
- * in the middle of the memory.
- *
- * This program itself should be somewhere in the first 4096 bytes of memory
- * where the kernel never will be. In this way it can never be overwritten
- * by itself.
- *
- * At this point the registers have:
- * a0: the start of the final kernel
- * a1: the start of the current kernel
- * a2: the end of the final ramdisk
- * a3: the end of the current ramdisk
- * d0: the kernel size
- * d1: the ramdisk size
- */
-asm ("
-.text
-.globl _copyall, _copyallend
-_copyall:
-
- movel a0,a4 /* save the start of the kernel for booting */
-
-1: movel a1@+,a0@+ /* copy the kernel starting at the beginning */
- subql #4,d0
- jcc 1b
-
- tstl d1
- beq 3f
-
-2: movel a3@-,a2@- /* copy the ramdisk starting at the end */
- subql #4,d1
- jcc 2b
-
-3: jmp a4@ /* jump to the start of the kernel */
-_copyallend:
-");
-
-extern char copyall, copyallend;
-
-
-/* Test for a Medusa: This is the only machine on which address 0 is
- * writeable!
- * ...err! On the Afterburner040 (for the Falcon) it's the same... So we do
- * another test with 0x00ff82fe, that gives a bus error on the Falcon, but is
- * in the range where the Medusa always asserts DTACK.
- * On the Hades address 0 is writeable as well and it asserts DTACK on
- * address 0x00ff82fe. To test if the machine is a Hades, address 0xb0000000
- * is tested. On the Medusa this gives a bus error.
- */
-
-int test_medusa( void )
-
-{ int rv = 0;
-
- __asm__ __volatile__
- ( "movel 0x8,a0\n\t"
- "movel sp,a1\n\t"
- "moveb 0x0,d1\n\t"
- "movel #Lberr,0x8\n\t"
- "moveq #0,%0\n\t"
- "clrb 0x0\n\t"
- "nop \n\t"
- "moveb d1,0x0\n\t"
- "nop \n\t"
- "tstb 0x00ff82fe\n\t"
- "nop \n\t"
- "moveq #1,%0\n\t"
- "tstb 0xb0000000\n\t"
- "nop \n\t"
- "moveq #0,%0\n"
- "Lberr:\t"
- "movel a1,sp\n\t"
- "movel a0,0x8"
- : "=d" (rv)
- : /* no inputs */
- : "d1", "a0", "a1", "memory" );
-
- return( rv );
-}
-
-
-/* Test if FPU instructions are executed in hardware, or if they're
- emulated in software. For this, the F-line vector is temporarily
- replaced. */
-
-int test_software_fpu(void)
-{
- int rv = 0;
-
- __asm__ __volatile__
- ( "movel 0x2c,a0\n\t"
- "movel sp,a1\n\t"
- "movel #Lfline,0x2c\n\t"
- "moveq #1,%0\n\t"
- "fnop \n\t"
- "nop \n\t"
- "moveq #0,%0\n"
- "Lfline:\t"
- "movel a1,sp\n\t"
- "movel a0,0x2c"
- : "=d" (rv)
- : /* no inputs */
- : "a0", "a1" );
-
- return rv;
-}
-
-
-void get_medusa_bank_sizes( u_long *bank1, u_long *bank2 )
-
-{ static u_long save_addr;
- u_long test_base, saved_contents[16];
-#define TESTADDR(i) (*((u_long *)((char *)test_base + i*8*MB)))
-#define TESTPAT 0x12345678
- unsigned short oldflags;
- int i;
-
- /* This ensures at least that none of the test addresses conflicts
- * with the test code itself */
- test_base = ((unsigned long)&save_addr & 0x007fffff) | 0x20000000;
- *bank1 = *bank2 = 0;
-
- /* Interrupts must be disabled because arbitrary addresses may be
- * temporarily overwritten, even code of an interrupt handler */
- __asm__ __volatile__ ( "movew sr,%0; oriw #0x700,sr" : "=g" (oldflags) : );
- disable_cache();
-
- /* save contents of the test addresses */
- for( i = 0; i < 16; ++i )
- saved_contents[i] = TESTADDR(i);
-
- /* write 0s into all test addresses */
- for( i = 0; i < 16; ++i )
- TESTADDR(i) = 0;
-
- /* test for bank 1 */
-#if 0
- /* This is Freddi's original test, but it didn't work. */
- TESTADDR(0) = TESTADDR(1) = TESTPAT;
- if (TESTADDR(1) == TESTPAT) {
- if (TESTADDR(2) == TESTPAT)
- *bank1 = 8*MB;
- else if (TESTADDR(3) == TESTPAT)
- *bank1 = 16*MB;
- else
- *bank1 = 32*MB;
- }
- else {
- if (TESTADDR(2) == TESTPAT)
- *bank1 = 0;
- else
- *bank1 = 16*MB;
- }
-#else
- TESTADDR(0) = TESTPAT;
- if (TESTADDR(1) == TESTPAT)
- *bank1 = 8*MB;
- else if (TESTADDR(2) == TESTPAT)
- *bank1 = 16*MB;
- else if (TESTADDR(4) == TESTPAT)
- *bank1 = 32*MB;
- else
- *bank1 = 64*MB;
-#endif
-
- /* test for bank2 */
- if (TESTADDR(8) != 0)
- *bank2 = 0;
- else {
- TESTADDR(8) = TESTPAT;
- if (TESTADDR(9) != 0) {
- if (TESTADDR(10) == TESTPAT)
- *bank2 = 8*MB;
- else
- *bank2 = 32*MB;
- }
- else {
- TESTADDR(9) = TESTPAT;
- if (TESTADDR(10) == TESTPAT)
- *bank2 = 16*MB;
- else
- *bank2 = 64*MB;
- }
- }
-
- /* restore contents of the test addresses and restore interrupt mask */
- for( i = 0; i < 16; ++i )
- TESTADDR(i) = saved_contents[i];
- __asm__ __volatile__ ( "movew %0,sr" : : "g" (oldflags) );
-}
-
-#undef TESTADDR
-#undef TESTPAT
-
-
-static int check_bootinfo_version(char *memptr)
-{
- struct bootversion *bv = (struct bootversion *)memptr;
- unsigned long version = 0;
- int i, kernel_major, kernel_minor, boots_major, boots_minor;
-
- printf( "\n" );
- if (bv->magic == BOOTINFOV_MAGIC) {
- for( i = 0; bv->machversions[i].machtype != 0; ++i ) {
- if (bv->machversions[i].machtype == MACH_ATARI) {
- version = bv->machversions[i].version;
- break;
- }
- }
- }
- if (!version)
- printf("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(ATARI_BOOTI_VERSION);
- boots_minor = BI_VERSION_MINOR(ATARI_BOOTI_VERSION);
- printf("Bootstrap's bootinfo version: %d.%d\n",
- boots_major, boots_minor);
- printf("Kernel's bootinfo version : %d.%d\n",
- kernel_major, kernel_minor);
-
- switch (kernel_major) {
- case BI_VERSION_MAJOR(ATARI_BOOTI_VERSION):
- if (kernel_minor > boots_minor) {
- printf("Warning: Bootinfo version of bootstrap and kernel "
- "differ!\n");
- printf(" Certain features may not work.\n");
- }
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_ATARI_BOOTI_VERSION):
- printf("(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;
-}
-
-
-#ifdef USE_BOOTP
-# include "bootp.h"
-#else
-# define ll_read read
-# define ll_lseek lseek
-# define ll_close close
-#endif
-
-#ifdef ZKERNEL
-static int load_zkernel( int fd );
-static int kread( int fd, void *buf, unsigned cnt );
-static int klseek( int fd, int where, int whence );
-static int kclose( int fd );
-#else
-# define kread read
-# define klseek lseek
-# define kclose close
-#endif
-
-/* ++andreas: this must be inline due to Super */
-static inline void boot_exit (int) __attribute__ ((noreturn));
-static inline void boot_exit(int status)
-{
- /* first go back to user mode */
- (void)Super(userstk);
- getchar();
- exit(status);
-}
-
-int main(int argc, char *argv[])
-{
- int debugflag = 0, ch, kfd, rfd = -1, i, ignore_ttram = 0;
- int load_to_stram = 0;
- char *ramdisk_name, *kernel_name, *memptr;
- u_long ST_ramsize, TT_ramsize, memreq;
- u_long cpu_type, fpu_type, mch_type, mint;
- struct exec kexec;
- int elf_kernel = 0;
- Elf32_Ehdr kexec_elf;
- Elf32_Phdr *kernel_phdrs = NULL;
- u_long start_mem, mem_size, rd_size, text_offset = 0, kernel_size;
- int prefer_bootp = 1, kname_set = 0, n_knames;
-#ifdef USE_BOOTP
- int err;
-#endif
- char kname_list[5][64];
- void *bi_ptr;
-
- ramdisk_name = NULL;
- kernel_name = "vmlinux";
-
- /* print the startup message */
- puts("\fLinux/68k Atari Bootstrap version 2.2"
-#ifdef USE_BOOTP
- " (with BOOTP)"
-#endif
- );
- puts("Copyright 1993,1994 by Arjan Knor, Robert de Vries, Roman Hodek, Andreas Schwab\n");
-
- /* ++roman: If no arguments on the command line, read them from
- * file */
- if (argc == 1)
- get_default_args( &argc, &argv );
-
- /* machine is Atari */
- bi.machtype = MACH_ATARI;
-
- /* check arguments */
- while ((ch = getopt(argc, argv, "bdtsk:r:")) != EOF)
- switch (ch) {
- case 'd':
- debugflag = 1;
- break;
- case 't':
- ignore_ttram = 1;
- break;
- case 's':
- load_to_stram = 1;
- break;
- case 'k':
- kernel_name = optarg;
- kname_set = 1;
- break;
- case 'r':
- ramdisk_name = optarg;
- break;
- case 'b':
- prefer_bootp = 0;
- break;
- case '?':
- default:
- usage();
- }
-
- argc -= optind;
- argv += optind;
-
- /* We have to access some system variables to get
- * the information we need, so we must switch to
- * supervisor mode first.
- */
- userstk = Super(0L);
-
- /* get the info we need from the cookie-jar */
- cookiejar = *_p_cookies;
- if(cookiejar == 0L) {
- /* if we find no cookies, it's probably an ST */
- fprintf(stderr, "Error: No cookiejar found. Is this an ST?\n");
- boot_exit(EXIT_FAILURE);
- }
-
- /* Exit if MiNT/MultiTOS is running. */
- if(getcookie("MiNT", &mint) != -1)
- {
- puts("Warning: MiNT is running\n");
-#if 0
- puts("Linux cannot be started when MiNT is running. Aborting...\n");
- boot_exit(EXIT_FAILURE);
-#endif
- }
-
- /* get _CPU, _FPU and _MCH */
- getcookie("_CPU", &cpu_type);
- getcookie("_FPU", &fpu_type);
- getcookie("_MCH", &mch_type);
-
- /* check if we are on a 68030/40 with FPU */
- if ((cpu_type != 30 && cpu_type != 40 && cpu_type != 60))
- {
- puts("Machine type currently not supported. Aborting...");
- boot_exit(EXIT_FAILURE);
- }
-
- switch(cpu_type) {
- case 0:
- case 10: break;
- case 20: bi.cputype = CPU_68020; bi.mmutype = MMU_68851; break;
- case 30: bi.cputype = CPU_68030; bi.mmutype = MMU_68030; break;
- case 40: bi.cputype = CPU_68040; bi.mmutype = MMU_68040; break;
- case 60: bi.cputype = CPU_68060; bi.mmutype = MMU_68060; break;
- default:
- fprintf(stderr, "Error: Unknown CPU type. Aborting...\n");
- boot_exit(EXIT_FAILURE);
- break;
- }
-
- printf("CPU: %ld; ", cpu_type + 68000);
- printf("FPU: ");
-
- /* check for FPU; in case of a '040 or '060, don't look at _FPU itself,
- * some software may set it to wrong values (68882 or the like) */
- if (cpu_type == 40) {
- bi.fputype = FPU_68040;
- puts( "68040\n" );
- }
- else if (cpu_type == 60) {
- bi.fputype = FPU_68060;
- puts( "68060\n" );
- }
- else {
- switch ((fpu_type >> 16) & 7) {
- case 0:
- puts("not present\n");
- break;
- case 1:
- puts("SFP004 not supported. Assuming no FPU.");
- break;
- case 2:
- /* try to determine real type */
- if (fpu_idle_frame_size () != 0x18)
- goto m68882;
- /* fall through */
- case 4:
- bi.fputype = FPU_68881;
- puts("68881\n");
- break;
- case 6:
- m68882:
- bi.fputype = FPU_68882;
- puts("68882\n");
- break;
- default:
- puts("Unknown FPU type. Assuming no FPU.");
- break;
- }
- }
- /* ++roman: If an FPU was announced in the cookie, test
- whether it is a real hardware FPU or a software emulator! */
- if (bi.fputype) {
- if (test_software_fpu()) {
- bi.fputype = 0;
- puts("FPU: software emulated. Assuming no FPU.");
- }
- }
-
- /* Get the amounts of ST- and TT-RAM. */
- /* The size must be a multiple of 1MB. */
- i = 0;
-
- if (!test_medusa()) {
- struct {
- unsigned short version; /* version - currently 1 */
- unsigned long fr_start; /* start addr FastRAM */
- unsigned long fr_len; /* length FastRAM */
- } *magn_cookie;
- struct {
- unsigned long version;
- unsigned long fr_start; /* start addr */
- unsigned long fr_len; /* length */
- } *fx_cookie;
-
- TT_ramsize = 0;
- if (!ignore_ttram) {
- /* "Original" or properly emulated TT-Ram */
- if (*ramtop) {
- /* the 'ramtop' variable at 0x05a4 is not
- * officially documented. We use it anyway
- * because it is the only way to get the TTram size.
- * (It is zero if there is no TTram.)
- */
- bi.memory[i].addr = TT_RAM_BASE;
- bi.memory[i].size = (*ramtop - TT_RAM_BASE) & ~(MB - 1);
- TT_ramsize = bi.memory[i].size / MB;
- i++;
- printf("TT-RAM: %ld Mb; ", TT_ramsize);
- }
-
- /* test for MAGNUM alternate RAM
- * added 26.9.1995 M. Schwingen, rincewind@discworld.oche.de
- */
- if (getcookie("MAGN", (u_long *)&magn_cookie) != -1) {
- bi.memory[i].addr = magn_cookie->fr_start;
- bi.memory[i].size = magn_cookie->fr_len & ~(MB - 1);
- TT_ramsize += bi.memory[i].size / MB;
- printf("MAGNUM alternate RAM: %ld Mb; ", bi.memory[i].size/MB);
- i++;
- }
-
- /* BlowUps FX */
- if (getcookie("BPFX", (u_long *)&fx_cookie) != -1 && fx_cookie) {
- /* if fx is set (cookie call above),
- * we assume that BlowUps FX-card
- * is installed. (Nat!)
- */
- bi.memory[i].addr = fx_cookie->fr_start;
- bi.memory[i].size = fx_cookie->fr_len & ~(MB - 1);
- printf("FX alternate RAM: %ld Mb; ", bi.memory[i].size/MB);
- i++;
- }
- }
-
- bi.memory[i].addr = 0;
- bi.memory[i].size = *phystop & ~(MB - 1);
- ST_ramsize = bi.memory[i].size / MB;
- i++;
- printf("ST-RAM: %ld Mb\n", ST_ramsize );
-
- bi.num_memory = i;
-
- if (load_to_stram && i > 1) {
- /* Put ST-RAM first in the list of mem blocks */
- struct mem_info temp = bi.memory[i - 1];
- bi.memory[i - 1] = bi.memory[0];
- bi.memory[0] = temp;
- }
- }
- else {
- u_long bank1, bank2, medusa_st_ram;
-
- get_medusa_bank_sizes( &bank1, &bank2 );
- medusa_st_ram = *phystop & ~(MB - 1);
- bank1 -= medusa_st_ram;
- TT_ramsize = 0;
-
- bi.memory[i].addr = 0;
- bi.memory[i].size = medusa_st_ram;
- ST_ramsize = bi.memory[i].size / MB;
- i++;
- printf("Medusa pseudo ST-RAM from bank 1: %ld Mb; ", ST_ramsize );
-
- if (!ignore_ttram && bank1 > 0) {
- bi.memory[i].addr = 0x20000000 + medusa_st_ram;
- bi.memory[i].size = bank1;
- TT_ramsize += bank1;
- i++;
- printf("TT-RAM bank 1: %ld Mb; ", bank1/MB );
- }
-
- if (!ignore_ttram && bank2 > 0) {
- bi.memory[i].addr = 0x24000000;
- bi.memory[i].size = bank2;
- TT_ramsize += bank2;
- i++;
- printf("TT-RAM bank 2: %ld Mb; ", bank2/MB );
- }
-
- bi.num_memory = i;
- printf("\n");
- }
-
- /* verify that there is enough RAM; ST- and TT-RAM combined */
- if (ST_ramsize + TT_ramsize < MIN_RAMSIZE) {
- puts("Not enough RAM. Aborting...");
- boot_exit(10);
- }
-
-#if 0
- /* Get language/keyboard info */
- /* TODO: do we need this ? */
- /* Could be used to auto-select keyboard map later on. (rdv) */
- if (getcookie("_AKP",&language) == -1)
- {
- /* Get the language info from the OS-header */
- os_header = *_sysbase;
- os_header = os_header->os_beg;
- lang = (os_header->os_conf) >> 1;
- printf("Language: ");
- switch(lang) {
- case HOL: puts("Dutch"); break; /* Own country first :-) */
- case USA: puts("American"); break;
- case SWG: puts("Switzerland (German)"); break;
- case FRG: puts("German"); break;
- case FRA: puts("French"); break;
- case SWF: puts("Switzerland (French)"); break;
- case UK: puts("English"); break;
- case SPA: puts("Spanish"); break;
- case ITA: puts("Italian"); break;
- case SWE: puts("Swedish"); break;
- case TUR: puts("Turkey"); break;
- case FIN: puts("Finnish"); break;
- case NOR: puts("Norwegian"); break;
- case DEN: puts("Danish"); break;
- case SAU: puts("Saudi-Arabian"); break;
- default: puts("Unknown"); break;
- }
- }
- else
- {
- printf("Language: ");
- switch(language & 0x0F)
- {
- case 1: printf("German "); break;
- case 2: printf("French "); break;
- case 4: printf("Spanish "); break;
- case 5: printf("Italian "); break;
- case 7: printf("Swiss French "); break;
- case 8: printf("Swiss German "); break;
- default: printf("English ");
- }
- printf("Keyboard type :");
- switch(language >> 8)
- {
- case 1: printf("German "); break;
- case 2: printf("French "); break;
- case 4: printf("Spanish "); break;
- case 5: printf("Italian "); break;
- case 7: printf("Swiss French "); break;
- case 8: printf("Swiss German "); break;
- default: printf("English ");
- }
- printf("\n");
- }
-#endif
-
- /* Pass contents of the _MCH cookie to the kernel */
- bi.mch_cookie = mch_type;
-
- /*
- * Copy command line options into the kernel command line.
- */
- i = 0;
- while (argc--) {
- if ((i+strlen(*argv)+1) < CL_SIZE) {
- i += strlen(*argv) + 1;
- if (bi.command_line[0])
- strcat (bi.command_line, " ");
- strcat (bi.command_line, *argv++);
- }
- }
- printf ("Command line is '%s'\n", bi.command_line);
-
- 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);
-
-#ifdef TEST
- /*
- ** Temporary exit point for testing
- */
- boot_exit(-1);
-#endif /* TEST */
-
- i = 0;
-#ifdef USE_BOOTP
- if (!kname_set)
- kname_list[i++][0] = '\0'; /* default kernel which BOOTP server says */
-#endif
-#ifdef ZKERNEL
- strcpy( kname_list[i], kernel_name );
- strcat( kname_list[i], ".gz" );
- ++i;
-#endif
- strcpy( kname_list[i++], kernel_name );
-#ifdef ZKERNEL
- if (!kname_set)
- strcpy( kname_list[i++], "vmlinuz" );
-#endif
- n_knames = i;
-
- kfd = -1;
-#ifdef USE_BOOTP
- if (prefer_bootp) {
- for( i = 0; i < n_knames; ++i ) {
- if ((err = get_remote_kernel( kname_list[i] )) >= 0)
- goto kernel_open;
- if (err < -1) /* fatal error; retries don't help... */
- break;
- }
- printf( "\nremote boot failed; trying local kernel\n" );
- }
-#endif
- for( i = 0; i < n_knames; ++i ) {
- if ((kfd = open( kname_list[i], O_RDONLY )) != -1)
- goto kernel_open;
- }
-#ifdef USE_BOOTP
- if (!prefer_bootp) {
- printf( "\nlocal kernel failed; trying remote boot\n" );
- for( i = 0; i < n_knames; ++i ) {
- if ((err = get_remote_kernel( kname_list[i] )) >= 0)
- goto kernel_open;
- if (err < -1) /* fatal error; retries don't help... */
- break;
- }
- }
-#endif
- fprintf( stderr, "Unable to open any kernel file\n(Tried " );
- for( i = 0; i < n_knames; ++i ) {
- fprintf( stderr, "%s%s", kname_list[i],
- i < n_knames-2 ? ", " :
- i == n_knames-2 ? ", and " :
- ")\n" );
- }
- boot_exit( EXIT_FAILURE );
-
- kernel_open:
-
- if (kread (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec))
- {
- fprintf (stderr, "Unable to read exec header from %s\n", kernel_name);
- boot_exit (EXIT_FAILURE);
- }
-
-#ifdef ZKERNEL
- if (((unsigned char *)&kexec)[0] == 037 &&
- (((unsigned char *)&kexec)[1] == 0213 ||
- ((unsigned char *)&kexec)[1] == 0236)) {
- /* That's a compressed kernel */
- printf( "Kernel is compressed\n" );
- if (load_zkernel( kfd )) {
- printf( "Decompression error -- aborting\n" );
- boot_exit( EXIT_FAILURE );
- }
- }
-#endif
-
- switch (N_MAGIC(kexec)) {
- case ZMAGIC:
- text_offset = N_TXTOFF(kexec);
- break;
- case QMAGIC:
- 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 */
- klseek (kfd, 0, SEEK_SET);
- 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;
- /* A few plausibility checks */
- if (kexec_elf.e_type != ET_EXEC || kexec_elf.e_machine != EM_68K
- || kexec_elf.e_version != EV_CURRENT)
- {
- fprintf (stderr, "Invalid ELF header contents in kernel\n");
- boot_exit (EXIT_FAILURE);
- }
- /* Load the program headers */
- kernel_phdrs = (Elf32_Phdr *) Malloc (kexec_elf.e_phnum * sizeof (Elf32_Phdr));
- if (kernel_phdrs == NULL)
- {
- fprintf (stderr, "Unable to allocate memory for program headers\n");
- boot_exit (EXIT_FAILURE);
- }
- klseek (kfd, kexec_elf.e_phoff, SEEK_SET);
- if (kread (kfd, (void *) kernel_phdrs,
- kexec_elf.e_phnum * sizeof (*kernel_phdrs))
- != kexec_elf.e_phnum * sizeof (*kernel_phdrs))
- {
- fprintf (stderr, "Unable to read program headers from %s\n",
- kernel_name);
- boot_exit (EXIT_FAILURE);
- }
- break;
- }
- fprintf (stderr, "Wrong magic number %lo in kernel header\n",
- N_MAGIC(kexec));
- boot_exit (EXIT_FAILURE);
- }
-
- /* Load the kernel 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;
-
- /* init ramdisk */
- if(ramdisk_name) {
- if((rfd = open(ramdisk_name, O_RDONLY)) == -1) {
- fprintf(stderr, "Unable to open ramdisk file %s\n",
- ramdisk_name);
- boot_exit(EXIT_FAILURE);
- }
- bi.ramdisk.size = lseek(rfd, 0, SEEK_END);
- }
- else
- bi.ramdisk.size = 0;
-
- /* 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;
-
- rd_size = bi.ramdisk.size;
- if (rd_size + kernel_size > mem_size - MB/2 && bi.num_memory > 1)
- /* If running low on ST ram load ramdisk into alternate ram. */
- bi.ramdisk.addr = (u_long) bi.memory[1].addr + bi.memory[1].size - rd_size;
- else
- /* Else hopefully there is enough ST ram. */
- bi.ramdisk.addr = (u_long)start_mem + mem_size - rd_size;
-
- /* create the bootinfo structure */
- if (!create_bootinfo())
- boot_exit (EXIT_FAILURE);
-
- memreq = kernel_size + bi_size;
-#ifdef BOOTINFO_COMPAT_1_0
- if (sizeof(compat_bootinfo) > bi_size)
- memreq = kernel_size+sizeof(compat_bootinfo);
-#endif /* BOOTINFO_COMPAT_1_0 */
- /* align load address of ramdisk image, read() is sloooow on odd addr. */
- memreq = ((memreq + 3) & ~3) + rd_size;
-
- /* allocate RAM for the kernel */
- if (!(memptr = (char *)Malloc (memreq)))
- {
- fprintf (stderr, "Unable to allocate memory for kernel and ramdisk\n");
- boot_exit (EXIT_FAILURE);
- }
- else
- fprintf(stderr, "kernel at address %lx\n", (u_long) memptr);
-
- (void)memset(memptr, 0, memreq);
-
- /* read the text and data segments from the kernel image */
- if (elf_kernel)
- {
- for (i = 0; i < kexec_elf.e_phnum; i++)
- {
- if (klseek (kfd, kernel_phdrs[i].p_offset, SEEK_SET) == -1)
- {
- fprintf (stderr, "Failed to seek to segment %d\n", i);
- boot_exit (EXIT_FAILURE);
- }
- if (kread (kfd, memptr + kernel_phdrs[i].p_vaddr - PAGE_SIZE,
- kernel_phdrs[i].p_filesz)
- != kernel_phdrs[i].p_filesz)
- {
- fprintf (stderr, "Failed to read segment %d\n", i);
- boot_exit (EXIT_FAILURE);
- }
- }
- }
- else
- {
- if (klseek (kfd, text_offset, SEEK_SET) == -1)
- {
- fprintf (stderr, "Failed to seek to text\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
-
- if (kread (kfd, memptr, kexec.a_text) != kexec.a_text)
- {
- fprintf (stderr, "Failed to read text\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
-
- /* data follows immediately after text */
- if (kread (kfd, memptr + kexec.a_text, kexec.a_data) != kexec.a_data)
- {
- fprintf (stderr, "Failed to read data\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- }
- kclose (kfd);
-
- /* Check kernel's bootinfo version */
- switch (check_bootinfo_version(memptr)) {
- case BI_VERSION_MAJOR(ATARI_BOOTI_VERSION):
- bi_ptr = &bi_union.record;
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_ATARI_BOOTI_VERSION):
- if (!create_compat_bootinfo()) {
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- bi_ptr = &compat_bootinfo;
- bi_size = sizeof(compat_bootinfo);
- break;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
- default:
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
-
- /* copy the boot_info struct to the end of the kernel image */
- memcpy ((void *)(memptr + kernel_size), bi_ptr, bi_size);
-
- /* read the ramdisk image */
- if (rfd != -1)
- {
- if (lseek (rfd, 0, SEEK_SET) == -1)
- {
- fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- if (read (rfd, memptr + memreq - rd_size,
- rd_size) != rd_size)
- {
- fprintf (stderr, "Failed to read ramdisk file\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- close (rfd);
- }
-
- /* for those who want to debug */
- if (debugflag)
- {
- if (bi.ramdisk.size)
- printf ("RAM disk at %#lx, size is %ld\n",
- (u_long)(memptr + memreq - rd_size),
- bi.ramdisk.size);
-
- if (elf_kernel)
- {
- for (i = 0; i < kexec_elf.e_phnum; i++)
- {
- printf ("Kernel segment %d at %#lx, size %ld\n", i,
- start_mem + kernel_phdrs[i].p_vaddr - PAGE_SIZE,
- kernel_phdrs[i].p_memsz);
- }
- }
- else
- {
- printf ("\nKernel text at %#lx, code size %d\n",
- start_mem, kexec.a_text);
- printf ("Kernel data at %#lx, data size %d\n",
- start_mem + kexec.a_text, kexec.a_data );
- printf ("Kernel bss at %#lx, bss size %d\n",
- start_mem + kexec.a_text + kexec.a_data, kexec.a_bss );
- }
- printf ("\nboot_info is at %#lx\n",
- start_mem + kernel_size);
- printf ("\nKernel entry is %#lx\n",
- elf_kernel ? kexec_elf.e_entry : kexec.a_entry);
- printf ("ramdisk dest top is %#lx\n", bi.ramdisk.addr + rd_size);
- printf ("ramdisk lower limit is %#lx\n",
- (u_long)(memptr + memreq - rd_size));
- printf ("ramdisk src top is %#lx\n", (u_long)(memptr + memreq));
-
- printf ("Type a key to continue the Linux boot...");
- fflush (stdout);
- getchar();
- }
-
- printf("Booting Linux...\n");
-
- sync ();
-
- /* turn off interrupts... */
- disable_interrupts();
-
- /* turn off caches... */
- disable_cache();
-
- /* ..and any MMU translation */
- disable_mmu();
-
- /* ++guenther: allow reset if launched with MiNT */
- *(long*)0x426 = 0;
-
- /* copy mover code to a safe place if needed */
- memcpy ((void *) 0x400, ©all, ©allend - ©all);
-
- /* setup stack */
- change_stack ((void *) PAGE_SIZE);
-
- /*
- * On the Atari you can have two situations:
- * 1. One piece of contiguous RAM (Falcon)
- * 2. Two pieces of contiguous RAM (TT)
- * In case 2 you can load your program into ST-ram and load your data in
- * any old RAM you have left.
- * In case 1 you could overwrite your own program when copying the
- * kernel and ramdisk to their final positions.
- * To solve this the mover code is copied to a safe place first.
- * Then this program jumps to the mover code. After the mover code
- * has finished it jumps to the start of the kernel in its new position.
- * I thought the memory just after the interrupt vector table was a safe
- * place because it is used by TOS to store some system variables.
- * This range goes from 0x400 to approx. 0x5B0.
- * This is more than enough for the miniscule mover routine (16 bytes).
- */
-
- jump_to_mover((char *) start_mem, memptr,
- (char *) bi.ramdisk.addr + rd_size, memptr + memreq,
- kernel_size + bi_size, rd_size,
- (void *) 0x400);
-
- for (;;);
- /* NOTREACHED */
-}
-
-
-
-#define MAXARGS 30
-
-static void get_default_args( int *argc, char ***argv )
-
-{ FILE *f;
- static char *nargv[MAXARGS];
- char arg[256], *p;
- int c, quote, state;
-
- if (!(f = fopen( "bootargs", "r" )))
- return;
-
- *argc = 1;
- if (***argv)
- nargv[0] = **argv;
- else
- nargv[0] = "bootstrap";
- *argv = nargv;
-
- quote = state = 0;
- p = arg;
- while( (c = fgetc(f)) != EOF ) {
-
- if (state == 0) {
- /* outside args, skip whitespace */
- if (!isspace(c)) {
- state = 1;
- p = arg;
- }
- }
-
- if (state) {
- /* inside an arg: copy it into 'arg', obeying quoting */
- if (!quote && (c == '\'' || c == '"'))
- quote = c;
- else if (quote && c == quote)
- quote = 0;
- else if (!quote && isspace(c)) {
- /* end of this arg */
- *p = 0;
- nargv[(*argc)++] = strdup(arg);
- state = 0;
- }
- else
- *p++ = c;
- }
- }
- if (state) {
- /* last arg finished by EOF! */
- *p = 0;
- nargv[(*argc)++] = strdup(arg);
- }
- fclose( f );
-
- nargv[*argc] = 0;
-}
-
-
- /*
- * 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);
-
- /* Atari tags */
- if (!add_bi_record(BI_ATARI_MCH_COOKIE, sizeof(bi.mch_cookie),
- &bi.mch_cookie))
- 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_short size2;
-
- size2 = (sizeof(struct bi_record)+size+3)&-4;
- if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
- fprintf (stderr, "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 {
- 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 %d 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) {
- 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_atari.hw_present = 0;
- compat_bootinfo.bi_atari.mch_cookie = bi.mch_cookie;
- return(1);
-}
-#endif /* BOOTINFO_COMPAT_1_0 */
-
-
-#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 **);
-
-#include "../../../../lib/inflate.c"
-
-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 = ll_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 (chunk >= ZFILE_N_CHUNKS) {
- fprintf( stderr, "compressed image too large! Aborting.\n" );
- boot_exit( EXIT_FAILURE );
- }
- if (!ZFile[chunk]) {
- if (!(ZFile[chunk] = (char *)Malloc( ZFILE_CHUNK_SIZE ))) {
- fprintf( stderr, "Out of memory for decompresing kernel image\n" );
- boot_exit( EXIT_FAILURE );
- }
- }
- memcpy( ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt );
- Zwpos += outcnt;
-
-#define DISPLAY_BITS 13
- if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0) {
- printf( "." );
- fflush( stdout );
- }
-
- 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 )
-{
- fprintf( stderr, "\n%s", x);
- exit_code = 1;
-}
-
-static int load_zkernel( int fd )
-{
- int i, err;
-
- for( i = 0; i < ZFILE_N_CHUNKS; ++i )
- ZFile[i] = NULL;
- Zinfd = fd;
- ll_lseek( fd, 0, SEEK_SET );
-
- if (!(inbuf = (uch *)Malloc( INBUFSIZ ))) {
- fprintf( stderr, "Couldn't allocate gunzip buffer\n" );
- boot_exit( EXIT_FAILURE );
- }
- if (!(window = (uch *)Malloc( WSIZE ))) {
- fprintf( stderr, "Couldn't allocate gunzip window\n" );
- boot_exit( EXIT_FAILURE );
- }
-
- printf( "Uncompressing kernel image " );
- fflush( stdout );
- makecrc();
- if (!(err = gunzip()))
- printf( "done\n" );
- ZFileSize = Zwpos;
- ll_close( Zinfd ); /* input file not needed anymore */
-
- Mfree( inbuf );
- Mfree( window );
- 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. Same considerations apply to the TFTP file buffers. (Roman)
- */
-
-static int kread( int fd, void *buf, unsigned cnt )
-{
- unsigned done = 0;
-
- if (!ZFileSize)
- return( ll_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) {
- Mfree( ZFile[chunk] );
- ZFile[chunk] = NULL;
- }
- }
-
- return( done );
-}
-
-
-static int klseek( int fd, int where, int whence )
-{
- unsigned oldpos, oldchunk, newchunk;
-
- if (!ZFileSize)
- return( ll_lseek( fd, where, whence ) );
-
- oldpos = ZFpos;
- switch( whence ) {
- case SEEK_SET:
- ZFpos = where;
- break;
- case SEEK_CUR:
- ZFpos += where;
- break;
- case SEEK_END:
- ZFpos = ZFileSize + where;
- break;
- default:
- return( -1 );
- }
- 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]) {
- Mfree( ZFile[oldchunk] );
- ZFile[oldchunk] = NULL;
- }
- ++oldchunk;
- }
-
- return( ZFpos );
-}
-
-
-static void free_zfile( void )
-{
- int i;
-
- for( i = 0; i < ZFILE_N_CHUNKS; ++i )
- if (ZFile[i]) Mfree( ZFile[i] );
-}
-
-static int kclose( int fd )
-{
- if (ZFileSize) {
- free_zfile();
- return( 0 );
- }
- else
- return( ll_close( fd ) );
-}
-
-
-
-#endif /* ZKERNEL */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov