Skip to content

Instantly share code, notes, and snippets.

@angerman
Created May 28, 2020 13:53
Show Gist options
  • Select an option

  • Save angerman/70c69c71bd91de3b9ea1ac1f438a8c62 to your computer and use it in GitHub Desktop.

Select an option

Save angerman/70c69c71bd91de3b9ea1ac1f438a8c62 to your computer and use it in GitHub Desktop.
NixOS on RockPi4
* Installing NixOS on the RockPi4 (B)
The general plan is to build an sd-image-aarch64 from
nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
flash it to the eMMC and have the system come up, similar to how this
"just works" for raspberry-pis.
The RockPi 4 is a RockChip RK3399 based board, build by [[https://radxa.com][radxa]] with the
same formfactor as a rasperry Pi. One noticable difference is that
the Rock Pi's cpu is at the bottom to better allow for the
installation of a heatsink. The heatsink as such will prevent it from
fitting into raspberry pi enclosures, however together with the
heatsink it forms a relatively stable package.
** RockPi disk layout
From [[https://wiki.radxa.com/Rockpi4/partitions][Rock Pi 4 Partitions]] we can see that the official linux image
partitions are layed out like this:
| Part Number | Offset | Name | Description |
|-------------+--------+---------+--------------------|
| 1 | 32KB | loader1 | First stage loader |
| 2 | 8MB | loader2 | U-boot image |
| 3 | 12MB | trust | ATF |
| 4 | 16MB | boot | Kernel partition |
| 5 | 128MB | rootfs | Rootsfs |
Thus we should be able to just ~dd~ the files onto it if
we had the files prepared like so:
#+BEGIN_SRC
dd if=idbloader.img of=/dev/sdx seek=64
dd if=uboot.img of=/dev/sdx seek=16384
dd if=trust.img of=/dev/sdx seek=24576
dd if=boot.img of=/dev/sdx seek=32768
dd if=rootfs.img of=/dev/sdx seek=262144
#+END_SRC
Inspecting the exampe
[[https://dl.radxa.com/rockpi/images/ubuntu/rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img.gz][rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img]], we'll find
#+BEGIN_SRC
$ sfdisk -l rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img -d
label: gpt
label-id: 992DF2C2-0170-4F66-9492-FBF320673EEF
device: rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img
unit: sectors
first-lba: 34
last-lba: 4458462
rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img1 : start= 64, size= 8000, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=95D89D52-CA00-42D6-883F-50F5720EF37E, name="loader1"
rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img2 : start= 16384, size= 8192, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=78BE2786-ACB9-4885-BB6C-77DDDEF5AAC9, name="loader2"
rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img3 : start= 24576, size= 8192, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A36BC2FB-B345-417B-8AEF-B49EA06C1F7B, name="trust"
rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img4 : start= 32768, size= 229376, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=CEE6EBD4-DA8F-4378-A430-05693004C5DA, name="boot"
rockpi4b-ubuntu-bionic-minimal-20191127_1942-gpt.img5 : start= 262144, size= 4196319, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE, name="rootfs"
#+END_SRC
The [[https://dl.radxa.com/rockpi/images/debian/rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img.gz][debian-stretch-desktop]] image has almost the identical layout:
#+BEGIN_SRC
sfdisk -l rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img -d
label: gpt
label-id: 69E3E4E5-2BF4-4C94-8774-841F0A4EE8CB
device: rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img
unit: sectors
first-lba: 34
last-lba: 7331806
rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img1 : start= 64, size= 8000, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=4C98C92E-398A-4FB8-AFD1-1529095B79B8, name="loader1"
rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img2 : start= 16384, size= 8192, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=C8BDD4F5-12D8-42B8-8F69-147391C0438A, name="loader2"
rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img3 : start= 24576, size= 8192, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=8E58643E-760F-452C-94F9-8703182E8FB2, name="trust"
rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img4 : start= 32768, size= 1048576, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=BBF86B96-61B3-446D-A789-BED7E5B85490, name="boot"
rockpi4-debian-stretch-desktop-arm64-20190730_2022-gpt.img5 : start= 1081344, size= 6250463, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE, name="rootfs"
#+END_SRC
radxa provides their [[https://github.com/radxa/build][build repo]] on github, where we can find the
[[https://github.com/radxa/build/blob/debian/mk-image.sh][mk-image.sh]] for some additonal assistence.
** A gpt based image
As of this writing [[https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix][sd-image-aarch64.nix]] will use [[https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/cd-dvd/sd-image.nix][sd-image.nix]] to build
the disk. However sd-image will generate a MBR partitioned image.
With a Fat32 ~/boot/firmware~ partition, and an ext4 ~/~ nixos root
partition. Thus for the rockpi; this is not very useful.
For the [[https://github.com/thefloweringash/rock64-nix][rock64]], [[https://github.com/thefloweringash][thefloweringash]] already built a gpt based
[[https://github.com/thefloweringash/rock64-nix/blob/master/sd-image-rockchip.nix][sd-image-rockchip.nix]].
The [[http://opensource.rock-chips.com/wiki_Boot_option][Boot options]] as described in the Rockchip wiki make be believe we
can get away with three partition. The SPL (idbloader.img),
u-boot.itb, and the rootfs (containg the kernel) as boot partition.
{ config, lib, pkgs, ... }: {
imports = [
<nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix>
./configuration.nix
];
# bzip2 compression takes loads of time with emulation, skip it. Enable this if you're low
# on space.
sdImage.compressImage = false;
system.build.sdImage = with lib;
let
rootfsImage = pkgs.callPackage <nixpkgs/nixos/lib/make-ext4-fs.nix> ({
inherit (config.sdImage) storePaths;
compressImage = true;
populateImageCommands = config.sdImage.populateRootCommands;
volumeLabel = "NIXOS_SD";
} // optionalAttrs (config.sdImage.rootPartitionUUID != null) {
uuid = config.sdImage.rootPartitionUUID;
});
in pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs,
mtools, libfaketime, utillinux, bzip2, zstd }: stdenv.mkDerivation {
name = config.sdImage.imageName;
nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux bzip2 zstd ];
inherit (config.sdImage) compressImage;
diskUUID = "A8ABB0FA-2FD7-4FB8-ABB0-2EEB7CD66AFA";
loadUUID = "534078AF-3BB4-EC43-B6C7-828FB9A788C6";
bootUUID = "95D89D52-CA00-42D6-883F-50F5720EF37E";
rootUUID = "0340EA1D-C827-8048-B631-0C60D4478796";
buildCommand = ''
mkdir -p $out/nix-support $out/sd-image
export img=$out/sd-image/${config.sdImage.imageName}
echo "${pkgs.stdenv.buildPlatform.system}" > $out/nix-support/system
if test -n "$compressImage"; then
echo "file sd-image $img.bz2" >> $out/nix-support/hydra-build-products
else
echo "file sd-image $img" >> $out/nix-support/hydra-build-products
fi
echo "Decompressing rootfs image"
zstd -d --no-progress "${rootfsImage}" -o ./root-fs.img
# Create the image file sized to fit /boot/firmware and /, plus slack for the gap.
rootSizeBlocks=$(du -B 512 --apparent-size ./root-fs.img | awk '{ print $1 }')
# rootfs will be at offset 0x8000, so we'll need to account for that.
# And add an additional 20mb slack at the end.
imageSize=$((0x8000 + rootSizeBlocks * 512 + 20 * 1024 * 1024))
truncate -s $imageSize $img
sfdisk --no-reread --no-tell-kernel $img <<EOF
label: gpt
label-id: $diskUUID
first-lba: 64
start=64, size=8000, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=$loadUUID, name=loader1
start=16384, size=8192, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=$bootUUID, name=loader2
start=32768, type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE, uuid=$rootUUID, name=boot, attrs=LegacyBIOSBootable
EOF
# Copy the rootfs into the SD image
eval $(partx $img -o START,SECTORS --nr 3 --pairs)
dd conv=notrunc if=./root-fs.img of=$img seek=$START count=$SECTORS
# Copy u-boot into the SD image
eval $(partx $img -o START,SECTORS --nr 2 --pairs)
dd conv=notrunc if=${pkgs.ubootRockPi4}/u-boot.itb of=$img seek=$START count=$SECTORS
# Copy bootloader into the SD image
eval $(partx $img -o START,SECTORS --nr 1 --pairs)
dd conv=notrunc if=${pkgs.ubootRockPi4}/idbloader.img of=$img seek=$START count=$SECTORS
if test -n "$compressImage"; then
bzip2 $img
fi
'';
}) {};
}
final: prev: {
ubootRockPi4 =
let plat = if builtins.currentSystem == "aarch64-linux" then prev
else prev.pkgsCross.aarch64-multiplatform;
in plat.buildUBoot {
defconfig = "rock-pi-4-rk3399_defconfig";
extraMeta.platforms = ["aarch64-linux"];
BL31 = "${plat.armTrustedFirmwareRK3399}/bl31.elf";
filesToInstall = ["idbloader.img" "u-boot.itb" ".config"];
};
}
@Tomaszal

Copy link
Copy Markdown

Hi @angerman, thanks for trying to get NixOS to work on RockPi4. How would I go about running this? I'm trying to compile the image as suggested on NixOS documentation: nix-build '<nixpkgs/nixos>' -A config.system.build.sdImage -I nixos-config=./sd-image.nix --argstr system aarch64-linux

However, that leads to the following error:

error: The option `system.build.sdImage' is defined multiple times.

       Definition values:
       - In `..../sd-image.nix'
       - In `/nix/var/nix/profiles/per-user/root/channels/nixpkgs/nixos/modules/installer/sd-card/sd-image.nix': <derivation /nix/store/3ncjdwbfvhf44ri1pmmy6wvvlcsy91a2-nixos-sd-image-22.11pre391248.49546f4413f-aarch64-linux.img.drv>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment