1/*-
2 * Copyright (C) 2010 Nathan Whitehorn
3 * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru)
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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <stand.h>
31#include <sys/param.h>
32
33#define _KERNEL
34#include <machine/cpufunc.h>
35
36#include "bootstrap.h"
37#include "lv1call.h"
38#include "ps3.h"
39#include "ps3devdesc.h"
40
41struct arch_switch	archsw;
42extern void *_end;
43
44extern char bootprog_name[];
45extern char bootprog_rev[];
46extern char bootprog_date[];
47extern char bootprog_maker[];
48
49int ps3_getdev(void **vdev, const char *devspec, const char **path);
50ssize_t ps3_copyin(const void *src, vm_offset_t dest, const size_t len);
51ssize_t ps3_copyout(vm_offset_t src, void *dest, const size_t len);
52ssize_t ps3_readin(const int fd, vm_offset_t dest, const size_t len);
53int ps3_autoload(void);
54int ps3_setcurrdev(struct env_var *ev, int flags, const void *value);
55
56static uint64_t basetb;
57
58int
59main(void)
60{
61	uint64_t maxmem = 0;
62	void *heapbase;
63	int i, err;
64	struct ps3_devdesc currdev;
65	struct open_file f;
66
67	lv1_get_physmem(&maxmem);
68
69	ps3mmu_init(maxmem);
70
71	/*
72	 * Set up console.
73	 */
74	cons_probe();
75
76	/*
77	 * Set the heap to one page after the end of the loader.
78	 */
79	heapbase = (void *)(maxmem - 0x80000);
80	setheap(heapbase, maxmem);
81
82	/*
83	 * March through the device switch probing for things.
84	 */
85	for (i = 0; devsw[i] != NULL; i++) {
86		if (devsw[i]->dv_init != NULL) {
87			err = (devsw[i]->dv_init)();
88			if (err) {
89				printf("\n%s: initialization failed err=%d\n",
90					devsw[i]->dv_name, err);
91				continue;
92			}
93		}
94
95		currdev.d_dev = devsw[i];
96		currdev.d_type = currdev.d_dev->dv_type;
97
98		if (strcmp(devsw[i]->dv_name, "cd") == 0) {
99			f.f_devdata = &currdev;
100			currdev.d_unit = 0;
101
102			if (devsw[i]->dv_open(&f, &currdev) == 0)
103				break;
104		}
105
106		if (strcmp(devsw[i]->dv_name, "disk") == 0) {
107			f.f_devdata = &currdev;
108			currdev.d_unit = 3;
109			currdev.d_disk.pnum = 1;
110			currdev.d_disk.ptype = PTYPE_GPT;
111
112			if (devsw[i]->dv_open(&f, &currdev) == 0)
113				break;
114		}
115
116		if (strcmp(devsw[i]->dv_name, "net") == 0)
117			break;
118	}
119
120	if (devsw[i] == NULL)
121		panic("No boot device found!");
122	else
123		printf("Boot device: %s\n", devsw[i]->dv_name);
124
125	/*
126	 * Get timebase at boot.
127	 */
128	basetb = mftb();
129
130	archsw.arch_getdev = ps3_getdev;
131	archsw.arch_copyin = ps3_copyin;
132	archsw.arch_copyout = ps3_copyout;
133	archsw.arch_readin = ps3_readin;
134	archsw.arch_autoload = ps3_autoload;
135
136	printf("\n");
137	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
138	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
139	printf("Memory: %lldKB\n", maxmem / 1024);
140
141	env_setenv("currdev", EV_VOLATILE, ps3_fmtdev(&currdev),
142	    ps3_setcurrdev, env_nounset);
143	env_setenv("loaddev", EV_VOLATILE, ps3_fmtdev(&currdev), env_noset,
144	    env_nounset);
145	setenv("LINES", "24", 1);
146	setenv("hw.platform", "ps3", 1);
147
148	interact();			/* doesn't return */
149
150	return (0);
151}
152
153void
154ppc_exception(int code, vm_offset_t where, register_t msr)
155{
156	mtmsr(PSL_IR | PSL_DR | PSL_RI);
157	printf("Exception %x at %#lx!\n", code, where);
158	printf("Rebooting in 5 seconds...\n");
159	delay(10000000);
160	lv1_panic(1);
161}
162
163const u_int ns_per_tick = 12;
164
165void
166exit(int code)
167{
168	lv1_panic(code);
169}
170
171void
172delay(int usecs)
173{
174	uint64_t tb,ttb;
175	tb = mftb();
176
177	ttb = tb + (usecs * 1000 + ns_per_tick - 1) / ns_per_tick;
178	while (tb < ttb)
179		tb = mftb();
180}
181
182int
183getsecs()
184{
185	return ((mftb() - basetb)*ns_per_tick/1000000000);
186}
187
188time_t
189time(time_t *tloc)
190{
191	time_t rv;
192
193	rv = getsecs();
194	if (tloc != NULL)
195		*tloc = rv;
196
197	return (rv);
198}
199
200ssize_t
201ps3_copyin(const void *src, vm_offset_t dest, const size_t len)
202{
203	bcopy(src, (void *)dest, len);
204	return (len);
205}
206
207ssize_t
208ps3_copyout(vm_offset_t src, void *dest, const size_t len)
209{
210	bcopy((void *)src, dest, len);
211	return (len);
212}
213
214ssize_t
215ps3_readin(const int fd, vm_offset_t dest, const size_t len)
216{
217	void            *buf;
218	size_t          resid, chunk, get;
219	ssize_t         got;
220	vm_offset_t     p;
221
222	p = dest;
223
224	chunk = min(PAGE_SIZE, len);
225	buf = malloc(chunk);
226	if (buf == NULL) {
227		printf("ps3_readin: buf malloc failed\n");
228		return(0);
229	}
230
231	for (resid = len; resid > 0; resid -= got, p += got) {
232		get = min(chunk, resid);
233		got = read(fd, buf, get);
234		if (got <= 0) {
235			if (got < 0)
236				printf("ps3_readin: read failed\n");
237			break;
238		}
239
240		bcopy(buf, (void *)p, got);
241	}
242
243	free(buf);
244	return (len - resid);
245}
246
247int
248ps3_autoload(void)
249{
250
251	return (0);
252}
253
254