Index: stand/defs.mk =================================================================== --- stand/defs.mk (revision 367806) +++ stand/defs.mk (working copy) @@ -105,10 +105,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.c =================================================================== --- stand/libofw/openfirm.c (revision 367806) +++ stand/libofw/openfirm.c (working copy) @@ -58,6 +58,8 @@ #include __FBSDID("$FreeBSD$"); +#include + #include #include @@ -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,12 +184,9 @@ 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) return (-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,21 +265,33 @@ 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. */ int OF_nextprop(phandle_t package, const char *previous, char *buf) @@ -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 = {}; + SETUP(args, "canon", 3, 1); - args.device = (cell_t)device; - args.buf = (cell_t)buf; - args.len = len; + 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]); + 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 = args.nreturns)); --n > 0;) - *va_arg(ap, cell_t *) = *--cp; + *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,15 +517,12 @@ 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", @@ -567,7 +537,7 @@ args.instance, args.addr, args.len, 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 = {}; + SETUP(args, "claim", 3, 1); - args.virt = (cell_t)virt; - args.size = size; - args.align = align; + 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 = {}; + SETUP(args, "chain", 5, 0); - args.virt = (cell_t)virt; - args.size = size; - args.entry = (cell_t)entry; - args.arg = (cell_t)arg; - args.len = len; + 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/libofw/openfirm.h =================================================================== --- stand/libofw/openfirm.h (revision 367806) +++ stand/libofw/openfirm.h (working copy) @@ -65,9 +65,9 @@ #include #include -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/powerpc/Makefile =================================================================== --- stand/powerpc/Makefile (revision 367806) +++ stand/powerpc/Makefile (working copy) @@ -4,10 +4,10 @@ .include -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 Index: stand/powerpc/boot1.chrp/boot1.c =================================================================== --- stand/powerpc/boot1.chrp/boot1.c (revision 367806) +++ stand/powerpc/boot1.chrp/boot1.c (working copy) @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -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,94 @@ b ofw_init \n\ "); +#if BYTE_ORDER == LITTLE_ENDIAN +ofwfp_t realofw; + +/* + * 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; +#if BYTE_ORDER == LITTLE_ENDIAN + realofw = openfirm; + ofw = call_ofw; +#else 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)); Index: stand/powerpc/ofw/Makefile =================================================================== --- stand/powerpc/ofw/Makefile (revision 367806) +++ stand/powerpc/ofw/Makefile (working copy) @@ -30,6 +30,10 @@ CFLAGS+= -DCAS .endif +.if ${MACHINE_ARCH} == "powerpc64le" +SRCS+= trampolineLE.S +.endif + HELP_FILES= ${FDTSRC}/help.fdt # Always add MI sources @@ -41,8 +45,14 @@ 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 CFLAGS+= -I${BOOTSRC}/libofw Index: stand/powerpc/ofw/ldscript.powerpcle =================================================================== --- stand/powerpc/ofw/ldscript.powerpcle (nonexistent) +++ stand/powerpc/ofw/ldscript.powerpcle (working copy) @@ -0,0 +1,142 @@ +/* $FreeBSD: head/stand/powerpc/ofw/ldscript.powerpc 358304 2020-02-25 00:45:09Z bdragon $ */ + +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 (revision 367806) +++ stand/powerpc/ofw/main.c (working copy) @@ -28,11 +28,14 @@ #include __FBSDID("$FreeBSD$"); +#include + #include #include "openfirm.h" #include "libofw.h" #include "bootstrap.h" +#include #include 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 (revision 367806) +++ stand/powerpc/ofw/ofwfdt.c (working copy) @@ -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); Index: stand/powerpc/ofw/trampolineLE.S =================================================================== --- stand/powerpc/ofw/trampolineLE.S (nonexistent) +++ stand/powerpc/ofw/trampolineLE.S (working copy) @@ -0,0 +1,70 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Brandon Bergren + * + * 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 + +/** + * 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 Property changes on: stand/powerpc/ofw/trampolineLE.S ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property