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", ®[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