/dists/trunk/linux-kbuild-2.6: Add.
svn path=/dists/trunk/linux-kbuild-2.6/; revision=6325
This commit is contained in:
commit
4b9ae46e44
|
@ -0,0 +1,153 @@
|
|||
#!/usr/bin/env python2.4
|
||||
import sys
|
||||
sys.path.append("debian/lib/python")
|
||||
import warnings
|
||||
from debian_linux.debian import *
|
||||
from debian_linux.utils import *
|
||||
|
||||
class packages_list(sorted_dict):
|
||||
def append(self, package):
|
||||
self[package['Package']] = package
|
||||
|
||||
def extend(self, packages):
|
||||
for package in packages:
|
||||
self[package['Package']] = package
|
||||
|
||||
class gencontrol(object):
|
||||
makefile_targets = ('binary-arch', 'build')
|
||||
|
||||
def __init__(self, underlay = None):
|
||||
self.changelog = read_changelog()
|
||||
self.templates = templates()
|
||||
self.version, self.changelog_vars = self.process_changelog({})
|
||||
|
||||
def __call__(self):
|
||||
packages = packages_list()
|
||||
makefile = []
|
||||
|
||||
self.do_source(packages)
|
||||
self.do_main(packages, makefile)
|
||||
|
||||
self.write_control(packages.itervalues())
|
||||
self.write_makefile(makefile)
|
||||
|
||||
def do_source(self, packages):
|
||||
source = self.templates["control.source"]
|
||||
packages['source'] = self.process_package(source[0], self.changelog_vars)
|
||||
|
||||
def do_main(self, packages, makefile):
|
||||
makeflags = {
|
||||
'VERSION': self.version['version'],
|
||||
'SOURCE_UPSTREAM': self.version['source_upstream'],
|
||||
'SOURCEVERSION': self.version['source'],
|
||||
'UPSTREAMVERSION': self.version['upstream'],
|
||||
}
|
||||
|
||||
vars = self.changelog_vars.copy()
|
||||
|
||||
self.do_main_setup(vars, makeflags)
|
||||
self.do_main_packages(packages)
|
||||
self.do_main_makefile(makefile, makeflags)
|
||||
|
||||
def do_main_setup(self, vars, makeflags):
|
||||
pass
|
||||
|
||||
def do_main_makefile(self, makefile, makeflags):
|
||||
makeflags_string = ' '.join(["%s='%s'" % i for i in makeflags.iteritems()])
|
||||
|
||||
for i in self.makefile_targets:
|
||||
makefile.append(("%s:" % i, ("$(MAKE) -f debian/rules.real %s %s" % (i, makeflags_string))))
|
||||
|
||||
def do_main_packages(self, packages):
|
||||
vars = self.changelog_vars
|
||||
|
||||
main = self.templates["control.main"]
|
||||
packages.extend(self.process_packages(main, vars))
|
||||
|
||||
def process_changelog(self, in_vars):
|
||||
ret = [None, None]
|
||||
ret[0] = version = self.changelog[0]['Version']
|
||||
vars = in_vars.copy()
|
||||
vars['upstreamversion'] = version['upstream']
|
||||
vars['version'] = version['version']
|
||||
vars['source_upstream'] = version['source_upstream']
|
||||
vars['major'] = version['major']
|
||||
ret[1] = vars
|
||||
return ret
|
||||
|
||||
def process_relation(self, key, e, in_e, vars):
|
||||
in_dep = in_e[key]
|
||||
dep = package_relation_list()
|
||||
for in_groups in in_dep:
|
||||
groups = package_relation_group()
|
||||
for in_item in in_groups:
|
||||
item = package_relation()
|
||||
item.name = self.substitute(in_item.name, vars)
|
||||
if in_item.version is not None:
|
||||
item.version = self.substitute(in_item.version, vars)
|
||||
item.arches = in_item.arches
|
||||
groups.append(item)
|
||||
dep.append(groups)
|
||||
e[key] = dep
|
||||
|
||||
def process_description(self, e, in_e, vars):
|
||||
in_desc = in_e['Description']
|
||||
desc = in_desc.__class__()
|
||||
desc.short = self.substitute(in_desc.short, vars)
|
||||
for i in in_desc.long:
|
||||
desc.long.append(self.substitute(i, vars))
|
||||
e['Description'] = desc
|
||||
|
||||
def process_package(self, in_entry, vars):
|
||||
e = package()
|
||||
for key, value in in_entry.iteritems():
|
||||
if isinstance(value, package_relation_list):
|
||||
self.process_relation(key, e, in_entry, vars)
|
||||
elif key == 'Description':
|
||||
self.process_description(e, in_entry, vars)
|
||||
elif key[:2] == 'X-':
|
||||
pass
|
||||
else:
|
||||
e[key] = self.substitute(value, vars)
|
||||
return e
|
||||
|
||||
def process_packages(self, in_entries, vars):
|
||||
entries = []
|
||||
for i in in_entries:
|
||||
entries.append(self.process_package(i, vars))
|
||||
return entries
|
||||
|
||||
def substitute(self, s, vars):
|
||||
if isinstance(s, (list, tuple)):
|
||||
for i in xrange(len(s)):
|
||||
s[i] = self.substitute(s[i], vars)
|
||||
return s
|
||||
def subst(match):
|
||||
return vars[match.group(1)]
|
||||
return re.sub(r'@([a-z_]+)@', subst, s)
|
||||
|
||||
def write_control(self, list):
|
||||
self.write_rfc822(file("debian/control", 'w'), list)
|
||||
|
||||
def write_makefile(self, out_list):
|
||||
out = file("debian/rules.gen", 'w')
|
||||
for item in out_list:
|
||||
if isinstance(item, (list, tuple)):
|
||||
out.write("%s\n" % item[0])
|
||||
cmd_list = item[1]
|
||||
if isinstance(cmd_list, basestring):
|
||||
cmd_list = cmd_list.split('\n')
|
||||
for j in cmd_list:
|
||||
out.write("\t%s\n" % j)
|
||||
else:
|
||||
out.write("%s\n" % item)
|
||||
|
||||
def write_rfc822(self, f, list):
|
||||
for entry in list:
|
||||
for key, value in entry.iteritems():
|
||||
f.write("%s: %s\n" % (key, value))
|
||||
f.write('\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
gencontrol()()
|
|
@ -0,0 +1,5 @@
|
|||
linux-kbuild-2.6 (2.6.16-1) UNRELEASED; urgency=low
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Bastian Blank <waldi@debian.org> Mon, 27 Mar 2006 19:06:30 +0200
|
|
@ -0,0 +1 @@
|
|||
4
|
|
@ -0,0 +1,3 @@
|
|||
from debian import *
|
||||
from utils import *
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
import itertools, os.path, re, utils
|
||||
|
||||
def read_changelog(dir = ''):
|
||||
r = re.compile(r"""
|
||||
^
|
||||
(
|
||||
(?P<header>
|
||||
(?P<header_source>
|
||||
\w[-+0-9a-z.]+
|
||||
)
|
||||
\
|
||||
\(
|
||||
(?P<header_version>
|
||||
[^\(\)\ \t]+
|
||||
)
|
||||
\)
|
||||
\s+
|
||||
(?P<header_distribution>
|
||||
[-0-9a-zA-Z]+
|
||||
)
|
||||
\;
|
||||
)
|
||||
)
|
||||
""", re.VERBOSE)
|
||||
f = file(os.path.join(dir, "debian/changelog"))
|
||||
entries = []
|
||||
act_upstream = None
|
||||
while True:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.strip('\n')
|
||||
match = r.match(line)
|
||||
if not match:
|
||||
continue
|
||||
if match.group('header'):
|
||||
e = {}
|
||||
e['Distribution'] = match.group('header_distribution')
|
||||
e['Source'] = match.group('header_source')
|
||||
version = parse_version(match.group('header_version'))
|
||||
e['Version'] = version
|
||||
if act_upstream is None:
|
||||
act_upstream = version['upstream']
|
||||
elif version['upstream'] != act_upstream:
|
||||
break
|
||||
entries.append(e)
|
||||
return entries
|
||||
|
||||
def parse_version(version):
|
||||
version_re = ur"""
|
||||
^
|
||||
(?P<source>
|
||||
(?P<parent>
|
||||
\d+\.\d+\.\d+\+
|
||||
)?
|
||||
(?P<upstream>
|
||||
(?P<version>
|
||||
(?P<major>\d+\.\d+)
|
||||
\.
|
||||
\d+
|
||||
)
|
||||
(?:
|
||||
-
|
||||
(?P<modifier>
|
||||
.+?
|
||||
)
|
||||
)?
|
||||
)
|
||||
-
|
||||
(?P<debian>[^-]+)
|
||||
)
|
||||
$
|
||||
"""
|
||||
match = re.match(version_re, version, re.X)
|
||||
if match is None:
|
||||
raise ValueError
|
||||
ret = match.groupdict()
|
||||
if ret['parent'] is not None:
|
||||
ret['source_upstream'] = ret['parent'] + ret['upstream']
|
||||
else:
|
||||
ret['source_upstream'] = ret['upstream']
|
||||
return ret
|
||||
|
||||
class package_description(object):
|
||||
__slots__ = "short", "long"
|
||||
|
||||
def __init__(self, value = None):
|
||||
if value is not None:
|
||||
self.short, long = value.split ("\n", 1)
|
||||
self.long = long.split ("\n.\n")
|
||||
else:
|
||||
self.short = None
|
||||
self.long = []
|
||||
|
||||
def __str__(self):
|
||||
ret = self.short + '\n'
|
||||
w = utils.wrap(width = 74, fix_sentence_endings = True)
|
||||
pars = []
|
||||
for i in self.long:
|
||||
pars.append('\n '.join(w.wrap(i)))
|
||||
return self.short + '\n ' + '\n .\n '.join(pars)
|
||||
|
||||
class package_relation(object):
|
||||
__slots__ = "name", "version", "arches"
|
||||
|
||||
_re = re.compile(r'^(\S+)(?: \(([^)]+)\))?(?: \[([^]]+)\])?$')
|
||||
|
||||
def __init__(self, value = None):
|
||||
if value is not None:
|
||||
match = self._re.match(value)
|
||||
if match is None:
|
||||
raise RuntimeError, "Can't parse dependency %s" % value
|
||||
match = match.groups()
|
||||
self.name = match[0]
|
||||
self.version = match[1]
|
||||
if match[2] is not None:
|
||||
self.arches = re.split('\s+', match[2])
|
||||
else:
|
||||
self.arches = []
|
||||
else:
|
||||
self.name = None
|
||||
self.version = None
|
||||
self.arches = []
|
||||
|
||||
def __str__(self):
|
||||
ret = [self.name]
|
||||
if self.version is not None:
|
||||
ret.extend([' (', self.version, ')'])
|
||||
if self.arches:
|
||||
ret.extend([' [', ' '.join(self.arches), ']'])
|
||||
return ''.join(ret)
|
||||
|
||||
class package_relation_list(list):
|
||||
def __init__(self, value = None):
|
||||
if isinstance(value, (list, tuple)):
|
||||
self.extend(value)
|
||||
elif value is not None:
|
||||
self.extend(value)
|
||||
|
||||
def __str__(self):
|
||||
return ', '.join([str(i) for i in self])
|
||||
|
||||
def _match(self, value):
|
||||
for i in self:
|
||||
if i._match(value):
|
||||
return i
|
||||
return None
|
||||
|
||||
def extend(self, value):
|
||||
if isinstance(value, basestring):
|
||||
value = [package_relation_group(j.strip()) for j in re.split(',', value.strip())]
|
||||
for i in value:
|
||||
if isinstance(i, basestring):
|
||||
i = package_relation_group(i)
|
||||
j = self._match(i)
|
||||
if j:
|
||||
j._update_arches(i)
|
||||
else:
|
||||
self.append(i)
|
||||
|
||||
class package_relation_group(list):
|
||||
def __init__(self, value = None):
|
||||
if isinstance(value, package_relation_list):
|
||||
self.extend(value)
|
||||
elif value is not None:
|
||||
self._extend(value)
|
||||
|
||||
def __str__(self):
|
||||
return ' | '.join([str(i) for i in self])
|
||||
|
||||
def _extend(self, value):
|
||||
self.extend([package_relation(j.strip()) for j in re.split('\|', value.strip())])
|
||||
|
||||
def _match(self, value):
|
||||
for i, j in itertools.izip(self, value):
|
||||
if i.name != j.name or i.version != j.version:
|
||||
return None
|
||||
return self
|
||||
|
||||
def _update_arches(self, value):
|
||||
for i, j in itertools.izip(self, value):
|
||||
if i.arches:
|
||||
for arch in j.arches:
|
||||
if arch not in i.arches:
|
||||
i.arches.append(arch)
|
||||
|
||||
class package(dict):
|
||||
_fields = utils.sorted_dict((
|
||||
('Package', str),
|
||||
('Source', str),
|
||||
('Architecture', utils.field_list),
|
||||
('Section', str),
|
||||
('Priority', str),
|
||||
('Maintainer', str),
|
||||
('Uploaders', str),
|
||||
('Standards-Version', str),
|
||||
('Build-Depends', package_relation_list),
|
||||
('Build-Depends-Indep', package_relation_list),
|
||||
('Provides', package_relation_list),
|
||||
('Depends', package_relation_list),
|
||||
('Recommends', package_relation_list),
|
||||
('Suggests', package_relation_list),
|
||||
('Replaces', package_relation_list),
|
||||
('Conflicts', package_relation_list),
|
||||
('Reverse-Depends', package_relation_list), # Some sort of hack
|
||||
('Description', package_description),
|
||||
))
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
try:
|
||||
cls = self._fields[key]
|
||||
if not isinstance(value, cls):
|
||||
value = cls(value)
|
||||
except KeyError: pass
|
||||
super(package, self).__setitem__(key, value)
|
||||
|
||||
def iterkeys(self):
|
||||
for i in self._fields.iterkeys():
|
||||
if self.has_key(i) and self[i]:
|
||||
yield i
|
||||
|
||||
def iteritems(self):
|
||||
for i in self._fields.iterkeys():
|
||||
if self.has_key(i) and self[i]:
|
||||
yield (i, self[i])
|
||||
|
||||
def itervalues(self):
|
||||
for i in self._fields.iterkeys():
|
||||
if self.has_key(i) and self[i]:
|
||||
yield self[i]
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import debian, re, textwrap
|
||||
|
||||
class sorted_dict(dict):
|
||||
__slots__ = '_list',
|
||||
|
||||
def __init__(self, entries = None):
|
||||
super(sorted_dict, self).__init__()
|
||||
self._list = []
|
||||
if entries is not None:
|
||||
for key, value in entries:
|
||||
self[key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
super(sorted_dict, self).__delitem__(key)
|
||||
self._list.remove(key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
super(sorted_dict, self).__setitem__(key, value)
|
||||
if key not in self._list:
|
||||
self._list.append(key)
|
||||
|
||||
def iterkeys(self):
|
||||
for i in iter(self._list):
|
||||
yield i
|
||||
|
||||
def iteritems(self):
|
||||
for i in iter(self._list):
|
||||
yield (i, self[i])
|
||||
|
||||
def itervalues(self):
|
||||
for i in iter(self._list):
|
||||
yield self[i]
|
||||
|
||||
class field_list(list):
|
||||
TYPE_WHITESPACE = object()
|
||||
TYPE_COMMATA = object()
|
||||
|
||||
def __init__(self, value = None, type = TYPE_WHITESPACE):
|
||||
self.type = type
|
||||
if isinstance(value, field_list):
|
||||
self.type = value.type
|
||||
self.extend(value)
|
||||
elif isinstance(value, (list, tuple)):
|
||||
self.extend(value)
|
||||
else:
|
||||
self._extend(value)
|
||||
|
||||
def __str__(self):
|
||||
if self.type is self.TYPE_WHITESPACE:
|
||||
type = ' '
|
||||
elif self.type is self.TYPE_COMMATA:
|
||||
type = ', '
|
||||
return type.join(self)
|
||||
|
||||
def _extend(self, value):
|
||||
if self.type is self.TYPE_WHITESPACE:
|
||||
type = '\s'
|
||||
elif self.type is self.TYPE_COMMATA:
|
||||
type = ','
|
||||
if value is not None:
|
||||
self.extend([j.strip() for j in re.split(type, value.strip())])
|
||||
|
||||
def extend(self, value):
|
||||
if isinstance(value, str):
|
||||
self._extend(value)
|
||||
else:
|
||||
super(field_list, self).extend(value)
|
||||
|
||||
class field_list_commata(field_list):
|
||||
def __init__(self, value = None):
|
||||
super(field_list_commata, self).__init__(value, field_list.TYPE_COMMATA)
|
||||
|
||||
class field_string(str):
|
||||
def __str__(self):
|
||||
return '\n '.join(self.split('\n'))
|
||||
|
||||
class templates(dict):
|
||||
def __init__(self, dir = None):
|
||||
if dir is None:
|
||||
self.dir = "debian/templates"
|
||||
else:
|
||||
self.dir = dir
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return dict.__getitem__(self, key)
|
||||
except KeyError: pass
|
||||
ret = self._read(key)
|
||||
dict.__setitem__(self, key, ret)
|
||||
return ret
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
raise NotImplemented()
|
||||
|
||||
def _read(self, filename):
|
||||
entries = []
|
||||
|
||||
f = file("%s/%s.in" % (self.dir, filename))
|
||||
|
||||
while True:
|
||||
e = debian.package()
|
||||
last = None
|
||||
lines = []
|
||||
while True:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.strip('\n')
|
||||
if not line:
|
||||
break
|
||||
if line[0] in ' \t':
|
||||
if not last:
|
||||
raise ValueError('Continuation line seen before first header')
|
||||
lines.append(line.lstrip())
|
||||
continue
|
||||
if last:
|
||||
e[last] = '\n'.join(lines)
|
||||
i = line.find(':')
|
||||
if i < 0:
|
||||
raise ValueError("Not a header, not a continuation: ``%s''" % line)
|
||||
last = line[:i]
|
||||
lines = [line[i+1:].lstrip()]
|
||||
if last:
|
||||
e[last] = '\n'.join(lines)
|
||||
if not e:
|
||||
break
|
||||
|
||||
entries.append(e)
|
||||
|
||||
return entries
|
||||
|
||||
class wrap(textwrap.TextWrapper):
|
||||
wordsep_re = re.compile(
|
||||
r'(\s+|' # any whitespace
|
||||
r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/make -f
|
||||
SHELL := sh -e
|
||||
DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH)
|
||||
DEB_BUILD_ARCH := $(shell dpkg-architecture -qDEB_BUILD_ARCH)
|
||||
srcver := $(shell dpkg-parsechangelog | awk '/^Version:/ {print $$2}')
|
||||
VERSION := $(shell echo $(srcver) | sed -e 's,-[^-]*$$,,')
|
||||
MAJOR := $(word 1,$(subst ., ,$(VERSION))).$(word 2,$(subst ., ,$(VERSION)))
|
||||
|
||||
include debian/rules.defs
|
||||
|
||||
build: debian/control $(STAMPS_DIR)/build-base
|
||||
$(STAMPS_DIR)/build-base: $(BUILD_DIR) $(STAMPS_DIR)
|
||||
dh_testdir
|
||||
$(MAKE) -f debian/rules.gen build
|
||||
touch $@
|
||||
|
||||
$(BUILD_DIR) $(STAMPS_DIR):
|
||||
@[ -d $@ ] || mkdir $@
|
||||
|
||||
orig: ../orig/linux-kbuild-$(MAJOR)-$(VERSION)
|
||||
rsync --delete --exclude debian --exclude .svn --link-dest=$^/ -av $^/ .
|
||||
|
||||
../orig/linux-kbuild-$(MAJOR)-$(VERSION):
|
||||
if [ -f "../linux-kbuild-$(MAJOR)_$(VERSION).orig.tar.gz" ]; then \
|
||||
mkdir -p ../orig; \
|
||||
tar -C ../orig -xzf ../linux-kbuild-$(MAJOR)_$(VERSION).orig.tar.gz; \
|
||||
else \
|
||||
echo "Can't find orig tarball." >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
maintainerclean:
|
||||
-rm debian/control debian/control.md5sum debian/rules.gen
|
||||
-rm -rf scripts
|
||||
|
||||
clean: debian/control
|
||||
dh_testdir
|
||||
rm -rf $(BUILD_DIR) $(STAMPS_DIR) debian/lib/python/debian_linux/*.pyc
|
||||
dh_clean
|
||||
|
||||
binary-indep:
|
||||
dh_testdir
|
||||
$(MAKE) -f debian/rules.gen binary-indep
|
||||
|
||||
binary-arch:
|
||||
dh_testdir
|
||||
$(MAKE) -f debian/rules.gen binary-arch
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
|
||||
CONTROL_FILES = debian/changelog $(wildcard debian/templates/control.*)
|
||||
debian/control debian/rules.gen: debian/bin/gencontrol.py $(CONTROL_FILES)
|
||||
if [ -f debian/control.md5sum ]; then \
|
||||
if md5sum $^ | diff - debian/control.md5sum > /dev/null; then true; else \
|
||||
$(MAKE) -f debian/rules debian/control-real; \
|
||||
fi \
|
||||
else \
|
||||
$(MAKE) -f debian/rules debian/control-real; \
|
||||
fi
|
||||
|
||||
debian/control-real: debian/bin/gencontrol.py $(CONTROL_FILES)
|
||||
chmod +x $<
|
||||
$<
|
||||
md5sum $^ > debian/control.md5sum
|
||||
@echo
|
||||
@echo This target is made to fail intentionally, to make sure
|
||||
@echo that it is NEVER run during the automated build. Please
|
||||
@echo ignore the following error, the debian/control file has
|
||||
@echo been generated SUCCESSFULLY.
|
||||
@echo
|
||||
exit 1
|
||||
|
||||
.PHONY: clean build setup binary-indep binary-arch binary
|
|
@ -0,0 +1,4 @@
|
|||
BUILD_DIR = debian/build
|
||||
STAMPS_DIR = debian/stamps
|
||||
TEMPLATES_DIR = debian/templates
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
export DH_OPTIONS
|
||||
|
||||
include debian/rules.defs
|
||||
|
||||
binary-arch: install-kbuild
|
||||
|
||||
build: $(STAMPS_DIR)/build
|
||||
|
||||
$(STAMPS_DIR)/build: DIR=$(BUILD_DIR)/build
|
||||
$(STAMPS_DIR)/build:
|
||||
rm -rf '$(DIR)'
|
||||
mkdir -p '$(DIR)'
|
||||
cp -al src/* '$(DIR)'
|
||||
make -C $(DIR) top_srcdir=$(CURDIR)
|
||||
touch '$@'
|
||||
|
||||
install-kbuild: PACKAGE_NAME = linux-kbuild-$(VERSION)
|
||||
install-kbuild: DH_OPTIONS = -p$(PACKAGE_NAME)
|
||||
install-kbuild: BASE_DIR = /usr/src/$(PACKAGE_NAME)
|
||||
install-kbuild: SOURCE_DIR = $(BUILD_DIR)/build
|
||||
install-kbuild: DIR = $(CURDIR)/debian/$(PACKAGE_NAME)/$(BASE_DIR)
|
||||
install-kbuild: $(STAMPS_DIR)/build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k -d
|
||||
make -C $(SOURCE_DIR) install prefix=$(DIR) top_srcdir=$(CURDIR)
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
Package: linux-kbuild-@version@
|
||||
Architecture: any
|
||||
Section: devel
|
||||
Priority: optional
|
||||
Provides: linux-kbuild, linux-kbuild-@major@
|
||||
Description: Linux kernel
|
||||
Kbuild
|
|
@ -0,0 +1,7 @@
|
|||
Source: linux-kbuild-@major@
|
||||
Section: devel
|
||||
Priority: optional
|
||||
Maintainer: Debian Kernel Team <debian-kernel@lists.debian.org>
|
||||
Uploaders: Bastian Blank <waldi@debian.org>
|
||||
Standards-Version: 3.6.2.0
|
||||
Build-Depends: debhelper (>= 4.1.0)
|
|
@ -0,0 +1,56 @@
|
|||
include Makefile.inc
|
||||
|
||||
PROGS = \
|
||||
bin2c \
|
||||
conmakehash \
|
||||
kallsyms \
|
||||
pnmtologo
|
||||
|
||||
SCRIPTS = \
|
||||
checkconfig.pl \
|
||||
checkincludes.pl \
|
||||
checkstack.pl \
|
||||
checkversion.pl \
|
||||
gcc-version.sh \
|
||||
gen_initramfs_list.sh \
|
||||
Kbuild.include \
|
||||
kernel-doc \
|
||||
Lindent \
|
||||
Makefile.build \
|
||||
Makefile.clean \
|
||||
Makefile.host \
|
||||
Makefile.lib \
|
||||
Makefile.modinst \
|
||||
Makefile.modpost \
|
||||
makelst \
|
||||
mksysmap \
|
||||
mkuboot.sh \
|
||||
mkversion \
|
||||
namespace.pl \
|
||||
patch-kernel \
|
||||
reference_discarded.pl \
|
||||
reference_init.pl \
|
||||
setlocalversion \
|
||||
show_delta \
|
||||
ver_linux
|
||||
|
||||
SUBDIRS = \
|
||||
basic \
|
||||
genksyms \
|
||||
kconfig \
|
||||
mod
|
||||
|
||||
VPATH = $(top_srcdir)/scripts
|
||||
|
||||
all-local: $(PROGS)
|
||||
|
||||
install-local: $(PROGS)
|
||||
@list='$(PROGS)'; for p in $$list; do \
|
||||
echo " install -D '$$p' '$(prefix)/scripts/$$p'"; \
|
||||
install -D "$$p" "$(prefix)/scripts/$$p"; \
|
||||
done
|
||||
@list='$(SCRIPTS)'; for p in $$list; do \
|
||||
echo " install -D '$(top_srcdir)/scripts/$$p' '$(prefix)/scripts/$$p'"; \
|
||||
install -D "$(top_srcdir)/scripts/$$p" "$(prefix)/scripts/$$p"; \
|
||||
done
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -Wall -W -O2
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
all: all-local all-recursive
|
||||
install: install-local install-recursive
|
||||
|
||||
all-recursive install-recursive:
|
||||
@target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; \
|
||||
for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
$(MAKE) -C $$subdir $$target \
|
||||
|| exit 1; \
|
||||
done
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
include ../Makefile.inc
|
||||
|
||||
PROGS = \
|
||||
docproc \
|
||||
fixdep \
|
||||
split-include
|
||||
|
||||
VPATH = $(top_srcdir)/scripts/basic
|
||||
|
||||
all-local: $(PROGS)
|
||||
|
||||
install-local: $(PROGS)
|
||||
@list='$(PROGS)'; for p in $$list; do \
|
||||
echo " install -D '$$p' '$(prefix)/scripts/basic/$$p'"; \
|
||||
install -D "$$p" "$(prefix)/scripts/basic/$$p"; \
|
||||
done
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
include ../Makefile.inc
|
||||
|
||||
PROGS = genksyms
|
||||
|
||||
VPATH = $(top_srcdir)/scripts/genksyms
|
||||
|
||||
CFLAGS += -I$(top_srcdir)/scripts/genksyms
|
||||
|
||||
all-local: $(PROGS)
|
||||
|
||||
install-local: $(PROGS)
|
||||
@list='$(PROGS)'; for p in $$list; do \
|
||||
echo " install -D '$$p' '$(prefix)/scripts/genksyms/$$p'"; \
|
||||
install -D "$$p" "$(prefix)/scripts/genksyms/$$p"; \
|
||||
done
|
||||
|
||||
genksyms: genksyms.o parse.o lex.o
|
||||
|
||||
lex.o: keywords.c parse.h
|
||||
|
||||
%.c: %.c_shipped
|
||||
ln -s $< $@
|
||||
|
||||
%.h: %.h_shipped
|
||||
ln -s $< $@
|
|
@ -0,0 +1,25 @@
|
|||
include ../Makefile.inc
|
||||
|
||||
PROGS = conf
|
||||
|
||||
VPATH = $(top_srcdir)/scripts/kconfig
|
||||
|
||||
CFLAGS += -I$(top_srcdir)/scripts/kconfig
|
||||
|
||||
all-local: $(PROGS)
|
||||
|
||||
install-local: $(PROGS)
|
||||
@list='$(PROGS)'; for p in $$list; do \
|
||||
echo " install -D '$$p' '$(prefix)/scripts/kconfig/$$p'"; \
|
||||
install -D "$$p" "$(prefix)/scripts/kconfig/$$p"; \
|
||||
done
|
||||
|
||||
conf: conf.o zconf.tab.o
|
||||
|
||||
zconf.tab.c: zconf.hash.c lex.zconf.c
|
||||
|
||||
%.c: %.c_shipped
|
||||
ln -s $< $@
|
||||
|
||||
%.h: %.h_shipped
|
||||
ln -s $< $@
|
|
@ -0,0 +1,17 @@
|
|||
include ../Makefile.inc
|
||||
|
||||
PROGS = modpost
|
||||
|
||||
all-local: $(PROGS)
|
||||
|
||||
install-local: $(PROGS)
|
||||
@list='$(PROGS)'; for p in $$list; do \
|
||||
echo " install -D '$$p' '$(prefix)/scripts/mod/$$p'"; \
|
||||
install -D "$$p" "$(prefix)/scripts/mod/$$p"; \
|
||||
done
|
||||
|
||||
modpost: elf.o modpost.o module.o module_devicetable.o module_devicetable_impl_2_6_16.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^
|
||||
|
||||
%.o: %.cpp %.hpp endian.hpp
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* 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,138 @@
|
|||
/*
|
||||
* 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,84 @@
|
|||
/*
|
||||
* 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 = 0, *dump_write = 0;
|
||||
bool all_versions = false, modversions = false;;
|
||||
|
||||
while ((opt = getopt (argc, argv, "ai: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 = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
modversions = true;
|
||||
break;
|
||||
case 'o':
|
||||
dump_write = optarg;
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dump_read)
|
||||
modules.dump_read (dump_read);
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
* 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 &name) throw ()
|
||||
: name (name)
|
||||
{
|
||||
std::string::size_type t1 = name.find_last_of ('/');
|
||||
if (t1 == std::string::npos)
|
||||
t1 = 0;
|
||||
else
|
||||
t1++;
|
||||
name_short = name.substr (t1, std::string::npos);
|
||||
|
||||
if (name == "vmlinux")
|
||||
is_vmlinux = true;
|
||||
}
|
||||
|
||||
module::module (const std::string &filename, bool) throw ()
|
||||
{
|
||||
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 (!is_vmlinux && !modinfo)
|
||||
throw std::runtime_error ("Not a kernel module, lacks modinfo section");
|
||||
if (!symtab)
|
||||
throw std::runtime_error ("Not a kernel module, lacks symbol table");
|
||||
|
||||
if (!is_vmlinux)
|
||||
{
|
||||
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) 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);
|
||||
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) 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);
|
||||
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)
|
||||
{ }
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* 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) throw ();
|
||||
|
||||
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:
|
||||
module (const std::string &filename, bool) throw ();
|
||||
|
||||
std::string name, name_short;
|
||||
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) throw (std::runtime_error);
|
||||
void dump_write (const std::string &filename) 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
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* 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_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_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);
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
#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_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_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_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_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 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_ieee1394);
|
||||
make_templates(device_pci);
|
||||
make_templates(device_pnp);
|
||||
make_templates(device_pnp_card);
|
||||
make_templates(device_usb);
|
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* 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 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_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_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_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_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<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
|
Loading…
Reference in New Issue