2 ** linux/arch/m68k/boot/amiga/bootstrap.c -- This program loads the Linux/m68k
3 ** kernel into an Amiga and launches
6 ** Copyright 1993,1994 by Hamish Macdonald, Greg Harp
8 ** Modified 11-May-94 by Geert Uytterhoeven
9 ** (Geert.Uytterhoeven@cs.kuleuven.ac.be)
10 ** - A3640 MapROM check
11 ** Modified 31-May-94 by Geert Uytterhoeven
12 ** - Memory thrash problem solved
13 ** Modified 07-March-95 by Geert Uytterhoeven
14 ** - Memory block sizes are rounded to a multiple of 256K instead of 1M
15 ** This _requires_ >0.9pl5 to work!
16 ** (unless all block sizes are multiples of 1M :-)
17 ** Modified 11-July-95 by Andreas Schwab
18 ** - Support for ELF kernel (untested!)
19 ** Modified 10-Jan-96 by Geert Uytterhoeven
20 ** - The real Linux/m68k boot code moved to linuxboot.[ch]
21 ** Modified 9-Sep-96 by Geert Uytterhoeven
22 ** - Rewritten option parsing
23 ** - New parameter passing to linuxboot() (linuxboot_args)
24 ** Modified 6-Oct-96 by Geert Uytterhoeven
25 ** - Updated for the new boot information structure
26 ** Modified 26-Feb-98 by Jesper Skov
27 ** - Added support for booting APUS systems.
29 ** This file is subject to the terms and conditions of the GNU General Public
30 ** License. See the file COPYING in the main directory of this archive
41 #include <sys/types.h>
44 /* required Linux/m68k include files */
45 #include <linux/a.out.h>
46 #include <linux/elf.h>
47 #include <asm/amigahw.h>
50 /* Amiga bootstrap include files */
51 #include "linuxboot.h"
52 #include "bootstrap.h"
56 long __oslibversion
= 36;
57 extern const struct ExecBase
*SysBase
;
59 static const char *memfile_name
= NULL
;
61 static int model
= AMI_UNKNOWN
;
63 static const char *ProgramName
;
65 struct linuxboot_args args
;
72 static void Usage(void) __attribute__ ((noreturn
));
73 int main(int argc
, char *argv
[]);
74 static void Puts(const char *str
);
75 static long GetChar(void);
76 static void PutChar(char c
);
77 static void Printf(const char *fmt
, ...);
78 static int Open(const char *path
);
79 static int Seek(int fd
, int offset
);
80 static int Read(int fd
, char *buf
, int count
);
81 static void Close(int fd
);
82 static int FileSize(const char *path
);
83 static void Sleep(u_long micros
);
86 static void Usage(void)
89 "Linux/m68k Amiga Bootstrap version " AMIBOOT_VERSION
"\n\n"
90 "Usage: %s [options] [kernel command line]\n\n"
92 " -h, --help Display this usage information\n"
93 " -k, --kernel file Use kernel image `file' (default is `vmlinux')\n"
94 " -r, --ramdisk file Use ramdisk image `file'\n"
96 " -d, --debug Enable debug mode\n"
97 " -b, --baud speed Set the serial port speed (default is 9600)\n"
98 " -m, --memfile file Use memory file `file'\n"
99 " -v, --keep-video Don't reset the video mode\n"
100 " -t, --model id Set the Amiga model to `id'\n"
101 " -p, --processor cfm Set the processor type to `cfm\n",
102 " --apus PPC boot on PowerUp\n",
103 " --checksum Make checksum of kernel image.\n\n",
108 struct PPCLibBase
*PPCLibBasePTR
= NULL
;
110 int main(int argc
, char *argv
[])
113 int processor
= 0, debugflag
= 0, keep_video
= 0;
114 int apus_boot
= 0, checksum
= 0;
116 const char *kernel_name
= NULL
;
117 const char *ramdisk_name
= NULL
;
118 char commandline
[CL_SIZE
] = "";
120 ProgramName
= argv
[0];
123 if (!strcmp(argv
[0], "-h") || !strcmp(argv
[0], "--help"))
125 else if (!strcmp(argv
[0], "-k") || !strcmp(argv
[0], "--kernel"))
126 if (--argc
&& !kernel_name
) {
127 kernel_name
= argv
[1];
131 else if (!strcmp(argv
[0], "-r") || !strcmp(argv
[0], "--ramdisk"))
132 if (--argc
&& !ramdisk_name
) {
133 ramdisk_name
= argv
[1];
137 else if (!strcmp(argv
[0], "-d") || !strcmp(argv
[0], "--debug"))
139 else if (!strcmp(argv
[0], "-b") || !strcmp(argv
[0], "--baud"))
140 if (--argc
&& !baud
) {
141 baud
= atoi(argv
[1]);
145 else if (!strcmp(argv
[0], "-m") || !strcmp(argv
[0], "--memfile"))
146 if (--argc
&& !memfile_name
) {
147 memfile_name
= argv
[1];
151 else if (!strcmp(argv
[0], "-v") || !strcmp(argv
[0], "--keep-video"))
153 else if (!strcmp(argv
[0], "-t") || !strcmp(argv
[0], "--model"))
154 if (--argc
&& !model
) {
155 model
= atoi(argv
[1]);
159 else if (!strcmp(argv
[0], "-p") || !strcmp(argv
[0], "--processor"))
160 if (--argc
&& !processor
) {
161 processor
= atoi(argv
[1]);
165 else if (!strcmp(argv
[0], "--apus"))
167 else if (!strcmp(argv
[0], "--checksum"))
173 kernel_name
= "vmlinux";
175 SysBase
= *(struct ExecBase
**)4;
178 if (!(PPCLibBasePTR
= (struct PPCLibBase
*)
179 OpenLibrary("ppc.library", 45))){
180 fprintf(stderr
, "Cannot open ppc.library version45+\n");
186 * Join command line options
190 if ((i
+strlen(*argv
)+1) < CL_SIZE
) {
191 i
+= strlen(*argv
) + 1;
193 strcat(commandline
, " ");
194 strcat(commandline
, *argv
++);
198 memset(&args
.bi
, 0, sizeof(args
.bi
));
200 int cpu
= processor
/100%10;
201 int fpu
= processor
/10%10;
202 int mmu
= processor
%10;
204 args
.bi
.cputype
= 1<<(cpu
-1);
206 args
.bi
.fputype
= 1<<(fpu
-1);
208 args
.bi
.mmutype
= 1<<(mmu
-1);
211 * If we have a memory file, read the memory information from it
217 if ((fp
= fopen(memfile_name
, "r")) == NULL
) {
218 perror("open memory file");
219 fprintf(stderr
, "Cannot open memory file %s\n", memfile_name
);
223 if (fscanf(fp
, "%lu", &args
.bi
.chip_size
) != 1) {
224 fprintf(stderr
, "memory file does not contain chip memory size\n");
229 for (i
= 0; i
< NUM_MEMINFO
; i
++)
230 if (fscanf(fp
, "%lx %lu", &args
.bi
.memory
[i
].addr
,
231 &args
.bi
.memory
[i
].size
) != 2)
235 args
.bi
.num_memory
= i
;
237 strncpy(args
.bi
.command_line
, commandline
, CL_SIZE
);
238 args
.bi
.command_line
[CL_SIZE
-1] = '\0';
239 if (model
!= AMI_UNKNOWN
)
240 args
.bi
.model
= model
;
242 args
.apus_boot
= apus_boot
;
243 args
.checksum
= checksum
;
245 args
.kernelname
= kernel_name
;
246 args
.ramdiskname
= ramdisk_name
;
247 args
.debugflag
= debugflag
;
248 args
.keep_video
= keep_video
;
249 args
.reset_boards
= 1;
252 args
.getchar
= GetChar
;
253 args
.putchar
= PutChar
;
254 args
.printf
= Printf
;
259 args
.filesize
= FileSize
;
262 /* Do The Right Stuff */
265 /* if we ever get here, something went wrong */
271 * Routines needed by linuxboot
274 static void Puts(const char *str
)
280 static long GetChar(void)
285 static void PutChar(char c
)
291 static void Printf(const char *fmt
, ...)
296 vfprintf(stderr
, fmt
, args
);
301 static int Open(const char *path
)
303 return(open(path
, O_RDONLY
));
306 static int Seek(int fd
, int offset
)
308 return(lseek(fd
, offset
, SEEK_SET
));
312 static int Read(int fd
, char *buf
, int count
)
314 return(read(fd
, buf
, count
));
317 static void Close(int fd
)
322 static int FileSize(const char *path
)
326 if ((fd
= open(path
, O_RDONLY
)) != -1) {
327 size
= lseek(fd
, 0, SEEK_END
);
333 static void Sleep(u_long micros
)
335 struct MsgPort
*TimerPort
;
336 struct timerequest
*TimerRequest
;
338 if ((TimerPort
= CreateMsgPort())) {
339 if ((TimerRequest
= CreateIORequest(TimerPort
,
340 sizeof(struct timerequest
)))) {
341 if (!OpenDevice("timer.device", UNIT_VBLANK
,
342 (struct IORequest
*)TimerRequest
, 0)) {
343 TimerRequest
->io_Command
= TR_ADDREQUEST
;
344 TimerRequest
->io_Flags
= IOF_QUICK
;
345 TimerRequest
->tv_secs
= micros
/1000000;
346 TimerRequest
->tv_micro
= micros
%1000000;
347 DoIO((struct IORequest
*)TimerRequest
);
348 CloseDevice((struct IORequest
*)TimerRequest
);
350 DeleteIORequest(TimerRequest
);
352 DeleteMsgPort(TimerPort
);