2013-02-28 17:44:05 +00:00
|
|
|
{ stdenv, runCommand, nettools, bc, perl, kmod, writeTextFile }:
|
2012-07-29 06:23:51 +01:00
|
|
|
|
|
|
|
with stdenv.lib;
|
|
|
|
|
|
|
|
let
|
|
|
|
|
2012-08-01 11:18:03 +01:00
|
|
|
# Function to parse the config file into a nix expression
|
|
|
|
readConfig = configFile:
|
2012-07-29 06:23:51 +01:00
|
|
|
let
|
2012-08-01 11:18:03 +01:00
|
|
|
configAttrs = import "${runCommand "config.nix" {} ''
|
manual-kernel: Fix handling spaces in readConfig.
The previos version did a for loop over the output of set, which spits out _all_
defined variables and their contents. This not only is dangerous if there is a
variable starting with CONFIG_ but also can't handle whitespace, as the IFS is
set to any (horizontal _and_ vertical) whitespace by default.
So, imagine (actually don't imagine, something like this is the case in a lot of
kernel configuration files) you have the following variable:
CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi ..."
A loop with for and the default IFS would result in the following variable
pieces:
0: CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi
1: -fcall-saved-rsi
2: ..."
This obviously leads to the problem that this config variable is being cut off
at the first whitespace.
Another downside of this approach is that set not only returns variables but
functions as well. This could lead to quite a lot of unexpected behaviour and
confusion.
So the new approach doesn't source the kernel configuration anymore but uses
`read` to parse the file line-by line, setting IFS to '=', thus splitting all
configuration lines into key/value pairs.
Using parameter expansion, we ensure that we only read lines starting with
"CONFIG_". This particularily has the advantage of not being bash-specific,
should we choose to change to a different default shell someday.
Now, after we got a correct "CONFIG_" line, we're using a temporary variable to
split off the first quote from the result. Particularily the reason behind this
is shell compatibility again, as ${${foo#"}%"} only works in Bash, Zsh and
whatnot but not in plain SH.
And within the next line we obviously insert the no_firstquote variable without
it's last quote removed.
But, what about escaping?
First of all, if we'd just eval the $val variable, we would correctly unescape
the value, but this has the downside that variables within the content would be
expanded, for example look at this:
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
Well, obviously this is a bad example at the Nix sense, but just to show that
variables within kernel configuration entries aren't impossible.
And second, which would have been a show stopper if \" would be within $val: It
simply would end up being an invalid Nix expression, because \" would end up as
a ploin " within a double quoted string.
Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2012-12-13 21:22:41 +00:00
|
|
|
echo "{" > "$out"
|
|
|
|
while IFS='=' read key val; do
|
|
|
|
[ "x''${key#CONFIG_}" != "x$key" ] || continue
|
|
|
|
no_firstquote="''${val#\"}";
|
|
|
|
echo ' "'"$key"'" = "'"''${no_firstquote%\"}"'";' >> "$out"
|
|
|
|
done < "${configFile}"
|
|
|
|
echo "}" >> $out
|
2012-07-29 20:54:31 +01:00
|
|
|
''}";
|
2012-07-29 06:23:51 +01:00
|
|
|
|
2012-08-01 11:18:03 +01:00
|
|
|
config = configAttrs // rec {
|
|
|
|
attrName = attr: "CONFIG_" + attr;
|
|
|
|
|
|
|
|
isSet = attr: hasAttr (attrName attr) config;
|
|
|
|
|
|
|
|
getValue = attr: if isSet attr then getAttr (attrName attr) config else null;
|
|
|
|
|
|
|
|
isYes = attr: (isSet attr) && ((getValue attr) == "y");
|
|
|
|
|
|
|
|
isNo = attr: (isSet attr) && ((getValue attr) == "n");
|
2012-07-29 06:23:51 +01:00
|
|
|
|
2012-08-01 11:18:03 +01:00
|
|
|
isModule = attr: (isSet attr) && ((getValue attr) == "m");
|
|
|
|
|
|
|
|
isEnabled = attr: (isModule attr) || (isYes attr);
|
|
|
|
|
|
|
|
isDisabled = attr: (!(isSet attr)) || (isNo attr);
|
|
|
|
};
|
|
|
|
in
|
|
|
|
config;
|
2012-07-29 06:23:51 +01:00
|
|
|
|
|
|
|
in
|
|
|
|
|
2012-07-29 09:31:40 +01:00
|
|
|
{
|
|
|
|
# The kernel version
|
|
|
|
version,
|
|
|
|
# The version of the kernel module directory
|
|
|
|
modDirVersion ? version,
|
|
|
|
# The kernel source (tarball, git checkout, etc.)
|
|
|
|
src,
|
|
|
|
# Any patches
|
2012-08-02 04:02:17 +01:00
|
|
|
kernelPatches ? [],
|
2012-07-29 09:31:40 +01:00
|
|
|
# The kernel .config file
|
2012-08-01 11:18:03 +01:00
|
|
|
configfile,
|
|
|
|
# Manually specified nixexpr representing the config
|
2012-07-29 09:52:34 +01:00
|
|
|
# If unspecified, this will be autodetected from the .config
|
2012-08-01 11:18:03 +01:00
|
|
|
config ? optionalAttrs allowImportFromDerivation (readConfig configfile),
|
2012-07-29 18:26:39 +01:00
|
|
|
# Whether to utilize the controversial import-from-derivation feature to parse the config
|
|
|
|
allowImportFromDerivation ? false
|
2012-07-29 09:31:40 +01:00
|
|
|
}:
|
|
|
|
|
2012-07-29 09:48:50 +01:00
|
|
|
let
|
2012-08-01 19:15:26 +01:00
|
|
|
installkernel = name: writeTextFile { name = "installkernel"; executable=true; text = ''
|
2012-07-29 09:48:50 +01:00
|
|
|
#!/bin/sh
|
|
|
|
mkdir $4
|
2012-08-07 11:36:50 +01:00
|
|
|
cp -av $2 $4/${name}
|
|
|
|
cp -av $3 $4
|
2012-07-29 09:48:50 +01:00
|
|
|
'';};
|
2012-08-01 11:18:03 +01:00
|
|
|
|
|
|
|
isModular = config.isYes "MODULES";
|
|
|
|
|
|
|
|
installsFirmware = (config.isEnabled "FW_LOADER") &&
|
2012-08-01 16:21:32 +01:00
|
|
|
(isModular || (config.isDisabled "FIRMWARE_IN_KERNEL"));
|
2012-08-01 19:15:26 +01:00
|
|
|
|
|
|
|
commonMakeFlags = [
|
2012-08-12 02:02:09 +01:00
|
|
|
"O=$(buildRoot)"
|
2012-08-01 19:15:26 +01:00
|
|
|
"INSTALL_PATH=$(out)"
|
2012-08-07 11:36:50 +01:00
|
|
|
] ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
|
2012-08-01 19:15:26 +01:00
|
|
|
++ optional installsFirmware "INSTALL_FW_PATH=$(out)/lib/firmware";
|
2012-08-12 02:02:09 +01:00
|
|
|
|
2012-08-12 02:21:06 +01:00
|
|
|
sourceRoot = stdenv.mkDerivation {
|
|
|
|
name = "linux-${version}-source";
|
2012-08-12 02:02:09 +01:00
|
|
|
|
2012-08-12 02:21:06 +01:00
|
|
|
inherit src;
|
2012-07-29 06:23:51 +01:00
|
|
|
|
2012-08-12 02:21:06 +01:00
|
|
|
patches = map (p: p.patch) kernelPatches;
|
2012-08-02 04:02:17 +01:00
|
|
|
|
2012-08-12 02:21:06 +01:00
|
|
|
phases = [ "unpackPhase" "patchPhase" "installPhase" ];
|
2012-08-12 02:02:09 +01:00
|
|
|
|
2012-08-12 02:21:06 +01:00
|
|
|
prePatch = ''
|
|
|
|
for mf in $(find -name Makefile -o -name Makefile.include -o -name install.sh); do
|
|
|
|
echo "stripping FHS paths in \`$mf'..."
|
|
|
|
sed -i "$mf" -e 's|/usr/bin/||g ; s|/bin/||g ; s|/sbin/||g'
|
|
|
|
done
|
|
|
|
sed -i Makefile -e 's|= depmod|= ${kmod}/sbin/depmod|'
|
|
|
|
'';
|
|
|
|
|
|
|
|
installPhase = ''
|
|
|
|
cd ..
|
|
|
|
mv $sourceRoot $out
|
|
|
|
'';
|
2012-08-12 02:02:09 +01:00
|
|
|
};
|
2013-03-02 14:53:56 +00:00
|
|
|
in
|
|
|
|
|
|
|
|
stdenv.mkDerivation {
|
|
|
|
name = "linux-${version}";
|
|
|
|
|
|
|
|
enableParallelBuilding = true;
|
|
|
|
|
|
|
|
outputs = if isModular then [ "out" "dev" ] else null;
|
|
|
|
|
|
|
|
passthru = {
|
|
|
|
inherit version modDirVersion config kernelPatches src;
|
|
|
|
};
|
|
|
|
|
|
|
|
inherit sourceRoot;
|
2012-07-29 06:23:51 +01:00
|
|
|
|
2012-08-12 02:02:09 +01:00
|
|
|
unpackPhase = ''
|
|
|
|
mkdir build
|
|
|
|
export buildRoot="$(pwd)/build"
|
2013-03-02 14:53:56 +00:00
|
|
|
cd ${sourceRoot}
|
2012-07-29 06:23:51 +01:00
|
|
|
'';
|
|
|
|
|
|
|
|
configurePhase = ''
|
|
|
|
runHook preConfigure
|
2013-03-02 12:55:07 +00:00
|
|
|
ln -sv ${configfile} $buildRoot/.config
|
2012-07-29 08:49:52 +01:00
|
|
|
make $makeFlags "''${makeFlagsArray[@]}" oldconfig
|
2012-07-29 06:23:51 +01:00
|
|
|
runHook postConfigure
|
|
|
|
'';
|
|
|
|
|
2013-03-02 09:41:53 +00:00
|
|
|
nativeBuildInputs = [ perl bc nettools ];
|
2012-07-29 09:59:38 +01:00
|
|
|
|
2012-08-01 19:15:26 +01:00
|
|
|
makeFlags = commonMakeFlags ++ [
|
|
|
|
"INSTALLKERNEL=${installkernel stdenv.platform.kernelTarget}"
|
|
|
|
];
|
|
|
|
|
|
|
|
crossAttrs = {
|
|
|
|
makeFlags = commonMakeFlags ++ [
|
|
|
|
"INSTALLKERNEL=${installkernel stdenv.cross.platform.kernelTarget}"
|
|
|
|
];
|
|
|
|
};
|
2012-07-29 06:23:51 +01:00
|
|
|
|
2012-08-07 11:36:50 +01:00
|
|
|
postInstall = optionalString installsFirmware ''
|
2012-08-01 16:56:12 +01:00
|
|
|
mkdir -p $out/lib/firmware
|
|
|
|
'' + (if isModular then ''
|
2012-07-29 07:57:58 +01:00
|
|
|
make modules_install $makeFlags "''${makeFlagsArray[@]}" \
|
|
|
|
$installFlags "''${installFlagsArray[@]}"
|
2012-08-12 02:07:37 +01:00
|
|
|
rm -f $out/lib/modules/${modDirVersion}/build
|
2013-03-02 14:53:56 +00:00
|
|
|
mkdir -p $dev/lib/modules/${modDirVersion}
|
|
|
|
mv $out/lib/modules/${modDirVersion}/source $dev/lib/modules/${modDirVersion}/source
|
|
|
|
mv $buildRoot $dev/lib/modules/${modDirVersion}/build
|
2012-08-01 11:18:03 +01:00
|
|
|
'' else optionalString installsFirmware ''
|
|
|
|
make firmware_install $makeFlags "''${makeFlagsArray[@]}" \
|
|
|
|
$installFlags "''${installFlagsArray[@]}"
|
2012-08-01 16:56:12 +01:00
|
|
|
'');
|
2012-07-29 09:23:28 +01:00
|
|
|
|
2013-03-02 12:51:12 +00:00
|
|
|
postFixup = if isModular then ''
|
2012-07-29 09:23:28 +01:00
|
|
|
if [ -z "$dontStrip" ]; then
|
2012-08-02 04:32:02 +01:00
|
|
|
find $out -name "*.ko" -print0 | xargs -0 -r strip -S
|
2013-03-02 14:53:56 +00:00
|
|
|
# Remove all references to the source directory to avoid unneeded
|
|
|
|
# runtime dependencies
|
|
|
|
find $out -name "*.ko" -print0 | xargs -0 -r sed -i \
|
|
|
|
"s|${sourceRoot}|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${sourceRoot.name}|g"
|
2012-07-29 09:23:28 +01:00
|
|
|
fi
|
2013-03-02 12:51:12 +00:00
|
|
|
'' else null;
|
|
|
|
|
2012-08-01 11:18:03 +01:00
|
|
|
meta = {
|
|
|
|
description = "The Linux kernel";
|
|
|
|
license = "GPLv2";
|
|
|
|
homepage = http://www.kernel.org/;
|
|
|
|
maintainers = [
|
|
|
|
maintainers.shlevy
|
|
|
|
];
|
|
|
|
platforms = lib.platforms.linux;
|
|
|
|
};
|
2012-08-12 02:21:06 +01:00
|
|
|
}
|