add new Installation guide

move the u-boot/serial stuff here from development, as the
reality of Liminix development in 2024 is that serial connection
is still the smoothest installation method
This commit is contained in:
Daniel Barlow 2024-07-11 23:31:00 +01:00
parent 2ce361d4e3
commit 241f1013ed
4 changed files with 174 additions and 192 deletions

View File

@ -116,140 +116,6 @@ human-readable format, use :command:`s6-tai64nlocal`.
Flashing and updating
*********************
Flashing from Liminix
=====================
The flash procedure from an existing Liminix-system has two steps.
First we reboot the device (using "kexec") into an "ephemeral"
RAM-based version of the new configuration, then when we're happy it
works we can flash the image - and if it doesn't work we can reboot
the device again and it will boot from the old image.
Building the RAM-based image
----------------------------
To create the ephemeral image, build ``outputs.kexecboot`` instead of
``outputs.default``. This generates a directory containing the root
filesystem image and kernel, along with an executable called `kexec`
and a `boot.sh` script that runs it with appropriate arguments.
For example
.. code-block:: console
nix-build -I liminix-config=./examples/arhcive.nix \
--arg device "import ./devices/gl-ar750"
-A outputs.kexecboot && \
(tar chf - result | ssh root@the-device tar -C /run -xvf -)
and then login to the device and run
.. code-block:: console
cd /run/result
sh ./boot.sh .
This will load the new kernel and map the root filesystem into a RAM
disk, then start executing the new kernel. *This is effectively a
reboot - be sure to close all open files and finish anything else
you were doing first.*
If the new system crashes or is rebooted, then the device will revert
to the old configuration it finds in flash.
Building the second (permanent) image
-------------------------------------
While running in the kexecboot system, you can build the permanent
image and copy it to the device with :command:`ssh`
.. code-block:: console
build-machine$ nix-build -I liminix-config=./examples/arhcive.nix \
--arg device "import ./devices/gl-ar750"
-A outputs.default && \
(tar chf - result | ssh root@the-device tar -C /run -xvf -)
build-machine$ tar chf - result/firmware.bin | \
ssh root@the-device tar -C /run -xvf -
Next you need to connect to the device and locate the "firmware"
partition, which you can do with a combination of :command:`dmesg`
output and the contents of :file:`/proc/mtd`
.. code-block:: console
<5>[ 0.469841] Creating 4 MTD partitions on "spi0.0":
<5>[ 0.474837] 0x000000000000-0x000000040000 : "u-boot"
<5>[ 0.480796] 0x000000040000-0x000000050000 : "u-boot-env"
<5>[ 0.487056] 0x000000050000-0x000000060000 : "art"
<5>[ 0.492753] 0x000000060000-0x000001000000 : "firmware"
# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00001000 "u-boot"
mtd1: 00010000 00001000 "u-boot-env"
mtd2: 00010000 00001000 "art"
mtd3: 00fa0000 00001000 "firmware"
mtd4: 002a0000 00001000 "kernel"
mtd5: 00d00000 00001000 "rootfs"
Now run (in this example)
.. code-block:: console
flashcp -v firmware.bin /dev/mtd3
"I know my new image is good, can I skip the intermediate step?"
----------------------------------------------------------------
In addition to giving you a chance to see if the new image works, this
two-step process ensures that you're not copying the new image over
the top of the active root filesystem. Sometimes it works, but you
will at least need physical access to the device to power-cycle it
because it will be effectively frozen afterwards.
Flashing from the boot monitor
==============================
If you are prepared to open the device and have a TTL serial adaptor
of some kind to connect it to, you can probably use U-Boot and a TFTP
server to download and flash the image. This is quite
hardware-specific, and sometimes involves soldering: please refer
to :ref:`serial`.
Flashing from OpenWrt
=====================
.. CAUTION:: Untested! A previous version of these instructions
(without the -e flag) led to bricking the device
when flashing a jffs2 image. If you are reading
this message, nobody has yet reported on whether the
new instructions are any better.
If your device is running OpenWrt then it probably has the
:command:`mtd` command installed. After transferring the image onto the
device using e.g. :command:`ssh`, you can run it as follows:
.. code-block:: console
mtd -e -r write /tmp/firmware.bin firmware
The options to this command are for "erase before writing" and "reboot
after writing".
For more information, please see the `OpenWrt manual <https://openwrt.org/docs/guide-user/installation/sysupgrade.cli>`_ which may also contain (hardware-dependent) instructions on how to flash an image using the vendor firmware - perhaps even from a web interface.
Updating an installed system (JFFS2)
************************************

View File

@ -88,64 +88,6 @@ time with configurations for RP-PPPoE and/or Accel PPP.`
Hardware devices
****************
.. _serial:
U-Boot and serial shenanigans
=============================
Every device that we have so far encountered in Liminix uses `U-Boot,
the "Universal Boot Loader" <https://docs.u-boot.org/en/latest/>`_ so
it's worth knowing a bit about it. "Universal" is in this context a
bit of a misnomer, though: encountering *mainline* U-Boot is very rare
and often you'll find it is a fork from some version last updated
in 2008. Upgrading U-Boot is more or less complicated depending on the
device and is outside scope for Liminix.
To speak to U-Boot on your device you'll usually need a serial
connection to it. This is device-specific. Usually it involves
opening the box, locating the serial header pins (TX, RX and GND) and
connecting a USB TTL converter to them.
The Rolls Royce of USB/UART cables is the `FTDI cable
<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_,
but there are cheaper alternatives based on the PL2303 and CP2102 chipsets. Or
get creative and use the `UART GPIO pins <https://pinout.xyz/>`_ on a Raspberry Pi. Whatever you do, make sure
that the voltages are compatible: if your device is 3.3V (this is
typical but not universal), you don't want to be sending it 5v or
(even worse) 12v.
Run a terminal emulator such as Minicom on the computer at other end
of the link. 115200 8N1 is the typical speed.
.. NOTE::
TTL serial connections typically have no form of flow control and
so don't always like having massive chunks of text pasted into
them - and U-Boot may drop characters while it's busy. So don't
necessarily expect to copy-paste large chunks of text into the
terminal emulator and have it work just like that.
If using Minicom, you may find it helps to bring up the "Termimal
settings" dialog (C^A T), then configure "Newline tx delay" to
some small but non-zero value.
When you turn the router on you should be greeted with some messages
from U-Boot, followed by the instruction to hit some key to stop
autoboot. Do this and you will get to the prompt. If you didn't see
anything, the strong likelihood is that TX and RX are the wrong way
around. If you see garbage, try a different speed.
Interesting commands to try first in U-Boot are :command:`help` and
:command:`printenv`.
To do anything useful with U-Boot you will probably need a way to get
large binary files onto the device, and the usual way to do this is by
adding a network connection and using TFTP to download them. It's
quite common that the device's U-Boot doesn't speak DHCP so it will
need a static LAN address. You might also want to keep it away from
your "real" LAN: see :ref:`bng` for some potentially useful tooling
to use it on an isolated network.
TFTP
====

View File

@ -8,6 +8,7 @@ Liminix
intro
tutorial
configuration
installation
admin
development
modules

173
doc/installation.rst Normal file
View File

@ -0,0 +1,173 @@
Installation
############
Hardware devices vary wildly in their affordances for installing new
operating systems, so it should be no surprise that the Liminix
installation procedure is hardware-dependent. This section contains
generic instructions, but please refer to the documentation for your
device to find whether and how well they apply.
Flashing from the boot monitor (TFTP install)
*********************************************
If you are prepared to open the device and have a TTL serial adaptor
of some kind to connect it to, you can probably use U-Boot and a TFTP
server to download and flash the image.
This is quite hardware-specific and may even involve soldering - see
the documention for your device. However, it is in some ways the most
"reliable" option: if you can see what's happening (or not happening)
in early boot, the risk of "bricking" is substantially reduced and you
have options for recovering if you misstep or flash a bad image.
.. _serial:
U-Boot and serial shenanigans
=============================
Every device that we have so far encountered in Liminix uses `U-Boot,
the "Universal Boot Loader" <https://docs.u-boot.org/en/latest/>`_ so
it's worth knowing a bit about it. "Universal" is in this context a
bit of a misnomer, though: encountering *mainline* U-Boot is very rare
and often you'll find it is a fork from some version last updated
in 2008. Upgrading U-Boot is more or less complicated depending on the
device and is outside scope for Liminix.
To speak to U-Boot on your device you'll usually need a serial
connection to it. This typically involves opening the box, locating
the serial header pins (TX, RX and GND) and connecting a USB TTL
converter to them.
The Rolls Royce of USB/UART cables is the `FTDI cable
<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_,
but there are cheaper alternatives based on the PL2303 and CP2102 chipsets - or you could even
get creative and use the `UART GPIO pins <https://pinout.xyz/>`_ on a Raspberry Pi. Whatever you do, make sure
that the voltages are compatible: if your device is 3.3V (this is
typical but not universal), you don't want to be sending it 5v or
(even worse) 12v.
Run a terminal emulator such as Minicom on the computer at other end
of the link. 115200 8N1 is the typical speed.
.. NOTE::
TTL serial connections often have no flow control and
so don't always like having massive chunks of text pasted into
them - and U-Boot may drop characters while it's busy. So don't
do that.
If using Minicom, you may find it helps to bring up the "Termimal
settings" dialog (C^A T), then configure "Newline tx delay" to
some small but non-zero value.
When you turn the router on you should be greeted with some messages
from U-Boot, followed by the instruction to hit some key to stop
autoboot. Do this and you will get to the prompt. If you didn't see
anything, the strong likelihood is that TX and RX are the wrong way
around. If you see garbage, try a different speed.
Interesting commands to try first in U-Boot are :command:`help` and
:command:`printenv`.
You will also need to configure a TFTP server on a network that's
accessible to the device: how you do that will vary according to which
TFTP server you're using and so is out of scope for this document.
Buildiing and installing the image
==================================
Follow the device-specific instructions for "TFTP install": usually,
the steps are
* build the `outputs.mtdimage` output
* copy :file:`result/firmware.bin` to your TFTP server
* copy/paste the commands in :file:`result/flash.scr` one at a time into the U-Boot command line
* reset the device
You should now see messages from U-Boot, then from the Linux kernel
and eventually a shell prompt.
.. NOTE:: Before you reboot, check which networks the device is
plugged into, and disconnect as necessary. If you've just
installed a DHCP server or anything similar that responds to
broadcasts, you may not want it to do that on the network
that you temporarily connected it to for installing it.
Flashing from OpenWrt
*********************
.. CAUTION:: Untested! A previous version of these instructions
(without the -e flag) led to bricking the device
when flashing a jffs2 image. If you are reading
this message, nobody has yet reported on whether the
new instructions are any better.
If your device is running OpenWrt then it probably has the
:command:`mtd` command installed. Build the `outputs.mtdimage` output
(as you would for a TFTP install) and then transfer
:file:`result/firmware.bin` onto the device using e.g.
:command:`scp`. Now flash as follows:
.. code-block:: console
mtd -e -r write /tmp/firmware.bin firmware
The options to this command are for "erase before writing" and "reboot
after writing".
For more information, please see the `OpenWrt manual <https://openwrt.org/docs/guide-user/installation/sysupgrade.cli>`_ which may also contain (hardware-dependent) instructions on how to flash an image using the vendor firmware - perhaps even from a web interface.
Flashing from Liminix
*********************
If the device is already running Liminix and has been configured with
:command:`levitate`, you can use that to safely flash your new image.
Refer to :ref:`levitate` for an explanation.
If the device is running Liminix but doesn't have :command:`levitate`
your options are more limited. You may attempt to use
:command:`flashcp` but it doesn't always work: as it copies the new
image over the top of the active root filesystem, surprise may ensue.
Consider instead using a serial connection: you may need one anyway
after trying flashcp if it corrupts the image.
flashcp (not generally recommended)
===================================
Connect to the device and locate the "firmware" partition, which you
can do with a combination of :command:`dmesg` output and the contents
of :file:`/proc/mtd`
.. code-block:: console
<5>[ 0.469841] Creating 4 MTD partitions on "spi0.0":
<5>[ 0.474837] 0x000000000000-0x000000040000 : "u-boot"
<5>[ 0.480796] 0x000000040000-0x000000050000 : "u-boot-env"
<5>[ 0.487056] 0x000000050000-0x000000060000 : "art"
<5>[ 0.492753] 0x000000060000-0x000001000000 : "firmware"
# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00001000 "u-boot"
mtd1: 00010000 00001000 "u-boot-env"
mtd2: 00010000 00001000 "art"
mtd3: 00fa0000 00001000 "firmware"
mtd4: 002a0000 00001000 "kernel"
mtd5: 00d00000 00001000 "rootfs"
Copy :file:`result/firmware.bin` to the device and now run (in this
example)
.. code-block:: console
flashcp -v firmware.bin /dev/mtd3