aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2007-06-13 07:34:15 +0000
committerMike Frysinger <vapier@gentoo.org>2007-06-13 07:34:15 +0000
commita78ef2ccf14a0b3bc50b8fd8fd3239ca1385ee2b (patch)
tree8f76a7bf9fc29d1b8ed6d27e4155321660aa37ca
parentd67cef2425fb5e75b75d52d9a308da6d29cd7a0d (diff)
downloadbusybox-w32-a78ef2ccf14a0b3bc50b8fd8fd3239ca1385ee2b.tar.gz
busybox-w32-a78ef2ccf14a0b3bc50b8fd8fd3239ca1385ee2b.tar.bz2
busybox-w32-a78ef2ccf14a0b3bc50b8fd8fd3239ca1385ee2b.zip
add support for firmware loading
-rw-r--r--util-linux/Config.in11
-rw-r--r--util-linux/mdev.c75
2 files changed, 84 insertions, 2 deletions
diff --git a/util-linux/Config.in b/util-linux/Config.in
index 2184df153..1040ce282 100644
--- a/util-linux/Config.in
+++ b/util-linux/Config.in
@@ -294,6 +294,17 @@ config FEATURE_MDEV_EXEC
294 294
295 For more information, please see docs/mdev.txt 295 For more information, please see docs/mdev.txt
296 296
297config FEATURE_MDEV_LOAD_FIRMWARE
298 bool "Support loading of firmwares"
299 default n
300 depends on MDEV
301 help
302 Some devices need to load firmware before they can be usable.
303
304 These devices will request userspace look up the files in
305 /lib/firmware/ and if it exists, send it to the kernel for
306 loading into the hardware.
307
297config MKSWAP 308config MKSWAP
298 bool "mkswap" 309 bool "mkswap"
299 default n 310 default n
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index d1b2684bc..8e5b8a94b 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -226,6 +226,71 @@ static void find_dev(char *path)
226 closedir(dir); 226 closedir(dir);
227} 227}
228 228
229/* For the full gory details, see linux/Documentation/firmware_class/README
230 *
231 * Firmware loading works like this:
232 * - kernel sets FIRMWARE env var
233 * - userspace checks /lib/firmware/$FIRMWARE
234 * - userspace waits for /sys/$DEVPATH/loading to appear
235 * - userspace writes "1" to /sys/$DEVPATH/loading
236 * - userspace copies /lib/firmware/$FIRMWARE into /sys/$DEVPATH/data
237 * - userspace writes "0" (worked) or "-1" (failed) to /sys/$DEVPATH/loading
238 * - kernel loads firmware into device
239 */
240static inline void load_firmware(const char * const firmware, const char * const sysfs_path)
241{
242 int cnt;
243 int firmware_fd, loading_fd, data_fd;
244
245 /* check for $FIRMWARE from kernel */
246 /* XXX: dont bother: open(NULL) works same as open("no-such-file")
247 * if (!firmware)
248 * return;
249 */
250
251 /* check for /lib/firmware/$FIRMWARE */
252 xchdir("/lib/firmware");
253 firmware_fd = xopen(firmware, O_WRONLY);
254
255 /* in case we goto out ... */
256 data_fd = -1;
257
258 /* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */
259 xchdir(sysfs_path);
260 for (cnt = 0; cnt < 30; ++cnt) {
261 loading_fd = open("loading", O_WRONLY);
262 if (loading_fd == -1)
263 sleep(1);
264 else
265 break;
266 }
267 if (loading_fd == -1)
268 goto out;
269
270 /* tell kernel we're loading by `echo 1 > /sys/$DEVPATH/loading` */
271 if (write(loading_fd, "1", 1) != 1)
272 goto out;
273
274 /* load firmware by `cat /lib/firmware/$FIRMWARE > /sys/$DEVPATH/data */
275 data_fd = open("data", O_WRONLY);
276 if (data_fd == -1)
277 goto out;
278 cnt = bb_copyfd_eof(firmware_fd, data_fd);
279
280 /* tell kernel result by `echo [0|-1] > /sys/$DEVPATH/loading` */
281 if (cnt > 0)
282 write(loading_fd, "0", 1);
283 else
284 write(loading_fd, "-1", 2);
285
286 out:
287 if (ENABLE_FEATURE_CLEAN_UP) {
288 close(firmware_fd);
289 close(loading_fd);
290 close(data_fd);
291 }
292}
293
229int mdev_main(int argc, char **argv); 294int mdev_main(int argc, char **argv);
230int mdev_main(int argc, char **argv) 295int mdev_main(int argc, char **argv)
231{ 296{
@@ -257,8 +322,14 @@ int mdev_main(int argc, char **argv)
257 bb_show_usage(); 322 bb_show_usage();
258 323
259 sprintf(temp, "/sys%s", env_path); 324 sprintf(temp, "/sys%s", env_path);
260 if (!strcmp(action, "add")) make_device(temp,0); 325 if (!strcmp(action, "remove"))
261 else if (!strcmp(action, "remove")) make_device(temp,1); 326 make_device(temp, 1);
327 else if (!strcmp(action, "add")) {
328 make_device(temp, 0);
329
330 if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE)
331 load_firmware(getenv("FIRMWARE"), temp);
332 }
262 } 333 }
263 334
264 if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp); 335 if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp);