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