Replace own modpost with a dispatcher and four version of the original one.
* src/mod/Makefile: Build all modpost variants. * src/mod/Makefile.real, src/mod/elfconfig.h, src/mod/modpost.c, src/mod/real-lsb-32/elfconfig.h, src/mod/real-lsb-64/elfconfig.h, src/mod/real-msb-32/elfconfig.h, src/mod/real-msb-64/elfconfig.h: Add. * src/mod/real-lsb-32, src/mod/real-lsb-64, src/mod/real-msb-32, src/mod/real-msb-64: New directory. * src/mod/elf.cpp, src/mod/elf.hpp, src/mod/endian.hpp, src/mod/modpost.cpp, src/mod/module.cpp, src/mod/module.hpp, src/mod/module_devicetable.cpp, src/mod/module_devicetable.hpp, src/mod/module_devicetable.tpp, src/mod/module_devicetable_impl_2_6_16.cpp, src/mod/module_devicetable_impl_2_6_16.hpp: Remove. svn path=/dists/trunk/linux-kbuild-2.6/; revision=7045
This commit is contained in:
parent
d525b055b2
commit
c3687a0f8c
|
@ -1,13 +1,20 @@
|
|||
PROGS = modpost
|
||||
PROGS = \
|
||||
modpost \
|
||||
modpost.real-lsb-32 \
|
||||
modpost.real-lsb-64 \
|
||||
modpost.real-msb-32 \
|
||||
modpost.real-msb-64
|
||||
|
||||
OUTDIR = mod
|
||||
|
||||
modpost: elf.o modpost.o module.o module_devicetable.o module_devicetable_impl_2_6_16.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^
|
||||
modpost.real-%:
|
||||
$(MAKE) -f Makefile.real TYPE=$* SOURCEDIR=$(top_srcdir)/scripts/mod
|
||||
|
||||
%.o: %.cpp %.hpp endian.hpp
|
||||
%: %.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
|
||||
|
||||
include ../Makefile.inc
|
||||
|
||||
clean:
|
||||
rm $(PROGS) *.o
|
||||
|
||||
include ../Makefile.inc
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
PROGS = modpost.real-$(TYPE)
|
||||
|
||||
include ../Makefile.inc
|
||||
|
||||
modpost.real-$(TYPE): file2alias.real-$(TYPE).o modpost.real-$(TYPE).o sumversion.real-$(TYPE).o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
|
||||
|
||||
%.real-$(TYPE).o: $(SOURCEDIR)/%.c
|
||||
$(CC) -I real-$(TYPE) $(CFLAGS) -c -o $@ $^
|
||||
|
243
src/mod/elf.cpp
243
src/mod/elf.cpp
|
@ -1,243 +0,0 @@
|
|||
/*
|
||||
* elf.cpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#include "elf.hpp"
|
||||
#include "endian.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <elf.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace Elf;
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename _class>
|
||||
struct _elfdef
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct _elfdef<file_class_32>
|
||||
{
|
||||
typedef Elf32_Ehdr Ehdr;
|
||||
typedef Elf32_Shdr Shdr;
|
||||
typedef Elf32_Sym Sym;
|
||||
static inline uint8_t st_bind (uint8_t st_info) throw () { return ELF32_ST_BIND (st_info); }
|
||||
static inline uint8_t st_type (uint8_t st_info) throw () { return ELF32_ST_TYPE (st_info); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct _elfdef<file_class_64>
|
||||
{
|
||||
typedef Elf64_Ehdr Ehdr;
|
||||
typedef Elf64_Shdr Shdr;
|
||||
typedef Elf64_Sym Sym;
|
||||
static inline uint8_t st_bind (uint8_t st_info) throw () { return ELF64_ST_BIND (st_info); }
|
||||
static inline uint8_t st_type (uint8_t st_info) throw () { return ELF64_ST_TYPE (st_info); }
|
||||
};
|
||||
}
|
||||
|
||||
file::file (const char *filename, void *mem, size_t len) throw (std::bad_alloc)
|
||||
: filename (std::string (filename)), mem (mem), len (len)
|
||||
{ }
|
||||
|
||||
file::~file () throw ()
|
||||
{
|
||||
::munmap (mem, len);
|
||||
for (std::vector<section *>::iterator it = sections.begin (); it != sections.end (); ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
file *file::open (const char *filename) throw (std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
struct stat buf;
|
||||
int fd;
|
||||
void *mem;
|
||||
size_t len;
|
||||
if ((fd = ::open (filename, O_RDONLY)) == -1)
|
||||
throw std::runtime_error ("mapping failed");
|
||||
try
|
||||
{
|
||||
if (::fstat (fd, &buf) == -1)
|
||||
throw std::runtime_error ("mapping failed");
|
||||
len = buf.st_size;
|
||||
if ((mem = ::mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
|
||||
throw std::runtime_error ("mapping failed");
|
||||
|
||||
const uint8_t *buf = static_cast <uint8_t *> (mem);
|
||||
|
||||
switch (buf[EI_CLASS])
|
||||
{
|
||||
case ELFCLASS32:
|
||||
return open_class<file_class_32> (filename, buf, mem, len);
|
||||
case ELFCLASS64:
|
||||
return open_class<file_class_64> (filename, buf, mem, len);
|
||||
default:
|
||||
throw std::runtime_error ("Invalid file class");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
::close (fd);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _class>
|
||||
file *file::open_class (const char *filename, const uint8_t *buf, void * mem, size_t len) throw (std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
switch (buf[EI_DATA])
|
||||
{
|
||||
case ELFDATA2LSB:
|
||||
return new file_data<_class, file_data_2LSB> (filename, mem, len);
|
||||
case ELFDATA2MSB:
|
||||
return new file_data<_class, file_data_2MSB> (filename, mem, len);
|
||||
default:
|
||||
throw std::runtime_error ("Invalid file data");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _class, typename _data>
|
||||
file_data<_class, _data>::file_data (const char *filename) throw (std::bad_alloc, std::runtime_error)
|
||||
: file (filename)
|
||||
{
|
||||
construct ();
|
||||
}
|
||||
|
||||
template <typename _class, typename _data>
|
||||
file_data<_class, _data>::file_data (const char *filename, void *mem, size_t len) throw (std::bad_alloc, std::runtime_error)
|
||||
: file (filename, mem, len)
|
||||
{
|
||||
construct ();
|
||||
}
|
||||
|
||||
template <typename _class, typename _data>
|
||||
void file_data<_class, _data>::construct () throw (std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
uint8_t *buf = static_cast <uint8_t *> (this->mem);
|
||||
if (buf[EI_CLASS] != _class::id)
|
||||
throw std::runtime_error ("Wrong file class");
|
||||
if (buf[EI_DATA] != _data::id)
|
||||
throw std::runtime_error ("Wrong data encoding");
|
||||
|
||||
typedef typename _elfdef<_class>::Ehdr Ehdr;
|
||||
Ehdr *ehdr = static_cast <Ehdr *> (this->mem);
|
||||
this->type = convert<_data, typeof (ehdr->e_type )> () (ehdr->e_type );
|
||||
this->machine = convert<_data, typeof (ehdr->e_machine )> () (ehdr->e_machine );
|
||||
this->shoff = convert<_data, typeof (ehdr->e_shoff )> () (ehdr->e_shoff );
|
||||
this->shnum = convert<_data, typeof (ehdr->e_shnum )> () (ehdr->e_shnum );
|
||||
this->shstrndx = convert<_data, typeof (ehdr->e_shstrndx)> () (ehdr->e_shstrndx);
|
||||
|
||||
typedef typename _elfdef<_class>::Shdr Shdr;
|
||||
Shdr *shdrs = static_cast <Shdr *> (static_cast <void *> (static_cast <char *> (this->mem) + this->shoff));
|
||||
|
||||
this->sections.reserve (this->shnum);
|
||||
|
||||
for (unsigned int i = 0; i < this->shnum; i++)
|
||||
{
|
||||
section *temp;
|
||||
switch (convert<_data, typeof (shdrs[i].sh_type)> () (shdrs[i].sh_type))
|
||||
{
|
||||
case section_type_SYMTAB::id:
|
||||
temp = new section_real<_class, _data, section_type_SYMTAB> (&shdrs[i], this->mem);
|
||||
break;
|
||||
default:
|
||||
temp = new section_real<_class, _data, section_type_UNDEFINED> (&shdrs[i], this->mem);
|
||||
break;
|
||||
}
|
||||
this->sections.push_back (temp);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < this->shnum; i++)
|
||||
this->sections[i]->update_string_table (this);
|
||||
}
|
||||
|
||||
void section::update_string_table (file *file) throw (std::bad_alloc)
|
||||
{
|
||||
const section *section = file->get_section (file->get_shstrndx ());
|
||||
this->name_string = std::string (static_cast <const char *> (section->_mem ()) + this->name);
|
||||
}
|
||||
|
||||
template <typename _class, typename _data>
|
||||
section_data<_class, _data>::section_data (void *header, void *mem) throw ()
|
||||
{
|
||||
typedef typename _elfdef<_class>::Shdr Shdr;
|
||||
Shdr *shdr = static_cast <Shdr *> (header);
|
||||
this->name = convert<_data, typeof (shdr->sh_name )> () (shdr->sh_name );
|
||||
this->type = convert<_data, typeof (shdr->sh_type )> () (shdr->sh_type );
|
||||
this->offset = convert<_data, typeof (shdr->sh_offset)> () (shdr->sh_offset);
|
||||
this->size = convert<_data, typeof (shdr->sh_size )> () (shdr->sh_size );
|
||||
this->link = convert<_data, typeof (shdr->sh_link )> () (shdr->sh_link );
|
||||
this->mem = static_cast <void *> (static_cast <char *> (mem) + this->offset);
|
||||
}
|
||||
|
||||
section_type<section_type_SYMTAB>::~section_type () throw ()
|
||||
{
|
||||
for (std::vector<symbol *>::iterator it = symbols.begin (); it != symbols.end (); ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
void section_type<section_type_SYMTAB>::update_string_table (file *file) throw (std::bad_alloc)
|
||||
{
|
||||
section::update_string_table (file);
|
||||
for (unsigned int i = 0; i < symbols.size (); i++)
|
||||
this->symbols[i]->update_string_table (file, link);
|
||||
}
|
||||
|
||||
template <typename _class, typename _data>
|
||||
section_real<_class, _data, section_type_SYMTAB>::section_real (void *header, void *mem) throw (std::bad_alloc)
|
||||
: section_data<_class, _data> (header, mem)
|
||||
{
|
||||
if (this->type != SHT_SYMTAB)
|
||||
throw std::logic_error ("Wrong section type");
|
||||
typedef typename _elfdef<_class>::Sym Sym;
|
||||
Sym *syms = static_cast <Sym *> (this->mem);
|
||||
unsigned int max = this->size / sizeof (Sym);
|
||||
|
||||
this->symbols.reserve (max);
|
||||
|
||||
for (unsigned int i = 0; i < max; i++)
|
||||
this->symbols.push_back (new symbol_data<_class, _data> (&syms[i]));
|
||||
}
|
||||
|
||||
template <typename _class, typename _data>
|
||||
symbol_data<_class, _data>::symbol_data (void *mem) throw ()
|
||||
{
|
||||
typedef typename _elfdef<_class>::Sym Sym;
|
||||
Sym *sym = static_cast <Sym *> (mem);
|
||||
this->name = convert<_data, typeof (sym->st_name )> () (sym->st_name);
|
||||
this->info = convert<_data, typeof (sym->st_info )> () (sym->st_info);
|
||||
this->shndx = convert<_data, typeof (sym->st_shndx)> () (sym->st_shndx);
|
||||
this->value = convert<_data, typeof (sym->st_value)> () (sym->st_value);
|
||||
this->size = convert<_data, typeof (sym->st_size )> () (sym->st_size);
|
||||
this->bind = _elfdef<_class>::st_bind (this->info);
|
||||
this->type = _elfdef<_class>::st_type (this->info);
|
||||
}
|
||||
|
||||
template <typename _class, typename _data>
|
||||
void symbol_data<_class, _data>::update_string_table (file *file, uint16_t s) throw (std::bad_alloc)
|
||||
{
|
||||
const section *section = file->get_section (s);
|
||||
this->name_string = std::string (static_cast <const char *> (section->_mem ()) + this->name);
|
||||
}
|
||||
|
219
src/mod/elf.hpp
219
src/mod/elf.hpp
|
@ -1,219 +0,0 @@
|
|||
/*
|
||||
* elf.hpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#ifndef ELF_HPP
|
||||
#define ELF_HPP
|
||||
|
||||
#include "endian.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Elf
|
||||
{
|
||||
class file_class_32 { public: static const unsigned int id = 1; };
|
||||
class file_class_64 { public: static const unsigned int id = 2; };
|
||||
class file_data_2LSB { public: static const unsigned int id = 1; };
|
||||
class file_data_2MSB { public: static const unsigned int id = 2; };
|
||||
class section_type_UNDEFINED { };
|
||||
class section_type_SYMTAB { public: static const unsigned int id = 2; };
|
||||
|
||||
class section;
|
||||
|
||||
class file
|
||||
{
|
||||
public:
|
||||
virtual ~file () throw ();
|
||||
|
||||
virtual const uint8_t get_class () const throw () = 0;
|
||||
virtual const uint8_t get_data () const throw () = 0;
|
||||
const uint16_t get_type () const throw () { return type; }
|
||||
const uint16_t get_machine () const throw () { return machine; }
|
||||
const uint16_t get_shstrndx () const throw () { return shstrndx; }
|
||||
|
||||
const std::vector <section *> get_sections () const throw () { return sections; };
|
||||
const section *get_section (unsigned int i) const throw (std::out_of_range) { return sections.at(i); };
|
||||
|
||||
const void *const _mem () const throw () { return mem; }
|
||||
|
||||
static file *open (const char *filename) throw (std::bad_alloc, std::runtime_error);
|
||||
|
||||
protected:
|
||||
file (const char *, void *, size_t len) throw (std::bad_alloc);
|
||||
|
||||
template<typename _class>
|
||||
static file *open_class (const char *, const uint8_t *, void *, size_t) throw (std::bad_alloc, std::runtime_error);
|
||||
|
||||
uint16_t type;
|
||||
uint16_t machine;
|
||||
uint64_t shoff;
|
||||
uint16_t shnum;
|
||||
uint16_t shstrndx;
|
||||
|
||||
std::vector <section *> sections;
|
||||
|
||||
const std::string filename;
|
||||
void *mem;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
template <typename _class, typename _data>
|
||||
class file_data : public file
|
||||
{
|
||||
public:
|
||||
file_data (const char *) throw (std::bad_alloc, std::runtime_error);
|
||||
file_data (const char *, void *, size_t len) throw (std::bad_alloc, std::runtime_error);
|
||||
|
||||
const uint8_t get_class () const throw () { return _class::id; }
|
||||
const uint8_t get_data () const throw () { return _data::id; }
|
||||
|
||||
private:
|
||||
void construct () throw (std::bad_alloc, std::runtime_error);
|
||||
};
|
||||
|
||||
class section
|
||||
{
|
||||
public:
|
||||
virtual ~section () throw () {}
|
||||
|
||||
uint32_t get_type () const throw () { return type; }
|
||||
uint64_t get_size () const throw () { return size; }
|
||||
const std::string &get_name_string () const throw () { return name_string; }
|
||||
|
||||
const void *const _mem () const throw () { return mem; }
|
||||
|
||||
virtual void update_string_table (file *) throw (std::bad_alloc);
|
||||
|
||||
protected:
|
||||
uint32_t name;
|
||||
uint32_t type;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
uint32_t link;
|
||||
|
||||
std::string name_string;
|
||||
|
||||
void *mem;
|
||||
};
|
||||
|
||||
template <typename _class, typename _data>
|
||||
class section_data : public virtual section
|
||||
{
|
||||
public:
|
||||
section_data (void *, void *) throw ();
|
||||
};
|
||||
|
||||
template <typename _type>
|
||||
class section_type : public virtual section
|
||||
{
|
||||
};
|
||||
|
||||
class symbol;
|
||||
|
||||
template <>
|
||||
class section_type<section_type_SYMTAB> : public virtual section
|
||||
{
|
||||
public:
|
||||
~section_type () throw ();
|
||||
|
||||
const std::vector<symbol *> &get_symbols () throw () { return symbols; }
|
||||
|
||||
void update_string_table (file *) throw (std::bad_alloc);
|
||||
|
||||
protected:
|
||||
std::vector<symbol *> symbols;
|
||||
};
|
||||
|
||||
template <typename _class, typename _data, typename _type>
|
||||
class section_real : public section_data<_class, _data>, public section_type<_type>
|
||||
{
|
||||
public:
|
||||
section_real (void *, void *) throw ();
|
||||
};
|
||||
|
||||
template <typename _class, typename _data>
|
||||
class section_real<_class, _data, section_type_UNDEFINED> : public section_data<_class, _data>, public section_type<section_type_UNDEFINED>
|
||||
{
|
||||
public:
|
||||
section_real (void *a, void *b) throw () : section_data<_class, _data> (a, b) { }
|
||||
};
|
||||
|
||||
template <typename _class, typename _data>
|
||||
class section_real<_class, _data, section_type_SYMTAB> : public section_data<_class, _data>, public section_type<section_type_SYMTAB>
|
||||
{
|
||||
public:
|
||||
section_real (void *, void *) throw (std::bad_alloc);
|
||||
};
|
||||
|
||||
class symbol
|
||||
{
|
||||
public:
|
||||
virtual ~symbol () throw () {}
|
||||
|
||||
uint8_t get_info () const throw () { return info; }
|
||||
uint16_t get_shndx () const throw () { return shndx; }
|
||||
uint64_t get_value () const throw () { return value; }
|
||||
uint64_t get_size () const throw () { return size; }
|
||||
uint8_t get_bind () const throw () { return bind; }
|
||||
uint8_t get_type () const throw () { return type; }
|
||||
const std::string &get_name_string () const throw () { return name_string; }
|
||||
|
||||
virtual void update_string_table (file *, uint16_t) throw (std::bad_alloc) = 0;
|
||||
|
||||
protected:
|
||||
uint32_t name;
|
||||
uint8_t info;
|
||||
uint16_t shndx;
|
||||
uint64_t value;
|
||||
uint64_t size;
|
||||
uint8_t bind;
|
||||
uint8_t type;
|
||||
|
||||
std::string name_string;
|
||||
};
|
||||
|
||||
template <typename _class, typename _data>
|
||||
class symbol_data : public symbol
|
||||
{
|
||||
public:
|
||||
symbol_data (void *) throw ();
|
||||
|
||||
void update_string_table (file *, uint16_t) throw (std::bad_alloc);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
template <typename from, typename type>
|
||||
struct convert
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert<file_data_2LSB, type> : public endian::convert<endian::little_endian, type>
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert<file_data_2MSB, type> : public endian::convert<endian::big_endian, type>
|
||||
{ };
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,7 @@
|
|||
#include <endian.h>
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define HOST_ELFDATA ELFDATA2LSB
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define HOST_ELFDATA ELFDATA2MSB
|
||||
#endif
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* endian.hpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#ifndef ENDIAN_HPP
|
||||
#define ENDIAN_HPP
|
||||
|
||||
#include <endian.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace endian
|
||||
{
|
||||
class little_endian
|
||||
{ };
|
||||
|
||||
class big_endian
|
||||
{ };
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
typedef little_endian host_endian;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
typedef big_endian host_endian;
|
||||
#endif
|
||||
|
||||
template <typename type>
|
||||
struct convert_nop
|
||||
{
|
||||
inline type operator () (const type &in) const throw () { return in; }
|
||||
};
|
||||
|
||||
template <typename type>
|
||||
struct convert_simple
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct convert_simple<uint8_t> : public convert_nop<uint8_t>
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct convert_simple<uint16_t>
|
||||
{
|
||||
inline uint16_t operator () (const uint16_t &in) const throw ()
|
||||
{
|
||||
return (in & 0x00ffU) << 8 |
|
||||
(in & 0xff00U) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct convert_simple<uint32_t>
|
||||
{
|
||||
inline uint32_t operator () (const uint32_t &in) const throw ()
|
||||
{
|
||||
return (in & 0x000000ffU) << 24 |
|
||||
(in & 0xff000000U) >> 24 |
|
||||
(in & 0x0000ff00U) << 8 |
|
||||
(in & 0x00ff0000U) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct convert_simple<uint64_t>
|
||||
{
|
||||
inline uint64_t operator () (const uint64_t &in) const throw ()
|
||||
{
|
||||
return (in & 0x00000000000000ffULL) << 56 |
|
||||
(in & 0xff00000000000000ULL) >> 56 |
|
||||
(in & 0x000000000000ff00ULL) << 40 |
|
||||
(in & 0x00ff000000000000ULL) >> 40 |
|
||||
(in & 0x0000000000ff0000ULL) << 24 |
|
||||
(in & 0x0000ff0000000000ULL) >> 24 |
|
||||
(in & 0x00000000ff000000ULL) << 8 |
|
||||
(in & 0x000000ff00000000ULL) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct convert_simple<const uint8_t> : public convert_simple<uint8_t>
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct convert_simple<const uint16_t> : public convert_simple<uint16_t>
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct convert_simple<const uint32_t> : public convert_simple<uint32_t>
|
||||
{ };
|
||||
|
||||
template <typename from, typename to, typename type>
|
||||
struct convert_complete
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert_complete<little_endian, little_endian, type> : public convert_nop<type>
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert_complete<little_endian, big_endian, type> : public convert_simple<type>
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert_complete<big_endian, big_endian, type> : public convert_nop<type>
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert_complete<big_endian, little_endian, type> : public convert_simple<type>
|
||||
{ };
|
||||
|
||||
template <typename from, typename type>
|
||||
struct convert
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert<little_endian, type> : public convert_complete<little_endian, host_endian, type>
|
||||
{ };
|
||||
|
||||
template <typename type>
|
||||
struct convert<big_endian, type> : public convert_complete<big_endian, host_endian, type>
|
||||
{ };
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
#include <elf.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
char const *data, *class;
|
||||
char prog[1024];
|
||||
unsigned char ei[EI_NIDENT];
|
||||
int opt;
|
||||
FILE *file;
|
||||
|
||||
while ((opt = getopt (argc, argv, "ai:I:mo:")) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 'a':
|
||||
case 'i':
|
||||
case 'I':
|
||||
case 'm':
|
||||
case 'o':
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(file = fopen (argv[optind], "r")))
|
||||
{
|
||||
fprintf (stderr, "Can't open file\n");
|
||||
return 1;
|
||||
}
|
||||
if (fread (ei, 1, EI_NIDENT, file) != 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_DATA]) {
|
||||
case ELFDATA2LSB:
|
||||
data = "lsb";
|
||||
break;
|
||||
case ELFDATA2MSB:
|
||||
data = "msb";
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
switch (ei[EI_CLASS]) {
|
||||
case ELFCLASS32:
|
||||
class = "32";
|
||||
break;
|
||||
case ELFCLASS64:
|
||||
class = "64";
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
snprintf (prog, sizeof prog, "%s.real-%s-%s", argv[0], data, class);
|
||||
|
||||
return execv (prog, argv);
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* modpost.cpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#include "elf.hpp"
|
||||
#include "module.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
using namespace linuxkernel;
|
||||
|
||||
modulelist modules;
|
||||
|
||||
int main (int argc, char *const argv[])
|
||||
{
|
||||
int ret = EXIT_SUCCESS;
|
||||
int opt;
|
||||
const char *dump_read_kernel = 0, *dump_read_module = 0, *dump_write = 0;
|
||||
bool all_versions = false, modversions = false;;
|
||||
|
||||
while ((opt = getopt (argc, argv, "ai:I:mo:")) != -1)
|
||||
{
|
||||
switch(opt) {
|
||||
case 'a':
|
||||
all_versions = true;
|
||||
std::clog << "*** Warning: CONFIG_MODULE_SRCVERSION_ALL is not supported!" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
case 'i':
|
||||
dump_read_kernel = optarg;
|
||||
break;
|
||||
case 'I':
|
||||
dump_read_module = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
modversions = true;
|
||||
break;
|
||||
case 'o':
|
||||
dump_write = optarg;
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dump_read_kernel)
|
||||
modules.dump_read (dump_read_kernel, true);
|
||||
if (dump_read_module)
|
||||
modules.dump_read (dump_read_module, false);
|
||||
|
||||
for (int i = optind; i < argc; i++)
|
||||
{
|
||||
std::string filename (argv[i]);
|
||||
try
|
||||
{
|
||||
modules.insert (filename);
|
||||
}
|
||||
catch (std::runtime_error &e)
|
||||
{
|
||||
std::clog << "*** Warning: \"" << filename << "\" failed to load: " << e.what () << std::endl;
|
||||
ret = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
modules.write (modversions);
|
||||
|
||||
if (dump_write)
|
||||
modules.dump_write (dump_write, dump_read_module ? false : true);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,455 +0,0 @@
|
|||
/*
|
||||
* module.cpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#include "module.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
|
||||
#include <elf.h>
|
||||
|
||||
using namespace linuxkernel;
|
||||
|
||||
const std::string module_real::symbol_name_cleanup ("cleanup_module");
|
||||
const std::string module_real::symbol_name_init ("init_module");
|
||||
const std::string module_real::symbol_prefix_crc ("__crc_");
|
||||
const std::string module_real::symbol_prefix_ksymtab ("__ksymtab_");
|
||||
|
||||
module::module (const std::string &filename, bool kernel) throw ()
|
||||
: kernel (kernel), is_vmlinux (false)
|
||||
{
|
||||
std::string::size_type t1 = filename.find_last_of ('/');
|
||||
std::string::size_type t2 = filename.find_last_of ('.');
|
||||
if (t1 == std::string::npos)
|
||||
t1 = 0;
|
||||
else
|
||||
t1++;
|
||||
name = filename.substr (0, t2);
|
||||
if (t2 != std::string::npos)
|
||||
t2 -= t1;
|
||||
name_short = filename.substr (t1, t2);
|
||||
|
||||
if (name == "vmlinux")
|
||||
is_vmlinux = true;
|
||||
}
|
||||
|
||||
module_real::module_real (const std::string &filename, Elf::file *file) throw (std::runtime_error)
|
||||
: module (filename, false), has_init (false), has_cleanup (false), file (file)
|
||||
{
|
||||
const std::vector <Elf::section *> §ions = file->get_sections ();
|
||||
Elf::section *modinfo = 0;
|
||||
symtab = 0;
|
||||
|
||||
for (std::vector <Elf::section *>::const_iterator it = sections.begin (); it != sections.end (); ++it)
|
||||
{
|
||||
const std::string &name = (*it)->get_name_string ();
|
||||
uint32_t type = (*it)->get_type ();
|
||||
if (name == ".modinfo")
|
||||
modinfo = *it;
|
||||
if (type == Elf::section_type_SYMTAB::id)
|
||||
symtab = dynamic_cast <Elf::section_type<Elf::section_type_SYMTAB> *> (*it);
|
||||
}
|
||||
|
||||
if (!symtab)
|
||||
throw std::runtime_error ("Not a kernel module, lacks symbol table");
|
||||
|
||||
if (modinfo)
|
||||
read_modinfo (modinfo);
|
||||
symbols_undefined.insert (std::pair<std::string, symbol_undefined> ("struct_module", symbol_undefined ("struct_module", 0)));
|
||||
|
||||
read_symtab (symtab);
|
||||
}
|
||||
|
||||
const Elf::symbol *module_real::_get_symbol (const std::string &name) const throw ()
|
||||
{
|
||||
for (std::vector<Elf::symbol *>::const_iterator it = symtab->get_symbols ().begin (); it != symtab->get_symbols ().end (); ++it)
|
||||
{
|
||||
Elf::symbol *symbol = *it;
|
||||
std::string symname = symbol->get_name_string ();
|
||||
if (symname == name)
|
||||
return symbol;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void module_real::write (const modulelist &list, bool modversions)
|
||||
{
|
||||
std::string filename = name + ".mod.c";
|
||||
std::ofstream out (filename.c_str ());
|
||||
write_header (out);
|
||||
if (modversions)
|
||||
write_versions (out, list);
|
||||
write_depends (out, list);
|
||||
write_moddevtable (out);
|
||||
}
|
||||
|
||||
module_real *module_real::open (const std::string &filename) throw (std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
Elf::file *file = Elf::file::open (filename.c_str ());
|
||||
switch (file->get_class ())
|
||||
{
|
||||
case Elf::file_class_32::id:
|
||||
return open_class<Elf::file_class_32> (filename, file);
|
||||
case Elf::file_class_64::id:
|
||||
return open_class<Elf::file_class_64> (filename, file);
|
||||
default:
|
||||
throw std::runtime_error ("Unsupported file class");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Elf_class>
|
||||
module_real *module_real::open_class (const std::string &filename, Elf::file *file) throw (std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
switch (file->get_data ())
|
||||
{
|
||||
case Elf::file_data_2LSB::id:
|
||||
return new module_data<Elf_class, Elf::file_data_2LSB> (filename, file);
|
||||
case Elf::file_data_2MSB::id:
|
||||
return new module_data<Elf_class, Elf::file_data_2MSB> (filename, file);
|
||||
default:
|
||||
throw std::runtime_error ("Unsupported data encoding");
|
||||
}
|
||||
}
|
||||
|
||||
void module_real::read_modinfo (Elf::section *section) throw (std::runtime_error)
|
||||
{
|
||||
const char *act, *end, *temp1, *temp2;
|
||||
act = static_cast <const char *> (section->_mem ());
|
||||
end = act + section->get_size ();
|
||||
while (act <= end)
|
||||
{
|
||||
temp1 = act;
|
||||
for (; *act && *act != '=' && act <= end; act++);
|
||||
if (act > end)
|
||||
break;
|
||||
temp2 = ++act;
|
||||
for (; *act && act <= end; act++);
|
||||
if (act > end)
|
||||
break;
|
||||
modinfo.insert (std::pair<std::string, std::string> (std::string (temp1, temp2 - temp1 - 1), std::string (temp2, act - temp2)));
|
||||
for (; !*act && act <= end; act++);
|
||||
}
|
||||
}
|
||||
|
||||
void module_real::read_symtab (Elf::section_type<Elf::section_type_SYMTAB> *section) throw (std::runtime_error)
|
||||
{
|
||||
for (std::vector<Elf::symbol *>::const_iterator it = section->get_symbols ().begin (); it != section->get_symbols ().end (); ++it)
|
||||
{
|
||||
Elf::symbol *symbol = *it;
|
||||
std::string symname = symbol->get_name_string ();
|
||||
|
||||
switch (symbol->get_shndx ())
|
||||
{
|
||||
case SHN_COMMON:
|
||||
std::clog << "*** Warning: \"" << symname << "\" [" << name << "] is COMMON symbol" << std::endl;
|
||||
break;
|
||||
case SHN_ABS:
|
||||
if (symname.compare (0, symbol_prefix_crc.size (), symbol_prefix_crc) == 0)
|
||||
{
|
||||
std::string symname_real (symname.substr (symbol_prefix_crc.size ()));
|
||||
std::map<std::string, symbol_exported>::iterator it = symbols_exported.find (symname_real);
|
||||
if (it == symbols_exported.end ())
|
||||
symbols_exported.insert (std::pair<std::string, symbol_exported> (symname_real, symbol_exported (symname_real, symbol->get_value ())));
|
||||
else
|
||||
it->second.set_crc (symbol->get_value ());
|
||||
}
|
||||
break;
|
||||
case SHN_UNDEF:
|
||||
if (symbol->get_bind () != STB_GLOBAL &&
|
||||
symbol->get_bind () != STB_WEAK)
|
||||
break;
|
||||
//FIXME: if (symbol->get_type () == STT_REGISTER)
|
||||
// break;
|
||||
/* ignore global offset table */
|
||||
if (symname == "_GLOBAL_OFFSET_TABLE_")
|
||||
break;
|
||||
/* ignore __this_module, it will be resolved shortly */
|
||||
if (symname == "__this_module")
|
||||
break;
|
||||
symbols_undefined.insert (std::pair<std::string, symbol_undefined> (symname, symbol_undefined (symname, symbol->get_bind () == STB_WEAK)));
|
||||
break;
|
||||
default:
|
||||
if (symname.compare (0, symbol_prefix_ksymtab.size (), symbol_prefix_ksymtab) == 0)
|
||||
{
|
||||
std::string symname_real (symname.substr (symbol_prefix_ksymtab.size ()));
|
||||
std::map<std::string, symbol_exported>::iterator it = symbols_exported.find (symname_real);
|
||||
if (it == symbols_exported.end ())
|
||||
symbols_exported.insert (std::pair<std::string, symbol_exported> (symname_real, symbol_exported (symname_real)));
|
||||
}
|
||||
else if (symname == symbol_name_cleanup)
|
||||
has_cleanup = true;
|
||||
else if (symname == symbol_name_init)
|
||||
has_init = true;
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void module_real::write_depends (std::ostream &out, const modulelist &list)
|
||||
{
|
||||
std::set<std::string> depends;
|
||||
for (std::map<std::string, symbol_undefined>::const_iterator it = symbols_undefined.begin (); it != symbols_undefined.end (); ++it)
|
||||
{
|
||||
try
|
||||
{
|
||||
const std::string &mod (list.get_module_name_short_for_symbol (it->first));
|
||||
if (mod != "vmlinux")
|
||||
depends.insert (mod);
|
||||
}
|
||||
catch (std::out_of_range &)
|
||||
{ }
|
||||
}
|
||||
out <<
|
||||
"static const char __module_depends[]\n"
|
||||
"__attribute_used__\n"
|
||||
"__attribute__((section(\".modinfo\"))) =\n"
|
||||
"\"depends=";
|
||||
if (depends.begin () != depends.end ())
|
||||
{
|
||||
std::set<std::string>::const_iterator it = depends.begin ();
|
||||
out << *it;
|
||||
for (++it; it != depends.end (); ++it)
|
||||
out << ',' << *it;
|
||||
}
|
||||
out << "\";\n\n";
|
||||
}
|
||||
|
||||
void module_real::write_header (std::ostream &out)
|
||||
{
|
||||
out <<
|
||||
"#include <linux/module.h>\n"
|
||||
"#include <linux/vermagic.h>\n"
|
||||
"#include <linux/compiler.h>\n"
|
||||
"\n"
|
||||
"MODULE_INFO(vermagic, VERMAGIC_STRING);\n"
|
||||
"\n"
|
||||
"struct module __this_module\n"
|
||||
"__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"
|
||||
" .name = KBUILD_MODNAME,\n";
|
||||
if (has_init)
|
||||
out << " .init = init_module,\n";
|
||||
if (has_cleanup)
|
||||
out <<
|
||||
"#ifdef CONFIG_MODULE_UNLOAD\n"
|
||||
" .exit = cleanup_module,\n"
|
||||
"#endif\n";
|
||||
out << "};\n\n";
|
||||
}
|
||||
|
||||
void module_real::write_moddevtable (std::ostream &out)
|
||||
{
|
||||
for (std::list<module_devicetable::table_base *>::iterator it = devicetables.begin (); it != devicetables.end (); ++it)
|
||||
{
|
||||
module_devicetable::table_base *ent = *it;
|
||||
if (ent)
|
||||
ent->write (out);
|
||||
}
|
||||
}
|
||||
|
||||
void module_real::write_versions (std::ostream &out, const modulelist &list)
|
||||
{
|
||||
out <<
|
||||
"static const struct modversion_info ____versions[]\n"
|
||||
"__attribute_used__\n"
|
||||
"__attribute__((section(\"__versions\"))) = {\n";
|
||||
|
||||
for (_symbols_undefined::const_iterator it = symbols_undefined.begin (); it != symbols_undefined.end (); ++it)
|
||||
{
|
||||
try
|
||||
{
|
||||
const symbol_exported &sym (list.get_symbol (it->first));
|
||||
if (sym.get_crc_valid ())
|
||||
out << "\t{ 0x" << std::hex << sym.get_crc () << std::dec << ", \"" << it->first << "\" },\n";
|
||||
else
|
||||
std::clog << "*** Warning: \"" << sym.get_name () << "\" [" << name << "] has no CRC!" << std::endl;
|
||||
}
|
||||
catch (std::out_of_range &)
|
||||
{
|
||||
if (list.report_symbols_missing)
|
||||
std::clog << "*** Warning: \"" << it->first << "\" is undefined!" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
out << "};\n\n";
|
||||
}
|
||||
|
||||
template <typename Elf_class, typename Elf_data>
|
||||
module_data<Elf_class, Elf_data>::module_data (const std::string &filename, Elf::file *file) throw (std::runtime_error)
|
||||
: module_real (filename, file)
|
||||
{
|
||||
module_devicetable::table_create<Elf_class, Elf_data> (devicetables, this, file);
|
||||
}
|
||||
|
||||
modulelist::modulelist () throw ()
|
||||
: report_symbols_missing (false)
|
||||
{ }
|
||||
|
||||
modulelist::~modulelist () throw ()
|
||||
{
|
||||
for (_modules_real::iterator it = modules_real.begin (); it != modules_real.end (); ++it)
|
||||
delete it->second;
|
||||
for (_modules_shadow::iterator it = modules_shadow.begin (); it != modules_shadow.end (); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
void modulelist::dump_read (const std::string &filename, bool kernel) throw (std::runtime_error)
|
||||
{
|
||||
std::ifstream in (filename.c_str ());
|
||||
while (in.good ())
|
||||
{
|
||||
char buf[512];
|
||||
in.getline (buf, sizeof (buf));
|
||||
std::stringstream str (buf);
|
||||
uint32_t crc;
|
||||
std::string symbol, module_name;
|
||||
str >> std::hex >> crc >> std::dec >> symbol >> module_name;
|
||||
_modules_shadow::const_iterator it = modules_shadow.find (module_name);
|
||||
module *mod;
|
||||
if (it == modules_shadow.end ())
|
||||
{
|
||||
mod = new module (module_name, kernel);
|
||||
modules_shadow.insert (_modules_shadow_pair (module_name, mod));
|
||||
}
|
||||
else
|
||||
mod = it->second;
|
||||
mod->symbols_exported.insert (std::pair<std::string, symbol_exported> (symbol, symbol_exported (symbol, crc)));
|
||||
symbols_exported.insert (std::pair<std::string, std::string> (symbol, module_name));
|
||||
if (mod->get_is_vmlinux ())
|
||||
report_symbols_missing = true;
|
||||
}
|
||||
}
|
||||
|
||||
void modulelist::dump_write (const std::string &filename, bool kernel) const throw (std::runtime_error)
|
||||
{
|
||||
char buf[128];
|
||||
std::ofstream out (filename.c_str (), std::ios::trunc);
|
||||
|
||||
for (_symbols::const_iterator it = symbols_exported.begin (); it != symbols_exported.end (); ++it)
|
||||
{
|
||||
const module *mod = get_module (it->second);
|
||||
const symbol_exported &sym = get_symbol (it->first);
|
||||
if (!kernel && mod->get_kernel ())
|
||||
continue;
|
||||
snprintf (buf, sizeof (buf), "0x%08x\t%s\t%s\n", sym.get_crc (), it->first.c_str (), mod->get_name ().c_str ());
|
||||
out << buf;
|
||||
}
|
||||
}
|
||||
|
||||
const module *modulelist::get_module (const std::string &name) const throw (std::out_of_range)
|
||||
{
|
||||
_modules_real::const_iterator it1 = modules_real.find (name);
|
||||
if (it1 != modules_real.end ())
|
||||
return it1->second;
|
||||
_modules_shadow::const_iterator it2 = modules_shadow.find (name);
|
||||
if (it2 != modules_shadow.end ())
|
||||
return it2->second;
|
||||
throw std::out_of_range ("Don't find module");
|
||||
}
|
||||
|
||||
const module *modulelist::get_module_for_symbol (const symbolname &name) const throw (std::out_of_range)
|
||||
{
|
||||
_symbols::const_iterator it = symbols_exported.find (name);
|
||||
if (it == symbols_exported.end ())
|
||||
throw std::out_of_range ("symbol is undefined");
|
||||
return get_module (it->second);
|
||||
}
|
||||
|
||||
const std::string &modulelist::get_module_name_short_for_symbol (const symbolname &name) const throw (std::out_of_range)
|
||||
{
|
||||
const module *mod = get_module_for_symbol (name);
|
||||
return mod->get_name_short ();
|
||||
}
|
||||
|
||||
const symbol_exported &modulelist::get_symbol (const symbolname &name) const throw (std::out_of_range)
|
||||
{
|
||||
const module *mod = get_module_for_symbol (name);
|
||||
std::map<std::string, symbol_exported>::const_iterator it = mod->get_symbols_exported ().find (name);
|
||||
if (it == mod->get_symbols_exported ().end ())
|
||||
throw std::logic_error ("Don't find symbol");
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void modulelist::insert (module_real *mod) throw (std::runtime_error)
|
||||
{
|
||||
bool overwrite = false;
|
||||
|
||||
if (mod->get_is_vmlinux ())
|
||||
{
|
||||
if (!modules_shadow.insert (_modules_shadow_pair (mod->get_name (), mod)).second)
|
||||
overwrite = true;
|
||||
report_symbols_missing = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!modules_real.insert (_modules_real_pair (mod->get_name (), mod)).second)
|
||||
throw std::runtime_error ("Already know a module with this name");
|
||||
}
|
||||
|
||||
for (std::map<std::string, symbol_exported>::const_iterator it = mod->get_symbols_exported ().begin ();
|
||||
it != mod->get_symbols_exported ().end (); ++it)
|
||||
if (!symbols_exported.insert (std::pair<std::string, std::string> (it->second.get_name (), mod->get_name ())).second)
|
||||
if (!overwrite)
|
||||
std::clog << "*** Warning: \"" << it->second.get_name () << "\" [" << mod->get_name () << "] duplicated symbol!" << std::endl;
|
||||
}
|
||||
|
||||
void modulelist::insert (const std::string &filename) throw (std::runtime_error)
|
||||
{
|
||||
module_real *mod = module_real::open (filename);
|
||||
try
|
||||
{
|
||||
insert (mod);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete mod;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void modulelist::write (bool modversions)
|
||||
{
|
||||
for (_modules_real::iterator it = modules_real.begin (); it != modules_real.end (); ++it)
|
||||
it->second->write (*this, modversions);
|
||||
}
|
||||
|
||||
symbol::symbol (const symbolname &name) throw ()
|
||||
: name (name)
|
||||
{ }
|
||||
|
||||
symbol_exported::symbol_exported (const symbolname &name) throw ()
|
||||
: symbol (name), crc_valid (false)
|
||||
{ }
|
||||
|
||||
symbol_exported::symbol_exported (const symbolname &name, uint32_t crc) throw ()
|
||||
: symbol (name), crc (crc), crc_valid (true)
|
||||
{ }
|
||||
|
||||
void symbol_exported::set_crc (uint32_t _crc) throw ()
|
||||
{
|
||||
crc = _crc;
|
||||
crc_valid = true;
|
||||
}
|
||||
|
||||
symbol_undefined::symbol_undefined (const symbolname &name, bool weak) throw ()
|
||||
: symbol (name), weak (weak)
|
||||
{ }
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
* module.hpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#ifndef MODULE_HPP
|
||||
#define MODULE_HPP
|
||||
|
||||
#define DISABLE_TEMPLATES
|
||||
#include "elf.hpp"
|
||||
#include "module_devicetable.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
||||
namespace linuxkernel
|
||||
{
|
||||
class modulelist;
|
||||
class symbolname;
|
||||
class symbol_exported;
|
||||
class symbol_undefined;
|
||||
|
||||
class module
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, symbol_exported> _symbols_exported;
|
||||
|
||||
module (const std::string &name, bool kernel) throw ();
|
||||
|
||||
bool get_kernel () const throw () { return kernel; }
|
||||
bool get_is_vmlinux () const throw () { return is_vmlinux; }
|
||||
const std::string &get_name () const throw () { return name; }
|
||||
const std::string &get_name_short () const throw () { return name_short; }
|
||||
const _symbols_exported &get_symbols_exported () const throw () { return symbols_exported; }
|
||||
|
||||
protected:
|
||||
std::string name, name_short;
|
||||
bool kernel;
|
||||
bool is_vmlinux;
|
||||
_symbols_exported symbols_exported;
|
||||
|
||||
friend class modulelist;
|
||||
};
|
||||
|
||||
class module_real : public module
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, symbol_undefined> _symbols_undefined;
|
||||
|
||||
module_real (const std::string &filename, Elf::file *file) throw (std::runtime_error);
|
||||
|
||||
const Elf::symbol *_get_symbol (const std::string &name) const throw ();
|
||||
|
||||
void write (const modulelist &, bool modversions);
|
||||
|
||||
static module_real *open (const std::string &filename) throw (std::bad_alloc, std::runtime_error);
|
||||
|
||||
const static std::string symbol_name_cleanup;
|
||||
const static std::string symbol_name_init;
|
||||
const static std::string symbol_prefix_crc;
|
||||
const static std::string symbol_prefix_ksymtab;
|
||||
|
||||
protected:
|
||||
template<typename Elf_class>
|
||||
static module_real *open_class (const std::string &filename, Elf::file *) throw (std::bad_alloc, std::runtime_error);
|
||||
|
||||
void read_modinfo (Elf::section *) throw (std::runtime_error);
|
||||
void read_symtab (Elf::section_type<Elf::section_type_SYMTAB> *) throw (std::runtime_error);
|
||||
|
||||
void write_depends (std::ostream &, const modulelist &);
|
||||
void write_header (std::ostream &);
|
||||
void write_moddevtable (std::ostream &);
|
||||
void write_versions (std::ostream &, const modulelist &);
|
||||
|
||||
std::map<std::string, std::string> modinfo;
|
||||
_symbols_undefined symbols_undefined;
|
||||
bool has_init;
|
||||
bool has_cleanup;
|
||||
Elf::section_type<Elf::section_type_SYMTAB> *symtab;
|
||||
std::list<module_devicetable::table_base *> devicetables;
|
||||
|
||||
Elf::file *file;
|
||||
};
|
||||
|
||||
template <typename Elf_class, typename Elf_data>
|
||||
class module_data : public module_real
|
||||
{
|
||||
public:
|
||||
module_data (const std::string &filename, Elf::file *file) throw (std::runtime_error);
|
||||
};
|
||||
|
||||
class modulelist
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, module_real *> _modules_real;
|
||||
typedef std::pair<std::string, module_real *> _modules_real_pair;
|
||||
typedef std::map<std::string, module *> _modules_shadow;
|
||||
typedef std::pair<std::string, module *> _modules_shadow_pair;
|
||||
typedef std::map<std::string, std::string> _symbols;
|
||||
|
||||
modulelist () throw ();
|
||||
~modulelist () throw ();
|
||||
|
||||
void dump_read (const std::string &filename, bool kernel) throw (std::runtime_error);
|
||||
void dump_write (const std::string &filename, bool kernel) const throw (std::runtime_error);
|
||||
|
||||
const _modules_real &get_modules_real () const throw () { return modules_real; }
|
||||
const _modules_shadow &get_modules_shadow () const throw () { return modules_shadow; }
|
||||
const module *get_module (const std::string &name) const throw (std::out_of_range);
|
||||
const module *get_module_for_symbol (const symbolname &name) const throw (std::out_of_range);
|
||||
const std::string &get_module_name_short_for_symbol (const symbolname &name) const throw (std::out_of_range);
|
||||
const symbol_exported &get_symbol (const symbolname &name) const throw (std::out_of_range);
|
||||
const _symbols &get_symbols_exported () const throw () { return symbols_exported; }
|
||||
|
||||
void insert (module_real *) throw (std::runtime_error);
|
||||
void insert (const std::string &filename) throw (std::runtime_error);
|
||||
|
||||
void write (bool modversions);
|
||||
|
||||
bool report_symbols_missing;
|
||||
|
||||
protected:
|
||||
_modules_real modules_real;
|
||||
_modules_shadow modules_shadow;
|
||||
_symbols symbols_exported;
|
||||
};
|
||||
|
||||
class symbolname : public std::string
|
||||
{
|
||||
public:
|
||||
symbolname () throw () {}
|
||||
symbolname (const std::string &name) throw ()
|
||||
: std::string (name)
|
||||
{
|
||||
if (size () && at (0) == '.')
|
||||
erase (0, 1);
|
||||
}
|
||||
symbolname (const char *name) throw ()
|
||||
: std::string (name)
|
||||
{
|
||||
if (size () && at (0) == '.')
|
||||
erase (0, 1);
|
||||
}
|
||||
};
|
||||
|
||||
class symbol
|
||||
{
|
||||
public:
|
||||
symbol () throw () {}
|
||||
symbol (const symbolname &name) throw ();
|
||||
|
||||
const symbolname &get_name () const throw () { return name; }
|
||||
|
||||
protected:
|
||||
symbolname name;
|
||||
};
|
||||
|
||||
class symbol_exported : public symbol
|
||||
{
|
||||
public:
|
||||
symbol_exported () throw () {}
|
||||
symbol_exported (const symbolname &name) throw ();
|
||||
symbol_exported (const symbolname &name, uint32_t) throw ();
|
||||
|
||||
uint32_t get_crc () const throw () { return crc; }
|
||||
bool get_crc_valid () const throw () { return crc_valid; }
|
||||
void set_crc (uint32_t) throw ();
|
||||
|
||||
protected:
|
||||
uint32_t crc;
|
||||
bool crc_valid;
|
||||
};
|
||||
|
||||
class symbol_undefined : public symbol
|
||||
{
|
||||
public:
|
||||
symbol_undefined () throw () {}
|
||||
symbol_undefined (const symbolname &name, bool weak) throw ();
|
||||
|
||||
protected:
|
||||
bool weak;
|
||||
};
|
||||
}
|
||||
|
||||
#include "module_devicetable.tpp"
|
||||
|
||||
#undef DISABLE_TEMPLATES
|
||||
#endif
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* module_devicetable.cpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#include "module.hpp"
|
||||
#include "module_devicetable.hpp"
|
||||
|
||||
namespace linuxkernel
|
||||
{
|
||||
namespace module_devicetable
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
const std::string def<device_ccw>::symbol = "__mod_ccw_device_table";
|
||||
const std::string def<device_i2c>::symbol = "__mod_i2c_device_table";
|
||||
const std::string def<device_ieee1394>::symbol = "__mod_ieee1394_device_table";
|
||||
const std::string def<device_input>::symbol = "__mod_input_device_table";
|
||||
const std::string def<device_of>::symbol = "__mod_of_device_table";
|
||||
const std::string def<device_pci>::symbol = "__mod_pci_device_table";
|
||||
const std::string def<device_pcmcia>::symbol = "__mod_pcmcia_device_table";
|
||||
const std::string def<device_pnp>::symbol = "__mod_pnp_device_table";
|
||||
const std::string def<device_pnp_card>::symbol = "__mod_pnp_card_device_table";
|
||||
const std::string def<device_serio>::symbol = "__mod_serio_device_table";
|
||||
const std::string def<device_usb>::symbol = "__mod_usb_device_table";
|
||||
const std::string def<device_vio>::symbol = "__mod_vio_device_table";
|
||||
}
|
||||
|
||||
void table_base::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
for (std::list<table_entry *>::const_iterator it = entries.begin (); it != entries.end (); ++it)
|
||||
{
|
||||
out << "MODULE_ALIAS(\"";
|
||||
(*it)->write (out);
|
||||
out << "\");\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* module_devicetable.hpp
|
||||
*
|
||||
* Copyright (C) 2005, 2006 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#ifndef MODULE_DEVICETABLE_HPP
|
||||
#define MODULE_DEVICETABLE_HPP
|
||||
|
||||
#include "elf.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace linuxkernel
|
||||
{
|
||||
class module_real;
|
||||
|
||||
namespace module_devicetable
|
||||
{
|
||||
class device_ccw { };
|
||||
class device_i2c { };
|
||||
class device_ieee1394 { };
|
||||
class device_input { };
|
||||
class device_of { };
|
||||
class device_pci { };
|
||||
class device_pcmcia { };
|
||||
class device_pnp { };
|
||||
class device_pnp_card { };
|
||||
class device_serio { };
|
||||
class device_usb { };
|
||||
class device_vio { };
|
||||
|
||||
class version_2_6_16 { };
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template<typename device>
|
||||
struct def {};
|
||||
template<> struct def<device_ccw> { static const std::string symbol; };
|
||||
template<> struct def<device_i2c> { static const std::string symbol; };
|
||||
template<> struct def<device_ieee1394> { static const std::string symbol; };
|
||||
template<> struct def<device_input> { static const std::string symbol; };
|
||||
template<> struct def<device_of> { static const std::string symbol; };
|
||||
template<> struct def<device_pci> { static const std::string symbol; };
|
||||
template<> struct def<device_pcmcia> { static const std::string symbol; };
|
||||
template<> struct def<device_pnp> { static const std::string symbol; };
|
||||
template<> struct def<device_pnp_card> { static const std::string symbol; };
|
||||
template<> struct def<device_serio> { static const std::string symbol; };
|
||||
template<> struct def<device_usb> { static const std::string symbol; };
|
||||
template<> struct def<device_vio> { static const std::string symbol; };
|
||||
}
|
||||
|
||||
class table_entry
|
||||
{
|
||||
public:
|
||||
virtual ~table_entry () {};
|
||||
virtual void write (std::ostream &) const throw (std::runtime_error) = 0;
|
||||
};
|
||||
|
||||
template<typename device, typename version>
|
||||
class table_entry_version : public table_entry
|
||||
{
|
||||
};
|
||||
|
||||
template<typename device, typename version, typename Elf_class, typename Elf_data>
|
||||
class table_entry_data : public table_entry_version<device, version>
|
||||
{
|
||||
};
|
||||
|
||||
class table_base
|
||||
{
|
||||
public:
|
||||
virtual ~table_base () throw () {};
|
||||
|
||||
void write (std::ostream &out) const throw (std::runtime_error);
|
||||
|
||||
|
||||
protected:
|
||||
table_base () throw () {};
|
||||
|
||||
std::list<table_entry *> entries;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
void table_create (std::list<table_base *> &, const module_real *m, const Elf::file *f) throw (std::runtime_error);
|
||||
|
||||
template<typename device, typename Elf_class, typename Elf_data>
|
||||
class table : public table_base
|
||||
{
|
||||
public:
|
||||
static table_base *create (const module_real *m, const Elf::file *f) throw (std::runtime_error);
|
||||
|
||||
protected:
|
||||
table () {};
|
||||
};
|
||||
|
||||
template<typename device, typename version, typename Elf_class, typename Elf_data>
|
||||
class table_data : public table<device, Elf_class, Elf_data>
|
||||
{
|
||||
public:
|
||||
table_data (const void *, size_t) throw (std::runtime_error);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_TEMPLATES
|
||||
#include "module_devicetable.tpp"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* module_devicetable.tpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#ifndef MODULE_DEVICETABLE_TPP
|
||||
#define MODULE_DEVICETABLE_TPP
|
||||
|
||||
#include "module.hpp"
|
||||
|
||||
namespace linuxkernel
|
||||
{
|
||||
namespace module_devicetable
|
||||
{
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
void table_create (std::list<table_base *> &list, const module_real *m, const Elf::file *file) throw (std::runtime_error)
|
||||
{
|
||||
list.push_back (table<module_devicetable::device_ccw, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_i2c, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_ieee1394, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_input, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_of, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_pci, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_pcmcia, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_pnp, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_pnp_card, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_serio, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_usb, Elf_class, Elf_data>::create (m, file));
|
||||
list.push_back (table<module_devicetable::device_vio, Elf_class, Elf_data>::create (m, file));
|
||||
}
|
||||
|
||||
template<typename device, typename Elf_class, typename Elf_data>
|
||||
table_base *table<device, Elf_class, Elf_data>::create (const module_real *m, const Elf::file *f) throw (std::runtime_error)
|
||||
{
|
||||
const Elf::symbol *sym = m->_get_symbol (internal::def<device>::symbol);
|
||||
if (!sym)
|
||||
return 0;
|
||||
const Elf::section *sec = f->get_section (sym->get_shndx ());
|
||||
const char *mem = static_cast <const char *> (sec->_mem ());
|
||||
return new table_data<device, version_2_6_16, Elf_class, Elf_data> (mem + sym->get_value (), sym->get_size ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,403 +0,0 @@
|
|||
/*
|
||||
* module_devicetable_impl_2_6_16.cpp
|
||||
*
|
||||
* Copyright (C) 2005 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#include "module_devicetable_impl_2_6_16.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <stdint.h>
|
||||
#include <sstream>
|
||||
|
||||
using namespace linuxkernel::module_devicetable;
|
||||
|
||||
std::ostream &operator << (std::ostream &out, const identifier_value<uint8_t> &id) throw ()
|
||||
{
|
||||
char buf[4];
|
||||
snprintf (buf, sizeof (buf), "%02X", id.value);
|
||||
out << buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator << (std::ostream &out, const identifier_value<uint16_t> &id) throw ()
|
||||
{
|
||||
char buf[8];
|
||||
snprintf (buf, sizeof (buf), "%04X", id.value);
|
||||
out << buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator << (std::ostream &out, const identifier_value<uint32_t> &id) throw ()
|
||||
{
|
||||
char buf[12];
|
||||
snprintf (buf, sizeof (buf), "%08X", id.value);
|
||||
out << buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
table_entry_version<device_ccw, version_2_6_16>::table_entry_version () throw () :
|
||||
cu_type ("t"),
|
||||
dev_type ("m"),
|
||||
cu_model ("dt"),
|
||||
dev_model ("dm")
|
||||
{ }
|
||||
|
||||
void table_entry_version<device_ccw, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
out << "ccw:";
|
||||
cu_type.write (out, match_flags & CCW_DEVICE_ID_MATCH_CU_TYPE);
|
||||
cu_model.write (out, match_flags & CCW_DEVICE_ID_MATCH_CU_MODEL);
|
||||
dev_type.write (out, match_flags & CCW_DEVICE_ID_MATCH_DEVICE_TYPE);
|
||||
dev_model.write (out, match_flags & CCW_DEVICE_ID_MATCH_DEVICE_TYPE);
|
||||
}
|
||||
|
||||
table_entry_version<device_i2c, version_2_6_16>::table_entry_version () throw ()
|
||||
{
|
||||
}
|
||||
|
||||
void table_entry_version<device_i2c, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
|
||||
{
|
||||
}
|
||||
|
||||
table_entry_version<device_ieee1394, version_2_6_16>::table_entry_version () throw () :
|
||||
vendor_id ("ven"),
|
||||
model_id ("mo"),
|
||||
specifier_id ("sp"),
|
||||
version ("ver")
|
||||
{ }
|
||||
|
||||
void table_entry_version<device_ieee1394, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
out << "ieee1394:";
|
||||
vendor_id.write (out, match_flags & IEEE1394_MATCH_VENDOR_ID);
|
||||
model_id.write (out, match_flags & IEEE1394_MATCH_MODEL_ID);
|
||||
specifier_id.write (out, match_flags & IEEE1394_MATCH_SPECIFIER_ID);
|
||||
version.write (out, match_flags & IEEE1394_MATCH_VERSION, true);
|
||||
}
|
||||
|
||||
table_entry_version<device_input, version_2_6_16>::table_entry_version () throw ()
|
||||
{
|
||||
}
|
||||
|
||||
void table_entry_version<device_input, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
|
||||
{
|
||||
}
|
||||
|
||||
table_entry_version<device_of, version_2_6_16>::table_entry_version () throw ()
|
||||
{
|
||||
}
|
||||
|
||||
void table_entry_version<device_of, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
|
||||
{
|
||||
}
|
||||
|
||||
table_entry_version<device_pci, version_2_6_16>::table_entry_version () throw () :
|
||||
vendor ("v"),
|
||||
device ("d"),
|
||||
subvendor ("sv"),
|
||||
subdevice ("sd")
|
||||
{ }
|
||||
|
||||
void table_entry_version<device_pci, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
out << "pci:";
|
||||
vendor.write (out, vendor != PCI_ANY_ID);
|
||||
device.write (out, device != PCI_ANY_ID);
|
||||
subvendor.write (out, subvendor != PCI_ANY_ID);
|
||||
subdevice.write (out, subdevice != PCI_ANY_ID);
|
||||
|
||||
identifier<uint8_t> baseclass ("bc", class_id >> 16);
|
||||
identifier_value<uint8_t> baseclass_mask (class_mask >> 16);
|
||||
identifier<uint8_t> subclass ("sc", class_id >> 8);
|
||||
identifier_value<uint8_t> subclass_mask (class_mask >> 8);
|
||||
identifier<uint8_t> interface ("i", class_id);
|
||||
identifier_value<uint8_t> interface_mask (class_mask);
|
||||
|
||||
if ((baseclass_mask != 0 && baseclass_mask != 0xFF) ||
|
||||
(subclass_mask != 0 && subclass_mask != 0xFF) ||
|
||||
(interface_mask != 0 && interface_mask != 0xFF))
|
||||
throw std::runtime_error ("Can't handle masks");
|
||||
|
||||
baseclass.write (out, baseclass_mask == 0xFF);
|
||||
subclass.write (out, subclass_mask == 0xFF);
|
||||
interface.write (out, interface_mask == 0xFF, true);
|
||||
}
|
||||
|
||||
table_entry_version<device_pcmcia, version_2_6_16>::table_entry_version () throw ()
|
||||
{
|
||||
}
|
||||
|
||||
void table_entry_version<device_pcmcia, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
|
||||
{
|
||||
}
|
||||
|
||||
void table_entry_version<device_pnp, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
out << "pnp:" << str << '*';
|
||||
}
|
||||
|
||||
void table_entry_version<device_pnp_card, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
out << "pnp:" << str << '*';
|
||||
}
|
||||
|
||||
table_entry_version<device_serio, version_2_6_16>::table_entry_version () throw ()
|
||||
{
|
||||
}
|
||||
|
||||
void table_entry_version<device_serio, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
|
||||
{
|
||||
}
|
||||
|
||||
table_entry_version<device_usb, version_2_6_16>::table_entry_version () throw () :
|
||||
idVendor ("v"),
|
||||
idProduct ("p"),
|
||||
bDeviceClass ("dc"),
|
||||
bDeviceSubClass ("dsc"),
|
||||
bDeviceProtocol ("dp"),
|
||||
bInterfaceClass ("ic"),
|
||||
bInterfaceSubClass ("isc"),
|
||||
bInterfaceProtocol ("ip")
|
||||
{ }
|
||||
|
||||
void table_entry_version<device_usb, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
if (!idVendor && !bDeviceClass && !bInterfaceClass)
|
||||
return;
|
||||
|
||||
out << "usb:";
|
||||
idVendor.write (out, match_flags & USB_DEVICE_ID_MATCH_VENDOR);
|
||||
idProduct.write (out, match_flags & USB_DEVICE_ID_MATCH_PRODUCT);
|
||||
out << 'd';
|
||||
if (bcdDevice_initial_digits)
|
||||
{
|
||||
char buf[12];
|
||||
snprintf (buf, sizeof (buf), "%0*X", bcdDevice_initial_digits, bcdDevice_initial);
|
||||
out << buf;
|
||||
}
|
||||
if (range_lo == range_hi)
|
||||
out << static_cast<int> (range_lo);
|
||||
else if (range_lo > 0 || range_hi < 9)
|
||||
out << '[' << static_cast<int> (range_lo) << '-' << static_cast<int> (range_hi) << ']';
|
||||
if (bcdDevice_initial_digits < 3)
|
||||
out << '*';
|
||||
bDeviceClass.write (out, match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS);
|
||||
bDeviceSubClass.write (out, match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS);
|
||||
bDeviceProtocol.write (out, match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL);
|
||||
bInterfaceClass.write (out, match_flags & USB_DEVICE_ID_MATCH_INT_CLASS);
|
||||
bInterfaceSubClass.write (out, match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS);
|
||||
bInterfaceProtocol.write (out, match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL, true);
|
||||
}
|
||||
|
||||
void table_entry_version<device_vio, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
|
||||
{
|
||||
out << "vio:" << str << '*';
|
||||
}
|
||||
|
||||
#define _do_convert(name) name = Elf::convert<Elf_data, typeof (id.name)> () (id.name)
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_ccw, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_ccw, Elf_class> &id) throw ()
|
||||
{
|
||||
_do_convert (match_flags);
|
||||
_do_convert (cu_type);
|
||||
_do_convert (dev_type);
|
||||
_do_convert (cu_model);
|
||||
_do_convert (dev_model);
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_i2c, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_i2c, Elf_class> &id __attribute__ ((unused))) throw ()
|
||||
{
|
||||
throw std::runtime_error ("Not implemented: I2C");
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_ieee1394, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_ieee1394, Elf_class> &id) throw ()
|
||||
{
|
||||
_do_convert (match_flags);
|
||||
_do_convert (vendor_id);
|
||||
_do_convert (model_id);
|
||||
_do_convert (specifier_id);
|
||||
_do_convert (version);
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_input, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_input, Elf_class> &id __attribute__ ((unused))) throw ()
|
||||
{
|
||||
throw std::runtime_error ("Not implemented: INPUT");
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_of, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_of, Elf_class> &id __attribute__ ((unused))) throw ()
|
||||
{
|
||||
throw std::runtime_error ("Not implemented: OF");
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_pci, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pci, Elf_class> &id) throw ()
|
||||
{
|
||||
_do_convert (vendor);
|
||||
_do_convert (device);
|
||||
_do_convert (subvendor);
|
||||
_do_convert (subdevice);
|
||||
_do_convert (class_id);
|
||||
_do_convert (class_mask);
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_pcmcia, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pcmcia, Elf_class> &id __attribute__ ((unused))) throw ()
|
||||
{
|
||||
throw std::runtime_error ("Not implemented: PCMCIA");
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_pnp, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pnp, Elf_class> &id) throw ()
|
||||
{
|
||||
std::stringstream s;
|
||||
s << 'd';
|
||||
s << static_cast <const char *> (static_cast <const void *> (id.id));
|
||||
str = s.str ();
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_pnp_card, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pnp_card, Elf_class> &id) throw ()
|
||||
{
|
||||
std::stringstream s;
|
||||
s << 'c';
|
||||
s << static_cast <const char *> (static_cast <const void *> (id.id));
|
||||
for (int i = 0; i < PNP_MAX_DEVICES; i++)
|
||||
{
|
||||
if (! *id.devs[i].id)
|
||||
break;
|
||||
s << 'd';
|
||||
s << static_cast <const char *> (static_cast <const void *> (id.devs[i].id));
|
||||
}
|
||||
str = s.str ();
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_serio, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_serio, Elf_class> &id __attribute__((unused))) throw ()
|
||||
{
|
||||
throw std::runtime_error ("Not implemented: SERIO");
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_usb, Elf_class> &id, uint16_t _bcdDevice_initial, int _bcdDevice_initial_digits, unsigned char _range_lo, unsigned char _range_hi) throw ()
|
||||
{
|
||||
_do_convert (match_flags);
|
||||
_do_convert (idVendor);
|
||||
_do_convert (idProduct);
|
||||
_do_convert (bDeviceClass);
|
||||
_do_convert (bDeviceSubClass);
|
||||
_do_convert (bDeviceProtocol);
|
||||
_do_convert (bInterfaceClass);
|
||||
_do_convert (bInterfaceSubClass);
|
||||
_do_convert (bInterfaceProtocol);
|
||||
bcdDevice_initial = _bcdDevice_initial;
|
||||
bcdDevice_initial_digits = _bcdDevice_initial_digits;
|
||||
range_lo = _range_lo;
|
||||
range_hi = _range_hi;
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
void table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data>::add (const device_id<device_usb, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
uint16_t match_flags;
|
||||
uint16_t idVendor;
|
||||
uint16_t bcdDevice_lo = 0;
|
||||
uint16_t bcdDevice_hi = ~0;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bInterfaceClass;
|
||||
|
||||
_do_convert (match_flags);
|
||||
_do_convert (idVendor);
|
||||
if (match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
|
||||
_do_convert (bcdDevice_lo);
|
||||
if (match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
|
||||
_do_convert (bcdDevice_hi);
|
||||
_do_convert (bDeviceClass);
|
||||
_do_convert (bInterfaceClass);
|
||||
|
||||
if (!(idVendor | bDeviceClass | bInterfaceClass))
|
||||
return;
|
||||
|
||||
for (int ndigits = 3; bcdDevice_lo <= bcdDevice_hi; ndigits--)
|
||||
{
|
||||
unsigned char clo = bcdDevice_lo & 0xf;
|
||||
unsigned char chi = bcdDevice_hi & 0xf;
|
||||
|
||||
if (chi > 9) /* it's bcd not hex */
|
||||
chi = 9;
|
||||
|
||||
bcdDevice_lo >>= 4;
|
||||
bcdDevice_hi >>= 4;
|
||||
|
||||
if (bcdDevice_lo == bcdDevice_hi || !ndigits)
|
||||
{
|
||||
table.push_back (new table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> (id, bcdDevice_lo, ndigits, clo, chi));
|
||||
return;
|
||||
}
|
||||
|
||||
if (clo > 0)
|
||||
table.push_back (new table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> (id, bcdDevice_lo++, ndigits, clo, 9));
|
||||
|
||||
if (chi < 9)
|
||||
table.push_back (new table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> (id, bcdDevice_hi--, ndigits, 0, chi));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
table_entry_data<device_vio, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_vio, Elf_class> &id) throw ()
|
||||
{
|
||||
std::stringstream s;
|
||||
s << 'T' << (id.type[0] ? id.type : "*");
|
||||
s << 'S' << (id.compat[0] ? id.compat : "*");
|
||||
str = s.str ();
|
||||
}
|
||||
|
||||
template<typename device, typename Elf_class, typename Elf_data>
|
||||
table_data<device, version_2_6_16, Elf_class, Elf_data>::table_data (const void *mem, size_t size) throw (std::runtime_error)
|
||||
{
|
||||
if (size % sizeof (devin))
|
||||
throw std::runtime_error ("Bad size");
|
||||
size_t len = size / sizeof (devin);
|
||||
// Remove the terminator.
|
||||
len--;
|
||||
const devin *e = static_cast <const devin *> (mem);
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
table_entry_data<device, version_2_6_16, Elf_class, Elf_data>::add (e[i], this->entries);
|
||||
}
|
||||
|
||||
#define make_templates(name) \
|
||||
template class table_data<name, version_2_6_16, Elf::file_class_32, Elf::file_data_2LSB>; \
|
||||
template class table_data<name, version_2_6_16, Elf::file_class_32, Elf::file_data_2MSB>; \
|
||||
template class table_data<name, version_2_6_16, Elf::file_class_64, Elf::file_data_2LSB>; \
|
||||
template class table_data<name, version_2_6_16, Elf::file_class_64, Elf::file_data_2MSB>
|
||||
make_templates(device_ccw);
|
||||
make_templates(device_i2c);
|
||||
make_templates(device_ieee1394);
|
||||
make_templates(device_input);
|
||||
make_templates(device_of);
|
||||
make_templates(device_pci);
|
||||
make_templates(device_pcmcia);
|
||||
make_templates(device_pnp);
|
||||
make_templates(device_pnp_card);
|
||||
make_templates(device_serio);
|
||||
make_templates(device_usb);
|
||||
make_templates(device_vio);
|
|
@ -1,525 +0,0 @@
|
|||
/*
|
||||
* module_devicetable_impl_2_6_16.hpp
|
||||
*
|
||||
* Copyright (C) 2005, 2006 Bastian Blank <waldi@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.
|
||||
*/
|
||||
|
||||
#ifndef MODULE_DEVICETABLE_IMPL_2_6_16_HPP
|
||||
#define MODULE_DEVICETABLE_IMPL_2_6_16_HPP
|
||||
|
||||
#include "module_devicetable.hpp"
|
||||
|
||||
#include "elf.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace linuxkernel::module_devicetable;
|
||||
|
||||
template<typename _class>
|
||||
struct _elfdef
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct _elfdef<Elf::file_class_32>
|
||||
{
|
||||
typedef uint32_t pointer;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _elfdef<Elf::file_class_64>
|
||||
{
|
||||
typedef uint64_t pointer;
|
||||
};
|
||||
|
||||
template<typename device, typename Elf_class>
|
||||
struct device_id
|
||||
{ };
|
||||
|
||||
template<typename Elf_class>
|
||||
struct device_id<device_ccw, Elf_class>
|
||||
{
|
||||
uint16_t match_flags;
|
||||
uint16_t cu_type;
|
||||
uint16_t dev_type;
|
||||
uint8_t cu_model;
|
||||
uint8_t dev_model;
|
||||
typename _elfdef<Elf_class>::pointer driver_info;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CCW_DEVICE_ID_MATCH_CU_TYPE = 0x01,
|
||||
CCW_DEVICE_ID_MATCH_CU_MODEL = 0x02,
|
||||
CCW_DEVICE_ID_MATCH_DEVICE_TYPE = 0x04,
|
||||
CCW_DEVICE_ID_MATCH_DEVICE_MODEL = 0x08,
|
||||
};
|
||||
|
||||
template<typename Elf_class>
|
||||
struct device_id<device_i2c, Elf_class>
|
||||
{
|
||||
uint16_t id;
|
||||
};
|
||||
|
||||
template<typename Elf_class>
|
||||
struct device_id<device_ieee1394, Elf_class>
|
||||
{
|
||||
uint32_t match_flags;
|
||||
uint32_t vendor_id;
|
||||
uint32_t model_id;
|
||||
uint32_t specifier_id;
|
||||
uint32_t version;
|
||||
typename _elfdef<Elf_class>::pointer driver_info;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IEEE1394_MATCH_VENDOR_ID = 0x0001,
|
||||
IEEE1394_MATCH_MODEL_ID = 0x0002,
|
||||
IEEE1394_MATCH_SPECIFIER_ID = 0x0004,
|
||||
IEEE1394_MATCH_VERSION = 0x0008,
|
||||
};
|
||||
|
||||
template<typename Elf_class>
|
||||
struct device_id<device_pci, Elf_class>
|
||||
{
|
||||
uint32_t vendor, device;
|
||||
uint32_t subvendor, subdevice;
|
||||
uint32_t class_id, class_mask;
|
||||
typename _elfdef<Elf_class>::pointer driver_info;
|
||||
};
|
||||
|
||||
const unsigned int PCI_ANY_ID = ~0U;
|
||||
const int PNP_ID_LEN = 8;
|
||||
const int PNP_MAX_DEVICES = 8;
|
||||
|
||||
template <typename Elf_class>
|
||||
struct device_id<device_pnp, Elf_class>
|
||||
{
|
||||
uint8_t id[PNP_ID_LEN];
|
||||
typename _elfdef<Elf_class>::pointer driver_info;
|
||||
};
|
||||
|
||||
template <typename Elf_class>
|
||||
struct device_id<device_pnp_card, Elf_class>
|
||||
{
|
||||
uint8_t id[PNP_ID_LEN];
|
||||
typename _elfdef<Elf_class>::pointer driver_info;
|
||||
struct
|
||||
{
|
||||
uint8_t id[PNP_ID_LEN];
|
||||
}
|
||||
devs[PNP_MAX_DEVICES];
|
||||
};
|
||||
|
||||
template <typename Elf_class>
|
||||
struct device_id<device_serio, Elf_class>
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t extra;
|
||||
uint8_t id;
|
||||
uint8_t proto;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SERIO_DEVICE_ID_ANY = 0xff,
|
||||
};
|
||||
|
||||
template <typename Elf_class>
|
||||
struct device_id<device_usb, Elf_class>
|
||||
{
|
||||
uint16_t match_flags;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice_lo;
|
||||
uint16_t bcdDevice_hi;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
typename _elfdef<Elf_class>::pointer driver_info;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
USB_DEVICE_ID_MATCH_VENDOR = 0x0001,
|
||||
USB_DEVICE_ID_MATCH_PRODUCT = 0x0002,
|
||||
USB_DEVICE_ID_MATCH_DEV_LO = 0x0004,
|
||||
USB_DEVICE_ID_MATCH_DEV_HI = 0x0008,
|
||||
USB_DEVICE_ID_MATCH_DEV_CLASS = 0x0010,
|
||||
USB_DEVICE_ID_MATCH_DEV_SUBCLASS = 0x0020,
|
||||
USB_DEVICE_ID_MATCH_DEV_PROTOCOL = 0x0040,
|
||||
USB_DEVICE_ID_MATCH_INT_CLASS = 0x0080,
|
||||
USB_DEVICE_ID_MATCH_INT_SUBCLASS = 0x0100,
|
||||
USB_DEVICE_ID_MATCH_INT_PROTOCOL = 0x0200,
|
||||
};
|
||||
|
||||
template<typename Elf_class>
|
||||
struct device_id<device_vio, Elf_class>
|
||||
{
|
||||
char type[32];
|
||||
char compat[32];
|
||||
};
|
||||
|
||||
template<typename type>
|
||||
class identifier_value
|
||||
{
|
||||
public:
|
||||
type value;
|
||||
|
||||
identifier_value () : value (0) { }
|
||||
identifier_value (const type &value) : value (value) { }
|
||||
const type &operator = (const type &_value) { value = _value; return value; }
|
||||
bool operator ! () const { return !value; }
|
||||
operator type () const { return value; }
|
||||
template<typename Elf_data>
|
||||
void set (const type _value)
|
||||
{ value = Elf::convert<Elf_data, type> () (_value); }
|
||||
};
|
||||
|
||||
template<typename type>
|
||||
class identifier
|
||||
{
|
||||
public:
|
||||
identifier_value<type> value;
|
||||
std::string sep;
|
||||
|
||||
identifier (const std::string &sep) : sep (sep) { }
|
||||
identifier (const std::string &sep, const type &value) : value (value), sep (sep) { }
|
||||
const type &operator = (const type &_value) { value = _value; return value.value; }
|
||||
bool operator ! () const { return !value; }
|
||||
operator type () const { return value; }
|
||||
void write (std::ostream &out, bool enable, bool last = false) const
|
||||
{
|
||||
out << sep;
|
||||
if (enable)
|
||||
{
|
||||
out << value;
|
||||
if (last)
|
||||
out << '*';
|
||||
}
|
||||
else
|
||||
out << '*';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream &operator << (std::ostream &out, const identifier_value<uint8_t> &id) throw ();
|
||||
std::ostream &operator << (std::ostream &out, const identifier_value<uint16_t> &id) throw ();
|
||||
std::ostream &operator << (std::ostream &out, const identifier_value<uint32_t> &id) throw ();
|
||||
|
||||
namespace linuxkernel
|
||||
{
|
||||
namespace module_devicetable
|
||||
{
|
||||
template<>
|
||||
class table_entry_version<device_ccw, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
|
||||
identifier_value<uint16_t> match_flags;
|
||||
identifier<uint16_t> cu_type;
|
||||
identifier<uint16_t> dev_type;
|
||||
identifier<uint8_t> cu_model;
|
||||
identifier<uint8_t> dev_model;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_ccw, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_ccw, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_ccw, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_ccw, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_ccw, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_i2c, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_i2c, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_i2c, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_i2c, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_i2c, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_i2c, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_ieee1394, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
|
||||
identifier_value<uint32_t> match_flags;
|
||||
identifier<uint32_t> vendor_id;
|
||||
identifier<uint32_t> model_id;
|
||||
identifier<uint32_t> specifier_id;
|
||||
identifier<uint32_t> version;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_ieee1394, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_ieee1394, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_ieee1394, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_ieee1394, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_ieee1394, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_input, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_input, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_input, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_input, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_input, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_input, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_of, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_of, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_of, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_of, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_of, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_of, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_pci, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
|
||||
identifier<uint32_t> vendor, device;
|
||||
identifier<uint32_t> subvendor, subdevice;
|
||||
identifier_value<uint32_t> class_id, class_mask;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_pci, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pci, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_pci, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_pci, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_pci, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_pcmcia, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_pcmcia, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pcmcia, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_pcmcia, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_pcmcia, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_pcmcia, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_pnp, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
|
||||
std::string str;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_pnp, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pnp, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_pnp, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_pnp, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_pnp, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_pnp_card, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
|
||||
std::string str;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_pnp_card, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pnp_card, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_pnp_card, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_pnp_card, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_pnp_card, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_serio, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_serio, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_serio, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_serio, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_serio, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_serio, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_usb, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
table_entry_version () throw ();
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
|
||||
identifier_value<uint16_t> match_flags;
|
||||
identifier<uint16_t> idVendor;
|
||||
identifier<uint16_t> idProduct;
|
||||
unsigned int bcdDevice_initial;
|
||||
int bcdDevice_initial_digits;
|
||||
unsigned char range_lo;
|
||||
unsigned char range_hi;
|
||||
identifier<uint8_t> bDeviceClass;
|
||||
identifier<uint8_t> bDeviceSubClass;
|
||||
identifier<uint8_t> bDeviceProtocol;
|
||||
identifier<uint8_t> bInterfaceClass;
|
||||
identifier<uint8_t> bInterfaceSubClass;
|
||||
identifier<uint8_t> bInterfaceProtocol;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_usb, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_usb, Elf_class> &, uint16_t bcdDevice_initial, int bcdDevice_initial_digits, unsigned char range_lo, unsigned char range_hi) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_usb, Elf_class> &, std::list<table_entry *> &table) throw ();
|
||||
};
|
||||
|
||||
template<>
|
||||
class table_entry_version<device_vio, version_2_6_16> : public table_entry
|
||||
{
|
||||
public:
|
||||
void write (std::ostream &) const throw (std::runtime_error);
|
||||
|
||||
std::string str;
|
||||
};
|
||||
|
||||
template<typename Elf_class, typename Elf_data>
|
||||
class table_entry_data<device_vio, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_vio, version_2_6_16>
|
||||
{
|
||||
protected:
|
||||
table_entry_data (const device_id<device_vio, Elf_class> &) throw ();
|
||||
|
||||
public:
|
||||
static void add (const device_id<device_vio, Elf_class> &id, std::list<table_entry *> &table) throw ()
|
||||
{
|
||||
table.push_back (new table_entry_data<device_vio, version_2_6_16, Elf_class, Elf_data> (id));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename device, typename Elf_class, typename Elf_data>
|
||||
class table_data<device, version_2_6_16, Elf_class, Elf_data> : public table<device, Elf_class, Elf_data>
|
||||
{
|
||||
protected:
|
||||
typedef device_id<device, Elf_class> devin;
|
||||
|
||||
public:
|
||||
table_data (const void *mem, size_t size) throw (std::runtime_error);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#define KERNEL_ELFCLASS ELFCLASS32
|
||||
#define KERNEL_ELFDATA ELFDATA2LSB
|
||||
#define MODULE_SYMBOL_PREFIX ""
|
||||
#include "../elfconfig.h"
|
|
@ -0,0 +1,4 @@
|
|||
#define KERNEL_ELFCLASS ELFCLASS64
|
||||
#define KERNEL_ELFDATA ELFDATA2LSB
|
||||
#define MODULE_SYMBOL_PREFIX ""
|
||||
#include "../elfconfig.h"
|
|
@ -0,0 +1,4 @@
|
|||
#define KERNEL_ELFCLASS ELFCLASS32
|
||||
#define KERNEL_ELFDATA ELFDATA2MSB
|
||||
#define MODULE_SYMBOL_PREFIX ""
|
||||
#include "../elfconfig.h"
|
|
@ -0,0 +1,4 @@
|
|||
#define KERNEL_ELFCLASS ELFCLASS64
|
||||
#define KERNEL_ELFDATA ELFDATA2MSB
|
||||
#define MODULE_SYMBOL_PREFIX ""
|
||||
#include "../elfconfig.h"
|
Loading…
Reference in New Issue