#!/usr/bin/env perl
# grubmod - modifies grub.conf for predefined monitor options
# usage: grubmod <xorg-driver> <os_distributor> <os_release_major> <os_release_minor>
# Joacim 17.8.2007 
# Sist endret av Ole B 29/4-2019

#use strict;
#use warnings;

use Tie::File;
use File::Copy;

my $xorgdrv = $ARGV[0] or die "Program argument <xorg-driver> missing: $!";
my $distro = $ARGV[1] or die "Program argument <os_distributor> missing: $!";
my $release_major = $ARGV[2] or die "Program argument <os_release_major> missing: $!";
my $release_minor = $ARGV[3] or die "Program argument <os_release_minor> missing: $!";

my $ititle = "Fully automatic display";
my $ikid = "dynamic";

# Is this safe for older hardware with real IDE disks?
if ($distro =~ /CentOS/ && $release_major == 5 && $release_minor == 5) {
	$ikid = "hda=noprobe hdc=noprobe dynamic";
}

# Oleb 26/10-2011: Nomodeset ga tullebilde p� M1 med F11
# if ($distro =~ /Fedora/ && ($release_major == 11 || $release_major == 12)) {
# 	$ikid = "nomodeset $ikid";
# }

# Oleb 29/4-2019: La til "singledisplay " for de som skal v�re single p� M3
my @stattab = ("Single display 1280x1024",
	       "singledisplay 1280x1024",
	       "Single display 1024x768",
	       "singledisplay 1024x768",
	       "Single display 800x600",
	       "singledisplay 800x600"
);

my @atitab = ("Dual display 1280x1024",
	      "ati_1280x1024",
	      "Dual display 1024x768",
	      "ati_1024x768",
	      "Dual display 800x600",
	      "ati_800x600"
);

my @inteltab = ("Dual display 1280x1024",
		"intel_1280x1024",
		"Dual display 1024x768",
		"intel_1024x768",
		"Dual display 800x600",
		"intel_800x600"
);

my $gc_fname = "/boot/grub/grub.conf";
my $gc_backup = "/boot/grub/grub.conf.gmbackup";
my $default = -1;
my @gconf;
my @titles;
my @default;
my $splash;

if (! -e $gc_backup) {
	copy($gc_fname, $gc_backup) or die "Copy failed: $!";
}

tie @gconf, 'Tie::File', $gc_fname or die "Can't open $gc_fname: $!";

for (my $i = 0; $i < @gconf; $i++) {
	if ($gconf[$i] =~ /^title\s/) {
		push @titles, $i;
	}
	elsif ($gconf[$i] =~ /^default=(.)/) {
		$default = $1;
	}
	elsif ($gconf[$i] =~ /splashimage=/) {
		$splash = $gconf[$i];
	}
}

if ($default >= 0) {
	if ($default < @titles-1) {
		for (my $i = $titles[$default]; $i < $titles[$default+1]; $i++) {
			push @default, $gconf[$i];
		}
	}
	else {
		for (my $i = $titles[$default]; $i < @gconf; $i++) {
			push @default, $gconf[$i];
		}
	}
}

my $linux = 0;
foreach (@default) {
	if ( /kernel\s.*vmlinuz/ ) {
		$linux = 1;
	}
}

# use first linux boot entry instead
my @linux;
my $firstlinux = 0;
if ($linux == 0) {
	TITLE: for (my $i = 0; $i < @titles; $i++) {
		if ( $i < @titles-1 ) {
			for (my $j = $titles[$i]; $j < $titles[$i+1]; $j++) {
				push @linux, $gconf[$j];
			}
		}
		else {
			for (my $j = $titles[$i]; $j < @gconf; $j++) {
				push @linux, $gconf[$j];
			}
		}
		foreach (@linux) {
			if ( /kernel\s.*vmlinuz/ ) {
				$firstlinux = 1;
			}
		}
		if ($firstlinux) {
			last TITLE;
		}
		@linux = ();
	}
	if (! $firstlinux) {
		print "grubmod: ERROR - No linux boot entry found!\n";
		exit 1;
	}
}
else {
	@linux = @default;
}

# keep non-linux titles
my @others;
for (my $i = 0; $i < @titles; $i++) {
	my @tmp;
	if ($i < @titles-1) {
		for (my $j = $titles[$i]; $j < $titles[$i+1]; $j++) {
			push @tmp, $gconf[$j];
		}
	}
	else {
		for (my $j = $titles[$i]; $j < @gconf; $j++) {
			push @tmp, $gconf[$j];
		}
	}
	my $type = "unknown";
	foreach (@tmp) {
		if ( /kernel\s.*vmlinuz/ ) {
			$type = "linux";
		}
		elsif ( /chainloader\s.*/ ) {
			$type = "other";
		}
	}
	if ($type eq "other") {
	    	push @tmp, "\tsavedefault";
		push @others, @tmp;
	}
	@tmp = ();
}

@gconf = ( "# Olex grub.conf",
	   "default saved",
	   "timeout=30",
	   "foreground ffffff",
	   "background 000000",
	   $splash );

my $snutoskjerm;
@snutoskjerm = @linux;

foreach (@linux) {
	s/(^title).*$/$1 $ititle/;
	s/kernel.*$/$& $ikid/;
}
push @linux, "\tsavedefault";
push @gconf, @linux;

# Oleb 11/11-2015 - lag ekstra snutoskjerm

foreach (@snutoskjerm) {
	s/(^title).*$/$1 Fully automatic display with swapped screens/;
	s/kernel.*$/$& $ikid snutoskjerm/;
}
push @snutoskjerm, "\tsavedefault";
push @gconf, @snutoskjerm;

#

my @newlinux;
my @linuxs;
for (my $i = 0; $i < @stattab; $i++) {
	@newlinux = @linux;
	foreach (@newlinux) {
		s/(^title).*$/$1 $stattab[$i]/;
		s/(kernel.*)\sdynamic$/$1 $stattab[++$i]/;
	}
	push @linuxs, @newlinux;
}
if ($xorgdrv =~ /intel/ || $xorgdrv =~ /i810/) {
	for (my $i = 0; $i < @inteltab; $i++) {
		@newlinux = @linux;
		foreach (@newlinux) {
			s/(^title).*$/$1 $inteltab[$i]/;
			s/(kernel.*)\sdynamic$/$1 $inteltab[++$i]/;
		}
		push @linuxs, @newlinux;
	}
}
elsif ($xorgdrv =~ /radeon/ || $xorgdrv =~ /ati/) {
	for (my $i = 0; $i < @atitab; $i++) {
		@newlinux = @linux;
		foreach (@newlinux) {
			s/(^title).*$/$1 $atitab[$i]/;
			s/(kernel.*)\sdynamic$/$1 $atitab[++$i]/;
		}
		push @linuxs, @newlinux;
	}
}
push @gconf, @linuxs; 

if (($distro =~ /Fedora/ && $release_major >= 11)
    || $distro =~ /Scientific Linux/) {
	my $ftitle = "Fallback VESA single display";
	my $fkid = "fallback"; 
	if (($distro =~ /Fedora/ && $release_major >= 13)
	    || $distro =~ /Scientific Linux/) {
		$fkid = "nomodeset fallback";
	}
	my @fallback = @linux;
	foreach (@fallback) {
		s/(^title).*$/$1 $ftitle/;
		s/(kernel.*)\sdynamic$/$1 $fkid/;
	}
	push @gconf, @fallback; 
}

push @gconf, @others; 

untie @gconf;
exit 0;