€•XŒsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ;/translations/zh_CN/driver-api/firmware/fallback-mechanisms”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ;/translations/zh_TW/driver-api/firmware/fallback-mechanisms”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ;/translations/it_IT/driver-api/firmware/fallback-mechanisms”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ;/translations/ja_JP/driver-api/firmware/fallback-mechanisms”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ;/translations/ko_KR/driver-api/firmware/fallback-mechanisms”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ;/translations/pt_BR/driver-api/firmware/fallback-mechanisms”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ;/translations/sp_SP/driver-api/firmware/fallback-mechanisms”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒFallback mechanisms”h]”hŒFallback mechanisms”…”�”}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒU/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms.rst”h´KubhŒ paragraph”“”)�”}”(hX1A 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:”h]”hX1A 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:”…”�”}”(hhÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhŒ block_quote”“”)�”}”(hX^* 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. ”h]”hŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hXCONFIG_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.”h]”hÌ)�”}”(hXCONFIG_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.”h]”hXCONFIG_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.”…”�”}”(hhìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hhèubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhhãubhç)�”}”(hX+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. ”h]”hÌ)�”}”(hX*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.”h]”hX*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.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khjubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhhãubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1háh³hÊh´K hhÝubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛh³hÊh´K hh·h²hubhÌ)�”}”(hŒ4Note that this means when having this configuration:”h]”hŒ4Note that this means when having this configuration:”…”�”}”(hj&h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(hŒFCONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n”h]”hŒFCONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n”…”�”}”(hj4h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(hŒ{the kobject uevent fallback mechanism will never take effect even for request_firmware_nowait() when uevent is set to true.”h]”hŒ{the kobject uevent fallback mechanism will never take effect even for request_firmware_nowait() when uevent is set to true.”…”�”}”(hjBh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubh¶)�”}”(hhh]”(h»)�”}”(hŒ*Justifying the firmware fallback mechanism”h]”hŒ*Justifying the firmware fallback mechanism”…”�”}”(hjSh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjPh²hh³hÊh´K ubhÌ)�”}”(hŒ¬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:”h]”hŒ¬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:”…”�”}”(hjah²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K"hjPh²hubhâ)�”}”(hhh]”(hç)�”}”(hŒ:Race against access with the root filesystem upon bootup. ”h]”hÌ)�”}”(hŒ9Race against access with the root filesystem upon bootup.”h]”hŒ9Race against access with the root filesystem upon bootup.”…”�”}”(hjvh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K&hjrubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjoh²hh³hÊh´Nubhç)�”}”(hŒ¼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(). ”h]”hÌ)�”}”(hŒ»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().”h]”hŒ»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().”…”�”}”(hjŽh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K(hjŠubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjoh²hh³hÊh´Nubhç)�”}”(hX 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. ”h]”(hÌ)�”}”(hŒ1Firmware is not accessible through typical means:”h]”hŒ1Firmware is not accessible through typical means:”…”�”}”(hj¦h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K,hj¢ubhÜ)�”}”(hX­* 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. ”h]”hâ)�”}”(hhh]”(hç)�”}”(hŒ/It cannot be installed into the root filesystem”h]”hÌ)�”}”(hj½h]”hŒ/It cannot be installed into the root filesystem”…”�”}”(hj¿h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K.hj»ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj¸ubhç)�”}”(hXoThe 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. ”h]”hÌ)�”}”(hXnThe 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.”h]”hXnThe 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.”…”�”}”(hjÖh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K/hjÒubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj¸ubeh}”(h]”h ]”h"]”h$]”h&]”jjuh1háh³hÊh´K.hj´ubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛh³hÊh´K.hj¢ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hæhjoh²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jjuh1háh³hÊh´K&hjPh²hubeh}”(h]”Œ*justifying-the-firmware-fallback-mechanism”ah ]”h"]”Œ*justifying the firmware fallback mechanism”ah$]”h&]”uh1hµhh·h²hh³hÊh´K ubh¶)�”}”(hhh]”(h»)�”}”(hŒTypes of fallback mechanisms”h]”hŒTypes of fallback mechanisms”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj h²hh³hÊh´K7ubhÌ)�”}”(hŒjThere are really two fallback mechanisms available using one shared sysfs interface as a loading facility:”h]”hŒjThere are really two fallback mechanisms available using one shared sysfs interface as a loading facility:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K9hj h²hubhâ)�”}”(hhh]”(hç)�”}”(hŒ!Kobject uevent fallback mechanism”h]”hÌ)�”}”(hj.h]”hŒ!Kobject uevent fallback mechanism”…”�”}”(hj0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K /sys/$DEVPATH/loading”h]”hŒecho 1 > /sys/$DEVPATH/loading”…”�”}”hj;sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1j9h³hÊh´Kfhjwh²hubhÌ)�”}”(hŒÚ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.”h]”hŒÚ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.”…”�”}”(hjKh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhjwh²hubhÌ)�”}”(hŒ½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.”h]”hŒ½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.”…”�”}”(hjYh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Klhjwh²hubh¶)�”}”(hhh]”(h»)�”}”(hŒfirmware_fallback_sysfs”h]”hŒfirmware_fallback_sysfs”…”�”}”(hjjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjgh²hh³hÊh´KqubhŒindex”“”)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œentries”]”(Œsingle”Œ$firmware_fallback_sysfs (C function)”Œc.firmware_fallback_sysfs”hNt”auh1jxhjgh²hh³Nh´NubhŒdesc”“”)�”}”(hhh]”(hŒdesc_signature”“”)�”}”(hŒrint firmware_fallback_sysfs (struct firmware *fw, const char *name, struct device *device, u32 opt_flags, int ret)”h]”hŒdesc_signature_line”“”)�”}”(hŒqint firmware_fallback_sysfs(struct firmware *fw, const char *name, struct device *device, u32 opt_flags, int ret)”h]”(hŒdesc_sig_keyword_type”“”)�”}”(hŒint”h]”hŒint”…”�”}”(hjœh²hh³Nh´Nubah}”(h]”h ]”Œkt”ah"]”h$]”h&]”uh1jšhj–h²hh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÕubhŒdesc_sig_space”“”)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj®h²hh³Nh´Nubah}”(h]”h ]”Œw”ah"]”h$]”h&]”uh1j¬hj–h²hh³j«h´KÕubhŒ desc_name”“”)�”}”(hŒfirmware_fallback_sysfs”h]”hŒ desc_sig_name”“”)�”}”(hŒfirmware_fallback_sysfs”h]”hŒfirmware_fallback_sysfs”…”�”}”(hjÅh²hh³Nh´Nubah}”(h]”h ]”Œn”ah"]”h$]”h&]”uh1jÃhj¿ubah}”(h]”h ]”(Œsig-name”Œdescname”eh"]”h$]”h&]”jIjJuh1j½hj–h²hh³j«h´KÕubhŒdesc_parameterlist”“”)�”}”(hŒV(struct firmware *fw, const char *name, struct device *device, u32 opt_flags, int ret)”h]”(hŒdesc_parameter”“”)�”}”(hŒstruct firmware *fw”h]”(hŒdesc_sig_keyword”“”)�”}”(hŒstruct”h]”hŒstruct”…”�”}”(hjêh²hh³Nh´Nubah}”(h]”h ]”Œk”ah"]”h$]”h&]”uh1jèhjäubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjùh²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hjäubh)�”}”(hhh]”jÄ)�”}”(hŒfirmware”h]”hŒfirmware”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhjubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”j Œreftype”Œ identifier”Œ reftarget”j Œmodname”NŒ classname”NŒ c:parent_key”Œsphinx.domains.c”Œ LookupKey”“”)�”}”Œdata”]”j%Œ ASTIdentifier”“”)�”}”j jÇsbŒc.firmware_fallback_sysfs”†”asbuh1hhjäubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj2h²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hjäubhŒdesc_sig_punctuation”“”)�”}”(hjh]”hŒ*”…”�”}”(hjBh²hh³Nh´Nubah}”(h]”h ]”Œp”ah"]”h$]”h&]”uh1j@hjäubjÄ)�”}”(hŒfw”h]”hŒfw”…”�”}”(hjPh²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhjäubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆjIjJuh1jâhjÞubjã)�”}”(hŒconst char *name”h]”(jé)�”}”(hŒconst”h]”hŒconst”…”�”}”(hjih²hh³Nh´Nubah}”(h]”h ]”jõah"]”h$]”h&]”uh1jèhjeubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjwh²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hjeubj›)�”}”(hŒchar”h]”hŒchar”…”�”}”(hj…h²hh³Nh´Nubah}”(h]”h ]”j§ah"]”h$]”h&]”uh1jšhjeubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj“h²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hjeubjA)�”}”(hjh]”hŒ*”…”�”}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”jLah"]”h$]”h&]”uh1j@hjeubjÄ)�”}”(hŒname”h]”hŒname”…”�”}”(hj®h²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhjeubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆjIjJuh1jâhjÞubjã)�”}”(hŒstruct device *device”h]”(jé)�”}”(hjìh]”hŒstruct”…”�”}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”jõah"]”h$]”h&]”uh1jèhjÃubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hjÃubh)�”}”(hhh]”jÄ)�”}”(hŒdevice”h]”hŒdevice”…”�”}”(hjåh²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhjâubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”j Œreftype”j Œ reftarget”jçŒmodname”NŒ classname”Nj$j')�”}”j*]”j.Œc.firmware_fallback_sysfs”†”asbuh1hhjÃubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hjÃubjA)�”}”(hjh]”hŒ*”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”jLah"]”h$]”h&]”uh1j@hjÃubjÄ)�”}”(hŒdevice”h]”hŒdevice”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhjÃubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆjIjJuh1jâhjÞubjã)�”}”(hŒ u32 opt_flags”h]”(h)�”}”(hhh]”jÄ)�”}”(hŒu32”h]”hŒu32”…”�”}”(hj:h²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhj7ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”j Œreftype”j Œ reftarget”j<Œmodname”NŒ classname”Nj$j')�”}”j*]”j.Œc.firmware_fallback_sysfs”†”asbuh1hhj3ubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hj3ubjÄ)�”}”(hŒ opt_flags”h]”hŒ opt_flags”…”�”}”(hjfh²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhj3ubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆjIjJuh1jâhjÞubjã)�”}”(hŒint ret”h]”(j›)�”}”(hŒint”h]”hŒint”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”j§ah"]”h$]”h&]”uh1jšhj{ubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hj{ubjÄ)�”}”(hŒret”h]”hŒret”…”�”}”(hj›h²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhj{ubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆjIjJuh1jâhjÞubeh}”(h]”h ]”h"]”h$]”h&]”jIjJuh1jÜhj–h²hh³j«h´KÕubeh}”(h]”h ]”h"]”h$]”h&]”jIjJŒ add_permalink”ˆuh1j”Œsphinx_line_type”Œ declarator”hj�h²hh³j«h´KÕubah}”(h]”j‡ah ]”(Œsig”Œ sig-object”eh"]”h$]”h&]”Œ is_multiline”ˆŒ _toc_parts”)Œ _toc_name”huh1jŽh³j«h´KÕhj‹h²hubhŒ desc_content”“”)�”}”(hhh]”hÌ)�”}”(hŒ+use the fallback mechanism to find firmware”h]”hŒ+use the fallback mechanism to find firmware”…”�”}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÕhjÌh²hubah}”(h]”h ]”h"]”h$]”h&]”uh1jÊhj‹h²hh³j«h´KÕubeh}”(h]”h ]”(j Œfunction”eh"]”h$]”h&]”Œdomain”j Œobjtype”jçŒdesctype”jçŒnoindex”‰Œ noindexentry”‰Œnocontentsentry”‰uh1j‰h²hhjgh³Nh´NubhŒ container”“”)�”}”(hXÀ**Parameters** ``struct firmware *fw`` pointer to firmware image ``const char *name`` name of firmware file to look for ``struct device *device`` device for which firmware is being loaded ``u32 opt_flags`` options to control firmware loading behaviour, as defined by :c:type:`enum fw_opt ` ``int ret`` return value from direct lookup which triggered the fallback mechanism **Description** This function is called if direct lookup for the firmware failed, it enables a fallback mechanism through userspace by exposing a sysfs loading interface. Userspace is in charge of loading the firmware through the sysfs loading interface. This sysfs fallback mechanism may be disabled completely on a system by setting the proc sysctl value ignore_sysfs_fallback to true. If this is false we check if the internal API caller set the **FW_OPT_NOFALLBACK_SYSFS** flag, if so it would also disable the fallback mechanism. A system may want to enforce the sysfs fallback mechanism at all times, it can do this by setting ignore_sysfs_fallback to false and force_sysfs_fallback to true. Enabling force_sysfs_fallback is functionally equivalent to build a kernel with CONFIG_FW_LOADER_USER_HELPER_FALLBACK.”h]”(hÌ)�”}”(hŒ**Parameters**”h]”hŒstrong”“”)�”}”(hjùh]”hŒ Parameters”…”�”}”(hjýh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jûhj÷ubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÙhjóubhŒdefinition_list”“”)�”}”(hhh]”(hŒdefinition_list_item”“”)�”}”(hŒ2``struct firmware *fw`` pointer to firmware image ”h]”(hŒterm”“”)�”}”(hŒ``struct firmware *fw``”h]”j)�”}”(hj h]”hŒstruct firmware *fw”…”�”}”(hj"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÖhjubhŒ definition”“”)�”}”(hhh]”hÌ)�”}”(hŒpointer to firmware image”h]”hŒpointer to firmware image”…”�”}”(hj;h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³j5h´KÖhj8ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³j5h´KÖhjubj)�”}”(hŒ7``const char *name`` name of firmware file to look for ”h]”(j)�”}”(hŒ``const char *name``”h]”j)�”}”(hj[h]”hŒconst char *name”…”�”}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjYubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´K×hjUubj7)�”}”(hhh]”hÌ)�”}”(hŒ!name of firmware file to look for”h]”hŒ!name of firmware file to look for”…”�”}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³jph´K×hjqubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hjUubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³jph´K×hjubj)�”}”(hŒD``struct device *device`` device for which firmware is being loaded ”h]”(j)�”}”(hŒ``struct device *device``”h]”j)�”}”(hj”h]”hŒstruct device *device”…”�”}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj’ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KØhjŽubj7)�”}”(hhh]”hÌ)�”}”(hŒ)device for which firmware is being loaded”h]”hŒ)device for which firmware is being loaded”…”�”}”(hj­h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³j©h´KØhjªubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hjŽubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³j©h´KØhjubj)�”}”(hŒn``u32 opt_flags`` options to control firmware loading behaviour, as defined by :c:type:`enum fw_opt ` ”h]”(j)�”}”(hŒ``u32 opt_flags``”h]”j)�”}”(hjÍh]”hŒ u32 opt_flags”…”�”}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjËubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÚhjÇubj7)�”}”(hhh]”hÌ)�”}”(hŒ[options to control firmware loading behaviour, as defined by :c:type:`enum fw_opt `”h]”(hŒ=options to control firmware loading behaviour, as defined by ”…”�”}”(hjæh²hh³Nh´Nubh)�”}”(hŒ:c:type:`enum fw_opt `”h]”j)�”}”(hjðh]”hŒ enum fw_opt”…”�”}”(hjòh²hh³Nh´Nubah}”(h]”h ]”(j j Œc-type”eh"]”h$]”h&]”uh1jhjîubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jŒ refdomain”j Œreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰j$j')�”}”j*]”sbjŒfw_opt”uh1hh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÙhjæubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³jh´KÙhjãubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hjÇubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³jâh´KÚhjubj)�”}”(hŒS``int ret`` return value from direct lookup which triggered the fallback mechanism ”h]”(j)�”}”(hŒ ``int ret``”h]”j)�”}”(hj)h]”hŒint ret”…”�”}”(hj+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj'ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÛhj#ubj7)�”}”(hhh]”hÌ)�”}”(hŒFreturn value from direct lookup which triggered the fallback mechanism”h]”hŒFreturn value from direct lookup which triggered the fallback mechanism”…”�”}”(hjBh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³j>h´KÛhj?ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hj#ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³j>h´KÛhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjóubhÌ)�”}”(hŒ**Description**”h]”jü)�”}”(hjdh]”hŒ Description”…”�”}”(hjfh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jûhjbubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÝhjóubhÌ)�”}”(hX This function is called if direct lookup for the firmware failed, it enables a fallback mechanism through userspace by exposing a sysfs loading interface. Userspace is in charge of loading the firmware through the sysfs loading interface. This sysfs fallback mechanism may be disabled completely on a system by setting the proc sysctl value ignore_sysfs_fallback to true. If this is false we check if the internal API caller set the **FW_OPT_NOFALLBACK_SYSFS** flag, if so it would also disable the fallback mechanism. A system may want to enforce the sysfs fallback mechanism at all times, it can do this by setting ignore_sysfs_fallback to false and force_sysfs_fallback to true. Enabling force_sysfs_fallback is functionally equivalent to build a kernel with CONFIG_FW_LOADER_USER_HELPER_FALLBACK.”h]”(hX±This function is called if direct lookup for the firmware failed, it enables a fallback mechanism through userspace by exposing a sysfs loading interface. Userspace is in charge of loading the firmware through the sysfs loading interface. This sysfs fallback mechanism may be disabled completely on a system by setting the proc sysctl value ignore_sysfs_fallback to true. If this is false we check if the internal API caller set the ”…”�”}”(hjzh²hh³Nh´Nubjü)�”}”(hŒ**FW_OPT_NOFALLBACK_SYSFS**”h]”hŒFW_OPT_NOFALLBACK_SYSFS”…”�”}”(hj‚h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jûhjzubhXT flag, if so it would also disable the fallback mechanism. A system may want to enforce the sysfs fallback mechanism at all times, it can do this by setting ignore_sysfs_fallback to false and force_sysfs_fallback to true. Enabling force_sysfs_fallback is functionally equivalent to build a kernel with CONFIG_FW_LOADER_USER_HELPER_FALLBACK.”…”�”}”(hjzh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œ€/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:114: ./drivers/base/firmware_loader/fallback.c”h´KÜhjóubeh}”(h]”h ]”Œ kernelindent”ah"]”h$]”h&]”uh1jñhjgh²hh³Nh´Nubeh}”(h]”Œfirmware-fallback-sysfs”ah ]”h"]”Œfirmware_fallback_sysfs”ah$]”h&]”uh1hµhjwh²hh³hÊh´Kqubeh}”(h]”Œfirmware-sysfs-loading-facility”ah ]”h"]”Œfirmware sysfs loading facility”ah$]”h&]”uh1hµhh·h²hh³hÊh´KBubh¶)�”}”(hhh]”(h»)�”}”(hŒ*Firmware kobject uevent fallback mechanism”h]”hŒ*Firmware kobject uevent fallback mechanism”…”�”}”(hjµh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj²h²hh³hÊh´KvubhÌ)�”}”(hX¾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().”h]”hX¾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().”…”�”}”(hjÃh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kxhj²h²hubhÌ)�”}”(hXFThe 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.”h]”hXJThe 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.”…”�”}”(hjÑh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj²h²hubhÌ)�”}”(hXí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.”h]”hX÷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.”…”�”}”(hjßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kˆhj²h²hubhÌ)�”}”(hŒ›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:”h]”hŒŸ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:”…”�”}”(hjíh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K“hj²h²hubhâ)�”}”(hhh]”(hç)�”}”(hŒFIRMWARE=firmware name”h]”hÌ)�”}”(hjh]”hŒFIRMWARE=firmware name”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K—hjþubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjûh²hh³hÊh´Nubhç)�”}”(hŒTIMEOUT=timeout value”h]”hÌ)�”}”(hjh]”hŒTIMEOUT=timeout value”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K˜hjubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjûh²hh³hÊh´Nubhç)�”}”(hŒ6ASYNC=whether or not the API request was asynchronous ”h]”hÌ)�”}”(hŒ5ASYNC=whether or not the API request was asynchronous”h]”hŒ5ASYNC=whether or not the API request was asynchronous”…”�”}”(hj0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K™hj,ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjûh²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jjuh1háh³hÊh´K—hj²h²hubhÌ)�”}”(hŒ{By default DEVPATH is set by the internal kernel kobject infrastructure. Below is an example simple kobject uevent script::”h]”hŒzBy default DEVPATH is set by the internal kernel kobject infrastructure. Below is an example simple kobject uevent script:”…”�”}”(hjJh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K›hj²h²hubj:)�”}”(hŒË# 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”h]”hŒË# 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”…”�”}”hjXsbah}”(h]”h ]”h"]”h$]”h&]”jIjJuh1j9h³hÊh´Kžhj²h²hubeh}”(h]”Œ*firmware-kobject-uevent-fallback-mechanism”ah ]”h"]”Œ*firmware kobject uevent fallback mechanism”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kvubh¶)�”}”(hhh]”(h»)�”}”(hŒ"Firmware custom fallback mechanism”h]”hŒ"Firmware custom fallback mechanism”…”�”}”(hjqh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjnh²hh³hÊh´K¥ubhÌ)�”}”(hXù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.”h]”hXý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.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K§hjnh²hubhÌ)�”}”(hX®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.”h]”hX®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.”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¯hjnh²hubeh}”(h]”Œ"firmware-custom-fallback-mechanism”ah ]”h"]”Œ"firmware custom fallback mechanism”ah$]”h&]”uh1hµhh·h²hh³hÊh´K¥ubh¶)�”}”(hhh]”(h»)�”}”(hŒFirmware fallback timeout”h]”hŒFirmware fallback timeout”…”�”}”(hj¦h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj£h²hh³hÊh´K¾ubhÌ)�”}”(hXž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.”h]”hXž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.”…”�”}”(hj´h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÀhj£h²hubhÌ)�”}”(hŒ`You can customize the firmware timeout by echo'ing your desired timeout into the following file:”h]”hŒbYou can customize the firmware timeout by echo’ing your desired timeout into the following file:”…”�”}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÇhj£h²hubhâ)�”}”(hhh]”hç)�”}”(hŒ/sys/class/firmware/timeout ”h]”hÌ)�”}”(hŒ/sys/class/firmware/timeout”h]”hŒ/sys/class/firmware/timeout”…”�”}”(hj×h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÊhjÓubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjÐh²hh³hÊh´Nubah}”(h]”h ]”h"]”h$]”h&]”jjuh1háh³hÊh´KÊhj£h²hubhÌ)�”}”(hŒcIf you echo 0 into it means MAX_JIFFY_OFFSET will be used. The data type for the timeout is an int.”h]”hŒcIf you echo 0 into it means MAX_JIFFY_OFFSET will be used. The data type for the timeout is an int.”…”�”}”(hjñh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÌhj£h²hubeh}”(h]”Œfirmware-fallback-timeout”ah ]”h"]”Œfirmware fallback timeout”ah$]”h&]”uh1hµhh·h²hh³hÊh´K¾ubh¶)�”}”(hhh]”(h»)�”}”(hŒ(EFI embedded firmware fallback mechanism”h]”hŒ(EFI embedded firmware fallback mechanism”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj h²hh³hÊh´KÐubhÌ)�”}”(hŒÓ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.”h]”hŒÙ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.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÒhj h²hubhÌ)�”}”(hŒà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.”h]”hŒà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.”…”�”}”(hj& h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÖhj h²hubhÌ)�”}”(hŒiA device driver which needs this can describe the firmware it needs using an efi_embedded_fw_desc struct:”h]”hŒiA device driver which needs this can describe the firmware it needs using an efi_embedded_fw_desc struct:”…”�”}”(hj4 h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÛhj h²hubjy)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œentries”]”(j…Œefi_embedded_fw_desc (C struct)”Œc.efi_embedded_fw_desc”hNt”auh1jxhj h²hh³Nh´NubjŠ)�”}”(hhh]”(j�)�”}”(hŒefi_embedded_fw_desc”h]”j•)�”}”(hŒstruct efi_embedded_fw_desc”h]”(jé)�”}”(hjìh]”hŒstruct”…”�”}”(hj[ h²hh³Nh´Nubah}”(h]”h ]”jõah"]”h$]”h&]”uh1jèhjW h²hh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Kubj­)�”}”(hŒ ”h]”hŒ ”…”�”}”(hji h²hh³Nh´Nubah}”(h]”h ]”j¹ah"]”h$]”h&]”uh1j¬hjW h²hh³jh h´Kubj¾)�”}”(hŒefi_embedded_fw_desc”h]”jÄ)�”}”(hjU h]”hŒefi_embedded_fw_desc”…”�”}”(hj{ h²hh³Nh´Nubah}”(h]”h ]”jÐah"]”h$]”h&]”uh1jÃhjw ubah}”(h]”h ]”(j×jØeh"]”h$]”h&]”jIjJuh1j½hjW h²hh³jh h´Kubeh}”(h]”h ]”h"]”h$]”h&]”jIjJj¼ˆuh1j”j½j¾hjS h²hh³jh h´Kubah}”(h]”jN ah ]”(jÂjÃeh"]”h$]”h&]”jLjjÈ)jÉhuh1jŽh³jh h´KhjP h²hubjË)�”}”(hhh]”hÌ)�”}”(hŒQThis struct is used by the EFI embedded-fw code to search for embedded firmwares.”h]”hŒQThis struct is used by the EFI embedded-fw code to search for embedded firmwares.”…”�”}”(hj� h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Khjš h²hubah}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjP h²hh³jh h´Kubeh}”(h]”h ]”(j Œstruct”eh"]”h$]”h&]”jëj jìjµ jíjµ jî‰jï‰jð‰uh1j‰h²hhj h³Nh´Nubjò)�”}”(hXw**Definition**:: struct efi_embedded_fw_desc { const char *name; u8 prefix[EFI_EMBEDDED_FW_PREFIX_LEN]; u32 length; u8 sha256[32]; }; **Members** ``name`` Name to register the firmware with if found ``prefix`` First 8 bytes of the firmware ``length`` Length of the firmware in bytes including prefix ``sha256`` SHA256 of the firmware”h]”(hÌ)�”}”(hŒ**Definition**::”h]”(jü)�”}”(hŒ**Definition**”h]”hŒ Definition”…”�”}”(hjÁ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jûhj½ ubhŒ:”…”�”}”(hj½ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Khj¹ ubj:)�”}”(hŒ„struct efi_embedded_fw_desc { const char *name; u8 prefix[EFI_EMBEDDED_FW_PREFIX_LEN]; u32 length; u8 sha256[32]; };”h]”hŒ„struct efi_embedded_fw_desc { const char *name; u8 prefix[EFI_EMBEDDED_FW_PREFIX_LEN]; u32 length; u8 sha256[32]; };”…”�”}”hjÚ sbah}”(h]”h ]”h"]”h$]”h&]”jIjJuh1j9h³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Khj¹ ubhÌ)�”}”(hŒ **Members**”h]”jü)�”}”(hjë h]”hŒMembers”…”�”}”(hjí h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jûhjé ubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´K#hj¹ ubj)�”}”(hhh]”(j)�”}”(hŒ5``name`` Name to register the firmware with if found ”h]”(j)�”}”(hŒ``name``”h]”j)�”}”(hj h]”hŒname”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Khj ubj7)�”}”(hhh]”hÌ)�”}”(hŒ+Name to register the firmware with if found”h]”hŒ+Name to register the firmware with if found”…”�”}”(hj# h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³j h´Khj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³j h´Khj ubj)�”}”(hŒ)``prefix`` First 8 bytes of the firmware ”h]”(j)�”}”(hŒ ``prefix``”h]”j)�”}”(hjC h]”hŒprefix”…”�”}”(hjE h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjA ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Khj= ubj7)�”}”(hhh]”hÌ)�”}”(hŒFirst 8 bytes of the firmware”h]”hŒFirst 8 bytes of the firmware”…”�”}”(hj\ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³jX h´KhjY ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hj= ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³jX h´Khj ubj)�”}”(hŒ<``length`` Length of the firmware in bytes including prefix ”h]”(j)�”}”(hŒ ``length``”h]”j)�”}”(hj| h]”hŒlength”…”�”}”(hj~ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjz ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Khjv ubj7)�”}”(hhh]”hÌ)�”}”(hŒ0Length of the firmware in bytes including prefix”h]”hŒ0Length of the firmware in bytes including prefix”…”�”}”(hj• h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³j‘ h´Khj’ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hjv ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³j‘ h´Khj ubj)�”}”(hŒ!``sha256`` SHA256 of the firmware”h]”(j)�”}”(hŒ ``sha256``”h]”j)�”}”(hjµ h]”hŒsha256”…”�”}”(hj· h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj³ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´Khj¯ ubj7)�”}”(hhh]”hÌ)�”}”(hŒSHA256 of the firmware”h]”hŒSHA256 of the firmware”…”�”}”(hjÎ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³Œx/var/lib/git/docbuild/linux/Documentation/driver-api/firmware/fallback-mechanisms:222: ./include/linux/efi_embedded_fw.h”h´KhjË ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hj¯ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³jÊ h´Khj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhj¹ ubeh}”(h]”h ]”Œ kernelindent”ah"]”h$]”h&]”uh1jñhj h²hh³Nh´NubhÌ)�”}”(hX!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.”h]”hX!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.”…”�”}”(hjö h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Káhj h²hubhÌ)�”}”(hŒË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.”h]”hŒÍ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.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kæhj h²hubhÌ)�”}”(hŒHTo register this array with the efi-embedded-fw code, a driver needs to:”h]”hŒHTo register this array with the efi-embedded-fw code, a driver needs to:”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kêhj h²hubhŒenumerated_list”“”)�”}”(hhh]”(hç)�”}”(hŒvAlways be builtin to the kernel or store the dmi_system_id array in a separate object file which always gets builtin. ”h]”hÌ)�”}”(hŒuAlways be builtin to the kernel or store the dmi_system_id array in a separate object file which always gets builtin.”h]”hŒuAlways be builtin to the kernel or store the dmi_system_id array in a separate object file which always gets builtin.”…”�”}”(hj) h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kìhj% ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj" h²hh³hÊh´Nubhç)�”}”(hŒZAdd an extern declaration for the dmi_system_id array to include/linux/efi_embedded_fw.h. ”h]”hÌ)�”}”(hŒYAdd an extern declaration for the dmi_system_id array to include/linux/efi_embedded_fw.h.”h]”hŒYAdd an extern declaration for the dmi_system_id array to include/linux/efi_embedded_fw.h.”…”�”}”(hjA h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kïhj= ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj" h²hh³hÊh´Nubhç)�”}”(hŒŸ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. ”h]”hÌ)�”}”(hŒž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.”h]”hŒž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.”…”�”}”(hjY h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KòhjU ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj" h²hh³hÊh´Nubhç)�”}”(hŒEAdd "select EFI_EMBEDDED_FIRMWARE if EFI_STUB" to its Kconfig entry. ”h]”hÌ)�”}”(hŒDAdd "select EFI_EMBEDDED_FIRMWARE if EFI_STUB" to its Kconfig entry.”h]”hŒHAdd “select EFI_EMBEDDED_FIRMWARE if EFI_STUBâ€� to its Kconfig entry.”…”�”}”(hjq h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Köhjm ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj" h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œarabic”Œprefix”hŒsuffix”Œ.”uh1j hj h²hh³hÊh´KìubhÌ)�”}”(hŒÖ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.”h]”hŒÖ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.”…”�”}”(hj� h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Køhj h²hubhÌ)�”}”(hŒ Note that:”h]”hŒ Note that:”…”�”}”(hjž h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kühj h²hubj! )�”}”(hhh]”(hç)�”}”(hX 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. ”h]”hÌ)�”}”(hXThe 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.”h]”hXThe 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.”…”�”}”(hj³ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kþhj¯ ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj¬ h²hh³hÊh´Nubhç)�”}”(hŒ·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. ”h]”hÌ)�”}”(hŒ¶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.”h]”hŒ¶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.”…”�”}”(hjË h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÇ ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj¬ h²hh³hÊh´Nubhç)�”}”(hŒ£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. ”h]”hÌ)�”}”(hŒ¢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.”h]”hŒ¢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.”…”�”}”(hjã h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjß ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj¬ h²hh³hÊh´Nubhç)�”}”(hXaThe 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. ”h]”hÌ)�”}”(hX`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.”h]”(hXThe 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 ”…”�”}”(hjû h²hh³Nh´NubhŒemphasis”“”)�”}”(hŒ *internal*”h]”hŒinternal”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjû ubhXW 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.”…”�”}”(hjû h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hj÷ ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhj¬ h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j‹ jŒ j� hjŽ j� uh1j hj h²hh³hÊh´Kþubh¶)�”}”(hhh]”(h»)�”}”(hŒ6Example how to check for and extract embedded firmware”h]”hŒ6Example how to check for and extract embedded firmware”…”�”}”(hj, h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj) h²hh³hÊh´MubhÌ)�”}”(hŒ\To check for, for example Silead touchscreen controller embedded firmware, do the following:”h]”hŒ\To check for, for example Silead touchscreen controller embedded firmware, do the following:”…”�”}”(hj: h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj) h²hubj! )�”}”(hhh]”(hç)�”}”(hŒ9Boot the system with efi=debug on the kernel commandline ”h]”hÌ)�”}”(hŒ8Boot the system with efi=debug on the kernel commandline”h]”hŒ8Boot the system with efi=debug on the kernel commandline”…”�”}”(hjO h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjK ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjH h²hh³hÊh´Nubhç)�”}”(hŒ>cp /sys/kernel/debug/efi/boot_services_code? to your home dir ”h]”hÌ)�”}”(hŒ=cp /sys/kernel/debug/efi/boot_services_code? to your home dir”h]”hŒ=cp /sys/kernel/debug/efi/boot_services_code? to your home dir”…”�”}”(hjg h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjc ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjH h²hh³hÊh´Nubhç)�”}”(hŒØ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. ”h]”hÌ)�”}”(hŒ×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.”h]”hŒ×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.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hj{ ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjH h²hh³hÊh´Nubhç)�”}”(hXThe 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. ”h]”hÌ)�”}”(hXThe 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.”•Wh]”hXThe 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.”…”�”}”(hj— h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M$hj“ ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjH h²hh³hÊh´Nubhç)�”}”(hŒÇ"dd if=boot_services_code? of=firmware bs=1 skip= count=" will extract the firmware for you. Inspect the firmware file in a hexeditor to make sure you got the dd parameters correct. ”h]”hÌ)�”}”(hŒÆ"dd if=boot_services_code? of=firmware bs=1 skip= count=" will extract the firmware for you. Inspect the firmware file in a hexeditor to make sure you got the dd parameters correct.”h]”hŒÊ“dd if=boot_services_code? of=firmware bs=1 skip= count=â€� will extract the firmware for you. Inspect the firmware file in a hexeditor to make sure you got the dd parameters correct.”…”�”}”(hj¯ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M,hj« ubah}”(h]”h ]”h"]”h$]”h&]”uh1hæhjH h²hh³hÊh´Nubhç)�”}”(hŒ=Copy it to /lib/firmware under the expected name to test it. ”h]”hÌ)�”}”(hŒ