You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
tbm-docs/user-doc/user-doc.tex

542 lines
24 KiB

\documentclass[twoside,a4paper]{article}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{booktabs}
\usepackage{enumitem}
\usepackage{fancyhdr}
\usepackage{float}
\usepackage{fontspec}
\usepackage{hyperref}
\usepackage[margin=2cm,includefoot,footskip=1.5cm]{geometry}
\usepackage{graphicx}
\usepackage{minted}
\usepackage{tikz}
\usepackage{url}
\usetikzlibrary{calc, shapes.misc}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}
%\setmainfont[BoldFont=OpenSans-Bold, ItalicFont=OpenSans-Italic, Ligatures=TeX]{OpenSans-Regular.ttf}
%\setsansfont[BoldFont=OpenSans-Bold, ItalicFont=OpenSans-Italic, Ligatures=TeX]{OpenSans-Regular.ttf}
\newfontfamily\Roboto[BoldFont=Roboto-Bold, Ligatures=TeX]{Roboto-Regular.ttf}
\setmainfont[BoldFont=Roboto-Bold, ItalicFont=Roboto-Italic, Ligatures=TeX]{Roboto-Regular.ttf}
\setsansfont[BoldFont=Roboto-Bold, ItalicFont=Roboto-Italic, Ligatures=TeX]{Roboto-Regular.ttf}
\definecolor{background}{RGB}{58,46,86}
\definecolor{border}{RGB}{234,211,186}
\patchcmd{\section}{\thispagestyle{plain}}{\thispagestyle{fancy}}{}{}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[C]{%
\begin{tikzpicture}[overlay, remember picture]%
\fill[border] (current page.north west) rectangle ($(current page.north east)+(0,-1.5cm)$);
\fill[background] (current page.north west) rectangle ($(current page.north east)+(0,-1.4cm)$);
\node[anchor=north west, text=white, font=\Large\Roboto, minimum size=1.4cm, inner xsep=5mm] at (current page.north west) {\textbf{white}box};
\end{tikzpicture}
}
\fancyfoot[LE,RO]{\thepage}
\newcommand\fancytitlecover {
\begin{tikzpicture}[remember picture, overlay, shorten >= -10pt]
\fill[border] (current page.north west) rectangle (current page.south east);
\fill[background] (current page.north west) rectangle ($(current page.south east)+(0,3mm)$);
\end{tikzpicture}
}
\makeatletter
\renewcommand*{\maketitle}{
\begin{titlepage}
\fancytitlecover
\color{white}
\begin{center}
\sffamily
\vspace*{3cm}
\huge \@title \\[1em]
{\Large\Roboto \textbf{white}box}
\vfill
%\large \@author \\[1em]
%\large \@date
\end{center}
\end{titlepage}
}
\makeatother
\makeatletter
\global\let\tikz@ensure@dollar@catcode=\relax
\makeatother
\begin{document}
\title{Trusted Boot Module \\[.5em]
\Large User Manual}
\author{}
\date{}
\maketitle
\tableofcontents
\newpage
\section{Introduction}
This document covers the installation and configuration of the \emph{Trusted Boot Module} (TBM) and the \emph{Read-Only Trusted System} (ROTS).
The TBM is an additional board that consists of a \emph{microcontroller unit} or MCU to manage the boot procedure of the host device in a secure fashion by managing keys, logs and other files related to trusted boot management.
Furthermore, the host device will be restricted to only boot from one read-only storage device that will contain a trusted image or the \emph{Read-Only Trusted System} (ROTS).
Once this image has been booted, the hosted device is in a trusted state from which it will be able to execute a minimal software stack to enumerate the images to boot, to verify these images and to select what image to boot.
Once the image has been booted, the host device will enter an untrusted stage and the TBM will only allow for restricted access.
This implementation allows the host device to only boot images that are trusted and prevents attackers from tampering with the host device or the TBM to boot untrusted images as long as they don't have physical access and as long as there are no vulnerabilities.
\begin{figure}[H]
\centering
\includegraphics[width=0.8\linewidth]{figures/tbm.pdf}
\caption{a high-level overview of the interaction between the host device and the Trusted Boot Module}
\label{fig:tbm-overview}
\end{figure}
Figure~\ref{fig:tbm-overview} shows a high-level overview of the design.
Once the device receives power the \emph{Trusted Boot Module} will boot and at some point the TBM will power on the host device.
The host device will then read the trusted image from the SPI NOR flash.
Because the device has been configured to be restricted to boot from the SPI NOR flash and because the SPI NOR flash has been configured to be read-only, the host device will be in a trusted state.
The image that has been booted is designed to be minimal and only contains the software necessary to perform the boot procedure.
Furthermore, the image does not contain a network stack to reduce the amount of possible vulnerabilities and thus to minimise the attack vector.
Once the trusted image has been booted, the host device will enumerate the images to boot and co-operate with the TBM to verify images and to select the image to boot.
This co-operation happens by means of serial communication with the TBM, where the TBM will grant access to the key storage to the ROTS.
Once an image has been selected to boot, the ROTS will inform the TBM that it will boot this image and enter the untrusted stage.
From there on the TBM will only allow for restricted access.
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{figures/tbm-lime.jpg}
\caption{the Trusted Boot Module}
\label{fig:tbm-lime}
\end{figure}
\section{Building ROTS}
\subsection{u-boot}
At the moment of writing, the mainline version of u-boot does not have support for SPI NOR flash on Allwinner SoCs such as the Allwinner A10, A20 and the A64.
A driver model compatible SPI driver for u-boot is has been worked on and the code can be found at \url{https://github.com/StephanvanSchaik/u-boot/tree/sunxi-spi}.
This driver has been tested on the following boards:
\begin{itemize}[noitemsep]
\item H2+ Orange Pi Zero with Macronix MX25L1605D 16 Mbit
\item A20 OLinuXino LIME 2 with Winbond W25Q128BV 128 Mbit
\item A64 Pine64+ with Winbond W25Q128BV 128 Mbit
\item A64 OLinuXino with Eon EN25Q64 64 Mbit
\end{itemize}
To compile u-boot with support for SPI NOR flash:
\begin{minted}[breaklines]{text}
git clone https://github.com/StephanvanSchaik/u-boot -b sunxi-spi
make clean
make A20-OLinuXino-Lime2_defconfig
CROSS_COMPILE=armv7a-hardfloat-linux-gnueabi- make
\end{minted}
After u-boot-sunxi-with-spl.bin has been built, we can put it on an SD card as follows to test it:
\begin{minted}[breaklines]{text}
dd if=u-boot-sunxi-with-spl.bin of=/dev/sda bs=1024 seek=8
\end{minted}
While U-boot also supports booting from SPI NOR flash, it has been disabled by default:
\begin{minted}[breaklines]{text}
make menuconfig
\end{minted}
Enable the {\tt CONFIG\_SPL\_SPI\_SUNXI} option.
It is possible that the resulting binary will be too large.
In that case, an option like {\tt CONFIG\_SPL\_MMC\_SUPPORT} can be disabled to save some space.
After the configuration options have been set up, rebuild the u-boot binary again.
\subsection{Linux kernel}
Make sure that the following options are enabled:
\begin{itemize}[noitemsep]
\item {\tt CONFIG\_BLK\_DEV\_INITRD}
\item {\tt CONFIG\_RD\_GZIP}
\item {\tt CONFIG\_RD\_BZIP2}
\item {\tt CONFIG\_RD\_LZMA}
\item {\tt CONFIG\_RD\_XZ}
\item {\tt CONFIG\_RD\_LZO}
\item {\tt CONFIG\_RD\_LZ4}
\item {\tt CONFIG\_KEXEC}
\end{itemize}
As the ROTS image will be read-only once it has been flashed to the SPI NOR flash, it is encouraged to build a minimal kernel images to reduce the amount of possible bugs and vulnerabilities.
More specifically, it is recommended to build a kernel without any support for networking, graphics and audio.
\subsection{initramfs}
For the initramfs, we will need static binaries of \emph{busybox}, \emph{kexec-tools}, \emph{cpio} and \emph{gzip}.
Run the following command to pack up the directory structure of the initramfs into a gzip compressed cpio archive:
\begin{minted}[breaklines]{text}
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
\end{minted}
Because u-boot expects the initramfs to be in the u-boot format, we also have to wrap it up in their format using \emph{mkimage}:
\begin{minted}[breaklines]{text}
mkimage -n 'Ramdisk Image' -A arm -O linux -T ramdisk -C gzip -d initramfs.cpio.gz initramfs.uImage
\end{minted}
\section{Flashing ROTS}
To write the ROTS image to the SPI NOR flash, we can either use an external programmer or boot the device in FEL mode and use the \emph{sunxi-fel} tool.
To write the images, it is strongly recommended to use the \emph{sunxi-fel} tool as it is much faster than using an external programmer.
However, to configure the write-protection an external programmer must be used, as there are few tools that support configuring the write-protection of the SPI NOR flash.
\subsection{Using an External Programmer}
In order to be able to program the SPI NOR flash with an external programmer, we will need an external programmer such as the BusPirate v3.6a or the BusPirate v4.0 and SOIC clip.
Figure~\ref{fig:winbond-pinout} illustrates the pin-out of a Winbond W25Q128.V SPI NOR flash, but any SPI NOR flash chip should be compatible with this pin-out.
The SPI NOR flash should have a circular shape at one of the corners, this corner should be bottom-right corner.
Once the pins of the SPI NOR flash are aligned with the pin-out in figure~\ref{fig:winbond-pinout}, we can clip the SPI NOR flash chip between the SOIC clip.
\begin{figure}[H]
\centering
\begin{tikzpicture}
% Draw the chip.
\node[draw=black,chamfered rectangle,align=center,fill=gray!10,minimum width=3.5cm,minimum height=3cm] (chip) {Winbond \\ W25Q128.V};
\node[draw=black,fill=gray!30,circle] at ($(chip.south west) + (.3,.3)$) {};
% Draw the pin-out at the bottom.
\path[draw] ($(chip.south)+(-1.2,0)$) -- ($(chip.south)+(-1.2,-.5)$) node[below] {CS};
\path[draw] ($(chip.south)+(-.4,0)$) -- ($(chip.south)+(-.4,-.5)$) node[below] {DO};
\path[draw] ($(chip.south)+(.4,0)$) -- ($(chip.south)+(.4,-.5)$) node[below] {\textbackslash WP};
\path[draw] ($(chip.south)+(1.2,0)$) -- ($(chip.south)+(1.2,-.5)$) node[below] {GND};
% Draw the pin-out at the top.
\path[draw] ($(chip.north)+(-1.2,0)$) -- ($(chip.north)+(-1.2,.5)$) node[above] {VCC};
\path[draw] ($(chip.north)+(-.4,0)$) -- ($(chip.north)+(-.4,.5)$) node[above] {H/R};
\path[draw] ($(chip.north)+(.4,0)$) -- ($(chip.north)+(.4,.5)$) node[above] {CLK};
\path[draw] ($(chip.north)+(1.2,0)$) -- ($(chip.north)+(1.2,.5)$) node[above] {DI};
\end{tikzpicture}
\caption{the pin-out of the Winbond W25Q128.V SPI NOR flash}
\label{fig:winbond-pinout}
\end{figure}
Figure~\ref{fig:bp36-connect} shows how to connect the BusPirate v3.6a with the SPI NOR flash chip.
Connect the \emph{Chip Select} (CS) pins using the white cable, the \emph{Master In Slave Out} (MISO) pin with the \emph{Data Out} (DO) pin using the black cable, the \emph{Master Out Slave In} (MOSI) pin with the \emph{Data In} (DI) pin using the grey cable and the \emph{Clock} (CLK) pins using the purple cable.
Further, the \emph{Ground} (GND) pins should be connected using the brown cable and the 5V and the VCC pins should be connected with the orange cable.
In order for the SPI NOR flash chip to function, the H/R pin of the SPI NOR flash chip should be pulled high, this can be done by connecting the 5V pin with the H/R pin.
Finally, to be able to program the chip in case write-protection has been configured before, we have to make sure that the \emph{Write-Protect} (WP) is pulled high to disable write-protection.
\begin{figure}[H]
\centering
\begin{tikzpicture}
% Draw the chip.
\node[draw=black,chamfered rectangle,align=center,fill=gray!10,minimum width=3.5cm,minimum height=3cm] (chip) {Winbond \\ W25Q128.V};
\node[draw=black,fill=gray!30,circle] at ($(chip.south west) + (.3,.3)$) {};
% Draw the pin-out at the bottom.
\path[line width=1.5mm,draw=black] ($(chip.south)+(-1.2,0)$) -- ($(chip.south)+(-1.2,-.7)$);
\path[line width=1.2mm,draw=white] ($(chip.south)+(-1.2,0)$) -- ($(chip.south)+(-1.2,-.7)$) node[below] {CS};
\path[line width=1.5mm,draw=black] ($(chip.south)+(-.4,0)$) -- ($(chip.south)+(-.4,-.7)$);
\path[line width=1.2mm,draw=black] ($(chip.south)+(-.4,0)$) -- ($(chip.south)+(-.4,-.7)$) node[below] {MISO};
\path[line width=1.5mm,draw=black] ($(chip.south)+(.4,0)$) -- ($(chip.south)+(.4,-.7)$);
\path[line width=1.2mm,draw=orange] ($(chip.south)+(.4,0)$) -- ($(chip.south)+(.4,-.7)$) node[below] {\textbackslash WP};
\path[line width=1.5mm,draw=black] ($(chip.south)+(1.2,0)$) -- ($(chip.south)+(1.2,-.7)$);
\path[line width=1.2mm,draw=brown] ($(chip.south)+(1.2,0)$) -- ($(chip.south)+(1.2,-.7)$) node[below] {GND};
% Draw the pin-out at the top.
\path[line width=1.5mm,draw=black] ($(chip.north)+(-1.2,0)$) -- ($(chip.north)+(-1.2,.7)$);
\path[line width=1.2mm,draw=orange] ($(chip.north)+(-1.2,0)$) -- ($(chip.north)+(-1.2,.7)$) node[above] {VCC};
\path[line width=1.5mm,draw=black] ($(chip.north)+(-.4,0)$) -- ($(chip.north)+(-.4,.7)$);
\path[line width=1.2mm,draw=orange] ($(chip.north)+(-.4,0)$) -- ($(chip.north)+(-.4,.7)$) node[above] {H/R};
\path[line width=1.5mm,draw=black] ($(chip.north)+(.4,0)$) -- ($(chip.north)+(.4,.7)$);
\path[line width=1.2mm,draw=purple] ($(chip.north)+(.4,0)$) -- ($(chip.north)+(.4,.7)$) node[above] {CLK};
\path[line width=1.5mm,draw=black] ($(chip.north)+(1.2,0)$) -- ($(chip.north)+(1.2,.7)$);
\path[line width=1.2mm,draw=gray] ($(chip.north)+(1.2,0)$) -- ($(chip.north)+(1.2,.7)$) node[above] {MOSI};
\end{tikzpicture}
\caption{connecting the BusPirate v3.6a with the SPI NOR Flash}
\label{fig:bp36-connect}
\end{figure}
Because the configuration of write-protection is vendor-specific, the mainline version of \emph{flashrom} does not support configuring write-protection.
Therefore, to be able to configure the write-protection of the SPI NOR flash chip, we have to use Google's fork of \emph{flashrom}.
Unlike the mainline version of flashrom, Google's fork has two flags to get the name and the
size of the Flash chip:
\begin{minted}[breaklines]{text}
./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --flash-name
flashrom v0.9.4 : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
vendor="Macronix" name="MX25L6406E"
./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --get-size
flashrom v0.9.4 : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
16777216
\end{minted}
Further, Google's fork of flashrom allows us to tag regions on the SPI NOR flash chip with a custom name.
Assuming that the SPI NOR flash chip is 16 MiB, we will be using the following \path{layout.txt} file for the ROTS:
\begin{minted}[breaklines]{text}
000000:09ffff uboot
0a0000:5fffff linux
600000:ffffff initramfs
\end{minted}
We can then write \path{u-boot.bin}, \path{bzImage} and \path{initramfs.cpio.gz} to the SPI NOR flash chip by using the respective names of the regions.
To speed up the process of writing these images, we have to disable parsing the fmap and the verification of unmodified regions.
Furthermore, to maintain an optimal stability, an SPI speed of no more than 2 MHz is recommended when using the BusPirate v3.6a:
\begin{minted}[breaklines]{text}
./flashrom --programmer=buspirate_spi:spispeed=2M,dev=/dev/buspirate -l layout.txt -i uboot:u-boot.bin linux:bzImage initramfs:initramfs.cpio.gz -w --ignore-fmap --fast-verify
\end{minted}
Now that the images have been written to their respective regions, we can look at the write-protect ranges supported by the chip:
\begin{minted}[breaklines]{text}
./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --wp-list
flashrom v0.9.4 : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
Valid write protection ranges:
start: 0x000000, length: 0x000000
start: 0xfc0000, length: 0x040000
start: 0xf80000, length: 0x080000
start: 0xf00000, length: 0x100000
start: 0xe00000, length: 0x200000
start: 0xc00000, length: 0x400000
start: 0x800000, length: 0x800000
start: 0x000000, length: 0x040000
start: 0x000000, length: 0x080000
start: 0x000000, length: 0x100000
start: 0x000000, length: 0x200000
start: 0x000000, length: 0x400000
start: 0x000000, length: 0x800000
start: 0x000000, length: 0x1000000
start: 0xfff000, length: 0x001000
start: 0xffe000, length: 0x002000
start: 0xffc000, length: 0x004000
start: 0xff8000, length: 0x008000
start: 0xff8000, length: 0x008000
start: 0x000000, length: 0x001000
start: 0x000000, length: 0x002000
start: 0x000000, length: 0x004000
start: 0x000000, length: 0x008000
start: 0x000000, length: 0x008000
\end{minted}
Since we don't want our images to be tampered with, we want to enable write-protection for the full range.
We can configure the write-protected range as follows:
\begin{minted}[breaklines]{text}
./flashrom --programmer=buspirate_spi:spispeed=2M,dev=/dev/buspirate --wp-range 0x000000 0x1000000
\end{minted}
After setting the range, we are still able to modify the contents of the entire SPI NOR flash chip.
To protect the range, we have to enable write protection as follows:
\begin{minted}[breaklines]{text}
./flashrom --programmer=buspirate_spi:spispeed=2M,dev=/dev/buspirate --wp-enable
\end{minted}
Upon enabling write-protection, the \emph{Write-Protect} (WP) pin has to be pulled low for the write-protection to be effective.
This prevents the user from disabling the write-protection feature, changing the write-protect range and from writing to the write-protected region.
\subsection{Using sunxi-fel}
Download and compile the \emph{sunxi-fel} tool as follows:
\begin{minted}[breaklines]{text}
git clone -b spiflash-a20-test https://github.com/ssvb/sunxi-tools.git
make
\end{minted}
Connect or reset while holding the recovery or FEL button.
Once the board has booted into FEL mode, we can detect the SPI NOR flash chip as follows:
\begin{minted}[breaklines]{text}
./sunxi-fel spiflash-info
Manufacturer: Winbond (EFh), model: 40h, size: 16777216 bytes.
\end{minted}
Then we can write the \path{u-boot.bin}, \path{bzImage} and \path{initramfs.uImage} images as follows:
\begin{minted}[breaklines]{text}
./sunxi-fel -p spiflash-write 0x000000 u-boot.bin
./sunxi-fel -p spiflash-write 0x0a0000 bzImage
./sunxi-fel -p spiflash-write 0x600000 initramfs.uImage
\end{minted}
\section{Booting ROTS}
After powering up the board, \emph{u-boot} will be loaded.
\emph{u-boot} will then load the Linux kernel image and the initramfs from the SPI NOR flash and boot the Linux kernel with the initramfs as follows:
\begin{minted}[breaklines]{text}
sf probe 0:0 6000000
sf read 0x42000000 0xa0000 5636096
sf read 0x43000000 0x600000 10485760
bootm 0x42000000 0x43000000
\end{minted}
The ROTS kernel will now boot up and mount the initramfs as the rootfs.
At some point the kernel will run the init script in the initramfs.
When this happens the ROTS will start communicating with the TBM to fetch the time as well as the certificates.
Once these have been retrieved from the TBM, the ROTS will mount the external media such as hard disks and enumerate and verify possible boot images on those media.
\section{Trusted Boot Module}
In this section the process of building, flashing and configuring the firmware for the TBM is described.
\subsection{Building}
A cross-compiler targetting ARMv6 or ARMv7-M such as the GNU ARM Embedded Toolchain is required to build the source code for the Trusted Boot Module.
Either install it using your package manager or download the toolchain from https://developer.arm.com/open-source/gnu-toolchain/gnu-rm.
For Gentoo users, an ebuild is available in the tbm-overlay repository.
Building your own cross-compiler using a tool like crossdev can be quite tricky, and is therefore discouraged.
To build the source code in this repository, you will also need libopencm3.
Download the source code for libopencm3 and build it as follows:
\begin{minted}[breaklines]{text}
git submodule init
git submodule update
make -C libopencm3
\end{minted}
To build the code for the Trusted Boot Module, run:
\begin{minted}[breaklines]{text}
TARGET=stm32f1 make
\end{minted}
\subsection{Flashing}
Connect your computer with a JTAG device and connect the I/O, CLK, GND and VDD wires with the SWD pin-out of the TBM.
Run the following as root:
\begin{minted}[breaklines]{text}
TARGET=stm32f1 make openocd
\end{minted}
If OpenOCD, the JTAG device and the TBM are functioning correctly, OpenOCD should report the available breakpoint registers.
To flash the firmware onto the device, run the following command:
\begin{minted}[breaklines]{text}
TARGET=stm32f1 make run
\end{minted}
Close OpenOCD and disconnect the power from the TBM, then detach the I/O and CLK wires.
\subsection{Configuration}
Download the source code for gorots and build the admin utility as follows:
\begin{minted}[breaklines]{text}
go build
\end{minted}
Attach a serial cable to the debugging serial interface of the TBM.
Power on the TBM using an external power source such as a JTAG adapter.
Run the {\tt prepare.sh} script to perform an initial configuration of the TBM.
This script will also perform tests to ensure the hardware is functioning as expected.
\section{Using gorots}
The gorots package consists of two tools: {\tt admin} and {\tt protocol}.
The {\tt protocol} utility is used by the ROTS to communicate with the user serial interface.
The {\tt admin} utility is used with the admin serial interface of the TBM to configure it.
The following commands are available for the {\tt admin} utility:
\begin{itemize}
\item {\tt ./admin echo <string>}
Returns the string passed as an argument to echo.
\item {\tt ./admin flash\_probe}
Mounts the SPI NOR flash device as a raw device.
\item {\tt ./admin flash\_erase <offset> <length>}
Erases the region provided by the offset and the length in blocks.
\item {\tt ./admin ftl\_probe}
Mounts the SPI NOR flash device and initialises the Flash Translation Layer.
\item {\tt ./admin date}
Returns the current time formatted as a human-readable date.
\item {\tt ./admin time}
Returns the current time in seconds since the UNIX epoch.
\item {\tt ./admin set-time <seconds>}
Sets the current time to the given time in seconds since the UNIX epoch.
\item {\tt ./admin sync-time }
Synchronizes the current time of the TBM with the current time of the host device
\item {\tt ./admin set-time <seconds>}
Sets the current time to the given time in seconds since the UNIX epoch.
\item {\tt ./admin sync-time }
Synchronizes the current time of the TBM with the current time of the host device.
\item {\tt ./admin mount }
Mounts the filesystem on the flash device.
\item {\tt ./admin umount}
Unmounts the currently mounted filesystem.
\item {\tt ./admin format}
Formats the filesystem of the flash device.
\item {\tt ./admin mkdir <path>}
Creates a directory at the given path, if the path does not yet exist and if the parent is a directory.
\item {\tt ./admin rmdir <path>}
Removes the directory at the given path, if the path exists and points to a directory.
\item {\tt ./admin ls <path>}
Lists the files in the given path, if the path exists and points to a directory.
\item {\tt ./admin cat <path>}
Concatenates the file with the standard output.
\item {\tt ./admin write <path> <file>}
Writes the contents of the file to the file at the given path. Creates a new file if the path does not point to an existing file. Otherwise the file will be truncated first.
\item {\tt ./admin append <path> <file>}
Appends the contents of the file to the file at the given path. Creates a new file if the path does not point to an existing file.
\item {\tt ./admin mv <old> <new>}
Moves the file or directory from the old path to the new path.
\item {\tt ./admin cp <old> <new>}
Copies the contents of the file from the old path to the file pointed to by the new path. Creates a file at the new path if it does not exist yet. Otherwise the file is truncated before copying the contents.
\item {\tt ./admin rm <path>}
Removes the file at the given path, if the path exists and points to a file.
\end{itemize}
\end{document}