#!/usr/bin/perl

#
# Linux kernel auto build script for various models and
# locales. Version 20020603
#
# See the arrays below for defining models and features.
#
# Copyright 2002 Tony Lindgren <tony@atomide.com>
#
# CHANGELOG
# 20020603 Added "def-configs" switch to just update the default config
#          files for various machines in arch/arm/def-configs/

use Cwd;

my $root_dir = "/home/arm";
my $src_dir = $root_dir."/dev/linux";
my $target_dir = "/home/upload/armlinux/kernels_must_be_uncompressed";

my $version = "";
my $config = "";

my @remove_files = (
  "drivers/char/keymap_psion*.c",
  "drivers/char/*.o",
  "drivers/ide/*.o",
  "drivers/pcmcia/*.o",
  "drivers/sound/*.o",
  "arch/arm/mach-psionw/*.o",
  "arch/arm/boot/Image"
);

my @locales = (
  "CONFIG_PSION_KBD_UK",
  "CONFIG_PSION_KBD_US",
  "CONFIG_PSION_KBD_DE"
);

my @config_machines = (
  "CONFIG_PSIONW_5MX",
  "CONFIG_PSIONW_5MXPRO24MB",
  "CONFIG_PSIONW_5MXPRO32MB",
  "CONFIG_PSIONW_REVO",
  "CONFIG_PSIONW_REVOPLUS"
);

my @config_extra_features = (
  "CONFIG_PCMCIA",
  "CONFIG_PCMCIA_ETNA",
  "CONFIG_NET_PCMCIA",
  "CONFIG_PCMCIA_PCNET",
  "CONFIG_IDE",
  "CONFIG_BLK_DEV_IDE",
  "CONFIG_BLK_DEV_IDEDISK",
  "CONFIG_BLK_DEV_IDECS"
);

# Array fields: Desc, Machine, Locales, Extra
my @machine_types = (
  ["psion_5mx_ericsson_mc218_16mb",     0, [0, 1, 2], 1],
  ["psion_5mx_pro_24mb",                1, [2      ], 1],
  ["psion_5mx_pro_32mb",                2, [2      ], 1],
  ["psion_revo_8mb",                    3, [0, 1, 2], 0],
  ["psion_revo_plus_diamond_mako_16mb", 4, [0, 1, 2], 0]
);

##
# Main Program
##
my($option) = @ARGV;

my $config_only = 0;
if ($option eq "def-configs") {
    print "Skipping build; Only update def-configs\n";
    $config_only = 1;
}

$version = get_version();
die("ERROR: Could not get the version\n") if ($version eq "");

$config = load_config();
die("ERROR: Could not load the .config file\n") if ($config eq "");

# Make sure we have a current config by runnin make menuconfig
#make_def_config();

# Iterate through the machines and do the build
foreach my $ref (@machine_types) {
  my($machine_desc, $machine_number, 
     $locale_ref, $machine_extra_features) = @$ref;
  build_locales($machine_desc, $machine_number,
		$locale_ref, $machine_extra_features,
                $config_only);
}

##
# Subroutines
##

sub build_locales() {
  my($machine_desc, $machine_number, 
     $locale_ref, $machine_extra_features,
     $config_only) = @_;
  my @machine_locales = @$locale_ref;

  print "\n\n***** Starting build for machine ".$machine_desc." *****\n\n";
  print "Machine number: ".$machine_number."\n";
  print "Locales:        ";
  foreach my $machine_locale (@machine_locales) {
    print $machine_locale." ";
  }
  print "\n";
  print "Extras:         ".$machine_extra_features."\n\n";

  foreach my $machine_locale (@machine_locales) {
    build($machine_desc, $machine_number,
	  $machine_extra_features, $machine_locale, 
          $config_only);
  }
}

sub build() {
  my($machine_desc, $machine_number, $machine_extra_features, $locale,
    $config_only) = @_;
  my $machine_option = @config_machines[$machine_number];
  my $locale_desc = @locales[$locale];
  my $locale_file_name = lc(substr($locale_desc, length($locale_desc) - 2));
  print "Building locale ".$locale_file_name."\n";
  my $cur_config = "# Automatically configured for ".
    $locale_file_name." ".
    $machine_desc;

  # Remove the unwanted files
  print "Removing unwanted files\n";
  foreach my $unwanted_file (@remove_files) {
    $unwanted_file = $src_dir."/".$unwanted_file;
    open SHELL, "rm -f $unwanted_file|";
    while (<SHELL>) {
      print;
    }
    close SHELL;
  }

  # Make a backup copy of the .config file
  my $config_file = $src_dir."/".".config";
  my $backup_file = $config_file.".bak";
  print "Making a backup copy of .config file\n";
  open SHELL, "cp $config_file $backup_file|";
  while (<SHELL>) {
    print;
  }
  close SHELL;

  my @lines = split("\n", $config);
  my $counter = 0;
  foreach my $line (@lines) {

    # Look for the machine type
    if ($line =~ /CONFIG_PSIONW_/) {
      #print "Found machine type: ".$line."\n";
      if ($line =~ /$machine_option/) {
	#print "Setting machine ".$machine_option."\n";
	@lines[$counter] = $machine_option."=y";
      } else {
	#print "Clearing option ".$line."\n";
	@lines[$counter] = "\# PSION machine option removed";
      }
    }

    # Look for the keyboard
    if ($line =~ /PSION_KBD/) {
      #print "Found locale: ".$line."\n";
      if ($line =~ /$locale_desc/) {
	#print "Setting option ".$locale_desc."\n";
	@lines[$counter] = $locale_desc."=y";
      } else {
	#print "Clearing option ".$line."\n";
	@lines[$counter] = "\# PSION keyboard option removed";
      }
    }

    # Filter out PCMCIA, IDE, etc
    if ($machine_extra_features == 0) {
      #print "Filtering extra features\n";
      for my $feature (@config_extra_features) {
	if ($line =~ /$feature/) {
	  #print "Filtering out extra feature: ".$feature."\n";
	  @lines[$counter] = "\# PSION extra feature removed";
	} else {
	  # Do nothing
	}
      }
    }
    $cur_config = join("\n",$cur_config, $line);
    $counter++;
  }

  #print "Cur_config: ".$cur_config."\n";
  print "Writing a new .config file for this build\n";
  open CONFIG_FILE, ">$config_file";
  foreach my $line (@lines) {
    print CONFIG_FILE $line."\n";
  }
  close CONFIG_FILE;

  # Generate include/linux/autoconf.h (yes "" | make config)
  $autoconfig_cmd = "yes \"\"\| make config";
  open CONFIG, "$autoconfig_cmd|";
  while (<CONFIG>) {
    print;
  }

  # Copy the machine specific .config file to arch/arm/def-configs/
  my $mach_config_file = $src_dir."/arch/arm/def-configs/".$machine_desc;
  print "Updating the machine config file in def-configs: ".
    $mach_config_file."\n";

  # Only create a def-config file for the first locale (UK)
  if ($locale == 0) {
    my @def_config_copy_cmd = ("cp", $config_file, $mach_config_file);
    system(@def_config_copy_cmd) == 0 
      or die "ERROR: Copying of kernel failed: $?";
  }

  # Restore .config file and return early if config_only is specified
  if ($config_only) {
    # Copy backup file back to .config file
    print "Restoring .config file\n";
    open SHELL, "cp $backup_file $config_file|";
    while (<SHELL>) {
      print;
    }
    close SHELL;

    return;
  }

  # Build the kernel if config_only is not specified
  print "Starting the kernel build\n";
  chdir($src_dir);
  $ENV{'MAKE'} = "make -j2";
  my @build_cmd = ("make", "dep", "Image");
  system(@build_cmd) == 0 or die "ERROR: Build failed: $?";

  # Copy the kernel to the right location
  $version_dir = $target_dir."/".$version;
  $locale_dir = $version_dir."/".$locale_file_name;
  open DIR, "$version_dir";
  if (-d DIR) {
    print "Found target directory: ".$version_dir."\n";
  } else {
    my @versiondircmd = ("mkdir", $version_dir);
    system(@versiondircmd) == 0 or die "ERROR: mkdir failed: $?";
  }
  close DIR;

  open DIR, "$locale_dir";
  if (-d DIR) {
    print "Found target directory: ".$locale_dir."\n";
  } else {
    my @localedircmd = ("mkdir", $locale_dir);
    system(@localedircmd) == 0 or die "ERROR: mkdir failed: $?";
  }
  close DIR;

  my $kernel_image = $src_dir."/arch/arm/boot/Image";
  my $kernel_locale = $locale_dir."/".$machine_desc;
  my @copy_cmd = ("cp", $kernel_image, $kernel_locale);
  system(@copy_cmd) == 0 or die "ERROR: Copying of kernel failed: $?";

  # Compress the kernel
  my @compress_cmd = ("gzip", $kernel_locale);
  system(@compress_cmd) == 0 or die "ERROR: Compressing the kernel failed: $?";


  # Copy backup file back to .config file
  print "Restoring .config file\n";
  open SHELL, "cp $backup_file $config_file|";
  while (<SHELL>) {
    print;
  }
  close SHELL;

  # Done with this build!
}

sub load_config() {
  print "Loading the current config file\n";
  my $config = "";
  chdir $src_dir;
  open(IN, "<.config");
  while (<IN>) {
    $config = $config.$_;
  }
  close IN;
  return $config;
}

sub get_version() {
  print "Getting version number\n";
  my $version = "";

  chdir $src_dir;
  open(IN, "<Makefile");
  while (<IN>) {
    if (/^VERSION =/) {
      $version = get_field("VERSION", $_);
    }
    if (/^PATCHLEVEL =/) {
      $version = $version.".".get_field("PATCHLEVEL", $_);
    }
    if (/^SUBLEVEL =/) {
      $version = $version.".".get_field("SUBLEVEL", $_);
    }
    if (/^EXTRAVERSION =/) {
      $version = $version.get_field("EXTRAVERSION", $_);
      break;
    }
  }
  close IN;
  print "Building for kernel version ".$version."\n";
  return $version;
}

sub get_field() {
  (my $name, my $data) = @_;
  my $key = "";
  my $val = "";
  $data =~ chomp($data);
  #print "Getting ".$name." from ".$data."\n";
  ($key, $val) = split("=", $data);
  $key =~ s/ //g;
  $val =~ s/ //g;
  #print "Got val \"".$val."\"\n";
  return $val;
}
