#!/usr/bin/perl -w # # $Id: device-prune.pl,v 1.1 2003/10/31 15:43:10 godot Exp $ # # Copyright (c) 2001, Jeremy A. Mates. This script is free software; # you can redistribute it and/or modify it under the same terms as # Perl itself. # # Run perldoc(1) on this file for additional documentation. # ###################################################################### # # REQUIREMENTS require 5; use strict; ###################################################################### # # MODULES use Carp; # better error reporting use Getopt::Std; # command line option processing ###################################################################### # # VARIABLES # how to match devices in dmesg output my $dmesg_re = '^([a-z]+)\d*\s+at\s+([a-z]+)'; # how to match devices in conf file my $conf_re = '^([a-z]+).{0,3}?\s+at\s+([a-z]+)'; # how to disable configuration lines (best to keep unique so device # prunes can be easily undone on updated hardware) my $prefix = '#PRUNED#'; # additional keys to put onto lookup table, for special stuff that the # dmesg parser misses (space separated values between parens) my @extra = qw(root mii); my $VERSION; ($VERSION = '$Revision: 1.1 $ ') =~ s/[^0-9.]//g; my (%opts, $lookup); ###################################################################### # # MAIN # parse command-line options getopts('h?f:k:', \%opts); help() if exists $opts{'h'} or exists $opts{'?'}; # load user-supplied spared devices list(s) push @extra, split /[,\s]+/, $opts{'k'} if exists $opts{'k'}; push @extra, load_extras($opts{'f'}) if exists $opts{'f'}; # read required files... my $arch_file = shift or help(); my $dmesg_file = shift; # read in dmesg output, turn into lookup table unless (defined $dmesg_file) { $lookup = parse_dmesg(*STDIN); } else { open FILE, $dmesg_file or die "Problem opening $dmesg_file: $!\n"; $lookup = parse_dmesg(*FILE); close FILE; } # slap extra lookup keys on @$lookup{@extra} = (0)x@extra; # walk arch-specific conf file, disabling devices not in lookup table open CONF, $arch_file or die "Problem opening $arch_file: $!\n"; while () { if (m/$conf_re/o) { unless (exists $lookup->{$1}) { $_ = $prefix.$_; } else { # and devices with same name but disabled parent... $_ = $prefix.$_ unless exists $lookup->{$2}; } } print; # send conf to STDOUT } close CONF; exit; ###################################################################### # # SUBROUTINES # extracts dmesg(8) device list into hash, returns reference of such sub parse_dmesg { my $fh = shift; my $lookup; while (<$fh>) { if (m/$dmesg_re/o) { $lookup->{$1}++; $lookup->{$2}++; } } return $lookup; } # takes a filename, and returns a list of lines minus comments sub load_extras { my $file = shift; my @tmp; open FILE, $file or die "Couldn't load $file: $!\n"; while () { # nix newlines, kill leading/trailing whitespace and # skip commented or blank lines chomp; s/^\s+//; s/\s+$//; next if /^(#|\Z)/; push @tmp, $_; } close FILE; return @tmp; } # a generic help blarb sub help { print <<"HELP"; Usage: $0 arch-conf-file [dmesg-file] Kernel configuration unused device pruner. Options for version $VERSION: -h/-? Display this message -f ff File containing list of extra devices to not disable. -k kk List of extra devices not to disable, space or CSV. Run perldoc(1) on this script for additional documentation. HELP exit; } ###################################################################### # # DOCUMENTATION =head1 NAME device-prune.pl - unused device pruner for OpenBSD kernel config =head1 SYNOPSIS To create the beginnings of a new kernel configuration: # cd /usr/src/sys/arch/`uname -m`/conf # dmesg | device-prune.pl GENERIC > MYCONFIG =head1 DESCRIPTION =head2 Overview This script uses information extracted from dmesg(8) to comment out lines in an OpenBSD arch-specific kernel configuration file. The lines disabled are those that do not reference any of the devices detected at startup. This allows one to easily build a kernel that runs faster and takes up less memory (at the cost of flexibility). One should review the changes done to the configuration file by this script, as something vital may have been disabled. Lines changed by this script are marked with C<#PRUNED#> by default. For debugging purposes, you should also build a C from the GENERIC configuration, in case of problems with the machine running the customized kernel. =head2 Normal Usage $ device-prune.pl [options] arch-conf-file [dmesg-file] See L<"OPTIONS"> for details on the command line switches supported. The I is the kernel configuration file containing all the device definitions for your architecture, under the C directory by default. I is optional, and if omitted the script will attempt to read the dmesg information from STDIN. The resulting configuration file is printed to STDOUT. =head1 OPTIONS This script currently supports the following command line switches: =over 4 =item B<-h>, B<-?> Prints a brief usage note about the script. =item B<-f> I Read an additional list of devices not to disable from I. This allows a custom local list of devices (e.g. USB) to be spared from pruning. Devices should be listed one per line. Leading and trailing whitespace will be destroyed, and lines beginning with the pound symbol skipped. =item B<-k> I List of I not to disable. Should be the device name(s) separated by whitespace or comma. =back =head1 EXAMPLES USB support tends to get clobbered by default (unless all the USB devices you ever might use are plugged in and detected at boot time), hence the B<-f> and B<-k> options to specify lists of devices not to disable. # dmesg | device-prune.pl -k "usb uhub ukbd" GENERIC > MYCONFIG Due to the custom prefix appended to changed lines in the resulting configuration file (C<#PRUNED#> by default), undoing the changes is easy, in the event you are applying an already customized config to new or updated hardware. # perl -i.orig -ple 's/#PRUNED#//' MYCONFIG See perlrun(1) for more information on the above command line arguments to perl. =head1 ENVIRONMENT Expects to be run on an OpenBSD system. May work with other *BSD systems, via tweaks to the regex used to parse dmesg and the configuration file. This option has not been explored yet. =head1 BUGS =head2 Reporting Bugs Newer versions of this script may be available from: http://www.sial.org/code/perl/ If the bug is in the latest version, send a report to the author. Patches that fix problems or add new features are welcome. =head2 Known Issues The default C<@extras> array in the VARIABLES section may need to be populated with more keys for virtual devices like mii(4). USB support tends to get beaten up. Use the B<-f> or B<-k> options to maintain a list of devices not to trample on. More testing will need to be done to make sure the script works right on the wide variety of hardware and platforms OpenBSD runs on. =head1 SEE ALSO config(8), options(4), perl(1) Another set of perl scripts by Camiel Dobbelaar to do similar things (found after writing this script): http://www.sentia.org/downloads/tweakboot http://www.sentia.org/downloads/tweakcompile =head1 AUTHOR Jeremy A. Mates, http://www.sial.org/contact/ =head1 COPYRIGHT Copyright (c) 2001, Jeremy A. Mates. This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 VERSION $Id: device-prune.pl,v 1.1 2003/10/31 15:43:10 godot Exp $ =cut