Awesome Hardware Linux

Orange Pi Zero running in QEMU

I needed a way to run an Orange Pi Zero SD-Card image of Armbian as a virtual machine. And this is actually possible with QEMU!

This is the command I used:

qemu-system-arm \
-M orangepi-pc -m 1024 -cpu cortex-a7 -dtb boot/dtb/sun8i-h3-orangepi-pc.dtb \
-kernel boot/vmlinuz-5.4.45-sunxi -initrd boot/initrd.img-5.4.45-sunxi \
-append 'earlyprintk loglevel=8 earlycon=uart8250,mmio32,0x1c28000,115200n8 console=ttyS0 root=/dev/mmcblk0p1' \
-nographic -serial stdio -monitor none \
-drive file=Armbian_20.05.3_Orangepizero_buster_current_5.4.45.img,format=raw,if=none,id=d1 \
-device sd-card,drive=d1 \
-nic user,model=allwinner-sun8i-emac,hostfwd=tcp::50022-:22

Original source:

You need to get the contents of the /boot directory from the SD Card image so that you can start booting it. I just used scp to copy it from a running Orange Pi Zero to my main machine. The command above doesn’t actually run an Orange Pi Zero board, it runs an Orange Pi PC, though this is almost the same thing. At least the CPU is the same (note: Allwinner H2+ and H3 are binary compatible). But it has more memory!

Why run Armbian in QEMU?

I wanted to compile an application written in Rust. The problem was that installing it the official way through rustup (or more precisely rustup-init) resulted in an error:

info: installing component 'cargo'
info: Defaulting to 139.4 MiB unpack ram
thread 'main' panicked at 'RUSTUP_UNPACK_RAM must be larger than 220000000', src/dist/component/
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at 'No process instance', src/

The newer versions of rust required more memory than the Orange Pi Zero had! Mine had 256 MB (since I thought I’d take this as a challenge instead of going with the 512 MB version). Rustup needed at least 220 MB on its own.

Alternatively I could get some cross-compilation toolchain. But that seemed even harder; I couldn’t find anything usable.


Awesome Linux Open source PinePhone Projects

Mouse in a Pipe

Have you ever wanted to control your notebook directly from your desktop? How about controlling your phone? Wouldn’t it be better to type that chat message using a real keyboard? I wanted the same thing, so I wrote an app for that!

More precisely I created a tool that enables you to redirect mouse and keyboard events from one device to another. It’s like you reconnected your mouse and keyboard, but without the physical effort! All of this happens on a very low level (through the kernel) so this works seamlessly with any application you want to control. All you need is a Linux OS on both of the devices.


One more interesting point is that the input events are pushed through a pipe, which is a generic way of transferring data among processes in Unix-based operating systems. It is up to you how you decide to transfer the data. Though most likely it will happen via SSH. You can easily generate input events on your main computer and then pipe them through SSH to your secondary computer (or a phone) and control it that way. Or you might decide to create a TCP connection and pass the data through that. That’s up to you!

And you know what else is this useful for? That’s right, you can finally play OpenTTD on a PinePhone with the full comfort of a mouse and keyboard!


Linux Open source PicoPosts PinePhone Projects

Arch Linux ARM Installer for PinePhone

I started building an automated Arch Linux ARM installation and customization set of scripts to be used for the PinePhone. The aim is to make the process easier while still being able to customize every aspect of the OS.

Repository URL:

Arch Linux ARM running LXDE, Firefox and Onboard keyboard.

Arch Linux ARM was the best OS for PinePhone I’ve seen so far. It might be due to personal preference, but I just love how you have the full power of Arch on your mobile phone.

And if Arch is not your thing, at least you can learn what are the steps required for bringing a Linux OS into a PinePhone.


Linux PinePhone

Errors During PinePhone Install

I learned a lot about hardware and operating systems since I received my PinePhone. A lot of times it was during error investigation. With a small chance that this information might get picked up by another PinePhone enthusiast, I’ll post the error messages and my solutions here.

RTL firmware not found

Bluetooth firmware on my Arch Linux ARM was missing, it is a non-free firmware so it is not included by default.

Feb 23 19:21:58 alarm kernel: bluetooth hci0: Direct firmware load for rtl_bt/rtl8723cs_xx_fw.bin failed with error -2
Feb 23 19:21:58 alarm kernel: Bluetooth: hci0: RTL: firmware file rtl_bt/rtl8723cs_xx_fw.bin not found

With this I just went over to my postmarketOS SD Card image and copied the corresponding files from /lib/firmware/rtl_bt/ over SSH

scp lib/firmware/rtl_bt/rtl8723cs_xx_fw.bin root@pinephone_ip_address:/lib/firmware/rtl_bt/
scp lib/firmware/rtl_bt/rtl8723cs_xx_config-pinebook.bin root@pinephone_ip_address:/lib/firmware/rtl_bt/rtl8723cs_xx_config-pinephone.bin # notice the rename

systemd-binfmt Failed

I was getting a lot of binfmt-related errors like the ones in bold below. And if there is one thing you don’t want to see it is a red FAILED log line during boot process.

Feb 23 19:36:10 alarm systemd[1]: Mounted Temporary Directory (/tmp).
Feb 23 19:36:10 alarm systemd[1]: Started Create list of static device nodes for the current kernel.
Feb 23 19:36:10 alarm systemd[1]: systemd-binfmt.service: Main process exited, code=exited, status=1/FAILURE
Feb 23 19:36:10 alarm systemd[1]: systemd-binfmt.service: Failed with result 'exit-code'.
Feb 23 19:36:10 alarm systemd[1]: Failed to start Set Up Additional Binary Formats.
Feb 23 19:36:10 alarm systemd[1]: Started Load Kernel Modules.
Feb 23 19:36:10 alarm systemd-binfmt[267]: Failed to add binary format: No such file or directory
Feb 23 19:36:13 alarm systemd[1]: Starting Load/Save RF Kill Switch Status…
Feb 23 19:36:13 alarm systemd-binfmt[385]: Failed to add binary format: No such file or directory
Feb 23 19:36:13 alarm systemd[1]: Condition check resulted in Create System Users being skipped.
Feb 23 19:36:13 alarm systemd[1]: systemd-binfmt.service: Main process exited, code=exited, status=1/FAILURE
Feb 23 19:36:13 alarm systemd[1]: systemd-binfmt.service: Failed with result 'exit-code'.
Feb 23 19:36:13 alarm systemd[1]: Failed to start Set Up Additional Binary Formats.
Feb 23 19:36:13 alarm systemd[1]: Started Load/Save RF Kill Switch Status.

So I went to investigate the service’s config files, seeing the “Failed to add binary format: No such file or directory” error. There are several directories that binfmt is looking for its config files. As it turns out all of them were empty apart from one. I found out that after installing mono it registered itself with binfmt. Not sure why, but I certainly don’t need it, so the solution is simple.

rm /usr/lib/binfmt.d/mono.conf 


Broken Battery In ACPI

Multiple components make use of the ACPI and all of them report a dead battery. E.g. battery applet or laptop-mode service:

Feb 23 19:22:05 alarm laptop-mode[1653]: Failed to re-set power saving mode for wireless card
Feb 23 19:22:05 alarm laptop-mode[1700]: WARNING: Battery does not report a capacity. Minimum battery
Feb 23 19:22:05 alarm laptop-mode[1701]: charge checking does not work without a design capacity.
Feb 23 19:22:05 alarm laptop-mode[1702]: WARNING: Battery does not report a design capacity. Auto hibernation
Feb 23 19:22:05 alarm laptop-mode[1703]: does not work without a design capacity.
Feb 23 19:22:05 alarm laptop-mode[1704]: You seem to have a broken battery
Feb 23 19:22:05 alarm laptop-mode[1705]: Cannot determine design_capacity_warning
Feb 23 19:22:05 alarm laptop-mode[1706]: Disabling hibernation
Feb 23 19:22:05 alarm laptop-mode[1707]: Failed to determine battery charge. Battery charge units are not in
Feb 23 19:22:05 alarm laptop-mode[1708]: mWh, uWh, mAh or uAh.
Feb 23 19:22:05 alarm laptop-mode[1711]: enabled, active

This is not the case since the battery is actually fine, it just doesn’t work with ACPI:

# cat /sys/class/power_supply/axp20x-battery/uevent 

Seems the kernel I’m using doesn’t have it enabled, as you can see here:

#  ls -l /usr/lib/modules/$(uname -r)/kernel/drivers/acpi
ls: cannot access '/usr/lib/modules/5.6.0-rc1-00239-geb93b104bbccb/kernel/drivers/acpi': No such file or directory


Linux Open source PinePhone

PinePhone Status Review 2020-02-22

I’ve spent a bit of time with my new Linux toy, PINE64 PinePhone. This is a smartphone built on top of components that are supported well by the mainline Linux kernel. So in theory it should be a piece of cake to get installed. Is it?

Various Gotchas

Let’s start with a few gotchas that somewhat surprised me.

WiFi needs a battery

The WiFi / GSM modem needs a battery to be connected in order to operate. Otherwise it won’t even appear as an available device. You could spend a lot of time trying to connect to the WiFi like this. In vain.

Power Hungry

The phone is really hungry for power and often it is not enough to connect it to a PC. The battery will discharge even when connected via a USB cable, unless the power source is strong enough. Running on 0.5A (2.5W) is not enough. It generally takes around 1.4A (7W) when running a full featured OS and it will drop to 0% eventually.


You never appreciate it enough until you lose it. Having a shell in your phone is great. Though you can’t really use it, since there is no keyboard available. This one is somewhat obvious, but it is a big hurdle when trying out various systems. You can install some virtual keyboard, but it won’t have all the keys you need and it doesn’t work in every environment. Not reliably at least. Your best bet is to get an SSH connection going as a workaround. Hardware keyboards are not supported / don’t exist right now.

Operating Systems

I’ve tried out multiple systems and environments, here are a few thoughts about them.


I’d say this is the best OS out there right now. At least in terms of having a solid PinePhone support, configurability and a reasonable Linux distribution underneath. It has a dedicated PinePhone wiki page. You have a choice of multiple UI environments (including phosh, mate and xfce4). It is based on Alpine Linux with all of its ARM packages at your disposal.

Though it was very exciting to have a full blown Linux desktop like Xfce on the phone’s screen, the touch controls were something to be desired. A much better experience can be achieved with Librem’s Phosh. This on the other hand has a scaling turned on (lowered DPI), which messes up a lot of applications so that they become unusable. But it is still closest to a usable working environment.

What I appreciated the most was pmbootstrap which is a CLI tool that lets you configure your custom OS image down to what UI and packages you want to include by default. Thanks to this you have a tailored SD Card ready to be used with your PinePhone.

Arch Linux ARM

My favorite Linux distribution is available for PinePhone as well! Although not customized for it, it is possible to use this and customize it on your own. There is a general guide on installing Arch for PINE64 board, which the PinePhone is based on. There is also a customized kernel that you can use over at with a nice tutorial on how to install it.

I’ve just started with this one, so not much to report apart from that it is working. I have a terminal login prompt on the screen and a SSH connection over a USB cable from my PC. Life is good.

Fedora Mobile

You can install all sorts of things on the PinePhone. I’ve tested this set of shell scripts that help you prepare a Fedora Mobile on an SD Card. A system that was not optimized for this device. The result itself was unusable (at least the release that I tested). Nevertheless I enjoyed learning about the process of preparing a bootable SD Card. Even though it is basically the same for every OS, this set of bash scripts was really easy to study and use it as a tutorial.

Ubuntu Touch

Ubuntu Touch somewhat effortlessly worked to the extend you’d expect with a partially supported device. I liked that they provide an SD Card image for the PinePhone, so all you have to do is to flash it (e.g. using dd) and pop it into the phone.

I personally don’t enjoy Ubuntu for some reason so I won’t experiment with it or comment on this much more.


Did I mention you can run OpenTTD on it? Oh yeah…


Hardware Linux

Root Access to TL-WDR3600

I played around with an old router I had lying around. It is a TP-LINK, model TL-WDR3600 (N600 Wireless Dual Band Gigabit Router). After opening the case you can see a 4-pin connection point that is apparently a serial port. The pinout being 3.3V, GND, TX, RX.

After powering it up with a 12V adapter and connecting to the serial port with a USB-to-Serial dongle you can get to a Linux login prompt. After a bit of searching I found out there is a root account with a factory default(!) password ‘sohoadmin’ [Source].

Logging into the TL-WDR3600 as root gives you a BusyBox shell with an ancient 2.6 Linux kernel. The root mount point seems to be a read-only (flash?) storage, so no fun to be had here. The system would probably need to be re-flashed to change any of the contents.


Hardware Linux

Serial Connection to ZyXEL NGB6515

This evening I toyed around with my now deprecated wireless router ZyXEL NGB6515. After opening the case there is a distinct 4-pin connection point for the serial console. The pins being 3.3V, GND, TX, RX (3.3V is the square pin).

Connecting a USB-to-Serial dongle set to 57600 bauds yielded a log from the main MediaTek MT7620a processor. Right after I connected the 12V power there is a short period when the bootloader (U-Boot) waits for an integer input to choose which mode of operation the device should run in (e.g. flashing, OS boot etc.).

By default the system boots a 3.2.9 Linux kernel. Though I couldn’t come up with a way of controlling the command prompt. There is a “cmd>” prompt, but it ignored any input and just reprinted the prompt on every newline.

Sadly this device is not supported by OpenWRT, even though the MT7620a processor is a pretty standard chip among home routers.


Linux PicoPosts

Adding certificates to Java keystore

Java has its own certificate storage. At least in Arch Linux it is located in:


To add a new certificate there, run this command:

keytool -keystore cacerts -importcert -alias myrootcert -file /path/to/MyRootCert.crt

(you might want to run that as root) As a password, the default is “changeit”.

I encountered this while setting up my Android project in IntelliJ IDEA, trying to do a Gradle build. Also the Android SDK tool was failing on an invalid SSL connection.


Awesome Linux Open source Programming Projects Technology Web development

HTTP and HTTPS running on the same port

Running HTTP and HTTPS on the same port with Apache. They said it couldn’t be done. They were wrong!

I’ve modified a simple Python port forwarding utility to act as a port multiplexer that can automatically forward HTTP and HTTPS requests to the appropriate ports. If the request looks like an HTTP in plain text, it forwards it to port A. Otherwise it is assumed to be HTTPS and is forwarded to port B.

Now you can run your web applications from a single port, regardless of using HTTP or HTTPS. Hooray!


Linux Open source Privacy Projects Technology Web development

How to become a Certification Authority

This short How-To has been compiled based on the work I’ve done so far while building my personal home server. To achieve reasonable level of privacy without spending a fortune on it, I’ve become my own Certification Authority (CA).


These are the basic steps covered later in detail:

  1. Create a CA key and certificate.
  2. Create a server key and a Certificate signing request (CSR).
  3. Sign the CSR using the CA key.
  4. Use the new server certificate in Apache.
  5. Import the CA certificate into your browsers.
  6. … Profit!

What this results in is a single certificate file for your CA that you distribute and import into your browsers (PC, phone, …). Every individual signed server / service certificate you create and use is then automatically recognized as valid and trusted. If you are using a personal set of services (various web applications, XMPP server, etc.), this saves you a lot of “exception adding”, just import one (your) CA certificate and everything is working, no need for the browser to nag about self-signed certificates.

Detailed how-to

Creating a CA key pair

First, prepare your “playground”, a data storage somewhere on your (preferably Linux) computer. It should look like this:

 |-- conf     ... for configuration files.
 |-- private  ... for private CA key (protect this directory!)
 |-- public   ... for public CA key
 |-- requests ... for incoming CSR
 +-- certs    ... for resulting certificates

Now cd to the root-ca directory. Create a configuration file conf/openssl.conf with the following content:

[ req ]
default_bits            = 2048
default_keyfile         = ./private/root.pem
default_md              = sha1
prompt                  = no
distinguished_name      = root_ca_distinguished_name
x509_extensions = v3_ca

[ root_ca_distinguished_name ]
countryName             = UK
stateOrProvinceName     = Sussex
localityName            = Brighton
0.organizationName      = Example Inc
commonName              = Example Inc Root CA
emailAddress            =

[ v3_ca ]
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always,issuer:always
basicConstraints        = CA:true

[ ca ]
default_ca              = CA_default

[ CA_default ]
dir                     = .
new_certs_dir           = ./certs/
database                = ./conf/index
certificate             = ./public/root.pem
serial                  = ./conf/serial
private_key             = ./private/root.pem
x509_extensions         = usr_cert
name_opt                = ca_default
cert_opt                = ca_default
default_crl_days        = 30
default_days            = 365
default_md              = sha1
preserve                = no
policy                  = policy_match

[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ usr_cert ]
basicConstraints        = CA:FALSE
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid,issuer:always
nsCaRevocationUrl       =

It might look long and complicated, but most of it is pretty self explanatory. What you should edit is the root_ca_distinguished_name section and the nsCaRevocationUrl.

Then initialize the “certificate counters”, like so:

echo "01" > conf/serial
touch conf/index

Finally, generate a CA key pair (public and private root.pem files):

openssl req -nodes -config conf/openssl.conf -days 1825 -x509 -newkey rsa:2048 -out public/root.pem -outform PEM

Creating a server key pair

On the server for which you want to obtain a signed certificate, do this:

openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr

Then you can transfer the server.csr file to the CA’s requests directory.

Signing the CSR

Simply call this command and you get a signed certificate server.cert from a request server.csr:

openssl ca -batch -config conf/openssl.conf -in requests/server.csr -out certs/server.cert

Setting up SSL in Apache

Somewhere in the httpd.conf or inside a virtual host configuration add these lines:

 Listen 443
 SSLEngine on
 SSLCertificateFile /path/to/keys/server.cert
 SSLCertificateKeyFile /path/to/keys/server.key
 SSLCertificateChainFile /path/to/keys/root.pem

These lines activate SSL and the port for SSL, specify server certificate, private certificate key and (optionally) root CA certificate. After restarting the server, HTTPS should be ready to use.

Importing and using

Different applications have different ways of importing trusted CA certificates.

On Windows, you just “execute” the certificate and install it into the appropriate category. This should take care of most of your applications. Web browser (e.g. Firefox) might need to have this certificate installed explicitly, ignoring certificates in the OS.

On Linux, look for /etc/ca-certificates.conf, add the certificate filename there and copy the file to /usr/share/ca-certificates/. Then run update-ca-certificates –fresh to recreate the list of known certificates.


Based on these articles: