svn commit: trunk/busybox/util-linux

vapier at busybox.net vapier at busybox.net
Wed Jun 13 07:34:17 UTC 2007


Author: vapier
Date: 2007-06-13 00:34:15 -0700 (Wed, 13 Jun 2007)
New Revision: 18810

Log:
add support for firmware loading

Modified:
   trunk/busybox/util-linux/Config.in
   trunk/busybox/util-linux/mdev.c


Changeset:
Modified: trunk/busybox/util-linux/Config.in
===================================================================
--- trunk/busybox/util-linux/Config.in	2007-06-13 06:47:47 UTC (rev 18809)
+++ trunk/busybox/util-linux/Config.in	2007-06-13 07:34:15 UTC (rev 18810)
@@ -294,6 +294,17 @@
 
 	  For more information, please see docs/mdev.txt
 
+config FEATURE_MDEV_LOAD_FIRMWARE
+	bool "Support loading of firmwares"
+	default n
+	depends on MDEV
+	help
+	  Some devices need to load firmware before they can be usable.
+
+	  These devices will request userspace look up the files in
+	  /lib/firmware/ and if it exists, send it to the kernel for
+	  loading into the hardware.
+
 config MKSWAP
 	bool "mkswap"
 	default n

Modified: trunk/busybox/util-linux/mdev.c
===================================================================
--- trunk/busybox/util-linux/mdev.c	2007-06-13 06:47:47 UTC (rev 18809)
+++ trunk/busybox/util-linux/mdev.c	2007-06-13 07:34:15 UTC (rev 18810)
@@ -226,6 +226,71 @@
 	closedir(dir);
 }
 
+/* For the full gory details, see linux/Documentation/firmware_class/README
+ *
+ * Firmware loading works like this:
+ * - kernel sets FIRMWARE env var
+ * - userspace checks /lib/firmware/$FIRMWARE
+ * - userspace waits for /sys/$DEVPATH/loading to appear
+ * - userspace writes "1" to /sys/$DEVPATH/loading
+ * - userspace copies /lib/firmware/$FIRMWARE into /sys/$DEVPATH/data
+ * - userspace writes "0" (worked) or "-1" (failed) to /sys/$DEVPATH/loading
+ * - kernel loads firmware into device
+ */
+static inline void load_firmware(const char * const firmware, const char * const sysfs_path)
+{
+	int cnt;
+	int firmware_fd, loading_fd, data_fd;
+
+	/* check for $FIRMWARE from kernel */
+	/* XXX: dont bother: open(NULL) works same as open("no-such-file")
+	 * if (!firmware)
+	 *	return;
+	 */
+
+	/* check for /lib/firmware/$FIRMWARE */
+	xchdir("/lib/firmware");
+	firmware_fd = xopen(firmware, O_WRONLY);
+
+	/* in case we goto out ... */
+	data_fd = -1;
+
+	/* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */
+	xchdir(sysfs_path);
+	for (cnt = 0; cnt < 30; ++cnt) {
+		loading_fd = open("loading", O_WRONLY);
+		if (loading_fd == -1)
+			sleep(1);
+		else
+			break;
+	}
+	if (loading_fd == -1)
+		goto out;
+
+	/* tell kernel we're loading by `echo 1 > /sys/$DEVPATH/loading` */
+	if (write(loading_fd, "1", 1) != 1)
+		goto out;
+
+	/* load firmware by `cat /lib/firmware/$FIRMWARE > /sys/$DEVPATH/data */
+	data_fd = open("data", O_WRONLY);
+	if (data_fd == -1)
+		goto out;
+	cnt = bb_copyfd_eof(firmware_fd, data_fd);
+
+	/* tell kernel result by `echo [0|-1] > /sys/$DEVPATH/loading` */
+	if (cnt > 0)
+		write(loading_fd, "0", 1);
+	else
+		write(loading_fd, "-1", 2);
+
+ out:
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		close(firmware_fd);
+		close(loading_fd);
+		close(data_fd);
+	}
+}
+
 int mdev_main(int argc, char **argv);
 int mdev_main(int argc, char **argv)
 {
@@ -257,8 +322,14 @@
 			bb_show_usage();
 
 		sprintf(temp, "/sys%s", env_path);
-		if (!strcmp(action, "add")) make_device(temp,0);
-		else if (!strcmp(action, "remove")) make_device(temp,1);
+		if (!strcmp(action, "remove"))
+			make_device(temp, 1);
+		else if (!strcmp(action, "add")) {
+			make_device(temp, 0);
+
+			if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE)
+				load_firmware(getenv("FIRMWARE"), temp);
+		}
 	}
 
 	if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp);




More information about the busybox-cvs mailing list