1/*	$NetBSD: boot.c,v 1.21 2019/09/03 14:18:32 martin Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <lib/libsa/stand.h>
35#include <lib/libsa/loadfile.h>
36#include <lib/libkern/libkern.h>
37#include <sys/reboot.h>
38#include <sys/boot_flag.h>
39#include <machine/bootinfo.h>
40#include <machine/cpu.h>
41#include <machine/residual.h>
42#include <powerpc/spr.h>
43#include <powerpc/oea/spr.h>
44
45#include "boot.h"
46#include "sdvar.h"
47
48char *names[] = {
49#ifdef SCSI_SUPPORT
50	"sd(0,0,0)netbsd", "sd(0,0,0)onetbsd",
51#endif
52	"in()",
53};
54#define	NUMNAMES (sizeof (names) / sizeof (names[0]))
55
56#define	NAMELEN	128
57char namebuf[NAMELEN];
58char nametmp[NAMELEN];
59
60char bootinfo[BOOTINFO_MAXSIZE];
61struct btinfo_residual btinfo_residual;
62struct btinfo_console btinfo_console;
63struct btinfo_clock btinfo_clock;
64
65RESIDUAL residual;
66
67extern u_long ns_per_tick;
68extern char bootprog_name[], bootprog_rev[];
69
70void boot(void *, u_long);
71static void exec_kernel(char *);
72
73void
74boot(void *resp, u_long loadaddr)
75{
76	extern char _end[], _edata[];
77	int n = 0;
78	int addr, speed;
79	unsigned int cpuvers;
80	char *name, *cnname, *p;
81
82	/* Clear all of BSS */
83	memset(_edata, 0, _end - _edata);
84
85	/*
86	 * console init
87	 */
88	cnname = cninit(&addr, &speed);
89#ifdef VGA_RESET
90	vga_reset((u_char *)0xc0000000);
91#endif
92
93	/* make bootinfo */
94	/*
95	 * residual data
96	 */
97	btinfo_residual.common.next = sizeof(btinfo_residual);
98	btinfo_residual.common.type = BTINFO_RESIDUAL;
99	if (resp) {
100		memcpy(&residual, resp, sizeof(residual));
101		btinfo_residual.addr = (void *)&residual;
102	} else {
103		printf("Warning: no residual data.\n");
104		btinfo_residual.addr = 0;
105	}
106
107	/*
108	 * console
109	 */
110	btinfo_console.common.next = sizeof(btinfo_console);
111	btinfo_console.common.type = BTINFO_CONSOLE;
112	strcpy(btinfo_console.devname, cnname);
113	btinfo_console.addr = addr;
114	btinfo_console.speed = speed;
115
116	/*
117	 * clock
118	 */
119	__asm volatile ("mfpvr %0" : "=r"(cpuvers));
120	cpuvers >>= 16;
121	btinfo_clock.common.next = 0;
122	btinfo_clock.common.type = BTINFO_CLOCK;
123	if (cpuvers == MPC601) {
124		btinfo_clock.ticks_per_sec = 1000000000;
125	} else {
126		btinfo_clock.ticks_per_sec = resp ?
127		    residual.VitalProductData.ProcessorBusHz/4 : TICKS_PER_SEC;
128	}
129	ns_per_tick = 1000000000 / btinfo_clock.ticks_per_sec;
130
131	p = bootinfo;
132        memcpy(p, (void *)&btinfo_residual, sizeof(btinfo_residual));
133        p += sizeof(btinfo_residual);
134        memcpy(p, (void *)&btinfo_console, sizeof(btinfo_console));
135        p += sizeof(btinfo_console);
136        memcpy(p, (void *)&btinfo_clock, sizeof(btinfo_clock));
137
138	/*
139	 * load kernel if attached
140	 */
141	init_in(loadaddr);
142
143	printf("\n");
144	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
145	printf("\n");
146
147#ifdef SCSI_SUPPORT
148	/*
149	 * Initialize siop@pci0 dev 16 func 0
150	 */
151	siop_init(0, 16, 0);
152#endif
153
154	for (;;) {
155		name = names[n++];
156		if (n >= NUMNAMES)
157			n = 0;
158
159		exec_kernel(name);
160	}
161}
162
163/*
164 * Exec kernel
165 */
166static void
167exec_kernel(char *name)
168{
169	int howto = 0;
170	char c, *ptr;
171	u_long marks[MARK_MAX];
172#ifdef DBMONITOR
173	int go_monitor;
174	extern int db_monitor(void);
175
176ret:
177#endif /* DBMONITOR */
178	printf("\nBoot: ");
179	memset(namebuf, 0, sizeof (namebuf));
180	if (tgets(namebuf) == -1)
181		printf("\n");
182
183	ptr = namebuf;
184#ifdef DBMONITOR
185	go_monitor = 0;
186	if (*ptr == '!') {
187		if (*(++ptr) == NULL) {
188			db_monitor();
189			printf("\n");
190			goto ret;
191		} else {
192			go_monitor++;
193		}
194	}
195#endif /* DBMONITOR */
196	while ((c = *ptr)) {
197		while (c == ' ')
198			c = *++ptr;
199		if (!c)
200			goto next;
201		if (c == '-') {
202			while ((c = *++ptr) && c != ' ')
203				BOOT_FLAG(c, howto);
204		} else {
205			name = ptr;
206			while ((c = *++ptr) && c != ' ');
207			if (c)
208				*ptr++ = 0;
209		}
210	}
211
212next:
213	printf("Loading %s", name);
214	if (howto)
215		printf(" (howto 0x%x)", howto);
216	printf("\n");
217
218	marks[MARK_START] = 0;
219	if (loadfile(name, marks, LOAD_ALL) == 0) {
220#ifdef DBMONITOR
221		if (go_monitor) {
222			db_monitor();
223			printf("\n");
224		}
225#endif /* DBMONITOR */
226
227		printf("start=0x%lx\n\n", marks[MARK_ENTRY]);
228		delay(1000);
229		__syncicache((void *)marks[MARK_ENTRY],
230			(u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]);
231
232		run((void *)marks[MARK_SYM],
233		    (void *)marks[MARK_END],
234		    (void *)howto,
235		    (void *)bootinfo,
236		    (void *)marks[MARK_ENTRY]);
237	}
238}
239
240void
241_rtt(void)
242{
243
244	/* XXXX */
245	__unreachable();
246}
247