1*cde8f271Sriastradh /* $NetBSD: boot.c,v 1.7 2022/02/16 23:49:27 riastradh Exp $ */
268fe5b6fSgarbled
368fe5b6fSgarbled /*
468fe5b6fSgarbled * Copyright (C) 1995, 1996 Wolfgang Solfrank.
568fe5b6fSgarbled * Copyright (C) 1995, 1996 TooLs GmbH.
668fe5b6fSgarbled * All rights reserved.
768fe5b6fSgarbled *
868fe5b6fSgarbled * Redistribution and use in source and binary forms, with or without
968fe5b6fSgarbled * modification, are permitted provided that the following conditions
1068fe5b6fSgarbled * are met:
1168fe5b6fSgarbled * 1. Redistributions of source code must retain the above copyright
1268fe5b6fSgarbled * notice, this list of conditions and the following disclaimer.
1368fe5b6fSgarbled * 2. Redistributions in binary form must reproduce the above copyright
1468fe5b6fSgarbled * notice, this list of conditions and the following disclaimer in the
1568fe5b6fSgarbled * documentation and/or other materials provided with the distribution.
1668fe5b6fSgarbled * 3. All advertising materials mentioning features or use of this software
1768fe5b6fSgarbled * must display the following acknowledgement:
1868fe5b6fSgarbled * This product includes software developed by TooLs GmbH.
1968fe5b6fSgarbled * 4. The name of TooLs GmbH may not be used to endorse or promote products
2068fe5b6fSgarbled * derived from this software without specific prior written permission.
2168fe5b6fSgarbled *
2268fe5b6fSgarbled * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2368fe5b6fSgarbled * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2468fe5b6fSgarbled * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2568fe5b6fSgarbled * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2668fe5b6fSgarbled * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2768fe5b6fSgarbled * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2868fe5b6fSgarbled * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2968fe5b6fSgarbled * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3068fe5b6fSgarbled * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3168fe5b6fSgarbled * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3268fe5b6fSgarbled */
3368fe5b6fSgarbled
3468fe5b6fSgarbled #include <lib/libsa/stand.h>
3568fe5b6fSgarbled #include <lib/libsa/loadfile.h>
3668fe5b6fSgarbled #include <lib/libkern/libkern.h>
3768fe5b6fSgarbled #include <sys/reboot.h>
3868fe5b6fSgarbled #include <sys/boot_flag.h>
3968fe5b6fSgarbled #include <machine/bootinfo.h>
4068fe5b6fSgarbled #include <machine/cpu.h>
41d8e4680bSgarbled #include <machine/iplcb.h>
4268fe5b6fSgarbled #include <powerpc/spr.h>
43eeda5809Smatt #include <powerpc/oea/spr.h>
4468fe5b6fSgarbled
4568fe5b6fSgarbled #include "boot.h"
4668fe5b6fSgarbled
4768fe5b6fSgarbled char *names[] = {
4868fe5b6fSgarbled "in()",
4968fe5b6fSgarbled };
5068fe5b6fSgarbled #define NUMNAMES (sizeof (names) / sizeof (names[0]))
5168fe5b6fSgarbled
5268fe5b6fSgarbled #define NAMELEN 128
5368fe5b6fSgarbled char namebuf[NAMELEN];
5468fe5b6fSgarbled char nametmp[NAMELEN];
5568fe5b6fSgarbled
5668fe5b6fSgarbled unsigned char cregs[10];
5768fe5b6fSgarbled
5868fe5b6fSgarbled char bootinfo[BOOTINFO_MAXSIZE];
5968fe5b6fSgarbled struct btinfo_iplcb btinfo_iplcb;
6068fe5b6fSgarbled struct btinfo_console btinfo_console;
6168fe5b6fSgarbled
6268fe5b6fSgarbled /*struct ipl_cb iplcb;
6368fe5b6fSgarbled struct ipl_directory ipldir;*/
6468fe5b6fSgarbled
6568fe5b6fSgarbled extern u_long ns_per_tick;
663c550524Sjoerg extern char bootprog_name[], bootprog_rev[];
6768fe5b6fSgarbled
6868fe5b6fSgarbled void boot(void *, void *);
6968fe5b6fSgarbled static void exec_kernel(char *);
7068fe5b6fSgarbled
7168fe5b6fSgarbled #define PSL_DR (1<<4)
7268fe5b6fSgarbled #define PSL_EE 0x00008000
7368fe5b6fSgarbled #define BAT_BL_128K 0x00000000
7468fe5b6fSgarbled #define BAT_BL_1M 0x0000001c
7568fe5b6fSgarbled #define BAT_BL_2M 0x0000003c
7668fe5b6fSgarbled #define BAT_W 0x00000040
7768fe5b6fSgarbled #define BAT_I 0x00000020
7868fe5b6fSgarbled #define BAT_M 0x00000010
7968fe5b6fSgarbled #define BAT_G 0x00000008
8068fe5b6fSgarbled #define BAT_X 0x00000004
8168fe5b6fSgarbled #define BAT_Vs 0x00000002
8268fe5b6fSgarbled #define BAT_Vu 0x00000001
8368fe5b6fSgarbled #define BAT_PP_RW 0x00000002
8468fe5b6fSgarbled #define BAT_RPN (~0x1ffff)
8568fe5b6fSgarbled #define BAT_EPI (~0x1ffffL)
8668fe5b6fSgarbled #define BAT_V (BAT_Vs|BAT_Vu)
8768fe5b6fSgarbled #define BAT_BL 0x00001ffc
8868fe5b6fSgarbled
8968fe5b6fSgarbled #define BATU(va, len, v) \
9068fe5b6fSgarbled (((va) & BAT_EPI) | ((len) & BAT_BL) | ((v) & BAT_V))
9168fe5b6fSgarbled #define BATL(pa, wimg, pp) \
9268fe5b6fSgarbled (((pa) & BAT_RPN) | (wimg) | (pp))
9368fe5b6fSgarbled
9468fe5b6fSgarbled
9568fe5b6fSgarbled static void
setled(uint32_t val)9668fe5b6fSgarbled setled(uint32_t val)
9768fe5b6fSgarbled {
9868fe5b6fSgarbled #ifdef POWER
9968fe5b6fSgarbled register_t savemsr, msr, savesr15;
10068fe5b6fSgarbled
10168fe5b6fSgarbled __asm volatile ("mfmsr %0" : "=r"(savemsr));
10268fe5b6fSgarbled msr = savemsr & ~PSL_DR;
10368fe5b6fSgarbled __asm volatile ("mtmsr %0" : : "r"(msr));
10468fe5b6fSgarbled
10568fe5b6fSgarbled __asm volatile ("mfsr %0,15;isync" : "=r"(savesr15));
10668fe5b6fSgarbled __asm volatile ("mtsr 15,%0" : : "r"(0x82040080));
10768fe5b6fSgarbled __asm volatile ("mtmsr %0" : : "r"(msr|PSL_DR));
10868fe5b6fSgarbled __asm volatile ("isync");
10968fe5b6fSgarbled *(uint32_t *)0xF0A00300 = val;
11068fe5b6fSgarbled __asm volatile ("mtmsr %0" : : "r"(savemsr));
11168fe5b6fSgarbled __asm volatile ("mtsr 15,%0;isync" : : "r"(savesr15));
11268fe5b6fSgarbled #else
11368fe5b6fSgarbled #ifdef NOTYET
11468fe5b6fSgarbled register_t savemsr, msr, batu, batl;
11568fe5b6fSgarbled
11668fe5b6fSgarbled /* turn on DR */
11768fe5b6fSgarbled __asm volatile ("mfmsr %0" : "=r"(savemsr));
11868fe5b6fSgarbled msr = savemsr|PSL_DR;
11968fe5b6fSgarbled __asm volatile ("mtmsr %0" : : "r"(msr));
12068fe5b6fSgarbled __asm volatile ("isync");
12168fe5b6fSgarbled
12268fe5b6fSgarbled /* set up a bat and map the whole NVRAM chunk */
12368fe5b6fSgarbled batl = BATL(0xFF600000, BAT_I|BAT_G, BAT_PP_RW);
12468fe5b6fSgarbled batu = BATU(0xFF600000, BAT_BL_1M, BAT_Vs);
12568fe5b6fSgarbled __asm volatile ("mtdbatl 1,%0; mtdbatu 1,%1;"
12668fe5b6fSgarbled :: "r"(batl), "r"(batu));
12768fe5b6fSgarbled __asm volatile ("isync");
12868fe5b6fSgarbled
12968fe5b6fSgarbled *(volatile uint32_t *)0xFF600300 = val;
130*cde8f271Sriastradh __asm volatile ("eieio" ::: "memory");
13168fe5b6fSgarbled __asm volatile ("isync");
13268fe5b6fSgarbled
13368fe5b6fSgarbled /* put back to normal */
13468fe5b6fSgarbled __asm volatile ("mtmsr %0" : : "r"(savemsr));
13568fe5b6fSgarbled __asm volatile ("isync");
13668fe5b6fSgarbled #endif /* NOTYET */
13768fe5b6fSgarbled #endif
13868fe5b6fSgarbled }
13968fe5b6fSgarbled
14068fe5b6fSgarbled
14168fe5b6fSgarbled void
boot(void * iplcb_p,void * extiplcb_p)14268fe5b6fSgarbled boot(void *iplcb_p, void *extiplcb_p)
14368fe5b6fSgarbled {
14468fe5b6fSgarbled extern char _end[], _edata[];
14568fe5b6fSgarbled int n = 0;
14668fe5b6fSgarbled int addr, speed;
14768fe5b6fSgarbled /*unsigned int cpuvers;*/
14868fe5b6fSgarbled char *name, *cnname, *p;
14968fe5b6fSgarbled struct ipl_cb *iplcb_ptr;
15068fe5b6fSgarbled struct ipl_directory *dirp;
15168fe5b6fSgarbled struct ipl_info *infop;
15268fe5b6fSgarbled
15368fe5b6fSgarbled //setled(0x30100000); /* we have control */
15468fe5b6fSgarbled //for (;;);
15568fe5b6fSgarbled iplcb_ptr = (struct ipl_cb *)iplcb_p;
15668fe5b6fSgarbled dirp = &(iplcb_ptr->dir);
15768fe5b6fSgarbled
15868fe5b6fSgarbled /* Clear all of BSS */
15968fe5b6fSgarbled memset(_edata, 0, _end - _edata);
16068fe5b6fSgarbled
16168fe5b6fSgarbled /*
16268fe5b6fSgarbled * console init
16368fe5b6fSgarbled */
16468fe5b6fSgarbled //setled(0x30000000); /* attempting r14 setup */
16568fe5b6fSgarbled setup_iocc();
16668fe5b6fSgarbled //setled(0x31000000); /* attempting console init */
16768fe5b6fSgarbled cnname = cninit(&addr, &speed);
16868fe5b6fSgarbled printf("\n");
16968fe5b6fSgarbled //setled(0x31100000); /* we have the console */
17068fe5b6fSgarbled
1714ecd76e5Srin printf("IPLCB ptr = %p\n", iplcb_p);
17268fe5b6fSgarbled
17368fe5b6fSgarbled infop = (struct ipl_info *)((char *)iplcb_p + dirp->iplinfo_off);
17468fe5b6fSgarbled printf("Machine model = 0x%x\n", infop->model);
17568fe5b6fSgarbled printf("RAM = 0x%x\n", infop->ram_size);
17668fe5b6fSgarbled
17768fe5b6fSgarbled //dump_iplcb(iplcb_p);
17868fe5b6fSgarbled
17968fe5b6fSgarbled /* make bootinfo */
18068fe5b6fSgarbled /*
18168fe5b6fSgarbled * ipl control block
18268fe5b6fSgarbled */
18368fe5b6fSgarbled btinfo_iplcb.common.next = sizeof(btinfo_iplcb);
18468fe5b6fSgarbled btinfo_iplcb.common.type = BTINFO_IPLCB;
18568fe5b6fSgarbled if (iplcb_ptr) {
18668fe5b6fSgarbled btinfo_iplcb.addr = (void *)iplcb_p;
18768fe5b6fSgarbled } else {
18868fe5b6fSgarbled printf("Warning: no IPL Control Block.\n");
18968fe5b6fSgarbled btinfo_iplcb.addr = 0;
19068fe5b6fSgarbled }
19168fe5b6fSgarbled
19268fe5b6fSgarbled /*
19368fe5b6fSgarbled * console
19468fe5b6fSgarbled */
19568fe5b6fSgarbled btinfo_console.common.next = sizeof(btinfo_console);
19668fe5b6fSgarbled btinfo_console.common.type = BTINFO_CONSOLE;
19768fe5b6fSgarbled strcpy(btinfo_console.devname, cnname);
19868fe5b6fSgarbled btinfo_console.addr = addr;
19968fe5b6fSgarbled btinfo_console.speed = speed;
20068fe5b6fSgarbled
20168fe5b6fSgarbled p = bootinfo;
20268fe5b6fSgarbled memcpy(p, (void *)&btinfo_iplcb, sizeof(btinfo_iplcb));
20368fe5b6fSgarbled p += sizeof(btinfo_iplcb);
20468fe5b6fSgarbled memcpy(p, (void *)&btinfo_console, sizeof(btinfo_console));
20568fe5b6fSgarbled p += sizeof(btinfo_console);
20668fe5b6fSgarbled
20768fe5b6fSgarbled /*
20868fe5b6fSgarbled * load kernel if attached
20968fe5b6fSgarbled */
21068fe5b6fSgarbled init_in(RELOC);
21168fe5b6fSgarbled
21268fe5b6fSgarbled setled(0x38000000); /* attempting boot */
21368fe5b6fSgarbled printf("\n");
21468fe5b6fSgarbled printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
21568fe5b6fSgarbled
21668fe5b6fSgarbled for (;;) {
21768fe5b6fSgarbled name = names[n++];
21868fe5b6fSgarbled if (n >= NUMNAMES)
21968fe5b6fSgarbled n = 0;
22068fe5b6fSgarbled setled(0x38100000 + (0x100000 * n));
22168fe5b6fSgarbled exec_kernel(name);
22268fe5b6fSgarbled setled(0x39900000); /* boot failed! */
22368fe5b6fSgarbled }
22468fe5b6fSgarbled }
22568fe5b6fSgarbled
22668fe5b6fSgarbled /*
22768fe5b6fSgarbled * Exec kernel
22868fe5b6fSgarbled */
22968fe5b6fSgarbled static void
exec_kernel(char * name)23068fe5b6fSgarbled exec_kernel(char *name)
23168fe5b6fSgarbled {
23268fe5b6fSgarbled int howto = 0;
23368fe5b6fSgarbled char c, *ptr;
23468fe5b6fSgarbled u_long marks[MARK_MAX];
23568fe5b6fSgarbled #ifdef DBMONITOR
23668fe5b6fSgarbled int go_monitor;
23702cdf4d2Sdsl extern int db_monitor(void);
23868fe5b6fSgarbled
23968fe5b6fSgarbled ret:
24068fe5b6fSgarbled #endif /* DBMONITOR */
24168fe5b6fSgarbled printf("\nBoot: ");
24268fe5b6fSgarbled memset(namebuf, 0, sizeof (namebuf));
24368fe5b6fSgarbled if (tgets(namebuf) == -1)
24468fe5b6fSgarbled printf("\n");
24568fe5b6fSgarbled
24668fe5b6fSgarbled ptr = namebuf;
24768fe5b6fSgarbled #ifdef DBMONITOR
24868fe5b6fSgarbled go_monitor = 0;
24968fe5b6fSgarbled if (*ptr == '!') {
25068fe5b6fSgarbled if (*(++ptr) == NULL) {
25168fe5b6fSgarbled db_monitor();
25268fe5b6fSgarbled printf("\n");
25368fe5b6fSgarbled goto ret;
25468fe5b6fSgarbled } else {
25568fe5b6fSgarbled go_monitor++;
25668fe5b6fSgarbled }
25768fe5b6fSgarbled }
25868fe5b6fSgarbled #endif /* DBMONITOR */
25968fe5b6fSgarbled while ((c = *ptr)) {
26068fe5b6fSgarbled while (c == ' ')
26168fe5b6fSgarbled c = *++ptr;
26268fe5b6fSgarbled if (!c)
26368fe5b6fSgarbled goto next;
26468fe5b6fSgarbled if (c == '-') {
26568fe5b6fSgarbled while ((c = *++ptr) && c != ' ')
26668fe5b6fSgarbled BOOT_FLAG(c, howto);
26768fe5b6fSgarbled } else {
26868fe5b6fSgarbled name = ptr;
26968fe5b6fSgarbled while ((c = *++ptr) && c != ' ');
27068fe5b6fSgarbled if (c)
27168fe5b6fSgarbled *ptr++ = 0;
27268fe5b6fSgarbled }
27368fe5b6fSgarbled }
27468fe5b6fSgarbled
27568fe5b6fSgarbled next:
27668fe5b6fSgarbled printf("Loading %s", name);
27768fe5b6fSgarbled if (howto)
27868fe5b6fSgarbled printf(" (howto 0x%x)", howto);
27968fe5b6fSgarbled printf("\n");
28068fe5b6fSgarbled
28168fe5b6fSgarbled marks[MARK_START] = 0;
28268fe5b6fSgarbled if (loadfile(name, marks, LOAD_ALL) == 0) {
28368fe5b6fSgarbled #ifdef DBMONITOR
28468fe5b6fSgarbled if (go_monitor) {
28568fe5b6fSgarbled db_monitor();
28668fe5b6fSgarbled printf("\n");
28768fe5b6fSgarbled }
28868fe5b6fSgarbled #endif /* DBMONITOR */
28968fe5b6fSgarbled
29068fe5b6fSgarbled printf("start=0x%lx\n\n", marks[MARK_ENTRY]);
29168fe5b6fSgarbled delay(1000);
29268fe5b6fSgarbled __syncicache((void *)marks[MARK_ENTRY],
29368fe5b6fSgarbled (u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]);
29468fe5b6fSgarbled printf("About to run\n");
29568fe5b6fSgarbled run((void *)marks[MARK_SYM],
29668fe5b6fSgarbled (void *)marks[MARK_END],
29768fe5b6fSgarbled (void *)howto,
29868fe5b6fSgarbled (void *)bootinfo,
29968fe5b6fSgarbled (void *)marks[MARK_ENTRY]);
30068fe5b6fSgarbled }
30168fe5b6fSgarbled }
302