diff --git a/en_US.ISO8859-1/books/arch-handbook/isa/chapter.sgml b/en_US.ISO8859-1/books/arch-handbook/isa/chapter.sgml
index f48cd1ac06..6c4c58213d 100644
--- a/en_US.ISO8859-1/books/arch-handbook/isa/chapter.sgml
+++ b/en_US.ISO8859-1/books/arch-handbook/isa/chapter.sgml
@@ -1,2483 +1,2483 @@
ISA device drivers
This chapter was written by &a.babkin; Modifications for the
handbook made by &a.murray;, &a.wylie;, and &a.logo;.
SynopsisThis chapter introduces the issues relevant to writing a
driver for an ISA device. The pseudo-code presented here is
rather detailed and reminiscent of the real code but is still
only pseudo-code. It avoids the details irrelevant to the
subject of the discussion. The real-life examples can be found
in the source code of real drivers. In particular the drivers
ep and aha are good sources of information.Basic informationA typical ISA driver would need the following include
files:#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <isa/isavar.h>
#include <isa/pnpvar.h>They describe the things specific to the ISA and generic
bus subsystem.The bus subsystem is implemented in an object-oriented
fashion, its main structures are accessed by associated method
functions.The list of bus methods implemented by an ISA driver is like
one for any other bus. For a hypothetical driver named xxx
they would be:static void xxx_isa_identify (driver_t *,
device_t); Normally used for bus drivers, not
device drivers. But for ISA devices this method may have
special use: if the device provides some device-specific
(non-PnP) way to auto-detect devices this routine may
implement it.static int xxx_isa_probe (device_t
dev); Probe for a device at a known (or PnP)
location. This routine can also accommodate device-specific
auto-detection of parameters for partially configured
devices.static int xxx_isa_attach (device_t
dev); Attach and initialize device.static int xxx_isa_detach (device_t
dev); Detach device before unloading the driver
module.static int xxx_isa_shutdown (device_t
dev); Execute shutdown of the device before
system shutdown.static int xxx_isa_suspend (device_t
dev); Suspend the device before the system goes
to the power-save state. May also abort transition to the
power-save state.static int xxx_isa_resume (device_t
dev); Resume the device activity after return
from power-save state.xxx_isa_probe() and
xxx_isa_attach() are mandatory, the rest of
the routines are optional, depending on the device's
needs.The driver is linked to the system with the following set of
descriptions. /* table of supported bus methods */
static device_method_t xxx_isa_methods[] = {
/* list all the bus method functions supported by the driver */
/* omit the unsupported methods */
DEVMETHOD(device_identify, xxx_isa_identify),
DEVMETHOD(device_probe, xxx_isa_probe),
DEVMETHOD(device_attach, xxx_isa_attach),
DEVMETHOD(device_detach, xxx_isa_detach),
DEVMETHOD(device_shutdown, xxx_isa_shutdown),
DEVMETHOD(device_suspend, xxx_isa_suspend),
DEVMETHOD(device_resume, xxx_isa_resume),
{ 0, 0 }
};
static driver_t xxx_isa_driver = {
"xxx",
xxx_isa_methods,
sizeof(struct xxx_softc),
};
static devclass_t xxx_devclass;
DRIVER_MODULE(xxx, isa, xxx_isa_driver, xxx_devclass,
load_function, load_argument);Here struct xxx_softc is a
device-specific structure that contains private driver data
and descriptors for the driver's resources. The bus code
automatically allocates one softc descriptor per device as
needed.If the driver is implemented as a loadable module then
load_function() is called to do
driver-specific initialization or clean-up when the driver is
loaded or unloaded and load_argument is passed as one of its
arguments. If the driver does not support dynamic loading (in
other words it must always be linked into kernel) then these
values should be set to 0 and the last definition would look
like: DRIVER_MODULE(xxx, isa, xxx_isa_driver,
xxx_devclass, 0, 0);If the driver is for a device which supports PnP then a
table of supported PnP IDs must be defined. The table
consists of a list of PnP IDs supported by this driver and
human-readable descriptions of the hardware types and models
having these IDs. It looks like: static struct isa_pnp_id xxx_pnp_ids[] = {
/* a line for each supported PnP ID */
{ 0x12345678, "Our device model 1234A" },
{ 0x12345679, "Our device model 1234B" },
{ 0, NULL }, /* end of table */
};If the driver does not support PnP devices it still needs
an empty PnP ID table, like: static struct isa_pnp_id xxx_pnp_ids[] = {
{ 0, NULL }, /* end of table */
};Device_t pointerDevice_t is the pointer type for
the device structure. Here we consider only the methods
interesting from the device driver writer's standpoint. The
methods to manipulate values in the device structure
are:device_t
device_get_parent(dev) Get the parent bus of a
device.driver_t
device_get_driver(dev) Get pointer to its driver
structure.char
*device_get_name(dev) Get the driver name, such
as "xxx" for our example.int device_get_unit(dev)
Get the unit number (units are numbered from 0 for the
devices associated with each driver).char
*device_get_nameunit(dev) Get the device name
including the unit number, such as xxx0, xxx1 and so
on.char
*device_get_desc(dev) Get the device
description. Normally it describes the exact model of device
in human-readable form.device_set_desc(dev,
desc) Set the description. This makes the device
description point to the string desc which may not be
deallocated or changed after that.device_set_desc_copy(dev,
desc) Set the description. The description is
copied into an internal dynamically allocated buffer, so the
string desc may be changed afterwards without adverse
effects.void
*device_get_softc(dev) Get pointer to the device
descriptor (struct xxx_softc)
associated with this device.u_int32_t
device_get_flags(dev) Get the flags specified for
the device in the configuration file.A convenience function device_printf(dev, fmt,
...) may be used to print the messages from the
device driver. It automatically prepends the unitname and
colon to the message.The device_t methods are implemented in the file
kern/bus_subr.c.Configuration file and the order of identifying and probing
during auto-configurationThe ISA devices are described in the kernel configuration file
like:device xxx0 at isa? port 0x300 irq 10 drq 5
iomem 0xd0000 flags 0x1 sensitiveThe values of port, IRQ and so on are converted to the
resource values associated with the device. They are optional,
depending on the device's needs and abilities for
auto-configuration. For example, some devices do not need DRQ
at all and some allow the driver to read the IRQ setting from
the device configuration ports. If a machine has multiple ISA
buses the exact bus may be specified in the configuration
line, like isa0 or isa1, otherwise the device would be
searched for on all the ISA buses.sensitive is a resource requesting that this device must
be probed before all non-sensitive devices. It is supported
but does not seem to be used in any current driver.For legacy ISA devices in many cases the drivers are still
able to detect the configuration parameters. But each device
to be configured in the system must have a config line. If two
devices of some type are installed in the system but there is
only one configuration line for the corresponding driver, ie:
device xxx0 at isa? then only
one device will be configured.But for the devices supporting automatic identification by
the means of Plug-n-Play or some proprietary protocol one
configuration line is enough to configure all the devices in
the system, like the one above or just simply:device xxx at isa?If a driver supports both auto-identified and legacy
devices and both kinds are installed at once in one machine
then it is enough to describe in the config file the legacy
devices only. The auto-identified devices will be added
automatically.When an ISA bus is auto-configured the events happen as
follows:All the drivers' identify routines (including the PnP
identify routine which identifies all the PnP devices) are
called in random order. As they identify the devices they add
them to the list on the ISA bus. Normally the drivers'
identify routines associate their drivers with the new
devices. The PnP identify routine does not know about the
other drivers yet so it does not associate any with the new
devices it adds.The PnP devices are put to sleep using the PnP protocol to
prevent them from being probed as legacy devices.The probe routines of non-PnP devices marked as
sensitive are called. If probe for a device went
successfully, the attach routine is called for it.The probe and attach routines of all non-PNP devices are
called likewise.The PnP devices are brought back from the sleep state and
assigned the resources they request: I/O and memory address
ranges, IRQs and DRQs, all of them not conflicting with the
attached legacy devices.Then for each PnP device the probe routines of all the
present ISA drivers are called. The first one that claims the
device gets attached. It is possible that multiple drivers
would claim the device with different priority; in this case, the
highest-priority driver wins. The probe routines must call
ISA_PNP_PROBE() to compare the actual PnP
ID with the list of the IDs supported by the driver and if the
ID is not in the table return failure. That means that
absolutely every driver, even the ones not supporting any PnP
devices must call ISA_PNP_PROBE(), at
least with an empty PnP ID table to return failure on unknown
PnP devices.The probe routine returns a positive value (the error
code) on error, zero or negative value on success.The negative return values are used when a PnP device
supports multiple interfaces. For example, an older
compatibility interface and a newer advanced interface which
are supported by different drivers. Then both drivers would
detect the device. The driver which returns a higher value in
the probe routine takes precedence (in other words, the driver
returning 0 has highest precedence, returning -1 is next,
returning -2 is after it and so on). In result the devices
which support only the old interface will be handled by the
old driver (which should return -1 from the probe routine)
while the devices supporting the new interface as well will be
handled by the new driver (which should return 0 from the
probe routine). If multiple drivers return the same value then
the one called first wins. So if a driver returns value 0 it
may be sure that it won the priority arbitration.The device-specific identify routines can also assign not
a driver but a class of drivers to the device. Then all the
drivers in the class are probed for this device, like the case
with PnP. This feature is not implemented in any existing
driver and is not considered further in this document.Because the PnP devices are disabled when probing the
legacy devices they will not be attached twice (once as legacy
and once as PnP). But in case of device-dependent identify
routines it is the responsibility of the driver to make sure
that the same device will not be attached by the driver twice:
once as legacy user-configured and once as
auto-identified.Another practical consequence for the auto-identified
devices (both PnP and device-specific) is that the flags can
not be passed to them from the kernel configuration file. So
they must either not use the flags at all or use the flags
from the device unit 0 for all the auto-identified devices or
use the sysctl interface instead of flags.Other unusual configurations may be accommodated by
accessing the configuration resources directly with functions
of families resource_query_*() and
resource_*_value(). Their implementations
are located in kern/subr_bus.h. The old IDE disk driver
i386/isa/wd.c contains examples of such use. But the standard
means of configuration must always be preferred. Leave parsing
the configuration resources to the bus configuration
code.ResourcesThe information that a user enters into the kernel
configuration file is processed and passed to the kernel as
configuration resources. This information is parsed by the bus
configuration code and transformed into a value of structure
device_t and the bus resources associated with it. The drivers
may access the configuration resources directly using
functions resource_* for more complex cases of
configuration. However, generally this is neither needed nor recommended,
so this issue is not discussed further here.The bus resources are associated with each device. They
are identified by type and number within the type. For the ISA
bus the following types are defined:SYS_RES_IRQ - interrupt
numberSYS_RES_DRQ - ISA DMA channel
numberSYS_RES_MEMORY - range of
device memory mapped into the system memory space
SYS_RES_IOPORT - range of
device I/O registersThe enumeration within types starts from 0, so if a device
has two memory regions it would have resources of type
SYS_RES_MEMORY numbered 0 and 1. The resource type has
nothing to do with the C language type, all the resource
values have the C language type unsigned long and must be
cast as necessary. The resource numbers do not have to be
contiguous, although for ISA they normally would be. The
permitted resource numbers for ISA devices are: IRQ: 0-1
DRQ: 0-1
MEMORY: 0-3
IOPORT: 0-7All the resources are represented as ranges, with a start
value and count. For IRQ and DRQ resources the count would
normally be equal to 1. The values for memory refer to the
physical addresses.Three types of activities can be performed on
resources:set/getallocate/releaseactivate/deactivateSetting sets the range used by the resource. Allocation
reserves the requested range that no other driver would be
able to reserve it (and checking that no other driver reserved
this range already). Activation makes the resource accessible
to the driver by doing whatever is necessary for that (for
example, for memory it would be mapping into the kernel
virtual address space).The functions to manipulate resources are:int bus_set_resource(device_t dev, int type,
int rid, u_long start, u_long count)Set a range for a resource. Returns 0 if successful,
error code otherwise. Normally, this function will
return an error only if one of type,
rid, start or
count has a value that falls out of the
permitted range. dev - driver's device type - type of resource, SYS_RES_* rid - resource number (ID) within type start, count - resource range int bus_get_resource(device_t dev, int type,
int rid, u_long *startp, u_long *countp)Get the range of resource. Returns 0 if successful,
error code if the resource is not defined yet.u_long bus_get_resource_start(device_t dev,
int type, int rid) u_long bus_get_resource_count (device_t
dev, int type, int rid)Convenience functions to get only the start or
count. Return 0 in case of error, so if the resource start
has 0 among the legitimate values it would be impossible
to tell if the value is 0 or an error occurred. Luckily,
no ISA resources for add-on drivers may have a start value
equal to 0.void bus_delete_resource(device_t dev, int
type, int rid) Delete a resource, make it undefined.struct resource *
bus_alloc_resource(device_t dev, int type, int *rid,
u_long start, u_long end, u_long count, u_int
flags)Allocate a resource as a range of count values not
allocated by anyone else, somewhere between start and
end. Alas, alignment is not supported. If the resource
was not set yet it is automatically created. The special
values of start 0 and end ~0 (all ones) means that the
fixed values previously set by
bus_set_resource() must be used
instead: start and count as themselves and
end=(start+count), in this case if the resource was not
defined before then an error is returned. Although rid is
passed by reference it is not set anywhere by the resource
allocation code of the ISA bus. (The other buses may use a
different approach and modify it).Flags are a bitmap, the flags interesting for the caller
are:RF_ACTIVE - causes the resource
to be automatically activated after allocation.RF_SHAREABLE - resource may be
shared at the same time by multiple drivers.RF_TIMESHARE - resource may be
time-shared by multiple drivers, i.e. allocated at the
same time by many but activated only by one at any given
moment of time.
-
+
Returns 0 on error. The allocated values may be
obtained from the returned handle using methods
rhand_*().int bus_release_resource(device_t dev, int
type, int rid, struct resource *r)Release the resource, r is the handle returned by
bus_alloc_resource(). Returns 0 on
success, error code otherwise.int bus_activate_resource(device_t dev, int
type, int rid, struct resource *r)int bus_deactivate_resource(device_t dev, int
type, int rid, struct resource *r)Activate or deactivate resource. Return 0 on success,
error code otherwise. If the resource is time-shared and
currently activated by another driver then EBUSY is
returned.int bus_setup_intr(device_t dev, struct
resource *r, int flags, driver_intr_t *handler, void *arg,
void **cookiep)int
bus_teardown_intr(device_t dev, struct resource *r, void
*cookie)Associate or de-associate the interrupt handler with a
device. Return 0 on success, error code otherwise.r - the activated resource handler describing the
IRQflags - the interrupt priority level, one of:INTR_TYPE_TTY - terminals and
other likewise character-type devices. To mask them
use spltty().(INTR_TYPE_TTY |
INTR_TYPE_FAST) - terminal type devices
with small input buffer, critical to the data loss on
input (such as the old-fashioned serial ports). To
mask them use spltty().INTR_TYPE_BIO - block-type
devices, except those on the CAM controllers. To mask
them use splbio().INTR_TYPE_CAM - CAM (Common
Access Method) bus controllers. To mask them use
splcam().INTR_TYPE_NET - network
interface controllers. To mask them use
splimp().INTR_TYPE_MISC -
miscellaneous devices. There is no other way to mask
them than by splhigh() which
masks all interrupts.When an interrupt handler executes all the other
interrupts matching its priority level will be masked. The
only exception is the MISC level for which no other interrupts
are masked and which is not masked by any other
interrupt.handler - pointer to the handler
function, the type driver_intr_t is defined as void
driver_intr_t(void *)arg - the argument passed to the
handler to identify this particular device. It is cast
from void* to any real type by the handler. The old
convention for the ISA interrupt handlers was to use the
unit number as argument, the new (recommended) convention
is using a pointer to the device softc structure.cookie[p] - the value received
from setup() is used to identify the
handler when passed to
teardown()A number of methods are defined to operate on the resource
handlers (struct resource *). Those of interest to the device
driver writers are:u_long rman_get_start(r) u_long
rman_get_end(r) Get the start and end of
allocated resource range.void *rman_get_virtual(r) Get
the virtual address of activated memory resource.Bus memory mappingIn many cases data is exchanged between the driver and the
device through the memory. Two variants are possible:(a) memory is located on the device card(b) memory is the main memory of the computerIn case (a) the driver always copies the data back and
forth between the on-card memory and the main memory as
necessary. To map the on-card memory into the kernel virtual
address space the physical address and length of the on-card
memory must be defined as a SYS_RES_MEMORY resource. That
resource can then be allocated and activated, and its virtual
address obtained using
rman_get_virtual(). The older drivers
used the function pmap_mapdev() for this
purpose, which should not be used directly any more. Now it is
one of the internal steps of resource activation.Most of the ISA cards will have their memory configured
for physical location somewhere in range 640KB-1MB. Some of
the ISA cards require larger memory ranges which should be
placed somewhere under 16MB (because of the 24-bit address
limitation on the ISA bus). In that case if the machine has
more memory than the start address of the device memory (in
other words, they overlap) a memory hole must be configured at
the address range used by devices. Many BIOSes allow
configuration of a memory hole of 1MB starting at 14MB or
15MB. FreeBSD can handle the memory holes properly if the BIOS
reports them properly (this feature may be broken on old BIOSes).In case (b) just the address of the data is sent to
the device, and the device uses DMA to actually access the
data in the main memory. Two limitations are present: First,
ISA cards can only access memory below 16MB. Second, the
contiguous pages in virtual address space may not be
contiguous in physical address space, so the device may have
to do scatter/gather operations. The bus subsystem provides
ready solutions for some of these problems, the rest has to be
done by the drivers themselves.Two structures are used for DMA memory allocation,
bus_dma_tag_t and bus_dmamap_t. Tag describes the properties
required for the DMA memory. Map represents a memory block
allocated according to these properties. Multiple maps may be
associated with the same tag.Tags are organized into a tree-like hierarchy with
inheritance of the properties. A child tag inherits all the
requirements of its parent tag, and may make them more strict
but never more loose.Normally one top-level tag (with no parent) is created for
each device unit. If multiple memory areas with different
requirements are needed for each device then a tag for each of
them may be created as a child of the parent tag.The tags can be used to create a map in two ways.First, a chunk of contiguous memory conformant with the
tag requirements may be allocated (and later may be
freed). This is normally used to allocate relatively
long-living areas of memory for communication with the
device. Loading of such memory into a map is trivial: it is
always considered as one chunk in the appropriate physical
memory range.Second, an arbitrary area of virtual memory may be loaded
into a map. Each page of this memory will be checked for
conformance to the map requirement. If it conforms then it is
left at its original location. If it is not then a fresh
conformant bounce page is allocated and used as intermediate
storage. When writing the data from the non-conformant
original pages they will be copied to their bounce pages first
and then transferred from the bounce pages to the device. When
reading the data would go from the device to the bounce pages
and then copied to their non-conformant original pages. The
process of copying between the original and bounce pages is
called synchronization. This is normally used on a per-transfer
basis: buffer for each transfer would be loaded, transfer done
and buffer unloaded.The functions working on the DMA memory are:int bus_dma_tag_create(bus_dma_tag_t parent,
bus_size_t alignment, bus_size_t boundary, bus_addr_t
lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filter, void
*filterarg, bus_size_t maxsize, int nsegments, bus_size_t
maxsegsz, int flags, bus_dma_tag_t *dmat)Create a new tag. Returns 0 on success, the error code
otherwise.parent - parent tag, or NULL to
create a top-level tag alignment -
required physical alignment of the memory area to be
allocated for this tag. Use value 1 for no specific
alignment. Applies only to the future
bus_dmamem_alloc() but not
bus_dmamap_create() calls.boundary - physical address
boundary that must not be crossed when allocating the
memory. Use value 0 for no boundary. Applies only to
the future bus_dmamem_alloc() but
not bus_dmamap_create() calls.
Must be power of 2. If the memory is planned to be used
in non-cascaded DMA mode (i.e. the DMA addresses will be
supplied not by the device itself but by the ISA DMA
controller) then the boundary must be no larger than
64KB (64*1024) due to the limitations of the DMA
hardware.lowaddr, highaddr - the names
are slightly misleading; these values are used to limit
the permitted range of physical addresses used to
allocate the memory. The exact meaning varies depending
on the planned future use:For bus_dmamem_alloc() all
the addresses from 0 to lowaddr-1 are considered
permitted, the higher ones are forbidden.For bus_dmamap_create() all
the addresses outside the inclusive range [lowaddr;
highaddr] are considered accessible. The addresses
of pages inside the range are passed to the filter
function which decides if they are accessible. If no
filter function is supplied then all the range is
considered unaccessible.For the ISA devices the normal values (with no
filter function) are:lowaddr = BUS_SPACE_MAXADDR_24BIThighaddr = BUS_SPACE_MAXADDRfilter, filterarg - the filter
function and its argument. If NULL is passed for filter
then the whole range [lowaddr, highaddr] is considered
unaccessible when doing
bus_dmamap_create(). Otherwise the
physical address of each attempted page in range
[lowaddr; highaddr] is passed to the filter function
which decides if it is accessible. The prototype of the
filter function is: int filterfunc(void *arg,
bus_addr_t paddr). It must return 0 if the
page is accessible, non-zero otherwise.maxsize - the maximal size of
memory (in bytes) that may be allocated through this
tag. In case it is difficult to estimate or could be
arbitrarily big, the value for ISA devices would be
BUS_SPACE_MAXSIZE_24BIT.nsegments - maximal number of
scatter-gather segments supported by the device. If
unrestricted then the value BUS_SPACE_UNRESTRICTED
should be used. This value is recommended for the parent
tags, the actual restrictions would then be specified
for the descendant tags. Tags with nsegments equal to
BUS_SPACE_UNRESTRICTED may not be used to actually load
maps, they may be used only as parent tags. The
practical limit for nsegments seems to be about 250-300,
higher values will cause kernel stack overflow (the hardware
can not normally support that many
scatter-gather buffers anyway).maxsegsz - maximal size of a
scatter-gather segment supported by the device. The
maximal value for ISA device would be
BUS_SPACE_MAXSIZE_24BIT.flags - a bitmap of flags. The
only interesting flags are:BUS_DMA_ALLOCNOW - requests
to allocate all the potentially needed bounce pages
when creating the tag.BUS_DMA_ISA - mysterious
flag used only on Alpha machines. It is not defined
for the i386 machines. Probably it should be used
by all the ISA drivers for Alpha machines but it
looks like there are no such drivers yet.dmat - pointer to the storage
for the new tag to be returned.int bus_dma_tag_destroy(bus_dma_tag_t
dmat)Destroy a tag. Returns 0 on success, the error code
otherwise.dmat - the tag to be destroyed.int bus_dmamem_alloc(bus_dma_tag_t dmat,
void** vaddr, int flags, bus_dmamap_t
*mapp)Allocate an area of contiguous memory described by the
tag. The size of memory to be allocated is tag's maxsize.
Returns 0 on success, the error code otherwise. The result
still has to be loaded by
bus_dmamap_load() before being used to get
the physical address of the memory.dmat - the tag
vaddr - pointer to the storage
for the kernel virtual address of the allocated area
to be returned.
flags - a bitmap of flags. The only interesting flag is:
BUS_DMA_NOWAIT - if the
memory is not immediately available return the
error. If this flag is not set then the routine
is allowed to sleep until the memory
becomes available.
mapp - pointer to the storage
for the new map to be returned.
void bus_dmamem_free(bus_dma_tag_t dmat, void
*vaddr, bus_dmamap_t map)
Free the memory allocated by
bus_dmamem_alloc(). At present,
freeing of the memory allocated with ISA restrictions is
not implemented. Because of this the recommended model
of use is to keep and re-use the allocated areas for as
long as possible. Do not lightly free some area and then
shortly allocate it again. That does not mean that
bus_dmamem_free() should not be
used at all: hopefully it will be properly implemented
soon.
dmat - the tag
vaddr - the kernel virtual
address of the memory
map - the map of the memory (as
returned from
bus_dmamem_alloc())
int bus_dmamap_create(bus_dma_tag_t dmat, int
flags, bus_dmamap_t *mapp)
Create a map for the tag, to be used in
bus_dmamap_load() later. Returns 0
on success, the error code otherwise.
dmat - the tag
flags - theoretically, a bit map
of flags. But no flags are defined yet, so at present
it will be always 0.
mapp - pointer to the storage
for the new map to be returned
int bus_dmamap_destroy(bus_dma_tag_t dmat,
bus_dmamap_t map)
Destroy a map. Returns 0 on success, the error code otherwise.
dmat - the tag to which the map is associated
map - the map to be destroyed
int bus_dmamap_load(bus_dma_tag_t dmat,
bus_dmamap_t map, void *buf, bus_size_t buflen,
bus_dmamap_callback_t *callback, void *callback_arg, int
flags)
Load a buffer into the map (the map must be previously
created by bus_dmamap_create() or
bus_dmamem_alloc()). All the pages
of the buffer are checked for conformance to the tag
requirements and for those not conformant the bounce
pages are allocated. An array of physical segment
descriptors is built and passed to the callback
routine. This callback routine is then expected to
handle it in some way. The number of bounce buffers in
the system is limited, so if the bounce buffers are
needed but not immediately available the request will be
queued and the callback will be called when the bounce
buffers will become available. Returns 0 if the callback
was executed immediately or EINPROGRESS if the request
was queued for future execution. In the latter case the
synchronization with queued callback routine is the
responsibility of the driver.
dmat - the tag
map - the map
buf - kernel virtual address of
the buffer
buflen - length of the buffer
callback,
callback_arg - the callback function and
its argument
The prototype of callback function is:
void callback(void *arg, bus_dma_segment_t
*seg, int nseg, int error)arg - the same as callback_arg
passed to bus_dmamap_load()seg - array of the segment
descriptors
nseg - number of descriptors in
array
error - indication of the
segment number overflow: if it is set to EFBIG then
the buffer did not fit into the maximal number of
segments permitted by the tag. In this case only the
permitted number of descriptors will be in the
array. Handling of this situation is up to the
driver: depending on the desired semantics it can
either consider this an error or split the buffer in
two and handle the second part separately
Each entry in the segments array contains the fields:
ds_addr - physical bus address
of the segment
ds_len - length of the segment
void bus_dmamap_unload(bus_dma_tag_t dmat,
bus_dmamap_t map)unload the map.
dmat - tag
map - loaded map
void bus_dmamap_sync (bus_dma_tag_t dmat,
bus_dmamap_t map, bus_dmasync_op_t op)
Synchronise a loaded buffer with its bounce pages before
and after physical transfer to or from device. This is
the function that does all the necessary copying of data
between the original buffer and its mapped version. The
buffers must be synchronized both before and after doing
the transfer.
dmat - tag
map - loaded map
op - type of synchronization
operation to perform:
BUS_DMASYNC_PREREAD - before
reading from device into buffer
BUS_DMASYNC_POSTREAD - after
reading from device into buffer
BUS_DMASYNC_PREWRITE - before
writing the buffer to device
BUS_DMASYNC_POSTWRITE - after
writing the buffer to device
As of now PREREAD and POSTWRITE are null operations but that
may change in the future, so they must not be ignored in the
driver. Synchronization is not needed for the memory
obtained from bus_dmamem_alloc().
Before calling the callback function from
bus_dmamap_load() the segment array is
stored in the stack. And it gets pre-allocated for the
maximal number of segments allowed by the tag. Because of
this the practical limit for the number of segments on i386
architecture is about 250-300 (the kernel stack is 4KB minus
the size of the user structure, size of a segment array
entry is 8 bytes, and some space must be left). Because the
array is allocated based on the maximal number this value
must not be set higher than really needed. Fortunately, for
most of hardware the maximal supported number of segments is
much lower. But if the driver wants to handle buffers with a
very large number of scatter-gather segments it should do
that in portions: load part of the buffer, transfer it to
the device, load next part of the buffer, and so on.
Another practical consequence is that the number of segments
may limit the size of the buffer. If all the pages in the
buffer happen to be physically non-contiguous then the
maximal supported buffer size for that fragmented case would
be (nsegments * page_size). For example, if a maximal number
of 10 segments is supported then on i386 maximal guaranteed
supported buffer size would be 40K. If a higher size is
desired then special tricks should be used in the driver.
If the hardware does not support scatter-gather at all or
the driver wants to support some buffer size even if it is
heavily fragmented then the solution is to allocate a
contiguous buffer in the driver and use it as intermediate
storage if the original buffer does not fit.
Below are the typical call sequences when using a map depend
on the use of the map. The characters -> are used to show
the flow of time.
For a buffer which stays practically fixed during all the
time between attachment and detachment of a device:
bus_dmamem_alloc -> bus_dmamap_load -> ...use buffer... ->
-> bus_dmamap_unload -> bus_dmamem_free
For a buffer that changes frequently and is passed from
outside the driver:
bus_dmamap_create ->
-> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->
-> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->
...
-> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->
-> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->
-> bus_dmamap_destroy
When loading a map created by
bus_dmamem_alloc() the passed address
and size of the buffer must be the same as used in
bus_dmamem_alloc(). In this case it is
guaranteed that the whole buffer will be mapped as one
segment (so the callback may be based on this assumption)
and the request will be executed immediately (EINPROGRESS
will never be returned). All the callback needs to do in
this case is to save the physical address.
A typical example would be:
static void
alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
{
*(bus_addr_t *)arg = seg[0].ds_addr;
}
...
int error;
struct somedata {
....
};
struct somedata *vsomedata; /* virtual address */
bus_addr_t psomedata; /* physical bus-relative address */
bus_dma_tag_t tag_somedata;
bus_dmamap_t map_somedata;
...
error=bus_dma_tag_create(parent_tag, alignment,
boundary, lowaddr, highaddr, /*filter*/ NULL, /*filterarg*/ NULL,
/*maxsize*/ sizeof(struct somedata), /*nsegments*/ 1,
/*maxsegsz*/ sizeof(struct somedata), /*flags*/ 0,
&tag_somedata);
if(error)
return error;
error = bus_dmamem_alloc(tag_somedata, &vsomedata, /* flags*/ 0,
&map_somedata);
if(error)
return error;
bus_dmamap_load(tag_somedata, map_somedata, (void *)vsomedata,
sizeof (struct somedata), alloc_callback,
(void *) &psomedata, /*flags*/0);
Looks a bit long and complicated but that is the way to do
it. The practical consequence is: if multiple memory areas
are allocated always together it would be a really good idea
to combine them all into one structure and allocate as one
(if the alignment and boundary limitations permit).
When loading an arbitrary buffer into the map created by
bus_dmamap_create() special measures
must be taken to synchronize with the callback in case it
would be delayed. The code would look like:
{
int s;
int error;
s = splsoftvm();
error = bus_dmamap_load(
dmat,
dmamap,
buffer_ptr,
buffer_len,
callback,
/*callback_arg*/ buffer_descriptor,
/*flags*/0);
if (error == EINPROGRESS) {
/*
* Do whatever is needed to ensure synchronization
* with callback. Callback is guaranteed not to be started
* until we do splx() or tsleep().
*/
}
splx(s);
}
Two possible approaches for the processing of requests are:
1. If requests are completed by marking them explicitly as
done (such as the CAM requests) then it would be simpler to
put all the further processing into the callback driver
which would mark the request when it is done. Then not much
extra synchronization is needed. For the flow control
reasons it may be a good idea to freeze the request queue
until this request gets completed.
2. If requests are completed when the function returns (such
as classic read or write requests on character devices) then
a synchronization flag should be set in the buffer
descriptor and tsleep() called. Later
when the callback gets called it will do its processing and
check this synchronization flag. If it is set then the
callback should issue a wakeup. In this approach the
callback function could either do all the needed processing
(just like the previous case) or simply save the segments
array in the buffer descriptor. Then after callback
completes the calling function could use this saved segments
array and do all the processing.
DMA
The Direct Memory Access (DMA) is implemented in the ISA bus
through the DMA controller (actually, two of them but that is
an irrelevant detail). To make the early ISA devices simple
and cheap the logic of the bus control and address
generation was concentrated in the DMA controller.
Fortunately, FreeBSD provides a set of functions that mostly
hide the annoying details of the DMA controller from the
device drivers.
The simplest case is for the fairly intelligent
devices. Like the bus master devices on PCI they can
generate the bus cycles and memory addresses all by
themselves. The only thing they really need from the DMA
controller is bus arbitration. So for this purpose they
pretend to be cascaded slave DMA controllers. And the only
thing needed from the system DMA controller is to enable the
cascaded mode on a DMA channel by calling the following
function when attaching the driver:
void isa_dmacascade(int channel_number)
All the further activity is done by programming the
device. When detaching the driver no DMA-related functions
need to be called.
For the simpler devices things get more complicated. The
functions used are:
int isa_dma_acquire(int chanel_number)
Reserve a DMA channel. Returns 0 on success or EBUSY
if the channel was already reserved by this or a
different driver. Most of the ISA devices are not able
to share DMA channels anyway, so normally this
function is called when attaching a device. This
reservation was made redundant by the modern interface
of bus resources but still must be used in addition to
the latter. If not used then later, other DMA routines
will panic.
int isa_dma_release(int chanel_number)
Release a previously reserved DMA channel. No
transfers must be in progress when the channel is
released (in addition the device must not try to
initiate transfer after the channel is released).
void isa_dmainit(int chan, u_int
bouncebufsize)
Allocate a bounce buffer for use with the specified
channel. The requested size of the buffer can not exceed
64KB. This bounce buffer will be automatically used
later if a transfer buffer happens to be not
physically contiguous or outside of the memory
accessible by the ISA bus or crossing the 64KB
boundary. If the transfers will be always done from
buffers which conform to these conditions (such as
those allocated by
bus_dmamem_alloc() with proper
limitations) then isa_dmainit()
does not have to be called. But it is quite convenient
to transfer arbitrary data using the DMA controller.
The bounce buffer will automatically care of the
scatter-gather issues.
chan - channel number
bouncebufsize - size of the
bounce buffer in bytes
void isa_dmastart(int flags, caddr_t addr, u_int
nbytes, int chan)
Prepare to start a DMA transfer. This function must be
called to set up the DMA controller before actually
starting transfer on the device. It checks that the
buffer is contiguous and falls into the ISA memory
range, if not then the bounce buffer is automatically
used. If bounce buffer is required but not set up by
isa_dmainit() or too small for
the requested transfer size then the system will
panic. In case of a write request with bounce buffer
the data will be automatically copied to the bounce
buffer.
flags - a bitmask determining the type of operation to
be done. The direction bits B_READ and B_WRITE are mutually
exclusive.
B_READ - read from the ISA bus into memory
B_WRITE - write from the memory to the ISA bus
B_RAW - if set then the DMA controller will remember
the buffer and after the end of transfer will
automatically re-initialize itself to repeat transfer
of the same buffer again (of course, the driver may
change the data in the buffer before initiating
another transfer in the device). If not set then the
parameters will work only for one transfer, and
isa_dmastart() will have to be
called again before initiating the next
transfer. Using B_RAW makes sense only if the bounce
buffer is not used.
addr - virtual address of the buffer
nbytes - length of the buffer. Must be less or equal to
64KB. Length of 0 is not allowed: the DMA controller will
understand it as 64KB while the kernel code will
understand it as 0 and that would cause unpredictable
effects. For channels number 4 and higher the length must
be even because these channels transfer 2 bytes at a
time. In case of an odd length the last byte will not be
transferred.
chan - channel number
void isa_dmadone(int flags, caddr_t addr, int
nbytes, int chan)
Synchronize the memory after device reports that transfer
is done. If that was a read operation with a bounce buffer
then the data will be copied from the bounce buffer to the
original buffer. Arguments are the same as for
isa_dmastart(). Flag B_RAW is
permitted but it does not affect
isa_dmadone() in any way.
int isa_dmastatus(int channel_number)
Returns the number of bytes left in the current transfer
to be transferred. In case the flag B_READ was set in
isa_dmastart() the number returned
will never be equal to zero. At the end of transfer it
will be automatically reset back to the length of
buffer. The normal use is to check the number of bytes
left after the device signals that the transfer is
completed. If the number of bytes is not 0 then something
probably went wrong with that transfer.
int isa_dmastop(int channel_number)
Aborts the current transfer and returns the number of
bytes left untransferred.
xxx_isa_probe
This function probes if a device is present. If the driver
supports auto-detection of some part of device configuration
(such as interrupt vector or memory address) this
auto-detection must be done in this routine.
As for any other bus, if the device cannot be detected or
is detected but failed the self-test or some other problem
happened then it returns a positive value of error. The
value ENXIO must be returned if the device is not
present. Other error values may mean other conditions. Zero
or negative values mean success. Most of the drivers return
zero as success.
The negative return values are used when a PnP device
supports multiple interfaces. For example, an older
compatibility interface and a newer advanced interface which
are supported by different drivers. Then both drivers would
detect the device. The driver which returns a higher value
in the probe routine takes precedence (in other words, the
driver returning 0 has highest precedence, one returning -1
is next, one returning -2 is after it and so on). In result
the devices which support only the old interface will be
handled by the old driver (which should return -1 from the
probe routine) while the devices supporting the new
interface as well will be handled by the new driver (which
should return 0 from the probe routine).
The device descriptor struct xxx_softc is allocated by the
system before calling the probe routine. If the probe
routine returns an error the descriptor will be
automatically deallocated by the system. So if a probing
error occurs the driver must make sure that all the
resources it used during probe are deallocated and that
nothing keeps the descriptor from being safely
deallocated. If the probe completes successfully the
descriptor will be preserved by the system and later passed
to the routine xxx_isa_attach(). If a
driver returns a negative value it can not be sure that it
will have the highest priority and its attach routine will
be called. So in this case it also must release all the
resources before returning and if necessary allocate them
again in the attach routine. When
xxx_isa_probe() returns 0 releasing the
resources before returning is also a good idea and a
well-behaved driver should do so. But in cases where there is
some problem with releasing the resources the driver is
allowed to keep resources between returning 0 from the probe
routine and execution of the attach routine.
A typical probe routine starts with getting the device
descriptor and unit:
struct xxx_softc *sc = device_get_softc(dev);
int unit = device_get_unit(dev);
int pnperror;
int error = 0;
sc->dev = dev; /* link it back */
sc->unit = unit;
Then check for the PnP devices. The check is carried out by
a table containing the list of PnP IDs supported by this
driver and human-readable descriptions of the device models
corresponding to these IDs.
pnperror=ISA_PNP_PROBE(device_get_parent(dev), dev,
xxx_pnp_ids); if(pnperror == ENXIO) return ENXIO;
The logic of ISA_PNP_PROBE is the following: If this card
(device unit) was not detected as PnP then ENOENT will be
returned. If it was detected as PnP but its detected ID does
not match any of the IDs in the table then ENXIO is
returned. Finally, if it has PnP support and it matches on
of the IDs in the table, 0 is returned and the appropriate
description from the table is set by
device_set_desc().
If a driver supports only PnP devices then the condition
would look like:
if(pnperror != 0)
return pnperror;
No special treatment is required for the drivers which do not
support PnP because they pass an empty PnP ID table and will
always get ENXIO if called on a PnP card.
The probe routine normally needs at least some minimal set
of resources, such as I/O port number to find the card and
probe it. Depending on the hardware the driver may be able
to discover the other necessary resources automatically. The
PnP devices have all the resources pre-set by the PnP
subsystem, so the driver does not need to discover them by
itself.
Typically the minimal information required to get access to
the device is the I/O port number. Then some devices allow
to get the rest of information from the device configuration
registers (though not all devices do that). So first we try
to get the port start value:
sc->port0 = bus_get_resource_start(dev,
SYS_RES_IOPORT, 0 /*rid*/); if(sc->port0 == 0) return ENXIO;
The base port address is saved in the structure softc for
future use. If it will be used very often then calling the
resource function each time would be prohibitively slow. If
we do not get a port we just return an error. Some device
drivers can instead be clever and try to probe all the
possible ports, like this:
/* table of all possible base I/O port addresses for this device */
static struct xxx_allports {
u_short port; /* port address */
short used; /* flag: if this port is already used by some unit */
} xxx_allports = {
{ 0x300, 0 },
{ 0x320, 0 },
{ 0x340, 0 },
{ 0, 0 } /* end of table */
};
...
int port, i;
...
port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0 /*rid*/);
if(port !=0 ) {
for(i=0; xxx_allports[i].port!=0; i++) {
if(xxx_allports[i].used || xxx_allports[i].port != port)
continue;
/* found it */
xxx_allports[i].used = 1;
/* do probe on a known port */
return xxx_really_probe(dev, port);
}
return ENXIO; /* port is unknown or already used */
}
/* we get here only if we need to guess the port */
for(i=0; xxx_allports[i].port!=0; i++) {
if(xxx_allports[i].used)
continue;
/* mark as used - even if we find nothing at this port
* at least we won't probe it in future
*/
xxx_allports[i].used = 1;
error = xxx_really_probe(dev, xxx_allports[i].port);
if(error == 0) /* found a device at that port */
return 0;
}
/* probed all possible addresses, none worked */
return ENXIO;
Of course, normally the driver's
identify() routine should be used for
such things. But there may be one valid reason why it may be
better to be done in probe(): if this
probe would drive some other sensitive device crazy. The
probe routines are ordered with consideration of the
sensitive flag: the sensitive devices get probed first and
the rest of the devices later. But the
identify() routines are called before
any probes, so they show no respect to the sensitive devices
and may upset them.
Now, after we got the starting port we need to set the port
count (except for PnP devices) because the kernel does not
have this information in the configuration file.
if(pnperror /* only for non-PnP devices */
&& bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port0,
XXX_PORT_COUNT)<0)
return ENXIO;
Finally allocate and activate a piece of port address space
(special values of start and end mean use those we set by
bus_set_resource()):
sc->port0_rid = 0;
sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,
&sc->port0_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->port0_r == NULL)
return ENXIO;
Now having access to the port-mapped registers we can poke
the device in some way and check if it reacts like it is
expected to. If it does not then there is probably some
other device or no device at all at this address.
Normally drivers do not set up the interrupt handlers until
the attach routine. Instead they do probes in the polling
mode using the DELAY() function for
timeout. The probe routine must never hang forever, all the
waits for the device must be done with timeouts. If the
device does not respond within the time it is probably broken
or misconfigured and the driver must return error. When
determining the timeout interval give the device some extra
time to be on the safe side: although
DELAY() is supposed to delay for the
same amount of time on any machine it has some margin of
error, depending on the exact CPU.
If the probe routine really wants to check that the
interrupts really work it may configure and probe the
interrupts too. But that is not recommended.
/* implemented in some very device-specific way */
if(error = xxx_probe_ports(sc))
goto bad; /* will deallocate the resources before returning */
The function xxx_probe_ports() may also
set the device description depending on the exact model of
device it discovers. But if there is only one supported
device model this can be as well done in a hardcoded way.
Of course, for the PnP devices the PnP support sets the
description from the table automatically.
if(pnperror)
device_set_desc(dev, "Our device model 1234");
Then the probe routine should either discover the ranges of
all the resources by reading the device configuration
registers or make sure that they were set explicitly by the
user. We will consider it with an example of on-board
memory. The probe routine should be as non-intrusive as
possible, so allocation and check of functionality of the
rest of resources (besides the ports) would be better left
to the attach routine.
The memory address may be specified in the kernel
configuration file or on some devices it may be
pre-configured in non-volatile configuration registers. If
both sources are available and different, which one should
be used? Probably if the user bothered to set the address
explicitly in the kernel configuration file they know what
they are doing and this one should take precedence. An
example of implementation could be:
/* try to find out the config address first */
sc->mem0_p = bus_get_resource_start(dev, SYS_RES_MEMORY, 0 /*rid*/);
if(sc->mem0_p == 0) { /* nope, not specified by user */
sc->mem0_p = xxx_read_mem0_from_device_config(sc);
if(sc->mem0_p == 0)
/* can't get it from device config registers either */
goto bad;
} else {
if(xxx_set_mem0_address_on_device(sc) < 0)
goto bad; /* device does not support that address */
}
/* just like the port, set the memory size,
* for some devices the memory size would not be constant
* but should be read from the device configuration registers instead
* to accommodate different models of devices. Another option would
* be to let the user set the memory size as "msize" configuration
* resource which will be automatically handled by the ISA bus.
*/
if(pnperror) { /* only for non-PnP devices */
sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
if(sc->mem0_size == 0) /* not specified by user */
sc->mem0_size = xxx_read_mem0_size_from_device_config(sc);
if(sc->mem0_size == 0) {
/* suppose this is a very old model of device without
* auto-configuration features and the user gave no preference,
* so assume the minimalistic case
* (of course, the real value will vary with the driver)
*/
sc->mem0_size = 8*1024;
}
if(xxx_set_mem0_size_on_device(sc) < 0)
goto bad; /* device does not support that size */
if(bus_set_resource(dev, SYS_RES_MEMORY, /*rid*/0,
sc->mem0_p, sc->mem0_size)<0)
goto bad;
} else {
sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
}
Resources for IRQ and DRQ are easy to check by analogy.
If all went well then release all the resources and return success.
xxx_free_resources(sc);
return 0;
Finally, handle the troublesome situations. All the
resources should be deallocated before returning. We make
use of the fact that before the structure softc is passed to
us it gets zeroed out, so we can find out if some resource
was allocated: then its descriptor is non-zero.
bad:
xxx_free_resources(sc);
if(error)
return error;
else /* exact error is unknown */
return ENXIO;
That would be all for the probe routine. Freeing of
resources is done from multiple places, so it is moved to a
function which may look like:
static void
xxx_free_resources(sc)
struct xxx_softc *sc;
{
/* check every resource and free if not zero */
/* interrupt handler */
if(sc->intr_r) {
bus_teardown_intr(sc->dev, sc->intr_r, sc->intr_cookie);
bus_release_resource(sc->dev, SYS_RES_IRQ, sc->intr_rid,
sc->intr_r);
sc->intr_r = 0;
}
/* all kinds of memory maps we could have allocated */
if(sc->data_p) {
bus_dmamap_unload(sc->data_tag, sc->data_map);
sc->data_p = 0;
}
if(sc->data) { /* sc->data_map may be legitimately equal to 0 */
/* the map will also be freed */
bus_dmamem_free(sc->data_tag, sc->data, sc->data_map);
sc->data = 0;
}
if(sc->data_tag) {
bus_dma_tag_destroy(sc->data_tag);
sc->data_tag = 0;
}
... free other maps and tags if we have them ...
if(sc->parent_tag) {
bus_dma_tag_destroy(sc->parent_tag);
sc->parent_tag = 0;
}
/* release all the bus resources */
if(sc->mem0_r) {
bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->mem0_rid,
sc->mem0_r);
sc->mem0_r = 0;
}
...
if(sc->port0_r) {
bus_release_resource(sc->dev, SYS_RES_IOPORT, sc->port0_rid,
sc->port0_r);
sc->port0_r = 0;
}
}xxx_isa_attachThe attach routine actually connects the driver to the
system if the probe routine returned success and the system
had chosen to attach that driver. If the probe routine
returned 0 then the attach routine may expect to receive the
device structure softc intact, as it was set by the probe
routine. Also if the probe routine returns 0 it may expect
that the attach routine for this device shall be called at
some point in the future. If the probe routine returns a
negative value then the driver may make none of these
assumptions.
The attach routine returns 0 if it completed successfully or
error code otherwise.
The attach routine starts just like the probe routine,
with getting some frequently used data into more accessible
variables.
struct xxx_softc *sc = device_get_softc(dev);
int unit = device_get_unit(dev);
int error = 0;Then allocate and activate all the necessary
resources. Because normally the port range will be released
before returning from probe, it has to be allocated
again. We expect that the probe routine had properly set all
the resource ranges, as well as saved them in the structure
softc. If the probe routine had left some resource allocated
then it does not need to be allocated again (which would be
considered an error).
sc->port0_rid = 0;
sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port0_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->port0_r == NULL)
return ENXIO;
/* on-board memory */
sc->mem0_rid = 0;
sc->mem0_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem0_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->mem0_r == NULL)
goto bad;
/* get its virtual address */
sc->mem0_v = rman_get_virtual(sc->mem0_r);The DMA request channel (DRQ) is allocated likewise. To
initialize it use functions of the
isa_dma*() family. For example:
isa_dmacascade(sc->drq0);The interrupt request line (IRQ) is a bit
special. Besides allocation the driver's interrupt handler
should be associated with it. Historically in the old ISA
drivers the argument passed by the system to the interrupt
handler was the device unit number. But in modern drivers
the convention suggests passing the pointer to structure
softc. The important reason is that when the structures
softc are allocated dynamically then getting the unit number
from softc is easy while getting softc from the unit number is
difficult. Also this convention makes the drivers for
different buses look more uniform and allows them to share
the code: each bus gets its own probe, attach, detach and
other bus-specific routines while the bulk of the driver
code may be shared among them.
sc->intr_rid = 0;
sc->intr_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->intr_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->intr_r == NULL)
goto bad;
/*
* XXX_INTR_TYPE is supposed to be defined depending on the type of
* the driver, for example as INTR_TYPE_CAM for a CAM driver
*/
error = bus_setup_intr(dev, sc->intr_r, XXX_INTR_TYPE,
(driver_intr_t *) xxx_intr, (void *) sc, &sc->intr_cookie);
if(error)
goto bad;
If the device needs to make DMA to the main memory then
this memory should be allocated like described before:
error=bus_dma_tag_create(NULL, /*alignment*/ 4,
/*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_24BIT,
/*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL,
/*maxsize*/ BUS_SPACE_MAXSIZE_24BIT,
/*nsegments*/ BUS_SPACE_UNRESTRICTED,
/*maxsegsz*/ BUS_SPACE_MAXSIZE_24BIT, /*flags*/ 0,
&sc->parent_tag);
if(error)
goto bad;
/* many things get inherited from the parent tag
* sc->data is supposed to point to the structure with the shared data,
* for example for a ring buffer it could be:
* struct {
* u_short rd_pos;
* u_short wr_pos;
* char bf[XXX_RING_BUFFER_SIZE]
* } *data;
*/
error=bus_dma_tag_create(sc->parent_tag, 1,
0, BUS_SPACE_MAXADDR, 0, /*filter*/ NULL, /*filterarg*/ NULL,
/*maxsize*/ sizeof(* sc->data), /*nsegments*/ 1,
/*maxsegsz*/ sizeof(* sc->data), /*flags*/ 0,
&sc->data_tag);
if(error)
goto bad;
error = bus_dmamem_alloc(sc->data_tag, &sc->data, /* flags*/ 0,
&sc->data_map);
if(error)
goto bad;
/* xxx_alloc_callback() just saves the physical address at
* the pointer passed as its argument, in this case &sc->data_p.
* See details in the section on bus memory mapping.
* It can be implemented like:
*
* static void
* xxx_alloc_callback(void *arg, bus_dma_segment_t *seg,
* int nseg, int error)
* {
* *(bus_addr_t *)arg = seg[0].ds_addr;
* }
*/
bus_dmamap_load(sc->data_tag, sc->data_map, (void *)sc->data,
sizeof (* sc->data), xxx_alloc_callback, (void *) &sc->data_p,
/*flags*/0);After all the necessary resources are allocated the
device should be initialized. The initialization may include
testing that all the expected features are functional. if(xxx_initialize(sc) < 0)
goto bad; The bus subsystem will automatically print on the
console the device description set by probe. But if the
driver wants to print some extra information about the
device it may do so, for example:
device_printf(dev, "has on-card FIFO buffer of %d bytes\n", sc->fifosize);
If the initialization routine experiences any problems
then printing messages about them before returning error is
also recommended.The final step of the attach routine is attaching the
device to its functional subsystem in the kernel. The exact
way to do it depends on the type of the driver: a character
device, a block device, a network device, a CAM SCSI bus
device and so on.If all went well then return success. error = xxx_attach_subsystem(sc);
if(error)
goto bad;
return 0; Finally, handle the troublesome situations. All the
resources should be deallocated before returning an
error. We make use of the fact that before the structure
softc is passed to us it gets zeroed out, so we can find out
if some resource was allocated: then its descriptor is
non-zero. bad:
xxx_free_resources(sc);
if(error)
return error;
else /* exact error is unknown */
return ENXIO;That would be all for the attach routine.xxx_isa_detach
If this function is present in the driver and the driver is
compiled as a loadable module then the driver gets the
ability to be unloaded. This is an important feature if the
hardware supports hot plug. But the ISA bus does not support
hot plug, so this feature is not particularly important for
the ISA devices. The ability to unload a driver may be
useful when debugging it, but in many cases installation of
the new version of the driver would be required only after
the old version somehow wedges the system and a reboot will be
needed anyway, so the efforts spent on writing the detach
routine may not be worth it. Another argument that
unloading would allow upgrading the drivers on a production
machine seems to be mostly theoretical. Installing a new
version of a driver is a dangerous operation which should
never be performed on a production machine (and which is not
permitted when the system is running in secure mode). Still,
the detach routine may be provided for the sake of
completeness.
The detach routine returns 0 if the driver was successfully
detached or the error code otherwise.
The logic of detach is a mirror of the attach. The first
thing to do is to detach the driver from its kernel
subsystem. If the device is currently open then the driver
has two choices: refuse to be detached or forcibly close and
proceed with detach. The choice used depends on the ability
of the particular kernel subsystem to do a forced close and
on the preferences of the driver's author. Generally the
forced close seems to be the preferred alternative.
struct xxx_softc *sc = device_get_softc(dev);
int error;
error = xxx_detach_subsystem(sc);
if(error)
return error;
Next the driver may want to reset the hardware to some
consistent state. That includes stopping any ongoing
transfers, disabling the DMA channels and interrupts to
avoid memory corruption by the device. For most of the
drivers this is exactly what the shutdown routine does, so
if it is included in the driver we can just call it.
xxx_isa_shutdown(dev);
And finally release all the resources and return success.
xxx_free_resources(sc);
return 0;xxx_isa_shutdown
This routine is called when the system is about to be shut
down. It is expected to bring the hardware to some
consistent state. For most of the ISA devices no special
action is required, so the function is not really necessary
because the device will be re-initialized on reboot
anyway. But some devices have to be shut down with a special
procedure, to make sure that they will be properly detected
after soft reboot (this is especially true for many devices
with proprietary identification protocols). In any case
disabling DMA and interrupts in the device registers and
stopping any ongoing transfers is a good idea. The exact
action depends on the hardware, so we do not consider it here
in any detail.
xxx_intr
The interrupt handler is called when an interrupt is
received which may be from this particular device. The ISA
bus does not support interrupt sharing (except in some special
cases) so in practice if the interrupt handler is called
then the interrupt almost for sure came from its
device. Still, the interrupt handler must poll the device
registers and make sure that the interrupt was generated by
its device. If not it should just return.
The old convention for the ISA drivers was getting the
device unit number as an argument. This is obsolete, and the
new drivers receive whatever argument was specified for them
in the attach routine when calling
bus_setup_intr(). By the new convention
it should be the pointer to the structure softc. So the
interrupt handler commonly starts as:
static void
xxx_intr(struct xxx_softc *sc)
{
It runs at the interrupt priority level specified by the
interrupt type parameter of
bus_setup_intr(). That means that all
the other interrupts of the same type as well as all the
software interrupts are disabled.
To avoid races it is commonly written as a loop:
while(xxx_interrupt_pending(sc)) {
xxx_process_interrupt(sc);
xxx_acknowledge_interrupt(sc);
}
The interrupt handler has to acknowledge interrupt to the
device only but not to the interrupt controller, the system
takes care of the latter.
diff --git a/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml b/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml
index a08c5e5cec..e72a1fb5ad 100644
--- a/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml
+++ b/en_US.ISO8859-1/books/arch-handbook/mac/chapter.sgml
@@ -1,5716 +1,5716 @@
ChrisCostelloTrustedBSD Projectchris@FreeBSD.orgRobertWatsonTrustedBSD Projectrwatson@FreeBSD.orgThe TrustedBSD MAC FrameworkSynopsisMandatory Access Control (MAC) is a security feature frequently
found in commercial trusted operating systems. MAC supplements
existing Discretionary Access Control (DAC) protections (such as
file system permissions and access control lists) by allowing the
security administrator to define mandatory protections for
system objects. Mandatory protections may be distinguished from
discretionary protections in that DAC is applied at the discretion
of the object owner, whereas MAC protections are defined by the
administrator and applied to all users and objects in the system
and may not be bypassed even by object owners. A variety of
MAC policies have been explored in security research literature
as well as the commercial trusted operating system space. These
include policies such as the Multi-Level Security (MLS)
confidentiality policy, used to prevent inappropriate sharing of
information on multi-user systems, and the Biba integrity policy,
typically used to protect the integrity of system and user
services.The implementation of MAC found in FreeBSD was developed by
the TrustedBSD Project, and includes support for both a number of
specific MAC policies, and for a flexible and extensible security
framework to support the easy creation of new kernel security
policies. This framework isolates the internals of specific MAC
policies from the implementation of kernel services, and
encapsulates the policies in policy modules. Policy modules may
be added to the system without changes to the base kernel, and can
augment the kernel security policy in a variety of ways. In
addition, policies may provide a shared object implementation
of common MAC interfaces for userland applications, permitting
applications to be easily extended to manage labels for new
policies. Support is provided for setting labels on user
processes at login, as well as in a number of other locations where
user context management occurs.This chapter introduces the MAC policy userland and kernel
policy frameworks and provides documentation for a sample MAC
policy module.IntroductionThe TrustedBSD MAC framework provides a mechanism to allow
the compile-time or run-time extension of the kernel access
control model. New system policies may be implemented as
kernel modules and linked to the kernel; if multiple policy
modules are present, their results will be composed. While the
framework is intended to support a variety of access control
models, its design was derived from the requirements of a set
of specific access control models required for the TrustedBSD
and CBOSS Projects. This includes support for fixed and
floating label Biba integrity policies, the MLS
confidentiality policy, the Type Enforcement rule-based access
control policy, and the ability to support layering of the NSA
FLASK framework above the TrustedBSD MAC framework. This
document describes the rough architecture of the framework,
with the understanding that this is a work-in-progress and may
change subtantially as requirements evolve.Kernel ArchitectureThe TrustedBSD MAC framework provides the opportunity for
policy modules to be augment system access control decisions.
Policies are permitted the opportunity to restrict the set of
rights available for processes at a variety of relevant points
in the kernel. In addition, they are provided the opportunity
to tag processes and various kernel objects with labels storing
access control information. Policy modules may register
interest in a subset of the total available events or objects,
and are not required to implement events or objects that are not
relevant to the policy. Multiple modules may be loaded at once,
and the results of the modules are composed as necessary to
build an over-all system policy. Policy modules may be
implemented such that they can be loaded on-demand at run-time,
or such that they may only be loaded early in the boot process.
This permits policies requiring pervasive labeling of all
objects to prevent improper use.Userland Architecture...Entry Point FrameworkFour classes of entry points are offered to policies
registered with the framework: entry points associated with
the registration and management of policies, entry points
denoting initialization, creation, destruction, and other life
cycle events for kernel objects, events assocated with access
control decisions that the policy module may influence, and
calls associated with the management of labels on objects. In
addition, a mac_syscall() entry point is
provided so that policies may extend the kernel interface
without registering new system calls.Policy module writers should be aware of the kernel
locking strategy, as well as what object locks are available
during which entry points. Writers should attempt to avoid
deadlock scenarios by avoiding grabbing non-leaf locks inside
of entry points, and also follow the locking protocol for
object access and modification. In particular, writers should
be aware that while necessary locks to access objects and
their labels are generally held, sufficient locks to modify an
object or its label may not be present for all entry points.
Locking information for arguments is documented in the MAC
framework entry point document.Policy entry points will pass a reference to the object
label along with the object itself. This permits labeled
policies to be unaware of the internals of the object yet
still make decisions based on the label. The exception to this
is the process credential, which is assumed to be understood
by policies as a first class security object in the kernel.
Policies that do not implement labels on kernel objects will
be passed NULL pointers for label arguments to entry
points.Policy Module RegistrationModules may be declared using the
MAC_POLICY_SET() macro, which names the
policy, provides a reference to the MAC entry point vector,
provides load-time flags determining how the policy framework
should handle the policy, and optionally requests the
allocation of label state by the framework:static struct mac_policy_op_entry mac_none_ops[] =
{
{ MAC_DESTROY,
(macop_t)mac_none_destroy },
{ MAC_INIT,
(macop_t)mac_none_init },
{ MAC_INIT_BPFDESC,
(macop_t)mac_none_init_bpfdesc },
/* ... */
{ MAC_CHECK_VNODE_STAT,
(macop_t)mac_none_check_vnode_stat },
{ MAC_CHECK_VNODE_WRITE,
(macop_t)mac_none_check_vnode_write },
{ MAC_OP_LAST, NULL }
};The MAC policy entry point vector,
mac_none_ops in this example, associates
functions defined in the module with specific entry points. A
complete listing of available entry points and their
prototypes may be found in the MAC entry point reference
section. Of specific interest during module registration are
the MAC_DESTROY and MAC_INIT
entry points. MAC_INIT will be invoked once a
policy is successfully registered with the module framework
but prior to any other entry points becoming active. This
permits the policy to perform any policy-specific allocation
and initialization, such as initialization of any data or
locks. MAC_DESTROY will be invoked when a
policy module is unloaded to permit releasing of any allocated
memory and destruction of locks. Currently, these two entry
points are invoked with the MAC policy list mutex held to
prevent any other entry points from being invoked: this will
be changed, but in the mean time, policies should be careful
about what kernel primitives they invoke so as to avoid lock
ordering or sleeping problems.The policy declaration's module name field exists so that
the module may be uniquely identified for the purposes of
module dependencies. An appropriate string should be selected.
The full string name of the policy is displayed to the user
via the kernel log during load and unload events, and also
exported when providing status information to userland
processes.The policy flags field permits the module to provide the
framework with information about its loader-related
capabilities. Currently, two flags are defined:MPC_LOADTIME_FLAG_UNLOADOKThis flag indicates that the policy module may be
unloaded. If this flag is not provided, then the policy
framework will reject requests to unload the module.
This flag might be used by modules that allocate label
state and are unable to free that state at
runtime.MPC_LOADTIME_FLAG_NOTLATEThis flag indicates that the policy module
must be loaded and initialized early in the boot
process. If the flag is specified, attempts to register
the module following boot will be rejected. The flag
may be used by policies that require pervasive labeling
of all system objects, and cannot handle objects that
have not been properly initialized by the policy.&mac.mpo;_initvoid
&mac.mpo;_initstruct mac_policy_conf
*conf
&mac.thead;
confMAC policy definitionPolicy load event. The policy list mutex is held, so
caution should be applied.&mac.mpo;_destroyvoid
&mac.mpo;_destroystruct mac_policy_conf
*conf
&mac.thead;
confMAC policy definitionPolicy load event. The policy list mutex is held, so
caution should be applied.Label EventsThis class of entry points is used by the MAC framework to
permit policies to maintain label information on kernel
objects. For each labeled kernel object of interest to a MAC
policy, entry points may be registered for relevant life cycle
events. All objects implement initialization, creation, and
destruction hooks. Some objects will also implement
relabeling, allowing user processes to change the labels on
objects. Some objects will also implement object-specific
events, such as label events associated with IP reassembly. A
typical labeled object will have the following life cycle of
entry points:Label initialization o
(object-specific wait) \
Label creation o
\
Relabel events, o--<--.
Various object-specific, | |
Access control events ~-->--o
\
Label destruction oLabel initialization permits policies to allocate memory
and set initial values for labels without context for the use
of the object. The label slot allocated to a policy will be
zero'd by default, so some policies may not need to perform
initialization.Label creation occurs when the kernel structure is
associated with an actual kernel object. For example, mbufs
may be allocated and remain unused in a pool until they are
required. mbuf allocation causes label initialization on the
mbuf to take place, but mbuf creation occurs when the mbuf is
associated with a datagram. Typically, context will be
provided for a creation event, including the circumstances of
the creation, and labels of other relevant objects in the
creation process. For example, when an mbuf is created from a
socket, the socket and its label will be presented to
registered policies in addition to the new mbuf and its label.
Memory allocation in creation events is discouraged, as it may
occur in performance sensitive ports of the kernel; in
addition, creation calls are not permitted to fail so a
failure to allocate memory cannot be reported.Object specific events do not generally fall into the
other broad classes of label events, but will generally
provide an opportunity to modify or update the label on an
object based on additional context. For example, the label on
an IP fragment reassembly queue may be updated during the
MAC_UPDATE_IPQ entry point as a result of the
acceptance of an additional mbuf to that queue.Access control events are discussed in detail in the
following section.Label destruction permits policies to release storage or
state associated with a label during its association with an
object so that the kernel data structures supporting the
object may be reused or released.In addition to labels associated with specific kernel
objects, an additional class of labels exists: temporary
labels. These labels are used to store update information
submitted by user processes. These labels are initialized and
destroyed as with other label types, but the creation event is
MAC_INTERNALIZE, which accepts a user label
to be converted to an in-kernel representation.File System Object Labeling Event Operations&mac.mpo;_create_devfs_devicevoid
&mac.mpo;_create_devfs_devicedev_t devstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
devDevice corresponding with
devfs_direntdevfs_direntDevfs directory entry to be labeled.labelLabel for devfs_dirent
to be filled in.Fill out the label on a devfs_dirent being created for
the passed device. This call will be made when the device
file system is mounted, regenerated, or a new device is made
available.&mac.mpo;_create_devfs_directoryvoid
&mac.mpo;_create_devfs_directorychar *dirnameint dirnamelenstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
dirnameName of directory being creatednamelenLength of string
dirnamedevfs_direntDevfs directory entry for directory being
created.Fill out the label on a devfs_dirent being created for
the passed directory. This call will be made when the device
file system is mounted, regenerated, or a new device
requiring a specific directory hierarchy is made
available.&mac.mpo;_create_devfs_vnodevoid
&mac.mpo;_create_devfs_vnodestruct devfs_dirent
*devfs_direntstruct label
*direntlabelstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
devfs_direntObject; devfs directory entrydirentlabelPolicy label for
devfs_direntvpObject; file system object being labeledvnodelabelPolicy label to be filled in for
vpFill out the label on the vnode being created for the
passed devfs_dirent. This call will be made when a vnode is
required to represent the specified devfs_dirent in a
mounted devfs instance.&mac.mpo;_vnode_create_from_vnodevoid
&mac.mpo;_vnode_create_from_vnodestruct ucred
*credstruct vnode
*parentstruct label
*parentlabelstruct vnode
*childstruct label
*childlabel
&mac.thead;
credSubject credentialparentParent vnode; the directory in which
child is being
createdparentlabelPolicy label for
parentchildNew vnodechildlabelLabel to be filled in for
childFill out the label on the vnode being created in the
passed vnode parent by the passed subject credential. This
call will be made when a vnode is allocated during a vnode
creation operation. For example, this call is made by
multi-label file systems during the creation of a new file
or directory.&mac.mpo;_create_mountvoid
&mac.mpo;_create_mountstruct ucred
*credstruct mount
*mpstruct label
*mntstruct label
*fslabel
&mac.thead;
credSubject credentialmpObject; file system being mountedmntlabelPolicy label to be filled in for
mpfslabelPolicy label for the file system
mp mounts.Fill out the labels on the mount point being created by
the passed subject credential. This call will be made when
a new file system is mounted.&mac.mpo;_create_root_mountvoid
&mac.mpo;_create_root_mountstruct ucred
*credstruct mount
*mpstruct label
*mntlabelstruct label
*fslabel
&mac.thead;
See .Fill out the labels on the mount point being created by
the passed subject credential. This call will be made when
the root file system is mounted, after
&mac.mpo;_create_mount;.&mac.mpo;_vnode_relabelvoid
&mac.mpo;_vnode_relabelstruct ucred
*credstruct vnode
*vpstruct label
*vnodelabelstruct label
*newlabel
&mac.thead;
credSubject credentialvpvnode to relabelvnodelabelExisting policy label for
vpnewlabelNew, possibly partial label to replace
vnodelabelUpdate the label on the passed vnode given the passed
update vnode label and the passed subject credential.&mac.mpo;_stdcreatevnode_eaint
&mac.mpo;_stdcreatevnode_eastruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
vpvnode to commitLocked on entry, locked on exitvnodelabelLabel associated with
vpThis entry point is called when a vnode is to be
committed to disk via the extended attribute service (see
&man.extattr.9;). If committing to the disk is successful,
a value of 0 should be returned;
otherwise, an appropriate error code should be
returned.The current implementation as of July 24, 2002
commits the data to disk from within the architecture.
The implementation will be updated to be closer to the
above documentation as development progresses.&mac.mpo;_update_devfsdirentvoid
&mac.mpo;_update_devfsdirentstruct devfs_dirent
*devfs_direntstruct label
*direntlabelstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
devfs_direntObject; devfs directory entrydirentlabelPolicy label for
devfs_dirent to be
updated.vpParent vnodeLockedvnodelabelPolicy label for
vpUpdate the devfs_dirent label
from the passed devfs vnode label. This call will be made
when a devfs vnode has been successfully relabeled to commit
the label change such that it lasts even if the vnode is
recycled. It will also be made when when a symlink is
created in devfs, following a call to
mac_vnode_create_from_vnode to
initialize the vnode label.&mac.mpo;_update_procfsvnodevoid
&mac.mpo;_update_procfsvnodestruct vnode
*vpstruct label
*vnodelabelstruct ucred
*cred
&mac.thead;
vpObject; procfs vnodeLockedvnodelabelPolicy label to be filled in for
vpcredSubject; credential for the process
entryImmutableUpdate the procfs vnode label from the passed subject
credential. This call will be made when an operation on a
procfs vnode requires a fresh label on a process-derived
vnode.&mac.mpo;_update_vnode_from_extattrint
&mac.mpo;_update_vnode_from_extattrstruct vnode
*vpstruct label
*vnodelabelstruct mount
*mpstruct label
*fslabel
&mac.thead;
vpObject; vnode whose label is being updatedLockedvnodelabelPolicy label to refreshmpMount point for
vpfslabelPolicy label for vp's
file system.Update the vnode label by refreshing the label data from
the extended attribute service for the vnode. The mount
point fslabel is also made available
so that the fslabel may be used as a
labeling source if fallback is appropriate for the policy.
This call is permitted to fail; if the call fails, the
associated label refresh will also fail, causing the failure
of the operation requiring the MAC check and vnode label
refresh, permitting a fail closed policy if
labeling data is not available.&mac.mpo;_update_from_externalizedint
&mac.mpo;_update_from_externalizedstruct vnode
*vpstruct label
*vnodelabelstruct mac
*extmac
&mac.thead;
vpObject; vnodeLockedvnodelabelPolicy label for
vpextmacExternalized MAC policy labelUpdate the vnode label from the passed externalized
label loaded from disk by the MAC framework. This call is
permitted to fail; if the call fails, the associated label
refresh will also fail, causing the failure of the operation
requiring the MAC check and vnode label refresh, permitting
a fail closed policy if labeling data is not
available. This call will be obsoleted by the new extended
attribute labeling interface.&mac.mpo;_update_vnode_from_mountvoid
&mac.mpo;_update_vnode_from_mountstruct vnode
*vpstruct label
*vnodelabelstruct mount
*mpstruct label
*mountlabel
&mac.thead;
vpObject; vnodeLockedvnodelabelPolicy label for
vpmpMount point where vp
residesfslabelPolicy label for the file system where
vp resides.Update the vnode label from the passed mount point
label. This call is made when a single label file system
vnode requires a label, or if the obsoleted MAC framework
externalized extended attribute read fails.IPC Object Labeling Event Operations&mac.mpo;_create_mbuf_from_socketvoid
&mac.mpo;_create_mbuf_from_socketstruct socket
*sostruct label
*socketlabelstruct mbuf *mstruct label
*mbuflabel
&mac.thead;
socketSocketSocket locking WIPsocketlabelPolicy label for
socketmObject; mbufmbuflabelPolicy label to fill in for
mSet the label on a newly created mbuf header from the
passed socket label. This call is made when a new datagram
or messsage is generated by the socket and stored in the
passed mbuf.&mac.mpo;_create_socketvoid
&mac.mpo;_create_socketstruct ucred
*credstruct socket
*sostruct label
*socketlabel
&mac.thead;
credSubject credentialImmutablesoObject; socket to labelsocketlabelLabel to fill in for
soSet the label on a newly created socket from the passed
subject credential. This call is made when a socket is
created.&mac.mpo;_create_socket_from_socketvoid
&mac.mpo;_create_socket_from_socketstruct socket
*oldsocketstruct label
*oldsocketlabelstruct socket
*newsocketstruct label
*newsocketlabel
&mac.thead;
oldsocketObject; parent socket; created from
&man.listen.2;oldsocketlabelLabel for
oldsocketnewsocketObject; child socket; incoming connectionnewsocketlabelLabel to be filled in for
newsocketSet the label on a newly created stream socket from the
passed listen socket. This call may occur during &man.accept.2;,
or prior to &man.accept.2;, depending on the protocol.&mac.mpo;_socket_relabelvoid
&mac.mpo;_socket_relabelstruct ucred
*credstruct socket
*sostruct label
*oldlabelstruct label
*newlabel
&mac.thead;
credSubject credentialImmutablesoObject; socketoldlabelCurrent label for
sonewlabelLabel update for
soUpdate the label on a socket from the passed socket
label update.&mac.mpo;_set_socket_peer_from_mbufvoid
&mac.mpo;_set_socket_peer_from_mbufstruct mbuf
*mbufstruct label
*mbuflabelstruct label
*oldlabelstruct label
*newlabel
&mac.thead;
mbufFirst datagram received over socketmbuflabelLabel for mbufoldlabelCurrent label for the socketnewlabelPolicy label to be filled out for the
socketSet the peer label on a stream socket from the passed
mbuf label. This call will be made when the first datagram
is received by the stream socket, with the exception of Unix
domain sockets.&mac.mpo;_set_socket_peer_from_socketvoid
&mac.mpo;_set_socket_peer_from_socketstruct socket
*oldsocketstruct label
*oldsocketlabelstruct socket
*newsocketstruct label
*newsocketpeerlabel
&mac.thead;
oldsocketLocal socketoldsocketlabelPolicy label for
oldsocketnewsocketPeer socketnewsocketpeerlabelPolicy label to fill in for
newsocketSet the peer label on a stream UNIX domain socket from
the passed remote socket endpoint. This call will be made
when the socket pair is connected, and will be made for both
endpoints.Network Object Labeling Event Operations&mac.mpo;_create_bpfdescvoid
&mac.mpo;_create_bpfdescstruct ucred
*credstruct bpf_d
*bpf_dstruct label
*bpflabel
&mac.thead;
credSubject credentialImmutablebpf_dObject; bpf descriptorbpfPolicy label to be filled in for
bpf_dSet the label on a newly created BPF descriptor from the
passed subject credential. This call will be made when a
BPF device node is opened by a process with the passed
subject credential.&mac.mpo;_create_ifnetvoid
&mac.mpo;_create_ifnetstruct ifnet
*ifnetstruct label
*ifnetlabel
&mac.thead;
ifnetNetwork interfaceifnetlabelPolicy label to fill in for
ifnetSet the label on a newly created interface. This call
may be made when a new physical interface becomes available
to the system, or when a pseudo-interface is instantiated
during the boot or as a result of a user action.&mac.mpo;_create_ipqvoid
&mac.mpo;_create_ipqstruct mbuf
*fragmentstruct label
*fragmentlabelstruct ipq
*ipqstruct label
*ipqlabel
&mac.thead;
fragmentFirst received IP fragmentfragmentlabelPolicy label for
fragmentipqIP reassembly queue to be labeledipqlabelPolicy label to be filled in for
ipqSet the label on a newly created IP fragment reassembly
queue from the mbuf header of the first received
fragment.&mac.mpo;_create_datagram_from_ipqvoid
&mac.mpo;_create_create_datagram_from_ipqstruct ipq
*ipqstruct label
*ipqlabelstruct mbuf
*datagramstruct label
*datagramlabel
&mac.thead;
ipqIP reassembly queueipqlabelPolicy label for
ipqdatagramDatagram to be labeleddatagramlabelPolicy label to be filled in for
datagramlabelSet the label on a newly reassembled IP datagram from
the IP fragment reassembly queue from which it was
generated.&mac.mpo;_create_fragmentvoid
&mac.mpo;_create_fragmentstruct mbuf
*datagramstruct label
*datagramlabelstruct mbuf
*fragmentstruct label
*fragmentlabel
&mac.thead;
datagramDatagramdatagramlabelPolicy label for
datagramfragmentFragment to be labeledfragmentlabelPolicy label to be filled in for
datagramSet the label on the mbuf header of a newly created IP
fragment from the label on the mbuf header of the datagram
it was generate from.&mac.mpo;_create_mbuf_from_mbufvoid
&mac.mpo;_create_mbuf_from_mbufstruct mbuf
*oldmbufstruct label
*oldmbuflabelstruct mbuf
*newmbufstruct label
*newmbuflabel
&mac.thead;
oldmbufExisting (source) mbufoldmbuflabelPolicy label for
oldmbufnewmbufNew mbuf to be labelednewmbuflabelPolicy label to be filled in for
newmbufSet the label on the mbuf header of a newly created
datagram from the mbuf header of an existing datagram. This
call may be made in a number of situations, including when
an mbuf is re-allocated for alignment purposes.&mac.mpo;_create_mbuf_linklayervoid
&mac.mpo;_create_mbuf_linklayerstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
ifnetNetwork interfaceifnetlabelPolicy label for
ifnetmbufmbuf header for new datagrammbuflabelPolicy label to be filled in for
mbufSet the label on the mbuf header of a newly created
datagram generated for the purposes of a link layer response
for the passed interface. This call may be made in a number
of situations, including for ARP or ND6 responses in the
IPv4 and IPv6 stacks.&mac.mpo;_create_mbuf_from_bpfdescvoid
&mac.mpo;_create_mbuf_from_bpfdescstruct bpf_d
*bpf_dstruct label
*bpflabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
bpf_dBPF descriptorbpflabelPolicy label for
bpflabelmbufNew mbuf to be labeledmbuflabelPolicy label to fill in for
mbufSet the label on the mbuf header of a newly created
datagram generated using the passed BPF descriptor. This
call is made when a write is performed to the BPF device
associated with the passed BPF descriptor.&mac.mpo;_create_mbuf_from_ifnetvoid
&mac.mpo;_create_mbuf_from_ifnetstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
ifnetNetwork interfaceifnetlabelPolicy label for
ifnetlabelmbufmbuf header for new datagrammbuflabelPolicy label to be filled in for
mbufSet the label on the mbuf header of a newly created
datagram generated from the passed network interface.&mac.mpo;_create_mbuf_multicast_encapvoid
&mac.mpo;_create_mbuf_multicast_encapstruct mbuf
*oldmbufstruct label
*oldmbuflabelstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*newmbufstruct label
*newmbuflabel
&mac.thead;
oldmbufmbuf header for existing datagramoldmbuflabelPolicy label for
oldmbufifnetNetwork interfaceifnetlabelPolicy label for
ifnetnewmbufmbuf header to be labeled for new
datagramnewmbuflabelPolicy label to be filled in for
newmbufSet the label on the mbuf header of a newly created
datagram generated from the existing passed datagram when it
is processed by the passed multicast encapsulation
interface. This call is made when an mbuf is to be
delivered using the virtual interface.&mac.mpo;_create_mbuf_netlayervoid
&mac.mpo;_create_mbuf_netlayerstruct mbuf
*oldmbufstruct label
*oldmbuflabelstruct mbuf
*newmbufstruct label
*newmbuflabel
&mac.thead;
oldmbufReceived datagramoldmbuflabelPolicy label for
oldmbufnewmbufNewly created datagramnewmbuflabelPolicy label for
newmbufSet the label on the mbuf header of a newly created
datagram generated by the IP stack in response to an
existing received datagram (oldmbuf).
This call may be made in a number of situations, including
when responding to ICMP request datagrams.&mac.mpo;_fragment_matchint
&mac.mpo;_fragment_matchstruct mbuf
*fragmentstruct label
*fragmentlabelstruct ipq
*ipqstruct label
*ipqlabel
&mac.thead;
fragmentIP datagram fragmentfragmentlabelPolicy label for
fragmentipqIP fragment reassembly queueipqlabelPolicy label for
ipqDetermine whether an mbuf header containing an IP
datagram (fragment) fragment matches
the label of the passed IP fragment reassembly queue
(ipq). Return
(1) for a successful match, or
(0) for no match. This call is
made when the IP stack attempts to find an existing fragment
reassembly queue for a newly received fragment; if this
fails, a new fragment reassembly queue may be instantiated
for the fragment. Policies may use this entry point to
prevent the reassembly of otherwise matching IP fragments if
policy does not permit them to be reassembled based on the
label or other information.&mac.mpo;_ifnet_relabelvoid
&mac.mpo;_ifnet_relabelstruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct label
*newlabel
&mac.thead;
credSubject credentialifnetObject; Network interfaceifnetlabelPolicy label for
ifnetnewlabelLabel update to apply to
ifnetUpdate the label of network interface,
ifnet, based on the passed update
label, newlabel, and the passed
subject credential, cred.&mac.mpo;_update_ipqvoid
&mac.mpo;_update_ipqstruct mbuf
*fragmentstruct label
*fragmentlabelstruct ipq
*ipqstruct label
*ipqlabel
&mac.thead;
mbufIP fragmentmbuflabelPolicy label for
mbufipqIP fragment reassembly queueipqlabelPolicy label to be updated for
ipqUpdate the label on an IP fragment reassembly queue
(ipq) based on the acceptance of the
passed IP fragment mbuf header
(mbuf).Process Labeling Event Operations&mac.mpo;_create_credvoid
&mac.mpo;_create_credstruct ucred
*parent_credstruct ucred
*child_cred
&mac.thead;
parent_credParent subject credentialchild_credChild subject credentialSet the label of a newly created subject credential from
the passed subject credential. This call will be made when
crcopy(9) is invoked on a newly created struct
ucred. This call should not be confused with a
process forking or creation event.&mac.mpo;_execve_transitionvoid
&mac.mpo;_execve_transitionstruct ucred
*oldstruct ucred
*newstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
oldExisting subject credentialImmutablenewNew subject credential to be labeledvpFile to executeLockedvnodelabelPolicy label for
vpUpdate the label of a newly created subject credential
(new) from the passed existing
subject credential (old) based on a
label transition caused by executing the passed vnode
(vp). This call occurs when a
process executes the passed vnode and one of the policies
returns a success from the
mpo_execve_will_transition entry point.
Policies may choose to implement this call simply by
invoking mpo_create_cred and passing
the two subject credentials so as not to implement a
transitioning event. Policies should not leave this entry
point unimplemented if they implement
mpo_create_cred, even if they do not
implement
mpo_execve_will_transition.&mac.mpo;_execve_will_transitionint
&mac.mpo;_execve_will_transitionstruct ucred
*oldstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
oldSubject credential prior to
&man.execve.2;ImmutablevpFile to executevnodelabelPolicy label for
vpDetermine whether the policy will want to perform a
transition event as a result of the execution of the passed
vnode by the passed subject credential. Return
1 if a transition is required,
0 if not. Even if a policy
returns 0, it should behave
correctly in the presence of an unexpected invocation of
mpo_execve_transition, as that call may
happen as a result of another policy requesting a
transition.&mac.mpo;_create_proc0void
&mac.mpo;_create_proc0struct ucred
*cred
&mac.thead;
credSubject credential to be filled inCreate the subject credential of process 0, the parent
of all kernel processes.&mac.mpo;_create_proc1void
&mac.mpo;_create_proc1struct ucred
*cred
&mac.thead;
credSubject credential to be filled inCreate the subject credential of process 1, the parent
of all kernel processes.&mac.mpo;_cred_relabelvoid
&mac.mpo;_cred_relabelstruct ucred
*credstruct label
*newlabel
&mac.thead;
credSubject credentialnewlabelLabel update to apply to
credUpdate the label on a subject credential from the passed
update label.Access Control ChecksAccess control entry points permit policy modules to
influence access control decisions made by the kernel.
Generally, although not always, arguments to an access control
entry point will include one or more authorizing credentials,
information (possibly including a label) for any other objects
involved in the operation. An access control entry point may
return 0 to permit the operation, and an &man.errno.2; error
value. The results of invoking the entry point across various
registered policy modules will be composed as follows: if all
modules permit the operation to succeed, success will be
returned. If one or modules returns a failure, a failure will
be returned. If more than one module returns a failure, the
errno value to return to the user will be selected using the
following precedence, implemented by the
error_select() function in
kern_mac.c:Most precedenceEDEADLKEINVALESRCHENOENTEACCESLeast precedenceEPERMIf none of the error values returned by all modules are
listed in the precedence chart then an arbitrarily selected
value from the set will be returned. In general, the rules
provide precedence to errors in the following order: kernel
failures, invalid arguments, object not present, access not
permitted, other.&mac.mpo;_check_bpfdesc_receiveint
&mac.mpo;_check_bpfdesc_receivestruct bpf_d
*bpf_dstruct label
*bpflabelstruct ifnet
*ifnetstruct label
*ifnetlabel
&mac.thead;
bpf_dSubject; BPF descriptorbpflabelPolicy label for
bpf_difnetObject; network interfaceifnetlabelPolicy label for
ifnetDetermine whether the MAC framework should permit
datagrams from the passed interface to be delivered to the
buffers of the passed BPF descriptor. Return
(0) for success, or an
errno value for failure Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege.&mac.mpo;_check_socket_bindint
&mac.mpo;_check_socket_bindstruct ucred
*credstruct socket
*socketstruct label
*socketlabelstruct sockaddr
*sockaddr
&mac.thead;
credSubject credentialsocketSocket to be boundsocketlabelPolicy label for
socketsockaddrAddress of
socket&mac.mpo;_check_socket_connectint
&mac.mpo;_check_socket_connectstruct ucred
*credstruct socket
*socketstruct label
*socketlabelstruct sockaddr
*sockaddr
&mac.thead;
credSubject credentialsocketSocket to be connectedsocketlabelPolicy label for
socketsockaddrAddress of
socketDetermine whether the subject credential
(cred) can connect the passed socket
(socket) to the passed socket address
(sockaddr). Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege.&mac.mpo;_check_cred_visibleint
&mac.mpo;_check_cred_visiblestruct ucred
*u1struct ucred
*u2
&mac.thead;
u1Subject credentialu2Object credentialDetermine whether the subject credential
u1 can see other
subjects with the passed subject credential
u2. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege, or
ESRCH to hide visibility. This call
may be made in a number of situations, including
inter-process status sysctls used by ps,
and in procfs lookups.&mac.mpo;_check_socket_visibleint
&mac.mpo;_check_socket_visiblestruct ucred
*credstruct socket
*socketstruct label
*socketlabel
&mac.thead;
credSubject credentialsocketObject; socketsocketlabelPolicy label for
socket&mac.mpo;_check_ifnet_relabelint
&mac.mpo;_check_ifnet_relabelstruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct label
*newlabel
&mac.thead;
credSubject credentialifnetObject; network interfaceifnetlabelExisting policy label for
ifnetnewlabelPolicy label update to later be applied to
ifnetDetermine whether the subject credential can relabel the
passed network interface to the passed label update.&mac.mpo;_check_socket_relabelint
&mac.mpo;_check_socket_relabelstruct ucred
*credstruct socket
*socketstruct label
*socketlabelstruct label
*newlabel
&mac.thead;
credSubject credentialsocketObject; socketsocketlabelExisting policy label for
socketnewlabelLabel update to later be applied to
socketlabelDetermine whether the subject credential can relabel the
passed socket to the passed label update.&mac.mpo;_check_cred_relabelint
&mac.mpo;_check_cred_relabelstruct ucred
*credstruct label
*newlabel
&mac.thead;
credSubject credentialnewlabelLabel update to later be applied to
credDetermine whether the subject credential can relabel
itself to the passed label update.&mac.mpo;_check_vnode_relabelint
&mac.mpo;_check_vnode_relabelstruct ucred
*credstruct vnode
*vpstruct label
*vnodelabelstruct label
*newlabel
&mac.thead;
credSubject credentialImmutablevpObject; vnodeLockedvnodelabelExisting policy label for
vpnewlabelPolicy label update to later be applied to
vpDetermine whether the subject credential can relabel the
passed vnode to the passed label update.&mac.mpo;_check_mount_statint &mac.mpo;_check_mount_statstruct ucred
*credstruct mount
*mpstruct label
*mountlabel
&mac.thead;
credSubject credentialmpObject; file system mountmountlabelPolicy label for
mpDetermine whether the subject credential can see the
results of a statfs performed on the file system. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches
or EPERM for lack of privilege. This
call may be made in a number of situations, including during
invocations of &man.statfs.2; and related calls, as well as to
determine what file systems to exclude from listings of file
systems, such as when &man.getfsstat.2; is invoked. &mac.mpo;_check_proc_debugint
&mac.mpo;_check_proc_debugstruct ucred
*credstruct proc
*proc
&mac.thead;
credSubject credentialImmutableprocObject; processDetermine whether the subject credential can debug the
passed process. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, EPERM for lack of
privilege, or ESRCH to hide
visibility of the target. This call may be made in a number
of situations, including use of the &man.ptrace.2; and
&man.ktrace.2; APIs, as well as for some types of procfs
operations.&mac.mpo;_check_vnode_accessint
&mac.mpo;_check_vnode_accessstruct ucred
*credstruct vnode
*vpstruct label
*labelint flags
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpflags&man.access.2; flagsDetermine how invocations of &man.access.2; and related
calls by the subject credential should return when performed
on the passed vnode using the passed access flags. This
should generally be implemented using the same semantics
used in &mac.mpo;_check_vnode_open.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_chdirint
&mac.mpo;_check_vnode_chdirstruct ucred
*credstruct vnode
*dvpstruct label
*dlabel
&mac.thead;
credSubject credentialdvpObject; vnode to &man.chdir.2; intodlabelPolicy label for
dvpDetermine whether the subject credential can change the
process working directory to the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_createint
&mac.mpo;_check_vnode_createstruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct componentname
*cnpstruct vattr
*vap
&mac.thead;
credSubject credentialdvpObject; vnodedlabelPolicy label for
dvpcnpComponent name for
dvpvapvnode attributes for vapDetermine whether the subject credential can create a
vnode with the passed parent directory, passed name
information, and passed attribute information. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES. for label mismatch,
or EPERM for lack of privilege.
This call may be made in a number of situations, including
as a result of calls to &man.open.2; with
O_CREAT, &man.mknod.2;, &man.mkfifo.2;, and
others.&mac.mpo;_check_vnode_deleteint
&mac.mpo;_check_vnode_deletestruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct vnode
*vpvoid *labelstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpParent directory vnodedlabelPolicy label for
dvpvpObject; vnode to deletelabelPolicy label for
vpcnpComponent name for
vpDetermine whether the subject credential can delete a
vnode from the passed parent directory and passed name
information. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege. This call may be made in a number of situations,
including as a result of calls to &man.unlink.2; and
&man.rmdir.2;. Policies implementing this entry point
should also implement
mpo_check_rename_to to authorize
deletion of objects as a result of being the target of a
rename.&mac.mpo;_check_vnode_deleteaclint
&mac.mpo;_check_vnode_deleteaclstruct ucred *credstruct vnode *vpstruct label *labelacl_type_t type
&mac.thead;
credSubject credentialImmutablevpObject; vnodeLockedlabelPolicy label for
vptypeACL typeDetermine whether the subject credential can delete the
ACL of passed type from the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_execint
&mac.mpo;_check_vnode_execstruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnode to executelabelPolicy label for
vpDetermine whether the subject credential can execute the
passed vnode. Determination of execute privilege is made
- seperately from decisions about any transitioning event.
+ separately from decisions about any transitioning event.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_getaclint
&mac.mpo;_check_vnode_getaclstruct ucred
*credstruct vnode
*vpstruct label
*labelacl_type_t
type
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vptypeACL typeDetermine whether the subject credentical can retrieve
the ACL of passed type from the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_getextattrint
&mac.mpo;_check_vnode_getextattrstruct ucred
*credstruct vnode
*vpstruct label
*labelint
attrnamespaceconst char
*namestruct uio
*uio
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpattrnamespaceExtended attribute namespacenameExtended attribute nameuioI/O structure pointer; see &man.uio.9;Determine whether the subject credential can retrieve
the extended attribute with the passed namespace and name
from the passed vnode. Policies implementing labeling using
extended attributes may be interested in special handling of
operations on those extended attributes. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_socket_listenint
&mac.mpo;_check_socket_listenstruct ucred
*credstruct socket
*socketstruct label
*socketlabel
&mac.thead;
credSubject credentialsocketObject; socketsocketlabelPolicy label for
socketDetermine whether the subject credential can listen on
the passed socket. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege.&mac.mpo;_check_vnode_lookupint
&mac.mpo;_check_vnode_lookupstruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpObject; vnodedlabelPolicy label for
dvpcnpComponent name being looked upDetermine whether the subject credential can perform a
lookup in the passed directory vnode for the passed name.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_openint
&mac.mpo;_check_vnode_openstruct ucred
*credstruct vnode
*vpstruct label
*labelmode_t
acc_mode
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpacc_mode&man.open.2; access modeDetermine whether the subject credential can perform an
open operation on the passed vnode with the passed access
mode. Return 0 for success, or
an errno value for failure. Suggested failure:
EACCES for label mismatch, or
EPERM for lack of privilege.&mac.mpo;_check_vnode_readdirint
&mac.mpo;_check_vnode_readdirstruct ucred
*credstruct vnode
*dvpstruct label
*dlabel
&mac.thead;
credSubject credentialdvpObject; directory vnodedlabelPolicy label for
dvpDetermine whether the subject credential can perform a
readdir operation on the passed
directory vnode. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege.&mac.mpo;_check_vnode_readlinkint
&mac.mpo;_check_vnode_readlinkstruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpDetermine whether the subject credential can perform a
readlink operation on the passed
symlink vnode. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege. This call may be made in a number of situations,
including an explicit readlink call by
the user process, or as a result of an implicit
readlink during a name lookup by the
process.&mac.mpo;_check_rename_from_vnodeint
&mac.mpo;_check_rename_from_vnodestruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct vnode
*vpstruct label
*labelstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpDirectory vnodedlabelPolicy label for
dvpvpObject; vnodelabelPolicy label for
vpcnpPathnameDetermine whether the subject credential can rename the
passed vnode (vp) in the passed
directory (dvp) using the passed name
(cnp). This call will be made in
combination with a follow-up call to
mpo_check_rename_to_vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_rename_to_vnodeint
&mac.mpo;_check_rename_to_vnodestruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct vnode
*vpstruct label
*labelint samedirstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpDirectory vnodedlabelPolicy label for dvpvpObject; vnodelabelPolicy label for
vpcnpPathnameDetermine whether the subject credential can rename to
the passed vnode (vp) and the passed
directory (dvp) with the passed name
(cnp). This call will be made in
combination with an earlier call to
mpo_check_rename_from_vnode.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_revokeint
&mac.mpo;_check_vnode_revokestruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpDetermine whether the subject credential can revoke
access to the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setaclint
&mac.mpo;_check_vnode_setaclstruct ucred
*credstruct vnode
*vpstruct label
*labelacl_type_t
typestruct acl
*acl
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vptypeACL typeaclACLDetermine whether the subject credential can set the
passed ACL of passed type on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setextattrint
&mac.mpo;_check_vnode_setextattrstruct ucred
*credstruct vnode
*vpstruct label
*labelint
attrnamespaceconst char
*namestruct uio
*uio
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for vpattrnamespaceExtended attribute namespacenameExtended attribute nameuioI/O structure pointer; see &man.uio.9;Determine whether the subject credentical can set the
extended attribute of passed name and passed namespace on
the passed vnode. Policies implementing security labels
backed into extended attributes may want to provide
additional protections for those attributes. Additionally,
policies should avoid making decisions based on the data
referenced from uio, as there is a
potential race condition between this check and the actual
operation. The uio may also be
NULL if a delete operation is being
performed. Return 0 for success,
or an errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setflagsint
&mac.mpo;_check_vnode_setflagsstruct ucred
*credstruct vnode
*vpstruct label
*labelu_long flags
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpflagsFile flags; see &man.chflags.2;Determine whether the subject credential can set the
passed flags on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setmodeint
&mac.mpo;_check_vnode_setmodestruct ucred
*credstruct vnode
*vpstruct label
*labelmode_t mode
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for vpmodeFile mode; see &man.chmod.2;Determine whether the subject credential can set the
pased mode on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setownerint
&mac.mpo;_check_vnode_setownerstruct ucred
*credstruct vnode
*vpstruct label
*labeluid_t uidgid_t gid
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for vpuidUser IDgidGroup IDDetermine whether the subject credential can set the
passed uid and passed gid as file uid and file gid on the
passed vnode. The IDs may be set to (-1)
to request no update. Return 0
for success, or an errno value for
failure. Suggested failure: EACCES
for label mismatch, or EPERM for lack
of privilege.&mac.mpo;_check_vnode_setutimesint
&mac.mpo;_check_vnode_setutimesstruct ucred
*credstruct vnode
*vpstruct label
*labelstruct timespec
atimestruct timespec
mtime
&mac.thead;
credSubject credentialvpObject; vplabelPolicy label for
vpatimeAccess time; see &man.utimes.2;mtimeModification time; see &man.utimes.2;Determine whether the subject credential can set the
passed access timestamps on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_proc_schedint
&mac.mpo;_check_proc_schedstruct ucred
*ucredstruct proc
*proc
&mac.thead;
credSubject credentialprocObject; processDetermine whether the subject credential can change the
scheduling parameters of the passed process. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
EPERM for lack of privilege, or
ESRCH to limit visibility.See &man.setpriority.2; for more information.&mac.mpo;_check_proc_signalint
&mac.mpo;_check_proc_signalstruct ucred
*credstruct proc
*procint signal
&mac.thead;
credSubject credentialprocObject; processsignalSignal; see &man.kill.2;Determine whether the subject credential can deliver the
passed signal to the passed process. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
EPERM for lack of privilege, or
ESRCH to limit visibility.&mac.mpo;_check_vnode_statint
&mac.mpo;_check_vnode_statstruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpDetermine whether the subject credential can
stat the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.See &man.stat.2; for more information.&mac.mpo;_check_ifnet_transmitint
&mac.mpo;_check_ifnet_transmitstruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
credSubject credentialifnetNetwork interfaceifnetlabelPolicy label for
ifnetmbufObject; mbuf to be sentmbuflabelPolicy label for
mbufDetermine whether the network interface can transmit the
passed mbuf. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege.&mac.mpo;_check_socket_receiveint
&mac.mpo;_check_socket_receivestruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
credSubject credentialifnetNetwork interfaceifnetlabelPolicy label for
ifnetmbufObject; mbuf to be receivedmbuflabelPolicy label for
mbufDetermine whether the socket may receive the datagram
stored in the passed mbuf header. Return
0 for success, or an
errno value for failure. Suggested
failures: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_socket_visibleint
&mac.mpo;_check_socket_visiblestruct ucred
*credstruct socket
*sostruct label
*socketlabel
&mac.thead;
credSubject credentialImmutablesoObject; socketsocketlabelPolicy label for
soDetermine whether the subject credential cred can "see"
the passed socket (socket) using
system monitoring functions, such as those employed by
&man.netstat.8; and &man.sockstat.1;. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege, or
ESRCH to hide visibility.Label Management CallsRelabel events occur when a user process has requested
that the label on an object be modified. A two-phase update
occurs: first, an access control check will be performed to
determine if the update is both valid and permitted, and then
- the update itself is performed via a seperate entry point.
+ the update itself is performed via a separate entry point.
Relabel entry points typically accept the object, object label
reference, and an update label submitted by the process.
Memory allocation during relabel is discouraged, as relabel
calls are not permitted to fail (failure should be reported
earlier in the relabel check).&mac.mpo;_init_bpfdescvoid
&mac.mpo;_init_bpfdescstruct bpf_d
*bpf_dstruct label
*label
&mac.thead;
bpf_dObject; bpf descriptorlabelNew label to applyInitialize the label on a newly instantiated bpfdesc (BPF
descriptor)&mac.mpo;_init_devfsdirentvoid
&mac.mpo;_init_devfsdirentstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
devfs_direntObject; devfs directory entrylabelNew label to applyInitialize the label on a newly instantiated devfs
entry.&mac.mpo;_init_ifnetvoid
&mac.mpo;_init_ifnetstruct ifnet
*ifnetstruct label
*label
&mac.thead;
ifnetObject; network interfacelabelNew label to applyInitialize the label on a newly instantiated network
interface.&mac.mpo;_init_ipqvoid
&mac.mpo;_init_ipqstruct ipq
*ipqstruct label
*label
&mac.thead;
ipqObject; IP reassembly queuelabelNew label to applyInitialize the label on a newly instantiated IP fragment
reassembly queue.&mac.mpo;_init_mbufvoid
&mac.mpo;_init_mbufstruct mbuf
*mbufint howstruct label
*label
&mac.thead;
mbufObject; mbufhowBlocking/non-blocking &man.malloc.9; see
belowlabelPolicy label to initializeInitialize the label on a newly instantiated mbuf packet
header (mbuf). The
how field may be one of
M_WAITOK and M_NOWAIT, and
should be employed to avoid performing a blocking
&man.malloc.9; during this initialization call. Mbuf
allocation frequently occurs in performance sensitive
environments, and the implementation should be careful to
avoid blocking or long-lived operations. This entry point
is permitted to fail resulting in the failure to allocate
the mbuf header.&mac.mpo;_init_mountvoid
&mac.mpo;_init_mountstruct mount
*mountstruct label
*mntlabelstruct label
*fslabel
&mac.thead;
mountObject; file system mount pointmntlabelPolicy label to be initialized for the mount
itselffslabelPolicy label to be initialized for the file
systemInitialize the labels on a newly instantiated mount
point.&mac.mpo;_init_socketvoid
&mac.mpo;_init_socketstruct socket
*socketstruct label
*labelstruct label
*peerlabel
&mac.thead;
socketObject; socketlabelNew label to apply to the socketpeerlabelNew label to apply to the socket's peerInitialize the labels on a newly instantiated
socket.&mac.mpo;_init_credvoid
&mac.mpo;_init_credstruct ucred
*credstruct label
*label
&mac.thead;
credSubject; user credetiallabelNew labelInitialize the labels on a newly instantiated subject.&mac.mpo;_init_tempvoid
&mac.mpo;_init_tempstruct label
*label
&mac.thead;
labelTemporary labelInitialize a newly instantiated temporary label;
temporary labels are frequently used to hold label update
requests.&mac.mpo;_init_vnodevoid
&mac.mpo;_init_vnodestruct vnode
*vpstruct label
*label
&mac.thead;
vpObject; file system objectlabelNew label to initializeInitialize the label on a newly instantiated vnode.&mac.mpo;_destroy_bpfdescvoid
&mac.mpo;_destroy_bpfdescstruct bpf_d
*bpf_dstruct label
*label
&mac.thead;
bpf_dObject; bpf descriptorlabelLabel being destroyedDestroy the label on a BPF descriptor. In this entry
point, a policy module should free any internal storage
associated with label so that it may
be destroyed.&mac.mpo;_destroy_devfsdirentvoid
&mac.mpo;_destroy_devfsdirentstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
devfs_direntObject; devfs directory entrylabelLabel being destroyedDestroy the label on a devfs entry. In this entry
point, a policy module should free any internal storage
asociated with label so that it may
be destroyed.&mac.mpo;_destroy_ifnetvoid
&mac.mpo;_destroy_ifnetstruct ifnet
*ifnetstruct label
*label
&mac.thead;
ifnetObject; network interfacelabelLabel being destroyedDestroy the label on a removed interface. In this entry
point, a policy module should free any internal storage
associated with label so that it may
be destroyed.&mac.mpo;_destroy_ipqvoid
&mac.mpo;_destroy_ipqstruct ipq
*ipqstruct label
*label
&mac.thead;
ipqObject; IP reassembly queuelabelLabel being destroyedDestroy the label on an IP fragment queue. In this
entry point, a policy module should free any internal
storage associated with label so that
it may be destroyed.&mac.mpo;_destroy_mbufvoid
&mac.mpo;_destroy_mbufstruct mbuf
*mbufstruct label
*label
&mac.thead;
mbufObject; mbuflabelLabel being destroyedDestroy the label on an mbuf header. In this entry
point, a policy module should free any internal storage
associated with label so that it may
be destroyed.&mac.mpo;_destroy_mountvoid
&mac.mpo;_destroy_mountstruct mount
*mpstruct label
*mntlabelstruct label
*fslabel
&mac.thead;
mpObject; file system mount pointmntlabelMount point label being destroyedfslabelFile system label being destroyed>
Destroy the labels on a mount point. In this entry
point, a policy module should free the internal storage
associated with mntlabel and
fslabel so that they may be
destroyed.&mac.mpo;_destroy_socketvoid
&mac.mpo;_destroy_socketstruct socket
*socketstruct label
*labelstruct label
*peerlabel
&mac.thead;
socketObject; socketlabelSocket label being destroyedpeerlabelSocket peer label being destroyedDestroy the labels on a socket. In this entry point, a
policy module should free any internal storage associated
with label and
peerlabel so that they may be
destroyed.&mac.mpo;_destroy_credvoid
&mac.mpo;_destroy_credstruct ucred
*credstruct label
*label
&mac.thead;
credSubject; user credentiallabelLabel being destroyedDestroy the label on a credential. In this entry point,
a policy module should free any internal storage associated
with label so that it may be
destroyed.&mac.mpo;_destroy_tempvoid
&mac.mpo;_destroy_tempstruct label
*label
&mac.thead;
labelTemporary label being destroyedDestroy a temporary label. In this entry point, a
policy module should free any internal storage associated
with the temporary label label so
that it may be destroyed.&mac.mpo;_destroy_vnodevoid
&mac.mpo;_destroy_vnodestruct vnode
*vpstruct label
*label
&mac.thead;
vpObject; file system objectlabelLabel being destroyedDestroy the label on a vnode. In this entry point, a
policy module should free any internal storage associated
with label so that it may be
destroyed.&mac.mpo;_externalizevoid
&mac.mpo;_externalizestruct label
*labelstruct mac
*extmac
&mac.thead;
labelLabel to be externalizedextmacMAC structure to be filled inGiven an internalized subject or object label, fill out
an externalized label. This call is permitted to fail.
This call will be obsoleted by the new userland and extended
attribute interfaces for the MAC framework.&mac.mpo;_internalizevoid
&mac.mpo;_internalizestruct label
*labelstruct mac
*extmac
&mac.thead;
labelLabel to be filled inextmacMAC structure to internalizeGiven an externalized subject or object label, likely
from userland, internalize the label. The entry point
implementation should handle incorrect or corrupted labels.
This call is permitted to fail. This call will be obsoleted
by the new userland and extended attribute interfaces for
the MAC framework.Additional Framework API CallsThe MAC_SYSCALL entry point provides a
policy-multiplexed system call so that policies may provide
additional services to user processes without registering
specific system calls. The policy name provided during
registration is used to demux calls from userland, and the
arguments will be forwarded to this entry point. When
implementing new services, security modules should be sure to
invoke appropriate access control checks from the MAC
framework as needed. For example, if a policy implements an
augmented signal functionality, it should call the necessary
signal access control checks to invoke the MAC framework and
other registered policies.Userland APIsThe userland API is still under development.Sample Policy ModulesThe mac_none policy provides sample
prototypes and registration of all available policy entry
points.The mac_seeotheruids policy provides
a simple access control policy without the use of labeling,
relying only on information already present in the kernel
objects.The mac_biba policy provides a sample
information flow based labeled access control policy,
assigning labels to all kernel objects.System Integration...ConclusionThe TrustedBSD MAC framework permits kernel modules to
augment the system security policy in a highly integrated
manner. They may do this based on existing object properties,
or based on label data that is maintained with the assistance of
the MAC framework. The framework is sufficiently flexible to
implement a variety of policy types, including information flow
security policies such as MLS and Biba, as well as policies
based on existing BSD credentials or file protections. Policy
authors may wish to consult this documentation as well as
existing security modules when implementing a new security
service.
diff --git a/en_US.ISO8859-1/books/developers-handbook/isa/chapter.sgml b/en_US.ISO8859-1/books/developers-handbook/isa/chapter.sgml
index f48cd1ac06..6c4c58213d 100644
--- a/en_US.ISO8859-1/books/developers-handbook/isa/chapter.sgml
+++ b/en_US.ISO8859-1/books/developers-handbook/isa/chapter.sgml
@@ -1,2483 +1,2483 @@
ISA device drivers
This chapter was written by &a.babkin; Modifications for the
handbook made by &a.murray;, &a.wylie;, and &a.logo;.
SynopsisThis chapter introduces the issues relevant to writing a
driver for an ISA device. The pseudo-code presented here is
rather detailed and reminiscent of the real code but is still
only pseudo-code. It avoids the details irrelevant to the
subject of the discussion. The real-life examples can be found
in the source code of real drivers. In particular the drivers
ep and aha are good sources of information.Basic informationA typical ISA driver would need the following include
files:#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <isa/isavar.h>
#include <isa/pnpvar.h>They describe the things specific to the ISA and generic
bus subsystem.The bus subsystem is implemented in an object-oriented
fashion, its main structures are accessed by associated method
functions.The list of bus methods implemented by an ISA driver is like
one for any other bus. For a hypothetical driver named xxx
they would be:static void xxx_isa_identify (driver_t *,
device_t); Normally used for bus drivers, not
device drivers. But for ISA devices this method may have
special use: if the device provides some device-specific
(non-PnP) way to auto-detect devices this routine may
implement it.static int xxx_isa_probe (device_t
dev); Probe for a device at a known (or PnP)
location. This routine can also accommodate device-specific
auto-detection of parameters for partially configured
devices.static int xxx_isa_attach (device_t
dev); Attach and initialize device.static int xxx_isa_detach (device_t
dev); Detach device before unloading the driver
module.static int xxx_isa_shutdown (device_t
dev); Execute shutdown of the device before
system shutdown.static int xxx_isa_suspend (device_t
dev); Suspend the device before the system goes
to the power-save state. May also abort transition to the
power-save state.static int xxx_isa_resume (device_t
dev); Resume the device activity after return
from power-save state.xxx_isa_probe() and
xxx_isa_attach() are mandatory, the rest of
the routines are optional, depending on the device's
needs.The driver is linked to the system with the following set of
descriptions. /* table of supported bus methods */
static device_method_t xxx_isa_methods[] = {
/* list all the bus method functions supported by the driver */
/* omit the unsupported methods */
DEVMETHOD(device_identify, xxx_isa_identify),
DEVMETHOD(device_probe, xxx_isa_probe),
DEVMETHOD(device_attach, xxx_isa_attach),
DEVMETHOD(device_detach, xxx_isa_detach),
DEVMETHOD(device_shutdown, xxx_isa_shutdown),
DEVMETHOD(device_suspend, xxx_isa_suspend),
DEVMETHOD(device_resume, xxx_isa_resume),
{ 0, 0 }
};
static driver_t xxx_isa_driver = {
"xxx",
xxx_isa_methods,
sizeof(struct xxx_softc),
};
static devclass_t xxx_devclass;
DRIVER_MODULE(xxx, isa, xxx_isa_driver, xxx_devclass,
load_function, load_argument);Here struct xxx_softc is a
device-specific structure that contains private driver data
and descriptors for the driver's resources. The bus code
automatically allocates one softc descriptor per device as
needed.If the driver is implemented as a loadable module then
load_function() is called to do
driver-specific initialization or clean-up when the driver is
loaded or unloaded and load_argument is passed as one of its
arguments. If the driver does not support dynamic loading (in
other words it must always be linked into kernel) then these
values should be set to 0 and the last definition would look
like: DRIVER_MODULE(xxx, isa, xxx_isa_driver,
xxx_devclass, 0, 0);If the driver is for a device which supports PnP then a
table of supported PnP IDs must be defined. The table
consists of a list of PnP IDs supported by this driver and
human-readable descriptions of the hardware types and models
having these IDs. It looks like: static struct isa_pnp_id xxx_pnp_ids[] = {
/* a line for each supported PnP ID */
{ 0x12345678, "Our device model 1234A" },
{ 0x12345679, "Our device model 1234B" },
{ 0, NULL }, /* end of table */
};If the driver does not support PnP devices it still needs
an empty PnP ID table, like: static struct isa_pnp_id xxx_pnp_ids[] = {
{ 0, NULL }, /* end of table */
};Device_t pointerDevice_t is the pointer type for
the device structure. Here we consider only the methods
interesting from the device driver writer's standpoint. The
methods to manipulate values in the device structure
are:device_t
device_get_parent(dev) Get the parent bus of a
device.driver_t
device_get_driver(dev) Get pointer to its driver
structure.char
*device_get_name(dev) Get the driver name, such
as "xxx" for our example.int device_get_unit(dev)
Get the unit number (units are numbered from 0 for the
devices associated with each driver).char
*device_get_nameunit(dev) Get the device name
including the unit number, such as xxx0, xxx1 and so
on.char
*device_get_desc(dev) Get the device
description. Normally it describes the exact model of device
in human-readable form.device_set_desc(dev,
desc) Set the description. This makes the device
description point to the string desc which may not be
deallocated or changed after that.device_set_desc_copy(dev,
desc) Set the description. The description is
copied into an internal dynamically allocated buffer, so the
string desc may be changed afterwards without adverse
effects.void
*device_get_softc(dev) Get pointer to the device
descriptor (struct xxx_softc)
associated with this device.u_int32_t
device_get_flags(dev) Get the flags specified for
the device in the configuration file.A convenience function device_printf(dev, fmt,
...) may be used to print the messages from the
device driver. It automatically prepends the unitname and
colon to the message.The device_t methods are implemented in the file
kern/bus_subr.c.Configuration file and the order of identifying and probing
during auto-configurationThe ISA devices are described in the kernel configuration file
like:device xxx0 at isa? port 0x300 irq 10 drq 5
iomem 0xd0000 flags 0x1 sensitiveThe values of port, IRQ and so on are converted to the
resource values associated with the device. They are optional,
depending on the device's needs and abilities for
auto-configuration. For example, some devices do not need DRQ
at all and some allow the driver to read the IRQ setting from
the device configuration ports. If a machine has multiple ISA
buses the exact bus may be specified in the configuration
line, like isa0 or isa1, otherwise the device would be
searched for on all the ISA buses.sensitive is a resource requesting that this device must
be probed before all non-sensitive devices. It is supported
but does not seem to be used in any current driver.For legacy ISA devices in many cases the drivers are still
able to detect the configuration parameters. But each device
to be configured in the system must have a config line. If two
devices of some type are installed in the system but there is
only one configuration line for the corresponding driver, ie:
device xxx0 at isa? then only
one device will be configured.But for the devices supporting automatic identification by
the means of Plug-n-Play or some proprietary protocol one
configuration line is enough to configure all the devices in
the system, like the one above or just simply:device xxx at isa?If a driver supports both auto-identified and legacy
devices and both kinds are installed at once in one machine
then it is enough to describe in the config file the legacy
devices only. The auto-identified devices will be added
automatically.When an ISA bus is auto-configured the events happen as
follows:All the drivers' identify routines (including the PnP
identify routine which identifies all the PnP devices) are
called in random order. As they identify the devices they add
them to the list on the ISA bus. Normally the drivers'
identify routines associate their drivers with the new
devices. The PnP identify routine does not know about the
other drivers yet so it does not associate any with the new
devices it adds.The PnP devices are put to sleep using the PnP protocol to
prevent them from being probed as legacy devices.The probe routines of non-PnP devices marked as
sensitive are called. If probe for a device went
successfully, the attach routine is called for it.The probe and attach routines of all non-PNP devices are
called likewise.The PnP devices are brought back from the sleep state and
assigned the resources they request: I/O and memory address
ranges, IRQs and DRQs, all of them not conflicting with the
attached legacy devices.Then for each PnP device the probe routines of all the
present ISA drivers are called. The first one that claims the
device gets attached. It is possible that multiple drivers
would claim the device with different priority; in this case, the
highest-priority driver wins. The probe routines must call
ISA_PNP_PROBE() to compare the actual PnP
ID with the list of the IDs supported by the driver and if the
ID is not in the table return failure. That means that
absolutely every driver, even the ones not supporting any PnP
devices must call ISA_PNP_PROBE(), at
least with an empty PnP ID table to return failure on unknown
PnP devices.The probe routine returns a positive value (the error
code) on error, zero or negative value on success.The negative return values are used when a PnP device
supports multiple interfaces. For example, an older
compatibility interface and a newer advanced interface which
are supported by different drivers. Then both drivers would
detect the device. The driver which returns a higher value in
the probe routine takes precedence (in other words, the driver
returning 0 has highest precedence, returning -1 is next,
returning -2 is after it and so on). In result the devices
which support only the old interface will be handled by the
old driver (which should return -1 from the probe routine)
while the devices supporting the new interface as well will be
handled by the new driver (which should return 0 from the
probe routine). If multiple drivers return the same value then
the one called first wins. So if a driver returns value 0 it
may be sure that it won the priority arbitration.The device-specific identify routines can also assign not
a driver but a class of drivers to the device. Then all the
drivers in the class are probed for this device, like the case
with PnP. This feature is not implemented in any existing
driver and is not considered further in this document.Because the PnP devices are disabled when probing the
legacy devices they will not be attached twice (once as legacy
and once as PnP). But in case of device-dependent identify
routines it is the responsibility of the driver to make sure
that the same device will not be attached by the driver twice:
once as legacy user-configured and once as
auto-identified.Another practical consequence for the auto-identified
devices (both PnP and device-specific) is that the flags can
not be passed to them from the kernel configuration file. So
they must either not use the flags at all or use the flags
from the device unit 0 for all the auto-identified devices or
use the sysctl interface instead of flags.Other unusual configurations may be accommodated by
accessing the configuration resources directly with functions
of families resource_query_*() and
resource_*_value(). Their implementations
are located in kern/subr_bus.h. The old IDE disk driver
i386/isa/wd.c contains examples of such use. But the standard
means of configuration must always be preferred. Leave parsing
the configuration resources to the bus configuration
code.ResourcesThe information that a user enters into the kernel
configuration file is processed and passed to the kernel as
configuration resources. This information is parsed by the bus
configuration code and transformed into a value of structure
device_t and the bus resources associated with it. The drivers
may access the configuration resources directly using
functions resource_* for more complex cases of
configuration. However, generally this is neither needed nor recommended,
so this issue is not discussed further here.The bus resources are associated with each device. They
are identified by type and number within the type. For the ISA
bus the following types are defined:SYS_RES_IRQ - interrupt
numberSYS_RES_DRQ - ISA DMA channel
numberSYS_RES_MEMORY - range of
device memory mapped into the system memory space
SYS_RES_IOPORT - range of
device I/O registersThe enumeration within types starts from 0, so if a device
has two memory regions it would have resources of type
SYS_RES_MEMORY numbered 0 and 1. The resource type has
nothing to do with the C language type, all the resource
values have the C language type unsigned long and must be
cast as necessary. The resource numbers do not have to be
contiguous, although for ISA they normally would be. The
permitted resource numbers for ISA devices are: IRQ: 0-1
DRQ: 0-1
MEMORY: 0-3
IOPORT: 0-7All the resources are represented as ranges, with a start
value and count. For IRQ and DRQ resources the count would
normally be equal to 1. The values for memory refer to the
physical addresses.Three types of activities can be performed on
resources:set/getallocate/releaseactivate/deactivateSetting sets the range used by the resource. Allocation
reserves the requested range that no other driver would be
able to reserve it (and checking that no other driver reserved
this range already). Activation makes the resource accessible
to the driver by doing whatever is necessary for that (for
example, for memory it would be mapping into the kernel
virtual address space).The functions to manipulate resources are:int bus_set_resource(device_t dev, int type,
int rid, u_long start, u_long count)Set a range for a resource. Returns 0 if successful,
error code otherwise. Normally, this function will
return an error only if one of type,
rid, start or
count has a value that falls out of the
permitted range. dev - driver's device type - type of resource, SYS_RES_* rid - resource number (ID) within type start, count - resource range int bus_get_resource(device_t dev, int type,
int rid, u_long *startp, u_long *countp)Get the range of resource. Returns 0 if successful,
error code if the resource is not defined yet.u_long bus_get_resource_start(device_t dev,
int type, int rid) u_long bus_get_resource_count (device_t
dev, int type, int rid)Convenience functions to get only the start or
count. Return 0 in case of error, so if the resource start
has 0 among the legitimate values it would be impossible
to tell if the value is 0 or an error occurred. Luckily,
no ISA resources for add-on drivers may have a start value
equal to 0.void bus_delete_resource(device_t dev, int
type, int rid) Delete a resource, make it undefined.struct resource *
bus_alloc_resource(device_t dev, int type, int *rid,
u_long start, u_long end, u_long count, u_int
flags)Allocate a resource as a range of count values not
allocated by anyone else, somewhere between start and
end. Alas, alignment is not supported. If the resource
was not set yet it is automatically created. The special
values of start 0 and end ~0 (all ones) means that the
fixed values previously set by
bus_set_resource() must be used
instead: start and count as themselves and
end=(start+count), in this case if the resource was not
defined before then an error is returned. Although rid is
passed by reference it is not set anywhere by the resource
allocation code of the ISA bus. (The other buses may use a
different approach and modify it).Flags are a bitmap, the flags interesting for the caller
are:RF_ACTIVE - causes the resource
to be automatically activated after allocation.RF_SHAREABLE - resource may be
shared at the same time by multiple drivers.RF_TIMESHARE - resource may be
time-shared by multiple drivers, i.e. allocated at the
same time by many but activated only by one at any given
moment of time.
-
+
Returns 0 on error. The allocated values may be
obtained from the returned handle using methods
rhand_*().int bus_release_resource(device_t dev, int
type, int rid, struct resource *r)Release the resource, r is the handle returned by
bus_alloc_resource(). Returns 0 on
success, error code otherwise.int bus_activate_resource(device_t dev, int
type, int rid, struct resource *r)int bus_deactivate_resource(device_t dev, int
type, int rid, struct resource *r)Activate or deactivate resource. Return 0 on success,
error code otherwise. If the resource is time-shared and
currently activated by another driver then EBUSY is
returned.int bus_setup_intr(device_t dev, struct
resource *r, int flags, driver_intr_t *handler, void *arg,
void **cookiep)int
bus_teardown_intr(device_t dev, struct resource *r, void
*cookie)Associate or de-associate the interrupt handler with a
device. Return 0 on success, error code otherwise.r - the activated resource handler describing the
IRQflags - the interrupt priority level, one of:INTR_TYPE_TTY - terminals and
other likewise character-type devices. To mask them
use spltty().(INTR_TYPE_TTY |
INTR_TYPE_FAST) - terminal type devices
with small input buffer, critical to the data loss on
input (such as the old-fashioned serial ports). To
mask them use spltty().INTR_TYPE_BIO - block-type
devices, except those on the CAM controllers. To mask
them use splbio().INTR_TYPE_CAM - CAM (Common
Access Method) bus controllers. To mask them use
splcam().INTR_TYPE_NET - network
interface controllers. To mask them use
splimp().INTR_TYPE_MISC -
miscellaneous devices. There is no other way to mask
them than by splhigh() which
masks all interrupts.When an interrupt handler executes all the other
interrupts matching its priority level will be masked. The
only exception is the MISC level for which no other interrupts
are masked and which is not masked by any other
interrupt.handler - pointer to the handler
function, the type driver_intr_t is defined as void
driver_intr_t(void *)arg - the argument passed to the
handler to identify this particular device. It is cast
from void* to any real type by the handler. The old
convention for the ISA interrupt handlers was to use the
unit number as argument, the new (recommended) convention
is using a pointer to the device softc structure.cookie[p] - the value received
from setup() is used to identify the
handler when passed to
teardown()A number of methods are defined to operate on the resource
handlers (struct resource *). Those of interest to the device
driver writers are:u_long rman_get_start(r) u_long
rman_get_end(r) Get the start and end of
allocated resource range.void *rman_get_virtual(r) Get
the virtual address of activated memory resource.Bus memory mappingIn many cases data is exchanged between the driver and the
device through the memory. Two variants are possible:(a) memory is located on the device card(b) memory is the main memory of the computerIn case (a) the driver always copies the data back and
forth between the on-card memory and the main memory as
necessary. To map the on-card memory into the kernel virtual
address space the physical address and length of the on-card
memory must be defined as a SYS_RES_MEMORY resource. That
resource can then be allocated and activated, and its virtual
address obtained using
rman_get_virtual(). The older drivers
used the function pmap_mapdev() for this
purpose, which should not be used directly any more. Now it is
one of the internal steps of resource activation.Most of the ISA cards will have their memory configured
for physical location somewhere in range 640KB-1MB. Some of
the ISA cards require larger memory ranges which should be
placed somewhere under 16MB (because of the 24-bit address
limitation on the ISA bus). In that case if the machine has
more memory than the start address of the device memory (in
other words, they overlap) a memory hole must be configured at
the address range used by devices. Many BIOSes allow
configuration of a memory hole of 1MB starting at 14MB or
15MB. FreeBSD can handle the memory holes properly if the BIOS
reports them properly (this feature may be broken on old BIOSes).In case (b) just the address of the data is sent to
the device, and the device uses DMA to actually access the
data in the main memory. Two limitations are present: First,
ISA cards can only access memory below 16MB. Second, the
contiguous pages in virtual address space may not be
contiguous in physical address space, so the device may have
to do scatter/gather operations. The bus subsystem provides
ready solutions for some of these problems, the rest has to be
done by the drivers themselves.Two structures are used for DMA memory allocation,
bus_dma_tag_t and bus_dmamap_t. Tag describes the properties
required for the DMA memory. Map represents a memory block
allocated according to these properties. Multiple maps may be
associated with the same tag.Tags are organized into a tree-like hierarchy with
inheritance of the properties. A child tag inherits all the
requirements of its parent tag, and may make them more strict
but never more loose.Normally one top-level tag (with no parent) is created for
each device unit. If multiple memory areas with different
requirements are needed for each device then a tag for each of
them may be created as a child of the parent tag.The tags can be used to create a map in two ways.First, a chunk of contiguous memory conformant with the
tag requirements may be allocated (and later may be
freed). This is normally used to allocate relatively
long-living areas of memory for communication with the
device. Loading of such memory into a map is trivial: it is
always considered as one chunk in the appropriate physical
memory range.Second, an arbitrary area of virtual memory may be loaded
into a map. Each page of this memory will be checked for
conformance to the map requirement. If it conforms then it is
left at its original location. If it is not then a fresh
conformant bounce page is allocated and used as intermediate
storage. When writing the data from the non-conformant
original pages they will be copied to their bounce pages first
and then transferred from the bounce pages to the device. When
reading the data would go from the device to the bounce pages
and then copied to their non-conformant original pages. The
process of copying between the original and bounce pages is
called synchronization. This is normally used on a per-transfer
basis: buffer for each transfer would be loaded, transfer done
and buffer unloaded.The functions working on the DMA memory are:int bus_dma_tag_create(bus_dma_tag_t parent,
bus_size_t alignment, bus_size_t boundary, bus_addr_t
lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filter, void
*filterarg, bus_size_t maxsize, int nsegments, bus_size_t
maxsegsz, int flags, bus_dma_tag_t *dmat)Create a new tag. Returns 0 on success, the error code
otherwise.parent - parent tag, or NULL to
create a top-level tag alignment -
required physical alignment of the memory area to be
allocated for this tag. Use value 1 for no specific
alignment. Applies only to the future
bus_dmamem_alloc() but not
bus_dmamap_create() calls.boundary - physical address
boundary that must not be crossed when allocating the
memory. Use value 0 for no boundary. Applies only to
the future bus_dmamem_alloc() but
not bus_dmamap_create() calls.
Must be power of 2. If the memory is planned to be used
in non-cascaded DMA mode (i.e. the DMA addresses will be
supplied not by the device itself but by the ISA DMA
controller) then the boundary must be no larger than
64KB (64*1024) due to the limitations of the DMA
hardware.lowaddr, highaddr - the names
are slightly misleading; these values are used to limit
the permitted range of physical addresses used to
allocate the memory. The exact meaning varies depending
on the planned future use:For bus_dmamem_alloc() all
the addresses from 0 to lowaddr-1 are considered
permitted, the higher ones are forbidden.For bus_dmamap_create() all
the addresses outside the inclusive range [lowaddr;
highaddr] are considered accessible. The addresses
of pages inside the range are passed to the filter
function which decides if they are accessible. If no
filter function is supplied then all the range is
considered unaccessible.For the ISA devices the normal values (with no
filter function) are:lowaddr = BUS_SPACE_MAXADDR_24BIThighaddr = BUS_SPACE_MAXADDRfilter, filterarg - the filter
function and its argument. If NULL is passed for filter
then the whole range [lowaddr, highaddr] is considered
unaccessible when doing
bus_dmamap_create(). Otherwise the
physical address of each attempted page in range
[lowaddr; highaddr] is passed to the filter function
which decides if it is accessible. The prototype of the
filter function is: int filterfunc(void *arg,
bus_addr_t paddr). It must return 0 if the
page is accessible, non-zero otherwise.maxsize - the maximal size of
memory (in bytes) that may be allocated through this
tag. In case it is difficult to estimate or could be
arbitrarily big, the value for ISA devices would be
BUS_SPACE_MAXSIZE_24BIT.nsegments - maximal number of
scatter-gather segments supported by the device. If
unrestricted then the value BUS_SPACE_UNRESTRICTED
should be used. This value is recommended for the parent
tags, the actual restrictions would then be specified
for the descendant tags. Tags with nsegments equal to
BUS_SPACE_UNRESTRICTED may not be used to actually load
maps, they may be used only as parent tags. The
practical limit for nsegments seems to be about 250-300,
higher values will cause kernel stack overflow (the hardware
can not normally support that many
scatter-gather buffers anyway).maxsegsz - maximal size of a
scatter-gather segment supported by the device. The
maximal value for ISA device would be
BUS_SPACE_MAXSIZE_24BIT.flags - a bitmap of flags. The
only interesting flags are:BUS_DMA_ALLOCNOW - requests
to allocate all the potentially needed bounce pages
when creating the tag.BUS_DMA_ISA - mysterious
flag used only on Alpha machines. It is not defined
for the i386 machines. Probably it should be used
by all the ISA drivers for Alpha machines but it
looks like there are no such drivers yet.dmat - pointer to the storage
for the new tag to be returned.int bus_dma_tag_destroy(bus_dma_tag_t
dmat)Destroy a tag. Returns 0 on success, the error code
otherwise.dmat - the tag to be destroyed.int bus_dmamem_alloc(bus_dma_tag_t dmat,
void** vaddr, int flags, bus_dmamap_t
*mapp)Allocate an area of contiguous memory described by the
tag. The size of memory to be allocated is tag's maxsize.
Returns 0 on success, the error code otherwise. The result
still has to be loaded by
bus_dmamap_load() before being used to get
the physical address of the memory.dmat - the tag
vaddr - pointer to the storage
for the kernel virtual address of the allocated area
to be returned.
flags - a bitmap of flags. The only interesting flag is:
BUS_DMA_NOWAIT - if the
memory is not immediately available return the
error. If this flag is not set then the routine
is allowed to sleep until the memory
becomes available.
mapp - pointer to the storage
for the new map to be returned.
void bus_dmamem_free(bus_dma_tag_t dmat, void
*vaddr, bus_dmamap_t map)
Free the memory allocated by
bus_dmamem_alloc(). At present,
freeing of the memory allocated with ISA restrictions is
not implemented. Because of this the recommended model
of use is to keep and re-use the allocated areas for as
long as possible. Do not lightly free some area and then
shortly allocate it again. That does not mean that
bus_dmamem_free() should not be
used at all: hopefully it will be properly implemented
soon.
dmat - the tag
vaddr - the kernel virtual
address of the memory
map - the map of the memory (as
returned from
bus_dmamem_alloc())
int bus_dmamap_create(bus_dma_tag_t dmat, int
flags, bus_dmamap_t *mapp)
Create a map for the tag, to be used in
bus_dmamap_load() later. Returns 0
on success, the error code otherwise.
dmat - the tag
flags - theoretically, a bit map
of flags. But no flags are defined yet, so at present
it will be always 0.
mapp - pointer to the storage
for the new map to be returned
int bus_dmamap_destroy(bus_dma_tag_t dmat,
bus_dmamap_t map)
Destroy a map. Returns 0 on success, the error code otherwise.
dmat - the tag to which the map is associated
map - the map to be destroyed
int bus_dmamap_load(bus_dma_tag_t dmat,
bus_dmamap_t map, void *buf, bus_size_t buflen,
bus_dmamap_callback_t *callback, void *callback_arg, int
flags)
Load a buffer into the map (the map must be previously
created by bus_dmamap_create() or
bus_dmamem_alloc()). All the pages
of the buffer are checked for conformance to the tag
requirements and for those not conformant the bounce
pages are allocated. An array of physical segment
descriptors is built and passed to the callback
routine. This callback routine is then expected to
handle it in some way. The number of bounce buffers in
the system is limited, so if the bounce buffers are
needed but not immediately available the request will be
queued and the callback will be called when the bounce
buffers will become available. Returns 0 if the callback
was executed immediately or EINPROGRESS if the request
was queued for future execution. In the latter case the
synchronization with queued callback routine is the
responsibility of the driver.
dmat - the tag
map - the map
buf - kernel virtual address of
the buffer
buflen - length of the buffer
callback,
callback_arg - the callback function and
its argument
The prototype of callback function is:
void callback(void *arg, bus_dma_segment_t
*seg, int nseg, int error)arg - the same as callback_arg
passed to bus_dmamap_load()seg - array of the segment
descriptors
nseg - number of descriptors in
array
error - indication of the
segment number overflow: if it is set to EFBIG then
the buffer did not fit into the maximal number of
segments permitted by the tag. In this case only the
permitted number of descriptors will be in the
array. Handling of this situation is up to the
driver: depending on the desired semantics it can
either consider this an error or split the buffer in
two and handle the second part separately
Each entry in the segments array contains the fields:
ds_addr - physical bus address
of the segment
ds_len - length of the segment
void bus_dmamap_unload(bus_dma_tag_t dmat,
bus_dmamap_t map)unload the map.
dmat - tag
map - loaded map
void bus_dmamap_sync (bus_dma_tag_t dmat,
bus_dmamap_t map, bus_dmasync_op_t op)
Synchronise a loaded buffer with its bounce pages before
and after physical transfer to or from device. This is
the function that does all the necessary copying of data
between the original buffer and its mapped version. The
buffers must be synchronized both before and after doing
the transfer.
dmat - tag
map - loaded map
op - type of synchronization
operation to perform:
BUS_DMASYNC_PREREAD - before
reading from device into buffer
BUS_DMASYNC_POSTREAD - after
reading from device into buffer
BUS_DMASYNC_PREWRITE - before
writing the buffer to device
BUS_DMASYNC_POSTWRITE - after
writing the buffer to device
As of now PREREAD and POSTWRITE are null operations but that
may change in the future, so they must not be ignored in the
driver. Synchronization is not needed for the memory
obtained from bus_dmamem_alloc().
Before calling the callback function from
bus_dmamap_load() the segment array is
stored in the stack. And it gets pre-allocated for the
maximal number of segments allowed by the tag. Because of
this the practical limit for the number of segments on i386
architecture is about 250-300 (the kernel stack is 4KB minus
the size of the user structure, size of a segment array
entry is 8 bytes, and some space must be left). Because the
array is allocated based on the maximal number this value
must not be set higher than really needed. Fortunately, for
most of hardware the maximal supported number of segments is
much lower. But if the driver wants to handle buffers with a
very large number of scatter-gather segments it should do
that in portions: load part of the buffer, transfer it to
the device, load next part of the buffer, and so on.
Another practical consequence is that the number of segments
may limit the size of the buffer. If all the pages in the
buffer happen to be physically non-contiguous then the
maximal supported buffer size for that fragmented case would
be (nsegments * page_size). For example, if a maximal number
of 10 segments is supported then on i386 maximal guaranteed
supported buffer size would be 40K. If a higher size is
desired then special tricks should be used in the driver.
If the hardware does not support scatter-gather at all or
the driver wants to support some buffer size even if it is
heavily fragmented then the solution is to allocate a
contiguous buffer in the driver and use it as intermediate
storage if the original buffer does not fit.
Below are the typical call sequences when using a map depend
on the use of the map. The characters -> are used to show
the flow of time.
For a buffer which stays practically fixed during all the
time between attachment and detachment of a device:
bus_dmamem_alloc -> bus_dmamap_load -> ...use buffer... ->
-> bus_dmamap_unload -> bus_dmamem_free
For a buffer that changes frequently and is passed from
outside the driver:
bus_dmamap_create ->
-> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->
-> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->
...
-> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->
-> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->
-> bus_dmamap_destroy
When loading a map created by
bus_dmamem_alloc() the passed address
and size of the buffer must be the same as used in
bus_dmamem_alloc(). In this case it is
guaranteed that the whole buffer will be mapped as one
segment (so the callback may be based on this assumption)
and the request will be executed immediately (EINPROGRESS
will never be returned). All the callback needs to do in
this case is to save the physical address.
A typical example would be:
static void
alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
{
*(bus_addr_t *)arg = seg[0].ds_addr;
}
...
int error;
struct somedata {
....
};
struct somedata *vsomedata; /* virtual address */
bus_addr_t psomedata; /* physical bus-relative address */
bus_dma_tag_t tag_somedata;
bus_dmamap_t map_somedata;
...
error=bus_dma_tag_create(parent_tag, alignment,
boundary, lowaddr, highaddr, /*filter*/ NULL, /*filterarg*/ NULL,
/*maxsize*/ sizeof(struct somedata), /*nsegments*/ 1,
/*maxsegsz*/ sizeof(struct somedata), /*flags*/ 0,
&tag_somedata);
if(error)
return error;
error = bus_dmamem_alloc(tag_somedata, &vsomedata, /* flags*/ 0,
&map_somedata);
if(error)
return error;
bus_dmamap_load(tag_somedata, map_somedata, (void *)vsomedata,
sizeof (struct somedata), alloc_callback,
(void *) &psomedata, /*flags*/0);
Looks a bit long and complicated but that is the way to do
it. The practical consequence is: if multiple memory areas
are allocated always together it would be a really good idea
to combine them all into one structure and allocate as one
(if the alignment and boundary limitations permit).
When loading an arbitrary buffer into the map created by
bus_dmamap_create() special measures
must be taken to synchronize with the callback in case it
would be delayed. The code would look like:
{
int s;
int error;
s = splsoftvm();
error = bus_dmamap_load(
dmat,
dmamap,
buffer_ptr,
buffer_len,
callback,
/*callback_arg*/ buffer_descriptor,
/*flags*/0);
if (error == EINPROGRESS) {
/*
* Do whatever is needed to ensure synchronization
* with callback. Callback is guaranteed not to be started
* until we do splx() or tsleep().
*/
}
splx(s);
}
Two possible approaches for the processing of requests are:
1. If requests are completed by marking them explicitly as
done (such as the CAM requests) then it would be simpler to
put all the further processing into the callback driver
which would mark the request when it is done. Then not much
extra synchronization is needed. For the flow control
reasons it may be a good idea to freeze the request queue
until this request gets completed.
2. If requests are completed when the function returns (such
as classic read or write requests on character devices) then
a synchronization flag should be set in the buffer
descriptor and tsleep() called. Later
when the callback gets called it will do its processing and
check this synchronization flag. If it is set then the
callback should issue a wakeup. In this approach the
callback function could either do all the needed processing
(just like the previous case) or simply save the segments
array in the buffer descriptor. Then after callback
completes the calling function could use this saved segments
array and do all the processing.
DMA
The Direct Memory Access (DMA) is implemented in the ISA bus
through the DMA controller (actually, two of them but that is
an irrelevant detail). To make the early ISA devices simple
and cheap the logic of the bus control and address
generation was concentrated in the DMA controller.
Fortunately, FreeBSD provides a set of functions that mostly
hide the annoying details of the DMA controller from the
device drivers.
The simplest case is for the fairly intelligent
devices. Like the bus master devices on PCI they can
generate the bus cycles and memory addresses all by
themselves. The only thing they really need from the DMA
controller is bus arbitration. So for this purpose they
pretend to be cascaded slave DMA controllers. And the only
thing needed from the system DMA controller is to enable the
cascaded mode on a DMA channel by calling the following
function when attaching the driver:
void isa_dmacascade(int channel_number)
All the further activity is done by programming the
device. When detaching the driver no DMA-related functions
need to be called.
For the simpler devices things get more complicated. The
functions used are:
int isa_dma_acquire(int chanel_number)
Reserve a DMA channel. Returns 0 on success or EBUSY
if the channel was already reserved by this or a
different driver. Most of the ISA devices are not able
to share DMA channels anyway, so normally this
function is called when attaching a device. This
reservation was made redundant by the modern interface
of bus resources but still must be used in addition to
the latter. If not used then later, other DMA routines
will panic.
int isa_dma_release(int chanel_number)
Release a previously reserved DMA channel. No
transfers must be in progress when the channel is
released (in addition the device must not try to
initiate transfer after the channel is released).
void isa_dmainit(int chan, u_int
bouncebufsize)
Allocate a bounce buffer for use with the specified
channel. The requested size of the buffer can not exceed
64KB. This bounce buffer will be automatically used
later if a transfer buffer happens to be not
physically contiguous or outside of the memory
accessible by the ISA bus or crossing the 64KB
boundary. If the transfers will be always done from
buffers which conform to these conditions (such as
those allocated by
bus_dmamem_alloc() with proper
limitations) then isa_dmainit()
does not have to be called. But it is quite convenient
to transfer arbitrary data using the DMA controller.
The bounce buffer will automatically care of the
scatter-gather issues.
chan - channel number
bouncebufsize - size of the
bounce buffer in bytes
void isa_dmastart(int flags, caddr_t addr, u_int
nbytes, int chan)
Prepare to start a DMA transfer. This function must be
called to set up the DMA controller before actually
starting transfer on the device. It checks that the
buffer is contiguous and falls into the ISA memory
range, if not then the bounce buffer is automatically
used. If bounce buffer is required but not set up by
isa_dmainit() or too small for
the requested transfer size then the system will
panic. In case of a write request with bounce buffer
the data will be automatically copied to the bounce
buffer.
flags - a bitmask determining the type of operation to
be done. The direction bits B_READ and B_WRITE are mutually
exclusive.
B_READ - read from the ISA bus into memory
B_WRITE - write from the memory to the ISA bus
B_RAW - if set then the DMA controller will remember
the buffer and after the end of transfer will
automatically re-initialize itself to repeat transfer
of the same buffer again (of course, the driver may
change the data in the buffer before initiating
another transfer in the device). If not set then the
parameters will work only for one transfer, and
isa_dmastart() will have to be
called again before initiating the next
transfer. Using B_RAW makes sense only if the bounce
buffer is not used.
addr - virtual address of the buffer
nbytes - length of the buffer. Must be less or equal to
64KB. Length of 0 is not allowed: the DMA controller will
understand it as 64KB while the kernel code will
understand it as 0 and that would cause unpredictable
effects. For channels number 4 and higher the length must
be even because these channels transfer 2 bytes at a
time. In case of an odd length the last byte will not be
transferred.
chan - channel number
void isa_dmadone(int flags, caddr_t addr, int
nbytes, int chan)
Synchronize the memory after device reports that transfer
is done. If that was a read operation with a bounce buffer
then the data will be copied from the bounce buffer to the
original buffer. Arguments are the same as for
isa_dmastart(). Flag B_RAW is
permitted but it does not affect
isa_dmadone() in any way.
int isa_dmastatus(int channel_number)
Returns the number of bytes left in the current transfer
to be transferred. In case the flag B_READ was set in
isa_dmastart() the number returned
will never be equal to zero. At the end of transfer it
will be automatically reset back to the length of
buffer. The normal use is to check the number of bytes
left after the device signals that the transfer is
completed. If the number of bytes is not 0 then something
probably went wrong with that transfer.
int isa_dmastop(int channel_number)
Aborts the current transfer and returns the number of
bytes left untransferred.
xxx_isa_probe
This function probes if a device is present. If the driver
supports auto-detection of some part of device configuration
(such as interrupt vector or memory address) this
auto-detection must be done in this routine.
As for any other bus, if the device cannot be detected or
is detected but failed the self-test or some other problem
happened then it returns a positive value of error. The
value ENXIO must be returned if the device is not
present. Other error values may mean other conditions. Zero
or negative values mean success. Most of the drivers return
zero as success.
The negative return values are used when a PnP device
supports multiple interfaces. For example, an older
compatibility interface and a newer advanced interface which
are supported by different drivers. Then both drivers would
detect the device. The driver which returns a higher value
in the probe routine takes precedence (in other words, the
driver returning 0 has highest precedence, one returning -1
is next, one returning -2 is after it and so on). In result
the devices which support only the old interface will be
handled by the old driver (which should return -1 from the
probe routine) while the devices supporting the new
interface as well will be handled by the new driver (which
should return 0 from the probe routine).
The device descriptor struct xxx_softc is allocated by the
system before calling the probe routine. If the probe
routine returns an error the descriptor will be
automatically deallocated by the system. So if a probing
error occurs the driver must make sure that all the
resources it used during probe are deallocated and that
nothing keeps the descriptor from being safely
deallocated. If the probe completes successfully the
descriptor will be preserved by the system and later passed
to the routine xxx_isa_attach(). If a
driver returns a negative value it can not be sure that it
will have the highest priority and its attach routine will
be called. So in this case it also must release all the
resources before returning and if necessary allocate them
again in the attach routine. When
xxx_isa_probe() returns 0 releasing the
resources before returning is also a good idea and a
well-behaved driver should do so. But in cases where there is
some problem with releasing the resources the driver is
allowed to keep resources between returning 0 from the probe
routine and execution of the attach routine.
A typical probe routine starts with getting the device
descriptor and unit:
struct xxx_softc *sc = device_get_softc(dev);
int unit = device_get_unit(dev);
int pnperror;
int error = 0;
sc->dev = dev; /* link it back */
sc->unit = unit;
Then check for the PnP devices. The check is carried out by
a table containing the list of PnP IDs supported by this
driver and human-readable descriptions of the device models
corresponding to these IDs.
pnperror=ISA_PNP_PROBE(device_get_parent(dev), dev,
xxx_pnp_ids); if(pnperror == ENXIO) return ENXIO;
The logic of ISA_PNP_PROBE is the following: If this card
(device unit) was not detected as PnP then ENOENT will be
returned. If it was detected as PnP but its detected ID does
not match any of the IDs in the table then ENXIO is
returned. Finally, if it has PnP support and it matches on
of the IDs in the table, 0 is returned and the appropriate
description from the table is set by
device_set_desc().
If a driver supports only PnP devices then the condition
would look like:
if(pnperror != 0)
return pnperror;
No special treatment is required for the drivers which do not
support PnP because they pass an empty PnP ID table and will
always get ENXIO if called on a PnP card.
The probe routine normally needs at least some minimal set
of resources, such as I/O port number to find the card and
probe it. Depending on the hardware the driver may be able
to discover the other necessary resources automatically. The
PnP devices have all the resources pre-set by the PnP
subsystem, so the driver does not need to discover them by
itself.
Typically the minimal information required to get access to
the device is the I/O port number. Then some devices allow
to get the rest of information from the device configuration
registers (though not all devices do that). So first we try
to get the port start value:
sc->port0 = bus_get_resource_start(dev,
SYS_RES_IOPORT, 0 /*rid*/); if(sc->port0 == 0) return ENXIO;
The base port address is saved in the structure softc for
future use. If it will be used very often then calling the
resource function each time would be prohibitively slow. If
we do not get a port we just return an error. Some device
drivers can instead be clever and try to probe all the
possible ports, like this:
/* table of all possible base I/O port addresses for this device */
static struct xxx_allports {
u_short port; /* port address */
short used; /* flag: if this port is already used by some unit */
} xxx_allports = {
{ 0x300, 0 },
{ 0x320, 0 },
{ 0x340, 0 },
{ 0, 0 } /* end of table */
};
...
int port, i;
...
port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0 /*rid*/);
if(port !=0 ) {
for(i=0; xxx_allports[i].port!=0; i++) {
if(xxx_allports[i].used || xxx_allports[i].port != port)
continue;
/* found it */
xxx_allports[i].used = 1;
/* do probe on a known port */
return xxx_really_probe(dev, port);
}
return ENXIO; /* port is unknown or already used */
}
/* we get here only if we need to guess the port */
for(i=0; xxx_allports[i].port!=0; i++) {
if(xxx_allports[i].used)
continue;
/* mark as used - even if we find nothing at this port
* at least we won't probe it in future
*/
xxx_allports[i].used = 1;
error = xxx_really_probe(dev, xxx_allports[i].port);
if(error == 0) /* found a device at that port */
return 0;
}
/* probed all possible addresses, none worked */
return ENXIO;
Of course, normally the driver's
identify() routine should be used for
such things. But there may be one valid reason why it may be
better to be done in probe(): if this
probe would drive some other sensitive device crazy. The
probe routines are ordered with consideration of the
sensitive flag: the sensitive devices get probed first and
the rest of the devices later. But the
identify() routines are called before
any probes, so they show no respect to the sensitive devices
and may upset them.
Now, after we got the starting port we need to set the port
count (except for PnP devices) because the kernel does not
have this information in the configuration file.
if(pnperror /* only for non-PnP devices */
&& bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port0,
XXX_PORT_COUNT)<0)
return ENXIO;
Finally allocate and activate a piece of port address space
(special values of start and end mean use those we set by
bus_set_resource()):
sc->port0_rid = 0;
sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,
&sc->port0_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->port0_r == NULL)
return ENXIO;
Now having access to the port-mapped registers we can poke
the device in some way and check if it reacts like it is
expected to. If it does not then there is probably some
other device or no device at all at this address.
Normally drivers do not set up the interrupt handlers until
the attach routine. Instead they do probes in the polling
mode using the DELAY() function for
timeout. The probe routine must never hang forever, all the
waits for the device must be done with timeouts. If the
device does not respond within the time it is probably broken
or misconfigured and the driver must return error. When
determining the timeout interval give the device some extra
time to be on the safe side: although
DELAY() is supposed to delay for the
same amount of time on any machine it has some margin of
error, depending on the exact CPU.
If the probe routine really wants to check that the
interrupts really work it may configure and probe the
interrupts too. But that is not recommended.
/* implemented in some very device-specific way */
if(error = xxx_probe_ports(sc))
goto bad; /* will deallocate the resources before returning */
The function xxx_probe_ports() may also
set the device description depending on the exact model of
device it discovers. But if there is only one supported
device model this can be as well done in a hardcoded way.
Of course, for the PnP devices the PnP support sets the
description from the table automatically.
if(pnperror)
device_set_desc(dev, "Our device model 1234");
Then the probe routine should either discover the ranges of
all the resources by reading the device configuration
registers or make sure that they were set explicitly by the
user. We will consider it with an example of on-board
memory. The probe routine should be as non-intrusive as
possible, so allocation and check of functionality of the
rest of resources (besides the ports) would be better left
to the attach routine.
The memory address may be specified in the kernel
configuration file or on some devices it may be
pre-configured in non-volatile configuration registers. If
both sources are available and different, which one should
be used? Probably if the user bothered to set the address
explicitly in the kernel configuration file they know what
they are doing and this one should take precedence. An
example of implementation could be:
/* try to find out the config address first */
sc->mem0_p = bus_get_resource_start(dev, SYS_RES_MEMORY, 0 /*rid*/);
if(sc->mem0_p == 0) { /* nope, not specified by user */
sc->mem0_p = xxx_read_mem0_from_device_config(sc);
if(sc->mem0_p == 0)
/* can't get it from device config registers either */
goto bad;
} else {
if(xxx_set_mem0_address_on_device(sc) < 0)
goto bad; /* device does not support that address */
}
/* just like the port, set the memory size,
* for some devices the memory size would not be constant
* but should be read from the device configuration registers instead
* to accommodate different models of devices. Another option would
* be to let the user set the memory size as "msize" configuration
* resource which will be automatically handled by the ISA bus.
*/
if(pnperror) { /* only for non-PnP devices */
sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
if(sc->mem0_size == 0) /* not specified by user */
sc->mem0_size = xxx_read_mem0_size_from_device_config(sc);
if(sc->mem0_size == 0) {
/* suppose this is a very old model of device without
* auto-configuration features and the user gave no preference,
* so assume the minimalistic case
* (of course, the real value will vary with the driver)
*/
sc->mem0_size = 8*1024;
}
if(xxx_set_mem0_size_on_device(sc) < 0)
goto bad; /* device does not support that size */
if(bus_set_resource(dev, SYS_RES_MEMORY, /*rid*/0,
sc->mem0_p, sc->mem0_size)<0)
goto bad;
} else {
sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
}
Resources for IRQ and DRQ are easy to check by analogy.
If all went well then release all the resources and return success.
xxx_free_resources(sc);
return 0;
Finally, handle the troublesome situations. All the
resources should be deallocated before returning. We make
use of the fact that before the structure softc is passed to
us it gets zeroed out, so we can find out if some resource
was allocated: then its descriptor is non-zero.
bad:
xxx_free_resources(sc);
if(error)
return error;
else /* exact error is unknown */
return ENXIO;
That would be all for the probe routine. Freeing of
resources is done from multiple places, so it is moved to a
function which may look like:
static void
xxx_free_resources(sc)
struct xxx_softc *sc;
{
/* check every resource and free if not zero */
/* interrupt handler */
if(sc->intr_r) {
bus_teardown_intr(sc->dev, sc->intr_r, sc->intr_cookie);
bus_release_resource(sc->dev, SYS_RES_IRQ, sc->intr_rid,
sc->intr_r);
sc->intr_r = 0;
}
/* all kinds of memory maps we could have allocated */
if(sc->data_p) {
bus_dmamap_unload(sc->data_tag, sc->data_map);
sc->data_p = 0;
}
if(sc->data) { /* sc->data_map may be legitimately equal to 0 */
/* the map will also be freed */
bus_dmamem_free(sc->data_tag, sc->data, sc->data_map);
sc->data = 0;
}
if(sc->data_tag) {
bus_dma_tag_destroy(sc->data_tag);
sc->data_tag = 0;
}
... free other maps and tags if we have them ...
if(sc->parent_tag) {
bus_dma_tag_destroy(sc->parent_tag);
sc->parent_tag = 0;
}
/* release all the bus resources */
if(sc->mem0_r) {
bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->mem0_rid,
sc->mem0_r);
sc->mem0_r = 0;
}
...
if(sc->port0_r) {
bus_release_resource(sc->dev, SYS_RES_IOPORT, sc->port0_rid,
sc->port0_r);
sc->port0_r = 0;
}
}xxx_isa_attachThe attach routine actually connects the driver to the
system if the probe routine returned success and the system
had chosen to attach that driver. If the probe routine
returned 0 then the attach routine may expect to receive the
device structure softc intact, as it was set by the probe
routine. Also if the probe routine returns 0 it may expect
that the attach routine for this device shall be called at
some point in the future. If the probe routine returns a
negative value then the driver may make none of these
assumptions.
The attach routine returns 0 if it completed successfully or
error code otherwise.
The attach routine starts just like the probe routine,
with getting some frequently used data into more accessible
variables.
struct xxx_softc *sc = device_get_softc(dev);
int unit = device_get_unit(dev);
int error = 0;Then allocate and activate all the necessary
resources. Because normally the port range will be released
before returning from probe, it has to be allocated
again. We expect that the probe routine had properly set all
the resource ranges, as well as saved them in the structure
softc. If the probe routine had left some resource allocated
then it does not need to be allocated again (which would be
considered an error).
sc->port0_rid = 0;
sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port0_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->port0_r == NULL)
return ENXIO;
/* on-board memory */
sc->mem0_rid = 0;
sc->mem0_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem0_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->mem0_r == NULL)
goto bad;
/* get its virtual address */
sc->mem0_v = rman_get_virtual(sc->mem0_r);The DMA request channel (DRQ) is allocated likewise. To
initialize it use functions of the
isa_dma*() family. For example:
isa_dmacascade(sc->drq0);The interrupt request line (IRQ) is a bit
special. Besides allocation the driver's interrupt handler
should be associated with it. Historically in the old ISA
drivers the argument passed by the system to the interrupt
handler was the device unit number. But in modern drivers
the convention suggests passing the pointer to structure
softc. The important reason is that when the structures
softc are allocated dynamically then getting the unit number
from softc is easy while getting softc from the unit number is
difficult. Also this convention makes the drivers for
different buses look more uniform and allows them to share
the code: each bus gets its own probe, attach, detach and
other bus-specific routines while the bulk of the driver
code may be shared among them.
sc->intr_rid = 0;
sc->intr_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->intr_rid,
/*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
if(sc->intr_r == NULL)
goto bad;
/*
* XXX_INTR_TYPE is supposed to be defined depending on the type of
* the driver, for example as INTR_TYPE_CAM for a CAM driver
*/
error = bus_setup_intr(dev, sc->intr_r, XXX_INTR_TYPE,
(driver_intr_t *) xxx_intr, (void *) sc, &sc->intr_cookie);
if(error)
goto bad;
If the device needs to make DMA to the main memory then
this memory should be allocated like described before:
error=bus_dma_tag_create(NULL, /*alignment*/ 4,
/*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_24BIT,
/*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL,
/*maxsize*/ BUS_SPACE_MAXSIZE_24BIT,
/*nsegments*/ BUS_SPACE_UNRESTRICTED,
/*maxsegsz*/ BUS_SPACE_MAXSIZE_24BIT, /*flags*/ 0,
&sc->parent_tag);
if(error)
goto bad;
/* many things get inherited from the parent tag
* sc->data is supposed to point to the structure with the shared data,
* for example for a ring buffer it could be:
* struct {
* u_short rd_pos;
* u_short wr_pos;
* char bf[XXX_RING_BUFFER_SIZE]
* } *data;
*/
error=bus_dma_tag_create(sc->parent_tag, 1,
0, BUS_SPACE_MAXADDR, 0, /*filter*/ NULL, /*filterarg*/ NULL,
/*maxsize*/ sizeof(* sc->data), /*nsegments*/ 1,
/*maxsegsz*/ sizeof(* sc->data), /*flags*/ 0,
&sc->data_tag);
if(error)
goto bad;
error = bus_dmamem_alloc(sc->data_tag, &sc->data, /* flags*/ 0,
&sc->data_map);
if(error)
goto bad;
/* xxx_alloc_callback() just saves the physical address at
* the pointer passed as its argument, in this case &sc->data_p.
* See details in the section on bus memory mapping.
* It can be implemented like:
*
* static void
* xxx_alloc_callback(void *arg, bus_dma_segment_t *seg,
* int nseg, int error)
* {
* *(bus_addr_t *)arg = seg[0].ds_addr;
* }
*/
bus_dmamap_load(sc->data_tag, sc->data_map, (void *)sc->data,
sizeof (* sc->data), xxx_alloc_callback, (void *) &sc->data_p,
/*flags*/0);After all the necessary resources are allocated the
device should be initialized. The initialization may include
testing that all the expected features are functional. if(xxx_initialize(sc) < 0)
goto bad; The bus subsystem will automatically print on the
console the device description set by probe. But if the
driver wants to print some extra information about the
device it may do so, for example:
device_printf(dev, "has on-card FIFO buffer of %d bytes\n", sc->fifosize);
If the initialization routine experiences any problems
then printing messages about them before returning error is
also recommended.The final step of the attach routine is attaching the
device to its functional subsystem in the kernel. The exact
way to do it depends on the type of the driver: a character
device, a block device, a network device, a CAM SCSI bus
device and so on.If all went well then return success. error = xxx_attach_subsystem(sc);
if(error)
goto bad;
return 0; Finally, handle the troublesome situations. All the
resources should be deallocated before returning an
error. We make use of the fact that before the structure
softc is passed to us it gets zeroed out, so we can find out
if some resource was allocated: then its descriptor is
non-zero. bad:
xxx_free_resources(sc);
if(error)
return error;
else /* exact error is unknown */
return ENXIO;That would be all for the attach routine.xxx_isa_detach
If this function is present in the driver and the driver is
compiled as a loadable module then the driver gets the
ability to be unloaded. This is an important feature if the
hardware supports hot plug. But the ISA bus does not support
hot plug, so this feature is not particularly important for
the ISA devices. The ability to unload a driver may be
useful when debugging it, but in many cases installation of
the new version of the driver would be required only after
the old version somehow wedges the system and a reboot will be
needed anyway, so the efforts spent on writing the detach
routine may not be worth it. Another argument that
unloading would allow upgrading the drivers on a production
machine seems to be mostly theoretical. Installing a new
version of a driver is a dangerous operation which should
never be performed on a production machine (and which is not
permitted when the system is running in secure mode). Still,
the detach routine may be provided for the sake of
completeness.
The detach routine returns 0 if the driver was successfully
detached or the error code otherwise.
The logic of detach is a mirror of the attach. The first
thing to do is to detach the driver from its kernel
subsystem. If the device is currently open then the driver
has two choices: refuse to be detached or forcibly close and
proceed with detach. The choice used depends on the ability
of the particular kernel subsystem to do a forced close and
on the preferences of the driver's author. Generally the
forced close seems to be the preferred alternative.
struct xxx_softc *sc = device_get_softc(dev);
int error;
error = xxx_detach_subsystem(sc);
if(error)
return error;
Next the driver may want to reset the hardware to some
consistent state. That includes stopping any ongoing
transfers, disabling the DMA channels and interrupts to
avoid memory corruption by the device. For most of the
drivers this is exactly what the shutdown routine does, so
if it is included in the driver we can just call it.
xxx_isa_shutdown(dev);
And finally release all the resources and return success.
xxx_free_resources(sc);
return 0;xxx_isa_shutdown
This routine is called when the system is about to be shut
down. It is expected to bring the hardware to some
consistent state. For most of the ISA devices no special
action is required, so the function is not really necessary
because the device will be re-initialized on reboot
anyway. But some devices have to be shut down with a special
procedure, to make sure that they will be properly detected
after soft reboot (this is especially true for many devices
with proprietary identification protocols). In any case
disabling DMA and interrupts in the device registers and
stopping any ongoing transfers is a good idea. The exact
action depends on the hardware, so we do not consider it here
in any detail.
xxx_intr
The interrupt handler is called when an interrupt is
received which may be from this particular device. The ISA
bus does not support interrupt sharing (except in some special
cases) so in practice if the interrupt handler is called
then the interrupt almost for sure came from its
device. Still, the interrupt handler must poll the device
registers and make sure that the interrupt was generated by
its device. If not it should just return.
The old convention for the ISA drivers was getting the
device unit number as an argument. This is obsolete, and the
new drivers receive whatever argument was specified for them
in the attach routine when calling
bus_setup_intr(). By the new convention
it should be the pointer to the structure softc. So the
interrupt handler commonly starts as:
static void
xxx_intr(struct xxx_softc *sc)
{
It runs at the interrupt priority level specified by the
interrupt type parameter of
bus_setup_intr(). That means that all
the other interrupts of the same type as well as all the
software interrupts are disabled.
To avoid races it is commonly written as a loop:
while(xxx_interrupt_pending(sc)) {
xxx_process_interrupt(sc);
xxx_acknowledge_interrupt(sc);
}
The interrupt handler has to acknowledge interrupt to the
device only but not to the interrupt controller, the system
takes care of the latter.
diff --git a/en_US.ISO8859-1/books/developers-handbook/mac/chapter.sgml b/en_US.ISO8859-1/books/developers-handbook/mac/chapter.sgml
index a08c5e5cec..e72a1fb5ad 100644
--- a/en_US.ISO8859-1/books/developers-handbook/mac/chapter.sgml
+++ b/en_US.ISO8859-1/books/developers-handbook/mac/chapter.sgml
@@ -1,5716 +1,5716 @@
ChrisCostelloTrustedBSD Projectchris@FreeBSD.orgRobertWatsonTrustedBSD Projectrwatson@FreeBSD.orgThe TrustedBSD MAC FrameworkSynopsisMandatory Access Control (MAC) is a security feature frequently
found in commercial trusted operating systems. MAC supplements
existing Discretionary Access Control (DAC) protections (such as
file system permissions and access control lists) by allowing the
security administrator to define mandatory protections for
system objects. Mandatory protections may be distinguished from
discretionary protections in that DAC is applied at the discretion
of the object owner, whereas MAC protections are defined by the
administrator and applied to all users and objects in the system
and may not be bypassed even by object owners. A variety of
MAC policies have been explored in security research literature
as well as the commercial trusted operating system space. These
include policies such as the Multi-Level Security (MLS)
confidentiality policy, used to prevent inappropriate sharing of
information on multi-user systems, and the Biba integrity policy,
typically used to protect the integrity of system and user
services.The implementation of MAC found in FreeBSD was developed by
the TrustedBSD Project, and includes support for both a number of
specific MAC policies, and for a flexible and extensible security
framework to support the easy creation of new kernel security
policies. This framework isolates the internals of specific MAC
policies from the implementation of kernel services, and
encapsulates the policies in policy modules. Policy modules may
be added to the system without changes to the base kernel, and can
augment the kernel security policy in a variety of ways. In
addition, policies may provide a shared object implementation
of common MAC interfaces for userland applications, permitting
applications to be easily extended to manage labels for new
policies. Support is provided for setting labels on user
processes at login, as well as in a number of other locations where
user context management occurs.This chapter introduces the MAC policy userland and kernel
policy frameworks and provides documentation for a sample MAC
policy module.IntroductionThe TrustedBSD MAC framework provides a mechanism to allow
the compile-time or run-time extension of the kernel access
control model. New system policies may be implemented as
kernel modules and linked to the kernel; if multiple policy
modules are present, their results will be composed. While the
framework is intended to support a variety of access control
models, its design was derived from the requirements of a set
of specific access control models required for the TrustedBSD
and CBOSS Projects. This includes support for fixed and
floating label Biba integrity policies, the MLS
confidentiality policy, the Type Enforcement rule-based access
control policy, and the ability to support layering of the NSA
FLASK framework above the TrustedBSD MAC framework. This
document describes the rough architecture of the framework,
with the understanding that this is a work-in-progress and may
change subtantially as requirements evolve.Kernel ArchitectureThe TrustedBSD MAC framework provides the opportunity for
policy modules to be augment system access control decisions.
Policies are permitted the opportunity to restrict the set of
rights available for processes at a variety of relevant points
in the kernel. In addition, they are provided the opportunity
to tag processes and various kernel objects with labels storing
access control information. Policy modules may register
interest in a subset of the total available events or objects,
and are not required to implement events or objects that are not
relevant to the policy. Multiple modules may be loaded at once,
and the results of the modules are composed as necessary to
build an over-all system policy. Policy modules may be
implemented such that they can be loaded on-demand at run-time,
or such that they may only be loaded early in the boot process.
This permits policies requiring pervasive labeling of all
objects to prevent improper use.Userland Architecture...Entry Point FrameworkFour classes of entry points are offered to policies
registered with the framework: entry points associated with
the registration and management of policies, entry points
denoting initialization, creation, destruction, and other life
cycle events for kernel objects, events assocated with access
control decisions that the policy module may influence, and
calls associated with the management of labels on objects. In
addition, a mac_syscall() entry point is
provided so that policies may extend the kernel interface
without registering new system calls.Policy module writers should be aware of the kernel
locking strategy, as well as what object locks are available
during which entry points. Writers should attempt to avoid
deadlock scenarios by avoiding grabbing non-leaf locks inside
of entry points, and also follow the locking protocol for
object access and modification. In particular, writers should
be aware that while necessary locks to access objects and
their labels are generally held, sufficient locks to modify an
object or its label may not be present for all entry points.
Locking information for arguments is documented in the MAC
framework entry point document.Policy entry points will pass a reference to the object
label along with the object itself. This permits labeled
policies to be unaware of the internals of the object yet
still make decisions based on the label. The exception to this
is the process credential, which is assumed to be understood
by policies as a first class security object in the kernel.
Policies that do not implement labels on kernel objects will
be passed NULL pointers for label arguments to entry
points.Policy Module RegistrationModules may be declared using the
MAC_POLICY_SET() macro, which names the
policy, provides a reference to the MAC entry point vector,
provides load-time flags determining how the policy framework
should handle the policy, and optionally requests the
allocation of label state by the framework:static struct mac_policy_op_entry mac_none_ops[] =
{
{ MAC_DESTROY,
(macop_t)mac_none_destroy },
{ MAC_INIT,
(macop_t)mac_none_init },
{ MAC_INIT_BPFDESC,
(macop_t)mac_none_init_bpfdesc },
/* ... */
{ MAC_CHECK_VNODE_STAT,
(macop_t)mac_none_check_vnode_stat },
{ MAC_CHECK_VNODE_WRITE,
(macop_t)mac_none_check_vnode_write },
{ MAC_OP_LAST, NULL }
};The MAC policy entry point vector,
mac_none_ops in this example, associates
functions defined in the module with specific entry points. A
complete listing of available entry points and their
prototypes may be found in the MAC entry point reference
section. Of specific interest during module registration are
the MAC_DESTROY and MAC_INIT
entry points. MAC_INIT will be invoked once a
policy is successfully registered with the module framework
but prior to any other entry points becoming active. This
permits the policy to perform any policy-specific allocation
and initialization, such as initialization of any data or
locks. MAC_DESTROY will be invoked when a
policy module is unloaded to permit releasing of any allocated
memory and destruction of locks. Currently, these two entry
points are invoked with the MAC policy list mutex held to
prevent any other entry points from being invoked: this will
be changed, but in the mean time, policies should be careful
about what kernel primitives they invoke so as to avoid lock
ordering or sleeping problems.The policy declaration's module name field exists so that
the module may be uniquely identified for the purposes of
module dependencies. An appropriate string should be selected.
The full string name of the policy is displayed to the user
via the kernel log during load and unload events, and also
exported when providing status information to userland
processes.The policy flags field permits the module to provide the
framework with information about its loader-related
capabilities. Currently, two flags are defined:MPC_LOADTIME_FLAG_UNLOADOKThis flag indicates that the policy module may be
unloaded. If this flag is not provided, then the policy
framework will reject requests to unload the module.
This flag might be used by modules that allocate label
state and are unable to free that state at
runtime.MPC_LOADTIME_FLAG_NOTLATEThis flag indicates that the policy module
must be loaded and initialized early in the boot
process. If the flag is specified, attempts to register
the module following boot will be rejected. The flag
may be used by policies that require pervasive labeling
of all system objects, and cannot handle objects that
have not been properly initialized by the policy.&mac.mpo;_initvoid
&mac.mpo;_initstruct mac_policy_conf
*conf
&mac.thead;
confMAC policy definitionPolicy load event. The policy list mutex is held, so
caution should be applied.&mac.mpo;_destroyvoid
&mac.mpo;_destroystruct mac_policy_conf
*conf
&mac.thead;
confMAC policy definitionPolicy load event. The policy list mutex is held, so
caution should be applied.Label EventsThis class of entry points is used by the MAC framework to
permit policies to maintain label information on kernel
objects. For each labeled kernel object of interest to a MAC
policy, entry points may be registered for relevant life cycle
events. All objects implement initialization, creation, and
destruction hooks. Some objects will also implement
relabeling, allowing user processes to change the labels on
objects. Some objects will also implement object-specific
events, such as label events associated with IP reassembly. A
typical labeled object will have the following life cycle of
entry points:Label initialization o
(object-specific wait) \
Label creation o
\
Relabel events, o--<--.
Various object-specific, | |
Access control events ~-->--o
\
Label destruction oLabel initialization permits policies to allocate memory
and set initial values for labels without context for the use
of the object. The label slot allocated to a policy will be
zero'd by default, so some policies may not need to perform
initialization.Label creation occurs when the kernel structure is
associated with an actual kernel object. For example, mbufs
may be allocated and remain unused in a pool until they are
required. mbuf allocation causes label initialization on the
mbuf to take place, but mbuf creation occurs when the mbuf is
associated with a datagram. Typically, context will be
provided for a creation event, including the circumstances of
the creation, and labels of other relevant objects in the
creation process. For example, when an mbuf is created from a
socket, the socket and its label will be presented to
registered policies in addition to the new mbuf and its label.
Memory allocation in creation events is discouraged, as it may
occur in performance sensitive ports of the kernel; in
addition, creation calls are not permitted to fail so a
failure to allocate memory cannot be reported.Object specific events do not generally fall into the
other broad classes of label events, but will generally
provide an opportunity to modify or update the label on an
object based on additional context. For example, the label on
an IP fragment reassembly queue may be updated during the
MAC_UPDATE_IPQ entry point as a result of the
acceptance of an additional mbuf to that queue.Access control events are discussed in detail in the
following section.Label destruction permits policies to release storage or
state associated with a label during its association with an
object so that the kernel data structures supporting the
object may be reused or released.In addition to labels associated with specific kernel
objects, an additional class of labels exists: temporary
labels. These labels are used to store update information
submitted by user processes. These labels are initialized and
destroyed as with other label types, but the creation event is
MAC_INTERNALIZE, which accepts a user label
to be converted to an in-kernel representation.File System Object Labeling Event Operations&mac.mpo;_create_devfs_devicevoid
&mac.mpo;_create_devfs_devicedev_t devstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
devDevice corresponding with
devfs_direntdevfs_direntDevfs directory entry to be labeled.labelLabel for devfs_dirent
to be filled in.Fill out the label on a devfs_dirent being created for
the passed device. This call will be made when the device
file system is mounted, regenerated, or a new device is made
available.&mac.mpo;_create_devfs_directoryvoid
&mac.mpo;_create_devfs_directorychar *dirnameint dirnamelenstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
dirnameName of directory being creatednamelenLength of string
dirnamedevfs_direntDevfs directory entry for directory being
created.Fill out the label on a devfs_dirent being created for
the passed directory. This call will be made when the device
file system is mounted, regenerated, or a new device
requiring a specific directory hierarchy is made
available.&mac.mpo;_create_devfs_vnodevoid
&mac.mpo;_create_devfs_vnodestruct devfs_dirent
*devfs_direntstruct label
*direntlabelstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
devfs_direntObject; devfs directory entrydirentlabelPolicy label for
devfs_direntvpObject; file system object being labeledvnodelabelPolicy label to be filled in for
vpFill out the label on the vnode being created for the
passed devfs_dirent. This call will be made when a vnode is
required to represent the specified devfs_dirent in a
mounted devfs instance.&mac.mpo;_vnode_create_from_vnodevoid
&mac.mpo;_vnode_create_from_vnodestruct ucred
*credstruct vnode
*parentstruct label
*parentlabelstruct vnode
*childstruct label
*childlabel
&mac.thead;
credSubject credentialparentParent vnode; the directory in which
child is being
createdparentlabelPolicy label for
parentchildNew vnodechildlabelLabel to be filled in for
childFill out the label on the vnode being created in the
passed vnode parent by the passed subject credential. This
call will be made when a vnode is allocated during a vnode
creation operation. For example, this call is made by
multi-label file systems during the creation of a new file
or directory.&mac.mpo;_create_mountvoid
&mac.mpo;_create_mountstruct ucred
*credstruct mount
*mpstruct label
*mntstruct label
*fslabel
&mac.thead;
credSubject credentialmpObject; file system being mountedmntlabelPolicy label to be filled in for
mpfslabelPolicy label for the file system
mp mounts.Fill out the labels on the mount point being created by
the passed subject credential. This call will be made when
a new file system is mounted.&mac.mpo;_create_root_mountvoid
&mac.mpo;_create_root_mountstruct ucred
*credstruct mount
*mpstruct label
*mntlabelstruct label
*fslabel
&mac.thead;
See .Fill out the labels on the mount point being created by
the passed subject credential. This call will be made when
the root file system is mounted, after
&mac.mpo;_create_mount;.&mac.mpo;_vnode_relabelvoid
&mac.mpo;_vnode_relabelstruct ucred
*credstruct vnode
*vpstruct label
*vnodelabelstruct label
*newlabel
&mac.thead;
credSubject credentialvpvnode to relabelvnodelabelExisting policy label for
vpnewlabelNew, possibly partial label to replace
vnodelabelUpdate the label on the passed vnode given the passed
update vnode label and the passed subject credential.&mac.mpo;_stdcreatevnode_eaint
&mac.mpo;_stdcreatevnode_eastruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
vpvnode to commitLocked on entry, locked on exitvnodelabelLabel associated with
vpThis entry point is called when a vnode is to be
committed to disk via the extended attribute service (see
&man.extattr.9;). If committing to the disk is successful,
a value of 0 should be returned;
otherwise, an appropriate error code should be
returned.The current implementation as of July 24, 2002
commits the data to disk from within the architecture.
The implementation will be updated to be closer to the
above documentation as development progresses.&mac.mpo;_update_devfsdirentvoid
&mac.mpo;_update_devfsdirentstruct devfs_dirent
*devfs_direntstruct label
*direntlabelstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
devfs_direntObject; devfs directory entrydirentlabelPolicy label for
devfs_dirent to be
updated.vpParent vnodeLockedvnodelabelPolicy label for
vpUpdate the devfs_dirent label
from the passed devfs vnode label. This call will be made
when a devfs vnode has been successfully relabeled to commit
the label change such that it lasts even if the vnode is
recycled. It will also be made when when a symlink is
created in devfs, following a call to
mac_vnode_create_from_vnode to
initialize the vnode label.&mac.mpo;_update_procfsvnodevoid
&mac.mpo;_update_procfsvnodestruct vnode
*vpstruct label
*vnodelabelstruct ucred
*cred
&mac.thead;
vpObject; procfs vnodeLockedvnodelabelPolicy label to be filled in for
vpcredSubject; credential for the process
entryImmutableUpdate the procfs vnode label from the passed subject
credential. This call will be made when an operation on a
procfs vnode requires a fresh label on a process-derived
vnode.&mac.mpo;_update_vnode_from_extattrint
&mac.mpo;_update_vnode_from_extattrstruct vnode
*vpstruct label
*vnodelabelstruct mount
*mpstruct label
*fslabel
&mac.thead;
vpObject; vnode whose label is being updatedLockedvnodelabelPolicy label to refreshmpMount point for
vpfslabelPolicy label for vp's
file system.Update the vnode label by refreshing the label data from
the extended attribute service for the vnode. The mount
point fslabel is also made available
so that the fslabel may be used as a
labeling source if fallback is appropriate for the policy.
This call is permitted to fail; if the call fails, the
associated label refresh will also fail, causing the failure
of the operation requiring the MAC check and vnode label
refresh, permitting a fail closed policy if
labeling data is not available.&mac.mpo;_update_from_externalizedint
&mac.mpo;_update_from_externalizedstruct vnode
*vpstruct label
*vnodelabelstruct mac
*extmac
&mac.thead;
vpObject; vnodeLockedvnodelabelPolicy label for
vpextmacExternalized MAC policy labelUpdate the vnode label from the passed externalized
label loaded from disk by the MAC framework. This call is
permitted to fail; if the call fails, the associated label
refresh will also fail, causing the failure of the operation
requiring the MAC check and vnode label refresh, permitting
a fail closed policy if labeling data is not
available. This call will be obsoleted by the new extended
attribute labeling interface.&mac.mpo;_update_vnode_from_mountvoid
&mac.mpo;_update_vnode_from_mountstruct vnode
*vpstruct label
*vnodelabelstruct mount
*mpstruct label
*mountlabel
&mac.thead;
vpObject; vnodeLockedvnodelabelPolicy label for
vpmpMount point where vp
residesfslabelPolicy label for the file system where
vp resides.Update the vnode label from the passed mount point
label. This call is made when a single label file system
vnode requires a label, or if the obsoleted MAC framework
externalized extended attribute read fails.IPC Object Labeling Event Operations&mac.mpo;_create_mbuf_from_socketvoid
&mac.mpo;_create_mbuf_from_socketstruct socket
*sostruct label
*socketlabelstruct mbuf *mstruct label
*mbuflabel
&mac.thead;
socketSocketSocket locking WIPsocketlabelPolicy label for
socketmObject; mbufmbuflabelPolicy label to fill in for
mSet the label on a newly created mbuf header from the
passed socket label. This call is made when a new datagram
or messsage is generated by the socket and stored in the
passed mbuf.&mac.mpo;_create_socketvoid
&mac.mpo;_create_socketstruct ucred
*credstruct socket
*sostruct label
*socketlabel
&mac.thead;
credSubject credentialImmutablesoObject; socket to labelsocketlabelLabel to fill in for
soSet the label on a newly created socket from the passed
subject credential. This call is made when a socket is
created.&mac.mpo;_create_socket_from_socketvoid
&mac.mpo;_create_socket_from_socketstruct socket
*oldsocketstruct label
*oldsocketlabelstruct socket
*newsocketstruct label
*newsocketlabel
&mac.thead;
oldsocketObject; parent socket; created from
&man.listen.2;oldsocketlabelLabel for
oldsocketnewsocketObject; child socket; incoming connectionnewsocketlabelLabel to be filled in for
newsocketSet the label on a newly created stream socket from the
passed listen socket. This call may occur during &man.accept.2;,
or prior to &man.accept.2;, depending on the protocol.&mac.mpo;_socket_relabelvoid
&mac.mpo;_socket_relabelstruct ucred
*credstruct socket
*sostruct label
*oldlabelstruct label
*newlabel
&mac.thead;
credSubject credentialImmutablesoObject; socketoldlabelCurrent label for
sonewlabelLabel update for
soUpdate the label on a socket from the passed socket
label update.&mac.mpo;_set_socket_peer_from_mbufvoid
&mac.mpo;_set_socket_peer_from_mbufstruct mbuf
*mbufstruct label
*mbuflabelstruct label
*oldlabelstruct label
*newlabel
&mac.thead;
mbufFirst datagram received over socketmbuflabelLabel for mbufoldlabelCurrent label for the socketnewlabelPolicy label to be filled out for the
socketSet the peer label on a stream socket from the passed
mbuf label. This call will be made when the first datagram
is received by the stream socket, with the exception of Unix
domain sockets.&mac.mpo;_set_socket_peer_from_socketvoid
&mac.mpo;_set_socket_peer_from_socketstruct socket
*oldsocketstruct label
*oldsocketlabelstruct socket
*newsocketstruct label
*newsocketpeerlabel
&mac.thead;
oldsocketLocal socketoldsocketlabelPolicy label for
oldsocketnewsocketPeer socketnewsocketpeerlabelPolicy label to fill in for
newsocketSet the peer label on a stream UNIX domain socket from
the passed remote socket endpoint. This call will be made
when the socket pair is connected, and will be made for both
endpoints.Network Object Labeling Event Operations&mac.mpo;_create_bpfdescvoid
&mac.mpo;_create_bpfdescstruct ucred
*credstruct bpf_d
*bpf_dstruct label
*bpflabel
&mac.thead;
credSubject credentialImmutablebpf_dObject; bpf descriptorbpfPolicy label to be filled in for
bpf_dSet the label on a newly created BPF descriptor from the
passed subject credential. This call will be made when a
BPF device node is opened by a process with the passed
subject credential.&mac.mpo;_create_ifnetvoid
&mac.mpo;_create_ifnetstruct ifnet
*ifnetstruct label
*ifnetlabel
&mac.thead;
ifnetNetwork interfaceifnetlabelPolicy label to fill in for
ifnetSet the label on a newly created interface. This call
may be made when a new physical interface becomes available
to the system, or when a pseudo-interface is instantiated
during the boot or as a result of a user action.&mac.mpo;_create_ipqvoid
&mac.mpo;_create_ipqstruct mbuf
*fragmentstruct label
*fragmentlabelstruct ipq
*ipqstruct label
*ipqlabel
&mac.thead;
fragmentFirst received IP fragmentfragmentlabelPolicy label for
fragmentipqIP reassembly queue to be labeledipqlabelPolicy label to be filled in for
ipqSet the label on a newly created IP fragment reassembly
queue from the mbuf header of the first received
fragment.&mac.mpo;_create_datagram_from_ipqvoid
&mac.mpo;_create_create_datagram_from_ipqstruct ipq
*ipqstruct label
*ipqlabelstruct mbuf
*datagramstruct label
*datagramlabel
&mac.thead;
ipqIP reassembly queueipqlabelPolicy label for
ipqdatagramDatagram to be labeleddatagramlabelPolicy label to be filled in for
datagramlabelSet the label on a newly reassembled IP datagram from
the IP fragment reassembly queue from which it was
generated.&mac.mpo;_create_fragmentvoid
&mac.mpo;_create_fragmentstruct mbuf
*datagramstruct label
*datagramlabelstruct mbuf
*fragmentstruct label
*fragmentlabel
&mac.thead;
datagramDatagramdatagramlabelPolicy label for
datagramfragmentFragment to be labeledfragmentlabelPolicy label to be filled in for
datagramSet the label on the mbuf header of a newly created IP
fragment from the label on the mbuf header of the datagram
it was generate from.&mac.mpo;_create_mbuf_from_mbufvoid
&mac.mpo;_create_mbuf_from_mbufstruct mbuf
*oldmbufstruct label
*oldmbuflabelstruct mbuf
*newmbufstruct label
*newmbuflabel
&mac.thead;
oldmbufExisting (source) mbufoldmbuflabelPolicy label for
oldmbufnewmbufNew mbuf to be labelednewmbuflabelPolicy label to be filled in for
newmbufSet the label on the mbuf header of a newly created
datagram from the mbuf header of an existing datagram. This
call may be made in a number of situations, including when
an mbuf is re-allocated for alignment purposes.&mac.mpo;_create_mbuf_linklayervoid
&mac.mpo;_create_mbuf_linklayerstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
ifnetNetwork interfaceifnetlabelPolicy label for
ifnetmbufmbuf header for new datagrammbuflabelPolicy label to be filled in for
mbufSet the label on the mbuf header of a newly created
datagram generated for the purposes of a link layer response
for the passed interface. This call may be made in a number
of situations, including for ARP or ND6 responses in the
IPv4 and IPv6 stacks.&mac.mpo;_create_mbuf_from_bpfdescvoid
&mac.mpo;_create_mbuf_from_bpfdescstruct bpf_d
*bpf_dstruct label
*bpflabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
bpf_dBPF descriptorbpflabelPolicy label for
bpflabelmbufNew mbuf to be labeledmbuflabelPolicy label to fill in for
mbufSet the label on the mbuf header of a newly created
datagram generated using the passed BPF descriptor. This
call is made when a write is performed to the BPF device
associated with the passed BPF descriptor.&mac.mpo;_create_mbuf_from_ifnetvoid
&mac.mpo;_create_mbuf_from_ifnetstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
ifnetNetwork interfaceifnetlabelPolicy label for
ifnetlabelmbufmbuf header for new datagrammbuflabelPolicy label to be filled in for
mbufSet the label on the mbuf header of a newly created
datagram generated from the passed network interface.&mac.mpo;_create_mbuf_multicast_encapvoid
&mac.mpo;_create_mbuf_multicast_encapstruct mbuf
*oldmbufstruct label
*oldmbuflabelstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*newmbufstruct label
*newmbuflabel
&mac.thead;
oldmbufmbuf header for existing datagramoldmbuflabelPolicy label for
oldmbufifnetNetwork interfaceifnetlabelPolicy label for
ifnetnewmbufmbuf header to be labeled for new
datagramnewmbuflabelPolicy label to be filled in for
newmbufSet the label on the mbuf header of a newly created
datagram generated from the existing passed datagram when it
is processed by the passed multicast encapsulation
interface. This call is made when an mbuf is to be
delivered using the virtual interface.&mac.mpo;_create_mbuf_netlayervoid
&mac.mpo;_create_mbuf_netlayerstruct mbuf
*oldmbufstruct label
*oldmbuflabelstruct mbuf
*newmbufstruct label
*newmbuflabel
&mac.thead;
oldmbufReceived datagramoldmbuflabelPolicy label for
oldmbufnewmbufNewly created datagramnewmbuflabelPolicy label for
newmbufSet the label on the mbuf header of a newly created
datagram generated by the IP stack in response to an
existing received datagram (oldmbuf).
This call may be made in a number of situations, including
when responding to ICMP request datagrams.&mac.mpo;_fragment_matchint
&mac.mpo;_fragment_matchstruct mbuf
*fragmentstruct label
*fragmentlabelstruct ipq
*ipqstruct label
*ipqlabel
&mac.thead;
fragmentIP datagram fragmentfragmentlabelPolicy label for
fragmentipqIP fragment reassembly queueipqlabelPolicy label for
ipqDetermine whether an mbuf header containing an IP
datagram (fragment) fragment matches
the label of the passed IP fragment reassembly queue
(ipq). Return
(1) for a successful match, or
(0) for no match. This call is
made when the IP stack attempts to find an existing fragment
reassembly queue for a newly received fragment; if this
fails, a new fragment reassembly queue may be instantiated
for the fragment. Policies may use this entry point to
prevent the reassembly of otherwise matching IP fragments if
policy does not permit them to be reassembled based on the
label or other information.&mac.mpo;_ifnet_relabelvoid
&mac.mpo;_ifnet_relabelstruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct label
*newlabel
&mac.thead;
credSubject credentialifnetObject; Network interfaceifnetlabelPolicy label for
ifnetnewlabelLabel update to apply to
ifnetUpdate the label of network interface,
ifnet, based on the passed update
label, newlabel, and the passed
subject credential, cred.&mac.mpo;_update_ipqvoid
&mac.mpo;_update_ipqstruct mbuf
*fragmentstruct label
*fragmentlabelstruct ipq
*ipqstruct label
*ipqlabel
&mac.thead;
mbufIP fragmentmbuflabelPolicy label for
mbufipqIP fragment reassembly queueipqlabelPolicy label to be updated for
ipqUpdate the label on an IP fragment reassembly queue
(ipq) based on the acceptance of the
passed IP fragment mbuf header
(mbuf).Process Labeling Event Operations&mac.mpo;_create_credvoid
&mac.mpo;_create_credstruct ucred
*parent_credstruct ucred
*child_cred
&mac.thead;
parent_credParent subject credentialchild_credChild subject credentialSet the label of a newly created subject credential from
the passed subject credential. This call will be made when
crcopy(9) is invoked on a newly created struct
ucred. This call should not be confused with a
process forking or creation event.&mac.mpo;_execve_transitionvoid
&mac.mpo;_execve_transitionstruct ucred
*oldstruct ucred
*newstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
oldExisting subject credentialImmutablenewNew subject credential to be labeledvpFile to executeLockedvnodelabelPolicy label for
vpUpdate the label of a newly created subject credential
(new) from the passed existing
subject credential (old) based on a
label transition caused by executing the passed vnode
(vp). This call occurs when a
process executes the passed vnode and one of the policies
returns a success from the
mpo_execve_will_transition entry point.
Policies may choose to implement this call simply by
invoking mpo_create_cred and passing
the two subject credentials so as not to implement a
transitioning event. Policies should not leave this entry
point unimplemented if they implement
mpo_create_cred, even if they do not
implement
mpo_execve_will_transition.&mac.mpo;_execve_will_transitionint
&mac.mpo;_execve_will_transitionstruct ucred
*oldstruct vnode
*vpstruct label
*vnodelabel
&mac.thead;
oldSubject credential prior to
&man.execve.2;ImmutablevpFile to executevnodelabelPolicy label for
vpDetermine whether the policy will want to perform a
transition event as a result of the execution of the passed
vnode by the passed subject credential. Return
1 if a transition is required,
0 if not. Even if a policy
returns 0, it should behave
correctly in the presence of an unexpected invocation of
mpo_execve_transition, as that call may
happen as a result of another policy requesting a
transition.&mac.mpo;_create_proc0void
&mac.mpo;_create_proc0struct ucred
*cred
&mac.thead;
credSubject credential to be filled inCreate the subject credential of process 0, the parent
of all kernel processes.&mac.mpo;_create_proc1void
&mac.mpo;_create_proc1struct ucred
*cred
&mac.thead;
credSubject credential to be filled inCreate the subject credential of process 1, the parent
of all kernel processes.&mac.mpo;_cred_relabelvoid
&mac.mpo;_cred_relabelstruct ucred
*credstruct label
*newlabel
&mac.thead;
credSubject credentialnewlabelLabel update to apply to
credUpdate the label on a subject credential from the passed
update label.Access Control ChecksAccess control entry points permit policy modules to
influence access control decisions made by the kernel.
Generally, although not always, arguments to an access control
entry point will include one or more authorizing credentials,
information (possibly including a label) for any other objects
involved in the operation. An access control entry point may
return 0 to permit the operation, and an &man.errno.2; error
value. The results of invoking the entry point across various
registered policy modules will be composed as follows: if all
modules permit the operation to succeed, success will be
returned. If one or modules returns a failure, a failure will
be returned. If more than one module returns a failure, the
errno value to return to the user will be selected using the
following precedence, implemented by the
error_select() function in
kern_mac.c:Most precedenceEDEADLKEINVALESRCHENOENTEACCESLeast precedenceEPERMIf none of the error values returned by all modules are
listed in the precedence chart then an arbitrarily selected
value from the set will be returned. In general, the rules
provide precedence to errors in the following order: kernel
failures, invalid arguments, object not present, access not
permitted, other.&mac.mpo;_check_bpfdesc_receiveint
&mac.mpo;_check_bpfdesc_receivestruct bpf_d
*bpf_dstruct label
*bpflabelstruct ifnet
*ifnetstruct label
*ifnetlabel
&mac.thead;
bpf_dSubject; BPF descriptorbpflabelPolicy label for
bpf_difnetObject; network interfaceifnetlabelPolicy label for
ifnetDetermine whether the MAC framework should permit
datagrams from the passed interface to be delivered to the
buffers of the passed BPF descriptor. Return
(0) for success, or an
errno value for failure Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege.&mac.mpo;_check_socket_bindint
&mac.mpo;_check_socket_bindstruct ucred
*credstruct socket
*socketstruct label
*socketlabelstruct sockaddr
*sockaddr
&mac.thead;
credSubject credentialsocketSocket to be boundsocketlabelPolicy label for
socketsockaddrAddress of
socket&mac.mpo;_check_socket_connectint
&mac.mpo;_check_socket_connectstruct ucred
*credstruct socket
*socketstruct label
*socketlabelstruct sockaddr
*sockaddr
&mac.thead;
credSubject credentialsocketSocket to be connectedsocketlabelPolicy label for
socketsockaddrAddress of
socketDetermine whether the subject credential
(cred) can connect the passed socket
(socket) to the passed socket address
(sockaddr). Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege.&mac.mpo;_check_cred_visibleint
&mac.mpo;_check_cred_visiblestruct ucred
*u1struct ucred
*u2
&mac.thead;
u1Subject credentialu2Object credentialDetermine whether the subject credential
u1 can see other
subjects with the passed subject credential
u2. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege, or
ESRCH to hide visibility. This call
may be made in a number of situations, including
inter-process status sysctls used by ps,
and in procfs lookups.&mac.mpo;_check_socket_visibleint
&mac.mpo;_check_socket_visiblestruct ucred
*credstruct socket
*socketstruct label
*socketlabel
&mac.thead;
credSubject credentialsocketObject; socketsocketlabelPolicy label for
socket&mac.mpo;_check_ifnet_relabelint
&mac.mpo;_check_ifnet_relabelstruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct label
*newlabel
&mac.thead;
credSubject credentialifnetObject; network interfaceifnetlabelExisting policy label for
ifnetnewlabelPolicy label update to later be applied to
ifnetDetermine whether the subject credential can relabel the
passed network interface to the passed label update.&mac.mpo;_check_socket_relabelint
&mac.mpo;_check_socket_relabelstruct ucred
*credstruct socket
*socketstruct label
*socketlabelstruct label
*newlabel
&mac.thead;
credSubject credentialsocketObject; socketsocketlabelExisting policy label for
socketnewlabelLabel update to later be applied to
socketlabelDetermine whether the subject credential can relabel the
passed socket to the passed label update.&mac.mpo;_check_cred_relabelint
&mac.mpo;_check_cred_relabelstruct ucred
*credstruct label
*newlabel
&mac.thead;
credSubject credentialnewlabelLabel update to later be applied to
credDetermine whether the subject credential can relabel
itself to the passed label update.&mac.mpo;_check_vnode_relabelint
&mac.mpo;_check_vnode_relabelstruct ucred
*credstruct vnode
*vpstruct label
*vnodelabelstruct label
*newlabel
&mac.thead;
credSubject credentialImmutablevpObject; vnodeLockedvnodelabelExisting policy label for
vpnewlabelPolicy label update to later be applied to
vpDetermine whether the subject credential can relabel the
passed vnode to the passed label update.&mac.mpo;_check_mount_statint &mac.mpo;_check_mount_statstruct ucred
*credstruct mount
*mpstruct label
*mountlabel
&mac.thead;
credSubject credentialmpObject; file system mountmountlabelPolicy label for
mpDetermine whether the subject credential can see the
results of a statfs performed on the file system. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches
or EPERM for lack of privilege. This
call may be made in a number of situations, including during
invocations of &man.statfs.2; and related calls, as well as to
determine what file systems to exclude from listings of file
systems, such as when &man.getfsstat.2; is invoked. &mac.mpo;_check_proc_debugint
&mac.mpo;_check_proc_debugstruct ucred
*credstruct proc
*proc
&mac.thead;
credSubject credentialImmutableprocObject; processDetermine whether the subject credential can debug the
passed process. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, EPERM for lack of
privilege, or ESRCH to hide
visibility of the target. This call may be made in a number
of situations, including use of the &man.ptrace.2; and
&man.ktrace.2; APIs, as well as for some types of procfs
operations.&mac.mpo;_check_vnode_accessint
&mac.mpo;_check_vnode_accessstruct ucred
*credstruct vnode
*vpstruct label
*labelint flags
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpflags&man.access.2; flagsDetermine how invocations of &man.access.2; and related
calls by the subject credential should return when performed
on the passed vnode using the passed access flags. This
should generally be implemented using the same semantics
used in &mac.mpo;_check_vnode_open.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_chdirint
&mac.mpo;_check_vnode_chdirstruct ucred
*credstruct vnode
*dvpstruct label
*dlabel
&mac.thead;
credSubject credentialdvpObject; vnode to &man.chdir.2; intodlabelPolicy label for
dvpDetermine whether the subject credential can change the
process working directory to the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_createint
&mac.mpo;_check_vnode_createstruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct componentname
*cnpstruct vattr
*vap
&mac.thead;
credSubject credentialdvpObject; vnodedlabelPolicy label for
dvpcnpComponent name for
dvpvapvnode attributes for vapDetermine whether the subject credential can create a
vnode with the passed parent directory, passed name
information, and passed attribute information. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES. for label mismatch,
or EPERM for lack of privilege.
This call may be made in a number of situations, including
as a result of calls to &man.open.2; with
O_CREAT, &man.mknod.2;, &man.mkfifo.2;, and
others.&mac.mpo;_check_vnode_deleteint
&mac.mpo;_check_vnode_deletestruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct vnode
*vpvoid *labelstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpParent directory vnodedlabelPolicy label for
dvpvpObject; vnode to deletelabelPolicy label for
vpcnpComponent name for
vpDetermine whether the subject credential can delete a
vnode from the passed parent directory and passed name
information. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege. This call may be made in a number of situations,
including as a result of calls to &man.unlink.2; and
&man.rmdir.2;. Policies implementing this entry point
should also implement
mpo_check_rename_to to authorize
deletion of objects as a result of being the target of a
rename.&mac.mpo;_check_vnode_deleteaclint
&mac.mpo;_check_vnode_deleteaclstruct ucred *credstruct vnode *vpstruct label *labelacl_type_t type
&mac.thead;
credSubject credentialImmutablevpObject; vnodeLockedlabelPolicy label for
vptypeACL typeDetermine whether the subject credential can delete the
ACL of passed type from the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_execint
&mac.mpo;_check_vnode_execstruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnode to executelabelPolicy label for
vpDetermine whether the subject credential can execute the
passed vnode. Determination of execute privilege is made
- seperately from decisions about any transitioning event.
+ separately from decisions about any transitioning event.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_getaclint
&mac.mpo;_check_vnode_getaclstruct ucred
*credstruct vnode
*vpstruct label
*labelacl_type_t
type
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vptypeACL typeDetermine whether the subject credentical can retrieve
the ACL of passed type from the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_getextattrint
&mac.mpo;_check_vnode_getextattrstruct ucred
*credstruct vnode
*vpstruct label
*labelint
attrnamespaceconst char
*namestruct uio
*uio
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpattrnamespaceExtended attribute namespacenameExtended attribute nameuioI/O structure pointer; see &man.uio.9;Determine whether the subject credential can retrieve
the extended attribute with the passed namespace and name
from the passed vnode. Policies implementing labeling using
extended attributes may be interested in special handling of
operations on those extended attributes. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_socket_listenint
&mac.mpo;_check_socket_listenstruct ucred
*credstruct socket
*socketstruct label
*socketlabel
&mac.thead;
credSubject credentialsocketObject; socketsocketlabelPolicy label for
socketDetermine whether the subject credential can listen on
the passed socket. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege.&mac.mpo;_check_vnode_lookupint
&mac.mpo;_check_vnode_lookupstruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpObject; vnodedlabelPolicy label for
dvpcnpComponent name being looked upDetermine whether the subject credential can perform a
lookup in the passed directory vnode for the passed name.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_openint
&mac.mpo;_check_vnode_openstruct ucred
*credstruct vnode
*vpstruct label
*labelmode_t
acc_mode
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpacc_mode&man.open.2; access modeDetermine whether the subject credential can perform an
open operation on the passed vnode with the passed access
mode. Return 0 for success, or
an errno value for failure. Suggested failure:
EACCES for label mismatch, or
EPERM for lack of privilege.&mac.mpo;_check_vnode_readdirint
&mac.mpo;_check_vnode_readdirstruct ucred
*credstruct vnode
*dvpstruct label
*dlabel
&mac.thead;
credSubject credentialdvpObject; directory vnodedlabelPolicy label for
dvpDetermine whether the subject credential can perform a
readdir operation on the passed
directory vnode. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege.&mac.mpo;_check_vnode_readlinkint
&mac.mpo;_check_vnode_readlinkstruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpDetermine whether the subject credential can perform a
readlink operation on the passed
symlink vnode. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege. This call may be made in a number of situations,
including an explicit readlink call by
the user process, or as a result of an implicit
readlink during a name lookup by the
process.&mac.mpo;_check_rename_from_vnodeint
&mac.mpo;_check_rename_from_vnodestruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct vnode
*vpstruct label
*labelstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpDirectory vnodedlabelPolicy label for
dvpvpObject; vnodelabelPolicy label for
vpcnpPathnameDetermine whether the subject credential can rename the
passed vnode (vp) in the passed
directory (dvp) using the passed name
(cnp). This call will be made in
combination with a follow-up call to
mpo_check_rename_to_vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_rename_to_vnodeint
&mac.mpo;_check_rename_to_vnodestruct ucred
*credstruct vnode
*dvpstruct label
*dlabelstruct vnode
*vpstruct label
*labelint samedirstruct componentname
*cnp
&mac.thead;
credSubject credentialdvpDirectory vnodedlabelPolicy label for dvpvpObject; vnodelabelPolicy label for
vpcnpPathnameDetermine whether the subject credential can rename to
the passed vnode (vp) and the passed
directory (dvp) with the passed name
(cnp). This call will be made in
combination with an earlier call to
mpo_check_rename_from_vnode.
Return 0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_revokeint
&mac.mpo;_check_vnode_revokestruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpDetermine whether the subject credential can revoke
access to the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setaclint
&mac.mpo;_check_vnode_setaclstruct ucred
*credstruct vnode
*vpstruct label
*labelacl_type_t
typestruct acl
*acl
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vptypeACL typeaclACLDetermine whether the subject credential can set the
passed ACL of passed type on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setextattrint
&mac.mpo;_check_vnode_setextattrstruct ucred
*credstruct vnode
*vpstruct label
*labelint
attrnamespaceconst char
*namestruct uio
*uio
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for vpattrnamespaceExtended attribute namespacenameExtended attribute nameuioI/O structure pointer; see &man.uio.9;Determine whether the subject credentical can set the
extended attribute of passed name and passed namespace on
the passed vnode. Policies implementing security labels
backed into extended attributes may want to provide
additional protections for those attributes. Additionally,
policies should avoid making decisions based on the data
referenced from uio, as there is a
potential race condition between this check and the actual
operation. The uio may also be
NULL if a delete operation is being
performed. Return 0 for success,
or an errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setflagsint
&mac.mpo;_check_vnode_setflagsstruct ucred
*credstruct vnode
*vpstruct label
*labelu_long flags
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpflagsFile flags; see &man.chflags.2;Determine whether the subject credential can set the
passed flags on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setmodeint
&mac.mpo;_check_vnode_setmodestruct ucred
*credstruct vnode
*vpstruct label
*labelmode_t mode
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for vpmodeFile mode; see &man.chmod.2;Determine whether the subject credential can set the
pased mode on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_vnode_setownerint
&mac.mpo;_check_vnode_setownerstruct ucred
*credstruct vnode
*vpstruct label
*labeluid_t uidgid_t gid
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for vpuidUser IDgidGroup IDDetermine whether the subject credential can set the
passed uid and passed gid as file uid and file gid on the
passed vnode. The IDs may be set to (-1)
to request no update. Return 0
for success, or an errno value for
failure. Suggested failure: EACCES
for label mismatch, or EPERM for lack
of privilege.&mac.mpo;_check_vnode_setutimesint
&mac.mpo;_check_vnode_setutimesstruct ucred
*credstruct vnode
*vpstruct label
*labelstruct timespec
atimestruct timespec
mtime
&mac.thead;
credSubject credentialvpObject; vplabelPolicy label for
vpatimeAccess time; see &man.utimes.2;mtimeModification time; see &man.utimes.2;Determine whether the subject credential can set the
passed access timestamps on the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_proc_schedint
&mac.mpo;_check_proc_schedstruct ucred
*ucredstruct proc
*proc
&mac.thead;
credSubject credentialprocObject; processDetermine whether the subject credential can change the
scheduling parameters of the passed process. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
EPERM for lack of privilege, or
ESRCH to limit visibility.See &man.setpriority.2; for more information.&mac.mpo;_check_proc_signalint
&mac.mpo;_check_proc_signalstruct ucred
*credstruct proc
*procint signal
&mac.thead;
credSubject credentialprocObject; processsignalSignal; see &man.kill.2;Determine whether the subject credential can deliver the
passed signal to the passed process. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
EPERM for lack of privilege, or
ESRCH to limit visibility.&mac.mpo;_check_vnode_statint
&mac.mpo;_check_vnode_statstruct ucred
*credstruct vnode
*vpstruct label
*label
&mac.thead;
credSubject credentialvpObject; vnodelabelPolicy label for
vpDetermine whether the subject credential can
stat the passed vnode. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatch,
or EPERM for lack of
privilege.See &man.stat.2; for more information.&mac.mpo;_check_ifnet_transmitint
&mac.mpo;_check_ifnet_transmitstruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
credSubject credentialifnetNetwork interfaceifnetlabelPolicy label for
ifnetmbufObject; mbuf to be sentmbuflabelPolicy label for
mbufDetermine whether the network interface can transmit the
passed mbuf. Return 0 for
success, or an errno value for failure.
Suggested failure: EACCES for label
mismatch, or EPERM for lack of
privilege.&mac.mpo;_check_socket_receiveint
&mac.mpo;_check_socket_receivestruct ucred
*credstruct ifnet
*ifnetstruct label
*ifnetlabelstruct mbuf
*mbufstruct label
*mbuflabel
&mac.thead;
credSubject credentialifnetNetwork interfaceifnetlabelPolicy label for
ifnetmbufObject; mbuf to be receivedmbuflabelPolicy label for
mbufDetermine whether the socket may receive the datagram
stored in the passed mbuf header. Return
0 for success, or an
errno value for failure. Suggested
failures: EACCES for label mismatch,
or EPERM for lack of
privilege.&mac.mpo;_check_socket_visibleint
&mac.mpo;_check_socket_visiblestruct ucred
*credstruct socket
*sostruct label
*socketlabel
&mac.thead;
credSubject credentialImmutablesoObject; socketsocketlabelPolicy label for
soDetermine whether the subject credential cred can "see"
the passed socket (socket) using
system monitoring functions, such as those employed by
&man.netstat.8; and &man.sockstat.1;. Return
0 for success, or an
errno value for failure. Suggested
failure: EACCES for label mismatches,
EPERM for lack of privilege, or
ESRCH to hide visibility.Label Management CallsRelabel events occur when a user process has requested
that the label on an object be modified. A two-phase update
occurs: first, an access control check will be performed to
determine if the update is both valid and permitted, and then
- the update itself is performed via a seperate entry point.
+ the update itself is performed via a separate entry point.
Relabel entry points typically accept the object, object label
reference, and an update label submitted by the process.
Memory allocation during relabel is discouraged, as relabel
calls are not permitted to fail (failure should be reported
earlier in the relabel check).&mac.mpo;_init_bpfdescvoid
&mac.mpo;_init_bpfdescstruct bpf_d
*bpf_dstruct label
*label
&mac.thead;
bpf_dObject; bpf descriptorlabelNew label to applyInitialize the label on a newly instantiated bpfdesc (BPF
descriptor)&mac.mpo;_init_devfsdirentvoid
&mac.mpo;_init_devfsdirentstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
devfs_direntObject; devfs directory entrylabelNew label to applyInitialize the label on a newly instantiated devfs
entry.&mac.mpo;_init_ifnetvoid
&mac.mpo;_init_ifnetstruct ifnet
*ifnetstruct label
*label
&mac.thead;
ifnetObject; network interfacelabelNew label to applyInitialize the label on a newly instantiated network
interface.&mac.mpo;_init_ipqvoid
&mac.mpo;_init_ipqstruct ipq
*ipqstruct label
*label
&mac.thead;
ipqObject; IP reassembly queuelabelNew label to applyInitialize the label on a newly instantiated IP fragment
reassembly queue.&mac.mpo;_init_mbufvoid
&mac.mpo;_init_mbufstruct mbuf
*mbufint howstruct label
*label
&mac.thead;
mbufObject; mbufhowBlocking/non-blocking &man.malloc.9; see
belowlabelPolicy label to initializeInitialize the label on a newly instantiated mbuf packet
header (mbuf). The
how field may be one of
M_WAITOK and M_NOWAIT, and
should be employed to avoid performing a blocking
&man.malloc.9; during this initialization call. Mbuf
allocation frequently occurs in performance sensitive
environments, and the implementation should be careful to
avoid blocking or long-lived operations. This entry point
is permitted to fail resulting in the failure to allocate
the mbuf header.&mac.mpo;_init_mountvoid
&mac.mpo;_init_mountstruct mount
*mountstruct label
*mntlabelstruct label
*fslabel
&mac.thead;
mountObject; file system mount pointmntlabelPolicy label to be initialized for the mount
itselffslabelPolicy label to be initialized for the file
systemInitialize the labels on a newly instantiated mount
point.&mac.mpo;_init_socketvoid
&mac.mpo;_init_socketstruct socket
*socketstruct label
*labelstruct label
*peerlabel
&mac.thead;
socketObject; socketlabelNew label to apply to the socketpeerlabelNew label to apply to the socket's peerInitialize the labels on a newly instantiated
socket.&mac.mpo;_init_credvoid
&mac.mpo;_init_credstruct ucred
*credstruct label
*label
&mac.thead;
credSubject; user credetiallabelNew labelInitialize the labels on a newly instantiated subject.&mac.mpo;_init_tempvoid
&mac.mpo;_init_tempstruct label
*label
&mac.thead;
labelTemporary labelInitialize a newly instantiated temporary label;
temporary labels are frequently used to hold label update
requests.&mac.mpo;_init_vnodevoid
&mac.mpo;_init_vnodestruct vnode
*vpstruct label
*label
&mac.thead;
vpObject; file system objectlabelNew label to initializeInitialize the label on a newly instantiated vnode.&mac.mpo;_destroy_bpfdescvoid
&mac.mpo;_destroy_bpfdescstruct bpf_d
*bpf_dstruct label
*label
&mac.thead;
bpf_dObject; bpf descriptorlabelLabel being destroyedDestroy the label on a BPF descriptor. In this entry
point, a policy module should free any internal storage
associated with label so that it may
be destroyed.&mac.mpo;_destroy_devfsdirentvoid
&mac.mpo;_destroy_devfsdirentstruct devfs_dirent
*devfs_direntstruct label
*label
&mac.thead;
devfs_direntObject; devfs directory entrylabelLabel being destroyedDestroy the label on a devfs entry. In this entry
point, a policy module should free any internal storage
asociated with label so that it may
be destroyed.&mac.mpo;_destroy_ifnetvoid
&mac.mpo;_destroy_ifnetstruct ifnet
*ifnetstruct label
*label
&mac.thead;
ifnetObject; network interfacelabelLabel being destroyedDestroy the label on a removed interface. In this entry
point, a policy module should free any internal storage
associated with label so that it may
be destroyed.&mac.mpo;_destroy_ipqvoid
&mac.mpo;_destroy_ipqstruct ipq
*ipqstruct label
*label
&mac.thead;
ipqObject; IP reassembly queuelabelLabel being destroyedDestroy the label on an IP fragment queue. In this
entry point, a policy module should free any internal
storage associated with label so that
it may be destroyed.&mac.mpo;_destroy_mbufvoid
&mac.mpo;_destroy_mbufstruct mbuf
*mbufstruct label
*label
&mac.thead;
mbufObject; mbuflabelLabel being destroyedDestroy the label on an mbuf header. In this entry
point, a policy module should free any internal storage
associated with label so that it may
be destroyed.&mac.mpo;_destroy_mountvoid
&mac.mpo;_destroy_mountstruct mount
*mpstruct label
*mntlabelstruct label
*fslabel
&mac.thead;
mpObject; file system mount pointmntlabelMount point label being destroyedfslabelFile system label being destroyed>
Destroy the labels on a mount point. In this entry
point, a policy module should free the internal storage
associated with mntlabel and
fslabel so that they may be
destroyed.&mac.mpo;_destroy_socketvoid
&mac.mpo;_destroy_socketstruct socket
*socketstruct label
*labelstruct label
*peerlabel
&mac.thead;
socketObject; socketlabelSocket label being destroyedpeerlabelSocket peer label being destroyedDestroy the labels on a socket. In this entry point, a
policy module should free any internal storage associated
with label and
peerlabel so that they may be
destroyed.&mac.mpo;_destroy_credvoid
&mac.mpo;_destroy_credstruct ucred
*credstruct label
*label
&mac.thead;
credSubject; user credentiallabelLabel being destroyedDestroy the label on a credential. In this entry point,
a policy module should free any internal storage associated
with label so that it may be
destroyed.&mac.mpo;_destroy_tempvoid
&mac.mpo;_destroy_tempstruct label
*label
&mac.thead;
labelTemporary label being destroyedDestroy a temporary label. In this entry point, a
policy module should free any internal storage associated
with the temporary label label so
that it may be destroyed.&mac.mpo;_destroy_vnodevoid
&mac.mpo;_destroy_vnodestruct vnode
*vpstruct label
*label
&mac.thead;
vpObject; file system objectlabelLabel being destroyedDestroy the label on a vnode. In this entry point, a
policy module should free any internal storage associated
with label so that it may be
destroyed.&mac.mpo;_externalizevoid
&mac.mpo;_externalizestruct label
*labelstruct mac
*extmac
&mac.thead;
labelLabel to be externalizedextmacMAC structure to be filled inGiven an internalized subject or object label, fill out
an externalized label. This call is permitted to fail.
This call will be obsoleted by the new userland and extended
attribute interfaces for the MAC framework.&mac.mpo;_internalizevoid
&mac.mpo;_internalizestruct label
*labelstruct mac
*extmac
&mac.thead;
labelLabel to be filled inextmacMAC structure to internalizeGiven an externalized subject or object label, likely
from userland, internalize the label. The entry point
implementation should handle incorrect or corrupted labels.
This call is permitted to fail. This call will be obsoleted
by the new userland and extended attribute interfaces for
the MAC framework.Additional Framework API CallsThe MAC_SYSCALL entry point provides a
policy-multiplexed system call so that policies may provide
additional services to user processes without registering
specific system calls. The policy name provided during
registration is used to demux calls from userland, and the
arguments will be forwarded to this entry point. When
implementing new services, security modules should be sure to
invoke appropriate access control checks from the MAC
framework as needed. For example, if a policy implements an
augmented signal functionality, it should call the necessary
signal access control checks to invoke the MAC framework and
other registered policies.Userland APIsThe userland API is still under development.Sample Policy ModulesThe mac_none policy provides sample
prototypes and registration of all available policy entry
points.The mac_seeotheruids policy provides
a simple access control policy without the use of labeling,
relying only on information already present in the kernel
objects.The mac_biba policy provides a sample
information flow based labeled access control policy,
assigning labels to all kernel objects.System Integration...ConclusionThe TrustedBSD MAC framework permits kernel modules to
augment the system security policy in a highly integrated
manner. They may do this based on existing object properties,
or based on label data that is maintained with the assistance of
the MAC framework. The framework is sufficiently flexible to
implement a variety of policy types, including information flow
security policies such as MLS and Biba, as well as policies
based on existing BSD credentials or file protections. Policy
authors may wish to consult this documentation as well as
existing security modules when implementing a new security
service.
diff --git a/en_US.ISO8859-1/books/handbook/install/chapter.sgml b/en_US.ISO8859-1/books/handbook/install/chapter.sgml
index 4fa93fe38d..6bd4d5202b 100644
--- a/en_US.ISO8859-1/books/handbook/install/chapter.sgml
+++ b/en_US.ISO8859-1/books/handbook/install/chapter.sgml
@@ -1,5827 +1,5827 @@
JimMockRestructured, reorganized, and parts
rewritten by RandyPrattThe sysinstall walkthrough, screenshots, and general
copy by Installing FreeBSDSynopsisinstallationFreeBSD is provided with a text-based, easy to use installation
program called Sysinstall. This is the
default installation program for FreeBSD, although vendors are free to
provide their own installation suite if they wish. This chapter
describes how to use Sysinstall to install
FreeBSD.After reading this chapter, you will know:How to create the FreeBSD installation disks.How FreeBSD refers to, and subdivides, your hard disks.How to start Sysinstall.The questions Sysinstall will ask
you, what they mean, and how to answer them.Before reading this chapter, you should:Read the supported hardware list that shipped with the version
of FreeBSD you are installing, and verify that your hardware is
supported.In general, these installation instructions are written
for i386 (PC compatible) architecture
computers. Where applicable, instructions specific to other
platforms (for example, Alpha) will be listed.Pre-installation TasksInventory Your ComputerBefore installing FreeBSD you should attempt to inventory the
components in your computer. The FreeBSD installation routines will
show you the components (hard disks, network cards, CDROM drives, and
so forth) with their model number and manufacturer. FreeBSD will also
attempt to determine the correct configuration for these devices,
which includes information about IRQ and IO port usage. Due to the
vagaries of PC hardware this process is not always completely
successful, and you may need to correct FreeBSD's determination of
your configuration.If you already have another operating system installed, such as
Windows or Linux, it is a good idea to use the facilities provided
by those operating systems to see how your hardware is already
configured. If you are really not sure what settings an expansion
card is using, you may find it printed on the card itself. Popular IRQ
numbers are 3, 5, and 7, and IO port addresses are normally written as
hexadecimal numbers, such as 0x330.We recommend you print or write down this information before
installing FreeBSD. It may help to use a table, like this:
Sample Device InventoryDevice NameIRQIO port(s)NotesFirst hard diskN/AN/A4 GB, made by Seagate, first IDE masterCDROMN/AN/AFirst IDE slaveSecond hard diskN/AN/A2GB, made by IBM, second IDE masterFirst IDE controller140x1f0Network cardN/AN/AIntel 10/100ModemN/AN/A3Com 56K faxmodem, on COM1…
Backup Your DataIf the computer you will be installing FreeBSD on contains
valuable data then ensure you have it backed up, and that you have
tested the backups before installing FreeBSD. The FreeBSD
installation routine will prompt you several times before writing any
data to your disk, but once that process has started it cannot be
undone.Decide Where to Install FreeBSDIf you want FreeBSD to use all your disk, then there is nothing
more to concern yourself with at this point — you can skip to the
next section.However, if you need FreeBSD to co-exist with other operating
systems then you need to have a rough understanding of how data is
laid out on the disk, and how this affects you.Disk Layouts for the i386A PC disk can be divided into discrete chunks. These chunks are
called partitions. By design, the PC only
supports four partitions per disk. These partitions are called
primary partitions. To work around this
limitation and allow more than four partitions, a new partition type
was created, the extended partition. A disk
may contain only one extended partition. Special partitions, called
logical partitions, can be created inside this
extended partition.Each partition has a partition ID, which is
a number used to identify the type of data on the partition. FreeBSD
partitions have the partition ID 165.In general, each operating system that you use will identify
partitions in a particular way. For example, DOS, and its
descendants, like Windows, assign each primary and logical partition a
drive letter, starting with
C:.FreeBSD must be installed into a primary partition. FreeBSD can
keep all its data, including any files that you create, on this one
partition. However, if you have multiple disks, then you can create a
FreeBSD partition on all, or some, of them. When you install FreeBSD,
you must have one partition available. This might be a blank
partition that you have prepared, or it might be an existing partition
that contains data that you no longer care about.If you are already using all the partitions on all your disks, then
you will have to free one of them for FreeBSD using the tools
provided by the other operating systems you use (e.g.,
fdisk on DOS or Windows).If you have a spare partition then you can use that. However, you
may need to shrink one or more of your existing partitions
first.A minimal installation of FreeBSD takes as little as 100 MB of disk
space. However, that is a very minimal install,
leaving almost no space for your own files. A more realistic minimum
is 250 MB without a graphical environment, and 350 MB or more if you
want a graphical user interface. If you intend to install a lot of
third party software as well, then you will need more space.You can use a commercial tool such as Partition
Magic to resize your partitions to make space for
FreeBSD. The tools directory on the CDROM
contains two free software tools which can carry out this task,
FIPS and
PResizer. Documentation for both of these
is in the same directory.Incorrect use of these tools can delete the data on your disk.
Be sure that you have recent, working backups before using
them.Using an existing partition unchangedSuppose that you have a computer with a single 4 GB disk that
already has a version of Windows installed, and you have split the
disk into two drive letters, C: and
D:, each of which is 2 GB in size. You have
1 GB of data on C:, and 0.5 GB of data on
D:.This means that your disk has two partitions on it, one per
drive letter. You can copy all your existing data from
D: to C:, which
will free up the second partition, ready for FreeBSD.Shrinking an existing partitionSuppose that you have a computer with a single 4 GB disk, that
already has a version of Windows installed. When you installed
Windows you created one large partition, giving you a
C: drive that is 4 GB in size. You are
currently using 1.5 GB of space, and want FreeBSD to have 2 GB of
space.In order to install FreeBSD you will need to either:Backup your Windows data, and then reinstall Windows,
asking for a 2 GB partition at install time.Use one of the tools such as Partition
Magic, described above, to shrink your Windows
partition.Disk Layouts for the AlphaAlphaYou will need a dedicated disk for FreeBSD on the
Alpha. It is not possible to share a disk with another
operating system at this time. Depending on the specific
Alpha machine you have, this disk can either be a SCSI disk
or an IDE disk, as long as your machine is capable of
booting from it.Following the conventions of the Digital / Compaq
manuals all SRM input is shown in uppercase. SRM is case
insensitive.To find the names and types of disks in your machine, use
the SHOW DEVICE command from the SRM
console prompt:>>>show device
dka0.0.0.4.0 DKA0 TOSHIBA CD-ROM XM-57 3476
dkc0.0.0.1009.0 DKC0 RZ1BB-BS 0658
dkc100.1.0.1009.0 DKC100 SEAGATE ST34501W 0015
dva0.0.0.0.1 DVA0
ewa0.0.0.3.0 EWA0 00-00-F8-75-6D-01
pkc0.7.0.1009.0 PKC0 SCSI Bus ID 7 5.27
pqa0.0.0.4.0 PQA0 PCI EIDE
pqb0.0.1.4.0 PQB0 PCI EIDEThis example is from a Digital Personal Workstation
433au and shows three disks attached to the machine. The
first is a CDROM drive called DKA0 and
the other two are disks and are called
DKC0 and
DKC100 respectively.Disks with names of the form DKx
are SCSI disks. For example DKA100
refers to a SCSI with SCSI target ID 1 on the first SCSI bus (A),
whereas DKC300 refers to a SCSI disk
with SCSI ID 3 on the third SCSI bus (C). Devicename
PKx refers to the SCSI host bus adapter. As
seen in the SHOW DEVICE output SCSI
CDROM drives are treated as any other SCSI hard disk drive.IDE disks have names similar to DQx,
while PQx is the associated IDE
controller.Collect Your Network Configuration DetailsIf you intend to connect to a network as part of your FreeBSD
installation (for example, if you will be installing from an FTP
site, or an
NFS server), then you need to know your network configuration. You
will be prompted for this information during the installation so that
FreeBSD can connect to the network to complete the install.Connecting to an Ethernet Network, or Cable/DSL ModemIf you connect to an Ethernet network, or you have an Internet
connection via cable or DSL, then you will need the following
information:IP address.IP address of the default gateway.Hostname.DNS server IP addresses.If you do not know this information, then ask your system
administrator or service provider. They may say that this
information is assigned automatically, using
DHCP. If so, make a note of this.Connecting Using a ModemIf you dial up to an ISP using a regular modem then you can
still install FreeBSD over the Internet, it will just take a very
long time.You will need to know:The phone number to dial for your ISP.The COM: port your modem is connected to.The username and password for your ISP account.Check for FreeBSD ErrataAlthough the FreeBSD project strives to ensure that each release
of FreeBSD is as stable as possible, bugs do occasionally creep into
the process. On very rare occasions those bugs affect the
installation process. As these problems are discovered and fixed they
are noted in the FreeBSD Errata, posted on the FreeBSD web site. You
should check the errata before installing to make sure that there are
no late-breaking problems which you should be aware of.Information about all the releases, including the errata for each
release, can be found on the
release
information section of the
FreeBSD web site.Obtain the FreeBSD installation filesThe FreeBSD installation process can install FreeBSD from files
located in the any of the following places:Local mediaA CDROMA DOS partition on the same computerA tapeFloppy disksNetworkAn FTP site, going through a firewall, or using an HTTP proxy,
as necessaryAn NFS serverA dedicated parallel or serial connectionIf you have purchased FreeBSD on CD or DVD then you already have
everything you need, and should proceed to the next section
(Preparing the Boot
Media).If you have not obtained the FreeBSD installation files you should
skip ahead to which explains how
to prepare to install FreeBSD from any of the above. After reading
that section, you should come back here, and read on to
.Prepare the Boot MediaThe FreeBSD installation process is started by booting your
computer into the FreeBSD installer—it is not a program you run
within another operating system. Your computer normally boots using
the operating system installed on your hard disk, but it can also be
configured to use a bootable floppy disk. It may also
be able to boot from a disk in the CDROM drive.If you have FreeBSD on CDROM or DVD (either one you purchased,
or you prepared yourself), and your computer allows you to boot from
the CDROM or DVD (typically a BIOS option called Boot
Order or similar) then you can skip this section. The
FreeBSD CDROM and DVD images are bootable and can be used to install
FreeBSD without any other special preparation.To create boot floppy images, follow these steps:Acquire the Boot Floppy ImagesThe boot discs are available on your installation media
in the floppies/ directory, and
can also be downloaded from the
floppies directory for the i386 architecture and from this floppies directory for the Alpha architecture.The floppy images have a .flp extension.
The floppies/ directory contains a number of
different images, and the ones you will need to use depends on the
version of FreeBSD you are installing, and in some cases, the
hardware you are installing to. In most cases you will need two
files, kern.flp and
mfsroot.flp, but check
README.TXT in the same directory to be
sure.Your FTP program must use binary mode
to download these disk images. Some web browsers have been
known to use text (or
ASCII) mode, which will be apparent if you
cannot boot from the disks.Prepare the Floppy DisksYou must prepare one floppy disk per image file you had to
download. It is imperative that these disks are free from
defects. The easiest way to test this is to format the disks
for yourself. Do not trust pre-formatted floppies.If you try to install FreeBSD and the installation
program crashes, freezes, or otherwise misbehaves, one of
the first things to suspect is the floppies. Try writing
the floppy image files to some other disks and try
again.Write the Image Files to the Floppy DisksThe .flp files are
not regular files you copy to the disk.
Instead, they are images of the complete contents of the
disk. This means that you cannot use
commands like DOS' copy to write the
files. Instead, you must use specific tools to write the
images directly to the disk.DOSIf you are creating the floppies on a computer running
DOS/Windows, then we provide a tool to do
this called fdimage.If you are using the floppies from the CDROM, and your
CDROM is the E: drive, then you would
run this:E:\>tools\fdimage floppies\kern.flp A:Repeat this command for each .flp
file, replacing the floppy disk each time, being sure to label
the disks with the name of the file that you copied to them.
Adjust the command line as necessary, depending on where you have
placed the .flp files. If you do not have
the CDROM, then fdimage can be downloaded from
the tools
directory on the FreeBSD FTP site.If you are writing the floppies on a Unix system (such as
another FreeBSD system) you can use the &man.dd.1; command to
write the image files directly to disk. On FreeBSD, you would
run:&prompt.root; dd if=kern.flp of=/dev/fd0On FreeBSD, /dev/fd0 refers to the
first floppy disk (the A: drive).
/dev/fd1 would be the
B: drive, and so on. Other Unix
variants might have different names for the floppy disk
devices, and you will need to check the documentation for the
system as necessary.You are now ready to start installing FreeBSD.Starting the InstallationBy default, the installation will not make any changes to your
disk(s) until you see the following message:Last Chance: Are you SURE you want continue the installation?
If you're running this on a disk with data you wish to save then WE
STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before proceeding!
We can take no responsibility for lost disk contents!The install can be exited at any time prior to the final
warning without changing the contents of the hard drive. If you are
concerned that you have configured something incorrectly you can just
turn the computer off before this point, and no damage will be
done.BootingBooting for the i386Start with your computer turned off.Turn on the computer. As it starts it should display an
option to enter the system set up menu, or BIOS, commonly reached
by keys like F2, F10,
Del, or
AltS. Use whichever keystroke is indicated on screen. In
some cases your computer may display a graphic while it starts.
Typically, pressing Esc will dismiss the graphic
and allow you to see the necessary messages.Find the setting that controls which devices the system boots
from. This is commonly shown as a list of devices, such as
Floppy, CDROM,
First Hard Disk, and so on.If you needed to prepare boot floppies, then make sure that the
floppy disk is selected. If you are booting from the CDROM then
make sure that that is selected instead. In case of doubt, you
should consult the manual that came with your computer, and/or its
motherboard.Make the change, then save and exit. The computer should now
restart.If you needed to prepare boot floppies, as described in
then one of them will be the
first boot disc, probably the one containing
kern.flp. Put this disc in your floppy
drive.If you are booting from CDROM, then you will need to turn on
the computer, and insert the CDROM at the first
opportunity.If your computer starts up as normal, and loads your existing
operating system then either:The disks were not inserted early enough in the boot
process. Leave them in, and try restarting your
computer.The BIOS changes earlier did not work correctly. You
should redo that step until you get the right option.FreeBSD will start to boot. If you are booting from CDROM you
will see a display similar to this (version information omitted):Verifying DMI Pool Data ........
Boot from ATAPI CD-ROM :
1. FD 2.88MB System Type-(00)
Uncompressing ... done
BTX loader 1.00 BTX version is 1.01
Console: internal video/keyboard
BIOS drive A: is disk0
BIOS drive B: is disk1
BIOS drive C: is disk2
BIOS drive C: is disk3
BIOS 639kB/261120kB available memory
FreeBSD/i386 bootstrap loader, Revision 0.8
/kernel text=0x277391 data=0x3268c+0x332a8 |
|
Hit [Enter] to boot immediately, or any other key for command prompt.
Booting [kernel] in 9 seconds... _If you are booting from floppy disc, you will see a display
similar to this (version information omitted):Verifying DMI Pool Data ........
BTX loader 1.00 BTX version is 1.01
Console: internal video/keyboard
BIOS drive A: is disk0
BIOS drive C: is disk1
BIOS 639kB/261120kB available memory
FreeBSD/i386 bootstrap loader, Revision 0.8
/kernel text=0x277391 data=0x3268c+0x332a8 |
Please insert MFS root floppy and press enter:Follow these instructions by removing the
kern.flp disc, insert the
mfsroot.flp disc, and press
Enter.Irrespective of whether you booted from floppy or CDROM, the
boot process will then get to this point:Hit [Enter] to boot immediately, or any other key for command prompt.
Booting [kernel] in 9 seconds... _Either wait ten seconds, or press Enter. This
will then launch the kernel configuration menu.Booting for the AlphaAlphaStart with your computer turned off.Turn on the computer and wait for a boot monitor
prompt.If you needed to prepare boot floppies, as described in
then one of them will be the
first boot disc, probably the one containing
kern.flp. Put this disc in your floppy
drive and type the following command to boot the disk
(substituting the name of your floppy drive if
necessary):>>>BOOT DVA0 -FLAGS '' -FILE ''If you are booting from CDROM, insert the CDROM into
the drive and type the following command to start the
installation (substituting the name of the appropriate
CDROM drive if necessary):>>>BOOT DKA0 -FLAGS '' -FILE ''FreeBSD will start to boot. If you are booting from a
floppy disc, at some point you will see the message:Please insert MFS root floppy and press enter:Follow these instructions by removing the
kern.flp disc, insert the
mfsroot.flp disc, and press
Enter.Irrespective of whether you booted from floppy or CDROM, the
boot process will then get to this point:Hit [Enter] to boot immediately, or any other key for command prompt.
Booting [kernel] in 9 seconds... _Either wait ten seconds, or press Enter. This
will then launch the kernel configuration menu.Kernel ConfigurationThe kernel is the core of the operating
system. It is responsible for many things, including access to all
the devices you may have on your system, such as hard disks, network
cards, sound cards, and so on. Each piece of hardware supported by
the FreeBSD kernel has a driver associated with it. Each driver has a
two or three letter name, such as sa for the
SCSI sequential access driver, or sio for the
Serial I/O driver (which manages COM ports).When the kernel starts, each driver checks the system to see
whether or not the hardware it supports exists on your system. If it
does, then the driver configures the hardware and makes it available
to the rest of the kernel.This checking is commonly referred to as device
probing. Unfortunately, it is not always possible to do
this in a safe way. Some hardware drivers do not co-exist well,
and probing for one piece of hardware can sometimes leave
another in an inconsistent state. This is a basic
limitation of the design of the PC.Many older devices are called ISA devices—as opposed
to PCI devices. The ISA specification requires each device to have
some information hard coded into it, typically the Interrupt Request
Line number (IRQ) and IO port address that the driver uses. This
information is commonly set by using physical
jumpers on the card, or by using a DOS based
utility.This was often a source of problems, because it was not possible
to have two devices that shared the same IRQ or port address.Newer devices follow the PCI specification, which does not require
this, as the devices are supposed to cooperate with the BIOS, and be
told which IRQ and IO port addresses to use.If you have any ISA devices in your computer then FreeBSD's
driver for that device will need to be configured with the IRQ and
port address that you have set the card to. This is why carrying out
an inventory of your hardware (see ) can be useful.Unfortunately, the default IRQs and memory ports used by some
drivers clash. This is because some ISA devices are shipped with IRQs
or memory ports that clash. The defaults in FreeBSD's drivers are
deliberately set to mirror the manufacturer's defaults, so that, out
of the box, as many devices as possible will work.This is almost never an issue when running FreeBSD day-to-day.
Your computer will not normally contain two pieces of hardware that
clash, because one of them would not work (irrespective of the
operating system you are using).It becomes an issue when you are installing FreeBSD for the first
time because the kernel used to carry out the install has to contain
as many drivers as possible, so that many different hardware
configurations can be supported. This means that some of
those drivers will have conflicting configurations. The devices are
probed in a strict order, and if you own a device that is probed late
in the process, but conflicted with an earlier probe, then your
hardware might not function or be probed correctly when you install
FreeBSD.Because of this, the first thing you have the opportunity to do
when installing FreeBSD is look at the list of drivers that are
configured into the kernel, and either disable some of them, if you
do not own that device, or confirm (and alter) the driver's
configuration if you do own the device but the defaults are
wrong.This probably sounds much more complicated than it actually
is. shows the first kernel
configuration menu. We recommend that you choose the
Start kernel configuration in full-screen visual
mode option, as it presents the easiest interface for
the new user.Kernel Configuration Menu&txt.install.userconfig;The kernel configuration screen ()
is then divided into four sections.A collapsible list of all the drivers that are currently
marked as active, subdivided into groups such as
Storage, and Network. Each
driver is shown as a description, its two or three letter driver
name, and the IRQ and memory port used by that driver. In
addition, if an active driver conflicts with another active driver
then CONF is shown next to the driver name.
This section also shows the total number of conflicting drivers
that are currently active.Drivers that have been marked inactive. They remain in the
kernel, but they will not probe for their device when the kernel
starts. These are subdivided into groups in the same way as the
active driver list.More detail about the currently selected driver, including its
IRQ and memory port address.Information about the keystrokes that are valid at this point
in time.The Kernel Device Configuration Visual Interface&txt.install.userconfig2;At this point there will always be conflicts listed. Do not worry
about this, it is to be expected; all the drivers are enabled, and
as has already been explained, some of them will conflict with one
another.You now have to work through the list of drivers, resolving the
conflicts.Resolving Driver ConflictsPress X. This will completely expand the
list of drivers, so you can see all of them. You will need to use
the arrow keys to scroll back and forth through the active driver
list. shows the result of
pressing X. Expanded Driver ListDisable all the drivers for devices that you do not have. To
disable a driver, highlight it with the arrow keys and press
Del. The driver will be moved to the
Inactive Drivers list.If you inadvertently disable a device that you need then press
Tab to switch to the Inactive
Drivers list, select the driver that you disabled, and
press Enter to move it back to the active
list.Do not disable sc0. This controls
the screen, and you will need this unless you are installing
over a serial cable.Only disable atkbd0 if you are
using a USB keyboard. If you have a normal keyboard then you
must keep atkbd0.If there are no conflicts listed then you can skip this step.
Otherwise, the remaining conflicts need to be examined. If they
do not have the indication of an allowed conflict
in the message area, then either the IRQ/address for device probe
will need to be changed, or the IRQ/address
on the hardware will need to be changed.To change the driver's configuration for IRQ and IO port
address, select the device and press Enter. The
cursor will move to the third section of the screen, and you can
change the values. You should enter the values for IRQ and port
address that you discovered when you made your hardware inventory.
Press Q to finish editing the device's
configuration and return to the active driver list.If you are not sure what these figures should be then you can
try using -1. Some FreeBSD drivers can safely
probe the hardware to discover what the correct value should be,
and a value of -1 configures them to do
this.The procedure for changing the address on the hardware varies
from device to device. For some devices you may need to
physically remove the card from your computer and adjust jumper
settings or DIP switches. Other cards may have come with a DOS
floppy that contains the programs used to reconfigure the card.
In any case, you should refer to the documentation that came with
the device. This will obviously entail restarting your computer,
so you will need to boot back into the FreeBSD installation
routine when you have reconfigured the card.When all the conflicts have been resolved the screen will look
similar to .Driver Configuration With No ConflictsAs you can see, the active driver list is now much smaller,
with only drivers for the hardware that actually exists being
listed.You can now save these changes, and move on to the next step
of the install. Press Q to quit the device
configuration interface. This message will appear:Save these parameters before exiting? ([Y]es/[N]o/[C]ancel)Answer Y to save the parameters and the
probing will start. After displaying the probe results in white
on black text Sysinstall will start
and display its main menu
().Sysinstall Main MenuReviewing the Device Probe ResultsThe last few hundred lines that have been displayed on screen are
stored and can be reviewed.To review the buffer, press Scroll Lock. This
turns on scrolling in the display. You can then use the arrow keys, or
PageUp and PageDown to view the
results. Press Scroll Lock again to stop
scrolling.Do this now, to review the text that scrolled off the screen when
the kernel was carrying out the device probes. You will see text
similar to , although the precise
text will differ depending on the devices that you have in your
computer.Typical Device Probe Resultsavail memory = 253050880 (247120K bytes)
Preloaded elf kernel "kernel" at 0xc0817000.
Preloaded mfs_root "/mfsroot" at 0xc0817084.
md0: Preloaded image </mfsroot> 4423680 bytes at 0xc03ddcd4
md1: Malloc disk
Using $PIR table, 4 entries at 0xc00fde60
npx0: <math processor> on motherboard
npx0: INT 16 interface
pcib0: <Host to PCI bridge> on motherboard
pci0: <PCI bus> on pcib0
pcib1:<VIA 82C598MVP (Apollo MVP3) PCI-PCI (AGP) bridge> at device 1.0 on pci0
pci1: <PCI bus> on pcib1
pci1: <Matrox MGA G200 AGP graphics accelereator> at 0.0 irq 11
isab0: <VIA 82C586 PCI-ISA bridge> at device 7.0 on pci0
isa0: <iSA bus> on isab0
atapci0: <VIA 82C586 ATA33 controller> port 0xe000-0xe00f at device 7.1 on pci0
ata0: at 0x1f0 irq 14 on atapci0
ata1: at 0x170 irq 15 on atapci0
uhci0 <VIA 83C572 USB controller> port 0xe400-0xe41f irq 10 at device 7.2 on pci
0
usb0: <VIA 83572 USB controller> on uhci0
usb0: USB revision 1.0
uhub0: VIA UHCI root hub, class 9/0, rev 1.00/1.00, addr1
uhub0: 2 ports with 2 removable, self powered
pci0: <unknown card> (vendor=0x1106, dev=0x3040) at 7.3
dc0: <ADMtek AN985 10/100BaseTX> port 0xe800-0xe8ff mem 0xdb000000-0xeb0003ff ir
q 11 at device 8.0 on pci0
dc0: Ethernet address: 00:04:5a:74:6b:b5
miibus0: <MII bus> on dc0
ukphy0: <Generic IEEE 802.3u media interface> on miibus0
ukphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
ed0: <NE2000 PCI Ethernet (RealTek 8029)> port 0xec00-0xec1f irq 9 at device 10.
0 on pci0
ed0 address 52:54:05:de:73:1b, type NE2000 (16 bit)
isa0: too many dependant configs (8)
isa0: unexpected small tag 14
orm0: <Option ROM> at iomem 0xc0000-0xc7fff on isa0
fdc0: <NEC 72065B or clone> at port 0x3f0-0x3f5,0x3f7 irq 6 drq2 on isa0
fdc0: FIFO enabled, 8 bytes threshold
fd0: <1440-KB 3.5" drive> on fdc0 drive 0
atkbdc0: <Keyboard controller (i8042)> at port 0x60,0x64 on isa0
atkbd0: <AT Keyboard> flags 0x1 irq1 on atkbdc0
kbd0 at atkbd0
psm0: <PS/2 Mouse> irq 12 on atkbdc0
psm0: model Generic PS/@ mouse, device ID 0
vga0: <Generic ISA VGA> at port 0x3c0-0x3df iomem 0xa0000-0xbffff on isa0
sc0: <System console> at flags 0x100 on isa0
sc0: VGA <16 virtual consoles, flags=0x300>
sio0 at port 0x3f8-0x3ff irq 4 flags 0x10 on isa0
sio0: type 16550A
sio1 at port 0x2f8-0x2ff irq 3 on isa0
sio1: type 16550A
ppc0: <Parallel port> at port 0x378-0x37f irq 7 on isa0
pppc0: SMC-like chipset (ECP/EPP/PS2/NIBBLE) in COMPATIBLE mode
ppc0: FIFO with 16/16/15 bytes threshold
plip0: <PLIP network interfce> on ppbus0
ad0: 8063MB <IBM-DHEA-38451> [16383/16/63] at ata0-master UDMA33
acd0: CD-RW <LITE-ON LTR-1210B> at ata1-slave PIO4
Mounting root from ufs:/dev/md0c
/stand/sysinstall running as init on vty0Check the probe results carefully to make sure that FreeBSD found
all the devices you expected. If a device was not found, then it will
not be listed. If the device's driver required configuring
with the IRQ and port address then you should check that you entered
them correctly.If you need to make changes to the UserConfig device probing,
its easy to exit the sysinstall program
and start over again. Its also a good way to become more familiar
with the process.Select Sysinstall ExitUse the arrow keys to select
Exit Install from the Main
Install Screen menu. The following message will display: User Confirmation Requested
Are you sure you wish to exit? The system will reboot
(be sure to remove any floppies from the drives).
[ Yes ] NoThe install program will start again if the CDROM is left
in the drive and [Yes] is selected.If you are booting from floppies it will be necessary to remove
the mfsroot.flp floppy and replace it with
kern.flp before rebooting.Introducing SysinstallSysinstall is the installation
application provided by the FreeBSD Project. It is console based and is
divided into a number of menus and screens that you can use to
configure and control the installation process.The Sysinstall menu system is controlled
by the arrow keys, Enter, Space, and
other keys. A detailed description of these keys, and what they do, is
contained in Sysinstall's usage
information.To review this information, ensure that the
Usage entry is highlighted and that the
[Select] button is selected, as shown in , then press Enter.The instructions for using the menu system will be displayed. After
reviewing them, press Enter to return to the Main
Menu.Selecting Usage From Sysinstall Main MenuSelecting The Documentation MenuFrom the Main Menu, select Doc with
the arrow keys and
press Enter.Selecting Documentation MenuThis will display the Documentation Menu.Sysinstall Documentation MenuIt is important to read the documents provided.To view a document, select it with the arrow keys and
press Enter. When finished reading a document,
pressing Enter will return to the Documentation
Menu.To return to the Main Installation Menu, select
Exit with the
arrow keys and press Enter.Selecting The Keymap MenuTo change the keyboard mapping, use the arrow keys to select
Keymap from the menu and press
Enter.Sysinstall Main MenuA different keyboard mapping may be chosen by selecting the
menu item using up/down arrow keys and pressing Space.
Pressing Space again will unselect the item.
When finished, choose the &gui.ok; using the arrow keys and press
Enter.Only a partial list is shown in this screen representation.
Selecting &gui.cancel; will use the default
keymap and return to the Main Install Menu.Sysinstall Keymap MenuInstallation Options ScreenSelect Options and press
Enter.Sysinstall Main MenuSysinstall OptionsThe default values are usually fine for most users and do
not need to be changed. The release name will vary according
to the version being installed.The description of the selected item will appear at the
bottom of the screen highlighted in blue. Notice that one of the
options is Use Defaults to reset all
values to startup defaults.Press F1 to read the help screen about the
various options.Pressing Q will return to the Main Install
menu.Begin A Standard InstallationThe Standard installation is the
option recommended for those new to Unix or FreeBSD. Use the arrow
keys to select Standard and
then press Enter to start the installation.Begin Standard InstallationAllocating Disk SpaceYour first task is to allocate disk space for FreeBSD, and label
that space so that Sysinstall can prepare
it. In order to do this you need to know how FreeBSD expects to find
information on the disk.BIOS Drive NumberingBefore you install and configure FreeBSD on your system, there is an
important subject that you should be aware of, especially if you have
multiple hard drives.DOSMicrosoft WindowsIn a PC running a BIOS-dependent operating system such as
MS-DOS or Microsoft Windows, the BIOS is able to abstract the
normal disk drive order, and
the operating system goes along with the change. This allows the user
to boot from a disk drive other than the so-called primary
master. This is especially convenient for some users who have
found that the simplest and cheapest way to keep a system backup is to
buy an identical second hard drive, and perform routine copies of the
first drive to the second drive using
Ghost or XCOPY
. Then, if the
first drive fails, or is attacked by a virus, or is scribbled upon by an
operating system defect, he can easily recover by instructing the BIOS
to logically swap the drives. It is like switching the cables on the
drives, but without having to open the case.SCSIBIOSMore expensive systems with SCSI controllers often include BIOS
extensions which allow the SCSI drives to be re-ordered in a similar
fashion for up to seven drives.A user who is accustomed to taking advantage of these features may
become surprised when the results with FreeBSD are not as expected.
FreeBSD does not use the BIOS, and does not know the logical BIOS
drive mapping. This can lead to very perplexing situations,
especially when drives are physically identical in geometry, and have
also been made as data clones of one another.When using FreeBSD, always restore the BIOS to natural drive
numbering before installing FreeBSD, and then leave it that way. If you
need to switch drives around, then do so, but do it the hard way, and
open the case and move the jumpers and cables.An Illustration from the Files of Bill and Fred's Exceptional
Adventures:Bill breaks-down an older Wintel box to make another FreeBSD box
for Fred. Bill installs a single SCSI drive as SCSI unit zero and
installs FreeBSD on it.Fred begins using the system, but after several days notices that
the older SCSI drive is reporting numerous soft errors and reports
this fact to Bill.After several more days, Bill decides it is time to address the
situation, so he grabs an identical SCSI drive from the disk drive
archive in the back room. An initial surface scan
indicates that
this drive is functioning well, so Bill installs this drive as SCSI
unit four and makes an image copy from drive zero to drive four. Now
that the new drive is installed and functioning nicely, Bill decides
that it is a good idea to start using it, so he uses features in the
SCSI BIOS to re-order the disk drives so that the system boots from
SCSI unit four. FreeBSD boots and runs just fine.Fred continues his work for several days, and soon Bill and Fred
decide that it is time for a new adventure -- time to upgrade to a
newer version of FreeBSD. Bill removes SCSI unit zero because it was
a bit flaky and replaces it with another identical disk drive from
the archive. Bill then installs the new version of
FreeBSD onto the new SCSI unit zero using Fred's magic Internet FTP
floppies. The installation goes well.Fred uses the new version of FreeBSD for a few days, and certifies
that it is good enough for use in the engineering department. It is
time to copy all of his work from the old version. So Fred mounts
SCSI unit four (the latest copy of the older FreeBSD version). Fred
is dismayed to find that none of his precious work is present on SCSI
unit four.Where did the data go?When Bill made an image copy of the original SCSI unit zero onto
SCSI unit four, unit four became the new clone.
When Bill re-ordered the SCSI BIOS so that he could boot from
SCSI unit four, he was only fooling himself.
FreeBSD was still running on SCSI unit zero.
Making this kind of BIOS change will cause some or all of the Boot and
Loader code to be fetched from the selected BIOS drive, but when the
FreeBSD kernel drivers take-over, the BIOS drive numbering will be
ignored, and FreeBSD will transition back to normal drive numbering.
In the illustration at hand, the system continued to operate on the
original SCSI unit zero, and all of Fred's data was there, not on SCSI
unit four. The fact that the system appeared to be running on SCSI
unit four was simply an artifact of human expectations.We are delighted to mention that no data bytes were killed or
harmed in any way by our discovery of this phenomenon. The older SCSI
unit zero was retrieved from the bone pile, and all of Fred's work was
returned to him, (and now Bill knows that he can count as high as
zero).Although SCSI drives were used in this illustration, the concepts
apply equally to IDE drives.Disk OrganizationThe smallest unit of organization that FreeBSD uses to find files
is the filename. Filenames are case-sensitive, which means that
readme.txt and README.TXT
are two separate files. FreeBSD does not use the extension
(.txt) of a file to determine whether the file is
program, or a document, or some other form of data.Files are stored in directories. A directory may contain no
files, or it may contain many hundreds of files. A directory can also
contain other directories, allowing you to build up a hierarchy of
directories within one another. This makes it much easier to organize
your data.Files and directories are referenced by giving the file or
directory name, followed by a forward slash, /,
followed by any other directory names that are necessary. If you have
directory foo, which contains directory
bar, which contains the file
readme.txt, then the full name, or
path to the file is
foo/bar/readme.txt.Directories and files are stored in a filesystem. Each filesystem
contains exactly one directory at the very top level, called the
root directory for that filesystem. This root
directory can then contain other directories.So far this is probably similar to any other operating system you
may have used. There are a few differences; for example, DOS uses
\ to separate file and directory names, while MacOS
uses :.FreeBSD does not use drive letters, or other drive names in the
path. You would not write c:/foo/bar/readme.txt
on FreeBSD.Instead, one filesystem is designated the root
filesystem. The root filesystem's root directory is
referred to as /. Every other filesystem is then
mounted under the root filesystem. No matter
how many disks you have on your FreeBSD system, every directory
appears to be part of the same disk.Suppose you have three filesystems, called A,
B, and C. Each filesystem has
one root directory, which contains two other directories, called
A1, A2 (and likewise
B1, B2 and
C1, C2).Call A the root filesystem. If you used the
ls command to view the contents of this directory
you would see two subdirectories, A1 and
A2. The directory tree looks like this: /
|
+--- A1
|
`--- A2A filesystem must be mounted on to a directory in another
filesystem. So now suppose that you mount filesystem
B on to the directory A1. The
root directory of B replaces A1,
and the directories in B appear accordingly: /
|
+--- A1
| |
| +--- B1
| |
| `--- B2
|
`--- A2Any files that are in the B1 or
B2 directories can be reached with the path
/A1/B1 or /A1/B2 as
necessary. Any files that were in /A1 have been
temporarily hidden. They will reappear if B is
unmounted from A.If B had been mounted on A2
then the diagram would look like this: /
|
+--- A1
|
`--- A2
|
+--- B1
|
`--- B2and the paths would be /A2/B1 and
/A2/B2 respectively.Filesystems can be mounted on top of one another. Continuing the
last example, the C filesystem could be mounted on
top of the B1 directory in the B
filesystem, leading to this arrangement: /
|
+--- A1
|
`--- A2
|
+--- B1
| |
| +--- C1
| |
| `--- C2
|
`--- B2Or C could be mounted directly on to the
A filesystem, under the A1
directory: /
|
+--- A1
| |
| +--- C1
| |
| `--- C2
|
`--- A2
|
+--- B1
|
`--- B2If you are familiar with DOS, this is similar, although not
identical, to the join command.This is not normally something you need to concern yourself with.
Typically you create filesystems when installing FreeBSD and decide
where to mount them, and then never change them unless you add a new
disk.It is entirely possible to have one large root filesystem, and not
need to create any others. There are some drawbacks to this approach,
and one advantage.Benefits of multiple filesystemsDifferent filesystems can have different mount
options. For example, with careful planning, the
root filesystem can be mounted read-only, making it impossible for
you to inadvertently delete or edit a critical file.FreeBSD automatically optimizes the layout of files on a
filesystem, depending on how the filesystem is being used. So a
filesystem that contains many small files that are written
frequently will have a different optimization to one that contains
fewer, larger files. By having one big filesystem this
optimization breaks down.FreeBSD's filesystems are very robust should you lose power.
However, a power loss at a critical point could still damage the
structure of the filesystem. By splitting your data over multiple
filesystems it is more likely that the system will still come up,
making it easier for you to restore from backup as
necessary.Benefit of a single filesystemFilesystems are a fixed size. If you create a filesystem when
you install FreeBSD and give it a specific size, you may later
discover that you need to make the partition bigger. This is not
easily accomplished without backing up, recreating the filesystems
with the size, and then restoring.FreeBSD 4.4 and up have a featured command, the
&man.growfs.8;, which will makes it possible to
increase the size of a filesystem on the fly, removing this
limitation.Filesystems are contained in partitions. This does not have the
same meaning as the earlier usage of the term partition in this
chapter, because of FreeBSD's Unix heritage. Each partition is
identified by a letter, a through to
h. Each partition can only contain one filesystem,
which means that filesystems are often described by either their
typical mount point on the root filesystem, or the letter of the
partition they are contained in.FreeBSD also uses disk space for swap
space. Swap space provides FreeBSD with
virtual memory. This allows your computer to
behave as though it has much more memory than it actually does. When
FreeBSD runs out of memory it moves some of the data that is not
currently being used to the swap space, and moves it back in (moving
something else out) when it needs it.Some partitions have certain conventions associated with
them.PartitionConventionaNormally contains the root filesystembNormally contains swap spacecNormally the same size as the enclosing slice. This
allows utilities that need to work on the entire slice (for
example, a bad block scanner) to work on the
c partition. You would not normally create
a filesystem on this partition.dPartition d used to have a special
meaning associated with it, although that is now gone. To
this day, some tools may operate oddly if told to work on
partition d, so
Sysinstall will not normally create
partition d.Each partition-that-contains-a-filesystem is stored in what
FreeBSD calls a slice. Slice is FreeBSD's term
for what were earlier called partitions, and again, this is because of
FreeBSD's Unix background. Slices are numbered, starting at 1,
through to 4.slicespartitionsdangerously dedicatedSlice numbers follow
the device name, prefixed with an s,
starting at 1. So da0s1
is the first slice on the first SCSI drive. There can only be
four physical slices on a disk, but you can have logical
slices inside physical slices of the appropriate type. These
extended slices are numbered starting at 5, so
ad0s5 is the first
extended slice on a disk. These devices are used by file
systems that expect to occupy a slice.Slices, dangerously dedicated physical
drives, and other drives contain
partitions, which are represented as
letters from a to h.
This letter is appended to the device name, so
da0a is the a partition on
the first da drive, which is dangerously dedicated.
ad1s3e is the fifth partition
in the third slice of the second IDE disk drive.Finally, each disk on the system is identified. A disk name
starts with a code that indicates the type of disk, and then a number,
indicating which disk it is. Unlike slices, disk numbering starts at
0. Common codes that you will see are listed in
.When referring to a partition FreeBSD requires that you also name
the slice and disk that contains the partition, and when referring to
a slice you should also refer to the disk name. Do this by listing
the disk name, s, the slice number, and then the
partition letter. Examples are shown in
. shows a conceptual
model of the disk layout that should help make things clearer.In order to install FreeBSD you must first configure the disk
slices, then create partitions within the slice you will use for
FreeBSD, and then create a filesystem (or swap space) in each
partition, and decide where that filesystem will be mounted.
Disk Device CodesCodeMeaningadATAPI (IDE) diskdaSCSI direct access diskacdATAPI (IDE) CDROMcdSCSI CDROMfdFloppy disk
Sample Disk, Slice, and Partition NamesNameMeaningad0s1aThe first partition (a) on the first
slice (s1) on the first IDE disk
(ad0).da1s2eThe fifth partition (e) on the
second slice (s2) on the second SCSI disk
(da1).Conceptual Model of a DiskThis diagram shows FreeBSD's view of the first IDE disk attached
to the system. Assume that the disk is 4 GB in size, and contains
two 2 GB slices (DOS partitions). The first slice contains a DOS
disk, C:, and the second slice contains a
FreeBSD installation. This example FreeBSD installation has three
partitions, and a swap partition.The three partitions will each hold a filesystem. Partition
a will be used for the root filesystem,
e for the /var directory
hierarchy, and f for the
/usr directory hierarchy..-----------------. --.
| | |
| DOS / Windows | |
: : > First slice, ad0s1
: : |
| | |
:=================: ==: --.
| | | Partition a, mounted as / |
| | > referred to as ad0s2a |
| | | |
:-----------------: ==: |
| | | Partition b, used as swap |
| | > referred to as ad0s2b |
| | | |
:-----------------: ==: | Partition c, no
| | | Partition e, used as /var > filesystem, all
| | > referred to as ad0s2e | of FreeBSD slice,
| | | | ad0s2c
:-----------------: ==: |
| | | |
: : | Partition f, used as /usr |
: : > referred to as ad0s2f |
: : | |
| | | |
| | --' |
`-----------------' --'Creating Slices using FDiskNo changes you make at this point will be written to the disk.
If you think you have made a mistake and want to start again you can
use the menus to exit Sysinstall and try
again. If you get confused and can not see how to exit you can
always turn your computer off.After choosing to begin a standard installation in
Sysinstall you will be shown this
message: Message
In the next menu, you will need to set up a DOS-style ("fdisk")
partitioning scheme for your hard disk. If you simply wish to devote
all disk space to FreeBSD (overwriting anything else that might be on
the disk(s) selected) then use the (A)ll command to select the default
partitioning scheme followed by a (Q)uit. If you wish to allocate only
free space to FreeBSD, move to a partition marked "unused" and use the
(C)reate command.
[ OK ]
[ Press enter or space ]Press Enter as instructed. You will then be
shown a list of all the hard drives that the kernel found when it
carried out the device probes.
shows an example from a
system with two IDE disks. They have been called
ad0 and ad2.Select Drive for FDiskYou might be wondering why ad1 is not
listed here. Why has it been missed?Consider what would happen if you had two IDE hard disks, one
as the master on the first IDE controller, and one as the master on
the second IDE controller. If FreeBSD numbered these as it found
them, as ad0 and
ad1 then everything would work.But if you then added a third disk, as the slave device on the
first IDE controller, it would now be ad1,
and the previous ad1 would become
ad2. Because device names (such as
ad1s1a) are used to find filesystems, you
may suddenly discover that some of your filesystems no longer
appear correctly, and you would need to change your FreeBSD
configuration.To work around this, the kernel can be configured to name IDE
disks based on where they are, and not the order in which they were
found. With this scheme the master disk on the second IDE
controller will always be
ad2, even if there are no
ad0 or ad1
devices.This configuration is the default for the FreeBSD kernel, which
is why this display shows ad0 and
ad2. The machine on which this screenshot
was taken had IDE disks on both master channels of the IDE
controllers, and no disks on the slave channels.You should select the disk on which you want to install FreeBSD,
and then press &gui.ok;.
FDisk will start, with a display similar to
that shown in .The FDisk display is broken into three
sections.The first section, covering the first two lines of the display,
shows details about the currently selected disk, including its FreeBSD
name, the disk geometry, and the total size of the disk.The second section shows the slices that are currently on the
disk, where they start and end, how large they are, the name FreeBSD
gives them, and their description and sub-type. This example shows two
small unused slices, which are artifacts of disk layout schemes on the
PC. It also shows one large FAT slice, which almost certainly appears
as C: in DOS / Windows, and an extended
slice, which may contain other drive letters for DOS / Windows.The third section shows the commands that are available in
FDisk.Typical Fdisk Partitions Before EditingWhat you do now will depend on how you want to slice up your
disk.If you want to use FreeBSD for the entire disk (which will delete
all the other data on this disk when you confirm that you want
Sysinstall to continue later in the
installation process) then you can press A, which
corresponds to the Use Entire Disk option.
The existing slices will be removed, and replaced with a small area
flagged as unused (again, an artifact of PC disk
layout), and then one large slice for FreeBSD. If you do this then
you should then select the newly created FreeBSD slice using the arrow
keys, and press S to mark the slice as being
bootable. The screen will then look very similar to
. Note the
A in the Flags column, which
indicates that this slice is active, and will be
booted from.If you will be deleting an existing slice to make space for
FreeBSD then you should select the slice using the arrow keys, and
then press D. You can then press C,
and be prompted for size of slice you want to create. Enter the
appropriate figure and press Enter.If you have already made space for FreeBSD (perhaps by using a
tool such as Partition Magic) then you can
press C to create a new slice. Again, you will be
prompted for the size of slice you would like to create.Fdisk Partition Using Entire DiskWhen finished, press Q. Your changes will be
saved in Sysinstall, but will not yet be
written to disk.Install a Boot ManagerYou now have the option to install a boot manager. In general,
you should choose to install the FreeBSD boot manager if:You have more than one drive, and have installed FreeBSD onto
a drive other than the first one.You have installed FreeBSD alongside another operating system
on the same disk, and you want to choose whether to start FreeBSD
or the other operating system when you start the computer.Make your choice and press Enter.Sysinstall Boot Manager MenuThe help screen, reached by pressing F1,
discusses the problems that can be encountered when trying to share
the hard disk between operating systems.Creating Slices on Another DriveIf there is more than one drive, it will return to the
Select Drives screen after the boot manager selection. If you wish to
install FreeBSD on to more than one disk, then you can select another
disk here and repeat the slice process using
FDisk.Exit Select DriveThe Tab key toggles between the last drive
selected, &gui.ok;, and
&gui.cancel;.Press the Tab once to toggle to the
&gui.ok;, then
press Enter
to continue with the installation.Creating Partitions using
DisklabelYou must now create some partitions inside each slice that you
have just created. Remember that each partition is lettered, from
a through to h, and that
partitions b, c, and
d have conventional meanings that you should adhere
to.Certain applications can benefit from particular partition
schemes, especially if you are laying out partitions across more than
one disk. However, for this, your first FreeBSD installation, you do
not need to give too much thought to how you partition the disk. It
is more important that you install FreeBSD and start learning how to
use it. You can always re-install FreeBSD to change your partition
scheme when you are more familiar with the operating system.This scheme features four partitions—one for swap space, and
three for filesystems.
Partition Layout for First DiskPartitionFilesystemSizeDescriptiona/100 MBThis is the root filesystem. Every other filesystem
will be mounted somewhere under this one. 100 MB is a
reasonable size for this filesystem. You will not be storing
too much data on it, as a regular FreeBSD install will put
about 40 MB of data here. The remaining space is for temporary
data, and also leaves expansion space if future versions of
FreeBSD need more space in /.bN/A2-3 x RAMThe system's swap space is kept on this partition.
Choosing the right amount of swap space can be a bit of an
art. A good rule of thumb is that your swap
space should be two or three times as much as the
available physical memory (RAM).
You should also have at least 64 MB of swap, so if you have
less than 32 MB of RAM in your computer then set the swap
amount to 64 MB.
If you have more than one disk then you can put swap
space on each disk. FreeBSD will then use each disk for
swap, which effectively speeds up the act of swapping. In
this case, calculate the total amount of swap you need
(e.g., 128 MB), and then divide this by the number of disks
you have (e.g., two disks) to give the amount of swap you
should put on each disk, in this example, 64 MB of swap per
disk.e/var50 MBThe /var directory contains variable
length files; log files, and other administrative files. Many
of these files are read-from or written-to extensively during
FreeBSD's day-to-day running. Putting these files on another
filesystem allows FreeBSD to optimise the access of these
files without affecting other files in other directories that
do not have the same access pattern.f/usrRest of diskAll your other files will typically be stored in
/usr, and its subdirectories.
If you will be installing FreeBSD on to more than one disk then
you must also create partitions in the other slices that you
configured. The easiest way to do this is to create two partitions on
each disk, one for the swap space, and one for a filesystem.
Partition Layout for Subsequent DisksPartitionFilesystemSizeDescriptionbN/ASee descriptionAs already discussed, you can split swap space across
each disk. Even though the a partition is
free, convention dictates that swap space stays on the
b partition.e/disknRest of diskThe rest of the disk is taken up with one big partition.
This could easily be put on the a
partition, instead of the e partition.
However, convention says that the a
partition on a slice is reserved for the filesystem that will
be the root (/) filesystem. You do not
have to follow this convention, but
Sysinstall does, so following it
yourself makes the installation slightly cleaner. You can
choose to mount this filesystem anywhere; this example
suggests that you mount them as directories
/diskn, where
n is a number that changes for each
disk. But you can use another scheme if you prefer.
Having chosen your partition layout you can now create it using
Sysinstall. You will see this
message: Message
Now, you need to create BSD partitions inside of the fdisk
partition(s) just created. If you have a reasonable amount of disk
space (200MB or more) and don't have any special requirements, simply
use the (A)uto command to allocate space automatically. If you have
more specific needs or just don't care for the layout chosen by
(A)uto, press F1 for more information on manual layout.
[ OK ]
[ Press enter or space ]Press Enter to start the FreeBSD partition
editor, called Disklabel. shows the display when you first
start Disklabel. The display is divided in
to three sections.The first few lines show the name of the disk you are currently
working on, and the slice that contains the partitions you are
creating (at this point Disklabel calls
this the Partition name rather than slice name).
This display also shows the amount of free space within the slice;
that is, space that was set aside in the slice, but that has not yet
been assigned to a partition.The middle of the display shows the partitions that have been
created, the name of the filesystem that each partition contains,
their size, and some options pertaining to the creation of the
filesystem.The bottom third of the screen shows the keystrokes that are valid
in Disklabel.Sysinstall Disklabel EditorDisklabel can automatically create
partitions for you and assign them default sizes. Try this now, by
Pressing A. You will see a display similar to that
shown in . Depending on the size of
the disk you are using the defaults may or may not be appropriate.
This does not matter, as you do not have to accept the
defaults.Beginning with FreeBSD 4.5, the default partitioning assigns
the /tmp directory its own partition instead
of being part of the / partition. This
helps avoid filling the / partition with
temporary files.Sysinstall Disklabel Editor With Auto DefaultsTo delete the suggested partitions, and replace them with your
own, use the arrow keys to select the first partition, and press
D to delete it. Repeat this to delete all the
suggested partitions.To create the first partition (a, mounted as
/), make sure the disk information at the top of
the screen is selected, and press C. A dialog box
will appear prompting you for the size of the new partition (as shown
in ). You can enter the size as
the number of disk blocks you want to use, or, more usefully, as a
number followed by either M for megabytes,
G for gigabytes, or C for
cylinders.Free Space For Root PartitionThe default size shown will create a partition that takes up the
rest of the slice. If you are using the partition sizes described
earlier, then delete the existing figure using
Backspace, and then type in
64M, as shown in
. Then press
&gui.ok;.Edit Root Partition SizeHaving chosen the partition's size you will then asked whether
this partition will contain a filesystem or swap space. The dialog
box is shown in . This first
partition will contain a filesystem, so check that
FS is selected and then press
Enter.Choose The Root Partition TypeFinally, because you are creating a filesystem, you must tell
Disklabel where the filesystem is to be
mounted. The dialog box is shown in
. The root filesystem's mount
point is /, so type /, and
then press Enter.Choose The Root Mount PointThe display will then update to show you the newly created
partition. You should repeat this procedure for the other
partitions. When you create the swap partition you will not be
prompted for the filesystem mount point, as swap partitions are never
mounted. When you create the final partition,
/usr, you can leave the suggested size as is, to
use the rest of the slice.Your final FreeBSD DiskLabel Editor screen will appear similar to
, although your values chosen may
be different. Press Q to finish.Sysinstall Disklabel EditorChoosing What To InstallSelect The Distribution SetDeciding which distribution set to install will depend largely
on the intended use of the system and the amount of disk space
available. The predefined options range from installing the
smallest possible configuration to everything. Those who are
new to Unix and/or FreeBSD should almost certainly select one
of these canned options. Customizing a distribution set is
typically for the more experienced user.Press F1 for more information on the
distribution set options and what they contain. When finished
reviewing the help, pressing Enter will return
to the Select Distributions Menu.If a graphical user interface is desired then a distribution
set that is preceded by an X should be
chosen. The configuration of XFree86 and selection of a default
desktop is part of the post-installation steps.The default version of XFree86 that is installed depends on the
version of the FreeBSD that you are installing. For FreeBSD versions
prior to 4.6, XFree86 3.X is installed. For FreeBSD 4.6 and later,
XFree86 4.X is the default.You should check to see whether your video card is supported at the
XFree86 web site. If it
is not supported under the default version that FreeBSD will install,
you should select a distribution without X for installation. After
installation, install and configure the appropriate version of
XFree86 using the ports collection.If compiling a custom kernel is anticipated, select an option
which includes the source code. For more information on why a
custom kernel should be built or how to build a custom kernel see
.Obviously, the most versatile system is one that includes
everything. If there is adequate disk space, select
All as shown in
by using the arrow keys and
press Enter. If there is a concern about disk
space consider using an option that is more suitable for the
situation. Other distributions can be added after installation.Choose DistributionsInstalling The Ports CollectionAfter selecting the desired distribution, an opportunity to
install the FreeBSD Ports Collection is presented. The ports
collection is an easy and convenient way to install software.
The ports collection does not contain the source code necessary
to compile the software. It is a collection of files which
automates the downloading, compiling and installation.
discusses how to use the ports
collection.The installation program does not check to see if you have
adequate space. Select this option only if you have
adequate hard disk space. User Confirmation Requested
Would you like to install the FreeBSD ports collection?
This will give you ready access to over &os.numports; ported software packages,
at a cost of around 165MB of disk space when "clean" and possibly much
more than that if a lot of the distribution tarballs are loaded
(unless you have the extra CDs from a FreeBSD CD/DVD distribution
available and can mount it on /cdrom, in which case this is far less
of a problem).
The ports collection is a very valuable resource and well worth having
on your /usr partition, so it is advisable to say Yes to this option.
For more information on the ports collection & the latest ports,
visit:
http://www.FreeBSD.org/ports
[ Yes ] NoSelect [ Yes ] with the arrow keys to
install the ports collection or [ No ] to
skip this option. Press Enter to continue.
The Choose Distributions menu will redisplay.Confirm DistributionsIf satisfied with the options, select
Exit with the arrow keys, ensure that
&gui.ok; is highlighted, and press
Enter to continue.Choosing Your Installation MediaIf Installing from a CDROM, use the arrow keys to highlight
Install from a FreeBSD CD/DVD. Ensure
that &gui.ok; is highlighted, then press
Enter to proceed with the installation.For other methods of installation, select the appropriate
option and follow the instructions.Press F1 to display the Online Help for
installation media. Press Enter to return
to the media selection menu.Choose Installation MediaFTP Installation ModesinstallationnetworkFTPThere are three FTP installation modes you can choose from:
active FTP, passive FTP, or via a HTTP proxy.FTP Active, Install from an FTP
serverThis option will make all FTP transfers
use Active
mode. This will not work through firewalls, but will
often work with older FTP servers that do not support
passive mode. If your connection hangs with passive
mode (the default), try active!FTP Passive, Install from an FTP server through a
firewallFTPPassive modeThis option instructs FreeBSD to use
Passive mode for all FTP operations.
This allows the user to pass through firewalls
that do not allow incoming connections on random port
addresses.FTP via a HTTP proxy, Install from an FTP server
through a http proxyFTPvia a HTTP proxyThis option instructs FreeBSD to use the HTTP
protocol (like a web browser) to connect to a proxy
for all FTP operations. The proxy will translate
the requests and send them to the FTP server.
This allows the user to pass through firewalls
that do not allow FTP at all, but offer a HTTP
proxy.
In this case, you have to specify the proxy in
addition to the FTP server.For a proxy FTP server, you should usually give the name of the
server you really want as a part of the username, after an
@ sign. The proxy server then fakes
the real server. For example, assuming you want to install from
ftp.FreeBSD.org, using the proxy FTP
server foo.example.com, listening on port
1024.In this case, you go to the options menu, set the FTP username
to ftp@ftp.FreeBSD.org, and the password to your
email address. As your installation media, you specify FTP (or
passive FTP, if the proxy supports it), and the URL
ftp://foo.example.com:1234/pub/FreeBSD.Since /pub/FreeBSD from
ftp.FreeBSD.org is proxied under
foo.example.com, you are able to install
from that machine (which will fetch the files
from ftp.FreeBSD.org as your
installation requests them).Committing to the InstallationThe installation can now proceed if desired. This is also
the last chance for aborting the installation to prevent changes
to the hard drive. User Confirmation Requested
Last Chance! Are you SURE you want to continue the installation?
If you're running this on a disk with data you wish to save then WE
STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before proceeding!
We can take no responsibility for lost disk contents!
[ Yes ] NoSelect [ Yes ] and press
Enter to proceed.The installation time will vary according to the distribution
chosen, installation media used, and the speed of the computer.
There will be a series of
messages displayed indicating the status.The installation is complete when the following message is
displayed: Message
Congratulations! You now have FreeBSD installed on your system.
We will now move on to the final configuration questions.
For any option you do not wish to configure, simply select No.
If you wish to re-enter this utility after the system is up, you may
do so by typing: /stand/sysinstall .
[ OK ]
[ Press enter to continue ]Press Enter to proceed with post-installation
configurations.Selecting [ No ] and pressing
Enter will abort
the installation so no changes will be made to your system. The
following message will appear: Message
Installation complete with some errors. You may wish to scroll
through the debugging messages on VTY1 with the scroll-lock feature.
You can also choose "No" at the next prompt and go back into the
installation menus to try and retry whichever operations have failed.
[ OK ]This message is generated because nothing was installed.
Pressing Enter will return to the
Main Installation Menu to exit the installation.Post-installationConfiguration of various options follows the successful
installation. An option can be configured by re-entering the
configuration options before booting the new FreeBSD
system or after installation using
/stand/sysinstall and selecting
Configure.Network Device ConfigurationIf you previously configured PPP for an FTP install, this screen
will not display and can be configured later as described
above.For detailed information on Local Area Networks and
configuring FreeBSD as a gateway/router refer to the
Advanced Networking
chapter. User Confirmation Requested
Would you like to configure any Ethernet or SLIP/PPP network devices?
[ Yes ] NoTo configure a network device, select
[ Yes ] and press Enter.
Otherwise, select [ No ] to continue.Selecting An Ethernet DeviceSelect the interface to be configured with the arrow keys and press
Enter. User Confirmation Requested
Do you want to try IPv6 configuration of the interface?
Yes [ No ]In this private local area network the current Internet
type protocol (IPv4) was sufficient and [ No ]
was selected with the arrow keys and Enter
pressed.If you want to try the new Internet protocol (IPv6), choose
[ Yes ] and press Enter.
It will take several seconds to scan for RA servers. User Confirmation Requested
Do you want to try DHCP configuration of the interface?
Yes [ No ]If DHCP (Dynamic Host Configuration Protocol) is not required
select [ No ] with the arrow keys and press
Enter.Selecting [ Yes ] will execute
dhclient, and if successful, will fill
in the network configuration information automatically. Refer to
for more information.The following Network Configuration screen shows the
configuration of the Ethernet device for a system that will act
as the gateway for a Local Area Network.Set Network Configuration For ed0Use Tab to select the information fields and
fill in appropriate information:HostThe fully-qualified hostname, e.g. k6-2.example.com in
this case.DomainThe name of the domain that your machine is
in, e.g. example.com for this case.IPv4 GatewayIP address of host forwarding packets to non-local
destinations. Fill this in only if the machine is a node
on the network. Leave this field blank
if the machine is the gateway to the Internet for the
network.Name serverIP address of your local DNS server. There is no local
DNS server on this private local area network so the IP
address of the provider's DNS server
(208.163.10.2) was used.IPv4 addressThe IP address to be used for this interface was
192.168.0.1NetmaskThe address block being used for this local area
network is a Class C block
(192.168.0.0 -
192.168.255.255).
The default netmask is for a Class C network
(255.255.255.0).Extra options to ifconfigAny interface-specific options to ifconfig
you would like to add. There were none in this case.Use Tab to select &gui.ok;
when finished and press Enter. User Confirmation Requested
Would you like to Bring Up the ed0 interface right now?
[ Yes ] NoChoosing [ Yes ] and pressing
Enter will bring
the machine up on the network and be ready for use after leaving
the installation.Configure Gateway User Confirmation Requested
Do you want this machine to function as a network gateway?
[ Yes ] NoIf the machine will be acting as the gateway for a local area
network and forwarding packets between other machines then select
[ Yes ] and press Enter.
If the machine is a node on a network then
select [ No ] and press
Enter to continue.Configure Internet Services User Confirmation Requested
Do you want to configure inetd and the network services that it provides?
Yes [ No ]If [ No ] is selected, various services
such telnetd will not be enabled. This
means that remote users will not be able to
telnet into this machine. Local users
will be still be able to access remote machines with
telnet.These services can be enabled after installation by editing
/etc/inetd.conf with your favorite text editor.
See for more information.Select [ Yes ] if you wish to
configure these services during install. An additional
confirmation will display: User Confirmation Requested
The Internet Super Server (inetd) allows a number of simple Internet
services to be enabled, including finger, ftp and telnetd. Enabling
these services may increase risk of security problems by increasing
the exposure of your system.
With this in mind, do you wish to enable inetd?
[ Yes ] NoSelect [ Yes ] to continue. User Confirmation Requested
inetd(8) relies on its configuration file, /etc/inetd.conf, to determine
which of its Internet services will be available. The default FreeBSD
inetd.conf(5) leaves all services disabled by default, so they must be
specifically enabled in the configuration file before they will
function, even once inetd(8) is enabled. Note that services for
-IPv6 must be seperately enabled from IPv4 services.
+IPv6 must be separately enabled from IPv4 services.
Select [Yes] now to invoke an editor on /etc/inetd.conf, or [No] to
use the current settings.
[ Yes ] NoSelecting [ Yes ] will allow adding
services by deleting the # at the beginning
of a line.Editing inetd.confAfter adding the desired services, pressing Esc
will display a menu which will allow exiting and saving
the changes.Anonymous FTP User Confirmation Requested
Do you want to have anonymous FTP access to this machine?
Yes [ No ]Deny Anonymous FTPSelecting the default [ No ] and pressing
Enter will still allow users who have accounts
with passwords to use FTP to access the machine.Allow Anonymous FTPAnyone can access your machine if you elect to allow
anonymous FTP connections. The security implications should be
considered before enabling this option. For more information
about security see .To allow anonymous FTP, use the arrow keys to select
[ Yes ] and press Enter.
The following screen (or similar) will display:Default Anonymous FTP ConfigurationPressing F1 will display the help:This screen allows you to configure the anonymous FTP user.
The following configuration values are editable:
UID: The user ID you wish to assign to the anonymous FTP user.
All files uploaded will be owned by this ID.
Group: Which group you wish the anonymous FTP user to be in.
Comment: String describing this user in /etc/passwd
FTP Root Directory:
Where files available for anonymous FTP will be kept.
Upload subdirectory:
Where files uploaded by anonymous FTP users will go.The ftp root directory will be put in /var
by default. If you do not have enough room there for the
anticipated FTP needs, the /usr directory
could be used by setting the FTP Root Directory to
/usr/ftp.When you are satisfied with the values, press
Enter to continue. User Confirmation Requested
Create a welcome message file for anonymous FTP users?
[ Yes ] NoIf you select [ Yes ] and press
Enter, an editor will automatically start
allowing you to edit the message.Edit The FTP Welcome MessageThis is a text editor called ee. Use the
instructions to change the message or change the message later
using a text editor of your choice. Note the file name/location
at the bottom of the editor screen.Press Esc and a pop-up menu will default
to a) leave editor. Press
Enter to exit and continue.Configure Network File ServicesNetwork File Services (NFS) allows sharing of files across a
network. A machine can be configured as a server, a client, or
both. Refer to for a more information.NFS Server User Confirmation Requested
Do you want to configure this machine as an NFS server?
Yes [ No ]If there is no need for a Network File System server or
client, select [ No ] and press
Enter.If [ Yes ] is chosen, a message will
pop-up indicating that the exports file must be
created. Message
Operating as an NFS server means that you must first configure an
/etc/exports file to indicate which hosts are allowed certain kinds of
access to your local filesystems.
Press [Enter] now to invoke an editor on /etc/exports
[ OK ]Press Enter to continue. A text editor will
start allowing the exports file to be created
and edited.Editing exportsUse the instructions to add the actual exported filesystems
now or later using a text editor of your choice. Note the
file name/location at the bottom of the editor screen.Press Esc and a pop-up menu will default to
a) leave editor. Press
Enter to exit and continue.NFS Client User Confirmation Requested
Do you want to configure this machine as an NFS client?
Yes [ No ]With the arrow keys, select [ Yes ]
or [ No ] as appropriate and
press Enter.Security ProfileA security profile is a set of
configuration options that attempts to achieve the desired
ratio of security to convenience by enabling and disabling
certain programs and other settings. The more severe the
security profile, the fewer programs will be enabled by
default. This is one of the basic principles of security: do
not run anything except what you must.Please note that the security profile is just a default
setting. All programs can be enabled and disabled after you
have installed FreeBSD by editing or adding the appropriate
line(s) to /etc/rc.conf. For more
information, please see the &man.rc.conf.5; manual
page.The following table describes what each of the security
profiles does. The columns are the choices you have for a
security profile, and the rows are the program or feature that
the profile enables or disables.
Possible security profilesExtremeModerate&man.sendmail.8;NOYES&man.sshd.8;NOYES&man.portmap.8;NOMAYBE
The portmapper is enabled if the machine has
been configured as an NFS client or server earlier
in the installation.NFS serverNOYES&man.securelevel.8;YES
If you choose a security profile that sets the
securelevel to Extreme or
High, you must be aware of the
implications. Please read the &man.init.8;
manual page and pay particular attention to the
meanings of the security levels, or you may have
significant trouble later!NO
User Confirmation Requested
Do you want to select a default security profile for this host (select
No for "medium" security)?
[ Yes ] NoSelecting [ No ] and pressing
Enter will set the security profile to medium.Selecting [ Yes ] and pressing
Enter will allow selecting a different security
profile.Security Profile OptionsPress F1 to display the help. Press
Enter to return to selection menu.Use the arrow keys to choose Medium
unless your are sure that another level is required for your needs.
With &gui.ok; highlighted, press
Enter.An appropriate confirmation message will display depending on
which security setting was chosen. Message
Moderate security settings have been selected.
Sendmail and SSHd have been enabled, securelevels are
disabled, and NFS server setting have been left intact.
PLEASE NOTE that this still does not save you from having
to properly secure your system in other ways or exercise
due diligence in your administration, this simply picks
a standard set of out-of-box defaults to start with.
To change any of these settings later, edit /etc/rc.conf
[OK] Message
Extreme security settings have been selected.
Sendmail, SSHd, and NFS services have been disabled, and
securelevels have been enabled.
PLEASE NOTE that this still does not save you from having
to properly secure your system in other ways or exercise
due diligence in your administration, this simply picks
a more secure set of out-of-box defaults to start with.
To change any of these settings later, edit /etc/rc.conf
[OK]Press Enter to continue with the
post-installation configuration.The security profile is not a silver bullet! Even if
you use the extreme setting, you need to keep up with
security issues by reading an appropriate mailing
list, using good passwords and passphrases, and
generally adhering to good security practices. It simply
sets up the desired security to convenience ratio out of the
box.System Console SettingsThere are several options available to customize the system
console. User Confirmation Requested
Would you like to customize your system console settings?
[ Yes ] NoTo view and configure the options, select
[ Yes ] and press
Enter.System Console Configuration OptionsA commonly used option is the screen saver. Use the arrow keys
to select Saver and then press
Enter.Screen Saver OptionsSelect the desired screen saver using the arrow keys
and then press Enter. The System Console
Configuration menu will redisplay.The default time interval is 300 seconds. To change the time
interval, select Saver again. At the
Screen Saver Options menu, select Timeout
using the arrow keys and press Enter. A pop-up
menu will appear:Screen Saver TimeoutThe value can be changed, then select &gui.ok;
and press Enter to return to the System Console
Configuration menu.System Console Configuration ExitSelecting Exit and pressing
Enter will continue with the post-installation
configurations.Setting The Time ZoneSetting the time zone for your machine will allow it to
automatically correct for any regional time changes and perform
other time zone related functions properly.The example shown is for a machine located in the Eastern
time zone of the United States. Your selections will vary according
to your geographical location. User Confirmation Requested
Would you like to set this machine's time zone now?
[ Yes ] NoSelect [ Yes ] and press
Enter to set the time zone. User Confirmation Requested
Is this machine's CMOS clock set to UTC? If it is set to local time
or you don't know, please choose NO here!
Yes [ No ]Select [ Yes ]
or [ No ] according to how the machine's
clock is configured and press Enter.Select Your RegionThe appropriate region is selected using the arrow keys
and then press Enter.Select Your CountrySelect the appropriate country using the arrow keys
and press Enter.Select Your Time ZoneThe appropriate time zone is selected using the arrow
keys and pressing Enter. Confirmation
Does the abbreviation 'EDT' look reasonable?
[ Yes ] NoConfirm the abbreviation for the time zone is correct.
If it looks okay, press Enter to continue with
the post-installation configuration.Linux Compatibility User Confirmation Requested
Would you like to enable Linux binary compatibility?
[ Yes ] NoSelecting [ Yes ] and pressing
Enter will allow
running Linux software on FreeBSD. The install will proceed to add
the appropriate packages for Linux compatibility.If installing by FTP, the machine will need to be connected to
the Internet. Sometimes a remote ftp site will not have all the
distributions like the Linux binary compatibility. This can
be installed later if necessary.Mouse SettingsThis option will allow you to cut and paste text in the
console and user programs with a 3-button mouse. If using a 2-button
mouse, refer to manual page, &man.moused.8;, after installation for
details on emulating the 3-button style. This example depicts a
non-USB mouse configuration: User Confirmation Requested
Does this system have a non-USB mouse attached to it?
[ Yes ] No Select [ Yes ] for a non-USB mouse or
[ No ] for a USB mouse and press
Enter.Select Mouse Protocol TypeUse the arrow keys to select Type and
press Enter.Set Mouse ProtocolThe mouse used in this example is a PS/2 type, so the default
Auto was appropriate. To change protocol,
use the arrow keys to select another option. Ensure that &gui.ok; is
highlighted and press Enter to exit this menu.Configure Mouse PortUse the arrow keys to select Port and
press Enter.Setting The Mouse PortThis system had a PS/2 mouse, so the default
PS/2 was appropriate. To change the port,
use the arrow keys and then press Enter.Enable The Mouse DaemonLast, the mouse daemon is enabled and tested.Test The Mouse DaemonThe cursor moved around the screen so the mouse daemon is
running.Select [ Yes ] to return to the previous
menu then select Exit with the arrow keys
and press Enter to return to continue with the
post-installation configuration.Configure X ServerIn order to use a graphical user interface such as
KDE, GNOME,
or others, the X server will need to be configured.In order to run XFree86 as a
non root user you will need to
have x11/wrapper installed.
This is installed by default beginning with FreeBSD 4.7. For
earlier versions this can be added
from the Package Selection menu.To see whether your video card is supported, check the
XFree86 web site. User Confirmation Requested
Would you like to configure your X server at this time?
[ Yes ] NoIt is necessary to know your monitor specifications and
video card information. Equipment damage can occur if settings
are incorrect. If you do not have this information, select
[ No ] and perform the configuration
after installation when you have the information using
/stand/sysinstall, selecting
Configure and then
XFree86.
If you have graphics card and monitor information, select
[ Yes ] and press Enter
to proceed with configuring the X server.Select Configuration Method MenuThere are several ways to configure the X server.
Use the arrow keys to select one of the methods and press
Enter. Be sure to read all instructions
carefully.The xf86cfg and
xf86cfg -textmode may make the screen
go dark and take a few seconds to start. Be patient.The following will illustrate the use of the
xf86config configuration tool. The
configuration choices you make will depend on the hardware in the
system so your choices will probably be different than those
shown: Message
You have configured and been running the mouse daemon.
Choose "/dev/sysmouse" as the mouse port and "SysMouse" or
"MouseSystems" as the mouse protocol in the X configuration utility.
[ OK ]
[ Press enter to continue ]This indicates that the mouse daemon previously configured has been
detected.
Press Enter to continue.Starting xf86config will display
a brief introduction:This program will create a basic XF86Config file, based on menu selections you
make.
The XF86Config file usually resides in /usr/X11R6/etc/X11 or /etc/X11. A sample
XF86Config file is supplied with XFree86; it is configured for a standard
VGA card and monitor with 640x480 resolution. This program will ask for a
pathname when it is ready to write the file.
You can either take the sample XF86Config as a base and edit it for your
configuration, or let this program produce a base XF86Config file for your
configuration and fine-tune it.
Before continuing with this program, make sure you know what video card
you have, and preferably also the chipset it uses and the amount of video
memory on your video card. SuperProbe may be able to help with this.
Press enter to continue, or ctrl-c to abort.Pressing Enter will start the mouse
configuration. Be sure to follow the instructions and use
Mouse Systems as the mouse protocol and
/dev/sysmouse as the mouse port even if
using a PS/2 mouse is shown as an illustration.First specify a mouse protocol type. Choose one from the following list:
1. Microsoft compatible (2-button protocol)
2. Mouse Systems (3-button protocol) & FreeBSD moused protocol
3. Bus Mouse
4. PS/2 Mouse
5. Logitech Mouse (serial, old type, Logitech protocol)
6. Logitech MouseMan (Microsoft compatible)
7. MM Series
8. MM HitTablet
9. Microsoft IntelliMouse
If you have a two-button mouse, it is most likely of type 1, and if you have
a three-button mouse, it can probably support both protocol 1 and 2. There are
two main varieties of the latter type: mice with a switch to select the
protocol, and mice that default to 1 and require a button to be held at
boot-time to select protocol 2. Some mice can be convinced to do 2 by sending
a special sequence to the serial port (see the ClearDTR/ClearRTS options).
Enter a protocol number: 2
You have selected a Mouse Systems protocol mouse. If your mouse is normally
in Microsoft-compatible mode, enabling the ClearDTR and ClearRTS options
may cause it to switch to Mouse Systems mode when the server starts.
Please answer the following question with either 'y' or 'n'.
Do you want to enable ClearDTR and ClearRTS? n
You have selected a three-button mouse protocol. It is recommended that you
do not enable Emulate3Buttons, unless the third button doesn't work.
Please answer the following question with either 'y' or 'n'.
Do you want to enable Emulate3Buttons? y
Now give the full device name that the mouse is connected to, for example
/dev/tty00. Just pressing enter will use the default, /dev/mouse.
On FreeBSD, the default is /dev/sysmouse.
Mouse device: /dev/sysmouseThe keyboard is the next item to be configured. A generic
101-key model is shown for illustration. Any name may be used
for the variant or simply press Enter to accept
the default value.Please select one of the following keyboard types that is the better
description of your keyboard. If nothing really matches,
choose 1 (Generic 101-key PC)
1 Generic 101-key PC
2 Generic 102-key (Intl) PC
3 Generic 104-key PC
4 Generic 105-key (Intl) PC
5 Dell 101-key PC
6 Everex STEPnote
7 Keytronic FlexPro
8 Microsoft Natural
9 Northgate OmniKey 101
10 Winbook Model XP5
11 Japanese 106-key
12 PC-98xx Series
13 Brazilian ABNT2
14 HP Internet
15 Logitech iTouch
16 Logitech Cordless Desktop Pro
17 Logitech Internet Keyboard
18 Logitech Internet Navigator Keyboard
19 Compaq Internet
20 Microsoft Natural Pro
21 Genius Comfy KB-16M
22 IBM Rapid Access
23 IBM Rapid Access II
24 Chicony Internet Keyboard
25 Dell Internet Keyboard
Enter a number to choose the keyboard.
1
Please select the layout corresponding to your keyboard
1 U.S. English
2 U.S. English w/ ISO9995-3
3 U.S. English w/ deadkeys
4 Albanian
5 Arabic
6 Armenian
7 Azerbaidjani
8 Belarusian
9 Belgian
10 Bengali
11 Brazilian
12 Bulgarian
13 Burmese
14 Canadian
15 Croatian
16 Czech
17 Czech (qwerty)
18 Danish
Enter a number to choose the country.
Press enter for the next page
1
Please enter a variant name for 'us' layout. Or just press enter
for default variant
us
Please answer the following question with either 'y' or 'n'.
Do you want to select additional XKB options (group switcher,
group indicator, etc.)? nNext, we proceed to the configuration for the monitor. Do not
exceed the ratings of your monitor. Damage could occur. If you
have any doubts, do the configuration after you have the
information.Now we want to set the specifications of the monitor. The two critical
parameters are the vertical refresh rate, which is the rate at which the
whole screen is refreshed, and most importantly the horizontal sync rate,
which is the rate at which scanlines are displayed.
The valid range for horizontal sync and vertical sync should be documented
in the manual of your monitor. If in doubt, check the monitor database
/usr/X11R6/lib/X11/doc/Monitors to see if your monitor is there.
Press enter to continue, or ctrl-c to abort.
You must indicate the horizontal sync range of your monitor. You can either
select one of the predefined ranges below that correspond to industry-
standard monitor types, or give a specific range.
It is VERY IMPORTANT that you do not specify a monitor type with a horizontal
sync range that is beyond the capabilities of your monitor. If in doubt,
choose a conservative setting.
hsync in kHz; monitor type with characteristic modes
1 31.5; Standard VGA, 640x480 @ 60 Hz
2 31.5 - 35.1; Super VGA, 800x600 @ 56 Hz
3 31.5, 35.5; 8514 Compatible, 1024x768 @ 87 Hz interlaced (no 800x600)
4 31.5, 35.15, 35.5; Super VGA, 1024x768 @ 87 Hz interlaced, 800x600 @ 56 Hz
5 31.5 - 37.9; Extended Super VGA, 800x600 @ 60 Hz, 640x480 @ 72 Hz
6 31.5 - 48.5; Non-Interlaced SVGA, 1024x768 @ 60 Hz, 800x600 @ 72 Hz
7 31.5 - 57.0; High Frequency SVGA, 1024x768 @ 70 Hz
8 31.5 - 64.3; Monitor that can do 1280x1024 @ 60 Hz
9 31.5 - 79.0; Monitor that can do 1280x1024 @ 74 Hz
10 31.5 - 82.0; Monitor that can do 1280x1024 @ 76 Hz
11 Enter your own horizontal sync range
Enter your choice (1-11): 6
You must indicate the vertical sync range of your monitor. You can either
select one of the predefined ranges below that correspond to industry-
standard monitor types, or give a specific range. For interlaced modes,
the number that counts is the high one (e.g. 87 Hz rather than 43 Hz).
1 50-70
2 50-90
3 50-100
4 40-150
5 Enter your own vertical sync range
Enter your choice: 2
You must now enter a few identification/description strings, namely an
identifier, a vendor name, and a model name. Just pressing enter will fill
in default names.
The strings are free-form, spaces are allowed.
Enter an identifier for your monitor definition: HitachiThe selection of a video card driver from a list is
next. If you pass your card on the list, continue to press
Enter and the list will repeat. Only an
excerpt from the list is shown:Now we must configure video card specific settings. At this point you can
choose to make a selection out of a database of video card definitions.
Because there can be variation in Ramdacs and clock generators even
between cards of the same model, it is not sensible to blindly copy
the settings (e.g. a Device section). For this reason, after you make a
selection, you will still be asked about the components of the card, with
the settings from the chosen database entry presented as a strong hint.
The database entries include information about the chipset, what driver to
run, the Ramdac and ClockChip, and comments that will be included in the
Device section. However, a lot of definitions only hint about what driver
to run (based on the chipset the card uses) and are untested.
If you can't find your card in the database, there's nothing to worry about.
You should only choose a database entry that is exactly the same model as
your card; choosing one that looks similar is just a bad idea (e.g. a
GemStone Snail 64 may be as different from a GemStone Snail 64+ in terms of
hardware as can be).
Do you want to look at the card database? y
288 Matrox Millennium G200 8MB mgag200
289 Matrox Millennium G200 SD 16MB mgag200
290 Matrox Millennium G200 SD 4MB mgag200
291 Matrox Millennium G200 SD 8MB mgag200
292 Matrox Millennium G400 mgag400
293 Matrox Millennium II 16MB mga2164w
294 Matrox Millennium II 4MB mga2164w
295 Matrox Millennium II 8MB mga2164w
296 Matrox Mystique mga1064sg
297 Matrox Mystique G200 16MB mgag200
298 Matrox Mystique G200 4MB mgag200
299 Matrox Mystique G200 8MB mgag200
300 Matrox Productiva G100 4MB mgag100
301 Matrox Productiva G100 8MB mgag100
302 MediaGX mediagx
303 MediaVision Proaxcel 128 ET6000
304 Mirage Z-128 ET6000
305 Miro CRYSTAL VRX Verite 1000
Enter a number to choose the corresponding card definition.
Press enter for the next page, q to continue configuration.
288
Your selected card definition:
Identifier: Matrox Millennium G200 8MB
Chipset: mgag200
Driver: mga
Do NOT probe clocks or use any Clocks line.
Press enter to continue, or ctrl-c to abort.
Now you must give information about your video card. This will be used for
the "Device" section of your video card in XF86Config.
You must indicate how much video memory you have. It is probably a good
idea to use the same approximate amount as that detected by the server you
intend to use. If you encounter problems that are due to the used server
not supporting the amount memory you have (e.g. ATI Mach64 is limited to
1024K with the SVGA server), specify the maximum amount supported by the
server.
How much video memory do you have on your video card:
1 256K
2 512K
3 1024K
4 2048K
5 4096K
6 Other
Enter your choice: 6
Amount of video memory in Kbytes: 8192
You must now enter a few identification/description strings, namely an
identifier, a vendor name, and a model name. Just pressing enter will fill
in default names (possibly from a card definition).
Your card definition is Matrox Millennium G200 8MB.
The strings are free-form, spaces are allowed.
Enter an identifier for your video card definition:Next, the video modes are set for the resolutions
desired. Typically, useful ranges are 640x480, 800x600, and 1024x768
but those are a function of video card capability, monitor size,
and eye comfort. When selecting a color depth, select the highest
mode that your card will support.For each depth, a list of modes (resolutions) is defined. The default
resolution that the server will start-up with will be the first listed
mode that can be supported by the monitor and card.
Currently it is set to:
"640x480" "800x600" "1024x768" "1280x1024" for 8-bit
"640x480" "800x600" "1024x768" "1280x1024" for 16-bit
"640x480" "800x600" "1024x768" "1280x1024" for 24-bit
Modes that cannot be supported due to monitor or clock constraints will
be automatically skipped by the server.
1 Change the modes for 8-bit (256 colors)
2 Change the modes for 16-bit (32K/64K colors)
3 Change the modes for 24-bit (24-bit color)
4 The modes are OK, continue.
Enter your choice: 2
Select modes from the following list:
1 "640x400"
2 "640x480"
3 "800x600"
4 "1024x768"
5 "1280x1024"
6 "320x200"
7 "320x240"
8 "400x300"
9 "1152x864"
a "1600x1200"
b "1800x1400"
c "512x384"
Please type the digits corresponding to the modes that you want to select.
For example, 432 selects "1024x768" "800x600" "640x480", with a
default mode of 1024x768.
Which modes? 432
You can have a virtual screen (desktop), which is screen area that is larger
than the physical screen and which is panned by moving the mouse to the edge
of the screen. If you don't want virtual desktop at a certain resolution,
you cannot have modes listed that are larger. Each color depth can have a
differently-sized virtual screen
Please answer the following question with either 'y' or 'n'.
Do you want a virtual screen that is larger than the physical screen? n
For each depth, a list of modes (resolutions) is defined. The default
resolution that the server will start-up with will be the first listed
mode that can be supported by the monitor and card.
Currently it is set to:
"640x480" "800x600" "1024x768" "1280x1024" for 8-bit
"1024x768" "800x600" "640x480" for 16-bit
"640x480" "800x600" "1024x768" "1280x1024" for 24-bit
Modes that cannot be supported due to monitor or clock constraints will
be automatically skipped by the server.
1 Change the modes for 8-bit (256 colors)
2 Change the modes for 16-bit (32K/64K colors)
3 Change the modes for 24-bit (24-bit color)
4 The modes are OK, continue.
Enter your choice: 4
Please specify which color depth you want to use by default:
1 1 bit (monochrome)
2 4 bits (16 colors)
3 8 bits (256 colors)
4 16 bits (65536 colors)
5 24 bits (16 million colors)
Enter a number to choose the default depth.
4Finally, the configuration needs to be saved. Be sure
to enter /etc/XF86Config as the location
for saving the configuration.I am going to write the XF86Config file now. Make sure you don't accidently
overwrite a previously configured one.
Shall I write it to /etc/X11/XF86Config? yIf the configuration fails, you can try the configuration again
by selecting [ Yes ] when the following
message appears: User Confirmation Requested
The XFree86 configuration process seems to have
failed. Would you like to try again?
[ Yes ] NoIf you have trouble configuring XFree86, select
[ No ] and press Enter
and continue with the installation process. After installation
you can use xf86cfg -textmode or
xf86config to access the command line
configuration utilities as root. There is
an additional method for configuring XFree86 described in
. If you choose not to configure
XFree86 at this time the next menu will be for package
selection.The default setting which allows the server to be killed
is the hotkey sequence CtrlAltBackspace. This
can be executed if something is wrong with the server settings and
prevent hardware damage.The default setting that allows video mode switching will
permit changing of the mode while running X with the hotkey
sequence
CtrlAlt+ or
CtrlAlt-.
After installation, the display can be adjusted for height,
width, or centering by using xvidtune
after you have XFree86 running with
xvidtune.There are warnings that improper settings can
damage your equipment. Heed them. If in doubt, do not do
it. Instead, use the monitor controls to adjust the display for
X Window. There may be some display differences when switching
back to text mode, but it is better than damaging equipment.Read the &man.xvidtune.1; manual page before making
any adjustments.Following a successful XFree86 configuration, it will proceed
to the selection of a default desktop.Select Default X DesktopThere are a variety of window managers available. They range
from very basic environments to full desktop environments with a
large suite of software. Some require only minimal disk space and
low memory while others with more features require much more. The
best way to determine which is most suitable for you is to try a few
different ones. Those are available from the ports collection or as
packages and can be added after installation.You can select one of the popular desktops to be installed
and configured as the default desktop. This will allow you
to start it right after installation.Select Default DesktopUse the arrow keys to select a desktop and press
Enter. Installation of the selected desktop will
proceed.Install PackagesThe packages are pre-compiled binaries and are a convenient
way to install software.Installation of one package is shown for purposes of
illustration. Additional packages can also be added at this
time if desired. After installation
/stand/sysinstall can be used to add additional
packages. User Confirmation Requested
The FreeBSD package collection is a collection of hundreds of
ready-to-run applications, from text editors to games to WEB servers
and more. Would you like to browse the collection now?
[ Yes ] NoSelecting [ Yes ] and pressing
Enter will be
followed by the Package Selection screens:Select Package CategoryAll packages available will be displayed if
All is selected or you can select a
particular category. Highlight your selection with the arrow
keys and press Enter.A menu will display showing all the packages available for
the selection made:Select PackagesThe bash shell is shown selected.
Select as many as desired by highlighting the package and pressing the
Space key. A short description of each package will
appear in the lower left corner of the screen.Pressing the Tab key will toggle between the last
selected package, &gui.ok;, and &gui.cancel;.When you have finished marking the packages for installation,
press Tab once to toggle to the &gui.ok; and press
Enter to return to the Package Selection menu.The left and right arrow keys will also toggle between &gui.ok;
and &gui.cancel;. This method can also be used to select &gui.ok; and
press Enter to return to the Package Selection
menu.Install PackagesUse the arrow keys to select [ Install ]
and press Enter. You will then need to confirm
that you want to install the packages:Confirm Package InstallationSelecting &gui.ok; and pressing Enter will start
the package installation. Installing messages will appear until
completed. Make note if there are any error messages.The final configuration continues after packages are
installed.Add Users/GroupsYou should add at least one user during the installation so
that you can use the system without being logged in as
root. The root partition is generally small
and running applications as root can quickly
fill it. A bigger danger is noted below: User Confirmation Requested
Would you like to add any initial user accounts to the system? Adding
at least one account for yourself at this stage is suggested since
working as the "root" user is dangerous (it is easy to do things which
adversely affect the entire system).
[ Yes ] NoSelect [ Yes ] and press
Enter to continue with adding a user.Select UserSelect User with the arrow keys
and press Enter.Add User InformationThe following descriptions will appear in the lower part of
the screen as the items are selected with Tab
to assist with entering the required information:Login IDThe login name of the new user (mandatory).UIDThe numerical ID for this user (leave blank for
automatic choice).GroupThe login group name for this user (leave blank for
automatic choice).PasswordThe password for this user (enter this field with
care!).Full nameThe user's full name (comment).Member groupsThe groups this user belongs to (i.e. gets access
rights for).Home directoryThe user's home directory (leave blank for
default).Login shellThe user's login shell (leave blank for
default, e.g. /bin/sh).The login shell was changed from /bin/sh to
/usr/local/bin/bash to use the
bash shell that was previously installed as
a package. Do not try to use a shell that does not exist or you will
not be able to login.The user was also added to the wheel group
to be able to become a superuser with root
privileges.When you are satisfied, press &gui.ok; and
the User and Group Management menu will redisplay:Exit User and Group ManagementGroups could also be added at this time if specific needs
are known. Otherwise, this may be accessed through using
/stand/sysinstall after installation is
completed.When you are finished adding users, select
Exit with the arrow keys and press
Enter to continue the installation.Set root Password Message
Now you must set the system manager's password.
This is the password you'll use to log in as "root".
[ OK ]
[ Press enter to continue ]Press Enter to set the root
password.The password will need to be typed in twice correctly. Needless to
say, make sure you have a way of finding the password if you
forget.Changing local password for root.
New password :
Retype new password :The installation will continue after the password is
successfully entered.Exiting InstallIf you need to configure additional network devices or to
do any other configurations, you can do it at this point or
after installation with /stand/sysinstall. User Confirmation Requested
Visit the general configuration menu for a chance to set any last
options?
Yes [ No ]Select [ No ] with the arrow keys
and press Enter to return to the Main
Installation Menu.Exit InstallSelect [X Exit Install] with the arrow
keys and press Enter. You will be asked to
confirm exiting the installation: User Confirmation Requested
Are you sure you wish to exit? The system will reboot (be sure to
remove any floppies from the drives).
[ Yes ] NoSelect [ Yes ] and remove the floppy if
booting from the floppy. The CDROM drive is locked until the machine
starts to reboot. The CDROM drive is then unlocked and the disk can
be removed from drive (quickly).The system will reboot so watch for any error messages that
may appear.FreeBSD BootupFreeBSD Bootup on the i386If everything went well, you will see messages scroll
off the screen and you will arrive at a login prompt. You can view
the content of the messages by pressing Scroll-Lock
and using PgUp and PgDn.
Pressing Scroll-Lock again will return
to the prompt.The entire message may not display (buffer limitation) but
it can be viewed from the command line after logging in by typing
dmesg at the prompt.Login using the username/password you set during installation
(rpratt, in this example). Avoid logging in as
root except when necessary.Typical boot messages (version information omitted):Copyright (c) 1992-2002 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
Timecounter "i8254" frequency 1193182 Hz
CPU: AMD-K6(tm) 3D processor (300.68-MHz 586-class CPU)
Origin = "AuthenticAMD" Id = 0x580 Stepping = 0
Features=0x8001bf<FPU,VME,DE,PSE,TSC,MSR,MCE,CX8,MMX>
AMD Features=0x80000800<SYSCALL,3DNow!>
real memory = 268435456 (262144K bytes)
config> di sn0
config> di lnc0
config> di le0
config> di ie0
config> di fe0
config> di cs0
config> di bt0
config> di aic0
config> di aha0
config> di adv0
config> q
avail memory = 256311296 (250304K bytes)
Preloaded elf kernel "kernel" at 0xc0491000.
Preloaded userconfig_script "/boot/kernel.conf" at 0xc049109c.
md0: Malloc disk
Using $PIR table, 4 entries at 0xc00fde60
npx0: <math processor> on motherboard
npx0: INT 16 interface
pcib0: <Host to PCI bridge> on motherboard
pci0: <PCI bus> on pcib0
pcib1: <VIA 82C598MVP (Apollo MVP3) PCI-PCI (AGP) bridge> at device 1.0 on pci0
pci1: <PCI bus> on pcib1
pci1: <Matrox MGA G200 AGP graphics accelerator> at 0.0 irq 11
isab0: <VIA 82C586 PCI-ISA bridge> at device 7.0 on pci0
isa0: <ISA bus> on isab0
atapci0: <VIA 82C586 ATA33 controller> port 0xe000-0xe00f at device 7.1 on pci0
ata0: at 0x1f0 irq 14 on atapci0
ata1: at 0x170 irq 15 on atapci0
uhci0: <VIA 83C572 USB controller> port 0xe400-0xe41f irq 10 at device 7.2 on pci0
usb0: <VIA 83C572 USB controller> on uhci0
usb0: USB revision 1.0
uhub0: VIA UHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub0: 2 ports with 2 removable, self powered
chip1: <VIA 82C586B ACPI interface> at device 7.3 on pci0
ed0: <NE2000 PCI Ethernet (RealTek 8029)> port 0xe800-0xe81f irq 9 at
device 10.0 on pci0
ed0: address 52:54:05:de:73:1b, type NE2000 (16 bit)
isa0: too many dependant configs (8)
isa0: unexpected small tag 14
fdc0: <NEC 72065B or clone> at port 0x3f0-0x3f5,0x3f7 irq 6 drq 2 on isa0
fdc0: FIFO enabled, 8 bytes threshold
fd0: <1440-KB 3.5" drive> on fdc0 drive 0
atkbdc0: <keyboard controller (i8042)> at port 0x60-0x64 on isa0
atkbd0: <AT Keyboard> flags 0x1 irq 1 on atkbdc0
kbd0 at atkbd0
psm0: <PS/2 Mouse> irq 12 on atkbdc0
psm0: model Generic PS/2 mouse, device ID 0
vga0: <Generic ISA VGA> at port 0x3c0-0x3df iomem 0xa0000-0xbffff on isa0
sc0: <System console> at flags 0x1 on isa0
sc0: VGA <16 virtual consoles, flags=0x300>
sio0 at port 0x3f8-0x3ff irq 4 flags 0x10 on isa0
sio0: type 16550A
sio1 at port 0x2f8-0x2ff irq 3 on isa0
sio1: type 16550A
ppc0: <Parallel port> at port 0x378-0x37f irq 7 on isa0
ppc0: SMC-like chipset (ECP/EPP/PS2/NIBBLE) in COMPATIBLE mode
ppc0: FIFO with 16/16/15 bytes threshold
ppbus0: IEEE1284 device found /NIBBLE
Probing for PnP devices on ppbus0:
plip0: <PLIP network interface> on ppbus0
lpt0: <Printer> on ppbus0
lpt0: Interrupt-driven port
ppi0: <Parallel I/O> on ppbus0
ad0: 8063MB <IBM-DHEA-38451> [16383/16/63] at ata0-master using UDMA33
ad2: 8063MB <IBM-DHEA-38451> [16383/16/63] at ata1-master using UDMA33
acd0: CDROM <DELTA OTC-H101/ST3 F/W by OIPD> at ata0-slave using PIO4
Mounting root from ufs:/dev/ad0s1a
swapon: adding /dev/ad0s1b as swap device
Automatic boot in progress...
/dev/ad0s1a: FILESYSTEM CLEAN; SKIPPING CHECKS
/dev/ad0s1a: clean, 48752 free (552 frags, 6025 blocks, 0.9% fragmentation)
/dev/ad0s1f: FILESYSTEM CLEAN; SKIPPING CHECKS
/dev/ad0s1f: clean, 128997 free (21 frags, 16122 blocks, 0.0% fragmentation)
/dev/ad0s1g: FILESYSTEM CLEAN; SKIPPING CHECKS
/dev/ad0s1g: clean, 3036299 free (43175 frags, 374073 blocks, 1.3% fragmentation)
/dev/ad0s1e: filesystem CLEAN; SKIPPING CHECKS
/dev/ad0s1e: clean, 128193 free (17 frags, 16022 blocks, 0.0% fragmentation)
Doing initial network setup: hostname.
ed0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255
inet6 fe80::5054::5ff::fede:731b%ed0 prefixlen 64 tentative scopeid 0x1
ether 52:54:05:de:73:1b
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x8
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
Additional routing options: IP gateway=YES TCP keepalive=YES
routing daemons:.
additional daemons: syslogd.
Doing additional network setup:.
Starting final network daemons: creating ssh RSA host key
Generating public/private rsa1 key pair.
Your identification has been saved in /etc/ssh/ssh_host_key.
Your public key has been saved in /etc/ssh/ssh_host_key.pub.
The key fingerprint is:
cd:76:89:16:69:0e:d0:6e:f8:66:d0:07:26:3c:7e:2d root@k6-2.example.com
creating ssh DSA host key
Generating public/private dsa key pair.
Your identification has been saved in /etc/ssh/ssh_host_dsa_key.
Your public key has been saved in /etc/ssh/ssh_host_dsa_key.pub.
The key fingerprint is:
f9:a1:a9:47:c4:ad:f9:8d:52:b8:b8:ff:8c:ad:2d:e6 root@k6-2.example.com.
setting ELF ldconfig path: /usr/lib /usr/lib/compat /usr/X11R6/lib
/usr/local/lib
a.out ldconfig path: /usr/lib/aout /usr/lib/compat/aout /usr/X11R6/lib/aout
starting standard daemons: inetd cron sshd usbd sendmail.
Initial rc.i386 initialization:.
rc.i386 configuring syscons: blank_time screensaver moused.
Additional ABI support: linux.
Local package initilization:.
Additional TCP options:.
FreeBSD/i386 (k6-2.example.com) (ttyv0)
login: rpratt
Password:Generating the RSA and DSA keys may take some time on slower
machines. This happens only on the initial boot-up of a new
installation. Subsequent boots will be faster.If the X server has been configured and a Default Desktop
chosen, it can be started by typing startx at
the command line.Bootup of FreeBSD on the AlphaAlphaOnce the install procedure has finished, you will be
able to start FreeBSD by typing something like this to the
SRM prompt:>>>BOOT DKC0This instructs the firmware to boot the specified
disk. To make FreeBSD boot automatically in the future, use
these commands:>>>SET BOOT_OSFLAGS A>>>SET BOOT_FILE ''>>>SET BOOTDEF_DEV DKC0>>>SET AUTO_ACTION BOOTThe boot messages will be similar (but not identical) to
those produced by FreeBSD booting on the i386.FreeBSD ShutdownIt is important to properly shutdown the operating
system. Do not just turn off power. First, become a superuser by
typing su at the command line and entering the
root password. This will work only if the user
is a member of the wheel group.
Otherwise, login as root and use
shutdown -h now.The operating system has halted.
Please press any key to reboot.It is safe to turn off the power after the shutdown command
has been issued and the message Please press any key to reboot
appears. If any key is pressed instead of turning off the power
switch, the system will reboot.You could also use the
CtrlAltDel
key combination to reboot the system, however this is not recommended
during normal operation.Supported HardwarehardwareFreeBSD currently runs on a wide variety of ISA, VLB, EISA, and PCI
bus-based PCs with Intel, AMD, Cyrix, or NexGen x86
processors, as well as a number of machines based on the Compaq Alpha
processor. Support for generic IDE or ESDI drive configurations,
various SCSI controllers, PCMCIA cards, USB devices, and network and
serial cards is also provided. FreeBSD also supports IBM's microchannel
(MCA) bus.A list of supported hardware is provided with each FreeBSD release
in the FreeBSD Hardware Notes. This document can usually be found in a
file named HARDWARE.TXT, in the top-level directory
of a CDROM or FTP distribution or in
sysinstall's documentation menu. It lists,
for a given architecture, what hardware devices are known to be
supported by each release of FreeBSD. Copies of the supported
hardware list for various releases and architectures can also be
found on the Release
Information page of the FreeBSD Web site.TroubleshootinginstallationtroubleshootingThe following section covers basic installation troubleshooting,
such as common problems people have reported. There are also a few
questions and answers for people wishing to dual-boot FreeBSD with
MS-DOS.What to Do If Something Goes WrongDue to various limitations of the PC architecture, it is
impossible for probing to be 100% reliable, however, there are a
few things you can do if it fails.Check the Hardware Notes document for your version of
FreeBSD to make sure your hardware is
supported.If your hardware is supported and you still experience
lock-ups or other problems, reset your computer, and when the
visual kernel configuration option is given, choose it. This will
allow you to go through your hardware and supply information to the
system about it. The kernel on the boot disks is configured
assuming that most hardware devices are in their factory default
configuration in terms of IRQs, IO addresses, and DMA channels. If
your hardware has been reconfigured, you will most likely need to
use the configuration editor to tell FreeBSD where to find
things.It is also possible that a probe for a device not present will
cause a later probe for another device that is present to fail. In
that case, the probes for the conflicting driver(s) should be
disabled.Some installation problems can be avoided or alleviated
by updating the firmware on various hardware components, most notably
the motherboard. The motherboard firmware may also be referred to
as BIOS and most of the motherboard or computer
manufactures have a website where the upgrades and upgrade information
may be located.Most manufacturers strongly advise against upgrading the motherboard
BIOS unless there is a good reason for doing so, which
could possibly be a critical update of sorts. The upgrade process
can go wrong, causing permanent damage to the
BIOS chip.Do not disable any drivers you will need during the
installation, such as your screen (sc0).
If the installation wedges or fails mysteriously after leaving
the configuration editor, you have probably removed or changed
something you should not have. Reboot and try again.In configuration mode, you can:List the device drivers installed in the kernel.Disable device drivers for hardware that is not present in
your system.Change IRQs, DRQs, and IO port addresses used by a device
driver.After adjusting the kernel to match your hardware
configuration, type Q to boot with the new
settings. Once the installation has completed, any changes you
made in the configuration mode will be permanent so you do not have
to reconfigure every time you boot. It is still highly likely that
you will eventually want to build a custom kernel.MS-DOS User's Questions and AnswersDOSMany users wish to install FreeBSD on PCs inhabited by MS-DOS.
Here are some commonly asked questions about installing FreeBSD on
such systems:Help, I have no space! Do I need to delete everything
first?If your machine is already running MS-DOS and has little
or no free space available for the FreeBSD installation, all
hope is not lost! You may find the FIPS
utility, provided
in the tools directory on the FreeBSD
CDROM or various FreeBSD FTP sites to be quite
useful.FIPSFIPS allows you to split an
existing MS-DOS partition into two pieces, preserving the
original partition and allowing you to install onto the second
free piece. You first defragment your MS-DOS partition using
the Windows DEFRAG utility (go into
Explorer, right-click on the hard drive, and choose to defrag
your hard drive), or Norton Disk Tools. You then must run
FIPS. It will prompt you for the
rest of the information it needs. Afterwards, you can reboot
and install FreeBSD on the new free slice. See the
Distributions menu for an estimate of how
much free space you will need for the kind of installation you
want.Partition MagicThere is also a very useful product
from PowerQuest
called Partition Magic. This
application has far more functionality than
FIPS, and is highly recommended if
you plan to often add/remove operating systems (like me).
However, it does cost money, and if you plan to install FreeBSD
once and then leave it there, FIPS
will probably be fine for you.Can I use compressed MS-DOS filesystems from
FreeBSD?No. If you are using a utility such as
Stacker or
DoubleSpace, FreeBSD
will only be able to use whatever portion of the filesystem
you leave uncompressed. The rest of the filesystem will
show up as one large file (the stacked/double spaced file!).
Do not remove that file or you will probably regret
it greatly!It is probably better to create another uncompressed
primary MS-DOS partition and use this for communications
between MS-DOS and FreeBSD.Can I mount my extended MS-DOS partition?partitionsslicesYes. DOS extended partitions are mapped in at the end
of the other slices in FreeBSD, e.g., your
D: drive might be
/dev/da0s5, your
E: drive,
/dev/da0s6, and so on. This example
assumes, of course, that your extended partition is on SCSI
drive 0. For IDE drives, substitute ad
for da appropriately if installing
4.0-RELEASE or later, and substitute
wd for da if you
are installing a version of FreeBSD prior to 4.0. You otherwise
mount extended partitions exactly like you would any other
DOS drive, for example:&prompt.root; mount -t msdos /dev/ad0s5 /dos_dAlpha User's Questions and AnswersAlphaThis section answers some commonly asked questions about
installing FreeBSD on Alpha systems.Can I boot from the ARC or Alpha BIOS Console?ARCAlpha BIOSSRMNo. &os;, like Compaq Tru64 and VMS, will only boot
from the SRM console.Help, I have no space! Do I need to delete
everything first?Unfortunately, yes.Can I mount my Compaq Tru64 or VMS filesystems?No, not at this time.ValentinoVaschettoContributed by Advanced Installation GuideThis section describes how to install FreeBSD in exceptional
cases.Installing FreeBSD on a System without a Monitor or
Keyboardinstallationheadless (serial console)serial consoleThis type of installation is called a headless
install, because the machine that you are trying to install
FreeBSD on either does not have a monitor attached to it, or does not
even have a VGA output. How is this possible you ask? Using a
serial console. A serial console is basically using another
machine to act as the main display and keyboard for a
system. To do this, just follow these steps:Fetch the Right Boot Floppy ImagesFirst you will need to get the right disk images so
that you can boot into the install program. The secret
with using a serial console is that you tell the boot
loader to send I/O through a serial port instead of
displaying console output to the VGA device and trying to
read input from a local keyboard. Enough of that now,
let's get back to getting these disk images.You will need to get
kern.flp
and
mfsroot.flp
from the
floppies directory.Write the Image Files to the Floppy DisksThe image files, such as kern.flp, are
not regular files that you copy to the disk.
Instead, they are images of the complete contents of the
disk.This means that you can not use
commands like DOS' copy to write the
files. Instead, you must use specific tools to write the
images directly to the disk.fdimageIf you are creating the floppies on a computer running
DOS then we provide a tool to do this called
fdimage.If you are using the floppies from the CDROM, and
your CDROM is the E: drive then
you would run this:E:\>tools\fdimage floppies\kern.flp A:Repeat this command for each .flp
file, replacing the floppy disk each time. Adjust the
command line as necessary, depending on where you have
placed the .flp files. If you do not
have the CDROM then fdimage can be
downloaded from the tools
directory on the FreeBSD FTP site.If you are writing the floppies on a Unix system (such
as another FreeBSD system) you can use the &man.dd.1;
command to write the image files directly to disk. On
FreeBSD you would run:&prompt.root; dd if=kern.flp of=/dev/fd0On FreeBSD /dev/fd0 refers to
the first floppy disk (the A:
drive). /dev/fd1 would be the
B: drive, and so on. Other Unix
variants might have different names for the floppy disk
devices, and you will need to check the documentation for
the system as necessary.Enabling the Boot Floppies to Boot into a Serial
ConsoleDo not try to mount the floppy if it is write-protected.mountIf you were to boot into the floppies that you just
made, FreeBSD would boot into its normal install mode. We
want FreeBSD to boot into a serial console for our
install. To do this, you have to mount the
kern.flp floppy onto your FreeBSD
system using the &man.mount.8; command.&prompt.root; mount /dev/fd0 /mntNow that you have the floppy mounted, you must
change into the floppy directory:&prompt.root; cd /mntHere is where you must set the floppy to boot into a
serial console. You have to make a file called
boot.config containing
/boot/loader -h. All this does is pass a flag to the bootloader to
boot into a serial console.&prompt.root; echo "/boot/loader -h" > boot.configNow that you have your floppy configured correctly,
you must unmount the floppy using the &man.umount.8;
command:&prompt.root; cd /
&prompt.root; umount /mntNow you can remove the floppy from the floppy
drive.Connecting Your Null Modem Cablenull modem cableYou now need to connect a null modem cable between
the two machines. Just connect the cable to the serial
ports of the 2 machines. A normal serial cable
will not work here, you need a null modem
cable because it has some of the wires inside crossed
over.Booting Up for the InstallIt is now time to go ahead and start the install. Put
the kern.flp floppy in the floppy
drive of the machine you are doing the headless install
on, and power on the machine.Connecting to Your Headless MachinecuNow you have to connect to that machine with
&man.cu.1;:&prompt.root; cu -l /dev/cuaa0That's it! You should be able to control the headless machine
through your cu session now. It will ask you to
put in the mfsroot.flp, and then it will come up
with a selection of what kind of terminal to use. Just select the
FreeBSD color console and proceed with your install!Preparing Your Own Installation MediaTo prevent repetition, FreeBSD disk in this context
means a FreeBSD CDROM or DVD that you have purchased, or produced
yourself.There may be some situations in which you need to create your own
FreeBSD installation media and/or source. This might be physical media,
such as a tape, or a source that Sysinstall
can use to retrieve the files, such as a local FTP site, or an MS-DOS
partition. For example:You have many machines connected to your local network, and one
FreeBSD disk. You want to create a local FTP site using the
contents of the FreeBSD disk, and then have your machines use this
local FTP site instead of needing to connect to the Internet.You have a FreeBSD disk, FreeBSD does not recognize your CD/DVD
drive, but DOS/Windows does. You want to copy the FreeBSD
installations files to a DOS partition on the same computer, and
then install FreeBSD using those files.The computer you want to install on does not have a CD/DVD
drive, or a network card, but you can connect a
Laplink-style serial or parallel cable to a computer
that does.You want to create a tape that can be used to install
FreeBSD.Creating an installation CDROMAs part of each release, the FreeBSD project makes available five
CDROM images (ISO images). These images can be written
(burned) to CDs if you have a CD writer, and then used
to install FreeBSD. If you have a CD writer, and bandwidth is cheap,
then this is the easiest way to install FreeBSD.Download the correct ISO imagesThe ISO images for each release can be downloaded from ftp://ftp.FreeBSD.org/pub/FreeBSD/ISO-IMAGES-arch/version or the closest mirror.
Substitute arch and
version as appropriate.That directory will normally contain the following images:
FreeBSD ISO image names and meaningsFilenameContainsversion-mini.isoEverything you need to install FreeBSD.version-disc1.isoEverything you need to install FreeBSD, and as many
additional third party packages as would fit on the
disc.version-disc2.isoA live filesystem, which is used in
conjunction with the Repair facility in
Sysinstall. A copy of the
FreeBSD CVS tree. As many additional third party packages
as would fit on the disc.version-disc3.isoAs many additional third party packages as would fit
on the disc.version-disc4.isoAs many additional third party packages as would fit
on the disc.
The mini ISO was only produced for FreeBSD 4.4 and
subsequent releases. The images for discs two, three, and four
were only produced for FreeBSD 4.5 and subsequent
releases.You must download one of either the mini
ISO image, or the image of disc one. Do not download both of them,
since the disc one image contains everything that the mini ISO
image contains.Use the mini ISO if Internet access is cheap for you. It will
let you install FreeBSD, and you can then install third party
packages by downloading them using the ports/packages system (see
) as
necessary.Use the image of disc one if you want a reasonable selection
of third party packages on the disc as well.The additional disc images are useful, but not essential,
especially if you have high-speed access to the Internet.Write the CDsYou must then write the CD images to disc. If you will be
doing this on another FreeBSD system then see
for more information (in
particular, and
).If you will be doing this on another platform then you will
need to use whatever utilities exist to control your CD writer on
that platform.Creating a Local FTP Site with a FreeBSD DiskinstallationnetworkFTPFreeBSD disks are laid out in the same way as the FTP site. This
makes it very easy for you to create a local FTP site that can be used
by other machines on your network when installing FreeBSD.On the FreeBSD computer that will host the FTP site, ensure
that the CDROM is in the drive, and mounted on
/cdrom.&prompt.root; mount /cdromCreate an account for anonymous FTP in
/etc/passwd. Do this by editing
/etc/passwd using &man.vipw.8; and adding
this line.ftp:*:99:99::0:0:FTP:/cdrom:/nonexistentEnsure that the FTP service is enabled in
/etc/inetd.conf.Anyone with network connectivity to your machine can now
chose a media type of FTP and type in
ftp://your machine
after picking Other in the FTP sites menu during
the install.This approach is OK for a machine that is on your local network,
and that is protected by your firewall. Offering up FTP services to
other machines over the Internet (and not your local network)
exposes your computer to the attention of crackers and other
undesirables. We strongly recommend that you follow good security
practices if you do this.Creating Installation FloppiesinstallationfloppiesIf you must install from floppy disk (which we suggest you
do not do), either due to unsupported
hardware or simply because you insist on doing things the hard
way, you must first prepare some floppies for the installation.At a minimum, you will need as many 1.44 MB or 1.2 MB floppies
as it takes to hold all the files in the
bin (binary distribution) directory. If
you are preparing the floppies from DOS, then they
MUST be formatted using the MS-DOS
FORMAT command. If you are using Windows,
use Explorer to format the disks (right-click on the
A: drive, and select Format.Do not trust factory pre-formatted
floppies. Format them again yourself, just to be sure. Many
problems reported by our users in the past have resulted from
the use of improperly formatted media, which is why we are
making a point of it now.If you are creating the floppies on another FreeBSD machine,
a format is still not a bad idea, though you do not need to put
a DOS filesystem on each floppy. You can use the
disklabel and newfs
commands to put a UFS filesystem on them instead, as the
following sequence of commands (for a 3.5" 1.44 MB floppy)
illustrates:&prompt.root; fdformat -f 1440 fd0.1440
&prompt.root; disklabel -w -r fd0.1440 floppy3
&prompt.root; newfs -t 2 -u 18 -l 1 -i 65536 /dev/fd0Use fd0.1200 and
floppy5 for 5.25" 1.2 MB disks.Then you can mount and write to them like any other
filesystem.After you have formatted the floppies, you will need to copy
the files to them. The distribution files are split into chunks
conveniently sized so that 5 of them will fit on a conventional
1.44 MB floppy. Go through all your floppies, packing as many
files as will fit on each one, until you have all of the
distributions you want packed up in this fashion. Each
distribution should go into a subdirectory on the floppy, e.g.:
a:\bin\bin.aa,
a:\bin\bin.ab, and so on.Once you come to the Media screen during the install
process, select Floppy and you will be prompted
for the rest.Installing from an MS-DOS Partitioninstallationfrom MS-DOSTo prepare for an installation from an MS-DOS partition,
copy the files from the distribution into a directory
called freebsd in the root directory of the
partition. For example, c:\freebsd. The
directory structure of the CDROM or FTP site must be partially
reproduced within this directory, so we suggest using the DOS
xcopy command if you are copying it from a CD.
For example, to prepare for a minimal installation of
FreeBSD:C:\>md c:\freebsdC:\>xcopy e:\bin c:\freebsd\bin\ /sC:\>xcopy e:\manpages c:\freebsd\manpages\ /sAssuming that C: is where you have
free space and E: is where your CDROM
is mounted.If you do not have a CDROM drive, you can download the
distribution from ftp.FreeBSD.org.
Each distribution is in its own directory; for example, the
bin distribution can be found in the &rel.current;/bin/
directory.For as many distributions you wish to install from an MS-DOS
partition (and you have the free space for), install each one
under c:\freebsd — the
BIN distribution is the only one required for
a minimum installation.Creating an Installation Tapeinstallationfrom QIC/SCSI TapeInstalling from tape is probably the easiest method, short
of an online FTP install or CDROM install. The installation
program expects the files to be simply tarred onto the tape.
After getting all of the distribution files you are interested
in, simply tar them onto the tape:&prompt.root; cd /freebsd/distdir
&prompt.root; tar cvf /dev/rwt0 dist1 ... dist2When you go to do the installation, you should also make
sure that you leave enough room in some temporary directory
(which you will be allowed to choose) to accommodate the
full contents of the tape you have created.
Due to the non-random access nature of tapes, this method of
installation requires quite a bit of temporary storage. You
should expect to require as much temporary storage as you have
stuff written on tape.When starting the installation, the tape must be in the
drive before booting from the boot
floppy. The installation probe may otherwise fail to find
it.Before Installing over a Networkinstallationnetworkserial (SLIP or PPP)installationnetworkparallel (PLIP)installationnetworkEthernetThere are three types of network installations you can do.
Serial port (SLIP or PPP), Parallel port (PLIP (laplink cable)),
or Ethernet (a standard Ethernet controller (includes some
PCMCIA)).The SLIP support is rather primitive, and limited primarily
to hard-wired links, such as a serial cable running between a
laptop computer and another computer. The link should be
hard-wired as the SLIP installation does not currently offer a
dialing capability; that facility is provided with the PPP
utility, which should be used in preference to SLIP whenever
possible.If you are using a modem, then PPP is almost certainly
your only choice. Make sure that you have your service
provider's information handy as you will need to know it fairly
early in the installation process.If you use PAP or CHAP to connect your ISP (in other words, if
you can connect to the ISP in Windows without using a script), then
all you will need to do is type in dial at the
ppp prompt. Otherwise, you will need to
know how to dial your ISP using the AT commands
specific to your modem, as the PPP dialer provides only a very
simple terminal emulator. Please refer to the user-ppp handbook and FAQ entries for further information.
If you have problems, logging can be directed to the screen using
the command set log local ....If a hard-wired connection to another FreeBSD (2.0-R or
later) machine is available, you might also consider installing
over a laplink parallel port cable. The data rate
over the parallel port is much higher than what is typically
possible over a serial line (up to 50 kbytes/sec), thus resulting
in a quicker installation.Finally, for the fastest possible network installation, an
Ethernet adapter is always a good choice! FreeBSD supports most
common PC Ethernet cards; a table of supported cards (and their
required settings) is provided in the Hardware Notes for each
release of FreeBSD. If you are using one of the supported PCMCIA
Ethernet cards, also be sure that it is plugged in
before the laptop is powered on! FreeBSD does
not, unfortunately, currently support hot insertion of PCMCIA cards
during installation.You will also need to know your IP address on the network,
the netmask value for your address class, and the name of your
machine. If you are installing over a PPP connection and do not
have a static IP, fear not, the IP address can be dynamically
assigned by your ISP. Your system administrator can tell you
which values to use for your particular network setup. If you
will be referring to other hosts by name rather than IP address,
you will also need a name server and possibly the address of a
gateway (if you are using PPP, it is your provider's IP address)
to use in talking to it. If you want to install by FTP via a
HTTP proxy (see below), you will also need the proxy's address.
If you do not know the answers to all or most of these questions,
then you should really probably talk to your system administrator
or ISP before trying this type of
installation.Before Installing via NFSinstallationnetworkNFSThe NFS installation is fairly straight-forward. Simply
copy the FreeBSD distribution files you want onto a server
somewhere and then point the NFS media selection at it.If this server supports only privileged port
(as is generally the default for Sun workstations), you will
need to set this option in the Options menu before
installation can proceed.If you have a poor quality Ethernet card which suffers
from very slow transfer rates, you may also wish to toggle the
appropriate Options flag.In order for NFS installation to work, the server must
support subdir mounts, e.g., if your FreeBSD 3.4 distribution
directory lives on:
ziggy:/usr/archive/stuff/FreeBSD, then
ziggy will have to allow the direct mounting
of /usr/archive/stuff/FreeBSD, not just
/usr or
/usr/archive/stuff.In FreeBSD's /etc/exports file, this
is controlled by the . Other NFS
servers may have different conventions. If you are getting
permission denied messages from the server, then
it is likely that you do not have this enabled
properly.
diff --git a/share/mk/doc.docbook.mk b/share/mk/doc.docbook.mk
index 027ef98614..a85bf9674f 100644
--- a/share/mk/doc.docbook.mk
+++ b/share/mk/doc.docbook.mk
@@ -1,804 +1,804 @@
#
# $FreeBSD$
#
# This include file handles building and installing of
# DocBook documentation in the FreeBSD Documentation Project.
#
# Documentation using DOCFORMAT=docbook is expected to be marked up
# according to the DocBook DTD
#
# ------------------------------------------------------------------------
#
# Document-specific variables
#
# DOC This should be set to the name of the DocBook
# marked-up file, without the .sgml or .docb suffix.
#
# It also determins the name of the output files -
# ${DOC}.html.
#
# DOCBOOKSUFFIX The suffix of your document, defaulting to .sgml
#
# SRCS The names of all the files that are needed to
# build this document - This is useful if any of
# them need to be generated. Changing any file in
# SRCS causes the documents to be rebuilt.
#
# HAS_INDEX This document has index terms and so an index
# can be created if specified with GEN_INDEX.
#
# ------------------------------------------------------------------------
#
# Variables used by both users and documents:
#
# SGMLFLAGS Additional options to pass to various SGML
# processors (e.g., jade, nsgmls). Typically
# used to define "IGNORE" entities to "INCLUDE"
# with "-i"
#
# JADEFLAGS Additional options to pass to Jade. Typically
# used to set additional variables, such as
# "%generate-article-toc%".
#
# TIDYFLAGS Additional flags to pass to Tidy. Typically
# used to set "-raw" flag to handle 8bit characters.
#
# EXTRA_CATALOGS Additional catalog files that should be used by
# any SGML processing applications.
#
# NO_TIDY If you do not want to use tidy, set this to "YES".
#
# GEN_INDEX If this document has an index (HAS_INDEX) and this
# variable is defined, then index.sgml will be added
# to the list of dependencies for source files, and
# collateindex.pl will be run to generate index.sgml.
#
# CSS_SHEET Full path to a CSS stylesheet suitable for DocBook.
# Default is ${DOC_PREFIX}/share/misc/docbook.css
#
# Print-output options :
#
# NICE_HEADERS If defined, customized chapter headers will be created
# that you may find more aesthetically pleasing. Note
# that this option only effects print output formats for
# Enlish language books.
#
# MIN_SECT_LABELS If defined, do not display the section number for 4th
# and 5th level section titles. This would change
# "N.N.N.N Section title" into "Section Title" while
# higher level sections are still printed with numbers.
#
# TRACE={1,2} Trace TeX's memory usage. Set this to 1 for minimal
# tracing or 2 for maximum tracing. TeX memory
# statistics will be written out to .log.
# For more information see the TeXbook, p301.
#
# TWO_SIDE If defined, two sided output will be created. This
# means that new chapters will only start on odd
# numbered (aka right side, aka recto) pages and the
# headers and footers will be aligned appropriately
# for double sided paper. Blank pages may be added as
# needed.
#
# JUSTIFY If defined, text will be right justified so that the
# right edge is smooth. Words may be hyphenated using
# the defalt TeX hyphenation rules for this purpose.
#
# BOOK_OUTPUT A collection of options are set suitable for printing
# a book. This option may be an order of magnitude more
# CPU intensive than the default build.
#
# RLE Use Run-Length Encoding for EPS files, this will
# result in signficiantly smaller PostScript files,
# but may take longer for a printer to process.
#
# Documents should use the += format to access these.
#
DOCBOOKSUFFIX?= sgml
MASTERDOC?= ${.CURDIR}/${DOC}.${DOCBOOKSUFFIX}
# Which stylesheet type to use. 'dsssl' or 'xsl'
STYLESHEET_TYPE?= dsssl
.if ${MACHINE_ARCH} != "i386"
OPENJADE= yes
.endif
.if defined(OPENJADE)
JADE?= ${PREFIX}/bin/openjade
JADECATALOG?= ${PREFIX}/share/sgml/openjade/catalog
NSGMLS?= ${PREFIX}/bin/onsgmls
JADEFLAGS+= -V openjade
SX?= ${PREFIX}/bin/osx
.else
JADE?= ${PREFIX}/bin/jade
JADECATALOG?= ${PREFIX}/share/sgml/jade/catalog
NSGMLS?= ${PREFIX}/bin/nsgmls
SX?= ${PREFIX}/bin/sx
.endif
DSLHTML?= ${DOC_PREFIX}/share/sgml/default.dsl
DSLPRINT?= ${DOC_PREFIX}/share/sgml/default.dsl
DSLPGP?= ${DOC_PREFIX}/share/sgml/pgp.dsl
FREEBSDCATALOG= ${DOC_PREFIX}/share/sgml/catalog
LANGUAGECATALOG=${DOC_PREFIX}/${LANGCODE}/share/sgml/catalog
ISO8879CATALOG= ${PREFIX}/share/sgml/iso8879/catalog
.if ${STYLESHEET_TYPE} == "dsssl"
DOCBOOKCATALOG= ${PREFIX}/share/sgml/docbook/catalog
.elif ${STYLESHEET_TYPE} == "xsl"
DOCBOOKCATALOG= ${PREFIX}/share/xml/docbook/catalog
.endif
DSSSLCATALOG= ${PREFIX}/share/sgml/docbook/dsssl/modular/catalog
COLLATEINDEX= ${PREFIX}/share/sgml/docbook/dsssl/modular/bin/collateindex.pl
XSLTPROC?= ${PREFIX}/bin/xsltproc
XSLHTML?= ${DOC_PREFIX}/share/xsl/freebsd-html.xsl
XSLHTMLCHUNK?= ${DOC_PREFIX}/share/xsl/freebsd-html-chunk.xsl
XSLFO?= ${DOC_PREFIX}/share/xsl/freebsd-fo.xsl
IMAGES_LIB?=
CATALOGS= -c ${LANGUAGECATALOG} -c ${FREEBSDCATALOG} \
-c ${DSSSLCATALOG} -c ${ISO8879CATALOG} \
-c ${DOCBOOKCATALOG} -c ${JADECATALOG} \
${EXTRA_CATALOGS:S/^/-c /g}
SGMLFLAGS+= -D ${CANONICALOBJDIR}
JADEOPTS= ${JADEFLAGS} ${SGMLFLAGS} ${CATALOGS}
KNOWN_FORMATS= html html.tar html-split html-split.tar \
txt rtf ps pdf tex dvi tar pdb
CSS_SHEET?= ${DOC_PREFIX}/share/misc/docbook.css
PDFTEX_DEF?= ${DOC_PREFIX}/share/web2c/pdftex.def
HTMLOPTS?= -ioutput.html -d ${DSLHTML} ${HTMLFLAGS}
PRINTOPTS?= -ioutput.print -d ${DSLPRINT} ${PRINTFLAGS}
.if defined(BOOK_OUTPUT)
NICE_HEADERS=1
MIN_SECT_LABELS=1
TWO_SIDE=1
JUSTIFY=1
#WITH_FOOTNOTES=1
#GEN_INDEX=1
.endif
.if defined(JUSTIFY)
TEXCMDS+= \RequirePackage{url}
PRINTOPTS+= -ioutput.print.justify
.endif
.if defined(TWO_SIDE)
PRINTOPTS+= -V %two-side% -ioutput.print.twoside
TEXCMDS+= \def\PageTwoSide{1}
.endif
.if defined(NICE_HEADERS)
PRINTOPTS+= -ioutput.print.niceheaders
.endif
.if defined(MIN_SECT_LABELS)
PRINTOPTS+= -V minimal-section-labels
.endif
.if defined(TRACE)
TEXCMDS+= \tracingstats=${TRACE}
.endif
.if defined(RLE)
PNMTOPSFLAGS+= -rle
.endif
PERL?= /usr/bin/perl
PKG_CREATE?= /usr/sbin/pkg_create
SORT?= /usr/bin/sort
TAR?= /usr/bin/tar
TOUCH?= /usr/bin/touch
XARGS?= /usr/bin/xargs
TEX?= ${PREFIX}/bin/tex
LATEX?= ${PREFIX}/bin/latex
PDFTEX?= ${PREFIX}/bin/pdftex
GROFF?= groff
TIDY?= ${PREFIX}/bin/tidy
TIDYOPTS?= -i -m -raw -preserve -f /dev/null ${TIDYFLAGS}
HTML2TXT?= ${PREFIX}/bin/links
HTML2TXTOPTS?= -dump ${HTML2TXTFLAGS}
HTML2PDB?= ${PREFIX}/bin/iSiloBSD
HTML2PDBOPTS?= -y -d0 -Idef ${HTML2PDBFLAGS}
DVIPS?= ${PREFIX}/bin/dvips
.if defined(PAPERSIZE)
DVIPSOPTS?= -t ${PAPERSIZE:L} ${DVIPSFLAGS}
.endif
GZIP?= -9
GZIP_CMD?= gzip -qf ${GZIP}
BZIP2?= -9
BZIP2_CMD?= bzip2 -qf ${BZIP2}
ZIP?= -9
ZIP_CMD?= ${PREFIX}/bin/zip -j ${ZIP}
# ------------------------------------------------------------------------
#
# Look at ${FORMATS} and work out which documents need to be generated.
# It is assumed that the HTML transformation will always create a file
# called index.html, and that for every other transformation the name
# of the generated file is ${DOC}.format.
#
# ${_docs} will be set to a list of all documents that must be made
# up to date.
#
# ${CLEANFILES} is a list of files that should be removed by the "clean"
# target. ${COMPRESS_EXT:S/^/${DOC}.${_cf}.&/ takes the COMPRESS_EXT
# var, and prepends the filename to each listed extension, building a
# second list of files with the compressed extensions added.
#
# Note: ".for _curformat in ${KNOWN_FORMATS}" is used several times in
# this file. I know they could have been rolled together in to one, much
# larger, loop. However, that would have made things more complicated
# for a newcomer to this file to unravel and understand, and a syntax
# error in the loop would have affected the entire
# build/compress/install process, instead of just one of them, making it
# more difficult to debug.
#
# Note: It is the aim of this file that *all* the targets be available,
# not just those appropriate to the current ${FORMATS} and
# ${INSTALL_COMPRESSED} values.
#
# For example, if FORMATS=html and INSTALL_COMPRESSED=gz you could still
# type
#
# make book.rtf.bz2
#
# and it will do the right thing. Or
#
# make install-rtf.bz2
#
# for that matter. But don't expect "make clean" to work if the FORMATS
# and INSTALL_COMPRESSED variables are wrong.
#
.if ${.OBJDIR} != ${.CURDIR}
LOCAL_CSS_SHEET= ${.OBJDIR}/${CSS_SHEET:T}
.else
LOCAL_CSS_SHEET= ${CSS_SHEET:T}
.endif
.for _curformat in ${FORMATS}
_cf=${_curformat}
.if ${_cf} == "html-split"
_docs+= index.html HTML.manifest ln*.html
CLEANFILES+= $$([ -f HTML.manifest ] && ${XARGS} < HTML.manifest) \
HTML.manifest ln*.html
CLEANFILES+= PLIST.${_curformat}
.else
_docs+= ${DOC}.${_curformat}
CLEANFILES+= ${DOC}.${_curformat}
CLEANFILES+= PLIST.${_curformat}
.if ${_cf} == "html-split.tar"
CLEANFILES+= $$([ -f HTML.manifest ] && ${XARGS} < HTML.manifest) \
HTML.manifest ln*.html
.elif ${_cf} == "html.tar"
CLEANFILES+= ${DOC}.html
.elif ${_cf} == "txt"
CLEANFILES+= ${DOC}.html-text
.elif ${_cf} == "dvi"
CLEANFILES+= ${DOC}.aux ${DOC}.log ${DOC}.tex
.elif ${_cf} == "tex"
CLEANFILES+= ${DOC}.aux ${DOC}.log
.elif ${_cf} == "ps"
CLEANFILES+= ${DOC}.aux ${DOC}.dvi ${DOC}.log ${DOC}.tex-ps
.elif ${_cf} == "pdf"
CLEANFILES+= ${DOC}.aux ${DOC}.dvi ${DOC}.log ${DOC}.out ${DOC}.tex-pdf
.elif ${_cf} == "pdb"
_docs+= ${.CURDIR:T}.pdb
CLEANFILES+= ${.CURDIR:T}.pdb
.endif
.endif
.if (${LOCAL_CSS_SHEET} != ${CSS_SHEET}) && \
(${_cf} == "html-split" || ${_cf} == "html-split.tar" || \
${_cf} == "html" || ${_cf} == "html.tar" || ${_cf} == "txt")
CLEANFILES+= ${LOCAL_CSS_SHEET}
.endif
.endfor
#
# Build a list of install-${format}.${compress_format} targets to be
# by "make install". Also, add ${DOC}.${format}.${compress_format} to
# ${_docs} and ${CLEANFILES} so they get built/cleaned by "all" and
# "clean".
#
.if defined(INSTALL_COMPRESSED) && !empty(INSTALL_COMPRESSED)
.for _curformat in ${FORMATS}
_cf=${_curformat}
.for _curcomp in ${INSTALL_COMPRESSED}
.if ${_cf} != "html-split" && ${_cf} != "html"
_curinst+= install-${_curformat}.${_curcomp}
_docs+= ${DOC}.${_curformat}.${_curcomp}
CLEANFILES+= ${DOC}.${_curformat}.${_curcomp}
.if ${_cf} == "pdb"
_docs+= ${.CURDIR:T}.${_curformat}.${_curcomp}
CLEANFILES+= ${.CURDIR:T}.${_curformat}.${_curcomp}
.endif
.endif
.endfor
.endfor
.endif
#
# Index generation
#
CLEANFILES+= ${INDEX_SGML}
.if defined(GEN_INDEX) && defined(HAS_INDEX)
JADEFLAGS+= -i chap.index
HTML_SPLIT_INDEX?= html-split.index
HTML_INDEX?= html.index
PRINT_INDEX?= print.index
INDEX_SGML?= index.sgml
CLEANFILES+= ${HTML_SPLIT_INDEX} ${HTML_INDEX} ${PRINT_INDEX}
.endif
.MAIN: all
all: ${_docs}
# XML --------------------------------------------------------------------
# sx generates a lot of (spurious) errors of the form "reference to
# internal SDATA entity ...". So dump the errors to separate file, and
# grep for any other errors to show them to the user.
#
# Better approaches to handling this would be most welcome
${DOC}.xml: ${SRCS}
echo '' > ${DOC}.xml
${SX} -xlower -xndata ${MASTERDOC} 2> .sxerr | tail -n +2 >> ${DOC}.xml
@-grep -v 'reference to internal SDATA entity' .sxerr
# HTML-SPLIT -------------------------------------------------------------
.if ${STYLESHEET_TYPE} == "dsssl"
index.html HTML.manifest: ${SRCS} ${LOCAL_IMAGES_LIB} ${LOCAL_IMAGES_PNG} \
${LOCAL_IMAGES_TXT} ${INDEX_SGML} ${HTML_SPLIT_INDEX} ${LOCAL_CSS_SHEET}
${JADE} -V html-manifest ${HTMLOPTS} -ioutput.html.images \
${JADEOPTS} -t sgml ${MASTERDOC}
.elif ${STYLESHEET_TYPE} == "xsl"
index.html: ${DOC}.xml ${LOCAL_IMAGES_LIB} ${LOCAL_IMAGES_PNG} \
${INDEX_SGML} ${HTML_SPLIT_INDEX} ${LOCAL_CSS_SHEET}
${XSLTPROC} --param freebsd.output.html.images "'1'" ${XSLHTMLCHUNK} \
${DOC}.xml
.endif
.if !defined(NO_TIDY)
-${TIDY} ${TIDYOPTS} $$(${XARGS} < HTML.manifest)
.endif
# HTML -------------------------------------------------------------------
.if ${STYLESHEET_TYPE} == "dsssl"
${DOC}.html: ${SRCS} ${LOCAL_IMAGES_LIB} ${LOCAL_IMAGES_PNG} \
${LOCAL_IMAGES_TXT} ${INDEX_SGML} ${HTML_INDEX} ${LOCAL_CSS_SHEET}
${JADE} -V nochunks ${HTMLOPTS} -ioutput.html.images \
${JADEOPTS} -t sgml ${MASTERDOC} > ${.TARGET} || \
(${RM} -f ${.TARGET} && false)
.elif ${STYLESHEET_TYPE} == "xsl"
${DOC}.html: ${DOC}.xml ${LOCAL_IMAGES_LIB} ${LOCAL_IMAGES_PNG} \
${INDEX_SGML} ${LOCAL_CSS_SHEET}
${XSLTPROC} --param freebsd.output.html.images "'1'" ${XSLHTML} \
${DOC}.xml > ${.TARGET}
.endif
.if !defined(NO_TIDY)
-${TIDY} ${TIDYOPTS} ${.TARGET}
.endif
# HTML-TEXT --------------------------------------------------------------
# Special target to produce HTML with no images in it.
.if ${STYLESHEET_TYPE} == "dsssl"
${DOC}.html-text: ${SRCS} ${INDEX_SGML} ${HTML_INDEX} ${LOCAL_IMAGES_TXT}
${JADE} -V nochunks ${HTMLOPTS} \
${JADEOPTS} -t sgml ${MASTERDOC} > ${.TARGET} || \
(${RM} -f ${.TARGET} && false)
.elif ${STYLESHEET_TYPE} == "xsl"
${DOC}.html-text: ${DOC}.xml ${INDEX_SGML} ${HTML_INDEX}
${XSLTPROC} --param freebsd.output.html.images "'0'" ${XSLHTML} \
${DOC}.xml > ${.TARGET}
.endif
${DOC}.html-split.tar: HTML.manifest ${LOCAL_IMAGES_LIB} \
${LOCAL_IMAGES_PNG} ${LOCAL_CSS_SHEET}
${TAR} cf ${.TARGET} $$(${XARGS} < HTML.manifest) \
${LOCAL_IMAGES_LIB} ${IMAGES_PNG} ${CSS_SHEET:T}
${DOC}.html.tar: ${DOC}.html ${LOCAL_IMAGES_LIB} \
${LOCAL_IMAGES_PNG} ${LOCAL_CSS_SHEET}
${TAR} cf ${.TARGET} ${DOC}.html \
${LOCAL_IMAGES_LIB} ${IMAGES_PNG} ${CSS_SHEET:T}
# TXT --------------------------------------------------------------------
${DOC}.txt: ${DOC}.html-text
${HTML2TXT} ${HTML2TXTOPTS} ${.ALLSRC} > ${.TARGET}
# PDB --------------------------------------------------------------------
${DOC}.pdb: ${DOC}.html ${LOCAL_IMAGES_LIB} ${LOCAL_IMAGES_PNG}
${HTML2PDB} ${HTML2PDBOPTS} ${DOC}.html ${.TARGET}
${.CURDIR:T}.pdb: ${DOC}.pdb
${LN} -f ${.ALLSRC} ${.TARGET}
.if defined(INSTALL_COMPRESSED) && !empty(INSTALL_COMPRESSED)
.for _curcomp in ${INSTALL_COMPRESSED}
${.CURDIR:T}.pdb.${_curcomp}: ${DOC}.pdb.${_curcomp}
${LN} -f ${.ALLSRC} ${.TARGET}
.endfor
.endif
# RTF --------------------------------------------------------------------
${DOC}.rtf: ${SRCS} ${LOCAL_IMAGES_EPS}
${JADE} -V rtf-backend ${PRINTOPTS} \
${JADEOPTS} -t rtf -o ${.TARGET} ${MASTERDOC}
#
# This sucks, but there's no way round it. The PS and PDF formats need
# to use different image formats, which are chosen at the .tex stage. So,
# we need to create a different .tex file depending on our eventual output
# format, which will then lead on to a different .dvi file as well.
#
${DOC}.tex: ${SRCS} ${LOCAL_IMAGES_EPS} ${INDEX_SGML} ${PRINT_INDEX}
${JADE} -V tex-backend ${PRINTOPTS} \
${JADEOPTS} -t tex -o ${.TARGET} ${MASTERDOC}
${DOC}.tex-ps: ${DOC}.tex
${LN} -f ${.ALLSRC} ${.TARGET}
${DOC}.tex-pdf: ${SRCS} ${IMAGES_PDF} ${INDEX_SGML} ${PRINT_INDEX}
${RM} -f ${.TARGET}
${CAT} ${PDFTEX_DEF} > ${.TARGET}
${JADE} -V tex-backend ${PRINTOPTS} -ioutput.print.pdf \
${JADEOPTS} -t tex -o /dev/stdout ${MASTERDOC} >> ${.TARGET}
${DOC}.dvi: ${DOC}.tex ${LOCAL_IMAGES_EPS}
@${ECHO} "==> TeX pass 1/3"
-${TEX} "&jadetex" '${TEXCMDS} \nonstopmode\input{${DOC}.tex}'
@${ECHO} "==> TeX pass 2/3"
-${TEX} "&jadetex" '${TEXCMDS} \nonstopmode\input{${DOC}.tex}'
@${ECHO} "==> TeX pass 3/3"
-${TEX} "&jadetex" '${TEXCMDS} \nonstopmode\input{${DOC}.tex}'
${DOC}.pdf: ${DOC}.tex-pdf ${IMAGES_PDF}
@${ECHO} "==> PDFTeX pass 1/3"
-${PDFTEX} "&pdfjadetex" '${TEXCMDS} \nonstopmode\input{${DOC}.tex-pdf}'
@${ECHO} "==> PDFTeX pass 2/3"
-${PDFTEX} "&pdfjadetex" '${TEXCMDS} \nonstopmode\input{${DOC}.tex-pdf}'
@${ECHO} "==> PDFTeX pass 3/3"
${PDFTEX} "&pdfjadetex" '${TEXCMDS} \nonstopmode\input{${DOC}.tex-pdf}'
${DOC}.ps: ${DOC}.dvi
${DVIPS} ${DVIPSOPTS} -o ${.TARGET} ${.ALLSRC}
${DOC}.tar: ${SRCS} ${LOCAL_IMAGES} ${LOCAL_CSS_SHEET}
${TAR} cf ${.TARGET} -C ${.CURDIR} ${SRCS} \
-C ${.OBJDIR} ${IMAGES} ${CSS_SHEET:T}
#
# Build targets for any formats we've missed that we don't handle.
#
.for _curformat in ${ALL_FORMATS}
.if !target(${DOC}.${_curformat})
${DOC}.${_curformat}:
@${ECHO_CMD} \"${_curformat}\" is not a valid output format for this document.
.endif
.endfor
# ------------------------------------------------------------------------
#
# Validation targets
#
#
# Lets you quickly check that the document conforms to the DTD without
# having to convert it to any other formats
#
lint validate:
${NSGMLS} -s ${SGMLFLAGS} ${CATALOGS} ${MASTERDOC}
# ------------------------------------------------------------------------
#
# Index targets
#
#
# Generate a different .index file based on the format name
#
# If we're not generating an index (the default) then we need to create
# an empty index.sgml file so that we can reference index.sgml in book.sgml
#
${INDEX_SGML}:
${PERL} ${COLLATEINDEX} -N -o ${.TARGET}
${HTML_INDEX}:
${JADE} -V html-index -V nochunks ${HTMLOPTS} -ioutput.html.images \
${JADEOPTS} -t sgml ${MASTERDOC} > /dev/null
${PERL} ${COLLATEINDEX} -g -o ${INDEX_SGML} ${.TARGET}
${HTML_SPLIT_INDEX}:
${JADE} -V html-index ${HTMLOPTS} -ioutput.html.images \
${JADEOPTS} -t sgml ${MASTERDOC} > /dev/null
${PERL} ${COLLATEINDEX} -g -o ${INDEX_SGML} ${.TARGET}
${PRINT_INDEX}: ${HTML_INDEX}
${CP} -p ${HTML_INDEX} ${.TARGET}
# ------------------------------------------------------------------------
#
# Compress targets
#
#
# The list of compression extensions this Makefile knows about. If you
# add new compression schemes, add to this list (which is a list of
# extensions, hence bz2, *not* bzip2) and extend the _PROG_COMPRESS_*
# targets.
#
KNOWN_COMPRESS= gz bz2 zip
#
# You can't build suffix rules to do compression, since you can't
# wildcard the source suffix. So these are defined .USE, to be tacked on
# as dependencies of the compress-* targets.
#
_PROG_COMPRESS_gz: .USE
${GZIP_CMD} < ${.ALLSRC} > ${.TARGET}
_PROG_COMPRESS_bz2: .USE
${BZIP2_CMD} < ${.ALLSRC} > ${.TARGET}
_PROG_COMPRESS_zip: .USE
${ZIP_CMD} ${.TARGET} ${.ALLSRC}
#
# Build a list of targets for each compression scheme and output format.
# Don't compress the html-split or html output format (because they need
# to be rolled in to tar files first).
#
.for _curformat in ${KNOWN_FORMATS}
_cf=${_curformat}
.for _curcompress in ${KNOWN_COMPRESS}
.if ${_cf} == "html-split" || ${_cf} == "html"
${DOC}.${_cf}.tar.${_curcompress}: ${DOC}.${_cf}.tar \
_PROG_COMPRESS_${_curcompress}
.else
${DOC}.${_cf}.${_curcompress}: ${DOC}.${_cf} _PROG_COMPRESS_${_curcompress}
.endif
.endfor
.endfor
#
# Build targets for any formats we've missed that we don't handle.
#
.for _curformat in ${ALL_FORMATS}
.for _curcompress in ${KNOWN_COMPRESS}
.if !target(${DOC}.${_curformat}.${_curcompress})
${DOC}.${_curformat}.${_curcompress}:
@${ECHO_CMD} \"${_curformat}.${_curcompress}\" is not a valid output format for this document.
.endif
.endfor
.endfor
# ------------------------------------------------------------------------
#
# Install targets
#
# Build install-* targets, one per allowed value in FORMATS. Need to
# build two specific targets;
#
# install-html-split - Handles multiple .html files being generated
# from one source. Uses the HTML.manifest file
# created by the stylesheets, which should list
# each .html file that's been created.
#
# install-* - Every other format. The wildcard expands to
# the other allowed formats, all of which should
# generate just one file.
#
# "beforeinstall" and "afterinstall" are hooks in to this process.
# Redefine them to do things before and after the files are installed,
# respectively.
#
# Build a list of install-format targets to be installed. These will be
# dependencies for the "realinstall" target.
#
.if !defined(INSTALL_ONLY_COMPRESSED) || empty(INSTALL_ONLY_COMPRESSED)
_curinst+= ${FORMATS:S/^/install-/g}
.endif
realinstall: ${_curinst}
.for _curformat in ${KNOWN_FORMATS}
_cf=${_curformat}
.if !target(install-${_cf})
.if ${_cf} == "html-split"
install-${_curformat}: index.html
.else
install-${_curformat}: ${DOC}.${_curformat}
.endif
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
.if ${_cf} == "html-split"
${INSTALL_DOCS} $$(${XARGS} < HTML.manifest) ${DESTDIR}
.else
${INSTALL_DOCS} ${.ALLSRC} ${DESTDIR}
.endif
.if (${_cf} == "html-split" || ${_cf} == "html") && !empty(LOCAL_CSS_SHEET)
${INSTALL_DOCS} ${LOCAL_CSS_SHEET} ${DESTDIR}
.if ${_cf} == "html-split"
@if [ -f ln*.html ]; then \
${INSTALL_DOCS} ln*.html ${DESTDIR}; \
fi
@if [ -f ${.OBJDIR}/${DOC}.ln ]; then \
cd ${DESTDIR}; sh ${.OBJDIR}/${DOC}.ln; \
fi
.endif
.for _curimage in ${IMAGES_LIB}
@[ -d ${DESTDIR}/${LOCAL_IMAGES_LIB_DIR}/${_curimage:H} ] || \
${MKDIR} -p ${DESTDIR}/${LOCAL_IMAGES_LIB_DIR}/${_curimage:H}
${INSTALL_DOCS} ${LOCAL_IMAGES_LIB_DIR}/${_curimage} \
${DESTDIR}/${LOCAL_IMAGES_LIB_DIR}/${_curimage:H}
.endfor
# Install the images. First, loop over all the image names that contain a
-# directory seperator, make the subdirectories, and install. Then loop over
+# directory separator, make the subdirectories, and install. Then loop over
# the ones that don't contain a directory separator, and install them in the
# top level.
# en_US.ISO8859-1 is replaced with the LANGCODE to allow installation of
# images built in en_US.ISO8859-1/ directory
.for _curimage in ${IMAGES_PNG:M*/*}
${MKDIR} -p ${DESTDIR}/${_curimage:H:S|${CURDIR}||:S|en_US.ISO8859-1|${LANGCODE}|}
${INSTALL_DOCS} ${_curimage} ${DESTDIR}/${_curimage:H:S|${CURDIR}||:S|en_US.ISO8859-1|${LANGCODE}|}
.endfor
.for _curimage in ${IMAGES_PNG:N*/*}
${INSTALL_DOCS} ${_curimage} ${DESTDIR}
.endfor
.elif ${_cf} == "tex" || ${_cf} == "dvi"
.for _curimage in ${IMAGES_EPS:M*/*}
${MKDIR} -p ${DESTDIR}/${_curimage:H:S|${CURDIR}||:S|en_US.ISO8859-1|${LANGCODE}|}
${INSTALL_DOCS} ${_curimage} ${DESTDIR}/${_curimage:H:S|${CURDIR}||:S|en_US.ISO8859-1|${LANGCODE}|}
.endfor
.for _curimage in ${IMAGES_EPS:N*/*}
${INSTALL_DOCS} ${_curimage} ${DESTDIR}
.endfor
.elif ${_cf} == "pdb"
${LN} -f ${DESTDIR}/${.ALLSRC} ${DESTDIR}/${.CURDIR:T}.${_curformat}
.endif
.if ${_cf} == "html-split"
.for _compressext in ${KNOWN_COMPRESS}
install-${_curformat}.tar.${_compressext}: ${DOC}.${_curformat}.tar.${_compressext}
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
${INSTALL_DOCS} ${.ALLSRC} ${DESTDIR}
.endfor
.else
.for _compressext in ${KNOWN_COMPRESS}
install-${_curformat}.${_compressext}: ${DOC}.${_curformat}.${_compressext}
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
${INSTALL_DOCS} ${.ALLSRC} ${DESTDIR}
.if ${_cf} == "pdb"
${LN} -f ${DESTDIR}/${.ALLSRC} \
${DESTDIR}/${.CURDIR:T}.${_curformat}.${_compressext}
.endif
.endfor
.endif
.endif
.endfor
#
# Build install- targets for any formats we've missed that we don't handle.
#
.for _curformat in ${ALL_FORMATS}
.if !target(install-${_curformat})
install-${_curformat}:
@${ECHO_CMD} \"${_curformat}\" is not a valid output format for this document.
.for _compressext in ${KNOWN_COMPRESS}
install-${_curformat}.${_compressext}:
@${ECHO_CMD} \"${_curformat}.${_compressext}\" is not a valid output format for this document.
.endfor
.endif
.endfor
# ------------------------------------------------------------------------
#
# Package building
#
#
# realpackage is what is called in each subdirectory when a package
# target is called, or, rather, package calls realpackage in each
# subdirectory as it goes.
#
# packagelist returns the list of targets that would be called during
# package building.
#
realpackage: ${FORMATS:S/^/package-/}
packagelist:
@${ECHO_CMD} ${FORMATS:S/^/package-/}
#
# Build a list of package targets for each output target. Each package
# target depends on the corresponding install target running.
#
.for _curformat in ${KNOWN_FORMATS}
_cf=${_curformat}
.if ${_cf} == "html-split"
PLIST.${_curformat}: index.html
@${SORT} HTML.manifest > PLIST.${_curformat}
.else
PLIST.${_curformat}: ${DOC}.${_curformat}
@${ECHO_CMD} ${DOC}.${_curformat} > PLIST.${_curformat}
.endif
.if (${_cf} == "html-split" || ${_cf} == "html") && \
(!empty(LOCAL_IMAGES_LIB) || !empty(IMAGES_PNG) || !empty(CSS_SHEET))
@${ECHO_CMD} ${LOCAL_IMAGES_LIB} ${IMAGES_PNG} ${LOCAL_CSS_SHEET} | \
${XARGS} -n1 >> PLIST.${_curformat}
.elif (${_cf} == "tex" || ${_cf} == "dvi") && !empty(IMAGES_EPS)
@${ECHO_CMD} ${IMAGES_EPS} | ${XARGS} -n1 >> PLIST.${_curformat}
.elif ${_cf} == "pdb"
@${ECHO_CMD} ${.CURDIR:T}.${_curformat} >> PLIST.${_curformat}
.endif
${PACKAGES}/${.CURDIR:T}.${LANGCODE}.${_curformat}.tgz: PLIST.${_cf}
@${PKG_CREATE} -v -f ${.ALLSRC} -p ${DESTDIR} -s ${.OBJDIR} \
-c -"FDP ${.CURDIR:T} ${_curformat} package" \
-d -"FDP ${.CURDIR:T} ${_curformat} package" ${.TARGET}
package-${_curformat}: ${PACKAGES}/${.CURDIR:T}.${LANGCODE}.${_curformat}.tgz
.endfor
.if ${LOCAL_CSS_SHEET} != ${CSS_SHEET}
${LOCAL_CSS_SHEET}: ${CSS_SHEET}
${RM} -f ${.TARGET}
${CAT} ${.ALLSRC} > ${.TARGET}
.if defined(CSS_SHEET_ADDITIONS)
${CAT} ${.CURDIR}/${CSS_SHEET_ADDITIONS} >> ${.TARGET}
.endif
.endif
diff --git a/share/mk/doc.html.mk b/share/mk/doc.html.mk
index e6bc90fee9..91a3c157e0 100644
--- a/share/mk/doc.html.mk
+++ b/share/mk/doc.html.mk
@@ -1,388 +1,388 @@
#
# $FreeBSD$
#
# This include file handles building and installing of
# HTML documentation in the FreeBSD Documentation Project.
#
# Documentation using DOCFORMAT=html is expected to be marked up
# according to the HTML DTD
#
# ------------------------------------------------------------------------
#
# Document-specific variables
#
# DOC This should be set to the name of the HTML
# marked-up file, without the .sgml or .docb suffix.
#
# It also determins the name of the output files -
# ${DOC}.html.
#
# DOCBOOKSUFFIX The suffix of your document, defaulting to .sgml
#
# SRCS The names of all the files that are needed to
# build this document - This is useful if any of
# them need to be generated. Changing any file in
# SRCS causes the documents to be rebuilt.
#
# ------------------------------------------------------------------------
#
# Variables used by both users and documents:
#
# TIDYFLAGS Additional flags to pass to Tidy. Typically
# used to set "-raw" flag to handle 8bit characters.
#
# EXTRA_CATALOGS Additional catalog files that should be used by
# any SGML processing applications.
#
# NO_TIDY If you do not want to use tidy, set this to "YES".
#
# Documents should use the += format to access these.
#
MASTERDOC?= ${.CURDIR}/${DOC}.sgml
KNOWN_FORMATS= html txt tar pdb
CSS_SHEET?=
HTMLCATALOG= ${PREFIX}/share/sgml/html/catalog
IMAGES_LIB?=
.if ${MACHINE_ARCH} != "i386"
OPENJADE= yes
.endif
.if defined(OPENJADE)
NSGMLS?= ${PREFIX}/bin/onsgmls
SGMLNORM?= ${PREFIX}/bin/osgmlnorm
.else
NSGMLS?= ${PREFIX}/bin/nsgmls
SGMLNORM?= ${PREFIX}/bin/sgmlnorm
.endif
PKG_CREATE?= /usr/sbin/pkg_create
TAR?= /usr/bin/tar
XARGS?= /usr/bin/xargs
TIDY?= ${PREFIX}/bin/tidy
TIDYOPTS?= -i -m -raw -preserve -f /dev/null ${TIDYFLAGS}
HTML2TXT?= ${PREFIX}/bin/links
HTML2TXTOPTS?= -dump ${HTML2TXTFLAGS}
HTML2PDB?= ${PREFIX}/bin/iSiloBSD
HTML2PDBOPTS?= -y -d0 -Idef ${HTML2PDBFLAGS}
GZIP?= -9
GZIP_CMD?= gzip -qf ${GZIP}
BZIP2?= -9
BZIP2_CMD?= bzip2 -qf ${BZIP2}
ZIP?= -9
ZIP_CMD?= ${PREFIX}/bin/zip -j ${ZIP}
# ------------------------------------------------------------------------
#
.if ${.OBJDIR} != ${.CURDIR}
LOCAL_CSS_SHEET= ${.OBJDIR}/${CSS_SHEET:T}
CLEANFILES+= ${LOCAL_CSS_SHEET}
.else
LOCAL_CSS_SHEET= ${CSS_SHEET:T}
.endif
.for _curformat in ${FORMATS}
_cf=${_curformat}
# Create a 'bogus' doc for any format we support or not. This is so
# that we can fake up a target for it later on, and this target can print
# the warning message about the unsupported format.
_docs+= ${DOC}.${_curformat}
CLEANFILES+= ${DOC}.${_curformat}
CLEANFILES+= PLIST.${_curformat}
.if ${_cf} == "txt"
.if ${LOCAL_CSS_SHEET} != ${CSS_SHEET}
CLEANFILES+= ${LOCAL_CSS_SHEET}
.endif
.elif ${_cf} == "txt"
CLEANFILES+= ${DOC}.html
.elif ${_cf} == "pdb"
_docs+= ${.CURDIR:T}.pdb
CLEANFILES+= ${.CURDIR:T}.pdb
.endif
.endfor
#
# Build a list of install-${format}.${compress_format} targets to be
# by "make install". Also, add ${DOC}.${format}.${compress_format} to
# ${_docs} and ${CLEANFILES} so they get built/cleaned by "all" and
# "clean".
#
.if defined(INSTALL_COMPRESSED) && !empty(INSTALL_COMPRESSED)
.for _curformat in ${FORMATS}
_cf=${_curformat}
.for _curcomp in ${INSTALL_COMPRESSED}
.if ${_cf} != "html-split"
_curinst+= install-${_curformat}.${_curcomp}
_docs+= ${DOC}.${_curformat}.${_curcomp}
CLEANFILES+= ${DOC}.${_curformat}.${_curcomp}
.if ${_cf} == "pdb"
_docs+= ${.CURDIR:T}.${_curformat}.${_curcomp}
CLEANFILES+= ${.CURDIR:T}.${_curformat}.${_curcomp}
.endif
.endif
.endfor
.endfor
.endif
.MAIN: all
all: ${_docs}
${DOC}.html: ${SRCS} ${LOCAL_IMAGES_LIB} ${LOCAL_IMAGES_PNG} ${LOCAL_CSS_SHEET}
${SGMLNORM} -c ${HTMLCATALOG} ${SRCS:S|^|${.CURDIR}/|} > ${.TARGET}
.if !defined(NO_TIDY)
-${TIDY} ${TIDYOPTS} ${.TARGET}
.endif
${DOC}.txt: ${DOC}.html
${HTML2TXT} ${HTML2TXTOPTS} ${.ALLSRC} > ${.TARGET}
${DOC}.pdb: ${DOC}.html ${LOCAL_IMAGES_LIB} ${LOCAL_IMAGES_PNG}
${HTML2PDB} ${HTML2PDBOPTS} ${DOC}.html ${.TARGET}
${.CURDIR:T}.pdb: ${DOC}.pdb
${LN} -f ${.ALLSRC} ${.TARGET}
.if defined(INSTALL_COMPRESSED) && !empty(INSTALL_COMPRESSED)
.for _curcomp in ${INSTALL_COMPRESSED}
${.CURDIR:T}.pdb.${_curcomp}: ${DOC}.pdb.${_curcomp}
${LN} -f ${.ALLSRC} ${.TARGET}
.endfor
.endif
${DOC}.tar: ${SRCS} ${LOCAL_IMAGES} ${LOCAL_CSS_SHEET}
${TAR} cf ${.TARGET} -C ${.CURDIR} ${SRCS} \
-C ${.OBJDIR} ${IMAGES} ${CSS_SHEET:T}
#
# Build targets for any formats we've missed that we don't handle.
#
.for _curformat in ${ALL_FORMATS}
.if !target(${DOC}.${_curformat})
${DOC}.${_curformat}:
@${ECHO_CMD} \"${_curformat}\" is not a valid output format for this document.
.endif
.endfor
# ------------------------------------------------------------------------
#
# Validation targets
#
#
# Lets you quickly check that the document conforms to the DTD without
# having to convert it to any other formats
#
lint validate:
${NSGMLS} -s -c ${HTMLCATALOG} ${MASTERDOC}
# ------------------------------------------------------------------------
#
# Compress targets
#
#
# The list of compression extensions this Makefile knows about. If you
# add new compression schemes, add to this list (which is a list of
# extensions, hence bz2, *not* bzip2) and extend the _PROG_COMPRESS_*
# targets.
#
KNOWN_COMPRESS= gz bz2 zip
#
# You can't build suffix rules to do compression, since you can't
# wildcard the source suffix. So these are defined .USE, to be tacked on
# as dependencies of the compress-* targets.
#
_PROG_COMPRESS_gz: .USE
${GZIP_CMD} < ${.ALLSRC} > ${.TARGET}
_PROG_COMPRESS_bz2: .USE
${BZIP2_CMD} < ${.ALLSRC} > ${.TARGET}
_PROG_COMPRESS_zip: .USE
${ZIP_CMD} ${.TARGET} ${.ALLSRC}
#
# Build a list of targets for each compression scheme and output format.
# Don't compress the html-split output format.
#
.for _curformat in ${KNOWN_FORMATS}
_cf=${_curformat}
.for _curcompress in ${KNOWN_COMPRESS}
${DOC}.${_cf}.${_curcompress}: ${DOC}.${_cf} _PROG_COMPRESS_${_curcompress}
.endfor
.endfor
#
# Build targets for any formats we've missed that we don't handle.
#
.for _curformat in ${ALL_FORMATS}
.for _curcompress in ${KNOWN_COMPRESS}
.if !target(${DOC}.${_curformat}.${_curcompress})
${DOC}.${_curformat}.${_curcompress}:
@${ECHO_CMD} \"${_curformat}.${_curcompress}\" is not a valid output format for this document.
.endif
.endfor
.endfor
# ------------------------------------------------------------------------
#
# Install targets
#
# Build install-* targets, one per allowed value in FORMATS.
#
# "beforeinstall" and "afterinstall" are hooks in to this process.
# Redefine them to do things before and after the files are installed,
# respectively.
#
# Build a list of install-format targets to be installed. These will be
# dependencies for the "realinstall" target.
#
.if !defined(INSTALL_ONLY_COMPRESSED) || empty(INSTALL_ONLY_COMPRESSED)
_curinst+= ${FORMATS:S/^/install-/g}
.endif
realinstall: ${_curinst}
.for _curformat in ${KNOWN_FORMATS}
_cf=${_curformat}
.if !target(install-${_cf})
install-${_curformat}: ${DOC}.${_curformat}
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
${INSTALL_DOCS} ${.ALLSRC} ${DESTDIR}
.if !empty(CSS_SHEET)
${INSTALL_DOCS} ${CSS_SHEET} ${DESTDIR}
.endif
.for _curimage in ${IMAGES_LIB}
@[ -d ${DESTDIR}/${LOCAL_IMAGES_LIB_DIR}/${_curimage:H} ] || \
${MKDIR} -p ${DESTDIR}/${LOCAL_IMAGES_LIB_DIR}/${_curimage:H}
${INSTALL_DOCS} ${LOCAL_IMAGES_LIB_DIR}/${_curimage} \
${DESTDIR}/${LOCAL_IMAGES_LIB_DIR}/${_curimage:H}
.endfor
# Install the images. First, loop over all the image names that contain a
-# directory seperator, make the subdirectories, and install. Then loop over
+# directory separator, make the subdirectories, and install. Then loop over
# the ones that don't contain a directory separator, and install them in the
# top level.
.for _curimage in ${IMAGES_PNG:M*/*}
${MKDIR} -p ${DESTDIR}/${_curimage:H}
${INSTALL_DOCS} ${.CURDIR}/${_curimage} ${DESTDIR}/${_curimage:H}
.endfor
.for _curimage in ${IMAGES_PNG:N*/*}
${INSTALL_DOCS} ${.CURDIR}/${_curimage} ${DESTDIR}
.endfor
.if ${_cf} == "pdb"
${LN} -f ${DESTDIR}/${.ALLSRC} ${DESTDIR}/${.CURDIR:T}.${_curformat}
.endif
.for _compressext in ${KNOWN_COMPRESS}
install-${_cf}.${_compressext}: ${DOC}.${_cf}.${_compressext}
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
${INSTALL_DOCS} ${.ALLSRC} ${DESTDIR}
.endfor
.endif
.endfor
#
# Build install- targets for any formats we've missed that we don't handle.
#
.for _curformat in ${ALL_FORMATS}
.if !target(install-${_curformat})
install-${_curformat}:
@${ECHO_CMD} \"${_curformat}\" is not a valid output format for this document.
.for _compressext in ${KNOWN_COMPRESS}
install-${_curformat}.${_compressext}:
@${ECHO_CMD} \"${_curformat}.${_compressext}\" is not a valid output format for this document.
.endfor
.endif
.endfor
# ------------------------------------------------------------------------
#
# Package building
#
#
# realpackage is what is called in each subdirectory when a package
# target is called, or, rather, package calls realpackage in each
# subdirectory as it goes.
#
# packagelist returns the list of targets that would be called during
# package building.
#
realpackage: ${FORMATS:S/^/package-/}
packagelist:
@${ECHO_CMD} ${FORMATS:S/^/package-/}
#
# Build a list of package targets for each output target. Each package
# target depends on the corresponding install target running.
#
.for _curformat in ${KNOWN_FORMATS}
_cf=${_curformat}
PLIST.${_curformat}: ${DOC}.${_curformat}
@${ECHO_CMD} ${DOC}.${_curformat} > PLIST.${_curformat}
.if ${_cf} == "html" && \
(!empty(LOCAL_IMAGES_LIB) || !empty(IMAGES_PNG) || !empty(CSS_SHEET))
@${ECHO_CMD} ${LOCAL_IMAGES_LIB} ${IMAGES_PNG} ${CSS_SHEET} | \
${XARGS} -n1 >> PLIST.${_curformat}
.elif ${_cf} == "pdb"
@${ECHO_CMD} ${.CURDIR:T}.${_curformat} >> PLIST.${_curformat}
.endif
${PACKAGES}/${.CURDIR:T}.${LANGCODE}.${_curformat}.tgz: PLIST.${_curformat}
@${PKG_CREATE} -v -f PLIST.${_curformat} -p ${DESTDIR} -s ${.OBJDIR} \
-c -"FDP ${.CURDIR:T} ${_curformat} package" \
-d -"FDP ${.CURDIR:T} ${_curformat} package" ${.TARGET}
package-${_curformat}: ${PACKAGES}/${.CURDIR:T}.${LANGCODE}.${_curformat}.tgz
.endfor
#
# Build install- targets for any formats we've missed that we don't handle.
#
.for _curformat in ${ALL_FORMATS}
.if !target(package-${_curformat})
package-${_curformat}:
@${ECHO_CMD} \"${_curformat}\" is not a valid output format for this document.
.endif
.endfor
.if ${LOCAL_CSS_SHEET} != ${CSS_SHEET}
${LOCAL_CSS_SHEET}: ${CSS_SHEET}
${CP} -p ${.ALLSRC} ${.TARGET}
.endif
diff --git a/share/sgml/freebsd.dsl b/share/sgml/freebsd.dsl
index f2aaaa6819..8e16134e3b 100644
--- a/share/sgml/freebsd.dsl
+++ b/share/sgml/freebsd.dsl
@@ -1,858 +1,858 @@
]]>
]]>
]>
(declare-flow-object-class formatting-instruction
"UNREGISTERED::James Clark//Flow Object Class::formatting-instruction")
(define %hyphenation% #f)
(define %gentext-nav-use-tables%
;; Use tables to build the navigation headers and footers?
#t)
(define %html-ext%
;; Default extension for HTML output files
".html")
(define %shade-verbatim%
;; Should verbatim environments be shaded?
#f)
(define %use-id-as-filename%
;; Use ID attributes as name for component HTML files?
#t)
(define %root-filename%
;; Name for the root HTML document
"index")
(define html-manifest
;; Write a manifest?
#f)
(define %generate-legalnotice-link%
;; Should legal notices be a link to a separate file?
;;
;; Naturally, this has no effect if you're building one big
;; HTML file.
#t)
(define (book-titlepage-recto-elements)
(list (normalize "title")
(normalize "subtitle")
(normalize "graphic")
(normalize "mediaobject")
(normalize "corpauthor")
(normalize "authorgroup")
(normalize "author")
(normalize "editor")
(normalize "copyright")
(normalize "abstract")
(normalize "legalnotice")
(normalize "isbn")))
(define ($email-footer$)
(empty-sosofo))
(define html-index-filename
(if nochunks
"html.index"
"html-split.index"))
(define %stylesheet%
"docbook.css")
(define ($html-body-end$)
(if (equal? $email-footer$ (normalize ""))
(empty-sosofo)
(make sequence
(if nochunks
(make empty-element gi: "hr")
(empty-sosofo))
($email-footer$))))
(define %refentry-xref-link%
;; REFENTRY refentry-xref-link
;; PURP Generate URL links when cross-referencing RefEntrys?
;; DESC
;; If true, a web link will be generated, presumably
;; to an online man->HTML gateway. The text of the link is
;; generated by the $create-refentry-xref-link$ function.
;; /DESC
;; AUTHOR N/A
;; /REFENTRY
#f)
; Empty function to quiet warnings
(define ($create-refentry-xref-link$)
(literal ""))
(element citerefentry
(let ((href ($create-refentry-xref-link$)))
(if %refentry-xref-link%
(create-link (list (list "HREF" href))
(if %refentry-xref-italic%
($italic-seq$)
($charseq$)))
(if %refentry-xref-italic%
($italic-seq$)
($charseq$)))))
(element filename
(let* ((class (attribute-string (normalize "role"))))
(cond
((equal? class "package")
(let* ((urlurl "http://www.FreeBSD.org/cgi/url.cgi")
(href (string-append urlurl "?ports/"
(data (current-node))
"/pkg-descr")))
(create-link (list (list "HREF" href)) ($mono-seq$))))
(else ($mono-seq$)))))
;; Ensure that we start with no preferred mediaobject notations,
;; so that in the text-only case we don't choose any of the
;; possible images, and fallback to the most appropriate
;; textobject
(define preferred-mediaobject-notations
'())
]]>
")))
(element filename
(pathwrap))
(element varname
(pathwrap))
]]>
(string-length url) 15)
(string=? (substring url 0 16) "file://localhost"))
(substring url 16 (string-length url))
url))
(element (primaryie ulink)
(indexentry-link (current-node)))
(element (secondaryie ulink)
(indexentry-link (current-node)))
(element (tertiaryie ulink)
(indexentry-link (current-node)))
;; Override the count-footnote? definition from dbblock.dsl
;; to fix a bug. Basically, the original procedure would count
;; all ulink elements when doing %footnote-ulinks%. It's
;; actually harder than that, because ulink elements with no
;; content shouldn't generate footnotes (the ulink element
;; definition just inserts the url attribute in-line, thus there
;; is no need for a footnote with the url). So, when we figure
;; out which footnotes to count for the purpose of determining
;; footnote numbers, we only count the ulink elements containing
;; content.
(define (count-footnote? footnote)
;; don't count footnotes in comments (unless you're showing comments)
;; or footnotes in tables which are handled locally in the table
(if (or (and (has-ancestor-member? footnote (list (normalize "comment")))
(not %show-comments%))
(has-ancestor-member? footnote (list (normalize "tgroup")))
(and (has-ancestor-member? footnote (list (normalize "ulink")))
(node-list-empty? (children footnote))))
#f
#t))
(element ulink
(make sequence
(if (node-list-empty? (children (current-node)))
(literal (fix-url (attribute-string (normalize "url"))))
(make sequence
($charseq$)
(if %footnote-ulinks%
(if (and (equal? (print-backend) 'tex) bop-footnotes)
(make sequence
($ss-seq$ + (literal (footnote-number (current-node))))
(make page-footnote
(make paragraph
font-size: (* %footnote-size-factor% %bf-size%)
font-posture: 'upright
quadding: %default-quadding%
line-spacing: (* (* %footnote-size-factor% %bf-size%)
%line-spacing-factor%)
space-before: %para-sep%
space-after: %para-sep%
start-indent: %footnote-field-width%
first-line-start-indent: (- %footnote-field-width%)
(make line-field
field-width: %footnote-field-width%
(literal (footnote-number (current-node))
(gentext-label-title-sep (normalize "footnote"))))
(literal (fix-url (attribute-string (normalize "url")))))))
($ss-seq$ + (literal (footnote-number (current-node)))))
(if (and %show-ulinks%
(not (equal? (fix-url (attribute-string (normalize "url")))
(data-of (current-node)))))
(make sequence
(literal " (")
(if %hyphenation%
(make formatting-instruction data:
(string-append "\\url{"
(fix-url (attribute-string
(normalize "url")))
"}"))
(literal (fix-url (attribute-string (normalize "url")))))
(literal ")"))
(empty-sosofo)))))))
(define (toc-depth nd)
(if (string=? (gi nd) (normalize "book"))
3
1))
(element programlisting
(if (and (equal? (attribute-string (normalize "role")) "pgpkey")
(not withpgpkeys))
(empty-sosofo)
(next-match)))
(define %body-start-indent%
0pi)
(define (book-titlepage-verso-elements)
(list (normalize "title")
(normalize "subtitle")
(normalize "corpauthor")
(normalize "authorgroup")
(normalize "author")
(normalize "editor")
(normalize "edition")
(normalize "pubdate")
(normalize "copyright")
(normalize "abstract")
(normalize "legalnotice")
(normalize "revhistory")
(normalize "isbn")))
;; Norm's stylesheets are smart about working out what sort of
;; object to display. But this bites us. Since we know that the
;; first item is going to be displayable, always use that.
(define (find-displayable-object objlist notlist extlist)
(let loop ((nl objlist))
(if (node-list-empty? nl)
(empty-node-list)
(let* ((objdata (node-list-filter-by-gi
(children (node-list-first nl))
(list (normalize "videodata")
(normalize "audiodata")
(normalize "imagedata"))))
(filename (data-filename objdata))
(extension (file-extension filename))
(notation (attribute-string (normalize "format") objdata)))
(node-list-first nl)))))
;; When selecting a filename to use, don't append the default
;; extension, instead, just use the bare filename, and let TeX
;; work it out. jadetex will use the .eps file, while pdfjadetex
;; will use the .png file automatically.
(define (graphic-file filename)
(let ((ext (file-extension filename)))
(if (or tex-backend ;; TeX can work this out itself
(not filename)
(not %graphic-default-extension%)
(member ext %graphic-extensions%))
filename
(string-append filename "." %graphic-default-extension%))))
;; Including bitmaps in the PS and PDF output tends to scale them
;; horribly. The solution is to scale them down by 50%.
;;
;; You could do this with 'imagedata scale="50"' in the source,
;; but that will affect all the output formats that we use (because
;; there is only one 'imagedata' per image).
;;
;; Solution is to have the authors include the "FORMAT" attribute,
;; set to PNG or EPS as appropriate, but to omit the extension.
;; If we're using the tex-backend, and the FORMAT is PNG, and the
;; author hasn't already set a scale, then set scale to 0.5.
;; Otherwise, use the supplied scale, or 1, as appropriate.
(define ($graphic$ fileref
#!optional (display #f) (format #f)
(scale #f) (align #f))
(let* ((graphic-format (if format format ""))
(graphic-scale (if scale
(/ (string->number scale) 100)
(if (and tex-backend
(equal? graphic-format "PNG"))
0.5 1)))
(graphic-align (cond ((equal? align (normalize "center"))
'center)
((equal? align (normalize "right"))
'end)
(else
'start))))
(make external-graphic
entity-system-id: (graphic-file fileref)
notation-system-id: graphic-format
scale: graphic-scale
display?: display
display-alignment: graphic-align)))
]]>
(define %section-autolabel%
#t)
(define %label-preface-sections%
#f)
(define %may-format-variablelist-as-table%
#f)
(define %indent-programlisting-lines%
" ")
(define %indent-screen-lines%
" ")
(define (article-titlepage-recto-elements)
(list (normalize "title")
(normalize "subtitle")
(normalize "corpauthor")
(normalize "authorgroup")
(normalize "author")
(normalize "releaseinfo")
(normalize "copyright")
(normalize "pubdate")
(normalize "revhistory")
(normalize "legalnotice")
(normalize "abstract")))
(define %admon-graphics%
;; Use graphics in admonitions?
#f)
(define %admon-graphics-path%
;; Path to admonition images
"./imagelib/admon/")
(define ($admon-graphic$ #!optional (nd (current-node)))
;; Admonition graphic file
(string-append %admon-graphics-path% (case-fold-down (gi nd)) ".png"))
+ authorgroup shows up as a separate sentence. -->
(element chapterinfo
(process-children))
(element sect1info
(process-children))
(element sect2info
(process-children))
(element sect3info
(process-children))
(element sect4info
(process-children))
(element sect5info
(process-children))
(element (chapterinfo authorgroup author)
(literal (author-list-string)))
(element (sect1info authorgroup author)
(literal (author-list-string)))
(element (sect2info authorgroup author)
(literal (author-list-string)))
(element (sect3info authorgroup author)
(literal (author-list-string)))
(element (sect4info authorgroup author)
(literal (author-list-string)))
(element (sect5info authorgroup author)
(literal (author-list-string)))
(define (custom-authorgroup)
($italic-seq$
(make sequence
(process-node-list (select-elements (descendants (current-node))
(normalize "contrib")))
(process-children)
(literal ". "))))
(element (chapterinfo authorgroup)
(custom-authorgroup))
(element (sect1info authorgroup)
(custom-authorgroup))
(element (sect2info authorgroup)
(custom-authorgroup))
(element (sect3info authorgroup)
(custom-authorgroup))
(element (sect4info authorgroup)
(custom-authorgroup))
(element (sect5info authorgroup)
(custom-authorgroup))
(element sgmltag ($mono-seq$
(make sequence
(literal "<")
(process-children)
(literal ">"))))
(element errorname
(make sequence
($mono-seq$ (process-children))
))
(element command ($mono-seq$))
(element envar ($mono-seq$))
(element application ($bold-seq$))
(element warning ($admonition$))
(element (warning title) (empty-sosofo))
(element (warning para) ($admonpara$))
(element (warning simpara) ($admonpara$))
(element caution ($admonition$))
(element (caution title) (empty-sosofo))
(element (caution para) ($admonpara$))
(element (caution simpara) ($admonpara$))
(element hostid
(if %hyphenation%
(urlwrap)
($mono-seq$)))
(element username ($mono-seq$))
(element groupname ($mono-seq$))
(element devicename ($mono-seq$))
(element maketarget ($mono-seq$))
(element makevar ($mono-seq$))
(define (generate-anchor #!optional (nd (current-node)))
(cond
((equal? (gi nd) (normalize "question"))
(string-append "Q" (question-answer-label)))
(else
(string-append "AEN" (number->string (all-element-number nd))))))
(define (xref-biblioentry target)
(let* ((abbrev (node-list-first
(node-list-filter-out-pis (children target))))
(label (attribute-string (normalize "xreflabel") target)))
(if biblio-xref-title
(let* ((citetitles (select-elements (descendants target)
(normalize "citetitle")))
(titles (select-elements (descendants target)
(normalize "title")))
(isbn (select-elements (descendants target)
(normalize "isbn")))
(publisher (select-elements (descendants target)
(normalize "publishername")))
(title (if (node-list-empty? citetitles)
(node-list-first titles)
(node-list-first citetitles))))
(with-mode xref-title-mode
(make sequence
(process-node-list title))))
(if biblio-number
(make sequence
(literal "[" (number->string (bibentry-number target)) "]"))
(if label
(make sequence
(literal "[" label "]"))
(if (equal? (gi abbrev) (normalize "abbrev"))
(make sequence
(process-node-list abbrev))
(make sequence
(literal "[" (id target) "]"))))))))
(define (can-link-here)
(cond ((has-ancestor-member? (current-node)
'("TITLE" "QUESTION")) #f)
(#t #t)))
(define (create-link attrlist target)
(if (can-link-here)
(make element gi: "A"
attributes: attrlist
target)
target))