mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
kernel: firmware loading
This commit is contained in:
@@ -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.
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
name=firmware
|
||||
version=0
|
||||
source_dir="firmware"
|
||||
Reference in New Issue
Block a user