diff --git a/firmware/LICENCE.rtlwifi_firmware.txt b/firmware/LICENCE.rtlwifi_firmware.txt new file mode 100644 index 00000000..d70921f4 --- /dev/null +++ b/firmware/LICENCE.rtlwifi_firmware.txt @@ -0,0 +1,39 @@ +Copyright (c) 2010, Realtek Semiconductor Corporation +All rights reserved. + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +* Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +* Neither the name of Realtek Semiconductor Corporation nor the names of its + suppliers may be used to endorse or promote products derived from this + software without specific prior written permission. +* No reverse engineering, decompilation, or disassembly of this software + is permitted. + +Limited patent license. Realtek Semiconductor Corporation grants a world-wide, +royalty-free, non-exclusive license under patents it now or hereafter +owns or controls to make, have made, use, import, offer to sell and +sell ("Utilize") this software, but solely to the extent that any +such patent is necessary to Utilize the software alone, or in +combination with an operating system licensed under an approved Open +Source license as listed by the Open Source Initiative at +http://opensource.org/licenses. The patent license shall not apply to +any other combinations which include this software. No hardware per +se is licensed hereunder. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/firmware/rtl8188eufw.bin b/firmware/rtl8188eufw.bin new file mode 100644 index 00000000..8bb12ea8 Binary files /dev/null and b/firmware/rtl8188eufw.bin differ diff --git a/kernel-src/include/kernel/firmware.h b/kernel-src/include/kernel/firmware.h new file mode 100644 index 00000000..e0b48c86 --- /dev/null +++ b/kernel-src/include/kernel/firmware.h @@ -0,0 +1,11 @@ +#ifndef _FIRMWARE_H +#define _FIRMWARE_H + +#include + +typedef void (*firmware_callback_t)(void *ctx, void *data, size_t size); + +// firmware data is only valid only for the duration of the callback +int firmware_load(const char *name, firmware_callback_t callback, void *ctx); + +#endif diff --git a/kernel-src/io/firmware.c b/kernel-src/io/firmware.c new file mode 100644 index 00000000..87e9dd32 --- /dev/null +++ b/kernel-src/io/firmware.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include + +#define FIRMWARE_SIZE_LIMIT (16 * 1024) +#define FIRMWARE_PATH "/usr/lib/firmware/" + +typedef struct { + const char *name; + firmware_callback_t callback; + void *ctx; +} firmware_ctx_t; + +static void do_load(void *ctx) { + firmware_ctx_t *fc = ctx; + printf("firmware: loading \"%s\"\n", fc->name); + + vnode_t *firmware_dir; + int error = vfs_lookup(&firmware_dir, vfsroot, FIRMWARE_PATH, NULL, 0); + if (error) { + printf("firmware: loading \"%s\" failed: failed to open %s (%s)\n", + fc->name, FIRMWARE_PATH, strerror(error)); + goto leave; + } + + VOP_UNLOCK(firmware_dir); // vfs_lookup returns vnode locked + + vnode_t *firmware_file; + error = vfs_lookup(&firmware_file, firmware_dir, fc->name, NULL, 0); + VOP_RELEASE(firmware_dir); + if (error) { + printf("firmware: loading \"%s\" failed: failed to open file (%s)\n", + fc->name, strerror(error)); + goto leave; + } + + vattr_t vattr; + error = VOP_GETATTR(firmware_file, &vattr, NULL); + VOP_UNLOCK(firmware_file); + if (error) + goto leave_release; + + if (vattr.size >= FIRMWARE_SIZE_LIMIT) { + error = EINVAL; + goto leave_release; + } + + void *buffer = alloc(vattr.size); + if (buffer == NULL) { + error = ENOMEM; + goto leave_release; + } + + size_t bytes_read; + error = vfs_read(firmware_file, buffer, vattr.size, 0, &bytes_read, 0); + if (error) + goto leave_free; + + if (bytes_read != vattr.size) { + error = EINVAL; + goto leave_free; + } + + printf("firmware: \"%s\" loaded\n", fc->name); + fc->callback(fc->ctx, buffer, vattr.size); + +leave_free: + free(buffer); +leave_release: + if (error) { + printf("firmware: loading \"%s\" failed: %s\n", + fc->name, strerror(error)); + } + VOP_RELEASE(firmware_file); +leave: + free(fc); +} + +int firmware_load(const char *name, firmware_callback_t callback, void *ctx) { + // TODO: support kernel embedded firmware + firmware_ctx_t *fc = alloc(sizeof(firmware_ctx_t)); + if (fc == NULL) + return ENOMEM; + + fc->name = name; + fc->callback = callback; + fc->ctx = ctx; + + int error = vfs_root_event_attach(do_load, fc); + if (error && error != EBUSY) { + free(fc); + return error; + } else if (error == EBUSY) { + do_load(fc); + } + + return 0; +} diff --git a/recipes/firmware b/recipes/firmware new file mode 100644 index 00000000..29641f82 --- /dev/null +++ b/recipes/firmware @@ -0,0 +1,8 @@ +name=firmware +revision=1 +from_source=firmware + +package() { + mkdir -p ${dest_dir}/usr/lib/firmware + cp -r ${source_dir}/* ${dest_dir}/usr/lib/firmware +} diff --git a/source-recipes/firmware b/source-recipes/firmware new file mode 100644 index 00000000..0cdf23fb --- /dev/null +++ b/source-recipes/firmware @@ -0,0 +1,3 @@ +name=firmware +version=0 +source_dir="firmware"