2011-12-22 01:30:48 +04:00
/*
2011-12-22 02:10:56 +04:00
* load kernel modules
2011-12-22 01:30:48 +04:00
*
* Copyright ( C ) 2011 Kay Sievers < kay . sievers @ vrfy . org >
2011-12-24 20:58:52 +04:00
* Copyright ( C ) 2011 ProFUSION embedded systems
2011-12-22 01:30:48 +04:00
*
* 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 , either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <unistd.h>
# include <string.h>
# include <errno.h>
# include <fcntl.h>
# include <sys/stat.h>
2011-12-23 07:50:33 +04:00
# include <sys/wait.h>
2011-12-23 21:19:18 +04:00
# include <libkmod.h>
2011-12-22 01:30:48 +04:00
# include "udev.h"
2011-12-23 21:19:18 +04:00
static struct kmod_ctx * ctx ;
2011-12-27 23:17:39 +04:00
static int load_module ( struct udev * udev , const char * alias )
2011-12-23 21:19:18 +04:00
{
2012-01-10 04:34:15 +04:00
struct kmod_list * list = NULL ;
struct kmod_list * l ;
int err ;
err = kmod_module_new_from_lookup ( ctx , alias , & list ) ;
if ( err < 0 )
return err ;
if ( list = = NULL )
2012-04-08 18:06:20 +04:00
log_debug ( " no module matches '%s' \n " , alias ) ;
2012-01-10 04:34:15 +04:00
2012-02-07 03:47:00 +04:00
kmod_list_foreach ( l , list ) {
2012-01-10 04:34:15 +04:00
struct kmod_module * mod = kmod_module_get_module ( l ) ;
2012-02-07 03:47:00 +04:00
err = kmod_module_probe_insert_module ( mod , KMOD_PROBE_APPLY_BLACKLIST , NULL , NULL , NULL , NULL ) ;
if ( err = = KMOD_PROBE_APPLY_BLACKLIST )
2012-04-08 18:06:20 +04:00
log_debug ( " module '%s' is blacklisted \n " , kmod_module_get_name ( mod ) ) ;
2012-02-07 03:47:00 +04:00
else if ( err = = 0 )
2012-04-08 18:06:20 +04:00
log_debug ( " inserted '%s' \n " , kmod_module_get_name ( mod ) ) ;
2012-01-10 04:34:15 +04:00
else
2012-04-08 18:06:20 +04:00
log_debug ( " failed to insert '%s' \n " , kmod_module_get_name ( mod ) ) ;
2012-01-10 04:34:15 +04:00
kmod_module_unref ( mod ) ;
}
kmod_module_unref_list ( list ) ;
return err ;
2011-12-23 21:19:18 +04:00
}
2011-12-25 21:59:42 +04:00
static void udev_kmod_log ( void * data , int priority , const char * file , int line ,
2012-01-10 04:34:15 +04:00
const char * fn , const char * format , va_list args )
2011-12-25 21:59:42 +04:00
{
2012-01-10 04:34:15 +04:00
udev_main_log ( data , priority , file , line , fn , format , args ) ;
2011-12-25 21:59:42 +04:00
}
2011-12-27 06:49:43 +04:00
/* needs to re-instantiate the context after a reload */
2011-12-23 05:02:44 +04:00
static int builtin_kmod ( struct udev_device * dev , int argc , char * argv [ ] , bool test )
2011-12-22 01:30:48 +04:00
{
2012-01-10 04:34:15 +04:00
struct udev * udev = udev_device_get_udev ( dev ) ;
int i ;
if ( ! ctx ) {
ctx = kmod_new ( NULL , NULL ) ;
if ( ! ctx )
return - ENOMEM ;
2012-04-08 18:06:20 +04:00
log_debug ( " load module index \n " ) ;
2012-01-10 04:34:15 +04:00
kmod_set_log_fn ( ctx , udev_kmod_log , udev ) ;
kmod_load_resources ( ctx ) ;
}
if ( argc < 3 | | strcmp ( argv [ 1 ] , " load " ) ) {
2012-04-08 18:06:20 +04:00
log_error ( " expect: %s load <module> \n " , argv [ 0 ] ) ;
2012-01-10 04:34:15 +04:00
return EXIT_FAILURE ;
}
for ( i = 2 ; argv [ i ] ; i + + ) {
2012-04-08 18:06:20 +04:00
log_debug ( " execute '%s' '%s' \n " , argv [ 1 ] , argv [ i ] ) ;
2012-01-10 04:34:15 +04:00
load_module ( udev , argv [ i ] ) ;
}
return EXIT_SUCCESS ;
2011-12-22 01:30:48 +04:00
}
2011-12-27 06:49:43 +04:00
/* called at udev startup */
2011-12-24 20:58:52 +04:00
static int builtin_kmod_init ( struct udev * udev )
2011-12-22 02:10:56 +04:00
{
2012-01-10 04:34:15 +04:00
if ( ctx )
return 0 ;
2011-12-25 19:37:15 +04:00
2012-01-10 04:34:15 +04:00
ctx = kmod_new ( NULL , NULL ) ;
if ( ! ctx )
return - ENOMEM ;
2011-12-23 21:19:18 +04:00
2012-04-08 18:06:20 +04:00
log_debug ( " load module index \n " ) ;
2012-01-10 04:34:15 +04:00
kmod_set_log_fn ( ctx , udev_kmod_log , udev ) ;
kmod_load_resources ( ctx ) ;
return 0 ;
2011-12-22 02:10:56 +04:00
}
2011-12-27 06:49:43 +04:00
/* called on udev shutdown and reload request */
static void builtin_kmod_exit ( struct udev * udev )
2011-12-22 02:10:56 +04:00
{
2012-04-08 18:06:20 +04:00
log_debug ( " unload module index \n " ) ;
2012-01-10 04:34:15 +04:00
ctx = kmod_unref ( ctx ) ;
2011-12-27 06:49:43 +04:00
}
/* called every couple of seconds during event activity; 'true' if config has changed */
static bool builtin_kmod_validate ( struct udev * udev )
{
2012-04-08 18:06:20 +04:00
log_debug ( " validate module index \n " ) ;
2012-01-10 04:34:15 +04:00
if ( kmod_validate_resources ( ctx ) ! = KMOD_RESOURCES_OK )
return true ;
return false ;
2011-12-22 02:10:56 +04:00
}
2011-12-22 01:30:48 +04:00
const struct udev_builtin udev_builtin_kmod = {
2012-01-10 04:34:15 +04:00
. name = " kmod " ,
. cmd = builtin_kmod ,
. init = builtin_kmod_init ,
. exit = builtin_kmod_exit ,
. validate = builtin_kmod_validate ,
. help = " kernel module loader " ,
. run_once = false ,
2011-12-22 01:30:48 +04:00
} ;