xref: /openbsd/sys/arch/loongson/stand/boot/machdep.c (revision cca36db2)
1 /*	$OpenBSD: machdep.c,v 1.4 2010/04/03 19:13:27 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 2010 Miodrag Vallat.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * Copyright (c) 1998-2004 Michael Shalayeff
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the above copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
35  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
41  * THE POSSIBILITY OF SUCH DAMAGE.
42  */
43 
44 #include <sys/param.h>
45 #include <lib/libkern/libkern.h>
46 #include "libsa.h"
47 #include <machine/cpu.h>
48 #include <machine/pmon.h>
49 #include <stand/boot/cmd.h>
50 
51 void	gdium_abort(void);
52 int	is_gdium;
53 int	boot_rd;
54 
55 extern int bootprompt;
56 
57 /*
58  * Console
59  */
60 
61 int
62 cnspeed(dev_t dev, int sp)
63 {
64 	return 9600;
65 }
66 
67 int
68 getchar()
69 {
70 	int c = cngetc();
71 
72 	if (c == '\r')
73 		c = '\n';
74 
75 	if ((c < ' ' && c != '\n') || c == '\177')
76 		return c;
77 
78 	putchar(c);
79 
80 	return c;
81 }
82 
83 int pch_pos;
84 
85 void
86 putchar(int c)
87 {
88 	switch (c) {
89 	case '\177':	/* DEL erases */
90 		cnputc('\b');
91 		cnputc(' ');
92 	case '\b':
93 		cnputc('\b');
94 		if (pch_pos)
95 			pch_pos--;
96 		break;
97 	case '\t':
98 		do
99 			cnputc(' ');
100 		while (++pch_pos % 8) ;
101 		break;
102 	case '\n':
103 	case '\r':
104 		cnputc(c);
105 		pch_pos = 0;
106 		break;
107 	default:
108 		cnputc(c);
109 		pch_pos++;
110 		break;
111 	}
112 }
113 
114 char *
115 ttyname(int fd)
116 {
117 	return "pmon console";
118 }
119 
120 dev_t
121 ttydev(char *name)
122 {
123 	/* we do not support any other console than pmon */
124 	return NODEV;
125 }
126 
127 /*
128  * Configuration and device path aerobics
129  */
130 
131 /*
132  * Return the default boot device.
133  */
134 void
135 devboot(dev_t dev, char *path)
136 {
137 	const char *bootpath = NULL;
138 	size_t bootpathlen = 0;	/* gcc -Wall */
139 	const char *tmp;
140 	int i;
141 
142 	/*
143 	 * If we are booting the initrd image, things are easy...
144 	 */
145 
146 	if (dev != 0) {
147 		strlcpy(path, "rd0a", BOOTDEVLEN);
148 		return;
149 	}
150 
151 	/*
152 	 * First, try to figure where we have been loaded from; we'll assume
153 	 * the default device to load the kernel from is the same.
154 	 *
155 	 * We may have been loaded in three different ways:
156 	 * - automatic load from `al' environment variable (similar to a
157 	 *   `load' and `go' sequence).
158 	 * - manual `boot' command, with path on the commandline.
159 	 * - manual `load' and `go' commands, with no path on the commandline.
160 	 */
161 
162 	if (pmon_argc > 0) {
163 		tmp = (const char *)pmon_getarg(0);
164 		if (tmp[0] != 'g') {
165 			/* manual load */
166 			for (i = 1; i < pmon_argc; i++) {
167 				tmp = (const char *)pmon_getarg(i);
168 				if (tmp[0] != '-') {
169 					bootpath = tmp;
170 					break;
171 				}
172 			}
173 		} else {
174 			/* possible automatic load */
175 			bootpath = pmon_getenv("al");
176 		}
177 	}
178 
179 	/*
180 	 * If the bootblocks have been loaded from the network,
181 	 * use the default disk.
182 	 */
183 
184 	if (bootpath != NULL && strncmp(bootpath, "tftp://", 7) == 0)
185 		bootpath = NULL;
186 
187 	/*
188 	 * Now extract the device name from the bootpath.
189 	 */
190 
191 	if (bootpath != NULL) {
192 		tmp = strchr(bootpath, '@');
193 		if (tmp == NULL) {
194 			bootpath = NULL;
195 		} else {
196 			bootpath = tmp + 1;
197 			tmp = strchr(bootpath, '/');
198 			if (tmp == NULL) {
199 				bootpath = NULL;
200 			} else {
201 				bootpathlen = tmp - bootpath;
202 			}
203 		}
204 	}
205 
206 	if (bootpath != NULL && bootpathlen >= 3) {
207 		if (bootpathlen >= BOOTDEVLEN)
208 			bootpathlen = BOOTDEVLEN - 1;
209 		strncpy(path, bootpath, bootpathlen);
210 		path[bootpathlen] = '\0';
211 		/* only add a partition letter if there is none */
212 		if (bootpath[bootpathlen - 1] >= '0' &&
213 		    bootpath[bootpathlen - 1] <= '9')
214 			strlcat(path, "a", BOOTDEVLEN);
215 	} else {
216 		strlcpy(path, "wd0a", BOOTDEVLEN);
217 	}
218 }
219 
220 /*
221  * Ugly (lack of) clock routines
222  */
223 
224 time_t
225 getsecs()
226 {
227 	return 0;
228 }
229 
230 /*
231  * Initialization
232  */
233 
234 void
235 machdep()
236 {
237 	const char *envvar;
238 
239 	/*
240 	 * Since we can't have non-blocking input, we will try to
241 	 * autoload the kernel pointed to by the `bsd' environment
242 	 * variable, and fallback to interactive mode if the variable
243 	 * is empty or the load fails.
244 	 */
245 
246 	if (boot_rd == 0) {
247 		envvar = pmon_getenv("bsd");
248 		if (envvar != NULL) {
249 			bootprompt = 0;
250 			kernelfile = (char *)envvar;
251 		} else {
252 			if (is_gdium)
253 				gdium_abort();
254 		}
255 	}
256 }
257 
258 int
259 main()
260 {
261 	const char *envvar;
262 
263 	cninit();
264 
265 	/*
266 	 * Figure out whether we are running on a Gdium system, which
267 	 * has an horribly castrated PMON. If we do, the best we can do
268 	 * is boot an initrd image.
269 	 */
270 	envvar = pmon_getenv("Version");
271 	if (envvar != NULL && strncmp(envvar, "Gdium", 5) == 0)
272 		is_gdium = 1;
273 
274 	/*
275 	 * Check if we have a valid initrd loaded.
276 	 */
277 
278 	envvar = pmon_getenv("rd");
279 	if (envvar != NULL && *envvar != '\0')
280 		boot_rd = rd_isvalid();
281 
282 	if (boot_rd != 0)
283 		bootprompt = 0;
284 
285 	boot(boot_rd);
286 	return 0;
287 }
288 
289 void
290 gdium_abort()
291 {
292 	/* Here's a nickel, kid.  Get yourself a better firmware */
293 	printf("\n\nSorry, OpenBSD boot blocks do not work on Gdium, "
294 	    "because of dire firmware limitations.\n"
295 	    "Also, the firmware has reset the USB controller so you "
296 	    "will need to power cycle.\n"
297 	    "We would apologize for this incovenience, but we have "
298 	    "no control about the firmware of your machine.\n\n");
299 	rd_invalidate();
300 	_rtt();
301 }
302