about summary refs log tree commit diff
path: root/server.nix
blob: eefab38b818bf5f781066efd084548be62430475 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
{
  fetchurl,
  writeText,
  libguestfs-with-appliance,
  pkgsCross,
  qemu,
  runCommand,
  cpio,
  writeShellApplication,
  sshPassword,
  sshPort,
  httpPort,
}:
let
  updateName = "remarkable-production-memfault-image-3.14.1.9-rm2-public";

  updateArchive = fetchurl {
    url =
      # TODO: this is not an official source. might be worth authenticating the updates
      "https://storage.googleapis.com/remarkable-versions/${updateName}.swu";
    hash = "sha256-8zlAGdv+w2KO7BruRQLQC9ivGSHtK82e36ASIeRF3zI=";
  };

  xochitlConfig = writeText "xochitl.conf" ''
    [General]
    DeveloperPassword=${sshPassword}
    wifion=false
    WebInterfaceEnabled=true
    IdleSuspendDelay=0
    SuspendPowerOffDelay=0
  '';

  usbMacAddr = "52:54:00:12:34:56";

  ifnameUdevRule = writeText "70-persistent-net.rules" ''
    SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", \
      ATTR{address}=="${usbMacAddr}", \
      ATTR{type}=="1", KERNEL=="eth*", NAME="usb0"
  '';

  usbNetworkConfig = writeText "10-usb.network" ''
    [Match]
    Name=usb*

    [Network]
    DHCP=yes
  '';

  xochitlService = writeText "xochitl.service" ''
    [Unit]
    Description=reMarkable main application
    After=home.mount network.target

    [Service]
    ExecStart=/usr/bin/xochitl --system
    Restart=always
    # required to make xochitl run
    Environment=LD_PRELOAD=/usr/lib/libfakefbdev.so

    [Install]
    WantedBy=multi-user.target
  '';

  fakefbdev = pkgsCross.armv7l-hf-multiplatform.gcc11Stdenv.mkDerivation {
    name = "fakefbdev";
    src = ./fakefbdev;

    installFlags = [ "DESTDIR=${placeholder "out"}" ];
  };

  kernel = pkgsCross.armv7l-hf-multiplatform.linux_5_4;

  rootfsImage = runCommand "rm-rootfs.ext4" { nativeBuildInputs = [ cpio ]; } ''
    cpio -i --file ${updateArchive}
     gzip -dc ${updateName}.ext4.gz > $out
  '';

  diskImage =
    runCommand "rm-disk.qcow2"
      {
        nativeBuildInputs = [
          qemu
          libguestfs-with-appliance
        ];
      }
      ''
        qemu-img create -f qcow2 $out 8G

        guestfish --rw --blocksize=512 --add $out <<EOF
        run

        # not the original partition table of the RM2
        part-init /dev/sda gpt
        part-add /dev/sda p     2048  2099199
        part-add /dev/sda p  2099200 10487807
        part-add /dev/sda p 10487808 12584959
        part-add /dev/sda p 12584960 16775167

        mkfs vfat /dev/sda1
        upload ${rootfsImage} /dev/sda2
        resize2fs /dev/sda2
        mkfs ext4 /dev/sda4

        mount /dev/sda2 /

        copy-in ${kernel}/lib/modules /lib

        download /etc/fstab fstab
        ! sed -i 's/mmcblk2p/vda/' fstab
        upload fstab /etc/fstab

        upload ${ifnameUdevRule} /etc/udev/rules.d/70-persistent-net.rules
        upload ${usbNetworkConfig} /etc/systemd/network/10-usb.network

        upload ${xochitlService} /lib/systemd/system/xochitl.service

        # delete any systemd units that hinder or delay startup
        rm /lib/systemd/system/kdump.service
        rm /lib/systemd/system/wacom_flash.service
        rm /lib/systemd/system/memfaultd.service
        rm /lib/systemd/system/swupdate.service
        rm /lib/systemd/system/swupdate.socket
        rm /etc/systemd/system/multi-user.target.wants/busybox-ifplugd@usb1.service

        upload ${fakefbdev}/lib/libfakefbdev.so /usr/lib/libfakefbdev.so
        chmod 0755 /usr/lib/libfakefbdev.so

        mount /dev/sda4 /home
        cp-a /etc/skel /home/root

        mkdir-p /home/root/.local/share/remarkable/xochitl
        mkdir-p /home/root/.config/remarkable
        upload ${xochitlConfig} /home/root/.config/remarkable/xochitl.conf

        EOF
      '';

in
writeShellApplication {
  name = "reMder-server";

  runtimeInputs = [ qemu ];

  text = ''
    qemu-img create -b ${diskImage} -F qcow2 -f qcow2 ./reMder.qcow2

    qemu-system-aarch64 \
        -machine virt \
        -enable-kvm \
        -cpu host,aarch64=off \
        -m 2048 \
        -kernel ${kernel}/zImage \
        -drive if=none,file=./reMder.qcow2,format=qcow2,id=hd \
        -device virtio-blk-device,drive=hd \
        -netdev user,hostfwd=tcp::${toString sshPort}-:22,hostfwd=tcp::${toString httpPort}-:80,id=net \
        -device virtio-net-device,netdev=net,mac=${usbMacAddr} \
        -append "console=ttyAMA0 rootfstype=ext4 root=/dev/vda2 rw rootwait init=/sbin/init" \
        -serial mon:stdio \
        -nographic
  '';
}