mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
wifi: get firmware from tar archive
This commit changes the firmware handling from requesting each firmware file as a ROM module that is checked against a list of known images (including their size) to requesting each file via the local VFS of the 'wifi_drv'. This allows for using the original probing mechanism that tries to select a matching firmware version. The 'repos/dde_linux/src/drivers/wifi/README' file contains more detailed information on how to configure the driver. Issue #4861.
This commit is contained in:
parent
3ba070e5e4
commit
ea0a692879
58
repos/dde_linux/include/wifi/firmware.h
Normal file
58
repos/dde_linux/include/wifi/firmware.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* \brief Firmware access interface
|
||||
* \author Josef Soentgen
|
||||
* \date 2023-05-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _WIFI__FIRMWARE_H_
|
||||
#define _WIFI__FIRMWARE_H_
|
||||
|
||||
#include <util/interface.h>
|
||||
|
||||
namespace Wifi {
|
||||
|
||||
struct Firmware_request : Genode::Interface
|
||||
{
|
||||
enum State { INVALID, PROBING, PROBING_COMPLETE,
|
||||
REQUESTING, REQUESTING_COMPLETE };
|
||||
State state { INVALID };
|
||||
bool success { false };
|
||||
|
||||
/* name of the firmware image requested by the driver */
|
||||
char const *name { nullptr };
|
||||
|
||||
/*
|
||||
* Length of the firmware image in bytes used for
|
||||
* arranging the memory buffer for the loaded firmware.
|
||||
*/
|
||||
unsigned long fw_len { 0 };
|
||||
|
||||
/*
|
||||
* Pointer to and length of the memory location where
|
||||
* the firmware image should be copied into to. It is
|
||||
* allocated by the driver.
|
||||
*/
|
||||
char *dst { nullptr };
|
||||
unsigned long dst_len { 0 };
|
||||
|
||||
virtual void submit_response() = 0;
|
||||
};
|
||||
|
||||
struct Firmware_request_handler : Genode::Interface
|
||||
{
|
||||
virtual void submit_request() = 0;
|
||||
};
|
||||
|
||||
void firmware_establish_handler(Firmware_request_handler &);
|
||||
Firmware_request *firmware_get_request();
|
||||
|
||||
} /* namespace Wifi */
|
||||
|
||||
#endif /* _WIFI__FIRMWARE_H_ */
|
@ -19,3 +19,5 @@ jiffies_64 D 0
|
||||
socket_call B 1
|
||||
wifi_ifindex T
|
||||
wifi_ifname T
|
||||
_ZN4Wifi20firmware_get_requestEv T
|
||||
_ZN4Wifi26firmware_establish_handlerERNS_24Firmware_request_handlerE T
|
||||
|
@ -1 +1 @@
|
||||
a04c8eb7c80e3d17836c7c8065c5c4358af8258b
|
||||
dc55c3afb4c9498364834030d33e3922addb1387
|
||||
|
@ -2,7 +2,7 @@ LICENSE := mixed
|
||||
VERSION := 1
|
||||
DOWNLOADS := fw.archive
|
||||
|
||||
FW_REV := a3216b6e5f31996f791577ba019a58419122ace6
|
||||
FW_REV := b7b5865b749f5a321259d95e0959929789a94959
|
||||
URL(fw) := https://github.com/cnuke/dde_linux_firmware/archive/$(FW_REV).tar.gz
|
||||
SHA(fw) := 310be6f8fd5ba65caa92187a4c1c9c6c8ab05ba4ef4df869e8a486594286fdc7
|
||||
SHA(fw) := 0fd10961cae2582a9a3e9efca7a8d761427f215562626a221062abd001e36772
|
||||
DIR(fw) := firmware
|
||||
|
@ -1,19 +0,0 @@
|
||||
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/*.bin .
|
||||
cp $(PORT_DIR)/firmware/*.ucode .
|
||||
cp $(PORT_DIR)/firmware/*.pnvm .
|
||||
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
|
@ -119,6 +119,9 @@ install_config {
|
||||
<jitterentropy name="urandom"/>
|
||||
</dir>
|
||||
<dir name="config"> <ram/> </dir>
|
||||
<dir name="firmware">
|
||||
<tar name="wifi_firmware.tar"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
<libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
|
||||
</config>
|
||||
@ -128,6 +131,7 @@ install_config {
|
||||
<service name="Report"> <child name="report_rom"/> </service>
|
||||
<service name="ROM" label="wifi_config"> <child name="config_rom"/> </service>
|
||||
<service name="ROM" label="wifi.lib.so"> <parent label="pc_wifi.lib.so"/> </service>
|
||||
<service name="ROM" label="wifi_firmware.tar"> <parent label="pc_wifi_firmware.tar"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
@ -20,15 +20,19 @@ can be used:
|
||||
! <libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
|
||||
! <vfs>
|
||||
! <dir name="dev"> <log/> <null/> <rtc/> <wifi/>
|
||||
! <jitterentropy name="random"/>
|
||||
! <jitterentropy name="urandom"/>
|
||||
! <jitterentropy name="random"/>
|
||||
! <jitterentropy name="urandom"/>
|
||||
! </dir>
|
||||
! <dir name="firmware"> <tar name="wifi_firmware.tar"/> </dir>
|
||||
! </vfs>
|
||||
! </config>
|
||||
! <route>
|
||||
! <service name="ROM" label="wifi.lib.so">
|
||||
! <parent label="pc_wifi.lib.so"/>
|
||||
! </service>
|
||||
! <service name="ROM" label="wifi_firmware.tar">
|
||||
! <parent label="pc_wifi_firmware.tar"/>
|
||||
! </service>
|
||||
! <service name="Rtc"> <any-child /> </service>
|
||||
! <any-service> <parent/> <any-child /> </any-service>
|
||||
! </route>
|
||||
@ -44,15 +48,19 @@ snippet illustrates the use of the driver on the PinePhone:
|
||||
! <libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
|
||||
! <vfs>
|
||||
! <dir name="dev"> <log/> <null/> <rtc/> <wifi/>
|
||||
! <jitterentropy name="random"/>
|
||||
! <jitterentropy name="urandom"/>
|
||||
! <jitterentropy name="random"/>
|
||||
! <jitterentropy name="urandom"/>
|
||||
! </dir>
|
||||
! <dir name="firmware"> <tar name="wifi_firmware.tar"/> </dir>
|
||||
! </vfs>
|
||||
! </config>
|
||||
! <route>
|
||||
! <service name="ROM" label="wifi.lib.so">
|
||||
! <parent label="a64_wifi.lib.so"/>
|
||||
! </service>
|
||||
! <service name="ROM" label="wifi_firmware.tar">
|
||||
! <parent label="a64_wifi_firmware.tar"/>
|
||||
! </service>
|
||||
! <service name="ROM" label="dtb">
|
||||
! <parent label="wifi-pinephone.dtb"/>
|
||||
! </service>
|
||||
@ -65,6 +73,12 @@ Note the ROM route for the device-tree binary that is essential on
|
||||
ARM-based platforms. The name of the request DTB can by changed
|
||||
by setting the 'dtb' attribute in the config node.
|
||||
|
||||
Depending on the used device additional firmware images might be
|
||||
required. The driver will request them by accessing the '/firmware'
|
||||
directory in the driver's local VFS. It is up to the configuration
|
||||
how those files are made available. In these examples they are
|
||||
contained in an '.tar' archive that is request as a ROM module.
|
||||
|
||||
The driver will request access to the ROM module 'wifi_config' to
|
||||
connect to a network:
|
||||
|
||||
|
77
repos/dde_linux/src/drivers/wifi/access_firmware.cc
Normal file
77
repos/dde_linux/src/drivers/wifi/access_firmware.cc
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* \brief Firmware I/O functions
|
||||
* \author Josef Soentgen
|
||||
* \date 2023-05-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <libc/component.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* local includes */
|
||||
#include "access_firmware.h"
|
||||
|
||||
|
||||
Stat_firmware_result access_firmware(char const *path)
|
||||
{
|
||||
Stat_firmware_result result { false, 0 };
|
||||
|
||||
|
||||
Libc::with_libc([&] {
|
||||
struct stat stat_buf { };
|
||||
int const err = ::stat(path, &stat_buf);
|
||||
if (!err) {
|
||||
result.success = true;
|
||||
result.length = stat_buf.st_size;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Read_firmware_result read_firmware(char const *path, char *dst, size_t dst_len)
|
||||
{
|
||||
Read_firmware_result result { false };
|
||||
|
||||
Libc::with_libc([&] {
|
||||
int const fd = ::open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
size_t total = 0;
|
||||
size_t remain = dst_len;
|
||||
do {
|
||||
ssize_t const cur = ::read(fd, dst, remain);
|
||||
if (cur < ssize_t(0) && errno != EINTR)
|
||||
break;
|
||||
if (cur == ssize_t(0))
|
||||
break;
|
||||
total += cur;
|
||||
dst += cur;
|
||||
remain -= (size_t)cur;
|
||||
|
||||
} while (total < dst_len);
|
||||
|
||||
(void)close(fd);
|
||||
|
||||
if (total > 0 && (size_t)total != dst_len)
|
||||
return;
|
||||
|
||||
result.success = true;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
33
repos/dde_linux/src/drivers/wifi/access_firmware.h
Normal file
33
repos/dde_linux/src/drivers/wifi/access_firmware.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* \brief Firmware I/O functions
|
||||
* \author Josef Soentgen
|
||||
* \date 2023-05-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _ACCESS_FIRMWARE_H_
|
||||
#define _ACCESS_FIRMWARE_H_
|
||||
|
||||
struct Stat_firmware_result
|
||||
{
|
||||
size_t length;
|
||||
bool success;
|
||||
};
|
||||
|
||||
Stat_firmware_result access_firmware(char const *path);
|
||||
|
||||
|
||||
struct Read_firmware_result
|
||||
{
|
||||
bool success;
|
||||
};
|
||||
|
||||
Read_firmware_result read_firmware(char const *path, char *dst, size_t dst_len);
|
||||
|
||||
#endif /* _ACCESS_FIRMWARE_H_ */
|
@ -20,11 +20,14 @@
|
||||
#include <timer_session/connection.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
/* local includes */
|
||||
#include <util.h>
|
||||
#include <wpa.h>
|
||||
#include <frontend.h>
|
||||
/* wifi library includes */
|
||||
#include <wifi/firmware.h>
|
||||
|
||||
/* local includes */
|
||||
#include "util.h"
|
||||
#include "wpa.h"
|
||||
#include "frontend.h"
|
||||
#include "access_firmware.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -98,12 +101,78 @@ struct Main
|
||||
|
||||
Blockade _wpa_startup_blockade { };
|
||||
|
||||
struct Request_handler : Wifi::Firmware_request_handler
|
||||
{
|
||||
Signal_handler<Request_handler> _handler;
|
||||
|
||||
void _handle_request()
|
||||
{
|
||||
using Fw_path = Genode::String<128>;
|
||||
using namespace Wifi;
|
||||
|
||||
Firmware_request *request_ptr = firmware_get_request();
|
||||
if (!request_ptr)
|
||||
return;
|
||||
|
||||
Firmware_request &request = *request_ptr;
|
||||
|
||||
request.success = false;
|
||||
|
||||
switch (request.state) {
|
||||
case Firmware_request::State::PROBING:
|
||||
{
|
||||
Fw_path const path { "/firmware/", request.name };
|
||||
|
||||
Stat_firmware_result const result = access_firmware(path.string());
|
||||
|
||||
request.fw_len = result.success ? result.length : 0;
|
||||
request.success = result.success;
|
||||
|
||||
request.submit_response();
|
||||
break;
|
||||
}
|
||||
case Firmware_request::State::REQUESTING:
|
||||
{
|
||||
Fw_path const path { "/firmware/", request.name };
|
||||
|
||||
Read_firmware_result const result =
|
||||
read_firmware(path.string(), request.dst, request.dst_len);
|
||||
|
||||
request.success = result.success;
|
||||
|
||||
request.submit_response();
|
||||
break;
|
||||
}
|
||||
case Firmware_request::State::INVALID:
|
||||
break;
|
||||
case Firmware_request::State::PROBING_COMPLETE:
|
||||
break;
|
||||
case Firmware_request::State::REQUESTING_COMPLETE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Request_handler(Genode::Entrypoint &ep)
|
||||
:
|
||||
_handler { ep, *this, &Request_handler::_handle_request }
|
||||
{ }
|
||||
|
||||
void submit_request() override
|
||||
{
|
||||
_handler.local_submit();
|
||||
}
|
||||
};
|
||||
|
||||
Request_handler _request_handler { env.ep() };
|
||||
|
||||
Main(Genode::Env &env) : env(env)
|
||||
{
|
||||
_frontend.construct(env, _wifi_msg_buffer);
|
||||
_wifi_frontend = &*_frontend;
|
||||
wifi_set_rfkill_sigh(_wifi_frontend->rfkill_sigh());
|
||||
|
||||
Wifi::firmware_establish_handler(_request_handler);
|
||||
|
||||
_wpa.construct(env, _wpa_startup_blockade);
|
||||
|
||||
wifi_init(env, _wpa_startup_blockade);
|
||||
|
@ -1,5 +1,5 @@
|
||||
TARGET := wifi_drv
|
||||
SRC_CC := main.cc wpa.cc
|
||||
SRC_CC := main.cc wpa.cc access_firmware.cc
|
||||
LIBS := base wifi
|
||||
LIBS += libc
|
||||
LIBS += wpa_supplicant
|
||||
|
@ -17,103 +17,41 @@
|
||||
|
||||
/* local includes */
|
||||
#include <lx_kit/env.h>
|
||||
#include <firmware_list.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
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-36.ucode", 2428004, nullptr },
|
||||
{ "iwlwifi-8265-36.ucode", 2436632, nullptr },
|
||||
|
||||
{ "iwlwifi-9000-pu-b0-jf-b0-46.ucode", 1514876, nullptr },
|
||||
{ "iwlwifi-9260-th-b0-jf-b0-46.ucode", 1490376, nullptr },
|
||||
|
||||
{ "iwlwifi-QuZ-a0-hr-b0-68.ucode", 1355800, nullptr },
|
||||
{ "iwlwifi-QuZ-a0-hr-b0-72.ucode", 1355800, "iwlwifi-QuZ-a0-hr-b0-68.ucode" },
|
||||
|
||||
{ "iwlwifi-so-a0-hr-b0-68.ucode", 1429192, nullptr },
|
||||
{ "iwlwifi-so-a0-hr-b0-72.ucode", 1429192, "iwlwifi-so-a0-hr-b0-68.ucode" },
|
||||
|
||||
{ "iwlwifi-so-a0-gf-a0-68.ucode", 1533812, nullptr },
|
||||
{ "iwlwifi-so-a0-gf-a0-72.ucode", 1533812, "iwlwifi-so-a0-gf-a0-68.ucode" },
|
||||
{ "iwlwifi-so-a0-gf-a0.pnvm", 41808, nullptr },
|
||||
|
||||
{ "iwlwifi-ty-a0-gf-a0-68.ucode", 1494304, nullptr },
|
||||
{ "iwlwifi-ty-a0-gf-a0-72.ucode", 1494304, "iwlwifi-ty-a0-gf-a0-68.ucode" },
|
||||
{ "iwlwifi-ty-a0-gf-a0.pnvm", 41588, nullptr },
|
||||
|
||||
{ "rtl8192eu_nic.bin", 31818, nullptr },
|
||||
{ "rtlwifi/rtl8192eefw.bin", 31818, "rtl8192eu_nic.bin" },
|
||||
{ "rtl8188efw.bin", 11216, nullptr },
|
||||
{ "rtlwifi/rtl8188efw.bin", 11216, "rtl8188efw.bin" }, /* FW Power Save off */
|
||||
};
|
||||
|
||||
|
||||
size_t fw_list_len = sizeof(fw_list) / sizeof(fw_list[0]);
|
||||
|
||||
|
||||
/**********************
|
||||
** linux/firmware.h **
|
||||
**********************/
|
||||
|
||||
extern size_t _wifi_probe_firmware(char const *name);
|
||||
extern int _wifi_request_firmware(char const *name, char *dst, size_t dst_len);
|
||||
|
||||
extern "C" int lx_emul_request_firmware_nowait(const char *name, void **dest,
|
||||
size_t *result, bool warn)
|
||||
size_t *result, bool /* warn */)
|
||||
{
|
||||
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 (strcmp(name, fw_list[i].requested_name) == 0) {
|
||||
fwl = &fw_list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fwl ) {
|
||||
if (warn)
|
||||
error("firmware '", name, "' is not in the firmware white list");
|
||||
size_t const fw_size = _wifi_probe_firmware(name);
|
||||
|
||||
if (!fw_size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
char const *fw_name = fwl->available_name
|
||||
? fwl->available_name : fwl->requested_name;
|
||||
Rom_connection rom(Lx_kit::env().env, fw_name);
|
||||
Dataspace_capability ds_cap = rom.dataspace();
|
||||
|
||||
if (!ds_cap.valid()) {
|
||||
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);
|
||||
char *data = (char*)Lx_kit::env().heap.alloc(fw_size);
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
void const *image = Lx_kit::env().env.rm().attach(ds_cap);
|
||||
memcpy(data, image, fwl->size);
|
||||
Lx_kit::env().env.rm().detach(image);
|
||||
if (_wifi_request_firmware(name, data, fw_size)) {
|
||||
error("could not request firmware ", name);
|
||||
Lx_kit::env().heap.free(data, fw_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*dest = data;
|
||||
*result = fwl->size;
|
||||
*result = fw_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* \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_ */
|
@ -136,34 +136,41 @@ void iput(struct inode * inode)
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#if 0
|
||||
struct firmware_work {
|
||||
struct work_struct work;
|
||||
struct firmware const *firmware;
|
||||
struct firmware *firmware;
|
||||
char const *name;
|
||||
void *context;
|
||||
void (*cont)(struct firmware const *, void *);
|
||||
};
|
||||
|
||||
extern int lx_emul_request_firmware_nowait(const char *name, void *dest,
|
||||
size_t *result, bool warn);
|
||||
|
||||
static void request_firmware_work_func(struct work_struct *work)
|
||||
{
|
||||
struct firmware_work *fw_work =
|
||||
container_of(work, struct firmware_work, work);
|
||||
struct firmware *fw = fw_work->firmware;
|
||||
|
||||
fw_work->cont(fw_work->firmware, fw_work->context);
|
||||
if (lx_emul_request_firmware_nowait(fw_work->name,
|
||||
&fw->data, &fw->size, true)) {
|
||||
/*
|
||||
* Free and set to NULL here as passing NULL to
|
||||
* 'cont()' triggers requesting next possible ucode
|
||||
* version.
|
||||
*/
|
||||
kfree(fw);
|
||||
fw = NULL;
|
||||
}
|
||||
|
||||
fw_work->cont(fw, fw_work->context);
|
||||
|
||||
kfree(fw_work);
|
||||
kfree(fw);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
extern int lx_emul_request_firmware_nowait(const char *name, void *dest,
|
||||
size_t *result, bool warn);
|
||||
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,
|
||||
@ -172,41 +179,15 @@ int request_firmware_nowait(struct module * module,
|
||||
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, true)) {
|
||||
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->name = name;
|
||||
fw_work->firmware = fw;
|
||||
fw_work->context = context;
|
||||
fw_work->cont = cont;
|
||||
@ -215,7 +196,6 @@ int request_firmware_nowait(struct module * module,
|
||||
schedule_work(&fw_work->work);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -246,8 +226,14 @@ int request_firmware(const struct firmware ** firmware_p,
|
||||
}
|
||||
|
||||
|
||||
extern void lx_emul_release_firmware(void const *data, size_t size);
|
||||
|
||||
|
||||
void release_firmware(const struct firmware * fw)
|
||||
{
|
||||
if (!fw)
|
||||
return;
|
||||
|
||||
lx_emul_release_firmware(fw->data, fw->size);
|
||||
kfree(fw);
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
_*wifi_*_rfkill*;
|
||||
_*wifi_kick_*;
|
||||
|
||||
_*Wifi*firmware*;
|
||||
|
||||
/* interface for libnl/wpa_driver_nl82011 */
|
||||
wifi_if*;
|
||||
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include <lx_kit/init.h>
|
||||
#include <lx_user/io.h>
|
||||
|
||||
/* wifi includes */
|
||||
#include <wifi/firmware.h>
|
||||
|
||||
/* local includes */
|
||||
#include "lx_user.h"
|
||||
#include "dtb_helper.h"
|
||||
@ -79,6 +82,168 @@ bool wifi_get_rfkill(void)
|
||||
}
|
||||
|
||||
|
||||
/* Firmware access, move to object later */
|
||||
|
||||
struct task_struct;
|
||||
|
||||
struct Firmware_helper
|
||||
{
|
||||
Firmware_helper(Firmware_helper const&) = delete;
|
||||
Firmware_helper & operator = (Firmware_helper const&) = delete;
|
||||
|
||||
void *_waiting_task { nullptr };
|
||||
void *_calling_task { nullptr };
|
||||
|
||||
Genode::Signal_handler<Firmware_helper> _response_handler;
|
||||
|
||||
void _handle_response()
|
||||
{
|
||||
if (_calling_task)
|
||||
lx_emul_task_unblock((struct task_struct*)_calling_task);
|
||||
|
||||
Lx_kit::env().scheduler.schedule();
|
||||
}
|
||||
|
||||
Wifi::Firmware_request_handler &_request_handler;
|
||||
|
||||
struct Request : Wifi::Firmware_request
|
||||
{
|
||||
Genode::Signal_context &_response_handler;
|
||||
|
||||
Request(Genode::Signal_context &sig_ctx)
|
||||
:
|
||||
_response_handler { sig_ctx }
|
||||
{ }
|
||||
|
||||
void submit_response() override
|
||||
{
|
||||
switch (state) {
|
||||
case Firmware_request::State::PROBING:
|
||||
state = Firmware_request::State::PROBING_COMPLETE;
|
||||
break;
|
||||
case Firmware_request::State::REQUESTING:
|
||||
state = Firmware_request::State::REQUESTING_COMPLETE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
_response_handler.local_submit();
|
||||
}
|
||||
};
|
||||
|
||||
using S = Wifi::Firmware_request::State;
|
||||
|
||||
Request _request { _response_handler };
|
||||
|
||||
void _update_waiting_task()
|
||||
{
|
||||
if (_waiting_task)
|
||||
if (_waiting_task != lx_emul_task_get_current())
|
||||
warning("Firmware_request: already waiting task is not current task");
|
||||
|
||||
_waiting_task = lx_emul_task_get_current();
|
||||
}
|
||||
|
||||
void _submit_request_and_wait_for(Wifi::Firmware_request::State state)
|
||||
{
|
||||
_calling_task = lx_emul_task_get_current();
|
||||
_request_handler.submit_request();
|
||||
|
||||
do {
|
||||
lx_emul_task_schedule(true);
|
||||
} while (_request.state != state);
|
||||
}
|
||||
|
||||
void _wait_until_pending_request_finished()
|
||||
{
|
||||
while (_request.state != S::INVALID) {
|
||||
|
||||
_update_waiting_task();
|
||||
lx_emul_task_schedule(true);
|
||||
}
|
||||
}
|
||||
|
||||
void _wakeup_any_waiting_request()
|
||||
{
|
||||
_request.state = S::INVALID;
|
||||
if (_waiting_task) {
|
||||
lx_emul_task_unblock((struct task_struct*)_waiting_task);
|
||||
_waiting_task = nullptr;
|
||||
}
|
||||
_calling_task = nullptr;
|
||||
}
|
||||
|
||||
Firmware_helper(Genode::Entrypoint &ep,
|
||||
Wifi::Firmware_request_handler &request_handler)
|
||||
:
|
||||
_response_handler { ep, *this, &Firmware_helper::_handle_response },
|
||||
_request_handler { request_handler }
|
||||
{ }
|
||||
|
||||
size_t perform_probing(char const *name)
|
||||
{
|
||||
_wait_until_pending_request_finished();
|
||||
|
||||
_request.name = name;
|
||||
_request.state = S::PROBING;
|
||||
_request.dst = nullptr;
|
||||
_request.dst_len = 0;
|
||||
|
||||
_submit_request_and_wait_for(S::PROBING_COMPLETE);
|
||||
|
||||
size_t const fw_length = _request.success ? _request.fw_len : 0;
|
||||
|
||||
_wakeup_any_waiting_request();
|
||||
|
||||
return fw_length;
|
||||
}
|
||||
|
||||
int perform_requesting(char const *name, char *dst, size_t dst_len)
|
||||
{
|
||||
_wait_until_pending_request_finished();
|
||||
|
||||
_request.name = name;
|
||||
_request.state = S::REQUESTING;
|
||||
_request.dst = dst;
|
||||
_request.dst_len = dst_len;
|
||||
|
||||
_submit_request_and_wait_for(S::REQUESTING_COMPLETE);
|
||||
|
||||
bool const success = _request.success;
|
||||
|
||||
_wakeup_any_waiting_request();
|
||||
|
||||
return success ? 0 : -1;
|
||||
}
|
||||
|
||||
Wifi::Firmware_request *request()
|
||||
{
|
||||
return &_request;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Constructible<Firmware_helper> firmware_helper { };
|
||||
|
||||
|
||||
size_t _wifi_probe_firmware(char const *name)
|
||||
{
|
||||
if (firmware_helper.constructed())
|
||||
return firmware_helper->perform_probing(name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int _wifi_request_firmware(char const *name, char *dst, size_t dst_len)
|
||||
{
|
||||
if (firmware_helper.constructed())
|
||||
return firmware_helper->perform_requesting(name, dst, dst_len);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned int wifi_ifindex(void)
|
||||
{
|
||||
/* TODO replace with actual qyery */
|
||||
@ -209,3 +374,18 @@ void wifi_set_rfkill_sigh(Signal_context_capability cap)
|
||||
{
|
||||
_rfkill_sigh_cap = cap;
|
||||
}
|
||||
|
||||
|
||||
void Wifi::firmware_establish_handler(Wifi::Firmware_request_handler &request_handler)
|
||||
{
|
||||
firmware_helper.construct(Lx_kit::env().env.ep(), request_handler);
|
||||
}
|
||||
|
||||
|
||||
Wifi::Firmware_request *Wifi::firmware_get_request()
|
||||
{
|
||||
if (firmware_helper.constructed())
|
||||
return firmware_helper->request();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -158,6 +158,7 @@ proc nic_driver_routes { } {
|
||||
set result(pc) {
|
||||
<service name="ROM" label="nic_drv"> <parent label="ipxe_nic_drv"/> </service>
|
||||
<service name="ROM" label="wifi.lib.so"> <parent label="pc_wifi.lib.so"/> </service>
|
||||
<service name="ROM" label="wifi_firmware.tar"> <parent label="pc_wifi_firmware.tar"/> </service>
|
||||
}
|
||||
|
||||
set result(mnt_reform2) {
|
||||
@ -173,6 +174,7 @@ proc nic_driver_routes { } {
|
||||
set result(pinephone) {
|
||||
<service name="ROM" label="wifi.lib.so"> <parent label="a64_wifi.lib.so"/> </service>
|
||||
<service name="ROM" label="wifi_drv.dtb"> <parent label="wifi-pinephone.dtb"/> </service>
|
||||
<service name="ROM" label="wifi_firmware.tar"> <parent label="a64_wifi_firmware.tar"/> </service>
|
||||
}
|
||||
|
||||
if {[info exists result([board])]} {
|
||||
|
@ -35,6 +35,11 @@ void Sculpt::gen_wifi_drv_start_content(Xml_generator &xml)
|
||||
gen_named_node(xml, "inline", "rtc", [&] () {
|
||||
xml.append("2018-01-01 00:01");
|
||||
});
|
||||
gen_named_node(xml, "dir", "firmware", [&] () {
|
||||
xml.node("tar", [&] () {
|
||||
xml.attribute("name", "wifi_firmware.tar");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
xml.node("libc", [&] () {
|
||||
@ -69,32 +74,9 @@ void Sculpt::gen_wifi_drv_start_content(Xml_generator &xml)
|
||||
gen_parent_rom_route(xml, "vfs_wifi.lib.so");
|
||||
gen_parent_rom_route(xml, "libssl.lib.so");
|
||||
gen_parent_rom_route(xml, "wifi.lib.so");
|
||||
gen_parent_rom_route(xml, "wifi_firmware.tar");
|
||||
gen_parent_rom_route(xml, "wpa_driver_nl80211.lib.so");
|
||||
gen_parent_rom_route(xml, "wpa_supplicant.lib.so");
|
||||
gen_parent_rom_route(xml, "iwlwifi-1000-5.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-3160-17.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-3168-17.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-5000-5.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-6000-4.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-6000g2a-6.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-6000g2b-6.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-7260-17.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-7265-17.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-7265D-29.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-8000C-36.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-8265-36.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-9000-pu-b0-jf-b0-46.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-9260-th-b0-jf-b0-46.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-QuZ-a0-hr-b0-68.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-so-a0-hr-b0-68.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-so-a0-gf-a0-68.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-so-a0-gf-a0.pnvm");
|
||||
gen_parent_rom_route(xml, "iwlwifi-ty-a0-gf-a0-68.ucode");
|
||||
gen_parent_rom_route(xml, "iwlwifi-ty-a0-gf-a0.pnvm");
|
||||
gen_parent_rom_route(xml, "rtl8192eu_nic.bin");
|
||||
gen_parent_rom_route(xml, "rtl8188efw.bin");
|
||||
gen_parent_rom_route(xml, "regulatory.db");
|
||||
gen_parent_rom_route(xml, "regulatory.db.p7s");
|
||||
gen_parent_route<Cpu_session> (xml);
|
||||
gen_parent_route<Pd_session> (xml);
|
||||
gen_parent_route<Rm_session> (xml);
|
||||
|
24
repos/pc/recipes/raw/pc_wifi_firmware/content.mk
Normal file
24
repos/pc/recipes/raw/pc_wifi_firmware/content.mk
Normal file
@ -0,0 +1,24 @@
|
||||
PORT_DIR := $(call port_dir,$(GENODE_DIR)/repos/dde_linux/ports/linux-firmware)
|
||||
|
||||
content: ucode_files LICENSE.wifi_drv pc_wifi_firmware.tar
|
||||
|
||||
|
||||
.PHONY: ucode_files
|
||||
ucode_files:
|
||||
cp -R $(PORT_DIR)/firmware/rtlwifi .
|
||||
cp $(PORT_DIR)/firmware/*.ucode .
|
||||
cp $(PORT_DIR)/firmware/*.pnvm .
|
||||
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
|
||||
|
||||
pc_wifi_firmware.tar: ucode_files LICENSE.wifi_drv
|
||||
tar --mtime='2023-05-03 00:00Z' --remove-files \
|
||||
-cf $@ -C . *.* rtlwifi/*.* && \
|
||||
rmdir rtlwifi
|
@ -1,3 +1,10 @@
|
||||
#
|
||||
# Set to true in case the driver needs to be debugged to
|
||||
# pull in the locally build binaries rather than the ones
|
||||
# from the depot.
|
||||
#
|
||||
set debug_driver false
|
||||
|
||||
#
|
||||
# Configure wireless lan
|
||||
#
|
||||
@ -80,6 +87,11 @@ set build_components {
|
||||
lib/vfs_lwip
|
||||
}
|
||||
|
||||
append_if $debug_driver build_components {
|
||||
drivers/wifi
|
||||
lib/pc_wifi
|
||||
}
|
||||
|
||||
build $build_components
|
||||
|
||||
#
|
||||
@ -270,7 +282,7 @@ append config {
|
||||
<config verbose="yes"/>
|
||||
</start>
|
||||
|
||||
<start name="wifi_drv" caps="250" priority="-1">
|
||||
<start name="wifi_drv" caps="260" priority="-1">
|
||||
<resource name="RAM" quantum="32M"/>
|
||||
<config ld_verbose="yes">
|
||||
<report mac_address="true"/>
|
||||
@ -281,6 +293,9 @@ append config {
|
||||
<jitterentropy name="urandom"/>
|
||||
<wifi/>
|
||||
</dir>
|
||||
<dir name="firmware">
|
||||
<tar name="wifi_firmware.tar"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
</config>
|
||||
<route>
|
||||
@ -291,6 +306,7 @@ append config {
|
||||
<service name="Report" label="devices"> <child name="devices_report_rom"/> </service>
|
||||
<service name="ROM" label="wifi_config"> <child name="config_rom"/> </service>
|
||||
<service name="ROM" label="wifi.lib.so"> <parent label="pc_wifi.lib.so"/> </service>
|
||||
<service name="ROM" label="wifi_firmware.tar"> <parent label="pc_wifi_firmware.tar"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
@ -299,6 +315,16 @@ append config {
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Provide dummy 'wifi.lib.so' shared-object for
|
||||
# boot-module assembly
|
||||
#
|
||||
if {$debug_driver} {
|
||||
exec rm bin/wifi.lib.so
|
||||
exec echo dummy > bin/wifi.lib.so
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
@ -261,7 +261,7 @@ append config { </wifi_config>
|
||||
</start>
|
||||
|
||||
<start name="nic_drv" caps="300">
|
||||
<binary name="pc_wifi_drv"/>
|
||||
<binary name="wifi_drv"/>
|
||||
<resource name="RAM" quantum="32M"/>
|
||||
<config>
|
||||
<libc stdout="/dev/null" stderr="/dev/log" rtc="/dev/rtc"/>
|
||||
@ -272,6 +272,9 @@ append config { </wifi_config>
|
||||
<jitterentropy name="urandom"/>
|
||||
<inline name="rtc">2018-01-01 00:01</inline>
|
||||
</dir>
|
||||
<dir name="firmware">
|
||||
<tar name="wifi_firmware.tar"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
</config>
|
||||
<route>
|
||||
@ -279,6 +282,7 @@ append config { </wifi_config>
|
||||
<service name="File_system"> <child name="config_fs"/> </service>
|
||||
<service name="ROM" label="wifi_config"> <child name="config_rom" /> </service>
|
||||
<service name="ROM" label="wifi.lib.so"> <parent label="pc_wifi.lib.so"/> </service>
|
||||
<service name="ROM" label="wifi_firmware.tar"> <parent label="pc_wifi_firmware.tar"/> </service>
|
||||
<service name="Report"> <child name="report_rom"/> </service>
|
||||
<service name="Uplink"> <child name="nic_router"/> </service>
|
||||
<any-service> <parent/> <any-child /> </any-service>
|
||||
|
Loading…
Reference in New Issue
Block a user