code:
.. SPDX-License-Identifier: GPL-2.0

=========================================
The Linux SYM-2 driver documentation file
=========================================

Written by Gerard Roudier <groudier@free.fr>

21 Rue Carnot

95170 DEUIL LA BARRE - FRANCE

Updated by Matthew Wilcox <matthew@wil.cx>

2004-10-09

.. Contents

   1.  Introduction
   2.  Supported chips and SCSI features
   3.  Advantages of this driver for newer chips.
         3.1 Optimized SCSI SCRIPTS
         3.2 New features appeared with the SYM53C896
   4.  Memory mapped I/O versus normal I/O
   5.  Tagged command queueing
   6.  Parity checking
   7.  Profiling information
   8.  Control commands
         8.1  Set minimum synchronous period
         8.2  Set wide size
         8.3  Set maximum number of concurrent tagged commands
         8.4  Set debug mode
         8.5  Set flag (no_disc)
         8.6  Set verbose level
         8.7  Reset all logical units of a target
         8.8  Abort all tasks of all logical units of a target
   9.  Configuration parameters
   10. Boot setup commands
         10.1 Syntax
         10.2 Available arguments
                10.2.1  Default number of tagged commands
                10.2.2  Burst max
                10.2.3  LED support
                10.2.4  Differential mode
                10.2.5  IRQ mode
                10.2.6  Check SCSI BUS
                10.2.7  Suggest a default SCSI id for hosts
                10.2.8  Verbosity level
                10.2.9  Debug mode
                10.2.10 Settle delay
                10.2.11 Serial NVRAM
                10.2.12 Exclude a host from being attached
         10.3 Converting from old options
         10.4 SCSI BUS checking boot option
   11. SCSI problem troubleshooting
         15.1 Problem tracking
         15.2 Understanding hardware error reports
   12. Serial NVRAM support (by Richard Waltham)
         17.1 Features
         17.2 Symbios NVRAM layout
         17.3 Tekram  NVRAM layout

1. Introduction
===============

This driver supports the whole SYM53C8XX family of PCI-SCSI controllers.
It also support the subset of LSI53C10XX PCI-SCSI controllers that are based
on the SYM53C8XX SCRIPTS language.

It replaces the sym53c8xx+ncr53c8xx driver bundle and shares its core code
with the FreeBSD SYM-2 driver. The 'glue' that allows this driver to work
under Linux is contained in 2 files named sym_glue.h and sym_glue.c.
Other drivers files are intended not to depend on the Operating System
on which the driver is used.

The history of this driver can be summarized as follows:

1993: ncr driver written for 386bsd and FreeBSD by:

          - Wolfgang Stanglmeier        <wolf@cologne.de>
          - Stefan Esser                <se@mi.Uni-Koeln.de>

1996: port of the ncr driver to Linux-1.2.13 and rename it ncr53c8xx.

          - Gerard Roudier

1998: new sym53c8xx driver for Linux based on LOAD/STORE instruction and that
      adds full support for the 896 but drops support for early NCR devices.

          - Gerard Roudier

1999: port of the sym53c8xx driver to FreeBSD and support for the LSI53C1010
      33 MHz and 66MHz Ultra-3 controllers. The new driver is named 'sym'.

          - Gerard Roudier

2000: Add support for early NCR devices to FreeBSD 'sym' driver.
      Break the driver into several sources and separate the OS glue
      code from the core code that can be shared among different O/Ses.
      Write a glue code for Linux.

          - Gerard Roudier

2004: Remove FreeBSD compatibility code.  Remove support for versions of
      Linux before 2.6.  Start using Linux facilities.

This README file addresses the Linux version of the driver. Under FreeBSD,
the driver documentation is the sym.8 man page.

Information about new chips is available at LSILOGIC web server:

          http://www.lsilogic.com/

SCSI standard documentations are available at T10 site:

          http://www.t10.org/

Useful SCSI tools written by Eric Youngdale are part of most Linux
distributions:

   ============ ==========================
   scsiinfo     command line tool
   scsi-config  TCL/Tk tool using scsiinfo
   ============ ==========================

2. Supported chips and SCSI features
====================================

The following features are supported for all chips:

	- Synchronous negotiation
	- Disconnection
	- Tagged command queuing
	- SCSI parity checking
	- PCI Master parity checking

Other features depends on chip capabilities.

The driver notably uses optimized SCRIPTS for devices that support
LOAD/STORE and handles PHASE MISMATCH from SCRIPTS for devices that
support the corresponding feature.

The following table shows some characteristics of the chip family.

+--------+-----------+-----+-----------+------------+------------+---------+
|        |           |     |           |            |Load/store  |Hardware |
|        |On board   |     |           |            |scripts     |phase    |
|Chip    |SDMS BIOS  |Wide |SCSI std.  | Max. sync  |            |mismatch |
+--------+-----------+-----+-----------+------------+------------+---------+
|810     |     N     |  N  | FAST10    | 10 MB/s    |      N     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|810A    |     N     |  N  | FAST10    | 10 MB/s    |      Y     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|815     |     Y     |  N  | FAST10    | 10 MB/s    |      N     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|825     |     Y     |  Y  | FAST10    | 20 MB/s    |      N     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|825A    |     Y     |  Y  | FAST10    | 20 MB/s    |      Y     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|860     |     N     |  N  | FAST20    | 20 MB/s    |      Y     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|875     |     Y     |  Y  | FAST20    | 40 MB/s    |      Y     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|875A    |     Y     |  Y  | FAST20    | 40 MB/s    |      Y     |    Y    |
+--------+-----------+-----+-----------+------------+------------+---------+
|876     |     Y     |  Y  | FAST20    | 40 MB/s    |      Y     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|895     |     Y     |  Y  | FAST40    | 80 MB/s    |      Y     |    N    |
+--------+-----------+-----+-----------+------------+------------+---------+
|895A    |     Y     |  Y  | FAST40    | 80 MB/s    |      Y     |    Y    |
+--------+-----------+-----+-----------+------------+------------+---------+
|896     |     Y     |  Y  | FAST40    | 80 MB/s    |      Y     |    Y    |
+--------+-----------+-----+-----------+------------+------------+---------+
|897     |     Y     |  Y  | FAST40    | 80 MB/s    |      Y     |    Y    |
+--------+-----------+-----+-----------+------------+------------+---------+
|1510D   |     Y     |  Y  | FAST40    | 80 MB/s    |      Y     |    Y    |
+--------+-----------+-----+-----------+------------+------------+---------+
|1010    |     Y     |  Y  | FAST80    |160 MB/s    |      Y     |    Y    |
+--------+-----------+-----+-----------+------------+------------+---------+
|1010_66 |     Y     |  Y  | FAST80    |160 MB/s    |      Y     |    Y    |
|[1]_    |           |     |           |            |            |         |
+--------+-----------+-----+-----------+------------+------------+---------+

.. [1] Chip supports 33MHz and 66MHz PCI bus clock.

Summary of other supported features:

:Module:                allow to load the driver
:Memory mapped I/O:     increases performance
:Control commands:      write operations to the proc SCSI file system
:Debugging information: written to syslog (expert only)
:Serial NVRAM:          Symbios and Tekram formats

- Scatter / gather
- Shared interrupt
- Boot setup commands

3. Advantages of this driver for newer chips.
=============================================

3.1 Optimized SCSI SCRIPTS
--------------------------

All chips except the 810, 815 and 825, support new SCSI SCRIPTS instructions
named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register
to/from memory much faster that the MOVE MEMORY instruction that is supported
by the 53c7xx and 53c8xx family.

The LOAD/STORE instructions support absolute and DSA relative addressing
modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead
of MOVE MEMORY instructions.

Due to the lack of LOAD/STORE SCRIPTS instructions by earlier chips, this
driver also incorporates a different SCRIPTS set based on MEMORY MOVE, in
order to provide support for the entire SYM53C8XX chips family.

3.2 New features appeared with the SYM53C896
--------------------------------------------

Newer chips (see above) allows handling of the phase mismatch context from
SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor
until the C code has saved the context of the transfer).

The 896 and 1010 chips support 64 bit PCI transactions and addressing,
while the 895A supports 32 bit PCI transactions and 64 bit addressing.
The SCRIPTS processor of these chips is not true 64 bit, but uses segment
registers for bit 32-63. Another interesting feature is that LOAD/STORE
instructions that address the on-chip RAM (8k) remain internal to the chip.

4. Memory mapped I/O versus normal I/O
======================================

Memory mapped I/O has less latency than normal I/O and is the recommended
way for doing IO with PCI devices. Memory mapped I/O seems to work fine on
most hardware configurations, but some poorly designed chipsets may break
this feature. A configuration option is provided for normal I/O to be
used but the driver defaults to MMIO.

5. Tagged command queueing
==========================

Queuing more than 1 command at a time to a device allows it to perform
optimizations based on actual head positions and its mechanical
characteristics. This feature may also reduce average command latency.
In order to really gain advantage of this feature, devices must have
a reasonable cache size (No miracle is to be expected for a low-end
hard disk with 128 KB or less).

Some known old SCSI devices do not properly support tagged command queuing.
Generally, firmware revisions that fix this kind of problems are available
at respective vendor web/ftp sites.

All I can say is that I never have had problem with tagged queuing using
this driver and its predecessors. Hard disks that behaved correctly for
me using tagged commands are the following:

- IBM S12 0662
- Conner 1080S
- Quantum Atlas I
- Quantum Atlas II
- Seagate Cheetah I
- Quantum Viking II
- IBM DRVS
- Quantum Atlas IV
- Seagate Cheetah II

If your controller has NVRAM, you can configure this feature per target
from the user setup tool. The Tekram Setup program allows to tune the
maximum number of queued commands up to 32. The Symbios Setup only allows
to enable or disable this feature.

The maximum number of simultaneous tagged commands queued to a device
is currently set to 16 by default.  This value is suitable for most SCSI
disks.  With large SCSI disks (>= 2GB, cache >= 512KB, average seek time
<= 10 ms), using a larger value may give better performances.

This driver supports up to 255 commands per device, and but using more than
64 is generally not worth-while, unless you are using a very large disk or
disk arrays. It is noticeable that most of recent hard disks seem not to
accept more than 64 simultaneous commands. So, using more than 64 queued
commands is probably just resource wasting.

If your controller does not have NVRAM or if it is managed by the SDMS
BIOS/SETUP, you can configure tagged queueing feature and device queue
depths from the boot command-line. For example::

  sym53c8xx=tags:4/t2t3q15-t4q7/t1u0q32

will set tagged commands queue depths as follow:

- target 2  all luns  on controller 0 --> 15
- target 3  all luns  on controller 0 --> 15
- target 4  all luns  on controller 0 -->  7
- target 1  lun 0     on controller 1 --> 32
- all other target/lun                -->  4

In some special conditions, some SCSI disk firmwares may return a
QUEUE FULL status for a SCSI command. This behaviour is managed by the
driver using the following heuristic:

- Each time a QUEUE FULL status is returned, tagged queue depth is reduced
  to the actual number of disconnected commands.

- Every 200 successfully completed SCSI commands, if allowed by the
  current limit, the maximum number of queueable commands is incremented.

Since QUEUE FULL status reception and handling is resource wasting, the
driver notifies by default this problem to user by indicating the actual
number of commands used and their status, as well as its decision on the
device queue depth change.
The heuristic used by the driver in handling QUEUE FULL ensures that the
impact on performances is not too bad. You can get rid of the messages by
setting verbose level to zero, as follow:

1st method:
	    boot your system using 'sym53c8xx=verb:0' option.
2nd method:
	    apply "setverbose 0" control command to the proc fs entry
            corresponding to your controller after boot-up.

6. Parity checking
==================

The driver supports SCSI parity checking and PCI bus master parity
checking.  These features must be enabled in order to ensure safe
data transfers.  Some flawed devices or mother boards may have problems
with parity.  The options to defeat parity checking have been removed
from the driver.

7. Profiling information
========================

This driver does not provide profiling information as did its predecessors.
This feature was not this useful and added complexity to the code.
As the driver code got more complex, I have decided to remove everything
that didn't seem actually useful.

8. Control commands
===================

Control commands can be sent to the driver with write operations to
the proc SCSI file system. The generic command syntax is the
following::

      echo "<verb> <parameters>" >/proc/scsi/sym53c8xx/0
      (assumes controller number is 0)

Using "all" for "<target>" parameter with the commands below will
apply to all targets of the SCSI chain (except the controller).

Available commands:

8.1 Set minimum synchronous period factor
-----------------------------------------

    setsync <target> <period factor>

    :target:   target number
    :period:   minimum synchronous period.
               Maximum speed = 1000/(4*period factor) except for special
               cases below.

    Specify a period of 0, to force asynchronous transfer mode.

     -  9 means 12.5 nano-seconds synchronous period
     - 10 means 25 nano-seconds synchronous period
     - 11 means 30 nano-seconds synchronous period
     - 12 means 50 nano-seconds synchronous period

8.2 Set wide size
-----------------

    setwide <target> <size>

    :target:   target number
    :size:     0=8 bits, 1=16bits

8.3 Set maximum number of concurrent tagged commands
----------------------------------------------------

    settags <target> <tags>

    :target:   target number
    :tags:     number of concurrent tagged commands
               must not be greater than configured (default: 16)

8.4 Set debug mode
------------------

    setdebug <list of debug flags>

    Available debug flags:

	======== ========================================================
        alloc    print info about memory allocations (ccb, lcb)
        queue    print info about insertions into the command start queue
        result   print sense data on CHECK CONDITION status
        scatter  print info about the scatter process
        scripts  print info about the script binding process
	tiny     print minimal debugging information
	timing   print timing information of the NCR chip
	nego     print information about SCSI negotiations
	phase    print information on script interruptions
	======== ========================================================

    Use "setdebug" with no argument to reset debug flags.

8.5 Set flag (no_disc)
----------------------

    setflag <target> <flag>

    :target:    target number

    For the moment, only one flag is available:

        no_disc:   not allow target to disconnect.

    Do not specify any flag in order to reset the flag. For example:

    setflag 4
      will reset no_disc flag for target 4, so will allow it disconnections.
    setflag all
      will allow disconnection for all devices on the SCSI bus.

8.6 Set verbose level
---------------------

    setverbose #level

    The driver default verbose level is 1. This command allows to change
    th driver verbose level after boot-up.

8.7 Reset all logical units of a target
---------------------------------------

    resetdev <target>

    :target:    target number

    The driver will try to send a BUS DEVICE RESET message to the target.

8.8 Abort all tasks of all logical units of a target
----------------------------------------------------

    cleardev <target>

    :target:    target number

    The driver will try to send a ABORT message to all the logical units
    of the target.

9. Configuration parameters
===========================

Under kernel configuration tools (make menuconfig, for example), it is
possible to change some default driver configuration parameters.
If the firmware of all your devices is perfect enough, all the
features supported by the driver can be enabled at start-up. However,
if only one has a flaw for some SCSI feature, you can disable the
support by the driver of this feature at linux start-up and enable
this feature after boot-up only for devices that support it safely.

Configuration parameters:

Use normal IO                         (default answer: n)
    Answer "y" if you suspect your mother board to not allow memory mapped I/O.
    May slow down performance a little.

Default tagged command queue depth    (default answer: 16)
    Entering 0 defaults to tagged commands not being used.
    This parameter can be specified from the boot command line.

Maximum number of queued commands     (default answer: 32)
    This option allows you to specify the maximum number of tagged commands
    that can be queued to a device. The maximum supported value is 255.

Synchronous transfers frequency       (default answer: 80)
    This option allows you to specify the frequency in MHz the driver
    will use at boot time for synchronous data transfer negotiations.
    0 means "asynchronous data transfers".

10. Boot setup commands
=======================

10.1 Syntax
-----------

Setup commands can be passed to the driver either at boot time or as
parameters to modprobe, as described in Documentation/admin-guide/kernel-parameters.rst

Example of boot setup command under lilo prompt::

    lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200

- enable tagged commands, up to 4 tagged commands queued.
- set synchronous negotiation speed to 10 Mega-transfers / second.
- set DEBUG_NEGO flag.

The following command will install the driver module with the same
options as above::

    modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200

10.2 Available arguments
------------------------

10.2.1  Default number of tagged commands
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        - cmd_per_lun=0 (or cmd_per_lun=1) tagged command queuing disabled
        - cmd_per_lun=#tags (#tags > 1) tagged command queuing enabled

  #tags will be truncated to the max queued commands configuration parameter.

10.2.2 Burst max
^^^^^^^^^^^^^^^^

	========== ======================================================
        burst=0    burst disabled
        burst=255  get burst length from initial IO register settings.
        burst=#x   burst enabled (1<<#x burst transfers max)

		   #x is an integer value which is log base 2 of the burst
		   transfers max.
	========== ======================================================

  By default the driver uses the maximum value supported by the chip.

10.2.3 LED support
^^^^^^^^^^^^^^^^^^

	=====      ===================
        led=1      enable  LED support
        led=0      disable LED support
	=====      ===================

  Do not enable LED support if your scsi board does not use SDMS BIOS.
  (See 'Configuration parameters')

10.2.4 Differential mode
^^^^^^^^^^^^^^^^^^^^^^^^

	======	=================================
	diff=0	never set up diff mode
        diff=1	set up diff mode if BIOS set it
        diff=2	always set up diff mode
        diff=3	set diff mode if GPIO3 is not set
	======	=================================

10.2.5 IRQ mode
^^^^^^^^^^^^^^^

	======     ================================================
        irqm=0     always open drain
        irqm=1     same as initial settings (assumed BIOS settings)
        irqm=2     always totem pole
	======     ================================================

10.2.6 Check SCSI BUS
^^^^^^^^^^^^^^^^^^^^^

        buschk=<option bits>

    Available option bits:

	===    ================================================
        0x0    No check.
        0x1    Check and do not attach the controller on error.
        0x2    Check and just warn on error.
	===    ================================================

10.2.7 Suggest a default SCSI id for hosts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

	==========	==========================================
        hostid=255	no id suggested.
        hostid=#x	(0 < x < 7) x suggested for hosts SCSI id.
	==========	==========================================

    If a host SCSI id is available from the NVRAM, the driver will ignore
    any value suggested as boot option. Otherwise, if a suggested value
    different from 255 has been supplied, it will use it. Otherwise, it will
    try to deduce the value previously set in the hardware and use value
    7 if the hardware value is zero.

10.2.8  Verbosity level
^^^^^^^^^^^^^^^^^^^^^^^

	======     ========
        verb=0     minimal
        verb=1     normal
        verb=2     too much
	======     ========

10.2.9 Debug mode
^^^^^^^^^^^^^^^^^

	=========   ====================================
        debug=0	    clear debug flags
        debug=#x    set debug flags

		    #x is an integer value combining the
		    following power-of-2 values:

		    =============  ======
		    DEBUG_ALLOC       0x1
		    DEBUG_PHASE       0x2
		    DEBUG_POLL        0x4
		    DEBUG_QUEUE       0x8
		    DEBUG_RESULT     0x10
		    DEBUG_SCATTER    0x20
		    DEBUG_SCRIPT     0x40
		    DEBUG_TINY       0x80
		    DEBUG_TIMING    0x100
		    DEBUG_NEGO      0x200
		    DEBUG_TAGS      0x400
		    DEBUG_FREEZE    0x800
		    DEBUG_RESTART  0x1000
		    =============  ======
	=========   ====================================

  You can play safely with DEBUG_NEGO. However, some of these flags may
  generate bunches of syslog messages.

10.2.10 Settle delay
^^^^^^^^^^^^^^^^^^^^

	========	===================
        settle=n	delay for n seconds
	========	===================

  After a bus reset, the driver will delay for n seconds before talking
  to any device on the bus.  The default is 3 seconds and safe mode will
  default it to 10.

10.2.11 Serial NVRAM
^^^^^^^^^^^^^^^^^^^^

	.. Note:: option not currently implemented.

	=======     =========================================
        nvram=n     do not look for serial NVRAM
        nvram=y     test controllers for onboard serial NVRAM
	=======     =========================================

        (alternate binary form)

        nvram=<bits options>

        ====   =================================================================
        0x01   look for NVRAM  (equivalent to nvram=y)
        0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
        0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
        0x08   ignore NVRAM "Scan at boot time" parameter for all devices
        0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
        ====   =================================================================

10.2.12 Exclude a host from being attached
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        excl=<io_address>,...

    Prevent host at a given io address from being attached.
    For example 'excl=0xb400,0xc000' indicate to the
    driver not to attach hosts at address 0xb400 and 0xc000.

10.3 Converting from old style options
--------------------------------------

Previously, the sym2 driver accepted arguments of the form::

	sym53c8xx=tags:4,sync:10,debug:0x200

As a result of the new module parameters, this is no longer available.
Most of the options have remained the same, but tags has become
cmd_per_lun to reflect its different purposes.  The sample above would
be specified as::

	modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200

or on the kernel boot line as::

	sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200

10.4 SCSI BUS checking boot option
----------------------------------

When this option is set to a non-zero value, the driver checks SCSI lines
logic state, 100 micro-seconds after having asserted the SCSI RESET line.
The driver just reads SCSI lines and checks all lines read FALSE except RESET.
Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI
RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem.
Unfortunately, the following common SCSI BUS problems are not detected:

- Only 1 terminator installed.
- Misplaced terminators.
- Bad quality terminators.

On the other hand, either bad cabling, broken devices, not conformant
devices, ... may cause a SCSI signal to be wrong when te driver reads it.

15. SCSI problem troubleshooting
================================

15.1 Problem tracking
---------------------

Most SCSI problems are due to a non conformant SCSI bus or too buggy
devices.  If unfortunately you have SCSI problems, you can check the
following things:

- SCSI bus cables
- terminations at both end of the SCSI chain
- linux syslog messages (some of them may help you)

If you do not find the source of problems, you can configure the
driver or devices in the NVRAM with minimal features.

- only asynchronous data transfers
- tagged commands disabled
- disconnections not allowed

Now, if your SCSI bus is ok, your system has every chance to work
with this safe configuration but performances will not be optimal.

If it still fails, then you can send your problem description to
appropriate mailing lists or news-groups.  Send me a copy in order to
be sure I will receive it.  Obviously, a bug in the driver code is
possible.

  My current email address: Gerard Roudier <groudier@free.fr>

Allowing disconnections is important if you use several devices on
your SCSI bus but often causes problems with buggy devices.
Synchronous data transfers increases throughput of fast devices like
hard disks.  Good SCSI hard disks with a large cache gain advantage of
tagged commands queuing.

15.2 Understanding hardware error reports
-----------------------------------------

When the driver detects an unexpected error condition, it may display a
message of the following pattern::

    sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
    sym0: script cmd = 19000000
    sym0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00.

Some fields in such a message may help you understand the cause of the
problem, as follows::

    sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
    .....A.........B.C....D.E..F....G.H..I.......J.....K...L.......

Field A : target number.
  SCSI ID of the device the controller was talking with at the moment the
  error occurs.

Field B : DSTAT io register (DMA STATUS)
  ========   =============================================================
  Bit 0x40   MDPE Master Data Parity Error
             Data parity error detected on the PCI BUS.
  Bit 0x20   BF   Bus Fault
             PCI bus fault condition detected
  Bit 0x01   IID  Illegal Instruction Detected
             Set by the chip when it detects an Illegal Instruction format
             on some condition that makes an instruction illegal.
  Bit 0x80   DFE Dma Fifo Empty
             Pure status bit that does not indicate an error.
  ========   =============================================================

  If the reported DSTAT value contains a combination of MDPE (0x40),
  BF (0x20), then the cause may be likely due to a PCI BUS problem.

Field C : SIST io register (SCSI Interrupt Status)
  ========   ==================================================================
  Bit 0x08   SGE  SCSI GROSS ERROR
             Indicates that the chip detected a severe error condition
             on the SCSI BUS that prevents the SCSI protocol from functioning
             properly.
  Bit 0x04   UDC  Unexpected Disconnection
             Indicates that the device released the SCSI BUS when the chip
             was not expecting this to happen. A device may behave so to
             indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occurred.
  Bit 0x02   RST  SCSI BUS Reset
             Generally SCSI targets do not reset the SCSI BUS, although any
             device on the BUS can reset it at any time.
  Bit 0x01   PAR  Parity
             SCSI parity error detected.
  ========   ==================================================================

  On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and
  PAR (0x01) may be detected by the chip. If your SCSI system sometimes
  encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI
  BUS problem is likely the cause of these errors.

For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file
that contains some minimal comments on IO register bits.

Field D : SOCL  Scsi Output Control Latch
          This register reflects the state of the SCSI control lines the
          chip want to drive or compare against.
Field E : SBCL  Scsi Bus Control Lines
          Actual value of control lines on the SCSI BUS.
Field F : SBDL  Scsi Bus Data Lines
          Actual value of data lines on the SCSI BUS.
Field G : SXFER  SCSI Transfer
          Contains the setting of the Synchronous Period for output and
          the current Synchronous offset (offset 0 means asynchronous).
Field H : SCNTL3 Scsi Control Register 3
          Contains the setting of timing values for both asynchronous and
          synchronous data transfers.
Field I : SCNTL4 Scsi Control Register 4
          Only meaningful for 53C1010 Ultra3 controllers.

Understanding Fields J, K, L and dumps requires to have good knowledge of
SCSI standards, chip cores functionnals and internal driver data structures.
You are not required to decode and understand them, unless you want to help
maintain the driver code.

17. Serial NVRAM (added by Richard Waltham: dormouse@farsrobt.demon.co.uk)
==========================================================================

17.1 Features
-------------

Enabling serial NVRAM support enables detection of the serial NVRAM included
on Symbios and some Symbios compatible host adaptors, and Tekram boards. The
serial NVRAM is used by Symbios and Tekram to hold set up parameters for the
host adaptor and its attached drives.

The Symbios NVRAM also holds data on the boot order of host adaptors in a
system with more than one host adaptor.  This information is no longer used
as it's fundamentally incompatible with the hotplug PCI model.

Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
and this is used to distinguish between Symbios compatible and Tekram host
adaptors. This is used to disable the Symbios compatible "diff" setting
incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT
configuration parameter is set enabling both Symbios and Tekram boards to be
used together with the Symbios cards using all their features, including
"diff" support. ("led pin" support for Symbios compatible cards can remain
enabled when using Tekram cards. It does nothing useful for Tekram host
adaptors but does not cause problems either.)

The parameters the driver is able to get from the NVRAM depend on the
data format used, as follow:

+-------------------------------+------------------+--------------+
|                               |Tekram format     |Symbios format|
+-------------------------------+------------------+--------------+
|General and host parameters    |                  |              |
+-------------------------------+------------------+--------------+
|  * Boot order                 |        N         |       Y      |
+-------------------------------+------------------+--------------+
|  * Host SCSI ID               |        Y         |       Y      |
+-------------------------------+------------------+--------------+
|  * SCSI parity checking       |        Y         |       Y      |
+-------------------------------+------------------+--------------+
|  * Verbose boot messages      |        N         |       Y      |
+-------------------------------+------------------+--------------+
|SCSI devices parameters                                          |
+-------------------------------+------------------+--------------+
|  * Synchronous transfer speed |        Y         |       Y      |
+-------------------------------+------------------+--------------+
|  * Wide 16 / Narrow           |        Y         |       Y      |
+-------------------------------+------------------+--------------+
|  * Tagged Command Queuing     |        Y         |       Y      |
|    enabled                    |                  |              |
+-------------------------------+------------------+--------------+
|  * Disconnections enabled     |        Y         |       Y      |
+-------------------------------+------------------+--------------+
|  * Scan at boot time          |        N         |       Y      |
+-------------------------------+------------------+--------------+

In order to speed up the system boot, for each device configured without
the "scan at boot time" option, the driver forces an error on the
first TEST UNIT READY command received for this device.

17.2 Symbios NVRAM layout
-------------------------

typical data at NVRAM address 0x100 (53c810a NVRAM)::

    00 00
    64 01
    8e 0b

    00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00

    04 00 0f 00 00 10 00 50 00 00 01 00 00 62
    04 00 03 00 00 10 00 58 00 00 01 00 00 63
    04 00 01 00 00 10 00 48 00 00 01 00 00 61
    00 00 00 00 00 00 00 00 00 00 00 00 00 00

    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00

    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00

    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00

    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00

    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00

    fe fe
    00 00
    00 00

NVRAM layout details

============= =================
NVRAM Address
============= =================
0x000-0x0ff   not used
0x100-0x26f   initialised data
0x270-0x7ff   not used
============= =================

general layout::

        header  -   6 bytes,
        data    - 356 bytes (checksum is byte sum of this data)
        trailer -   6 bytes
                  ---
        total     368 bytes

data area layout::

        controller set up  -  20 bytes
        boot configuration -  56 bytes (4x14 bytes)
        device set up      - 128 bytes (16x8 bytes)
        unused (spare?)    - 152 bytes (19x8 bytes)
                             ---
        total                356 bytes

header::

    00 00   - ?? start marker
    64 01   - byte count (lsb/msb excludes header/trailer)
    8e 0b   - checksum (lsb/msb excludes header/trailer)

controller set up::

    00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00
		    |     |           |     |
		    |     |           |      -- host ID
		    |     |           |
		    |     |            --Removable Media Support
		    |     |               0x00 = none
		    |     |               0x01 = Bootable Device
		    |     |               0x02 = All with Media
		    |     |
		    |      --flag bits 2
		    |        0x00000001= scan order hi->low
		    |            (default 0x00 - scan low->hi)
			--flag bits 1
			0x00000001 scam enable
			0x00000010 parity enable
			0x00000100 verbose boot msgs

remaining bytes unknown - they do not appear to change in my
current set up for any of the controllers.

default set up is identical for 53c810a and 53c875 NVRAM
(Removable Media added Symbios BIOS version 4.09)

boot configuration

boot order set by order of the devices in this table::

    04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller
    04 00 03 00 00 10 00 58 00 00 01 00 00 63    2nd controller
    04 00 01 00 00 10 00 48 00 00 01 00 00 61    3rd controller
    00 00 00 00 00 00 00 00 00 00 00 00 00 00    4th controller
	|  |  |  |     |        |     |  |
	|  |  |  |     |        |      ---- PCI io port adr
	|  |  |  |     |         --0x01 init/scan at boot time
	|  |  |  |      --PCI device/function number (0xdddddfff)
	|  |   ----- ?? PCI vendor ID (lsb/msb)
	    ----PCI device ID (lsb/msb)

?? use of this data is a guess but seems reasonable

remaining bytes unknown - they do not appear to change in my
current set up

default set up is identical for 53c810a and 53c875 NVRAM

device set up (up to 16 devices - includes controller)::

    0f 00 08 08 64 00 0a 00 - id 0
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00

    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00
    0f 00 08 08 64 00 0a 00 - id 15
    |     |  |  |     |  |
    |     |  |  |      ----timeout (lsb/msb)
    |     |  |   --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28)
    |     |  |                  (0x30 20 Mtrans/sec- fast 20)
    |     |  |                  (0x64 10 Mtrans/sec- fast )
    |     |  |                  (0xc8  5 Mtrans/sec)
    |     |  |                  (0x00  asynchronous)
    |     |   -- ?? max sync offset (0x08 in NVRAM on 53c810a)
    |     |                         (0x10 in NVRAM on 53c875)
    |      --device bus width (0x08 narrow)
    |                         (0x10 16 bit wide)
    --flag bits
	0x00000001 - disconnect enabled
	0x00000010 - scan at boot time
	0x00000100 - scan luns
	0x00001000 - queue tags enabled

remaining bytes unknown - they do not appear to change in my
current set up

?? use of this data is a guess but seems reasonable
(but it could be max bus width)

default set up for 53c810a NVRAM
default set up for 53c875 NVRAM

				- bus width     - 0x10
                                - sync offset ? - 0x10
                                - sync period   - 0x30

?? spare device space (32 bit bus ??)::

    00 00 00 00 00 00 00 00  (19x8bytes)
    .
    .
    00 00 00 00 00 00 00 00

default set up is identical for 53c810a and 53c875 NVRAM

trailer::

    fe fe   - ? end marker ?
    00 00
    00 00

default set up is identical for 53c810a and 53c875 NVRAM

17.3 Tekram NVRAM layout
------------------------

nvram 64x16 (1024 bit)

Drive settings::

    Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID)
		(addr 0x0yyyy1 = 0x0000)

	x x x x  x x x x  x x x x  x x x x
		| | |      | |  | | | |
		| | |      | |  | | |  ----- parity check   0 - off
		| | |      | |  | | |                       1 - on
		| | |      | |  | | |
		| | |      | |  | |  ------- sync neg       0 - off
		| | |      | |  | |                         1 - on
		| | |      | |  | |
		| | |      | |  |  --------- disconnect     0 - off
		| | |      | |  |                           1 - on
		| | |      | |  |
		| | |      | |   ----------- start cmd      0 - off
		| | |      | |                              1 - on
		| | |      | |
		| | |      |  -------------- tagged cmds    0 - off
		| | |      |                                1 - on
		| | |      |
		| | |       ---------------- wide neg       0 - off
		| | |                                       1 - on
		| | |
		    --------------------------- sync rate      0 - 10.0 Mtrans/sec
							    1 -  8.0
							    2 -  6.6
							    3 -  5.7
							    4 -  5.0
							    5 -  4.0
							    6 -  3.0
							    7 -  2.0
							    7 -  2.0
							    8 - 20.0
							    9 - 16.7
							    a - 13.9
							    b - 11.9

Global settings

Host flags 0 (addr 0x100000, 32)::

    x x x x  x x x x  x x x x  x x x x
    | | | |  | | | |           | | | |
    | | | |  | | | |            ----------- host ID    0x00 - 0x0f
    | | | |  | | | |
    | | | |  | | |  ----------------------- support for    0 - off
    | | | |  | | |                          > 2 drives     1 - on
    | | | |  | | |
    | | | |  | |  ------------------------- support drives 0 - off
    | | | |  | |                            > 1Gbytes      1 - on
    | | | |  | |
    | | | |  |  --------------------------- bus reset on   0 - off
    | | | |  |                                power on     1 - on
    | | | |  |
    | | | |   ----------------------------- active neg     0 - off
    | | | |                                                1 - on
    | | | |
    | | |  -------------------------------- imm seek       0 - off
    | | |                                                  1 - on
    | | |
    | |  ---------------------------------- scan luns      0 - off
    | |                                                    1 - on
    | |
     -------------------------------------- removable      0 - disable
                                            as BIOS dev    1 - boot device
                                                           2 - all

Host flags 1 (addr 0x100001, 33)::

    x x x x  x x x x  x x x x  x x x x
               | | |             | | |
               | | |              --------- boot delay     0 -   3 sec
               | | |                                       1 -   5
               | | |                                       2 -  10
               | | |                                       3 -  20
               | | |                                       4 -  30
               | | |                                       5 -  60
               | | |                                       6 - 120
               | | |
                --------------------------- max tag cmds   0 -  2
                                                           1 -  4
                                                           2 -  8
                                                           3 - 16
                                                           4 - 32

Host flags 2 (addr 0x100010, 34)::

    x x x x  x x x x  x x x x  x x x x
                                     |
                                      ----- F2/F6 enable   0 - off ???
                                                           1 - on  ???

checksum (addr 0x111111)

checksum = 0x1234 - (sum addr 0-63)

----------------------------------------------------------------------------

default nvram data::

    0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
    0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
    0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
    0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000

    0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000
    0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
    0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
    0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc


code:
.. SPDX-License-Identifier: GPL-2.0

========================
tcm_qla2xxx Driver Notes
========================

tcm_qla2xxx jam_host attribute
------------------------------
There is now a new module endpoint atribute called jam_host
attribute::

	jam_host: boolean=0/1

This attribute and accompanying code is only included if the
Kconfig parameter TCM_QLA2XXX_DEBUG is set to Y

By default this jammer code and functionality is disabled

Use this attribute to control the discarding of SCSI commands to a
selected host.

This may be useful for testing error handling and simulating slow drain
and other fabric issues.

Setting a boolean of 1 for the jam_host attribute for a particular host
will discard the commands for that host.

Reset back to 0 to stop the jamming.

Enable host 4 to be jammed::

  echo 1 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host

Disable jamming on host 4::

  echo 0 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host

repo_name: angery/linux


code:
.. SPDX-License-Identifier: GPL-2.0

=======================
Universal Flash Storage
=======================

.. Contents

   1. Overview
   2. UFS Architecture Overview
     2.1 Application Layer
     2.2 UFS Transport Protocol (UTP) layer
     2.3 UFS Interconnect (UIC) Layer
   3. UFSHCD Overview
     3.1 UFS controller initialization
     3.2 UTP Transfer requests
     3.3 UFS error handling
     3.4 SCSI Error handling
   4. BSG Support
   5. UFS Reference Clock Frequency configuration

1. Overview
===========

Universal Flash Storage (UFS) is a storage specification for flash devices.
It aims to provide a universal storage interface for both
embedded and removable flash memory-based storage in mobile
devices such as smart phones and tablet computers. The specification
is defined by JEDEC Solid State Technology Association. UFS is based
on the MIPI M-PHY physical layer standard. UFS uses MIPI M-PHY as the
physical layer and MIPI Unipro as the link layer.

The main goals of UFS are to provide:

 * Optimized performance:

   For UFS version 1.0 and 1.1 the target performance is as follows:

   - Support for Gear1 is mandatory (rate A: 1248Mbps, rate B: 1457.6Mbps)
   - Support for Gear2 is optional (rate A: 2496Mbps, rate B: 2915.2Mbps)

   Future version of the standard,

   - Gear3 (rate A: 4992Mbps, rate B: 5830.4Mbps)

 * Low power consumption
 * High random IOPs and low latency

2. UFS Architecture Overview
============================

UFS has a layered communication architecture which is based on SCSI
SAM-5 architectural model.

UFS communication architecture consists of the following layers.

2.1 Application Layer
---------------------

  The Application layer is composed of the UFS command set layer (UCS),
  Task Manager and Device manager. The UFS interface is designed to be
  protocol agnostic, however SCSI has been selected as a baseline
  protocol for versions 1.0 and 1.1 of the UFS protocol layer.

  UFS supports a subset of SCSI commands defined by SPC-4 and SBC-3.

  * UCS:
     It handles SCSI commands supported by UFS specification.
  * Task manager:
     It handles task management functions defined by the
     UFS which are meant for command queue control.
  * Device manager:
     It handles device level operations and device
     configuration operations. Device level operations mainly involve
     device power management operations and commands to Interconnect
     layers. Device level configurations involve handling of query
     requests which are used to modify and retrieve configuration
     information of the device.

2.2 UFS Transport Protocol (UTP) layer
--------------------------------------

  The UTP layer provides services for
  the higher layers through Service Access Points. UTP defines 3
  service access points for higher layers.

  * UDM_SAP: Device manager service access point is exposed to device
    manager for device level operations. These device level operations
    are done through query requests.
  * UTP_CMD_SAP: Command service access point is exposed to UFS command
    set layer (UCS) to transport commands.
  * UTP_TM_SAP: Task management service access point is exposed to task
    manager to transport task management functions.

  UTP transports messages through UFS protocol information unit (UPIU).

2.3 UFS Interconnect (UIC) Layer
--------------------------------

  UIC is the lowest layer of the UFS layered architecture. It handles
  the connection between UFS host and UFS device. UIC consists of
  MIPI UniPro and MIPI M-PHY. UIC provides 2 service access points
  to upper layer:

  * UIC_SAP: To transport UPIU between UFS host and UFS device.
  * UIO_SAP: To issue commands to Unipro layers.

3. UFSHCD Overview
==================

The UFS host controller driver is based on the Linux SCSI Framework.
UFSHCD is a low-level device driver which acts as an interface between
the SCSI Midlayer and PCIe-based UFS host controllers.

The current UFSHCD implementation supports the following functionality:

3.1 UFS controller initialization
---------------------------------

  The initialization module brings the UFS host controller to active state
  and prepares the controller to transfer commands/responses between
  UFSHCD and UFS device.

3.2 UTP Transfer requests
-------------------------

  Transfer request handling module of UFSHCD receives SCSI commands
  from the SCSI Midlayer, forms UPIUs and issues the UPIUs to the UFS Host
  controller. Also, the module decodes responses received from the UFS
  host controller in the form of UPIUs and intimates the SCSI Midlayer
  of the status of the command.

3.3 UFS error handling
----------------------

  Error handling module handles Host controller fatal errors,
  Device fatal errors and UIC interconnect layer-related errors.

3.4 SCSI Error handling
-----------------------

  This is done through UFSHCD SCSI error handling routines registered
  with the SCSI Midlayer. Examples of some of the error handling commands
  issues by the SCSI Midlayer are Abort task, LUN reset and host reset.
  UFSHCD Routines to perform these tasks are registered with
  SCSI Midlayer through .eh_abort_handler, .eh_device_reset_handler and
  .eh_host_reset_handler.

In this version of UFSHCD, Query requests and power management
functionality are not implemented.

4. BSG Support
==============

This transport driver supports exchanging UFS protocol information units
(UPIUs) with a UFS device. Typically, user space will allocate
struct ufs_bsg_request and struct ufs_bsg_reply (see ufs_bsg.h) as
request_upiu and reply_upiu respectively.  Filling those UPIUs should
be done in accordance with JEDEC spec UFS2.1 paragraph 10.7.
*Caveat emptor*: The driver makes no further input validations and sends the
UPIU to the device as it is.  Open the bsg device in /dev/ufs-bsg and
send SG_IO with the applicable sg_io_v4::

	io_hdr_v4.guard = 'Q';
	io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
	io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
	io_hdr_v4.response = (__u64)reply_upiu;
	io_hdr_v4.max_response_len = reply_len;
	io_hdr_v4.request_len = request_len;
	io_hdr_v4.request = (__u64)request_upiu;
	if (dir == SG_DXFER_TO_DEV) {
		io_hdr_v4.dout_xfer_len = (uint32_t)byte_cnt;
		io_hdr_v4.dout_xferp = (uintptr_t)(__u64)buff;
	} else {
		io_hdr_v4.din_xfer_len = (uint32_t)byte_cnt;
		io_hdr_v4.din_xferp = (uintptr_t)(__u64)buff;
	}

If you wish to read or write a descriptor, use the appropriate xferp of
sg_io_v4.

The userspace tool that interacts with the ufs-bsg endpoint and uses its
UPIU-based protocol is available at:

	https://github.com/westerndigitalcorporation/ufs-tool

For more detailed information about the tool and its supported
features, please see the tool's README.

UFS specifications can be found at:

- UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf
- UFSHCI - http://www.jedec.org/sites/default/files/docs/JESD223.pdf

5. UFS Reference Clock Frequency configuration
==============================================

Devicetree can define a clock named "ref_clk" under the UFS controller node
to specify the intended reference clock frequency for the UFS storage
parts. ACPI-based system can specify the frequency using ACPI
Device-Specific Data property named "ref-clk-freq". In both ways the value
is interpreted as frequency in Hz and must match one of the values given in
the UFS specification. UFS subsystem will attempt to read the value when
executing common controller initialization. If the value is available, UFS
subsytem will ensure the bRefClkFreq attribute of the UFS storage device is
set accordingly and will modify it if there is a mismatch.


code:
.. SPDX-License-Identifier: GPL-2.0

===============================================================
Driver for Western Digital WD7193, WD7197 and WD7296 SCSI cards
===============================================================

The card requires firmware that can be cut out of the Windows NT driver that
can be downloaded from WD at:
http://support.wdc.com/product/download.asp?groupid=801&sid=27&lang=en

There is no license anywhere in the file or on the page - so the firmware
probably cannot be added to linux-firmware.

This script downloads and extracts the firmware, creating wd719x-risc.bin and
d719x-wcs.bin files. Put them in /lib/firmware/::

	#!/bin/sh
	wget http://support.wdc.com/download/archive/pciscsi.exe
	lha xi pciscsi.exe pci-scsi.exe
	lha xi pci-scsi.exe nt/wd7296a.sys
	rm pci-scsi.exe
	dd if=wd7296a.sys of=wd719x-risc.bin bs=1 skip=5760 count=14336
	dd if=wd7296a.sys of=wd719x-wcs.bin bs=1 skip=20096 count=514
	rm wd7296a.sys


code:
=================================
IMA Template Management Mechanism
=================================

Introduction
============

The original ``ima`` template is fixed length, containing the filedata hash
and pathname. The filedata hash is limited to 20 bytes (md5/sha1).
The pathname is a null terminated string, limited to 255 characters.
To overcome these limitations and to add additional file metadata, it is
necessary to extend the current version of IMA by defining additional
templates. For example, information that could be possibly reported are
the inode UID/GID or the LSM labels either of the inode and of the process
that is accessing it.

However, the main problem to introduce this feature is that, each time
a new template is defined, the functions that generate and display
the measurements list would include the code for handling a new format
and, thus, would significantly grow over the time.

The proposed solution solves this problem by separating the template
management from the remaining IMA code. The core of this solution is the
definition of two new data structures: a template descriptor, to determine
which information should be included in the measurement list; a template
field, to generate and display data of a given type.

Managing templates with these structures is very simple. To support
a new data type, developers define the field identifier and implement
two functions, init() and show(), respectively to generate and display
measurement entries. Defining a new template descriptor requires
specifying the template format (a string of field identifiers separated
by the ``|`` character) through the ``ima_template_fmt`` kernel command line
parameter. At boot time, IMA initializes the chosen template descriptor
by translating the format into an array of template fields structures taken
from the set of the supported ones.

After the initialization step, IMA will call ``ima_alloc_init_template()``
(new function defined within the patches for the new template management
mechanism) to generate a new measurement entry by using the template
descriptor chosen through the kernel configuration or through the newly
introduced ``ima_template`` and ``ima_template_fmt`` kernel command line parameters.
It is during this phase that the advantages of the new architecture are
clearly shown: the latter function will not contain specific code to handle
a given template but, instead, it simply calls the ``init()`` method of the template
fields associated to the chosen template descriptor and store the result
(pointer to allocated data and data length) in the measurement entry structure.

The same mechanism is employed to display measurements entries.
The functions ``ima[_ascii]_measurements_show()`` retrieve, for each entry,
the template descriptor used to produce that entry and call the show()
method for each item of the array of template fields structures.

Supported Template Fields and Descriptors
=========================================

In the following, there is the list of supported template fields
``('<identifier>': description)``, that can be used to define new template
descriptors by adding their identifier to the format string
(support for more data types will be added later):

 - 'd': the digest of the event (i.e. the digest of a measured file),
   calculated with the SHA1 or MD5 hash algorithm;
 - 'n': the name of the event (i.e. the file name), with size up to 255 bytes;
 - 'd-ng': the digest of the event, calculated with an arbitrary hash
   algorithm (field format: <hash algo>:digest);
 - 'd-ngv2': same as d-ng, but prefixed with the "ima" or "verity" digest type
   (field format: <digest type>:<hash algo>:digest);
 - 'd-modsig': the digest of the event without the appended modsig;
 - 'n-ng': the name of the event, without size limitations;
 - 'sig': the file signature, based on either the file's/fsverity's digest[1],
   or the EVM portable signature, if 'security.ima' contains a file hash.
 - 'modsig' the appended file signature;
 - 'buf': the buffer data that was used to generate the hash without size limitations;
 - 'evmsig': the EVM portable signature;
 - 'iuid': the inode UID;
 - 'igid': the inode GID;
 - 'imode': the inode mode;
 - 'xattrnames': a list of xattr names (separated by ``|``), only if the xattr is
    present;
 - 'xattrlengths': a list of xattr lengths (u32), only if the xattr is present;
 - 'xattrvalues': a list of xattr values;

Below, there is the list of defined template descriptors:

 - "ima": its format is ``d|n``;
 - "ima-ng" (default): its format is ``d-ng|n-ng``;
 - "ima-ngv2": its format is ``d-ngv2|n-ng``;
 - "ima-sig": its format is ``d-ng|n-ng|sig``;
 - "ima-sigv2": its format is ``d-ngv2|n-ng|sig``;
 - "ima-buf": its format is ``d-ng|n-ng|buf``;
 - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
 - "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;

Use
===

To specify the template descriptor to be used to generate measurement entries,
currently the following methods are supported:

 - select a template descriptor among those supported in the kernel
   configuration (``ima-ng`` is the default choice);
 - specify a template descriptor name from the kernel command line through
   the ``ima_template=`` parameter;
 - register a new template descriptor with custom format through the kernel
   command line parameter ``ima_template_fmt=``.


code:
.. SPDX-License-Identifier: GPL-2.0

====
SCTP
====

SCTP LSM Support
================

Security Hooks
--------------

For security module support, three SCTP specific hooks have been implemented::

    security_sctp_assoc_request()
    security_sctp_bind_connect()
    security_sctp_sk_clone()
    security_sctp_assoc_established()

The usage of these hooks are described below with the SELinux implementation
described in the `SCTP SELinux Support`_ chapter.

security_sctp_assoc_request()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passes the ``@asoc`` and ``@chunk->skb`` of the association INIT packet to the
security module. Returns 0 on success, error on failure.
::

    @asoc - pointer to sctp association structure.
    @skb - pointer to skbuff of association packet.

security_sctp_bind_connect()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passes one or more ipv4/ipv6 addresses to the security module for validation
based on the ``@optname`` that will result in either a bind or connect
service as shown in the permission check tables below.
Returns 0 on success, error on failure.
::

    @sk      - Pointer to sock structure.
    @optname - Name of the option to validate.
    @address - One or more ipv4 / ipv6 addresses.
    @addrlen - The total length of address(s). This is calculated on each
               ipv4 or ipv6 address using sizeof(struct sockaddr_in) or
               sizeof(struct sockaddr_in6).

  ------------------------------------------------------------------
  |                     BIND Type Checks                           |
  |       @optname             |         @address contains         |
  |----------------------------|-----------------------------------|
  | SCTP_SOCKOPT_BINDX_ADD     | One or more ipv4 / ipv6 addresses |
  | SCTP_PRIMARY_ADDR          | Single ipv4 or ipv6 address       |
  | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address       |
  ------------------------------------------------------------------

  ------------------------------------------------------------------
  |                   CONNECT Type Checks                          |
  |       @optname             |         @address contains         |
  |----------------------------|-----------------------------------|
  | SCTP_SOCKOPT_CONNECTX      | One or more ipv4 / ipv6 addresses |
  | SCTP_PARAM_ADD_IP          | One or more ipv4 / ipv6 addresses |
  | SCTP_SENDMSG_CONNECT       | Single ipv4 or ipv6 address       |
  | SCTP_PARAM_SET_PRIMARY     | Single ipv4 or ipv6 address       |
  ------------------------------------------------------------------

A summary of the ``@optname`` entries is as follows::

    SCTP_SOCKOPT_BINDX_ADD - Allows additional bind addresses to be
                             associated after (optionally) calling
                             bind(3).
                             sctp_bindx(3) adds a set of bind
                             addresses on a socket.

    SCTP_SOCKOPT_CONNECTX - Allows the allocation of multiple
                            addresses for reaching a peer
                            (multi-homed).
                            sctp_connectx(3) initiates a connection
                            on an SCTP socket using multiple
                            destination addresses.

    SCTP_SENDMSG_CONNECT  - Initiate a connection that is generated by a
                            sendmsg(2) or sctp_sendmsg(3) on a new asociation.

    SCTP_PRIMARY_ADDR     - Set local primary address.

    SCTP_SET_PEER_PRIMARY_ADDR - Request peer sets address as
                                 association primary.

    SCTP_PARAM_ADD_IP          - These are used when Dynamic Address
    SCTP_PARAM_SET_PRIMARY     - Reconfiguration is enabled as explained below.

To support Dynamic Address Reconfiguration the following parameters must be
enabled on both endpoints (or use the appropriate **setsockopt**\(2))::

    /proc/sys/net/sctp/addip_enable
    /proc/sys/net/sctp/addip_noauth_enable

then the following *_PARAM_*'s are sent to the peer in an
ASCONF chunk when the corresponding ``@optname``'s are present::

          @optname                      ASCONF Parameter
         ----------                    ------------------
    SCTP_SOCKOPT_BINDX_ADD     ->   SCTP_PARAM_ADD_IP
    SCTP_SET_PEER_PRIMARY_ADDR ->   SCTP_PARAM_SET_PRIMARY

security_sctp_sk_clone()
~~~~~~~~~~~~~~~~~~~~~~~~
Called whenever a new socket is created by **accept**\(2)
(i.e. a TCP style socket) or when a socket is 'peeled off' e.g userspace
calls **sctp_peeloff**\(3).
::

    @asoc - pointer to current sctp association structure.
    @sk - pointer to current sock structure.
    @newsk - pointer to new sock structure.

security_sctp_assoc_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when a COOKIE ACK is received, and the peer secid will be
saved into ``@asoc->peer_secid`` for client::

    @asoc - pointer to sctp association structure.
    @skb - pointer to skbuff of the COOKIE ACK packet.

Security Hooks used for Association Establishment
-------------------------------------------------

The following diagram shows the use of ``security_sctp_bind_connect()``,
``security_sctp_assoc_request()``, ``security_sctp_assoc_established()`` when
establishing an association.
::

      SCTP endpoint "A"                                SCTP endpoint "Z"
      =================                                =================
    sctp_sf_do_prm_asoc()
 Association setup can be initiated
 by a connect(2), sctp_connectx(3),
 sendmsg(2) or sctp_sendmsg(3).
 These will result in a call to
 security_sctp_bind_connect() to
 initiate an association to
 SCTP peer endpoint "Z".
         INIT --------------------------------------------->
                                                   sctp_sf_do_5_1B_init()
                                                 Respond to an INIT chunk.
                                             SCTP peer endpoint "A" is asking
                                             for a temporary association.
                                             Call security_sctp_assoc_request()
                                             to set the peer label if first
                                             association.
                                             If not first association, check
                                             whether allowed, IF so send:
          <----------------------------------------------- INIT ACK
          |                                  ELSE audit event and silently
          |                                       discard the packet.
          |
    COOKIE ECHO ------------------------------------------>
                                                  sctp_sf_do_5_1D_ce()
                                             Respond to an COOKIE ECHO chunk.
                                             Confirm the cookie and create a
                                             permanent association.
                                             Call security_sctp_assoc_request() to
                                             do the same as for INIT chunk Response.
          <------------------------------------------- COOKIE ACK
          |                                               |
    sctp_sf_do_5_1E_ca                                    |
 Call security_sctp_assoc_established()                   |
 to set the peer label.                                   |
          |                                               |
          |                               If SCTP_SOCKET_TCP or peeled off
          |                               socket security_sctp_sk_clone() is
          |                               called to clone the new socket.
          |                                               |
      ESTABLISHED                                    ESTABLISHED
          |                                               |
    ------------------------------------------------------------------
    |                     Association Established                    |
    ------------------------------------------------------------------

SCTP SELinux Support
====================

Security Hooks
--------------

The `SCTP LSM Support`_ chapter above describes the following SCTP security
hooks with the SELinux specifics expanded below::

    security_sctp_assoc_request()
    security_sctp_bind_connect()
    security_sctp_sk_clone()
    security_sctp_assoc_established()

security_sctp_assoc_request()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passes the ``@asoc`` and ``@chunk->skb`` of the association INIT packet to the
security module. Returns 0 on success, error on failure.
::

    @asoc - pointer to sctp association structure.
    @skb - pointer to skbuff of association packet.

The security module performs the following operations:
     IF this is the first association on ``@asoc->base.sk``, then set the peer
     sid to that in ``@skb``. This will ensure there is only one peer sid
     assigned to ``@asoc->base.sk`` that may support multiple associations.

     ELSE validate the ``@asoc->base.sk peer_sid`` against the ``@skb peer sid``
     to determine whether the association should be allowed or denied.

     Set the sctp ``@asoc sid`` to socket's sid (from ``asoc->base.sk``) with
     MLS portion taken from ``@skb peer sid``. This will be used by SCTP
     TCP style sockets and peeled off connections as they cause a new socket
     to be generated.

     If IP security options are configured (CIPSO/CALIPSO), then the ip
     options are set on the socket.

security_sctp_bind_connect()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Checks permissions required for ipv4/ipv6 addresses based on the ``@optname``
as follows::

  ------------------------------------------------------------------
  |                   BIND Permission Checks                       |
  |       @optname             |         @address contains         |
  |----------------------------|-----------------------------------|
  | SCTP_SOCKOPT_BINDX_ADD     | One or more ipv4 / ipv6 addresses |
  | SCTP_PRIMARY_ADDR          | Single ipv4 or ipv6 address       |
  | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address       |
  ------------------------------------------------------------------

  ------------------------------------------------------------------
  |                 CONNECT Permission Checks                      |
  |       @optname             |         @address contains         |
  |----------------------------|-----------------------------------|
  | SCTP_SOCKOPT_CONNECTX      | One or more ipv4 / ipv6 addresses |
  | SCTP_PARAM_ADD_IP          | One or more ipv4 / ipv6 addresses |
  | SCTP_SENDMSG_CONNECT       | Single ipv4 or ipv6 address       |
  | SCTP_PARAM_SET_PRIMARY     | Single ipv4 or ipv6 address       |
  ------------------------------------------------------------------

`SCTP LSM Support`_ gives a summary of the ``@optname``
entries and also describes ASCONF chunk processing when Dynamic Address
Reconfiguration is enabled.

security_sctp_sk_clone()
~~~~~~~~~~~~~~~~~~~~~~~~
Called whenever a new socket is created by **accept**\(2) (i.e. a TCP style
socket) or when a socket is 'peeled off' e.g userspace calls
**sctp_peeloff**\(3). ``security_sctp_sk_clone()`` will set the new
sockets sid and peer sid to that contained in the ``@asoc sid`` and
``@asoc peer sid`` respectively.
::

    @asoc - pointer to current sctp association structure.
    @sk - pointer to current sock structure.
    @newsk - pointer to new sock structure.

security_sctp_assoc_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when a COOKIE ACK is received where it sets the connection's peer sid
to that in ``@skb``::

    @asoc - pointer to sctp association structure.
    @skb - pointer to skbuff of the COOKIE ACK packet.

Policy Statements
-----------------
The following class and permissions to support SCTP are available within the
kernel::

    class sctp_socket inherits socket { node_bind }

whenever the following policy capability is enabled::

    policycap extended_socket_class;

SELinux SCTP support adds the ``name_connect`` permission for connecting
to a specific port type and the ``association`` permission that is explained
in the section below.

If userspace tools have been updated, SCTP will support the ``portcon``
statement as shown in the following example::

    portcon sctp 1024-1036 system_u:object_r:sctp_ports_t:s0

SCTP Peer Labeling
------------------
An SCTP socket will only have one peer label assigned to it. This will be
assigned during the establishment of the first association. Any further
associations on this socket will have their packet peer label compared to
the sockets peer label, and only if they are different will the
``association`` permission be validated. This is validated by checking the
socket peer sid against the received packets peer sid to determine whether
the association should be allowed or denied.

NOTES:
   1) If peer labeling is not enabled, then the peer context will always be
      ``SECINITSID_UNLABELED`` (``unlabeled_t`` in Reference Policy).

   2) As SCTP can support more than one transport address per endpoint
      (multi-homing) on a single socket, it is possible to configure policy
      and NetLabel to provide different peer labels for each of these. As the
      socket peer label is determined by the first associations transport
      address, it is recommended that all peer labels are consistent.

   3) **getpeercon**\(3) may be used by userspace to retrieve the sockets peer
      context.

   4) While not SCTP specific, be aware when using NetLabel that if a label
      is assigned to a specific interface, and that interface 'goes down',
      then the NetLabel service will remove the entry. Therefore ensure that
      the network startup scripts call **netlabelctl**\(8) to set the required
      label (see **netlabel-config**\(8) helper script for details).

   5) The NetLabel SCTP peer labeling rules apply as discussed in the following
      set of posts tagged "netlabel" at: https://www.paul-moore.com/blog/t.

   6) CIPSO is only supported for IPv4 addressing: ``socket(AF_INET, ...)``
      CALIPSO is only supported for IPv6 addressing: ``socket(AF_INET6, ...)``

      Note the following when testing CIPSO/CALIPSO:
         a) CIPSO will send an ICMP packet if an SCTP packet cannot be
            delivered because of an invalid label.
         b) CALIPSO does not send an ICMP packet, just silently discards it.

   7) IPSEC is not supported as RFC 3554 - sctp/ipsec support has not been
      implemented in userspace (**racoon**\(8) or **ipsec_pluto**\(8)),
      although the kernel supports SCTP/IPSEC.


code:
====================
Credentials in Linux
====================

By: David Howells <dhowells@redhat.com>

.. contents:: :local:

Overview
========

There are several parts to the security check performed by Linux when one
object acts upon another:

 1. Objects.

     Objects are things in the system that may be acted upon directly by
     userspace programs.  Linux has a variety of actionable objects, including:

	- Tasks
	- Files/inodes
	- Sockets
	- Message queues
	- Shared memory segments
	- Semaphores
	- Keys

     As a part of the description of all these objects there is a set of
     credentials.  What's in the set depends on the type of object.

 2. Object ownership.

     Amongst the credentials of most objects, there will be a subset that
     indicates the ownership of that object.  This is used for resource
     accounting and limitation (disk quotas and task rlimits for example).

     In a standard UNIX filesystem, for instance, this will be defined by the
     UID marked on the inode.

 3. The objective context.

     Also amongst the credentials of those objects, there will be a subset that
     indicates the 'objective context' of that object.  This may or may not be
     the same set as in (2) - in standard UNIX files, for instance, this is the
     defined by the UID and the GID marked on the inode.

     The objective context is used as part of the security calculation that is
     carried out when an object is acted upon.

 4. Subjects.

     A subject is an object that is acting upon another object.

     Most of the objects in the system are inactive: they don't act on other
     objects within the system.  Processes/tasks are the obvious exception:
     they do stuff; they access and manipulate things.

     Objects other than tasks may under some circumstances also be subjects.
     For instance an open file may send SIGIO to a task using the UID and EUID
     given to it by a task that called ``fcntl(F_SETOWN)`` upon it.  In this case,
     the file struct will have a subjective context too.

 5. The subjective context.

     A subject has an additional interpretation of its credentials.  A subset
     of its credentials forms the 'subjective context'.  The subjective context
     is used as part of the security calculation that is carried out when a
     subject acts.

     A Linux task, for example, has the FSUID, FSGID and the supplementary
     group list for when it is acting upon a file - which are quite separate
     from the real UID and GID that normally form the objective context of the
     task.

 6. Actions.

     Linux has a number of actions available that a subject may perform upon an
     object.  The set of actions available depends on the nature of the subject
     and the object.

     Actions include reading, writing, creating and deleting files; forking or
     signalling and tracing tasks.

 7. Rules, access control lists and security calculations.

     When a subject acts upon an object, a security calculation is made.  This
     involves taking the subjective context, the objective context and the
     action, and searching one or more sets of rules to see whether the subject
     is granted or denied permission to act in the desired manner on the
     object, given those contexts.

     There are two main sources of rules:

     a. Discretionary access control (DAC):

	 Sometimes the object will include sets of rules as part of its
	 description.  This is an 'Access Control List' or 'ACL'.  A Linux
	 file may supply more than one ACL.

	 A traditional UNIX file, for example, includes a permissions mask that
	 is an abbreviated ACL with three fixed classes of subject ('user',
	 'group' and 'other'), each of which may be granted certain privileges
	 ('read', 'write' and 'execute' - whatever those map to for the object
	 in question).  UNIX file permissions do not allow the arbitrary
	 specification of subjects, however, and so are of limited use.

	 A Linux file might also sport a POSIX ACL.  This is a list of rules
	 that grants various permissions to arbitrary subjects.

     b. Mandatory access control (MAC):

	 The system as a whole may have one or more sets of rules that get
	 applied to all subjects and objects, regardless of their source.
	 SELinux and Smack are examples of this.

	 In the case of SELinux and Smack, each object is given a label as part
	 of its credentials.  When an action is requested, they take the
	 subject label, the object label and the action and look for a rule
	 that says that this action is either granted or denied.

Types of Credentials
====================

The Linux kernel supports the following types of credentials:

 1. Traditional UNIX credentials.

	- Real User ID
	- Real Group ID

     The UID and GID are carried by most, if not all, Linux objects, even if in
     some cases it has to be invented (FAT or CIFS files for example, which are
     derived from Windows).  These (mostly) define the objective context of
     that object, with tasks being slightly different in some cases.

	- Effective, Saved and FS User ID
	- Effective, Saved and FS Group ID
	- Supplementary groups

     These are additional credentials used by tasks only.  Usually, an
     EUID/EGID/GROUPS will be used as the subjective context, and real UID/GID
     will be used as the objective.  For tasks, it should be noted that this is
     not always true.

 2. Capabilities.

	- Set of permitted capabilities
	- Set of inheritable capabilities
	- Set of effective capabilities
	- Capability bounding set

     These are only carried by tasks.  They indicate superior capabilities
     granted piecemeal to a task that an ordinary task wouldn't otherwise have.
     These are manipulated implicitly by changes to the traditional UNIX
     credentials, but can also be manipulated directly by the ``capset()``
     system call.

     The permitted capabilities are those caps that the process might grant
     itself to its effective or permitted sets through ``capset()``.  This
     inheritable set might also be so constrained.

     The effective capabilities are the ones that a task is actually allowed to
     make use of itself.

     The inheritable capabilities are the ones that may get passed across
     ``execve()``.

     The bounding set limits the capabilities that may be inherited across
     ``execve()``, especially when a binary is executed that will execute as
     UID 0.

 3. Secure management flags (securebits).

     These are only carried by tasks.  These govern the way the above
     credentials are manipulated and inherited over certain operations such as
     execve().  They aren't used directly as objective or subjective
     credentials.

 4. Keys and keyrings.

     These are only carried by tasks.  They carry and cache security tokens
     that don't fit into the other standard UNIX credentials.  They are for
     making such things as network filesystem keys available to the file
     accesses performed by processes, without the necessity of ordinary
     programs having to know about security details involved.

     Keyrings are a special type of key.  They carry sets of other keys and can
     be searched for the desired key.  Each process may subscribe to a number
     of keyrings:

	Per-thread keying
	Per-process keyring
	Per-session keyring

     When a process accesses a key, if not already present, it will normally be
     cached on one of these keyrings for future accesses to find.

     For more information on using keys, see ``Documentation/security/keys/*``.

 5. LSM

     The Linux Security Module allows extra controls to be placed over the
     operations that a task may do.  Currently Linux supports several LSM
     options.

     Some work by labelling the objects in a system and then applying sets of
     rules (policies) that say what operations a task with one label may do to
     an object with another label.

 6. AF_KEY

     This is a socket-based approach to credential management for networking
     stacks [RFC 2367].  It isn't discussed by this document as it doesn't
     interact directly with task and file credentials; rather it keeps system
     level credentials.

When a file is opened, part of the opening task's subjective context is
recorded in the file struct created.  This allows operations using that file
struct to use those credentials instead of the subjective context of the task
that issued the operation.  An example of this would be a file opened on a
network filesystem where the credentials of the opened file should be presented
to the server, regardless of who is actually doing a read or a write upon it.

File Markings
=============

Files on disk or obtained over the network may have annotations that form the
objective security context of that file.  Depending on the type of filesystem,
this may include one or more of the following:

 * UNIX UID, GID, mode;
 * Windows user ID;
 * Access control list;
 * LSM security label;
 * UNIX exec privilege escalation bits (SUID/SGID);
 * File capabilities exec privilege escalation bits.

These are compared to the task's subjective security context, and certain
operations allowed or disallowed as a result.  In the case of execve(), the
privilege escalation bits come into play, and may allow the resulting process
extra privileges, based on the annotations on the executable file.

Task Credentials
================

In Linux, all of a task's credentials are held in (uid, gid) or through
(groups, keys, LSM security) a refcounted structure of type 'struct cred'.
Each task points to its credentials by a pointer called 'cred' in its
task_struct.

Once a set of credentials has been prepared and committed, it may not be
changed, barring the following exceptions:

 1. its reference count may be changed;

 2. the reference count on the group_info struct it points to may be changed;

 3. the reference count on the security data it points to may be changed;

 4. the reference count on any keyrings it points to may be changed;

 5. any keyrings it points to may be revoked, expired or have their security
    attributes changed; and

 6. the contents of any keyrings to which it points may be changed (the whole
    point of keyrings being a shared set of credentials, modifiable by anyone
    with appropriate access).

To alter anything in the cred struct, the copy-and-replace principle must be
adhered to.  First take a copy, then alter the copy and then use RCU to change
the task pointer to make it point to the new copy.  There are wrappers to aid
with this (see below).

A task may only alter its _own_ credentials; it is no longer permitted for a
task to alter another's credentials.  This means the ``capset()`` system call
is no longer permitted to take any PID other than the one of the current
process. Also ``keyctl_instantiate()`` and ``keyctl_negate()`` functions no
longer permit attachment to process-specific keyrings in the requesting
process as the instantiating process may need to create them.

Immutable Credentials
---------------------

Once a set of credentials has been made public (by calling ``commit_creds()``
for example), it must be considered immutable, barring two exceptions:

 1. The reference count may be altered.

 2. While the keyring subscriptions of a set of credentials may not be
    changed, the keyrings subscribed to may have their contents altered.

To catch accidental credential alteration at compile time, struct task_struct
has _const_ pointers to its credential sets, as does struct file.  Furthermore,
certain functions such as ``get_cred()`` and ``put_cred()`` operate on const
pointers, thus rendering casts unnecessary, but require to temporarily ditch
the const qualification to be able to alter the reference count.

Accessing Task Credentials
--------------------------

A task being able to alter only its own credentials permits the current process
to read or replace its own credentials without the need for any form of locking
-- which simplifies things greatly.  It can just call::

	const struct cred *current_cred()

to get a pointer to its credentials structure, and it doesn't have to release
it afterwards.

There are convenience wrappers for retrieving specific aspects of a task's
credentials (the value is simply returned in each case)::

	uid_t current_uid(void)		Current's real UID
	gid_t current_gid(void)		Current's real GID
	uid_t current_euid(void)	Current's effective UID
	gid_t current_egid(void)	Current's effective GID
	uid_t current_fsuid(void)	Current's file access UID
	gid_t current_fsgid(void)	Current's file access GID
	kernel_cap_t current_cap(void)	Current's effective capabilities
	struct user_struct *current_user(void)  Current's user account

There are also convenience wrappers for retrieving specific associated pairs of
a task's credentials::

	void current_uid_gid(uid_t *, gid_t *);
	void current_euid_egid(uid_t *, gid_t *);
	void current_fsuid_fsgid(uid_t *, gid_t *);

which return these pairs of values through their arguments after retrieving
them from the current task's credentials.

In addition, there is a function for obtaining a reference on the current
process's current set of credentials::

	const struct cred *get_current_cred(void);

and functions for getting references to one of the credentials that don't
actually live in struct cred::

	struct user_struct *get_current_user(void);
	struct group_info *get_current_groups(void);

which get references to the current process's user accounting structure and
supplementary groups list respectively.

Once a reference has been obtained, it must be released with ``put_cred()``,
``free_uid()`` or ``put_group_info()`` as appropriate.

Accessing Another Task's Credentials
------------------------------------

While a task may access its own credentials without the need for locking, the
same is not true of a task wanting to access another task's credentials.  It
must use the RCU read lock and ``rcu_dereference()``.

The ``rcu_dereference()`` is wrapped by::

	const struct cred *__task_cred(struct task_struct *task);

This should be used inside the RCU read lock, as in the following example::

	void foo(struct task_struct *t, struct foo_data *f)
	{
		const struct cred *tcred;
		...
		rcu_read_lock();
		tcred = __task_cred(t);
		f->uid = tcred->uid;
		f->gid = tcred->gid;
		f->groups = get_group_info(tcred->groups);
		rcu_read_unlock();
		...
	}

Should it be necessary to hold another task's credentials for a long period of
time, and possibly to sleep while doing so, then the caller should get a
reference on them using::

	const struct cred *get_task_cred(struct task_struct *task);

This does all the RCU magic inside of it.  The caller must call put_cred() on
the credentials so obtained when they're finished with.

.. note::
   The result of ``__task_cred()`` should not be passed directly to
   ``get_cred()`` as this may race with ``commit_cred()``.

There are a couple of convenience functions to access bits of another task's
credentials, hiding the RCU magic from the caller::

	uid_t task_uid(task)		Task's real UID
	uid_t task_euid(task)		Task's effective UID

If the caller is holding the RCU read lock at the time anyway, then::

	__task_cred(task)->uid
	__task_cred(task)->euid

should be used instead.  Similarly, if multiple aspects of a task's credentials
need to be accessed, RCU read lock should be used, ``__task_cred()`` called,
the result stored in a temporary pointer and then the credential aspects called
from that before dropping the lock.  This prevents the potentially expensive
RCU magic from being invoked multiple times.

Should some other single aspect of another task's credentials need to be
accessed, then this can be used::

	task_cred_xxx(task, member)

where 'member' is a non-pointer member of the cred struct.  For instance::

	uid_t task_cred_xxx(task, suid);

will retrieve 'struct cred::suid' from the task, doing the appropriate RCU
magic.  This may not be used for pointer members as what they point to may
disappear the moment the RCU read lock is dropped.

Altering Credentials
--------------------

As previously mentioned, a task may only alter its own credentials, and may not
alter those of another task.  This means that it doesn't need to use any
locking to alter its own credentials.

To alter the current process's credentials, a function should first prepare a
new set of credentials by calling::

	struct cred *prepare_creds(void);

this locks current->cred_replace_mutex and then allocates and constructs a
duplicate of the current process's credentials, returning with the mutex still
held if successful.  It returns NULL if not successful (out of memory).

The mutex prevents ``ptrace()`` from altering the ptrace state of a process
while security checks on credentials construction and changing is taking place
as the ptrace state may alter the outcome, particularly in the case of
``execve()``.

The new credentials set should be altered appropriately, and any security
checks and hooks done.  Both the current and the proposed sets of credentials
are available for this purpose as current_cred() will return the current set
still at this point.

When replacing the group list, the new list must be sorted before it
is added to the credential, as a binary search is used to test for
membership.  In practice, this means groups_sort() should be
called before set_groups() or set_current_groups().
groups_sort() must not be called on a ``struct group_list`` which
is shared as it may permute elements as part of the sorting process
even if the array is already sorted.

When the credential set is ready, it should be committed to the current process
by calling::

	int commit_creds(struct cred *new);

This will alter various aspects of the credentials and the process, giving the
LSM a chance to do likewise, then it will use ``rcu_assign_pointer()`` to
actually commit the new credentials to ``current->cred``, it will release
``current->cred_replace_mutex`` to allow ``ptrace()`` to take place, and it
will notify the scheduler and others of the changes.

This function is guaranteed to return 0, so that it can be tail-called at the
end of such functions as ``sys_setresuid()``.

Note that this function consumes the caller's reference to the new credentials.
The caller should _not_ call ``put_cred()`` on the new credentials afterwards.

Furthermore, once this function has been called on a new set of credentials,
those credentials may _not_ be changed further.

Should the security checks fail or some other error occur after
``prepare_creds()`` has been called, then the following function should be
invoked::

	void abort_creds(struct cred *new);

This releases the lock on ``current->cred_replace_mutex`` that
``prepare_creds()`` got and then releases the new credentials.

A typical credentials alteration function would look something like this::

	int alter_suid(uid_t suid)
	{
		struct cred *new;
		int ret;

		new = prepare_creds();
		if (!new)
			return -ENOMEM;

		new->suid = suid;
		ret = security_alter_suid(new);
		if (ret < 0) {
			abort_creds(new);
			return ret;
		}

		return commit_creds(new);
	}

Managing Credentials
--------------------

There are some functions to help manage credentials:

 - ``void put_cred(const struct cred *cred);``

     This releases a reference to the given set of credentials.  If the
     reference count reaches zero, the credentials will be scheduled for
     destruction by the RCU system.

 - ``const struct cred *get_cred(const struct cred *cred);``

     This gets a reference on a live set of credentials, returning a pointer to
     that set of credentials.

 - ``struct cred *get_new_cred(struct cred *cred);``

     This gets a reference on a set of credentials that is under construction
     and is thus still mutable, returning a pointer to that set of credentials.

Open File Credentials
=====================

When a new file is opened, a reference is obtained on the opening task's
credentials and this is attached to the file struct as ``f_cred`` in place of
``f_uid`` and ``f_gid``.  Code that used to access ``file->f_uid`` and
``file->f_gid`` should now access ``file->f_cred->fsuid`` and
``file->f_cred->fsgid``.

It is safe to access ``f_cred`` without the use of RCU or locking because the
pointer will not change over the lifetime of the file struct, and nor will the
contents of the cred struct pointed to, barring the exceptions listed above
(see the Task Credentials section).

To avoid "confused deputy" privilege escalation attacks, access control checks
during subsequent operations on an opened file should use these credentials
instead of "current"'s credentials, as the file may have been passed to a more
privileged process.

Overriding the VFS's Use of Credentials
=======================================

Under some circumstances it is desirable to override the credentials used by
the VFS, and that can be done by calling into such as ``vfs_mkdir()`` with a
different set of credentials.  This is done in the following places:

 * ``sys_faccessat()``.
 * ``do_coredump()``.
 * nfs4recover.c.


code:
==================================
Digital Signature Verification API
==================================

:Author: Dmitry Kasatkin
:Date: 06.10.2011

.. CONTENTS

   1. Introduction
   2. API
   3. User-space utilities

Introduction
============

Digital signature verification API provides a method to verify digital signature.
Currently digital signatures are used by the IMA/EVM integrity protection subsystem.

Digital signature verification is implemented using cut-down kernel port of
GnuPG multi-precision integers (MPI) library. The kernel port provides
memory allocation errors handling, has been refactored according to kernel
coding style, and checkpatch.pl reported errors and warnings have been fixed.

Public key and signature consist of header and MPIs::

	struct pubkey_hdr {
		uint8_t		version;	/* key format version */
		time_t		timestamp;	/* key made, always 0 for now */
		uint8_t		algo;
		uint8_t		nmpi;
		char		mpi[0];
	} __packed;

	struct signature_hdr {
		uint8_t		version;	/* signature format version */
		time_t		timestamp;	/* signature made */
		uint8_t		algo;
		uint8_t		hash;
		uint8_t		keyid[8];
		uint8_t		nmpi;
		char		mpi[0];
	} __packed;

keyid equals to SHA1[12-19] over the total key content.
Signature header is used as an input to generate a signature.
Such approach insures that key or signature header could not be changed.
It protects timestamp from been changed and can be used for rollback
protection.

API
===

API currently includes only 1 function::

	digsig_verify() - digital signature verification with public key

	/**
	* digsig_verify() - digital signature verification with public key
	* @keyring:	keyring to search key in
	* @sig:	digital signature
	* @sigen:	length of the signature
	* @data:	data
	* @datalen:	length of the data
	* @return:	0 on success, -EINVAL otherwise
	*
	* Verifies data integrity against digital signature.
	* Currently only RSA is supported.
	* Normally hash of the content is used as a data for this function.
	*
	*/
	int digsig_verify(struct key *keyring, const char *sig, int siglen,
			  const char *data, int datalen);

User-space utilities
====================

The signing and key management utilities evm-utils provide functionality
to generate signatures, to load keys into the kernel keyring.
Keys can be in PEM or converted to the kernel format.
When the key is added to the kernel keyring, the keyid defines the name
of the key: 5D2B05FC633EE3E8 in the example bellow.

Here is example output of the keyctl utility::

	$ keyctl show
	Session Keyring
	-3 --alswrv      0     0  keyring: _ses
	603976250 --alswrv      0    -1   \_ keyring: _uid.0
	817777377 --alswrv      0     0       \_ user: kmk
	891974900 --alswrv      0     0       \_ encrypted: evm-key
	170323636 --alswrv      0     0       \_ keyring: _module
	548221616 --alswrv      0     0       \_ keyring: _ima
	128198054 --alswrv      0     0       \_ keyring: _evm

	$ keyctl list 128198054
	1 key in keyring:
	620789745: --alswrv     0     0 user: 5D2B05FC633EE3E8


code:
======================
Security Documentation
======================

.. toctree::
   :maxdepth: 1

   credentials
   IMA-templates
   keys/index
   lsm
   lsm-development
   sak
   SCTP
   self-protection
   siphash
   tpm/index
   digsig
   landlock
   secrets/index