Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111649282
D32160.id95831.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
31 KB
Referenced Files
None
Subscribers
None
D32160.id95831.diff
View Options
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", ®, sizeof(reg));
+ sz = OF_getencprop(memoryp, "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
Details
Attached
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)
Attached To
Mode
D32160: powerpc64le: stand fixes
Attached
Detach File
Event Timeline
Log In to Comment