static void fdt_fixup_busfreq(phandle_t root) { phandle_t sb, cpus, child; pcell_t freq; /* * Do a strict check so as to skip non-SOC nodes, which also claim * simple-bus compatibility such as eLBC etc. */ if ((sb = fdt_find_compatible(root, "simple-bus", 1)) == 0) return; /* * This fixup uses /cpus/ bus-frequency prop value to set simple-bus * bus-frequency property. */ if ((cpus = OF_finddevice("/cpus")) == 0) return; if ((child = OF_child(cpus)) == 0) return; if (OF_getprop(child, "bus-frequency", (void *)&freq, sizeof(freq)) <= 0) return; OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq)); }
static void aml8726_fixup_busfreq(void) { phandle_t node; pcell_t freq, prop; ssize_t len; /* * Set the bus-frequency for the SoC simple-bus if it * needs updating (meaning the current frequency is zero). */ if ((freq = aml8726_clkmsr_bus_frequency()) == 0 || (node = OF_finddevice("/soc")) == 0 || fdt_is_compatible_strict(node, "simple-bus") == 0) while (1); freq = cpu_to_fdt32(freq); len = OF_getencprop(node, "bus-frequency", &prop, sizeof(prop)); if ((len / sizeof(prop)) == 1 && prop == 0) OF_setprop(node, "bus-frequency", (void *)&freq, sizeof(freq)); }
int openpromioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { struct opiocdesc *op; int node, len, ok, error, s; char *name, *value, *nextprop; static char buf[32]; /* XXX */ if (optionsnode == 0) { s = splhigh(); optionsnode = OF_getnodebyname(0, "options"); splx(s); } /* All too easy... */ if (cmd == OPIOCGETOPTNODE) { *(int *)data = optionsnode; return (0); } /* Verify node id */ op = (struct opiocdesc *)data; node = op->op_nodeid; if (node != 0 && node != lastnode && node != optionsnode) { /* Not an easy one, must search for it */ s = splhigh(); ok = openpromcheckid(OF_peer(0), node); splx(s); if (!ok) return (EINVAL); lastnode = node; } name = value = NULL; error = 0; switch (cmd) { case OPIOCGET: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; s = splhigh(); strlcpy(buf, name, 32); /* XXX */ len = OF_getproplen(node, buf); splx(s); if (len > op->op_buflen) { error = ENOMEM; break; } op->op_buflen = len; /* -1 means no entry; 0 means no value */ if (len <= 0) break; value = malloc(len, M_TEMP, M_WAITOK); s = splhigh(); strlcpy(buf, name, 32); /* XXX */ OF_getprop(node, buf, value, len); splx(s); error = copyout(value, op->op_buf, len); break; case OPIOCSET: if ((flags & FWRITE) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; error = openpromgetstr(op->op_buflen, op->op_buf, &value); if (error) break; s = splhigh(); strlcpy(buf, name, 32); /* XXX */ len = OF_setprop(node, buf, value, op->op_buflen + 1); splx(s); if (len != op->op_buflen) error = EINVAL; break; case OPIOCNEXTPROP: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; if (op->op_buflen <= 0) { error = ENAMETOOLONG; break; } value = nextprop = malloc(OPROMMAXPARAM, M_TEMP, M_WAITOK); if (nextprop == NULL) { error = ENOMEM; break; } s = splhigh(); strlcpy(buf, name, 32); /* XXX */ error = OF_nextprop(node, buf, nextprop); splx(s); if (error == -1) { error = EINVAL; break; } if (error == 0) { char nul = '\0'; op->op_buflen = 0; error = copyout(&nul, op->op_buf, sizeof(char)); break; } len = strlen(nextprop); if (len > op->op_buflen) len = op->op_buflen; else op->op_buflen = len; error = copyout(nextprop, op->op_buf, len); break; case OPIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); s = splhigh(); node = OF_peer(node); splx(s); *(int *)data = lastnode = node; break; case OPIOCGETCHILD: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); s = splhigh(); node = OF_child(node); splx(s); *(int *)data = lastnode = node; break; default: return (ENOTTY); } if (name) free(name, M_TEMP); if (value) free(value, M_TEMP); return (error); }
int openfirm_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) { struct ofiocdesc *of; phandle_t node; int len, ok, error; char *name, *value; char newname[32]; if ((flags & FREAD) == 0) return (EBADF); of = (struct ofiocdesc *)data; switch (cmd) { case OFIOCGETOPTNODE: *(phandle_t *) data = OF_finddevice("/options"); return (0); case OFIOCGET: case OFIOCSET: case OFIOCNEXTPROP: case OFIOCFINDDEVICE: case OFIOCGETPROPLEN: node = of->of_nodeid; break; case OFIOCGETNEXT: case OFIOCGETCHILD: node = *(phandle_t *)data; break; default: return (ENOIOCTL); } if (node != 0 && node != lastnode) { /* Not an easy one, we must search for it. */ ok = openfirm_checkid(OF_peer(0), node); if (!ok) return (EINVAL); lastnode = node; } name = value = NULL; error = 0; switch (cmd) { case OFIOCGET: case OFIOCGETPROPLEN: if (node == 0) return (EINVAL); error = openfirm_getstr(of->of_namelen, of->of_name, &name); if (error) break; len = OF_getproplen(node, name); if (cmd == OFIOCGETPROPLEN) { of->of_buflen = len; break; } if (len > of->of_buflen) { error = ENOMEM; break; } of->of_buflen = len; /* -1 means no entry; 0 means no value. */ if (len <= 0) break; value = malloc(len, M_TEMP, M_WAITOK); if (value == NULL) { error = ENOMEM; break; } len = OF_getprop(node, name, (void *)value, len); error = copyout(value, of->of_buf, len); break; case OFIOCSET: /* * Note: Text string values for at least the /options node * have to be null-terminated and the length parameter must * include this terminating null. However, like OF_getprop(), * OF_setprop() will return the actual length of the text * string, i.e. omitting the terminating null. */ if ((flags & FWRITE) == 0) return (EBADF); if (node == 0) return (EINVAL); if ((u_int)of->of_buflen > OFIOCMAXVALUE) return (ENAMETOOLONG); error = openfirm_getstr(of->of_namelen, of->of_name, &name); if (error) break; value = malloc(of->of_buflen, M_TEMP, M_WAITOK); if (value == NULL) { error = ENOMEM; break; } error = copyin(of->of_buf, value, of->of_buflen); if (error) break; len = OF_setprop(node, name, value, of->of_buflen); if (len < 0) error = EINVAL; of->of_buflen = len; break; case OFIOCNEXTPROP: if (node == 0 || of->of_buflen < 0) return (EINVAL); if (of->of_namelen != 0) { error = openfirm_getstr(of->of_namelen, of->of_name, &name); if (error) break; } ok = OF_nextprop(node, name, newname, sizeof(newname)); if (ok == 0) { error = ENOENT; break; } if (ok == -1) { error = EINVAL; break; } len = strlen(newname) + 1; if (len > of->of_buflen) len = of->of_buflen; else of->of_buflen = len; error = copyout(newname, of->of_buf, len); break; case OFIOCGETNEXT: node = OF_peer(node); *(phandle_t *)data = lastnode = node; break; case OFIOCGETCHILD: if (node == 0) return (EINVAL); node = OF_child(node); *(phandle_t *)data = lastnode = node; break; case OFIOCFINDDEVICE: error = openfirm_getstr(of->of_namelen, of->of_name, &name); if (error) break; node = OF_finddevice(name); if (node == 0 || node == -1) { error = ENOENT; break; } of->of_nodeid = lastnode = node; break; } if (name != NULL) free(name, M_TEMP); if (value != NULL) free(value, M_TEMP); return (error); }
/* perform model-specific actions at initppc() */ void model_init(void) { int qhandle, phandle, j; memset(&modeldata, 0, sizeof(struct model_data)); /* provide sane defaults */ for (j=0; j < MAX_PCI_BUSSES; j++) { modeldata.pciiodata[j].start = 0x00008000; modeldata.pciiodata[j].limit = 0x0000ffff; } modeldata.ranges_offset = 1; if (strncmp(model_name, "FirePower,", 10) == 0) { modeldata.ranges_offset = 0; } if (strcmp(model_name, "MOT,PowerStack_II_Pro4000") == 0) { modeldata.ranges_offset = 0; } /* 7044-270 and 7044-170 */ if (strncmp(model_name, "IBM,7044", 8) == 0) { for (j=0; j < MAX_PCI_BUSSES; j++) { modeldata.pciiodata[j].start = 0x00fff000; modeldata.pciiodata[j].limit = 0x00ffffff; } } /* Pegasos1, Pegasos2 */ if (strncmp(model_name, "Pegasos", 7) == 0) { static uint16_t modew[] = { 640, 800, 1024, 1280, 0 }; static uint16_t modeh[] = { 480, 600, 768, 1024, 0 }; uint32_t width, height, mode, fbaddr; char buf[32]; int i; modeldata.ranges_offset = 1; modeldata.pciiodata[0].start = 0x00001400; modeldata.pciiodata[0].limit = 0x0000ffff; /* the pegasos doesn't bother to set the L2 cache up*/ l2cr_config = L2CR_L2PE; /* fix the device_type property of a graphics card */ for (qhandle = OF_peer(0); qhandle; qhandle = phandle) { if (OF_getprop(qhandle, "name", buf, sizeof buf) > 0 && strncmp(buf, "display", 7) == 0) { OF_setprop(qhandle, "device_type", "display", 8); break; } if ((phandle = OF_child(qhandle))) continue; while (qhandle) { if ((phandle = OF_peer(qhandle))) break; qhandle = OF_parent(qhandle); } } /* * Get screen width/height and switch to framebuffer mode. * The default dimensions are: 800 x 600 */ OF_interpret("screen-width", 0, 1, &width); if (width == 0) width = 800; OF_interpret("screen-height", 0, 1, &height); if (height == 0) height = 600; /* find VESA mode */ for (i = 0, mode = 0; modew[i] != 0; i++) { if (modew[i] == width && modeh[i] == height) { mode = 0x101 + 2 * i; break; } } if (!mode) { mode = 0x102; width = 800; height = 600; } /* init frame buffer mode */ sprintf(buf, "%x vesa-set-mode", mode); OF_interpret(buf, 0, 0); /* set dimensions and frame buffer address in OFW */ sprintf(buf, "%x to screen-width", width); OF_interpret(buf, 0, 0); sprintf(buf, "%x to screen-height", height); OF_interpret(buf, 0, 0); OF_interpret("vesa-frame-buffer-adr", 0, 1, &fbaddr); if (fbaddr != 0) { sprintf(buf, "%x to frame-buffer-adr", fbaddr); OF_interpret(buf, 0, 0); } } }
void main(void) { extern char bootprog_name[], bootprog_rev[]; int chosen; char bootline[512]; /* Should check size? */ char *cp, *startbuf, *endbuf; u_long marks[MARK_MAX], size; u_int32_t entry; void *ssym, *esym; printf("\n"); printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); /* * Get the boot arguments from Openfirmware */ if ((chosen = OF_finddevice("/chosen")) == -1 || OF_getprop(chosen, "bootpath", bootdev, sizeof bootdev) < 0 || OF_getprop(chosen, "bootargs", bootline, sizeof bootline) < 0) { printf("Invalid Openfirmware environment\n"); OF_exit(); } prom2boot(bootdev); parseargs(bootline, &boothowto); DPRINTF("bootline=%s\n", bootline); /* * Per the ARM OpenFirmware bindings, the firmware must * allocate and map at least 6MB of physical memory starting * at VA 0xf0000000. We have been loaded at 0xf0000000, * and the memory after us has been unmapped and freed. * We expect to load the kernel at 0xf0100000, so we will * allocate 5MB of virtual memory starting there, and * unmap/free what we don't use. */ startbuf = OF_claim((void *) 0xf0100000, (5 * 1024 * 1024), 0); if (startbuf != (void *) 0xf0100000) { printf("Unable to claim buffer for kernel\n"); OF_exit(); } endbuf = startbuf + (5 * 1024 * 1024); for (;;) { int i; if (boothowto & RB_ASKNAME) { printf("Boot: "); gets(bootline); parseargs(bootline, &boothowto); } if (bootline[0]) { kernels[0] = bootline; kernels[1] = NULL; } for (i = 0; kernels[i]; i++) { DPRINTF("Trying %s\n", kernels[i]); marks[MARK_START] = 0xf0100000; if (loadfile(kernels[i], marks, LOAD_KERNEL) >= 0) goto loaded; } boothowto |= RB_ASKNAME; } loaded: /* * Okay, kernel is loaded, free the extra memory at the end. * Round to the ARM OpenFirmare page size (4k). */ cp = (char *) ((marks[MARK_END] + 0xfff) & ~0xfff); size = (u_long) (endbuf - cp); if (size) OF_release(cp, size); #ifdef __notyet__ OF_setprop(chosen, "bootpath", opened_name, strlen(opened_name) + 1); cp = bootline; #else strcpy(bootline, opened_name); cp = bootline + strlen(bootline); *cp++ = ' '; #endif *cp = '-'; if (boothowto & RB_ASKNAME) *++cp = 'a'; if (boothowto & RB_SINGLE) *++cp = 's'; if (boothowto & RB_KDB) *++cp = 'd'; if (*cp == '-') #ifdef __notyet__ *cp = 0; #else *--cp = 0; #endif else
int openfirmioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) { struct ofiocdesc *of; int node, len, ok, error, s; char *name, *value; if (cmd == OFIOCGETOPTNODE) { s = splhigh(); *(int *) data = OF_finddevice("/options"); splx(s); return (0); } /* Verify node id */ of = (struct ofiocdesc *)data; node = of->of_nodeid; if (node != 0 && node != lastnode) { /* Not an easy one, must search for it */ s = splhigh(); ok = openfirmcheckid(OF_peer(0), node); splx(s); if (!ok) return (EINVAL); lastnode = node; } name = value = NULL; error = 0; switch (cmd) { case OFIOCGET: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openfirmgetstr(of->of_namelen, of->of_name, &name); if (error) break; s = splhigh(); len = OF_getproplen(node, name); splx(s); if (len > of->of_buflen) { error = ENOMEM; break; } of->of_buflen = len; /* -1 means no entry; 0 means no value */ if (len <= 0) break; value = malloc(len, M_TEMP, M_WAITOK); if (value == NULL) { error = ENOMEM; break; } s = splhigh(); len = OF_getprop(node, name, (void *)value, len); splx(s); error = copyout(value, of->of_buf, len); break; case OFIOCSET: if ((flags & FWRITE) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openfirmgetstr(of->of_namelen, of->of_name, &name); if (error) break; error = openfirmgetstr(of->of_buflen, of->of_buf, &value); if (error) break; s = splhigh(); len = OF_setprop(node, name, value, of->of_buflen + 1); splx(s); /* * XXX * some OF implementations return the buffer length including * the trailing zero ( like macppc ) and some without ( like * FirmWorks OF used in Shark ) */ if ((len != (of->of_buflen + 1)) && (len != of->of_buflen)) error = EINVAL; break; case OFIOCNEXTPROP: { char newname[32]; if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); if (of->of_namelen != 0) { error = openfirmgetstr(of->of_namelen, of->of_name, &name); if (error) break; } s = splhigh(); ok = OF_nextprop(node, name, newname); splx(s); if (ok == 0) { error = ENOENT; break; } if (ok == -1) { error = EINVAL; break; } len = strlen(newname); if (len > of->of_buflen) len = of->of_buflen; else of->of_buflen = len; error = copyout(newname, of->of_buf, len); break; } case OFIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); s = splhigh(); node = OF_peer(node); splx(s); *(int *)data = lastnode = node; break; case OFIOCGETCHILD: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); s = splhigh(); node = OF_child(node); splx(s); *(int *)data = lastnode = node; break; case OFIOCFINDDEVICE: if ((flags & FREAD) == 0) return (EBADF); error = openfirmgetstr(of->of_namelen, of->of_name, &name); if (error) break; node = OF_finddevice(name); if (node == 0 || node == -1) { error = ENOENT; break; } of->of_nodeid = lastnode = node; break; default: return (ENOTTY); } if (name) free(name, M_TEMP); if (value) free(value, M_TEMP); return (error); }