Skip to content

Instantly share code, notes, and snippets.

@telent
Last active June 27, 2021 23:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save telent/dcbcccf06d0b044823a214b1be43ee48 to your computer and use it in GitHub Desktop.
Save telent/dcbcccf06d0b044823a214b1be43ee48 to your computer and use it in GitHub Desktop.

Out of date

Checkout https://github.com/telent/nixelec instead of this


Given a configuration.nix for an aarch64 machine here called odroid.lan, and an x86-64 machine to build on, you can cross-compile and update it by running something like this on the build machine:

    NIXOS_CONFIG=/home/dan/src/odroid/cross/configuration.nix NIXPKGS_ALLOW_UNFREE=1  \
     nix-build -E 'let pkgs = (import /home/dan/src/nixpkgs) {}; in (pkgs.pkgsCross.aarch64-multiplatform.nixos /home/dan/src/odroid/cros/configuration.nix)'.config.system.build.toplevel    -o k2  
    nix-copy-closure --to root@odroid.lan -v --include-outputs ./k2
    ssh root@odroid.lan `readlink k2`/bin/switch-to-configuration switch

If you don't already have the host machine up and running Nix, given some additional entries in the configuration.nix (look for all the sdImage bits) you can use it to create an initial sdcard image by running the nix-build line as above, but substituting config.system.build.sdImage for config.system.build.sdImage.

# this is Work In Progress configuration.nix for cross-compiling
# a Kodi appliance based on the Odroid C2
{ config, lib, pkgs, ... }:
{
nixpkgs.overlays = [
(self: super: {
# make-tarball is hardcoded to use pixz, but waqnts a host
# version not a build version
pixz = super.buildPackages.pixz;
linuxPackages = super.linuxPackages_latest.extend (lpself: lpsuper: {
kernel = super.linuxPackages_latest.kernel.override {
extraConfig = ''
STAGING y
STAGING_MEDIA y
VIDEO_MESON_VDEC m
'';
};
});
tdb = super.tdb.overrideAttrs(o: {
nativeBuildInputs = o.nativeBuildInputs ++ [ self.python3 ];
});
atk = super.atk.overrideAttrs(o: {
nativeBuildInputs = o.nativeBuildInputs ++
[ self.pkg-config self.buildPackages.stdenv.cc ];
});
# gobject-introspection =
# let moreCross = builtins.toFile "cross-exe-wrapper.conf" ''
# [binaries]
# exe_wrapper = '/nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64'
# '';
# d = super.gobject-introspection.overrideAttrs(o: {
# mesonFlags = [ "-Dcairo=disabled"
# "-Ddoctool=disabled"
# "--cross-file=${moreCross}" ];
# nativeBuildInputs = o.nativeBuildInputs ++
# [ self.buildPackages.stdenv.cc ];
# });
# in d.override {
# x11Support = false;
# # python38 fails on aarch64, "No module named 'giscanner._giscanner'"
# python3 = self.python37;
# };
harfbuzz = (super.harfbuzz.overrideAttrs(o: {
doCheck = false;
mesonFlags = ["-Dgobject=disabled"
"-Dicu=disabled"
"-Dintrospection=disabled"
];
})).override({gobject-introspection = null;});
mesa =
(super.mesa.overrideAttrs (o:{
mesonFlags =
let moreCross = self.writeText "cross-exe-wrapper.conf" ''
[binaries]
llvm-config = '${self.llvmPackages_11.llvm.dev}/bin/llvm-config'
cmake = '${self.buildPackages.cmake}/bin/cmake'
exe_wrapper = '/nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64'
''; in
["-Dgallium-drivers=[lima,panfrost]"
"--cross-file=${moreCross}"
] ++ o.mesonFlags;
}));
gdk-pixbuf= (super.gdk-pixbuf.overrideAttrs(o:{
preInstall = "mkdir -p $out/share/doc $installedTests/foo";
mesonFlags = o.mesonFlags ++ [
"-Dgtk_doc=false"
];
})).override { doCheck = false; gobject-introspection = null;};
pango = null;
kodi = super.kodi.override {
x11Support = false;
dbusSupport = false;
joystickSupport = false;
nfsSupport = false;
pulseSupport = false;
sambaSupport = false;
udevSupport = false;
usbSupport = false;
vdpauSupport = false;
gbmSupport = true;
jre_headless = self.buildPackages.adoptopenjdk-openj9-bin-11 ;
lirc = null;
};
rtmpdump = super.rtmpdump.overrideAttrs(o:{
makeFlags = o.makeFlags ++ [
"CC=${self.stdenv.cc.targetPrefix}cc"
"AR=${self.stdenv.cc.targetPrefix}ar"
];
});
})
];
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
# need this for deploying to the odroid
<nixpkgs/nixos/modules/installer/sd-card/sd-image.nix>
];
# Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
boot.loader.grub.enable = false;
sdImage.populateRootCommands = ''
mkdir -p ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
# Odroid c2 doesn't seem to need a firmware partition (it's a RPi thing)
sdImage.populateFirmwareCommands = "";
# I have a slow cpu and a fast network, so I don't compress the image
sdImage.compressImage = false;
# The Odroid C2 requires some futzing around with the sd card image to
# install necessary firmware plus U-boot into specific places. See
# https://nixos.wiki/wiki/NixOS_on_ARM/ODROID-C2 for context and
# https://archlinuxarm.org/packages/aarch64/uboot-odroid-c2-mainline/files/sd_fusing.sh?raw
# for the script whence these magic offsets were taken
sdImage.postBuildCommands =
let u = pkgs.ubootOdroidC2;
bl1 = "${u}/bl1.bin.hardkernel";
uboot = "${u}/u-boot.gxbb"; in
#
''
dd if=${bl1} of=$img conv=fsync,notrunc bs=1 count=442
dd if=${bl1} of=$img conv=fsync,notrunc bs=512 skip=1 seek=1
dd if=${uboot} of=$img conv=fsync,notrunc bs=512 seek=97
'';
# Enables the generation of /boot/extlinux/extlinux.conf
boot.loader.generic-extlinux-compatible = {
enable = true;
configurationLimit = 0;
};
# unsure if needed
boot.blacklistedKernelModules = [ "meson_gxbb_wdt" ] ;
# override systemd core file processing, which grinds the box to a
# halt (load av > 11)
boot.kernel.sysctl."kernel.core_pattern" = "/dev/null";
networking.hostName = "odroid"; # Define your hostname.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
systemd.services.kodi = {
# enable = false;
wantedBy = [ "multi-user.target"];
serviceConfig = {
WorkingDirectory = "/home/kodi";
User = "kodi";
ExecStart = ''
${pkgs.kodi}/bin/kodi --windowing=gbm
'';
};
};
# Enable sound.
sound.enable = true;
# hardware.pulseaudio.enable = true;
# Define a user account. Don't forget to set a password with ‘passwd’.
users.users.dan = {
isNormalUser = true;
extraGroups = [ "weston-launch" "wheel" "video" "audio"]; # Enable ‘sudo’ for the user.
};
users.users.kodi = {
isNormalUser = true;
extraGroups = [ "input" "video" "audio"];
};
# for i in `find /run/current-system/kernel-modules/lib/modules/5.12.10/kernel/ -name video\* -type f ` ;do sudo modprobe `basename $i .ko.xz`;done
# Enable the OpenSSH daemon.
services.openssh.enable = true;
system.stateVersion = "21.05"; # Did you read the comment?
hardware.opengl = { enable = true; driSupport = true; };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment