Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,33 @@
=================
Built-in firmware
=================
Firmware can be built-in to the kernel, this means building the firmware
into vmlinux directly, to enable avoiding having to look for firmware from
the filesystem. Instead, firmware can be looked for inside the kernel
directly. You can enable built-in firmware using the kernel configuration
options:
* CONFIG_EXTRA_FIRMWARE
* CONFIG_EXTRA_FIRMWARE_DIR
There are a few reasons why you might want to consider building your firmware
into the kernel with CONFIG_EXTRA_FIRMWARE:
* Speed
* Firmware is needed for accessing the boot device, and the user doesn't
want to stuff the firmware into the boot initramfs.
Even if you have these needs there are a few reasons why you may not be
able to make use of built-in firmware:
* Legalese - firmware is non-GPL compatible
* Some firmware may be optional
* Firmware upgrades are possible, therefore a new firmware would implicate
a complete kernel rebuild.
* Some firmware files may be really large in size. The remote-proc subsystem
is an example subsystem which deals with these sorts of firmware
* The firmware may need to be scraped out from some device specific location
dynamically, an example is calibration data for some WiFi chipsets. This
calibration data can be unique per sold device.
@@ -0,0 +1,17 @@
==========================
Firmware API core features
==========================
The firmware API has a rich set of core features available. This section
documents these features.
.. toctree::
fw_search_path
built-in-fw
firmware_cache
direct-fs-lookup
fallback-mechanisms
lookup-order
firmware-usage-guidelines
@@ -0,0 +1,30 @@
========================
Direct filesystem lookup
========================
Direct filesystem lookup is the most common form of firmware lookup performed
by the kernel. The kernel looks for the firmware directly on the root
filesystem in the paths documented in the section 'Firmware search paths'.
The filesystem lookup is implemented in fw_get_filesystem_firmware(), it
uses common core kernel file loader facility kernel_read_file_from_path().
The max path allowed is PATH_MAX -- currently this is 4096 characters.
It is recommended you keep /lib/firmware paths on your root filesystem,
avoid having a separate partition for them in order to avoid possible
races with lookups and avoid uses of the custom fallback mechanisms
documented below.
Firmware and initramfs
----------------------
Drivers which are built-in to the kernel should have the firmware integrated
also as part of the initramfs used to boot the kernel given that otherwise
a race is possible with loading the driver and the real rootfs not yet being
available. Stuffing the firmware into initramfs resolves this race issue,
however note that using initrd does not suffice to address the same race.
There are circumstances that justify not wanting to include firmware into
initramfs, such as dealing with large firmware files for the
remote-proc subsystem. For such cases using a userspace fallback mechanism
is currently the only viable solution as only userspace can know for sure
when the real rootfs is ready and mounted.
@@ -0,0 +1,16 @@
.. SPDX-License-Identifier: GPL-2.0
====================================================
Unified Extensible Firmware Interface (UEFI) Support
====================================================
UEFI stub library functions
===========================
.. kernel-doc:: drivers/firmware/efi/libstub/mem.c
:internal:
UEFI Common Platform Error Record (CPER) functions
==================================================
.. kernel-doc:: drivers/firmware/efi/cper.c
@@ -0,0 +1,308 @@
===================
Fallback mechanisms
===================
A fallback mechanism is supported to allow to overcome failures to do a direct
filesystem lookup on the root filesystem or when the firmware simply cannot be
installed for practical reasons on the root filesystem. The kernel
configuration options related to supporting the firmware fallback mechanism are:
* CONFIG_FW_LOADER_USER_HELPER: enables building the firmware fallback
mechanism. Most distributions enable this option today. If enabled but
CONFIG_FW_LOADER_USER_HELPER_FALLBACK is disabled, only the custom fallback
mechanism is available and for the request_firmware_nowait() call.
* CONFIG_FW_LOADER_USER_HELPER_FALLBACK: force enables each request to
enable the kobject uevent fallback mechanism on all firmware API calls
except request_firmware_direct(). Most distributions disable this option
today. The call request_firmware_nowait() allows for one alternative
fallback mechanism: if this kconfig option is enabled and your second
argument to request_firmware_nowait(), uevent, is set to false you are
informing the kernel that you have a custom fallback mechanism and it will
manually load the firmware. Read below for more details.
Note that this means when having this configuration:
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n
the kobject uevent fallback mechanism will never take effect even
for request_firmware_nowait() when uevent is set to true.
Justifying the firmware fallback mechanism
==========================================
Direct filesystem lookups may fail for a variety of reasons. Known reasons for
this are worth itemizing and documenting as it justifies the need for the
fallback mechanism:
* Race against access with the root filesystem upon bootup.
* Races upon resume from suspend. This is resolved by the firmware cache, but
the firmware cache is only supported if you use uevents, and its not
supported for request_firmware_into_buf().
* Firmware is not accessible through typical means:
* It cannot be installed into the root filesystem
* The firmware provides very unique device specific data tailored for
the unit gathered with local information. An example is calibration
data for WiFi chipsets for mobile devices. This calibration data is
not common to all units, but tailored per unit. Such information may
be installed on a separate flash partition other than where the root
filesystem is provided.
Types of fallback mechanisms
============================
There are really two fallback mechanisms available using one shared sysfs
interface as a loading facility:
* Kobject uevent fallback mechanism
* Custom fallback mechanism
First lets document the shared sysfs loading facility.
Firmware sysfs loading facility
===============================
In order to help device drivers upload firmware using a fallback mechanism
the firmware infrastructure creates a sysfs interface to enable userspace
to load and indicate when firmware is ready. The sysfs directory is created
via fw_create_instance(). This call creates a new struct device named after
the firmware requested, and establishes it in the device hierarchy by
associating the device used to make the request as the device's parent.
The sysfs directory's file attributes are defined and controlled through
the new device's class (firmware_class) and group (fw_dev_attr_groups).
This is actually where the original firmware_class module name came from,
given that originally the only firmware loading mechanism available was the
mechanism we now use as a fallback mechanism, which registers a struct class
firmware_class. Because the attributes exposed are part of the module name, the
module name firmware_class cannot be renamed in the future, to ensure backward
compatibility with old userspace.
To load firmware using the sysfs interface we expose a loading indicator,
and a file upload firmware into:
* /sys/$DEVPATH/loading
* /sys/$DEVPATH/data
To upload firmware you will echo 1 onto the loading file to indicate
you are loading firmware. You then write the firmware into the data file,
and you notify the kernel the firmware is ready by echo'ing 0 onto
the loading file.
The firmware device used to help load firmware using sysfs is only created if
direct firmware loading fails and if the fallback mechanism is enabled for your
firmware request, this is set up with :c:func:`firmware_fallback_sysfs`. It is
important to re-iterate that no device is created if a direct filesystem lookup
succeeded.
Using::
echo 1 > /sys/$DEVPATH/loading
Will clean any previous partial load at once and make the firmware API
return an error. When loading firmware the firmware_class grows a buffer
for the firmware in PAGE_SIZE increments to hold the image as it comes in.
firmware_data_read() and firmware_loading_show() are just provided for the
test_firmware driver for testing, they are not called in normal use or
expected to be used regularly by userspace.
firmware_fallback_sysfs
-----------------------
.. kernel-doc:: drivers/base/firmware_loader/fallback.c
:functions: firmware_fallback_sysfs
Firmware kobject uevent fallback mechanism
==========================================
Since a device is created for the sysfs interface to help load firmware as a
fallback mechanism userspace can be informed of the addition of the device by
relying on kobject uevents. The addition of the device into the device
hierarchy means the fallback mechanism for firmware loading has been initiated.
For details of implementation refer to fw_load_sysfs_fallback(), in particular
on the use of dev_set_uevent_suppress() and kobject_uevent().
The kernel's kobject uevent mechanism is implemented in lib/kobject_uevent.c,
it issues uevents to userspace. As a supplement to kobject uevents Linux
distributions could also enable CONFIG_UEVENT_HELPER_PATH, which makes use of
core kernel's usermode helper (UMH) functionality to call out to a userspace
helper for kobject uevents. In practice though no standard distribution has
ever used the CONFIG_UEVENT_HELPER_PATH. If CONFIG_UEVENT_HELPER_PATH is
enabled this binary would be called each time kobject_uevent_env() gets called
in the kernel for each kobject uevent triggered.
Different implementations have been supported in userspace to take advantage of
this fallback mechanism. When firmware loading was only possible using the
sysfs mechanism the userspace component "hotplug" provided the functionality of
monitoring for kobject events. Historically this was superseded be systemd's
udev, however firmware loading support was removed from udev as of systemd
commit be2ea723b1d0 ("udev: remove userspace firmware loading support")
as of v217 on August, 2014. This means most Linux distributions today are
not using or taking advantage of the firmware fallback mechanism provided
by kobject uevents. This is specially exacerbated due to the fact that most
distributions today disable CONFIG_FW_LOADER_USER_HELPER_FALLBACK.
Refer to do_firmware_uevent() for details of the kobject event variables
setup. The variables currently passed to userspace with a "kobject add"
event are:
* FIRMWARE=firmware name
* TIMEOUT=timeout value
* ASYNC=whether or not the API request was asynchronous
By default DEVPATH is set by the internal kernel kobject infrastructure.
Below is an example simple kobject uevent script::
# Both $DEVPATH and $FIRMWARE are already provided in the environment.
MY_FW_DIR=/lib/firmware/
echo 1 > /sys/$DEVPATH/loading
cat $MY_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
echo 0 > /sys/$DEVPATH/loading
Firmware custom fallback mechanism
==================================
Users of the request_firmware_nowait() call have yet another option available
at their disposal: rely on the sysfs fallback mechanism but request that no
kobject uevents be issued to userspace. The original logic behind this
was that utilities other than udev might be required to lookup firmware
in non-traditional paths -- paths outside of the listing documented in the
section 'Direct filesystem lookup'. This option is not available to any of
the other API calls as uevents are always forced for them.
Since uevents are only meaningful if the fallback mechanism is enabled
in your kernel it would seem odd to enable uevents with kernels that do not
have the fallback mechanism enabled in their kernels. Unfortunately we also
rely on the uevent flag which can be disabled by request_firmware_nowait() to
also setup the firmware cache for firmware requests. As documented above,
the firmware cache is only set up if uevent is enabled for an API call.
Although this can disable the firmware cache for request_firmware_nowait()
calls, users of this API should not use it for the purposes of disabling
the cache as that was not the original purpose of the flag. Not setting
the uevent flag means you want to opt-in for the firmware fallback mechanism
but you want to suppress kobject uevents, as you have a custom solution which
will monitor for your device addition into the device hierarchy somehow and
load firmware for you through a custom path.
Firmware fallback timeout
=========================
The firmware fallback mechanism has a timeout. If firmware is not loaded
onto the sysfs interface by the timeout value an error is sent to the
driver. By default the timeout is set to 60 seconds if uevents are
desirable, otherwise MAX_JIFFY_OFFSET is used (max timeout possible).
The logic behind using MAX_JIFFY_OFFSET for non-uevents is that a custom
solution will have as much time as it needs to load firmware.
You can customize the firmware timeout by echo'ing your desired timeout into
the following file:
* /sys/class/firmware/timeout
If you echo 0 into it means MAX_JIFFY_OFFSET will be used. The data type
for the timeout is an int.
EFI embedded firmware fallback mechanism
========================================
On some devices the system's EFI code / ROM may contain an embedded copy
of firmware for some of the system's integrated peripheral devices and
the peripheral's Linux device-driver needs to access this firmware.
Device drivers which need such firmware can use the
firmware_request_platform() function for this, note that this is a
separate fallback mechanism from the other fallback mechanisms and
this does not use the sysfs interface.
A device driver which needs this can describe the firmware it needs
using an efi_embedded_fw_desc struct:
.. kernel-doc:: include/linux/efi_embedded_fw.h
:functions: efi_embedded_fw_desc
The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE memory
segments for an eight byte sequence matching prefix; if the prefix is found it
then does a sha256 over length bytes and if that matches makes a copy of length
bytes and adds that to its list with found firmwares.
To avoid doing this somewhat expensive scan on all systems, dmi matching is
used. Drivers are expected to export a dmi_system_id array, with each entries'
driver_data pointing to an efi_embedded_fw_desc.
To register this array with the efi-embedded-fw code, a driver needs to:
1. Always be builtin to the kernel or store the dmi_system_id array in a
separate object file which always gets builtin.
2. Add an extern declaration for the dmi_system_id array to
include/linux/efi_embedded_fw.h.
3. Add the dmi_system_id array to the embedded_fw_table in
drivers/firmware/efi/embedded-firmware.c wrapped in a #ifdef testing that
the driver is being builtin.
4. Add "select EFI_EMBEDDED_FIRMWARE if EFI_STUB" to its Kconfig entry.
The firmware_request_platform() function will always first try to load firmware
with the specified name directly from the disk, so the EFI embedded-fw can
always be overridden by placing a file under /lib/firmware.
Note that:
1. The code scanning for EFI embedded-firmware runs near the end
of start_kernel(), just before calling rest_init(). For normal drivers and
subsystems using subsys_initcall() to register themselves this does not
matter. This means that code running earlier cannot use EFI
embedded-firmware.
2. At the moment the EFI embedded-fw code assumes that firmwares always start at
an offset which is a multiple of 8 bytes, if this is not true for your case
send in a patch to fix this.
3. At the moment the EFI embedded-fw code only works on x86 because other archs
free EFI_BOOT_SERVICES_CODE before the EFI embedded-fw code gets a chance to
scan it.
4. The current brute-force scanning of EFI_BOOT_SERVICES_CODE is an ad-hoc
brute-force solution. There has been discussion to use the UEFI Platform
Initialization (PI) spec's Firmware Volume protocol. This has been rejected
because the FV Protocol relies on *internal* interfaces of the PI spec, and:
1. The PI spec does not define peripheral firmware at all
2. The internal interfaces of the PI spec do not guarantee any backward
compatibility. Any implementation details in FV may be subject to change,
and may vary system to system. Supporting the FV Protocol would be
difficult as it is purposely ambiguous.
Example how to check for and extract embedded firmware
------------------------------------------------------
To check for, for example Silead touchscreen controller embedded firmware,
do the following:
1. Boot the system with efi=debug on the kernel commandline
2. cp /sys/kernel/debug/efi/boot_services_code? to your home dir
3. Open the boot_services_code? files in a hex-editor, search for the
magic prefix for Silead firmware: F0 00 00 00 02 00 00 00, this gives you
the beginning address of the firmware inside the boot_services_code? file.
4. The firmware has a specific pattern, it starts with a 8 byte page-address,
typically F0 00 00 00 02 00 00 00 for the first page followed by 32-bit
word-address + 32-bit value pairs. With the word-address incrementing 4
bytes (1 word) for each pair until a page is complete. A complete page is
followed by a new page-address, followed by more word + value pairs. This
leads to a very distinct pattern. Scroll down until this pattern stops,
this gives you the end of the firmware inside the boot_services_code? file.
5. "dd if=boot_services_code? of=firmware bs=1 skip=<begin-addr> count=<len>"
will extract the firmware for you. Inspect the firmware file in a
hexeditor to make sure you got the dd parameters correct.
6. Copy it to /lib/firmware under the expected name to test it.
7. If the extracted firmware works, you can use the found info to fill an
efi_embedded_fw_desc struct to describe it, run "sha256sum firmware"
to get the sha256sum to put in the sha256 field.
@@ -0,0 +1,49 @@
===================
Firmware Guidelines
===================
Users switching to a newer kernel should *not* have to install newer
firmware files to keep their hardware working. At the same time updated
firmware files must not cause any regressions for users of older kernel
releases.
Drivers that use firmware from linux-firmware should follow the rules in
this guide. (Where there is limited control of the firmware,
i.e. company doesn't support Linux, firmwares sourced from misc places,
then of course these rules will not apply strictly.)
* Firmware files shall be designed in a way that it allows checking for
firmware ABI version changes. It is recommended that firmware files be
versioned with at least a major/minor version. It is suggested that
the firmware files in linux-firmware be named with some device
specific name, and just the major version. The firmware version should
be stored in the firmware header, or as an exception, as part of the
firmware file name, in order to let the driver detact any non-ABI
fixes/changes. The firmware files in linux-firmware should be
overwritten with the newest compatible major version. Newer major
version firmware shall remain compatible with all kernels that load
that major number.
* If the kernel support for the hardware is normally inactive, or the
hardware isn't available for public consumption, this can
be ignored, until the first kernel release that enables that hardware.
This means no major version bumps without the kernel retaining
backwards compatibility for the older major versions. Minor version
bumps should not introduce new features that newer kernels depend on
non-optionally.
* If a security fix needs lockstep firmware and kernel fixes in order to
be successful, then all supported major versions in the linux-firmware
repo that are required by currently supported stable/LTS kernels,
should be updated with the security fix. The kernel patches should
detect if the firmware is new enough to declare if the security issue
is fixed. All communications around security fixes should point at
both the firmware and kernel fixes. If a security fix requires
deprecating old major versions, then this should only be done as a
last option, and be stated clearly in all communications.
* Firmware files that affect the User API (UAPI) shall not introduce
changes that break existing userspace programs. Updates to such firmware
must ensure backward compatibility with existing userspace applications.
This includes maintaining consistent interfaces and behaviors that
userspace programs rely on.
@@ -0,0 +1,51 @@
==============
Firmware cache
==============
When Linux resumes from suspend some device drivers require firmware lookups to
re-initialize devices. During resume there may be a period of time during which
firmware lookups are not possible, during this short period of time firmware
requests will fail. Time is of essence though, and delaying drivers to wait for
the root filesystem for firmware delays user experience with device
functionality. In order to support these requirements the firmware
infrastructure implements a firmware cache for device drivers for most API
calls, automatically behind the scenes.
The firmware cache makes using certain firmware API calls safe during a device
driver's suspend and resume callback. Users of these API calls needn't cache
the firmware by themselves for dealing with firmware loss during system resume.
The firmware cache works by requesting for firmware prior to suspend and
caching it in memory. Upon resume device drivers using the firmware API will
have access to the firmware immediately, without having to wait for the root
filesystem to mount or dealing with possible race issues with lookups as the
root filesystem mounts.
Some implementation details about the firmware cache setup:
* The firmware cache is setup by adding a devres entry for each device that
uses all synchronous call except :c:func:`request_firmware_into_buf`.
* If an asynchronous call is used the firmware cache is only set up for a
device if the second argument (uevent) to request_firmware_nowait() is
true. When uevent is true it requests that a kobject uevent be sent to
userspace for the firmware request through the sysfs fallback mechanism
if the firmware file is not found.
* If the firmware cache is determined to be needed as per the above two
criteria the firmware cache is setup by adding a devres entry for the
device making the firmware request.
* The firmware devres entry is maintained throughout the lifetime of the
device. This means that even if you release_firmware() the firmware cache
will still be used on resume from suspend.
* The timeout for the fallback mechanism is temporarily reduced to 10 seconds
as the firmware cache is set up during suspend, the timeout is set back to
the old value you had configured after the cache is set up.
* Upon suspend any pending non-uevent firmware requests are killed to avoid
stalling the kernel, this is done with kill_requests_without_uevent(). Kernel
calls requiring the non-uevent therefore need to implement their own firmware
cache mechanism but must not use the firmware API on suspend.
@@ -0,0 +1,31 @@
=====================
Firmware search paths
=====================
The following search paths are used to look for firmware on your
root filesystem.
* fw_path_para - module parameter - default is empty so this is ignored
* /lib/firmware/updates/UTS_RELEASE/
* /lib/firmware/updates/
* /lib/firmware/UTS_RELEASE/
* /lib/firmware/
The module parameter ''path'' can be passed to the firmware_class module
to activate the first optional custom fw_path_para. The custom path can
only be up to 256 characters long. The kernel parameter passed would be:
* 'firmware_class.path=$CUSTOMIZED_PATH'
There is an alternative to customize the path at run time after bootup, you
can use the file:
* /sys/module/firmware_class/parameters/path
You would echo into it your custom path and firmware requested will be searched
for there first. Be aware that newline characters will be taken into account
and may not produce the intended effects. For instance you might want to use:
echo -n /path/to/script > /sys/module/firmware_class/parameters/path
to ensure that your script is being used.
@@ -0,0 +1,127 @@
.. SPDX-License-Identifier: GPL-2.0
===================
Firmware Upload API
===================
A device driver that registers with the firmware loader will expose
persistent sysfs nodes to enable users to initiate firmware updates for
that device. It is the responsibility of the device driver and/or the
device itself to perform any validation on the data received. Firmware
upload uses the same *loading* and *data* sysfs files described in the
documentation for firmware fallback. It also adds additional sysfs files
to provide status on the transfer of the firmware image to the device.
Register for firmware upload
============================
A device driver registers for firmware upload by calling
firmware_upload_register(). Among the parameter list is a name to
identify the device under /sys/class/firmware. A user may initiate a
firmware upload by echoing a 1 to the *loading* sysfs file for the target
device. Next, the user writes the firmware image to the *data* sysfs
file. After writing the firmware data, the user echos 0 to the *loading*
sysfs file to signal completion. Echoing 0 to *loading* also triggers the
transfer of the firmware to the lower-lever device driver in the context
of a kernel worker thread.
To use the firmware upload API, write a driver that implements a set of
ops. The probe function calls firmware_upload_register() and the remove
function calls firmware_upload_unregister() such as::
static const struct fw_upload_ops m10bmc_ops = {
.prepare = m10bmc_sec_prepare,
.write = m10bmc_sec_write,
.poll_complete = m10bmc_sec_poll_complete,
.cancel = m10bmc_sec_cancel,
.cleanup = m10bmc_sec_cleanup,
};
static int m10bmc_sec_probe(struct platform_device *pdev)
{
const char *fw_name, *truncate;
struct m10bmc_sec *sec;
struct fw_upload *fwl;
unsigned int len;
sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL);
if (!sec)
return -ENOMEM;
sec->dev = &pdev->dev;
sec->m10bmc = dev_get_drvdata(pdev->dev.parent);
dev_set_drvdata(&pdev->dev, sec);
fw_name = dev_name(sec->dev);
truncate = strstr(fw_name, ".auto");
len = (truncate) ? truncate - fw_name : strlen(fw_name);
sec->fw_name = kmemdup_nul(fw_name, len, GFP_KERNEL);
fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name,
&m10bmc_ops, sec);
if (IS_ERR(fwl)) {
dev_err(sec->dev, "Firmware Upload driver failed to start\n");
kfree(sec->fw_name);
return PTR_ERR(fwl);
}
sec->fwl = fwl;
return 0;
}
static int m10bmc_sec_remove(struct platform_device *pdev)
{
struct m10bmc_sec *sec = dev_get_drvdata(&pdev->dev);
firmware_upload_unregister(sec->fwl);
kfree(sec->fw_name);
return 0;
}
firmware_upload_register
------------------------
.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c
:identifiers: firmware_upload_register
firmware_upload_unregister
--------------------------
.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c
:identifiers: firmware_upload_unregister
Firmware Upload Ops
-------------------
.. kernel-doc:: include/linux/firmware.h
:identifiers: fw_upload_ops
Firmware Upload Progress Codes
------------------------------
The following progress codes are used internally by the firmware loader.
Corresponding strings are reported through the status sysfs node that
is described below and are documented in the ABI documentation.
.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.h
:identifiers: fw_upload_prog
Firmware Upload Error Codes
---------------------------
The following error codes may be returned by the driver ops in case of
failure:
.. kernel-doc:: include/linux/firmware.h
:identifiers: fw_upload_err
Sysfs Attributes
================
In addition to the *loading* and *data* sysfs files, there are additional
sysfs files to monitor the status of the data transfer to the target
device and to determine the final pass/fail status of the transfer.
Depending on the device and the size of the firmware image, a firmware
update could take milliseconds or minutes.
The additional sysfs files are:
* status - provides an indication of the progress of a firmware update
* error - provides error information for a failed firmware update
* remaining_size - tracks the data transfer portion of an update
* cancel - echo 1 to this file to cancel the update
@@ -0,0 +1,12 @@
==================
Linux Firmware API
==================
.. toctree::
introduction
core
efi/index
request_firmware
fw_upload
other_interfaces
@@ -0,0 +1,27 @@
============
Introduction
============
The firmware API enables kernel code to request files required
for functionality from userspace, the uses vary:
* Microcode for CPU errata
* Device driver firmware, required to be loaded onto device
microcontrollers
* Device driver information data (calibration data, EEPROM overrides),
some of which can be completely optional.
Types of firmware requests
==========================
There are two types of calls:
* Synchronous
* Asynchronous
Which one you use vary depending on your requirements, the rule of thumb
however is you should strive to use the asynchronous APIs unless you also
are already using asynchronous initialization mechanisms which will not
stall or delay boot. Even if loading firmware does not take a lot of time
processing firmware might, and this can still delay boot or initialization,
as such mechanisms such as asynchronous probe can help supplement drivers.
@@ -0,0 +1,20 @@
=====================
Firmware lookup order
=====================
Different functionality is available to enable firmware to be found.
Below is chronological order of how firmware will be looked for once
a driver issues a firmware API call.
* The ''Built-in firmware'' is checked first, if the firmware is present we
return it immediately
* The ''Firmware cache'' is looked at next. If the firmware is found we
return it immediately
* The ''Direct filesystem lookup'' is performed next, if found we
return it immediately
* The ''Platform firmware fallback'' is performed next, but only when
firmware_request_platform() is used, if found we return it immediately
* If no firmware has been found and the fallback mechanism was enabled
the sysfs interface is created. After this either a kobject uevent
is issued or the custom firmware loading is relied upon for firmware
loading up to the timeout value.
@@ -0,0 +1,51 @@
Other Firmware Interfaces
=========================
DMI Interfaces
--------------
.. kernel-doc:: drivers/firmware/dmi_scan.c
:export:
EDD Interfaces
--------------
.. kernel-doc:: drivers/firmware/edd.c
:internal:
Generic System Framebuffers Interface
-------------------------------------
.. kernel-doc:: drivers/firmware/sysfb.c
:export:
Intel Stratix10 SoC Service Layer
---------------------------------
Some features of the Intel Stratix10 SoC require a level of privilege
higher than the kernel is granted. Such secure features include
FPGA programming. In terms of the ARMv8 architecture, the kernel runs
at Exception Level 1 (EL1), access to the features requires
Exception Level 3 (EL3).
The Intel Stratix10 SoC service layer provides an in kernel API for
drivers to request access to the secure features. The requests are queued
and processed one by one. ARM’s SMCCC is used to pass the execution
of the requests on to a secure monitor (EL3).
.. kernel-doc:: include/linux/firmware/intel/stratix10-svc-client.h
:functions: stratix10_svc_command_code
.. kernel-doc:: include/linux/firmware/intel/stratix10-svc-client.h
:functions: stratix10_svc_client_msg
.. kernel-doc:: include/linux/firmware/intel/stratix10-svc-client.h
:functions: stratix10_svc_command_config_type
.. kernel-doc:: include/linux/firmware/intel/stratix10-svc-client.h
:functions: stratix10_svc_cb_data
.. kernel-doc:: include/linux/firmware/intel/stratix10-svc-client.h
:functions: stratix10_svc_client
.. kernel-doc:: drivers/firmware/stratix10-svc.c
:export:
@@ -0,0 +1,80 @@
====================
request_firmware API
====================
You would typically load firmware and then load it into your device somehow.
The typical firmware work flow is reflected below::
if(request_firmware(&fw_entry, $FIRMWARE, device) == 0)
copy_fw_to_device(fw_entry->data, fw_entry->size);
release_firmware(fw_entry);
Synchronous firmware requests
=============================
Synchronous firmware requests will wait until the firmware is found or until
an error is returned.
request_firmware
----------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: request_firmware
firmware_request_nowarn
-----------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: firmware_request_nowarn
firmware_request_platform
-------------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: firmware_request_platform
request_firmware_direct
-----------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: request_firmware_direct
request_firmware_into_buf
-------------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: request_firmware_into_buf
Asynchronous firmware requests
==============================
Asynchronous firmware requests allow driver code to not have to wait
until the firmware or an error is returned. Function callbacks are
provided so that when the firmware or an error is found the driver is
informed through the callback. request_firmware_nowait() cannot be called
in atomic contexts.
request_firmware_nowait
-----------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: request_firmware_nowait
Special optimizations on reboot
===============================
Some devices have an optimization in place to enable the firmware to be
retained during system reboot. When such optimizations are used the driver
author must ensure the firmware is still available on resume from suspend,
this can be done with firmware_request_cache() instead of requesting for the
firmware to be loaded.
firmware_request_cache()
------------------------
.. kernel-doc:: drivers/base/firmware_loader/main.c
:functions: firmware_request_cache
request firmware API expected driver use
========================================
Once an API call returns you process the firmware and then release the
firmware. For example if you used request_firmware() and it returns,
the driver has the firmware image accessible in fw_entry->{data,size}.
If something went wrong request_firmware() returns non-zero and fw_entry
is set to NULL. Once your driver is done with processing the firmware it
can call release_firmware(fw_entry) to release the firmware image
and any related resource.