kernel: firmware loading

This commit is contained in:
Matheus
2026-09-09 16:37:15 -03:00
parent de0d5cb8f9
commit 2328f889ef
6 changed files with 160 additions and 0 deletions
+39
View File
@@ -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.
Binary file not shown.
+11
View File
@@ -0,0 +1,11 @@
#ifndef _FIRMWARE_H
#define _FIRMWARE_H
#include <stddef.h>
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
+99
View File
@@ -0,0 +1,99 @@
#include <kernel/firmware.h>
#include <kernel/vfs.h>
#include <kernel/alloc.h>
#include <errno.h>
#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;
}
+8
View File
@@ -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
}
+3
View File
@@ -0,0 +1,3 @@
name=firmware
version=0
source_dir="firmware"