From e7e7893f2281db84b094784647edda6a911c47a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Thu, 10 Feb 2022 18:09:17 +0100 Subject: [PATCH] pc: update wifi driver The driver falls in line with the previous 'legacy_wifi_drv' component where the ported wireless LAN stack and device driver is encapsulated in a library. This library in return is used by the 'Libc::Component' providing the necessary environment for the 'wpa_supplicant'. In constrast to the old driver a 'wifi' VFS plugin is in charge of initalizing the 'Lx_kit::Env' prior to executing any static constructors. Fixes #4455. --- .../recipes/raw/wifi_firmware/content.mk | 17 + .../dde_linux/recipes/raw/wifi_firmware/hash | 1 + repos/pc/lib/mk/spec/x86_32/wifi.mk | 5 + repos/pc/lib/mk/spec/x86_64/wifi.mk | 3 + repos/pc/lib/mk/vfs_wifi.mk | 11 + repos/pc/lib/mk/wifi.inc | 48 + repos/pc/lib/mk/wifi_firmware.mk | 24 + repos/pc/recipes/pkg/wifi/README | 2 + repos/pc/recipes/pkg/wifi/archives | 6 + repos/pc/recipes/pkg/wifi/hash | 1 + repos/pc/recipes/pkg/wifi/runtime | 43 + repos/pc/recipes/src/pc_wifi_drv/content.mk | 72 + repos/pc/recipes/src/pc_wifi_drv/hash | 1 + repos/pc/recipes/src/pc_wifi_drv/used_apis | 12 + repos/pc/run/wifi.run | 283 +++ repos/pc/src/drivers/wifi/pc/README | 108 ++ repos/pc/src/drivers/wifi/pc/frontend.h | 1658 +++++++++++++++++ repos/pc/src/drivers/wifi/pc/main.cc | 147 ++ repos/pc/src/drivers/wifi/pc/target.mk | 10 + repos/pc/src/drivers/wifi/pc/util.h | 90 + repos/pc/src/drivers/wifi/pc/wpa.cc | 57 + repos/pc/src/drivers/wifi/pc/wpa.h | 39 + repos/pc/src/lib/vfs/wifi/target.mk | 1 + repos/pc/src/lib/vfs/wifi/vfs.cc | 87 + repos/pc/src/lib/wifi/dummies.c | 798 ++++++++ repos/pc/src/lib/wifi/firmware.cc | 106 ++ repos/pc/src/lib/wifi/firmware_list.h | 26 + repos/pc/src/lib/wifi/generated_dummies.c | 1346 +++++++++++++ repos/pc/src/lib/wifi/libc_errno.h | 109 ++ repos/pc/src/lib/wifi/lx_emul.c | 765 ++++++++ repos/pc/src/lib/wifi/lx_emul.h | 37 + .../pc/src/lib/wifi/lx_emul/initcall_order.h | 208 +++ repos/pc/src/lib/wifi/lx_emul/pci_fixups.h | 5 + repos/pc/src/lib/wifi/lx_socket_call.c | 279 +++ repos/pc/src/lib/wifi/lx_socket_call.h | 75 + repos/pc/src/lib/wifi/misc.cc | 20 + repos/pc/src/lib/wifi/random.cc | 111 ++ repos/pc/src/lib/wifi/socket_call.cc | 724 +++++++ repos/pc/src/lib/wifi/spec/x86_32/source.list | 273 +++ repos/pc/src/lib/wifi/spec/x86_64/dep.list | 1290 +++++++++++++ repos/pc/src/lib/wifi/spec/x86_64/source.list | 273 +++ repos/pc/src/lib/wifi/symbol.map | 29 + repos/pc/src/lib/wifi/time.cc | 25 + repos/pc/src/lib/wifi/uplink.c | 285 +++ repos/pc/src/lib/wifi/wlan.cc | 104 ++ 45 files changed, 9614 insertions(+) create mode 100644 repos/dde_linux/recipes/raw/wifi_firmware/content.mk create mode 100644 repos/dde_linux/recipes/raw/wifi_firmware/hash create mode 100644 repos/pc/lib/mk/spec/x86_32/wifi.mk create mode 100644 repos/pc/lib/mk/spec/x86_64/wifi.mk create mode 100644 repos/pc/lib/mk/vfs_wifi.mk create mode 100644 repos/pc/lib/mk/wifi.inc create mode 100644 repos/pc/lib/mk/wifi_firmware.mk create mode 100644 repos/pc/recipes/pkg/wifi/README create mode 100644 repos/pc/recipes/pkg/wifi/archives create mode 100644 repos/pc/recipes/pkg/wifi/hash create mode 100644 repos/pc/recipes/pkg/wifi/runtime create mode 100644 repos/pc/recipes/src/pc_wifi_drv/content.mk create mode 100644 repos/pc/recipes/src/pc_wifi_drv/hash create mode 100644 repos/pc/recipes/src/pc_wifi_drv/used_apis create mode 100644 repos/pc/run/wifi.run create mode 100644 repos/pc/src/drivers/wifi/pc/README create mode 100644 repos/pc/src/drivers/wifi/pc/frontend.h create mode 100644 repos/pc/src/drivers/wifi/pc/main.cc create mode 100644 repos/pc/src/drivers/wifi/pc/target.mk create mode 100644 repos/pc/src/drivers/wifi/pc/util.h create mode 100644 repos/pc/src/drivers/wifi/pc/wpa.cc create mode 100644 repos/pc/src/drivers/wifi/pc/wpa.h create mode 100644 repos/pc/src/lib/vfs/wifi/target.mk create mode 100644 repos/pc/src/lib/vfs/wifi/vfs.cc create mode 100644 repos/pc/src/lib/wifi/dummies.c create mode 100644 repos/pc/src/lib/wifi/firmware.cc create mode 100644 repos/pc/src/lib/wifi/firmware_list.h create mode 100644 repos/pc/src/lib/wifi/generated_dummies.c create mode 100644 repos/pc/src/lib/wifi/libc_errno.h create mode 100644 repos/pc/src/lib/wifi/lx_emul.c create mode 100644 repos/pc/src/lib/wifi/lx_emul.h create mode 100644 repos/pc/src/lib/wifi/lx_emul/initcall_order.h create mode 100644 repos/pc/src/lib/wifi/lx_emul/pci_fixups.h create mode 100644 repos/pc/src/lib/wifi/lx_socket_call.c create mode 100644 repos/pc/src/lib/wifi/lx_socket_call.h create mode 100644 repos/pc/src/lib/wifi/misc.cc create mode 100644 repos/pc/src/lib/wifi/random.cc create mode 100644 repos/pc/src/lib/wifi/socket_call.cc create mode 100644 repos/pc/src/lib/wifi/spec/x86_32/source.list create mode 100644 repos/pc/src/lib/wifi/spec/x86_64/dep.list create mode 100644 repos/pc/src/lib/wifi/spec/x86_64/source.list create mode 100644 repos/pc/src/lib/wifi/symbol.map create mode 100644 repos/pc/src/lib/wifi/time.cc create mode 100644 repos/pc/src/lib/wifi/uplink.c create mode 100644 repos/pc/src/lib/wifi/wlan.cc diff --git a/repos/dde_linux/recipes/raw/wifi_firmware/content.mk b/repos/dde_linux/recipes/raw/wifi_firmware/content.mk new file mode 100644 index 0000000000..7855d1f15d --- /dev/null +++ b/repos/dde_linux/recipes/raw/wifi_firmware/content.mk @@ -0,0 +1,17 @@ +PORT_DIR := $(call port_dir,$(REP_DIR)/ports/linux-firmware) + +content: ucode_files LICENSE.wifi_drv + + +.PHONY: ucode_files +ucode_files: + cp $(PORT_DIR)/firmware/*.ucode . + cp $(PORT_DIR)/firmware/regulatory.db . + cp $(PORT_DIR)/firmware/regulatory.db.p7s . + +LICENSE.wifi_drv: + for i in $(PORT_DIR)/firmware/LICEN*E.*; do \ + echo "$${i##*/}:" >> $@; \ + cat $$i >> $@; \ + echo >> $@; \ + done diff --git a/repos/dde_linux/recipes/raw/wifi_firmware/hash b/repos/dde_linux/recipes/raw/wifi_firmware/hash new file mode 100644 index 0000000000..c1f691ebb5 --- /dev/null +++ b/repos/dde_linux/recipes/raw/wifi_firmware/hash @@ -0,0 +1 @@ +2019-11-25 ff24f3bafaeeb47c053670264b5096dbc4b9a36d diff --git a/repos/pc/lib/mk/spec/x86_32/wifi.mk b/repos/pc/lib/mk/spec/x86_32/wifi.mk new file mode 100644 index 0000000000..6160802395 --- /dev/null +++ b/repos/pc/lib/mk/spec/x86_32/wifi.mk @@ -0,0 +1,5 @@ +include $(REP_DIR)/lib/mk/wifi.inc + +REQUIRES += 32bit + +SRC_C += lx_emul/spec/x86_32/atomic64_32.c diff --git a/repos/pc/lib/mk/spec/x86_64/wifi.mk b/repos/pc/lib/mk/spec/x86_64/wifi.mk new file mode 100644 index 0000000000..afe2b9b5dd --- /dev/null +++ b/repos/pc/lib/mk/spec/x86_64/wifi.mk @@ -0,0 +1,3 @@ +include $(REP_DIR)/lib/mk/wifi.inc + +REQUIRES += 64bit diff --git a/repos/pc/lib/mk/vfs_wifi.mk b/repos/pc/lib/mk/vfs_wifi.mk new file mode 100644 index 0000000000..f2306c1676 --- /dev/null +++ b/repos/pc/lib/mk/vfs_wifi.mk @@ -0,0 +1,11 @@ +SRC_CC = vfs.cc + +DDE_LINUX_DIR := $(subst /src/include/lx_kit,,$(call select_from_repositories,src/include/lx_kit)) + +INC_DIR += $(DDE_LINUX_DIR)/src/include + +LIBS := wifi + +vpath %.cc $(REP_DIR)/src/lib/vfs/wifi + +SHARED_LIB := yes diff --git a/repos/pc/lib/mk/wifi.inc b/repos/pc/lib/mk/wifi.inc new file mode 100644 index 0000000000..82c306a0b4 --- /dev/null +++ b/repos/pc/lib/mk/wifi.inc @@ -0,0 +1,48 @@ +REQUIRES := x86 + +TARGET_LIB_DIR := $(REP_DIR)/src/lib/wifi + +SHARED_LIB := yes + +LD_OPT += --version-script=$(TARGET_LIB_DIR)/symbol.map + +LIBS += base pc_linux_generated pc_lx_emul +INC_DIR := $(TARGET_LIB_DIR) +SRC_CC += wlan.cc +SRC_CC += misc.cc +SRC_CC += time.cc +SRC_CC += firmware.cc +SRC_CC += socket_call.cc +SRC_CC += random.cc + +SRC_C += dummies.c +SRC_C += lx_emul.c +SRC_C += uplink.c + +CC_OPT_lx_socket_call += -DKBUILD_MODNAME='"lx_socket_call"' +SRC_C += lx_socket_call.c + +SRC_C += $(notdir $(wildcard $(TARGET_LIB_DIR)/generated_dummies.c)) +SRC_C += pc/lx_emul/common_dummies.c +SRC_C += lx_emul/spec/x86/pci.c + +CC_C_OPT += -I$(LX_SRC_DIR)/drivers/net/wireless/intel/iwlwifi +CC_C_OPT += -I$(LX_SRC_DIR)/include/linux + +CC_C_OPT += -Wno-address-of-packed-member + +#CC_OPT += -DCONFIG_IWLWIFI_DEBUG + +vpath %.c $(TARGET_LIB_DIR) +vpath %.cc $(TARGET_LIB_DIR) +vpath pc/lx_emul/common_dummies.c $(REP_DIR)/src/lib + +CUSTOM_TARGET_DEPS += $(TARGET_LIB_DIR)/symbol.map + +# +# Genode C-API backends +# + +SRC_CC += genode_c_api/uplink.cc + +vpath genode_c_api/uplink.cc $(subst /genode_c_api,,$(call select_from_repositories,src/lib/genode_c_api)) diff --git a/repos/pc/lib/mk/wifi_firmware.mk b/repos/pc/lib/mk/wifi_firmware.mk new file mode 100644 index 0000000000..a00a214329 --- /dev/null +++ b/repos/pc/lib/mk/wifi_firmware.mk @@ -0,0 +1,24 @@ +# +# Pseudo library to copy wireless LAN firmware to build directory +# + +FW_CONTRIB_DIR := $(call select_from_ports,linux-firmware) + +IMAGES := $(notdir $(wildcard $(FW_CONTRIB_DIR)/firmware/*.ucode)) +IMAGES += $(notdir $(wildcard $(FW_CONTRIB_DIR)/firmware/*.db)) +IMAGES += $(notdir $(wildcard $(FW_CONTRIB_DIR)/firmware/*.p7s)) +BIN_DIR := $(BUILD_BASE_DIR)/bin +FW_DIR := $(FW_CONTRIB_DIR)/firmware + +CUSTOM_TARGET_DEPS += $(addprefix $(BIN_DIR)/,$(IMAGES)) + +$(BIN_DIR)/%.ucode: $(FW_DIR)/%.ucode + $(VERBOSE)cp $^ $@ + +$(BIN_DIR)/%.db: $(FW_DIR)/%.db + $(VERBOSE)cp $^ $@ + +$(BIN_DIR)/%.p7s: $(FW_DIR)/%.p7s + $(VERBOSE)cp $^ $@ + +CC_CXX_WARN_STRICT = diff --git a/repos/pc/recipes/pkg/wifi/README b/repos/pc/recipes/pkg/wifi/README new file mode 100644 index 0000000000..574933d1f6 --- /dev/null +++ b/repos/pc/recipes/pkg/wifi/README @@ -0,0 +1,2 @@ + + Package for bundling pc_wifi_drv and wifi_firmware diff --git a/repos/pc/recipes/pkg/wifi/archives b/repos/pc/recipes/pkg/wifi/archives new file mode 100644 index 0000000000..406537fad5 --- /dev/null +++ b/repos/pc/recipes/pkg/wifi/archives @@ -0,0 +1,6 @@ +_/src/pc_wifi_drv +_/src/openssl +_/src/vfs +_/src/vfs_jitterentropy +_/src/libc +_/raw/wifi_firmware diff --git a/repos/pc/recipes/pkg/wifi/hash b/repos/pc/recipes/pkg/wifi/hash new file mode 100644 index 0000000000..4b20d36a86 --- /dev/null +++ b/repos/pc/recipes/pkg/wifi/hash @@ -0,0 +1 @@ +2022-03-28-c 2f0c23734634d4c90d6c4ed2d08a5873bd3daed1 diff --git a/repos/pc/recipes/pkg/wifi/runtime b/repos/pc/recipes/pkg/wifi/runtime new file mode 100644 index 0000000000..cb00960e49 --- /dev/null +++ b/repos/pc/recipes/pkg/wifi/runtime @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/repos/pc/recipes/src/pc_wifi_drv/content.mk b/repos/pc/recipes/src/pc_wifi_drv/content.mk new file mode 100644 index 0000000000..f00b567bf0 --- /dev/null +++ b/repos/pc/recipes/src/pc_wifi_drv/content.mk @@ -0,0 +1,72 @@ +# +# Driver portions +# + +LIB_MK := $(addprefix lib/mk/,wifi_firmware.mk wifi.inc vfs_wifi.mk) \ + $(foreach SPEC,x86_32 x86_64,lib/mk/spec/$(SPEC)/wifi.mk) \ + +MIRROR_FROM_REP_DIR := src/drivers/wifi/pc \ + src/lib/pc/lx_emul \ + $(LIB_MK) \ + $(shell cd $(REP_DIR); find src/drivers/wifi -type f) \ + $(shell cd $(REP_DIR); find src/lib/wifi -type f) \ + $(shell cd $(REP_DIR); find src/lib/vfs/wifi -type f) + +MIRROR_FROM_OS_DIR := src/lib/genode_c_api/uplink.cc + +# +# DDE Linux portions (wpa_supplicant, libnl) +# + +DDE_LINUX_REP_DIR := $(GENODE_DIR)/repos/dde_linux +DDE_LINUX_PORT_DIR := $(call port_dir,$(DDE_LINUX_REP_DIR)/ports/dde_linux) + +DDE_LINUX_LIB_MK := \ + $(addprefix lib/mk/,libnl.inc libnl_include.mk) \ + $(foreach SPEC,x86_32 x86_64,lib/mk/spec/$(SPEC)/libnl.mk) \ + $(addprefix lib/mk/spec/x86/,wpa_driver_nl80211.mk wpa_supplicant.mk) + +MIRROR_FROM_DDE_LINUX_DIR := $(DDE_LINUX_LIB_MK) \ + lib/import/import-libnl_include.mk \ + lib/import/import-libnl.mk \ + include/wifi \ + $(shell cd $(DDE_LINUX_REP_DIR); find src/lib/libnl -type f) \ + $(shell cd $(DDE_LINUX_REP_DIR); find src/lib/wpa_driver_nl80211 -type f) \ + $(shell cd $(DDE_LINUX_REP_DIR); find src/lib/wpa_supplicant -type f) + +MIRROR_FROM_DDE_LINUX_PORT_DIR := $(shell cd $(DDE_LINUX_PORT_DIR); find src/lib/libnl -type f) \ + $(shell cd $(DDE_LINUX_PORT_DIR); find src/app/wpa_supplicant -type f) + +content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_OS_DIR) $(MIRROR_FROM_DDE_LINUX_DIR) \ + $(MIRROR_FROM_DDE_LINUX_PORT_DIR) cleanup-wpa + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +$(MIRROR_FROM_OS_DIR): + mkdir -p $(dir $@) + cp -r $(GENODE_DIR)/repos/os/$@ $@ + +$(MIRROR_FROM_DDE_LINUX_DIR): + mkdir -p $(dir $@) + cp -r $(GENODE_DIR)/repos/dde_linux/$@ $@ + +$(MIRROR_FROM_DDE_LINUX_PORT_DIR): + mkdir -p $(dir $@) + cp -r $(DDE_LINUX_PORT_DIR)/$@ $@ + +cleanup-wpa: $(MIRROR_FROM_DDE_LINUX_PORT_DIR) + @for dir in .git doc eap_example hs20 mac80211_hwsim radius_example \ + hostapd tests wlantest wpadebug wpaspy; do \ + rm -rf src/app/wpa_supplicant/$$dir; done + +content: LICENSE +LICENSE: + ( echo "Linux is subject to GNU General Public License version 2, see:"; \ + echo "https://www.kernel.org/pub/linux/kernel/COPYING"; \ + echo; \ + echo "Libnl is subject to GNU LESSER GENERAL PUBLIC LICENSE Verson 2.1, see:"; \ + echo " src/lib/libnl/COPYING"; \ + echo; \ + echo "Wpa_supplicant is subject to 3-clause BSD license, see:"; \ + echo " src/app/wpa_supplicant/COPYING"; ) > $@ diff --git a/repos/pc/recipes/src/pc_wifi_drv/hash b/repos/pc/recipes/src/pc_wifi_drv/hash new file mode 100644 index 0000000000..7ebc5c77cb --- /dev/null +++ b/repos/pc/recipes/src/pc_wifi_drv/hash @@ -0,0 +1 @@ +2022-03-25-d 6b387b53c6390a75e1fdd55586aac54d3812271c diff --git a/repos/pc/recipes/src/pc_wifi_drv/used_apis b/repos/pc/recipes/src/pc_wifi_drv/used_apis new file mode 100644 index 0000000000..e00fd16fee --- /dev/null +++ b/repos/pc/recipes/src/pc_wifi_drv/used_apis @@ -0,0 +1,12 @@ +base +genode_c_api +libc +openssl +os +pc_linux +nic_session +platform_session +report_session +timer_session +uplink_session +vfs diff --git a/repos/pc/run/wifi.run b/repos/pc/run/wifi.run new file mode 100644 index 0000000000..65bb545e68 --- /dev/null +++ b/repos/pc/run/wifi.run @@ -0,0 +1,283 @@ +# +# Configure wireless lan +# + +proc wifi_ssid { } { + return $::env(GENODE_WIFI_SSID) +} + +proc wifi_psk { } { + return $::env(GENODE_WIFI_PSK) +} + +# +# widi_drv config generator (supporting a network list) +# +# You may script your tests with this function in the dynamic_rom config below. +# The syntax for the networks parameter is +# +# { ssid protection passphrase explicit_scan } +# +# Example dynamic_rom config: +# +# { +# } [wifi_config 30 5 no [list "net1 WPA2 net1_psk no" "net2 WPA2 net2_psk no"]] { +# +# +# } [wifi_config 30 5 no [list "net1 WPA2 net1_psk no" "net2 WPA2 net2_psk yes"]] { +# } + +set wifi_verbose false +set wifi_verbose_state false + +proc wifi_config { connected_scan_interval scan_interval rfkill networks } { + global wifi_verbose + global wifi_verbose_state + + set config "\n" + foreach n $networks { + append config " \n" + } + append config "\n" + + return $config +} + +# +# Restrict platforms +# +assert_spec x86 + +# +# Build +# + +set build_components { + core init timer + drivers/rtc + drivers/wifi/pc + server/report_rom + server/dynamic_rom + server/nic_router + test/lwip/http_srv + lib/vfs/wifi + lib/vfs/jitterentropy + lib/vfs/lwip +} + +source ${genode_dir}/repos/base/run/platform_drv.inc +append_platform_drv_build_components + +build $build_components + +create_boot_directory + +# +# Generate config +# + +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} [wifi_config 30 5 no {}] { + + + +} [wifi_config 30 5 no [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] { + + + +} [wifi_config 30 5 yes [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] { + + + +} [wifi_config 30 5 no [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +append_platform_drv_config + +append config { + +} + +install_config $config + +set firmware_modules { + iwlwifi-1000-5.ucode + iwlwifi-3160-17.ucode + iwlwifi-3168-29.ucode + iwlwifi-5000-5.ucode + iwlwifi-6000-4.ucode + iwlwifi-7260-17.ucode + iwlwifi-7265-17.ucode + iwlwifi-7265D-29.ucode + iwlwifi-8000C-36.ucode + iwlwifi-8265-36.ucode + iwlwifi-9000-pu-b0-jf-b0-34.ucode + iwlwifi-9000-pu-b0-jf-b0-46.ucode + iwlwifi-QuZ-a0-hr-b0-63.ucode + regulatory.db + regulatory.db.p7s +} + +# +# Boot modules +# + +# generic modules +set boot_modules { + core ld.lib.so init timer rtc_drv report_rom dynamic_rom + vfs_jitterentropy.lib.so + libc.lib.so vfs.lib.so libcrypto.lib.so libssl.lib.so + wpa_driver_nl80211.lib.so wpa_supplicant.lib.so + pc_wifi_drv wifi.lib.so vfs_wifi.lib.so + nic_router + + test-lwip_httpsrv + vfs_lwip.lib.so +} + +append boot_modules $firmware_modules + +append_platform_drv_boot_modules + +build_boot_image $boot_modules + +run_genode_until forever + +# vi: set ft=tcl : diff --git a/repos/pc/src/drivers/wifi/pc/README b/repos/pc/src/drivers/wifi/pc/README new file mode 100644 index 0000000000..982ed0c8f6 --- /dev/null +++ b/repos/pc/src/drivers/wifi/pc/README @@ -0,0 +1,108 @@ +The pc_wifi_drv component is a port of the Linux mac802.11 stack, including +the iwlwifi driver as well as libnl and wpa_supplicant, to Genode. + +To start the component the following configuration snippet can be used: + +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! + +To temporarily prevent any radio activity, the 'rfkill' attribute +can be set to 'true'. + +If the network is protected by, e.g., WPA/WPA2, the protection type, either +'WPA' or 'WPA2' as well as the the passphrase have to be specified. +The 'bssid' attribute can be used to select a specifc accesspoint within a +network. Of all attributes only the 'ssid' attribute is mandatory, all others +are optional and should only be used when needed. + +The configuration may contain more than one network. In This case the driver +will try to select the best one it gets a response from. To prevent it +from automatically joining the network the 'auto_connect' attribute must be +set to 'false'; the default value is 'true'. If the 'explicit_scan' attribute +is set, the driver will pro-actively scan for a hidden network with the given +SSID: + +! +! +! +! + +By default, the driver scans for available networks only when not +connected. This can be changed with the 'connected_scan_interval' +attribute, which specifies the interval for connected scans in +seconds and directly influences any roaming decision, i.e., select +a better fit accesspoint for the configured network. + +Also, the driver can be switched to verbose logging during runtime +by setting the 'verbose' or 'verbose_state' attribute to 'true'. + +The wifi_drv creates two distinct reports to communicate its state and +information about the wireless infrastructure to other components. The +first one is a list of all available accesspoints. The following examplary +report shows its general structure: + +! +! +! +! +! + +Each accesspoint node has attributes that contain the SSID and the BSSID +of the accesspoint as well as the link quality (signal strength). These +attributes are mandatory. If the network is protected, the node will also +have an attribute describing the type of protection in addition. + +The second report provides information about the state of the connection +to the currently connected accesspoint: + +! +! +! + +Valid state values are 'connected', 'disconnected', 'connecting'. Depending +on the state, there are additional attributes that can be checked. In case +of an authentication error, e.g. the passphrase is wrong, the 'auth_failure' +attribute will be set to 'true'. The 'rfkilled' attribute is set to 'true' +if a disconnect was triggered by disabling the radio activity via setting +the 'rfkill' attribute. + +By subscribing to both reports and providing the required 'wifi_config' ROM +module, a component is able control the wireless driver. + +Currently only WPA/WPA2 protection using a passphrase is supported and the the +SSID is copied verbatim. At the moment, there is no way to express or escape +non alphanumeric characters. + +On certain cards, e.g. Intel Wireless 6200 ABG, it may be necessary to disable +the 11n mode. This can be achieved by setting the 'use_11n' attribute in +the 'wifi_config' node to 'no'. + +The driver optionally reports the following information under the +label "devices" if requested in the config as depicted. + +! + +! diff --git a/repos/pc/src/drivers/wifi/pc/frontend.h b/repos/pc/src/drivers/wifi/pc/frontend.h new file mode 100644 index 0000000000..63ad6b8a2d --- /dev/null +++ b/repos/pc/src/drivers/wifi/pc/frontend.h @@ -0,0 +1,1658 @@ + /* + * \author Josef Soentgen + * \date 2018-07-31 + * + * This wifi driver front end uses the CTRL interface of the wpa_supplicant via + * a Genode specific backend, which merely wraps a shared memory buffer, to + * manage the supplicant. + * + * Depending on the 'wifi_config' ROM content it will instruct the supplicant + * to enable, disable and connect to wireless networks. Commands and their + * corresponding execute result are handled by the '_cmd_handler' dispatcher. + * This handler drives the front end's state-machine. Any different type of + * action can only be initiated from the 'IDLE' state. Unsolicited events, e.g. + * a scan-results-available event, may influence the current state. Config + * updates are deferred in case the current state is not 'IDLE'. + * + * brain-dump + * ========== + * + * config update overview: + * [[block any new update]] > [mark stale] > [rm stale] > [add new] > [update new] > [[unblock update]] + * + * add new network: + * [[new ap]] > [ssid] > bssid? + [bssid] > [psk] > auto? + [enable] > new ap? + [[new ap]] + * + * update network: + * [[update ap] > bssid? + [bssid] > psk? + [psk] > auto? + [enable] > update ap? + [[update ap]] + * + * remove network: + * [[mark stale]] > [remove network] > stale? + [remove network] + */ + +/* + * Copyright (C) 2018-2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _WIFI_FRONTEND_H_ +#define _WIFI_FRONTEND_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* rep includes */ +#include +#include + +/* local includes */ +#include + +/* declare manually as it is a internal hack^Winterface */ +extern void wifi_kick_socketcall(); + + +namespace Wifi { + struct Frontend; +} + + +/* keep ordered! */ +static struct Recv_msg_table { + char const *string; + size_t len; +} recv_table[] = { + { "OK", 2 }, + { "FAIL", 4 }, + { "CTRL-EVENT-SCAN-RESULTS", 23 }, + { "CTRL-EVENT-CONNECTED", 20 }, + { "CTRL-EVENT-DISCONNECTED", 23 }, + { "SME: Trying to authenticate", 27 }, + { "CTRL-EVENT-NETWORK-NOT-FOUND", 28 }, +}; + +enum Rmi { + OK = 0, + FAIL, + SCAN_RESULTS, + CONNECTED, + DISCONNECTED, + SME_AUTH, + NOT_FOUND, +}; + + +static inline bool check_recv_msg(char const *msg, + Recv_msg_table const &entry) { + return Genode::strcmp(entry.string, msg, entry.len) == 0; } + + +static bool cmd_successful(char const *msg) { + return check_recv_msg(msg, recv_table[OK]); } + + +static bool cmd_fail(char const *msg) { + return check_recv_msg(msg, recv_table[FAIL]); } + + +static bool results_available(char const *msg) { + return check_recv_msg(msg, recv_table[SCAN_RESULTS]); } + + +static bool connecting_to_network(char const *msg) { + return check_recv_msg(msg, recv_table[SME_AUTH]); } + + +static bool network_not_found(char const *msg) { + return check_recv_msg(msg, recv_table[NOT_FOUND]); } + + +static bool scan_results(char const *msg) { + return Genode::strcmp("bssid", msg, 5) == 0; } + + +static bool list_network_results(char const *msg) { + return Genode::strcmp("network", msg, 7) == 0; } + + +/* + * Central network data structure + */ +struct Accesspoint : Genode::Interface +{ + using Bssid = Genode::String<17+1>; + using Freq = Genode::String< 4+1>; + using Prot = Genode::String< 7+1>; + using Ssid = Genode::String<32+1>; + using Pass = Genode::String<63+1>; + + /* + * Accesspoint information fields used by the front end + */ + Bssid bssid { }; + Freq freq { }; + Prot prot { }; + Ssid ssid { }; + Pass pass { }; + unsigned signal { 0 }; + + /* + * CTRL interface fields + * + * The 'enabled' field is set to true if ENABLE_NETWORK + * was successfully executed. The network itself might + * get disabled by wpa_supplicant itself in case it cannot + * connect to the network, which will _not_ be reflected + * here. + */ + int id { -1 }; + bool enabled { false }; + + /* + * Internal configuration fields + */ + bool auto_connect { false }; + bool update { false }; + bool stale { false }; + bool explicit_scan { false }; + + /** + * Default constructor + */ + Accesspoint() { } + + /** + * Constructor that initializes information fields + */ + Accesspoint(char const *bssid, char const *freq, + char const *prot, char const *ssid, unsigned signal) + : bssid(bssid), freq(freq), prot(prot), ssid(ssid), signal(signal) + { } + + void invalidate() { ssid = Ssid(); bssid = Bssid(); } + + bool valid() const { return ssid.length() > 1; } + bool bssid_valid() const { return bssid.length() > 1; } + bool wpa() const { return prot != "NONE"; } + bool stored() const { return id != -1; } +}; + + +template +static void for_each_line(char const *msg, FUNC const &func) +{ + char line_buffer[1024]; + size_t cur = 0; + + while (msg[cur] != 0) { + size_t until = Util::next_char(msg, cur, '\n'); + Genode::memcpy(line_buffer, &msg[cur], until); + line_buffer[until] = 0; + cur += until + 1; + + func(line_buffer); + } +} + + +template +static void for_each_result_line(char const *msg, FUNC const &func) +{ + char line_buffer[1024]; + size_t cur = 0; + + /* skip headline */ + size_t until = Util::next_char(msg, cur, '\n'); + cur += until + 1; + + while (msg[cur] != 0) { + until = Util::next_char(msg, cur, '\n'); + Genode::memcpy(line_buffer, &msg[cur], until); + line_buffer[until] = 0; + cur += until + 1; + + char const *s[5] = { }; + + for (size_t c = 0, i = 0; i < 5; i++) { + size_t pos = Util::next_char(line_buffer, c, '\t'); + line_buffer[c+pos] = 0; + s[i] = (char const*)&line_buffer[c]; + c += pos + 1; + } + + bool const is_wpa1 = Util::string_contains((char const*)s[3], "WPA"); + bool const is_wpa2 = Util::string_contains((char const*)s[3], "WPA2"); + + unsigned signal = Util::approximate_quality(s[2]); + + char const *prot = is_wpa1 ? "WPA" : "NONE"; + prot = is_wpa2 ? "WPA2" : prot; + + Accesspoint ap(s[0], s[1], prot, s[4], signal); + + func(ap); + } +} + + +/* + * Wifi driver front end + */ +struct Wifi::Frontend +{ + Frontend(const Frontend&) = delete; + Frontend& operator=(const Frontend&) = delete; + + /* accesspoint */ + + Genode::Heap _ap_allocator; + + using Accesspoint_r = Genode::Registered; + + Genode::Registry _aps { }; + + Accesspoint *_lookup_ap_by_ssid(Accesspoint::Ssid const &ssid) + { + Accesspoint *p = nullptr; + _aps.for_each([&] (Accesspoint &ap) { + if (ap.valid() && ap.ssid == ssid) { p = ≈ } + }); + return p; + } + + Accesspoint *_lookup_ap_by_bssid(Accesspoint::Bssid const &bssid) + { + Accesspoint *p = nullptr; + _aps.for_each([&] (Accesspoint &ap) { + if (ap.valid() && ap.bssid == bssid) { p = ≈ } + }); + return p; + } + + Accesspoint *_alloc_ap() + { + return new (&_ap_allocator) Accesspoint_r(_aps); + } + + void _free_ap(Accesspoint &ap) + { + Genode::destroy(&_ap_allocator, &ap); + } + + template + void _for_each_ap(FUNC const &func) + { + _aps.for_each([&] (Accesspoint &ap) { + func(ap); + }); + } + + unsigned _count_to_be_enabled() + { + unsigned count = 0; + auto enable = [&](Accesspoint const &ap) { + count += ap.auto_connect; + }; + _for_each_ap(enable); + return count; + } + + unsigned _count_enabled() + { + unsigned count = 0; + auto enabled = [&](Accesspoint const &ap) { + count += ap.enabled; + }; + _for_each_ap(enabled); + return count; + } + + unsigned _count_stored() + { + unsigned count = 0; + auto enabled = [&](Accesspoint const &ap) { + count += ap.stored(); + }; + _for_each_ap(enabled); + return count; + } + + /* remaining stuff */ + + Msg_buffer _msg { }; + + Genode::Blockade _notify_blockade { }; + + void _notify_lock_lock() { _notify_blockade.block(); } + void _notify_lock_unlock() { _notify_blockade.wakeup(); } + + bool _rfkilled { false }; + + Genode::Signal_handler _rfkill_handler; + + void _handle_rfkill() + { + _rfkilled = wifi_get_rfkill(); + + /* re-enable scan timer */ + if (!_rfkilled) { + _scan_timer.sigh(_scan_timer_sigh); + _arm_scan_timer(false); + } else { + _scan_timer.sigh(Genode::Signal_context_capability()); + } + + if (_rfkilled && _state != State::IDLE) { + Genode::warning("rfkilled in state ", state_strings(_state)); + } + } + + /* config */ + + Genode::Attached_rom_dataspace _config_rom; + Genode::Signal_handler _config_sigh; + + bool _verbose { false }; + bool _verbose_state { false }; + bool _use_11n { true }; + + bool _deferred_config_update { false }; + bool _single_autoconnect { false }; + + Genode::uint64_t _connected_scan_interval { 30 }; + Genode::uint64_t _scan_interval { 5 }; + + void _config_update(bool signal) + { + _config_rom.update(); + + if (!_config_rom.valid()) { return; } + + Genode::Xml_node config = _config_rom.xml(); + + _verbose = config.attribute_value("verbose", _verbose); + _verbose_state = config.attribute_value("verbose_state", _verbose_state); + + /* only evaluated at start-up */ + _use_11n = config.attribute_value("use_11n", _use_11n); + + Genode::uint64_t connected_scan_interval = + Util::check_time(config.attribute_value("connected_scan_interval", + _connected_scan_interval), + 0, 15*60); + + Genode::uint64_t scan_interval = + Util::check_time(config.attribute_value("scan_interval", + _scan_interval), + 5, 15*60); + + if ( connected_scan_interval > _connected_scan_interval + || scan_interval > _scan_interval) { + _arm_scan_timer(_connected_ap.bssid_valid()); + } + + _connected_scan_interval = connected_scan_interval; + _scan_interval = scan_interval; + + /* + * Always handle rfkill, regardless in which state we are currently in. + * When we come back from rfkill, will most certainly will be IDLE anyway. + */ + if (config.has_attribute("rfkill")) { + bool const blocked = config.attribute_value("rfkill", false); + wifi_set_rfkill(blocked); + + /* + * In case we get blocked set rfkilled immediately to prevent + * any further scanning operation. The actual value will be set + * by the singal handler but is not expected to be any different + * as the rfkill call is not supposed to fail. + */ + if (blocked && !_rfkilled) { + _rfkilled = true; + + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("state", "disconnected"); + xml.attribute("rfkilled", _rfkilled); + }); + }); + + _connected_ap.invalidate(); + } + } + + /* + * Block any further config updates until we have finished applying + * the current one. + */ + if (_state != State::IDLE) { + Genode::warning("deferring config update (", state_strings(_state), ")"); + _deferred_config_update = true; + return; + } + + bool single_autoconnect = false; + + /* update AP list */ + auto parse = [&] ( Genode::Xml_node node) { + + Accesspoint ap; + ap.ssid = node.attribute_value("ssid", Accesspoint::Ssid()); + ap.bssid = node.attribute_value("bssid", Accesspoint::Bssid()); + + size_t const ssid_len = ap.ssid.length() - 1; + if (ssid_len == 0 || ssid_len > 32) { + Genode::warning("ignoring accesspoint with invalid ssid"); + return; + } + + Accesspoint *p = _lookup_ap_by_ssid(ap.ssid); + if (p) { + if (_verbose) { Genode::log("Update: '", p->ssid, "'"); } + /* mark for updating */ + p->update = true; + } else { + p = _alloc_ap(); + if (!p) { + Genode::warning("could not add accesspoint, no slots left"); + return; + } + } + + ap.pass = node.attribute_value("passphrase", Accesspoint::Pass("")); + ap.prot = node.attribute_value("protection", Accesspoint::Prot("NONE")); + ap.auto_connect = node.attribute_value("auto_connect", true); + ap.explicit_scan = node.attribute_value("explicit_scan", false); + + if (ap.wpa()) { + size_t const psk_len = ap.pass.length() - 1; + if (psk_len < 8 || psk_len > 63) { + Genode::warning("ignoring accesspoint '", ap.ssid, + "' with invalid pass"); + return; + } + } + + + /* check if updating is really necessary */ + if (p->update) { + p->update = ((ap.bssid.length() > 1 && ap.bssid != p->bssid) + || ap.pass != p->pass + || ap.prot != p->prot + || ap.auto_connect != p->auto_connect); + } + + /* TODO add better way to check validity */ + if (ap.bssid.length() == 17 + 1) { p->bssid = ap.bssid; } + + p->ssid = ap.ssid; + p->prot = ap.prot; + p->pass = ap.pass; + p->auto_connect = ap.auto_connect; + p->explicit_scan = ap.explicit_scan; + + single_autoconnect |= (p->update || p->auto_connect) && !_connected_ap.valid(); + }; + config.for_each_sub_node("network", parse); + + /* + * To accomodate a management component that only deals + * with on network, e.g. the sculpt_manager, generate a + * fake connecting event. Either a connected or disconnected + * event will bring us to square one. + */ + if (signal && _count_to_be_enabled() == 1 && single_autoconnect && !_rfkilled) { + + auto lookup = [&] (Accesspoint const &ap) { + if (!ap.auto_connect) { return; } + + if (_verbose) { Genode::log("Single autoconnect event for '", ap.ssid, "'"); } + + try { + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("ssid", ap.ssid); + xml.attribute("state", "connecting"); + }); + }); + + _single_autoconnect = true; + + } catch (...) { } + }; + _for_each_ap(lookup); + } + + /* + * Marking removes stale APs first and triggers adding of + * new ones afterwards. + */ + _mark_stale_aps(config); + } + + void _handle_config_update() { _config_update(true); } + + /* state */ + + Accesspoint *_processed_ap { nullptr }; + Accesspoint _connected_ap { }; + + enum State { + IDLE = 0x00, + SCAN = 0x01, + NETWORK = 0x02, + CONNECT = 0x03, + STATUS = 0x04, + INFO = 0x05, + + INITIATE_SCAN = 0x00|SCAN, + PENDING_RESULTS = 0x10|SCAN, + + ADD_NETWORK = 0x00|NETWORK, + FILL_NETWORK_SSID = 0x10|NETWORK, + FILL_NETWORK_BSSID = 0x20|NETWORK, + FILL_NETWORK_PSK = 0x30|NETWORK, + REMOVE_NETWORK = 0x40|NETWORK, + ENABLE_NETWORK = 0x50|NETWORK, + DISABLE_NETWORK = 0x60|NETWORK, + DISCONNECT_NETWORK = 0x70|NETWORK, + LIST_NETWORKS = 0x80|NETWORK, + + CONNECTING = 0x00|CONNECT, + CONNECTED = 0x10|CONNECT, + DISCONNECTED = 0x20|CONNECT, + }; + + State _state { State::IDLE }; + + char const *state_strings(State state) + { + switch (state) { + case IDLE: return "idle"; + case INITIATE_SCAN: return "initiate scan"; + case PENDING_RESULTS: return "pending results"; + case ADD_NETWORK: return "add network"; + case FILL_NETWORK_SSID: return "fill network ssid"; + case FILL_NETWORK_BSSID: return "fill network bssid"; + case FILL_NETWORK_PSK: return "fill network pass"; + case REMOVE_NETWORK: return "remove network"; + case ENABLE_NETWORK: return "enable network"; + case DISABLE_NETWORK: return "disable network"; + case CONNECTING: return "connecting"; + case CONNECTED: return "connected"; + case DISCONNECTED: return "disconnected"; + case STATUS: return "status"; + case LIST_NETWORKS: return "list networks"; + case INFO: return "info"; + default: return "unknown"; + }; + } + + void _state_transition(State ¤t, State next) + { + if (_verbose_state) { + using namespace Genode; + log("Transition: ", state_strings(current), " -> ", + state_strings(next)); + } + + current = next; + } + + using Cmd_str = Genode::String; + + void _submit_cmd(Cmd_str const &str) + { + Genode::memset(_msg.send, 0, sizeof(_msg.send)); + Genode::memcpy(_msg.send, str.string(), str.length()); + ++_msg.send_id; + + wpa_ctrl_set_fd(); + + /* + * We might have to pull the socketcall task out of poll_all() + * because otherwise we might be late and wpa_supplicant has + * already removed all scan results due to BSS age settings. + */ + wifi_kick_socketcall(); + } + + /* scan */ + + Timer::Connection _scan_timer; + Genode::Signal_handler _scan_timer_sigh; + + void _handle_scan_timer() + { + /* + * If we are blocked or currently trying to join a network + * suspend scanning. + */ + if (_rfkilled || _connecting.length() > 1) { + if (_verbose) { Genode::log("Suspend scan timer"); } + return; + } + + /* scanning was disabled, ignore current request */ + if (!_arm_scan_timer(_connected_ap.bssid_valid())) { + if (_verbose) { Genode::log("Scanning disabled, ignore current scan request"); } + return; + } + + /* skip as we will be scheduled some time soon(tm) anyway */ + if (_state != State::IDLE) { + if (_verbose) { + Genode::log("Not idle, ignore scan request, state: ", + Genode::Hex((unsigned)_state)); + } + return; + } + + /* left one attempt out */ + if (_scan_busy) { + if (_verbose) { Genode::log("Scan already pending, ignore scan request"); } + _scan_busy = false; + return; + } + + enum { SSID_ARG_LEN = 6 + 64, /* " ssid " + "a5a5a5a5..." */ }; + /* send buffer - 'SCAN ' + stuff */ + char ssid_buffer[sizeof(Msg_buffer::send)-16] = { }; + size_t buffer_pos = 0; + + auto valid_ssid = [&] (Accesspoint const &ap) { + + if (buffer_pos + SSID_ARG_LEN >= sizeof(ssid_buffer)) { + return; + } + + if (!ap.explicit_scan) { return; } + + char ssid_hex[64+1] = { }; + char const *ssid = ap.ssid.string(); + + for (size_t i = 0; i < ap.ssid.length() - 1; i++) { + Util::byte2hex((ssid_hex + i * 2), ssid[i]); + } + + Genode::String tmp(" ssid ", (char const*)ssid_hex); + size_t const tmp_len = tmp.length() - 1; + + Genode::memcpy((ssid_buffer + buffer_pos), tmp.string(), tmp_len); + buffer_pos += tmp_len; + }; + _for_each_ap(valid_ssid); + + _state_transition(_state, State::INITIATE_SCAN); + _submit_cmd(Cmd_str("SCAN", (char const*)ssid_buffer)); + } + + bool _arm_scan_timer(bool connected) + { + Genode::uint64_t const sec = connected ? _connected_scan_interval : _scan_interval; + if (!sec) { return false; } + + if (_verbose) { + Genode::log("Arm ", connected ? "connected " : "", + "scan: ", sec, " sec"); + } + + _scan_timer.trigger_once(sec * (1000 * 1000)); + return true; + } + + Genode::Constructible _ap_reporter { }; + + void _generate_scan_results_report(char const *msg) + { + unsigned count_lines = 0; + for_each_line(msg, [&] (char const*) { count_lines++; }); + + if (!count_lines) { + if (_verbose) { Genode::log("Scan results empty"); } + return; + } + + bool connecting_attempt = false; + try { + + _ap_reporter->generate([&] (Genode::Xml_generator &xml) { + + for_each_result_line(msg, [&] (Accesspoint const &ap) { + + /* ignore potentially empty ssids */ + if (ap.ssid == "") { return; } + + xml.node("accesspoint", [&]() { + xml.attribute("ssid", ap.ssid); + xml.attribute("bssid", ap.bssid); + xml.attribute("freq", ap.freq); + xml.attribute("quality", ap.signal); + if (ap.wpa()) { xml.attribute("protection", ap.prot); } + }); + + auto check_existence = [&] (Accesspoint &lap) { + connecting_attempt |= (lap.ssid == ap.ssid) && ap.auto_connect; + }; + _for_each_ap(check_existence); + }); + }); + + } catch (...) { /* silently omit report */ } + + try { + if (!_connected_ap.bssid_valid() && connecting_attempt) { + + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("state", "connecting"); + }); + }); + } + } catch (...) { /* silently omit state */ } + } + + /* network commands */ + + void _mark_stale_aps(Genode::Xml_node const &config) + { + auto mark_stale = [&] (Accesspoint &ap) { + ap.stale = true; + + config.for_each_sub_node("network", [&] ( Genode::Xml_node node) { + Accesspoint::Ssid ssid = node.attribute_value("ssid", Accesspoint::Ssid("")); + + if (ap.ssid == ssid) { ap.stale = false; } + }); + }; + _for_each_ap(mark_stale); + + _remove_stale_aps(); + } + + void _remove_stale_aps() + { + if (_state != State::IDLE) { + Genode::warning("cannot remove stale APs in non-idle state " + "(", state_strings(_state), ")"); + return; + } + + if (_processed_ap) { return; } + + _aps.for_each([&] (Accesspoint &ap) { + if (!_processed_ap && ap.valid() && ap.stale) { + _processed_ap = ≈ + } + }); + + if (!_processed_ap) { + /* TODO move State transition somewhere more sane */ + _state_transition(_state, State::IDLE); + _add_new_aps(); + return; + } + + if (_verbose) { + Genode::log("Remove network: '", _processed_ap->ssid, "'"); + } + + _state_transition(_state, State::REMOVE_NETWORK); + _submit_cmd(Cmd_str("REMOVE_NETWORK ", _processed_ap->id)); + } + + void _update_aps() + { + if (_state != State::IDLE) { + Genode::warning("cannot enable network in non-idle state"); + return; + } + + if (_processed_ap) { return; } + + _aps.for_each([&] (Accesspoint &ap) { + if (!_processed_ap && ap.stored() && ap.update) { + _processed_ap = ≈ + } + }); + + if (!_processed_ap) { return; } + + if (_verbose) { + Genode::log("Update network: '", _processed_ap->ssid, "'"); + } + + /* re-use state to change PSK */ + _state_transition(_state, State::FILL_NETWORK_PSK); + _network_set_psk(); + } + + + void _add_new_aps() + { + if (_state != State::IDLE) { + Genode::warning("cannot enable network in non-idle state"); + return; + } + + if (_processed_ap) { return; } + + _aps.for_each([&] (Accesspoint &ap) { + if (!_processed_ap && ap.valid() && !ap.stored()) { + _processed_ap = ≈ + } + }); + + if (!_processed_ap) { + /* XXX move State transition somewhere more sane */ + _state_transition(_state, State::IDLE); + _update_aps(); + return; + } + + if (_verbose) { + Genode::log("Add network: '", _processed_ap->ssid, "'"); + } + + _state_transition(_state, State::ADD_NETWORK); + _submit_cmd(Cmd_str("ADD_NETWORK")); + } + + void _network_enable() + { + if (_state != State::IDLE) { + Genode::warning("cannot enable network in non-idle state"); + return; + } + + if (_processed_ap) { return; } + + _aps.for_each([&] (Accesspoint &ap) { + if ( !_processed_ap && ap.valid() + && !ap.enabled && ap.auto_connect) { + _processed_ap = ≈ + } + }); + + if (!_processed_ap) { + + return; + } + + if (_verbose) { + Genode::log("Enable network: '", _processed_ap->ssid, "'"); + } + + _state_transition(_state, State::ENABLE_NETWORK); + _submit_cmd(Cmd_str("ENABLE_NETWORK ", _processed_ap->id)); + } + + void _network_disable() + { + if (_state != State::IDLE) { + Genode::warning("cannot enable network in non-idle state"); + return; + } + + if (_processed_ap) { return; } + + _aps.for_each([&] (Accesspoint &ap) { + if ( !_processed_ap && ap.valid() + && ap.enabled && ap.auto_connect) { + _processed_ap = ≈ + } + }); + + if (!_processed_ap) { + /* XXX move State transition somewhere more sane */ + _state_transition(_state, State::IDLE); + _add_new_aps(); + return; + } + + if (_verbose) { + Genode::log("Disable network: '", _processed_ap->ssid, "'"); + } + + _state_transition(_state, State::DISABLE_NETWORK); + _submit_cmd(Cmd_str("DISABLE_NETWORK ", _processed_ap->id)); + } + + void _network_disconnect() + { + _state_transition(_state, State::DISCONNECT_NETWORK); + _submit_cmd(Cmd_str("DISCONNECT")); + } + + void _network_set_ssid(char const *msg) + { + long id = -1; + Genode::ascii_to(msg, id); + + _processed_ap->id = static_cast(id); + _submit_cmd(Cmd_str("SET_NETWORK ", _processed_ap->id, + " ssid \"", _processed_ap->ssid, "\"")); + } + + void _network_set_bssid() + { + bool const valid = _processed_ap->bssid.length() == 17 + 1; + char const *bssid = valid ? _processed_ap->bssid.string() : ""; + + _submit_cmd(Cmd_str("SET_NETWORK ", _processed_ap->id, + " bssid ", bssid)); + } + + void _network_set_psk() + { + if (_processed_ap->wpa()) { + _submit_cmd(Cmd_str("SET_NETWORK ", _processed_ap->id, + " psk \"", _processed_ap->pass, "\"")); + } else { + _submit_cmd(Cmd_str("SET_NETWORK ", _processed_ap->id, + " key_mgmt NONE")); + } + } + + /* result handling */ + + bool _scan_busy { false }; + + void _handle_scan_results(State state, char const *msg) + { + switch (state) { + case State::INITIATE_SCAN: + if (!cmd_successful(msg)) { + _scan_busy = Genode::strcmp(msg, "FAIL-BUSY"); + if (!_scan_busy) { + Genode::warning("could not initiate scan: ", msg); + } + } + _state_transition(_state, State::IDLE); + break; + case State::PENDING_RESULTS: + if (scan_results(msg)) { + _state_transition(_state, State::IDLE); + _generate_scan_results_report(msg); + } + break; + default: + Genode::warning("unknown SCAN state: ", msg); + break; + } + } + + void _handle_network_results(State state, char const *msg) + { + bool successfully = false; + + switch (state) { + case State::ADD_NETWORK: + if (cmd_fail(msg)) { + Genode::error("could not add network: ", msg); + _state_transition(_state, State::IDLE); + } else { + _state_transition(_state, State::FILL_NETWORK_SSID); + _network_set_ssid(msg); + + successfully = true; + } + break; + case State::REMOVE_NETWORK: + _state_transition(_state, State::IDLE); + + if (cmd_fail(msg)) { + Genode::error("could not remove network: ", msg); + } else { + _free_ap(*_processed_ap); + + /* trigger the next round */ + _processed_ap = nullptr; + _remove_stale_aps(); + + successfully = true; + } + break; + case State::FILL_NETWORK_SSID: + _state_transition(_state, State::IDLE); + + if (!cmd_successful(msg)) { + Genode::error("could not set ssid for network: ", msg); + _state_transition(_state, State::IDLE); + } else { + _state_transition(_state, State::FILL_NETWORK_BSSID); + _network_set_bssid(); + + successfully = true; + } + break; + case State::FILL_NETWORK_BSSID: + _state_transition(_state, State::IDLE); + + if (!cmd_successful(msg)) { + Genode::error("could not set bssid for network: ", msg); + _state_transition(_state, State::IDLE); + } else { + + _state_transition(_state, State::FILL_NETWORK_PSK); + _network_set_psk(); + + successfully = true; + } + break; + case State::FILL_NETWORK_PSK: + _state_transition(_state, State::IDLE); + + if (!cmd_successful(msg)) { + Genode::error("could not set passphrase for network: ", msg); + } else { + + /* + * Disable network to trick wpa_supplicant into reloading + * the settings. + */ + if (_processed_ap->update) { + _processed_ap->enabled = false; + + _state_transition(_state, State::DISABLE_NETWORK); + _submit_cmd(Cmd_str("DISABLE_NETWORK ", _processed_ap->id)); + } else + + if (_processed_ap->auto_connect) { + + _state_transition(_state, State::ENABLE_NETWORK); + _submit_cmd(Cmd_str("ENABLE_NETWORK ", _processed_ap->id)); + } else { + /* trigger the next round */ + _processed_ap = nullptr; + _add_new_aps(); + } + + successfully = true; + } + break; + case State::ENABLE_NETWORK: + _state_transition(_state, State::IDLE); + + if (!cmd_successful(msg)) { + Genode::error("could not enable network: ", msg); + } else { + _processed_ap->enabled = true; + + /* trigger the next round */ + _processed_ap = nullptr; + _add_new_aps(); + + successfully = true; + } + break; + case State::DISABLE_NETWORK: + _state_transition(_state, State::IDLE); + + if (!cmd_successful(msg)) { + Genode::error("could not disable network: ", msg); + } else { + + /* + * Updated settings are applied, enable the network + * anew an try again. + */ + if (_processed_ap->update) { + _processed_ap->update = false; + + if (_processed_ap->auto_connect) { + _state_transition(_state, State::ENABLE_NETWORK); + _submit_cmd(Cmd_str("ENABLE_NETWORK ", _processed_ap->id)); + } + } else { + + _processed_ap->enabled = false; + + /* trigger the next round */ + _processed_ap = nullptr; + _network_disable(); + } + + successfully = true; + } + break; + case State::DISCONNECT_NETWORK: + _state_transition(_state, State::IDLE); + + if (!cmd_successful(msg)) { + Genode::error("could not disconnect from network: ", msg); + } else { + _network_disable(); + successfully = true; + } + break; + case State::LIST_NETWORKS: + _state_transition(_state, State::IDLE); + + if (list_network_results(msg)) { + Genode::error("List networks:\n", msg); + } + break; + default: + Genode::warning("unknown network state: ", msg); + break; + } + + /* + * If some step failed we have to generate a fake + * disconnect event. + */ + if (_single_autoconnect && !successfully) { + try { + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("state", "disconnected"); + xml.attribute("rfkilled", _rfkilled); + xml.attribute("config_error", true); + }); + }); + + _single_autoconnect = false; + } catch (...) { } + } + } + + void _handle_status_result(State &state, char const *msg) + { + _state_transition(state, State::IDLE); + + /* + * Querying the status might have failed but we already sent + * out a rudimentary report, just stop here. + */ + if (0 == msg[0]) { return; } + + Accesspoint ap { }; + + auto fill_ap = [&] (char const *line) { + if (Genode::strcmp(line, "ssid=", 5) == 0) { + ap.ssid = Accesspoint::Ssid(line+5); + } else + + if (Genode::strcmp(line, "bssid=", 6) == 0) { + ap.bssid = Accesspoint::Bssid(line+6); + } else + + if (Genode::strcmp(line, "freq=", 5) == 0) { + ap.freq = Accesspoint::Freq(line+5); + } + }; + for_each_line(msg, fill_ap); + + if (!ap.ssid.valid()) { + Genode::error("Cannot query SSID :-("); + return; + } + + Accesspoint *p = _lookup_ap_by_ssid(ap.ssid); + if (p) { + p->bssid = ap.bssid; + p->freq = ap.freq; + } + + _connected_ap.ssid = ap.ssid; + + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("ssid", ap.ssid); + xml.attribute("bssid", ap.bssid); + xml.attribute("freq", ap.freq); + xml.attribute("state", "connected"); + }); + }); + } + + void _handle_info_result(State &state, char const *msg) + { + _state_transition(state, State::IDLE); + + if (!_connected_event && !_disconnected_event) { return; } + + /* + * It might happen that the supplicant already flushed + * its internal BSS information and cannot help us out. + * Since we already sent out a rudimentary report, just + * stop here. + */ + if (0 == msg[0]) { return; } + + Accesspoint ap { }; + + auto fill_ap = [&] (char const *line) { + if (Genode::strcmp(line, "ssid=", 5) == 0) { + ap.ssid = Accesspoint::Ssid(line+5); + } else + + if (Genode::strcmp(line, "bssid=", 6) == 0) { + ap.bssid = Accesspoint::Bssid(line+6); + } else + + if (Genode::strcmp(line, "freq=", 5) == 0) { + ap.freq = Accesspoint::Freq(line+5); + } + }; + for_each_line(msg, fill_ap); + + /* + * When the config is changed while we are still connecting and + * for some reasons the accesspoint does not get disabled + * a connected event could arrive and we will get a nullptr... + */ + Accesspoint *p = _lookup_ap_by_ssid(ap.ssid); + + /* + * ... but we still generate a report and let the management + * component deal with it. + */ + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("ssid", ap.ssid); + xml.attribute("bssid", ap.bssid); + xml.attribute("freq", ap.freq); + xml.attribute("state", _connected_event ? "connected" + : "disconnected"); + if (!_connected_event) { + xml.attribute("rfkilled", _rfkilled); + xml.attribute("auth_failure", _disconnected_fail); + } + }); + }); + + if (_disconnected_fail) { + /* + * Being able to remove a failed network from the internal + * state of the supplicant relies on a sucessful BSS request. + * In case that failes the supplicant will try to join the + * network again and again... + */ + if (!p || _processed_ap) { + Genode::error("cannot disabled failed network"); + } else { + _processed_ap = p; + _state_transition(state, State::DISABLE_NETWORK); + _submit_cmd(Cmd_str("DISABLE_NETWORK ", p->id)); + } + } else + + if (_connected_event) { + /* + * In case the BSS cmd did not return a valid SSID, which + * was observed only with hidden networks so far, check the + * current status. + */ + if (!p) { + _state_transition(state, State::STATUS); + _submit_cmd(Cmd_str("STATUS")); + + } else { + p->bssid = ap.bssid; + p->freq = ap.freq; + } + + _connected_ap = ap; + } + } + + /* connection state */ + + Genode::Constructible _state_reporter { }; + + Accesspoint::Bssid _connecting { }; + + Accesspoint::Bssid const _extract_bssid(char const *msg, State state) + { + char bssid[32] = { }; + /* by the power of wc -c, I have the start pos... */ + enum { BSSID_CONNECT = 37, BSSID_DISCONNECT = 30, BSSID_CONNECTING = 33, }; + + bool const connected = state == State::CONNECTED; + bool const connecting = state == State::CONNECTING; + + size_t const len = 17; + size_t const start = connected ? BSSID_CONNECT + : connecting ? BSSID_CONNECTING + : BSSID_DISCONNECT; + Genode::memcpy(bssid, msg + start, len); + return Accesspoint::Bssid((char const*)bssid); + } + + bool _auth_failure(char const *msg) + { + enum { REASON_OFFSET = 55, }; + unsigned reason = 0; + Genode::ascii_to((msg + REASON_OFFSET), reason); + switch (reason) { + case 2: /* prev auth no longer valid */ + case 15: /* 4-way handshake timeout/failed */ + return true; + default: + return false; + } + } + + /* events */ + + bool _connected_event { false }; + bool _disconnected_event { false }; + bool _disconnected_fail { false }; + + enum { MAX_ATTEMPTS = 3, }; + unsigned _scan_attempts { 0 }; + + Accesspoint::Bssid _pending_bssid { }; + + void _handle_connection_events(char const *msg) + { + bool const connected = check_recv_msg(msg, recv_table[Rmi::CONNECTED]); + bool const disconnected = check_recv_msg(msg, recv_table[Rmi::DISCONNECTED]); + bool const auth_failed = disconnected && _auth_failure(msg); + + State state = connected ? State::CONNECTED : State::DISCONNECTED; + Accesspoint::Bssid const &bssid = _extract_bssid(msg, state); + + /* + * Always reset the "global" connection state first + */ + _connected_ap.invalidate(); + if (connected) { _connected_ap.bssid = bssid; } + if (connected || disconnected) { _connecting = Accesspoint::Bssid(); } + + /* + * Save local connection state here for later re-use when + * the BSS information are handled. + */ + _connected_event = connected; + _disconnected_event = disconnected; + _disconnected_fail = auth_failed; + + if (!_rfkilled) { + + /* + * As we only received the BSSID, try to gather more information + * so we may generate a more thorough follow-up state report. + */ + if (_state != State::IDLE) { + _pending_bssid = bssid; + } else { + _state_transition(_state, State::INFO); + _submit_cmd(Cmd_str("BSS ", bssid)); + } + + _arm_scan_timer(connected); + } + + /* + * Generate the first rudimentary report whose missing information + * are (potentially) filled in later (see above). + */ + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("bssid", bssid); + xml.attribute("state", connected ? "connected" + : "disconnected"); + if (disconnected) { + xml.attribute("rfkilled", _rfkilled); + if (auth_failed) { + xml.attribute("auth_failure", auth_failed); + } + } + }); + }); + + /* reset */ + _single_autoconnect = false; + } + + Genode::Signal_handler _events_handler; + + unsigned _last_event_id { 0 }; + + void _handle_events() + { + char const *msg = reinterpret_cast(_msg.event); + unsigned const event_id = _msg.event_id; + + /* return early */ + if (_last_event_id == event_id) { + _notify_lock_unlock(); + return; + } + + if (results_available(msg)) { + + /* + * We might have to pull the socketcall task out of poll_all() + * because otherwise we might be late and wpa_supplicant has + * already removed all scan results due to BSS age settings. + */ + wifi_kick_socketcall(); + + if (_state == State::IDLE) { + _state_transition(_state, State::PENDING_RESULTS); + _submit_cmd(Cmd_str("SCAN_RESULTS")); + } + } else + + if (connecting_to_network(msg)) { + if (!_single_autoconnect) { + Accesspoint::Bssid const &bssid = _extract_bssid(msg, State::CONNECTING); + _connecting = bssid; + + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("bssid", bssid); + xml.attribute("state", "connecting"); + }); + }); + } + } else + + if (network_not_found(msg)) { + + /* always try to update the accesspoint list */ + if (_state == State::IDLE) { + _state_transition(_state, State::PENDING_RESULTS); + _submit_cmd(Cmd_str("SCAN_RESULTS")); + } + + if (_single_autoconnect && ++_scan_attempts >= MAX_ATTEMPTS) { + _scan_attempts = 0; + _single_autoconnect = false; + + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("state", "disconnected"); + xml.attribute("rfkilled", _rfkilled); + xml.attribute("not_found", true); + }); + }); + } + + } else + + { + _handle_connection_events(msg); + } + + _notify_lock_unlock(); + } + + Genode::Signal_handler _cmd_handler; + + unsigned _last_recv_id { 0 }; + + void _handle_cmds() + { + char const *msg = reinterpret_cast(_msg.recv); + unsigned const recv_id = _msg.recv_id; + + + /* return early */ + if (_last_recv_id == recv_id) { + _notify_lock_unlock(); + return; + } + + _last_recv_id = recv_id; + + switch (_state & 0xf) { + case State::SCAN: + _handle_scan_results(_state, msg); + break; + case State::NETWORK: + _handle_network_results(_state, msg); + break; + case State::STATUS: + _handle_status_result(_state, msg); + break; + case State::INFO: + _handle_info_result(_state, msg); + break; + case State::IDLE: + default: + break; + } + _notify_lock_unlock(); + + if (_verbose_state) { + Genode::log("State:", + " connected: ", _connected_ap.bssid_valid(), + " connecting: ", _connecting.length() > 1, + " enabled: ", _count_enabled(), + " stored: ", _count_stored(), + ""); + } + + if (_state == State::IDLE && _deferred_config_update) { + _deferred_config_update = false; + _handle_config_update(); + } + + if (_state == State::IDLE && _pending_bssid.length() > 1) { + _state_transition(_state, State::INFO); + _submit_cmd(Cmd_str("BSS ", _pending_bssid)); + + _pending_bssid = Accesspoint::Bssid(); + } + } + + /** + * Constructor + */ + Frontend(Genode::Env &env) + : + _ap_allocator(env.ram(), env.rm()), + _rfkill_handler(env.ep(), *this, &Wifi::Frontend::_handle_rfkill), + _config_rom(env, "wifi_config"), + _config_sigh(env.ep(), *this, &Wifi::Frontend::_handle_config_update), + _scan_timer(env), + _scan_timer_sigh(env.ep(), *this, &Wifi::Frontend::_handle_scan_timer), + _events_handler(env.ep(), *this, &Wifi::Frontend::_handle_events), + _cmd_handler(env.ep(), *this, &Wifi::Frontend::_handle_cmds) + { + _config_rom.sigh(_config_sigh); + _scan_timer.sigh(_scan_timer_sigh); + + /* set/initialize as unblocked */ + _notify_blockade.wakeup(); + + try { + _ap_reporter.construct(env, "accesspoints", "accesspoints"); + _ap_reporter->generate([&] (Genode::Xml_generator &) { }); + } catch (...) { + Genode::warning("no Report session available, scan results will " + "not be reported"); + } + + try { + _state_reporter.construct(env, "state"); + _state_reporter->enabled(true); + + Genode::Reporter::Xml_generator xml(*_state_reporter, [&] () { + xml.node("accesspoint", [&] () { + xml.attribute("state", "disconnected"); + xml.attribute("rfkilled", _rfkilled); + }); + }); + } catch (...) { + Genode::warning("no Report session available, connectivity will " + "not be reported"); + } + + /* read in list of APs */ + _config_update(false); + + /* kick-off initial scanning */ + _handle_scan_timer(); + } + + /** + * Return if 11n operation is enabled + */ + bool use_11n() const { return _use_11n; } + + /** + * Get RFKILL signal capability + * + * Used by the wifi_drv to notify front end. + */ + Genode::Signal_context_capability rfkill_sigh() + { + return _rfkill_handler; + } + + /** + * Get result signal capability + * + * Used by the wpa_supplicant to notify front end after processing + * a command. + */ + Genode::Signal_context_capability result_sigh() + { + return _cmd_handler; + } + + /** + * Get event signal capability + * + * Used by the wpa_supplicant to notify front whenever a event + * was triggered. + */ + Genode::Signal_context_capability event_sigh() + { + return _events_handler; + } + + /** + * Block until events were handled by the front end + * + * Used by the wpa_supplicant to wait for the front end. + */ + void block_for_processing() { _notify_lock_lock(); } + + /** + * Return shared memory message buffer + * + * Used for communication between front end and wpa_supplicant. + */ + Msg_buffer &msg_buffer() { return _msg; } +}; + +#endif /* _WIFI_FRONTEND_H_ */ diff --git a/repos/pc/src/drivers/wifi/pc/main.cc b/repos/pc/src/drivers/wifi/pc/main.cc new file mode 100644 index 0000000000..dc7a09a581 --- /dev/null +++ b/repos/pc/src/drivers/wifi/pc/main.cc @@ -0,0 +1,147 @@ +/* + * \brief Startup Wifi driver + * \author Josef Soentgen + * \date 2014-03-03 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include + +/* local includes */ +#include +#include +#include + + +using namespace Genode; + + +static Wifi::Frontend *_wifi_frontend = nullptr; + + +/** + * Notify front end about command processing + * + * Called by the CTRL interface after wpa_supplicant has processed + * the command. + */ +void wifi_block_for_processing(void) +{ + if (!_wifi_frontend) { + warning("frontend not available, dropping notification"); + return; + } + + /* + * Next time we block as long as the front end has not finished + * handling our previous request + */ + _wifi_frontend->block_for_processing(); + + /* XXX hack to trick poll() into returning faster */ + wpa_ctrl_set_fd(); +} + + +void wifi_notify_cmd_result(void) +{ + if (!_wifi_frontend) { + warning("frontend not available, dropping notification"); + return; + } + + Signal_transmitter(_wifi_frontend->result_sigh()).submit(); +} + + +/** + * Notify front end about triggered event + * + * Called by the CTRL interface whenever wpa_supplicant has triggered + * a event. + */ +void wifi_notify_event(void) +{ + if (!_wifi_frontend) { + Genode::warning("frontend not available, dropping notification"); + return; + } + + Signal_transmitter(_wifi_frontend->event_sigh()).submit(); +} + + +/* exported by wifi.lib.so */ +extern void wifi_init(Genode::Env&, + Genode::Blockade&, + bool, + Genode::Signal_context_capability); + +struct Main +{ + Env &env; + + Constructible _wpa; + Constructible _frontend; + + Blockade _wpa_startup_blockade { }; + + Main(Genode::Env &env) : env(env) + { + _wpa.construct(env, _wpa_startup_blockade); + + wifi_init(env, _wpa_startup_blockade, false, + Genode::Signal_context_capability()); + } +}; + +static Main *_main; + + +/** + * Return shared-memory message buffer + * + * It is used by the wpa_supplicant CTRL interface. + */ +void *wifi_get_buffer(void) +{ + /* + * XXX creating the front end at this point is merely a hack + * to post-pone its creation + */ + if (_wifi_frontend) + return &_wifi_frontend->msg_buffer(); + + Libc::with_libc([&] () { + + if (_main->_frontend.constructed()) + return; + + _main->_frontend.construct(_main->env); + _wifi_frontend = &*_main->_frontend; + }); + + return &_wifi_frontend->msg_buffer(); +} + + +void Libc::Component::construct(Libc::Env &env) +{ + Libc::with_libc([&] () { + static Main server(env); + _main = &server; + }); +} diff --git a/repos/pc/src/drivers/wifi/pc/target.mk b/repos/pc/src/drivers/wifi/pc/target.mk new file mode 100644 index 0000000000..18c96e2f15 --- /dev/null +++ b/repos/pc/src/drivers/wifi/pc/target.mk @@ -0,0 +1,10 @@ +TARGET := pc_wifi_drv +SRC_CC := main.cc wpa.cc +LIBS := base wifi wifi_firmware +LIBS += libc +LIBS += wpa_supplicant +LIBS += libcrypto libssl wpa_driver_nl80211 + +INC_DIR += $(PRG_DIR) + +CC_CXX_WARN_STRICT := diff --git a/repos/pc/src/drivers/wifi/pc/util.h b/repos/pc/src/drivers/wifi/pc/util.h new file mode 100644 index 0000000000..14833bcf31 --- /dev/null +++ b/repos/pc/src/drivers/wifi/pc/util.h @@ -0,0 +1,90 @@ +/* + * \brief Wifi front end utilities + * \author Josef Soentgen + * \date 2018-07-23 + */ + +/* + * Copyright (C) 2018-2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _WIFI__UTIL_H_ +#define _WIFI__UTIL_H_ + +/* Genode includes */ +#include + +typedef unsigned long size_t; +typedef long long ssize_t; +typedef unsigned char uint8_t; + + +namespace Util { + + using size_t = Genode::size_t; + using uint8_t = Genode::uint8_t; + + size_t next_char(char const *s, size_t start, char const c) + { + size_t v = start; + while (s[v]) { + if (s[v] == c) { break; } + v++; + } + return v - start; + } + + bool string_contains(char const *str, char const *pattern) + { + char const *p = pattern; + while (*str && *p) { + p = *str == *p ? p + 1 : pattern; + str++; + } + return !*p; + } + + void byte2hex(char *dest, uint8_t b) + { + int i = 1; + if (b < 16) { dest[i--] = '0'; } + + for (; b > 0; b /= 16) { + uint8_t const v = b % 16; + uint8_t const c = (v > 9) ? v + 'a' - 10 : v + '0'; + dest[i--] = (char)c; + } + } + + /********************************** + ** Front end specific utilities ** + **********************************/ + + inline unsigned approximate_quality(char const *str) + { + long level = 0; + Genode::ascii_to(str, level); + + /* + * We provide an quality value by transforming the actual + * signal level [-50,-100] (dBm) to [100,0] (%). + */ + if (level <= -100) { return 0; } + else if (level >= -50) { return 100; } + + return 2 * (unsigned)(level + 100); + } + + inline Genode::uint64_t check_time(Genode::uint64_t value, Genode::uint64_t min, Genode::uint64_t max) + { + if (value < min) { return min; } + else if (value > max) { return max; } + return value; + } + +} /* namespace Util */ + +#endif /* _WIFI__UTIL_H_ */ diff --git a/repos/pc/src/drivers/wifi/pc/wpa.cc b/repos/pc/src/drivers/wifi/pc/wpa.cc new file mode 100644 index 0000000000..61c342281d --- /dev/null +++ b/repos/pc/src/drivers/wifi/pc/wpa.cc @@ -0,0 +1,57 @@ +/* + * \brief Wpa_supplicant thread of the wifi driver + * \author Josef Soentgen + * \author Christian Helmuth + * \date 2019-12-18 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include + +/* libc includes */ +#include +#include +#include + +#include "wpa.h" + + +/* entry function */ +extern "C" int wpa_main(void); + + +void * Wpa_thread::_entry_trampoline(void *arg) +{ + Wpa_thread *t = (Wpa_thread *)arg; + t->_entry(); + return nullptr; +} + + +void Wpa_thread::_entry() +{ + /* wait until the wifi driver is up and running */ + _blockade.block(); + _exit = wpa_main(); + Genode::sleep_forever(); +} + + +Wpa_thread::Wpa_thread(Genode::Env &env, Genode::Blockade &blockade) +: _blockade(blockade), _exit(-1) +{ + pthread_t tid = 0; + if (pthread_create(&tid, 0, _entry_trampoline, this) != 0) { + printf("Error: pthread_create() failed\n"); + exit(-1); + } +} diff --git a/repos/pc/src/drivers/wifi/pc/wpa.h b/repos/pc/src/drivers/wifi/pc/wpa.h new file mode 100644 index 0000000000..3a124cc142 --- /dev/null +++ b/repos/pc/src/drivers/wifi/pc/wpa.h @@ -0,0 +1,39 @@ +/* + * \brief Wpa_supplicant thread of the wifi driver + * \author Josef Soentgen + * \date 2014-03-03 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _WIFI__WPA_H_ +#define _WIFI__WPA_H_ + + +namespace Genode { + struct Env; + struct Blockade; +} + +class Wpa_thread +{ + private: + + Genode::Blockade &_blockade; + int _exit; + + static void * _entry_trampoline(void *arg); + + void _entry(); + + public: + + Wpa_thread(Genode::Env &, Genode::Blockade &); +}; + +#endif /* _WIFI__WPA_H_ */ diff --git a/repos/pc/src/lib/vfs/wifi/target.mk b/repos/pc/src/lib/vfs/wifi/target.mk new file mode 100644 index 0000000000..8e08765e45 --- /dev/null +++ b/repos/pc/src/lib/vfs/wifi/target.mk @@ -0,0 +1 @@ +LIBS := vfs_wifi diff --git a/repos/pc/src/lib/vfs/wifi/vfs.cc b/repos/pc/src/lib/vfs/wifi/vfs.cc new file mode 100644 index 0000000000..e26c052f80 --- /dev/null +++ b/repos/pc/src/lib/vfs/wifi/vfs.cc @@ -0,0 +1,87 @@ +/* + * \brief Minimal VFS plugin for bringing up WLAN driver + * \author Josef Soentgen + * \date 2022-02-20 + * + * The sole purpose of this VFS plugin is to call 'Lx_kit::initialize_env' + * at the right time before 'env.exec_static_constructors' is executed. + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include + +/* DDE Linux includes */ +#include + + +namespace Vfs_wlan +{ + using namespace Vfs; + using namespace Genode; + + struct File_system; +} + +struct Vfs_wlan::File_system : Single_file_system +{ + + File_system(Vfs::Env &env, Xml_node config) + : + Single_file_system { Vfs::Node_type::CONTINUOUS_FILE, name(), + Vfs::Node_rwx::ro(), config } + { + /* + * Various ports of a DDE Linux based library rely on the + * 'env' being set before any static constructor is executed. + * So we set it here and wait for the user of the library to + * execute the constructors at the proper time. + */ + + Lx_kit::initialize(env.env()); + } + + Open_result open(char const *, unsigned, + Vfs::Vfs_handle **, + Allocator &) override + { + return OPEN_ERR_UNACCESSIBLE; + } + + Stat_result stat(char const *, Stat &) override + { + return STAT_ERR_NO_ENTRY; + } + + static char const *name() { return "wlan"; } + char const *type() override { return name(); } +}; + + +/************************** + ** VFS plugin interface ** + **************************/ + +extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) +{ + struct Factory : Vfs::File_system_factory + { + Vfs::File_system *create(Vfs::Env &vfs_env, + Genode::Xml_node node) override + { + static Vfs::File_system *fs = + new (vfs_env.alloc()) Vfs_wlan::File_system(vfs_env, node); + return fs; + } + }; + + static Factory factory; + return &factory; +} diff --git a/repos/pc/src/lib/wifi/dummies.c b/repos/pc/src/lib/wifi/dummies.c new file mode 100644 index 0000000000..5819fcd0ad --- /dev/null +++ b/repos/pc/src/lib/wifi/dummies.c @@ -0,0 +1,798 @@ +/* + * \brief Dummy definitions of Linux Kernel functions - handled manually + * \author Josef Soentgen + * \date 2022-02-09 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +#include + +int __cpuhp_setup_state(enum cpuhp_state state,const char * name,bool invoke,int (* startup)(unsigned int cpu),int (* teardown)(unsigned int cpu),bool multi_instance) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +void update_vsyscall(struct timekeeper * tk) +{ + lx_emul_trace(__func__); +} + + +#include + +void clocksource_arch_init(struct clocksource * cs) +{ + lx_emul_trace(__func__); +} + + +#include + +void ignore_signals(struct task_struct * t) +{ + lx_emul_trace(__func__); +} + + +#include + +void calc_global_load(void) +{ + lx_emul_trace(__func__); +} + + +#include + +void account_process_tick(struct task_struct * p,int user_tick) +{ + lx_emul_trace(__func__); +} + + +#include + +void rcu_sched_clock_irq(int user) +{ + lx_emul_trace(__func__); +} + + +#include + +int sysfs_create_bin_file(struct kobject * kobj,const struct bin_attribute * attr) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +int sysfs_create_file_ns(struct kobject * kobj,const struct attribute * attr,const void * ns) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +int sysfs_create_groups(struct kobject * kobj,const struct attribute_group ** groups) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +int sysfs_create_group(struct kobject * kobj,const struct attribute_group * grp) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +int sysfs_create_link(struct kobject * kobj,struct kobject * target,const char * name) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +void sysfs_remove_link(struct kobject * kobj,const char * name) +{ + lx_emul_trace(__func__); +} + + +#include + +void sysfs_remove_file_ns(struct kobject * kobj,const struct attribute * attr,const void * ns) +{ + lx_emul_trace(__func__); +} + + +#include + +void sysfs_remove_groups(struct kobject * kobj,const struct attribute_group ** groups) +{ + lx_emul_trace(__func__); +} + + +#include + +void sysfs_remove_dir(struct kobject * kobj) +{ + lx_emul_trace(__func__); +} + + +#include + +void sysfs_remove_bin_file(struct kobject * kobj,const struct bin_attribute * attr) +{ + lx_emul_trace(__func__); +} + + +#include + +void kernfs_get(struct kernfs_node * kn) +{ + lx_emul_trace(__func__); +} + + +#include + +void kernfs_put(struct kernfs_node * kn) +{ + lx_emul_trace(__func__); +} + + +#include + +int kobject_uevent(struct kobject * kobj,enum kobject_action action) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +int add_random_ready_callback(struct random_ready_callback * rdy) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +void add_device_randomness(const void * buf,unsigned int size) +{ + lx_emul_trace(__func__); +} + + +#include + +void add_interrupt_randomness(int irq,int irq_flags) +{ + lx_emul_trace(__func__); +} + + +extern bool irq_wait_for_poll(struct irq_desc * desc); +bool irq_wait_for_poll(struct irq_desc * desc) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void note_interrupt(struct irq_desc * desc,irqreturn_t action_ret) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int __register_chrdev(unsigned int major,unsigned int baseminor,unsigned int count,const char * name,const struct file_operations * fops) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +int register_chrdev_region(dev_t from,unsigned count,const char * name) +{ + lx_emul_trace(__func__); + return 0; +} + + +extern void register_handler_proc(unsigned int irq,struct irqaction * action); +void register_handler_proc(unsigned int irq,struct irqaction * action) +{ + lx_emul_trace(__func__); +} + + +extern void register_irq_proc(unsigned int irq,struct irq_desc * desc); +void register_irq_proc(unsigned int irq,struct irq_desc * desc) +{ + lx_emul_trace(__func__); +} + + +#include + +void cdev_init(struct cdev * cdev,const struct file_operations * fops) +{ + lx_emul_trace(__func__); +} + + +#include + +int cdev_add(struct cdev * p,dev_t dev,unsigned count) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +void cdev_del(struct cdev * p) +{ + lx_emul_trace(__func__); +} + + +#include + +void register_syscore_ops(struct syscore_ops * ops) +{ + lx_emul_trace(__func__); +} + + +#include + +struct proc_dir_entry { int dummy; }; + +struct proc_dir_entry * proc_create_seq_private(const char * name,umode_t mode,struct proc_dir_entry * parent,const struct seq_operations * ops,unsigned int state_size,void * data) +{ + static struct proc_dir_entry ret; + lx_emul_trace(__func__); + return &ret; +} + + +#include + +int software_node_notify(struct device * dev,unsigned long action) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include +#include + +struct user_namespace init_user_ns; + +struct uts_namespace init_uts_ns; + + + +/* + * linux/seq_file.h depends on user_namespace being defined, add + * all dummies pulling in this header below here + */ + + +#include + +void seq_vprintf(struct seq_file * m,const char * f,va_list args) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void unblank_screen(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void pci_allocate_vc_save_buffers(struct pci_dev * dev); +void pci_allocate_vc_save_buffers(struct pci_dev * dev) +{ + lx_emul_trace(__func__); +} + + +extern void pci_vpd_init(struct pci_dev * dev); +void pci_vpd_init(struct pci_dev * dev) +{ + lx_emul_trace(__func__); +} + + +extern int pci_proc_attach_device(struct pci_dev * dev); +int pci_proc_attach_device(struct pci_dev * dev) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +bool parse_option_str(const char * str,const char * option) +{ + lx_emul_trace(__func__); + return false; +} + + +extern bool pat_enabled(void); +bool pat_enabled(void) +{ + // XXX pat_enabled necessary? + lx_emul_trace(__func__); + return false; +} + + +#include + +bool is_vmalloc_addr(const void * x) +{ + lx_emul_trace(__func__); + return false; +} + + +unsigned long init_stack[THREAD_SIZE / sizeof(unsigned long)]; + + +extern int pci_dev_specific_acs_enabled(struct pci_dev * dev,u16 acs_flags); +int pci_dev_specific_acs_enabled(struct pci_dev * dev,u16 acs_flags) +{ + lx_emul_trace(__func__); + return 0; +} + + +extern int pci_dev_specific_disable_acs_redir(struct pci_dev * dev); +int pci_dev_specific_disable_acs_redir(struct pci_dev * dev) +{ + lx_emul_trace(__func__); + return 0; +} + + +extern int pci_dev_specific_enable_acs(struct pci_dev * dev); +int pci_dev_specific_enable_acs(struct pci_dev * dev) +{ + lx_emul_trace(__func__); + return 0; +} + + +extern int pci_dev_specific_reset(struct pci_dev * dev,int probe); +int pci_dev_specific_reset(struct pci_dev * dev,int probe) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +void pci_fixup_device(enum pci_fixup_pass pass,struct pci_dev * dev) +{ + lx_emul_trace(__func__); +} + + +#include + +int pci_disable_link_state(struct pci_dev * pdev,int state) +{ + lx_emul_trace(__func__); + return 0; +} + + +const unsigned long module_cert_size = 0; +const u8 system_certificate_list[] = { }; +const unsigned long system_certificate_list_size = sizeof (system_certificate_list); + +const u8 shipped_regdb_certs[] = { }; +unsigned int shipped_regdb_certs_len = sizeof (shipped_regdb_certs); + + + +/* + * Generate_dummies.c will otherwise pull in + * that clashes with rcutiny.h. + */ +void rcu_barrier(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include +#include /* for DEFINE_STATIC_KEY_FALSE */ + +void bpf_prog_change_xdp(struct bpf_prog *prev_prog, struct bpf_prog *prog) +{ + lx_emul_trace(__func__); +} + +DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key); + + +asmlinkage __wsum csum_partial(const void * buff,int len,__wsum sum) +{ + lx_emul_trace_and_stop(__func__); +} + + +struct static_key_false init_on_alloc; + + +#include + +int proc_alloc_inum(unsigned int * inum) +{ + *inum = 1; /* according to linux/proc_ns.h without CONFIG_PROC_FS */ + return 0; +} + + +#include + +__init int net_sysctl_init(void) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +struct proc_dir_entry * proc_create_net_data(const char * name,umode_t mode,struct proc_dir_entry * parent,const struct seq_operations * ops,unsigned int state_size,void * data) +{ + static struct proc_dir_entry _proc_dir_entry; + lx_emul_trace(__func__); + return &_proc_dir_entry; +} + + +#include + +unsigned int get_next_ino(void) +{ + static unsigned int count = 0; + return ++count; +} + + +#include + +int __init dev_proc_init(void) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +unsigned int full_name_hash(const void * salt,const char * name,unsigned int len) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +static struct key _key; + +struct key * keyring_alloc(const char * description,kuid_t uid,kgid_t gid,const struct cred * cred,key_perm_t perm,unsigned long flags,struct key_restriction * restrict_link,struct key * dest) +{ + lx_emul_trace(__func__); + return &_key; +} + + +#include + +int kobject_uevent_env(struct kobject * kobj,enum kobject_action action,char * envp_ext[]) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +void sched_set_fifo(struct task_struct * p) +{ + lx_emul_trace(__func__); +} + + +#include + +void kernel_param_lock(struct module * mod) +{ + lx_emul_trace(__func__); +} + + +#include + +void kernel_param_unlock(struct module * mod) +{ + lx_emul_trace(__func__); +} + + +unsigned long lpj_fine = 0; + + +#include + +void put_pid(struct pid * pid) +{ + lx_emul_trace(__func__); +} + + +#include + +int sk_filter_trim_cap(struct sock * sk,struct sk_buff * skb,unsigned int cap) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +bool file_ns_capable(const struct file * file,struct user_namespace * ns,int cap) +{ + lx_emul_trace(__func__); + return true; +} + + +#include + +void synchronize_rcu(void) +{ + lx_emul_trace(__func__); +} + + +#include + +void __skb_get_hash(struct sk_buff * skb) +{ + lx_emul_trace(__func__); +} + + +#include + +bool __skb_flow_dissect(const struct net * net,const struct sk_buff * skb,struct flow_dissector * flow_dissector,void * target_container,const void * data,__be16 proto,int nhoff,int hlen,unsigned int flags) +{ + lx_emul_trace(__func__); + return false; +} + + +#include + +pid_t pid_vnr(struct pid * pid) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include + +int verify_pkcs7_signature(const void *data, size_t len, + const void *raw_pkcs7, size_t pkcs7_len, + struct key *trusted_keys, + enum key_being_used_for usage, + int (*view_content)(void *ctx, + const void *data, size_t len, + size_t asn1hdrlen), + void *ctx) +{ + return true; +} + + +#include +#include +#include +#include + +int acpi_device_modalias(struct device *d, char * s, int i) +{ + lx_emul_trace_and_stop(__func__); +} + + +int acpi_device_uevent_modalias(struct device *d, struct kobj_uevent_env *k) +{ + lx_emul_trace_and_stop(__func__); +} + + +int acpi_dma_configure_id(struct device *dev, + enum dev_dma_attr attr, + const u32 *input_id) +{ + lx_emul_trace_and_stop(__func__); +} + + +bool acpi_driver_match_device(struct device *dev, const struct device_driver *drv) +{ + lx_emul_trace_and_stop(__func__); +} + + +union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, + u64 rev, u64 func, union acpi_object *argv4) +{ + return NULL; +} + + +acpi_status acpi_evaluate_object(acpi_handle handle, + acpi_string pathname, + struct acpi_object_list *external_params, + struct acpi_buffer *return_buffer) +{ + lx_emul_trace_and_stop(__func__); +} + + +enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) +{ + lx_emul_trace_and_stop(__func__); +} + + +acpi_status acpi_get_handle(acpi_handle parent,acpi_string pathname,acpi_handle * ret_handle) +{ + lx_emul_trace_and_stop(__func__); +} + + +int acpi_platform_notify(struct device *dev, enum kobject_action action) +{ + return 0; +} + + +bool is_acpi_device_node(const struct fwnode_handle *fwnode) +{ + return false; +} + +#include + +const struct attribute_group pci_dev_acpi_attr_group; + +int pci_acpi_program_hp_params(struct pci_dev *dev) +{ + return -ENODEV; +} + + +struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus) +{ + return NULL; +} + + +bool pciehp_is_native(struct pci_dev *bridge) +{ + return true; +} + + +#include + +struct thermal_cooling_device *thermal_cooling_device_register(const char *s, + void *p, const struct thermal_cooling_device_ops *op) +{ + return ERR_PTR(-ENODEV); +} + + +void thermal_cooling_device_unregister(struct thermal_cooling_device *tcd) +{ + lx_emul_trace(__func__); +} + + +int thermal_zone_device_enable(struct thermal_zone_device *tz) +{ + return -ENODEV; +} + + +struct thermal_zone_device *thermal_zone_device_register(const char *s, int i, int j, + void *p, struct thermal_zone_device_ops *ops, + struct thermal_zone_params *params, int x, int y) +{ + return ERR_PTR(-ENODEV); +} + + +void thermal_zone_device_unregister(struct thermal_zone_device *tzd) +{ + lx_emul_trace(__func__); +} + + +void thermal_zone_device_update(struct thermal_zone_device *tzd, + enum thermal_notify_event e) +{ + lx_emul_trace(__func__); +} + + +#include + +int net_ratelimit(void) +{ + lx_emul_trace(__func__); + /* suppress */ + return 0; +} diff --git a/repos/pc/src/lib/wifi/firmware.cc b/repos/pc/src/lib/wifi/firmware.cc new file mode 100644 index 0000000000..e454ff7f54 --- /dev/null +++ b/repos/pc/src/lib/wifi/firmware.cc @@ -0,0 +1,106 @@ +/* + * \brief Linux wireless stack + * \author Josef Soentgen + * \date 2018-06-29 + */ + +/* + * Copyright (C) 2018-2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include +#include + + +Firmware_list fw_list[] = { + { "regulatory.db", 4144, nullptr }, + { "regulatory.db.p7s", 1182, nullptr }, + + { "iwlwifi-1000-5.ucode", 337520, nullptr }, + { "iwlwifi-3160-17.ucode", 918268, nullptr }, + { "iwlwifi-5000-5.ucode", 340696, nullptr }, + { "iwlwifi-6000-4.ucode", 454608, nullptr }, + { "iwlwifi-6000-6.ucode", 454608, "iwlwifi-6000-4.ucode" }, + { "iwlwifi-6000g2a-6.ucode", 677296, nullptr }, + { "iwlwifi-6000g2b-6.ucode", 679436, nullptr }, + { "iwlwifi-7260-17.ucode", 1049340, nullptr }, + { "iwlwifi-7265-16.ucode", 1180412, nullptr }, + { "iwlwifi-7265D-29.ucode", 1036772, nullptr }, + { "iwlwifi-8000C-22.ucode", 2120860, nullptr }, + { "iwlwifi-8000C-36.ucode", 2428004, nullptr }, + { "iwlwifi-8265-22.ucode", 1811984, nullptr }, + { "iwlwifi-8265-36.ucode", 2436632, nullptr }, + + { "iwlwifi-9000-pu-b0-jf-b0-34.ucode", 2678284, nullptr }, + { "iwlwifi-9000-pu-b0-jf-b0-36.ucode", 2678284, "iwlwifi-9000-pu-b0-jf-b0-34.ucode" }, + { "iwlwifi-9000-pu-b0-jf-b0-46.ucode", 1514876, nullptr }, + + { "iwlwifi-QuZ-a0-hr-b0-63.ucode", 1334804, nullptr }, + { "iwlwifi-QuZ-a0-hr-b0-64.ucode", 1334804, "iwlwifi-QuZ-a0-hr-b0-63.ucode" }, +}; + + +size_t fw_list_len = sizeof(fw_list) / sizeof(fw_list[0]); + + +/********************** + ** linux/firmware.h ** + **********************/ + +extern "C" int lx_emul_request_firmware_nowait(const char *name, void **dest, size_t *result) +{ + if (!dest || !result) + return -1; + + /* only try to load known firmware images */ + Firmware_list *fwl = 0; + for (size_t i = 0; i < fw_list_len; i++) { + if (Genode::strcmp(name, fw_list[i].requested_name) == 0) { + fwl = &fw_list[i]; + break; + } + } + + if (!fwl) { + Genode::error("firmware '", name, "' is not in the firmware white list"); + return -1; + } + + char const *fw_name = fwl->available_name + ? fwl->available_name : fwl->requested_name; + Genode::Rom_connection rom(Lx_kit::env().env, fw_name); + Genode::Dataspace_capability ds_cap = rom.dataspace(); + + if (!ds_cap.valid()) { + Genode::error("could not get firmware ROM dataspace"); + return -1; + } + + /* use allocator because fw is too big for slab */ + void *data = Lx_kit::env().heap.alloc(fwl->size); + if (!data) + return -1; + + void const *image = Lx_kit::env().env.rm().attach(ds_cap); + Genode::memcpy(data, image, fwl->size); + Lx_kit::env().env.rm().detach(image); + + *dest = data; + *result = fwl->size; + + return 0; +} + + +extern "C" void lx_emul_release_firmware(void const *data, size_t size) +{ + Lx_kit::env().heap.free(const_cast(data), size); +} diff --git a/repos/pc/src/lib/wifi/firmware_list.h b/repos/pc/src/lib/wifi/firmware_list.h new file mode 100644 index 0000000000..50e960ad58 --- /dev/null +++ b/repos/pc/src/lib/wifi/firmware_list.h @@ -0,0 +1,26 @@ +/* + * \brief List for firmware images and their sizes + * \author Josef Soentgen + * \date 2014-03-26 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _FIRMWARE_LIST_H_ +#define _FIRMWARE_LIST_H_ + +typedef __SIZE_TYPE__ size_t; + +struct Firmware_list +{ + char const *requested_name; + size_t size; + char const *available_name; +}; + +#endif /* _FIRMWARE_LIST_H_ */ diff --git a/repos/pc/src/lib/wifi/generated_dummies.c b/repos/pc/src/lib/wifi/generated_dummies.c new file mode 100644 index 0000000000..73210cde4a --- /dev/null +++ b/repos/pc/src/lib/wifi/generated_dummies.c @@ -0,0 +1,1346 @@ +/* + * \brief Dummy definitions of Linux Kernel functions + * \author Automatically generated file - do no edit + * \date 2022-02-28 + */ + +#include + + +#include + +void * PDE_DATA(const struct inode * inode) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int ___ratelimit(struct ratelimit_state * rs,const char * func) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +const char * __clk_get_name(const struct clk * clk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int __ethtool_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * link_ksettings) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +unsigned long __fdget(unsigned int fd) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +unsigned long __get_free_pages(gfp_t gfp_mask,unsigned int order) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int __get_unused_fd_flags(unsigned flags,unsigned long nofile) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void __gnet_stats_copy_basic(const seqcount_t * running,struct gnet_stats_basic_packed * bstats,struct gnet_stats_basic_cpu __percpu * cpu,struct gnet_stats_basic_packed * b) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void __gnet_stats_copy_queue(struct gnet_stats_queue * qstats,const struct gnet_stats_queue __percpu * cpu,const struct gnet_stats_queue * q,__u32 qlen) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void __put_cred(struct cred * cred) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void __put_task_struct(struct task_struct * tsk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void __scm_destroy(struct scm_cookie * scm) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int __scm_send(struct socket * sock,struct msghdr * msg,struct scm_cookie * p) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +u32 __skb_get_hash_symmetric(const struct sk_buff * skb) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +u64 __sock_gen_cookie(struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void __srcu_read_unlock(struct srcu_struct * ssp,int idx) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void * __vmalloc_node(unsigned long size,unsigned long align,gfp_t gfp_mask,int node,const void * caller) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +unsigned long _copy_to_user(void __user * to,const void * from,unsigned long n) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void ack_bad_irq(unsigned int irq); +void ack_bad_irq(unsigned int irq) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int add_uevent_var(struct kobj_uevent_env * env,const char * format,...) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct file * alloc_file_pseudo(struct inode * inode,struct vfsmount * mnt,const char * name,int flags,const struct file_operations * fops) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct msi_desc * alloc_msi_entry(struct device * dev,int nvec,const struct irq_affinity_desc * affinity) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void arc4_crypt(struct arc4_ctx * ctx,u8 * out,const u8 * in,unsigned int len) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int arc4_setkey(struct arc4_ctx * ctx,const u8 * in_key,unsigned int key_len) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +async_cookie_t async_schedule_node(async_func_t func,void * data,int node) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void async_synchronize_full(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int bpf_prog_create_from_user(struct bpf_prog ** pfp,struct sock_fprog * fprog,bpf_aux_classic_check_t trans,bool save_orig) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void bpf_prog_destroy(struct bpf_prog * fp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void bpf_warn_invalid_xdp_action(u32 act) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void bust_spinlocks(int yes) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void console_flush_on_panic(enum con_flush_mode mode) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int console_printk[] = {}; + + +#include + +void console_unblank(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int copy_bpf_fprog_from_user(struct sock_fprog * dst,sockptr_t src,int len) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +size_t copy_page_from_iter(struct page * page,size_t offset,size_t bytes,struct iov_iter * i) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int dev_ifconf(struct net * net,struct ifconf * ifc,int size) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int dev_ioctl(struct net * net,unsigned int cmd,struct ifreq * ifr,bool * need_copyout) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +asmlinkage __visible void do_softirq(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void dst_release(struct dst_entry * dst) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +char * dynamic_dname(struct dentry * dentry,char * buffer,int buflen,const char * fmt,...) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void emergency_restart(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +u32 ethtool_op_get_link(struct net_device * dev) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int ethtool_op_get_ts_info(struct net_device * dev,struct ethtool_ts_info * info) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +pid_t f_getown(struct file * filp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int f_setown(struct file * filp,unsigned long arg,int force) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int fasync_helper(int fd,struct file * filp,int on,struct fasync_struct ** fapp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void fd_install(unsigned int fd,struct file * file) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct task_struct * find_task_by_vpid(pid_t vnr) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct flow_dissector flow_keys_basic_dissector; + + +#include + +void fput(struct file * file) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void free_msi_entry(struct msi_desc * entry) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void free_uid(struct user_struct * up) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct fwnode_handle * fwnode_create_software_node(const struct property_entry * properties,const struct fwnode_handle * parent) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void fwnode_remove_software_node(struct fwnode_handle * fwnode) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +unsigned long gcd(unsigned long a,unsigned long b) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void gen_kill_estimator(struct net_rate_estimator __rcu ** rate_est) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +ssize_t generic_file_splice_read(struct file * in,loff_t * ppos,struct pipe_inode_info * pipe,size_t len,unsigned int flags) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +ssize_t generic_splice_sendpage(struct pipe_inode_info * pipe,struct file * out,loff_t * ppos,size_t len,unsigned int flags) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int get_option(char ** str,int * pint) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +char * get_options(const char * str,int nints,int * ints) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int get_unused_fd_flags(unsigned flags) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int gnet_stats_copy_basic(const seqcount_t * running,struct gnet_dump * d,struct gnet_stats_basic_cpu __percpu * cpu,struct gnet_stats_basic_packed * b) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int gnet_stats_copy_queue(struct gnet_dump * d,struct gnet_stats_queue __percpu * cpu_q,struct gnet_stats_queue * q,__u32 qlen) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +const u8 guid_index[16] = {}; + + +#include + +ssize_t import_iovec(int type,const struct iovec __user * uvec,unsigned nr_segs,unsigned fast_segs,struct iovec ** iovp,struct iov_iter * i) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int import_single_range(int rw,void __user * buf,size_t len,struct iovec * iov,struct iov_iter * i) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +bool initcall_debug; + + +#include + +void inode_init_once(struct inode * inode) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void io_schedule_finish(int token) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int io_schedule_prepare(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +long __sched io_schedule_timeout(long timeout) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void iov_iter_kvec(struct iov_iter * i,unsigned int direction,const struct kvec * kvec,unsigned long nr_segs,size_t count) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void iov_iter_revert(struct iov_iter * i,size_t unroll) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void iput(struct inode * inode) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void irq_work_tick(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +bool is_software_node(const struct fwnode_handle * fwnode) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies; + + +#include + +struct kobject *kernel_kobj; + + +#include + +key_ref_t key_create_or_update(key_ref_t keyring_ref,const char * type,const char * description,const void * payload,size_t plen,key_perm_t perm,unsigned long flags) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void key_put(struct key * key) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void kill_anon_super(struct super_block * sb) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void kill_fasync(struct fasync_struct ** fp,int sig,int band) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int kmem_cache_alloc_bulk(struct kmem_cache * s,gfp_t flags,size_t size,void ** p) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void kmem_cache_destroy(struct kmem_cache * s) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void kmem_cache_free_bulk(struct kmem_cache * s,size_t size,void ** p) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void kmsg_dump(enum kmsg_dump_reason reason) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int kobject_synth_uevent(struct kobject * kobj,const char * buf,size_t count) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +unsigned long long memparse(const char * ptr,char ** retptr) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int msi_domain_alloc_irqs(struct irq_domain * domain,struct device * dev,int nvec) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void msi_domain_free_irqs(struct irq_domain * domain,struct device * dev) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +const struct nla_policy nda_policy[] = {}; + + +#include + +void netdev_rss_key_fill(void * buffer,size_t len) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct irq_chip no_irq_chip; + + +#include + +loff_t no_llseek(struct file * file,loff_t offset,int whence) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int open_related_ns(struct ns_common * ns,struct ns_common * (* get_ns)(struct ns_common * ns)) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +enum reboot_mode panic_reboot_mode; + + +#include + +void pci_assign_unassigned_bridge_resources(struct pci_dev * bridge) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void pci_assign_unassigned_bus_resources(struct pci_bus * bus) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern unsigned long pci_cardbus_resource_alignment(struct resource * res); +unsigned long pci_cardbus_resource_alignment(struct resource * res) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +unsigned int pci_flags; + + +extern int pci_idt_bus_quirk(struct pci_bus * bus,int devfn,u32 * l,int timeout); +int pci_idt_bus_quirk(struct pci_bus * bus,int devfn,u32 * l,int timeout) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int pci_mmap_resource_range(struct pci_dev * pdev,int bar,struct vm_area_struct * vma,enum pci_mmap_state mmap_state,int write_combine) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void __init pci_realloc_get_opt(char * str); +void __init pci_realloc_get_opt(char * str) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void pci_restore_vc_state(struct pci_dev * dev); +void pci_restore_vc_state(struct pci_dev * dev) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern int pci_save_vc_state(struct pci_dev * dev); +int pci_save_vc_state(struct pci_dev * dev) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void pci_stop_and_remove_bus_device(struct pci_dev * dev) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void pci_stop_and_remove_bus_device_locked(struct pci_dev * dev) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void pci_vpd_release(struct pci_dev * dev); +void pci_vpd_release(struct pci_dev * dev) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern unsigned int pcibios_assign_all_busses(void); +unsigned int pcibios_assign_all_busses(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void pcie_aspm_init_link_state(struct pci_dev * pdev); +void pcie_aspm_init_link_state(struct pci_dev * pdev) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void pcie_aspm_pm_state_change(struct pci_dev * pdev); +void pcie_aspm_pm_state_change(struct pci_dev * pdev) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void pcie_aspm_powersave_config_link(struct pci_dev * pdev); +void pcie_aspm_powersave_config_link(struct pci_dev * pdev) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int poll_select_set_timeout(struct timespec64 * to,time64_t sec,long nsec) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int printk_deferred(const char * fmt,...) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void printk_safe_flush_on_panic(void) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void proc_free_inum(unsigned int inum) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int put_cmsg(struct msghdr * msg,int level,int type,int len,void * data) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void put_cmsg_scm_timestamping(struct msghdr * msg,struct scm_timestamping_internal * tss_internal) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void put_cmsg_scm_timestamping64(struct msghdr * msg,struct scm_timestamping_internal * tss_internal) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void put_unused_fd(unsigned int fd) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int raw_pci_read(unsigned int domain,unsigned int bus,unsigned int devfn,int reg,int len,u32 * val) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +enum reboot_mode reboot_mode; + + +#include + +void remove_proc_entry(const char * name,struct proc_dir_entry * parent) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int reuseport_detach_prog(struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void reuseport_detach_sock(struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void scm_detach_fds(struct msghdr * msg,struct scm_cookie * scm) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct hlist_node * seq_hlist_next_rcu(void * v,struct hlist_head * head,loff_t * ppos) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct hlist_node * seq_hlist_start_head_rcu(struct hlist_head * head,loff_t pos) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct list_head * seq_list_next(void * v,struct list_head * head,loff_t * ppos) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct list_head * seq_list_start(struct list_head * head,loff_t pos) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct list_head * seq_list_start_head(struct list_head * head,loff_t pos) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void seq_printf(struct seq_file * m,const char * f,...) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void seq_putc(struct seq_file * m,char c) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void seq_puts(struct seq_file * m,const char * s) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void sha224_final(struct sha256_state * sctx,u8 * out) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void sha256_final(struct sha256_state * sctx,u8 * out) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void sha256_update(struct sha256_state * sctx,const u8 * data,unsigned int len) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void show_mem(unsigned int filter,nodemask_t * nodemask) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void show_state_filter(unsigned int state_filter) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int simple_setattr(struct user_namespace * mnt_userns,struct dentry * dentry,struct iattr * iattr) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int simple_statfs(struct dentry * dentry,struct kstatfs * buf) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sk_attach_bpf(u32 ufd,struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sk_attach_filter(struct sock_fprog * fprog,struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sk_detach_filter(struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void sk_filter_uncharge(struct sock * sk,struct sk_filter * fp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sk_get_filter(struct sock * sk,struct sock_filter __user * ubuf,unsigned int len) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sk_reuseport_attach_bpf(u32 ufd,struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sk_reuseport_attach_filter(struct sock_fprog * fprog,struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int smp_call_function_single(int cpu,void (* func)(void * info),void * info,int wait) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void sock_diag_broadcast_destroy(struct sock * sk) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void srcu_drive_gp(struct work_struct * wp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +bool static_key_initialized; + + +#include + +int stream_open(struct inode * inode,struct file * filp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int string_escape_mem(const char * src,size_t isz,char * dst,size_t osz,unsigned int flags,const char * only) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int suppress_printk; + + +#include + +void synchronize_srcu(struct srcu_struct * ssp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void sysfs_delete_link(struct kobject * kobj,struct kobject * targ,const char * name) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sysfs_emit(char * buf,const char * fmt,...) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sysfs_emit_at(char * buf,int at,const char * fmt,...) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +bool sysfs_remove_file_self(struct kobject * kobj,const struct attribute * attr) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void sysfs_remove_group(struct kobject * kobj,const struct attribute_group * grp) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sysfs_rename_dir_ns(struct kobject * kobj,const char * new_name,const void * new_ns) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int sysfs_rename_link_ns(struct kobject * kobj,struct kobject * targ,const char * old,const char * new,const void * new_ns) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct callback_head * task_work_cancel(struct task_struct * task,task_work_func_t func) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void tasklet_kill(struct tasklet_struct * t) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int unregister_filesystem(struct file_system_type * fs) +{ + lx_emul_trace_and_stop(__func__); +} + + +extern void unregister_handler_proc(unsigned int irq,struct irqaction * action); +void unregister_handler_proc(unsigned int irq,struct irqaction * action) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +const u8 uuid_index[16] = {}; + + +#include + +int vm_insert_page(struct vm_area_struct * vma,unsigned long addr,struct page * page) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +struct page * vmalloc_to_page(const void * vmalloc_addr) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void wake_q_add_safe(struct wake_q_head * head,struct task_struct * task) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +int xdp_do_generic_redirect(struct net_device * dev,struct sk_buff * skb,struct xdp_buff * xdp,struct bpf_prog * xdp_prog) +{ + lx_emul_trace_and_stop(__func__); +} + + +#include + +void __sched yield(void) +{ + lx_emul_trace_and_stop(__func__); +} + diff --git a/repos/pc/src/lib/wifi/libc_errno.h b/repos/pc/src/lib/wifi/libc_errno.h new file mode 100644 index 0000000000..1ee1f6f36d --- /dev/null +++ b/repos/pc/src/lib/wifi/libc_errno.h @@ -0,0 +1,109 @@ +/* + * \brief Libc errno values + * \date 2022-03-03 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _WLAN__LIBC_ERRNO_H_ +#define _WLAN__LIBC_ERRNO_H_ + +/* Linux errno values */ +#include + +namespace Libc { + + enum class Errno : int { + /* + * The following numbers correspond to the FreeBSD errno values + */ + BSD_EPERM = 1, + BSD_ENOENT = 2, + BSD_ESRCH = 3, + BSD_EINTR = 4, + BSD_EIO = 5, + BSD_ENXIO = 6, + BSD_E2BIG = 7, + BSD_ENOEXEC = 8, + BSD_EBADF = 9, + BSD_EDEADLK = 11, + BSD_ENOMEM = 12, + BSD_EACCES = 13, + BSD_EFAULT = 14, + BSD_EBUSY = 16, + BSD_EEXIST = 17, + BSD_EXDEV = 18, + BSD_ENODEV = 19, + BSD_EINVAL = 22, + BSD_ENFILE = 23, + BSD_ENOTTY = 25, + BSD_EFBIG = 27, + BSD_ENOSPC = 28, + BSD_ESPIPE = 29, + BSD_EPIPE = 32, + BSD_EDOM = 33, + BSD_ERANGE = 34, + BSD_EAGAIN = 35, + BSD_EINPROGRESS = 36, + BSD_EALREADY = 37, + BSD_ENOTSOCK = 38, + BSD_EDESTADDRREQ = 39, + BSD_EMSGSIZE = 40, + BSD_ENOPROTOOPT = 42, + BSD_EPROTONOSUPPORT = 43, + BSD_ESOCKTNOSUPPORT = 44, + BSD_EOPNOTSUPP = 45, + BSD_EPFNOSUPPORT = 46, + BSD_EAFNOSUPPORT = 47, + BSD_EADDRINUSE = 48, + BSD_EADDRNOTAVAIL = 49, + BSD_ENETDOWN = 50, + BSD_ENETUNREACH = 51, + BSD_ECONNABORTED = 53, + BSD_ECONNRESET = 54, + BSD_ENOBUFS = 55, + BSD_EISCONN = 56, + BSD_ENOTCONN = 57, + BSD_ETIMEDOUT = 60, + BSD_ECONNREFUSED = 61, + BSD_ENAMETOOLONG = 63, + BSD_EHOSTDOWN = 64, + BSD_EHOSTUNREACH = 65, + BSD_ENOSYS = 78, + BSD_ENOMSG = 83, + BSD_EOVERFLOW = 84, + BSD_ECANCELED = 85, + BSD_EILSEQ = 86, + BSD_EBADMSG = 89, + BSD_ENOLINK = 91, + BSD_EPROTO = 92, + + /* + * The following numbers correspond to nothing + */ + BSD_EREMOTEIO = 200, + BSD_ERESTARTSYS = 201, + BSD_ENODATA = 202, + BSD_ETOOSMALL = 203, + BSD_ENOIOCTLCMD = 204, + BSD_ENONET = 205, + BSD_ENOTSUPP = 206, + BSD_ENOTUNIQ = 207, + BSD_ERFKILL = 208, + BSD_ETIME = 209, + BSD_EPROBE_DEFER = 210, + + BSD_EL3RST = 211, + BSD_ENOKEY = 212, + BSD_ECHRNG = 213, + + MAX_ERRNO = 4095, + }; +} /* namespace Libc */ + +#endif /* _WLAN__LIBC_ERRNO_H_ */ diff --git a/repos/pc/src/lib/wifi/lx_emul.c b/repos/pc/src/lib/wifi/lx_emul.c new file mode 100644 index 0000000000..7f21f6a1d2 --- /dev/null +++ b/repos/pc/src/lib/wifi/lx_emul.c @@ -0,0 +1,765 @@ +/* + * \brief Linux emulation environment specific to this driver + * \author Josef Soentgen + * \date 2022-02-09 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include + +#include +#include + + +#include + +void __const_udelay(unsigned long xloops) +{ + lx_emul_time_udelay(xloops / 0x10C7UL); +} + + +void __udelay(unsigned long usecs) +{ + lx_emul_time_udelay(usecs); +} + + +#include + +atomic_t __num_online_cpus = ATOMIC_INIT(1); + + +#include + +dma_addr_t dma_map_page_attrs(struct device * dev, + struct page * page, + size_t offset, + size_t size, + enum dma_data_direction dir, + unsigned long attrs) +{ + dma_addr_t const dma_addr = page_to_phys(page); + unsigned long const virt_addr = (unsigned long)page_to_virt(page); + + lx_emul_mem_cache_clean_invalidate((void *)(virt_addr + offset), size); + return dma_addr + offset; +} + + +#include + +struct dma_pool { + size_t size; + size_t align; +}; + +void * dma_pool_alloc(struct dma_pool * pool, gfp_t mem_flags, dma_addr_t * handle) +{ + void * ret = + lx_emul_mem_alloc_aligned_uncached(pool->size, pool->align); + *handle = lx_emul_mem_dma_addr(ret); + return ret; +} + + +struct dma_pool * dma_pool_create(const char * name, + struct device * dev, + size_t size, + size_t align, + size_t boundary) +{ + struct dma_pool * pool = kmalloc(sizeof(struct dma_pool), GFP_KERNEL); + pool->size = size; + pool->align = align; + return pool; +} + + +void dma_pool_free(struct dma_pool * pool,void * vaddr,dma_addr_t dma) +{ + lx_emul_mem_free(vaddr); +} + + +struct dma_pool *dmam_pool_create(const char *name, + struct device *dev, + size_t size, + size_t align, + size_t allocation) +{ + /* + * Only take care of allocating the pool because + * we do not detach the driver anyway. + */ + return dma_pool_create(name, dev, size, align, 0); +} + + +#include + +int dma_supported(struct device * dev,u64 mask) +{ + lx_emul_trace(__func__); + return 1; +} + + +#include + +void dma_unmap_page_attrs(struct device * dev, + dma_addr_t addr, + size_t size, + enum dma_data_direction dir, + unsigned long attrs) +{ + unsigned long const virt_addr = lx_emul_mem_virt_addr((void*)addr); + + if (!virt_addr) + return; + + if (dir == DMA_FROM_DEVICE) + lx_emul_mem_cache_invalidate((void *)virt_addr, size); +} + + +#include + +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, + size_t size, enum dma_data_direction dir) +{ + unsigned long const virt_addr = lx_emul_mem_virt_addr((void*)addr); + + if (!virt_addr) + return; + + lx_emul_mem_cache_invalidate((void *)virt_addr, size); +} + + +#include + +void dma_sync_single_for_device(struct device *dev, dma_addr_t addr, + size_t size, enum dma_data_direction dir) +{ + unsigned long const virt_addr = lx_emul_mem_virt_addr((void*)addr); + + if (!virt_addr) + return; + + lx_emul_mem_cache_clean_invalidate((void *)virt_addr, size); +} + + +#include + +void * kmalloc_order(size_t size, gfp_t flags, unsigned int order) +{ + return kmalloc(size, flags); +} + + +#include +#include +#include + +int simple_pin_fs(struct file_system_type * type, struct vfsmount ** mount, int * count) +{ + *mount = kmalloc(sizeof(struct vfsmount), GFP_KERNEL); + return 0; +} + + +#include + +void simple_release_fs(struct vfsmount ** mount,int * count) +{ + kfree(*mount); +} + + +#include + +struct inode * alloc_anon_inode(struct super_block * s) +{ + return kmalloc(sizeof(struct inode), GFP_KERNEL); +} + + +#include + +// softirq.c +void tasklet_setup(struct tasklet_struct * t, + void (* callback)(struct tasklet_struct *)) +{ + t->next = NULL; + t->state = 0; + atomic_set(&t->count, 0); + t->callback = callback; + t->use_callback = true; + t->data = 0; +} + + +void __tasklet_schedule(struct tasklet_struct * t) +{ + if (test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) + t->callback(t); +} + + +void __tasklet_hi_schedule(struct tasklet_struct * t) +{ + if (test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) + t->callback(t); +} + + +#include + +void call_rcu(struct rcu_head * head,rcu_callback_t func) +{ + enum { KVFREE_RCU_OFFSET = 4096, }; + if (func < (rcu_callback_t)KVFREE_RCU_OFFSET) { + kvfree((void*)head - (unsigned long)func); + return; + } + + func(head); +} + + +#include + +void __iomem * ioremap(resource_size_t phys_addr, unsigned long size) +{ + return lx_emul_io_mem_map(phys_addr, size); +} + + +#include + +void iounmap(volatile void __iomem * addr) +{ + (void)addr; +} + + +#include + +struct kmem_cache * kmem_cache_create_usercopy(const char * name, + unsigned int size, + unsigned int align, + slab_flags_t flags, + unsigned int useroffset, + unsigned int usersize, + void (* ctor)(void *)) +{ + return kmem_cache_create(name, size, align, flags, ctor); +} + + +#include + +int register_filesystem(struct file_system_type * fs) +{ + lx_emul_trace(__func__); + return 0; +} + + +#include +#include +#include +#include +#include + +struct pseudo_fs_context * init_pseudo(struct fs_context *fc, + unsigned long magic) +{ + struct pseudo_fs_context *pfs_ctx; + + pfs_ctx = kzalloc(sizeof (struct pseudo_fs_context), GFP_KERNEL); + if (pfs_ctx) { + pfs_ctx->magic = magic; + fc->fs_private = pfs_ctx; + } + return pfs_ctx; +} + + +struct vfsmount * kern_mount(struct file_system_type * type) +{ + struct vfsmount *m; + + /* + * This sets everything up so that 'new_inode_pseudo()' + * called from 'sock_alloc()' properly allocates the inode. + */ + + m = kzalloc(sizeof (struct vfsmount), 0); + if (m) { + + struct fs_context fs_ctx; + + if (type->init_fs_context) { + type->init_fs_context(&fs_ctx); + + m->mnt_sb = kzalloc(sizeof (struct super_block), GFP_KERNEL); + m->mnt_sb->s_type = type; + m->mnt_sb->s_op = + ((struct pseudo_fs_context*)fs_ctx.fs_private)->ops; + } else { + kfree(m); + m = (struct vfsmount*)ERR_PTR(-ENOMEM); + } + } + + return m; +} + + +struct inode * new_inode_pseudo(struct super_block * sb) +{ + const struct super_operations *ops = sb->s_op; + struct inode *inode; + + if (ops->alloc_inode) { + inode = ops->alloc_inode(sb); + } + + if (!inode) + return (struct inode*)ERR_PTR(-ENOMEM); + + return inode; +} + + +#include + +int sysfs_create_dir_ns(struct kobject * kobj,const void * ns) +{ + lx_emul_trace(__func__); + kobj->sd = kzalloc(sizeof(*kobj->sd), GFP_KERNEL); + return 0; +} + + +#include + +#if 0 +struct firmware_work { + struct work_struct work; + struct firmware const *firmware; + void *context; + void (*cont)(struct firmware const *, void *); +}; + + +static void request_firmware_work_func(struct work_struct *work) +{ + struct firmware_work *fw_work = + container_of(work, struct firmware_work, work); + + fw_work->cont(fw_work->firmware, fw_work->context); + + kfree(fw_work); +} +#endif + + +extern int lx_emul_request_firmware_nowait(const char *name, void *dest, size_t *result); +extern void lx_emul_release_firmware(void const *data, size_t size); + +extern void rtnl_lock(void); +extern void rtnl_unlock(void); + +int request_firmware_nowait(struct module * module, + bool uevent, const char * name, + struct device * device, gfp_t gfp, + void * context, + void (* cont)(const struct firmware * fw, + void * context)) +{ + struct firmware *fw = kzalloc(sizeof (struct firmware), GFP_KERNEL); +#if 0 + struct firmware_work *fw_work; +#endif + bool reg_db; + + if (lx_emul_request_firmware_nowait(name, &fw->data, &fw->size)) { + kfree(fw); + return -1; + } + + /* + * Normally we would schedule fw_work but for reasons not + * yet understood doing so will lead to a page-fault. So + * for the time being we will execute the callback directly + * and we have to make sure to manage the RTNL lock as the + * callback will grab it while we already hold it. + */ + reg_db = strcmp(name, "regulatory.db") == 0; + + if (reg_db) + rtnl_unlock(); + + cont(fw, context); + + if (reg_db) + rtnl_lock(); + return 0; + +#if 0 + fw_work = kzalloc(sizeof (struct firmware_work), GFP_KERNEL); + if (!fw_work) { + kfree(fw); + return -1; + } + + fw_work->firmware = fw; + fw_work->context = context; + fw_work->cont = cont; + + INIT_WORK(&fw_work->work, request_firmware_work_func); + schedule_work(&fw_work->work); + + return 0; +#endif +} + + +int request_firmware(const struct firmware ** firmware_p, + const char * name, struct device * device) +{ + struct firmware *fw; + + if (!*firmware_p) + return -1; + + fw = kzalloc(sizeof (struct firmware), GFP_KERNEL); + + if (lx_emul_request_firmware_nowait(name, &fw->data, &fw->size)) { + kfree(fw); + return -1; + } + + *firmware_p = fw; + return 0; +} + + +void release_firmware(const struct firmware * fw) +{ + lx_emul_release_firmware(fw->data, fw->size); + kfree(fw); +} + + +/* + * This function is only called when using newer WIFI6 devices to + * load 'iwl-debug-yoyo.bin'. We simply deny the request. + */ +int firmware_request_nowarn(const struct firmware ** firmware,const char * name,struct device * device) +{ + return -1; +} + + +#include + +int pcim_iomap_regions_request_all(struct pci_dev * pdev,int mask,const char * name) +{ + return 0; +} + + +#include + +static unsigned long *_pci_iomap_table; + +void __iomem * const * pcim_iomap_table(struct pci_dev * pdev) +{ + unsigned i; + + if (!_pci_iomap_table) + _pci_iomap_table = kzalloc(sizeof (unsigned long*) * 6, GFP_KERNEL); + + if (!_pci_iomap_table) + return NULL; + + for (i = 0; i < 6; i++) { + struct resource *r = &pdev->resource[i]; + unsigned long phys_addr = r->start; + unsigned long size = r->end - r->start; + + if (!phys_addr || !size) + continue; + + _pci_iomap_table[i] = + (unsigned long)lx_emul_io_mem_map(phys_addr, size); + } + + return (void const *)_pci_iomap_table; +} + + +#include + +int task_work_add(struct task_struct * task,struct callback_head * work,enum task_work_notify_mode notify) +{ + printk("%s: task: %p work: %p notify: %u\n", __func__, task, work, notify); + return -1; +} + + +#include + +void vfree(const void * addr) +{ + kfree(addr); +} + + +#include + +void * vmalloc(unsigned long size) +{ + return kmalloc(size, GFP_KERNEL); +} + + +#include + +void * vzalloc(unsigned long size) +{ + return kzalloc(size, GFP_KERNEL); +} + + +#include + +void __raise_softirq_irqoff(unsigned int nr) +{ + raise_softirq(nr); +} + + +#include + +void kfree_sensitive(const void *p) +{ + size_t ks; + void *mem = (void *)p; + + ks = ksize(mem); + if (ks) + memset(mem, 0, ks); + + kfree(mem); +} + + +#include + +void free_pages(unsigned long addr,unsigned int order) +{ + __free_pages(virt_to_page((void *)addr), order); +} + + +#include +#include + +unsigned long get_zeroed_page(gfp_t gfp_mask) +{ + return (unsigned long)kzalloc(PAGE_SIZE, gfp_mask | __GFP_ZERO); +} + + +#include + +pid_t __task_pid_nr_ns(struct task_struct * task, + enum pid_type type, + struct pid_namespace * ns) +{ + (void)type; + (void)ns; + + return lx_emul_task_pid(task); +} + + +#include + +unsigned long _copy_from_user(void * to, const void __user * from, + unsigned long n) +{ + memcpy(to, from, n); + return 0; +} + + +#include + +size_t _copy_from_iter(void * addr, size_t bytes, struct iov_iter * i) +{ + char *kdata; + struct iovec const *iov; + size_t len; + + if (bytes > i->count) + bytes = i->count; + + if (bytes == 0) + return 0; + + kdata = (char*)(addr); + iov = i->iov; + + len = bytes; + while (len > 0) { + if (iov->iov_len) { + size_t copy_len = (size_t)len < iov->iov_len ? len + : iov->iov_len; + memcpy(kdata, iov->iov_base, copy_len); + + len -= copy_len; + kdata += copy_len; + } + iov++; + } + + return bytes; +} + + +#include + +size_t _copy_to_iter(const void * addr, size_t bytes, struct iov_iter * i) +{ + char *kdata; + struct iovec const *iov; + size_t len; + + if (bytes > i->count) + bytes = i->count; + + if (bytes == 0) + return 0; + + kdata = (char*)(addr); + iov = i->iov; + + len = bytes; + while (len > 0) { + if (iov->iov_len) { + size_t copy_len = (size_t)len < iov->iov_len ? len + : iov->iov_len; + memcpy(iov->iov_base, kdata, copy_len); + + len -= copy_len; + kdata += copy_len; + } + iov++; + } + + return bytes; +} + + +#include + +asmlinkage __visible void dump_stack(void) +{ + lx_backtrace(); +} + + +#include + +void __put_page(struct page * page) +{ + __free_pages(page, 0); +} + + +#include + +u32 get_random_u32(void) +{ + return lx_emul_get_random_u32(); +} + + +int __must_check get_random_bytes_arch(void *buf, int nbytes) +{ + if (nbytes < 0) + return -1; + + lx_emul_get_random_bytes(buf, (unsigned long)nbytes); + return 0; +} + + +void get_random_bytes(void *buf, int nbytes) +{ + get_random_bytes_arch(buf, nbytes); +} + + +#include + +void prandom_bytes(void *buf, size_t bytes) +{ + lx_emul_get_random_bytes(buf, bytes); +} + + +u32 prandom_u32(void) +{ + return lx_emul_get_random_u32(); +} + + +#include + +void *page_frag_alloc_align(struct page_frag_cache *nc, + unsigned int fragsz, gfp_t gfp_mask, + unsigned int align_mask) +{ + (void)nc; + unsigned int const order = fragsz / PAGE_SIZE; + struct page *page = __alloc_pages(gfp_mask, order, 0, NULL); + + if (!page) + return NULL; + + /* see page_frag_free */ + if (order > 0) + printk("%s: alloc might leak memory: fragsz: %u PAGE_SIZE: %u " + "order: %u page: %p addr: %p\n", __func__, fragsz, PAGE_SIZE, order, page, page->virtual); + + return page->virtual; +} + + +#include + +void page_frag_free(void * addr) +{ + struct page *page = lx_emul_virt_to_pages(addr, 1ul); + if (!page) { + printk("BUG %s: page for addr: %p not found\n", __func__, addr); + lx_backtrace(); + } + + __free_pages(page, 0ul); +} diff --git a/repos/pc/src/lib/wifi/lx_emul.h b/repos/pc/src/lib/wifi/lx_emul.h new file mode 100644 index 0000000000..b2cf5ffb06 --- /dev/null +++ b/repos/pc/src/lib/wifi/lx_emul.h @@ -0,0 +1,37 @@ +/** + * \brief Dummy definitions of Linux Kernel functions + * \author Stefan Kalkowski + * \date 2021-03-16 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Needed to trace and stop */ +#include + +/* fix for wait_for_completion_timeout where the __sched include is missing */ +#include + +/* fix for missing include in linux/dynamic_debug.h */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void lx_backtrace(void); + +void lx_emul_time_udelay(unsigned long usec); + +void lx_emul_get_random_bytes(void *buf, unsigned long nbytes); +unsigned int lx_emul_get_random_u32(void); + + +#ifdef __cplusplus +} +#endif diff --git a/repos/pc/src/lib/wifi/lx_emul/initcall_order.h b/repos/pc/src/lib/wifi/lx_emul/initcall_order.h new file mode 100644 index 0000000000..3d2d9e5750 --- /dev/null +++ b/repos/pc/src/lib/wifi/lx_emul/initcall_order.h @@ -0,0 +1,208 @@ +/* + * \brief Array defining order of Linux Kernel initcalls + * \author Automatically generated file - do no edit + * \date 2022-02-28 + */ + +#pragma once + +static const char * lx_emul_initcall_order[] = { + "__initcall_init_hw_perf_eventsearly", + "__initcall_start", + "__initcall_init_real_modeearly", + "__initcall_validate_x2apicearly", + "__initcall_register_nmi_cpu_backtrace_handlerearly", + "__initcall_spawn_ksoftirqdearly", + "__initcall_static_call_initearly", + "__initcall_init_zero_pfnearly", + "__initcall_initialize_ptr_randomearly", + "__initcall_init_mmap_min_addr0", + "__initcall_pci_realloc_setup_params0", + "__initcall_net_ns_init0", + "__initcall_reboot_init1", + "__initcall_wq_sysfs_init1", + "__initcall_ksysfs_init1", + "__initcall_rcu_set_runtime_mode1", + "__initcall_init_jiffies_clocksource1", + "__initcall_init_script_binfmt1", + "__initcall_init_elf_binfmt1", + "__initcall_prandom_init_early1", + "__initcall_sock_init1", + "__initcall_net_inuse_init1", + "__initcall_net_defaults_init1", + "__initcall_init_default_flow_dissectors1", + "__initcall_netlink_proto_init1", + "__initcall_genl_init1", + "__initcall_irq_sysfs_init2", + "__initcall_bdi_class_init2", + "__initcall_mm_sysfs_init2", + "__initcall_init_per_zone_wmark_min2", + "__initcall_mpi_init2", + "__initcall_pcibus_class_init2", + "__initcall_pci_driver_init2", + "__initcall_tty_class_init2", + "__initcall_vtconsole_class_init2", + "__initcall_devlink_class_init2", + "__initcall_software_node_init2", + "__initcall_amd_postcore_init2", + "__initcall_kobject_uevent_init2", + "__initcall_bts_init3", + "__initcall_pt_init3", + "__initcall_boot_params_ksysfs_init3", + "__initcall_sbf_init3", + "__initcall_arch_kdebugfs_init3", + "__initcall_intel_pconfig_init3", + "__initcall_cryptomgr_init3", + "__initcall_pci_arch_init3", + "__initcall_init_vdso4", + "__initcall_fixup_ht_bug4", + "__initcall_topology_init4", + "__initcall_uid_cache_init4", + "__initcall_param_sysfs_init4", + "__initcall_user_namespace_sysctl_init4", + "__initcall_oom_init4", + "__initcall_default_bdi_init4", + "__initcall_percpu_enable_async4", + "__initcall_init_user_reserve4", + "__initcall_init_admin_reserve4", + "__initcall_init_reserve_notifier4", + "__initcall_rsa_init4", + "__initcall_crypto_cmac_module_init4", + "__initcall_crypto_null_mod_init4", + "__initcall_sha256_generic_mod_init4", + "__initcall_crypto_ctr_module_init4", + "__initcall_crypto_gcm_module_init4", + "__initcall_crypto_ccm_module_init4", + "__initcall_aes_init4", + "__initcall_ghash_mod_init4", + "__initcall_pci_slot_init4", + "__initcall_misc_init4", + "__initcall_usb_common_init4", + "__initcall_usb_init4", + "__initcall_serio_init4", + "__initcall_input_init4", + "__initcall_proto_init4", + "__initcall_net_dev_init4", + "__initcall_neigh_init4", + "__initcall_fib_notifier_init4", + "__initcall_ethnl_init4", + "__initcall_ieee80211_init4", + "__initcall_pci_subsys_init4", + "__initcall_nmi_warning_debugfs5", + "__initcall_hpet_late_init5", + "__initcall_init_amd_nbs5", + "__initcall_iomem_init_inode5", + "__initcall_clocksource_done_booting5", + "__initcall_init_pipe_fs5", + "__initcall_anon_inode_init5", + "__initcall_proc_cmdline_init5", + "__initcall_proc_consoles_init5", + "__initcall_proc_cpuinfo_init5", + "__initcall_proc_devices_init5", + "__initcall_proc_interrupts_init5", + "__initcall_proc_loadavg_init5", + "__initcall_proc_meminfo_init5", + "__initcall_proc_stat_init5", + "__initcall_proc_uptime_init5", + "__initcall_proc_version_init5", + "__initcall_proc_softirqs_init5", + "__initcall_proc_kmsg_init5", + "__initcall_proc_page_init5", + "__initcall_init_ramfs_fs5", + "__initcall_chr_dev_init5", + "__initcall_firmware_class_init5", + "__initcall_sysctl_core_init5", + "__initcall_eth_offload_init5", + "__initcall_cfg80211_init5", + "__initcall_pcibios_assign_resources5", + "__initcall_pci_apply_final_quirks5s", + "__initcall_populate_rootfsrootfs", + "__initcall_pci_iommu_initrootfs", + "__initcall_rapl_pmu_init6", + "__initcall_packet_init6", + "__initcall_amd_uncore_init6", + "__initcall_amd_ibs_init6", + "__initcall_msr_init6", + "__initcall_intel_uncore_init6", + "__initcall_cstate_pmu_init6", + "__initcall_register_kernel_offset_dumper6", + "__initcall_i8259A_init_ops6", + "__initcall_init_tsc_clocksource6", + "__initcall_add_rtc_cmos6", + "__initcall_umwait_init6", + "__initcall_ioapic_init_ops6", + "__initcall_sysfb_init6", + "__initcall_proc_execdomains_init6", + "__initcall_ioresources_init6", + "__initcall_timekeeping_init_ops6", + "__initcall_init_clocksource_sysfs6", + "__initcall_init_timer_list_procfs6", + "__initcall_alarmtimer_init6", + "__initcall_clockevents_init_sysfs6", + "__initcall_utsname_sysctl_init6", + "__initcall_perf_event_sysfs_init6", + "__initcall_system_trusted_keyring_init6", + "__initcall_kswapd_init6", + "__initcall_workingset_init6", + "__initcall_proc_vmalloc_init6", + "__initcall_fcntl_init6", + "__initcall_proc_filesystems_init6", + "__initcall_start_dirtytime_writeback6", + "__initcall_init_devpts_fs6", + "__initcall_key_proc_init6", + "__initcall_crypto_algapi_init6", + "__initcall_asymmetric_key_init6", + "__initcall_x509_key_init6", + "__initcall_pci_proc_init6", + "__initcall_gpio_clk_driver_init6", + "__initcall_plt_clk_driver_init6", + "__initcall_n_null_init6", + "__initcall_pty_init6", + "__initcall_serial8250_init6", + "__initcall_serial_pci_driver_init6", + "__initcall_exar_pci_driver_init6", + "__initcall_lpss8250_pci_driver_init6", + "__initcall_mid8250_pci_driver_init6", + "__initcall_topology_sysfs_init6", + "__initcall_cacheinfo_sysfs_init6", + "__initcall_net_olddevs_init6", + "__initcall_blackhole_netdev_init6", + "__initcall_iwl_drv_init6", + "__initcall_iwl_init6", + "__initcall_iwl_mvm_init6", + "__initcall_ehci_hcd_init6", + "__initcall_ehci_pci_init6", + "__initcall_ohci_hcd_mod_init6", + "__initcall_ohci_pci_init6", + "__initcall_xhci_hcd_init6", + "__initcall_xhci_pci_init6", + "__initcall_i8042_init6", + "__initcall_serport_init6", + "__initcall_atkbd_init6", + "__initcall_psmouse_init6", + "__initcall_pmc_atom_init6", + "__initcall_sock_diag_init6", + "__initcall_update_mp_table7", + "__initcall_lapic_insert_resource7", + "__initcall_print_ICs7", + "__initcall_create_tlb_single_page_flush_ceiling7", + "__initcall_init_oops_id7", + "__initcall_reboot_ksysfs_init7", + "__initcall_sched_clock_init_late7", + "__initcall_sched_init_debug7", + "__initcall_printk_late_init7", + "__initcall_load_system_certificate_list7", + "__initcall_check_early_ioremap_leak7", + "__initcall_init_root_keyring7", + "__initcall_prandom_init_late7", + "__initcall_pci_resource_alignment_sysfs_init7", + "__initcall_pci_sysfs_init7", + "__initcall_sync_state_resume_initcall7", + "__initcall_deferred_probe_initcall7", + "__initcall_regulatory_init_db7", + "__initcall_clk_disable_unused7s", + "__initcall_con_initcon", + "__initcall_end", + "__initcall_univ8250_console_initcon", + "END_OF_INITCALL_ORDER_ARRAY_DUMMY_ENTRY" +}; diff --git a/repos/pc/src/lib/wifi/lx_emul/pci_fixups.h b/repos/pc/src/lib/wifi/lx_emul/pci_fixups.h new file mode 100644 index 0000000000..866a2be59f --- /dev/null +++ b/repos/pc/src/lib/wifi/lx_emul/pci_fixups.h @@ -0,0 +1,5 @@ +#pragma once + +static const char * lx_emul_pci_final_fixups[] = { + "END_OF_PCI_FIXUPS" +}; diff --git a/repos/pc/src/lib/wifi/lx_socket_call.c b/repos/pc/src/lib/wifi/lx_socket_call.c new file mode 100644 index 0000000000..45ce95436f --- /dev/null +++ b/repos/pc/src/lib/wifi/lx_socket_call.c @@ -0,0 +1,279 @@ +/* + * \brief Linux socket call interface back end + * \author Josef Soentgen + * \date 2022-02-17 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* DDE Linux includes */ +#include "lx_socket_call.h" + +/* kernel includes */ +#include +#include +#include + + +struct task_struct *lx_socket_call_task; +void *lx_socket_call_task_args; +extern int run_lx_socket_call_task(void *p); + + +extern struct net init_net; + +void lx_user_init(void) +{ + int pid = kernel_thread(run_lx_socket_call_task, + lx_socket_call_task_args, + CLONE_FS | CLONE_FILES); + lx_socket_call_task = find_task_by_pid_ns(pid, NULL); +} + + +int lx_sock_create_kern(int domain, int type, int protocol, + struct socket **res) +{ + int const err = __sock_create(&init_net, domain, type, protocol, res, 1); + if (err) + return err; + + init_waitqueue_head(&(*res)->wq.wait); + return 0; +} + + +int lx_sock_release(struct socket *sock) +{ + return sock->ops->release(sock); +} + + +int lx_sock_bind(struct socket *sock, void *sockaddr, int sockaddr_len) +{ + return sock->ops->bind(sock, sockaddr, sockaddr_len); +} + + +int lx_sock_getname(struct socket *sock, void *sockaddr, int peer) +{ + return sock->ops->getname(sock, sockaddr, peer); +} + + +int lx_sock_recvmsg(struct socket *sock, struct lx_msghdr *lx_msg, + int flags, int dontwait) +{ + struct msghdr *msg; + struct iovec *iov; + size_t iovlen; + unsigned iov_count; + unsigned i; + + int err = -1; + + iov_count = lx_msg->msg_iovcount; + + msg = kzalloc(sizeof (struct msghdr), GFP_KERNEL); + if (!msg) + goto err_msg; + iov = kzalloc(sizeof (struct iovec) * iov_count, GFP_KERNEL); + if (!iov) + goto err_iov; + + iovlen = 0; + for (i = 0; i < iov_count; i++) { + iov[i].iov_base = lx_msg->msg_iov[i].iov_base; + iov[i].iov_len = lx_msg->msg_iov[i].iov_len; + + iovlen += lx_msg->msg_iov[i].iov_len; + } + + msg->msg_name = lx_msg->msg_name; + msg->msg_namelen = lx_msg->msg_namelen; + msg->msg_iter.iov = iov; + msg->msg_iter.nr_segs = iov_count; + msg->msg_iter.count = iovlen; + + msg->msg_flags = flags; + if (dontwait) { + msg->msg_flags |= MSG_DONTWAIT; + flags |= MSG_DONTWAIT; + } + + err = sock->ops->recvmsg(sock, msg, iovlen, flags); + + kfree(iov); +err_iov: + kfree(msg); +err_msg: + return err; +} + + +int lx_sock_sendmsg(struct socket *sock, struct lx_msghdr* lx_msg, + int flags, int dontwait) +{ + struct msghdr *msg; + struct iovec *iov; + size_t iovlen; + unsigned iov_count; + unsigned i; + + int err = -1; + + iov_count = lx_msg->msg_iovcount; + + msg = kzalloc(sizeof (struct msghdr), GFP_KERNEL); + if (!msg) + goto err_msg; + iov = kzalloc(sizeof (struct iovec) * iov_count, GFP_KERNEL); + if (!iov) + goto err_iov; + + iovlen = 0; + for (i = 0; i < iov_count; i++) { + iov[i].iov_base = lx_msg->msg_iov[i].iov_base; + iov[i].iov_len = lx_msg->msg_iov[i].iov_len; + + iovlen += lx_msg->msg_iov[i].iov_len; + } + + msg->msg_name = lx_msg->msg_name; + msg->msg_namelen = lx_msg->msg_namelen; + msg->msg_iter.iov = iov; + msg->msg_iter.nr_segs = iov_count; + msg->msg_iter.count = iovlen; + + msg->msg_flags = flags; + if (dontwait) + msg->msg_flags |= MSG_DONTWAIT; + + err = sock->ops->sendmsg(sock, msg, iovlen); + + kfree(iov); +err_iov: + kfree(msg); +err_msg: + return err; +} + + +int lx_sock_setsockopt(struct socket *sock, int level, int optname, + void const *optval, unsigned optlen) +{ + sockptr_t soptval = (sockptr_t) { .user = optval }; + + if (level == SOL_SOCKET) + return sock_setsockopt(sock, level, optname, + soptval, optlen); + + return sock->ops->setsockopt(sock, level, optname, + soptval, optlen); +} + + +unsigned char const* lx_get_mac_addr() +{ + static char mac_addr_buffer[16]; + + struct sockaddr addr; + int err; + size_t length; + + memset(mac_addr_buffer, 0, sizeof (mac_addr_buffer)); + memset(addr.sa_data, 0, sizeof (addr.sa_data)); + + err = dev_get_mac_address(&addr, &init_net, "wlan0"); + if (err) + return NULL; + + length = sizeof (mac_addr_buffer) < sizeof (addr.sa_data) + ? sizeof (mac_addr_buffer) + : sizeof (addr.sa_data); + memcpy(mac_addr_buffer, addr.sa_data, length); + + return mac_addr_buffer; +} + + +struct lx_poll_result lx_sock_poll(struct socket *sock) +{ + enum { + POLLIN_SET = (EPOLLRDHUP | EPOLLIN | EPOLLRDNORM), + POLLOUT_SET = (EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND), + POLLEX_SET = (EPOLLERR | EPOLLPRI) + }; + + // enum { + // POLLIN_SET = (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR) + // POLLOUT_SET = (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR) + // POLLEX_SET = (EPOLLPRI) + // }; + + int const mask = sock->ops->poll(0, sock, 0); + + struct lx_poll_result result = { false, false, false }; + + if (mask & POLLIN_SET) + result.in = true; + if (mask & POLLOUT_SET) + result.out = true; + if (mask & POLLEX_SET) + result.ex = true; + + return result; +} + + +int lx_sock_poll_wait(struct socket *socks[], unsigned num, int timeout) +{ + unsigned i; + unsigned long j; + signed long ex; + unsigned int to; + + enum { NUM_WQE = 8u, }; + struct wait_queue_entry sock_wqe[NUM_WQE]; + + /* should not happen as the number of sockets is capped by libnl */ + if ((unsigned)NUM_WQE < num) + printk("%s: more num: %d sockets than available" + "wait queue entries: %d\n", __func__, num, (unsigned)NUM_WQE); + + /* + * Add the appropriate wait queue entries and sleep afterwards + * for the requested timeout duration. Either a 'wake_up' call + * or the timeout will get us going again. + */ + + __set_current_state(TASK_INTERRUPTIBLE); + + for (i = 0; i < num; i++) { + struct socket *sock = socks[i]; + if (!sock) + continue; + + init_waitqueue_entry(&sock_wqe[i], current); + add_wait_queue(&(sock->sk->sk_wq->wait), &sock_wqe[i]); + } + + j = msecs_to_jiffies(timeout); + ex = schedule_timeout(j); + to = jiffies_to_msecs(ex); + + for (i = 0; i < num; i++) { + struct socket *sock = socks[i]; + if (!sock) + continue; + + remove_wait_queue(&(sock->sk->sk_wq->wait), &sock_wqe[i]); + } + + return (int)to; +} diff --git a/repos/pc/src/lib/wifi/lx_socket_call.h b/repos/pc/src/lib/wifi/lx_socket_call.h new file mode 100644 index 0000000000..2a343aa4bc --- /dev/null +++ b/repos/pc/src/lib/wifi/lx_socket_call.h @@ -0,0 +1,75 @@ +/* + * \brief Linux socket call interface back end + * \author Josef Soentgen + * \date 2022-02-17 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LX_SOCKET_CALL_H_ +#define _LX_SOCKET_CALL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct lx_iov +{ + void *iov_base; + unsigned long iov_len; +}; + +enum { MAX_IOV_LEN = 8 }; + + +struct lx_msghdr +{ + void *msg_name; + unsigned msg_namelen; + struct lx_iov msg_iov[MAX_IOV_LEN]; + unsigned msg_iovcount; + /* + * Omit total length covered by vector as it is + * calculated where needed. + */ + + void *msg_control; + unsigned msg_controllen; +}; + +struct socket; + +int lx_sock_create_kern(int domain, int type, int protocol, + struct socket **res); +int lx_sock_release(struct socket *sock); +int lx_sock_bind(struct socket *sock, void *sockaddr, int sockaddr_len); +int lx_sock_getname(struct socket *sock, void *sockaddr, int peer); +int lx_sock_recvmsg(struct socket *sock, struct lx_msghdr *lx_msg, + int flags, int dontwait); +int lx_sock_sendmsg(struct socket *socket, struct lx_msghdr* lx_msg, + int flags, int dontwait); +int lx_sock_setsockopt(struct socket *sock, int level, int optname, + void const *optval, unsigned optlen); +unsigned char const* lx_get_mac_addr(void); + +struct lx_poll_result +{ + int in; + int out; + int ex; +}; + +struct lx_poll_result lx_sock_poll(struct socket *sock); + +int lx_sock_poll_wait(struct socket *sock[], unsigned num, int timeout); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _LX_SOCKET_CALL_H_ */ diff --git a/repos/pc/src/lib/wifi/misc.cc b/repos/pc/src/lib/wifi/misc.cc new file mode 100644 index 0000000000..73f6e67174 --- /dev/null +++ b/repos/pc/src/lib/wifi/misc.cc @@ -0,0 +1,20 @@ +/* + * \brief Misc + * \author Josef Soentgen + * \date 2022-01-20 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include + +extern "C" void lx_backtrace(void) +{ + Genode::backtrace(); +} diff --git a/repos/pc/src/lib/wifi/random.cc b/repos/pc/src/lib/wifi/random.cc new file mode 100644 index 0000000000..cd8ee6bafe --- /dev/null +++ b/repos/pc/src/lib/wifi/random.cc @@ -0,0 +1,111 @@ +/* + * \brief Linux random emulation code + * \author Josef Soentgen + * \date 2016-10-19 + * + * For all intents and purposes this random back end should be treated + * as a gloryfied counter. + */ + +/* + * Copyright (C) 2016-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include + + +using Genode::uint64_t; + +/* + * Xoroshiro128+ written in 2014-2016 by Sebastiano Vigna (vigna@acm.org) + * + * (see http://xoroshiro.di.unimi.it/xorshift128plus.c and + * http://xoroshiro.di.unimi.it/splitmix64.c) + */ + +struct Xoroshiro +{ + uint64_t seed; + + uint64_t splitmix64() + { + uint64_t z = (seed += __UINT64_C(0x9E3779B97F4A7C15)); + z = (z ^ (z >> 30)) * __UINT64_C(0xBF58476D1CE4E5B9); + z = (z ^ (z >> 27)) * __UINT64_C(0x94D049BB133111EB); + return z ^ (z >> 31); + } + + Xoroshiro(uint64_t seed) : seed(seed) + { + s[0] = splitmix64(); + s[1] = splitmix64(); + } + + uint64_t s[2]; + + static uint64_t rotl(uint64_t const x, int k) { + return (x << k) | (x >> (64 - k)); + } + + uint64_t get() + { + uint64_t const s0 = s[0]; + uint64_t s1 = s[1]; + uint64_t const result = s0 + s1; + + s1 ^= s0; + + s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); + s[1] = rotl(s1, 36); + + return result; + } +}; + + +static Xoroshiro &xoroshiro() +{ + static Xoroshiro inst(0x636864324d766931); + return inst; +} + + +/******************** + ** linux/random.h ** + ********************/ + +extern "C" void lx_emul_get_random_bytes(void *buf, unsigned long nbytes) +{ + if (!buf || !nbytes) + return; + + char *p = reinterpret_cast(buf); + + unsigned long const rounds = nbytes / 8; + for (unsigned long i = 0; i < rounds; i++) { + uint64_t const v = xoroshiro().get(); + + Genode::memcpy(p, &v, 8); + p += 8; + } + + unsigned long const remain = nbytes - rounds * 8; + if (!remain) { + return; + } + + uint64_t const v = xoroshiro().get(); + Genode::memcpy(p, &v, remain); +} + + +extern "C" unsigned int lx_emul_get_random_u32(void) +{ + return (unsigned int)xoroshiro().get(); +} diff --git a/repos/pc/src/lib/wifi/socket_call.cc b/repos/pc/src/lib/wifi/socket_call.cc new file mode 100644 index 0000000000..10bc976073 --- /dev/null +++ b/repos/pc/src/lib/wifi/socket_call.cc @@ -0,0 +1,724 @@ + /* + * \brief Linux socket call interface front end + * \author Josef Soentgen + * \date 2014-08-04 + */ + +/* + * Copyright (C) 2014-2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include + +/* DDE Linux includes */ +#include +#include +#include + +/* local includes */ +#include "lx_socket_call.h" +#include "libc_errno.h" + +/* + * The values were taken from 'uapi/asm-generic/socket.h', + * 'uapi/linux/netlink.h' and 'linux/socket.h' and must be + * kept in sync. + */ +enum : int { + SOL_SOCKET = 1, + SOL_NETLINK = 270, + + SO_SNDBUF = 7, + SO_RCVBUF = 8, + SO_PASSCRED = 16, + SO_WIFI_STATUS = 41, + + NETLINK_ADD_MEMBERSHIP = 1, + NETLINK_DROP_MEMBERSHIP = 2, + NETLINK_PKTINFO = 3, + + MSG_DONTWAIT = 0x40, + MSG_ERRQUEUE = 0x2000, +}; + + +static int convert_errno_from_linux(int linux_errno) +{ + if (linux_errno >= 0) + return linux_errno; + + linux_errno *= -1; + + switch (linux_errno) { + case 0: return 0; + case E2BIG: return -(int)Libc::Errno::BSD_E2BIG; + case EACCES: return -(int)Libc::Errno::BSD_EACCES; + case EADDRINUSE: return -(int)Libc::Errno::BSD_EADDRINUSE; + case EADDRNOTAVAIL: return -(int)Libc::Errno::BSD_EADDRNOTAVAIL; + case EAFNOSUPPORT: return -(int)Libc::Errno::BSD_EAFNOSUPPORT; + case EAGAIN: return -(int)Libc::Errno::BSD_EAGAIN; + case EALREADY: return -(int)Libc::Errno::BSD_EALREADY; + case EBADF: return -(int)Libc::Errno::BSD_EBADF; + case EBADMSG: return -(int)Libc::Errno::BSD_EBADMSG; + case EBUSY: return -(int)Libc::Errno::BSD_EBUSY; + case ECANCELED: return -(int)Libc::Errno::BSD_ECANCELED; + case ECONNABORTED: return -(int)Libc::Errno::BSD_ECONNABORTED; + case ECONNREFUSED: return -(int)Libc::Errno::BSD_ECONNREFUSED; + case ECONNRESET: return -(int)Libc::Errno::BSD_ECONNRESET; + case EDEADLK: return -(int)Libc::Errno::BSD_EDEADLK; + case EDESTADDRREQ: return -(int)Libc::Errno::BSD_EDESTADDRREQ; + case EDOM: return -(int)Libc::Errno::BSD_EDOM; + case EEXIST: return -(int)Libc::Errno::BSD_EEXIST; + case EFAULT: return -(int)Libc::Errno::BSD_EFAULT; + case EFBIG: return -(int)Libc::Errno::BSD_EFBIG; + case EHOSTDOWN: return -(int)Libc::Errno::BSD_EHOSTDOWN; + case EHOSTUNREACH: return -(int)Libc::Errno::BSD_EHOSTUNREACH; + case EILSEQ: return -(int)Libc::Errno::BSD_EILSEQ; + case EINPROGRESS: return -(int)Libc::Errno::BSD_EINPROGRESS; + case EINTR: return -(int)Libc::Errno::BSD_EINTR; + case EINVAL: return -(int)Libc::Errno::BSD_EINVAL; + case EIO: return -(int)Libc::Errno::BSD_EIO; + case EISCONN: return -(int)Libc::Errno::BSD_EISCONN; + case EMSGSIZE: return -(int)Libc::Errno::BSD_EMSGSIZE; + case ENAMETOOLONG: return -(int)Libc::Errno::BSD_ENAMETOOLONG; + case ENETDOWN: return -(int)Libc::Errno::BSD_ENETDOWN; + case ENETUNREACH: return -(int)Libc::Errno::BSD_ENETUNREACH; + case ENFILE: return -(int)Libc::Errno::BSD_ENFILE; + case ENOBUFS: return -(int)Libc::Errno::BSD_ENOBUFS; + case ENODEV: return -(int)Libc::Errno::BSD_ENODEV; + case ENOENT: return -(int)Libc::Errno::BSD_ENOENT; + case ENOEXEC: return -(int)Libc::Errno::BSD_ENOEXEC; + case ENOLINK: + Genode::error("ENOLINK (", (int) ENOLINK, ") -> ", (int)Libc::Errno::BSD_ENOLINK); + return -(int)Libc::Errno::BSD_ENOLINK; + case ENOMEM: return -(int)Libc::Errno::BSD_ENOMEM; + case ENOMSG: return -(int)Libc::Errno::BSD_ENOMSG; + case ENOPROTOOPT: return -(int)Libc::Errno::BSD_ENOPROTOOPT; + case ENOSPC: return -(int)Libc::Errno::BSD_ENOSPC; + case ENOSYS: return -(int)Libc::Errno::BSD_ENOSYS; + case ENOTCONN: return -(int)Libc::Errno::BSD_ENOTCONN; + case ENOTSOCK: return -(int)Libc::Errno::BSD_ENOTSOCK; + case ENOTTY: return -(int)Libc::Errno::BSD_ENOTTY; + case ENXIO: return -(int)Libc::Errno::BSD_ENXIO; + case EOPNOTSUPP: return -(int)Libc::Errno::BSD_EOPNOTSUPP; + case EOVERFLOW: return -(int)Libc::Errno::BSD_EOVERFLOW; + case EPERM: return -(int)Libc::Errno::BSD_EPERM; + case EPFNOSUPPORT: return -(int)Libc::Errno::BSD_EPFNOSUPPORT; + case EPIPE: return -(int)Libc::Errno::BSD_EPIPE; + case EPROTO: return -(int)Libc::Errno::BSD_EPROTO; + case EPROTONOSUPPORT: return -(int)Libc::Errno::BSD_EPROTONOSUPPORT; + case ERANGE: return -(int)Libc::Errno::BSD_ERANGE; + case ESOCKTNOSUPPORT: return -(int)Libc::Errno::BSD_ESOCKTNOSUPPORT; + case ESPIPE: return -(int)Libc::Errno::BSD_ESPIPE; + case ESRCH: return -(int)Libc::Errno::BSD_ESRCH; + case ETIMEDOUT: return -(int)Libc::Errno::BSD_ETIMEDOUT; + case EXDEV: return -(int)Libc::Errno::BSD_EXDEV; + default: + Genode::error(__func__, ": unhandled errno ", linux_errno); + return linux_errno; + } +} + + +static_assert((unsigned)Wifi::Msghdr::MAX_IOV_LEN == (unsigned)MAX_IOV_LEN); + + +extern "C" struct task_struct *lx_socket_call_task; +extern "C" void *lx_socket_call_task_args; + + + +/* XXX move Wifi::Socket definition to better location */ +struct Wifi::Socket +{ + void *socket = nullptr; + bool non_block = false; + + Socket() { } + + explicit Socket(void *s) : socket(s) { } + + void print(Genode::Output &out) const + { + Genode::print(out, "this: ", this, " socket: ", socket, " non_block: ", non_block); + } +}; + + +struct Call +{ + enum Opcode { + NONE, SOCKET, CLOSE, + BIND, GETSOCKNAME, RECVMSG, SENDMSG, SENDTO, SETSOCKOPT, + GET_MAC_ADDRESS, POLL_ALL, NON_BLOCK, + }; + + Opcode opcode = NONE; + Wifi::Socket *handle = nullptr; + + union { + struct + { + int domain; + int type; + int protocol; + void *result; + } socket; + struct { /* no args */ } close; + struct + { + void const *addr; + int addrlen; + } bind; + struct + { + void *addr; + int *addrlen; + } getsockname; + struct + { + lx_msghdr msg; + int flags; + } recvmsg; + struct + { + lx_msghdr msg; + int flags; + } sendmsg; + struct { + int level; + int optname; + void const *optval; + unsigned optlen; + } setsockopt; + struct + { + unsigned char *addr; + unsigned int addr_len; + } get_mac_address; + struct + { + Wifi::Poll_socket_fd *sockets; + unsigned num; + int timeout; + } poll_all; + struct + { + bool value; + } non_block; + }; + + int err = 0; +}; + +static Call _call; +static Genode::Semaphore _block; + + +namespace Lx { + class Socket; +} + + + +/** + * Context for socket calls + */ +class Lx::Socket +{ + private: + + Socket(const Socket&) = delete; + Socket& operator=(const Socket&) = delete; + + Genode::Signal_transmitter _sender { }; + Genode::Signal_handler _dispatcher; + + struct socket *_sock_poll_table[Wifi::MAX_POLL_SOCKETS] { }; + + struct socket *_call_socket() + { + struct socket *sock = static_cast(_call.handle->socket); + if (!sock) + Genode::error("BUG: sock is zero"); + + return sock; + } + + void _do_socket() + { + struct socket *s; + int res = lx_sock_create_kern(_call.socket.domain, _call.socket.type, + _call.socket.protocol, &s); + if (!res) { + _call.socket.result = s; + _call.err = 0; + return; + } + + _call.socket.result = nullptr; + _call.err = res; + } + + void _do_close() + { + struct socket *sock = _call_socket(); + + _call.err = lx_sock_release(sock); + } + + void _do_bind() + { + struct socket *sock = _call_socket(); + + _call.err = lx_sock_bind(sock, + const_cast(_call.bind.addr), + _call.bind.addrlen); + } + + void _do_getsockname() + { + struct socket *sock = _call_socket(); + int addrlen = *_call.getsockname.addrlen; + + _call.err = lx_sock_getname(sock, _call.getsockname.addr, 0); + + *_call.getsockname.addrlen = addrlen; + } + + void _do_recvmsg() + { + struct socket *sock = _call_socket(); + + _call.err = lx_sock_recvmsg(sock, &_call.recvmsg.msg, + _call.recvmsg.flags, + _call.handle->non_block); + } + + void _do_sendmsg() + { + struct socket *sock = _call_socket(); + + _call.err = lx_sock_sendmsg(sock, &_call.sendmsg.msg, + _call.sendmsg.flags, + _call.handle->non_block); + } + + void _do_setsockopt() + { + struct socket *sock = _call_socket(); + + _call.err = lx_sock_setsockopt(sock, + _call.setsockopt.level, + _call.setsockopt.optname, + _call.setsockopt.optval, + _call.setsockopt.optlen); + } + + void _do_get_mac_address() + { + unsigned const char *addr = lx_get_mac_addr(); + if (!addr) + return; + + Genode::size_t const copy = 6 > _call.get_mac_address.addr_len + ? _call.get_mac_address.addr_len + : 6; + + Genode::memcpy(_call.get_mac_address.addr, addr, copy); + } + + void _do_poll_all() + { + Wifi::Poll_socket_fd *sockets = _call.poll_all.sockets; + unsigned num = _call.poll_all.num; + int timeout = _call.poll_all.timeout; + + int nready = 0; + bool timeout_triggered = false; + bool woken_up = false; + do { + /** + * Timeout was triggered, exit early. + */ + if (timeout_triggered) { + break; + } + + /** + * Poll each socket and check if there is something of interest. + */ + for (unsigned i = 0; i < num; i++) { + struct socket *sock = static_cast(sockets[i].s->socket); + + struct lx_poll_result result = lx_sock_poll(sock); + + sockets[i].revents = 0; + if (result.in) + sockets[i].revents |= sockets[i].events & Wifi::WIFI_POLLIN ? Wifi::WIFI_POLLIN : 0; + if (result.out) + sockets[i].revents |= sockets[i].events & Wifi::WIFI_POLLOUT ? Wifi::WIFI_POLLOUT : 0; + if (result.ex) + sockets[i].revents |= sockets[i].events & Wifi::WIFI_POLLEX ? Wifi::WIFI_POLLEX : 0; + + if (sockets[i].revents) + nready++; + } + + /** + * We were woken up but there is still nothing of interest. + */ + if (woken_up) { + break; + } + + /** + * Exit the loop if either a socket is ready or there is + * no timeout given. + */ + if (nready || !timeout) { + break; + } + + /** + * In case of a timeout add all sockets to an artificial wait list + * so at least one is woken up an sk_data_ready() call. + */ + for (unsigned i = 0; i < num; i++) { + struct socket *sock = static_cast(sockets[i].s->socket); + _sock_poll_table[i] = sock; + } + + timeout_triggered = !lx_sock_poll_wait(_sock_poll_table, num, timeout); + + woken_up = true; + } while (1); + + _call.err = nready; + } + + void _do_non_block() + { + _call.handle->non_block = _call.non_block.value; + } + + void _handle() + { + lx_emul_task_unblock(lx_socket_call_task); + Lx_kit::env().scheduler.schedule(); + } + + public: + + Socket(Genode::Entrypoint &ep) + : + _dispatcher(ep, *this, &Lx::Socket::_handle) + { + _sender.context(_dispatcher); + } + + void exec_call() + { + switch (_call.opcode) { + case Call::BIND: _do_bind(); break; + case Call::CLOSE: _do_close(); break; + case Call::GETSOCKNAME: _do_getsockname(); break; + case Call::POLL_ALL: _do_poll_all(); break; + case Call::RECVMSG: _do_recvmsg(); break; + case Call::SENDMSG: _do_sendmsg(); break; + case Call::SETSOCKOPT: _do_setsockopt(); break; + case Call::SOCKET: _do_socket(); break; + case Call::GET_MAC_ADDRESS: _do_get_mac_address(); break; + case Call::NON_BLOCK: _do_non_block(); break; + + case Call::NONE: [[fallthrough]];/* ignore silently */ + default: + _call.err = -1; + break; + } + + /* + * Save old call opcode as we may only release the blocker + * when actually did something useful, i.e., were called by + * some socket operation and not by kicking the socket. + */ + Call::Opcode old = _call.opcode; + + _call.opcode = Call::NONE; + + if (old != Call::NONE) { _block.up(); } + } + + void submit_and_block() + { + _sender.submit(); + _block.down(); + } +}; + + +static Lx::Socket *_socket; + + +extern Genode::Blockade *wpa_blockade; +extern "C" void uplink_init(void); + +extern "C" int run_lx_socket_call_task(void *) +{ + static Lx::Socket inst(Lx_kit::env().env.ep()); + _socket = &inst; + + uplink_init(); + wpa_blockade->wakeup(); + + while (true) { + + _socket->exec_call(); + + lx_emul_task_schedule(true); + } +} + + +void wifi_kick_socketcall() +{ + /* ignore silently, the function might be called to before init */ + if (!_socket) { return; } + + lx_emul_task_unblock(lx_socket_call_task); + Lx_kit::env().scheduler.schedule(); +} + + +/************************** + ** Socket_call instance ** + **************************/ + +Wifi::Socket_call socket_call; + + +/*************************** + ** Socket_call interface ** + ***************************/ + +using namespace Wifi; + + +Wifi::Socket *Socket_call::socket(int domain, int type, int protocol) +{ + /* FIXME domain, type, protocol values */ + _call.opcode = Call::SOCKET; + _call.socket.domain = domain; + _call.socket.type = type & 0xff; + _call.socket.protocol = protocol; + + _socket->submit_and_block(); + + if (_call.socket.result == 0) + return 0; + + Wifi::Socket *s = new (Lx_kit::env().heap) Wifi::Socket(_call.socket.result); + + return s; +} + + +int Socket_call::close(Socket *s) +{ + _call.opcode = Call::CLOSE; + _call.handle = s; + + _socket->submit_and_block(); + + if (_call.err) + Genode::warning("closing socket failed: ", _call.err); + + destroy(Lx_kit::env().heap, s); + return _call.err; +} + + +int Socket_call::bind(Socket *s, Wifi::Sockaddr const *addr, unsigned addrlen) +{ + /* FIXME convert to/from Sockaddr */ + _call.opcode = Call::BIND; + _call.handle = s; + _call.bind.addr = (void const *)addr; + _call.bind.addrlen = addrlen; + + _socket->submit_and_block(); + + return convert_errno_from_linux(_call.err); +} + + +int Socket_call::getsockname(Socket *s, Wifi::Sockaddr *addr, unsigned *addrlen) +{ + /* FIXME convert to/from Sockaddr */ + /* FIXME unsigned * -> int * */ + _call.opcode = Call::GETSOCKNAME; + _call.handle = s; + _call.getsockname.addr = (void *)addr; + _call.getsockname.addrlen = (int *)addrlen; + + _socket->submit_and_block(); + + return convert_errno_from_linux(_call.err); +} + + +int Socket_call::poll_all(Poll_socket_fd *s, unsigned num, int timeout) +{ + _call.opcode = Call::POLL_ALL; + _call.handle = 0; + _call.poll_all.sockets = s; + _call.poll_all.num = num; + _call.poll_all.timeout = timeout; + + _socket->submit_and_block(); + + return convert_errno_from_linux(_call.err); +} + + +static inline int msg_flags(Wifi::Flags in) +{ + int out = Wifi::WIFI_F_NONE; + if (in & Wifi::WIFI_F_MSG_ERRQUEUE) + out |= MSG_ERRQUEUE; + if (in & Wifi::WIFI_F_MSG_DONTWAIT) { + out |= MSG_DONTWAIT; + } + + return out; +}; + + +Wifi::ssize_t Socket_call::recvmsg(Socket *s, Wifi::Msghdr *msg, Wifi::Flags flags) +{ + _call.opcode = Call::RECVMSG; + _call.handle = s; + _call.recvmsg.msg.msg_name = msg->msg_name; + _call.recvmsg.msg.msg_namelen = msg->msg_namelen; + _call.recvmsg.msg.msg_iovcount = msg->msg_iovlen; + + _call.recvmsg.msg.msg_control = msg->msg_control; + _call.recvmsg.msg.msg_controllen = msg->msg_controllen; + _call.recvmsg.flags = msg_flags(flags); + + for (unsigned i = 0; i < msg->msg_iovlen; ++i) { + _call.recvmsg.msg.msg_iov[i].iov_base = msg->msg_iov[i].iov_base; + _call.recvmsg.msg.msg_iov[i].iov_len = msg->msg_iov[i].iov_len; + } + + _socket->submit_and_block(); + + msg->msg_namelen = _call.recvmsg.msg.msg_namelen; + + return convert_errno_from_linux(_call.err); +} + + +Wifi::ssize_t Socket_call::sendmsg(Socket *s, Wifi::Msghdr const *msg, Wifi::Flags flags) +{ + _call.opcode = Call::SENDMSG; + _call.handle = s; + _call.sendmsg.msg.msg_name = msg->msg_name; + _call.sendmsg.msg.msg_namelen = msg->msg_namelen; + _call.sendmsg.msg.msg_iovcount = msg->msg_iovlen; + + _call.sendmsg.msg.msg_control = 0; + _call.sendmsg.msg.msg_controllen = 0; + _call.sendmsg.flags = msg_flags(flags); + + for (unsigned i = 0; i < msg->msg_iovlen; ++i) { + _call.sendmsg.msg.msg_iov[i].iov_base = msg->msg_iov[i].iov_base; + _call.sendmsg.msg.msg_iov[i].iov_len = msg->msg_iov[i].iov_len; + } + + _socket->submit_and_block(); + + return convert_errno_from_linux(_call.err); +} + + +static int sockopt_level(Sockopt_level const in) +{ + switch (in) { + case Wifi::WIFI_SOL_SOCKET: return SOL_SOCKET; + case Wifi::WIFI_SOL_NETLINK: return SOL_NETLINK; + } + + return -1; +} + + +static int sockopt_name(Sockopt_level const level, Sockopt_name const in) +{ + switch (level) { + case Wifi::WIFI_SOL_SOCKET: + switch (in) { + case Wifi::WIFI_SO_SNDBUF: return SO_SNDBUF; + case Wifi::WIFI_SO_RCVBUF: return SO_RCVBUF; + case Wifi::WIFI_SO_PASSCRED: return SO_PASSCRED; + case Wifi::WIFI_SO_WIFI_STATUS: return SO_WIFI_STATUS; + + default: return -1; + } + case Wifi::WIFI_SOL_NETLINK: + switch (in) { + case Wifi::WIFI_NETLINK_ADD_MEMBERSHIP: return NETLINK_ADD_MEMBERSHIP; + case Wifi::WIFI_NETLINK_DROP_MEMBERSHIP: return NETLINK_DROP_MEMBERSHIP; + case Wifi::WIFI_NETLINK_PKTINFO: return NETLINK_PKTINFO; + + default: return -1; + } + } + + return -1; +} + + +int Socket_call::setsockopt(Socket *s, + Wifi::Sockopt_level level, Wifi::Sockopt_name optname, + const void *optval, unsigned optlen) +{ + /* FIXME optval values */ + _call.opcode = Call::SETSOCKOPT; + _call.handle = s; + _call.setsockopt.level = sockopt_level(level); + _call.setsockopt.optname = sockopt_name(level, optname); + _call.setsockopt.optval = optval; + _call.setsockopt.optlen = optlen; + + _socket->submit_and_block(); + + return convert_errno_from_linux(_call.err); +} + + +void Socket_call::non_block(Socket *s, bool value) +{ + _call.opcode = Call::NON_BLOCK; + _call.handle = s; + _call.non_block.value = value; + + _socket->submit_and_block(); +} + + +void Socket_call::get_mac_address(unsigned char *addr) +{ + _call.opcode = Call::GET_MAC_ADDRESS; + _call.handle = 0; + _call.get_mac_address.addr = addr; + _call.get_mac_address.addr_len = 6; // XXX enforce and set from caller + + _socket->submit_and_block(); +} diff --git a/repos/pc/src/lib/wifi/spec/x86_32/source.list b/repos/pc/src/lib/wifi/spec/x86_32/source.list new file mode 100644 index 0000000000..4b8da6c6b2 --- /dev/null +++ b/repos/pc/src/lib/wifi/spec/x86_32/source.list @@ -0,0 +1,273 @@ +arch/x86/pci/legacy.c +drivers/base/bus.c +drivers/base/class.c +drivers/base/component.c +drivers/base/core.c +drivers/base/dd.c +drivers/base/devres.c +drivers/base/driver.c +drivers/base/platform.c +drivers/base/property.c +drivers/clk/clk-devres.c +drivers/pci/access.c +drivers/pci/bus.c +drivers/pci/host-bridge.c +drivers/pci/msi.c +drivers/pci/pci.c +drivers/pci/pci-driver.c +drivers/pci/pci-sysfs.c +drivers/pci/probe.c +drivers/pci/rom.c +drivers/pci/search.c +drivers/pci/setup-res.c +drivers/pci/slot.c +fs/nls/nls_base.c +kernel/irq/chip.c +kernel/irq/devres.c +kernel/irq/handle.c +kernel/irq/irqdesc.c +kernel/irq/irqdomain.c +kernel/irq/manage.c +kernel/irq/resend.c +kernel/kthread.c +kernel/locking/mutex.c +kernel/locking/osq_lock.c +kernel/locking/rwsem.c +kernel/notifier.c +kernel/panic.c +kernel/resource.c +kernel/sched/clock.c +kernel/sched/completion.c +kernel/sched/swait.c +kernel/sched/wait.c +kernel/smpboot.c +kernel/time/clockevents.c +kernel/time/clocksource.c +kernel/time/hrtimer.c +kernel/time/jiffies.c +kernel/time/ntp.c +kernel/time/tick-common.c +kernel/time/time.c +kernel/time/timeconv.c +kernel/time/timecounter.c +kernel/time/timekeeping.c +kernel/time/timer.c +kernel/time/timer_list.c +kernel/workqueue.c +lib/bitmap.c +lib/crc32.c +lib/ctype.c +lib/debug_locks.c +lib/find_bit.c +lib/hexdump.c +lib/idr.c +lib/irq_regs.c +lib/kasprintf.c +lib/klist.c +lib/kobject.c +lib/kstrtox.c +lib/list_sort.c +lib/iomap.c +lib/math/div64.c +lib/pci_iomap.c +lib/radix-tree.c +lib/rbtree.c +lib/refcount.c +lib/scatterlist.c +lib/siphash.c +lib/sort.c +lib/string.c +lib/timerqueue.c +lib/vsprintf.c +lib/xarray.c +mm/mempool.c +mm/util.c + +certs/common.c +crypto/acompress.c +crypto/aead.c +crypto/aes_generic.c +crypto/ahash.c +crypto/akcipher.c +crypto/algapi.c +crypto/algboss.c +crypto/api.c +crypto/ccm.c +crypto/cipher.c +crypto/cmac.c +crypto/compress.c +crypto/crypto_null.c +crypto/ctr.c +crypto/gcm.c +crypto/geniv.c +crypto/gf128mul.c +crypto/ghash-generic.c +crypto/hash_info.c +crypto/kpp.c +crypto/memneq.c +crypto/proc.c +crypto/rng.c +crypto/scatterwalk.c +crypto/scompress.c +crypto/sha256_generic.c +crypto/shash.c +crypto/skcipher.c +crypto/testmgr.c +drivers/net/Space.c +drivers/net/loopback.c +drivers/net/wireless/intel/iwlwifi/cfg/1000.c +drivers/net/wireless/intel/iwlwifi/cfg/2000.c +drivers/net/wireless/intel/iwlwifi/cfg/22000.c +drivers/net/wireless/intel/iwlwifi/cfg/5000.c +drivers/net/wireless/intel/iwlwifi/cfg/6000.c +drivers/net/wireless/intel/iwlwifi/cfg/7000.c +drivers/net/wireless/intel/iwlwifi/cfg/8000.c +drivers/net/wireless/intel/iwlwifi/cfg/9000.c +drivers/net/wireless/intel/iwlwifi/dvm/calib.c +drivers/net/wireless/intel/iwlwifi/dvm/devices.c +drivers/net/wireless/intel/iwlwifi/dvm/lib.c +drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +drivers/net/wireless/intel/iwlwifi/dvm/main.c +drivers/net/wireless/intel/iwlwifi/dvm/power.c +drivers/net/wireless/intel/iwlwifi/dvm/rs.c +drivers/net/wireless/intel/iwlwifi/dvm/rx.c +drivers/net/wireless/intel/iwlwifi/dvm/rxon.c +drivers/net/wireless/intel/iwlwifi/dvm/scan.c +drivers/net/wireless/intel/iwlwifi/dvm/sta.c +drivers/net/wireless/intel/iwlwifi/dvm/tt.c +drivers/net/wireless/intel/iwlwifi/dvm/tx.c +drivers/net/wireless/intel/iwlwifi/dvm/ucode.c +drivers/net/wireless/intel/iwlwifi/fw/acpi.c +drivers/net/wireless/intel/iwlwifi/fw/dbg.c +drivers/net/wireless/intel/iwlwifi/fw/dump.c +drivers/net/wireless/intel/iwlwifi/fw/img.c +drivers/net/wireless/intel/iwlwifi/fw/init.c +drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c +drivers/net/wireless/intel/iwlwifi/fw/paging.c +drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +drivers/net/wireless/intel/iwlwifi/fw/smem.c +drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +drivers/net/wireless/intel/iwlwifi/iwl-debug.c +drivers/net/wireless/intel/iwlwifi/iwl-drv.c +drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c +drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c +drivers/net/wireless/intel/iwlwifi/iwl-io.c +drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c +drivers/net/wireless/intel/iwlwifi/iwl-trans.c +drivers/net/wireless/intel/iwlwifi/mvm/binding.c +drivers/net/wireless/intel/iwlwifi/mvm/coex.c +drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +drivers/net/wireless/intel/iwlwifi/mvm/fw.c +drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +drivers/net/wireless/intel/iwlwifi/mvm/offloading.c +drivers/net/wireless/intel/iwlwifi/mvm/ops.c +drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +drivers/net/wireless/intel/iwlwifi/mvm/power.c +drivers/net/wireless/intel/iwlwifi/mvm/quota.c +drivers/net/wireless/intel/iwlwifi/mvm/rfi.c +drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +drivers/net/wireless/intel/iwlwifi/mvm/rs.c +drivers/net/wireless/intel/iwlwifi/mvm/rx.c +drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +drivers/net/wireless/intel/iwlwifi/mvm/scan.c +drivers/net/wireless/intel/iwlwifi/mvm/sf.c +drivers/net/wireless/intel/iwlwifi/mvm/sta.c +drivers/net/wireless/intel/iwlwifi/mvm/tdls.c +drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +drivers/net/wireless/intel/iwlwifi/mvm/tt.c +drivers/net/wireless/intel/iwlwifi/mvm/tx.c +drivers/net/wireless/intel/iwlwifi/mvm/utils.c +drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +drivers/net/wireless/intel/iwlwifi/pcie/drv.c +drivers/net/wireless/intel/iwlwifi/pcie/rx.c +drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +drivers/net/wireless/intel/iwlwifi/pcie/trans.c +drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +drivers/net/wireless/intel/iwlwifi/pcie/tx.c +drivers/net/wireless/intel/iwlwifi/queue/tx.c +lib/asn1_decoder.c +lib/bsearch.c +lib/crypto/aes.c +lib/dynamic_queue_limits.c +lib/hweight.c +lib/nlattr.c +lib/rhashtable.c +net/core/datagram.c +net/core/dev.c +net/core/dev_addr_lists.c +net/core/link_watch.c +net/core/net-sysfs.c +net/core/net_namespace.c +net/core/rtnetlink.c +net/core/skbuff.c +net/core/sock.c +net/core/xdp.c +net/ethernet/eth.c +net/ethtool/common.c +net/socket.c +net/sched/sch_generic.c +net/sched/sch_mq.c +net/mac80211/aead_api.c +net/mac80211/aes_cmac.c +net/mac80211/aes_gmac.c +net/mac80211/agg-rx.c +net/mac80211/agg-tx.c +net/mac80211/airtime.c +net/mac80211/cfg.c +net/mac80211/chan.c +net/mac80211/driver-ops.c +net/mac80211/ethtool.c +net/mac80211/fils_aead.c +net/mac80211/he.c +net/mac80211/ht.c +net/mac80211/ibss.c +net/mac80211/iface.c +net/mac80211/key.c +net/mac80211/main.c +net/mac80211/michael.c +net/mac80211/mlme.c +net/mac80211/ocb.c +net/mac80211/offchannel.c +net/mac80211/rate.c +net/mac80211/rc80211_minstrel_ht.c +net/mac80211/rx.c +net/mac80211/s1g.c +net/mac80211/scan.c +net/mac80211/spectmgmt.c +net/mac80211/sta_info.c +net/mac80211/status.c +net/mac80211/tdls.c +net/mac80211/tkip.c +net/mac80211/trace.c +net/mac80211/tx.c +net/mac80211/util.c +net/mac80211/vht.c +net/mac80211/wep.c +net/mac80211/wme.c +net/mac80211/wpa.c +net/netlink/af_netlink.c +net/netlink/genetlink.c +net/netlink/policy.c +net/packet/af_packet.c +net/wireless/ap.c +net/wireless/chan.c +net/wireless/core.c +net/wireless/ethtool.c +net/wireless/ibss.c +net/wireless/mesh.c +net/wireless/mlme.c +net/wireless/nl80211.c +net/wireless/ocb.c +net/wireless/pmsr.c +net/wireless/radiotap.c +net/wireless/reg.c +net/wireless/scan.c +net/wireless/sme.c +net/wireless/sysfs.c +net/wireless/trace.c +net/wireless/util.c diff --git a/repos/pc/src/lib/wifi/spec/x86_64/dep.list b/repos/pc/src/lib/wifi/spec/x86_64/dep.list new file mode 100644 index 0000000000..7c716ea0e3 --- /dev/null +++ b/repos/pc/src/lib/wifi/spec/x86_64/dep.list @@ -0,0 +1,1290 @@ +arch/x86/include/asm/acenv.h +arch/x86/include/asm/acpi.h +arch/x86/include/asm/alternative.h +arch/x86/include/asm/apicdef.h +arch/x86/include/asm/arch_hweight.h +arch/x86/include/asm/asm.h +arch/x86/include/asm/atomic.h +arch/x86/include/asm/atomic64_64.h +arch/x86/include/asm/barrier.h +arch/x86/include/asm/bitops.h +arch/x86/include/asm/bug.h +arch/x86/include/asm/cache.h +arch/x86/include/asm/cacheflush.h +arch/x86/include/asm/checksum.h +arch/x86/include/asm/checksum_64.h +arch/x86/include/asm/clocksource.h +arch/x86/include/asm/cmpxchg.h +arch/x86/include/asm/cmpxchg_64.h +arch/x86/include/asm/compat.h +arch/x86/include/asm/cpu_entry_area.h +arch/x86/include/asm/cpufeatures.h +arch/x86/include/asm/cpumask.h +arch/x86/include/asm/delay.h +arch/x86/include/asm/desc.h +arch/x86/include/asm/desc_defs.h +arch/x86/include/asm/device.h +arch/x86/include/asm/disabled-features.h +arch/x86/include/asm/div64.h +arch/x86/include/asm/dma.h +arch/x86/include/asm/elf.h +arch/x86/include/asm/emergency-restart.h +arch/x86/include/asm/exec.h +arch/x86/include/asm/extable.h +arch/x86/include/asm/fixmap.h +arch/x86/include/asm/fpu/api.h +arch/x86/include/asm/fpu/types.h +arch/x86/include/asm/fsgsbase.h +arch/x86/include/asm/ftrace.h +arch/x86/include/asm/hardirq.h +arch/x86/include/asm/hw_breakpoint.h +arch/x86/include/asm/hw_irq.h +arch/x86/include/asm/intel_ds.h +arch/x86/include/asm/invpcid.h +arch/x86/include/asm/irq.h +arch/x86/include/asm/irq_vectors.h +arch/x86/include/asm/irq_work.h +arch/x86/include/asm/irqdomain.h +arch/x86/include/asm/ist.h +arch/x86/include/asm/jailhouse_para.h +arch/x86/include/asm/kaslr.h +arch/x86/include/asm/kdebug.h +arch/x86/include/asm/kgdb.h +arch/x86/include/asm/kprobes.h +arch/x86/include/asm/kvm_para.h +arch/x86/include/asm/linkage.h +arch/x86/include/asm/local.h +arch/x86/include/asm/math_emu.h +arch/x86/include/asm/mem_encrypt.h +arch/x86/include/asm/memtype.h +arch/x86/include/asm/mmu.h +arch/x86/include/asm/mmu_context.h +arch/x86/include/asm/module.h +arch/x86/include/asm/mpspec.h +arch/x86/include/asm/mpspec_def.h +arch/x86/include/asm/msi.h +arch/x86/include/asm/msr-index.h +arch/x86/include/asm/msr.h +arch/x86/include/asm/nmi.h +arch/x86/include/asm/nops.h +arch/x86/include/asm/numa.h +arch/x86/include/asm/orc_types.h +arch/x86/include/asm/page_64_types.h +arch/x86/include/asm/page_types.h +arch/x86/include/asm/paravirt.h +arch/x86/include/asm/pci.h +arch/x86/include/asm/pci_x86.h +arch/x86/include/asm/percpu.h +arch/x86/include/asm/perf_event.h +arch/x86/include/asm/pgtable_64_types.h +arch/x86/include/asm/pgtable_areas.h +arch/x86/include/asm/pgtable_types.h +arch/x86/include/asm/posix_types.h +arch/x86/include/asm/preempt.h +arch/x86/include/asm/processor-flags.h +arch/x86/include/asm/processor.h +arch/x86/include/asm/proto.h +arch/x86/include/asm/pti.h +arch/x86/include/asm/ptrace.h +arch/x86/include/asm/required-features.h +arch/x86/include/asm/rmwcc.h +arch/x86/include/asm/segment.h +arch/x86/include/asm/set_memory.h +arch/x86/include/asm/shmparam.h +arch/x86/include/asm/signal.h +arch/x86/include/asm/smap.h +arch/x86/include/asm/smp.h +arch/x86/include/asm/sparsemem.h +arch/x86/include/asm/stacktrace.h +arch/x86/include/asm/static_call.h +arch/x86/include/asm/string.h +arch/x86/include/asm/string_64.h +arch/x86/include/asm/syscall_wrapper.h +arch/x86/include/asm/text-patching.h +arch/x86/include/asm/thread_info.h +arch/x86/include/asm/timex.h +arch/x86/include/asm/tlb.h +arch/x86/include/asm/tlbbatch.h +arch/x86/include/asm/tlbflush.h +arch/x86/include/asm/topology.h +arch/x86/include/asm/trace_clock.h +arch/x86/include/asm/tsc.h +arch/x86/include/asm/uaccess.h +arch/x86/include/asm/unistd.h +arch/x86/include/asm/unwind_hints.h +arch/x86/include/asm/user.h +arch/x86/include/asm/user32.h +arch/x86/include/asm/user_64.h +arch/x86/include/asm/vdso.h +arch/x86/include/asm/vdso/clocksource.h +arch/x86/include/asm/vdso/processor.h +arch/x86/include/asm/vga.h +arch/x86/include/asm/vmalloc.h +arch/x86/include/asm/vmxfeatures.h +arch/x86/include/asm/word-at-a-time.h +arch/x86/include/asm/x86_init.h +arch/x86/include/uapi/asm/auxvec.h +arch/x86/include/uapi/asm/bitsperlong.h +arch/x86/include/uapi/asm/bootparam.h +arch/x86/include/uapi/asm/byteorder.h +arch/x86/include/uapi/asm/hw_breakpoint.h +arch/x86/include/uapi/asm/ist.h +arch/x86/include/uapi/asm/kvm_para.h +arch/x86/include/uapi/asm/ldt.h +arch/x86/include/uapi/asm/mman.h +arch/x86/include/uapi/asm/msr.h +arch/x86/include/uapi/asm/perf_regs.h +arch/x86/include/uapi/asm/posix_types_64.h +arch/x86/include/uapi/asm/processor-flags.h +arch/x86/include/uapi/asm/ptrace-abi.h +arch/x86/include/uapi/asm/ptrace.h +arch/x86/include/uapi/asm/sembuf.h +arch/x86/include/uapi/asm/shmbuf.h +arch/x86/include/uapi/asm/sigcontext.h +arch/x86/include/uapi/asm/siginfo.h +arch/x86/include/uapi/asm/signal.h +arch/x86/include/uapi/asm/stat.h +arch/x86/include/uapi/asm/swab.h +arch/x86/include/uapi/asm/unistd.h +arch/x86/include/uapi/asm/vsyscall.h +certs/common.h +crypto/internal.h +drivers/base/base.h +drivers/base/power/power.h +drivers/base/trace.h +drivers/net/wireless/intel/iwlwifi/dvm/agn.h +drivers/net/wireless/intel/iwlwifi/dvm/calib.h +drivers/net/wireless/intel/iwlwifi/dvm/commands.h +drivers/net/wireless/intel/iwlwifi/dvm/dev.h +drivers/net/wireless/intel/iwlwifi/dvm/led.h +drivers/net/wireless/intel/iwlwifi/dvm/power.h +drivers/net/wireless/intel/iwlwifi/dvm/rs.h +drivers/net/wireless/intel/iwlwifi/dvm/tt.h +drivers/net/wireless/intel/iwlwifi/fw/acpi.h +drivers/net/wireless/intel/iwlwifi/fw/api/alive.h +drivers/net/wireless/intel/iwlwifi/fw/api/binding.h +drivers/net/wireless/intel/iwlwifi/fw/api/cmdhdr.h +drivers/net/wireless/intel/iwlwifi/fw/api/coex.h +drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +drivers/net/wireless/intel/iwlwifi/fw/api/config.h +drivers/net/wireless/intel/iwlwifi/fw/api/context.h +drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +drivers/net/wireless/intel/iwlwifi/fw/api/filter.h +drivers/net/wireless/intel/iwlwifi/fw/api/led.h +drivers/net/wireless/intel/iwlwifi/fw/api/location.h +drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +drivers/net/wireless/intel/iwlwifi/fw/api/paging.h +drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h +drivers/net/wireless/intel/iwlwifi/fw/api/phy.h +drivers/net/wireless/intel/iwlwifi/fw/api/power.h +drivers/net/wireless/intel/iwlwifi/fw/api/rfi.h +drivers/net/wireless/intel/iwlwifi/fw/api/rs.h +drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +drivers/net/wireless/intel/iwlwifi/fw/api/sf.h +drivers/net/wireless/intel/iwlwifi/fw/api/soc.h +drivers/net/wireless/intel/iwlwifi/fw/api/sta.h +drivers/net/wireless/intel/iwlwifi/fw/api/stats.h +drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h +drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h +drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +drivers/net/wireless/intel/iwlwifi/fw/api/txq.h +drivers/net/wireless/intel/iwlwifi/fw/dbg.h +drivers/net/wireless/intel/iwlwifi/fw/debugfs.h +drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +drivers/net/wireless/intel/iwlwifi/fw/file.h +drivers/net/wireless/intel/iwlwifi/fw/img.h +drivers/net/wireless/intel/iwlwifi/fw/notif-wait.h +drivers/net/wireless/intel/iwlwifi/fw/pnvm.h +drivers/net/wireless/intel/iwlwifi/fw/runtime.h +drivers/net/wireless/intel/iwlwifi/fw/uefi.h +drivers/net/wireless/intel/iwlwifi/iwl-agn-hw.h +drivers/net/wireless/intel/iwlwifi/iwl-config.h +drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +drivers/net/wireless/intel/iwlwifi/iwl-context-info.h +drivers/net/wireless/intel/iwlwifi/iwl-csr.h +drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h +drivers/net/wireless/intel/iwlwifi/iwl-debug.h +drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h +drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h +drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h +drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h +drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h +drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h +drivers/net/wireless/intel/iwlwifi/iwl-drv.h +drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h +drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.h +drivers/net/wireless/intel/iwlwifi/iwl-fh.h +drivers/net/wireless/intel/iwlwifi/iwl-io.h +drivers/net/wireless/intel/iwlwifi/iwl-modparams.h +drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h +drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h +drivers/net/wireless/intel/iwlwifi/iwl-phy-db.h +drivers/net/wireless/intel/iwlwifi/iwl-prph.h +drivers/net/wireless/intel/iwlwifi/iwl-scd.h +drivers/net/wireless/intel/iwlwifi/iwl-trans.h +drivers/net/wireless/intel/iwlwifi/mvm/constants.h +drivers/net/wireless/intel/iwlwifi/mvm/debugfs.h +drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +drivers/net/wireless/intel/iwlwifi/mvm/rs.h +drivers/net/wireless/intel/iwlwifi/mvm/sta.h +drivers/net/wireless/intel/iwlwifi/mvm/testmode.h +drivers/net/wireless/intel/iwlwifi/mvm/time-event.h +drivers/net/wireless/intel/iwlwifi/pcie/internal.h +drivers/net/wireless/intel/iwlwifi/queue/tx.h +drivers/pci/pci.h +drivers/pci/pcie/portdrv.h +include/acpi/acbuffer.h +include/acpi/acconfig.h +include/acpi/acexcep.h +include/acpi/acnames.h +include/acpi/acoutput.h +include/acpi/acpi.h +include/acpi/acpi_bus.h +include/acpi/acpi_drivers.h +include/acpi/acpi_io.h +include/acpi/acpi_numa.h +include/acpi/acpiosxf.h +include/acpi/acpixf.h +include/acpi/acrestyp.h +include/acpi/actbl.h +include/acpi/actbl1.h +include/acpi/actbl2.h +include/acpi/actbl3.h +include/acpi/actypes.h +include/acpi/pdc_intel.h +include/acpi/platform/acenv.h +include/acpi/platform/acenvex.h +include/acpi/platform/acgcc.h +include/acpi/platform/acgccex.h +include/acpi/platform/aclinux.h +include/acpi/platform/aclinuxex.h +include/asm-generic/atomic-instrumented.h +include/asm-generic/atomic-long.h +include/asm-generic/barrier.h +include/asm-generic/bitops/const_hweight.h +include/asm-generic/bitops/ext2-atomic-setbit.h +include/asm-generic/bitops/find.h +include/asm-generic/bitops/instrumented-atomic.h +include/asm-generic/bitops/instrumented-lock.h +include/asm-generic/bitops/instrumented-non-atomic.h +include/asm-generic/bitops/le.h +include/asm-generic/bitops/sched.h +include/asm-generic/bitsperlong.h +include/asm-generic/bug.h +include/asm-generic/cacheflush.h +include/asm-generic/compat.h +include/asm-generic/delay.h +include/asm-generic/div64.h +include/asm-generic/early_ioremap.h +include/asm-generic/error-injection.h +include/asm-generic/fixmap.h +include/asm-generic/getorder.h +include/asm-generic/int-ll64.h +include/asm-generic/io.h +include/asm-generic/ioctl.h +include/asm-generic/iomap.h +include/asm-generic/irq_regs.h +include/asm-generic/kmap_size.h +include/asm-generic/kprobes.h +include/asm-generic/local64.h +include/asm-generic/logic_io.h +include/asm-generic/mmiowb.h +include/asm-generic/mmu_context.h +include/asm-generic/module.h +include/asm-generic/param.h +include/asm-generic/pci.h +include/asm-generic/pci_iomap.h +include/asm-generic/percpu.h +include/asm-generic/pgtable-nop4d.h +include/asm-generic/resource.h +include/asm-generic/rwonce.h +include/asm-generic/sections.h +include/asm-generic/set_memory.h +include/asm-generic/termios.h +include/asm-generic/tlb.h +include/asm-generic/topology.h +include/asm-generic/unaligned.h +include/crypto/acompress.h +include/crypto/aead.h +include/crypto/aes.h +include/crypto/akcipher.h +include/crypto/algapi.h +include/crypto/arc4.h +include/crypto/b128ops.h +include/crypto/ctr.h +include/crypto/drbg.h +include/crypto/gcm.h +include/crypto/gf128mul.h +include/crypto/ghash.h +include/crypto/hash.h +include/crypto/hash_info.h +include/crypto/internal/acompress.h +include/crypto/internal/aead.h +include/crypto/internal/akcipher.h +include/crypto/internal/cipher.h +include/crypto/internal/geniv.h +include/crypto/internal/hash.h +include/crypto/internal/kpp.h +include/crypto/internal/rng.h +include/crypto/internal/scompress.h +include/crypto/internal/simd.h +include/crypto/internal/skcipher.h +include/crypto/kpp.h +include/crypto/md5.h +include/crypto/null.h +include/crypto/rng.h +include/crypto/scatterwalk.h +include/crypto/sha1.h +include/crypto/sha2.h +include/crypto/sha256_base.h +include/crypto/skcipher.h +include/crypto/streebog.h +include/dt-bindings/leds/common.h +include/linux/acpi.h +include/linux/acpi_iort.h +include/linux/aer.h +include/linux/alarmtimer.h +include/linux/align.h +include/linux/apm_bios.h +include/linux/arch_topology.h +include/linux/asn1.h +include/linux/asn1_ber_bytecode.h +include/linux/asn1_decoder.h +include/linux/assoc_array.h +include/linux/async.h +include/linux/atomic-arch-fallback.h +include/linux/atomic.h +include/linux/audit.h +include/linux/auxvec.h +include/linux/average.h +include/linux/backing-dev-defs.h +include/linux/binfmts.h +include/linux/bio.h +include/linux/bit_spinlock.h +include/linux/bitfield.h +include/linux/bitmap.h +include/linux/bitops.h +include/linux/bitrev.h +include/linux/bits.h +include/linux/blk-cgroup.h +include/linux/blk_types.h +include/linux/blkdev.h +include/linux/bottom_half.h +include/linux/bpf-cgroup.h +include/linux/bpf-netns.h +include/linux/bpf.h +include/linux/bpf_local_storage.h +include/linux/bpf_trace.h +include/linux/bpfptr.h +include/linux/bsearch.h +include/linux/bsg.h +include/linux/btf_ids.h +include/linux/bug.h +include/linux/build_bug.h +include/linux/buildid.h +include/linux/bvec.h +include/linux/byteorder/generic.h +include/linux/byteorder/little_endian.h +include/linux/cache.h +include/linux/capability.h +include/linux/cc_platform.h +include/linux/cdev.h +include/linux/cfi.h +include/linux/cgroup-defs.h +include/linux/cgroup.h +include/linux/clk-provider.h +include/linux/clk.h +include/linux/clk/clk-conf.h +include/linux/clockchips.h +include/linux/clocksource.h +include/linux/clocksource_ids.h +include/linux/compat.h +include/linux/compiler-gcc.h +include/linux/compiler.h +include/linux/compiler_attributes.h +include/linux/compiler_types.h +include/linux/completion.h +include/linux/component.h +include/linux/console.h +include/linux/console_struct.h +include/linux/consolemap.h +include/linux/const.h +include/linux/context_tracking.h +include/linux/context_tracking_state.h +include/linux/cookie.h +include/linux/cpu.h +include/linux/cpu_rmap.h +include/linux/cpufreq.h +include/linux/cpuhotplug.h +include/linux/cpuidle.h +include/linux/cpumask.h +include/linux/cpuset.h +include/linux/crash_core.h +include/linux/crash_dump.h +include/linux/crc32.h +include/linux/crc32poly.h +include/linux/cred.h +include/linux/crypto.h +include/linux/ctype.h +include/linux/dax.h +include/linux/dcache.h +include/linux/debug_locks.h +include/linux/debugfs.h +include/linux/debugobjects.h +include/linux/delay.h +include/linux/delayacct.h +include/linux/delayed_call.h +include/linux/dev_printk.h +include/linux/devcoredump.h +include/linux/device.h +include/linux/device/bus.h +include/linux/device/class.h +include/linux/device/driver.h +include/linux/dma-direction.h +include/linux/dma-map-ops.h +include/linux/dma-mapping.h +include/linux/dmaengine.h +include/linux/dmapool.h +include/linux/dmi.h +include/linux/dqblk_qtree.h +include/linux/dqblk_v1.h +include/linux/dqblk_v2.h +include/linux/dynamic_debug.h +include/linux/dynamic_queue_limits.h +include/linux/edd.h +include/linux/elevator.h +include/linux/elf-randomize.h +include/linux/elf.h +include/linux/elfcore.h +include/linux/energy_model.h +include/linux/err.h +include/linux/errname.h +include/linux/errno.h +include/linux/error-injection.h +include/linux/errqueue.h +include/linux/errseq.h +include/linux/etherdevice.h +include/linux/ethtool.h +include/linux/ethtool_netlink.h +include/linux/eventfd.h +include/linux/export.h +include/linux/fault-inject-usercopy.h +include/linux/fault-inject.h +include/linux/fcntl.h +include/linux/file.h +include/linux/filter.h +include/linux/fips.h +include/linux/firmware.h +include/linux/flex_proportions.h +include/linux/freelist.h +include/linux/freezer.h +include/linux/fs.h +include/linux/fs_context.h +include/linux/fs_types.h +include/linux/ftrace.h +include/linux/ftrace_irq.h +include/linux/fwnode.h +include/linux/gcd.h +include/linux/genetlink.h +include/linux/genhd.h +include/linux/gfp.h +include/linux/gpio/consumer.h +include/linux/hardirq.h +include/linux/hash.h +include/linux/hashtable.h +include/linux/highmem-internal.h +include/linux/highmem.h +include/linux/highuid.h +include/linux/hrtimer.h +include/linux/hrtimer_defs.h +include/linux/huge_mm.h +include/linux/hugetlb.h +include/linux/hugetlb_inline.h +include/linux/hypervisor.h +include/linux/icmpv6.h +include/linux/idr.h +include/linux/ieee80211.h +include/linux/if_arp.h +include/linux/if_bridge.h +include/linux/if_ether.h +include/linux/if_link.h +include/linux/if_macvlan.h +include/linux/if_tun.h +include/linux/if_tunnel.h +include/linux/if_vlan.h +include/linux/in.h +include/linux/in6.h +include/linux/indirect_call_wrapper.h +include/linux/inet.h +include/linux/inetdevice.h +include/linux/init.h +include/linux/init_task.h +include/linux/instrumentation.h +include/linux/instrumented.h +include/linux/interrupt.h +include/linux/interval_tree.h +include/linux/io.h +include/linux/iocontext.h +include/linux/iopoll.h +include/linux/ioport.h +include/linux/ioprio.h +include/linux/ip.h +include/linux/ipc.h +include/linux/ipv6.h +include/linux/ipv6_route.h +include/linux/irq.h +include/linux/irq_work.h +include/linux/irqchip.h +include/linux/irqdesc.h +include/linux/irqdomain.h +include/linux/irqflags.h +include/linux/irqhandler.h +include/linux/irqnr.h +include/linux/irqreturn.h +include/linux/jhash.h +include/linux/jiffies.h +include/linux/jump_label.h +include/linux/jump_label_ratelimit.h +include/linux/kallsyms.h +include/linux/kasan-checks.h +include/linux/kasan.h +include/linux/kconfig.h +include/linux/kcov.h +include/linux/kcsan-checks.h +include/linux/kcsan.h +include/linux/kdebug.h +include/linux/kdev_t.h +include/linux/kern_levels.h +include/linux/kernel.h +include/linux/kernel_read_file.h +include/linux/kernel_stat.h +include/linux/kernfs.h +include/linux/kexec.h +include/linux/key.h +include/linux/kgdb.h +include/linux/klist.h +include/linux/kmemleak.h +include/linux/kmod.h +include/linux/kmsg_dump.h +include/linux/kobject.h +include/linux/kobject_ns.h +include/linux/kprobes.h +include/linux/kref.h +include/linux/kstrtox.h +include/linux/kthread.h +include/linux/ktime.h +include/linux/kvm_para.h +include/linux/latencytop.h +include/linux/leds.h +include/linux/limits.h +include/linux/linkage.h +include/linux/linkmode.h +include/linux/list.h +include/linux/list_bl.h +include/linux/list_lru.h +include/linux/list_nulls.h +include/linux/list_sort.h +include/linux/livepatch.h +include/linux/llist.h +include/linux/local_lock.h +include/linux/local_lock_internal.h +include/linux/lockdep.h +include/linux/lockdep_types.h +include/linux/lockref.h +include/linux/log2.h +include/linux/logic_pio.h +include/linux/math.h +include/linux/math64.h +include/linux/mdio.h +include/linux/mem_encrypt.h +include/linux/memblock.h +include/linux/memcontrol.h +include/linux/memory_hotplug.h +include/linux/mempolicy.h +include/linux/mempool.h +include/linux/memremap.h +include/linux/migrate.h +include/linux/migrate_mode.h +include/linux/mii.h +include/linux/mii_timestamper.h +include/linux/minmax.h +include/linux/mm.h +include/linux/mm_types.h +include/linux/mm_types_task.h +include/linux/mman.h +include/linux/mmap_lock.h +include/linux/mmdebug.h +include/linux/mmu_context.h +include/linux/mmu_notifier.h +include/linux/mmzone.h +include/linux/mod_devicetable.h +include/linux/module.h +include/linux/moduleparam.h +include/linux/mount.h +include/linux/mpls.h +include/linux/msi.h +include/linux/mutex.h +include/linux/net.h +include/linux/netdev_features.h +include/linux/netdevice.h +include/linux/netfilter.h +include/linux/netfilter_defs.h +include/linux/netfilter_ingress.h +include/linux/netlink.h +include/linux/netpoll.h +include/linux/nfs_fs_i.h +include/linux/nls.h +include/linux/nmi.h +include/linux/node.h +include/linux/nodemask.h +include/linux/nospec.h +include/linux/notifier.h +include/linux/ns_common.h +include/linux/nsproxy.h +include/linux/numa.h +include/linux/nvmem-consumer.h +include/linux/nvmem-provider.h +include/linux/objtool.h +include/linux/of.h +include/linux/of_address.h +include/linux/of_clk.h +include/linux/of_device.h +include/linux/of_fdt.h +include/linux/of_graph.h +include/linux/of_irq.h +include/linux/of_net.h +include/linux/of_pci.h +include/linux/of_platform.h +include/linux/once.h +include/linux/once_lite.h +include/linux/osq_lock.h +include/linux/overflow.h +include/linux/page-flags-layout.h +include/linux/page-flags.h +include/linux/page_counter.h +include/linux/page_ext.h +include/linux/page_ref.h +include/linux/pageblock-flags.h +include/linux/pagemap.h +include/linux/panic.h +include/linux/panic_notifier.h +include/linux/path.h +include/linux/pci-dma-compat.h +include/linux/pci.h +include/linux/pci_hotplug.h +include/linux/pci_ids.h +include/linux/percpu-defs.h +include/linux/percpu-refcount.h +include/linux/percpu-rwsem.h +include/linux/percpu.h +include/linux/percpu_counter.h +include/linux/perf_event.h +include/linux/perf_regs.h +include/linux/personality.h +include/linux/pfn.h +include/linux/phy.h +include/linux/phylink.h +include/linux/pid.h +include/linux/pid_namespace.h +include/linux/pinctrl/devinfo.h +include/linux/pipe_fs_i.h +include/linux/pkeys.h +include/linux/platform_data/dsa.h +include/linux/platform_device.h +include/linux/plist.h +include/linux/pm.h +include/linux/pm_domain.h +include/linux/pm_qos.h +include/linux/pm_runtime.h +include/linux/pm_wakeup.h +include/linux/poison.h +include/linux/poll.h +include/linux/posix-timers.h +include/linux/pps_kernel.h +include/linux/prandom.h +include/linux/preempt.h +include/linux/prefetch.h +include/linux/printk.h +include/linux/proc_fs.h +include/linux/proc_ns.h +include/linux/processor.h +include/linux/profile.h +include/linux/projid.h +include/linux/property.h +include/linux/pseudo_fs.h +include/linux/psi.h +include/linux/psi_types.h +include/linux/ptp_classify.h +include/linux/ptp_clock_kernel.h +include/linux/ptr_ring.h +include/linux/ptrace.h +include/linux/pvclock_gtod.h +include/linux/quota.h +include/linux/radix-tree.h +include/linux/random.h +include/linux/range.h +include/linux/ratelimit.h +include/linux/ratelimit_types.h +include/linux/rbtree.h +include/linux/rbtree_augmented.h +include/linux/rbtree_latch.h +include/linux/rcu_segcblist.h +include/linux/rcu_sync.h +include/linux/rculist.h +include/linux/rculist_bl.h +include/linux/rculist_nulls.h +include/linux/rcupdate.h +include/linux/rcupdate_wait.h +include/linux/rcutiny.h +include/linux/rcuwait.h +include/linux/reboot.h +include/linux/refcount.h +include/linux/resource.h +include/linux/resource_ext.h +include/linux/restart_block.h +include/linux/rfkill.h +include/linux/rhashtable-types.h +include/linux/rhashtable.h +include/linux/ring_buffer.h +include/linux/rtc.h +include/linux/rtnetlink.h +include/linux/rwlock.h +include/linux/rwlock_types.h +include/linux/rwsem.h +include/linux/sbitmap.h +include/linux/scatterlist.h +include/linux/sched.h +include/linux/sched/autogroup.h +include/linux/sched/clock.h +include/linux/sched/coredump.h +include/linux/sched/cpufreq.h +include/linux/sched/cputime.h +include/linux/sched/deadline.h +include/linux/sched/debug.h +include/linux/sched/hotplug.h +include/linux/sched/idle.h +include/linux/sched/init.h +include/linux/sched/isolation.h +include/linux/sched/jobctl.h +include/linux/sched/loadavg.h +include/linux/sched/mm.h +include/linux/sched/nohz.h +include/linux/sched/numa_balancing.h +include/linux/sched/prio.h +include/linux/sched/rt.h +include/linux/sched/signal.h +include/linux/sched/smt.h +include/linux/sched/stat.h +include/linux/sched/sysctl.h +include/linux/sched/task.h +include/linux/sched/task_stack.h +include/linux/sched/topology.h +include/linux/sched/types.h +include/linux/sched/user.h +include/linux/sched/wake_q.h +include/linux/sched/xacct.h +include/linux/sched_clock.h +include/linux/screen_info.h +include/linux/sctp.h +include/linux/seccomp.h +include/linux/securebits.h +include/linux/security.h +include/linux/sem.h +include/linux/semaphore.h +include/linux/seq_buf.h +include/linux/seq_file.h +include/linux/seq_file_net.h +include/linux/seqlock.h +include/linux/set_memory.h +include/linux/shm.h +include/linux/shrinker.h +include/linux/signal.h +include/linux/signal_types.h +include/linux/siphash.h +include/linux/sizes.h +include/linux/skb_array.h +include/linux/skbuff.h +include/linux/slab.h +include/linux/smp.h +include/linux/smp_types.h +include/linux/smpboot.h +include/linux/sock_diag.h +include/linux/socket.h +include/linux/sockptr.h +include/linux/sort.h +include/linux/spinlock.h +include/linux/spinlock_api_up.h +include/linux/spinlock_types.h +include/linux/spinlock_types_up.h +include/linux/spinlock_up.h +include/linux/splice.h +include/linux/srcu.h +include/linux/srcutiny.h +include/linux/stackdepot.h +include/linux/stacktrace.h +include/linux/stat.h +include/linux/static_call.h +include/linux/static_call_types.h +include/linux/static_key.h +include/linux/stddef.h +include/linux/stop_machine.h +include/linux/string.h +include/linux/string_helpers.h +include/linux/stringhash.h +include/linux/stringify.h +include/linux/suspend.h +include/linux/swab.h +include/linux/swait.h +include/linux/swap.h +include/linux/sync_core.h +include/linux/syscall_user_dispatch.h +include/linux/syscalls.h +include/linux/syscore_ops.h +include/linux/sysctl.h +include/linux/sysfs.h +include/linux/sysrq.h +include/linux/task_io_accounting.h +include/linux/task_work.h +include/linux/tcp.h +include/linux/textsearch.h +include/linux/thermal.h +include/linux/thread_info.h +include/linux/threads.h +include/linux/tick.h +include/linux/time.h +include/linux/time32.h +include/linux/time64.h +include/linux/timecounter.h +include/linux/timekeeper_internal.h +include/linux/timekeeping.h +include/linux/timer.h +include/linux/timerqueue.h +include/linux/timex.h +include/linux/topology.h +include/linux/trace.h +include/linux/trace_clock.h +include/linux/trace_events.h +include/linux/trace_recursion.h +include/linux/trace_seq.h +include/linux/tracepoint-defs.h +include/linux/tracepoint.h +include/linux/tsacct_kern.h +include/linux/tty.h +include/linux/tty_driver.h +include/linux/tty_ldisc.h +include/linux/typecheck.h +include/linux/types.h +include/linux/u64_stats_sync.h +include/linux/uaccess.h +include/linux/udp.h +include/linux/uidgid.h +include/linux/uio.h +include/linux/umh.h +include/linux/unaligned/packed_struct.h +include/linux/units.h +include/linux/uprobes.h +include/linux/user.h +include/linux/user_namespace.h +include/linux/userfaultfd_k.h +include/linux/utsname.h +include/linux/uuid.h +include/linux/verification.h +include/linux/vgaarb.h +include/linux/virtio.h +include/linux/virtio_byteorder.h +include/linux/virtio_config.h +include/linux/virtio_net.h +include/linux/vm_event_item.h +include/linux/vmalloc.h +include/linux/vmpressure.h +include/linux/vmstat.h +include/linux/vt.h +include/linux/vt_kern.h +include/linux/vtime.h +include/linux/wait.h +include/linux/wait_bit.h +include/linux/win_minmax.h +include/linux/wireless.h +include/linux/workqueue.h +include/linux/writeback.h +include/linux/ww_mutex.h +include/linux/xarray.h +include/linux/xattr.h +include/net/Space.h +include/net/act_api.h +include/net/addrconf.h +include/net/arp.h +include/net/bpf_sk_storage.h +include/net/busy_poll.h +include/net/cfg80211-wext.h +include/net/cfg80211.h +include/net/checksum.h +include/net/cls_cgroup.h +include/net/codel.h +include/net/codel_impl.h +include/net/compat.h +include/net/devlink.h +include/net/dsa.h +include/net/dsfield.h +include/net/dst.h +include/net/dst_cache.h +include/net/dst_metadata.h +include/net/dst_ops.h +include/net/fib_notifier.h +include/net/fib_rules.h +include/net/flow.h +include/net/flow_dissector.h +include/net/flow_offload.h +include/net/fq.h +include/net/fq_impl.h +include/net/gen_stats.h +include/net/genetlink.h +include/net/gro.h +include/net/gro_cells.h +include/net/ieee80211_radiotap.h +include/net/if_inet6.h +include/net/inet_connection_sock.h +include/net/inet_ecn.h +include/net/inet_frag.h +include/net/inet_hashtables.h +include/net/inet_sock.h +include/net/inet_timewait_sock.h +include/net/inetpeer.h +include/net/ip.h +include/net/ip6_checksum.h +include/net/ip6_fib.h +include/net/ip_fib.h +include/net/ip_tunnels.h +include/net/ipv6.h +include/net/ipv6_stubs.h +include/net/iw_handler.h +include/net/l3mdev.h +include/net/lwtunnel.h +include/net/mac80211.h +include/net/mpls.h +include/net/mptcp.h +include/net/ndisc.h +include/net/neighbour.h +include/net/net_namespace.h +include/net/netlink.h +include/net/netns/bpf.h +include/net/netns/can.h +include/net/netns/core.h +include/net/netns/generic.h +include/net/netns/hash.h +include/net/netns/ieee802154_6lowpan.h +include/net/netns/ipv4.h +include/net/netns/ipv6.h +include/net/netns/mib.h +include/net/netns/mpls.h +include/net/netns/netfilter.h +include/net/netns/nexthop.h +include/net/netns/nftables.h +include/net/netns/packet.h +include/net/netns/sctp.h +include/net/netns/smc.h +include/net/netns/unix.h +include/net/netns/x_tables.h +include/net/netns/xdp.h +include/net/netns/xfrm.h +include/net/netprio_cgroup.h +include/net/page_pool.h +include/net/pkt_cls.h +include/net/pkt_sched.h +include/net/protocol.h +include/net/regulatory.h +include/net/request_sock.h +include/net/route.h +include/net/rtnetlink.h +include/net/sch_generic.h +include/net/scm.h +include/net/snmp.h +include/net/sock.h +include/net/sock_reuseport.h +include/net/switchdev.h +include/net/tcp.h +include/net/tcp_states.h +include/net/timewait_sock.h +include/net/tso.h +include/net/udp.h +include/net/udp_tunnel.h +include/net/wext.h +include/net/xdp.h +include/net/xdp_priv.h +include/net/xdp_sock.h +include/net/xdp_sock_drv.h +include/net/xfrm.h +include/net/xsk_buff_pool.h +include/trace/define_trace.h +include/trace/events/irq.h +include/trace/events/napi.h +include/trace/events/net.h +include/trace/events/netlink.h +include/trace/events/power.h +include/trace/events/qdisc.h +include/trace/events/sched.h +include/trace/events/skb.h +include/trace/events/sock.h +include/trace/events/timer.h +include/trace/events/tlb.h +include/trace/events/workqueue.h +include/trace/events/xdp.h +include/trace/syscall.h +include/uapi/asm-generic/bitsperlong.h +include/uapi/asm-generic/bpf_perf_event.h +include/uapi/asm-generic/errno-base.h +include/uapi/asm-generic/errno.h +include/uapi/asm-generic/fcntl.h +include/uapi/asm-generic/hugetlb_encode.h +include/uapi/asm-generic/int-ll64.h +include/uapi/asm-generic/ioctl.h +include/uapi/asm-generic/ioctls.h +include/uapi/asm-generic/ipcbuf.h +include/uapi/asm-generic/mman-common.h +include/uapi/asm-generic/mman.h +include/uapi/asm-generic/param.h +include/uapi/asm-generic/poll.h +include/uapi/asm-generic/posix_types.h +include/uapi/asm-generic/resource.h +include/uapi/asm-generic/shmbuf.h +include/uapi/asm-generic/siginfo.h +include/uapi/asm-generic/signal-defs.h +include/uapi/asm-generic/socket.h +include/uapi/asm-generic/sockios.h +include/uapi/asm-generic/termbits.h +include/uapi/asm-generic/termios.h +include/uapi/asm-generic/types.h +include/uapi/linux/aio_abi.h +include/uapi/linux/apm_bios.h +include/uapi/linux/audit.h +include/uapi/linux/auxvec.h +include/uapi/linux/binfmts.h +include/uapi/linux/blkzoned.h +include/uapi/linux/bpf.h +include/uapi/linux/bpf_common.h +include/uapi/linux/bpf_perf_event.h +include/uapi/linux/bsg.h +include/uapi/linux/btf.h +include/uapi/linux/byteorder/little_endian.h +include/uapi/linux/capability.h +include/uapi/linux/cgroupstats.h +include/uapi/linux/const.h +include/uapi/linux/cryptouser.h +include/uapi/linux/devlink.h +include/uapi/linux/dqblk_xfs.h +include/uapi/linux/edd.h +include/uapi/linux/elf-em.h +include/uapi/linux/elf.h +include/uapi/linux/errno.h +include/uapi/linux/errqueue.h +include/uapi/linux/ethtool.h +include/uapi/linux/ethtool_netlink.h +include/uapi/linux/eventpoll.h +include/uapi/linux/fcntl.h +include/uapi/linux/fib_rules.h +include/uapi/linux/filter.h +include/uapi/linux/fs.h +include/uapi/linux/gen_stats.h +include/uapi/linux/genetlink.h +include/uapi/linux/hash_info.h +include/uapi/linux/hdlc/ioctl.h +include/uapi/linux/icmpv6.h +include/uapi/linux/if.h +include/uapi/linux/if_addr.h +include/uapi/linux/if_arp.h +include/uapi/linux/if_bonding.h +include/uapi/linux/if_bridge.h +include/uapi/linux/if_ether.h +include/uapi/linux/if_link.h +include/uapi/linux/if_packet.h +include/uapi/linux/if_tun.h +include/uapi/linux/if_tunnel.h +include/uapi/linux/if_vlan.h +include/uapi/linux/if_xdp.h +include/uapi/linux/in.h +include/uapi/linux/in6.h +include/uapi/linux/in_route.h +include/uapi/linux/ioctl.h +include/uapi/linux/ip.h +include/uapi/linux/ipc.h +include/uapi/linux/ipsec.h +include/uapi/linux/ipv6.h +include/uapi/linux/ipv6_route.h +include/uapi/linux/irqnr.h +include/uapi/linux/kcov.h +include/uapi/linux/kd.h +include/uapi/linux/kdev_t.h +include/uapi/linux/kernel.h +include/uapi/linux/kexec.h +include/uapi/linux/kvm_para.h +include/uapi/linux/libc-compat.h +include/uapi/linux/limits.h +include/uapi/linux/lwtunnel.h +include/uapi/linux/magic.h +include/uapi/linux/major.h +include/uapi/linux/mdio.h +include/uapi/linux/membarrier.h +include/uapi/linux/mempolicy.h +include/uapi/linux/mii.h +include/uapi/linux/mman.h +include/uapi/linux/mpls.h +include/uapi/linux/neighbour.h +include/uapi/linux/net.h +include/uapi/linux/net_namespace.h +include/uapi/linux/net_tstamp.h +include/uapi/linux/netdevice.h +include/uapi/linux/netfilter.h +include/uapi/linux/netfilter/nf_tables.h +include/uapi/linux/netlink.h +include/uapi/linux/nl80211.h +include/uapi/linux/openat2.h +include/uapi/linux/param.h +include/uapi/linux/pci.h +include/uapi/linux/pci_regs.h +include/uapi/linux/perf_event.h +include/uapi/linux/personality.h +include/uapi/linux/pfkeyv2.h +include/uapi/linux/pkt_cls.h +include/uapi/linux/pkt_sched.h +include/uapi/linux/poll.h +include/uapi/linux/posix_types.h +include/uapi/linux/pps.h +include/uapi/linux/ptp_clock.h +include/uapi/linux/ptrace.h +include/uapi/linux/quota.h +include/uapi/linux/random.h +include/uapi/linux/reboot.h +include/uapi/linux/resource.h +include/uapi/linux/rfkill.h +include/uapi/linux/route.h +include/uapi/linux/rseq.h +include/uapi/linux/rtc.h +include/uapi/linux/rtnetlink.h +include/uapi/linux/sched.h +include/uapi/linux/sched/types.h +include/uapi/linux/screen_info.h +include/uapi/linux/sctp.h +include/uapi/linux/seccomp.h +include/uapi/linux/securebits.h +include/uapi/linux/sem.h +include/uapi/linux/shm.h +include/uapi/linux/signal.h +include/uapi/linux/snmp.h +include/uapi/linux/sock_diag.h +include/uapi/linux/socket.h +include/uapi/linux/sockios.h +include/uapi/linux/stat.h +include/uapi/linux/stddef.h +include/uapi/linux/string.h +include/uapi/linux/swab.h +include/uapi/linux/sysctl.h +include/uapi/linux/sysinfo.h +include/uapi/linux/taskstats.h +include/uapi/linux/tcp.h +include/uapi/linux/termios.h +include/uapi/linux/thermal.h +include/uapi/linux/time.h +include/uapi/linux/time_types.h +include/uapi/linux/timex.h +include/uapi/linux/tty.h +include/uapi/linux/tty_flags.h +include/uapi/linux/types.h +include/uapi/linux/udp.h +include/uapi/linux/uio.h +include/uapi/linux/un.h +include/uapi/linux/unistd.h +include/uapi/linux/utsname.h +include/uapi/linux/uuid.h +include/uapi/linux/virtio_config.h +include/uapi/linux/virtio_ids.h +include/uapi/linux/virtio_net.h +include/uapi/linux/virtio_types.h +include/uapi/linux/vmcore.h +include/uapi/linux/vt.h +include/uapi/linux/wait.h +include/uapi/linux/wireless.h +include/uapi/linux/xattr.h +include/uapi/linux/xfrm.h +include/uapi/video/edid.h +include/vdso/bits.h +include/vdso/clocksource.h +include/vdso/const.h +include/vdso/jiffies.h +include/vdso/ktime.h +include/vdso/limits.h +include/vdso/math64.h +include/vdso/time.h +include/vdso/time32.h +include/vdso/time64.h +include/video/edid.h +include/video/vga.h +kernel/irq/debug.h +kernel/irq/internals.h +kernel/irq/settings.h +kernel/locking/lock_events.h +kernel/locking/lock_events_list.h +kernel/locking/mutex.h +kernel/sched/autogroup.h +kernel/sched/cpudeadline.h +kernel/sched/cpupri.h +kernel/sched/features.h +kernel/sched/sched.h +kernel/sched/stats.h +kernel/smpboot.h +kernel/time/ntp_internal.h +kernel/time/tick-internal.h +kernel/time/tick-sched.h +kernel/time/timekeeping.h +kernel/time/timekeeping_internal.h +kernel/workqueue_internal.h +lib/crc32defs.h +lib/kstrtox.h +mm/internal.h +mm/slab.h +net/core/datagram.h +net/core/net-sysfs.h +net/ethtool/common.h +net/mac80211/aead_api.h +net/mac80211/aes_ccm.h +net/mac80211/aes_cmac.h +net/mac80211/aes_gcm.h +net/mac80211/aes_gmac.h +net/mac80211/debug.h +net/mac80211/debugfs.h +net/mac80211/debugfs_key.h +net/mac80211/debugfs_netdev.h +net/mac80211/debugfs_sta.h +net/mac80211/driver-ops.h +net/mac80211/fils_aead.h +net/mac80211/ieee80211_i.h +net/mac80211/key.h +net/mac80211/led.h +net/mac80211/mesh.h +net/mac80211/michael.h +net/mac80211/rate.h +net/mac80211/rc80211_minstrel_ht.h +net/mac80211/sta_info.h +net/mac80211/tkip.h +net/mac80211/trace.h +net/mac80211/trace_msg.h +net/mac80211/wep.h +net/mac80211/wme.h +net/mac80211/wpa.h +net/netlink/af_netlink.h +net/packet/internal.h +net/wireless/core.h +net/wireless/debugfs.h +net/wireless/nl80211.h +net/wireless/rdev-ops.h +net/wireless/reg.h +net/wireless/sysfs.h +net/wireless/trace.h +net/wireless/wext-compat.h diff --git a/repos/pc/src/lib/wifi/spec/x86_64/source.list b/repos/pc/src/lib/wifi/spec/x86_64/source.list new file mode 100644 index 0000000000..97ee7ef1ca --- /dev/null +++ b/repos/pc/src/lib/wifi/spec/x86_64/source.list @@ -0,0 +1,273 @@ +arch/x86/pci/legacy.c +drivers/base/bus.c +drivers/base/class.c +drivers/base/component.c +drivers/base/core.c +drivers/base/dd.c +drivers/base/devres.c +drivers/base/driver.c +drivers/base/platform.c +drivers/base/property.c +drivers/clk/clk-devres.c +drivers/pci/access.c +drivers/pci/bus.c +drivers/pci/host-bridge.c +drivers/pci/msi.c +drivers/pci/pci.c +drivers/pci/pci-driver.c +drivers/pci/pci-sysfs.c +drivers/pci/probe.c +drivers/pci/rom.c +drivers/pci/search.c +drivers/pci/setup-res.c +drivers/pci/slot.c +fs/nls/nls_base.c +kernel/irq/chip.c +kernel/irq/devres.c +kernel/irq/handle.c +kernel/irq/irqdesc.c +kernel/irq/irqdomain.c +kernel/irq/manage.c +kernel/irq/resend.c +kernel/kthread.c +kernel/locking/mutex.c +kernel/locking/osq_lock.c +kernel/locking/rwsem.c +kernel/notifier.c +kernel/panic.c +kernel/resource.c +kernel/sched/clock.c +kernel/sched/completion.c +kernel/sched/swait.c +kernel/sched/wait.c +kernel/smpboot.c +kernel/time/clockevents.c +kernel/time/clocksource.c +kernel/time/hrtimer.c +kernel/time/jiffies.c +kernel/time/ntp.c +kernel/time/tick-broadcast.c +kernel/time/tick-common.c +kernel/time/time.c +kernel/time/timeconv.c +kernel/time/timecounter.c +kernel/time/timekeeping.c +kernel/time/timer.c +kernel/time/timer_list.c +kernel/workqueue.c +lib/bitmap.c +lib/crc32.c +lib/ctype.c +lib/debug_locks.c +lib/find_bit.c +lib/hexdump.c +lib/idr.c +lib/irq_regs.c +lib/kasprintf.c +lib/klist.c +lib/kobject.c +lib/kstrtox.c +lib/list_sort.c +lib/iomap.c +lib/pci_iomap.c +lib/radix-tree.c +lib/rbtree.c +lib/refcount.c +lib/scatterlist.c +lib/siphash.c +lib/sort.c +lib/string.c +lib/timerqueue.c +lib/vsprintf.c +lib/xarray.c +mm/mempool.c +mm/util.c + +certs/common.c +crypto/acompress.c +crypto/aead.c +crypto/aes_generic.c +crypto/ahash.c +crypto/akcipher.c +crypto/algapi.c +crypto/algboss.c +crypto/api.c +crypto/ccm.c +crypto/cipher.c +crypto/cmac.c +crypto/compress.c +crypto/crypto_null.c +crypto/ctr.c +crypto/gcm.c +crypto/geniv.c +crypto/gf128mul.c +crypto/ghash-generic.c +crypto/hash_info.c +crypto/kpp.c +crypto/memneq.c +crypto/proc.c +crypto/rng.c +crypto/scatterwalk.c +crypto/scompress.c +crypto/sha256_generic.c +crypto/shash.c +crypto/skcipher.c +crypto/testmgr.c +drivers/net/Space.c +drivers/net/loopback.c +drivers/net/wireless/intel/iwlwifi/cfg/1000.c +drivers/net/wireless/intel/iwlwifi/cfg/2000.c +drivers/net/wireless/intel/iwlwifi/cfg/22000.c +drivers/net/wireless/intel/iwlwifi/cfg/5000.c +drivers/net/wireless/intel/iwlwifi/cfg/6000.c +drivers/net/wireless/intel/iwlwifi/cfg/7000.c +drivers/net/wireless/intel/iwlwifi/cfg/8000.c +drivers/net/wireless/intel/iwlwifi/cfg/9000.c +drivers/net/wireless/intel/iwlwifi/dvm/calib.c +drivers/net/wireless/intel/iwlwifi/dvm/devices.c +drivers/net/wireless/intel/iwlwifi/dvm/lib.c +drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +drivers/net/wireless/intel/iwlwifi/dvm/main.c +drivers/net/wireless/intel/iwlwifi/dvm/power.c +drivers/net/wireless/intel/iwlwifi/dvm/rs.c +drivers/net/wireless/intel/iwlwifi/dvm/rx.c +drivers/net/wireless/intel/iwlwifi/dvm/rxon.c +drivers/net/wireless/intel/iwlwifi/dvm/scan.c +drivers/net/wireless/intel/iwlwifi/dvm/sta.c +drivers/net/wireless/intel/iwlwifi/dvm/tt.c +drivers/net/wireless/intel/iwlwifi/dvm/tx.c +drivers/net/wireless/intel/iwlwifi/dvm/ucode.c +drivers/net/wireless/intel/iwlwifi/fw/acpi.c +drivers/net/wireless/intel/iwlwifi/fw/dbg.c +drivers/net/wireless/intel/iwlwifi/fw/dump.c +drivers/net/wireless/intel/iwlwifi/fw/img.c +drivers/net/wireless/intel/iwlwifi/fw/init.c +drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c +drivers/net/wireless/intel/iwlwifi/fw/paging.c +drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +drivers/net/wireless/intel/iwlwifi/fw/smem.c +drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +drivers/net/wireless/intel/iwlwifi/iwl-debug.c +drivers/net/wireless/intel/iwlwifi/iwl-drv.c +drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c +drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c +drivers/net/wireless/intel/iwlwifi/iwl-io.c +drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c +drivers/net/wireless/intel/iwlwifi/iwl-trans.c +drivers/net/wireless/intel/iwlwifi/mvm/binding.c +drivers/net/wireless/intel/iwlwifi/mvm/coex.c +drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +drivers/net/wireless/intel/iwlwifi/mvm/fw.c +drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +drivers/net/wireless/intel/iwlwifi/mvm/offloading.c +drivers/net/wireless/intel/iwlwifi/mvm/ops.c +drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +drivers/net/wireless/intel/iwlwifi/mvm/power.c +drivers/net/wireless/intel/iwlwifi/mvm/quota.c +drivers/net/wireless/intel/iwlwifi/mvm/rfi.c +drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +drivers/net/wireless/intel/iwlwifi/mvm/rs.c +drivers/net/wireless/intel/iwlwifi/mvm/rx.c +drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +drivers/net/wireless/intel/iwlwifi/mvm/scan.c +drivers/net/wireless/intel/iwlwifi/mvm/sf.c +drivers/net/wireless/intel/iwlwifi/mvm/sta.c +drivers/net/wireless/intel/iwlwifi/mvm/tdls.c +drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +drivers/net/wireless/intel/iwlwifi/mvm/tt.c +drivers/net/wireless/intel/iwlwifi/mvm/tx.c +drivers/net/wireless/intel/iwlwifi/mvm/utils.c +drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +drivers/net/wireless/intel/iwlwifi/pcie/drv.c +drivers/net/wireless/intel/iwlwifi/pcie/rx.c +drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +drivers/net/wireless/intel/iwlwifi/pcie/trans.c +drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +drivers/net/wireless/intel/iwlwifi/pcie/tx.c +drivers/net/wireless/intel/iwlwifi/queue/tx.c +lib/asn1_decoder.c +lib/bsearch.c +lib/crypto/aes.c +lib/dynamic_queue_limits.c +lib/hweight.c +lib/nlattr.c +lib/rhashtable.c +net/core/datagram.c +net/core/dev.c +net/core/dev_addr_lists.c +net/core/link_watch.c +net/core/net-sysfs.c +net/core/net_namespace.c +net/core/rtnetlink.c +net/core/skbuff.c +net/core/sock.c +net/core/xdp.c +net/ethernet/eth.c +net/ethtool/common.c +net/socket.c +net/sched/sch_generic.c +net/sched/sch_mq.c +net/mac80211/aead_api.c +net/mac80211/aes_cmac.c +net/mac80211/aes_gmac.c +net/mac80211/agg-rx.c +net/mac80211/agg-tx.c +net/mac80211/airtime.c +net/mac80211/cfg.c +net/mac80211/chan.c +net/mac80211/driver-ops.c +net/mac80211/ethtool.c +net/mac80211/fils_aead.c +net/mac80211/he.c +net/mac80211/ht.c +net/mac80211/ibss.c +net/mac80211/iface.c +net/mac80211/key.c +net/mac80211/main.c +net/mac80211/michael.c +net/mac80211/mlme.c +net/mac80211/ocb.c +net/mac80211/offchannel.c +net/mac80211/rate.c +net/mac80211/rc80211_minstrel_ht.c +net/mac80211/rx.c +net/mac80211/s1g.c +net/mac80211/scan.c +net/mac80211/spectmgmt.c +net/mac80211/sta_info.c +net/mac80211/status.c +net/mac80211/tdls.c +net/mac80211/tkip.c +net/mac80211/trace.c +net/mac80211/tx.c +net/mac80211/util.c +net/mac80211/vht.c +net/mac80211/wep.c +net/mac80211/wme.c +net/mac80211/wpa.c +net/netlink/af_netlink.c +net/netlink/genetlink.c +net/netlink/policy.c +net/packet/af_packet.c +net/wireless/ap.c +net/wireless/chan.c +net/wireless/core.c +net/wireless/ethtool.c +net/wireless/ibss.c +net/wireless/mesh.c +net/wireless/mlme.c +net/wireless/nl80211.c +net/wireless/ocb.c +net/wireless/pmsr.c +net/wireless/radiotap.c +net/wireless/reg.c +net/wireless/scan.c +net/wireless/sme.c +net/wireless/sysfs.c +net/wireless/trace.c +net/wireless/util.c diff --git a/repos/pc/src/lib/wifi/symbol.map b/repos/pc/src/lib/wifi/symbol.map new file mode 100644 index 0000000000..df3487a3ba --- /dev/null +++ b/repos/pc/src/lib/wifi/symbol.map @@ -0,0 +1,29 @@ +{ + global: + + /* needed by vfs_wlan */ + *Lx_kit*initialize*; + + /* initialize function */ + _*wifi_init*; + /* Wifi::Socket_call interface */ + *Socket_call*; + /* Wifi::Socket_call instance */ + socket_call; + /* rfkill interface */ + _*wifi_*_rfkill*; + _*wifi_kick_*; + + /* interface for libnl/wpa_driver_nl82011 */ + wifi_if*; + + /* used by libnl's time() */ + jiffies; + + /* for general debugging purposes */ + lx_backtrace; + + local: + + *; +}; diff --git a/repos/pc/src/lib/wifi/time.cc b/repos/pc/src/lib/wifi/time.cc new file mode 100644 index 0000000000..0f8f40ad69 --- /dev/null +++ b/repos/pc/src/lib/wifi/time.cc @@ -0,0 +1,25 @@ +/* + * \brief Lx_emul udelay function for very short delays + * \author Stefan Kalkowski + * \date 2021-07-10 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include + +extern "C" void lx_emul_time_udelay(unsigned long usec); +extern "C" void lx_emul_time_udelay(unsigned long usec) +{ + if (usec > 100) + Genode::error("Cannot delay that long ", usec, " microseconds"); + + unsigned long long start = Lx_kit::env().timer.curr_time().trunc_to_plain_us().value; + while (Lx_kit::env().timer.curr_time().trunc_to_plain_us().value < (start + usec)) { ; } +} diff --git a/repos/pc/src/lib/wifi/uplink.c b/repos/pc/src/lib/wifi/uplink.c new file mode 100644 index 0000000000..d278b6fa43 --- /dev/null +++ b/repos/pc/src/lib/wifi/uplink.c @@ -0,0 +1,285 @@ +/* + * \brief Wireless LAN driver uplink back end + * \author Norman Feske + * \author Josef Soentgen + * \date 2021-06-02 + */ + +/* + * Copyright (C) 2021-2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include +#include +#include + + +static struct genode_uplink *dev_genode_uplink(struct net_device *dev) +{ + return (struct genode_uplink *)dev->ifalias; +} + + +struct genode_uplink_rx_context +{ + struct net_device *dev; +}; + + +struct genode_uplink_tx_packet_context +{ + struct sk_buff *skb; +}; + + +static unsigned long uplink_tx_packet_content(struct genode_uplink_tx_packet_context *ctx, + char *dst, unsigned long dst_len) +{ + struct sk_buff * const skb = ctx->skb; + unsigned long total = 0; + unsigned long result = 0; + unsigned long linear = 0; + + /* + * We always get the ethernet header from the headroom. In case + * the payload is stored in frags we have to copy them as well. + */ + + /* get ethernet header from head before calling skb_headlen */ + skb_push(skb, ETH_HLEN); + total = skb->len; + + if (dst_len < total) { + printk("uplink_tx_packet_content: packet exceeds uplink packet size\n"); + memset(dst, 0, dst_len); + return 0; + } + + linear = min_t(int, skb_headlen(skb), total); + skb_copy_from_linear_data(skb, dst, linear); + + total -= linear; + result += linear; + + if (total && skb_shinfo(skb)->nr_frags) { + unsigned int i; + + for (i = skb_shinfo(skb)->nr_frags - 1; (int)i >= 0; i--) { + unsigned int size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + void const * frag = skb_frag_address_safe(&skb_shinfo(skb)->frags[i]); + + memcpy(dst + result, frag, size); + result += size; + } + } + + return result; +} + + +static rx_handler_result_t handle_rx(struct sk_buff **pskb) +{ + struct sk_buff *skb = *pskb; + struct net_device *dev = skb->dev; + struct genode_uplink_tx_packet_context ctx = { .skb = skb }; + + /* + * Pass on EAPOL related frames to send them to the + * wpa_supplicant. + */ + if (ntohs(skb->protocol) == ETH_P_PAE) + return RX_HANDLER_PASS; + + { + bool uplink_available = !!dev_genode_uplink(dev); + bool progress = uplink_available && + genode_uplink_tx_packet(dev_genode_uplink(dev), + uplink_tx_packet_content, + &ctx); + if (!progress && uplink_available) + printk("handle_rx: uplink saturated, dropping packet\n"); + + if (progress) + genode_uplink_notify_peers(); + } + + kfree_skb(skb); + return RX_HANDLER_CONSUMED; +} + + +/** + * Create Genode uplink for given net device + * + * The uplink is registered at the dev->ifalias pointer. + */ +static void handle_create_uplink(struct net_device *dev) +{ + struct genode_uplink_args args; + + if (dev_genode_uplink(dev)) + return; + + if (!netif_carrier_ok(dev)) + return; + + printk("create uplink for net device %s\n", &dev->name[0]); + + memset(&args, 0, sizeof(args)); + + if (dev->addr_len != sizeof(args.mac_address)) { + printk("error: net device has unexpected addr_len %u\n", dev->addr_len); + return; + } + + { + unsigned i; + for (i = 0; i < dev->addr_len; i++) + args.mac_address[i] = dev->dev_addr[i]; + } + + args.label = &dev->name[0]; + + dev->ifalias = (struct dev_ifalias *)genode_uplink_create(&args); +} + + +static void handle_destroy_uplink(struct net_device *dev) +{ + struct genode_uplink *uplink = dev_genode_uplink(dev); + + if (!uplink) + return; + + if (netif_carrier_ok(dev)) + return; + + genode_uplink_destroy(uplink); + + dev->ifalias = NULL; +} + + +static genode_uplink_rx_result_t uplink_rx_one_packet(struct genode_uplink_rx_context *ctx, + char const *ptr, unsigned long len) +{ + struct sk_buff *skb = alloc_skb(len + 128, GFP_KERNEL); + skb_reserve(skb, 128); + + if (!skb) { + printk("alloc_skb failed\n"); + return GENODE_UPLINK_RX_RETRY; + } + + skb_copy_to_linear_data(skb, ptr, len); + skb_put(skb, len); + skb->dev = ctx->dev; + + if (dev_queue_xmit(skb) < 0) { + printk("lx_user: failed to xmit packet\n"); + return GENODE_UPLINK_RX_REJECTED; + } + + return GENODE_UPLINK_RX_ACCEPTED; +} + + + +struct task_struct *uplink_task_struct_ptr; /* used by 'Main' for lx_emul_task_unblock */ + + +#include + +struct netdev_event_notification +{ + struct notifier_block nb; + struct netdev_net_notifier nn; + + bool registered; +}; + + +static int uplink_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + /* + * For now we ignore what kind of event occurred and simply + * unblock the uplink task. + */ + if (uplink_task_struct_ptr) + lx_emul_task_unblock(uplink_task_struct_ptr); + + return NOTIFY_DONE; +} + + +static int user_task_function(void *arg) +{ + struct netdev_event_notification events; + memset(&events, 0, sizeof (struct netdev_event_notification)); + + events.nb.notifier_call = uplink_netdev_event; + events.registered = false; + + for (;;) { + + struct net_device *dev; + + for_each_netdev(&init_net, dev) { + + /* there might be more devices, e.g. 'lo', in the netnamespace */ + if (strcmp(&dev->name[0], "wlan0") != 0) + continue; + + /* enable link sensing, repeated calls are handled by testing IFF_UP */ + dev_open(dev, 0); + + /* install rx handler once */ + if (!netdev_is_rx_handler_busy(dev)) + netdev_rx_handler_register(dev, handle_rx, NULL); + + /* register notifier once */ + if (!events.registered) { + events.registered = + !register_netdevice_notifier_dev_net(dev, + &events.nb, + &events.nn); + } + + /* respond to cable plug/unplug */ + handle_create_uplink(dev); + handle_destroy_uplink(dev); + + /* transmit packets received from the uplink session */ + if (netif_carrier_ok(dev)) { + + struct genode_uplink_rx_context ctx = { .dev = dev }; + + while (genode_uplink_rx(dev_genode_uplink(dev), + uplink_rx_one_packet, + &ctx)); + } + }; + + /* block until lx_emul_task_unblock */ + lx_emul_task_schedule(true); + } + + return 0; +} + + +void uplink_init(void) +{ + pid_t pid; + + skb_init(); + + pid = kernel_thread(user_task_function, NULL, CLONE_FS | CLONE_FILES); + + uplink_task_struct_ptr = find_task_by_pid_ns(pid, NULL); +} diff --git a/repos/pc/src/lib/wifi/wlan.cc b/repos/pc/src/lib/wifi/wlan.cc new file mode 100644 index 0000000000..98c48dff3a --- /dev/null +++ b/repos/pc/src/lib/wifi/wlan.cc @@ -0,0 +1,104 @@ +/* + * \brief Wireless network driver Linux port + * \author Josef Soentgen + * \date 2022-02-10 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include + +/* DDE Linux includes */ +#include +#include +#include +#include +#include +#include + + +extern "C" void lx_user_handle_io(void) { } + + +using namespace Genode; + + +bool wifi_get_rfkill(void) +{ + return false; +} + + +void wifi_set_rfkill(bool blocked) +{ + (void)blocked; +} + + +extern "C" unsigned int wifi_ifindex(void) +{ + /* TODO replace with actual qyery */ + return 2; +} + + +extern "C" char const *wifi_ifname(void) +{ + /* TODO replace with actual qyery */ + return "wlan0"; +} + + +extern "C" struct task_struct *uplink_task_struct_ptr; + +struct Wlan +{ + Env &_env; + Io_signal_handler _signal_handler { _env.ep(), *this, + &Wlan::_handle_signal }; + + void _handle_signal() + { + if (uplink_task_struct_ptr) { + lx_emul_task_unblock(uplink_task_struct_ptr); + Lx_kit::env().scheduler.schedule(); + } + + genode_uplink_notify_peers(); + } + + Wlan(Env &env) : _env { env } + { + genode_uplink_init(genode_env_ptr(_env), + genode_allocator_ptr(Lx_kit::env().heap), + genode_signal_handler_ptr(_signal_handler)); + + lx_emul_start_kernel(nullptr); + } +}; + + +Genode::Blockade *wpa_blockade; + + +void wifi_init(Genode::Env &env, + Genode::Blockade &blockade, + bool disable_11n, + Genode::Signal_context_capability rfkill) +{ + (void)disable_11n; + (void)rfkill; + + wpa_blockade = &blockade; + + static Wlan wlan(env); +}