On Tue, Apr 13, 2004 at 06:12:56PM +0200, Bastian Blank wrote: > The attached patch inplements 2.6 support in busybox insmod. Please test > them. I merged depmod. Bastian -- I object to intellect without discipline; I object to power without constructive purpose. -- Spock, "The Squire of Gothos", stardate 2124.5
Index: modutils/lsmod.c
===================================================================
--- modutils/lsmod.c (revision 290)
+++ modutils/lsmod.c (working copy)
@@ -38,16 +38,10 @@
#include <sys/file.h>
#include "busybox.h"
+#include "obj/module.h"
-#ifndef CONFIG_FEATURE_CHECK_TAINTED_MODULE
-static inline void check_tainted(void) { printf("\n"); }
-#else
-#define TAINT_FILENAME "/proc/sys/kernel/tainted"
-#define TAINT_PROPRIETORY_MODULE (1<<0)
-#define TAINT_FORCED_MODULE (1<<1)
-#define TAINT_UNSAFE_SMP (1<<2)
-
-static void check_tainted(void)
+#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+static inline void check_tainted(void)
{
int tainted;
FILE *f;
@@ -67,108 +61,84 @@
printf(" Not tainted\n");
}
}
+#else
+static inline void check_tainted(void)
+{
+ printf("\n");
+}
#endif
-#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
-
-struct module_info
+static inline int lsmod_query(void)
{
- unsigned long addr;
- unsigned long size;
- unsigned long flags;
- long usecount;
-};
+ struct module_info info;
+ char *module_names, *mn, *deps, *dn;
+ size_t bufsize, depsize, nmod, count, i, j;
+ module_names = xmalloc(bufsize = 256);
+ if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize, &nmod)) {
+ bb_perror_msg_and_die("QM_MODULES");
+ }
-int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
+ deps = xmalloc(depsize = 256);
-/* Values for query_module's which. */
-static const int QM_MODULES = 1;
-static const int QM_DEPS = 2;
-static const int QM_REFS = 3;
-static const int QM_SYMBOLS = 4;
-static const int QM_INFO = 5;
+ for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
+ if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
+ if (errno == ENOENT) {
+ /* The module was removed out from underneath us. */
+ continue;
+ }
+ /* else choke */
+ bb_perror_msg_and_die("module %s: QM_INFO", mn);
+ }
+ if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) {
+ if (errno == ENOENT) {
+ /* The module was removed out from underneath us. */
+ continue;
+ }
+ bb_perror_msg_and_die("module %s: QM_REFS", mn);
+ }
+ printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
+ if (info.flags & NEW_MOD_DELETED)
+ printf(" (deleted)");
+ else if (info.flags & NEW_MOD_INITIALIZING)
+ printf(" (initializing)");
+ else if (!(info.flags & NEW_MOD_RUNNING))
+ printf(" (uninitialized)");
+ else {
+ if (info.flags & NEW_MOD_AUTOCLEAN)
+ printf(" (autoclean) ");
+ if (!(info.flags & NEW_MOD_USED_ONCE))
+ printf(" (unused)");
+ }
+ if (count) printf(" [");
+ for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
+ printf("%s%s", dn, (j==count-1)? "":" ");
+ }
+ if (count) printf("]");
-/* Bits of module.flags. */
-static const int NEW_MOD_RUNNING = 1;
-static const int NEW_MOD_DELETED = 2;
-static const int NEW_MOD_AUTOCLEAN = 4;
-static const int NEW_MOD_VISITED = 8;
-static const int NEW_MOD_USED_ONCE = 16;
-static const int NEW_MOD_INITIALIZING = 64;
+ printf("\n");
+ }
-extern int lsmod_main(int argc, char **argv)
-{
- struct module_info info;
- char *module_names, *mn, *deps, *dn;
- size_t bufsize, depsize, nmod, count, i, j;
-
- module_names = xmalloc(bufsize = 256);
- if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize,
- &nmod)) {
- bb_perror_msg_and_die("QM_MODULES");
- }
-
- deps = xmalloc(depsize = 256);
- printf("Module Size Used by");
- check_tainted();
-
- for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
- if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
- if (errno == ENOENT) {
- /* The module was removed out from underneath us. */
- continue;
- }
- /* else choke */
- bb_perror_msg_and_die("module %s: QM_INFO", mn);
- }
- if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) {
- if (errno == ENOENT) {
- /* The module was removed out from underneath us. */
- continue;
- }
- bb_perror_msg_and_die("module %s: QM_REFS", mn);
- }
- printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
- if (info.flags & NEW_MOD_DELETED)
- printf(" (deleted)");
- else if (info.flags & NEW_MOD_INITIALIZING)
- printf(" (initializing)");
- else if (!(info.flags & NEW_MOD_RUNNING))
- printf(" (uninitialized)");
- else {
- if (info.flags & NEW_MOD_AUTOCLEAN)
- printf(" (autoclean) ");
- if (!(info.flags & NEW_MOD_USED_ONCE))
- printf(" (unused)");
- }
- if (count) printf(" [");
- for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
- printf("%s%s", dn, (j==count-1)? "":" ");
- }
- if (count) printf("]");
-
- printf("\n");
- }
-
-#ifdef CONFIG_FEATURE_CLEAN_UP
- free(module_names);
-#endif
-
- return( 0);
+ return( 0);
}
-#else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
-
extern int lsmod_main(int argc, char **argv)
{
printf("Module Size Used by");
check_tainted();
+#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+ if (getuid() != 0)
+ {
+#endif
if (bb_xprint_file_by_name("/proc/modules") < 0) {
return 0;
}
return 1;
+#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+ }
+ return lsmod_query();
+#endif
}
-#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
+
Index: modutils/modutils.c
===================================================================
--- modutils/modutils.c (revision 0)
+++ modutils/modutils.c (revision 0)
@@ -0,0 +1,33 @@
+#include <stdlib.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include "modutils.h"
+
+/* Get the kernel version in the canonical integer form. */
+
+int get_kernel_version(char str[STRVERSIONLEN])
+{
+ char *p, *q;
+ int a, b, c;
+ struct utsname uts_info;
+
+ if (uname (&uts_info))
+ return -1;
+
+ strncpy(str, uts_info.release, STRVERSIONLEN-1);
+ str[STRVERSIONLEN-1] = '\0';
+ p = str;
+
+ a = strtoul(p, &p, 10);
+ if (*p != '.')
+ return -1;
+ b = strtoul(p + 1, &p, 10);
+ if (*p != '.')
+ return -1;
+ c = strtoul(p + 1, &q, 10);
+ if (p + 1 == q)
+ return -1;
+
+ return a << 16 | b << 8 | c;
+}
+
Index: modutils/Makefile.in
===================================================================
--- modutils/Makefile.in (revision 290)
+++ modutils/Makefile.in (working copy)
@@ -26,7 +26,7 @@
CFLAGS_MODUTILS += -DELF_MACHINE_H='"elf_$(host_cpu_modutils).h"'
CFLAGS_MODUTILS += -DELF_MACHINE_H_BIARCH='"elf_$(host_cpu_modutils_biarch).h"'
-MODUTILS-y:=
+MODUTILS-y := modutils.o
MODUTILS-$(CONFIG_INSMOD) += insmod.o
MODUTILS-$(CONFIG_LSMOD) += lsmod.o
MODUTILS-$(CONFIG_MODPROBE) += modprobe.o
Index: modutils/modutils.h
===================================================================
--- modutils/modutils.h (revision 290)
+++ modutils/modutils.h (working copy)
@@ -1,3 +1,6 @@
-#define _PATH_MODULES "/lib/modules"
+#define _PATH_MODULES "/lib/modules"
+#define MODULE_DIR "/lib/modules"
+#define STRVERSIONLEN 32
int check_module (const char *mod);
+int get_kernel_version(char str[STRVERSIONLEN]);
Index: modutils/modprobe.c
===================================================================
--- modutils/modprobe.c (revision 290)
+++ modutils/modprobe.c (working copy)
@@ -21,7 +21,6 @@
*
*/
-#include <sys/utsname.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
@@ -31,8 +30,8 @@
#include <fcntl.h>
#include "busybox.h"
+#include "modutils.h"
-
struct dep_t {
char * m_module;
char * m_options;
@@ -58,6 +57,7 @@
static struct dep_t *depend;
static int autoclean, show_only, quiet, do_syslog, verbose;
static int k_version;
+char k_strversion[STRVERSIONLEN];
int parse_tag_value ( char *buffer, char **ptag, char **pvalue )
{
@@ -112,33 +112,22 @@
static struct dep_t *build_dep ( void )
{
int fd;
- struct utsname un;
struct dep_t *first = 0;
struct dep_t *current = 0;
char buffer[256];
char *filename = buffer;
int continuation_line = 0;
- k_version = 0;
- if ( uname ( &un ))
- return 0;
+ k_version = get_kernel_version(k_strversion);
- // check for buffer overflow in following code
- if ( bb_strlen ( un.release ) > ( sizeof( buffer ) - 64 )) {
- return 0;
- }
- if (un.release[0] == '2') {
- k_version = un.release[2] - '0';
- }
-
- strcpy ( filename, "/lib/modules/" );
- strcat ( filename, un.release );
+ strcpy ( filename, _PATH_MODULES );
+ strcat ( filename, k_strversion );
strcat ( filename, "/modules.dep" );
if (( fd = open ( filename, O_RDONLY )) < 0 ) {
/* Ok, that didn't work. Fall back to looking in /lib/modules */
- if (( fd = open ( "/lib/modules/modules.dep", O_RDONLY )) < 0 ) {
+ if (( fd = open ( _PATH_MODULES "/modules.dep", O_RDONLY )) < 0 ) {
return 0;
}
}
Index: modutils/depmod.c
===================================================================
--- modutils/depmod.c (revision 290)
+++ modutils/depmod.c (working copy)
@@ -37,27 +37,22 @@
#include <syslog.h>
#include <limits.h>
#include <elf.h>
-#include <sys/utsname.h>
#include "busybox.h"
#include "obj/module.h"
#include "obj/obj.h"
#include "obj/modstat.h"
+#include "modutils.h"
+static int k_version = 0;
+static char k_strversion[STRVERSIONLEN];
+
+#if defined(CONFIG_FEATURE_2_2_MODULES) || defined(CONFIG_FEATURE_2_4_MODULES)
+
#define ALLOC_MODULE 5000 /* Number of modules we can handle... */
#define ALLOC_SYM 10000 /* Number of symbols allocated per chunk */
#define MAX_MAP_SYM 100000 /* Maximum number of symbols in map */
-#ifndef __u32
-#define __u32 u_int32_t
-#endif
-#ifndef __u16
-#define __u16 u_int16_t
-#endif
-#ifndef __u8
-#define __u8 u_int8_t
-#endif
-
typedef struct SYMBOL{
struct SYMBOL *next; /* List connected via hashing */
struct MODULE *module; /* Module declaring this symbol */
@@ -781,6 +776,12 @@
return (FALSE);
}
+#endif /* CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES */
+
+#ifdef CONFIG_FEATURE_2_6_MODULES
+int depmod_main_2_6(int argc, char *argv[], int all, int verbose, int doing_stdout, const char *system_map, const char *base_dir, const char *module_dir);
+#endif /* CONFIG_FEATURE_2_6_MODULES */
+
extern int depmod_main(int argc, char **argv)
{
int ret = -1;
@@ -793,7 +794,6 @@
char *base_dir = "";
char *module_dir = NULL;
int ignore_suffix = 0; /* Ignore genksyms suffix on resolve? */
- struct utsname myuname;
while ((o = getopt(argc, argv, "aAb:C:eF:hnqsvVru")) != EOF) {
switch (o) {
@@ -803,27 +803,26 @@
stdmode = 1; /* Probe standard directory */
break; /* using the config file */
- case 'e':
- showerror = 1;
- break;
-
case 'b':
base_dir = optarg;
break;
- case '?':
- case 'h':
- return 0;
- break;
-
case 'C':
conf_file = optarg;
break;
+ case 'e':
+ showerror = 1;
+ break;
+
case 'F':
file_syms = optarg;
break;
+ case 'h':
+ return 0;
+ break;
+
case 'n':
nflag = 1;
break;
@@ -844,19 +843,20 @@
if (err) {
bb_error_msg("Aborting");
- return -1;
+ return EXIT_FAILURE;
}
- /* else */
argc -= optind;
argv += optind;
ignore_suffix = file_syms != NULL;
- if (uname(&myuname) == 0) {
+ k_version = get_kernel_version(k_strversion);
+
+ if (k_version != -1) {
char tmdn[FILENAME_MAX];
char real_module_dir[FILENAME_MAX];
- snprintf(tmdn, FILENAME_MAX, "%s/lib/modules/%s/", base_dir, myuname.release);
+ snprintf(tmdn, FILENAME_MAX, "%s" _PATH_MODULES "/%s/", base_dir, k_strversion);
if (realpath (tmdn, real_module_dir) == NULL)
module_dir = tmdn;
else
@@ -865,22 +865,36 @@
else
return EXIT_FAILURE;
- if (stdmode || argc == 0) {
- if ((ret = addksyms(file_syms)) != -1) {
- recursive_action(module_dir, TRUE, FALSE, FALSE,
- add_module, 0, NULL);
-
- resolve();
- ret = prtdepend(base_dir, module_dir, nflag) || ret;
- }
- } else {
- /* not stdmode */
- if ((ret = addksyms(file_syms)) != -1) {
- for (; argc > 0 && ret != -1; ++argv, --argc)
- loadobj(*argv, ignore_suffix);
- resolve();
- ret = prtdepend(base_dir, module_dir, 1) || ret;
- }
+ if (k_version > 0x20500)
+#ifdef CONFIG_FEATURE_2_6_MODULES
+ ret = depmod_main_2_6(argc, argv, stdmode || argc == 0, !quiet, nflag, file_syms, base_dir, module_dir);
+#else
+ return EXIT_FAILURE;
+#endif
+ else
+ {
+#if defined(CONFIG_FEATURE_2_2_MODULES) || defined(CONFIG_FEATURE_2_4_MODULES)
+ if (stdmode || argc == 0)
+ {
+ if ((ret = addksyms(file_syms)) != -1) {
+ recursive_action(module_dir, TRUE, FALSE, FALSE, add_module, 0, NULL);
+ resolve();
+ ret = prtdepend(base_dir, module_dir, nflag) || ret;
+ }
+ }
+ else
+ {
+ /* not stdmode */
+ if ((ret = addksyms(file_syms)) != -1) {
+ for (; argc > 0 && ret != -1; ++argv, --argc)
+ loadobj(*argv, ignore_suffix);
+ resolve();
+ ret = prtdepend(base_dir, module_dir, 1) || ret;
+ }
+ }
+#else
+ return EXIT_FAILURE;
+#endif /* CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES */
}
return ret;
Index: modutils/Config.in
===================================================================
--- modutils/Config.in (revision 290)
+++ modutils/Config.in (working copy)
@@ -6,22 +6,28 @@
menu "Linux Module Utilities"
if 0
+config CONFIG_MODUTILS
+ bool "modutils"
+ default n
config CONFIG_MODUTILS_OBJ
bool "modutils"
default n
+ select CONFIG_MODUTILS
+config CONFIG_MODUTILS_OBJ_2_6
+ bool "modutils"
+ default n
+ select CONFIG_MODUTILS
endif
config CONFIG_DEPMOD
bool "depmod"
default n
- select CONFIG_MODUTILS_OBJ
help
Please submit a patch to add help text for this item.
config CONFIG_INSMOD
bool "insmod"
default n
- select CONFIG_MODUTILS_OBJ
help
insmod is used to load specified modules in the running kernel.
@@ -29,6 +35,7 @@
bool " Support older (pre 2.1) Linux kernels"
default n
depends on CONFIG_INSMOD
+ select CONFIG_MODUTILS_OBJ
help
Provide insmod support for older (pre 2.1) Linux kernels.
@@ -36,17 +43,17 @@
bool " Support version 2.1.x to 2.4.x Linux kernels"
default y
depends on CONFIG_INSMOD
+ select CONFIG_MODUTILS_OBJ
help
Support module loading for newer (post 2.1) Linux kernels.
-if 0
config CONFIG_FEATURE_2_6_MODULES
bool " Support version 2.6.x Linux kernels"
default n
depends on CONFIG_INSMOD
+ select CONFIG_MODUTILS_OBJ_2_6
help
- Support module loading for newer (post 2.1) Linux kernels.
-endif
+ Support module loading for post 2.6 Linux kernels.
config CONFIG_FEATURE_INSMOD_VERSION_CHECKING
bool " Module version checking"
@@ -94,7 +101,7 @@
lsmod is used to display a list of loaded modules.
config CONFIG_FEATURE_QUERY_MODULE_INTERFACE
- bool " Support lsmod query_module interface (add 638 bytes)"
+ bool " Support lsmod query_module interface"
default y
depends on CONFIG_LSMOD && ( CONFIG_FEATURE_2_4_MODULES || CONFIG_FEATURE_2_6_MODULES )
help
Index: modutils/insmod.c
===================================================================
--- modutils/insmod.c (revision 291)
+++ modutils/insmod.c (working copy)
@@ -77,7 +77,6 @@
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
-#include <sys/utsname.h>
#include "busybox.h"
#include "modutils.h"
@@ -92,16 +91,18 @@
static int flag_quiet = 0;
static int flag_export = 1;
+static int k_version = 0;
+static char k_strversion[STRVERSIONLEN];
+
static int n_ext_modules_used;
static int m_has_modinfo;
static int gplonly_seen;
-char *m_filename;
-char *m_fullName;
+static char *m_filename;
+static char *m_fullName;
/*======================================================================*/
-
static int check_module_name_match(const char *filename, struct stat *statbuf,
void *userdata)
{
@@ -127,10 +128,8 @@
/* Conditionally add the symbols from the given symbol set to the
new module. */
-static int
-add_symbols_from(
- struct obj_file *f,
- int idx, struct module_symbol *syms, size_t nsyms, int gpl)
+static int add_symbols_from(struct obj_file *f, int idx,
+ struct module_symbol *syms, size_t nsyms, int gpl)
{
struct module_symbol *s;
size_t i;
@@ -160,6 +159,7 @@
}
sym = obj_find_symbol(f, (char *) s->name);
+
if (sym && ELFW(ST_BIND) (sym->info) != STB_LOCAL) {
sym = obj_add_symbol(f, (char *) s->name, -1,
ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
@@ -222,159 +222,11 @@
}
+#ifdef CONFIG_FEATURE_2_2_MODULES
+
/*======================================================================*/
/* Functions relating to module loading in pre 2.1 kernels. */
- static int
-old_process_module_arguments(struct obj_file *f, int argc, char **argv)
-{
- while (argc > 0) {
- char *p, *q;
- struct obj_symbol *sym;
- int *loc;
-
- p = *argv;
- if ((q = strchr(p, '=')) == NULL) {
- argc--;
- continue;
- }
- *q++ = '\0';
-
- sym = obj_find_symbol(f, p);
-
- /* Also check that the parameter was not resolved from the kernel. */
- if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
- bb_error_msg("symbol for parameter %s not found", p);
- return 0;
- }
-
- loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
-
- /* Do C quoting if we begin with a ". */
- if (*q == '"') {
- char *r, *str;
-
- str = alloca(strlen(q));
- for (r = str, q++; *q != '"'; ++q, ++r) {
- if (*q == '\0') {
- bb_error_msg("improperly terminated string argument for %s", p);
- return 0;
- } else if (*q == '\\')
- switch (*++q) {
- case 'a':
- *r = '\a';
- break;
- case 'b':
- *r = '\b';
- break;
- case 'e':
- *r = '\033';
- break;
- case 'f':
- *r = '\f';
- break;
- case 'n':
- *r = '\n';
- break;
- case 'r':
- *r = '\r';
- break;
- case 't':
- *r = '\t';
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- int c = *q - '0';
- if (q[1] >= '0' && q[1] <= '7') {
- c = (c * 8) + *++q - '0';
- if (q[1] >= '0' && q[1] <= '7')
- c = (c * 8) + *++q - '0';
- }
- *r = c;
- }
- break;
-
- default:
- *r = *q;
- break;
- } else
- *r = *q;
- }
- *r = '\0';
- obj_string_patch(f, sym->secidx, sym->value, str);
- } else if (*q >= '0' && *q <= '9') {
- do
- *loc++ = strtoul(q, &q, 0);
- while (*q++ == ',');
- } else {
- char *contents = f->sections[sym->secidx]->contents;
- char *myloc = contents + sym->value;
- char *r; /* To search for commas */
-
- /* Break the string with comas */
- while ((r = strchr(q, ',')) != (char *) NULL) {
- *r++ = '\0';
- obj_string_patch(f, sym->secidx, myloc - contents, q);
- myloc += sizeof(char *);
- q = r;
- }
-
- /* last part */
- obj_string_patch(f, sym->secidx, myloc - contents, q);
- }
-
- argc--, argv++;
- }
-
- return 1;
-}
-
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
-static int old_is_module_checksummed(struct obj_file *f)
-{
- return obj_find_symbol(f, "Using_Versions") != NULL;
-}
-/* Get the module's kernel version in the canonical integer form. */
-
- static int
-old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
-{
- struct obj_symbol *sym;
- char *p, *q;
- int a, b, c;
-
- sym = obj_find_symbol(f, "kernel_version");
- if (sym == NULL)
- return -1;
-
- p = f->sections[sym->secidx]->contents + sym->value;
- safe_strncpy(str, p, STRVERSIONLEN);
-
- a = strtoul(p, &p, 10);
- if (*p != '.')
- return -1;
- b = strtoul(p + 1, &p, 10);
- if (*p != '.')
- return -1;
- c = strtoul(p + 1, &q, 10);
- if (p + 1 == q)
- return -1;
-
- return a << 16 | b << 8 | c;
-}
-
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
-
-#ifdef CONFIG_FEATURE_2_2_MODULES
-
/* Fetch all the symbols and divvy them up as appropriate for the modules. */
static int old_get_kernel_symbols(const char *m_name)
@@ -449,19 +301,6 @@
return 1;
}
-/* Return the kernel symbol checksum version, or zero if not used. */
-
-static int old_is_kernel_checksummed(void)
-{
- /* Using_Versions is the first symbol. */
- if (nksyms > 0
- && strcmp((char *) ksyms[0].name,
- "Using_Versions") == 0) return ksyms[0].value;
- else
- return 0;
-}
-
-
static int old_create_mod_use_count(struct obj_file *f)
{
struct obj_section *sec;
@@ -585,292 +424,11 @@
#endif /* CONFIG_FEATURE_2_2_MODULES */
+#ifdef CONFIG_FEATURE_2_4_MODULES
-
/*======================================================================*/
/* Functions relating to module loading after 2.1.18. */
- static int
-new_process_module_arguments(struct obj_file *f, int argc, char **argv)
-{
- while (argc > 0) {
- char *p, *q, *key, *sym_name;
- struct obj_symbol *sym;
- char *contents, *loc;
- int min, max, n;
-
- p = *argv;
- if ((q = strchr(p, '=')) == NULL) {
- argc--;
- continue;
- }
-
- key = alloca(q - p + 6);
- memcpy(key, "parm_", 5);
- memcpy(key + 5, p, q - p);
- key[q - p + 5] = 0;
-
- p = get_modinfo_value(f, key);
- key += 5;
- if (p == NULL) {
- bb_error_msg("invalid parameter %s", key);
- return 0;
- }
-
-#ifdef SYMBOL_PREFIX
- sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
- strcpy (sym_name, SYMBOL_PREFIX);
- strcat (sym_name, key);
-#else
- sym_name = key;
-#endif
- sym = obj_find_symbol(f, sym_name);
-
- /* Also check that the parameter was not resolved from the kernel. */
- if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
- bb_error_msg("symbol for parameter %s not found", key);
- return 0;
- }
-
- if (isdigit(*p)) {
- min = strtoul(p, &p, 10);
- if (*p == '-')
- max = strtoul(p + 1, &p, 10);
- else
- max = min;
- } else
- min = max = 1;
-
- contents = f->sections[sym->secidx]->contents;
- loc = contents + sym->value;
- n = (*++q != '\0');
-
- while (1) {
- if ((*p == 's') || (*p == 'c')) {
- char *str;
-
- /* Do C quoting if we begin with a ", else slurp the lot. */
- if (*q == '"') {
- char *r;
-
- str = alloca(strlen(q));
- for (r = str, q++; *q != '"'; ++q, ++r) {
- if (*q == '\0') {
- bb_error_msg("improperly terminated string argument for %s",
- key);
- return 0;
- } else if (*q == '\\')
- switch (*++q) {
- case 'a':
- *r = '\a';
- break;
- case 'b':
- *r = '\b';
- break;
- case 'e':
- *r = '\033';
- break;
- case 'f':
- *r = '\f';
- break;
- case 'n':
- *r = '\n';
- break;
- case 'r':
- *r = '\r';
- break;
- case 't':
- *r = '\t';
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- int c = *q - '0';
- if (q[1] >= '0' && q[1] <= '7') {
- c = (c * 8) + *++q - '0';
- if (q[1] >= '0' && q[1] <= '7')
- c = (c * 8) + *++q - '0';
- }
- *r = c;
- }
- break;
-
- default:
- *r = *q;
- break;
- } else
- *r = *q;
- }
- *r = '\0';
- ++q;
- } else {
- char *r;
-
- /* In this case, the string is not quoted. We will break
- it using the coma (like for ints). If the user wants to
- include comas in a string, he just has to quote it */
-
- /* Search the next coma */
- r = strchr(q, ',');
-
- /* Found ? */
- if (r != (char *) NULL) {
- /* Recopy the current field */
- str = alloca(r - q + 1);
- memcpy(str, q, r - q);
-
- /* I don't know if it is useful, as the previous case
- doesn't nul terminate the string ??? */
- str[r - q] = '\0';
-
- /* Keep next fields */
- q = r;
- } else {
- /* last string */
- str = q;
- q = "";
- }
- }
-
- if (*p == 's') {
- /* Normal string */
- obj_string_patch(f, sym->secidx, loc - contents, str);
- loc += tgt_sizeof_char_p;
- } else {
- /* Array of chars (in fact, matrix !) */
- unsigned long charssize; /* size of each member */
-
- /* Get the size of each member */
- /* Probably we should do that outside the loop ? */
- if (!isdigit(*(p + 1))) {
- bb_error_msg("parameter type 'c' for %s must be followed by"
- " the maximum size", key);
- return 0;
- }
- charssize = strtoul(p + 1, (char **) NULL, 10);
-
- /* Check length */
- if (strlen(str) >= charssize) {
- bb_error_msg("string too long for %s (max %ld)", key,
- charssize - 1);
- return 0;
- }
-
- /* Copy to location */
- strcpy((char *) loc, str);
- loc += charssize;
- }
- } else {
- long v = strtoul(q, &q, 0);
- switch (*p) {
- case 'b':
- *loc++ = v;
- break;
- case 'h':
- *(short *) loc = v;
- loc += tgt_sizeof_short;
- break;
- case 'i':
- *(int *) loc = v;
- loc += tgt_sizeof_int;
- break;
- case 'l':
- *(long *) loc = v;
- loc += tgt_sizeof_long;
- break;
-
- default:
- bb_error_msg("unknown parameter type '%c' for %s", *p, key);
- return 0;
- }
- }
-
-retry_end_of_value:
- switch (*q) {
- case '\0':
- goto end_of_arg;
-
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- ++q;
- goto retry_end_of_value;
-
- case ',':
- if (++n > max) {
- bb_error_msg("too many values for %s (max %d)", key, max);
- return 0;
- }
- ++q;
- break;
-
- default:
- bb_error_msg("invalid argument syntax for %s", key);
- return 0;
- }
- }
-
-end_of_arg:
- if (n < min) {
- bb_error_msg("too few values for %s (min %d)", key, min);
- return 0;
- }
-
- argc--, argv++;
- }
-
- return 1;
-}
-
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
-static int new_is_module_checksummed(struct obj_file *f)
-{
- const char *p = get_modinfo_value(f, "using_checksums");
- if (p)
- return atoi(p);
- else
- return 0;
-}
-
-/* Get the module's kernel version in the canonical integer form. */
-
- static int
-new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
-{
- char *p, *q;
- int a, b, c;
-
- p = get_modinfo_value(f, "kernel_version");
- if (p == NULL)
- return -1;
- safe_strncpy(str, p, STRVERSIONLEN);
-
- a = strtoul(p, &p, 10);
- if (*p != '.')
- return -1;
- b = strtoul(p + 1, &p, 10);
- if (*p != '.')
- return -1;
- c = strtoul(p + 1, &q, 10);
- if (p + 1 == q)
- return -1;
-
- return a << 16 | b << 8 | c;
-}
-
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
-
-
-#ifdef CONFIG_FEATURE_2_4_MODULES
-
/* Fetch the loaded modules, and all currently exported symbols. */
static int new_get_kernel_symbols(void)
@@ -963,23 +521,6 @@
}
-/* Return the kernel symbol checksum version, or zero if not used. */
-
-static int new_is_kernel_checksummed(void)
-{
- struct module_symbol *s;
- size_t i;
-
- /* Using_Versions is not the first symbol, but it should be in there. */
-
- for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
- if (strcmp((char *) s->name, "Using_Versions") == 0)
- return s->value;
-
- return 0;
-}
-
-
static int new_create_this_module(struct obj_file *f, const char *m_name)
{
struct obj_section *sec;
@@ -1274,29 +815,83 @@
if (fd >= 0)
close(fd);
}
-#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
-#define check_tainted_module(x, y) do { } while(0);
#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
-/* add module source, timestamp, kernel version and a symbol for the
- * start of some sections. this info is used by ksymoops to do better
- * debugging.
- */
- static int
-get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
-{
#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
- if (get_modinfo_value(f, "kernel_version") == NULL)
- return old_get_module_version(f, str);
- else
- return new_get_module_version(f, str);
-#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
- strncpy(str, "???", sizeof(str));
+/* Get the module's kernel version in the canonical integer form. */
+static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
+{
+ int a, b, c;
+ char *p, *q;
+
+ if ((p = get_modinfo_value(f, "kernel_version")) == NULL) {
+ struct obj_symbol *sym;
+
+ m_has_modinfo = 0;
+ if ((sym = obj_find_symbol(f, "kernel_version")) == NULL)
+ sym = obj_find_symbol(f, "__module_kernel_version");
+ if (sym == NULL)
+ return -1;
+ p = f->sections[sym->secidx]->contents + sym->value;
+ } else
+ m_has_modinfo = 1;
+
+ strncpy(str, p, STRVERSIONLEN-1);
+ str[STRVERSIONLEN-1] = '\0';
+ p = str;
+
+ a = strtoul(p, &p, 10);
+ if (*p != '.')
+ return -1;
+ b = strtoul(p + 1, &p, 10);
+ if (*p != '.')
+ return -1;
+ c = strtoul(p + 1, &q, 10);
+ if (p + 1 == q)
+ return -1;
+
+ return a << 16 | b << 8 | c;
+}
+#else
+static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) __attribute__((unused));
+static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
+{
return -1;
+}
#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+/* Return the kernel symbol checksum version, or zero if not used. */
+static int is_kernel_checksummed(void)
+{
+ struct module_symbol *s;
+ size_t i;
+
+ /*
+ * Using_Versions might not be the first symbol,
+ * but it should be in there.
+ */
+ for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
+ if (strcmp((char *) s->name, "Using_Versions") == 0)
+ return s->value;
+
+ return 0;
}
+static int is_module_checksummed(struct obj_file *f)
+{
+ if (m_has_modinfo) {
+ const char *p = get_modinfo_value(f, "using_checksums");
+ if (p)
+ return atoi(p);
+ else
+ return 0;
+ } else
+ return obj_find_symbol(f, "Using_Versions") != NULL;
+}
+#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
/* add module source, timestamp, kernel version and a symbol for the
* start of some sections. this info is used by ksymoops to do better
* debugging.
@@ -1371,7 +966,7 @@
new_add_ksymtab(f, sym);
}
free(absolute_filename);
-#ifdef _NOT_SUPPORTED_
+
/* record where the persistent data is going, same address as previous symbol */
if (f->persist) {
@@ -1388,7 +983,7 @@
if (use_ksymtab)
new_add_ksymtab(f, sym);
}
-#endif /* _NOT_SUPPORTED_ */
+
/* tag the desired sections if size is non-zero */
for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
@@ -1414,6 +1009,246 @@
}
#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+static int process_module_arguments(struct obj_file *f, int argc, char **argv, int required)
+{
+ for (; argc > 0; ++argv, --argc) {
+ struct obj_symbol *sym;
+ int c;
+ int min, max;
+ int n;
+ char *contents;
+ char *input;
+ char *fmt;
+ char *key;
+ char *loc;
+
+ if ((input = strchr(*argv, '=')) == NULL)
+ continue;
+
+ n = input - *argv;
+ input += 1; /* skip '=' */
+
+ key = alloca(n + 6);
+
+ if (m_has_modinfo) {
+ memcpy(key, "parm_", 5);
+ memcpy(key + 5, *argv, n);
+ key[n + 5] = '\0';
+ if ((fmt = get_modinfo_value(f, key)) == NULL) {
+ if (required || flag_verbose) {
+ bb_error_msg("Warning: ignoring %s, no such parameter in this module", *argv);
+ continue;
+ }
+ }
+ key += 5;
+
+ if (isdigit(*fmt)) {
+ min = strtoul(fmt, &fmt, 10);
+ if (*fmt == '-')
+ max = strtoul(fmt + 1, &fmt, 10);
+ else
+ max = min;
+ } else
+ min = max = 1;
+ } else { /* not m_has_modinfo */
+ memcpy(key, *argv, n);
+ key[n] = '\0';
+
+ if (isdigit(*input))
+ fmt = "i";
+ else
+ fmt = "s";
+ min = max = 0;
+ }
+
+ sym = obj_find_symbol(f, key);
+
+ /*
+ * Also check that the parameter was not
+ * resolved from the kernel.
+ */
+ if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
+ bb_error_msg("symbol for parameter %s not found", key);
+ return 0;
+ }
+
+ contents = f->sections[sym->secidx]->contents;
+ loc = contents + sym->value;
+ n = 1;
+
+ while (*input) {
+ char *str;
+
+ switch (*fmt) {
+ case 's':
+ case 'c':
+ /*
+ * Do C quoting if we begin with a ",
+ * else slurp the lot.
+ */
+ if (*input == '"') {
+ char *r;
+
+ str = alloca(strlen(input));
+ for (r = str, input++; *input != '"'; ++input, ++r) {
+ if (*input == '\0') {
+ bb_error_msg("improperly terminated string argument for %s", key);
+ return 0;
+ }
+ /* else */
+ if (*input != '\\') {
+ *r = *input;
+ continue;
+ }
+ /* else handle \ */
+ switch (*++input) {
+ case 'a': *r = '\a'; break;
+ case 'b': *r = '\b'; break;
+ case 'e': *r = '\033'; break;
+ case 'f': *r = '\f'; break;
+ case 'n': *r = '\n'; break;
+ case 'r': *r = '\r'; break;
+ case 't': *r = '\t'; break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ c = *input - '0';
+ if ('0' <= input[1] && input[1] <= '7') {
+ c = (c * 8) + *++input - '0';
+ if ('0' <= input[1] && input[1] <= '7')
+ c = (c * 8) + *++input - '0';
+ }
+ *r = c;
+ break;
+
+ default: *r = *input; break;
+ }
+ }
+ *r = '\0';
+ ++input;
+ } else {
+ /*
+ * The string is not quoted.
+ * We will break it using the comma
+ * (like for ints).
+ * If the user wants to include commas
+ * in a string, he just has to quote it
+ */
+ char *r;
+
+ /* Search the next comma */
+ if ((r = strchr(input, ',')) != NULL) {
+ /*
+ * Found a comma
+ * Recopy the current field
+ */
+ str = alloca(r - input + 1);
+ memcpy(str, input, r - input);
+ str[r - input] = '\0';
+ /* Keep next fields */
+ input = r;
+ } else {
+ /* last string */
+ str = input;
+ input = "";
+ }
+ }
+
+ if (*fmt == 's') {
+ /* Normal string */
+ obj_string_patch(f, sym->secidx, loc - contents, str);
+ loc += tgt_sizeof_char_p;
+ } else {
+ /* Array of chars (in fact, matrix !) */
+ long charssize; /* size of each member */
+
+ /* Get the size of each member */
+ /* Probably we should do that outside the loop ? */
+ if (!isdigit(*(fmt + 1))) {
+ bb_error_msg("parameter type 'c' for %s must be followed by"
+ " the maximum size", key);
+ return 0;
+ }
+ charssize = strtoul(fmt + 1, (char **) NULL, 10);
+
+ /* Check length */
+ if (strlen(str) >= charssize-1) {
+ bb_error_msg("string too long for %s (max %ld)",
+ key, charssize - 1);
+ return 0;
+ }
+ /* Copy to location */
+ strcpy((char *) loc, str); /* safe, see check above */
+ loc += charssize;
+ }
+ /*
+ * End of 's' and 'c'
+ */
+ break;
+
+ case 'b':
+ *loc++ = strtoul(input, &input, 0);
+ break;
+
+ case 'h':
+ *(short *) loc = strtoul(input, &input, 0);
+ loc += tgt_sizeof_short;
+ break;
+
+ case 'i':
+ *(int *) loc = strtoul(input, &input, 0);
+ loc += tgt_sizeof_int;
+ break;
+
+ case 'l':
+ *(long *) loc = strtoul(input, &input, 0);
+ loc += tgt_sizeof_long;
+ break;
+
+ default:
+ bb_error_msg("unknown parameter type '%c' for %s",
+ *fmt, key);
+ return 0;
+ }
+ /*
+ * end of switch (*fmt)
+ */
+
+ while (*input && isspace(*input))
+ ++input;
+ if (*input == '\0')
+ break; /* while (*input) */
+ /* else */
+
+ if (*input == ',') {
+ if (max && (++n > max)) {
+ bb_error_msg("too many values for %s (max %d)", key, max);
+ return 0;
+ }
+ ++input;
+ /* continue with while (*input) */
+ } else {
+ bb_error_msg("invalid argument syntax for %s: '%c'",
+ key, *input);
+ return 0;
+ }
+ } /* end of while (*input) */
+
+ if (min && (n < min)) {
+ bb_error_msg("too few values for %s (min %d)", key, min);
+ return 0;
+ }
+ } /* end of for (;argc > 0;) */
+
+ return 1;
+}
+
#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
static void print_load_map(struct obj_file *f)
{
@@ -1506,77 +1341,73 @@
#endif
+#if defined(CONFIG_FEATURE_2_2_MODULES) || defined (CONFIG_FEATURE_2_4_MODULES)
+static int do_2_0_and_2_4(int fp, int argc, char **argv, char *m_name);
+#endif
+#ifdef CONFIG_FEATURE_2_6_MODULES
+static int do_2_6(int fp, int argc, char **argv);
+#endif
+
extern int insmod_main( int argc, char **argv)
{
int opt;
- int k_crcs;
int len;
char *tmp, *tmp1;
- unsigned long m_size;
- ElfW(Addr) m_addr;
- struct obj_file *f;
struct stat st;
char *m_name = 0;
- int exit_status = EXIT_FAILURE;
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
- struct utsname uts_info;
- char m_strversion[STRVERSIONLEN];
- int m_version;
- int m_crcs;
-#endif
- int fp = 0;
+ int fp;
#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
int flag_print_load_map = 0;
#endif
- int gpl;
/* Parse any options */
#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
- while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0) {
+ while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
#else
- while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0) {
+ while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
#endif
- switch (opt) {
- case 'f': /* force loading */
- flag_force_load = 1;
- break;
- case 'k': /* module loaded by kerneld, auto-cleanable */
- flag_autoclean = 1;
- break;
- case 's': /* log to syslog */
- /* log to syslog -- not supported */
- /* but kernel needs this for request_module(), */
- /* as this calls: modprobe -k -s -- <module> */
- /* so silently ignore this flag */
- break;
- case 'v': /* verbose output */
- flag_verbose = 1;
- break;
- case 'q': /* silent */
- flag_quiet = 1;
- break;
- case 'x': /* do not export externs */
- flag_export = 0;
- break;
- case 'o': /* name the output module */
- free(m_name);
- m_name = bb_xstrdup(optarg);
- break;
- case 'L': /* Stub warning */
- /* This is needed for compatibility with modprobe.
- * In theory, this does locking, but we don't do
- * that. So be careful and plan your life around not
- * loading the same module 50 times concurrently. */
- break;
+ {
+ switch (opt) {
+ case 'f': /* force loading */
+ flag_force_load = 1;
+ break;
+ case 'k': /* module loaded by kerneld, auto-cleanable */
+ flag_autoclean = 1;
+ break;
+ case 's': /* log to syslog */
+ /* log to syslog -- not supported */
+ /* but kernel needs this for request_module(), */
+ /* as this calls: modprobe -k -s -- <module> */
+ /* so silently ignore this flag */
+ break;
+ case 'v': /* verbose output */
+ flag_verbose = 1;
+ break;
+ case 'q': /* silent */
+ flag_quiet = 1;
+ break;
+ case 'x': /* do not export externs */
+ flag_export = 0;
+ break;
+ case 'o': /* name the output module */
+ free(m_name);
+ m_name = bb_xstrdup(optarg);
+ break;
+ case 'L': /* Stub warning */
+ /* This is needed for compatibility with modprobe.
+ * In theory, this does locking, but we don't do
+ * that. So be careful and plan your life around not
+ * loading the same module 50 times concurrently. */
+ break;
#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
- case 'm': /* print module load map */
- flag_print_load_map = 1;
- break;
+ case 'm': /* print module load map */
+ flag_print_load_map = 1;
+ break;
#endif
- default:
- bb_show_usage();
+ default:
+ bb_show_usage();
+ }
}
- }
if (argv[optind] == NULL) {
bb_show_usage();
@@ -1587,15 +1418,24 @@
tmp = basename(tmp1);
len = strlen(tmp);
- if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
- len-=2;
+ k_version = get_kernel_version(k_strversion);
+
+#if defined(CONFIG_FEATURE_2_6_MODULES)
+ if (k_version > 0x20500 && len > 3 && tmp[len - 3] == '.' &&
+ tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
+ len-=3;
tmp[len] = '\0';
}
+ else
+#endif
+ if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
+ len-=2;
+ tmp[len] = '\0';
+ }
- bb_xasprintf(&m_fullName, "%s.o", tmp);
#if defined(CONFIG_FEATURE_2_6_MODULES)
- if (k_version > 4)
+ if (k_version > 0x20500)
bb_xasprintf(&m_fullName, "%s.ko", tmp);
else
#endif
@@ -1605,22 +1445,19 @@
m_name = tmp;
} else {
free(tmp1);
- tmp1 = 0; /* flag for free(m_name) before exit() */
}
/* Get a filedesc for the module. Check we we have a complete path */
if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
- (fp = open(argv[optind], O_RDONLY)) == 0) {
- struct utsname myuname;
-
+ (fp = open(argv[optind], O_RDONLY)) < 0) {
/* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
* but do not error out yet if we fail to find it... */
- if (uname(&myuname) == 0) {
+ if (k_version) { /* uname succeedd */
char *module_dir;
char *tmdn;
char real_module_dir[FILENAME_MAX];
- tmdn = concat_path_file(_PATH_MODULES, myuname.release);
+ tmdn = concat_path_file(_PATH_MODULES, k_strversion);
/* Jump through hoops in case /lib/modules/`uname -r`
* is a symlink. We do not want recursive_action to
* follow symlinks, but we do want to follow the
@@ -1636,7 +1473,7 @@
}
/* Check if we have found anything yet */
- if (m_filename == 0 || ((fp = open(m_filename, O_RDONLY)) == 0))
+ if (m_filename == 0 || ((fp = open(m_filename, O_RDONLY)) < 0))
{
char module_dir[FILENAME_MAX];
@@ -1647,94 +1484,103 @@
/* No module found under /lib/modules/`uname -r`, this
* time cast the net a bit wider. Search /lib/modules/ */
if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
- check_module_name_match, 0, m_fullName))
+ check_module_name_match, 0, m_fullName))
{
if (m_filename == 0
- || ((fp = open(m_filename, O_RDONLY)) == 0))
+ || ((fp = open(m_filename, O_RDONLY)) < 0))
{
bb_error_msg("%s: no module by that name found", m_fullName);
- goto out;
+ return EXIT_FAILURE;
}
} else
bb_error_msg_and_die("%s: no module by that name found", m_fullName);
}
- } else
+ } else
m_filename = bb_xstrdup(argv[optind]);
if (!flag_quiet)
printf("Using %s\n", m_filename);
+ if (k_version > 0x20500)
+ {
+#ifdef CONFIG_FEATURE_2_6_MODULES
+ return do_2_6(fp, argc - optind, argv + optind);
+#endif
+ }
+ else if (k_version > 0x20100)
+ {
+#ifdef CONFIG_FEATURE_2_4_MODULES
+ return do_2_0_and_2_4(fp, argc - optind, argv + optind, m_name);
+#endif
+ }
+ else if (k_version > 0x20000)
+ {
+#ifdef CONFIG_FEATURE_2_2_MODULES
+ return do_2_0_and_2_4(fp, argc - optind, argv + optind, m_name);
+#endif
+ }
+ return EXIT_FAILURE;
+}
+
+#if defined(CONFIG_FEATURE_2_2_MODULES) || defined (CONFIG_FEATURE_2_4_MODULES)
+static int do_2_0_and_2_4(int fp, int argc, char **argv, char *m_name)
+{
+ struct obj_file *f;
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+ int k_crcs;
+ char m_strversion[STRVERSIONLEN];
+ int m_version;
+ int m_crcs;
+#endif
+ unsigned long m_size;
+ ElfW(Addr) m_addr;
+ int gpl;
+
if ((f = obj_load(fp, ET_REL, m_filename)) == NULL)
bb_perror_msg_and_die("Could not load the module");
- if (get_modinfo_value(f, "kernel_version") == NULL)
- m_has_modinfo = 0;
- else
- m_has_modinfo = 1;
-
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
/* Version correspondence? */
- if (!flag_quiet) {
- if (uname(&uts_info) < 0)
- uts_info.release[0] = '\0';
- if (m_has_modinfo) {
- m_version = new_get_module_version(f, m_strversion);
- } else {
- m_version = old_get_module_version(f, m_strversion);
- if (m_version == -1) {
- bb_error_msg("couldn't find the kernel version the module was "
- "compiled for");
- goto out;
- }
- }
-
- if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
- if (flag_force_load) {
- bb_error_msg("Warning: kernel-module version mismatch\n"
- "\t%s was compiled for kernel version %s\n"
- "\twhile this kernel is version %s",
- m_filename, m_strversion, uts_info.release);
- } else {
- bb_error_msg("kernel-module version mismatch\n"
- "\t%s was compiled for kernel version %s\n"
- "\twhile this kernel is version %s.",
- m_filename, m_strversion, uts_info.release);
- goto out;
- }
- }
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+ m_version = get_module_version(f, m_strversion);
+ if (m_version == -1) {
+ bb_error_msg_and_die("couldn't find the kernel version the module was compiled for");
}
-
- k_crcs = 0;
#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
- k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
-
- if (k_new_syscalls) {
+ if (k_version > 0x20100)
+ {
#ifdef CONFIG_FEATURE_2_4_MODULES
if (!new_get_kernel_symbols())
- goto out;
- k_crcs = new_is_kernel_checksummed();
-#else
- bb_error_msg("Not configured to support new kernels");
- goto out;
+ return EXIT_FAILURE;
#endif
- } else {
+ }
+ else
+ {
#ifdef CONFIG_FEATURE_2_2_MODULES
- if (!old_get_kernel_symbols(m_name))
- goto out;
- k_crcs = old_is_kernel_checksummed();
-#else
- bb_error_msg("Not configured to support old kernels");
- goto out;
+ if (!old_get_kernel_symbols())
+ return EXIT_FAILURE;
#endif
}
#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
- if (m_has_modinfo)
- m_crcs = new_is_module_checksummed(f);
- else
- m_crcs = old_is_module_checksummed(f);
-
+ k_crcs = is_kernel_checksummed();
+ m_crcs = is_module_checksummed(f);
+ if ((m_crcs == 0 || k_crcs == 0) &&
+ strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
+ if (flag_force_load) {
+ bb_error_msg("Warning: kernel-module version mismatch\n"
+ "\t%s was compiled for kernel version %s\n"
+ "\twhile this kernel is version %s",
+ m_name, m_strversion, k_strversion);
+ } else {
+ if (!flag_quiet)
+ bb_error_msg("kernel-module version mismatch\n"
+ "\t%s was compiled for kernel version %s\n"
+ "\twhile this kernel is version %s.",
+ m_name, m_strversion, k_strversion);
+ return EXIT_FAILURE;
+ }
+ }
if (m_crcs != k_crcs)
obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
@@ -1745,29 +1591,27 @@
/* Allocate common symbols, symbol tables, and string tables. */
- if (k_new_syscalls
+ if (k_new_syscalls
? !new_create_this_module(f, m_name)
- : !old_create_mod_use_count(f))
+ : !old_create_mod_use_count(f))
{
- goto out;
+ return EXIT_FAILURE;
}
if (!obj_check_undefineds(f, 0)) {
- goto out;
+ return EXIT_FAILURE;
}
obj_allocate_commons(f);
+#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
check_tainted_module(f, m_name);
+#endif
/* done with the module name, on to the optional var=value arguments */
++optind;
if (optind < argc) {
- if (m_has_modinfo
- ? !new_process_module_arguments(f, argc - optind, argv + optind)
- : !old_process_module_arguments(f, argc - optind, argv + optind))
- {
- goto out;
- }
+ if (!process_module_arguments(f, argc - optind, argv + optind, 1))
+ return EXIT_FAILURE;
}
arch_create_got(f);
@@ -1787,26 +1631,26 @@
if (m_addr == -1) switch (errno) {
case EEXIST:
bb_error_msg("A module named %s already exists", m_name);
- goto out;
+ return EXIT_FAILURE;
case ENOMEM:
bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes", m_size);
- goto out;
+ return EXIT_FAILURE;
default:
bb_perror_msg("create_module: %s", m_name);
- goto out;
+ return EXIT_FAILURE;
}
if (!obj_relocate(f, m_addr)) {
delete_module(m_name);
- goto out;
+ return EXIT_FAILURE;
}
- if (k_new_syscalls
+ if (k_new_syscalls
? !new_init_module(m_name, f, m_size)
- : !old_init_module(m_name, f, m_size))
+ : !old_init_module(m_name, f, m_size))
{
delete_module(m_name);
- goto out;
+ return EXIT_FAILURE;
}
#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
@@ -1814,22 +1658,71 @@
print_load_map(f);
#endif
- exit_status = EXIT_SUCCESS;
+ return EXIT_SUCCESS;
+}
+#endif /* CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES */
-out:
-#ifdef CONFIG_FEATURE_CLEAN_UP
- if(fp)
- fclose(fp);
- if(tmp1) {
- free(tmp1);
- } else {
- free(m_name);
+#ifdef CONFIG_FEATURE_2_6_MODULES
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+/* We use error numbers in a loose translation... */
+static const char *moderror(int err)
+{
+ switch (err) {
+ case ENOEXEC:
+ return "Invalid module format";
+ case ENOENT:
+ return "Unknown symbol in module";
+ case ESRCH:
+ return "Module has wrong symbol version";
+ case EINVAL:
+ return "Invalid parameters";
+ default:
+ return strerror(err);
}
- free(m_filename);
-#endif
- return(exit_status);
}
+static int do_2_6(int fd, int argc, char **argv)
+{
+ int i;
+ long int ret;
+ struct stat st;
+ unsigned long len;
+ void *map;
+ char *options = bb_xstrdup("");
+
+ /* Rest is options */
+ for (i = 2; i < argc; i++) {
+ options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
+ /* Spaces handled by "" pairs, but no way of escaping quotes */
+ if (strchr(argv[i], ' ')) {
+ strcat(options, "\"");
+ strcat(options, argv[i]);
+ strcat(options, "\"");
+ } else {
+ strcat(options, argv[i]);
+ }
+ strcat(options, " ");
+ }
+
+ fstat(fd, &st);
+ len = st.st_size;
+ map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ if (map == MAP_FAILED) {
+ bb_perror_msg_and_die("cannot mmap `%s'", m_filename);
+ }
+
+ ret = syscall(__NR_init_module, map, len, options);
+ if (ret != 0) {
+ bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
+ m_filename, moderror(errno), ret);
+ }
+
+ return 0;
+}
+#endif /* CONFIG_FEATURE_2_6_MODULES */
+
int check_module (const char *mod)
{
k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
@@ -1842,3 +1735,4 @@
return -1;
}
+
Index: modutils/obj-2.6/moduleops_core.c
===================================================================
--- modutils/obj-2.6/moduleops_core.c (revision 0)
+++ modutils/obj-2.6/moduleops_core.c (revision 0)
@@ -0,0 +1,169 @@
+/* Load the given section: NULL on error. */
+static void *PERBIT(load_section)(ElfPERBIT(Ehdr) *hdr,
+ const char *secname,
+ unsigned long *size)
+{
+ ElfPERBIT(Shdr) *sechdrs;
+ unsigned int i;
+ char *secnames;
+
+ /* Grab section headers and strings so we can tell who is who */
+ sechdrs = (void *)hdr + hdr->e_shoff;
+ secnames = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ /* Find the section they want */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
+ *size = sechdrs[i].sh_size;
+ return (void *)hdr + sechdrs[i].sh_offset;
+ }
+ }
+ *size = 0;
+ return NULL;
+}
+
+static void PERBIT(load_symbols)(struct module *module)
+{
+ struct PERBIT(kernel_symbol) *ksyms;
+ char *ksymstrings;
+ unsigned long i, size;
+
+ /* New-style: strings are in this section. */
+ ksymstrings = PERBIT(load_section)(module->data, "__ksymtab_strings",
+ &size);
+ if (ksymstrings) {
+ unsigned int i = 0;
+ for (;;) {
+ /* Skip any zero padding. */
+ while (!ksymstrings[i])
+ if (++i >= size)
+ return;
+ add_symbol(ksymstrings+i, module);
+ i += strlen(ksymstrings+i);
+ }
+ /* GPL symbols too */
+ ksymstrings = PERBIT(load_section)(module->data,
+ "__ksymtab_strings_gpl",
+ &size);
+ for (;;) {
+ /* Skip any zero padding. */
+ while (!ksymstrings[i])
+ if (++i >= size)
+ return;
+ add_symbol(ksymstrings+i, module);
+ i += strlen(ksymstrings+i);
+ }
+ return;
+ }
+
+ /* Old-style. */
+ ksyms = PERBIT(load_section)(module->data, "__ksymtab", &size);
+ for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
+ add_symbol(ksyms[i].name, module);
+ ksyms = PERBIT(load_section)(module->data, "__gpl_ksymtab", &size);
+ for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
+ add_symbol(ksyms[i].name, module);
+}
+
+static char *PERBIT(get_aliases)(struct module *module, unsigned long *size)
+{
+ return PERBIT(load_section)(module->data, ".modalias", size);
+}
+
+static char *PERBIT(get_modinfo)(struct module *module, unsigned long *size)
+{
+ return PERBIT(load_section)(module->data, ".modinfo", size);
+}
+
+#ifndef STT_REGISTER
+#define STT_REGISTER 13 /* Global register reserved to app. */
+#endif
+
+/* Calculate the dependencies for this module */
+static void PERBIT(calculate_deps)(struct module *module, int verbose)
+{
+ unsigned int i;
+ unsigned long size;
+ char *strings;
+ ElfPERBIT(Sym) *syms;
+ ElfPERBIT(Ehdr) *hdr;
+ int handle_register_symbols;
+
+ strings = PERBIT(load_section)(module->data, ".strtab", &size);
+ syms = PERBIT(load_section)(module->data, ".symtab", &size);
+
+ if (!strings || !syms) {
+ warn("Couldn't find symtab and strtab in module %s\n",
+ module->pathname);
+ return;
+ }
+
+ hdr = module->data;
+ handle_register_symbols = 0;
+ if (hdr->e_machine == EM_SPARC ||
+ hdr->e_machine == EM_SPARCV9)
+ handle_register_symbols = 1;
+
+ module->num_deps = 0;
+ module->deps = NULL;
+ for (i = 1; i < size / sizeof(syms[0]); i++) {
+ if (syms[i].st_shndx == SHN_UNDEF) {
+ /* Look for symbol */
+ const char *name = strings + syms[i].st_name;
+ struct module *owner;
+ int weak;
+
+ /* Not really undefined: sparc gcc 3.3 creates
+ U references when you have global asm
+ variables, to avoid anyone else mising
+ them. */
+ if (handle_register_symbols
+ && (ELFPERBIT(ST_TYPE)(syms[i].st_info)
+ == STT_REGISTER))
+ continue;
+
+ weak = ELFPERBIT(ST_BIND)(syms[i].st_info) == STB_WEAK;
+ owner = find_symbol(name, module->pathname, weak);
+ if (owner) {
+ if (verbose)
+ printf("%s needs \"%s\": %s\n",
+ module->pathname, name,
+ owner->pathname);
+ add_dep(module, owner);
+ }
+ }
+ }
+}
+
+static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr, const char *name)
+{
+ unsigned int i;
+ unsigned long size;
+ char *strings;
+ ElfPERBIT(Sym) *syms;
+ ElfPERBIT(Shdr) *sechdrs;
+
+ sechdrs = (void *)hdr + hdr->e_shoff;
+ strings = PERBIT(load_section)(hdr, ".strtab", &size);
+ syms = PERBIT(load_section)(hdr, ".symtab", &size);
+
+ /* Don't warn again: we already have above */
+ if (!strings || !syms)
+ return NULL;
+
+ for (i = 0; i < size / sizeof(syms[0]); i++) {
+ if (strcmp(strings + syms[i].st_name, name) == 0) {
+ return (void *)hdr
+ + sechdrs[syms[i].st_shndx].sh_offset
+ + syms[i].st_value;
+ }
+ }
+ return NULL;
+}
+
+struct module_ops PERBIT(mod_ops) = {
+ .load_symbols = PERBIT(load_symbols),
+ .calculate_deps = PERBIT(calculate_deps),
+ .get_aliases = PERBIT(get_aliases),
+ .get_modinfo = PERBIT(get_modinfo),
+};
Index: modutils/obj-2.6/list.h
===================================================================
--- modutils/obj-2.6/list.h (revision 0)
+++ modutils/obj-2.6/list.h (revision 0)
@@ -0,0 +1,238 @@
+/* Stolen from Linux Kernel Source's list.h -- GPL. */
+#ifndef _MODINITTOOLS_LIST_H
+#define _MODINITTOOLS_LIST_H
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#endif
Index: modutils/obj-2.6/Makefile.in
===================================================================
--- modutils/obj-2.6/Makefile.in (revision 0)
+++ modutils/obj-2.6/Makefile.in (revision 0)
@@ -0,0 +1,34 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2002 by Erik Andersen <andersee@debian.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; 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+MODUTILS_OBJ_2_6_AR:=obj-2.6.a
+ifndef $(MODUTILS_OBJ_2_6_DIR)
+MODUTILS_OBJ_2_6_DIR:=$(TOPDIR)modutils/obj-2.6/
+endif
+
+MODUTILS_OBJ_2_6-$(CONFIG_MODUTILS_OBJ_2_6) += \
+ depmod.o \
+ moduleops.o \
+ zlibsupport.o
+
+libraries-y+=$(MODUTILS_OBJ_2_6_DIR)$(MODUTILS_OBJ_2_6_AR)
+
+$(MODUTILS_OBJ_2_6_DIR)$(MODUTILS_OBJ_2_6_AR): $(patsubst %,$(MODUTILS_OBJ_2_6_DIR)%, $(MODUTILS_OBJ_2_6-y))
+ $(AR) -ro $@ $(patsubst %,$(MODUTILS_OBJ_2_6_DIR)%, $(MODUTILS_OBJ_2_6-y))
+
Index: modutils/obj-2.6/zlibsupport.h
===================================================================
--- modutils/obj-2.6/zlibsupport.h (revision 0)
+++ modutils/obj-2.6/zlibsupport.h (revision 0)
@@ -0,0 +1,10 @@
+#ifndef _ZLIB_SUPPORT_H
+#define _ZLIB_SUPPORT_H
+
+/* Grab file. Decompresses if that is supported. Returns NULL on error. */
+extern void *grab_file(const char *filename, unsigned long *size);
+
+/* Free it up. */
+extern void release_file(void *data, unsigned long size);
+
+#endif /* _ZLIB_SUPPORT_H */
Index: modutils/obj-2.6/moduleops.c
===================================================================
--- modutils/obj-2.6/moduleops.c (revision 0)
+++ modutils/obj-2.6/moduleops.c (revision 0)
@@ -0,0 +1,22 @@
+/* The nasty work of reading 32 and 64-bit modules is in here. */
+#include <elf.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "depmod.h"
+#include "moduleops.h"
+
+#define PERBIT(x) x##32
+#define ElfPERBIT(x) Elf32_##x
+#define ELFPERBIT(x) ELF32_##x
+#include "moduleops_core.c"
+
+#undef PERBIT
+#undef ElfPERBIT
+#undef ELFPERBIT
+#define PERBIT(x) x##64
+#define ElfPERBIT(x) Elf64_##x
+#define ELFPERBIT(x) ELF64_##x
+#include "moduleops_core.c"
Index: modutils/obj-2.6/depmod.c
===================================================================
--- modutils/obj-2.6/depmod.c (revision 0)
+++ modutils/obj-2.6/depmod.c (revision 0)
@@ -0,0 +1,628 @@
+/* New simplified depmod without backwards compat stuff and not
+ requiring ksyms.
+
+ (C) 2002 Rusty Russell IBM Corporation
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <elf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/mman.h>
+
+#include "busybox.h"
+
+#include "depmod.h"
+#include "moduleops.h"
+#include "zlibsupport.h"
+
+/* I hate strcmp. */
+#define streq(a,b) (strcmp((a),(b)) == 0)
+
+#ifndef MODULE_DIR
+#define MODULE_DIR "/lib/modules/"
+#endif
+
+static int verbose;
+static unsigned int skipchars;
+
+void *do_nofail(void *ptr, const char *file, int line, const char *expr)
+{
+ if (!ptr) {
+ bb_error_msg_and_die("Memory allocation failure %s line %d: %s.\n",
+ file, line, expr);
+ }
+ return ptr;
+}
+
+#define SYMBOL_HASH_SIZE 1024
+struct symbol
+{
+ struct symbol *next;
+ struct module *owner;
+ char name[0];
+};
+
+static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
+
+/* This is based on the hash agorithm from gdbm, via tdb */
+static inline unsigned int tdb_hash(const char *name)
+{
+ unsigned value; /* Used to compute the hash value. */
+ unsigned i; /* Used to cycle through random values. */
+
+ /* Set the initial value from the key size. */
+ for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++)
+ value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
+
+ return (1103515243 * value + 12345);
+}
+
+void add_symbol(const char *name, struct module *owner)
+{
+ unsigned int hash;
+ struct symbol *new = NOFAIL(malloc(sizeof *new + strlen(name) + 1));
+
+ new->owner = owner;
+ strcpy(new->name, name);
+
+ hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
+ new->next = symbolhash[hash];
+ symbolhash[hash] = new;
+}
+
+static int print_unknown;
+
+struct module *find_symbol(const char *name, const char *modname, int weak)
+{
+ struct symbol *s;
+
+ /* For our purposes, .foo matches foo. PPC64 needs this. */
+ if (name[0] == '.')
+ name++;
+
+ for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) {
+ if (streq(s->name, name))
+ return s->owner;
+ }
+
+ if (print_unknown && !weak)
+ bb_error_msg("%s needs unknown symbol %s\n", modname, name);
+
+ return NULL;
+}
+
+void add_dep(struct module *mod, struct module *depends_on)
+{
+ unsigned int i;
+
+ for (i = 0; i < mod->num_deps; i++)
+ if (mod->deps[i] == depends_on)
+ return;
+
+ mod->deps = realloc(mod->deps, sizeof(mod->deps[0])*(mod->num_deps+1));
+ mod->deps[mod->num_deps++] = depends_on;
+}
+
+static void load_system_map(const char *filename)
+{
+ FILE *system_map;
+ char line[10240];
+
+ system_map = fopen(filename, "r");
+ if (!system_map)
+ bb_error_msg_and_die("Could not open '%s': %s\n", filename, strerror(errno));
+
+ /* eg. c0294200 R __ksymtab_devfs_alloc_devnum */
+ while (fgets(line, sizeof(line)-1, system_map)) {
+ char *ptr;
+
+ /* Snip \n */
+ ptr = strchr(line, '\n');
+ *ptr = '\0';
+
+ ptr = strchr(line, ' ');
+ if (!ptr || !(ptr = strchr(ptr + 1, ' ')))
+ continue;
+
+ /* Covers gpl-only and normal symbols. */
+ if (strncmp(ptr+1, "__ksymtab_", strlen("__ksymtab_")) == 0)
+ add_symbol(ptr+1+strlen("__ksymtab_"), NULL);
+ }
+
+ /* __this_module is magic inserted by kernel loader. */
+ add_symbol("__this_module", NULL);
+ /* On S390, this is faked up too */
+ add_symbol("_GLOBAL_OFFSET_TABLE_", NULL);
+}
+
+static struct option options[] = { { "all", 0, NULL, 'a' },
+ { "quick", 0, NULL, 'A' },
+ { "basedir", 1, NULL, 'b' },
+ { "errsyms", 0, NULL, 'e' },
+ { "filesyms", 1, NULL, 'F' },
+ { "help", 0, NULL, 'h' },
+ { "show", 0, NULL, 'n' },
+ { "dry-run", 0, NULL, 'n' },
+ { "quiet", 0, NULL, 'q' },
+ { "root", 0, NULL, 'r' },
+ { "unresolved-error", 0, NULL, 'u' },
+ { "verbose", 0, NULL, 'v' },
+ { "version", 0, NULL, 'V' },
+ /* Obsolete, but we need to parse it. */
+ { "config", 1, NULL, 'C' },
+ { NULL, 0, NULL, 0 } };
+
+/* Version number or module name? Don't assume extension. */
+static int is_version_number(const char *version)
+{
+ unsigned int dummy;
+
+ return (sscanf(version, "%u.%u.%u", &dummy, &dummy, &dummy) == 3);
+}
+
+static int old_module_version(const char *version)
+{
+ /* Expect three part version. */
+ unsigned int major, sub, minor;
+
+ sscanf(version, "%u.%u.%u", &major, &sub, &minor);
+
+ if (major > 2) return 0;
+ if (major < 2) return 1;
+
+ /* 2.x */
+ if (sub > 5) return 0;
+ if (sub < 5) return 1;
+
+ /* 2.5.x */
+ if (minor >= 48) return 0;
+ return 1;
+}
+
+static void exec_old_depmod(char *argv[])
+{
+ char *sep;
+ char pathname[strlen(argv[0])+1];
+ char oldname[strlen("depmod") + strlen(argv[0]) + sizeof(".modutils")];
+
+ memset(pathname, 0, strlen(argv[0])+1);
+ sep = strrchr(argv[0], '/');
+ if (sep)
+ memcpy(pathname, argv[0], sep - argv[0]+1);
+ sprintf(oldname, "%s%s.modutils", pathname, "depmod");
+
+ /* Recursion detection: we need an env var since we can't
+ change argv[0] (as older modutils uses it to determine
+ behavior). */
+ if (getenv("MODULE_RECURSE"))
+ return;
+ setenv("MODULE_RECURSE", "y", 0);
+
+ execvp(oldname, argv);
+ fprintf(stderr,
+ "Version requires old depmod, but couldn't run %s: %s\n",
+ oldname, strerror(errno));
+ exit(2);
+}
+
+static int ends_in(const char *name, const char *ext)
+{
+ unsigned int namelen, extlen;
+
+ /* Grab lengths */
+ namelen = strlen(name);
+ extlen = strlen(ext);
+
+ if (namelen < extlen) return 0;
+
+ if (streq(name + namelen - extlen, ext))
+ return 1;
+ return 0;
+}
+
+static struct module *grab_module(const char *_dirname,
+ const char *filename,
+ struct module *next)
+{
+ struct module *new;
+
+ new = NOFAIL(malloc(sizeof(*new)
+ + strlen(_dirname) + 1 + strlen(filename) + 1));
+ sprintf(new->pathname, "%s/%s", _dirname, filename);
+ INIT_LIST_HEAD(&new->dep_list);
+
+ new->data = grab_file(new->pathname, &new->len);
+ if (!new->data) {
+ bb_error_msg("Can't read module %s: %s\n",
+ new->pathname, strerror(errno));
+ goto fail_data;
+ }
+
+ /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
+ if (memcmp(new->data, ELFMAG, SELFMAG) != 0) {
+ bb_error_msg("Module %s is not an elf object\n", new->pathname);
+ goto fail;
+ }
+
+ switch (((char *)new->data)[EI_CLASS]) {
+ case ELFCLASS32:
+ new->ops = &mod_ops32;
+ break;
+ case ELFCLASS64:
+ new->ops = &mod_ops64;
+ break;
+ default:
+ bb_error_msg("Module %s has elf unknown identifier %i\n",
+ new->pathname, ((char *)new->data)[EI_CLASS]);
+ goto fail;
+ }
+ new->ops->load_symbols(new);
+
+ new->next = next;
+ return new;
+
+fail:
+ release_file(new->data, new->len);
+fail_data:
+ free(new);
+ return next;
+}
+
+struct module_traverse
+{
+ struct module_traverse *prev;
+ struct module *mod;
+};
+
+static int in_loop(struct module *mod, const struct module_traverse *traverse)
+{
+ const struct module_traverse *i;
+
+ for (i = traverse; i; i = i->prev) {
+ if (i->mod == mod)
+ return 1;
+ }
+ return 0;
+}
+
+/* Assume we are doing all the modules, so only report each loop once. */
+static void report_loop(const struct module *mod,
+ const struct module_traverse *traverse)
+{
+ const struct module_traverse *i;
+
+ /* Check that start is least alphabetically. eg. a depends
+ on b depends on a will get reported for a, not b. */
+ for (i = traverse->prev; i->prev; i = i->prev) {
+ if (strcmp(mod->pathname, i->mod->pathname) > 0)
+ return;
+ }
+
+ /* Is start in the loop? If not, don't report now. eg. a
+ depends on b which depends on c which depends on b. Don't
+ report when generating depends for a. */
+ if (mod != i->mod)
+ return;
+
+ bb_error_msg("Loop detected: %s ", mod->pathname);
+ for (i = traverse->prev; i->prev; i = i->prev)
+ fprintf(stderr, "needs %s ", basename(i->mod->pathname));
+ fprintf(stderr, "which needs %s again!\n", basename(mod->pathname));
+}
+
+/* This is damn slow, but loops actually happen, and we don't want to
+ just exit() and leave the user without any modules. */
+static int has_dep_loop(struct module *module, struct module_traverse *prev)
+{
+ unsigned int i;
+ struct module_traverse traverse = { .prev = prev, .mod = module };
+
+ if (in_loop(module, prev)) {
+ report_loop(module, &traverse);
+ return 1;
+ }
+
+ for (i = 0; i < module->num_deps; i++)
+ if (has_dep_loop(module->deps[i], &traverse))
+ return 1;
+ return 0;
+}
+
+/* Uniquifies and orders a dependency list. */
+static void order_dep_list(struct module *start, struct module *mod)
+{
+ unsigned int i;
+
+ for (i = 0; i < mod->num_deps; i++) {
+ /* If it was previously depended on, move it to the
+ tail. ie. if a needs b and c, and c needs b, we
+ must order b after c. */
+ list_del(&mod->deps[i]->dep_list);
+ list_add_tail(&mod->deps[i]->dep_list, &start->dep_list);
+ order_dep_list(start, mod->deps[i]);
+ }
+}
+
+static void del_module(struct module **modules, struct module *delme)
+{
+ struct module **i;
+
+ /* Find pointer to it. */
+ for (i = modules; *i != delme; i = &(*i)->next);
+
+ *i = delme->next;
+}
+
+static void output_deps(struct module *modules,
+ FILE *out)
+{
+ struct module *i;
+
+ for (i = modules; i; i = i->next)
+ i->ops->calculate_deps(i, verbose);
+
+ /* Strip out loops. */
+ again:
+ for (i = modules; i; i = i->next) {
+ if (has_dep_loop(i, NULL)) {
+ bb_error_msg("Module %s ignored, due to loop\n",
+ i->pathname + skipchars);
+ del_module(&modules, i);
+ goto again;
+ }
+ }
+
+ /* Now dump them out. */
+ for (i = modules; i; i = i->next) {
+ struct list_head *j, *tmp;
+ order_dep_list(i, i);
+
+ fprintf(out, "%s:", i->pathname + skipchars);
+ list_for_each_safe(j, tmp, &i->dep_list) {
+ struct module *dep
+ = list_entry(j, struct module, dep_list);
+ fprintf(out, " %s", dep->pathname + skipchars);
+ list_del_init(j);
+ }
+ fprintf(out, "\n");
+ }
+}
+
+static int smells_like_module(const char *name)
+{
+ return ends_in(name,".ko") || ends_in(name, ".ko.gz");
+}
+
+static struct module *grab_dir(const char *_dirname, struct module *next)
+{
+ DIR *dir;
+ struct dirent *dirent;
+
+ dir = opendir(_dirname);
+ if (!dir) {
+ bb_error_msg("Couldn't open directory %s: %s\n",
+ _dirname, strerror(errno));
+ return next;
+ }
+
+ while ((dirent = readdir(dir)) != NULL) {
+ if (smells_like_module(dirent->d_name))
+ next = grab_module(_dirname, dirent->d_name, next);
+ else if (!streq(dirent->d_name, ".")
+ && !streq(dirent->d_name, "..")) {
+ struct stat st;
+
+ char subdir[strlen(_dirname) + 1
+ + strlen(dirent->d_name) + 1];
+ sprintf(subdir, "%s/%s", _dirname, dirent->d_name);
+ if (lstat(subdir, &st) != 0)
+ bb_error_msg("Couldn't stat %s: %s\n", subdir,
+ strerror(errno));
+ else if (S_ISDIR(st.st_mode))
+ next = grab_dir(subdir, next);
+ }
+ }
+ closedir(dir);
+ return next;
+}
+
+/* Convert filename to the module name. Works if filename == modname, too. */
+static void filename2modname(char *modname, const char *filename)
+{
+ const char *afterslash;
+ unsigned int i;
+
+ afterslash = strrchr(filename, '/');
+ if (!afterslash)
+ afterslash = filename;
+ else
+ afterslash++;
+
+ /* Convert to underscores, stop at first . */
+ for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
+ if (afterslash[i] == '-')
+ modname[i] = '_';
+ else
+ modname[i] = afterslash[i];
+ }
+ modname[i] = '\0';
+}
+
+/* Simply dump hash table. */
+static void output_symbols(struct module *unused, FILE *out)
+{
+ unsigned int i;
+
+ fprintf(out, "# Aliases for symbols, used by symbol_request().\n");
+ for (i = 0; i < SYMBOL_HASH_SIZE; i++) {
+ struct symbol *s;
+
+ for (s = symbolhash[i]; s; s = s->next) {
+ if (s->owner) {
+ char modname[strlen(s->owner->pathname)+1];
+ filename2modname(modname, s->owner->pathname);
+ fprintf(out, "alias symbol:%s %s\n",
+ s->name, modname);
+ }
+ }
+ }
+}
+
+static const char *next_string(const char *string, unsigned long *secsize)
+{
+ /* Skip non-zero chars */
+ while (string[0]) {
+ string++;
+ if ((*secsize)-- <= 1)
+ return NULL;
+ }
+
+ /* Skip any zero padding. */
+ while (!string[0]) {
+ string++;
+ if ((*secsize)-- <= 1)
+ return NULL;
+ }
+ return string;
+}
+
+static void output_aliases(struct module *modules, FILE *out)
+{
+ struct module *i;
+ const char *p;
+ long size;
+
+ fprintf(out, "# Aliases extracted from modules themselves.\n");
+ for (i = modules; i; i = i->next) {
+ char modname[strlen(i->pathname)+1];
+
+ filename2modname(modname, i->pathname);
+
+ /* Grab from old-style .modalias section. */
+ for (p = i->ops->get_aliases(i, &size);
+ p;
+ p = next_string(p, &size))
+ fprintf(out, "alias %s %s\n", p, modname);
+
+ /* Grab form new-style .modinfo section. */
+ for (p = i->ops->get_modinfo(i, &size);
+ p;
+ p = next_string(p, &size)) {
+ if (strncmp(p, "alias=", strlen("alias=")) == 0)
+ fprintf(out, "alias %s %s\n",
+ p + strlen("alias="), modname);
+ }
+ }
+}
+
+struct depfile {
+ char *name;
+ void (*func)(struct module *, FILE *);
+};
+
+static struct depfile depfiles[] = {
+ { "modules.dep", output_deps }, /* This is what we check for '-A'. */
+};
+
+/* If we can't figure it out, it's safe to say "true". */
+static int any_modules_newer(const char *_dirname, time_t mtime)
+{
+ DIR *dir;
+ struct dirent *dirent;
+
+ dir = opendir(_dirname);
+ if (!dir)
+ return 1;
+
+ while ((dirent = readdir(dir)) != NULL) {
+ struct stat st;
+ char file[strlen(_dirname) + 1 + strlen(dirent->d_name) + 1];
+
+ if (streq(dirent->d_name, ".") || streq(dirent->d_name, ".."))
+ continue;
+
+ sprintf(file, "%s/%s", _dirname, dirent->d_name);
+ if (lstat(file, &st) != 0)
+ return 1;
+
+ if (smells_like_module(dirent->d_name)) {
+ if (st.st_mtime > mtime)
+ return 1;
+ } else if (S_ISDIR(st.st_mode)) {
+ if (any_modules_newer(file, mtime))
+ return 1;
+ }
+ }
+ closedir(dir);
+ return 0;
+}
+
+static int depfile_out_of_date(const char *_dirname)
+{
+ struct stat st;
+ char depfile[strlen(_dirname) + 1 + strlen(depfiles[0].name) + 1];
+
+ sprintf(depfile, "%s/%s", _dirname, depfiles[0].name);
+
+ if (stat(depfile, &st) != 0)
+ return 1;
+
+ return any_modules_newer(_dirname, st.st_mtime);
+}
+
+int depmod_main_2_6(int argc, char *argv[], int all, int _verbose, int doing_stdout, const char *system_map, const char *base_dir, const char *_dirname)
+{
+ struct module *list = NULL;
+ int i;
+
+ verbose = _verbose;
+
+ /* We can't print unknowns without a System.map */
+ if (!system_map)
+ print_unknown = 0;
+ else
+ load_system_map(system_map);
+
+ if (!all) {
+ /* Do command line args. */
+ for (; argc; ++argv, --argc)
+ list = grab_module("", *argv, list);
+ } else {
+ list = grab_dir(_dirname, list);
+ }
+
+ for (i = 0; i < sizeof(depfiles)/sizeof(depfiles[0]); i++) {
+ FILE *out;
+ struct depfile *d = &depfiles[i];
+ char depname[strlen(_dirname) + 1 + strlen(d->name) + 1];
+ char tmpname[strlen(_dirname) + 1 + strlen(d->name) +
+ strlen(".temp") + 1];
+
+ sprintf(depname, "%s/%s", _dirname, d->name);
+ sprintf(tmpname, "%s/%s.temp", _dirname, d->name);
+ if (!doing_stdout) {
+ out = fopen(tmpname, "w");
+ if (!out)
+ bb_error_msg_and_die("Could not open %s for writing: %s\n",
+ tmpname, strerror(errno));
+ } else
+ out = stdout;
+ d->func(list, out);
+ if (!doing_stdout) {
+ fclose(out);
+ if (rename(tmpname, depname) < 0)
+ bb_error_msg_and_die("Could not rename %s into %s: %s\n",
+ tmpname, depname, strerror(errno));
+ }
+ }
+
+ return 0;
+}
Index: modutils/obj-2.6/moduleops.h
===================================================================
--- modutils/obj-2.6/moduleops.h (revision 0)
+++ modutils/obj-2.6/moduleops.h (revision 0)
@@ -0,0 +1,27 @@
+#ifndef MODINITTOOLS_MODULEOPS_H
+#define MODINITTOOLS_MODULEOPS_H
+#include <stdio.h>
+
+/* All the icky stuff to do with manipulating 64 and 32-bit modules
+ belongs here. */
+struct kernel_symbol32 {
+ char value[4];
+ char name[64 - 4];
+};
+
+struct kernel_symbol64 {
+ char value[8];
+ char name[64 - 8];
+};
+
+struct module_ops
+{
+ void (*load_symbols)(struct module *module);
+ void (*calculate_deps)(struct module *module, int verbose);
+ char *(*get_aliases)(struct module *module, unsigned long *size);
+ char *(*get_modinfo)(struct module *module, unsigned long *size);
+};
+
+extern struct module_ops mod_ops32, mod_ops64;
+
+#endif /* MODINITTOOLS_MODULEOPS_H */
Index: modutils/obj-2.6/Makefile
===================================================================
--- modutils/obj-2.6/Makefile (revision 0)
+++ modutils/obj-2.6/Makefile (revision 0)
@@ -0,0 +1,30 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2002 Erik Andersen <andersee@debian.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; 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+TOPDIR:= ../../
+MODUTILS_OBJ_2_6_DIR:=./
+include $(TOPDIR).config
+include $(TOPDIR)Rules.mak
+include Makefile.in
+all: $(libraries-y)
+-include $(TOPDIR).depend
+
+clean:
+ rm -f *.o *.a $(AR_TARGET)
+
Index: modutils/obj-2.6/zlibsupport.c
===================================================================
--- modutils/obj-2.6/zlibsupport.c (revision 0)
+++ modutils/obj-2.6/zlibsupport.c (revision 0)
@@ -0,0 +1,40 @@
+/* Support for compressed modules. Willy Tarreau <willy@meta-x.org>
+ * did the support for modutils, Andrey Borzenkov <arvidjaar@mail.ru>
+ * ported it to module-init-tools, and I said it was too ugly to live
+ * and rewrote it 8).
+ *
+ * (C) 2003 Rusty Russell, IBM Corporation.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "zlibsupport.h"
+
+void *grab_file(const char *filename, unsigned long *size)
+{
+ int fd;
+ struct stat st;
+ void *map;
+
+ fd = open(filename, O_RDONLY, 0);
+ if (fd < 0)
+ return NULL;
+
+ fstat(fd, &st);
+ *size = st.st_size;
+ map = mmap(0, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (map == MAP_FAILED)
+ map = NULL;
+
+ close(fd);
+ return map;
+}
+
+void release_file(void *data, unsigned long size)
+{
+ munmap(data, size);
+}
Index: modutils/obj-2.6/depmod.h
===================================================================
--- modutils/obj-2.6/depmod.h (revision 0)
+++ modutils/obj-2.6/depmod.h (revision 0)
@@ -0,0 +1,58 @@
+#ifndef MODINITTOOLS_DEPMOD_H
+#define MODINITTOOLS_DEPMOD_H
+#include "list.h"
+
+struct module;
+
+/* Functions provided by depmod.c */
+void fatal(const char *fmt, ...) __attribute__ ((noreturn,
+ format (printf, 1, 2)));
+void warn(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+void *do_nofail(void *ptr, const char *file, int line, const char *expr);
+#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr)
+
+void add_symbol(const char *name, struct module *owner);
+struct module *find_symbol(const char *name, const char *modname, int weak);
+void add_dep(struct module *mod, struct module *depends_on);
+
+struct module
+{
+ /* Next module in list of all modules */
+ struct module *next;
+
+ /* 64 or 32 bit? */
+ struct module_ops *ops;
+
+ /* Dependencies: filled in by ops->calculate_deps() */
+ unsigned int num_deps;
+ struct module **deps;
+
+ /* Set while we are traversing dependencies */
+ struct list_head dep_list;
+
+ /* Tables extracted from module by ops->fetch_tables(). */
+ /* FIXME: Do other tables too --RR */
+ unsigned int pci_size;
+ void *pci_table;
+ unsigned int usb_size;
+ void *usb_table;
+ unsigned int ieee1394_size;
+ void *ieee1394_table;
+ unsigned int ccw_size;
+ void *ccw_table;
+ unsigned int pnp_size;
+ void *pnp_table;
+ unsigned int pnp_card_size;
+ unsigned int pnp_card_offset;
+ void *pnp_card_table;
+ unsigned int input_size;
+ void *input_table;
+
+ /* File contents and length. */
+ void *data;
+ unsigned long len;
+
+ char pathname[0];
+};
+
+#endif /* MODINITTOOLS_DEPMOD_H */
Index: Makefile
===================================================================
--- Makefile (revision 290)
+++ Makefile (working copy)
@@ -28,7 +28,7 @@
include Rules.mak
DIRS:=applets archival archival/libunarchive coreutils console-tools \
- debianutils editors findutils init miscutils modutils modutils/obj networking \
+ debianutils editors findutils init miscutils modutils modutils/obj modutils/obj-2.6 networking \
networking/libiproute networking/udhcp procps loginutils shell \
sysklogd util-linux libpwdgrp coreutils/libcoreutils libbb
Attachment:
signature.asc
Description: Digital signature