#!/bin/sh
# --------------------------------------------------------------------------------------------
#
#                                                                        kernel liberator v1.1
#
# In kernel 2.6.25, the kernel developers introduced some restrictions to the linux kernel.
# Non-GPL USB drivers and ndiswrapper are no longer given access to gpl only symbols. This
# means that such modules which allow many peripheral devices to work with linux can not be
# loaded any more, thus rendering these devices useless in linux. I'd like to note that the
# developers had their reasons for doing this, which I don't judge here. However, from the view
# of a linux user, this is just annoying and not acceptable. Very many people rely on ndiswrapper
# for running their WLAN cards. In recent laptops these WLAN cards are often# built-in, so users
# can't even replace the card with a new one that is supported by gpl-compliant drivers. This
# script removes these restrictions, giving all drivers access to gpl only symbols, by patching
# the kernel source files. When a symbol is exported as a gpl only, EXPORT_SYMBOL_GPL is used.
# The definition of EXPORT_SYMBOL_GPL is in the file "include/linux/module.h". Changing the
# definition of EXPORT_SYMBOL_GPL in a way that an gpl-only symbol is no longer recognized as
# such will disable this mechanism, allowing all drivers to use all symbols, no matter if
# marked gpl-only or not.
#
# The syntax is very simple. You pass the path to the kernel you want to patch, for example:
# kernel-liberator.sh /usr/src/linux-2.6.25.
#
# Running the script without parameters will show the built-in help.
#
# A closing remark: It's great to have sources. In a closed source system, such a patch
# would've been far more difficult.
#
# Disclaimer: I am not responsible for direct and indirect damage caused by this script.
#             You use this software at your own risk !
#
# License:    GPL v2
#
# Author:     da.phreak@gmx.net. Please include kernel liberator in the subject line
#
# History:    v1.1  Changed from removing all EXPORT_SYMBOL_GPL in all source filed to
#                   just modifying the definition of EXPORT_SYMBOL_GPL.
#             v1.0  Initial Release
# --------------------------------------------------------------------------------------------

function help {
    echo ""
    echo "kernel liberator - Liberates the linux kernel from gpl only restrictions."
    echo ""
    echo ""
    echo "Syntax: $0 [--fullclean] path_to_kernel"
    echo ""
    echo "        --fullclean: By default, this script only patches the file module.h and"
    echo "                     disables the EXPORT_SYMBOL_GPL machanism. If you want your"
    echo "                     kernel totally free of any GPL only references, use this"
    echo "                     option. It is not necessary, but probably makes you feel"
    echo "                     better knowing everything is removed :-)."
    echo "                     If not sure, omit this parameter and only specify the path to"
    echo "                     the kernel source."
    echo ""
}

function init {
  fullclean=0

  if [ $argc -eq 0 ]; then
    help
    exit 1
  fi

  if [ $argc -eq 1 ]; then
    dir="$argv1"
  fi

  if [ $argc -eq 2 ]; then
    dir="$argv2"
    if [ "$argv1" == "--fullclean" ]; then
      fullclean=1
    else
      help
      exit 1
    fi
  fi

  cd "$dir" 2> /dev/null

  if [ $? -gt 0 ]; then
    echo "Error: Can't chdir to directory $dir"
    exit 1
  fi

  moduleh="include/linux/module.h"
  tmp="/tmp/kernel-liberator.tmp"
}

function patch_moduleh {
  gr=$(grep '"_gpl"' "$moduleh")
  if [ "$gr" == "" ]; then
    echo "File $moduleh is already patched."
  else
    echo "Patching file $moduleh."
    sed 's/"_gpl"/""/' "include/linux/module.h" | sed 's/"_gpl_future"/""/'  > "$tmp"
    rm -f "$moduleh"
    mv "$tmp" "$moduleh"
  fi
}

function check_gpl_only {
  gplonly=0
  gr=$(grep "EXPORT_SYMBOL_GPL" "$F")
  if [ "$gr" != "" ]; then
    gplonly=1
  fi
}

function replace_gpl_only {
  echo "Patching file $F"
  sed 's/EXPORT_SYMBOL_GPL_FUTURE/EXPORT_SYMBOL/g' "$F" | sed 's/EXPORT_SYMBOL_GPL/EXPORT_SYMBOL/g' > "$tmp"
  rm -f "$F"
  cp "$tmp" "$F"
}

function fullclean_source {
  cfiles=$(find . -type f -name "*.c")

  for F in $cfiles
  do
    check_gpl_only

    if [ $gplonly -eq 1 ]; then
      replace_gpl_only
    fi
  done

  rm -f "$tmp"
}



#                         -- Main --

argc=$#; argv1=$1; argv2=$2

init
patch_moduleh

if [ $fullclean -eq 1 ]; then
  fullclean_source
fi

#                         ----------

