Page MenuHomeFreeBSD

D32160.id95831.diff
No OneTemporary

D32160.id95831.diff

Index: stand/common/load_elf.c
===================================================================
--- stand/common/load_elf.c
+++ stand/common/load_elf.c
@@ -750,13 +750,6 @@
}
#endif
size = shdr[i].sh_size;
-#if defined(__powerpc__)
- #if __ELF_WORD_SIZE == 64
- size = htobe64(size);
- #else
- size = htobe32(size);
- #endif
-#endif
archsw.arch_copyin(&size, lastaddr, sizeof(size));
lastaddr += sizeof(size);
@@ -802,17 +795,6 @@
printf("]");
#endif
-#if defined(__powerpc__)
- /* On PowerPC we always need to provide BE data to the kernel */
- #if __ELF_WORD_SIZE == 64
- ssym = htobe64((uint64_t)ssym);
- esym = htobe64((uint64_t)esym);
- #else
- ssym = htobe32((uint32_t)ssym);
- esym = htobe32((uint32_t)esym);
- #endif
-#endif
-
file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym);
Index: stand/defs.mk
===================================================================
--- stand/defs.mk
+++ stand/defs.mk
@@ -120,10 +120,12 @@
# Machine specific flags for all builds here
-# Ensure PowerPC64 and PowerPC64LE boot loaders are compiled as 32 bit
-# and in big endian.
-.if ${MACHINE_ARCH:Mpowerpc64*} != ""
+# Ensure PowerPC64 and PowerPC64LE boot loaders are compiled as 32 bit.
+# PowerPC64LE boot loaders are 32-bit little-endian.
+.if ${MACHINE_ARCH} == "powerpc64"
CFLAGS+= -m32 -mcpu=powerpc -mbig-endian
+.elif ${MACHINE_ARCH} == "powerpc64le"
+CFLAGS+= -m32 -mcpu=powerpc -mlittle-endian
.endif
# For amd64, there's a bit of mixed bag. Some of the tree (i386, lib*32) is
Index: stand/libofw/openfirm.h
===================================================================
--- stand/libofw/openfirm.h
+++ stand/libofw/openfirm.h
@@ -65,9 +65,9 @@
#include <sys/cdefs.h>
#include <sys/types.h>
-typedef unsigned int ihandle_t;
-typedef unsigned int phandle_t;
-typedef unsigned long int cell_t;
+typedef uint32_t ihandle_t;
+typedef uint32_t phandle_t;
+typedef uint32_t cell_t;
extern int (*openfirmware)(void *);
extern phandle_t chosen;
@@ -91,6 +91,7 @@
phandle_t OF_instance_to_package(ihandle_t);
int OF_getproplen(phandle_t, const char *);
int OF_getprop(phandle_t, const char *, void *, int);
+int OF_getencprop(phandle_t, const char *, cell_t *, int);
int OF_nextprop(phandle_t, const char *, char *);
int OF_setprop(phandle_t, const char *, void *, int);
int OF_canon(const char *, char *, int);
Index: stand/libofw/openfirm.c
===================================================================
--- stand/libofw/openfirm.c
+++ stand/libofw/openfirm.c
@@ -58,6 +58,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/endian.h>
+
#include <machine/stdarg.h>
#include <stand.h>
@@ -71,6 +73,13 @@
ihandle_t memory;
int real_mode = 0;
+#define IN(x) htobe32((cell_t)x)
+#define OUT(x) be32toh(x)
+#define SETUP(a, b, c, d) \
+ a.name = IN( (b) ); \
+ a.nargs = IN( (c) ); \
+ a.nreturns = IN( (d) );
+
/* Initialiser */
void
@@ -117,16 +126,13 @@
cell_t nreturns;
cell_t service;
cell_t missing;
- } args = {
- (cell_t)"test",
- 1,
- 1,
- };
+ } args = {};
+ SETUP(args, "test", 1, 1);
- args.service = (cell_t)name;
+ args.service = IN(name);
if (openfirmware(&args) == -1)
return (-1);
- return (args.missing);
+ return (OUT(args.missing));
}
/* Return firmware millisecond count. */
@@ -138,14 +144,11 @@
cell_t nargs;
cell_t nreturns;
cell_t ms;
- } args = {
- (cell_t)"milliseconds",
- 0,
- 1,
- };
+ } args = {};
+ SETUP(args, "milliseconds", 0, 1);
openfirmware(&args);
- return (args.ms);
+ return (OUT(args.ms));
}
/*
@@ -162,11 +165,8 @@
cell_t nreturns;
cell_t node;
cell_t next;
- } args = {
- (cell_t)"peer",
- 1,
- 1,
- };
+ } args = {};
+ SETUP(args, "peer", 1, 1);
args.node = node;
if (openfirmware(&args) == -1)
@@ -184,11 +184,8 @@
cell_t nreturns;
cell_t node;
cell_t child;
- } args = {
- (cell_t)"child",
- 1,
- 1,
- };
+ } args = {};
+ SETUP(args, "child", 1, 1);
args.node = node;
if (openfirmware(&args) == -1)
@@ -206,11 +203,8 @@
cell_t nreturns;
cell_t node;
cell_t parent;
- } args = {
- (cell_t)"parent",
- 1,
- 1,
- };
+ } args = {};
+ SETUP(args, "parent", 1, 1);
args.node = node;
if (openfirmware(&args) == -1)
@@ -228,11 +222,8 @@
cell_t nreturns;
cell_t instance;
cell_t package;
- } args = {
- (cell_t)"instance-to-package",
- 1,
- 1,
- };
+ } args = {};
+ SETUP(args, "instance-to-package", 1, 1);
args.instance = instance;
if (openfirmware(&args) == -1)
@@ -251,17 +242,14 @@
cell_t package;
cell_t propname;
cell_t proplen;
- } args = {
- (cell_t)"getproplen",
- 2,
- 1,
- };
+ } args = {};
+ SETUP(args, "getproplen", 2, 1);
args.package = package;
- args.propname = (cell_t)propname;
+ args.propname = IN(propname);
if (openfirmware(&args) == -1)
return (-1);
- return (args.proplen);
+ return (OUT(args.proplen));
}
/* Get the value of a property of a package. */
@@ -277,19 +265,31 @@
cell_t buf;
cell_t buflen;
cell_t size;
- } args = {
- (cell_t)"getprop",
- 4,
- 1,
- };
+ } args = {};
+ SETUP(args, "getprop", 4, 1);
args.package = package;
- args.propname = (cell_t)propname;
- args.buf = (cell_t)buf;
- args.buflen = buflen;
+ args.propname = IN(propname);
+ args.buf = IN(buf);
+ args.buflen = IN(buflen);
if (openfirmware(&args) == -1)
return (-1);
- return (args.size);
+ return (OUT(args.size));
+}
+
+/* Decode a binary property from a package. */
+int
+OF_getencprop(phandle_t package, const char *propname, cell_t *buf, int buflen)
+{
+ int retval, i;
+ retval = OF_getprop(package, propname, buf, buflen);
+ if (retval == -1)
+ return (retval);
+
+ for (i = 0; i < buflen/4; i++)
+ buf[i] = be32toh((uint32_t)buf[i]);
+
+ return (retval);
}
/* Get the next property of a package. */
@@ -304,18 +304,15 @@
cell_t previous;
cell_t buf;
cell_t flag;
- } args = {
- (cell_t)"nextprop",
- 3,
- 1,
- };
+ } args = {};
+ SETUP(args, "nextprop", 3, 1);
args.package = package;
- args.previous = (cell_t)previous;
- args.buf = (cell_t)buf;
+ args.previous = IN(previous);
+ args.buf = IN(buf);
if (openfirmware(&args) == -1)
return (-1);
- return (args.flag);
+ return (OUT(args.flag));
}
/* Set the value of a property of a package. */
@@ -332,19 +329,16 @@
cell_t buf;
cell_t len;
cell_t size;
- } args = {
- (cell_t)"setprop",
- 4,
- 1,
- };
+ } args = {};
+ SETUP(args, "setprop", 4, 1);
args.package = package;
- args.propname = (cell_t)propname;
- args.buf = (cell_t)buf;
- args.len = len;
+ args.propname = IN(propname);
+ args.buf = IN(buf);
+ args.len = IN(len);
if (openfirmware(&args) == -1)
return (-1);
- return (args.size);
+ return (OUT(args.size));
}
/* Convert a device specifier to a fully qualified pathname. */
@@ -359,18 +353,15 @@
cell_t buf;
cell_t len;
cell_t size;
- } args = {
- (cell_t)"canon",
- 3,
- 1,
- };
-
- args.device = (cell_t)device;
- args.buf = (cell_t)buf;
- args.len = len;
+ } args = {};
+ SETUP(args, "canon", 3, 1);
+
+ args.device = IN(device);
+ args.buf = IN(buf);
+ args.len = IN(len);
if (openfirmware(&args) == -1)
return (-1);
- return (args.size);
+ return (OUT(args.size));
}
/* Return a package handle for the specified device. */
@@ -383,13 +374,10 @@
cell_t nreturns;
cell_t device;
cell_t package;
- } args = {
- (cell_t)"finddevice",
- 1,
- 1,
- };
+ } args = {};
+ SETUP(args, "finddevice", 1, 1);
- args.device = (cell_t)device;
+ args.device = IN(device);
if (openfirmware(&args) == -1)
return (-1);
return (args.package);
@@ -407,18 +395,15 @@
cell_t buf;
cell_t len;
cell_t size;
- } args = {
- (cell_t)"instance-to-path",
- 3,
- 1,
- };
+ } args = {};
+ SETUP(args, "instance-to-path", 3, 1);
args.instance = instance;
- args.buf = (cell_t)buf;
- args.len = len;
+ args.buf = IN(buf);
+ args.len = IN(len);
if (openfirmware(&args) == -1)
return (-1);
- return (args.size);
+ return (OUT(args.size));
}
/* Return the fully qualified pathname corresponding to a package. */
@@ -433,18 +418,15 @@
cell_t buf;
cell_t len;
cell_t size;
- } args = {
- (cell_t)"package-to-path",
- 3,
- 1,
- };
+ } args = {};
+ SETUP(args, "package-to-path", 3, 1);
args.package = package;
- args.buf = (cell_t)buf;
- args.len = len;
+ args.buf = IN(buf);
+ args.len = IN(len);
if (openfirmware(&args) == -1)
return (-1);
- return (args.size);
+ return (OUT(args.size));
}
/* Call the method in the scope of a given instance. */
@@ -459,30 +441,26 @@
cell_t method;
cell_t instance;
cell_t args_n_results[12];
- } args = {
- (cell_t)"call-method",
- 2,
- 1,
- };
+ } args = {};
+ SETUP(args, "call-method", nargs + 2, nreturns + 1);
cell_t *cp;
int n;
if (nargs > 6)
return (-1);
- args.nargs = nargs + 2;
- args.nreturns = nreturns + 1;
- args.method = (cell_t)method;
+ args.method = IN(method);
args.instance = instance;
va_start(ap, nreturns);
for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
- *--cp = va_arg(ap, cell_t);
+ *--cp = IN(va_arg(ap, cell_t));
if (openfirmware(&args) == -1)
return (-1);
if (args.args_n_results[nargs])
- return (args.args_n_results[nargs]);
- for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns));
- --n > 0;)
- *va_arg(ap, cell_t *) = *--cp;
+ return (OUT(args.args_n_results[nargs]));
+ /* XXX what if ihandles or phandles are returned */
+ for (cp = (cell_t *)(args.args_n_results + nargs +
+ (n = be32toh(args.nreturns))); --n > 0;)
+ *va_arg(ap, cell_t *) = OUT(*--cp);
va_end(ap);
return (0);
}
@@ -501,13 +479,10 @@
cell_t nreturns;
cell_t device;
cell_t instance;
- } args = {
- (cell_t)"open",
- 1,
- 1,
- };
+ } args = {};
+ SETUP(args, "open", 1, 1);
- args.device = (cell_t)device;
+ args.device = IN(device);
if (openfirmware(&args) == -1 || args.instance == 0) {
return (-1);
}
@@ -523,10 +498,8 @@
cell_t nargs;
cell_t nreturns;
cell_t instance;
- } args = {
- (cell_t)"close",
- 1,
- };
+ } args = {};
+ SETUP(args, "close", 1, 0);
args.instance = instance;
openfirmware(&args);
@@ -544,19 +517,16 @@
cell_t addr;
cell_t len;
cell_t actual;
- } args = {
- (cell_t)"read",
- 3,
- 1,
- };
+ } args = {};
+ SETUP(args, "read", 3, 1);
args.instance = instance;
- args.addr = (cell_t)addr;
- args.len = len;
+ args.addr = IN(addr);
+ args.len = IN(len);
#if defined(OPENFIRM_DEBUG)
printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
- args.instance, args.addr, args.len);
+ instance, addr, len);
#endif
if (openfirmware(&args) == -1)
@@ -564,10 +534,10 @@
#if defined(OPENFIRM_DEBUG)
printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
- args.instance, args.addr, args.len, args.actual);
+ args.instance, OUT(args.addr), OUT(args.len), OUT(args.actual));
#endif
- return (args.actual);
+ return (OUT(args.actual));
}
/* Write to an instance. */
@@ -582,18 +552,15 @@
cell_t addr;
cell_t len;
cell_t actual;
- } args = {
- (cell_t)"write",
- 3,
- 1,
- };
+ } args = {};
+ SETUP(args, "write", 3, 1);
args.instance = instance;
- args.addr = (cell_t)addr;
- args.len = len;
+ args.addr = IN(addr);
+ args.len = IN(len);
if (openfirmware(&args) == -1)
return (-1);
- return (args.actual);
+ return (OUT(args.actual));
}
/* Seek to a position. */
@@ -608,18 +575,15 @@
cell_t poshi;
cell_t poslo;
cell_t status;
- } args = {
- (cell_t)"seek",
- 3,
- 1,
- };
+ } args = {};
+ SETUP(args, "seek", 3, 1);
args.instance = instance;
- args.poshi = pos >> 32;
- args.poslo = pos;
+ args.poshi = IN(((uint64_t)pos >> 32));
+ args.poslo = IN(pos);
if (openfirmware(&args) == -1)
return (-1);
- return (args.status);
+ return (OUT(args.status));
}
/* Blocks. */
@@ -633,16 +597,13 @@
cell_t instance;
cell_t result;
cell_t blocks;
- } args = {
- (cell_t)"#blocks",
- 2,
- 1,
- };
+ } args = {};
+ SETUP(args, "#blocks", 2, 1);
args.instance = instance;
if (openfirmware(&args) == -1)
return ((unsigned int)-1);
- return (args.blocks);
+ return (OUT(args.blocks));
}
/* Block size. */
@@ -656,16 +617,13 @@
cell_t instance;
cell_t result;
cell_t size;
- } args = {
- (cell_t)"block-size",
- 2,
- 1,
- };
+ } args = {};
+ SETUP(args, "block-size", 2, 1);
args.instance = instance;
if (openfirmware(&args) == -1)
return (512);
- return (args.size);
+ return (OUT(args.size));
}
/*
@@ -684,18 +642,15 @@
cell_t size;
cell_t align;
cell_t baseaddr;
- } args = {
- (cell_t)"claim",
- 3,
- 1,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- args.align = align;
+ } args = {};
+ SETUP(args, "claim", 3, 1);
+
+ args.virt = IN(virt);
+ args.size = IN(size);
+ args.align = IN(align);
if (openfirmware(&args) == -1)
return ((void *)-1);
- return ((void *)args.baseaddr);
+ return ((void *)OUT(args.baseaddr));
}
/* Release an area of memory. */
@@ -708,13 +663,11 @@
cell_t nreturns;
cell_t virt;
cell_t size;
- } args = {
- (cell_t)"release",
- 2,
- };
+ } args = {};
+ SETUP(args, "release", 2, 0);
- args.virt = (cell_t)virt;
- args.size = size;
+ args.virt = IN(virt);
+ args.size = IN(size);
openfirmware(&args);
}
@@ -731,12 +684,10 @@
cell_t nargs;
cell_t nreturns;
cell_t bootspec;
- } args = {
- (cell_t)"boot",
- 1,
- };
+ } args = {};
+ SETUP(args, "boot", 1, 0);
- args.bootspec = (cell_t)bootspec;
+ args.bootspec = IN(bootspec);
openfirmware(&args);
for (;;) /* just in case */
;
@@ -750,9 +701,8 @@
cell_t name;
cell_t nargs;
cell_t nreturns;
- } args = {
- (cell_t)"enter",
- };
+ } args = {};
+ SETUP(args, "enter", 0, 0);
openfirmware(&args);
/* We may come back. */
@@ -766,9 +716,8 @@
cell_t name;
cell_t nargs;
cell_t nreturns;
- } args = {
- (cell_t)"exit",
- };
+ } args = {};
+ SETUP(args, "exit", 0, 0);
openfirmware(&args);
for (;;) /* just in case */
@@ -782,9 +731,8 @@
cell_t name;
cell_t nargs;
cell_t nreturns;
- } args = {
- (cell_t)"quiesce",
- };
+ } args = {};
+ SETUP(args, "quiesce", 0, 0);
openfirmware(&args);
}
@@ -803,16 +751,14 @@
cell_t entry;
cell_t arg;
cell_t len;
- } args = {
- (cell_t)"chain",
- 5,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- args.entry = (cell_t)entry;
- args.arg = (cell_t)arg;
- args.len = len;
+ } args = {};
+ SETUP(args, "chain", 5, 0);
+
+ args.virt = IN(virt);
+ args.size = IN(size);
+ args.entry = IN(entry);
+ args.arg = IN(arg);
+ args.len = IN(len);
openfirmware(&args);
}
#else
Index: stand/powerpc/Makefile
===================================================================
--- stand/powerpc/Makefile
+++ stand/powerpc/Makefile
@@ -4,10 +4,10 @@
.include <bsd.init.mk>
-SUBDIR.yes= boot1.chrp ofw uboot
+SUBDIR.yes= boot1.chrp ofw
.if "${MACHINE_ARCH}" == "powerpc64"
-SUBDIR.${MK_FDT}+= kboot
+SUBDIR.${MK_FDT}+= uboot kboot
.endif
.include <bsd.subdir.mk>
Index: stand/powerpc/boot1.chrp/boot1.c
===================================================================
--- stand/powerpc/boot1.chrp/boot1.c
+++ stand/powerpc/boot1.chrp/boot1.c
@@ -20,6 +20,7 @@
#include <sys/param.h>
#include <sys/dirent.h>
+#include <sys/endian.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
#include <machine/md_var.h>
@@ -82,11 +83,11 @@
*/
typedef uint32_t ofwcell_t;
typedef uint32_t u_ofwh_t;
-typedef int (*ofwfp_t)(void *);
+typedef int (*ofwfp_t)(ofwcell_t *);
ofwfp_t ofw; /* the prom Open Firmware entry */
ofwh_t chosenh;
-void ofw_init(void *, int, int (*)(void *), char *, int);
+void ofw_init(void *, int, ofwfp_t, char *, int);
static ofwh_t ofw_finddevice(const char *);
static ofwh_t ofw_open(const char *);
static int ofw_close(ofwh_t);
@@ -101,6 +102,16 @@
ofwh_t bootdevh;
ofwh_t stdinh, stdouth;
+/*
+ * Note about the entry point:
+ *
+ * For some odd reason, the first page of the load appears to have trouble
+ * when entering in LE. The first five instructions decode weirdly.
+ * I suspect it is some cache weirdness between the ELF headers and .text.
+ *
+ * Ensure we have a gap between the start of .text and the entry as a
+ * workaround.
+ */
__asm(" \n\
.data \n\
.align 4 \n\
@@ -108,6 +119,8 @@
.space 16384 \n\
\n\
.text \n\
+ /* SLOF cache hack */ \n\
+ .space 4096 \n\
.globl _start \n\
_start: \n\
lis %r1,stack@ha \n\
@@ -117,18 +130,95 @@
b ofw_init \n\
");
+ofwfp_t realofw;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * Minimal endianness-swap trampoline for LE.
+ */
+__attribute__((naked)) int
+ofwtramp(void *buf, ofwfp_t cb)
+{
+__asm(" \n\
+ mflr %r0 \n\
+ stw %r0, 4(%r1) \n\
+ stwu %r1, -16(%r1) \n\
+ stw %r30, 8(%r1) \n\
+ /* Save current MSR for restoration post-call. */ \n\
+ mfmsr %r30 \n\
+ mr %r5, %r30 \n\
+ /* Remove LE bit from MSR. */ \n\
+ clrrwi %r5, %r5, 1 \n\
+ mtsrr0 %r4 \n\
+ mtsrr1 %r5 \n\
+ bcl 20, 31, .+4 /* LOAD_LR_NIA */ \n\
+1: \n\
+ mflr %r4 \n\
+ addi %r4, %r4, (2f - 1b) \n\
+ mtlr %r4 \n\
+ /* Switch to BE and transfer control to OF entry */ \n\
+ rfid \n\
+2: \n\
+ /* Control is returned here, but in BE. */ \n\
+ .long 0x05009f42 /* LOAD_LR_NIA */\n\
+ /* 0: */\n\
+ .long 0xa603db7f /* mtsrr1 %r30 */\n\
+ .long 0xa602c87f /* mflr %r30 */\n\
+ .long 0x1400de3b /* addi %r30, %r30, (1f - 0b) */\n\
+ .long 0xa603da7f /* mtsrr0 %r30 */\n\
+ .long 0x2400004c /* rfid */\n\
+ /* 1: */\n\
+1: \n\
+ /* Back to normal. Tidy up for return. */ \n\
+ lwz %r30, 8(%r1) \n\
+ lwz %r0, 20(%r1) \n\
+ addi %r1, %r1, 16 \n\
+ mtlr %r0 \n\
+ blr \n\
+");
+}
+
+/*
+ * Little-endian OFW entrypoint replacement.
+ *
+ * We are doing all the byteswapping in one place here to save space.
+ * This means instance handles will be byteswapped as well.
+ */
+int
+call_ofw(ofwcell_t* buf)
+{
+ int ret, i, ncells;
+
+ ncells = 3 + buf[1] + buf[2];
+ for (i = 0; i < ncells; i++)
+ buf[i] = htobe32(buf[i]);
+
+ ret = (ofwtramp(buf, realofw));
+ for (i = 0; i < ncells; i++)
+ buf[i] = be32toh(buf[i]);
+ return (ret);
+}
+#endif
+
void
-ofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
+ofw_init(void *vpd, int res, ofwfp_t openfirm, char *arg, int argl)
{
char *av[16];
char *p;
int ac;
- ofw = openfirm;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ realofw = openfirm;
+ ofw = call_ofw;
+#else
+ realofw = ofw = openfirm;
+#endif
chosenh = ofw_finddevice("/chosen");
ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh));
+ stdinh = be32toh(stdinh);
ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth));
+ stdouth = be32toh(stdouth);
ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs));
ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
@@ -537,8 +627,8 @@
__syncicache(p, ph.p_memsz);
}
ofw_close(bootdev);
- (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0,
- ofw,NULL,0);
+ (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0,
+ realofw, NULL, 0);
}
static int
Index: stand/powerpc/ofw/Makefile
===================================================================
--- stand/powerpc/ofw/Makefile
+++ stand/powerpc/ofw/Makefile
@@ -28,11 +28,15 @@
SRCS+= ofwfdt.c
.endif
-.if ${MACHINE_ARCH} == "powerpc64"
+.if ${MACHINE_ARCH:Mpowerpc64*} != ""
SRCS+= cas.c
CFLAGS+= -DCAS
.endif
+.if ${MACHINE_ARCH} == "powerpc64le"
+SRCS+= trampolineLE.S
+.endif
+
HELP_FILES= ${FDTSRC}/help.fdt
# Always add MI sources
@@ -44,7 +48,13 @@
RELOC?= 0x1C00000
CFLAGS+= -DRELOC=${RELOC} -g
-LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.powerpc
+LDFLAGS= -nostdlib -static
+
+.if ${MACHINE_ARCH} == "powerpc64le"
+LDFLAGS+= -T ${.CURDIR}/ldscript.powerpcle
+.else
+LDFLAGS+= -T ${.CURDIR}/ldscript.powerpc
+.endif
# Open Firmware standalone support library
LIBOFW= ${BOOTOBJ}/libofw/libofw.a
Index: stand/powerpc/ofw/cas.c
===================================================================
--- stand/powerpc/ofw/cas.c
+++ stand/powerpc/ofw/cas.c
@@ -29,6 +29,8 @@
#include <openfirm.h>
#include <stand.h>
+#include <sys/endian.h>
+
/* #define CAS_DEBUG */
#ifdef CAS_DEBUG
#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
@@ -132,12 +134,12 @@
struct opt_vec5 vec5;
} __packed ibm_arch_vec = {
/* pvr_list */ {
- { PVR_CPU_MASK, PVR_CPU_P8 }, /* POWER8 */
- { PVR_CPU_MASK, PVR_CPU_P8E }, /* POWER8E */
- { PVR_CPU_MASK, PVR_CPU_P8NVL }, /* POWER8NVL */
- { PVR_CPU_MASK, PVR_CPU_P9 }, /* POWER9 */
- { PVR_ISA_MASK, PVR_ISA_207 }, /* All ISA 2.07 */
- { PVR_ISA_MASK, PVR_ISA_300 }, /* All ISA 3.00 */
+ { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8) },
+ { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8E) },
+ { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8NVL) },
+ { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P9) },
+ { htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_207) },
+ { htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_300) },
{ 0, 0xffffffffu } /* terminator */
},
4, /* num_opts (4 actually means 5 option vectors) */
Index: stand/powerpc/ofw/ldscript.powerpcle
===================================================================
--- /dev/null
+++ stand/powerpc/ofw/ldscript.powerpcle
@@ -0,0 +1,142 @@
+/* $FreeBSD$ */
+
+OUTPUT_FORMAT("elf32-powerpcle-freebsd", "elf32-powerpcle-freebsd",
+ "elf32-powerpcle-freebsd")
+OUTPUT_ARCH(powerpcle:common)
+ENTRY(_start)
+SEARCH_DIR(/usr/lib);
+PROVIDE (__stack = 0);
+PHDRS
+{
+ text PT_LOAD;
+}
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x02c00000 + SIZEOF_HEADERS;
+ .interp : { *(.interp) } :text
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rela.text :
+ { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+ .rela.data :
+ { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+ .rela.rodata :
+ { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+ .rela.got : { *(.rela.got) }
+ .rela.got1 : { *(.rela.got1) }
+ .rela.got2 : { *(.rela.got2) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rela.init : { *(.rela.init) }
+ .rela.fini : { *(.rela.fini) }
+ .rela.bss : { *(.rela.bss) }
+ .rela.plt : { *(.rela.plt) }
+ .rela.sdata : { *(.rela.sdata) }
+ .rela.sbss : { *(.rela.sbss) }
+ .rela.sdata2 : { *(.rela.sdata2) }
+ .rela.sbss2 : { *(.rela.sbss2) }
+ .text :
+ {
+ *(.text)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
+ .init : { *(.init) } =0
+ .fini : { *(.fini) } =0
+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 : { *(.sdata2) }
+ .sbss2 : { *(.sbss2) }
+ /* Adjust the address for the data segment to the next page up. */
+ . = ((. + 0x1000) & ~(0x1000 - 1));
+ .data :
+ {
+ *(.data)
+ *(.gnu.linkonce.d*)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .got1 : { *(.got1) }
+ .dynamic : { *(.dynamic) }
+ /* Put .ctors and .dtors next to the .got2 section, so that the pointers
+ get relocated with -mrelocatable. Also put in the .fixup pointers.
+ The current compiler no longer needs this, but keep it around for 2.7.2 */
+ PROVIDE (_GOT2_START_ = .);
+ .got2 : { *(.got2) }
+ PROVIDE (__CTOR_LIST__ = .);
+ .ctors : { *(.ctors) }
+ PROVIDE (__CTOR_END__ = .);
+ PROVIDE (__DTOR_LIST__ = .);
+ .dtors : { *(.dtors) }
+ PROVIDE (__DTOR_END__ = .);
+ PROVIDE (_FIXUP_START_ = .);
+ .fixup : { *(.fixup) }
+ PROVIDE (_FIXUP_END_ = .);
+ PROVIDE (_GOT2_END_ = .);
+ PROVIDE (_GOT_START_ = .);
+ .got : { *(.got) }
+ .got.plt : { *(.got.plt) }
+ PROVIDE (_GOT_END_ = .);
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ .sbss :
+ {
+ PROVIDE (__sbss_start = .);
+ *(.sbss)
+ *(.scommon)
+ *(.dynsbss)
+ PROVIDE (__sbss_end = .);
+ }
+ .plt : { *(.plt) }
+ .bss :
+ {
+ PROVIDE (__bss_start = .);
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
+
Index: stand/powerpc/ofw/main.c
===================================================================
--- stand/powerpc/ofw/main.c
+++ stand/powerpc/ofw/main.c
@@ -28,11 +28,14 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/endian.h>
+
#include <stand.h>
#include "openfirm.h"
#include "libofw.h"
#include "bootstrap.h"
+#include <machine/asm.h>
#include <machine/psl.h>
struct arch_switch archsw; /* MI/MD interface boundary */
@@ -77,7 +80,7 @@
memsz = 0;
memoryp = OF_instance_to_package(memory);
- sz = OF_getprop(memoryp, "reg", &reg, sizeof(reg));
+ sz = OF_getencprop(memoryp, "reg", &reg[0], sizeof(reg));
sz /= sizeof(reg[0]);
for (i = 0; i < sz; i += (acells + scells)) {
@@ -104,6 +107,26 @@
}
#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * In Little-endian, we cannot just branch to the client interface. Since
+ * the client interface is big endian, we have to rfid to it.
+ * Likewise, when execution resumes, we are in the wrong endianness so
+ * we must do a fixup before returning to the caller.
+ */
+static int (*openfirmware_entry)(void *);
+extern int openfirmware_trampoline(void *buf, int (*cb)(void *));
+
+/*
+ * Wrapper to pass the real entry point to our trampoline.
+ */
+static int
+openfirmware_docall(void *buf)
+{
+ return openfirmware_trampoline(buf, openfirmware_entry);
+}
+#endif
+
int
main(int (*openfirm)(void *))
{
@@ -117,13 +140,21 @@
/*
* Initialise the Open Firmware routines by giving them the entry point.
*/
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /*
+ * Use a trampoline entry point for endian fixups.
+ */
+ openfirmware_entry = openfirm;
+ OF_init(openfirmware_docall);
+#else
OF_init(openfirm);
+#endif
root = OF_finddevice("/");
scells = acells = 1;
- OF_getprop(root, "#address-cells", &acells, sizeof(acells));
- OF_getprop(root, "#size-cells", &scells, sizeof(scells));
+ OF_getencprop(root, "#address-cells", &acells, sizeof(acells));
+ OF_getencprop(root, "#size-cells", &scells, sizeof(scells));
/*
* Initialise the heap as early as possible. Once this is done,
Index: stand/powerpc/ofw/ofwfdt.c
===================================================================
--- stand/powerpc/ofw/ofwfdt.c
+++ stand/powerpc/ofw/ofwfdt.c
@@ -112,7 +112,7 @@
node = OF_finddevice("/rtas");
OF_package_to_path(node, path, sizeof(path));
- OF_getprop(node, "rtas-size", &len, sizeof(len));
+ OF_getencprop(node, "rtas-size", &len, sizeof(len));
/* Allocate memory */
rtasmem = OF_claim(0, len, 4096);
@@ -133,6 +133,7 @@
sizeof(base));
/* Mark RTAS private data area reserved */
+ base = fdt32_to_cpu(base);
fdt_add_mem_rsv(fdtp, base, len);
} else {
/*
@@ -157,8 +158,7 @@
for (i = 0; chosenprops[i] != NULL; i++) {
ihand = fdt_getprop(fdtp, offset, chosenprops[i], &len);
if (ihand != NULL && len == sizeof(*ihand)) {
- node = OF_instance_to_package(
- fdt32_to_cpu(*ihand));
+ node = OF_instance_to_package(*ihand);
if (OF_hasprop(node, "phandle"))
OF_getprop(node, "phandle", &node,
sizeof(node));
@@ -168,7 +168,6 @@
else if (OF_hasprop(node, "ibm,phandle"))
OF_getprop(node, "ibm,phandle", &node,
sizeof(node));
- node = cpu_to_fdt32(node);
fdt_setprop(fdtp, offset, chosenprops[i], &node,
sizeof(node));
}
Index: stand/powerpc/ofw/trampolineLE.S
===================================================================
--- /dev/null
+++ stand/powerpc/ofw/trampolineLE.S
@@ -0,0 +1,71 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Brandon Bergren <bdragon@FreeBSD.org>
+ *
+ * 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 AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asm.h>
+
+/**
+ * int openfirmware_trampoline(void *buf, int (*cb)(void *));
+ */
+ASENTRY_NOPROF(openfirmware_trampoline)
+ mflr %r0
+ stw %r0, 4(%r1)
+ stwu %r1, -16(%r1)
+ stw %r30, 8(%r1)
+ /* Save current MSR for restoration post-call. */
+ mfmsr %r30
+ mr %r5, %r30
+ /* Remove LE bit from MSR. */
+ clrrwi %r5, %r5, 1
+ mtsrr0 %r4
+ mtsrr1 %r5
+ LOAD_LR_NIA
+1:
+ mflr %r4
+ addi %r4, %r4, (2f - 1b)
+ mtlr %r4
+ /* Switch to BE and transfer control to OF entry */
+ rfid
+2:
+ /* Control is returned here, but in BE. */
+ .long 0x05009f42 /* LOAD_LR_NIA */
+ /* 0: */
+ .long 0xa603db7f /* mtsrr1 %r30 */
+ .long 0xa602c87f /* mflr %r30 */
+ .long 0x1400de3b /* addi %r30, %r30, (1f - 0b) */
+ .long 0xa603da7f /* mtsrr0 %r30 */
+ .long 0x2400004c /* rfid */
+ /* 1: */
+1:
+ /* Back to normal. Tidy up for return. */
+ lwz %r30, 8(%r1)
+ lwz %r0, 20(%r1)
+ addi %r1, %r1, 16
+ mtlr %r0
+ blr
+ASEND(openfirmware_trampoline)

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 7, 12:22 PM (20 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17031979
Default Alt Text
D32160.id95831.diff (31 KB)

Event Timeline