#!/usr/bin/perl
use strict;

my $debug = 0;

die "Usage: $ARGV[0] <srctree> <objtree> <dtb-file> <overlay-tool> <its-dir>\n"
		if @ARGV != 5;

my $srctree = shift @ARGV;
my $objtree = shift @ARGV;
my $dtb_tgt = shift @ARGV;
my $fdtoverlay = shift @ARGV;
my $dir = shift @ARGV;

print "  DTC-M   $dtb_tgt\n";

# Find all .its files
my @its_files = glob "$srctree/$dir/*.its";

my $tgt;

# Generate target config string
if ($dtb_tgt =~ /\/([^\/]+)\.dtb$/) {
  $tgt = $1;
}

my @dtbs;

# Parse all .its files to find corresponding config
foreach my $its_file (@its_files) {
  open my $in,"<$its_file" or die "Unable to open $its_file\n";

  my $conf = 0;
  my $image = 0;

  my %conf_map = ();
  my %image_map = ();

  foreach (<$in>) {
    if (/^\s*images \{/) {
      $image = 1;
      next;
    }
    if ($image && /(\S*) \{/) {
      $image = $1;
    }
    if ($image && /data\s*=\s*\/incbin\// && /\"(.*)\"/) {
      $image_map{$image} = $1;
    }
    if (/^\s*configurations \{/) {
      $conf = 1;
      $image = 0;
      next;
    }
    if ($conf && /(\S*) \{/) {
      $conf = $1;
      $conf =~ s/\.dtb$//;
    }
    if ($conf && /fdt = (.*);/) {
      my $fdts = $1;
      $fdts =~ s/ |"//g;
      $conf_map{$conf} = { fdts => [] };
      foreach my $fdt (split ",", $fdts) {
        push @{ $conf_map{$conf}->{fdts} }, $image_map{$fdt};
      }
    }
  }

  close $in;

  # Try matching the config
  @dtbs = find_config(\%conf_map, $tgt);
  last if @dtbs;
}

die "No config found for $tgt\n" if !@dtbs;

print "Found config for $tgt:\n" if $debug;

# Generate the merged dtb file
my $cmd = "$fdtoverlay";
$cmd .= " -v" if $debug;
$cmd .= " -o $dtb_tgt -i";

foreach my $dtb (@dtbs) {
  $cmd .= " $objtree/$dir/$dtb";
}

exit system($cmd);

sub find_config {
  my $map = shift @_;
  my $conf = shift @_;

  my @confs = split("-",$conf);

  for (my $i = @confs - 1; $i >= 0; $i--) {
    my $tmp = join("-",@confs[0 .. $i]);
    if ($map->{$tmp}) {
      if ($i == @confs - 1) {
        return @{ $map->{$tmp}->{fdts} };
      } else {
        my @res = find_config($map, join("-",@confs[$i + 1 .. @confs - 1]));
        return @{ $map->{$tmp}->{fdts} }, @res if @res;
      }
    }
  }

  return ();
}
