This source file includes following definitions.
- usage
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <stddef.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/file.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30
31
32 #include "bootstrap.h"
33
34
35 #include <linux/a.out.h>
36 #include <asm/bootinfo.h>
37
38
39 #define TEMP_STACKSIZE 256
40
41
42 extern struct ExecBase *SysBase;
43
44 extern char *optarg;
45
46 struct exec kexec;
47 char *memptr;
48 u_long start_mem;
49 u_long mem_size;
50 u_long rd_size;
51
52 struct ExpansionBase *ExpansionBase;
53 struct GfxBase *GfxBase;
54
55 struct bootinfo bi;
56 u_long bi_size = sizeof bi;
57
58 caddr_t CustomBase = (caddr_t)CUSTOM_PHYSADDR;
59
60 void usage(void)
61 {
62 fprintf (stderr, "Usage:\n"
63 "\tbootstrap [-d] [-k kernel_executable] [-r ramdisk_file]"
64 " [option...]\n");
65 exit (EXIT_FAILURE);
66 }
67
68
69
70
71
72
73
74 #ifndef __GNUC__
75 #error GNU CC is required to compile the bootstrap program
76 #endif
77 asm("
78 .text
79 .globl _copyall, _copyallend
80 _copyall:
81 |
82 lea _kexec,a3 |
83 movel _memptr,a4
84 movel _start_mem,a5
85 movel _mem_size,d0
86 movel _rd_size,d1
87 movel _bi_size,d5
88 movel a3@(4),d2 | kexec.a_text
89 movel a3@(8),d3 | kexec.a_data
90 movel a3@(12),d4 | kexec.a_bss
91
92 |
93 movel a4,a0 | src = (u_long *)memptr;
94 movel a0,a2 | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data);
95 addl d2,a2
96 addl d3,a2
97 movel a5,a1 | dest = (u_long *)start_mem;
98 1: cmpl a0,a2
99 beqs 2f | while (src < limit)
100 moveb a0@+,a1@+ | *dest++ = *src++;
101 bras 1b
102 2:
103
104 |
105 movel a1,a0 | dest = (u_long *)(start_mem + kexec.a_text + kexec.a_data);
106 movel a1,a2 | limit = dest + kexec.a_bss / sizeof(u_long);
107 addl d4,a2
108 1: cmpl a0,a2
109 beqs 2f | while (dest < limit)
110 clrb a0@+ | *dest++ = 0;
111 bras 1b
112 2:
113
114 |
115 movel a4,a1 | src = (u long *)memptr + kexec.a_text + kexec.a_data);
116 addl d2,a1
117 addl d3,a1 | dest = end of bss (already in a0)
118 movel d5,d7 | count = sizeof bi
119 subql #1,d7
120 1: moveb a1@+,a0@+ | while (--count > -1)
121 dbra d7,1b | *dest++ = *src++
122
123
124 |
125 movel a5,a1 | dest = (u_long *)(start_mem + mem_size);
126 addl d0,a1
127 movel a4,a2 | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data + sizeof bi);
128 addl d2,a2
129 addl d3,a2
130 addl d5,a2
131 movel a2,a0 | src = (u_long *)((u_long)limit + rd_size);
132 addl d1,a0
133 1: cmpl a0,a2
134 beqs 2f | while (src > limit)
135 moveb a0@-,a1@- | *--dest = *--src;
136 bras 1b
137 2:
138 |
139 movel a5,a0 | jump_to (START_MEM);
140 jsr a0@
141 _copyallend:
142 ");
143
144 asm("
145 .text
146 .globl _maprommed
147 _maprommed:
148 oriw #0x0700,sr
149 moveml #0x3f20,sp@-
150
151 .long 0x4e7a1002
152
153 .long 0x4e7a2003
154 .long 0x4e7a3004
155 .long 0x4e7a4005
156 .long 0x4e7a5006
157 .long 0x4e7a6007
158 moveq #0,d0
159 movel d0,a2
160
161 .long 0x4e7b0002
162
163 .long 0x4e7b0003
164 .long 0x4e7b0004
165 .long 0x4e7b0005
166 .long 0x4e7b0006
167 .long 0x4e7b0007
168 lea 0x07f80000,a0
169 lea 0x00f80000,a1
170 movel a0@,d7
171 cmpl a1@,d7
172 jnes 1f
173 movel d7,d0
174 notl d0
175 movel d0,a0@
176 nop
177 cmpl a1@,d0
178 jnes 1f
179
180 moveq #-1,d0
181 movel d0,a2
182 1: movel d7,a0@
183
184 .long 0x4e7b2003
185 .long 0x4e7b3004
186 .long 0x4e7b4005
187 .long 0x4e7b5006
188 .long 0x4e7b6007
189
190 .long 0x4e7b1002
191 movel a2,d0
192 moveml sp@+,#0x04fc
193 rte
194 ");
195
196 extern unsigned long maprommed();
197
198
199 extern char copyall, copyallend;
200
201 int main(int argc, char *argv[])
202 {
203 int ch, debugflag = 0, kfd, rfd = -1, i;
204 long fast_total = 0;
205 struct MemHeader *mnp;
206 struct ConfigDev *cdp = NULL;
207 char *kernel_name = "vmlinux";
208 char *ramdisk_name = NULL;
209 char *memfile = NULL;
210 u_long memreq;
211 void (*startfunc)(void);
212 long startcodesize;
213 u_long *stack, text_offset;
214 unsigned char *rb3_reg = NULL, *piccolo_reg = NULL, *sd64_reg = NULL;
215
216
217 puts("Linux/68k Amiga Bootstrap version 1.11");
218 puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n");
219
220
221 bi.machtype = MACH_AMIGA;
222
223
224 while ((ch = getopt(argc, argv, "dk:r:m:")) != EOF)
225 switch (ch) {
226 case 'd':
227 debugflag = 1;
228 break;
229 case 'k':
230 kernel_name = optarg;
231 break;
232 case 'r':
233 ramdisk_name = optarg;
234 break;
235 case 'm':
236 memfile = optarg;
237 break;
238 case '?':
239 default:
240 usage();
241 }
242 argc -= optind;
243 argv += optind;
244
245 SysBase = *(struct ExecBase **)4;
246
247
248
249
250 ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library", 36);
251 if (!ExpansionBase) {
252 puts("Unable to open expansion.library V36 or greater! Aborting...");
253 exit(EXIT_FAILURE);
254 }
255
256
257 cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
258 for (i=0; (i < NUM_AUTO) && cdp; i++) {
259
260 memcpy(&bi.bi_amiga.autocon[i], cdp, sizeof(struct ConfigDev));
261
262
263 bi.bi_amiga.num_autocon++;
264
265
266 cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
267 }
268
269
270 for (mnp = (struct MemHeader *)SysBase->MemList.l_head;
271 (bi.num_memory < NUM_MEMINFO) && mnp->mh_Node.ln_Succ;
272 mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ)
273 {
274 struct MemHeader mh;
275
276
277 mh = *mnp;
278
279
280
281
282
283
284 if (mh.mh_Upper == (void *)0x07f80000)
285 if ((SysBase->AttnFlags & AFF_68040) && Supervisor(maprommed))
286 printf("A3640 MapROM detected.\n");
287 else {
288 mh.mh_Upper = (void *)0x08000000;
289 printf("A3000 shadowed Kickstart detected.\n");
290 }
291
292
293
294 if (mh.mh_Lower == (void *)0x00280020) {
295 mh.mh_Lower = (void *)0x00200000;
296 printf("ZKick detected.\n");
297 }
298
299
300
301
302
303 if (mh.mh_Lower >= (void *)0x07000000 &&
304 mh.mh_Lower < (void *)0x08000000 &&
305 (mh.mh_Attributes & MEMF_LOCAL))
306 bi.bi_amiga.model = AMI_3000;
307
308
309 mh.mh_Upper = (void *)((u_long)mh.mh_Upper & 0xfffff000);
310 mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
311
312
313 if (mh.mh_Attributes & MEMF_FAST) {
314 unsigned long size;
315
316
317 bi.memory[bi.num_memory].addr = (u_long)mh.mh_Lower;
318
319
320 size = (u_long)mh.mh_Upper - (u_long)mh.mh_Lower;
321
322
323 size &= 0xfffc0000;
324
325 fast_total += size;
326
327 if (size > 0)
328
329 bi.memory[bi.num_memory++].size = size;
330
331 } else if (mh.mh_Attributes & MEMF_CHIP) {
332
333 bi.bi_amiga.chip_size =
334 (u_long)mh.mh_Upper;
335 }
336 }
337
338 CloseLibrary((struct Library *)ExpansionBase);
339
340
341
342
343 if (memfile) {
344 FILE *fp;
345 int i;
346
347 if ((fp = fopen (memfile, "r")) == NULL) {
348 perror ("open memory file");
349 fprintf (stderr, "Cannot open memory file %s\n", memfile);
350 exit (EXIT_FAILURE);
351 }
352
353 if (fscanf (fp, "%lu", &bi.bi_amiga.chip_size) != 1) {
354 fprintf (stderr, "memory file does not contain chip memory size\n");
355 fclose (fp);
356 exit (EXIT_FAILURE);
357 }
358
359 for (i = 0; i < NUM_MEMINFO; i++) {
360 if (fscanf (fp, "%lx %lu", &bi.memory[i].addr,
361 &bi.memory[i].size) != 2)
362 break;
363 }
364
365 fclose (fp);
366
367 if (i != bi.num_memory && i > 0)
368 bi.num_memory = i;
369 }
370
371
372 bi.bi_amiga.vblank = SysBase->VBlankFrequency;
373 bi.bi_amiga.psfreq = SysBase->PowerSupplyFrequency;
374 bi.bi_amiga.eclock = SysBase->EClockFrequency;
375
376
377 GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", 0);
378
379
380 bi.bi_amiga.chipset = CS_STONEAGE;
381 if(GfxBase)
382 {
383 if(GfxBase->ChipRevBits0 & GFXG_AGA)
384 {
385 bi.bi_amiga.chipset = CS_AGA;
386
387
388
389
390
391
392
393
394 bi.bi_amiga.model =
395 (bi.bi_amiga.model == AMI_3000) ? AMI_4000 : AMI_1200;
396 }
397 else if(GfxBase->ChipRevBits0 & GFXG_ECS)
398 bi.bi_amiga.chipset = CS_ECS;
399 else if(GfxBase->ChipRevBits0 & GFXG_OCS)
400 bi.bi_amiga.chipset = CS_OCS;
401 }
402
403
404 switch (bi.bi_amiga.model) {
405 case AMI_UNKNOWN:
406 break;
407 case AMI_500:
408 printf ("Amiga 500 ");
409 break;
410 case AMI_2000:
411 printf ("Amiga 2000 ");
412 break;
413 case AMI_3000:
414 printf ("Amiga 3000 ");
415 break;
416 case AMI_4000:
417 printf ("Amiga 4000 ");
418 break;
419 case AMI_1200:
420 printf ("Amiga 1200 ");
421 break;
422 }
423
424
425 printf("CPU: ");
426 if (SysBase->AttnFlags & AFF_68040) {
427 printf("68040");
428 bi.cputype = CPU_68040;
429 if (SysBase->AttnFlags & AFF_FPU40) {
430 printf(" with internal FPU");
431 bi.cputype |= FPU_68040;
432 } else
433 printf(" without FPU");
434 } else {
435 if (SysBase->AttnFlags & AFF_68030) {
436 printf("68030");
437 bi.cputype = CPU_68030;
438 } else if (SysBase->AttnFlags & AFF_68020) {
439 printf("68020 (Do you have an MMU?)");
440 bi.cputype = CPU_68020;
441 } else {
442 puts("Insufficient for Linux. Aborting...");
443 printf("SysBase->AttnFlags = %#x\n", SysBase->AttnFlags);
444 exit (EXIT_FAILURE);
445 }
446 if (SysBase->AttnFlags & AFF_68882) {
447 printf(" with 68882 FPU");
448 bi.cputype |= FPU_68882;
449 } else if (SysBase->AttnFlags & AFF_68881) {
450 printf(" with 68881 FPU");
451 bi.cputype |= FPU_68881;
452 } else
453 printf(" without FPU");
454 }
455
456 switch(bi.bi_amiga.chipset)
457 {
458 case CS_STONEAGE:
459 printf(", old or unknown chipset");
460 break;
461 case CS_OCS:
462 printf(", OCS");
463 break;
464 case CS_ECS:
465 printf(", ECS");
466 break;
467 case CS_AGA:
468 printf(", AGA chipset");
469 break;
470 }
471
472 putchar ('\n');
473 putchar ('\n');
474
475
476
477
478 i = 0;
479 while (argc--) {
480 if ((i+strlen(*argv)+1) < CL_SIZE) {
481 i += strlen(*argv) + 1;
482 if (bi.command_line[0])
483 strcat (bi.command_line, " ");
484 strcat (bi.command_line, *argv++);
485 }
486 }
487 printf ("Command line is '%s'\n", bi.command_line);
488
489
490 printf("Vertical Blank Frequency: %dHz\nPower Supply Frequency: %dHz\n",
491 bi.bi_amiga.vblank, bi.bi_amiga.psfreq);
492 printf("EClock Frequency: %7.5fKHz\n\n",
493 (float)bi.bi_amiga.eclock / 1000);
494
495
496 if (bi.bi_amiga.num_autocon) {
497 printf("Found %d AutoConfig Device%s", bi.bi_amiga.num_autocon,
498 (bi.bi_amiga.num_autocon > 1)?"s\n":"\n");
499 for (i=0; i<bi.bi_amiga.num_autocon; i++)
500 {
501 printf("Device %d: addr = %08lx\n", i,
502 (u_long)bi.bi_amiga.autocon[i].cd_BoardAddr);
503
504 if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH1) &&
505 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_RAINBOW3) )
506 {
507 printf("(Found a Rainbow 3 board - will reset it at kernel boot time)\n");
508 rb3_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x01002000);
509 }
510
511
512 if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
513 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_PICCOLO_REG) )
514 {
515 printf("(Found a Piccolo board - will reset it at kernel boot time)\n");
516 piccolo_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
517 }
518
519
520 if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
521 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_SD64_REG) )
522 {
523 printf("(Found a SD64 board - will reset it at kernel boot time)\n");
524 sd64_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
525 }
526
527
528
529
530
531 }
532 } else
533 puts("No AutoConfig Devices Found");
534
535
536 if (bi.num_memory) {
537 printf("\n%d Block%sof Memory Found\n", bi.num_memory,
538 (bi.num_memory > 1)?"s ":" ");
539 for (i=0; i<bi.num_memory; i++) {
540 printf("Block %d: %08lx to %08lx (%ldKB)\n",
541 i, bi.memory[i].addr,
542 bi.memory[i].addr + bi.memory[i].size,
543 bi.memory[i].size >> 10);
544 }
545 } else {
546 puts("No memory found?! Aborting...");
547 exit(10);
548 }
549
550
551 printf ("%ldK of CHIP memory\n", bi.bi_amiga.chip_size >> 10);
552
553 start_mem = bi.memory[0].addr;
554 mem_size = bi.memory[0].size;
555
556
557 printf("\nThe kernel will be located at %08lx\n", start_mem);
558
559
560 if (bi.bi_amiga.chip_size < 512*1024) {
561 puts("\nNot enough Chip RAM in this system. Aborting...");
562 exit(10);
563 }
564
565
566 if (fast_total < 2*1024*1024) {
567 puts("\nNot enough Fast RAM in this system. Aborting...");
568 exit(10);
569 }
570
571
572 if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
573 fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
574 exit (EXIT_FAILURE);
575 }
576
577 if (read (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
578 fprintf (stderr, "Unable to read exec header from %s\n",
579 kernel_name);
580 exit (EXIT_FAILURE);
581 }
582
583 switch (N_MAGIC(kexec)) {
584 case ZMAGIC:
585 text_offset = N_TXTOFF(kexec);
586 break;
587 case QMAGIC:
588 text_offset = sizeof(kexec);
589
590 kexec.a_text -= sizeof(kexec);
591 break;
592 default:
593 fprintf (stderr, "Wrong magic number %lo in kernel header\n",
594 N_MAGIC(kexec));
595 exit (EXIT_FAILURE);
596 }
597
598
599 start_mem += PAGE_SIZE;
600 mem_size -= PAGE_SIZE;
601
602 kexec.a_bss = (kexec.a_bss + 3) & ~3;
603
604 if (ramdisk_name) {
605 if ((rfd = open (ramdisk_name, O_RDONLY)) == -1) {
606 fprintf (stderr, "Unable to open ramdisk file %s\n",
607 ramdisk_name);
608 exit (EXIT_FAILURE);
609 }
610
611 bi.ramdisk_size = (lseek (rfd, 0, L_XTND) + 1023) >> 10;
612 } else
613 bi.ramdisk_size = 0;
614
615 rd_size = bi.ramdisk_size << 10;
616 bi.ramdisk_addr = (u_long)start_mem + mem_size - rd_size;
617
618 memreq = kexec.a_text + kexec.a_data + sizeof(bi) + rd_size;
619 if (!(memptr = (char *)AllocMem (memreq, MEMF_FAST | MEMF_CLEAR))) {
620 fprintf (stderr, "Unable to allocate memory\n");
621 exit (EXIT_FAILURE);
622 }
623
624 if (lseek (kfd, text_offset, L_SET) == -1) {
625 fprintf (stderr, "Failed to seek to text\n");
626 FreeMem ((void *)memptr, memreq);
627 exit (EXIT_FAILURE);
628 }
629 if (read (kfd, memptr, kexec.a_text) != kexec.a_text) {
630 fprintf (stderr, "Failed to read text\n");
631 FreeMem ((void *)memptr, memreq);
632 exit (EXIT_FAILURE);
633 }
634
635
636 if (read (kfd, memptr + kexec.a_text, kexec.a_data) != kexec.a_data) {
637 fprintf (stderr, "Failed to read data\n");
638 FreeMem ((void *)memptr, memreq);
639 exit (EXIT_FAILURE);
640 }
641 close (kfd);
642
643
644 memcpy ((void *)(memptr + kexec.a_text + kexec.a_data), &bi,
645 sizeof(bi));
646
647 if (rfd != -1) {
648 if (lseek (rfd, 0, L_SET) == -1) {
649 fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
650 FreeMem ((void *)memptr, memreq);
651 exit (EXIT_FAILURE);
652 }
653 if (read (rfd, memptr + kexec.a_text + kexec.a_data
654 + sizeof(bi), rd_size) != rd_size) {
655 fprintf (stderr, "Failed to read ramdisk file\n");
656 FreeMem ((void *)memptr, memreq);
657 exit (EXIT_FAILURE);
658 }
659 close (rfd);
660 }
661
662
663 stack = (u_long *)AllocMem( TEMP_STACKSIZE, MEMF_CHIP|MEMF_CLEAR);
664 if (!stack) {
665 fprintf (stderr, "Unable to allocate memory for stack\n");
666 FreeMem ((void *)memptr, memreq);
667 exit (EXIT_FAILURE);
668 }
669
670
671 startcodesize = ©allend - ©all;
672 startfunc = (void (*)(void))AllocMem( startcodesize, MEMF_CHIP);
673 if (!startfunc) {
674 fprintf (stderr, "Unable to allocate memory for code\n");
675 FreeMem ((void *)memptr, memreq);
676 FreeMem ((void *)stack, TEMP_STACKSIZE);
677 exit (EXIT_FAILURE);
678 }
679
680
681 memcpy (startfunc, ©all, startcodesize);
682
683 if (debugflag) {
684 if (bi.ramdisk_size)
685 printf ("RAM disk at %#lx, size is %ldK\n",
686 (u_long)memptr + kexec.a_text + kexec.a_data,
687 bi.ramdisk_size);
688
689 printf ("\nKernel text at %#lx, code size %x\n",
690 start_mem, kexec.a_text);
691 printf ("Kernel data at %#lx, data size %x\n",
692 start_mem + kexec.a_text, kexec.a_data );
693 printf ("Kernel bss at %#lx, bss size %x\n",
694 start_mem + kexec.a_text + kexec.a_data,
695 kexec.a_bss );
696 printf ("boot info at %#lx\n", start_mem + kexec.a_text
697 + kexec.a_data + kexec.a_bss);
698
699 printf ("\nKernel entry is %#x\n", kexec.a_entry );
700
701 printf ("ramdisk dest top is %#lx\n", start_mem + mem_size);
702 printf ("ramdisk lower limit is %#lx\n",
703 (u_long)(memptr + kexec.a_text + kexec.a_data));
704 printf ("ramdisk src top is %#lx\n",
705 (u_long)(memptr + kexec.a_text + kexec.a_data)
706 + rd_size);
707
708 printf ("Type a key to continue the Linux boot...");
709 fflush (stdout);
710 getchar();
711 }
712
713
714 sleep(2);
715
716
717
718
719 if (rb3_reg != NULL)
720 {
721
722 *rb3_reg = 0x01;
723
724 sleep(1);
725
726 *rb3_reg = 0x00;
727 }
728
729
730
731
732
733 if (piccolo_reg != NULL)
734 {
735
736 *piccolo_reg = 0x01;
737
738 sleep(1);
739
740 *piccolo_reg = 0x51;
741 }
742
743
744
745 if (sd64_reg != NULL)
746 {
747
748 *sd64_reg = 0x1f;
749
750 sleep(1);
751
752 *sd64_reg = 0x4f;
753 }
754
755 if (GfxBase) {
756
757 LoadView (NULL);
758 CloseLibrary ((struct Library *)GfxBase);
759 }
760
761 Disable();
762
763
764 custom.dmacon = DMAF_ALL | DMAF_MASTER;
765
766
767 CacheControl (0L, ~0L);
768
769
770 SuperState ();
771
772
773 change_stack ((char *) stack + TEMP_STACKSIZE);
774
775
776 disable_mmu ();
777
778
779 startfunc();
780
781
782 }