#!/usr/bin/perl -w

# the first parameter is the data dump, the second param is the key to look for to begin and end, the third is the length of the last byteset, and the return is the binary data
# this is the function you probably want to use
sub parseDump {
	my @strippedData = stripData($_[0],$_[1]);
	my $totalBin = "";
	my $count = 1;
	foreach $line (@strippedData) {
		if ($count == scalar(@strippedData)) {
			# the additional param tells it to only read that number of bytes
			$totalBin .= dataToBin($line,$_[2]);
		} else {
			$totalBin .= dataToBin($line);
		}
		$count++;
	}
	
	return $totalBin;
}

# function to pick out the good data and identify any misordering
# this function will return an array of only the hex digits separated by spaces
sub stripData {
	my @strippedLines;
	my $startkey = $_[1];
	my $count = 0;
	my $foundStart = 0;
	my @seplines = split(/\n/,$_[0]);
	my $append = 0;
	foreach $line (@seplines) {
		# check to see if the previous line was messed up and needs this one appended to it
		if ($append == 1) {
			$line =~ /kernel: (.*)/;
			$strippedLines[$count - 1] .= $1;
			chomp ($strippedLines[$count-1]);
		}
		# now that any messed up lines have been taken care of, make sure $append gets decremented
		if ($append > 0) {
			$append--;
		} elsif ($foundStart eq 1 and $line =~ /$startkey dump complete/) {
			#print "Found end!\n";
			return @strippedLines;
		} elsif ($line =~ /$startkey dump/) {
			#print "Found starting point\n";
			$foundStart = 1;

		} elsif ($foundStart eq 1 and $line =~ /kernel: 0x0[08]([a-fA-F0-9]{6}): (.*)$/) {
			# check for junk thrown in to the data stream and remove if necessary
			my $hexdigits = $1;
			my $tmpline = $2;
			if ($tmpline =~ s/(.*)<7>.*/$1/) {
				# append the next line
				$append = 1;
			} elsif ($tmpline =~ s/(.*)<4>.*/$1/) {
				# skip two lines before appending
				$append = 3;
			}
			if (hex($hexdigits)/200 == $count) {
				#print "Good data\n";
				$strippedLines[$count] = $tmpline;
				chomp ($strippedLines[$count]);
				$count++;
			} else {
				print "Warning! Data set ",hex($1)/200," on count $count\n";
				print hex($1)/200-($count-1)." lines missing!\n";
				exit 1;
			}
		}
	}
}

# this function takes in a string of hex digits separated by spaces and converts it to a binary string
# there should be exactly 200 hex values on every line
sub dataToBin {
	my $retstring = "";
	# strip the ^M off the end
	$_[0] =~ s/\r//;
	my @hexsets = split(/ /, $_[0]);
	my $count = 0;
	foreach $hexchar (@hexsets) {
		$retstring .= chr(hex($hexchar));
		if (scalar(@_) == 2 && $_[1]-1 == $count) {
			last;
		}
		$count++;
	}
	if ($count != 200 && scalar(@_) == 1) {
		print "Warning! $count values were found for this line!\n";
	}
	return $retstring;
}


# turn on autoflush
$|=1;
# this script takes the output from the WCTC4xxp card and converts the hex dump to a binary dump file (missing the last 10 bytes....)
my $tmp = @ARGV;
if ($tmp < 2 or $tmp > 4) {
	print "Proper usage of this script is as follows:\n binparse.pl [-s ][-e ]<input file from dmesg> <binary output base name>\n";
	exit 1;
}
my $count = 0;
my $eramdump = 0;
my $sdramdump = 0;
my $infile = "";
my $outfile = "";
foreach $_ (@ARGV) {
	if ($_ =~ /-e/) {
		$eramdump = 1;
	} elsif ($_ =~ /-s/) {
		$sdramdump = 1;
	} elsif ($count == 0) {
		$infile = $_;
		$count++;
	} elsif ($count == 1) {
		$outfile = $_;
	}
}
if ($eramdump == 0 and $sdramdump == 0) {
	print "You didn't request a dump output type.  Please specify -e and/or -s.\n";
	exit 1;
} elsif ($infile =~ /^$/ or $outfile =~ /^$/) {
	print "You're missing the input and/or output file.  You need both.\n";
	exit 1;
}
print "Reading input data...";
my $data = `cat $infile`;
print "done.\n";
if ($sdramdump == 1) {
	print "Parsing dump for SDRAM data...";
	my $sdout = parseDump($data,"SDRAM",16);
	open (OUTFILE, ">",$outfile.".sdram");
	print OUTFILE $sdout;
	close OUTFILE;
	if (-s $outfile.".sdram" != 16777216) {
		print "WARNING: The output file does not appear to be the correct size!\n";
	} else {
		print "done\n";
	}
}

if ($eramdump == 1) {
	print "Parsing dump for ERAM data...";
	my $eout = parseDump($data,"ERAM",64);
	open (OUTFILE, ">",$outfile.".eram");
	print OUTFILE $eout;
	close OUTFILE;
	if (-s $outfile.".eram" != 1572864) {
		print "WARNING: The output file does not appear to be the correct size!\n";
	} else {
		print "done\n";
	}
}

exit 0;
