diff options
| -rw-r--r-- | include/linux/mod_devicetable.h | 11 | ||||
| -rw-r--r-- | scripts/Makefile | 16 | ||||
| -rw-r--r-- | scripts/Makefile.build | 3 | ||||
| -rw-r--r-- | scripts/elfconfig.h | 4 | ||||
| -rw-r--r-- | scripts/empty.c | 1 | ||||
| -rw-r--r-- | scripts/file2alias.c | 181 | ||||
| -rw-r--r-- | scripts/file2alias_inc.c | 79 | ||||
| -rw-r--r-- | scripts/mk_elfconfig.c | 57 |
8 files changed, 203 insertions, 149 deletions
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index f285481d5c79..9baa5a448684 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -7,19 +7,18 @@ #ifndef LINUX_MOD_DEVICETABLE_H #define LINUX_MOD_DEVICETABLE_H -#include <linux/types.h> - #ifdef __KERNEL__ +#include <linux/types.h> typedef unsigned long kernel_ulong_t; #endif #define PCI_ANY_ID (~0) struct pci_device_id { - unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ - unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ - unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ - kernel_ulong_t driver_data; /* Data private to the driver */ + __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ + __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ + __u32 class, class_mask; /* (class,subclass,prog-if) triplet */ + kernel_ulong_t driver_data; /* Data private to the driver */ }; /* diff --git a/scripts/Makefile b/scripts/Makefile index cf5a1862ea1d..59bdaae2e5b7 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -9,11 +9,23 @@ # conmakehash: Create arrays for initializing the kernel console tables host-progs := fixdep split-include conmakehash docproc kallsyms modpost \ - file2alias -build-targets := $(host-progs) + file2alias mk_elfconfig +build-targets := $(host-progs) empty.o # Let clean descend into subdirs subdir- := lxdialog kconfig # fixdep is needed to compile other host programs $(addprefix $(obj)/,$(filter-out fixdep,$(host-progs))): $(obj)/fixdep + +# dependencies on generated files need to be listed explicitly + +$(obj)/file2alias: $(obj)/elfconfig.h + +quiet_cmd_elfconfig = MKTARGET $@ + cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@ + +$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE + $(call if_changed,elfconfig) + +targets += $(obj)/target.h diff --git a/scripts/Makefile.build b/scripts/Makefile.build index c32cfce4f9b8..a80f195f0c80 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -199,7 +199,8 @@ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< %.o: %.S FORCE $(call if_changed_dep,as_o_S) -targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) +targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) \ + $(build-targets) # Build the compiled-in targets # --------------------------------------------------------------------------- diff --git a/scripts/elfconfig.h b/scripts/elfconfig.h new file mode 100644 index 000000000000..807d67db5eed --- /dev/null +++ b/scripts/elfconfig.h @@ -0,0 +1,4 @@ +#define KERNEL_ELFCLASS ELFCLASS32 +#define KERNEL_ELFDATA ELFDATA2LSB +#define HOST_ELFCLASS ELFCLASS32 +#define HOST_ELFDATA ELFDATA2LSB diff --git a/scripts/empty.c b/scripts/empty.c new file mode 100644 index 000000000000..49839cc4ff26 --- /dev/null +++ b/scripts/empty.c @@ -0,0 +1 @@ +/* empty file to figure out endianness / word size */ diff --git a/scripts/file2alias.c b/scripts/file2alias.c index 525a766bab3e..b638f80de910 100644 --- a/scripts/file2alias.c +++ b/scripts/file2alias.c @@ -14,13 +14,43 @@ #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> +#include <stdint.h> +#include <endian.h> -/* 32 bits: if it turns out to be 64, we add explicitly (see EXTRA_SIZE). */ -typedef int kernel_ulong_t; -#include "../include/linux/types.h" +#include "elfconfig.h" + +/* We use the ELF typedefs, since we can't rely on stdint.h being present. */ + +#if KERNEL_ELFCLASS == ELFCLASS32 +typedef Elf32_Addr kernel_ulong_t; +#else +typedef Elf64_Addr kernel_ulong_t; +#endif + +typedef Elf32_Word __u32; +typedef Elf32_Half __u16; +typedef unsigned char __u8; + +/* Big exception to the "don't include kernel headers into userspace, which + * even potentially has different endianness and word sizes, since + * we handle those differences explicitly below */ #include "../include/linux/mod_devicetable.h" -static int switch_endian; +#if KERNEL_ELFCLASS == ELFCLASS32 + +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym + +#else + +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym + +#endif + +#if KERNEL_ELFDATA != HOST_ELFDATA static void __endian(const void *src, void *dest, unsigned int size) { @@ -29,14 +59,22 @@ static void __endian(const void *src, void *dest, unsigned int size) ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; } + + #define TO_NATIVE(x) \ ({ \ typeof(x) __x; \ - if (switch_endian) __endian(&(x), &(__x), sizeof(__x)); \ - else __x = x; \ + __endian(&(x), &(__x), sizeof(__x)); \ __x; \ }) +#else /* endianness matches */ + +#define TO_NATIVE(x) (x) + +#endif + + #define ADD(str, sep, cond, field) \ do { \ strcat(str, sep); \ @@ -161,30 +199,80 @@ static int do_table(void *symval, unsigned long size, return wrote; } -/* This is the best way of doing this without making a complete mess - of the code. */ -#undef analyse_file -#undef Elf_Ehdr -#undef Elf_Shdr -#undef Elf_Sym -#undef EXTRA_SIZE -#define analyse_file analyze_file32 -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define EXTRA_SIZE 0 -#include "file2alias_inc.c" -#undef analyse_file -#undef Elf_Ehdr -#undef Elf_Shdr -#undef Elf_Sym -#undef EXTRA_SIZE -#define analyse_file analyze_file64 -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#define EXTRA_SIZE 4 -#include "file2alias_inc.c" +/* This contains the cookie-cutter code for ELF handling (32 v 64). */ +static void analyze_file(Elf_Ehdr *hdr, + unsigned int size, + const char *filename) +{ + unsigned int i, num_syms = 0; + Elf_Shdr *sechdrs; + Elf_Sym *syms = NULL; + char *secstrings, *strtab = NULL; + int first = 1; + + if (size < sizeof(*hdr)) + goto truncated; + + sechdrs = (void *)hdr + TO_NATIVE(hdr->e_shoff); + hdr->e_shoff = TO_NATIVE(hdr->e_shoff); + hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); + hdr->e_shnum = TO_NATIVE(hdr->e_shnum); + for (i = 0; i < hdr->e_shnum; i++) { + sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); + sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); + sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); + sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); + } + + /* Find symbol table. */ + secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + for (i = 1; i < hdr->e_shnum; i++) { + if (sechdrs[i].sh_offset > size) + goto truncated; + if (sechdrs[i].sh_type == SHT_SYMTAB) { + syms = (void *)hdr + sechdrs[i].sh_offset; + num_syms = sechdrs[i].sh_size / sizeof(syms[0]); + } else if (sechdrs[i].sh_type == SHT_STRTAB) + strtab = (void *)hdr + sechdrs[i].sh_offset; + } + + if (!strtab || !syms) { + fprintf(stderr, "table2alias: %s no symtab?\n", filename); + abort(); + } + + for (i = 0; i < num_syms; i++) { + const char *symname; + void *symval; + + syms[i].st_shndx = TO_NATIVE(syms[i].st_shndx); + syms[i].st_name = TO_NATIVE(syms[i].st_name); + syms[i].st_value = TO_NATIVE(syms[i].st_value); + syms[i].st_size = TO_NATIVE(syms[i].st_size); + + if (!syms[i].st_shndx || syms[i].st_shndx >= hdr->e_shnum) + continue; + + symname = strtab + syms[i].st_name; + symval = (void *)hdr + + sechdrs[syms[i].st_shndx].sh_offset + + syms[i].st_value; + if (sym_is(symname, "__mod_pci_device_table")) + do_table(symval, syms[i].st_size, + sizeof(struct pci_device_id), + do_pci_entry, filename, &first); + else if (sym_is(symname, "__mod_usb_device_table")) + do_table(symval, syms[i].st_size, + sizeof(struct usb_device_id), + do_usb_entry, filename, &first); + } + return; + + truncated: + fprintf(stderr, "table2alias: %s is truncated.\n", filename); + abort(); +} static void *grab_file(const char *filename, unsigned long *size) { @@ -215,45 +303,16 @@ int main(int argc, char *argv[]) { void *file; unsigned long size; - int endian; - union { short s; char c[2]; } endian_test; - - endian_test.s = 1; - if (endian_test.c[1] == 1) endian = ELFDATA2MSB; - else if (endian_test.c[0] == 1) endian = ELFDATA2LSB; - else - abort(); for (; argv[1]; argv++) { file = grab_file(argv[1], &size); if (!file) { fprintf(stderr, "file2alias: opening %s: %s\n", argv[1], strerror(errno)); - continue; - } - - if (size < SELFMAG || memcmp(file, ELFMAG, SELFMAG) != 0) - goto bad_elf; - - if (((unsigned char *)file)[EI_DATA] != endian) - switch_endian = 1; - - switch (((unsigned char *)file)[EI_CLASS]) { - case ELFCLASS32: - analyze_file32(file, size, argv[1]); - break; - case ELFCLASS64: - analyze_file64(file, size, argv[1]); - break; - default: - goto bad_elf; + abort(); } + analyze_file(file, size, argv[1]); munmap(file, size); - continue; - - bad_elf: - fprintf(stderr, "file2alias: %s is not elf\n", argv[1]); - return 1; } return 0; } diff --git a/scripts/file2alias_inc.c b/scripts/file2alias_inc.c deleted file mode 100644 index 3fcf52e0e3d4..000000000000 --- a/scripts/file2alias_inc.c +++ /dev/null @@ -1,79 +0,0 @@ -/* This contains the cookie-cutter code for ELF handling (32 v 64). - Return true if anything output. */ -static void analyse_file(Elf_Ehdr *hdr, - unsigned int size, - const char *filename) -{ - unsigned int i, num_syms = 0; - Elf_Shdr *sechdrs; - Elf_Sym *syms = NULL; - char *secstrings, *strtab = NULL; - int first = 1; - - if (size < sizeof(*hdr)) - goto truncated; - - sechdrs = (void *)hdr + TO_NATIVE(hdr->e_shoff); - if (switch_endian) { - hdr->e_shoff = TO_NATIVE(hdr->e_shoff); - hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); - hdr->e_shnum = TO_NATIVE(hdr->e_shnum); - for (i = 0; i < hdr->e_shnum; i++) { - sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); - sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); - sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); - sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); - } - } - - /* Find symbol table. */ - secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - - for (i = 1; i < hdr->e_shnum; i++) { - if (sechdrs[i].sh_offset > size) - goto truncated; - if (sechdrs[i].sh_type == SHT_SYMTAB) { - syms = (void *)hdr + sechdrs[i].sh_offset; - num_syms = sechdrs[i].sh_size / sizeof(syms[0]); - } else if (sechdrs[i].sh_type == SHT_STRTAB) - strtab = (void *)hdr + sechdrs[i].sh_offset; - } - - if (!strtab || !syms) { - fprintf(stderr, "table2alias: %s no symtab?\n", filename); - return; - } - - for (i = 0; i < num_syms; i++) { - const char *symname; - void *symval; - - if (switch_endian) { - syms[i].st_shndx = TO_NATIVE(syms[i].st_shndx); - syms[i].st_name = TO_NATIVE(syms[i].st_name); - syms[i].st_value = TO_NATIVE(syms[i].st_value); - syms[i].st_size = TO_NATIVE(syms[i].st_size); - } - - if (!syms[i].st_shndx || syms[i].st_shndx >= hdr->e_shnum) - continue; - - symname = strtab + syms[i].st_name; - symval = (void *)hdr - + sechdrs[syms[i].st_shndx].sh_offset - + syms[i].st_value; - if (sym_is(symname, "__mod_pci_device_table")) - do_table(symval, syms[i].st_size, - sizeof(struct pci_device_id) + EXTRA_SIZE * 1, - do_pci_entry, filename, &first); - else if (sym_is(symname, "__mod_usb_device_table")) - do_table(symval, syms[i].st_size, - sizeof(struct usb_device_id) + EXTRA_SIZE * 1, - do_usb_entry, filename, &first); - } - return; - - truncated: - fprintf(stderr, "table2alias: %s is truncated.\n", filename); - return; -} diff --git a/scripts/mk_elfconfig.c b/scripts/mk_elfconfig.c new file mode 100644 index 000000000000..578785973bd7 --- /dev/null +++ b/scripts/mk_elfconfig.c @@ -0,0 +1,57 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <elf.h> + +int +main(int argc, char **argv) +{ + unsigned char ei[EI_NIDENT]; + union { short s; char c[2]; } endian_test; + + if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) { + fprintf(stderr, "Error: input truncated\n"); + return 1; + } + if (memcmp(ei, ELFMAG, SELFMAG) != 0) { + fprintf(stderr, "Error: not ELF\n"); + return 1; + } + switch (ei[EI_CLASS]) { + case ELFCLASS32: + printf("#define KERNEL_ELFCLASS ELFCLASS32\n"); + break; + case ELFCLASS64: + printf("#define KERNEL_ELFCLASS ELFCLASS64\n"); + break; + default: + abort(); + } + switch (ei[EI_DATA]) { + case ELFDATA2LSB: + printf("#define KERNEL_ELFDATA ELFDATA2LSB\n"); + break; + case ELFDATA2MSB: + printf("#define KERNEL_ELFDATA ELFDATA2MSB\n"); + break; + default: + abort(); + } + + if (sizeof(unsigned long) == 4) { + printf("#define HOST_ELFCLASS ELFCLASS32\n"); + } else if (sizeof(unsigned long) == 8) { + printf("#define HOST_ELFCLASS ELFCLASS64\n"); + } + + endian_test.s = 0x0102; + if (memcmp(endian_test.c, "\x01\x02", 2) == 0) + printf("#define HOST_ELFDATA ELFDATA2MSB\n"); + else if (memcmp(endian_test.c, "\x02\x01", 2) == 0) + printf("#define HOST_ELFDATA ELFDATA2LSB\n"); + else + abort(); + + return 0; +} + |
