summaryrefslogtreecommitdiffstats
path: root/sys/dev/ofw
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2004-05-22 16:43:42 +0000
committermarius <marius@FreeBSD.org>2004-05-22 16:43:42 +0000
commit630c60c775383107787c595cde447ba88cb494be (patch)
treef278fb8e30dee2cf60cd930fb8596885755725cc /sys/dev/ofw
parentef31e6c3b5eecc0138972fe13b84d260b34f2cbb (diff)
downloadFreeBSD-src-630c60c775383107787c595cde447ba88cb494be.zip
FreeBSD-src-630c60c775383107787c595cde447ba88cb494be.tar.gz
- 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
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r--sys/dev/ofw/openfirmio.c28
-rw-r--r--sys/dev/ofw/openfirmio.h9
2 files changed, 24 insertions, 13 deletions
diff --git a/sys/dev/ofw/openfirmio.c b/sys/dev/ofw/openfirmio.c
index 358109e..adb3929 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 ae5837e..c4f21d2 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_ */
OpenPOWER on IntegriCloud