summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md224
-rw-r--r--TODO2
-rwxr-xr-xcommands/build-all15
-rwxr-xr-xcommands/build-arch67
-rwxr-xr-xcommands/check16
-rwxr-xr-xcommands/copy-modules168
-rwxr-xr-xcommands/find-dups24
-rwxr-xr-xcommands/find-unpackaged35
-rwxr-xr-xcommands/gen-control98
-rwxr-xr-xcommands/gen-deps35
-rwxr-xr-xcommands/help12
-rwxr-xr-xcommands/install-files170
-rwxr-xr-xcommands/preprocess224
-rwxr-xr-xgeneric-rules31
-rwxr-xr-xkernel-wedge20
-rw-r--r--lib/KernelWedge.pm148
-rw-r--r--man/kernel-wedge-build-all.116
-rw-r--r--man/kernel-wedge-build-arch.118
-rw-r--r--man/kernel-wedge-check.112
-rw-r--r--man/kernel-wedge-copy-modules.113
-rw-r--r--man/kernel-wedge-find-dups.113
-rw-r--r--man/kernel-wedge-find-unpackaged.112
-rw-r--r--man/kernel-wedge-gen-control.164
-rw-r--r--man/kernel-wedge-gen-deps.112
-rw-r--r--man/kernel-wedge-help.111
-rw-r--r--man/kernel-wedge-install-files.19
-rw-r--r--man/kernel-wedge-preprocess.128
-rw-r--r--man/kernel-wedge.115
28 files changed, 1512 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..06d5d3c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,224 @@
+# kernel-wedge, an industrial strength kernel splitting tool
+
+kernel-wedge is used to generate kernel module udebs for the debian
+installer.
+
+kernel-wedge is now used as part of the build process of the linux and
+kfreebsd-* source packages, but can also be used separately.
+
+## Configuration directory layout
+
+The default-configuration directory contains the following files:
+
+modules/*<BR>
+package-list
+
+The environment variable `$KW_DEFCONFIG_DIR` must be set, naming the
+default-configuration directory.
+
+Each configuration directory contains the following files:
+
+kernel-versions<BR>
+modules/*arch*/\*<BR>
+exclude-packages (optional)<BR>
+package-list
+
+The environment variable `$KW_CONFIG_DIR` may be set, naming the
+configuration directory; otherwise the default value is "`.`".
+Typically there is a separate configuration directory per
+architecture, but this is not required. The configuration directory
+may be the same as the default-configuration directory.
+
+## Use in a kernel source package
+
+### Configuration files
+
+The kernel-versions file lists the kernel flavours to produce packages
+for. There are 6 whitespace separated fields per line, and it looks
+something like this:
+
+ # arch version flavour installedname suffix build-depends
+ i386 - 686 - - -
+ i386 - 686-pae - - -
+
+The arch column must be set to the target Debian architecture and the
+flavour to the kernel flavour name that appears in the package and
+file names.
+
+The version, installedname and build-depends columns must all be set
+to "`-`" in this case.
+
+The suffix column is either `y`, `-` or `-`*suffix*; if it is `y` then
+the kernel image inside the udeb will include the version and flavour
+in its name, if it is `-`*suffix* then it will include this. (So will
+the System.map).
+
+The udebs are named with the version of the kernel in their package name,
+since that can be useful during kernel transitions. The string `-di` is
+appended to prevent any posible collisions in names with real debs.
+
+The package-list and (optional) exclude-packages configuration files
+are used by `gen-control`, as explained in its online help.
+
+Finally, you need a modules/*arch* directory, or directories. These are
+used to list the modules that go in a package. For example, for i386, we
+want to have some nic drivers, so we create a modules/i386/nic-modules
+listing them:
+
+ # My short list of nic modules.
+ 8139too
+ e100
+ natsemi
+ ne2k-pci
+ tulip
+ winbond-840
+ 3c59x
+
+But for Linux, drivers are organised into subdirectories by type, and
+we can instead include (most) Ethernet drivers using a wildcard:
+
+ drivers/net/ethernet/**
+
+Suppose we want a different set of modules in the 686 flavour kernel.
+Then create a `modules/`*arch*-*flavour*`/nic-modules` instead, and it
+will be used by preference. One udeb will be created for each modules
+list file, containing the listed modules. The names of the files
+should match the names of the various modules listed in the
+package-list file in the default-configuration directory.
+
+You will also want a special modules list file for the kernel-image udeb.
+If you need to include no modules with your kernel, it can be an empty file.
+but you should have a modules/*arch*/kernel-image.
+
+`kernel-wedge` will copy the listed modules into each package. If a listed
+module does not exist, it will fail by default. Sometimes you might want to
+make a module be included but it's not fatal for it not to be available.
+To indicate this, follow the module with a space and a "`?`".
+
+Module list files can also include other module lists by reference. This
+works similar to cpp includes, and can be used to include module lists
+distributed as part of kernel-wedge, or others. For example:
+
+ # kernel-wedge's standard set of cdrom modules
+ #include <cdrom-core-modules>
+ # my own list
+ #include "../../includes/cdrom-modules"
+
+The `<name>` syntax includes a file from the modules subdirectory of the
+default-configuration directory.
+
+A final capability of the module list files is the ability to include a
+module list and then override parts of it. Follow a module name with " `-`" to
+remove it from the list if it was previously listed, as by an include:
+
+ # kernel-wedge's standard set of cdrom modules
+ #include <cdrom-core-modules>
+ # but not this one
+ sr_mod -
+
+### Debian directory
+
+To add the udeb packages to the control file, run for each
+architecture:
+
+`kernel-wedge gen-control `*version*` >> debian/control`
+
+Where *version* is the kernel ABI/version that appears in package
+names.
+
+In case you use the same kernel flavour name on multiple
+architectures, you will need to merge the output from multiple
+invocations of `kernel-wedge gen-control`.
+
+## Use in a separate source package
+
+### Configuration files
+
+The kernel-versions file looks something like this:
+
+ # arch version flavour installedname suffix build-depends
+ i386 2.4.25-1 386 2.4.25-1-386 - kernel-image-2.4.25-1-386, kernel-pcmcia-modules-2.4.25-1-386
+ i386 2.4.24 speakup 2.4.24-speakup - kernel-image-2.4.24-speakup
+
+In this case we are building two different flavours of i386 kernels.
+We could just as easily be building kernels for different architectures.
+
+The arch, flavour and suffix columns are set as above.
+
+The version is the kernel version, or can be "`-`", in which case a
+version must be specified when running the `gen-control` and
+`install-files` commands.
+
+The installedname column gives the directory/filename that the kernel and
+modules are installed using in the kernel `.deb`. If it is "`-`", it's
+generated from the version and flavor.
+
+The build-depends are the package that is split up by kernel-wedge.
+
+The other configuration files are set in the same way as normal.
+
+### Debian directory
+
+Your source package will be very simple, looking something like this:
+
+debian/copyright<BR>
+debian/changelog<BR>
+debian/rules<BR>
+debian/control.stub
+
+Let's get the easy files out of the way. The changelog is a
+changelog, like any other, as is the copyright. The debian/rules
+can be something as simple as this:
+
+ #!/usr/bin/make -f
+ include /usr/share/kernel-wedge/generic-rules
+
+Or you can use the `kernel-wedge` command directly in your own rules file.
+Run it for some semblance of usage help.
+
+`debian/control.stub` is the top of a control file. Something like this:
+
+ Source: linux-kernel-di-i386
+ Section: debian-installer
+ Priority: optional
+ Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
+ Build-Depends: kernel-wedge
+
+The rest of the control file will be generated for you.
+
+Once you have your source package set up, run:
+
+ kernel-wedge gen-control > debian/control
+
+You only need to do this once. Then build it like any other package.
+Note that you will have to have the kernels listed as build dependencies
+installed normally; but see "`kernel-wedge help build-all`" for an
+alternative.
+
+## Misc other info
+
+The "`kernel-wedge copy-modules`" command does the actual copying of modules
+to the temp dirs that are used to build the package. It is complicated by
+the need to make sure that all of a module's dependencies are included in
+its package, or in a package on which it depends. If necessary, extra
+modules will be added to a package to make sure the dependencies are
+satisfied.
+
+The dependency information from modules.dep is compared with the output of
+the "`kernel-wedge gen-deps`" command, which extracts dependency information
+from package-lists, and formats it in a form used by tsort. If any
+additional modules are needed to meet dependencies of modules in the udebs,
+they will automatically be added. Since that might result in modules being
+copied to multiple udebs, the "`kernel-wedge find-dups`" command is used to
+scan for duplicates of modules. When you have duplicates, you need to find
+(or make) a package that both packages depend on, and move the duplicate
+modules to it. Alternatively, as a quick hack you can just touch a file
+named ignore-dups in the root of your package and duplicate modules will
+stop being a fatal error.
+
+`SOURCEDIR` can be set to a directory containing a tree of kernel modules and
+kernel image, and it will be used instead of the usual tree. That directory
+will need to have a modules.dep file already generated for this to work
+though -- but the modules.dep can even be copied from another system and
+it'll work. This can be useful if you cannot install the required
+kernel-image package, or are cross-compiling.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..5c8df11
--- /dev/null
+++ b/TODO
@@ -0,0 +1,2 @@
+* Better docs for making a custom modules package, or using a different or
+ custom kernel.
diff --git a/commands/build-all b/commands/build-all
new file mode 100755
index 0000000..afb677f
--- /dev/null
+++ b/commands/build-all
@@ -0,0 +1,15 @@
+#!/bin/sh
+# This is a wrapper script that can be used to build all architectures.
+#
+# The script builds all architectures listed in kernel-versions.
+# It expects to have the unpacked kernel packages for various arches in
+# ../alpha, etc. modules.dep files have to be put in there too if they are
+# not shipped in the .deb (varies)
+#
+# dpkg-cross must be installed, but you do not need a cross compiler.
+
+set -e
+
+for arch in $(cut -d ' ' -f 1 kernel-versions | grep -v ^# | uniq); do
+ kernel-wedge build-arch "$arch"
+done
diff --git a/commands/build-arch b/commands/build-arch
new file mode 100755
index 0000000..5b910ab
--- /dev/null
+++ b/commands/build-arch
@@ -0,0 +1,67 @@
+#!/bin/sh
+# This is a wrapper script to build a specific architecture.
+#
+# It takes the architecture to be built as parameter and that architecture
+# needs to be listed in kernel-versions.
+# It expects to have the unpacked kernel packages for the architecture in
+# e.g. ../alpha. modules.dep files have to be put in there too if they are
+# not shipped in the .deb (varies)
+#
+# dpkg-cross must be installed, but you do not need a cross compiler.
+
+set -e
+
+buildpackage () {
+ dpkg-buildpackage -d -us -uc -rfakeroot -tc -I $@
+}
+
+# Build source package. Binaries are built below.
+buildpackage -S
+
+# Directory for stubs, added to PATH.
+arch="$1"
+trap 'rm -rf $tmpdir' EXIT
+tmpdir=$(mktemp -d)
+PATH=$PATH:$tmpdir
+export PATH
+
+if [ -z "$arch" ]; then
+ echo "** Error: architecture not specified"
+ exit 1
+fi
+if ! cut -d ' ' -f 1 kernel-versions | grep -v "^$arch$"; then
+ echo "** Error: arch $arch not listed in kernel-versions"
+ exit 1
+fi
+
+if [ "$arch" != "`dpkg-architecture -qDEB_BUILD_ARCH`" ]; then
+ # Generate cross-compiler stub, this is needed to get the
+ # debian build system to cross-build the given arch w/o a
+ # real cross compiler.
+ CC=$tmpdir/$arch-linux-gcc
+ echo "#!/bin/sh" > $CC
+ echo "echo $arch-linux" >> $CC
+ chmod +x $CC
+ # Not only must it be in the path, but CC needs to be
+ # exported as well.
+ export CC
+else
+ # native build
+ unset CC
+fi
+
+if [ -d ../$arch ]; then
+ export SOURCEDIR=`pwd`/../$arch
+else
+ unset SOURCEDIR
+fi
+
+if [ "$arch" != "`dpkg-architecture -qDEB_BUILD_ARCH`" ]; then
+ if [ -z "$SOURCEDIR" ]; then
+ echo "** Warning: no SOURCEDIR for arch $arch" >&2
+ fi
+ buildpackage -b -a$arch
+else
+ # native build
+ buildpackage
+fi
diff --git a/commands/check b/commands/check
new file mode 100755
index 0000000..4b416d1
--- /dev/null
+++ b/commands/check
@@ -0,0 +1,16 @@
+#!/bin/sh -e
+empty=
+if [ $# -ge 1 ]; then
+ packages="$*"
+else
+ packages="$(dh_listpackages -s)"
+fi
+for pkg in $packages; do
+ if [ -z "$(find debian/$pkg -type f)" ]; then
+ echo "$pkg will be empty" >&2
+ empty=1
+ fi
+done
+if [ "$empty" -a -z "$KW_CHECK_NONFATAL" ]; then
+ exit 1
+fi
diff --git a/commands/copy-modules b/commands/copy-modules
new file mode 100755
index 0000000..30f9dc5
--- /dev/null
+++ b/commands/copy-modules
@@ -0,0 +1,168 @@
+#!/bin/bash
+#
+# Copy modules into the right directories in preparation for building udebs.
+# This script is named after the its counterpart in the original
+# kernel-image-di package by Joey Hess <joeyh@debian.org>.
+#
+# Copyright (c) 2001-2002 Herbert Xu <herbert@debian.org>
+#
+# Usage: copy-modules version flavour installedname
+
+set -e
+
+deplist() {
+ local deps=$1
+ local list=$2
+
+ cp $list $tmpdir/work
+
+ # recursively append external dependencies to $list
+ while :; do
+
+ # list external dependencies of $work
+ join -o 2.2 $tmpdir/work $deps | sort -u | comm -23 - $list \
+ > $tmpdir/work.new
+ mv $tmpdir/work.new $tmpdir/work
+
+ # exit if work is empty
+ [ -s $tmpdir/work ] || break
+
+ # append work to $list
+ sort -um -o $list $list $tmpdir/work
+ done
+}
+
+version=$1-$2
+flavour=$2
+installedname=$3
+configdir=$(readlink -f ${KW_CONFIG_DIR:-.})
+arch=$(dpkg-architecture -qDEB_HOST_ARCH)
+os=$(dpkg-architecture -qDEB_HOST_ARCH_OS)
+home=$PWD
+
+trap 'rm -rf $tmpdir' EXIT
+tmpdir=$(mktemp -d)
+
+# SOURCEDIR may be set externally to control where to copy from.
+if [ -n "$SOURCEDIR" ]; then
+ moddir=$SOURCEDIR/lib/modules/$installedname
+else
+ moddir=/lib/modules/$installedname
+fi
+
+if [ ! -d $moddir ]; then
+ exit 0
+fi
+
+# The directory of modules lists to use.
+if [ -d $configdir/modules/$arch-$flavour ]; then
+ modlistdir=$configdir/modules/$arch-$flavour
+elif [ -d $configdir/modules/$flavour ]; then
+ modlistdir=$configdir/modules/$flavour
+else
+ modlistdir=$configdir/modules/$arch
+fi
+
+if [ "$os" = "linux" ] ; then
+ if [ "$SOURCEDIR" ]; then
+ modulesdep=$tmpdir/modules.dep
+ PATH="/usr/sbin:/sbin:$PATH" depmod \
+ -b $SOURCEDIR $installedname -n \
+ | sed '/^#/d; /^alias /,$d' >$modulesdep
+ elif [ -e "$moddir/modules.dep" ]; then
+ modulesdep=$moddir/modules.dep
+ else
+ echo "Installed kernel package is missing $moddir/modules.dep" >&2
+ exit 1
+ fi
+
+ # get module dependencies from modules.dep
+ # sort it by field 2
+ perl -lne '
+ @words=split(" ");
+ s!'/lib/modules/$installedname'/!! foreach (@words);
+ if ($words[0] =~ /:$/) {
+ $words[0]=~s/:$//;
+ $module=shift @words;
+ }
+ foreach (@words) {
+ print "$module\t$_" unless $_ eq "\\";
+ }
+ ' $modulesdep | sort -k 2,2 > $tmpdir/deps
+
+ if [ ! -s $tmpdir/deps ] && [ ! -e $configdir/no-modules ]; then
+ echo "No module interdependencies found. This probably means your modules.dep is broken." >&2
+ echo "If this is intentional, touch $configdir/no-modules" >&2
+ exit 1
+ fi
+else
+ touch $tmpdir/deps
+fi
+
+mkdir $tmpdir/module-deps $tmpdir/module-list
+
+# generate module interrelationships from package-list file
+kernel-wedge gen-deps $flavour > $tmpdir/module-deps.packages
+
+code=0
+# loop over all udebs, sort that all dependent modules are processed first
+for i in $(
+ {
+ find $modlistdir/ -maxdepth 1 \( -type f -or -type l \) -not -name '*.lnk' -printf "%f\t%f\n"
+ cat $tmpdir/module-deps.packages
+ } | tsort | tac
+); do
+ # write dependent (direct and indirect) udebs to exclude
+ # write dependencies to module-deps/$i
+ echo $i | join -o 2.2 - $tmpdir/module-deps.packages | { # dependent modules
+ cd $tmpdir/module-deps
+ xargs -r sh -c 'printf "%s\n" "$@"; cat "$@"' sh # direct and indirect deps
+ } | sort -u | tee $tmpdir/module-deps/$i | { # write deps
+ cd $tmpdir/module-list
+ xargs -r cat
+ } | sort -u > $tmpdir/exclude # modules to exclude
+
+ # preprocess file, handle includes and excludes and sort so that
+ # the joins work, no matter what the order of the input.
+ kernel-wedge preprocess $modlistdir/$i $moddir |
+ sort > $tmpdir/module-list/$i
+ test ${PIPESTATUS[0]} = 0
+
+ # exclude modules in exclude from dependency list
+ join -o 2.1,2.2 -2 2 -v 2 $tmpdir/exclude $tmpdir/deps |
+ sort -k 1,1 > $tmpdir/tmpdeps
+
+ # include dependent modules which are not in a
+ # dependent udeb into module-list/$i
+ deplist $tmpdir/tmpdeps $tmpdir/module-list/$i
+
+ if [ -s $tmpdir/module-list/$i ] && dh_listpackages | grep -qx "$i-$version-di"; then
+ # copy kernel modules to package build dir
+ cd $moddir
+ ret=$( ( (
+ set +e
+ tar cfT - $tmpdir/module-list/$i
+ printf $? >&3
+ ) | (
+ set +e
+ dir=$home/debian/$i-$version-di/lib/modules/$installedname
+ mkdir -p $dir
+ cd $dir
+ tar xf -
+ printf $? >&3
+ ) ) 3>&1)
+ if [ "$ret" != "00" ]; then
+ echo "tar failed" >&2
+ exit $ret
+ fi
+ cd $home
+
+ if [ "$os" = linux ]; then
+ cat >"debian/$i-$version-di.postinst" <<EOF
+#!/bin/sh -e
+depmod $installedname
+EOF
+ fi
+ fi
+done
+exit $code
diff --git a/commands/find-dups b/commands/find-dups
new file mode 100755
index 0000000..7c4d45a
--- /dev/null
+++ b/commands/find-dups
@@ -0,0 +1,24 @@
+#!/bin/bash -e
+# Find duplicate modules. Pass the kernel name.
+kernel=$1
+(
+ shopt -s nullglob
+ for dir in debian/*-modules-$kernel-di; do
+ cd $dir
+ find lib -type f -printf "$dir %p\n"
+ cd ../..
+ done
+) | sort -k2 | perl -ne '
+ my $configdir = ($ENV{KW_CONFIG_DIR} || ".");
+ while (<>) {
+ ($d, $f)=split;
+ if ($f eq $lf) { print "$d $f\n$ld $lf\n"; $dups++ }
+ $lf=$f;
+ $ld=$d
+ }
+ if ($dups) {
+ print STDERR "some modules are in more than one package\n";
+ exit 1 unless (-e "$configdir/ignore-dups" ||
+ length($ENV{KW_CHECK_NONFATAL}));
+ }
+'
diff --git a/commands/find-unpackaged b/commands/find-unpackaged
new file mode 100755
index 0000000..a7bcf6d
--- /dev/null
+++ b/commands/find-unpackaged
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+# Find unpackaged modules. Pass the kernel name and installed name
+# (normally the same).
+use strict;
+use warnings;
+use File::Find ();
+use File::Spec;
+
+my $kernel = $ARGV[0];
+my $installedname = $ARGV[1];
+
+my $moddir = "/lib/modules/$installedname";
+my $sourcedir = $ENV{SOURCEDIR} || '';
+
+my %unpackaged;
+my $dir = "$sourcedir$moddir";
+File::Find::find(
+ sub {
+ $unpackaged{File::Spec->abs2rel($File::Find::name, $dir)} = 1
+ if /\.k?o$/;
+ },
+ $dir);
+for my $dir (glob("debian/*-modules-$kernel-di$moddir")) {
+ File::Find::find(
+ sub {
+ delete $unpackaged{File::Spec->abs2rel($File::Find::name, $dir)}
+ if /\.k?o$/;
+ },
+ $dir);
+}
+
+print "These modules from $kernel are unpackaged:\n";
+for my $path (sort(keys(%unpackaged))) {
+ print "\t\t$path\n";
+}
diff --git a/commands/gen-control b/commands/gen-control
new file mode 100755
index 0000000..67922d8
--- /dev/null
+++ b/commands/gen-control
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+# Generate a debian/control from the control stub, the kernel-versions
+# files, and the package-list.
+use strict;
+use warnings;
+
+use KernelWedge qw(CONFIG_DIR CONTROL_FIELDS read_kernel_versions
+ read_package_lists for_each_package);
+
+my @builddeps;
+my %excluded;
+
+my $fixkernelversion = $ARGV[0];
+
+if (open(EXCLUDED, CONFIG_DIR . "/exclude-packages")) {
+ while (<EXCLUDED>) {
+ chomp;
+ $excluded{$_}=1;
+ }
+ close EXCLUDED;
+}
+
+my $versions = read_kernel_versions($fixkernelversion);
+
+for my $ver (@$versions) {
+ (my $arch, my $kernelversion, undef, undef, undef, my $builddep) =
+ @$ver;
+ if (defined($fixkernelversion)) {
+ $ver->[1] = $fixkernelversion;
+ }
+ elsif ($kernelversion eq "-") {
+ die "kernel version not set in file or on command line";
+ }
+ if ($builddep ne "-") {
+ foreach my $pkg (split(", ", $builddep)) {
+ push @builddeps, "$pkg [$arch]";
+ }
+ }
+}
+
+# Building with installed kernel package, or as part of a package?
+if (@builddeps) {
+ open(STUB, "debian/control.stub") || die "debian/control.stub: $!";
+ while (<STUB>) {
+ chomp;
+ if (/^Build-Depends:/) {
+ $_=join(", ", $_, @builddeps);
+ }
+ print $_."\n";
+ }
+ close STUB;
+}
+
+my $packages = read_package_lists();
+
+for_each_package($packages, $versions, sub {
+ my ($arch, $kernelversion, $flavour, $modlistdir, $template) = @_;
+
+ my %override;
+ $override{Architecture}=$arch;
+ $override{Package}=$template->("Package")."-".$kernelversion."-".$flavour."-di";
+ $override{'Package-Type'}="udeb";
+ $override{'Kernel-Version'}=$kernelversion."-".$flavour;
+
+ return if $excluded{$override{Package}};
+
+ print "\n";
+
+ if (! defined $template->("Section") || $template->("Section") !~ /debian-installer$/) {
+ $override{Section}="debian-installer";
+ }
+
+ if (defined $template->("Depends")) {
+ $override{Depends}=join(", ",
+ map { $_."-".$kernelversion."-".$flavour."-di" }
+ # Remove force marker.
+ map { s/!$//; $_ }
+ # If the dep is not built for this arch,
+ # skip it, unless it's forced.
+ grep { -e "$modlistdir/$_" || /!$/ }
+ split(", ", $template->("Depends")));
+ }
+
+ foreach my $field (CONTROL_FIELDS) {
+ my $value = $override{$field} || $template->($field);
+ if ($field eq 'Provides') {
+ if (defined $value) {
+ print $field.": ".$template->("Package").", ".$value."\n";
+ }
+ else {
+ print $field.": ".$template->("Package")."\n";
+ }
+ }
+ else {
+ print $field.": ".$value."\n" if defined $value;
+ }
+ }
+});
diff --git a/commands/gen-deps b/commands/gen-deps
new file mode 100755
index 0000000..3a1a90c
--- /dev/null
+++ b/commands/gen-deps
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+# Generates from debian/control a dependency file, suitable to be fed to
+# tsort. The file has the base package name on the left, and the package it
+# depends on is on the right. It is sorted.
+use strict;
+use warnings;
+
+use KernelWedge qw(read_kernel_versions read_package_lists for_each_package);
+
+my $arch=`dpkg-architecture -qDEB_HOST_ARCH`;
+chomp $arch;
+
+my $flavour=$ARGV[0];
+
+my @out;
+
+my $versions = [[$arch, '-', $flavour]];
+my $packages = read_package_lists();
+
+for_each_package($packages, $versions, sub {
+ my ($arch, $kernelversion, $flavour, $modlistdir, $package) = @_;
+ my $pkg_name = $package->("Package");
+ my @depends = split(", ", $package->("Depends") || "");
+
+ @out = grep(!/^$pkg_name\t/, @out);
+
+ foreach my $dep (@depends) {
+ # Skip depends that are not built for this
+ # architecture.
+ next unless -e "$modlistdir/$dep";
+ push @out, "$pkg_name\t$dep\n";
+ }
+});
+
+print sort @out;
diff --git a/commands/help b/commands/help
new file mode 100755
index 0000000..4a7a73f
--- /dev/null
+++ b/commands/help
@@ -0,0 +1,12 @@
+#!/bin/sh
+LIBDIR=/usr/share/kernel-wedge/commands
+set -e
+command=$1
+if [ -z "$command" ]; then
+ kernel-wedge
+fi
+if [ ! -x "$LIBDIR/$command" ]; then
+ echo "No such command."
+ exit 1
+fi
+exec man 1 "kernel-wedge-$command"
diff --git a/commands/install-files b/commands/install-files
new file mode 100755
index 0000000..c88e29a
--- /dev/null
+++ b/commands/install-files
@@ -0,0 +1,170 @@
+#!/usr/bin/perl -w
+# Create and populate the package build directories.
+
+sub doit {
+ print "\t".join(" ", @_)."\n";
+ my $ret=(system(@_) >> 8);
+ if ($ret != 0) {
+ die "command exited with status $ret\n";
+ }
+}
+
+my $hostarch=`dpkg-architecture -qDEB_HOST_ARCH`;
+chomp $hostarch;
+my $hostos=`dpkg-architecture -qDEB_HOST_ARCH_OS`;
+chomp $hostos;
+
+my $configdir = ($ENV{KW_CONFIG_DIR} || '.');
+my $fixsourcedir = $ENV{SOURCEDIR};
+
+my $fixkernelversion = $ARGV[0];
+
+open(KVERS, "$configdir/kernel-versions") || die "kernel-versions: $!";
+my $version = 0;
+while (<KVERS>) {
+ chomp;
+ next if /^#/ || ! length;
+
+ my ($arch, $kernelversion, $flavour, $installedname, $suffix, $builddep)=split(' ', $_, 6);
+ if (! length $arch || ! length $kernelversion ||
+ ! length $installedname || ! length $flavour ||
+ ! length $builddep ) {
+ die "parse error: $_";
+ }
+ next unless $arch eq $hostarch;
+
+ if (defined($fixkernelversion)) {
+ $kernelversion = $fixkernelversion;
+ }
+ elsif ($kernelversion eq "-") {
+ die "kernel version not set in file or on command line";
+ }
+
+ if ($installedname eq "-") {
+ $installedname = "$kernelversion-$flavour";
+ }
+
+ my $sourcedir;
+ my $bootwrapper_sourcedir;
+ if (defined $fixsourcedir) {
+ $sourcedir = $fixsourcedir;
+ }
+ else {
+ # Building with installed kernel package, or as part
+ # of a package?
+ if ($builddep ne "-") {
+ $sourcedir = "";
+ }
+ elsif ($arch =~ /^kfreebsd-/) {
+ $sourcedir = "debian/kfreebsd-image-$installedname";
+ }
+ else {
+ ($sourcedir) = grep {-d}
+ ("debian/linux-image-$installedname",
+ "debian/linux-image-$installedname-unsigned");
+ ($bootwrapper_sourcedir) = grep {-d}
+ "debian/linux-bootwrapper-$kernelversion";
+ }
+ # Set SOURCEDIR for copy-modules
+ $ENV{SOURCEDIR} = $sourcedir;
+ }
+
+ my $extraname="";
+ if ($suffix =~ /^[yY]/) {
+ $extraname="-$kernelversion-$flavour";
+ }
+ elsif ($suffix =~ /^-.+/) {
+ $extraname="$suffix";
+ }
+
+ my $modlistdir;
+ if (-d "$configdir/modules/$arch-$flavour") {
+ $modlistdir = "$configdir/modules/$arch-$flavour";
+ }
+ elsif (-d "$configdir/modules/$flavour") {
+ $modlistdir = "$configdir/modules/$flavour";
+ }
+ else {
+ $modlistdir = "$configdir/modules/$arch";
+ }
+
+ if (! -e "$modlistdir/kernel-image") {
+ # copy no kernel
+ }
+ elsif ($hostos eq 'linux') {
+ if (-e "$sourcedir/boot/vmlinux-$installedname") {
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/vmlinux-$installedname",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/vmlinux$extraname");
+ }
+ elsif (-e "$sourcedir/boot/vmlinuz-$installedname") {
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/vmlinuz-$installedname",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/vmlinuz$extraname");
+ }
+ else {
+ die "could not find kernel image";
+ }
+ if (-e "$sourcedir/lib/modules/$installedname") {
+ doit("install", "-d",
+ "debian/kernel-image-$kernelversion-$flavour-di/lib/modules/$installedname");
+ doit("install", "-m", 644,
+ "$sourcedir/lib/modules/$installedname/modules.builtin",
+ "$sourcedir/lib/modules/$installedname/modules.order",
+ "debian/kernel-image-$kernelversion-$flavour-di/lib/modules/$installedname/");
+ }
+ }
+ elsif (-e "$sourcedir/boot/kfreebsd-$installedname.gz") {
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/kfreebsd-$installedname.gz",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/kfreebsd$extraname.gz");
+ }
+ else {
+ die "could not find kernel image";
+ }
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/System.map-$installedname",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/System.map$extraname")
+ if -e "$sourcedir/boot/System.map-$installedname" &&
+ -e "$modlistdir/kernel-image";
+
+ # Include extra files to help the d-i build process build kernels
+ # for certain subarchitectures. This is powerpc-specific at the
+ # moment.
+ if (-d "$sourcedir/usr/lib/linux-image-$kernelversion-$flavour") {
+ my $installdir =
+ "debian/kernel-image-$kernelversion-$flavour-di" .
+ "/usr/lib/linux-image-$installedname";
+
+ doit("install", "-d",
+ "debian/kernel-image-$kernelversion-$flavour-di/usr/lib");
+ doit("cp", "-a",
+ "$sourcedir/usr/lib/linux-image-$kernelversion-$flavour",
+ $installdir);
+
+ # Replace symlinks into linux-bootwrapper with the target
+ # files, rather than building yet another udeb.
+ if (defined($bootwrapper_sourcedir)) {
+ opendir(my $dh, $installdir)
+ or die "opendir: $installdir: $!";
+ for my $name (readdir($dh)) {
+ my $fullname = "$installdir/$name";
+ my $target = readlink($fullname);
+ next unless defined($target) &&
+ $target eq "../linux-bootwrapper-$kernelversion/$name";
+ unlink($fullname)
+ or die "unlink: $fullname: $!";
+ doit("cp", "-a",
+ $bootwrapper_sourcedir .
+ "/usr/lib/linux-bootwrapper-$kernelversion/$name",
+ $fullname);
+ }
+ closedir($dh);
+ }
+ }
+
+ doit("kernel-wedge", "copy-modules", $kernelversion, $flavour, $installedname);
+ doit("kernel-wedge", "find-dups", "$kernelversion-$flavour");
+ doit("kernel-wedge", "find-unpackaged", "$kernelversion-$flavour", $installedname);
+}
+close KVERS;
diff --git a/commands/preprocess b/commands/preprocess
new file mode 100755
index 0000000..7cd1041
--- /dev/null
+++ b/commands/preprocess
@@ -0,0 +1,224 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use File::Find ();
+use File::Spec ();
+
+# Dummy filename for when we find that a module is actually built-in
+use constant BUILTIN => "<builtin>";
+
+my $defconfigdir = $ENV{KW_DEFCONFIG_DIR};
+if (!defined($defconfigdir)) {
+ print STDERR "$0: Required environment variable \$KW_DEFCONFIG_DIR is not defined\n";
+ exit 2;
+}
+my $sysdir="$defconfigdir/modules/";
+my $os = `dpkg-architecture -qDEB_HOST_ARCH_OS`;
+chomp $os;
+
+my @module_files;
+my @modules_builtin;
+my %modules;
+my %missing;
+my %loaded;
+
+sub find_all_modules {
+ my ($moddir) = @_;
+
+ File::Find::find({
+ follow => 1, # If $moddir is a symlink, follow it.
+ wanted => sub {
+ if (/\.ko(?:\.(?:xz|zstd))?$/) {
+ push @module_files,
+ File::Spec->abs2rel($File::Find::name,
+ $moddir);
+ }
+ }
+ }, $moddir);
+
+ if ($os eq 'linux') {
+ if (open(my $builtin, "$moddir/modules.builtin")) {
+ while (<$builtin>) {
+ chomp;
+ push @modules_builtin, $_;
+ }
+ close($builtin);
+ }
+ }
+}
+
+sub wildcard_to_regexp {
+ my ($pattern) = @_;
+
+ # Convert to regexp syntax. We handle '**' as a recursive
+ # match-all. We don't bother to handle '\' or '[...]'.
+ my %glob_re = ('?' => '[^/]',
+ '*' => '[^/]*',
+ '**' => '.*',
+ '' => '');
+ my $extra_wild;
+ if ($os eq 'linux') {
+ # Linux treats '-' and '_' as equivalent, and neither
+ # is used consistently. So let each match the other.
+ $glob_re{'-'} = $glob_re{'_'} = '[-_]';
+ $extra_wild = '|[-_]';
+ } else {
+ $extra_wild = '';
+ }
+ $pattern =~ s/(.*?)(\*\*|[?*]$extra_wild|)/
+ quotemeta($1) . $glob_re{$2}/eg;
+
+ return $pattern;
+}
+
+sub is_really_wild {
+ my ($pattern) = @_;
+
+ return scalar($pattern =~ /[?*]/);
+}
+
+sub find_modules {
+ my ($moddir, $pattern, $optional) = @_;
+ my $wild = is_really_wild($pattern);
+
+ my @regexps;
+ if ($wild) {
+ my $re;
+ if ($pattern =~ m|^([^?*]*)/(.*)|) {
+ my $subdir = $1;
+ if (! -d "$moddir/$subdir") {
+ if (-d "$moddir/kernel/$subdir") {
+ $subdir = "kernel/$subdir";
+ } elsif (!$optional) {
+ print STDERR "pattern $pattern refers to nonexistent subdirectory\n";
+ unless ($ENV{KW_CHECK_NONFATAL}) {
+ $! = 1;
+ die;
+ }
+ } else {
+ return ();
+ }
+ }
+ $re = quotemeta($subdir) . '/' . wildcard_to_regexp($2);
+ } else {
+ $re = wildcard_to_regexp($pattern);
+ }
+
+ # Add module suffix; anchor at start and end of string
+ @regexps = ('^' . $re . '\.ko(?:\.(?:xz|zstd))?$');
+ } else {
+ # If pattern doesn't include a wildcard, find the
+ # module in any subdir, but prefer a module in the
+ # kernel subdir. We still do wildcard processing
+ # to handle equivalence of '-' and '_' for Linux.
+ my $re = wildcard_to_regexp($pattern);
+ @regexps = ('^kernel/(?:.*/)?' . $re . '\.ko(?:\.(?:xz|zstd))?$',
+ '(?:^|/)' . $re . '\.ko(?:\.(?:xz|zstd))?$');
+ }
+
+ my @modules;
+ regexp_loop:
+ for my $re (@regexps) {
+ for (@module_files) {
+ if (/$re/) {
+ push @modules, $_;
+ last regexp_loop unless $wild;
+ }
+ }
+ if (!$wild && grep(/$re/, @modules_builtin)) {
+ push @modules, BUILTIN;
+ last;
+ }
+ }
+
+ return @modules;
+}
+
+sub loadlist {
+ my ($list, $moddir) = @_;
+
+ if ($loaded{$list}) {
+ $! = 1;
+ die "include loop detected loading $list\n";
+ }
+ $loaded{$list}=1;
+
+ my $fh;
+ unless (open($fh, $list)) {
+ $! = 1;
+ die "cannot read $list\n";
+ }
+ while (<$fh>) {
+ s/^\s*//;
+ s/\s*$//;
+ if (/^#include\s+<(.*)>$/) {
+ my $basename=$1;
+ loadlist($sysdir.$basename, $moddir);
+ }
+ elsif (/^#include\s+"(.*)"$/) {
+ my $include=$1;
+ my ($dirname)=$list=~m!(.*/).*!;
+ loadlist($dirname.$include, $moddir);
+ }
+ elsif (/^$/) {
+ next;
+ }
+ elsif (/^#/) {
+ next;
+ }
+ elsif (/^(.*) -$/) {
+ # If this was explicitly included and is missing,
+ # we no longer care
+ delete $missing{$1};
+
+ for (find_modules($moddir, $1, 1)) {
+ delete $modules{$_};
+ }
+ }
+ else {
+ my ($pattern, $optional, @found);
+
+ if (/^(.*) \?$/) {
+ ($pattern, $optional) = ($1, 1);
+ }
+ # Support dash prefixing for backwards compatibility.
+ elsif (/^-(.*)/) {
+ ($pattern, $optional) = ($1, 1);
+ } else {
+ ($pattern, $optional) = ($_, 0);
+ }
+
+ @found = find_modules($moddir, $pattern, $optional);
+ for (@found) {
+ $modules{$_} = 1 unless $_ eq BUILTIN;
+ }
+
+ # Check for missing required module. This is not
+ # yet an error as it might be excluded later.
+ if (!is_really_wild($pattern) && !$optional
+ && !@found) {
+ $missing{$pattern} = 1;
+ }
+ }
+ }
+ close $fh;
+}
+
+if (@ARGV < 2) {
+ print STDERR "$0: Required parameters missing\n";
+ exit 2;
+}
+my ($file, $moddir) = @ARGV;
+find_all_modules($moddir);
+loadlist($file, $moddir);
+
+if (keys %missing) {
+ for (keys %missing) {
+ print STDERR "missing module $_\n";
+ }
+ exit 1 unless $ENV{'KW_CHECK_NONFATAL'};
+}
+
+foreach my $m (sort keys %modules) {
+ print "$m\n";
+}
diff --git a/generic-rules b/generic-rules
new file mode 100755
index 0000000..6ef8263
--- /dev/null
+++ b/generic-rules
@@ -0,0 +1,31 @@
+#!/usr/bin/make -f
+# Generic rules file for kernel-wedge using packages.
+# Just include it into your own rules file.
+
+export DH_COMPAT=7
+
+debian/control:
+ kernel-wedge gen-control > debian/control
+
+build: debian/control
+ dh_testdir
+
+clean: debian/control
+ dh_testdir
+ dh_clean `find modules -type l`
+
+binary-indep:
+
+binary-arch: debian/control
+ dh_testdir
+ dh_prep
+
+ kernel-wedge install-files
+ kernel-wedge check
+
+ dh_fixperms -s
+ dh_gencontrol -s
+ dh_builddeb -s
+
+binary: build binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary debian/control
diff --git a/kernel-wedge b/kernel-wedge
new file mode 100755
index 0000000..24cd2f5
--- /dev/null
+++ b/kernel-wedge
@@ -0,0 +1,20 @@
+#!/bin/sh
+LIBDIR=/usr/share/kernel-wedge/commands
+usage () {
+ echo "Usage: kernel-wedge command options"
+ echo "Commands:"
+ for file in $LIBDIR/*; do
+ printf " %s\n" "${file##*/}"
+ done
+ exit 1
+}
+set -e
+command=$1
+if [ -z "$command" ]; then
+ usage
+fi
+if [ ! -x "$LIBDIR/$command" ]; then
+ usage
+fi
+shift 1 || true
+$LIBDIR/$command "$@"
diff --git a/lib/KernelWedge.pm b/lib/KernelWedge.pm
new file mode 100644
index 0000000..a171dfb
--- /dev/null
+++ b/lib/KernelWedge.pm
@@ -0,0 +1,148 @@
+package KernelWedge;
+
+use strict;
+use warnings;
+
+BEGIN {
+ use Exporter ();
+ our @ISA = qw(Exporter);
+ our @EXPORT_OK = qw(CONTROL_FIELDS CONFIG_DIR DEFCONFIG_DIR
+ read_package_lists read_kernel_versions
+ for_each_package);
+}
+
+use constant CONTROL_FIELDS => qw(
+ Package Package-Type Provides Depends Architecture Kernel-Version
+ Section Priority Description
+);
+
+use constant DEFCONFIG_DIR => $ENV{KW_DEFCONFIG_DIR};
+if (!defined(DEFCONFIG_DIR)) {
+ die "Required environment variable \$KW_DEFCONFIG_DIR is not defined";
+}
+use constant CONFIG_DIR => ($ENV{KW_CONFIG_DIR} || '.');
+
+sub read_package_list
+{
+ my ($packages, $order, $file) = @_;
+
+ sub merge_package
+ {
+ my ($packages, $order, $pkg) = @_;
+ if (not exists $packages->{$pkg->{Package}}) {
+ $packages->{$pkg->{Package}} = {};
+ push @$order, $pkg->{Package};
+ }
+ my $real_pkg = $packages->{$pkg->{Package}};
+ foreach (keys(%$pkg)) {
+ $real_pkg->{$_} = $pkg->{$_};
+ }
+ }
+
+ open(LIST, $file) || die "package-list: $!";
+ my $field;
+ my %pkg;
+ while (<LIST>) {
+ chomp;
+ next if /^#/;
+
+ if (/^(\S+):\s*(.*)/) {
+ $field=$1;
+ my $val=$2;
+ if (! grep { $field =~ /^\Q$_\E(_.+)?$/ } CONTROL_FIELDS) {
+ die "unknown field, $field";
+ }
+ $pkg{$field}=$val;
+ }
+ elsif (/^$/) {
+ if (%pkg) {
+ merge_package($packages, $order, \%pkg);
+ %pkg=();
+ }
+ }
+ elsif (/^(\s+.*)/) {
+ # continued field
+ $pkg{$field}.="\n".$1;
+ }
+ }
+ if (%pkg) {
+ merge_package($packages, $order, \%pkg);
+ }
+ close LIST;
+}
+
+sub read_package_lists {
+ my %packages;
+ my @order;
+
+ read_package_list(\%packages, \@order, DEFCONFIG_DIR . "/package-list")
+ unless DEFCONFIG_DIR eq CONFIG_DIR;
+ read_package_list(\%packages, \@order, CONFIG_DIR . "/package-list");
+
+ return [map {$packages{$_}} @order];
+}
+
+sub read_kernel_versions {
+ my ($fixkernelversion) = @_;
+ my @versions;
+
+ open(KVERS, CONFIG_DIR . "/kernel-versions") || die "kernel-versions: $!";
+ while (<KVERS>) {
+ chomp;
+ next if /^#/ || ! length;
+
+ my @fields = split(' ', $_, 6);
+ my ($arch, $kernelversion, $flavour) = @fields;
+ if (! length $arch || ! length $kernelversion || ! length $flavour) {
+ die "parse error";
+ }
+ push @versions, \@fields;
+ }
+ close KVERS;
+
+ return \@versions;
+}
+
+sub for_each_package {
+ my ($packages, $versions, $fn) = @_;
+
+ foreach my $ver (@$versions) {
+ my ($arch, $kernelversion, $flavour) = @$ver;
+ foreach my $pkg (@$packages) {
+ # Used to get a field of the package, looking first for
+ # architecture-specific fields.
+ my $package = sub {
+ my $field=shift;
+ return $pkg->{$field."_".$flavour}
+ if exists $pkg->{$field."_".$flavour};
+ return $pkg->{$field."_".$arch."_".$flavour}
+ if exists $pkg->{$field."_".$arch."_".$flavour};
+ return $pkg->{$field."_".$arch}
+ if exists $pkg->{$field."_".$arch};
+ return $pkg->{$field}
+ if exists $pkg->{$field};
+ return undef;
+ };
+
+ # Check for a modules list file for this architecture and
+ # package.
+ my $modlistdir="";
+ if (-d (CONFIG_DIR . "/modules/$arch-$flavour")) {
+ $modlistdir = CONFIG_DIR . "/modules/$arch-$flavour";
+ }
+ elsif (-d (CONFIG_DIR . "/modules/$flavour")) {
+ $modlistdir = CONFIG_DIR . "/modules/$flavour";
+ }
+ else {
+ $modlistdir = CONFIG_DIR . "/modules/$arch";
+ }
+
+ next unless -e "$modlistdir/".$package->("Package");
+
+ $fn->($arch, $kernelversion, $flavour, $modlistdir,
+ $package);
+ }
+ }
+}
+
+1;
diff --git a/man/kernel-wedge-build-all.1 b/man/kernel-wedge-build-all.1
new file mode 100644
index 0000000..4cfb5ea
--- /dev/null
+++ b/man/kernel-wedge-build-all.1
@@ -0,0 +1,16 @@
+.TH KERNEL\-WEDGE\-BUILD\-ALL 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-build\-all \- build udebs for all architectures
+.SH SYNOPSIS
+.B kernel\-wedge build\-all
+.SH DESCRIPTION
+This is a wrapper script that can be used to build all architectures.
+
+The script builds all architectures listed in kernel\-versions.
+It expects to have the unpacked kernel packages for various arches in
+\a../alpha, etc. modules.dep files have to be put in there too if they are
+not shipped in the .deb (varies)
+
+\fBdpkg\-cross\fR must be installed, but you do not need a cross compiler.
+.SH AUTHOR
+Joey Hess
diff --git a/man/kernel-wedge-build-arch.1 b/man/kernel-wedge-build-arch.1
new file mode 100644
index 0000000..87255c8
--- /dev/null
+++ b/man/kernel-wedge-build-arch.1
@@ -0,0 +1,18 @@
+.TH KERNEL\-WEDGE\-BUILD\-ARCH 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-build\-arch \- build udebs for a single architecture
+.SH SYNOPSIS
+.B kernel\-wedge build\-arch
+.I architecture
+.SH DESCRIPTION
+This is a wrapper script to build a specific architecture.
+
+It takes the architecture to be built as parameter and that architecture
+needs to be listed in kernel-versions.
+It expects to have the unpacked kernel packages for the architecture in
+e.g. ../alpha. modules.dep files have to be put in there too if they are
+not shipped in the .deb (varies)
+
+\fBdpkg-cross\fR must be installed, but you do not need a cross compiler.
+.SH AUTHOR
+Frans Pop
diff --git a/man/kernel-wedge-check.1 b/man/kernel-wedge-check.1
new file mode 100644
index 0000000..03864f2
--- /dev/null
+++ b/man/kernel-wedge-check.1
@@ -0,0 +1,12 @@
+.TH KERNEL\-WEDGE\-CHECK 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-check \- check files installed in package directories
+.SH SYNOPSIS
+.B kernel\-wedge check
+.SH DESCRIPTION
+Check for various problems in the packages.
+
+Return 1 if any problems are found, unless $KW_CHECK_NONFATAL is
+non-empty.
+.SH AUTHOR
+Joey Hess
diff --git a/man/kernel-wedge-copy-modules.1 b/man/kernel-wedge-copy-modules.1
new file mode 100644
index 0000000..a52fa0d
--- /dev/null
+++ b/man/kernel-wedge-copy-modules.1
@@ -0,0 +1,13 @@
+.TH KERNEL\-WEDGE\-COPY\-MODULES 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-copy\-modules \- install modules into package directories
+.SH SYNOPSIS
+.B kernel\-wedge copy\-modules
+.I version flavour installedname
+.SH DESCRIPTION
+Copy modules into the right directories in preparation for building udebs.
+
+Return 1 if a required module is missing, unless $KW_CHECK_NONFATAL is
+non-empty.
+.SH AUTHOR
+Joey Hess
diff --git a/man/kernel-wedge-find-dups.1 b/man/kernel-wedge-find-dups.1
new file mode 100644
index 0000000..450c69b
--- /dev/null
+++ b/man/kernel-wedge-find-dups.1
@@ -0,0 +1,13 @@
+.TH KERNEL\-WEDGE\-FIND\-DUPS 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-find\-dups \- find duplicate modules in package directories
+.SH SYNOPSIS
+.B kernel\-wedge find\-dups
+.I kernel-name
+.SH DESCRIPTION
+Find duplicate modules. Pass the kernel name.
+
+Return 1 if any duplicates are found, unless $KW_CHECK_NONFATAL is
+non-empty or the configuration file 'ignore\-dups' exists.
+.SH AUTHOR
+Joey Hess
diff --git a/man/kernel-wedge-find-unpackaged.1 b/man/kernel-wedge-find-unpackaged.1
new file mode 100644
index 0000000..fd53b2a
--- /dev/null
+++ b/man/kernel-wedge-find-unpackaged.1
@@ -0,0 +1,12 @@
+.TH KERNEL\-WEDGE\-FIND\-UNPACKAGED 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-find\-unpackaged - list modules not packaged in a udeb
+.SH SYNOPSIS
+.B kernel\-wedge find\-unpackaged
+.I kernel\-name
+.SH DESCRIPTION
+List modules that are not packaged in a udeb. Pass the kernel name.
+
+Always return 0.
+.SH AUTHOR
+Ben Hutchings <ben@decadent.org.uk>
diff --git a/man/kernel-wedge-gen-control.1 b/man/kernel-wedge-gen-control.1
new file mode 100644
index 0000000..49b4707
--- /dev/null
+++ b/man/kernel-wedge-gen-control.1
@@ -0,0 +1,64 @@
+.TH KERNEL\-WEDGE\-GEN\-CONTROL 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-gen\-control \- generate debian/control file
+.SH SYNOPSIS
+.B kernel\-wedge gen\-control
+.SH DESCRIPTION
+Generate a debian/control from the control stub, the kernel\-versions
+files, and the package\-list files.
+
+For each kernel version and flavour, and for each module list defined
+for that flavour, \fBgen\-control\fR will create a binary package control
+paragraph. This is normally based on a template in the package\-list
+in the default-configuration directory.
+
+Templates are processed as follows:
+
+.IP 1. 4
+For each standard control field \fIname\fR, copy the template control
+field \fIname\fR_\fIflavour\fR, \fIname\fR_\fIarch\fR_\fIflavour\fR,
+\fIname\fR_\fIarch\fR, or \fIname\fR (in descending order of priority).
+.IP 2. 4
+Append the kernel version and flavour to package names in the
+Package and Depends fields.
+.IP 3. 4
+Stop processing the package if it has been excluded.
+.IP 4. 4
+Set the Architecture, Package\-Type, Kernel\-Version, and Section
+fields automatically.
+.IP 5. 4
+Remove any package that is not going to be built from the Depends
+field. This can be overridden by adding a "!" to the dependency
+name.
+.IP 6. 4
+Add the original (unsuffixed) package name to the Provides field.
+.IP 7. 4
+Emit the processed control paragraph.
+.RE
+
+The package\-list in the configuration directory may add new package
+templates or override template field values. For example:
+
+.RS 4
+.EX
+# This file is used to build up the control file. The kernel version and
+# "\-di" are appended to the package names. Section can be left out. So can
+# architecture, which is derived from the files in the modules directory.
+# It overwrites specifications from /usr/share/kernel\-wedge/package\-list.
+Package: fat\-modules
+Priority: standard
+
+Package: nic\-modules
+Depends: kernel\-image, nic\-shared\-modules, core\-modules, firewire\-core\-modules
+
+Package: other\-modules
+Depends: kernel\-image
+Description: some other modules I like to have in the installer
+.EE
+.RE
+
+The configuration directory may have an exclude\-packages file that
+lists any udebs (by full package name) that would normally be built,
+but should be excluded from the control file.
+.SH AUTHOR
+Joey Hess, Ben Hutchings <ben@decadent.org.uk>
diff --git a/man/kernel-wedge-gen-deps.1 b/man/kernel-wedge-gen-deps.1
new file mode 100644
index 0000000..c9bf9d8
--- /dev/null
+++ b/man/kernel-wedge-gen-deps.1
@@ -0,0 +1,12 @@
+.TH KERNEL\-WEDGE\-GEN\-DEPS 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-gen\-deps \- generate package dependency list
+.SH SYNOPSIS
+.B kernel\-wedge gen\-deps
+.I flavour
+.SH DESCRIPTION
+Generates from the package\-list a dependency file for the given kernel
+flavour, suitable to be fed to tsort. The file has the base package name on
+the left, and the package it depends on is on the right. It is sorted.
+.SH AUTHOR
+Joey Hess
diff --git a/man/kernel-wedge-help.1 b/man/kernel-wedge-help.1
new file mode 100644
index 0000000..3f7a246
--- /dev/null
+++ b/man/kernel-wedge-help.1
@@ -0,0 +1,11 @@
+.TH KERNEL\-WEDGE\-HELP 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-help \- display online help
+.SH SYNOPSIS
+.B kernel\-wedge help
+.I command
+.SH DESCRIPTION
+The \fBhelp\fR command displays the manual page for a \fBkernel-wedge\fR
+command.
+.SH AUTHOR
+Joey Hess
diff --git a/man/kernel-wedge-install-files.1 b/man/kernel-wedge-install-files.1
new file mode 100644
index 0000000..d0d5da9
--- /dev/null
+++ b/man/kernel-wedge-install-files.1
@@ -0,0 +1,9 @@
+.TH KERNEL\-WEDGE\-INSTALL\-FILES 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-install\-files \- install files into package directories
+.SH SYNOPSIS
+.B kernel\-wedge install\-files
+.SH DESCRIPTION
+Create and populate the package build directories.
+.SH AUTHOR
+Joey Hess
diff --git a/man/kernel-wedge-preprocess.1 b/man/kernel-wedge-preprocess.1
new file mode 100644
index 0000000..ea26e8b
--- /dev/null
+++ b/man/kernel-wedge-preprocess.1
@@ -0,0 +1,28 @@
+.TH KERNEL\-WEDGE\-PREPROCESS 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge\-preprocess \- process a module list file
+.SH SYNOPSIS
+.B kernel\-wedge preprocess
+.I module-list module-dir
+.SH DESCRIPTION
+Preprocesses the \fImodule-list\fR, performing list includes and module
+excludes, removing blank lines and comments, and expanding wildcards.
+Emits a list of filenames to stdout.
+
+Return 1 if a required module or directory is missing, unless
+$KW_CHECK_NONFATAL is non-empty.
+
+The supported wildcards are:
+
+.TS
+nokeep;
+lB l.
+? Match a single character within a path component
+* Match any number of characters within a path component
+** Match any number of characters including multiple path components
+.TE
+
+On Linux, '\-' and '_' also match each other since the kernel and kmod
+treat them as equivalent in module names.
+.SH AUTHOR
+Joey Hess, Ben Hutchings <ben@decadent.org.uk>
diff --git a/man/kernel-wedge.1 b/man/kernel-wedge.1
new file mode 100644
index 0000000..ba482e4
--- /dev/null
+++ b/man/kernel-wedge.1
@@ -0,0 +1,15 @@
+.TH KERNEL\-WEDGE 1 "June 2019" "Kernel-wedge"
+.SH NAME
+kernel\-wedge \- industrial strength kernel splitter
+.SH SYNOPSIS
+.B kernel\-wedge
+.IR "subcommand " [ options ]
+.SH "DESCRIPTION"
+.B kernel\-wedge
+is used to generate kernel module udebs for the debian installer.
+Type \fBkernel\-wedge\fR without any parameters for a list of subcommands,
+and use \fBkernel\-wedge help\fR \fIsubcommand\fR for details on the usage of a
+particular subcommand.
+See /usr/share/doc/kernel-wedge/README.md.gz for detailed documentation.
+.SH AUTHOR
+Joey Hess