armsr: armv8: enable serial console for Renesas platforms
[openwrt/staging/stintel.git] / scripts / package-metadata.pl
index b69ceb216a11e32f7bd8b26fba0b94c5a0cabd4c..a46f819ab50f0fc8ce3b133ddff93ee6295b221f 100755 (executable)
@@ -4,6 +4,8 @@ use lib "$FindBin::Bin";
 use strict;
 use metadata;
 use Getopt::Long;
+use Time::Piece;
+use JSON::PP;
 
 my %board;
 
@@ -160,6 +162,8 @@ sub mconf_depends {
                $depend =~ s/^([@\+]+)// and $flags = $1;
                my $condition = $parent_condition;
 
+               $depend = $2 if $depend =~ /^(.+):(.+)$/ and $dep->{$1} eq 'select';
+
                next if $condition eq $depend;
                next if $seen->{"$parent_condition:$depend"};
                next if $seen->{":$depend"};
@@ -191,9 +195,9 @@ sub mconf_depends {
                                $depend = shift @vdeps;
 
                                if (@vdeps > 1) {
-                                       $condition = ($condition ? "$condition && " : '') . '!('.join("||", map { "PACKAGE_".$_ } @vdeps).')';
+                                       $condition = ($condition ? "$condition && " : '') . join("&&", map { "PACKAGE_$_<PACKAGE_$pkgname" } @vdeps);
                                } elsif (@vdeps > 0) {
-                                       $condition = ($condition ? "$condition && " : '') . '!PACKAGE_'.$vdeps[0];
+                                       $condition = ($condition ? "$condition && " : '') . "PACKAGE_${vdeps[0]}<PACKAGE_$pkgname";
                                }
                        }
 
@@ -232,7 +236,7 @@ sub mconf_depends {
                mconf_depends($pkgname, $tdep->[0], 1, $dep, $seen, $tdep->[1]);
        }
 
-       foreach my $depend (keys %$dep) {
+       foreach my $depend (sort keys %$dep) {
                my $m = $dep->{$depend};
                $res .= "\t\t$m $depend\n";
        }
@@ -358,14 +362,30 @@ sub gen_package_config() {
        print_package_overrides();
 }
 
+sub and_condition($) {
+       my $condition = shift;
+       my @spl_and = split('\&\&', $condition);
+       if (@spl_and == 1) {
+               return "\$(CONFIG_$spl_and[0])";
+       }
+       return "\$(and " . join (',', map("\$(CONFIG_$_)", @spl_and)) . ")";
+}
+
+sub gen_condition ($) {
+       my $condition = shift;
+       # remove '!()', just as include/package-ipkg.mk does
+       $condition =~ s/[()!]//g;
+       return join("", map(and_condition($_), split('\|\|', $condition)));
+}
+
 sub get_conditional_dep($$) {
        my $condition = shift;
        my $depstr = shift;
        if ($condition) {
                if ($condition =~ /^!(.+)/) {
-                       return "\$(if \$(CONFIG_$1),,$depstr)";
+                       return "\$(if " . gen_condition($1) . ",,$depstr)";
                } else {
-                       return "\$(if \$(CONFIG_$condition),$depstr)";
+                       return "\$(if " . gen_condition($condition) . ",$depstr)";
                }
        } else {
                return $depstr;
@@ -516,13 +536,16 @@ sub gen_package_auxiliary() {
                if ($pkg->{name} && $pkg->{repository}) {
                        print "Package/$name/subdir = $pkg->{repository}\n";
                }
-               if ($pkg->{name} && defined($pkg->{abiversion})) {
-                       if ($pkg->{abiversion} =~ m!^(\d{4})-(\d{2})-(\d{2})-[0-9a-f]{7,40}$!) {
-                               print STDERR "WARNING: Reducing ABI version '$pkg->{abiversion}' of package '$name' to '$1$2$3'\n";
-                               print "Package/$name/abiversion = $1$2$3\n";
+               my %depends;
+               foreach my $dep (@{$pkg->{depends} || []}) {
+                       if ($dep =~ m!^\+?(?:[^:]+:)?([^@]+)$!) {
+                               $depends{$1}++;
                        }
-                       elsif (length $pkg->{abiversion}) {
-                               print "Package/$name/abiversion = $pkg->{abiversion}\n";
+               }
+               my @depends = sort keys %depends;
+               if (@depends > 0) {
+                       foreach my $n (@{$pkg->{provides}}) {
+                               print "Package/$n/depends = @depends\n";
                        }
                }
        }
@@ -566,6 +589,210 @@ sub gen_usergroup_list() {
        }
 }
 
+sub gen_package_manifest_json() {
+       my $json;
+       parse_package_metadata($ARGV[0]) or exit 1;
+       foreach my $name (sort {uc($a) cmp uc($b)} keys %package) {
+               my %depends;
+               my $pkg = $package{$name};
+               foreach my $dep (@{$pkg->{depends} || []}) {
+                       if ($dep =~ m!^\+?(?:[^:]+:)?([^@]+)$!) {
+                               $depends{$1}++;
+                       }
+               }
+               my @depends = sort keys %depends;
+               my $pkg_deps = join ' ', map { qq/"$_",/ } @depends;
+               $pkg_deps =~ s/\,$//;
+
+               my $pkg_maintainer = join ' ', map { qq/"$_",/ } @{$pkg->{maintainer} || []};
+               $pkg_maintainer =~ s/\,$//;
+
+               $json = <<"END_JSON";
+${json}{
+"name":"$name",
+"version":"$pkg->{version}",
+"category":"$pkg->{category}",
+"license":"$pkg->{license}",
+"cpe_id":"$pkg->{cpe_id}",
+"maintainer": [$pkg_maintainer],
+"depends":[$pkg_deps]},
+END_JSON
+       }
+
+       $json =~ s/[\n\r]//g;
+       $json =~ s/\,$//;
+       print "[$json]";
+}
+
+sub image_manifest_packages($)
+{
+       my %packages;
+       my $imgmanifest = shift;
+
+       open FILE, "<$imgmanifest" or return;
+       while (<FILE>) {
+               /^(.+?) - (.+)$/ and $packages{$1} = $2;
+       }
+       close FILE;
+
+       return %packages;
+}
+
+sub dump_cyclonedxsbom_json {
+       my (@components) = @_;
+
+       my $uuid = sprintf(
+           "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
+           rand(0xffff), rand(0xffff), rand(0xffff),
+           rand(0x0fff) | 0x4000,
+           rand(0x3fff) | 0x8000,
+           rand(0xffff), rand(0xffff), rand(0xffff)
+       );
+
+       my $cyclonedx = {
+               bomFormat => "CycloneDX",
+               specVersion => "1.4",
+               serialNumber => "urn:uuid:$uuid",
+               version => 1,
+               metadata => {
+                       timestamp => gmtime->datetime,
+               },
+               "components" => [@components],
+       };
+
+       return encode_json($cyclonedx);
+}
+
+sub gen_image_cyclonedxsbom() {
+       my $pkginfo = shift @ARGV;
+       my $imgmanifest = shift @ARGV;
+       my @components;
+       my %image_packages;
+
+       %image_packages = image_manifest_packages($imgmanifest);
+       %image_packages or exit 1;
+       parse_package_metadata($pkginfo) or exit 1;
+
+       $package{"kernel"} = {
+               license => "GPL-2.0",
+               cpe_id  => "cpe:/o:linux:linux_kernel",
+               name    => "kernel",
+               category  => "operating-system",
+       };
+
+       my %abimap;
+       my @abipkgs = grep { defined $package{$_}->{abi_version} } keys %package;
+       foreach my $name (@abipkgs) {
+               my $pkg = $package{$name};
+               my $abipkg = $name . $pkg->{abi_version};
+               $abimap{$abipkg} = $name;
+       }
+
+       foreach my $name (sort {uc($a) cmp uc($b)} keys %image_packages) {
+               my $pkg = $package{$name};
+               if (!$pkg) {
+                       $pkg = $package{$abimap{$name}};
+                       next if !$pkg;
+               }
+
+               my @licenses;
+               my @license = split(/\s+/, $pkg->{license});
+               foreach my $lic (@license) {
+                       push @licenses, (
+                               { "license" => { "name" => $lic } }
+                       );
+               }
+               my $type;
+               if ($pkg->{category}) {
+                       my $category = $pkg->{category};
+                       my %cat_type = (
+                               "operating-system"        => "operating-system",
+                               "Firmware"        => "firmware",
+                               "Libraries"       => "library"
+                       );
+
+                       if ($cat_type{$category}) {
+                               $type = $cat_type{$category};
+                       } else {
+                               $type = "application";
+                       }
+               }
+
+               my $version = $pkg->{version};
+               if ($image_packages{$name}) {
+                       $version = $image_packages{$name};
+               }
+               $version =~ s/-\d+$// if $version;
+               if ($name =~ /^(kernel|kmod-)/ and $version =~ /^(\d+\.\d+\.\d+)/) {
+                       $version = $1;
+               }
+
+               push @components, {
+                       name => $pkg->{name},
+                       version => $version,
+                       @licenses > 0 ? (licenses => [ @licenses ]) : (),
+                       $pkg->{cpe_id} ? (cpe => $pkg->{cpe_id}.":".$version) : (),
+                       $type ? (type => $type) : (),
+                       $version ? (version => $version) : (),
+               };
+       }
+
+       print dump_cyclonedxsbom_json(@components);
+}
+
+sub gen_package_cyclonedxsbom() {
+       my $pkgmanifest = shift @ARGV;
+       my @components;
+       my %mpkgs;
+
+       %mpkgs = parse_package_manifest_metadata($pkgmanifest);
+       %mpkgs or exit 1;
+
+       foreach my $name (sort {uc($a) cmp uc($b)} keys %mpkgs) {
+               my $pkg = $mpkgs{$name};
+
+               my @licenses;
+               my @license = split(/\s+/, $pkg->{license});
+               foreach my $lic (@license) {
+                       push @licenses, (
+                               { "license" => { "name" => $lic } }
+                       );
+               }
+
+               my $type;
+               if ($pkg->{section}) {
+                       my $section = $pkg->{section};
+                       my %section_type = (
+                               "firmware" => "firmware",
+                               "libs" => "library"
+                       );
+
+                       if ($section_type{$section}) {
+                               $type = $section_type{$section};
+                       } else {
+                               $type = "application";
+                       }
+               }
+
+               my $version = $pkg->{version};
+               $version =~ s/-\d+$// if $version;
+               if ($name =~ /^(kernel|kmod-)/ and $version =~ /^(\d+\.\d+\.\d+)/) {
+                       $version = $1;
+               }
+
+               push @components, {
+                       name => $name,
+                       version => $version,
+                       @licenses > 0 ? (licenses => [ @licenses ]) : (),
+                       $pkg->{cpe_id} ? (cpe => $pkg->{cpe_id}.":".$version) : (),
+                       $type ? (type => $type) : (),
+                       $version ? (version => $version) : (),
+               };
+       }
+
+       print dump_cyclonedxsbom_json(@components);
+}
+
 sub parse_command() {
        GetOptions("ignore=s", \@ignore);
        my $cmd = shift @ARGV;
@@ -575,6 +802,9 @@ sub parse_command() {
                /^kconfig/ and return gen_kconfig_overrides();
                /^source$/ and return gen_package_source();
                /^pkgaux$/ and return gen_package_auxiliary();
+               /^pkgmanifestjson$/ and return gen_package_manifest_json();
+               /^imgcyclonedxsbom$/ and return gen_image_cyclonedxsbom();
+               /^pkgcyclonedxsbom$/ and return gen_package_cyclonedxsbom();
                /^license$/ and return gen_package_license(0);
                /^licensefull$/ and return gen_package_license(1);
                /^usergroup$/ and return gen_usergroup_list();
@@ -582,14 +812,17 @@ sub parse_command() {
        }
        die <<EOF
 Available Commands:
-       $0 mk [file]                            Package metadata in makefile format
-       $0 config [file]                        Package metadata in Kconfig format
+       $0 mk [file]                                    Package metadata in makefile format
+       $0 config [file]                                Package metadata in Kconfig format
        $0 kconfig [file] [config] [patchver]   Kernel config overrides
-       $0 source [file]                        Package source file information
-       $0 pkgaux [file]                        Package auxiliary variables in makefile format
-       $0 license [file]                       Package license information
+       $0 source [file]                                Package source file information
+       $0 pkgaux [file]                                Package auxiliary variables in makefile format
+       $0 pkgmanifestjson [file]                       Package manifests in JSON format
+       $0 imgcyclonedxsbom <file> [manifest]   Image package manifest in CycloneDX SBOM JSON format
+       $0 pkgcyclonedxsbom <file>                      Package manifest in CycloneDX SBOM JSON format
+       $0 license [file]                               Package license information
        $0 licensefull [file]                   Package license information (full list)
-       $0 usergroup [file]                     Package usergroup allocation list
+       $0 usergroup [file]                             Package usergroup allocation list
        $0 version_filter [patchver] [list...]  Filter list of version tagged strings
 
 Options: