= 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. Most of the supported devices fall into one of two broad categories: * devices we install by preparing a raw flash image and copying it directly onto (some part of) the flash. This is analogous to (though not quite the same as) using https://www.man7.org/linux/man-pages/man1/dd.1.html:dd(1) on a "grown up" computer to copy a raw disk image. Devices in this category are usually smaller, older, and/or less powerful. * devices where the vendor provides a "higher level" storage abstraction, such as http://linux-mtd.infradead.org/doc/ubi.html:UBI over raw flash, or a consumer flash such as MMC, or another storage technology entirely. Installation on these devices is less uniform because it depends on exactly what kind of storage abstraction. == Building a firmware image Liminix uses the Nix language to provide congruent configuration management. This means that to change anything about the way in which a Liminix system works, you make that change in your `+configuration.nix+` (or one of the other files it references), and rerun `+nix-build+` to action the change. It is not possible (at least, without shenanigans) to make changes by logging into the device and running imperative commands whose effects may later be overridden: `+configuration.nix+` always describes the entire system and can be used to recreate that system at any time. You can usefully keep it under version control. If you are familiar with NixOS, you will notice some similarities between NixOS and Liminix configuration, and also some differences. Sometimes the differences are due to the resource-constrained devices we deploy onto, sometimes due to differences in the uses these devices are put to. For a more full description of how to configure Liminix, see <<_configuration>>. Assuming for the moment that you want a typical home wireless gateway/router, the best way to get started is to copy `+examples/rotuer.nix+` and edit it for your requirements. [source,console] ---- $ cp examples/rotuer.nix configuration.nix $ vi configuration.nix # other editors are available $ # adjust this next command for your hardware device $ nix-build -I liminix-config=./configuration.nix \ --arg device "import ./devices/gl-mt300a" -A outputs.default ---- For raw flash devices, this will leave you with a file `+result/firmware.bin+` which you now need to write to the flash. For other devices, _please check the device documentation_ == Flashing from the boot monitor (TFTP install) You will need * to open the device and attach a TTL serial adaptor of some kind * a TFTP server on the network that the device is plugged into (or can be plugged into for installation) Installing via serial connection is quite hardware-specific and depending on the device may even involve soldering. 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]] === Serial connections 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 https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable[FTDI cable], but there are cheaper alternatives based on the PL2303 and CP2102 chipsets - or you could even get creative and use the https://pinout.xyz/[UART GPIO pins] 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, or your computer is expecting flow control which the 3 wire connection does not provide. If you see garbage, try a different speed. Interesting commands to try first in U-Boot are `+help+` and `+printenv+`. === TFTP 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. HINT: <>, a rudimentary TFTP server, is supplied with Liminix for development purposes. It may or may not fit your needs here. ==== Building and installing the image Follow the device-specific instructions for "TFTP install": usually, the steps are * build the [.title-ref]#outputs.mtdimage# output * copy `+result/firmware.bin+` to wherever your TFTP server serves files from * execute the commands listed in `+result/flash.scr+` at 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 else 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 soft-bricking the device when flashing a JFFS2 image. The current version _should_ work better but if you are reading this message then nobody has yet confirmed it If your device is running OpenWrt then it probably has the `+mtd+` command installed. Transfer `+result/firmware.bin+` onto the running device using e.g. `+scp+`. Now flash as follows: [source,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 https://openwrt.org/docs/guide-user/installation/sysupgrade.cli[OpenWrt manual] 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 then in general you cannot safely copy a new image over the top of the running system while it is running. If the running system was configured with <> you can use that to safely flash your new image. Otherwise you may attempt to use `+flashcp+` directly, but bust out the serial leads in preparation for it going horribly wrong.