{ pkgs, lib, config, modulesPath, ... }:
{
imports = [
  "${modulesPath}/installer/sd-card/sd-image.nix"
];

boot.supportedFilesystems = [
  #"btrfs"
  #"reiserfs"
  "vfat"
  #"f2fs"
  #"xfs"
  #"zfs"
  #"ntfs"
  #"cifs"
];

# The serial ports listed here are:
# - ttyS0: for Tegra (Jetson TK1)
# - ttymxc0: for i.MX6 (Wandboard)
# - ttyAMA0: for Allwinner (pcDuino3 Nano) and QEMU's -machine virt
# - ttyO0: for OMAP (BeagleBone Black)
# - ttySAC2: for Exynos (ODROID-XU3)
boot.consoleLogLevel = lib.mkDefault 7;
boot.kernelParams = [
  "console=ttyS0,115200n8"
  "console=ttymxc0,115200n8"
  "console=ttyAMA0,115200n8"
  "console=ttyO0,115200n8"
  "console=ttySAC2,115200n8"
  "console=tty0"
];

#nixpkgs.config.allowUnfree = true;
nixpkgs.crossSystem = lib.systems.examples.armv7l-hf-multiplatform;
nixpkgs.overlays = [
  (final: super: {
    # https://linux-sunxi.org/Mali_Open_Source_Driver#Configuration_and_Build
    mesa = super.mesa.override {
      driDrivers = [];
      eglPlatforms = ["x11"];
      enableGalliumNine = false;
      galliumDrivers = ["lima" "panfrost" "kmsro" "swrast"];
      vulkanDrivers = [];
    };
  })
  (final: super: {
    linuxPackages_latest_Cubieboard2 = super.linuxPackages_latest.extend (kself: ksuper: {
      kernel = ksuper.kernel.override {
        defconfig = "sunxi_defconfig";
        structuredExtraConfig = with lib.kernel; {
          #
          # File systems
          #
          PSTORE = yes;
          VFAT_FS = yes;
          EXT4_FS = yes;
          EXT4_USE_FOR_EXT2 = yes;

          #
          # Networking options
          #
          TCP_CONG_BBR = module;
          IPV6 = yes;
          IPV6_ROUTER_PREF = yes;
          IPV6_ROUTE_INFO = yes;
          IPV6_OPTIMISTIC_DAD = yes;
          INET6_AH = module;
          INET6_ESP = module;
          INET6_ESP_OFFLOAD = module;
          INET6_ESPINTCP = yes;
          INET6_IPCOMP = module;
          IPV6_MIP6 = module;
          IPV6_ILA = module;
          INET6_XFRM_TUNNEL = module;
          INET6_TUNNEL = module;
          IPV6_VTI = module;
          IPV6_SIT = module;
          IPV6_SIT_6RD = yes;
          IPV6_NDISC_NODETYPE = yes;
          IPV6_TUNNEL = module;
          IPV6_MULTIPLE_TABLES = yes;
          IPV6_SUBTREES = yes;
          IPV6_MROUTE = yes;
          IPV6_MROUTE_MULTIPLE_TABLES = yes;
          IPV6_PIMSM_V2 = yes;
          IPV6_SEG6_LWTUNNEL = yes;
          IPV6_SEG6_HMAC = yes;
          IPV6_RPL_LWTUNNEL = yes;
          # CONFIG_MPTCP is not set
          # CONFIG_NETWORK_SECMARK is not set
          NET_PTP_CLASSIFY = yes;
          # CONFIG_NETWORK_PHY_TIMESTAMPING is not set
          NETFILTER = yes;
          NETFILTER_ADVANCED = yes;

          #
          # Core Netfilter Configuration
          #
          NETFILTER_INGRESS = yes;
          NETFILTER_NETLINK = module;
          NETFILTER_FAMILY_ARP = yes;
          NETFILTER_NETLINK_HOOK = module;
          NETFILTER_NETLINK_ACCT = module;
          NETFILTER_NETLINK_QUEUE = module;
          NETFILTER_NETLINK_LOG = module;
          NETFILTER_NETLINK_OSF = module;
          NF_CONNTRACK = module;
          NF_LOG_SYSLOG = module;
          NETFILTER_CONNCOUNT = module;
          NF_CONNTRACK_MARK = yes;
          NF_CONNTRACK_ZONES = yes;
          NF_CONNTRACK_PROCFS = yes;
          NF_CONNTRACK_EVENTS = yes;
          NF_CONNTRACK_TIMEOUT = yes;
          NF_CONNTRACK_TIMESTAMP = yes;
          NF_CONNTRACK_LABELS = yes;
          NF_CT_PROTO_DCCP = yes;
          NF_CT_PROTO_SCTP = yes;
          NF_CT_PROTO_UDPLITE = yes;
          # CONFIG_NF_CONNTRACK_AMANDA is not set
          # CONFIG_NF_CONNTRACK_FTP is not set
          # CONFIG_NF_CONNTRACK_H323 is not set
          # CONFIG_NF_CONNTRACK_IRC is not set
          # CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
          # CONFIG_NF_CONNTRACK_SNMP is not set
          # CONFIG_NF_CONNTRACK_PPTP is not set
          # CONFIG_NF_CONNTRACK_SANE is not set
          # CONFIG_NF_CONNTRACK_SIP is not set
          # CONFIG_NF_CONNTRACK_TFTP is not set
          NF_CT_NETLINK = module;
          NF_CT_NETLINK_TIMEOUT = module;
          NF_CT_NETLINK_HELPER = module;
          NETFILTER_NETLINK_GLUE_CT = yes;
          NF_NAT = module;
          NF_NAT_REDIRECT = yes;
          NF_NAT_MASQUERADE = yes;
          NETFILTER_SYNPROXY = module;
          NF_TABLES = module;
          NF_TABLES_INET = yes;
          NF_TABLES_NETDEV = yes;
          NFT_NUMGEN = module;
          NFT_CT = module;
          NFT_COUNTER = module;
          NFT_CONNLIMIT = module;
          NFT_LOG = module;
          NFT_LIMIT = module;
          NFT_MASQ = module;
          NFT_REDIR = module;
          NFT_NAT = module;
          NFT_TUNNEL = module;
          NFT_OBJREF = module;
          NFT_QUEUE = module;
          NFT_QUOTA = module;
          NFT_REJECT = module;
          NFT_REJECT_INET = module;
          NFT_COMPAT = module;
          NFT_HASH = module;
          NFT_FIB = module;
          NFT_FIB_INET = module;
          NFT_XFRM = module;
          NFT_SOCKET = module;
          NFT_OSF = module;
          NFT_TPROXY = module;
          NFT_SYNPROXY = module;
          NF_DUP_NETDEV = module;
          NFT_DUP_NETDEV = module;
          NFT_FWD_NETDEV = module;
          NFT_FIB_NETDEV = module;
          NFT_REJECT_NETDEV = module;
          # CONFIG_NF_FLOW_TABLE is not set
          NETFILTER_XTABLES = module;

          #
          # Xtables combined modules
          #
          NETFILTER_XT_MARK = module;
          NETFILTER_XT_CONNMARK = module;
          NETFILTER_XT_SET = module;

          #
          # Xtables targets
          #
          NETFILTER_XT_TARGET_CHECKSUM = module;
          NETFILTER_XT_TARGET_CLASSIFY = module;
          NETFILTER_XT_TARGET_CONNMARK = module;
          NETFILTER_XT_TARGET_CT = module;
          NETFILTER_XT_TARGET_DSCP = module;
          NETFILTER_XT_TARGET_HL = module;
          NETFILTER_XT_TARGET_HMARK = module;
          NETFILTER_XT_TARGET_IDLETIMER = module;
          NETFILTER_XT_TARGET_LED = module;
          NETFILTER_XT_TARGET_LOG = module;
          NETFILTER_XT_TARGET_MARK = module;
          NETFILTER_XT_NAT = module;
          NETFILTER_XT_TARGET_NETMAP = module;
          NETFILTER_XT_TARGET_NFLOG = module;
          NETFILTER_XT_TARGET_NFQUEUE = module;
          NETFILTER_XT_TARGET_NOTRACK = module;
          NETFILTER_XT_TARGET_RATEEST = module;
          NETFILTER_XT_TARGET_REDIRECT = module;
          NETFILTER_XT_TARGET_MASQUERADE = module;
          NETFILTER_XT_TARGET_TEE = module;
          NETFILTER_XT_TARGET_TPROXY = module;
          NETFILTER_XT_TARGET_TRACE = module;
          NETFILTER_XT_TARGET_TCPMSS = module;
          NETFILTER_XT_TARGET_TCPOPTSTRIP = module;

          #
          # Xtables matches
          #
          NETFILTER_XT_MATCH_ADDRTYPE = module;
          NETFILTER_XT_MATCH_BPF = module;
          NETFILTER_XT_MATCH_CGROUP = module;
          NETFILTER_XT_MATCH_CLUSTER = module;
          NETFILTER_XT_MATCH_COMMENT = module;
          NETFILTER_XT_MATCH_CONNBYTES = module;
          NETFILTER_XT_MATCH_CONNLABEL = module;
          NETFILTER_XT_MATCH_CONNLIMIT = module;
          NETFILTER_XT_MATCH_CONNMARK = module;
          NETFILTER_XT_MATCH_CONNTRACK = module;
          NETFILTER_XT_MATCH_CPU = module;
          NETFILTER_XT_MATCH_DCCP = module;
          NETFILTER_XT_MATCH_DEVGROUP = module;
          NETFILTER_XT_MATCH_DSCP = module;
          NETFILTER_XT_MATCH_ECN = module;
          NETFILTER_XT_MATCH_ESP = module;
          NETFILTER_XT_MATCH_HASHLIMIT = module;
          NETFILTER_XT_MATCH_HELPER = module;
          NETFILTER_XT_MATCH_HL = module;
          NETFILTER_XT_MATCH_IPCOMP = module;
          NETFILTER_XT_MATCH_IPRANGE = module;
          NETFILTER_XT_MATCH_L2TP = module;
          NETFILTER_XT_MATCH_LENGTH = module;
          NETFILTER_XT_MATCH_LIMIT = module;
          NETFILTER_XT_MATCH_MAC = module;
          NETFILTER_XT_MATCH_MARK = module;
          NETFILTER_XT_MATCH_MULTIPORT = module;
          NETFILTER_XT_MATCH_NFACCT = module;
          NETFILTER_XT_MATCH_OSF = module;
          NETFILTER_XT_MATCH_OWNER = module;
          # CONFIG_NETFILTER_XT_MATCH_POLICY is not set
          NETFILTER_XT_MATCH_PKTTYPE = module;
          NETFILTER_XT_MATCH_QUOTA = module;
          NETFILTER_XT_MATCH_RATEEST = module;
          NETFILTER_XT_MATCH_REALM = module;
          NETFILTER_XT_MATCH_RECENT = module;
          NETFILTER_XT_MATCH_SCTP = module;
          NETFILTER_XT_MATCH_SOCKET = module;
          NETFILTER_XT_MATCH_STATE = module;
          NETFILTER_XT_MATCH_STATISTIC = module;
          NETFILTER_XT_MATCH_STRING = module;
          NETFILTER_XT_MATCH_TCPMSS = module;
          NETFILTER_XT_MATCH_TIME = module;
          NETFILTER_XT_MATCH_U32 = module;
          # end of Core Netfilter Configuration

          IP_SET = module;
          IP_SET_MAX.freeform = "256";
          IP_SET_BITMAP_IP = module;
          IP_SET_BITMAP_IPMAC = module;
          IP_SET_BITMAP_PORT = module;
          IP_SET_HASH_IP = module;
          IP_SET_HASH_IPMARK = module;
          IP_SET_HASH_IPPORT = module;
          IP_SET_HASH_IPPORTIP = module;
          IP_SET_HASH_IPPORTNET = module;
          IP_SET_HASH_IPMAC = module;
          IP_SET_HASH_MAC = module;
          IP_SET_HASH_NETPORTNET = module;
          IP_SET_HASH_NET = module;
          IP_SET_HASH_NETNET = module;
          IP_SET_HASH_NETPORT = module;
          IP_SET_HASH_NETIFACE = module;
          IP_SET_LIST_SET = module;
          # CONFIG_IP_VS is not set

          #
          # IP: Netfilter Configuration
          #
          NF_DEFRAG_IPV4 = module;
          NF_SOCKET_IPV4 = module;
          NF_TPROXY_IPV4 = module;
          NF_TABLES_IPV4 = yes;
          NFT_REJECT_IPV4 = module;
          NFT_DUP_IPV4 = module;
          NFT_FIB_IPV4 = module;
          # CONFIG_NF_TABLES_ARP is not set
          NF_DUP_IPV4 = module;
          # CONFIG_NF_LOG_ARP is not set
          # CONFIG_NF_LOG_IPV4 is not set
          NF_REJECT_IPV4 = module;
          IP_NF_IPTABLES = module;
          IP_NF_MATCH_AH = module;
          IP_NF_MATCH_ECN = module;
          IP_NF_MATCH_RPFILTER = module;
          IP_NF_MATCH_TTL = module;
          IP_NF_FILTER = module;
          IP_NF_TARGET_REJECT = module;
          IP_NF_TARGET_SYNPROXY = module;
          IP_NF_NAT = module;
          IP_NF_TARGET_MASQUERADE = module;
          IP_NF_TARGET_NETMAP = module;
          IP_NF_TARGET_REDIRECT = module;
          IP_NF_MANGLE = module;
          IP_NF_TARGET_CLUSTERIP = module;
          IP_NF_TARGET_ECN = module;
          IP_NF_TARGET_TTL = module;
          # CONFIG_IP_NF_RAW is not set
          # CONFIG_IP_NF_ARPTABLES is not set
          # end of IP: Netfilter Configuration

          #
          # IPv6: Netfilter Configuration
          #
          NF_SOCKET_IPV6 = module;
          NF_TPROXY_IPV6 = module;
          NF_TABLES_IPV6 = yes;
          NFT_REJECT_IPV6 = module;
          NFT_DUP_IPV6 = module;
          NFT_FIB_IPV6 = module;
          NF_DUP_IPV6 = module;
          NF_REJECT_IPV6 = module;
          NF_LOG_IPV6 = module;
          IP6_NF_IPTABLES = module;
          IP6_NF_MATCH_AH = module;
          IP6_NF_MATCH_EUI64 = module;
          IP6_NF_MATCH_FRAG = module;
          IP6_NF_MATCH_OPTS = module;
          IP6_NF_MATCH_HL = module;
          IP6_NF_MATCH_IPV6HEADER = module;
          IP6_NF_MATCH_MH = module;
          IP6_NF_MATCH_RPFILTER = module;
          IP6_NF_MATCH_RT = module;
          IP6_NF_MATCH_SRH = module;
          IP6_NF_TARGET_HL = module;
          IP6_NF_FILTER = module;
          IP6_NF_TARGET_REJECT = module;
          IP6_NF_TARGET_SYNPROXY = module;
          IP6_NF_MANGLE = module;
          IP6_NF_RAW = module;
          IP6_NF_NAT = module;
          IP6_NF_TARGET_MASQUERADE = module;
          IP6_NF_TARGET_NPT = module;
          # end of IPv6: Netfilter Configuration

          NF_DEFRAG_IPV6 = module;

          #
          # Disabling
          #
          ADFS_FS = no;
          AFFS_FS = no;
          BEFS_FS = no;
          BFS_FS = no;
          BTRFS = no;
          BTRFS_FS = no;
          CEPH_FS = no;
          CIFS = no;
          CRAMFS = no;
          ECRYPT_FS = no;
          EFS_FS = no;
          EROFS_FS = no;
          EXT2_FS = no;
          EXT3_FS = no;
          F2FS_FS = lib.mkForce no;
          GFS2_FS = no;
          HFSPLUS_FS = no;
          HFS_FS = no;
          HPFS_FS = no;
          JFS_FS = no;
          MINIX_FS = no;
          NET_9P = no;
          NFSD = no;
          NFS_FS = no;
          NILFS2_FS = no;
          OMFS_FS = no;
          ORANGEFS_FS = no;
          QNX4FS_FS = no;
          QNX6FS_FS = no;
          REISERFS_FS = no;
          ROMFS_FS = no;
          SQUASHFS = no;
          SYSV_FS = no;
          UFS_FS = no;
          VXFS_FS = no;
          XFS_FS = no;

          MISC_FILESYSTEMS = no;

          DECNET = no;
          SCTP = no;
          RDS = no;
          DCCP = no;
          TIPC = no;
          CAIF = no;
          CEPH = no;
          VMW_SOCK = no;
          HSR = no;
          QRTR = no;
          MPI = no;
          RAID6 = no;
          STAGING = lib.mkForce no;

          "6LOWPAN" = no;
          ARCNET = no;
          B53 = no;
          BATMAN_ADV = no;
          BT = no;
          CAN = no;
          COMEDI = no;
          DRM_STM = lib.mkForce no;
          INFINIBAND = no;
          INPUT_TOUCHSCREEN = no;
          MEDIA_ANALOG_TV_SUPPORT = lib.mkForce no;
          MEDIA_DIGITAL_TV_SUPPORT = lib.mkForce no;
          MEDIA_TUNER = no;
          MPLS = no;
          MPTCP = lib.mkForce no;
          NFC = no;
          NF_TABLES_BRIDGE = lib.mkForce no;
          NVME = no;
          OPENVSWITCH = no;
          PARAVIRT = lib.mkForce no;
          POWER_SUPPLY = no;
          USB_GSPCA = lib.mkForce no;
          VIDEO_STK1160_COMMON = lib.mkForce no;
          XEN = lib.mkForce no;
          #NVME_CORE = no;
        };
        #ignoreConfigErrors = true;
      };
    });
  })
];
boot.cleanTmpDir = true;
boot.tmpOnTmpfs = lib.mkForce false;
# TODO: is that needed?
hardware.enableRedistributableFirmware = true;
sdImage = {
  postBuildCommands = ''
    dd if=${pkgs.ubootCubieboard2}/u-boot-sunxi-with-spl.bin of=$img bs=1024 seek=8 conv=notrunc
  '';
  compressImage = true;
  expandOnBoot = true;
  firmwareSize = 1;
  populateFirmwareCommands = "";
  populateRootCommands = ''
    mkdir -p ./files/boot
    ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
  '';
};
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
# nix -L build .#nixosConfigurations.${hostName}.config.boot.kernelPackages.kernel.configfile
boot.kernelPackages = lib.mkForce pkgs.linuxPackages_latest_Cubieboard2;
boot.initrd.availableKernelModules = lib.mkForce [
  "mmc_block"
  "usbhid"
  "hid_generic"
  "hid_microsoft"
];
}