#!/usr/bin/perl -w

use strict;
use Data::Dumper;

my $spec_in = "dtb.spec.in";

# DTB packages names, ordered by file names
my @armv7l_package_list = (
    ['dtb-am335x',     'ti/omap/am335x-*.dts',     "TI AM335x based systems"],
    ['dtb-am3517',     'ti/omap/am3517*.dts',      "TI AM3517 based systems"], # exception: am3517_mt_ventoux.dts
    ['dtb-am57xx',     'ti/omap/am57xx-*.dts',     "TI AM57xx based systems"],
    ['dtb-armada-370', 'marvell/armada-370-*.dts', "Armada 370 based systems"],
    ['dtb-armada-375', 'marvell/armada-375-*.dts', "Armada 375 based systems"],
    ['dtb-armada-385', 'marvell/armada-385-*.dts', "Armada 385 based systems"],
    ['dtb-armada-388', 'marvell/armada-388-*.dts', "Armada 388 based systems"],
    ['dtb-armada-398', 'marvell/armada-398-*.dts', "Armada 398 based systems"],
    ['dtb-armada-xp',  'marvell/armada-xp-*.dts',  "Armada XP based systems"],
    ['dtb-bcm2836',    'broadcom/bcm2836*.dts',     "Raspberry Pi 2 Model B"],
    ['dtb-dove',       'marvell/dove-*.dts',       "Marvell dove based systems"],
    ['dtb-exynos4',    'samsung/exynos4*.dts',     "Samsung Exynos 4 based systems"],
    ['dtb-exynos5',    'samsung/exynos5*.dts',     "Samsung Exynos 5 based systems"],
    ['dtb-imx5',       'nxp/imx/imx5*.dts',        "Freescale i.MX51 and i.MX53 based systems"],
    ['dtb-imx6',       'nxp/imx/imx6*.dts',        "Freescale i.MX6 based systems"],
    ['dtb-imx7',       'nxp/imx/imx7*.dts',        "Freescale i.MX7 based systems"],
    ['dtb-keystone',   'ti/keystone/keystone-*.dts',   "TI Keystone 2 based systems"],
    ['dtb-meson6',     'amlogic/meson6-*.dts',     "Amlogic Meson 6 based systems"],
    ['dtb-meson8',     'amlogic/meson8-*.dts',     "Amlogic Meson 8 based systems"],
    ['dtb-meson8b',    'amlogic/meson8b-*.dts',    "Amlogic Meson 8b based systems"],
    ['dtb-mt76',       'mediatek/mt76*.dts',        "MediaTek mt76 based systems"],
    ['dtb-omap3',      'ti/omap/omap3*.dts',       "TI OMAP3 based systems"],
    ['dtb-omap4',      'ti/omap/omap4*.dts',       "TI OMAP4 based systems"],
    ['dtb-omap5',      'ti/omap/omap5*.dts',       "TI OMAP5 based systems"],
    ['dtb-qcom',       'qcom/qcom-*.dts',       "Qualcomm Snapdragon based systems"],
    ['dtb-rk3',        'rockchip/rk3*.dts',         "Rockchip RK3xxx based systems"],
    ['dtb-socfpga',    'intel/socfpga/socfpga_*.dts',    "Altera SoC FPGA based systems"],
    ['dtb-ste',        'st/ste-*.dts',        "ST Ericsson based systems"],
    ['dtb-sun4i',      'allwinner/sun4i-*.dts',      "Allwinner sun4i based systems"],
    ['dtb-sun5i',      'allwinner/sun5i-*.dts',      "Allwinner sun5i based systems"],
    ['dtb-sun6i',      'allwinner/sun6i-*.dts',      "Allwinner sun6i based systems"],
    ['dtb-sun7i',      'allwinner/sun7i-*.dts',      "Allwinner sun7i based systems"],
    ['dtb-sun8i',      'allwinner/sun8i-*.dts',      "Allwinner sun8i based systems"],
    ['dtb-sun9i',      'allwinner/sun9i-*.dts',      "Allwinner sun9i based systems"],
    ['dtb-tegra2',     'nvidia/tegra20-*.dts',    "NVidia Tegra2 based systems"],
    ['dtb-tegra3',     'nvidia/tegra30-*.dts',    "NVidia Tegra3 based systems"],
    ['dtb-tegra114',   'nvidia/tegra114-*.dts',   "NVidia Tegra4 based systems"],
    ['dtb-tegra124',   'nvidia/tegra124-*.dts',   "NVidia Tegra K1 based systems"],
    ['dtb-vexpress',   'arm/vexpress-*.dts',   "ARM Versatile Express machines"],
    ['dtb-vf500',      'nxp/vf/vf500-*.dts',      "Freescale Vybrid VF500 based systems"],
    ['dtb-vf6',        'nxp/vf/vf610-*.dts',      "Freescale Vybrid VF610 based systems"],
    ['dtb-xenvm',      'xen/xenvm-*.dts',      "Xen virtual machines"],
    ['dtb-zynq',       'xilinx/zynq-*.dts',       "Xilinx Zynq based systems"],
);

# DTB packages names
my @armv6l_package_list = (
     ['dtb-bcm2835',   'broadcom/bcm2835*.dts',   "Raspberry Pi 1 (A+, B, B+)"],
);

# DTB packages names
my @aarch64_package_list = (
     ['dtb-allwinner',       'allwinner/*.dts',        "Allwinner based arm64 systems"],
     ['dtb-altera',          'altera/*.dts',           "Altera based arm64 systems"],
     ['dtb-amazon',          'amazon/*.dts',           "Amazon based arm64 systems"],
     ['dtb-amd',             'amd/*.dts',              "AMD based arm64 systems"],
     ['dtb-amlogic',         'amlogic/*.dts',          "Amlogic based arm64 systems"],
     ['dtb-apm',             'apm/*.dts',              "AppliedMicro based arm64 systems"],
     ['dtb-apple',           'apple/*.dts',            "Apple SOC based arm64 systems"],
     ['dtb-arm',             'arm/*.dts',              "ARM Ltd. based arm64 systems"],
     ['dtb-broadcom',        'broadcom/*.dts',         "Broadcom based arm64 systems"],
     ['dtb-cavium',          'cavium/*.dts',           "Cavium based arm64 systems"],
     ['dtb-exynos',          'exynos/*.dts',           "Samsung Exynos based arm64 systems"],
     ['dtb-freescale',       'freescale/*.dts',        "NXP (Freescale) based arm64 systems"],
     ['dtb-hisilicon',       'hisilicon/*.dts',        "HiSilicon based arm64 systems"],
     ['dtb-lg',              'lg/*.dts',               "LG based arm64 systems"],
     ['dtb-marvell',         'marvell/*.dts',          "Marvell based arm64 systems"],
     ['dtb-mediatek',        'mediatek/*.dts',         "MediaTek based arm64 systems"],
     ['dtb-nvidia',          'nvidia/*.dts',           "Nvidia based arm64 systems"],
     ['dtb-qcom',            'qcom/*.dts',             "Qualcomm based arm64 systems"],
     ['dtb-renesas',         'renesas/*.dts',          "Renesas based arm64 systems"],
     ['dtb-rockchip',        'rockchip/*.dts',         "Rockchip based arm64 systems"],
     ['dtb-socionext',       'socionext/*.dts',        "Socionext based arm64 systems"],
     ['dtb-sprd',            'sprd/*.dts',             "Spreadtrum based arm64 systems"],
     ['dtb-xilinx',          'xilinx/*.dts',           "Xilinx based arm64 systems"],
);

# DTB packages names
my @riscv64_package_list = (
     ['dtb-allwinner', 'allwinner/*.dts',   "Allwinner based riscv64 systems"],
     ['dtb-microchip', 'microchip/*.dts',   "Microchip based riscv64 systems"],
     ['dtb-renesas',   'renesas/*.dts',     "Renesas based riscv64 systems"],
     ['dtb-sifive',    'sifive/*.dts',      "SiFive based riscv64 systems"],
     ['dtb-starfive',  'starfive/*.dts',    "StarFive based riscv64 systems"],
     ['dtb-thead',     'thead/*.dts',       "T-HEAD based riscv64 systems"],
);

sub generate_spec($$$)
{
    my ($main_package, $exclusive_arch, $package_list) = @_;

    print "$main_package.spec\n";
    # open .spec and .spec.in files
    open (SPEC, ">$main_package.spec") or die "Unable to open $main_package.spec.\n";
    open (TEMPLATE, "$spec_in") or die "Unable to open $spec_in.\n";

    my $ARCH_RESTRICTIONS = "";
    $ARCH_RESTRICTIONS = "ExclusiveArch:  $exclusive_arch"
        unless ($exclusive_arch eq 'none');

    my $subpkg_desc = "";
    my $subpkg_post = "";
    my $subpkg_files = "";
    my $subpkg_case = "";
    my $all_supported_dtb = "";
    my $DTS_folder = "arch/arm/boot/dts";
    if ($exclusive_arch =~ /aarch64/) {
	   $DTS_folder = "arch/arm64/boot/dts";
    } elsif ($exclusive_arch =~ /riscv64/) {
	   $DTS_folder = "arch/riscv/boot/dts";
    }

    foreach my $NAME (@$package_list) {
        my $PKG_NAME = @{$NAME}[0];
        my $SUPPORTED_DTB = @{$NAME}[1];
        my $MACHINES = @{$NAME}[2];

        $subpkg_desc .=
            "%package -n $PKG_NAME\n" .
            "Summary:        $MACHINES\n" .
            "Group:          System/Boot\n";
        if ($PKG_NAME eq 'dtb-keystone' and $main_package eq 'dtb-armv7l') {
            $subpkg_desc .= "Provides:       dtb-k2e = %version\n" .
                            "Provides:       dtb-k2l = %version\n";
        }
        if ($PKG_NAME eq 'dtb-amazon' and $main_package eq 'dtb-aarch64') {
            $subpkg_desc .= "Provides:       dtb-al = %version\n";
        }
        if ($PKG_NAME eq 'dtb-apm' and $main_package eq 'dtb-aarch64') {
            $subpkg_desc .= "Provides:       dtb-apm-mustang = %version\n";
        }
        if ($PKG_NAME eq 'dtb-arm' and $main_package eq 'dtb-aarch64') {
            $subpkg_desc .= "Provides:       dtb-foundation-v8 = %version\n" .
                            "Provides:       dtb-rtsm_ve-aemv8a = %version\n";
        }
        if ($PKG_NAME eq 'dtb-cavium' and $main_package eq 'dtb-aarch64') {
            $subpkg_desc .= "Provides:       dtb-thunder-88xx = %version\n";
        }
        if ($PKG_NAME eq 'dtb-hisilicon' and $main_package eq 'dtb-aarch64') {
            $subpkg_desc .= "Provides:       dtb-hisilicon64 = %version\n";
        }
        $subpkg_desc .=
            "Provides:       multiversion(dtb)\n" .
            "Requires(post): coreutils\n" .
            "\n" .
            "%description -n $PKG_NAME\n" .
            "Device Tree files for $MACHINES.\n\n";

        $subpkg_post .=
            "%post -n $PKG_NAME\n" .
            "cd /boot\n" .
            "# If /boot/dtb is a symlink, remove it, so that we can replace it.\n" .
            "[ -d dtb ] && [ -L dtb ] && rm -f dtb\n" .
            "# Unless /boot/dtb exists as real directory, create a symlink.\n" .
            "[ -d dtb ] || ln -sf dtb-%kernelrelease dtb\n\n";

        my $bin_supported_dtb = $SUPPORTED_DTB;
        $bin_supported_dtb =~ s/\.dts/\.dtb/g;

        my $dtb_subdir = "";
        my $path = "";
        my @components = split(/\//, $bin_supported_dtb);
        pop @components; # filename
        foreach my $subdir (@components) {
            $path .= "/$subdir";
            $dtb_subdir .= "%dir %{dtbdir}$path\n";
        }

        $subpkg_files .=
            "%ifarch %arm aarch64 riscv64\n" .
            "%files -n $PKG_NAME -f $PKG_NAME.list\n" .
            "%else\n" .
            "%files -n $PKG_NAME\n" .
            "%endif\n" .
            "%defattr(-,root,root)\n" .
            "%ghost /boot/dtb\n" .
            "%dir %{dtbdir}\n" .
            $dtb_subdir .
            "%{dtbdir}/$bin_supported_dtb\n" .
            "\n";

        if ($main_package eq 'dtb-armv6l' or $main_package eq 'dtb-armv7l') {
            # Map dts file name back to subpkg name
            $subpkg_case .= "      $SUPPORTED_DTB) pkgname=$PKG_NAME;;\n"
        }
        $all_supported_dtb .= "$SUPPORTED_DTB ";
    }
    chomp($all_supported_dtb);

    # spec file generation
    while(<TEMPLATE>){
        $_ =~ s/\$NAME/$main_package/g;
        $_ =~ s/\$ARCH_RESTRICTIONS/$ARCH_RESTRICTIONS/g;
        $_ =~ s/\$DTS_folder/$DTS_folder/g;
        $_ =~ s/\$SUBPKG_DESC/$subpkg_desc/g;
        $_ =~ s/\$ALL_SUPPORTED_DTB/$all_supported_dtb/g;
        $_ =~ s/\$SUBPKG_POST\n?/$subpkg_post/g;
        $_ =~ s/\$SUBPKG_FILES\n?/$subpkg_files/g;
        $_ =~ s/\$SUBPKG_CASE\n?/$subpkg_case/g;
        print SPEC $_;
    }

    close(TEMPLATE);
    close(SPEC);
}
if ( grep( /armv7/, @ARGV)) {
generate_spec('dtb-armv7l', "armv7l armv7hl", \@armv7l_package_list);
}
if ( grep( /armv6/, @ARGV)) {
generate_spec('dtb-armv6l', "armv6l armv6hl", \@armv6l_package_list);
}
if ( grep( /aarch64/, @ARGV)) {
generate_spec('dtb-aarch64', "aarch64", \@aarch64_package_list);
}
if ( grep( /riscv64/, @ARGV)) {
generate_spec('dtb-riscv64', "riscv64", \@riscv64_package_list);
}
