From 073e8552f826ee10465d90a12d0dc31cb0679b1f Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Sat, 22 May 2004 16:43:42 +0000 Subject: [PATCH] - Move OFW_NAME_MAX, used as a limit for OFW property names and device identifiers, to openfirmio.h as OFIOCMAXNAME, so programs can use it for buffer sizes etc. Note: Although this is only a rough upper limit to make the code more robust and to prevent the allocation of ridiculous amounts of memory, the current limit of one page (8191 + '\0' in openfirm_getstr()) still appears a bit high. The maximum length of OFW property names is 31. I didn't find a maximum length for the device identifiers in the OFW documentation but it certainly is much smaller than 8191, too. - Enable the OFIOCSET ioctl, i.e. move it out from under #if 0. - Don't use openfirm_getstr() for the property value in OFIOCSET, there are also properties whose values aren't strings and it makes sense to use a different maximum length for property values than OFW_NAME_MAX/ OFIOCMAXNAME. The maximum accepted property value is defined in openfirmio.h as OFIOCMAXVALUE (currently the maximum size of the value of the nvramrc property). - Make OFIOCSET not return EINVAL when OF_setprop() returns a different length for the written value than it was told to write, this is normal for the text string values of the properties in the OFW /options node. Instead, only return EINVAL if OF_setprop() returned -1 (value could not be written or property could not be created). Add a comment about the specialty of the OFW /options node. - Make OFIOCSET return the length of the written value returned by OF_setprop(), just like OF_getprop() does. Quite useful, at least for debugging. Reviewed by: tmm --- sys/dev/ofw/openfirmio.c | 28 ++++++++++++++++++---------- sys/dev/ofw/openfirmio.h | 9 ++++++--- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/sys/dev/ofw/openfirmio.c b/sys/dev/ofw/openfirmio.c index 358109e7835..adb39296ab7 100644 --- a/sys/dev/ofw/openfirmio.c +++ b/sys/dev/ofw/openfirmio.c @@ -74,9 +74,6 @@ static phandle_t lastnode; /* speed hack */ static int openfirm_checkid(phandle_t, phandle_t); static int openfirm_getstr(int, const char *, char **); -/* Maximum accepted name length. */ -#define OFW_NAME_MAX 8191 - /* * Verify target ID is valid (exists in the OPENPROM tree), as * listed from node ID sid forward. @@ -99,7 +96,7 @@ openfirm_getstr(int len, const char *user, char **cpp) char *cp; /* Reject obvious bogus requests */ - if ((u_int)len > OFW_NAME_MAX) + if ((u_int)len > OFIOCMAXNAME) return (ENAMETOOLONG); *cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK); @@ -129,9 +126,7 @@ openfirm_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, *(phandle_t *) data = OF_finddevice("/options"); return (0); case OFIOCGET: -#if 0 case OFIOCSET: -#endif case OFIOCNEXTPROP: case OFIOCFINDDEVICE: case OFIOCGETPROPLEN: @@ -186,23 +181,36 @@ openfirm_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, error = copyout(value, of->of_buf, len); break; -#if 0 case OFIOCSET: + /* + * Note: Text string values for at least the /options node + * have to be null-terminated and the length paramter must + * include this terminating null. However, like OF_getprop(), + * OF_setprop() will return the 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; - error = openfirm_getstr(of->of_buflen, of->of_buf, &value); + 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 != of->of_buflen) + if (len < 0) error = EINVAL; + of->of_buflen = len; break; -#endif case OFIOCNEXTPROP: if (node == 0 || of->of_buflen < 0) diff --git a/sys/dev/ofw/openfirmio.h b/sys/dev/ofw/openfirmio.h index ae5837ecd0a..c4f21d2897a 100644 --- a/sys/dev/ofw/openfirmio.h +++ b/sys/dev/ofw/openfirmio.h @@ -54,10 +54,8 @@ struct ofiocdesc { /* Get openprom field. */ #define OFIOCGET _IOWR(OFIOC_BASE, 1, struct ofiocdesc) -#if 0 /* Set openprom field. */ -#define OFIOCSET _IOW(OFIOC_BASE, 2, struct ofiocdesc) -#endif +#define OFIOCSET _IOWR(OFIOC_BASE, 2, struct ofiocdesc) /* Get next property. */ #define OFIOCNEXTPROP _IOWR(OFIOC_BASE, 3, struct ofiocdesc) /* Get options node. */ @@ -71,4 +69,9 @@ struct ofiocdesc { /* Retrieve the size of a property. */ #define OFIOCGETPROPLEN _IOWR(OFIOC_BASE, 8, struct ofiocdesc) +/* Maximum accepted name length. */ +#define OFIOCMAXNAME 8191 +/* Maximum accepted value length (maximum of nvramrc property). */ +#define OFIOCMAXVALUE 8192 + #endif /* _DEV_OFW_OPENFIRMIO_H_ */