xref: /freebsd-src/stand/powerpc/ofw/main.c (revision 3e15b01d6914c927e37d1699645783acf286655c)
1e05bc4f9SNathan Whitehorn /*-
2e05bc4f9SNathan Whitehorn  * Copyright (c) 2000 Benno Rice <benno@jeamland.net>
3e05bc4f9SNathan Whitehorn  * Copyright (c) 2000 Stephane Potvin <sepotvin@videotron.ca>
4e05bc4f9SNathan Whitehorn  * All rights reserved.
5e05bc4f9SNathan Whitehorn  *
6e05bc4f9SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
7e05bc4f9SNathan Whitehorn  * modification, are permitted provided that the following conditions
8e05bc4f9SNathan Whitehorn  * are met:
9e05bc4f9SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
10e05bc4f9SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
11e05bc4f9SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
12e05bc4f9SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
13e05bc4f9SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
14e05bc4f9SNathan Whitehorn  *
15e05bc4f9SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16e05bc4f9SNathan Whitehorn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e05bc4f9SNathan Whitehorn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e05bc4f9SNathan Whitehorn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e05bc4f9SNathan Whitehorn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e05bc4f9SNathan Whitehorn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e05bc4f9SNathan Whitehorn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e05bc4f9SNathan Whitehorn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e05bc4f9SNathan Whitehorn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e05bc4f9SNathan Whitehorn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e05bc4f9SNathan Whitehorn  * SUCH DAMAGE.
26e05bc4f9SNathan Whitehorn  */
27e05bc4f9SNathan Whitehorn 
28f8328864SLeandro Lupori #include <sys/endian.h>
29f8328864SLeandro Lupori 
30e05bc4f9SNathan Whitehorn #include <stand.h>
31e05bc4f9SNathan Whitehorn #include "openfirm.h"
32e05bc4f9SNathan Whitehorn #include "libofw.h"
33e05bc4f9SNathan Whitehorn #include "bootstrap.h"
34e05bc4f9SNathan Whitehorn 
35f8328864SLeandro Lupori #include <machine/asm.h>
3618a119d7SNathan Whitehorn #include <machine/psl.h>
3718a119d7SNathan Whitehorn 
38e05bc4f9SNathan Whitehorn struct arch_switch	archsw;		/* MI/MD interface boundary */
39e05bc4f9SNathan Whitehorn 
40e05bc4f9SNathan Whitehorn extern char end[];
41e05bc4f9SNathan Whitehorn 
4256e53cb8SWarner Losh uint32_t	acells, scells;
43e05bc4f9SNathan Whitehorn 
44e05bc4f9SNathan Whitehorn static char bootargs[128];
45e05bc4f9SNathan Whitehorn 
46e05bc4f9SNathan Whitehorn #define	HEAP_SIZE	0x800000
47e05bc4f9SNathan Whitehorn static char heap[HEAP_SIZE]; // In BSS, so uses no space
48e05bc4f9SNathan Whitehorn 
49e05bc4f9SNathan Whitehorn #define OF_puts(fd, text) OF_write(fd, text, strlen(text))
50e05bc4f9SNathan Whitehorn 
5118a119d7SNathan Whitehorn static __inline register_t
mfmsr(void)5218a119d7SNathan Whitehorn mfmsr(void)
5318a119d7SNathan Whitehorn {
5418a119d7SNathan Whitehorn 	register_t value;
5518a119d7SNathan Whitehorn 
5618a119d7SNathan Whitehorn 	__asm __volatile ("mfmsr %0" : "=r"(value));
5718a119d7SNathan Whitehorn 
5818a119d7SNathan Whitehorn 	return (value);
5918a119d7SNathan Whitehorn }
6018a119d7SNathan Whitehorn 
61e05bc4f9SNathan Whitehorn void
init_heap(void)62e05bc4f9SNathan Whitehorn init_heap(void)
63e05bc4f9SNathan Whitehorn {
64e05bc4f9SNathan Whitehorn 	bzero(heap, HEAP_SIZE);
65e05bc4f9SNathan Whitehorn 
669e4c35f8SBrandon Bergren 	setheap(heap, (void *)((uintptr_t)heap + HEAP_SIZE));
67e05bc4f9SNathan Whitehorn }
68e05bc4f9SNathan Whitehorn 
69e05bc4f9SNathan Whitehorn uint64_t
memsize(void)70e05bc4f9SNathan Whitehorn memsize(void)
71e05bc4f9SNathan Whitehorn {
72e05bc4f9SNathan Whitehorn 	phandle_t	memoryp;
73e05bc4f9SNathan Whitehorn 	cell_t		reg[24];
74e05bc4f9SNathan Whitehorn 	int		i, sz;
7556e53cb8SWarner Losh 	uint64_t	memsz;
76e05bc4f9SNathan Whitehorn 
77e05bc4f9SNathan Whitehorn 	memsz = 0;
78e05bc4f9SNathan Whitehorn 	memoryp = OF_instance_to_package(memory);
79e05bc4f9SNathan Whitehorn 
80f8328864SLeandro Lupori 	sz = OF_getencprop(memoryp, "reg", &reg[0], sizeof(reg));
81e05bc4f9SNathan Whitehorn 	sz /= sizeof(reg[0]);
82e05bc4f9SNathan Whitehorn 
83e05bc4f9SNathan Whitehorn 	for (i = 0; i < sz; i += (acells + scells)) {
84e05bc4f9SNathan Whitehorn 		if (scells > 1)
85e05bc4f9SNathan Whitehorn 			memsz += (uint64_t)reg[i + acells] << 32;
86e05bc4f9SNathan Whitehorn 		memsz += reg[i + acells + scells - 1];
87e05bc4f9SNathan Whitehorn 	}
88e05bc4f9SNathan Whitehorn 
89e05bc4f9SNathan Whitehorn 	return (memsz);
90e05bc4f9SNathan Whitehorn }
91e05bc4f9SNathan Whitehorn 
9283e356c3SLeandro Lupori #ifdef CAS
9383e356c3SLeandro Lupori extern int ppc64_cas(void);
9483e356c3SLeandro Lupori 
9583e356c3SLeandro Lupori static int
ppc64_autoload(void)9683e356c3SLeandro Lupori ppc64_autoload(void)
9783e356c3SLeandro Lupori {
9883e356c3SLeandro Lupori 	const char *cas;
9983e356c3SLeandro Lupori 
10083e356c3SLeandro Lupori 	if ((cas = getenv("cas")) && cas[0] == '1')
10183e356c3SLeandro Lupori 		if (ppc64_cas() != 0)
10283e356c3SLeandro Lupori 			return (-1);
10383e356c3SLeandro Lupori 	return (ofw_autoload());
10483e356c3SLeandro Lupori }
10583e356c3SLeandro Lupori #endif
10683e356c3SLeandro Lupori 
107f8328864SLeandro Lupori #if BYTE_ORDER == LITTLE_ENDIAN
108f8328864SLeandro Lupori /*
109f8328864SLeandro Lupori  * In Little-endian, we cannot just branch to the client interface. Since
110f8328864SLeandro Lupori  * the client interface is big endian, we have to rfid to it.
111f8328864SLeandro Lupori  * Likewise, when execution resumes, we are in the wrong endianness so
112f8328864SLeandro Lupori  * we must do a fixup before returning to the caller.
113f8328864SLeandro Lupori  */
114f8328864SLeandro Lupori static int (*openfirmware_entry)(void *);
115f8328864SLeandro Lupori extern int openfirmware_trampoline(void *buf, int (*cb)(void *));
116f8328864SLeandro Lupori 
117f8328864SLeandro Lupori /*
118f8328864SLeandro Lupori  * Wrapper to pass the real entry point to our trampoline.
119f8328864SLeandro Lupori  */
120f8328864SLeandro Lupori static int
openfirmware_docall(void * buf)121f8328864SLeandro Lupori openfirmware_docall(void *buf)
122f8328864SLeandro Lupori {
123f8328864SLeandro Lupori 	return openfirmware_trampoline(buf, openfirmware_entry);
124f8328864SLeandro Lupori }
125f8328864SLeandro Lupori #endif
126f8328864SLeandro Lupori 
127e05bc4f9SNathan Whitehorn int
main(int (* openfirm)(void *))128e05bc4f9SNathan Whitehorn main(int (*openfirm)(void *))
129e05bc4f9SNathan Whitehorn {
130e05bc4f9SNathan Whitehorn 	phandle_t	root;
131e05bc4f9SNathan Whitehorn 	int		i;
132e05bc4f9SNathan Whitehorn 	char		bootpath[64];
133e05bc4f9SNathan Whitehorn 	char		*ch;
134e05bc4f9SNathan Whitehorn 	int		bargc;
135e05bc4f9SNathan Whitehorn 	char		**bargv;
136e05bc4f9SNathan Whitehorn 
137e05bc4f9SNathan Whitehorn 	/*
138e05bc4f9SNathan Whitehorn 	 * Initialise the Open Firmware routines by giving them the entry point.
139e05bc4f9SNathan Whitehorn 	 */
140f8328864SLeandro Lupori #if BYTE_ORDER == LITTLE_ENDIAN
141f8328864SLeandro Lupori 	/*
142f8328864SLeandro Lupori 	 * Use a trampoline entry point for endian fixups.
143f8328864SLeandro Lupori 	 */
144f8328864SLeandro Lupori 	openfirmware_entry = openfirm;
145f8328864SLeandro Lupori 	OF_init(openfirmware_docall);
146f8328864SLeandro Lupori #else
147e05bc4f9SNathan Whitehorn 	OF_init(openfirm);
148f8328864SLeandro Lupori #endif
149e05bc4f9SNathan Whitehorn 
150e05bc4f9SNathan Whitehorn 	root = OF_finddevice("/");
151e05bc4f9SNathan Whitehorn 
152e05bc4f9SNathan Whitehorn 	scells = acells = 1;
153f8328864SLeandro Lupori 	OF_getencprop(root, "#address-cells", &acells, sizeof(acells));
154f8328864SLeandro Lupori 	OF_getencprop(root, "#size-cells", &scells, sizeof(scells));
155e05bc4f9SNathan Whitehorn 
156e05bc4f9SNathan Whitehorn 	/*
157e05bc4f9SNathan Whitehorn 	 * Initialise the heap as early as possible.  Once this is done,
158e05bc4f9SNathan Whitehorn 	 * alloc() is usable. The stack is buried inside us, so this is
159e05bc4f9SNathan Whitehorn 	 * safe.
160e05bc4f9SNathan Whitehorn 	 */
161e05bc4f9SNathan Whitehorn 	init_heap();
162e05bc4f9SNathan Whitehorn 
163e05bc4f9SNathan Whitehorn 	/*
164e05bc4f9SNathan Whitehorn          * Set up console.
165e05bc4f9SNathan Whitehorn          */
166e05bc4f9SNathan Whitehorn 	cons_probe();
167e05bc4f9SNathan Whitehorn 
168680ca739SLeandro Lupori 	archsw.arch_getdev = ofw_getdev;
169680ca739SLeandro Lupori 	archsw.arch_copyin = ofw_copyin;
170680ca739SLeandro Lupori 	archsw.arch_copyout = ofw_copyout;
171680ca739SLeandro Lupori 	archsw.arch_readin = ofw_readin;
172680ca739SLeandro Lupori #ifdef CAS
173680ca739SLeandro Lupori 	setenv("cas", "1", 0);
174680ca739SLeandro Lupori 	archsw.arch_autoload = ppc64_autoload;
175680ca739SLeandro Lupori #else
176680ca739SLeandro Lupori 	archsw.arch_autoload = ofw_autoload;
177680ca739SLeandro Lupori #endif
178680ca739SLeandro Lupori 
179b4cb3fe0SToomas Soome 	/* Set up currdev variable to have hooks in place. */
180*1c1783d6SWarner Losh 	env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset);
181b4cb3fe0SToomas Soome 
18266012c8fSWarner Losh 	devinit();
183e05bc4f9SNathan Whitehorn 
184e05bc4f9SNathan Whitehorn 	printf("\n%s", bootprog_info);
185e05bc4f9SNathan Whitehorn 	printf("Memory: %lldKB\n", memsize() / 1024);
186e05bc4f9SNathan Whitehorn 
187e05bc4f9SNathan Whitehorn 	OF_getprop(chosen, "bootpath", bootpath, 64);
188e05bc4f9SNathan Whitehorn 	ch = strchr(bootpath, ':');
189e05bc4f9SNathan Whitehorn 	*ch = '\0';
190e05bc4f9SNathan Whitehorn 	printf("Booted from: %s\n", bootpath);
191e05bc4f9SNathan Whitehorn 
192e05bc4f9SNathan Whitehorn 	printf("\n");
193e05bc4f9SNathan Whitehorn 
194e05bc4f9SNathan Whitehorn 	/*
195e05bc4f9SNathan Whitehorn 	 * Only parse the first bootarg if present. It should
196e05bc4f9SNathan Whitehorn 	 * be simple to handle extra arguments
197e05bc4f9SNathan Whitehorn 	 */
198e05bc4f9SNathan Whitehorn 	OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs));
199e05bc4f9SNathan Whitehorn 	bargc = 0;
200e05bc4f9SNathan Whitehorn 	parse(&bargc, &bargv, bootargs);
201e05bc4f9SNathan Whitehorn 	if (bargc == 1)
202*1c1783d6SWarner Losh 		env_setenv("currdev", EV_VOLATILE, bargv[0], gen_setcurrdev,
203e05bc4f9SNathan Whitehorn 		    env_nounset);
204e05bc4f9SNathan Whitehorn 	else
205e05bc4f9SNathan Whitehorn 		env_setenv("currdev", EV_VOLATILE, bootpath,
206*1c1783d6SWarner Losh 			   gen_setcurrdev, env_nounset);
207e05bc4f9SNathan Whitehorn 	env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset,
208e05bc4f9SNathan Whitehorn 	    env_nounset);
209e05bc4f9SNathan Whitehorn 	setenv("LINES", "24", 1);		/* optional */
210e05bc4f9SNathan Whitehorn 
21118a119d7SNathan Whitehorn 	/*
21218a119d7SNathan Whitehorn 	 * On non-Apple hardware, where it works reliably, pass flattened
21318a119d7SNathan Whitehorn 	 * device trees to the kernel by default instead of OF CI pointers.
21418a119d7SNathan Whitehorn 	 * Apple hardware is the only virtual-mode OF implementation in
21518a119d7SNathan Whitehorn 	 * existence, so far as I am aware, so use that as a flag.
21618a119d7SNathan Whitehorn 	 */
21718a119d7SNathan Whitehorn 	if (!(mfmsr() & PSL_DR))
21818a119d7SNathan Whitehorn 		setenv("usefdt", "1", 1);
21918a119d7SNathan Whitehorn 
220e05bc4f9SNathan Whitehorn 	interact();				/* doesn't return */
221e05bc4f9SNathan Whitehorn 
222e05bc4f9SNathan Whitehorn 	OF_exit();
223e05bc4f9SNathan Whitehorn 
224e05bc4f9SNathan Whitehorn 	return 0;
225e05bc4f9SNathan Whitehorn }
226e05bc4f9SNathan Whitehorn 
227e05bc4f9SNathan Whitehorn COMMAND_SET(halt, "halt", "halt the system", command_halt);
228e05bc4f9SNathan Whitehorn 
229e05bc4f9SNathan Whitehorn static int
command_halt(int argc,char * argv[])230e05bc4f9SNathan Whitehorn command_halt(int argc, char *argv[])
231e05bc4f9SNathan Whitehorn {
232e05bc4f9SNathan Whitehorn 
233e05bc4f9SNathan Whitehorn 	OF_exit();
234e05bc4f9SNathan Whitehorn 	return (CMD_OK);
235e05bc4f9SNathan Whitehorn }
236e05bc4f9SNathan Whitehorn 
237e05bc4f9SNathan Whitehorn COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
238e05bc4f9SNathan Whitehorn 
239e05bc4f9SNathan Whitehorn int
command_memmap(int argc,char ** argv)240e05bc4f9SNathan Whitehorn command_memmap(int argc, char **argv)
241e05bc4f9SNathan Whitehorn {
242e05bc4f9SNathan Whitehorn 
243e05bc4f9SNathan Whitehorn 	ofw_memmap(acells);
244e05bc4f9SNathan Whitehorn 	return (CMD_OK);
245e05bc4f9SNathan Whitehorn }
246