2 * linux/arch/m68k/boot/amiga/linuxboot.c -- Generic routine to boot Linux/m68k
3 * on Amiga, used by both Amiboot and
6 * Created 1996 by Geert Uytterhoeven
9 * This file is based on the original bootstrap code (bootstrap.c):
11 * Copyright (C) 1993, 1994 Hamish Macdonald
14 * with work by Michael Rausch
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
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
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)
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]
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)
49 #error GNU CC is required to compile this program
53 #define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
54 /* support compressed kernels? */
60 #include <sys/types.h>
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>
69 #include "linuxboot.h"
74 #define INTUITION_CLASSES_H 1
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"
86 #define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
88 /* temporary stack size */
89 #define TEMP_STACKSIZE (256)
91 #define DEFAULT_BAUD (9600)
93 extern char copyall
, copyallend
;
95 extern char getvbr
, wedgie
;
97 static struct exec kexec
;
98 static Elf32_Ehdr kexec_elf
;
99 static const struct linuxboot_args
*linuxboot_args
;
102 struct amiga_bootinfo bi
;
104 #ifdef BOOTINFO_COMPAT_1_0
105 static struct compat_bootinfo compat_bootinfo
;
106 #endif /* BOOTINFO_COMPAT_1_0 */
108 #define MAX_BI_SIZE (4096)
109 static u_long bi_size
;
111 struct bi_record record
;
112 u_char fake
[MAX_BI_SIZE
];
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
122 #define apus_boot linuxboot_args->apus_boot
123 #define checksum linuxboot_args->checksum
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
137 * Function Prototypes
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);
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
);
171 * Reset functions for nasty Zorro boards
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
);
181 static void reset_a2060(const struct ConfigDev
*cd
);
188 void (*reset
)(const struct ConfigDev
*cd
);
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
},
199 { MANUF_COMMODORE
, PROD_A2060
, "A2060", reset_a2060
},
202 #define NUM_BOARDRESET sizeof(boardresetdb)/sizeof(*boardresetdb)
204 static void (*boardresetfuncs
[ZORRO_NUM_AUTO
])(const struct ConfigDev
*cd
);
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"
212 const u_long first_amiga_model
= AMI_500
;
213 const u_long last_amiga_model
= AMI_DRACO
;
216 #define MASK(model) (1<<AMI_##model)
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))
224 * Boot the Linux/m68k Operating System
227 u_long
linuxboot(const struct linuxboot_args
*args
)
229 int kfd
= -1, rfd
= -1, elf_kernel
= 0, do_fast
, do_chip
;
231 const struct MemHeader
*mnp
;
232 struct ConfigDev
*cdp
= NULL
;
234 u_long
*stack
= NULL
;
235 u_long fast_total
, model_mask
, startcodesize
, start_mem
, mem_size
, rd_size
;
238 u_long memreq
= 0, text_offset
= 0;
239 Elf32_Phdr
*kernel_phdrs
= NULL
;
240 void (*startfunc
)(void);
245 struct ConfigDev
*zdevs
[ZORRO_NUM_AUTO
];
247 linuxboot_args
= args
;
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");
253 /* Note: Initial values in bi override detected values */
256 /* machine is Amiga */
257 bi
.machtype
= MACH_AMIGA
;
259 /* determine chipset */
261 bi
.chipset
= get_chipset();
263 /* determine CPU, FPU and MMU type */
265 get_processor(&bi
.cputype
, &bi
.fputype
, &bi
.mmutype
);
267 /* determine Amiga model */
269 bi
.model
= get_model(bi
.chipset
);
270 model_mask
= (bi
.model
!= AMI_UNKNOWN
) ? 1<<bi
.model
: 0;
272 /* Memory & AutoConfig based on 'unix_boot.c' by C= */
274 /* find all of the autoconfig boards in the system */
276 for (i
= 0; (cdp
= (struct ConfigDev
*)FindConfigDev(cdp
, -1, -1)); i
++)
277 if (bi
.num_autocon
< ZORRO_NUM_AUTO
) {
279 /* copy the contents of each structure into our boot info and
281 memcpy(&bi
.autocon
[bi
.num_autocon
++], cdp
,
282 sizeof(struct ConfigDev
));
284 Printf("Warning: too many AutoConfig devices. Ignoring device "
285 "at 0x%08lx\n", cdp
->cd_BoardAddr
);
287 do_fast
= bi
.num_memory
? 0 : 1;
288 do_chip
= bi
.chip_size
? 0 : 1;
289 /* find out the memory in the system */
290 for (mnp
= (struct MemHeader
*)SysBase
->MemList
.lh_Head
;
291 mnp
->mh_Node
.ln_Succ
;
292 mnp
= (struct MemHeader
*)mnp
->mh_Node
.ln_Succ
) {
295 /* copy the information */
298 /* skip virtual memory */
299 if (!(mh
.mh_Attributes
& MEMF_PUBLIC
))
302 /* if we suspect that Kickstart is shadowed in an A3000,
303 modify the entry to show 512K more at the top of RAM
304 Check first for a MapROMmed A3640 board: overwriting the
305 Kickstart image causes an infinite lock-up on reboot! */
306 if ((mh
.mh_Upper
== (void *)0x07f80000) &&
307 (model_mask
& (CLASS_A3000
| CLASS_A4000
)))
308 if ((bi
.cputype
& CPU_68040
) && Supervisor(maprommed
))
309 Puts("A3640 MapROM detected.\n");
310 else if (model_mask
& CLASS_A3000
) {
311 mh
.mh_Upper
= (void *)0x08000000;
312 Puts("A3000 shadowed Kickstart detected.\n");
315 /* if we suspect that Kickstart is zkicked,
316 modify the entry to show 512K more at the botton of RAM */
317 if ((mh
.mh_Lower
== (void *)0x00280020) &&
318 (model_mask
& CLASS_ZKICK
)) {
319 mh
.mh_Lower
= (void *)0x00200000;
320 Puts("ZKick detected.\n");
323 /* mask the memory limit values */
324 mh
.mh_Upper
= (void *)((u_long
)mh
.mh_Upper
& 0xfffff000);
325 mh
.mh_Lower
= (void *)((u_long
)mh
.mh_Lower
& 0xfffff000);
328 if (do_fast
&& mh
.mh_Attributes
& MEMF_FAST
) {
329 /* set the size value to the size of this block and mask off to a
331 u_long size
= ((u_long
)mh
.mh_Upper
-(u_long
)mh
.mh_Lower
)&0xfffc0000;
333 if (bi
.num_memory
< NUM_MEMINFO
) {
334 /* record the start and size */
335 bi
.memory
[bi
.num_memory
].addr
= (u_long
)mh
.mh_Lower
;
336 bi
.memory
[bi
.num_memory
].size
= size
;
337 /* count this block */
340 Printf("Warning: too many memory blocks. Ignoring block "
341 "of %ldK at 0x%08x\n", size
>>10,
342 (u_long
)mh
.mh_Lower
);
343 } else if (do_chip
&& mh
.mh_Attributes
& MEMF_CHIP
)
344 /* if CHIP memory, record the size */
345 bi
.chip_size
= (u_long
)mh
.mh_Upper
;
348 /* get info from ExecBase */
350 bi
.vblank
= SysBase
->VBlankFrequency
;
352 bi
.psfreq
= SysBase
->PowerSupplyFrequency
;
354 bi
.eclock
= SysBase
->ex_EClockFrequency
;
358 realbaud
= baud
? baud
: DEFAULT_BAUD
;
359 bi
.serper
= (5*bi
.eclock
+realbaud
/2)/realbaud
-1;
362 /* display Amiga model */
363 if (bi
.model
>= first_amiga_model
&& bi
.model
<= last_amiga_model
)
364 Printf("%s ", amiga_models
[bi
.model
-first_amiga_model
]);
368 /* display the CPU type */
370 switch (bi
.cputype
) {
372 Puts("68020 (Do you have an MMU?)");
384 Puts("Insufficient for Linux. Aborting...\n");
385 Printf("SysBase->AttnFlags = 0x%08lx\n", SysBase
->AttnFlags
);
388 switch (bi
.fputype
) {
390 Puts(" with 68881 FPU");
393 Puts(" with 68882 FPU");
397 Puts(" with internal FPU");
400 Puts(" without FPU");
404 /* display the chipset */
405 switch (bi
.chipset
) {
407 Puts(", old or unknown chipset");
416 Puts(", AGA chipset");
420 /* Look for PowerUp PCI bridge. Signal result to kernel in model type.
421 * Not pretty, but it'll do for now.
427 vbr
= (unsigned long) Supervisor((void*)&getvbr
);
428 if (probe_powerup(vbr
)) {
429 Puts("APUS: PCI Bridge detected.");
432 Puts("APUS: No PCI Bridge detected.");
438 /* display the command line */
439 Printf("Command line is '%s'\n", bi
.command_line
);
441 /* display the clock statistics */
442 Printf("Vertical Blank Frequency: %ldHz\n", bi
.vblank
);
443 Printf("Power Supply Frequency: %ldHz\n", bi
.psfreq
);
444 Printf("EClock Frequency: %ldHz\n\n", bi
.eclock
);
446 /* display autoconfig devices */
447 if (bi
.num_autocon
) {
448 Printf("Found %ld AutoConfig Device%s\n", bi
.num_autocon
,
449 bi
.num_autocon
> 1 ? "s" : "");
450 for (i
= 0; i
< bi
.num_autocon
; i
++) {
451 Printf("Device %ld: addr = 0x%08lx", i
,
452 (u_long
)zdevs
[i
]->cd_BoardAddr
);
453 boardresetfuncs
[i
] = NULL
;
455 manuf
= zdevs
[i
]->cd_Rom
.er_Manufacturer
;
456 prod
= zdevs
[i
]->cd_Rom
.er_Product
;
457 for (j
= 0; j
< NUM_BOARDRESET
; j
++)
458 if ((manuf
== boardresetdb
[j
].manuf
) &&
459 (prod
== boardresetdb
[j
].prod
)) {
460 Printf(" [%s - will be reset at kernel boot time]",
461 boardresetdb
[j
].name
);
462 boardresetfuncs
[i
] = boardresetdb
[j
].reset
;
469 Puts("No AutoConfig Devices Found\n");
473 Printf("\nFound %ld Block%sof Memory\n", bi
.num_memory
,
474 bi
.num_memory
> 1 ? "s " : " ");
475 for (i
= 0; i
< bi
.num_memory
; i
++)
476 Printf("Block %ld: 0x%08lx to 0x%08lx (%ldK)\n", i
,
477 bi
.memory
[i
].addr
, bi
.memory
[i
].addr
+bi
.memory
[i
].size
,
478 bi
.memory
[i
].size
>>10);
480 Puts("No memory found?! Aborting...\n");
484 /* display chip memory size */
485 Printf("%ldK of CHIP memory\n", bi
.chip_size
>>10);
487 start_mem
= bi
.memory
[0].addr
;
488 mem_size
= bi
.memory
[0].size
;
490 /* tell us where the kernel will go */
491 Printf("\nThe kernel will be located at 0x%08lx\n", start_mem
);
493 /* verify that there is enough Chip RAM */
494 if (bi
.chip_size
< 512*1024) {
495 Puts("Not enough Chip RAM in this system. Aborting...\n");
499 /* verify that there is enough Fast RAM */
500 for (fast_total
= 0, i
= 0; i
< bi
.num_memory
; i
++)
501 fast_total
+= bi
.memory
[i
].size
;
502 if (fast_total
< 2*1024*1024) {
503 Puts("Not enough Fast RAM in this system. Aborting...\n");
507 /* support for ramdisk */
511 if ((size
= FileSize(ramdiskname
)) == -1) {
512 Printf("Unable to find size of ramdisk file `%s'\n", ramdiskname
);
515 /* record ramdisk size */
516 bi
.ramdisk
.size
= size
;
519 rd_size
= bi
.ramdisk
.size
;
520 bi
.ramdisk
.addr
= (u_long
)start_mem
+mem_size
-rd_size
;
522 /* create the bootinfo structure */
523 if (!create_bootinfo())
526 /* open kernel executable and read exec header */
527 if ((kfd
= Open(kernelname
)) == -1) {
528 Printf("Unable to open kernel file `%s'\n", kernelname
);
531 if (KRead(kfd
, (void *)&kexec
, sizeof(kexec
)) != sizeof(kexec
)) {
532 Puts("Unable to read exec header from kernel file\n");
537 if (((unsigned char *)&kexec
)[0] == 037 &&
538 (((unsigned char *)&kexec
)[1] == 0213 ||
539 ((unsigned char *)&kexec
)[1] == 0236)) {
540 /* That's a compressed kernel */
541 Puts("Kernel is compressed\n");
542 if (load_zkernel(kfd
)) {
543 Puts("Decompression error -- aborting\n");
549 switch (N_MAGIC(kexec
)) {
552 Puts("\nLoading a.out (ZMAGIC) Linux/m68k kernel...\n");
553 text_offset
= N_TXTOFF(kexec
);
558 Puts("\nLoading a.out (QMAGIC) Linux/m68k kernel...\n");
559 text_offset
= sizeof(kexec
);
560 /* the text size includes the exec header; remove this */
561 kexec
.a_text
-= sizeof(kexec
);
565 /* Try to parse it as an ELF header */
567 if ((KRead(kfd
, (void *)&kexec_elf
, sizeof(kexec_elf
)) ==
568 sizeof(kexec_elf
)) &&
569 (memcmp(&kexec_elf
.e_ident
[EI_MAG0
], ELFMAG
, SELFMAG
) == 0)) {
572 Puts("\nLoading ELF Linux/m68k kernel...\n");
573 /* A few plausibility checks */
574 if ((kexec_elf
.e_type
!= ET_EXEC
) ||
575 (kexec_elf
.e_machine
!= EM_PPC
&& apus_boot
) ||
576 (kexec_elf
.e_machine
!= EM_68K
&& !apus_boot
) ||
577 (kexec_elf
.e_version
!= EV_CURRENT
)) {
578 Puts("Invalid ELF header contents in kernel\n");
579 Printf("machine : %d, type: %d, version: %d\n",
580 kexec_elf
.e_machine
, kexec_elf
.e_type
, kexec_elf
.e_version
);
583 /* Load the program headers */
585 (Elf32_Phdr
*)AllocMem(kexec_elf
.e_phnum
*sizeof(Elf32_Phdr
),
586 MEMF_FAST
| MEMF_PUBLIC
|
588 Puts("Unable to allocate memory for program headers\n");
591 KSeek(kfd
, kexec_elf
.e_phoff
);
592 if (KRead(kfd
, (void *)kernel_phdrs
,
593 kexec_elf
.e_phnum
*sizeof(*kernel_phdrs
)) !=
594 kexec_elf
.e_phnum
*sizeof(*kernel_phdrs
)) {
595 Puts("Unable to read program headers from kernel file\n");
600 Printf("Wrong magic number 0x%08lx in kernel header\n",
605 /* Load the kernel at one page after start of mem */
607 start_mem
+= PAGE_SIZE
;
608 mem_size
-= PAGE_SIZE
;
611 /* Align bss size to multiple of four */
613 kexec
.a_bss
= (kexec
.a_bss
+3) & ~3;
615 /* calculate the total required amount of memory */
617 u_long min_addr
= 0xffffffff, max_addr
= 0;
618 for (i
= 0; i
< kexec_elf
.e_phnum
; i
++) {
619 if (min_addr
> kernel_phdrs
[i
].p_vaddr
)
620 min_addr
= kernel_phdrs
[i
].p_vaddr
;
621 if (max_addr
< kernel_phdrs
[i
].p_vaddr
+kernel_phdrs
[i
].p_memsz
)
622 max_addr
= kernel_phdrs
[i
].p_vaddr
+kernel_phdrs
[i
].p_memsz
;
624 /* This is needed for newer linkers that include the header in
625 the first segment. */
627 /* Avoid ugly hacks further down. */
628 kernel_phdrs
[0].p_vaddr
= PAGE_SIZE
;
629 } else if (min_addr
== 0) {
630 min_addr
= PAGE_SIZE
;
631 kernel_phdrs
[0].p_vaddr
+= PAGE_SIZE
;
632 kernel_phdrs
[0].p_offset
+= PAGE_SIZE
;
633 kernel_phdrs
[0].p_filesz
-= PAGE_SIZE
;
634 kernel_phdrs
[0].p_memsz
-= PAGE_SIZE
;
636 kernel_size
= max_addr
-min_addr
;
638 kernel_size
= kexec
.a_text
+kexec
.a_data
+kexec
.a_bss
;
639 memreq
= kernel_size
+bi_size
+rd_size
;
640 #ifdef BOOTINFO_COMPAT_1_0
641 if (sizeof(compat_bootinfo
) > bi_size
)
642 memreq
= kernel_size
+sizeof(compat_bootinfo
)+rd_size
;
643 #endif /* BOOTINFO_COMPAT_1_0 */
644 if (!(memptr
= (char *)AllocMem(memreq
, MEMF_FAST
| MEMF_PUBLIC
|
646 Puts("Unable to allocate memory\n");
650 /* read the text and data segments from the kernel image */
652 for (i
= 0; i
< kexec_elf
.e_phnum
; i
++) {
653 if (KSeek(kfd
, kernel_phdrs
[i
].p_offset
) == -1) {
654 Printf("Failed to seek to segment %ld\n", i
);
657 if (KRead(kfd
, memptr
+kernel_phdrs
[i
].p_vaddr
-PAGE_SIZE
,
658 kernel_phdrs
[i
].p_filesz
) != kernel_phdrs
[i
].p_filesz
) {
659 Printf("Failed to read segment %ld\n", i
);
664 if (KSeek(kfd
, text_offset
) == -1) {
665 Puts("Failed to seek to text\n");
668 if (KRead(kfd
, memptr
, kexec
.a_text
) != kexec
.a_text
) {
669 Puts("Failed to read text\n");
672 /* data follows immediately after text */
673 if (KRead(kfd
, memptr
+kexec
.a_text
, kexec
.a_data
) != kexec
.a_data
) {
674 Puts("Failed to read data\n");
681 /* Check kernel's bootinfo version */
682 switch (apus_boot
? BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION
) :
683 check_bootinfo_version(memptr
)) {
684 case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION
):
685 bi_ptr
= &bi_union
.record
;
688 #ifdef BOOTINFO_COMPAT_1_0
689 case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION
):
690 if (!create_compat_bootinfo())
692 bi_ptr
= &compat_bootinfo
;
693 bi_size
= sizeof(compat_bootinfo
);
695 #endif /* BOOTINFO_COMPAT_1_0 */
701 /* copy the bootinfo to the end of the kernel image */
702 memcpy((void *)(memptr
+kernel_size
), bi_ptr
, bi_size
);
705 if ((rfd
= Open(ramdiskname
)) == -1) {
706 Printf("Unable to open ramdisk file `%s'\n", ramdiskname
);
709 if (Read(rfd
, memptr
+kernel_size
+bi_size
, rd_size
) != rd_size
) {
710 Puts("Failed to read ramdisk file\n");
717 /* allocate temporary chip ram stack */
718 if (!(stack
= (u_long
*)AllocMem(TEMP_STACKSIZE
, MEMF_CHIP
| MEMF_CLEAR
))) {
719 Puts("Unable to allocate memory for stack\n");
723 /* allocate chip ram for copy of startup code */
724 startcodesize
= ©allend
-©all
;
725 if (!(startfunc
= (void (*)(void))AllocMem(startcodesize
,
726 MEMF_CHIP
| MEMF_CLEAR
))) {
727 Puts("Unable to allocate memory for startcode\n");
731 /* copy startup code to CHIP RAM */
732 memcpy(startfunc
, ©all
, startcodesize
);
736 Printf("RAM disk at 0x%08lx, size is %ldK\n",
737 (u_long
)memptr
+kernel_size
, bi
.ramdisk
.size
>>10);
741 for (i
= 0; i
< kexec_elf
.e_phnum
; i
++)
742 Printf("Kernel segment %ld at 0x%08lx, size %ld\n", i
,
743 start_mem
+kernel_phdrs
[i
].p_vaddr
-PAGE_SIZE
,
744 kernel_phdrs
[i
].p_memsz
);
745 Printf("Boot info at 0x%08lx\n", start_mem
+kernel_size
);
747 Printf("\nKernel text at 0x%08lx, code size 0x%08lx\n", start_mem
,
749 Printf("Kernel data at 0x%08lx, data size 0x%08lx\n",
750 start_mem
+kexec
.a_text
, kexec
.a_data
);
751 Printf("Kernel bss at 0x%08lx, bss size 0x%08lx\n",
752 start_mem
+kexec
.a_text
+kexec
.a_data
, kexec
.a_bss
);
753 Printf("Boot info at 0x%08lx\n", start_mem
+kernel_size
);
755 Printf("\nKernel entry is 0x%08lx\n", elf_kernel
? kexec_elf
.e_entry
:
758 Printf("ramdisk dest top is 0x%08lx\n", start_mem
+mem_size
);
759 Printf("ramdisk lower limit is 0x%08lx\n",
760 (u_long
)(memptr
+kernel_size
));
761 Printf("ramdisk src top is 0x%08lx\n",
762 (u_long
)(memptr
+kernel_size
)+rd_size
);
764 Puts("\nType a key to continue the Linux/m68k boot...");
769 /* wait for things to settle down */
777 #define CHIP_PTR (0xfff00)
778 #define INFO_SIZE (0x3000 + 0x0100)
780 /* Let the PowerPC handle the actual kernel start */
782 /* Store some relevant information about the kernel image
783 * and RAM disk at *CHIP_PTR.
785 unsigned long boot_msg
;
787 /* Make sure the CHIP_PTR will not be destroyed. */
788 if (!AllocAbs (0x10, CHIP_PTR
)){
789 Puts("Unable to allocate CHIP memory at 0xfff00.\n"
790 "Try booting with a smaller resolution.\n");
793 if (!(boot_msg
= (unsigned long) AllocMem (0x200,
798 Puts("Unable to allocate CHIP memory for boot message\n");
802 if (!(info
= (unsigned long*) AllocMem (INFO_SIZE
,
803 MEMF_CHIP
| MEMF_CLEAR
))){
804 Puts("Unable to allocate CHIP memory for info table and"
809 /* Leave the pointer in chip mem at address CHIP_PTR. */
810 *((unsigned long*) CHIP_PTR
) = (unsigned long) info
;
811 info
[0] = (unsigned long) (memptr
+kernel_phdrs
[0].p_vaddr
-PAGE_SIZE
);
813 info
[2] = kernel_size
;
817 info
[6] = boot_msg
+ 0x100;
818 info
[7] = 0; /* checksum */
819 info
[8] = (unsigned long)info
+ 0x2000; /* stack */
821 /* Calculate a simple kernel checksum. */
824 int i
= (info
[2] + info
[3]) / 4;
825 unsigned char* k_p
= (unsigned char*) info
[0];
826 unsigned long kcs
= 0;
847 /* Set LVL7 vector ("expose the top rim of our shorts") */
851 vbr
= (unsigned long*) Supervisor((void*)&getvbr
);
852 vbr
[31] = (unsigned long) &wedgie
;
859 struct TagItem MyTags
[2];
862 /* Load PPC elf object. */
863 MyTags
[0].ti_Tag
= PPCELFLOADTAG_ELFADDRESS
;
864 MyTags
[0].ti_Data
= (u_long
)myppc_boot
;
865 MyTags
[1].ti_Tag
= TAG_DONE
;
867 elfObject
= (void*) PPCLoadObjectTagList(MyTags
);
869 /* Start PPC code, asking for a MSGPORT to be created. */
870 MyTags
[0].ti_Tag
= PPCTASKTAG_MSGPORT
;
871 MyTags
[0].ti_Data
= TRUE
;
872 MyTags
[1].ti_Tag
= TAG_DONE
;
873 task
= PPCCreateTask(elfObject
, MyTags
);
875 tag
.ti_Tag
= PPCTASKINFOTAG_MSGPORT
;
876 if (PPCPort
=(void*) PPCGetTaskAttrs(task
, &tag
))
878 PPCMsg
= PPCCreateMessage(NULL
, 0);
882 if (PPCPort
== 0 || PPCMsg
== 0)
884 Puts ("Didn't get contact with PPC task...\n");
890 /* turn off caches */
894 /* set graphics mode to a nice normal one */
897 /* reset nasty Zorro boards */
899 for (i
= 0; i
< bi
.num_autocon
; i
++)
900 if (boardresetfuncs
[i
])
901 boardresetfuncs
[i
](zdevs
[i
]);
903 if (apus_boot
&& PPCPort
&& PPCMsg
)
905 /* Notify the PPC that we are done ("bend over") */
906 PPCSendMessage(PPCPort
, PPCMsg
, NULL
, 0, 0);
910 /* Go into supervisor state */
914 /* Turn off interrupts. */
917 /* Turn off all DMA */
918 custom
.dmacon
= DMAF_ALL
| DMAF_MASTER
;
920 /* turn off any mmu translation */
923 /* execute the copy-and-go code (from CHIP RAM) */
924 start_kernel(startfunc
, (char *)stack
+TEMP_STACKSIZE
, memptr
, start_mem
,
925 mem_size
, rd_size
, kernel_size
);
927 /* Clean up and exit in case of a failure */
934 FreeMem((void *) info
, INFO_SIZE
);
936 FreeMem((void *)memptr
, memreq
);
938 FreeMem((void *)stack
, TEMP_STACKSIZE
);
940 FreeMem((void *)kernel_phdrs
, kexec_elf
.e_phnum
*sizeof(Elf32_Phdr
));
946 * Determine the Chipset
949 static u_long
get_chipset(void)
954 if (GfxBase
->Version
>= 39)
955 cs
= SetChipRev(SETCHIPREV_BEST
);
957 cs
= GfxBase
->ChipRevBits0
;
958 if ((cs
& GFXG_AGA
) == GFXG_AGA
)
960 else if ((cs
& GFXG_ECS
) == GFXG_ECS
)
962 else if ((cs
& GFXG_OCS
) == GFXG_OCS
)
965 chipset
= CS_STONEAGE
;
971 * Determine the CPU Type
974 static void get_processor(u_long
*cpu
, u_long
*fpu
, u_long
*mmu
)
978 if (SysBase
->AttnFlags
& AFF_68060
)
980 else if (SysBase
->AttnFlags
& AFF_68040
)
982 else if (SysBase
->AttnFlags
& AFF_68030
)
984 else if (SysBase
->AttnFlags
& AFF_68020
)
987 if (*cpu
== CPU_68040
|| *cpu
== CPU_68060
) {
988 if (SysBase
->AttnFlags
& AFF_FPU40
)
990 } else if (SysBase
->AttnFlags
& AFF_68882
)
992 else if (SysBase
->AttnFlags
& AFF_68881
)
999 * Determine the Amiga Model
1002 static u_long
get_model(u_long chipset
)
1004 u_long model
= AMI_UNKNOWN
;
1007 Puts("Amiga model identification:\n");
1008 if (probe_resource("draco.resource"))
1016 Puts("Old or unknown\n");
1023 OCS
: if (probe_resident("cd.device"))
1026 /* let's call it an A2000 (may be A500, A1000, A2500) */
1033 if (probe_resident("Magic 36.7") ||
1034 probe_resident("kickad 36.57") ||
1035 probe_resident("A3000 Bonus") ||
1036 probe_resident("A3000 bonus"))
1037 /* let's call it an A3000 (may be A3000T) */
1039 else if (probe_resource("card.resource"))
1042 /* let's call it an A2000 (may be A500[+], A1000, A2500) */
1049 if (probe_resident("A1000 Bonus") ||
1050 probe_resident("A4000 bonus"))
1051 model
= probe_resident("NCR scsi.device") ? AMI_4000T
:
1053 else if (probe_resource("card.resource"))
1055 else if (probe_resident("cd.device"))
1058 model
= AMI_3000PLUS
;
1063 Puts("\nType a key to continue...");
1072 * Probe for a Resident Modules
1075 static int probe_resident(const char *name
)
1077 const struct Resident
*res
;
1080 Printf(" Module `%s': ", name
);
1081 res
= FindResident(name
);
1084 Printf("0x%08lx\n", res
);
1086 Puts("not present\n");
1087 return(res
? TRUE
: FALSE
);
1092 * Probe for an available Resource
1095 static int probe_resource(const char *name
)
1100 Printf(" Resource `%s': ", name
);
1101 res
= OpenResource(name
);
1104 Printf("0x%08lx\n", res
);
1106 Puts("not present\n");
1107 return(res
? TRUE
: FALSE
);
1112 * Create the Bootinfo structure
1115 static int create_bootinfo(void)
1118 struct bi_record
*record
;
1120 /* Initialization */
1124 if (!add_bi_record(BI_MACHTYPE
, sizeof(bi
.machtype
), &bi
.machtype
))
1126 if (!add_bi_record(BI_CPUTYPE
, sizeof(bi
.cputype
), &bi
.cputype
))
1128 if (!add_bi_record(BI_FPUTYPE
, sizeof(bi
.fputype
), &bi
.fputype
))
1130 if (!add_bi_record(BI_MMUTYPE
, sizeof(bi
.mmutype
), &bi
.mmutype
))
1132 for (i
= 0; i
< bi
.num_memory
; i
++)
1133 if (!add_bi_record(BI_MEMCHUNK
, sizeof(bi
.memory
[i
]), &bi
.memory
[i
]))
1135 if (bi
.ramdisk
.size
)
1136 if (!add_bi_record(BI_RAMDISK
, sizeof(bi
.ramdisk
), &bi
.ramdisk
))
1138 if (!add_bi_string(BI_COMMAND_LINE
, bi
.command_line
))
1142 if (!add_bi_record(BI_AMIGA_MODEL
, sizeof(bi
.model
), &bi
.model
))
1144 for (i
= 0; i
< bi
.num_autocon
; i
++)
1145 if (!add_bi_record(BI_AMIGA_AUTOCON
, sizeof(bi
.autocon
[i
]),
1148 if (!add_bi_record(BI_AMIGA_CHIP_SIZE
, sizeof(bi
.chip_size
), &bi
.chip_size
))
1150 if (!add_bi_record(BI_AMIGA_VBLANK
, sizeof(bi
.vblank
), &bi
.vblank
))
1152 if (!add_bi_record(BI_AMIGA_PSFREQ
, sizeof(bi
.psfreq
), &bi
.psfreq
))
1154 if (!add_bi_record(BI_AMIGA_ECLOCK
, sizeof(bi
.eclock
), &bi
.eclock
))
1156 if (!add_bi_record(BI_AMIGA_CHIPSET
, sizeof(bi
.chipset
), &bi
.chipset
))
1158 if (!add_bi_record(BI_AMIGA_SERPER
, sizeof(bi
.serper
), &bi
.serper
))
1162 record
= (struct bi_record
*)((u_long
)&bi_union
.record
+bi_size
);
1163 record
->tag
= BI_LAST
;
1164 bi_size
+= sizeof(bi_union
.record
.tag
);
1171 * Add a Record to the Bootinfo Structure
1174 static int add_bi_record(u_short tag
, u_short size
, const void *data
)
1176 struct bi_record
*record
;
1179 size2
= (sizeof(struct bi_record
)+size
+3)&-4;
1180 if (bi_size
+size2
+sizeof(bi_union
.record
.tag
) > MAX_BI_SIZE
) {
1181 Puts("Can't add bootinfo record. Ask a wizard to enlarge me.\n");
1184 record
= (struct bi_record
*)((u_long
)&bi_union
.record
+bi_size
);
1186 record
->size
= size2
;
1187 memcpy(record
->data
, data
, size
);
1194 * Add a String Record to the Bootinfo Structure
1197 static int add_bi_string(u_short tag
, const u_char
*s
)
1199 return(add_bi_record(tag
, strlen(s
)+1, (void *)s
));
1203 #ifdef BOOTINFO_COMPAT_1_0
1206 * Create the Bootinfo structure for backwards compatibility mode
1209 static int create_compat_bootinfo(void)
1213 compat_bootinfo
.machtype
= bi
.machtype
;
1214 if (bi
.cputype
& CPU_68020
)
1215 compat_bootinfo
.cputype
= COMPAT_CPU_68020
;
1216 else if (bi
.cputype
& CPU_68030
)
1217 compat_bootinfo
.cputype
= COMPAT_CPU_68030
;
1218 else if (bi
.cputype
& CPU_68040
)
1219 compat_bootinfo
.cputype
= COMPAT_CPU_68040
;
1220 else if (bi
.cputype
& CPU_68060
)
1221 compat_bootinfo
.cputype
= COMPAT_CPU_68060
;
1223 Printf("CPU type 0x%08lx not supported by kernel\n", bi
.cputype
);
1226 if (bi
.fputype
& FPU_68881
)
1227 compat_bootinfo
.cputype
|= COMPAT_FPU_68881
;
1228 else if (bi
.fputype
& FPU_68882
)
1229 compat_bootinfo
.cputype
|= COMPAT_FPU_68882
;
1230 else if (bi
.fputype
& FPU_68040
)
1231 compat_bootinfo
.cputype
|= COMPAT_FPU_68040
;
1232 else if (bi
.fputype
& FPU_68060
)
1233 compat_bootinfo
.cputype
|= COMPAT_FPU_68060
;
1234 else if (bi
.fputype
) {
1235 Printf("FPU type 0x%08lx not supported by kernel\n", bi
.fputype
);
1238 compat_bootinfo
.num_memory
= bi
.num_memory
;
1239 if (compat_bootinfo
.num_memory
> COMPAT_NUM_MEMINFO
) {
1240 Printf("Warning: using only %ld blocks of memory\n",
1241 COMPAT_NUM_MEMINFO
);
1242 compat_bootinfo
.num_memory
= COMPAT_NUM_MEMINFO
;
1244 for (i
= 0; i
< compat_bootinfo
.num_memory
; i
++) {
1245 compat_bootinfo
.memory
[i
].addr
= bi
.memory
[i
].addr
;
1246 compat_bootinfo
.memory
[i
].size
= bi
.memory
[i
].size
;
1248 if (bi
.ramdisk
.size
) {
1249 compat_bootinfo
.ramdisk_size
= (bi
.ramdisk
.size
+1023)/1024;
1250 compat_bootinfo
.ramdisk_addr
= bi
.ramdisk
.addr
;
1252 compat_bootinfo
.ramdisk_size
= 0;
1253 compat_bootinfo
.ramdisk_addr
= 0;
1255 strncpy(compat_bootinfo
.command_line
, bi
.command_line
, COMPAT_CL_SIZE
);
1256 compat_bootinfo
.command_line
[COMPAT_CL_SIZE
-1] = '\0';
1258 compat_bootinfo
.bi_amiga
.model
= bi
.model
;
1259 compat_bootinfo
.bi_amiga
.num_autocon
= bi
.num_autocon
;
1260 if (compat_bootinfo
.bi_amiga
.num_autocon
> COMPAT_NUM_AUTO
) {
1261 Printf("Warning: using only %ld AutoConfig devices\n",
1263 compat_bootinfo
.bi_amiga
.num_autocon
= COMPAT_NUM_AUTO
;
1265 for (i
= 0; i
< compat_bootinfo
.bi_amiga
.num_autocon
; i
++)
1266 compat_bootinfo
.bi_amiga
.autocon
[i
] = bi
.autocon
[i
];
1267 compat_bootinfo
.bi_amiga
.chip_size
= bi
.chip_size
;
1268 compat_bootinfo
.bi_amiga
.vblank
= bi
.vblank
;
1269 compat_bootinfo
.bi_amiga
.psfreq
= bi
.psfreq
;
1270 compat_bootinfo
.bi_amiga
.eclock
= bi
.eclock
;
1271 compat_bootinfo
.bi_amiga
.chipset
= bi
.chipset
;
1272 compat_bootinfo
.bi_amiga
.hw_present
= 0;
1275 #endif /* BOOTINFO_COMPAT_1_0 */
1279 * Compare the Bootstrap and Kernel Versions
1282 static int check_bootinfo_version(const char *memptr
)
1284 const struct bootversion
*bv
= (struct bootversion
*)memptr
;
1285 unsigned long version
= 0;
1286 int i
, kernel_major
, kernel_minor
, boots_major
, boots_minor
;
1288 if (bv
->magic
== BOOTINFOV_MAGIC
)
1289 for (i
= 0; bv
->machversions
[i
].machtype
!= 0; ++i
)
1290 if (bv
->machversions
[i
].machtype
== MACH_AMIGA
) {
1291 version
= bv
->machversions
[i
].version
;
1295 Puts("Kernel has no bootinfo version info, assuming 0.0\n");
1297 kernel_major
= BI_VERSION_MAJOR(version
);
1298 kernel_minor
= BI_VERSION_MINOR(version
);
1299 boots_major
= BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION
);
1300 boots_minor
= BI_VERSION_MINOR(AMIGA_BOOTI_VERSION
);
1301 Printf("Bootstrap's bootinfo version: %ld.%ld\n", boots_major
,
1303 Printf("Kernel's bootinfo version : %ld.%ld\n", kernel_major
,
1306 switch (kernel_major
) {
1307 case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION
):
1308 if (kernel_minor
> boots_minor
) {
1309 Puts("Warning: Bootinfo version of bootstrap and kernel "
1311 Puts(" Certain features may not work.\n");
1315 #ifdef BOOTINFO_COMPAT_1_0
1316 case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION
):
1317 Puts("(using backwards compatibility mode)\n");
1319 #endif /* BOOTINFO_COMPAT_1_0 */
1322 Printf("\nThis bootstrap is too %s for this kernel!\n",
1323 boots_major
< kernel_major
? "old" : "new");
1326 return(kernel_major
);
1331 * Call the copy-and-go-code
1334 static void start_kernel(void (*startfunc
)(), char *stackp
, char *memptr
,
1335 u_long start_mem
, u_long mem_size
, u_long rd_size
,
1338 register void (*a0
)() __asm("a0") = startfunc
;
1339 register char *a2
__asm("a2") = stackp
;
1340 register char *a3
__asm("a3") = memptr
;
1341 register u_long a4
__asm("a4") = start_mem
;
1342 register u_long d0
__asm("d0") = mem_size
;
1343 register u_long d1
__asm("d1") = rd_size
;
1344 register u_long d2
__asm("d2") = kernel_size
;
1345 register u_long d3
__asm("d3") = bi_size
;
1347 __asm
__volatile ("movel a2,sp;"
1350 : "r" (a0
), "r" (a2
), "r" (a3
), "r" (a4
), "r" (d0
),
1351 "r" (d1
), "r" (d2
), "r" (d3
)
1353 /* fake a noreturn */
1359 SYMBOL_NAME_STR(_getvbr
) ":
1365 /* LPSTOP cannot be used on the 68060. Apparently the
1366 CyberStorm bus design cannot cope with it.*/
1367 /* Just let the 68k hang for now. */
1370 SYMBOL_NAME_STR(_wedgie
) ":
1377 SYMBOL_NAME_STR(_probe_powerup
) ":
1378 moveml d2/a5/a6,a7@-
1411 moveml a7@+,d2/a5/a6
1423 * This assembler code is copied to chip ram, and then executed.
1424 * It copies the kernel to it's final resting place.
1426 * It is called with:
1438 SYMBOL_NAME_STR(_copyall
) ":
1439 | /* copy kernel text and data */
1440 movel a3,a0 | src = (u_long *)memptr;
1441 movel a0,a2 | limit = (u_long *)(memptr+kernel_size);
1443 movel a4,a1 | dest = (u_long *)start_mem;
1445 jeq 2f | while (src < limit)
1446 moveb a0@+,a1@+ | *dest++ = *src++;
1449 | /* copy bootinfo to end of bss */
1450 movel a3,a0 | src = (u_long *)(memptr+kernel_size);
1451 addl d2,a0 | dest = end of bss (already in a1)
1452 movel d3,d7 | count = bi_size
1454 1: moveb a0@+,a1@+ | while (--count > -1)
1455 dbra d7,1b | *dest++ = *src++
1457 | /* copy the ramdisk to the top of memory */
1458 | /* (from back to front) */
1459 movel a4,a1 | dest = (u_long *)(start_mem+mem_size);
1461 movel a3,a2 | limit = (u_long *)(memptr+kernel_size +
1462 addl d2,a2 | bi_size);
1464 movel a2,a0 | src = (u_long *)((u_long)limit+rd_size);
1467 beqs 2f | while (src > limit)
1468 moveb a0@-,a1@- | *--dest = *--src;
1471 | /* jump to start of kernel */
1472 movel a4,a0 | jump_to (start_mem);
1475 SYMBOL_NAME_STR(_copyallend
) ":
1480 * Test for a MapROMmed A3640 Board
1485 SYMBOL_NAME_STR(_maprommed
) ":
1488 | /* Save cache settings */
1489 .long 0x4e7a1002 | movec cacr,d1 */
1490 | /* Save MMU settings */
1491 .long 0x4e7a2003 | movec tc,d2
1492 .long 0x4e7a3004 | movec itt0,d3
1493 .long 0x4e7a4005 | movec itt1,d4
1494 .long 0x4e7a5006 | movec dtt0,d5
1495 .long 0x4e7a6007 | movec dtt1,d6
1498 | /* Disable caches */
1499 .long 0x4e7b0002 | movec d0,cacr
1501 .long 0x4e7b0003 | movec d0,tc
1502 .long 0x4e7b0004 | movec d0,itt0
1503 .long 0x4e7b0005 | movec d0,itt1
1504 .long 0x4e7b0006 | movec d0,dtt0
1505 .long 0x4e7b0007 | movec d0,dtt1
1514 nop | /* Thanks to Jörg Mayer! */
1517 moveq #-1,d0 | /* MapROMmed A3640 present */
1520 | /* Restore MMU settings */
1521 .long 0x4e7b2003 | movec d2,tc
1522 .long 0x4e7b3004 | movec d3,itt0
1523 .long 0x4e7b4005 | movec d4,itt1
1524 .long 0x4e7b5006 | movec d5,dtt0
1525 .long 0x4e7b6007 | movec d6,dtt1
1526 | /* Restore cache settings */
1527 .long 0x4e7b1002 | movec d1,cacr
1535 * Reset functions for nasty Zorro boards
1538 static void reset_rb3(const struct ConfigDev
*cd
)
1540 volatile u_char
*rb3_reg
= (u_char
*)(cd
->cd_BoardAddr
+0x01002000);
1542 /* FN: If a Rainbow III board is present, reset it to disable */
1543 /* its (possibly activated) vertical blank interrupts as the */
1544 /* kernel is not yet prepared to handle them (level 6). */
1546 /* set RESET bit in special function register */
1548 /* actually, only a few cycles delay are required... */
1550 /* clear reset bit */
1554 static void reset_piccolo(const struct ConfigDev
*cd
)
1556 volatile u_char
*piccolo_reg
= (u_char
*)(cd
->cd_BoardAddr
+0x8000);
1558 /* FN: the same stuff as above, for the Piccolo board. */
1559 /* this also has the side effect of resetting the board's */
1560 /* output selection logic to use the Amiga's display in single */
1561 /* monitor systems - which is currently what we want. */
1563 /* set RESET bit in special function register */
1564 *piccolo_reg
= 0x01;
1565 /* actually, only a few cycles delay are required... */
1567 /* clear reset bit */
1568 *piccolo_reg
= 0x51;
1571 static void reset_sd64(const struct ConfigDev
*cd
)
1573 volatile u_char
*sd64_reg
= (u_char
*)(cd
->cd_BoardAddr
+0x8000);
1575 /* FN: the same stuff as above, for the SD64 board. */
1576 /* just as on the Piccolo, this also resets the monitor switch */
1578 /* set RESET bit in special function register */
1580 /* actually, only a few cycles delay are required... */
1582 /* clear reset bit AND switch monitor bit (0x20) */
1586 static void reset_a2065(const struct ConfigDev
*cd
)
1588 volatile u_short
*lance_rdp
= (u_short
*)(cd
->cd_BoardAddr
+0x4000);
1589 volatile u_short
*lance_rap
= (u_short
*)(cd
->cd_BoardAddr
+0x4002);
1594 *lance_rap
= 0; /* PCnet-ISA Controller Status (CSR0) */
1595 *lance_rdp
= 4; /* STOP */
1600 static void reset_ariadne(const struct ConfigDev
*cd
)
1602 volatile u_short
*lance_rdp
= (u_short
*)(cd
->cd_BoardAddr
+0x0370);
1603 volatile u_short
*lance_rap
= (u_short
*)(cd
->cd_BoardAddr
+0x0372);
1604 volatile u_short
*lance_reset
= (u_short
*)(cd
->cd_BoardAddr
+0x0374);
1606 volatile u_char
*pit_paddr
= (u_char
*)(cd
->cd_BoardAddr
+0x1004);
1607 volatile u_char
*pit_pbddr
= (u_char
*)(cd
->cd_BoardAddr
+0x1006);
1608 volatile u_char
*pit_pacr
= (u_char
*)(cd
->cd_BoardAddr
+0x100b);
1609 volatile u_char
*pit_pbcr
= (u_char
*)(cd
->cd_BoardAddr
+0x100e);
1610 volatile u_char
*pit_psr
= (u_char
*)(cd
->cd_BoardAddr
+0x101a);
1617 * Reset the Ethernet part (Am79C960 PCnet-ISA)
1620 in
= *lance_reset
; /* Reset Chip on Read Access */
1621 *lance_rap
= 0x0000; /* PCnet-ISA Controller Status (CSR0) */
1622 *lance_rdp
= 0x0400; /* STOP */
1625 * Reset the Parallel part (MC68230 PI/T)
1628 *pit_pacr
&= 0xfd; /* Port A Control Register */
1629 *pit_pbcr
&= 0xfd; /* Port B Control Register */
1630 *pit_psr
= 0x05; /* Port Status Register */
1631 *pit_paddr
= 0x00; /* Port A Data Direction Register */
1632 *pit_pbddr
= 0x00; /* Port B Data Direction Register */
1637 static void reset_hydra(const struct ConfigDev
*cd
)
1639 volatile u_char
*nic_cr
= (u_char
*)(cd
->cd_BoardAddr
+0xffe1);
1640 volatile u_char
*nic_isr
= (u_char
*)(cd
->cd_BoardAddr
+0xffe1 + 14);
1645 *nic_cr
= 0x21; /* nic command register: software reset etc. */
1646 while (((*nic_isr
& 0x80) == 0) && --n
) /* wait for reset to complete */
1653 static void reset_a2060(const struct ConfigDev
*cd
)
1655 #error reset_a2060: not yet implemented
1662 #define ZFILE_CHUNK_BITS 16 /* chunk is 64 KB */
1663 #define ZFILE_CHUNK_SIZE (1 << ZFILE_CHUNK_BITS)
1664 #define ZFILE_CHUNK_MASK (ZFILE_CHUNK_SIZE-1)
1665 #define ZFILE_N_CHUNKS (2*1024*1024/ZFILE_CHUNK_SIZE)
1667 /* variables for storing the uncompressed data */
1668 static char *ZFile
[ZFILE_N_CHUNKS
];
1669 static int ZFileSize
= 0;
1670 static int ZFpos
= 0;
1671 static int Zwpos
= 0;
1673 static int Zinfd
= 0; /* fd of compressed file */
1679 #define OF(args) args
1681 #define memzero(s, n) memset ((s), 0, (n))
1683 typedef unsigned char uch
;
1684 typedef unsigned short ush
;
1685 typedef unsigned long ulg
;
1687 #define INBUFSIZ 4096
1688 #define WSIZE 0x8000 /* window size--must be a power of two, and */
1689 /* at least 32K for zip's deflate method */
1694 static unsigned insize
= 0; /* valid bytes in inbuf */
1695 static unsigned inptr
= 0; /* index of next byte to be processed in inbuf */
1696 static unsigned outcnt
= 0; /* bytes in output buffer */
1697 static int exit_code
= 0;
1698 static long bytes_out
= 0;
1700 #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
1702 /* Diagnostic functions (stubbed out) */
1703 #define Assert(cond,msg)
1708 #define Tracecv(c,x)
1710 #define STATIC static
1712 static int fill_inbuf(void);
1713 static void flush_window(void);
1714 static void error(char *m
);
1715 static void gzip_mark(void **);
1716 static void gzip_release(void **);
1718 #define malloc(x) AllocVec(x, MEMF_FAST | MEMF_PUBLIC)
1719 #define free(x) FreeVec(x)
1722 #include "inflate.c"
1724 #include "../../../../lib/inflate.c"
1727 static void gzip_mark(void **ptr
)
1731 static void gzip_release(void **ptr
)
1737 * Fill the input buffer. This is called only when the buffer is empty
1738 * and at least one byte is really needed.
1740 static int fill_inbuf(void)
1745 insize
= Read(Zinfd
, inbuf
, INBUFSIZ
);
1754 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
1755 * (Used for the decompressed data only.)
1757 static void flush_window(void)
1759 ulg c
= crc
; /* temporary variable */
1762 int chunk
= Zwpos
>> ZFILE_CHUNK_BITS
;
1767 if (chunk
>= ZFILE_N_CHUNKS
) {
1768 error("Compressed image too large! Aborting.\n");
1771 if (!ZFile
[chunk
]) {
1772 if (!(ZFile
[chunk
] = (char *)AllocMem(ZFILE_CHUNK_SIZE
,
1773 MEMF_FAST
| MEMF_PUBLIC
))) {
1774 error("Out of memory for decompresing kernel image\n");
1778 memcpy(ZFile
[chunk
] + (Zwpos
& ZFILE_CHUNK_MASK
), window
, outcnt
);
1781 #define DISPLAY_BITS 10
1782 if ((Zwpos
& ((1 << DISPLAY_BITS
)-1)) == 0)
1786 for (n
= 0; n
< outcnt
; n
++) {
1788 c
= crc_32_tab
[((int)c
^ ch
) & 0xff] ^ (c
>> 8);
1791 bytes_out
+= (ulg
)outcnt
;
1795 static void error(char *x
)
1801 static inline int call_sub(int (*func
)(void), void *stackp
)
1803 register int _res
__asm("d0");
1804 register int (*a0
)(void) __asm("a0") = func
;
1805 register int (*a1
)(void) __asm("a1") = stackp
;
1807 __asm
__volatile ("movel sp,a2;"
1812 : "r" (a0
), "r" (a1
)
1813 : "a0", "a1", "a2", "d0", "d1", "memory");
1817 static int load_zkernel(int fd
)
1820 #define ZSTACKSIZE (16384)
1823 for (i
= 0; i
< ZFILE_N_CHUNKS
; ++i
)
1828 if (!(inbuf
= (uch
*)AllocMem(INBUFSIZ
, MEMF_FAST
| MEMF_PUBLIC
)))
1829 Puts("Couldn't allocate gunzip buffer\n");
1831 if (!(window
= (uch
*)AllocMem(WSIZE
, MEMF_FAST
| MEMF_PUBLIC
)))
1832 Puts("Couldn't allocate gunzip window\n");
1834 if (!(zstack
= (u_long
*)AllocMem(ZSTACKSIZE
,
1835 MEMF_FAST
| MEMF_PUBLIC
)))
1836 Puts("Couldn't allocate gunzip stack\n");
1838 Puts("Uncompressing kernel image ");
1840 if (!(err
= call_sub(gunzip
, (char *)zstack
+ZSTACKSIZE
)))
1843 FreeMem(zstack
, ZSTACKSIZE
);
1845 FreeMem(window
, WSIZE
);
1848 FreeMem(inbuf
, INBUFSIZ
);
1851 Close(Zinfd
); /* input file not needed anymore */
1856 /* Note about the read/lseek wrapper and its memory management: It assumes
1857 * that all seeks are only forward, and thus data already read or skipped can
1858 * be freed. This is true for current organization of bootstrap and kernels.
1859 * Little exception: The struct kexec at the start of the file. After reading
1860 * it, there may be a seek back to the end of the file. But this currently
1861 * doesn't hurt. (Roman)
1864 static int KRead(int fd
, void *buf
, int cnt
)
1869 return(Read(fd
, buf
, cnt
));
1871 if (ZFpos
+ cnt
> ZFileSize
)
1872 cnt
= ZFileSize
- ZFpos
;
1875 unsigned chunk
= ZFpos
>> ZFILE_CHUNK_BITS
;
1876 unsigned endchunk
= (chunk
+1) << ZFILE_CHUNK_BITS
;
1879 if (ZFpos
+ n
> endchunk
)
1880 n
= endchunk
- ZFpos
;
1881 memcpy(buf
, ZFile
[chunk
] + (ZFpos
& ZFILE_CHUNK_MASK
), n
);
1887 if (ZFpos
== endchunk
) {
1888 FreeMem(ZFile
[chunk
], ZFILE_CHUNK_SIZE
);
1889 ZFile
[chunk
] = NULL
;
1897 static int KSeek(int fd
, int offset
)
1899 unsigned oldpos
, oldchunk
, newchunk
;
1902 return(Seek(fd
, offset
));
1909 } else if (ZFpos
> ZFileSize
) {
1914 /* free memory of skipped-over data */
1915 oldchunk
= oldpos
>> ZFILE_CHUNK_BITS
;
1916 newchunk
= ZFpos
>> ZFILE_CHUNK_BITS
;
1917 while(oldchunk
< newchunk
) {
1918 if (ZFile
[oldchunk
]) {
1919 FreeMem(ZFile
[oldchunk
], ZFILE_CHUNK_SIZE
);
1920 ZFile
[oldchunk
] = NULL
;
1928 static void free_zfile(void)
1932 for (i
= 0; i
< ZFILE_N_CHUNKS
; ++i
)
1934 FreeMem(ZFile
[i
], ZFILE_CHUNK_SIZE
);
1939 static int KClose(int fd
)
1948 #endif /* ZKERNEL */