Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/powerpc/ofw/main.c
34869 views
1
/*-
2
* Copyright (c) 2000 Benno Rice <[email protected]>
3
* Copyright (c) 2000 Stephane Potvin <[email protected]>
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/endian.h>
29
30
#include <stand.h>
31
#include "openfirm.h"
32
#include "libofw.h"
33
#include "bootstrap.h"
34
35
#include <machine/asm.h>
36
#include <machine/psl.h>
37
38
#ifdef CAS
39
static int ppc64_autoload(void);
40
#endif
41
42
struct arch_switch archsw = { /* MI/MD interface boundary */
43
.arch_getdev = ofw_getdev,
44
.arch_copyin = ofw_copyin,
45
.arch_copyout = ofw_copyout,
46
.arch_readin = ofw_readin,
47
#ifdef CAS
48
.arch_autoload = ppc64_autoload,
49
#else
50
.arch_autoload = ofw_autoload,
51
#endif
52
};
53
54
uint32_t acells, scells;
55
56
static char bootargs[128];
57
58
#define HEAP_SIZE 0x800000
59
static char heap[HEAP_SIZE]; // In BSS, so uses no space
60
61
#define OF_puts(fd, text) OF_write(fd, text, strlen(text))
62
63
static __inline register_t
64
mfmsr(void)
65
{
66
register_t value;
67
68
__asm __volatile ("mfmsr %0" : "=r"(value));
69
70
return (value);
71
}
72
73
void
74
init_heap(void)
75
{
76
bzero(heap, HEAP_SIZE);
77
78
setheap(heap, (void *)((uintptr_t)heap + HEAP_SIZE));
79
}
80
81
uint64_t
82
memsize(void)
83
{
84
phandle_t memoryp;
85
cell_t reg[24];
86
int i, sz;
87
uint64_t memsz;
88
89
memsz = 0;
90
memoryp = OF_instance_to_package(memory);
91
92
sz = OF_getencprop(memoryp, "reg", &reg[0], sizeof(reg));
93
sz /= sizeof(reg[0]);
94
95
for (i = 0; i < sz; i += (acells + scells)) {
96
if (scells > 1)
97
memsz += (uint64_t)reg[i + acells] << 32;
98
memsz += reg[i + acells + scells - 1];
99
}
100
101
return (memsz);
102
}
103
104
#ifdef CAS
105
extern int ppc64_cas(void);
106
107
static int
108
ppc64_autoload(void)
109
{
110
const char *cas;
111
112
if ((cas = getenv("cas")) && cas[0] == '1')
113
if (ppc64_cas() != 0)
114
return (-1);
115
return (ofw_autoload());
116
}
117
#endif
118
119
#if BYTE_ORDER == LITTLE_ENDIAN
120
/*
121
* In Little-endian, we cannot just branch to the client interface. Since
122
* the client interface is big endian, we have to rfid to it.
123
* Likewise, when execution resumes, we are in the wrong endianness so
124
* we must do a fixup before returning to the caller.
125
*/
126
static int (*openfirmware_entry)(void *);
127
extern int openfirmware_trampoline(void *buf, int (*cb)(void *));
128
129
/*
130
* Wrapper to pass the real entry point to our trampoline.
131
*/
132
static int
133
openfirmware_docall(void *buf)
134
{
135
return openfirmware_trampoline(buf, openfirmware_entry);
136
}
137
#endif
138
139
int
140
main(int (*openfirm)(void *))
141
{
142
phandle_t root;
143
int i;
144
char bootpath[64];
145
char *ch;
146
int bargc;
147
char **bargv;
148
149
/*
150
* Initialise the Open Firmware routines by giving them the entry point.
151
*/
152
#if BYTE_ORDER == LITTLE_ENDIAN
153
/*
154
* Use a trampoline entry point for endian fixups.
155
*/
156
openfirmware_entry = openfirm;
157
OF_init(openfirmware_docall);
158
#else
159
OF_init(openfirm);
160
#endif
161
162
root = OF_finddevice("/");
163
164
scells = acells = 1;
165
OF_getencprop(root, "#address-cells", &acells, sizeof(acells));
166
OF_getencprop(root, "#size-cells", &scells, sizeof(scells));
167
168
/*
169
* Initialise the heap as early as possible. Once this is done,
170
* alloc() is usable. The stack is buried inside us, so this is
171
* safe.
172
*/
173
init_heap();
174
175
/*
176
* Set up console.
177
*/
178
cons_probe();
179
180
#ifdef CAS
181
setenv("cas", "1", 0);
182
#endif
183
184
/* Set up currdev variable to have hooks in place. */
185
env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset);
186
187
devinit();
188
189
printf("\n%s", bootprog_info);
190
printf("Memory: %lldKB\n", memsize() / 1024);
191
192
OF_getprop(chosen, "bootpath", bootpath, 64);
193
ch = strchr(bootpath, ':');
194
*ch = '\0';
195
printf("Booted from: %s\n", bootpath);
196
197
printf("\n");
198
199
/*
200
* Only parse the first bootarg if present. It should
201
* be simple to handle extra arguments
202
*/
203
OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs));
204
bargc = 0;
205
parse(&bargc, &bargv, bootargs);
206
if (bargc == 1)
207
env_setenv("currdev", EV_VOLATILE, bargv[0], gen_setcurrdev,
208
env_nounset);
209
else
210
env_setenv("currdev", EV_VOLATILE, bootpath,
211
gen_setcurrdev, env_nounset);
212
env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset,
213
env_nounset);
214
setenv("LINES", "24", 1); /* optional */
215
216
/*
217
* On non-Apple hardware, where it works reliably, pass flattened
218
* device trees to the kernel by default instead of OF CI pointers.
219
* Apple hardware is the only virtual-mode OF implementation in
220
* existence, so far as I am aware, so use that as a flag.
221
*/
222
if (!(mfmsr() & PSL_DR))
223
setenv("usefdt", "1", 1);
224
225
interact(); /* doesn't return */
226
227
OF_exit();
228
229
return 0;
230
}
231
232
COMMAND_SET(halt, "halt", "halt the system", command_halt);
233
234
static int
235
command_halt(int argc, char *argv[])
236
{
237
238
OF_exit();
239
return (CMD_OK);
240
}
241
242
COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
243
244
int
245
command_memmap(int argc, char **argv)
246
{
247
248
ofw_memmap(acells);
249
return (CMD_OK);
250
}
251
252