Setting up RM110

So I got one of those. Noris digital jumbo draws nicely on it. Drawing is indeed faster than typing.

SSH from any network interface

First, install opkg on the RM110.

Put this in front of ~/.bashrc. export PATH=/opt/bin:/opt/bin:${PATH}

rm11x:

# overwrite stock wget (which has no TLS support)
cp /opt/bin/wget /usr/bin/wget

opkg install rsync openssh-server

RM110 has little computing power, so I generated SSH host keys on another machine.

host:

ssh-keygen -q -N "" -t rsa -b 4096 -f ssh_host_rsa_key
ssh-keygen -q -N "" -t ed25519 -f ssh_host_ed25519_key
# send it
rsync ssh_host_* 11:/opt/etc/ssh/

rm11x:

# check how to start sshd
opkg files openssh-server
# start sshd
/opt/etc/init.d/S40sshd start
# see ip addr
ip addr

Now I can SSH into the RM110 using WiFi!

Getting kakoune on there

No entware? No problem. Alpine has us covered.

host:

wget2 https://dl-cdn.alpinelinux.org/alpine/latest-stable/community/armv7/kakoune-2024.05.18-r0.apk
# be in a empty directory first, or i hope you well :)
tar -xvf kakoune-2024.05.18-r0.apk
rsync -a usr/ 11:/opt/usr/

Hmm?

host:

❯ file usr/bin/kak
usr/bin/kak: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-armhf.so.1, BuildID[sha1]=7de0311cdba583b5da3f881c36599c46fd455378, stripped
❯ rsync 11:/usr/bin/xochitl ./
❯ file xochitl
xochitl: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=f45f1a5d5638c43f1de512656e8a5600095c037d, for GNU/Linux 3.2.0, stripped

Ok, maybe not.

Please accept this as your own children.

host:

patchelf --set-interpreter /lib/ld-linux-armhf.so.3 --set-os-abi Linux usr/bin/kak
patchelf --replace-needed libc.musl-armv7.so.1 ld-linux-armhf.so.3 usr/bin/kak
rsync usr/bin/kak 11:/opt/usr/bin/kak

rm11x:

reMarkable: ~/ /opt/usr/bin/kak
/opt/usr/bin/kak: symbol lookup error: /opt/usr/bin/kak: undefined symbol: __select_time64

:(

interlude - Free init.d testing

The thing just restarted by itself.

ssh still works; yay!

Setting up a build environment

no shortcut eh?

Let’s try Zig.

host:

zvm i 0.13.0
zig init
zig build -Dtarget=arm-linux-gnueabihf
ldd zig-out/bin/hello-world
scp zig-out/bin/hello-world 11:

rm11x:

reMarkable: ~/ ./hello-world 
All your codebase are belong to us.
Run `zig build test` to run the tests.

nice.

interlude - what the bash?

reMarkable: // cd ~
reMarkable: ~/ cd /
reMarkable: // 

// ??????

Getting kakoune on there - continued

  • git clone https://github.com/mawww/kakoune

  • edit Makefile

    - CXX = c++
    + CXX = zig c++
    
    - CXXFLAGS-default = -std=c++2a -Wall -Wextra -pedantic -Wno-unused-parameter -Wno-sign-compare
    + CXXFLAGS-default = -std=c++2a -Wall -Wextra -pedantic -Wno-unused-parameter -Wno-sign-compare --target=arm-linux-gnueabihf
    
  • make -j

  • scp src/kak.opt 11:/opt/bin/kak

isn’t zig nice?

rm11x:

reMarkable: ~/ kak
Fatal error: mkdir failed for directory '/tmp' errno 17

hmm. kakoune?


void make_directory(StringView dir, mode_t mode)
{
    auto it = dir.begin(), end = dir.end();
    while(it != end)
    {
        it = std::find(it+1, end, '/');
        struct stat st;
        StringView dirname{dir.begin(), it};
        if (stat(dirname.zstr(), &st) == 0)
        {
            if (not S_ISDIR(st.st_mode))
                throw runtime_error(format("cannot make directory, '{}' exists but is not a directory", dirname));
        }
        else
        {
            auto old_mask = umask(0);
            auto restore_mask = on_scope_end([old_mask]() { umask(old_mask); });

            if (mkdir(dirname.zstr(), mode) != 0)
                throw runtime_error(format("mkdir failed for directory '{}' errno {}", dirname, errno));
        }
    }
}

This looks correct.

rm11x:

opkg install gdb

host:

rsync -a src/ 11:src/

rm11x:

gdb kak

(gdb) b make_directory
Breakpoint 1 at 0x120488: make_directory. (3 locations)
(gdb) r

ok.

so stat("/tmp/", &st) != 0

let’s see.

reMarkable: ~/ stat /tmp/
  File: /tmp/
  Size: 260       	Blocks: 0          IO Block: 4096   directory
Device: 17h/23d	Inode: 7304        Links: 6
Access: (1777/drwxrwxrwt)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-06-13 19:27:50.718366010 +0000
Modify: 2024-06-13 19:26:57.218726460 +0000
Change: 2024-06-13 19:26:57.218726460 +0000

what

reMarkable: ~/ vim a.c # the sad reality that we must use vim
reMarkable: ~/ cat a.c
#include <sys/stat.h>
int main() {
struct stat st;
return stat("/tmp/", &st);
}
reMarkable: ~/ cc a.c
reMarkable: ~/ ./a.out
reMarkable: ~/ ./a.out && echo 1
1

okay. libc is working then.

host:

rsync -a 11:/opt/ ~/sysroot/rm11x/

patch Makefile

- CXXFLAGS-default = -std=c++2a -Wall -Wextra -pedantic -Wno-unused-parameter -Wno-sign-compare --target=arm-linux-gnueabihf
+ CXXFLAGS-default = -std=c++2a -Wall -Wextra -pedantic -Wno-unused-parameter -Wno-sign-compare --target=arm-linux-gnueabihf -isysroot=~/sysroot/rm11x -rdynamic

here we go again

make clean
make -j
rsync src/kak.opt 11:/opt/bin/kak
reMarkable: ~/ /opt/bin/kak
Fatal error: mkdir failed for directory '/tmp' errno 17

hmm.

Figuring out what’s wrong with the toolchain

luckily, objdump is available on the device.

the good program:

00010490 <__stat>:
   10490:       e1a02001        mov     r2, r1
   10494:       e1a01000        mov     r1, r0
   10498:       e3a00003        mov     r0, #3
   1049c:       eaffffad        b       10358 <__xstat@plt>

the bad program:

00023f00 <__stat>:
   23f00:    e1a02001     mov    r2, r1
   23f04:    e1a01000     mov    r1, r0
   23f08:    e3a00000     mov    r0, #0
   23f0c:    ea00824f     b    44850 <_fini+0x80>

host cc:

❯ zig cc --version
clang version 18.1.6 (https://github.com/ziglang/zig-bootstrap 98bc6bf4fc4009888d33941daf6b600d20a42a56)
Target: x86_64-unknown-linux-musl
Thread model: posix
InstalledDir: /usr/bin

device cc:

reMarkable: ~/ cc --version
cc (OpenWrt GCC 8.4.0) 8.4.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

it’s a zig bug

zvm use 0.11.0 and it works.

i think -isysroot is unnecessary.

now i have kakoune there.

Getting dinit on there

The stock OS runs systemd. Not ideal. We need to remove it ASAP.

but like, the software update runs on systemd, so i don’t know what to do here.

the device itself is kind of simple. there is one button that cycles the power.

if i do this, i have to make sure that

  • i have a jig with a pogo pins breakout board that i can use to unbrick the device.
  • (optional) i have a way to get xochitl from official software updates without actually updating the device(, in case i needed the compiled code in there)
  • ???

I should try out rm2-stuff first.


Update: I bricked the device and sent it home.