1 /*******************************************************************************
2 this code is protected by the GNU affero GPLv3
3 author:Sylvain BERTRAND <sylvain.bertrand AT gmail dot com>
4 *******************************************************************************/
7 #include <ulinux/compiler_types.h>
8 #include <ulinux/types.h>
9 #include <ulinux/sysc.h>
11 #include <ulinux/mmap.h>
12 #include <ulinux/error.h>
13 #include <ulinux/file.h>
14 #include <ulinux/fs.h>
15 #include <ulinux/dirent.h>
16 #include <ulinux/utils/mem.h>
17 #include <ulinux/utils/ascii/string/string.h>
20 #include "ulinux_namespace.h"
21 #include "static_modules.h"
23 static struct kmod_ctx
*kmod_ctx
;
25 static u8
is_current(u8
*n
)
27 if(n
[0]=='.'&&n
[1]==0) return 1;
31 static u8
is_parent(u8
*n
)
33 if(n
[0]=='.'&&n
[1]=='.'&&n
[2]==0) return 1;
37 /*that for some kmod stuff*/
39 static void driver_modules_probe(u8
*modalias
)
43 struct kmod_list
*list
;
44 struct kmod_list
*list_entry
;
47 /*shutdown libkmod output since we expect a lot of error/warning messages*/
48 log_prio
=kmod_get_log_priority(kmod_ctx
);
49 kmod_set_log_priority(kmod_ctx
,0);
50 r
=kmod_module_new_from_lookup(kmod_ctx
,(const char*)modalias
,&list
);
51 kmod_set_log_priority(kmod_ctx
,log_prio
);
52 if(r
<0) return;/*we may not have any alias for this hardware, skipping*/
54 log_prio
=kmod_get_log_priority(kmod_ctx
);
56 kmod_set_log_priority(kmod_ctx
,0);
57 kmod_list_foreach(list_entry
,list
){
58 struct kmod_module
*m
;
60 m
=kmod_module_get_module(list_entry
);
61 /*try to probe the driver module, may not be there, keep going in any case*/
62 kmod_module_probe_insert_module(m
,KMOD_PROBE_IGNORE_COMMAND
,0,0,0,0);
65 kmod_set_log_priority(kmod_ctx
,log_prio
);
66 kmod_module_unref_list(list
);
69 #define MODALIAS_SZ_MAX PAGE_SZ/*sysfs attributes are of page sz*/
70 static void modalias_process(i parent_fd
)
74 u8 modalias
[MODALIAS_SZ_MAX
];
77 fd
=(i
)ul_openat(parent_fd
,"modalias",RDONLY
|NONBLOCK
);
81 OUT("WARNING(%d):unable to open modalias, skipping\n",fd
);
85 /*the size of a page size reported by the sysfs filesystem is not revelant
89 r
=read(fd
,modalias
,MODALIAS_SZ_MAX
);
90 if(r
!=-EINTR
&&r
!=-EAGAIN
) break;
93 OUT("ERROR(%ld):unable to read modalias file\n",r
);
97 modalias
[r
-1]=0;/*replace the modalias \n terminating char with 0*/
99 driver_modules_probe(modalias
);
108 #define MODALIAS_FOUND 1
109 #define MODALIAS_MISSING 0
110 static u8
modalias_search(u8
*dirents
,l ds_sz
)
113 u8 r
=MODALIAS_MISSING
;
119 if(d_u8_idx
>=ds_sz
) break;
121 d
=(struct dirent64
*)(dirents
+d_u8_idx
);
123 cmp
=strcmp("modalias",d
->name
);
129 d_u8_idx
+=d
->rec_len
;
134 /*forward declaration*/
135 static void sys_devices_parse(i parent_fd
);
136 static void real_subdirs_recurse(i parent_fd
,u8
*dirents
,l ds_sz
)
143 if(d_u8_idx
>=ds_sz
) break;
145 d
=(struct dirent64
*)(dirents
+d_u8_idx
);
147 if(d
->type
==DT_DIR
&&!is_current(d
->name
)&&!is_parent(d
->name
)){
151 subdir_fd
=(i
)ul_openat(parent_fd
,d
->name
,RDONLY
|NONBLOCK
);
152 if(subdir_fd
!=-EINTR
) break;
155 OUT("WARNING(%d):unable to open subdir:%s:skipping\n",subdir_fd
,
158 sys_devices_parse(subdir_fd
);
167 d_u8_idx
+=d
->rec_len
;
171 #define DIRENTS_BUF_SZ 8192
173 The dentry type is supported by sysfs. Top-down parsing, we load the tree-upper
174 driver modules first.
176 static void sys_devices_parse(i parent_fd
)
178 u8 dirents
[DIRENTS_BUF_SZ
];
182 ds_sz
=getdents64(parent_fd
,dirents
,DIRENTS_BUF_SZ
);
184 OUT("ERROR(%ld):getdents error\n",ds_sz
);
188 if(!ds_sz
) return;/*no dirents*/
190 have_modalias
=modalias_search(dirents
,ds_sz
);
192 if(have_modalias
==MODALIAS_FOUND
) modalias_process(parent_fd
);
194 real_subdirs_recurse(parent_fd
,dirents
,ds_sz
);
197 void modules_probe_name(u8
*name
)
200 struct kmod_module
*m
;
202 r
=kmod_module_new_from_name(kmod_ctx
,(const char*)name
,&m
);
205 OUT("ERROR(%d):unable to create a module description for %s, skipping\n",
210 r
=kmod_module_probe_insert_module(m
,KMOD_PROBE_IGNORE_COMMAND
,0,0,0,0);
212 OUT("ERROR(%d):unable to probe module %s, skipping\n",r
,name
);
217 kmod_module_unref(m
);
220 /*probe upper layer disk modules and user extra modules*/
221 void modules_probe_static(void)
225 m_name
=&static_modules
[0];
227 if(*m_name
==0) break;
229 modules_probe_name(*m_name
);
235 void modules_setup(void)
237 kmod_ctx
=kmod_new(0,0);
239 OUT("ERROR:unable to init libkmod\n");
244 void modules_cleanup(void)
246 kmod_unref(kmod_ctx
);
250 void modules_probe_drivers(void)
255 sys_devices_fd
=(i
)open("/sys/devices",RDONLY
|NONBLOCK
);
256 if(sys_devices_fd
!=-EINTR
) break;
258 if(ISERR(sys_devices_fd
)){
259 OUT("ERROR(%d):unable to open /sys/devices dir\n",sys_devices_fd
);
263 sys_devices_parse(sys_devices_fd
);
264 close(sys_devices_fd
);