| #!/bin/sh |
| # Not every host installs perl at the same location, handle many locations: |
| PATH=/usr/bin:/usr/local/bin:$PATH |
| exec perl -x -S $0 ${1+"$@"} |
| exit $? |
| #!perl -w |
| #line 8 |
| |
| # xt-buildroot-overlay-install [-t overlay_tarball] [-b buildroot_dir] \ |
| # [-k kernel_dir] \ |
| # [-c config_name] [-l long_name] [-f] [--help] |
| # |
| # Creates individual overlay tarballs for gcc, binutils, gdb, and |
| # the Linux kernel, out of the Xtensa Configuration Overlay tarball from |
| # a Tensilica Core Package. And installs these individual tarballs |
| # at the appropriate locations within a buildroot source tree. |
| # |
| # The Xtensa configuration overlay tarball is located in: |
| # <xtensa_root>/src/xtensa-config-overlay.tar.gz |
| # where <xtensa_root> is the path to the Tensilica Core Package. |
| # |
| # Copyright (c) 2003-2009 by Tensilica Inc. |
| # History: |
| # 2007-NOV-08 1.0 meg Initial version |
| # 2007-NOV-21 1.1 meg Add -k parameter |
| # 2007-DEC-06 1.2 meg Make -k and -b optional, check overlay sw vers. |
| # 2008-FEB-27 1.3 meg Accept Xtensa Tools RB-2008.3 overlays |
| |
| $progvers = "1.3"; |
| $progname = $0; |
| $progname =~ s|.*[/\\:]||; |
| |
| |
| ###################################################################### |
| # |
| # Parse cmdline |
| # |
| |
| my $overlay_tarball = undef; |
| my $buildroot_dir = undef; |
| my $kernel_dir = undef; |
| my $config_name = undef; |
| my $config_long_name = undef; |
| my $force_clobber = 0; |
| my $prompt = 1; # undocumented option |
| |
| sub usage { |
| print "$progname version $progvers\n" |
| ."Usage: $progname <parameters> [<options>]\n" |
| ."Where <parameters> are:\n" |
| ." -t file.tgz Specify path to the Xtensa Linux overlay tarball, typically\n" |
| ." <xtensa_root>/src/xtensa-config-overlay.tar.gz\n" |
| ." -b dir Path to the base of the buildroot source tree, in which\n" |
| ." package specific overlay tarballs get installed.\n" |
| ." -k dir Path to the base of the Linux kernel source tree, in which\n" |
| ." the Linux kernel specific overlay gets installed.\n" |
| ." -c config_name Name for the Xtensa processor configuration as it will be\n" |
| ." known to the open source community. Must be a lowercase\n" |
| ." identifier, starting with a letter, consisting of letters\n" |
| ." and numbers and underscores, not ending with underscore\n" |
| ." and not containing consecutive underscores. For examples:\n" |
| ." dc232b , dc232b_be , mmubasele , fsf , s5000 .\n" |
| ." -l long_name Long name for the Xtensa processor configuration, human-\n" |
| ." readable with spaces etc allowed (must be quoted).\n" |
| ." For example: 'Diamond 232L Standard Core Rev.B (LE)'\n" |
| ." Try to keep it within approximately 40 characters.\n" |
| ."And <options> are:\n" |
| ." -f If package specific overlay tarballs already exist in\n" |
| ." the destination source tree, overwrite them without asking.\n" |
| ." --help Show this usage message.\n"; |
| } |
| |
| # Get arguments: |
| if (!@ARGV) { |
| usage(); |
| exit 0; |
| } |
| while( defined($_ = shift) ) { |
| if( /^-[tbclk]$/ ) { # option taking an argument |
| my $arg = shift; |
| if( !defined($arg) ) { |
| print STDERR "$progname: ERROR: missing parameter after '$_' option\n\n"; |
| usage(); |
| exit 1; |
| } |
| $overlay_tarball = $arg if $_ eq "-t"; |
| $buildroot_dir = $arg if $_ eq "-b"; |
| $kernel_dir = $arg if $_ eq "-k"; |
| $config_name = $arg if $_ eq "-c"; |
| $config_long_name = $arg if $_ eq "-l"; |
| next; |
| } |
| if( /^-f$/ ) { |
| $force_clobber = 1; |
| next; |
| } |
| if( /^--[m-t]{8}$/ && /[new]([wow])([pup])[fur]\1[maze]\2[tuff]/ ) { |
| $prompt = 0; |
| next; |
| } |
| if( /^-(h|help|\-h|\-help|\?)$/i ) { |
| usage(); |
| exit 0; |
| } |
| print STDERR "$progname: ERROR: unrecognized option or argument '$_'\n\n"; |
| usage(); |
| exit 1; |
| } |
| |
| |
| ###################################################################### |
| # |
| # Validate cmdline arguments |
| # |
| |
| ErrorU("missing -c argument (core name)") |
| unless defined($config_name); |
| # Try to enforce reasonable names: |
| ErrorU("-c: malformed core name '$config_name' (must be lowercase, letter followed by letters/digits, may contain underscore separators)") |
| unless $config_name =~ /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/; |
| ErrorU("-c: core name too short '$config_name'") |
| unless length($config_name) >= 2; |
| ErrorU("-c: core name too long '$config_name'") |
| unless length($config_name) <= 16; |
| |
| |
| ErrorU("missing -l argument (core long name)") |
| unless defined($config_long_name); |
| $config_long_name =~ s/^\s+//; # trim extra whitespace... |
| $config_long_name =~ s/\s+$//; |
| $config_long_name =~ s/\s+/ /g; |
| # Try to enforce reasonable names: |
| ErrorU("-l: invalid (non-ASCII-printable) characters in core long name '$config_long_name'") |
| unless $config_long_name =~ /^[\x20-\x7E]+$/; |
| ErrorU("-l: disallowed characters (\"\'\\) in core long name '$config_long_name'") |
| if $config_long_name =~ /[\'\"\\]/; |
| ErrorU("-l: core long name too short '$config_long_name'") |
| unless length($config_long_name) >= 5; |
| ErrorU("-l: core long name too long '$config_long_name'") |
| unless length($config_long_name) <= 60; |
| |
| |
| #ErrorU("missing -b argument (buildroot source tree directory)") |
| # unless defined($buildroot_dir); |
| if (defined($buildroot_dir)) { |
| ErrorU("-b: not a directory: $buildroot_dir") |
| unless -d $buildroot_dir; |
| foreach my $p ("toolchain/gcc", "toolchain/binutils", "toolchain/gdb", "target/xtensa") { |
| ErrorU("-b: not a buildroot directory: missing $buildroot_dir/$p") |
| unless -d $buildroot_dir . "/" . $p; |
| } |
| } |
| |
| |
| #ErrorU("missing -k argument (Linux kernel source tree directory)") |
| # unless defined($kernel_dir); |
| if (defined($kernel_dir)) { |
| ErrorU("-k: not a directory: $kernel_dir") |
| unless -d $kernel_dir; |
| foreach my $p ("kernel", "arch/xtensa/kernel", "include/asm-xtensa") { |
| ErrorU("-k: not a Linux kernel directory: missing $kernel_dir/$p") |
| unless -d $kernel_dir . "/" . $p; |
| } |
| } |
| |
| |
| if (!defined($buildroot_dir) and !defined($kernel_dir)) { |
| print STDERR "$progname: WARNING:\n"; |
| print STDERR "$progname: WARNING: Test run only, NOTHING WILL BE INSTALLED\n"; |
| print STDERR "$progname: WARNING: (use -b and -k to specify install destination)\n"; |
| print STDERR "$progname: WARNING:\n"; |
| } |
| |
| |
| my @ovpaths = ( "/src/xtensa-config-overlay.tar.gz", |
| "/xtensa-elf/src/linux/misc/linux-overlay.tar.gz" ); |
| if (!defined($overlay_tarball)) { |
| # Try to locate the overlay tarball based on XTENSA_SYSTEM and XTENSA_CORE |
| # settings: |
| my $xtensa_root = `xt-xcc --show-config=config 2>/dev/null`; |
| $xtensa_root = "" unless defined($xtensa_root); |
| chomp($xtensa_root); |
| if ($xtensa_root ne "") { |
| ($overlay_tarball) = grep(-f $xtensa_root.$_, @ovpaths); |
| if (!defined($overlay_tarball)) { |
| ErrorU("Xtensa configuration overlay tarball not found: ".$xtensa_root.$ovpaths[0]) |
| } |
| } else { |
| ErrorU("missing -t argument (Xtensa configuration overlay tarball filename)\n" |
| ."and no default Xtensa Core Package defined in the environment"); |
| } |
| } else { |
| foreach my $p ("", @ovpaths) { |
| if (-f $overlay_tarball.$p) { |
| $overlay_tarball .= $p; |
| last; |
| } |
| } |
| ErrorU("-t: file not found: $overlay_tarball") unless -f $overlay_tarball; |
| } |
| |
| |
| ###################################################################### |
| # |
| # Misc |
| # |
| |
| my $overlay_unpacked = 0; |
| my $ovdir; |
| |
| sub cleanup { |
| if ($overlay_unpacked) { |
| system("rm -rf '$ovdir' 2>/dev/null"); |
| } |
| } |
| |
| sub ErrorEmit { |
| my ($msg,$usage) = @_; |
| $msg =~ s|\n|"\n${progname}: ERROR: "|ge; |
| print STDERR "$progname: ERROR: $msg\n"; |
| if ($usage) { |
| print "\n"; |
| usage(); |
| } |
| cleanup(); |
| exit 1; |
| } |
| sub ErrorU { ErrorEmit(shift,1); } |
| sub Error { ErrorEmit(shift); } |
| |
| |
| # Read specified file (as binary), returning contents. |
| # |
| sub readfile { |
| my ($filename) = @_; |
| # Read the file: |
| open(INFILE,"<$filename") or Error("error reading from '$filename': $!"); |
| my $savesep = $/; |
| undef $/; |
| my $file = <INFILE>; |
| $/ = $savesep; |
| close(INFILE); |
| $file; |
| } |
| |
| # Write specified file (as binary) with first argument (string). |
| # |
| sub writefile { |
| my ($filename, $file) = @_; |
| # Read the file: |
| open(INFILE,">$filename") or Error("error writing to '$filename': $!"); |
| print INFILE $file; |
| close(INFILE) or Error("error closing file '$filename': $!"); |
| } |
| |
| |
| ###################################################################### |
| # |
| # Determine a temporary directory. |
| # |
| |
| my $tmpdir = "/tmp"; |
| if (defined($ENV{"TMP"}) and -d $ENV{"TMP"}) { |
| $tmpdir = $ENV{"TMP"}; |
| } elsif (defined($ENV{"TEMP"}) and -d $ENV{"TEMP"}) { |
| $tmpdir = $ENV{"TEMP"}; |
| } |
| |
| |
| ###################################################################### |
| # |
| # Unpack the general overlay tarball |
| # |
| |
| my $user = defined($ENV{"USER"}) ? $ENV{"USER"} : "xtensa"; |
| $ovdir = $tmpdir."/tmp-overlay-${user}-$$"; |
| mkdir $ovdir or Error("cannot create directory $ovdir"); |
| $overlay_unpacked = 1; |
| system("tar xfz '$overlay_tarball' -C '$ovdir'") |
| and Error("tar failed..."); |
| |
| |
| ###################################################################### |
| # |
| # Define and sanity check contents of overlay |
| # |
| |
| my $oldpack = -f $ovdir."/xtensa-elf/src/linux/misc/core.h"; |
| my $pf1 = ($oldpack ? "src/" : ""); |
| my $pf2 = ($oldpack ? "xtensa-elf/src/linux/misc/" : "config/"); |
| |
| my @packages = ( |
| ["binutils", "toolchain/binutils", |
| ["${pf1}/binutils/xtensa-modules.c", "bfd/"], |
| ["${pf1}/binutils/xtensa-config.h", "include/"], |
| #["${pf1}/binutils/xtensa-config.sh", "ld/emulparams/"], |
| ], |
| ["gcc", "toolchain/gcc", |
| ["${pf1}/gcc/xtensa-config.h", "include/"], |
| ], |
| ["gdb", "toolchain/gdb", |
| ["${pf1}/gdb/xtensa-modules.c", "bfd/"], |
| ["${pf1}/gdb/xtensa-config.h", "include/"], |
| ["${pf1}/gdb/xtensa-config.c", "gdb/"], |
| ["${pf1}/gdb/xtensa-regmap.c", "gdb/gdbserver/"], |
| ["${pf1}/gdb/xtensa-regmap.c", "gdb/gdbserver/xtensa-xtregs.c"], # for GDB 6.8 |
| ["${pf1}/gdb/xtensa-regmap.c", "gdb/xtensa-xtregs.c"], # for GDB 6.8 |
| ["${pf1}/gdb/reg-xtensa.dat", "gdb/regformats/"], |
| ], |
| ["kernel", "target/xtensa", # ??? |
| ["${pf2}core.h", "include/asm-xtensa/variant-${config_name}/"], |
| ["${pf2}tie.h", "include/asm-xtensa/variant-${config_name}/"], |
| ["${pf2}tie-asm.h", "include/asm-xtensa/variant-${config_name}/"], |
| ], |
| ); |
| |
| # Check that all files are present ... |
| foreach my $pack (@packages) { |
| my ($pname, $buildroot_subdir, @files) = @$pack; |
| print "Checking files for $pname ...\n"; |
| foreach my $f (@files) { |
| my ($src, $dst) = @$f; |
| -f $ovdir."/".$src or Error("missing '$src' in overlay tarball"); |
| } |
| } |
| |
| |
| ###################################################################### |
| # |
| # Extract some useful information |
| # |
| |
| # Extract core name as specified in the build. |
| my $coreh = readfile($ovdir."/".$pf2."core.h"); |
| |
| $coreh =~ /^\s*\#\s*define\s+XCHAL_SW_VERSION\s+(\w+)/m; |
| my $swversion = $1; |
| defined($swversion) or Error("missing XCHAL_SW_VERSION in overlay core.h file;\n" |
| ."overlay is too old, need RB-2008.3 (SW version 7.1.1) or later"); |
| |
| $coreh =~ /^\s*\#\s*define\s+XCHAL_CORE_ID\s+"([^"]+)"/m; |
| my $coreid = $1; |
| defined($coreid) or Error("missing XCHAL_CORE_ID in overlay core.h file"); |
| |
| $coreh =~ /^\s*\#\s*define\s+XCHAL_HW_VERSION_NAME\s+"([^"]+)"/m; |
| my $hwversion = $1; |
| defined($hwversion) or Error("missing XCHAL_HW_VERSION_NAME in overlay core.h file"); |
| |
| |
| $swvers_human = sprintf("%u.%u.%u", |
| $swversion/100000, (($swversion/1000) % 100), ($swversion % 1000)); |
| my $release = "software version $swvers_human"; |
| if (-f $ovdir."/release") { |
| $release = readfile($ovdir."/release"); |
| chomp($release); |
| } |
| |
| |
| ###################################################################### |
| # |
| # Prompt user to be sure this is what he wants to do |
| # |
| |
| # Catch Ctrl-C so we can do a proper cleanup: |
| sub catch_term { |
| my $signame = shift; |
| #print STDERR "whoa!\n"; |
| cleanup(); |
| print STDERR "\n$progname: Cleaned up.\n"; |
| exit 3; |
| } |
| $SIG{TERM} = \&catch_term; |
| $SIG{HUP} = \&catch_term; |
| $SIG{INT} = \&catch_term; |
| |
| $| = 1; |
| print "\n", |
| "About to generate package-specific overlay tarballs for the following:\n", |
| "\n", |
| " Xtensa processor short name: $config_name\n"; |
| print " This short name overrides the name specified in the XPG: $coreid\n" if $coreid ne $config_name; |
| #print " Please ensure that's the name you want. If submitted to the open source\n", |
| # " community, it can be a hassle to change later on.\n"; |
| print " Xtensa processor description: $config_long_name\n", |
| " Targeting Xtensa HW version: $hwversion\n", |
| " Xtensa configuration overlay: $overlay_tarball\n", |
| " (release of overlay): $release\n", |
| " Destination buildroot dir: ".(defined($buildroot_dir)?$buildroot_dir:"(none, not installed)")."\n", |
| " Destination Linux kernel dir: ".(defined($kernel_dir)?$kernel_dir:"(none, not installed)")."\n", |
| "\n", |
| "Are you sure? (y/n) "; |
| if ($prompt) { |
| my $line = <STDIN>; |
| chomp($line); |
| if ($line !~ /^y(es)?$/i) { |
| print "\nInstallation aborted.\n"; |
| cleanup(); |
| exit 2; |
| } |
| } else { |
| print "YES [no prompt]\n"; |
| } |
| print "\n"; |
| |
| |
| ###################################################################### |
| # |
| # Now generate the tarballs |
| # |
| |
| # Now generate each tarball ... |
| foreach my $pack (@packages) { |
| my ($pname, $buildroot_subdir, @files) = @$pack; |
| my $tarname = "${pname}-xtensa_${config_name}.tgz"; |
| my $fulltarname; |
| if (defined($buildroot_dir)) { |
| my $tarsubname = $buildroot_subdir . "/" . $tarname; |
| print "Generating and installing $tarsubname ...\n"; |
| $fulltarname = $buildroot_dir . "/" . $tarsubname; |
| } else { |
| print "Generating $tarname ...\n"; |
| $fulltarname = $ovdir . "/" . $tarname; |
| } |
| if (-e $fulltarname) { |
| if ($force_clobber or !defined($buildroot_dir)) { |
| unlink($fulltarname) or Error("could not delete '$fulltarname': $!"); |
| } else { |
| Error("destination tarball already exists: '$fulltarname'"); |
| } |
| } |
| my $pdir = $ovdir."/tmp-".$pname; |
| system("rm -fr '${pdir}' 2>/dev/null"); |
| mkdir $pdir or Error("cannot create directory $pdir"); |
| foreach my $f (@files) { |
| my ($src, $dst) = @$f; |
| # If $dst ends in / , take filename from $src : |
| if ($dst =~ m|/$|) { |
| my $fname = $src; |
| $fname =~ s|^.*/||; |
| $dst .= $fname; |
| } |
| # Ensure destination directory exists: |
| my $dstdir = $pdir; |
| while ($dst =~ s|^([^/]+)/+||) { |
| $dstdir .= "/" . $1; |
| mkdir($dstdir); |
| } |
| # Read file: |
| my $content = readfile($ovdir."/".$src); |
| |
| # Adjust contents of file. |
| # Fix-up typo: |
| $content =~ s/XCHAL_SA_(NCP|CP\d+)_/XCHAL_$1_SA_/g; |
| # Update core name info: |
| my $iscore = ($content =~ s/^(\s*\#\s*define\s+XCHAL_CORE_ID\s+)"[^"]+"/$1"$config_name"/mg); |
| $iscore or $content =~ s{^(\s*\#\s*define\s+XCHAL_INST_FETCH_WIDTH\s+\S+\s*(/\*[^\*]*\*/)?\s*$)} |
| {$1\n\#undef XCHAL_CORE_ID\n\#define XCHAL_CORE_ID\t\t\t"$config_name"\n}smg; |
| # Update core description info: |
| $content =~ s/^(\s*\#\s*define\s+XCHAL_CORE_DESCRIPTION\s+)"[^"]+"/$1"$config_long_name"/mg |
| or $content =~ s{^(\s*\#\s*define\s+XCHAL_CORE_ID\s+\S+\s*(/\*[^\*]*\*/)?\s*$)} |
| {"$1\n" . ($iscore ? "" : "\n\#undef XCHAL_CORE_DESCRIPTION\n") |
| . "\#define XCHAL_CORE_DESCRIPTION\t\t\"${config_long_name}\""}smge; |
| |
| # Write (possibly modified) file: |
| writefile($dstdir."/".$dst, $content); |
| } |
| my $tarcmd = "tar cfz '${fulltarname}' -C '${pdir}' ."; |
| system($tarcmd) and Error("failed executing: $tarcmd"); |
| |
| # Install Linux kernel overlay: |
| if ($pname eq "kernel" and defined($kernel_dir)) { |
| print "Installing Linux kernel overlay from $tarname ...\n"; |
| my $untarcmd = "tar xfz '${fulltarname}' -C '${kernel_dir}' ."; |
| system($untarcmd) and Error("failed executing: $tarcmd"); |
| } |
| # Possible TODO: update arch/xtensa/{Kconfig,Makefile} to add this config? |
| } |
| |
| |
| ###################################################################### |
| # |
| # The End |
| # |
| |
| cleanup(); |
| print "Done.\n"; |
| exit 0; |
| |