Specific topics to be covered include the types and attributes of solid state media suitable for disk use in FreeBSD, kernel options that are of interest in such an environment, the [.filename]#rc.initdiskless# mechanisms that automate the initialization of such systems and the need for read-only filesystems, and building filesystems from scratch.
The article will conclude with some general strategies for small and read-only FreeBSD environments.
The scope of this article will be limited to solid state disk devices made from flash memory.
Flash memory is a solid state memory (no moving parts) that is non-volatile (the memory maintains data even after all power sources have been disconnected).
Flash memory can withstand tremendous physical shock and is reasonably fast (the flash memory solutions covered in this article are slightly slower than a EIDE hard disk for write operations, and much faster for read operations).
One very important aspect of flash memory, the ramifications of which will be discussed later in this article, is that each sector has a limited rewrite capacity.
You can only write, erase, and write again to a sector of flash memory a certain number of times before the sector becomes permanently unusable.
Although many flash memory products automatically map bad blocks, and although some even distribute write operations evenly throughout the unit, the fact remains that there exists a limit to the amount of writing that can be done to the device.
Competitive units have between 1,000,000 and 10,000,000 writes per sector in their specification.
This figure varies due to the temperature of the environment.
All embedded FreeBSD systems that use flash memory as system disk will be interested in memory disks and memory filesystems.
As a result of the limited number of writes that can be done to flash memory, the disk and the filesystems on the disk will most likely be mounted read-only.
In this environment, filesystems such as [.filename]#/tmp# and [.filename]#/var# are mounted as memory filesystems to allow the system to create logs and update counters and temporary files.
Memory filesystems are a critical component to a successful solid state FreeBSD implementation.
[.filename]#/etc/rc.d/var# mounts [.filename]#/var# as a memory filesystem, makes a configurable list of directories in [.filename]#/var# with the man:mkdir[1] command, and changes modes on some of those directories.
In the execution of [.filename]#/etc/rc.d/var#, one other [.filename]#rc.conf# variable comes into play - `varsize`.
A [.filename]#/var# partition is created by [.filename]#/etc/rc.d/var# based on the value of this variable in [.filename]#rc.conf#:
The fact that [.filename]#/var# is a read-write filesystem is an important distinction, as the [.filename]#/# partition (and any other partitions you may have on your flash media) should be mounted read-only.
Remember that in <<intro>> we detailed the limitations of flash memory - specifically the limited write capability.
The importance of not mounting filesystems on flash media read-write, and the importance of not using a swap file, cannot be overstated.
A swap file on a busy system can burn through a piece of flash media in less than one year.
Heavy logging or temporary file creation and destruction can do the same.
Therefore, in addition to removing the `swap` entry from your [.filename]#/etc/fstab#, you should also change the Options field for each filesystem to `ro` as follows:
A few applications in the average system will immediately begin to fail as a result of this change.
For instance, cron will not run properly as a result of missing cron tabs in the [.filename]#/var# created by [.filename]#/etc/rc.d/var#, and syslog and dhcp will encounter problems as well as a result of the read-only filesystem and missing items in the [.filename]#/var# that [.filename]#/etc/rc.d/var# has created.
These are only temporary problems though, and are addressed, along with solutions to the execution of other common software packages in <<strategies>>.
An important thing to remember is that a filesystem that was mounted read-only with [.filename]#/etc/fstab# can be made read-write at any time by issuing the command:
Since ATA compatible compact-flash cards are seen by FreeBSD as normal IDE hard drives, you could theoretically install FreeBSD from the network using the kern and mfsroot floppies or from a CD.
However, even a small installation of FreeBSD using normal installation procedures can produce a system in size of greater than 200 megabytes.
Most people will be using smaller flash memory devices (128 megabytes is considered fairly large - 32 or even 16 megabytes is common), so an installation using normal mechanisms is not possible-there is simply not enough disk space for even the smallest of conventional installations.
The easiest way to overcome this space limitation is to install FreeBSD using conventional means to a normal hard disk.
After the installation is complete, pare down the operating system to a size that will fit onto your flash media, then tar the entire filesystem.
The following steps will guide you through the process of preparing a piece of flash memory for your tarred filesystem.
Remember, because a normal installation is not being performed, operations such as partitioning, labeling, file-system creation, etc. need to be performed by hand.
In addition to the kern and mfsroot floppy disks, you will also need to use the fixit floppy.
Now that the machine is on the network, transfer your tar file.
You may be faced with a bit of a dilemma at this point - if your flash memory part is 128 megabytes, for instance, and your tar file is larger than 64 megabytes, you cannot have your tar file on the flash media at the same time as you explode it - you will run out of space.
One solution to this problem, if you are using FTP, is to untar the file while it is transferred over FTP.
If you perform your transfer in this manner, you will never have the tar file and the tar contents on your disk at the same time:
Assuming that you configured your filesystem correctly when it was built on the normal hard disk (with your filesystems mounted read-only, and with the necessary options compiled into the kernel) you should now be successfully booting your FreeBSD embedded system.
====
[[strategies]]
== System Strategies for Small and Read Only Environments
In <<ro-fs>>, it was pointed out that the [.filename]#/var# filesystem constructed by [.filename]#/etc/rc.d/var# and the presence of a read-only root filesystem causes problems with many common software packages used with FreeBSD.
In this article, suggestions for successfully running cron, syslog, ports installations, and the Apache web server will be provided.
Upon boot, [.filename]#/var# gets populated by [.filename]#/etc/rc.d/var# using the list from [.filename]#/etc/mtree/BSD.var.dist#, so the [.filename]#cron#, [.filename]#cron/tabs#, [.filename]#at#, and a few other standard directories get created.
However, this does not solve the problem of maintaining cron tabs across reboots.
When the system reboots, the [.filename]#/var# filesystem that is in memory will disappear and any cron tabs you may have had in it will also disappear.
Therefore, one solution would be to create cron tabs for the users that need them, mount your [.filename]#/# filesystem as read-write and copy those cron tabs to somewhere safe, like [.filename]#/etc/tabs#, then add a line to the end of [.filename]#/etc/rc.initdiskless# that copies those crontabs into [.filename]#/var/cron/tabs# after that directory has been created during system initialization.
You may also need to add a line that changes modes and permissions on the directories you create and the files you copy with [.filename]#/etc/rc.initdiskless#.
[.filename]#syslog.conf# specifies the locations of certain log files that exist in [.filename]#/var/log#.
These files are not created by [.filename]#/etc/rc.d/var# upon system initialization.
Therefore, somewhere in [.filename]#/etc/rc.d/var#, after the section that creates the directories in [.filename]#/var#, you will need to add something like this:
Before discussing the changes necessary to successfully use the ports tree, a reminder is necessary regarding the read-only nature of your filesystems on the flash media.
Since they are read-only, you will need to temporarily mount them read-write using the mount syntax shown in <<ro-fs>>.
You should always remount those filesystems read-only when you are done with any maintenance - unnecessary writes to the flash media could considerably shorten its lifespan.
To make it possible to enter a ports directory and successfully run `make install`, we must create a packages directory on a non-memory filesystem that will keep track of our packages across reboots.
As it is necessary to mount your filesystems as read-write for the installation of a package anyway, it is sensible to assume that an area on the flash media can also be used for package information to be written to.
Now, any time that you mount your filesystems as read-write and install a package, the `make install` will work, and package information will be written successfully to [.filename]#/etc/pkg# (because the filesystem will, at that time, be mounted read-write) which will always be available to the operating system as [.filename]#/var/db/pkg#.
It is now assumed that Apache keeps its log files in a directory [.filename]#apache_log_dir# outside of [.filename]#/var#.
When this directory lives on a read-only filesystem, Apache will not be able to save any log files, and may have problems working.
If so, it is necessary to add a new directory to the list of directories in [.filename]#/etc/rc.d/var# to create in [.filename]#/var#, and to link [.filename]#apache_log_dir# to [.filename]#/var/log/apache#.
It is also necessary to set permissions and ownership on this new directory.