IEEE1275 a.k.a. Open Firmware clearly states that property name strings can have a length of up to 31 characters. That same limit is mentioned in various documents on the flattened device tree format. Unfortunately that limit seems to be ignored. The device tree on the POWER9 machines has property names longer than that, and I have seen this on some ARM boards as well.
The maximum property name length is relevant for the OF_nextprop() interface, which assumes the buffer you pass it is big enough to store the property name. The FDT implementation of that interface truncates property names to 31 characters in order to avoid a buffer overflow. The problem wit that is that if you pass this truncated name to OF_nextprop() the lookup fails. As a result the output of eeprom -p is incomplete. The diff below fixes this by making the buffers 64 bytes in size. That is good enough for treu Open Firmware systems as well. And by having a central define there is less risk of the fdt.c implementation of OF_nextprop() getting out of sync with the openprom(4) implementation. The diff also removes some warts from the openprom(4) implementations for armv7, arm64, octeon and powerpc64. I think the static buffer was a workaround for Apple's broken Open Firmware implementation. Tested on armv7, arm64 and macppc. ok? Index: arch/arm/arm/openprom.c =================================================================== RCS file: /cvs/src/sys/arch/arm/arm/openprom.c,v retrieving revision 1.2 diff -u -p -r1.2 openprom.c --- arch/arm/arm/openprom.c 23 May 2016 00:05:34 -0000 1.2 +++ arch/arm/arm/openprom.c 5 Jul 2020 17:49:26 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: openprom.c,v 1.2 2016/05/23 00:05:34 deraadt Exp $ */ +/* $OpenBSD: openprom.c,v 1.1 2017/01/23 12:34:06 kettenis Exp $ */ /* $NetBSD: openprom.c,v 1.4 2002/01/10 06:21:53 briggs Exp $ */ /* @@ -55,13 +55,11 @@ #include <dev/ofw/openfirm.h> -#define OPROMMAXPARAM 32 +static int lastnode; /* speed hack */ +static int optionsnode; /* node ID of ROM's options */ -static int lastnode; /* speed hack */ -static int optionsnode; /* node ID of ROM's options */ - -static int openpromcheckid(int, int); -static int openpromgetstr(int, char *, char **); +int openpromcheckid(int, int); +int openpromgetstr(int, char *, char **); void openpromattach(int); void @@ -115,15 +113,11 @@ 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; + int node, len, ok, error; char *name, *value, *nextprop; - static char buf[32]; /* XXX */ - if (optionsnode == 0) { - s = splhigh(); + if (optionsnode == 0) optionsnode = OF_getnodebyname(0, "options"); - splx(s); - } /* All too easy... */ if (cmd == OPIOCGETOPTNODE) { @@ -136,9 +130,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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; @@ -156,10 +148,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + len = OF_getproplen(node, name); if (len > op->op_buflen) { error = ENOMEM; break; @@ -169,34 +158,10 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + OF_getprop(node, name, value, len); error = copyout(value, op->op_buf, len); break; -#if 0 - 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; -#endif - case OPIOCNEXTPROP: if ((flags & FREAD) == 0) return (EBADF); @@ -209,16 +174,13 @@ openpromioctl(dev_t dev, u_long cmd, cad error = ENAMETOOLONG; break; } - value = nextprop = malloc(OPROMMAXPARAM, M_TEMP, + value = nextprop = malloc(OFMAXPARAM, M_TEMP, M_WAITOK | M_CANFAIL); if (nextprop == NULL) { error = ENOMEM; break; } - s = splhigh(); - strlcpy(buf, name, 32); /* XXX */ - error = OF_nextprop(node, buf, nextprop); - splx(s); + error = OF_nextprop(node, name, nextprop); if (error == -1) { error = EINVAL; break; @@ -241,9 +203,7 @@ openpromioctl(dev_t dev, u_long cmd, cad case OPIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); - s = splhigh(); node = OF_peer(node); - splx(s); *(int *)data = lastnode = node; break; @@ -252,9 +212,7 @@ openpromioctl(dev_t dev, u_long cmd, cad return (EBADF); if (node == 0) return (EINVAL); - s = splhigh(); node = OF_child(node); - splx(s); *(int *)data = lastnode = node; break; Index: arch/arm64/arm64/openprom.c =================================================================== RCS file: /cvs/src/sys/arch/arm64/arm64/openprom.c,v retrieving revision 1.1 diff -u -p -r1.1 openprom.c --- arch/arm64/arm64/openprom.c 23 Jan 2017 12:34:06 -0000 1.1 +++ arch/arm64/arm64/openprom.c 5 Jul 2020 17:49:26 -0000 @@ -55,13 +55,11 @@ #include <dev/ofw/openfirm.h> -#define OPROMMAXPARAM 32 +static int lastnode; /* speed hack */ +static int optionsnode; /* node ID of ROM's options */ -static int lastnode; /* speed hack */ -static int optionsnode; /* node ID of ROM's options */ - -static int openpromcheckid(int, int); -static int openpromgetstr(int, char *, char **); +int openpromcheckid(int, int); +int openpromgetstr(int, char *, char **); void openpromattach(int); void @@ -115,15 +113,11 @@ 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; + int node, len, ok, error; char *name, *value, *nextprop; - static char buf[32]; /* XXX */ - if (optionsnode == 0) { - s = splhigh(); + if (optionsnode == 0) optionsnode = OF_getnodebyname(0, "options"); - splx(s); - } /* All too easy... */ if (cmd == OPIOCGETOPTNODE) { @@ -136,9 +130,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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; @@ -156,10 +148,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + len = OF_getproplen(node, name); if (len > op->op_buflen) { error = ENOMEM; break; @@ -169,34 +158,10 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + OF_getprop(node, name, value, len); error = copyout(value, op->op_buf, len); break; -#if 0 - 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; -#endif - case OPIOCNEXTPROP: if ((flags & FREAD) == 0) return (EBADF); @@ -209,16 +174,13 @@ openpromioctl(dev_t dev, u_long cmd, cad error = ENAMETOOLONG; break; } - value = nextprop = malloc(OPROMMAXPARAM, M_TEMP, + value = nextprop = malloc(OFMAXPARAM, M_TEMP, M_WAITOK | M_CANFAIL); if (nextprop == NULL) { error = ENOMEM; break; } - s = splhigh(); - strlcpy(buf, name, 32); /* XXX */ - error = OF_nextprop(node, buf, nextprop); - splx(s); + error = OF_nextprop(node, name, nextprop); if (error == -1) { error = EINVAL; break; @@ -241,9 +203,7 @@ openpromioctl(dev_t dev, u_long cmd, cad case OPIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); - s = splhigh(); node = OF_peer(node); - splx(s); *(int *)data = lastnode = node; break; @@ -252,9 +212,7 @@ openpromioctl(dev_t dev, u_long cmd, cad return (EBADF); if (node == 0) return (EINVAL); - s = splhigh(); node = OF_child(node); - splx(s); *(int *)data = lastnode = node; break; Index: arch/octeon/octeon/openprom.c =================================================================== RCS file: /cvs/src/sys/arch/octeon/octeon/openprom.c,v retrieving revision 1.2 diff -u -p -r1.2 openprom.c --- arch/octeon/octeon/openprom.c 5 Jul 2016 13:41:46 -0000 1.2 +++ arch/octeon/octeon/openprom.c 5 Jul 2020 17:49:27 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: openprom.c,v 1.2 2016/07/05 13:41:46 visa Exp $ */ +/* $OpenBSD: openprom.c,v 1.1 2017/01/23 12:34:06 kettenis Exp $ */ /* $NetBSD: openprom.c,v 1.4 2002/01/10 06:21:53 briggs Exp $ */ /* @@ -55,13 +55,11 @@ #include <dev/ofw/openfirm.h> -#define OPROMMAXPARAM 32 +static int lastnode; /* speed hack */ +static int optionsnode; /* node ID of ROM's options */ -static int lastnode; /* speed hack */ -static int optionsnode; /* node ID of ROM's options */ - -static int openpromcheckid(int, int); -static int openpromgetstr(int, char *, char **); +int openpromcheckid(int, int); +int openpromgetstr(int, char *, char **); void openpromattach(int); void @@ -115,15 +113,11 @@ 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; + int node, len, ok, error; char *name, *value, *nextprop; - static char buf[32]; /* XXX */ - if (optionsnode == 0) { - s = splhigh(); + if (optionsnode == 0) optionsnode = OF_getnodebyname(0, "options"); - splx(s); - } /* All too easy... */ if (cmd == OPIOCGETOPTNODE) { @@ -136,9 +130,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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; @@ -156,10 +148,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + len = OF_getproplen(node, name); if (len > op->op_buflen) { error = ENOMEM; break; @@ -169,34 +158,10 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + OF_getprop(node, name, value, len); error = copyout(value, op->op_buf, len); break; -#if 0 - 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; -#endif - case OPIOCNEXTPROP: if ((flags & FREAD) == 0) return (EBADF); @@ -209,16 +174,13 @@ openpromioctl(dev_t dev, u_long cmd, cad error = ENAMETOOLONG; break; } - value = nextprop = malloc(OPROMMAXPARAM, M_TEMP, + value = nextprop = malloc(OFMAXPARAM, M_TEMP, M_WAITOK | M_CANFAIL); if (nextprop == NULL) { error = ENOMEM; break; } - s = splhigh(); - strlcpy(buf, name, 32); /* XXX */ - error = OF_nextprop(node, buf, nextprop); - splx(s); + error = OF_nextprop(node, name, nextprop); if (error == -1) { error = EINVAL; break; @@ -241,9 +203,7 @@ openpromioctl(dev_t dev, u_long cmd, cad case OPIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); - s = splhigh(); node = OF_peer(node); - splx(s); *(int *)data = lastnode = node; break; @@ -252,9 +212,7 @@ openpromioctl(dev_t dev, u_long cmd, cad return (EBADF); if (node == 0) return (EINVAL); - s = splhigh(); node = OF_child(node); - splx(s); *(int *)data = lastnode = node; break; Index: arch/powerpc64/powerpc64/openprom.c =================================================================== RCS file: /cvs/src/sys/arch/powerpc64/powerpc64/openprom.c,v retrieving revision 1.1 diff -u -p -r1.1 openprom.c --- arch/powerpc64/powerpc64/openprom.c 27 Jun 2020 21:39:05 -0000 1.1 +++ arch/powerpc64/powerpc64/openprom.c 5 Jul 2020 17:49:27 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: openprom.c,v 1.1 2020/06/27 21:39:05 kettenis Exp $ */ +/* $OpenBSD: openprom.c,v 1.1 2017/01/23 12:34:06 kettenis Exp $ */ /* $NetBSD: openprom.c,v 1.4 2002/01/10 06:21:53 briggs Exp $ */ /* @@ -55,13 +55,11 @@ #include <dev/ofw/openfirm.h> -#define OPROMMAXPARAM 32 +static int lastnode; /* speed hack */ +static int optionsnode; /* node ID of ROM's options */ -static int lastnode; /* speed hack */ -static int optionsnode; /* node ID of ROM's options */ - -static int openpromcheckid(int, int); -static int openpromgetstr(int, char *, char **); +int openpromcheckid(int, int); +int openpromgetstr(int, char *, char **); void openpromattach(int); void @@ -115,15 +113,11 @@ 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; + int node, len, ok, error; char *name, *value, *nextprop; - static char buf[32]; /* XXX */ - if (optionsnode == 0) { - s = splhigh(); + if (optionsnode == 0) optionsnode = OF_getnodebyname(0, "options"); - splx(s); - } /* All too easy... */ if (cmd == OPIOCGETOPTNODE) { @@ -136,9 +130,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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; @@ -156,10 +148,7 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + len = OF_getproplen(node, name); if (len > op->op_buflen) { error = ENOMEM; break; @@ -169,34 +158,10 @@ openpromioctl(dev_t dev, u_long cmd, cad 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); + OF_getprop(node, name, value, len); error = copyout(value, op->op_buf, len); break; -#if 0 - 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; -#endif - case OPIOCNEXTPROP: if ((flags & FREAD) == 0) return (EBADF); @@ -209,16 +174,13 @@ openpromioctl(dev_t dev, u_long cmd, cad error = ENAMETOOLONG; break; } - value = nextprop = malloc(OPROMMAXPARAM, M_TEMP, + value = nextprop = malloc(OFMAXPARAM, M_TEMP, M_WAITOK | M_CANFAIL); if (nextprop == NULL) { error = ENOMEM; break; } - s = splhigh(); - strlcpy(buf, name, 32); /* XXX */ - error = OF_nextprop(node, buf, nextprop); - splx(s); + error = OF_nextprop(node, name, nextprop); if (error == -1) { error = EINVAL; break; @@ -241,9 +203,7 @@ openpromioctl(dev_t dev, u_long cmd, cad case OPIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); - s = splhigh(); node = OF_peer(node); - splx(s); *(int *)data = lastnode = node; break; @@ -252,9 +212,7 @@ openpromioctl(dev_t dev, u_long cmd, cad return (EBADF); if (node == 0) return (EINVAL); - s = splhigh(); node = OF_child(node); - splx(s); *(int *)data = lastnode = node; break; Index: dev/ofw/fdt.c =================================================================== RCS file: /cvs/src/sys/dev/ofw/fdt.c,v retrieving revision 1.23 diff -u -p -r1.23 fdt.c --- dev/ofw/fdt.c 10 Aug 2019 13:16:01 -0000 1.23 +++ dev/ofw/fdt.c 5 Jul 2020 17:49:28 -0000 @@ -24,9 +24,6 @@ #include <dev/ofw/fdt.h> #include <dev/ofw/openfirm.h> -/* XXX */ -#define OPROMMAXPARAM 32 - unsigned int fdt_check_head(void *); char *fdt_get_str(u_int32_t); void *skip_property(u_int32_t *); @@ -904,13 +901,13 @@ OF_nextprop(int handle, char *prop, void if (fdt_node_property(node, "name", &data) == -1) { if (strcmp(prop, "") == 0) - return strlcpy(nextprop, "name", OPROMMAXPARAM); + return strlcpy(nextprop, "name", OFMAXPARAM); if (strcmp(prop, "name") == 0) prop = ""; } if (fdt_next_property(node, prop, &data)) - return strlcpy(nextprop, data, OPROMMAXPARAM); + return strlcpy(nextprop, data, OFMAXPARAM); return -1; } Index: dev/ofw/openfirm.h =================================================================== RCS file: /cvs/src/sys/dev/ofw/openfirm.h,v retrieving revision 1.15 diff -u -p -r1.15 openfirm.h --- dev/ofw/openfirm.h 27 Dec 2017 11:40:14 -0000 1.15 +++ dev/ofw/openfirm.h 5 Jul 2020 17:49:28 -0000 @@ -38,6 +38,8 @@ #include <sys/param.h> #include <sys/device.h> +#define OFMAXPARAM 64 + int openfirmware(void *); extern char OF_buf[];