Changeset View
Changeset View
Standalone View
Standalone View
stand/powerpc/boot1.chrp/boot1.c
| Show All 14 Lines | |||||
| * purpose. | * purpose. | ||||
| */ | */ | ||||
| #include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
| __FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
| #include <sys/param.h> | #include <sys/param.h> | ||||
| #include <sys/dirent.h> | #include <sys/dirent.h> | ||||
| #include <sys/endian.h> | |||||
| #include <machine/elf.h> | #include <machine/elf.h> | ||||
| #include <machine/stdarg.h> | #include <machine/stdarg.h> | ||||
| #include <machine/md_var.h> | #include <machine/md_var.h> | ||||
| #include <ufs/ffs/fs.h> | #include <ufs/ffs/fs.h> | ||||
| #include "paths.h" | #include "paths.h" | ||||
| #define BSIZEMAX 16384 | #define BSIZEMAX 16384 | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
| static char *__uitoa(char *buf, u_int val, int base); | static char *__uitoa(char *buf, u_int val, int base); | ||||
| static char *__ultoa(char *buf, u_long val, int base); | static char *__ultoa(char *buf, u_long val, int base); | ||||
| /* | /* | ||||
| * Open Firmware interface functions | * Open Firmware interface functions | ||||
| */ | */ | ||||
| typedef uint32_t ofwcell_t; | typedef uint32_t ofwcell_t; | ||||
| typedef uint32_t u_ofwh_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 */ | ofwfp_t ofw; /* the prom Open Firmware entry */ | ||||
| ofwh_t chosenh; | 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_finddevice(const char *); | ||||
| static ofwh_t ofw_open(const char *); | static ofwh_t ofw_open(const char *); | ||||
| static int ofw_close(ofwh_t); | static int ofw_close(ofwh_t); | ||||
| static int ofw_getprop(ofwh_t, const char *, void *, size_t); | static int ofw_getprop(ofwh_t, const char *, void *, size_t); | ||||
| static int ofw_setprop(ofwh_t, const char *, void *, size_t); | static int ofw_setprop(ofwh_t, const char *, void *, size_t); | ||||
| static int ofw_read(ofwh_t, void *, size_t); | static int ofw_read(ofwh_t, void *, size_t); | ||||
| static int ofw_write(ofwh_t, const void *, size_t); | static int ofw_write(ofwh_t, const void *, size_t); | ||||
| static int ofw_claim(void *virt, size_t len, u_int align); | static int ofw_claim(void *virt, size_t len, u_int align); | ||||
| static int ofw_seek(ofwh_t, uint64_t); | static int ofw_seek(ofwh_t, uint64_t); | ||||
| static void ofw_exit(void) __dead2; | static void ofw_exit(void) __dead2; | ||||
| ofwh_t bootdevh; | ofwh_t bootdevh; | ||||
| ofwh_t stdinh, stdouth; | 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\ | __asm(" \n\ | ||||
| .data \n\ | .data \n\ | ||||
| .align 4 \n\ | .align 4 \n\ | ||||
| stack: \n\ | stack: \n\ | ||||
| .space 16384 \n\ | .space 16384 \n\ | ||||
| \n\ | \n\ | ||||
| .text \n\ | .text \n\ | ||||
| /* SLOF cache hack */ \n\ | |||||
| .space 4096 \n\ | |||||
| .globl _start \n\ | .globl _start \n\ | ||||
| _start: \n\ | _start: \n\ | ||||
| lis %r1,stack@ha \n\ | lis %r1,stack@ha \n\ | ||||
| addi %r1,%r1,stack@l \n\ | addi %r1,%r1,stack@l \n\ | ||||
| addi %r1,%r1,8192 \n\ | addi %r1,%r1,8192 \n\ | ||||
| \n\ | \n\ | ||||
| b ofw_init \n\ | 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 | 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 *av[16]; | ||||
| char *p; | char *p; | ||||
| int ac; | int ac; | ||||
| ofw = openfirm; | #if BYTE_ORDER == LITTLE_ENDIAN | ||||
| realofw = openfirm; | |||||
| ofw = call_ofw; | |||||
| #else | |||||
| realofw = ofw = openfirm; | |||||
| #endif | |||||
| chosenh = ofw_finddevice("/chosen"); | chosenh = ofw_finddevice("/chosen"); | ||||
| ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); | ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); | ||||
| stdinh = be32toh(stdinh); | |||||
| ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); | ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); | ||||
| stdouth = be32toh(stdouth); | |||||
| ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); | ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); | ||||
| ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); | ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); | ||||
| bootargs[sizeof(bootargs) - 1] = '\0'; | bootargs[sizeof(bootargs) - 1] = '\0'; | ||||
| bootpath[sizeof(bootpath) - 1] = '\0'; | bootpath[sizeof(bootpath) - 1] = '\0'; | ||||
| p = bootpath; | p = bootpath; | ||||
| while (*p != '\0') { | while (*p != '\0') { | ||||
| ▲ Show 20 Lines • Show All 392 Lines • ▼ Show 20 Lines | if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { | ||||
| printf("Can't read content of section %d\n", i); | printf("Can't read content of section %d\n", i); | ||||
| return; | return; | ||||
| } | } | ||||
| if (ph.p_filesz != ph.p_memsz) | if (ph.p_filesz != ph.p_memsz) | ||||
| bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); | bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); | ||||
| __syncicache(p, ph.p_memsz); | __syncicache(p, ph.p_memsz); | ||||
| } | } | ||||
| ofw_close(bootdev); | ofw_close(bootdev); | ||||
| (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0, | (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0, | ||||
| ofw,NULL,0); | realofw, NULL, 0); | ||||
| } | } | ||||
| static int | static int | ||||
| dskread(void *buf, uint64_t lba, int nblk) | dskread(void *buf, uint64_t lba, int nblk) | ||||
| { | { | ||||
| /* | /* | ||||
| * The Open Firmware should open the correct partition for us. | * The Open Firmware should open the correct partition for us. | ||||
| * That means, if we read from offset zero on an open instance handle, | * That means, if we read from offset zero on an open instance handle, | ||||
| ▲ Show 20 Lines • Show All 228 Lines • Show Last 20 Lines | |||||