summaryrefslogtreecommitdiffstats
path: root/stand/powerpc/ps3/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'stand/powerpc/ps3/main.c')
-rw-r--r--stand/powerpc/ps3/main.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/stand/powerpc/ps3/main.c b/stand/powerpc/ps3/main.c
new file mode 100644
index 0000000..be8708a
--- /dev/null
+++ b/stand/powerpc/ps3/main.c
@@ -0,0 +1,248 @@
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <sys/param.h>
+
+#define _KERNEL
+#include <machine/cpufunc.h>
+
+#include "bootstrap.h"
+#include "lv1call.h"
+#include "ps3.h"
+#include "ps3devdesc.h"
+
+struct arch_switch archsw;
+extern void *_end;
+
+extern char bootprog_info[];
+
+int ps3_getdev(void **vdev, const char *devspec, const char **path);
+ssize_t ps3_copyin(const void *src, vm_offset_t dest, const size_t len);
+ssize_t ps3_copyout(vm_offset_t src, void *dest, const size_t len);
+ssize_t ps3_readin(const int fd, vm_offset_t dest, const size_t len);
+int ps3_autoload(void);
+int ps3_setcurrdev(struct env_var *ev, int flags, const void *value);
+
+static uint64_t basetb;
+
+int
+main(void)
+{
+ uint64_t maxmem = 0;
+ void *heapbase;
+ int i, err;
+ struct ps3_devdesc currdev;
+ struct open_file f;
+
+ lv1_get_physmem(&maxmem);
+
+ ps3mmu_init(maxmem);
+
+ /*
+ * Set up console.
+ */
+ cons_probe();
+
+ /*
+ * Set the heap to one page after the end of the loader.
+ */
+ heapbase = (void *)(maxmem - 0x80000);
+ setheap(heapbase, maxmem);
+
+ /*
+ * March through the device switch probing for things.
+ */
+ for (i = 0; devsw[i] != NULL; i++) {
+ if (devsw[i]->dv_init != NULL) {
+ err = (devsw[i]->dv_init)();
+ if (err) {
+ printf("\n%s: initialization failed err=%d\n",
+ devsw[i]->dv_name, err);
+ continue;
+ }
+ }
+
+ currdev.d_dev = devsw[i];
+ currdev.d_type = currdev.d_dev->dv_type;
+
+ if (strcmp(devsw[i]->dv_name, "cd") == 0) {
+ f.f_devdata = &currdev;
+ currdev.d_unit = 0;
+
+ if (devsw[i]->dv_open(&f, &currdev) == 0)
+ break;
+ }
+
+ if (strcmp(devsw[i]->dv_name, "disk") == 0) {
+ f.f_devdata = &currdev;
+ currdev.d_unit = 3;
+ currdev.d_disk.pnum = 1;
+ currdev.d_disk.ptype = PTYPE_GPT;
+
+ if (devsw[i]->dv_open(&f, &currdev) == 0)
+ break;
+ }
+
+ if (strcmp(devsw[i]->dv_name, "net") == 0)
+ break;
+ }
+
+ if (devsw[i] == NULL)
+ panic("No boot device found!");
+ else
+ printf("Boot device: %s\n", devsw[i]->dv_name);
+
+ /*
+ * Get timebase at boot.
+ */
+ basetb = mftb();
+
+ archsw.arch_getdev = ps3_getdev;
+ archsw.arch_copyin = ps3_copyin;
+ archsw.arch_copyout = ps3_copyout;
+ archsw.arch_readin = ps3_readin;
+ archsw.arch_autoload = ps3_autoload;
+
+ printf("\n%s", bootprog_info);
+ printf("Memory: %lldKB\n", maxmem / 1024);
+
+ env_setenv("currdev", EV_VOLATILE, ps3_fmtdev(&currdev),
+ ps3_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, ps3_fmtdev(&currdev), env_noset,
+ env_nounset);
+ setenv("LINES", "24", 1);
+ setenv("hw.platform", "ps3", 1);
+
+ interact(NULL); /* doesn't return */
+
+ return (0);
+}
+
+void
+ppc_exception(int code, vm_offset_t where, register_t msr)
+{
+ mtmsr(PSL_IR | PSL_DR | PSL_RI);
+ printf("Exception %x at %#lx!\n", code, where);
+ printf("Rebooting in 5 seconds...\n");
+ delay(10000000);
+ lv1_panic(1);
+}
+
+const u_int ns_per_tick = 12;
+
+void
+exit(int code)
+{
+ lv1_panic(code);
+}
+
+void
+delay(int usecs)
+{
+ uint64_t tb,ttb;
+ tb = mftb();
+
+ ttb = tb + howmany(usecs * 1000, ns_per_tick);
+ while (tb < ttb)
+ tb = mftb();
+}
+
+time_t
+getsecs(void)
+{
+ return ((time_t)((mftb() - basetb)*ns_per_tick/1000000000));
+}
+
+time_t
+time(time_t *tloc)
+{
+ time_t rv;
+
+ rv = getsecs();
+ if (tloc != NULL)
+ *tloc = rv;
+
+ return (rv);
+}
+
+ssize_t
+ps3_copyin(const void *src, vm_offset_t dest, const size_t len)
+{
+ bcopy(src, (void *)dest, len);
+ return (len);
+}
+
+ssize_t
+ps3_copyout(vm_offset_t src, void *dest, const size_t len)
+{
+ bcopy((void *)src, dest, len);
+ return (len);
+}
+
+ssize_t
+ps3_readin(const int fd, vm_offset_t dest, const size_t len)
+{
+ void *buf;
+ size_t resid, chunk, get;
+ ssize_t got;
+ vm_offset_t p;
+
+ p = dest;
+
+ chunk = min(PAGE_SIZE, len);
+ buf = malloc(chunk);
+ if (buf == NULL) {
+ printf("ps3_readin: buf malloc failed\n");
+ return(0);
+ }
+
+ for (resid = len; resid > 0; resid -= got, p += got) {
+ get = min(chunk, resid);
+ got = read(fd, buf, get);
+ if (got <= 0) {
+ if (got < 0)
+ printf("ps3_readin: read failed\n");
+ break;
+ }
+
+ bcopy(buf, (void *)p, got);
+ }
+
+ free(buf);
+ return (len - resid);
+}
+
+int
+ps3_autoload(void)
+{
+
+ return (0);
+}
+
OpenPOWER on IntegriCloud