Kernel Config

Serge Vakulenko edited this page Jul 9, 2015 · 10 revisions

Building LiteBSD Kernels with Config

The document is based on article "Building 4.4BSD Kernels with Config" by Samuel J. Leffler and Michael J. Karels, with modifications relevant to LiteBSD operating system and target PIC32 platform.

Abstract

This document describes the use of config(8) to configure and create LiteBSD kernel images. It discusses the structure of kernel configuration files and how to configure systems with non-standard hardware configurations. Sections describing the preferred way to add new code to the kernel and how the system’s autoconfiguration process operates are included. An appendix contains a summary of the rules used by the kernel in calculating the size of system data structures, and also indicates some of the standard kernel size limitations (and how to change them). Other configuration options are also listed.

Revised June 4, 2015

1. Introduction

Config is a tool used in building LiteBSD system images (the UNIX kernel). It takes a file describing a kernel’s tunable parameters and hardware support, and generates a collection of files which are then used to build a copy of UNIX appropriate to that configuration. Config simplifies kernel maintenance by isolating system dependencies in a single, easy to understand, file.

This document describes the content and format of kernel configuration files and the rules which must be followed when creating these files. Example configuration files are constructed and discussed.

Later sections suggest guidelines to be used in modifying kernel source and explain some of the inner workings of the autoconfiguration process. Appendix C summarizes the rules used in calculating the most important kernel data structures and indicates some inherent kernel data structure size limitations (and how to go about modifying them).

2. Configuration File Contents

A kernel configuration must include at least the following pieces of information:

  • machine type
  • cpu type
  • system identification
  • timezone
  • maximum number of users
  • location of the root file system
  • available hardware

Config allows multiple kernel images to be generated from a single configuration description. Each kernel image is configured for identical hardware, but may have different locations for the root file system and, possibly, other system devices.

2.1. Machine type

The machine type indicates if the system is going to operate on a PIC32 microcontroller, or some other platform on which LiteBSD operates. The machine type is used to locate certain data files which are platform specific, and also to select rules used in constructing the resultant configuration files.

2.2. Cpu type

The cpu type indicates which, of possibly many, cpu’s the kernel is to operate on. For example, if the system is being configured as a PIC32, it could be running on a PIC32MZ, or other variants (not yet). Specifying more than one cpu type implies that the system should be configured to run on any of the cpu’s specified. For some types of machines this is not possible and config will print a diagnostic indicating such.

2.3. System identification

The system identification is a moniker attached to the system, and often identifies the board type, on which the system is to run. For example, for PIC32MZ we have boards SDZL, MEBII, WIFIRE, and so on. The system identifier selected is used to create a global C "#define" which may be used to isolate board dependent pieces of code in the kernel.

The system identifier "GENERIC" is given to a system which will run on any cpu of a particular machine type; it should not otherwise be used for a system identifier.

2.4. Timezone

The timezone in which the system is to run is used to define the information returned by the gettimeofday(2) system call. This value is specified as the number of hours east or west of GMT. Negative numbers indicate a value east of GMT. The timezone specification may also indicate the type of daylight savings time rules to be applied.

2.5. Maximum number of users

The kernel allocates many system data structures at boot time based on the maximum number of users the system will support. This number is normally between 8 and 40, depending on the hardware and expected job mix. The rules used to calculate kernel data structures are discussed in Appendix C.

2.6. Root file system location

When the kernel boots it must know the location of the root of the file system tree. This location and the part(s) of the disk(s) to be used for paging and swapping must be specified in order to create a complete configuration description. Config uses many rules to calculate default locations for these items; these are described in Appendix B.

When a generic system is configured, the root file system is left undefined until the system is booted. In this case, the root file system need not be specified, only that the system is a generic system.

2.7. Hardware devices

When the kernel boots it goes through an autoconfiguration phase. During this period, the kernel searches for all those hardware devices which the system builder has indicated might be present. This probing sequence requires certain pieces of information such as register addresses, bus interconnects, etc. A system’s hardware may be configured in a very flexible manner or be specified without any flexibility whatsoever. Most people do not configure hardware devices into the kernel unless they are currently present on the machine, expect them to be present in the near future, or are simply guarding against a hardware failure somewhere else at the site (it is often wise to configure in extra disks in case an emergency requires moving one off a machine which has hardware problems).

The specification of hardware devices usually occupies the majority of the configuration file. As such, a large portion of this document will be spent understanding it. Section 6.3 contains a description of the autoconfiguration process, as it applies to those planning to write, or modify existing, device drivers.

2.8. Pseudo devices

Several kernel facilities are configured in a manner like that used for hardware devices although they are not associated with specific hardware. These system options are configured as pseudo-devices. Some pseudo devices allow an optional parameter that sets the limit on the number of instances of the device that are active simultaneously.

2.9. System options

Other than the mandatory pieces of information described above, it is also possible to include various optional kernel facilities or to modify system behavior and/or limits. Optional support is provided for disk quotas and tracing the performance of the virtual memory subsystem. Any optional facilities to be configured into the kernel are specified in the configuration file. The resultant files generated by config will automatically include the necessary pieces of the system.

3. System Building Process

In this section we consider the steps necessary to build a bootable kernel image. We assume the kernel source is located in the "$BSDSRC/sys" directory and that, initially, the system is being configured from source code.

Under normal circumstances there are 5 steps in building a kernel.

  • Create a configuration file for the kernel.
  • Make a directory for the kernel to be constructed in.
  • Run config on the configuration file to generate the files required to compile and load the kernel image.
  • Construct the source code interdependency rules for the configured kernel with makedepend using make(1).
  • Compile and load the kernel with make.

Steps 1 and 2 are usually done only once. When a kernel configuration changes it usually suffices to just run config on the modified configuration file, rebuild the source code dependencies, and remake the kernel. Sometimes, however, configuration dependencies may not be noticed in which case it is necessary to clean out the relocatable object files saved in the kernel’s directory; this will be discussed later.

3.1. Creating a configuration file

Configuration files normally reside in the machine-dependent directory like "$BSDSRC/sys/mips/conf". A configuration file is most easily constructed by copying an existing configuration file and modifying it. The LiteBSD distribution contains a number of configuration files for well known boards; one may be suitable for you, or a copy of the generic configuration file may be edited.

The configuration file must have the same name as the directory in which the configured kernel is to be built. Further, config assumes this directory is located in the parent directory of the directory in which it is run. For example, the generic system has a configuration file "sys/mips/conf/GENERIC" and an accompanying directory named "sys/compile/GENERIC". Although it is not required that the kernel sources and configuration files reside in "sys", the configuration and compilation procedure depends on the relative locations of directories within that hierarchy, as most of the system code and the files created by config use pathnames of the form "../". If the system files are not located in "$BSDSRC/sys", it is desirable to make a symbolic link there for use in installation of other parts of the system that share files with the kernel.

When building the configuration file, be sure to include the items described in section 2. In particular, the machine type, cpu type, timezone, system identifier, maximum users, and root device must be specified. The specification of the hardware present may take a bit of work; particularly if your hardware is configured at non-standard places (e.g. device registers located at funny places or devices not supported by the system). Section 4 of this document gives a detailed description of the configuration file syntax, section 5 explains some sample configuration files, and section 6 discusses how to add new devices to the kernel. If the devices to be configured are not already described in one of the existing configuration files you should check the manual pages in section 4 of the UNIX Programmers Manual. For each supported device, the manual page synopsis entry gives a sample configuration line.

Once the configuration file is complete, run it through config and look for any errors. Never try and use a kernel which config has complained about; the results are unpredictable. For the most part, config’s error diagnostics are self explanatory. It may be the case that the line numbers given with the error messages are off by one.

A successful run of config on your configuration file will generate a number of files in the configuration directory. These files are:

  • A file to be used by make(1) in compiling and loading the kernel, Makefile.
  • One file for each possible kernel image for this machine, swapxxx.c, where xxx is the name of the kernel image, which describes where swapping, the root file system, and other miscellaneous system devices are located.
  • A collection of header files, one per possible device the system supports, which define the hardware configured.
  • A file containing the I/O configuration tables used by the kernel during its autoconfiguration phase, ioconf.c.
  • An assembly language file of interrupt vectors which connect interrupts from the machine’s external buses to the main system path for handling interrupts, and a file that contains counters and names for the interrupt vectors.

Unless you have reason to doubt config, or are curious how the kernel’s autoconfiguration scheme works, you should never have to look at any of these files.

3.2. Constructing source code dependencies

When config is done generating the files needed to compile and link your kernel it will terminate with a message of the form "Don’t forget to run make depend". This is a reminder that you should change over to the configuration directory for the kernel just configured and type "make depend" to build the rules used by make to recognize interdependencies in the system source code. This will insure that any changes to a piece of the system source code will result in the proper modules being recompiled the next time make is run.

This step is particularly important if your site makes changes to the system include files. The rules generated specify which source code files are dependent on which include files. Without these rules, make will not recognize when it must rebuild modules due to the modification of a system header file. The dependency rules are generated by a pass of the C preprocessor and reflect the global system options. This step must be repeated when the configuration file is changed and config is used to regenerate the system makefile.

3.3. Building the kernel

The makefile constructed by config should allow a new kernel to be rebuilt by simply typing "make image-name". For example, if you have named your bootable kernel image "vmunix", then "make vmunix" will generate a bootable image named "vmunix". Alternate kernel image names are used when the root file system location and/or swapping configuration is done in more than one way. The makefile which config creates has entry points for each kernel image defined in the configuration file. Thus, if you have configured "vmunix" to be a kernel with the root file system on an "sd" device and "hkvmunix" to be a kernel with the root file system on an "hk" device, then "make vmunix hkvmunix" will generate binary images for each.

Note that the name of a bootable image is different from the system identifier. All bootable images are configured for the same system; only the information about the root file system and paging devices differ. (This is described in more detail in section 4.)

4. Configuration File Syntax

In this section we consider the specific rules used in writing a configuration file. A complete grammar for the input language can be found in Appendix A and may be of use if you should have problems with syntax errors.

A configuration file is broken up into three logical pieces:

  • configuration parameters global to all kernel images specified in the configuration file,
  • parameters specific to each kernel image to be generated, and
  • device specifications.

4.1. Global configuration parameters

The global configuration parameters are the type of machine, cpu types, options, timezone, system identifier, and maximum users. Each is specified with a separate line in the configuration file.

  • machine "type"

The kernel is to run on the machine type specified. No more than one machine type can appear in the configuration file. Currently the only legal value is pic32. Other variants are outdated (like vax, tahoe, hp300, i386, mips, pmax, luna68k and news3400).

  • cpu "mtype"

This kernel is to run on the cpu type specified. More than one cpu type specification can appear in a configuration file. Legal type for a pic32 machine is PIC32MZ.

  • options optionlist

Compile the listed optional code into the kernel. Options in this list are separated by commas. Possible options are listed at the top of the generic makefile. A line of the form "options FUNNY,HAHA" generates global "#define"s −DFUNNY −DHAHA in the resultant makefile. An option may be given a value by following its name with "=", then the value enclosed in (double) quotes. The following are major options are currently in use: INET (Internet communication protocols), and QUOTA (enable disk quotas). Other kernel options controlling system sizes and limits are listed in Appendix C; options for the network are found in Appendix D. There are additional options which are associated with certain peripheral devices; those are listed in the Synopsis section of the manual page for the device.

  • makeoptions optionlist

Options that are used within the kernel makefile and evaluated by make are listed as makeoptions. Options are listed with their values with the form "makeoptions name=value,name2=value2". The values must be enclosed in double quotes if they include numerals or begin with a dash.

  • timezone number [ dst [ number ] ]

Specifies the timezone used by the system. This is measured in the number of hours your timezone is west of GMT. EST is 5 hours west of GMT, PST is 8. Negative numbers indicate hours east of GMT. If you specify dst, the system will operate under daylight savings time. An optional integer or floating point number may be included to specify a particular daylight saving time correction algorithm; the default value is 1, indicating the United States. Other values are: 2 (Australian style), 3 (Western European), 4 (Middle European), and 5 (Eastern European). See gettimeofday(2) and ctime(3) for more information.

  • ident name

This system is to be known as name. This is usually a short name like WIFIRE (for chipKIT Wi-Fire board) or MEBII (for Microchip Multimedia Expansion Board II). This value is defined for use in conditional compilation, and is also used to locate an optional list of source files specific to this system.

  • maxusers number

The maximum expected number of simultaneously active users on this system is number. This number is used to size several kernel data structures.

4.2. Kernel image parameters

Multiple bootable images may be specified in a single configuration file. The kernels will have the same global configuration parameters and devices, but the location of the root file system and other system specific devices may be different. A kernel image is specified with a "config" line:

config sysname config-clauses

The sysname field is the name given to the loaded kernel image; almost everyone names their standard kernel image "vmunix". The configuration clauses are one or more specifications indicating where the root file system is located and the number and location of paging devices.

A configuration clause is one of the following

root [ on ] root-device
swap [ on ] swap-device [ and swap-device ] ...
dumps [ on ] dump-device

(the "on" is optional.) Multiple configuration clauses are separated by white space; config allows specifications to be continued across multiple lines by beginning the continuation line with a tab character. The "root" clause specifies where the root file system is located, the "swap" clause indicates swapping and paging area(s), and the "dumps" clause can be used to force kernel dumps to be taken on a particular device.

The device names supplied in the clauses may be fully specified as a device, unit, and file system partition; or underspecified in which case config will use builtin rules to select default unit numbers and file system partitions.

The defaulting rules are a bit complicated as they are dependent on the overall kernel configuration. For example, the swap area need not be specified at all if the root device is specified; in this case the swap area is placed in the "b" partition of the same disk where the root file system is located. Appendix B contains a complete list of the defaulting rules used in selecting kernel configuration devices.

The device names are translated to the appropriate major and minor device numbers on a per-machine basis. A file like "$BSDSRC/sys/mips/conf/devices.machine" (where "machine" is the machine type specified in the configuration file) is used to map a device name to its major block device number. The minor device number is calculated using the standard disk partitioning rules: on unit 0, while drive is minor device 0, partition "a" is minor device 1, partition "b" is minor device 2, and so on; for units other than 0, add 8 times the unit number to get the minor device.

If the default mapping of device name to major/minor device number is incorrect for your configuration, it can be replaced by an explicit specification of the major/minor device. This is done by substituting

major x minor y

where the device name would normally be found. For example,

config vmunix root on major 99 minor 1

Normally, the areas configured for swap space are sized by the kernel at boot time. If a non-standard size is to be used for one or more swap areas (less than the full partition), this can also be specified. To do this, the device name specified for a swap area should have a "size" specification appended. For example,

config vmunix root on sd0 swap on sd0b size 1200

would force swapping to be done in partition "b" of "sd0" and the swap partition size would be set to 1200 sectors. A swap area sized larger than the associated disk partition is trimmed to the partition size.

To create a generic configuration, only the clause "swap generic" should be specified; any extra clauses will cause an error.

4.3. Device specifications

Each device attached to a machine must be specified to config so that the kernel generated will know to probe for it during the autoconfiguration process carried out at boot time. Hardware specified in the configuration need not actually be present on the machine where the generated kernel is to be run. Only the hardware actually found at boot time will be used by the system.

A device specification takes one of the following forms:

controller device-name device-info [ interrupt-spec ]
device device-name device-info interrupt-spec
disk device-name device-info

A "controller" is typically an SPI or I2C bus port. A "device" is an autonomous device which connects directly to the processor (as opposed to something like SPI devices which connects through an SPI controller). "Disk" identify disk drives like SD cards connected to SPI "controller".

The device-name is one of the standard device names, as indicated in section 4 of the UNIX Programmers Manual, concatenated with the logical unit number to be assigned the device (the logical unit number may be different than the physical unit number indicated on the front of something like a disk; the logical unit number is used to refer to the UNIX device, not the physical unit number). For example, "sd0" is logical unit 0 of a storage device.

The device-info clause specifies how the hardware is connected in the interconnection hierarchy. On the PIC32, SD cards and Wi-Fi controllers are connected through SPI ports. Thus, one of the following specifications would be used:

disk    sd0     at spi2     drive 0 flags 0x79
device  mrf0    at spi3     flags 0x71641f49

Certain device drivers require extra information passed to them at boot time to tailor their operation to the actual hardware present. The line printer driver, for example, needs to know how many columns are present on each non-standard line printer (i.e. a line printer with other than 80 columns). The drivers for the terminal multiplexors need to know which lines are attached to modem lines so that no one will be allowed to use them unless a connection is present. For this reason, one last parameter may be specified to a device, a flags field. It has the syntax

flags number

and is usually placed after other specifications. The number is passed directly to the associated driver. The manual pages in section 4 should be consulted to determine how each driver uses this value (if at all). Communications interface drivers commonly use the flags to indicate whether modem control signals are in use.

The exact syntax for each specific device is given in the Synopsis section of its manual page in section 4 of the manual.

4.4. Pseudo-devices

A number of drivers and software subsystems are treated like device drivers without any associated hardware. To include any of these pieces, a "pseudo-device" specification must be used. A specification for a pseudo device takes the form

pseudo-device device-name [ howmany ]

Examples of pseudo devices are pty, the pseudo terminal driver (where the optional howmany value indicates the number of pseudo terminals to configure, 32 default), and loop, the software loopback network pseudo-interface. Other pseudo devices for the network include imp (required when a CSS or ACC imp is configured) and ether (used by the Address Resolution Protocol on 10 Mb/sec Ethernets). More information on configuring each of these can also be found in section 4 of the manual.

5. Sample Configuration Files

In this section we will consider how to configure a sample PIC32MZ system for SDZL board. We then study the rules needed to configure a PIC32MZ to run in a networking environment.

5.1. PIC32MZ System

Our PIC32MZ kernel is configured with hardware peripherals avalable on SDZL board. Table 1 lists the pertinent hardware to be configured.

Table 1. PIC32MZ Hardware support.

Item Connection Name
UART port 1 cpu uart1
UART port 2 cpu uart2
SPI port 1 cpu spi1
SPI port 2 cpu spi2
SPI port 3 cpu spi3
SPI port 4 cpu spi4
microSD card spi2 sd0

We will call this machine SDZL and construct a configuration file one step at a time.

The first step is to fill in the global configuration parameters. The target is a PIC32MZ microcontroller, so the machine type is "pic32". We will assume this kernel will run only on this one processor, so the cpu type is "PIC32MZ". The options are empty since this is going to be a "vanilla" PIC32. The system identifier, as mentioned before, is "SDZL", and the maximum number of users we plan to support is about 40. Thus the beginning of the configuration file looks like this:

#
# SDZL board
#
machine     "pic32"
cpu         "PIC32MZ"
timezone    8 dst
ident       SDZL
maxusers    2

To this we must then add the specification for the kernel image. It will be our standard kernel with the root on "sd0" and swapping on the same drive as the root.

config      vmunix  root on sd0

Finally, the hardware must be specified. Let us first just try transcribing the information from Table 1.

device      uart1   flags 0x4243                # pins rx=RD2,   tx=RD3
device      uart2   flags 0x2726                # pins rx=RB7,   tx=RB6
controller  spi1    flags 0x6160                # pins sdi=RF1,  sdo=RF0
controller  spi2    flags 0x7778                # pins sdi=RG7,  sdo=RG8
controller  spi3    flags 0x2923                # pins sdi=RB9,  sdo=RB3
controller  spi4    flags 0x4b40                # pins sdi=RD11, sdo=RD0
disk        sd0     at spi2 drive 0 flags 0x79  # select pin RG9

The completed configuration file for SDZL is available here: SDZL.pic32.

5.2. PIC32MZ with network support

Our PIC32MZ system will work on MEB-II board connected to 100Mb/s Ethernet local area network. First the global parameters:

#
# Microchip Multimedia Expansion Board II
#
machine     "pic32"
cpu         "PIC32MZ"
ident       MEBII
timezone    8 dst
maxusers    2
options     INET

The value of 2 given for the maximum number of users is done to keep the kernel data structures compact. The "INET" indicates that we plan to use the standard Internet protocols on this machine.

The kernel image, serial ports and disks are configured next.

config      vmunix  root on sd0

device      uart1   flags 0x1e1f                # pins rx=RA14,  tx=RA15
controller  spi1    flags 0x4e2a                # pins sdi=RD14, sdo=RB10
controller  spi2    flags 0x4778                # pins sdi=RD7,  sdo=RG8
controller  spi4    flags 0x7723                # pins sdi=RG7,  sdo=RB3
disk        sd0     at spi2 drive 0 flags 0x2e  # select pin RB14

Finally, we add in the network devices. Pseudo terminals are needed to allow users to log in across the network (remember the only hardwired terminal is the console). The software loopback device is used for on-machine communications. And, finally, there are the two Ethernet devices. These use a special protocol, the Address Resolution Protocol (ARP), to map between Internet and Ethernet addresses. Thus, yet another pseudo-device is needed. The additional device specifications are show below.

pseudo-device   pty     4
pseudo-device   loop
pseudo-device   ether
controller      en0

The completed configuration file for MEB-II is available here: MEBII.pic32.

6. Adding New System Software

This section is not for the novice, it describes some of the inner workings of the configuration process as well as the pertinent parts of the system autoconfiguration process. It is intended to give those people who intend to install new device drivers and/or other kernel facilities sufficient information to do so in the manner which will allow others to easily share the changes.

This section is broken into four parts:

  • general guidelines to be followed in modifying kernel code,
  • how to add non-standard kernel facilities to LiteBSD,
  • how to add a device driver to LiteBSD, and

6.1. Modifying kernel code

If you wish to make site-specific modifications to the system it is best to bracket them with

#ifdef SITENAME
...
#endif

to allow your source to be easily distributed to others, and also to simplify diff(1) listings. If you choose not to use a source code control system (e.g. SCCS, RCS), and perhaps even if you do, it is recommended that you save the old code with something of the form:

#ifndef SITENAME
...
#endif

We try to isolate our site-dependent code in individual files which may be configured with pseudo-device specifications.

Indicate machine-specific code with "#ifdef PIC32MZ" (or other machine, as appropriate). LiteBSD underwent extensive work to make it extremely portable to machines with similar architectures − you may someday find yourself trying to use a single copy of the source code on multiple machines.

6.2. Adding non-standard kernel facilities

This section considers the work needed to augment config’s data base files for non-standard kernel facilities. Config uses a set of files that list the source modules that may be required when building a system. The data bases are taken from the directory in which config is run, like $BSDSRC/sys/mips/conf. Three such files may be used: files, files.machine, and files.ident. The first is common to all systems, the second contains files unique to a single machine type, and the third is an optional list of modules for use on a specific machine. This last file may override specifications in the first two. The format of the files file has grown somewhat complex over time. Entries are normally of the form

dir/source.c   type  option-list modifiers

for example,

mips/dev/spi.c  optional spi device-driver

The type is one of standard or optional. Files marked as standard are included in all system configurations. Optional file specifications include a list of one or more system options that together require the inclusion of this module. The options in the list may be either names of devices that may be in the configuration file, or the names of system options that may be defined. An optional file may be listed multiple times with different options; if all of the options for any of the entries are satisfied, the module is included.

If a file is specified as a device-driver, any special compilation options for device drivers will be invoked. On the PIC32 it make no difference, but on other architectures it can result in the use of some special options for the C compiler.

Two other optional keywords modify the usage of the file. Config understands that certain files are used especially for kernel profiling. These files are indicated in the files files with a profiling-routine keyword. For example, the current profiling subroutines are sequestered off in a separate file with the following entry:

sys/subr_mcount.c   optional  profiling-routine

The profiling-routine keyword forces config not to compile the source file with the −pg option.

The second keyword which can be of use is the config-dependent keyword. This causes config to compile the indicated module with the global configuration parameters. This allows certain modules, such as machdep.c to size kernel data structures based on the maximum number of users configured for the system.

6.3. Adding device drivers to LiteBSD

The I/O system and config have been designed to easily allow new device support to be added. The kernel source directories are organized as follows:

sys/sys     machine independent include files
sys/kern    machine-independent kernel source files
sys/libkern kernel library routines
sys/conf    site configuration files and basic templates
sys/dev     machine-independent device drivers
sys/mips    MIPS PIC32-specific code and drivers
sys/miscfs  code for optional filesystems
sys/net     network-related, protocol-independent code
sys/netinet Internet protocol code
sys/nfs     network filesystem code
sys/ufs     Unix filesystem code
sys/vm      virtual memory code

Existing device drivers for the PIC32 reside in "$BSDSRC/sys/mips/dev". Any new device drivers should be placed in the appropriate source code directory and named so as not to conflict with existing devices. Normally, definitions for things like device registers are placed in a separate file in the same directory. For example, the "dh" device driver is named "dh.c" and its associated include file is named "dhreg.h".

Once the source for the device driver has been placed in a directory, the file "../files.machine", and possibly "../devices.machine" should be modified. The files files in the conf directory contain a line for each C source or binary-only file in the system. Those files which are machine independent are located in "$BSDSRC/sys/conf/files", while machine specific files are in "$BSDSRC/sys/ARCH/conf/files.machine". The "devices.machine" file is used to map device names to major block device numbers. If the device driver being added provides support for a new disk you will want to modify this file (the format is obvious).

In addition to including the driver in the files file, it must also be added to the device configuration tables. These are located in "$BSDSRC/sys/mips/pic32/conf.c", or similar for machines other than the PIC32. If you don’t understand what to add to this file, you should study an entry for an existing driver. Remember that the position in the device table specifies the major device number. The block major number is needed in the "devices.machine" file if the device is a disk.

With the configuration information in place, your configuration file appropriately modified, and a system reconfigured and rebooted you should incorporate the shell commands needed to install the special files in the file system to the file "/dev/MAKEDEV" or "/dev/MAKEDEV.local". This is discussed in the document "Installing and Operating LiteBSD".

Appendix A. Configuration File Grammar

The following grammar is a compressed form of the actual yacc(1) grammar used by config to parse configuration files. Terminal symbols are shown all in upper case, literals are emboldened; optional clauses are enclosed in brackets, "[" and "]"; zero or more instantiations are denoted with "*".

Configuration ::= [ Spec ; ]*

Spec          ::= Config_spec
                | Device_spec
                | trace
                | /* lambda */

/* configuration specifications */

Config_spec   ::= machine ID
                | cpu ID
                | options Opt_list
                | ident ID
                | System_spec
                | timezone [ − ] NUMBER [ dst [ NUMBER ] ]
                | timezone [ − ] FPNUMBER [ dst [ NUMBER ] ]
                | maxusers NUMBER

/* system configuration specifications */

System_spec   ::= config ID System_parameter [ System_parameter ]*

System_parameter ::= swap_spec | root_spec | dump_spec | arg_spec

swap_spec     ::= swap [ on ] swap_dev [ and swap_dev ]*

swap_dev      ::= dev_spec [ size NUMBER ]

root_spec     ::= root [ on ] dev_spec

dump_spec     ::= dumps [ on ] dev_spec

arg_spec      ::= args [ on ] dev_spec

dev_spec      ::= dev_name | major_minor

major_minor   ::= major NUMBER minor NUMBER

dev_name      ::= ID [ NUMBER [ ID ] ]

/* option specifications */

Opt_list      ::= Option [ , Option ]*

Option        ::= ID [ = Opt_value ]

Opt_value     ::= ID | NUMBER

Mkopt_list    ::= Mkoption [ , Mkoption ]*

Mkoption      ::= ID = Opt_value

/* device specifications */

Device_spec   ::= device Dev_name Dev_info Int_spec
                | disk Dev_name Dev_info
                | controller Dev_name Dev_info [ Int_spec ]
                | pseudo-device Dev [ NUMBER ]

Dev_name      ::= Dev NUMBER

Dev           ::= ID

Dev_info      ::= Con_info [ Info ]*

Con_info      ::= at Dev NUMBER

Info          ::= drive NUMBER
                | flags NUMBER

Int_spec      ::= priority NUMBER

Lexical Conventions

The terminal symbols are loosely defined as:

  • ID

One or more alphabetics, either upper or lower case, and underscore, "_".

  • NUMBER

Approximately the C language specification for an integer number. That is, a leading "0x" indicates a hexadecimal value, a leading "0" indicates an octal value, otherwise the number is expected to be a decimal value. Hexadecimal numbers may use either upper or lower case alphabetics.

  • FPNUMBER

A floating point number without exponent. That is a number of the form "nnn.ddd", where the fractional component is optional.

In special instances a question mark, "?", can be substituted for a "NUMBER" token. This is used to effect wildcarding in device interconnection specifications.

Comments in configuration files are indicated by a "#" character at the beginning of the line; the remainder of the line is discarded.

A specification is interpreted as a continuation of the previous line if the first character of the line is tab.

Appendix B. Rules for Defaulting System Devices

When config processes a "config" rule which does not fully specify the location of the root file system, paging area(s), and device for kernel dumps, it applies a set of rules to define those values left unspecified. The following list of rules are used in defaulting system devices.

  • If a root device is not specified, the swap specification must indicate a "generic" system is to be built.
  • If the root device does not specify a unit number, it defaults to unit 0.
  • If the root device does not include a partition specification, it defaults to the "a" partition.
  • If no swap area is specified, it defaults to the "b" partition of the root device.
  • If no device is specified for processing argument lists, the first swap partition is selected.
  • If no device is chosen for kernel dumps, the first swap partition is selected (see below to find out where dumps are placed within the partition).

The following table summarizes the default partitions selected when a device specification is incomplete, e.g. "sd0".

Type Partition
root "a"
swap "b"
args "b"
dumps "b"

Multiple swap/paging areas

When multiple swap partitions are specified, the kernel treats the first specified as a "primary" swap area which is always used. The remaining partitions are then interleaved into the paging system at the time a swapon(2) system call is made. This is normally done at boot time with a call to swapon(8) from the /etc/rc file.

Kernel dumps

Kernel dumps are automatically taken after a system crash, provided the device driver for the "dumps" device supports this. The dump contains the contents of memory, but not the swap areas. Normally the dump device is a disk in which case the information is copied to a location at the back of the partition. The dump is placed in the back of the partition because the primary swap and dump device are commonly the same device and this allows the system to be rebooted without immediately overwriting the saved information. When a dump has occurred, the system variable dumpsize is set to a non-zero value indicating the size (in bytes) of the dump. The savecore(8) program then copies the information from the dump partition to a file in a "crash" directory and also makes a copy of the kernel which was running at the time of the crash (usually "/vmunix"). The offset to the kernel dump is defined in the system variable dumplo (a sector offset from the front of the dump partition). The savecore program operates by reading the contents of dumplo, dumpdev, and dumpmagic from /dev/kmem, then comparing the value of dumpmagic read from /dev/kmem to that located in corresponding location in the dump area of the dump partition. If a match is found, savecore assumes a crash occurred and reads dumpsize from the dump area of the dump partition. This value is then used in copying the kernel dump. Refer to savecore(8) for more information about its operation.

The value dumplo is calculated to be

dumpdev-size - memsize

where dumpdev-size is the size of the disk partition where kernel dumps are to be placed, and memsize is the size of physical memory. If the disk partition is not large enough to hold a full dump, dumplo is set to 0 (the start of the partition).

Appendix C. Kernel Data Structure Sizing Rules

Certain kernel data structures are sized at compile time according to the maximum number of simultaneous users expected, while others are calculated at boot time based on the physical resources present, e.g. memory. This appendix lists both sets of rules and also includes some hints on changing built-in limitations on certain data structures.

Compile time rules

The file $BSDSRC/sys/conf/param.c contains the definitions of almost all data structures sized at compile time. This file is copied into the directory of each configured kernel to allow configuration-dependent rules and values to be maintained. (Each copy normally depends on the copy in $BSDSRC/sys/conf, and global modifications cause the file to be recopied unless the makefile is modified.) The rules implied by its contents are summarized below (here MAXUSERS refers to the value defined in the configuration file in the "maxusers" rule). Most limits are computed at compile time and stored in global variables for use by other modules; they may generally be patched in the kernel binary image before rebooting to test new values.

  • maxproc

The maximum number of processes which may be running at any time. It is referred to in other calculations as NPROC and is defined to be

8 + 8 * MAXUSERS
  • desiredvnodes

The maximum number of files in the file system which may be active at any time. This includes files in use by users, as well as directory files being read or written by the system and files associated with bound sockets in the UNIX IPC domain. It is defined as

NPROC + 2 * MAXUSERS + 24
  • maxfiles

The number of "file table" structures. One file table structure is used for each open, unshared, file descriptor. Multiple file descriptors may reference a single file table entry when they are created through a dup call, or as the result of a fork. This is defined to be

2 * NPROC + 16
  • ncallout

The number of "callout" structures. One callout structure is used per internal system event handled with a timeout. Timeouts are used for terminal delays, watchdog routines in device drivers, protocol timeout processing, etc. This is defined as

16 + NPROC
  • nmbclusters

The maximum number of pages which may be allocated by the network. This is machine-dependent and defined as 16 (64 kbytes of memory) for PIC32 in $BSDSRC/sys/mips/include/param.h. In practice, network starts off by allocating 8 kilobytes of memory, then requesting more as required. This value represents an upper bound.

Run-time calculations

The most important data structures sized at run-time are those used in the buffer cache. Allocation is done by allocating physical memory (and system virtual memory) immediately after the kernel has been started up; look in the file $BSDSRC/sys/mips/pic32/machdep.c. The amount of physical memory which may be allocated to the buffer cache is constrained by the size of the kernel page tables, among other things. While the system may calculate a large amount of memory to be allocated to the buffer cache, if the kernel page table is too small to map this physical memory into the virtual address space of the system, only as much as can be mapped will be used.

The buffer cache is comprised of a number of "buffer headers" and a pool of pages attached to these headers. Buffer headers are divided into two categories: those used for swapping and paging, and those used for normal file I/O. The kernel tries to allocate 10% of the first two megabytes and 5% of the remaining available physical memory for the buffer cache (where available does not count that space occupied by the kernel’s text and data segments). If this results in fewer than 16 pages of memory allocated, then 16 pages are allocated. This value is kept in the initialized variable bufpages so that it may be patched in the binary image (to allow tuning without recompiling the kernel), or the default may be overridden with a configuration-file option. For example, the option options BUFPAGES="3200" causes 3200 pages (3.2M bytes) to be used by the buffer cache. A sufficient number of file I/O buffer headers are then allocated to allow each to hold 2 pages each. Each buffer maps 8K bytes. If the number of buffer pages is larger than can be mapped by the buffer headers, the number of pages is reduced. The number of buffer headers allocated is stored in the global variable nbuf, which may be patched before the kernel is booted. The system option options NBUF="1000" forces the allocation of 1000 buffer headers. Half as many swap I/O buffer headers as file I/O buffers are allocated, but no more than 256.

Kernel size limitations

As distributed, the sum of the virtual sizes of the core-resident processes is limited to 256M bytes. The size of the text segment of a single process is currently limited to 6M bytes. It may be increased to no greater than the data segment size limit (see below) by redefining MAXTSIZ. This may be done with a configuration file option, e.g. options MAXTSIZ="(10*1024*1024)" to set the limit to 10 million bytes. Other per-process limits discussed here may be changed with similar options with names given in parentheses. Soft, user-changeable limits are set to 512K bytes for stack (DFLSSIZ) and 6M bytes for the data segment (DFLDSIZ) by default; these may be increased up to the hard limit with the setrlimit(2) system call. The data and stack segment size hard limits are set by a kernel configuration option to one of 17M, 33M or 64M bytes. One of these sizes is chosen based on the definition of MAXDSIZ; with no option, the limit is 17M bytes; with an option options MAXDSIZ="(32*1024*1024)" (or any value between 17M and 33M), the limit is increased to 33M bytes, and values larger than 33M result in a limit of 64M bytes. You must be careful in doing this that you have adequate paging space. As normally configured, the kernel has 16M or 32M bytes per paging area, depending on disk size. The best way to get more space is to provide multiple, thereby interleaved, paging areas. Increasing the virtual memory limits results in interleaving of swap space in larger sections (from 500K bytes to 1M or 2M bytes).

Because the file system block numbers are stored in page table pg_blkno entries, the maximum size of a file system is limited to 2^24 1024 byte blocks. Thus no file system can be larger than 8 gigabytes.

Appendix D. Network Configuration Options

The network support in the kernel is self-configuring according to the INET protocol support option and the network hardware discovered during autoconfiguration. There are several changes that may be made to customize network behavior due to local restrictions. Within the Internet protocol routines, the following options set in the kernel configuration file are supported:

  • GATEWAY

The machine is to be used as a gateway. This option currently makes only minor changes. First, the size of the network routing hash table is increased. Secondly, machines that have only a single hardware network interface will not forward IP packets; without this option, they will also refrain from sending any error indication to the source of unforwardable packets. Gateways with only a single interface are assumed to have missing or broken interfaces, and will return ICMP unreachable errors to hosts sending them packets to be forwarded.

  • IPFORWARDING

Normally, LiteBSD machines with multiple network interfaces will forward IP packets received that should be resent to another host. If the line `options IPFORWARDING="0"' is in the kernel configuration file, IP packet forwarding will be disabled.

  • IPSENDREDIRECTS

When forwarding IP packets, LiteBSD IP will note when a packet is forwarded using the same interface on which it arrived. When this is noted, if the source machine is on the directly-attached network, an ICMP redirect is sent to the source host. If the packet was forwarded using a route to a host or to a subnet, a host redirect is sent, otherwise a network redirect is sent. The generation of redirects may be inhibited with the configuration option `options IPSENDREDIRECTS="0"'.

  • SUBNETSARELOCAL

TCP calculates a maximum segment size to use for each connection, and sends no datagrams larger than that size. This size will be no larger than that supported on the outgoing interface. Furthermore, if the destination is not on the local network, the size will be no larger than 576 bytes. For this test, other subnets of a directly-connected subnetted network are considered to be local unless the line `options SUBNETSARELOCAL="0"' is used in the kernel configuration file.