/*
* $NetBSD: main.c,v 1.32 2021/12/05 08:09:30 msaitoh Exp $
*
*
* Copyright (c) 1996,1999 Ignatios Souvatzis
* Copyright (c) 1994 Michael L. Hitch
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* Kernel startup interface version
* 1: first version of loadbsd
* 2: needs esym location passed in a4
* 3: load kernel image into fastmem rather than chipmem
* MAX: highest version with backward compatibility.
*/
/*
* we need V36 for: EClock, RDB Bootblocks, CacheClearU
*/
if (SysBase->LibNode.Version < EXECMIN) {
printf("Exec V%ld, need V%ld\n",
(long)SysBase->LibNode.Version, (long)EXECMIN);
goto out;
}
/*
* XXX Do this differently; default boot will attempt to load a list of
* XXX kernels until one of them succeeds.
*/
timelimit = 3;
again:
#ifdef PPCBOOTER
printf("\nNetBSD/AmigaPPC " NETBSD_VERS " Bootstrap, Revision %s\n",
bootprog_rev);
#else
printf("\nNetBSD/Amiga " NETBSD_VERS " Bootstrap, Revision %s\n",
bootprog_rev);
#endif
printf("\n");
printf("Boot: [%s] ", kernel_name);
kgets(linebuf, sizeof(linebuf));
if (*linebuf == 'q')
return 1;
if (*linebuf)
path = linebuf;
/*
* parse boot command for path name and process any options
*/
while ((c = *path)) {
while (c == ' ')
c = *++path;
if (c == '-') {
while ((c = *++path) && c != ' ') {
switch (c) {
case 'a': /* multi-user state */
boothowto &= ~RB_SINGLE;
break;
case 'b': /* ask for root device */
boothowto |= RB_ASKNAME;
break;
case 'c': /* force machine model */
cpuid = get_number(&path) << 16;
break;
case 'k': /* Reserve first 4M fastmem */
k_flag++;
break;
case 'm': /* Force fastmem size */
m_value = get_number(&path) * 1024;
break;
case 'n': /* non-contiguous memory */
amiga_flags |=
(get_number(&path) & 3) << 1;
break;
case 'p': /* Select fastmem by priority */
p_flag = 1;
break;
case 'q':
boothowto |= AB_QUIET;
break;
case 's': /* single-user state */
boothowto |= RB_SINGLE;
break;
case 't': /* test flag */
/* t_flag = 1; */
break;
case 'v':
boothowto |= AB_VERBOSE;
break;
case 'A': /* enable AGA modes */
amiga_flags |= 1;
break;
case 'C': /* Serial Console */
amiga_flags |= (1 << 3);
break;
case 'D': /* enter Debugger */
boothowto |= RB_KDB;
break;
case 'I': /* inhibit sync negotiation */
I_flag = get_number(&path);
break;
case 'K': /* remove 1st 4MB fastmem */
break;
case 'S': /* include debug symbols */
S_flag = 1;
break;
}
}
} else {
/* XXX Handle kernel_name differently */
kernel_name = path;
while ((c = *++path) && c != ' ')
;
if (c)
*path++ = 0;
}
}
/* XXX Handle kernel_name differently */
while ((c = *kernel_name) && c == ' ')
++kernel_name;
path = kernel_name;
while ((c = *path) && c != ' ')
++path;
if (c)
*path = 0;
if (get_cpuid(&cpuid))
goto out;
ExpansionBase = OpenLibrary("expansion.library", 0);
if (!ExpansionBase) {
printf("can't open %s\n", "expansion.library");
return 1;
}
static
long get_number(char **ptr)
{
long value = 0;
int base = 10;
char *p = *ptr;
char c;
char sign = 0;
c = *++p;
while (c == ' ')
c = *++p;
if (c == '-') {
sign = -1;
c = *++p;
}
if (c == '$') {
base = 16;
c = *++p;
} else if (c == '0') {
c = *++p;
if ((c & 0xdf) == 'X') {
base = 16;
c = *++p;
}
}
while (c) {
if (c >= '0' && c <= '9')
c -= '0';
else {
c = (c & 0xdf) - 'A' + 10;
if (base != 16 || c < 10 || c > 15)
break;
}
value = value * base + c;
c = *++p;
}
*ptr = p - 1;
#ifdef TEST
fprintf(stderr, "get_number: got %c0x%x",
sign ? '-' : '+', value);
#endif
return (sign ? -value : value);
}
/*
* Try to determine the machine ID by searching the resident module list
* for modules only present on specific machines. (Thanks, Bill!)
*/
int
get_cpuid(u_int32_t *cpuid)
{
uint8_t alicerev;
alicerev = *((uint8_t *)0xdff004) & 0x6f;
*cpuid |= SysBase->AttnFlags; /* get FPU and CPU flags */
if (*cpuid & 0xffff0000) {
if ((*cpuid >> 24) == 0x7D)
return 0;
switch (*cpuid >> 16) {
case 500:
case 600:
case 1000:
case 1200:
case 2000:
case 3000:
case 4000:
return 0;
default:
printf("Amiga %ld ???\n",
(long)(*cpuid >> 16));
return(1);
}
}
if (FindResident("A4000 Bonus") || FindResident("A4000 bonus")
|| FindResident("A1000 Bonus"))
*cpuid |= 4000 << 16;
else if (FindResident("A3000 Bonus") || FindResident("A3000 bonus")
|| (SysBase->LibNode.Version == 36))
*cpuid |= 3000 << 16;
else if (OpenResource("card.resource")) {
if (alicerev == 0x22 || alicerev == 0x23)
*cpuid |= 1200 << 16; /* AGA + PCMCIA = A1200 */
else
*cpuid |= 600 << 16; /* noAGA + PCMCIA = A600 */
} else if (OpenResource("draco.resource")) {
*cpuid |= (32000 | DRACOREVISION) << 16;
}
/*
* Nothing found, it's probably an A2000 or A500
*/
if ((*cpuid >> 16) == 0)
*cpuid |= 2000 << 16;