chiark / gitweb /
add firmware_helper to load firmware
authorKay Sievers <kay.sievers@suse.de>
Tue, 9 Aug 2005 17:00:37 +0000 (19:00 +0200)
committerKay Sievers <kay.sievers@suse.de>
Tue, 9 Aug 2005 17:00:37 +0000 (19:00 +0200)
From: Bill Nottingham <notting@redhat.com>

Changed reading of firmware blob to mmap and let firmware_helper
follow the setting of the log level with UDEV_LOG.

extras/firmware/Makefile [new file with mode: 0644]
extras/firmware/firmware_helper.c [new file with mode: 0644]
logging.h
test/simple-build-check.sh

diff --git a/extras/firmware/Makefile b/extras/firmware/Makefile
new file mode 100644 (file)
index 0000000..6417bbf
--- /dev/null
@@ -0,0 +1,51 @@
+# Makefile for usb_id
+#
+# Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+
+PROG = firmware_helper
+
+all:   $(PROG)
+
+prefix =
+exec_prefix =  ${prefix}
+etcdir =       ${prefix}/etc
+sbindir =      ${exec_prefix}/sbin
+usrbindir =    ${exec_prefix}/usr/bin
+usrsbindir =   ${exec_prefix}/usr/sbin
+mandir =       ${prefix}/usr/share/man
+devddir =      ${etcdir}/dev.d/default
+configdir =    ${etcdir}/udev/
+initdir =      ${etcdir}/init.d/
+srcdir = .
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA  = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+
+OBJS = $(PROG).o $(VOLUME_ID_OBJS) ../../udev.a ../../libsysfs/sysfs.a
+HEADERS =
+
+$(OBJS): $(HEADERS)
+
+.c.o:
+       $(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
+
+$(PROG): $(OBJS) $(HEADERS)
+       $(QUIET) $(LD) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIB_OBJS)
+
+clean:
+       rm -f $(PROG) $(OBJS)
+
+spotless: clean
+
+install: all
+       $(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(sbindir)/$(PROG)
+
+uninstall:
+       - rm $(DESTDIR)$(sbindir)/$(PROG)
diff --git a/extras/firmware/firmware_helper.c b/extras/firmware/firmware_helper.c
new file mode 100644 (file)
index 0000000..283ea9f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * A simple firmware helper program.
+ * 
+ * Copyright 2005 Red Hat, Inc.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "../../udev_utils.h"
+#include "../../logging.h"
+
+#define FIRMWARE_PATH                  "/lib/firmware"
+#define PATH_SIZE                      256
+
+#ifdef USE_LOG
+void log_message(int priority, const char *format, ...)
+{
+       va_list args;
+       static int udev_log = -1;
+
+       if (udev_log == -1) {
+               const char *value;
+
+               value = getenv("UDEV_LOG");
+               if (value)
+                       udev_log = log_priority(value);
+               else
+                       udev_log = LOG_ERR;
+       }
+
+       if (priority > udev_log)
+               return;
+
+       va_start(args, format);
+       vsyslog(priority, format, args);
+       va_end(args);
+}
+#endif
+
+/* Set the 'loading' attribute for a firmware device.
+ * 1 == currently loading
+ * 0 == done loading
+ * -1 == error
+ */
+static int set_loading(const char *device, int value) {
+       char loading_path[PATH_SIZE];
+       int rc;
+       FILE *f;
+
+       snprintf(loading_path, sizeof(loading_path), "/sys/%s/loading", device);
+       loading_path[sizeof(loading_path)-1] = '\0';
+       f = fopen(loading_path, "w");
+       if (!f)
+               return -1;
+       rc = fprintf(f, "%d", value);
+       fclose(f);
+       if (rc < 0)
+               return rc;
+       return 0;
+}
+
+int main(int argc, char **argv) {
+       char *devpath, *firmware, *action, *driver;
+       char fw_path[PATH_SIZE];
+       char data_path[PATH_SIZE];
+       int fw_fd;
+       char *fw_buffer;
+       size_t fw_buffer_size;
+       size_t count;
+       int rc = 0;
+
+       logging_init("firmware_helper");
+
+       driver = getenv("PHYSDEVDRIVER");
+       if (!driver)
+               driver = "(unknown)";
+       devpath = getenv("DEVPATH");
+       firmware = getenv("FIRMWARE");
+       action = getenv("ACTION");
+       if (!devpath || !firmware || !action || strcmp(action,"add") != 0) {
+               err("missing devpath, action or firmware");
+               exit(1);
+       }
+
+       dbg("try to load firmware '%s' for '%s'", firmware, devpath);
+       set_loading(devpath, 1);
+
+       snprintf(fw_path, sizeof(fw_path), "%s/%s", FIRMWARE_PATH, firmware);
+       fw_path[sizeof(fw_path)-1] = '\0';
+       if (file_map(fw_path, &fw_buffer, &fw_buffer_size) != 0 || fw_buffer_size == 0) {
+               err("could not load firmware '%s' for '%s'", fw_path, devpath);
+               fw_buffer = NULL;
+               goto out_err;
+       }
+
+       snprintf(data_path, sizeof(data_path), "/sys/%s/data", devpath);
+       fw_path[sizeof(data_path)-1] = '\0';
+       fw_fd = open(data_path, O_RDWR);
+       if (fw_fd < 0) {
+               rc = errno;
+               goto out_err;
+       }
+
+       count = 0;
+       while (count < fw_buffer_size) {
+               int c;
+
+               c = write(fw_fd, fw_buffer+count, fw_buffer_size);
+               if (c <= 0) {
+                       rc = errno;
+                       close(fw_fd);
+                       goto out_err;
+               }
+               count += c;
+       }
+
+       close(fw_fd);
+       file_unmap(fw_buffer, fw_buffer_size);
+       set_loading(devpath, 0);
+       info("loaded '%s' for device '%s'", fw_path, devpath);
+       logging_close();
+       return 0;
+
+out_err:
+       if (fw_buffer)
+               file_unmap(fw_buffer, fw_buffer_size);
+       set_loading(devpath, -1);
+
+       err("error loading '%s' for device '%s' with driver '%s'", fw_path, devpath, driver);
+       logging_close();
+       return rc;
+}
index 904355cb2cf4fa4f590f3bcd7f950069ca95cefe..0126de99eb94b2dec6d88896a809272a1f07d6f7 100644 (file)
--- a/logging.h
+++ b/logging.h
@@ -38,7 +38,7 @@
 #undef err
 #define err(format, arg...)                                                    \
        do {                                                                    \
 #undef err
 #define err(format, arg...)                                                    \
        do {                                                                    \
-               log_message(LOG_INFO ,"%s: " format ,__FILE__ ,## arg);         \
+               log_message(LOG_ERR ,"%s: " format ,__FILE__ ,## arg);          \
        } while (0)
 
 #undef info
        } while (0)
 
 #undef info
index 742b28ec1c53d5ddc102367186f928ed46002ce9..521691618a4f81241fe20d2cdf22a238ffe8be4d 100755 (executable)
@@ -8,7 +8,8 @@ EXTRAS="\
        extras/usb_id \
        extras/dasd_id \
        extras/floppy \
        extras/usb_id \
        extras/dasd_id \
        extras/floppy \
-       extras/run_directory"
+       extras/run_directory \
+       extras/firmware"
 
 [ -z "$KERNEL_DIR" ] && KERNEL_DIR=/lib/modules/`uname -r`/build
 echo KERNEL_DIR: "$KERNEL_DIR"
 
 [ -z "$KERNEL_DIR" ] && KERNEL_DIR=/lib/modules/`uname -r`/build
 echo KERNEL_DIR: "$KERNEL_DIR"