mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-01 18:39:16 +00:00
Merge remote-tracking branch 'Kernel/master'
This commit is contained in:
51
Kernel/library/bitmap.cpp
Normal file
51
Kernel/library/bitmap.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <bitmap.hpp>
|
||||
|
||||
bool Bitmap::Get(uint64_t index)
|
||||
{
|
||||
if (index > Size * 8)
|
||||
return false;
|
||||
|
||||
uint64_t byteIndex = index / 8;
|
||||
uint8_t bitIndex = index % 8;
|
||||
uint8_t bitIndexer = 0b10000000 >> bitIndex;
|
||||
|
||||
if ((Buffer[byteIndex] & bitIndexer) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bitmap::Set(uint64_t index, bool value)
|
||||
{
|
||||
if (index > Size * 8)
|
||||
return false;
|
||||
|
||||
uint64_t byteIndex = index / 8;
|
||||
uint8_t bitIndex = index % 8;
|
||||
uint8_t bitIndexer = 0b10000000 >> bitIndex;
|
||||
|
||||
Buffer[byteIndex] &= ~bitIndexer;
|
||||
if (value)
|
||||
Buffer[byteIndex] |= bitIndexer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bitmap::operator[](uint64_t index) { return this->Get(index); }
|
28
Kernel/library/c/ctype.c
Normal file
28
Kernel/library/c/ctype.c
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
int tolower(int c)
|
||||
{
|
||||
return _tolower(c);
|
||||
}
|
||||
|
||||
int toupper(int c)
|
||||
{
|
||||
return _toupper(c);
|
||||
}
|
100
Kernel/library/c/stdio.cpp
Normal file
100
Kernel/library/c/stdio.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
|
||||
FILE __local_stdin = {.st = 0};
|
||||
FILE __local_stdout = {.st = 1};
|
||||
FILE __local_stderr = {.st = 2};
|
||||
|
||||
FILE *stdin = &__local_stdin;
|
||||
FILE *stdout = &__local_stdout;
|
||||
FILE *stderr = &__local_stderr;
|
||||
|
||||
EXTERNC int asprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int ret = vasprintf(strp, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
|
||||
EXTERNC int vasprintf(char **strp, const char *fmt, va_list ap)
|
||||
{
|
||||
va_list ap2;
|
||||
va_copy(ap2, ap);
|
||||
int len = vsnprintf(NULL, 0, fmt, ap2);
|
||||
va_end(ap2);
|
||||
if (len < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*strp = (char *)malloc(len + 1);
|
||||
if (!*strp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int ret = vsnprintf(*strp, len + 1, fmt, ap);
|
||||
if (ret < 0)
|
||||
{
|
||||
free(*strp);
|
||||
*strp = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fprintf(FILE *stream, const char *format, ...)
|
||||
{
|
||||
switch (stream->st)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
error("fprintf() called with stdin");
|
||||
return -1;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int ret = vprintf(format, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int ret = vprintf(format, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int fputs(const char *s, FILE *stream)
|
||||
{
|
||||
for (const char *c = s; *c; c++)
|
||||
uart_wrapper(*c, NULL);
|
||||
return 0;
|
||||
}
|
27
Kernel/library/c/stdlib.cpp
Normal file
27
Kernel/library/c/stdlib.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
|
||||
EXTERNC void abort()
|
||||
{
|
||||
error("abort() called");
|
||||
CPU::Stop();
|
||||
__builtin_unreachable();
|
||||
}
|
512
Kernel/library/cargs.c
Normal file
512
Kernel/library/cargs.c
Normal file
@ -0,0 +1,512 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Leonard Iklé
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cargs.h>
|
||||
#include <convert.h>
|
||||
|
||||
#define CAG_OPTION_PRINT_DISTANCE 4
|
||||
#define CAG_OPTION_PRINT_MIN_INDENTION 20
|
||||
|
||||
static void cag_option_print_value(const cag_option *option,
|
||||
size_t *accessor_length, FILE *destination)
|
||||
{
|
||||
if (option->value_name != NULL)
|
||||
{
|
||||
*accessor_length += fprintf(destination, "=%s", option->value_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void cag_option_print_letters(const cag_option *option, bool *first,
|
||||
size_t *accessor_length, FILE *destination)
|
||||
{
|
||||
const char *access_letter;
|
||||
access_letter = option->access_letters;
|
||||
if (access_letter != NULL)
|
||||
{
|
||||
while (*access_letter)
|
||||
{
|
||||
if (*first)
|
||||
{
|
||||
*accessor_length += fprintf(destination, "-%c", *access_letter);
|
||||
*first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*accessor_length += fprintf(destination, ", -%c", *access_letter);
|
||||
}
|
||||
++access_letter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cag_option_print_name(const cag_option *option, bool *first,
|
||||
size_t *accessor_length, FILE *destination)
|
||||
{
|
||||
if (option->access_name != NULL)
|
||||
{
|
||||
if (*first)
|
||||
{
|
||||
*accessor_length += fprintf(destination, "--%s", option->access_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
*accessor_length += fprintf(destination, ", --%s", option->access_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t cag_option_get_print_indention(const cag_option *options,
|
||||
size_t option_count)
|
||||
{
|
||||
size_t option_index, indention, result;
|
||||
const cag_option *option;
|
||||
|
||||
result = CAG_OPTION_PRINT_MIN_INDENTION;
|
||||
|
||||
for (option_index = 0; option_index < option_count; ++option_index)
|
||||
{
|
||||
indention = CAG_OPTION_PRINT_DISTANCE;
|
||||
option = &options[option_index];
|
||||
if (option->access_letters != NULL && *option->access_letters)
|
||||
{
|
||||
indention += strlen(option->access_letters) * 4 - 2;
|
||||
if (option->access_name != NULL)
|
||||
{
|
||||
indention += strlen(option->access_name) + 4;
|
||||
}
|
||||
}
|
||||
else if (option->access_name != NULL)
|
||||
{
|
||||
indention += strlen(option->access_name) + 2;
|
||||
}
|
||||
|
||||
if (option->value_name != NULL)
|
||||
{
|
||||
indention += strlen(option->value_name) + 1;
|
||||
}
|
||||
|
||||
if (indention > result)
|
||||
{
|
||||
result = indention;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void cag_option_print(const cag_option *options, size_t option_count,
|
||||
FILE *destination)
|
||||
{
|
||||
size_t option_index, indention, i, accessor_length;
|
||||
const cag_option *option;
|
||||
bool first;
|
||||
|
||||
indention = cag_option_get_print_indention(options, option_count);
|
||||
|
||||
for (option_index = 0; option_index < option_count; ++option_index)
|
||||
{
|
||||
option = &options[option_index];
|
||||
accessor_length = 0;
|
||||
first = true;
|
||||
|
||||
fputs(" ", destination);
|
||||
|
||||
cag_option_print_letters(option, &first, &accessor_length, destination);
|
||||
cag_option_print_name(option, &first, &accessor_length, destination);
|
||||
cag_option_print_value(option, &accessor_length, destination);
|
||||
|
||||
for (i = accessor_length; i < indention; ++i)
|
||||
{
|
||||
fputs(" ", destination);
|
||||
}
|
||||
|
||||
fputs(" ", destination);
|
||||
fputs(option->description, destination);
|
||||
|
||||
fprintf(destination, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void cag_option_prepare(cag_option_context *context, const cag_option *options,
|
||||
size_t option_count, int argc, char **argv)
|
||||
{
|
||||
// This just initialized the values to the beginning of all the arguments.
|
||||
context->options = options;
|
||||
context->option_count = option_count;
|
||||
context->argc = argc;
|
||||
context->argv = argv;
|
||||
context->index = 1;
|
||||
context->inner_index = 0;
|
||||
context->forced_end = false;
|
||||
}
|
||||
|
||||
static const cag_option *cag_option_find_by_name(cag_option_context *context,
|
||||
char *name, size_t name_size)
|
||||
{
|
||||
const cag_option *option;
|
||||
size_t i;
|
||||
|
||||
// We loop over all the available options and stop as soon as we have found
|
||||
// one. We don't use any hash map table, since there won't be that many
|
||||
// arguments anyway.
|
||||
for (i = 0; i < context->option_count; ++i)
|
||||
{
|
||||
option = &context->options[i];
|
||||
|
||||
// The option might not have an item name, we can just skip those.
|
||||
if (option->access_name == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to compare the name of the access name. We can use the name_size or
|
||||
// this comparison, since we are guaranteed to have null-terminated access
|
||||
// names.
|
||||
if (strncmp(option->access_name, name, name_size) == 0)
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const cag_option *cag_option_find_by_letter(cag_option_context *context,
|
||||
char letter)
|
||||
{
|
||||
const cag_option *option;
|
||||
size_t i;
|
||||
|
||||
// We loop over all the available options and stop as soon as we have found
|
||||
// one. We don't use any look up table, since there won't be that many
|
||||
// arguments anyway.
|
||||
for (i = 0; i < context->option_count; ++i)
|
||||
{
|
||||
option = &context->options[i];
|
||||
|
||||
// If this option doesn't have any access letters we will skip them.
|
||||
if (option->access_letters == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify whether this option has the access letter in it's access letter
|
||||
// string. If it does, then this is our option.
|
||||
if (strchr(option->access_letters, letter) != NULL)
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cag_option_parse_value(cag_option_context *context,
|
||||
const cag_option *option, char **c)
|
||||
{
|
||||
// And now let's check whether this option is supposed to have a value, which
|
||||
// is the case if there is a value name set. The value can be either submitted
|
||||
// with a '=' sign or a space, which means we would have to jump over to the
|
||||
// next argv index. This is somewhat ugly, but we do it to behave the same as
|
||||
// the other option parsers.
|
||||
if (option->value_name != NULL)
|
||||
{
|
||||
if (**c == '=')
|
||||
{
|
||||
context->value = ++(*c);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the next index is larger or equal to the argument count, then the
|
||||
// parameter for this option is missing. The user will know about this,
|
||||
// since the value pointer of the context will be NULL because we don't
|
||||
// set it here in that case.
|
||||
if (context->argc > context->index + 1)
|
||||
{
|
||||
// We consider this argv to be the value, no matter what the contents
|
||||
// are.
|
||||
++context->index;
|
||||
*c = context->argv[context->index];
|
||||
context->value = *c;
|
||||
}
|
||||
}
|
||||
|
||||
// Move c to the end of the value, to not confuse the caller about our
|
||||
// position.
|
||||
while (**c)
|
||||
{
|
||||
++(*c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cag_option_parse_access_name(cag_option_context *context, char **c)
|
||||
{
|
||||
const cag_option *option;
|
||||
char *n;
|
||||
|
||||
// Now we need to extract the access name, which is any symbol up to a '=' or
|
||||
// a '\0'.
|
||||
n = *c;
|
||||
while (**c && **c != '=')
|
||||
{
|
||||
++*c;
|
||||
}
|
||||
|
||||
// Now this will obviously always be true, but we are paranoid. Sometimes. It
|
||||
// doesn't hurt to check.
|
||||
assert(*c >= n);
|
||||
|
||||
// Figure out which option this name belongs to. This might return NULL if the
|
||||
// name is not registered, which means the user supplied an unknown option. In
|
||||
// that case we return true to indicate that we finished with this option. We
|
||||
// have to skip the value parsing since we don't know whether the user thinks
|
||||
// this option has one or not. Since we don't set any identifier specifically,
|
||||
// it will remain '?' within the context.
|
||||
option = cag_option_find_by_name(context, n, (size_t)(*c - n));
|
||||
if (option == NULL)
|
||||
{
|
||||
// Since this option is invalid, we will move on to the next index. There is
|
||||
// nothing we can do about this.
|
||||
++context->index;
|
||||
return;
|
||||
}
|
||||
|
||||
// We found an option and now we can specify the identifier within the
|
||||
// context.
|
||||
context->identifier = option->identifier;
|
||||
|
||||
// And now we try to parse the value. This function will also check whether
|
||||
// this option is actually supposed to have a value.
|
||||
cag_option_parse_value(context, option, c);
|
||||
|
||||
// And finally we move on to the next index.
|
||||
++context->index;
|
||||
}
|
||||
|
||||
static void cag_option_parse_access_letter(cag_option_context *context,
|
||||
char **c)
|
||||
{
|
||||
const cag_option *option;
|
||||
char *n = *c;
|
||||
char *v;
|
||||
|
||||
// Figure out which option this letter belongs to. This might return NULL if
|
||||
// the letter is not registered, which means the user supplied an unknown
|
||||
// option. In that case we return true to indicate that we finished with this
|
||||
// option. We have to skip the value parsing since we don't know whether the
|
||||
// user thinks this option has one or not. Since we don't set any identifier
|
||||
// specifically, it will remain '?' within the context.
|
||||
option = cag_option_find_by_letter(context, n[context->inner_index]);
|
||||
if (option == NULL)
|
||||
{
|
||||
++context->index;
|
||||
context->inner_index = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// We found an option and now we can specify the identifier within the
|
||||
// context.
|
||||
context->identifier = option->identifier;
|
||||
|
||||
// And now we try to parse the value. This function will also check whether
|
||||
// this option is actually supposed to have a value.
|
||||
v = &n[++context->inner_index];
|
||||
cag_option_parse_value(context, option, &v);
|
||||
|
||||
// Check whether we reached the end of this option argument.
|
||||
if (*v == '\0')
|
||||
{
|
||||
++context->index;
|
||||
context->inner_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void cag_option_shift(cag_option_context *context, int start, int option,
|
||||
int end)
|
||||
{
|
||||
char *tmp;
|
||||
int a_index, shift_index, shift_count, left_index, right_index;
|
||||
|
||||
shift_count = option - start;
|
||||
|
||||
// There is no shift is required if the start and the option have the same
|
||||
// index.
|
||||
if (shift_count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Lets loop through the option strings first, which we will move towards the
|
||||
// beginning.
|
||||
for (a_index = option; a_index < end; ++a_index)
|
||||
{
|
||||
// First remember the current option value, because we will have to save
|
||||
// that later at the beginning.
|
||||
tmp = context->argv[a_index];
|
||||
|
||||
// Let's loop over all option values and shift them one towards the end.
|
||||
// This will override the option value we just stored temporarily.
|
||||
for (shift_index = 0; shift_index < shift_count; ++shift_index)
|
||||
{
|
||||
left_index = a_index - shift_index;
|
||||
right_index = a_index - shift_index - 1;
|
||||
context->argv[left_index] = context->argv[right_index];
|
||||
}
|
||||
|
||||
// Now restore the saved option value at the beginning.
|
||||
context->argv[a_index - shift_count] = tmp;
|
||||
}
|
||||
|
||||
// The new index will be before all non-option values, in such a way that they
|
||||
// all will be moved again in the next fetch call.
|
||||
context->index = end - shift_count;
|
||||
}
|
||||
|
||||
static bool cag_option_is_argument_string(const char *c)
|
||||
{
|
||||
return *c == '-' && *(c + 1) != '\0';
|
||||
}
|
||||
|
||||
static int cag_option_find_next(cag_option_context *context)
|
||||
{
|
||||
int next_index, next_option_index;
|
||||
char *c;
|
||||
|
||||
// Prepare to search the next option at the next index.
|
||||
next_index = context->index;
|
||||
next_option_index = next_index;
|
||||
|
||||
// Grab a pointer to the string and verify that it is not the end. If it is
|
||||
// the end, we have to return false to indicate that we finished.
|
||||
c = context->argv[next_option_index];
|
||||
if (context->forced_end || c == NULL || (uintptr_t)c == (uintptr_t)0xfffffffffffff000 /* TODO: workaround */)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check whether it is a '-'. We need to find the next option - and an option
|
||||
// always starts with a '-'. If there is a string "-\0", we don't consider it
|
||||
// as an option neither.
|
||||
while (!cag_option_is_argument_string(c))
|
||||
{
|
||||
c = context->argv[++next_option_index];
|
||||
if (c == NULL)
|
||||
{
|
||||
// We reached the end and did not find any argument anymore. Let's tell
|
||||
// our caller that we reached the end.
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate that we found an option which can be processed. The index of the
|
||||
// next option will be returned.
|
||||
return next_option_index;
|
||||
}
|
||||
|
||||
bool cag_option_fetch(cag_option_context *context)
|
||||
{
|
||||
char *c;
|
||||
int old_index, new_index;
|
||||
|
||||
// Reset our identifier to a question mark, which indicates an "unknown"
|
||||
// option. The value is set to NULL, to make sure we are not carrying the
|
||||
// parameter from the previous option to this one.
|
||||
context->identifier = '?';
|
||||
context->value = NULL;
|
||||
|
||||
// Check whether there are any options left to parse and remember the old
|
||||
// index as well as the new index. In the end we will move the option junk to
|
||||
// the beginning, so that non option arguments can be read.
|
||||
old_index = context->index;
|
||||
new_index = cag_option_find_next(context);
|
||||
if (new_index >= 0)
|
||||
{
|
||||
context->index = new_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab a pointer to the beginning of the option. At this point, the next
|
||||
// character must be a '-', since if it was not the prepare function would
|
||||
// have returned false. We will skip that symbol and proceed.
|
||||
c = context->argv[context->index];
|
||||
assert(*c == '-');
|
||||
++c;
|
||||
|
||||
// Check whether this is a long option, starting with a double "--".
|
||||
if (*c == '-')
|
||||
{
|
||||
++c;
|
||||
|
||||
// This might be a double "--" which indicates the end of options. If this
|
||||
// is the case, we will not move to the next index. That ensures that
|
||||
// another call to the fetch function will not skip the "--".
|
||||
if (*c == '\0')
|
||||
{
|
||||
context->forced_end = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We parse now the access name. All information about it will be written
|
||||
// to the context.
|
||||
cag_option_parse_access_name(context, &c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is no long option, so we can just parse an access letter.
|
||||
cag_option_parse_access_letter(context, &c);
|
||||
}
|
||||
|
||||
// Move the items so that the options come first followed by non-option
|
||||
// arguments.
|
||||
cag_option_shift(context, old_index, new_index, context->index);
|
||||
|
||||
return context->forced_end == false;
|
||||
}
|
||||
|
||||
char cag_option_get(const cag_option_context *context)
|
||||
{
|
||||
// We just return the identifier here.
|
||||
return context->identifier;
|
||||
}
|
||||
|
||||
const char *cag_option_get_value(const cag_option_context *context)
|
||||
{
|
||||
// We just return the internal value pointer of the context.
|
||||
return context->value;
|
||||
}
|
||||
|
||||
int cag_option_get_index(const cag_option_context *context)
|
||||
{
|
||||
// Either we point to a value item,
|
||||
return context->index;
|
||||
}
|
1120
Kernel/library/convert.cpp
Normal file
1120
Kernel/library/convert.cpp
Normal file
File diff suppressed because it is too large
Load Diff
96
Kernel/library/crc32.c
Normal file
96
Kernel/library/crc32.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <crc32.h>
|
||||
|
||||
uint32_t LookupTable[256] =
|
||||
{
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
|
||||
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
|
||||
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
|
||||
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
||||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
||||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
|
||||
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
|
||||
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
||||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
|
||||
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
|
||||
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
||||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
||||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
|
||||
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
|
||||
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
||||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
||||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
|
||||
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
|
||||
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
||||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
|
||||
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
|
||||
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
||||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
||||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
|
||||
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
|
||||
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
||||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
|
||||
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
|
||||
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
||||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
||||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
|
||||
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
|
||||
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
||||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
||||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
|
||||
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
|
||||
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
||||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
|
||||
|
||||
uint32_t crc32(const uint8_t *Buffer, int Length)
|
||||
{
|
||||
uint32_t ret = 0xffffffff;
|
||||
while (Length--)
|
||||
{
|
||||
ret = (ret << 8) ^ LookupTable[((ret >> 24) ^ *Buffer) & 255];
|
||||
Buffer++;
|
||||
}
|
||||
return ret;
|
||||
}
|
1507
Kernel/library/cwalk.c
Normal file
1507
Kernel/library/cwalk.c
Normal file
File diff suppressed because it is too large
Load Diff
30
Kernel/library/cwalk_path_style.cpp
Normal file
30
Kernel/library/cwalk_path_style.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cwalk.h>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
__aligned(16) static cwk_path_style path_style = CWK_STYLE_UNIX;
|
||||
|
||||
EXTERNC cwk_path_style *__cwalk_path_style(void)
|
||||
{
|
||||
if (unlikely(!TaskManager || !thisThread))
|
||||
return &path_style;
|
||||
return &thisThread->Info.PathStyle;
|
||||
}
|
88
Kernel/library/dumper.cpp
Normal file
88
Kernel/library/dumper.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dumper.hpp"
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <printf.h>
|
||||
#include <uart.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <md5.h>
|
||||
|
||||
NewLock(DumperLock);
|
||||
|
||||
using namespace UniversalAsynchronousReceiverTransmitter;
|
||||
|
||||
int vprintf_dumper(const char *format, va_list list) { return vfctprintf(uart_wrapper, NULL, format, list); }
|
||||
|
||||
void WriteRaw(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf_dumper(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void DumpData(const char *Description, void *Address, unsigned long Length)
|
||||
{
|
||||
if (Length == 0)
|
||||
return;
|
||||
|
||||
SmartLock(DumperLock);
|
||||
WriteRaw("-------------------------------------------------------------------------\n");
|
||||
unsigned char *AddressChar = (unsigned char *)Address;
|
||||
unsigned char Buffer[17];
|
||||
unsigned long Iterate;
|
||||
|
||||
if (Description != nullptr)
|
||||
WriteRaw("%s (%d bytes):\n", Description, Length);
|
||||
|
||||
for (Iterate = 0; Iterate < Length; Iterate++)
|
||||
{
|
||||
if ((Iterate % 16) == 0)
|
||||
{
|
||||
if (Iterate != 0)
|
||||
WriteRaw(" %s\n", Buffer);
|
||||
WriteRaw(" %04x ", Iterate);
|
||||
}
|
||||
|
||||
WriteRaw(" %02x", AddressChar[Iterate]);
|
||||
|
||||
if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e))
|
||||
Buffer[Iterate % 16] = '.';
|
||||
else
|
||||
Buffer[Iterate % 16] = AddressChar[Iterate];
|
||||
|
||||
Buffer[(Iterate % 16) + 1] = '\0';
|
||||
}
|
||||
|
||||
while ((Iterate % 16) != 0)
|
||||
{
|
||||
WriteRaw(" ");
|
||||
Iterate++;
|
||||
}
|
||||
|
||||
WriteRaw(" %s\n", Buffer);
|
||||
WriteRaw("-------------------------------------------------------------------------\n");
|
||||
WriteRaw("Length: %ld bytes\n", Length);
|
||||
uint8_t *result = md5File(AddressChar, Length);
|
||||
WriteRaw("MD5: ");
|
||||
for (int i = 0; i < 16; i++)
|
||||
WriteRaw("%02x", result[i]);
|
||||
kfree(result);
|
||||
WriteRaw("\n-------------------------------------------------------------------------\n");
|
||||
}
|
254
Kernel/library/kexcept/cxxabi.cpp
Normal file
254
Kernel/library/kexcept/cxxabi.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <kexcept/cxxabi.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
extern "C" _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception);
|
||||
|
||||
using namespace __cxxabiv1;
|
||||
|
||||
atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
|
||||
uarch_t __atexit_func_count = 0;
|
||||
|
||||
__cxa_eh_globals *__cxa_get_globals() noexcept
|
||||
{
|
||||
return &GetCurrentCPU()->Exception.globals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param f The destructor
|
||||
* @param objptr The object to be destructed
|
||||
* @param dso The DSO from which the object was obtained (unused in our case)
|
||||
* @return Zero on success, non-zero on failure
|
||||
*/
|
||||
extern "C" int __cxa_atexit(void (*f)(void *), void *objptr, void *dso)
|
||||
{
|
||||
if (KernelSymbolTable)
|
||||
{
|
||||
debug("Registering atexit function for \"%s\" with destructor \"%s\"",
|
||||
KernelSymbolTable->GetSymbol((uintptr_t)objptr),
|
||||
KernelSymbolTable->GetSymbol((uintptr_t)f));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Registering atexit function for %p with destructor %p",
|
||||
objptr, f);
|
||||
}
|
||||
|
||||
if (__atexit_func_count >= ATEXIT_MAX_FUNCS)
|
||||
return -1;
|
||||
__atexit_funcs[__atexit_func_count].destructor_func = f;
|
||||
__atexit_funcs[__atexit_func_count].obj_ptr = objptr;
|
||||
__atexit_funcs[__atexit_func_count].dso_handle = dso;
|
||||
__atexit_func_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_finalize(void *f)
|
||||
{
|
||||
func("%p", f);
|
||||
uarch_t i = __atexit_func_count;
|
||||
if (f == nullptr)
|
||||
{
|
||||
while (i--)
|
||||
{
|
||||
if (__atexit_funcs[i].destructor_func)
|
||||
{
|
||||
if (KernelSymbolTable)
|
||||
{
|
||||
debug("Calling atexit function \"%s\"",
|
||||
KernelSymbolTable->GetSymbol((uintptr_t)__atexit_funcs[i].destructor_func));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Calling atexit function %p",
|
||||
__atexit_funcs[i].destructor_func);
|
||||
}
|
||||
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (i--)
|
||||
{
|
||||
if (__atexit_funcs[i].destructor_func == f)
|
||||
{
|
||||
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
||||
__atexit_funcs[i].destructor_func = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context)
|
||||
{
|
||||
fixme("__gxx_personality_v0( %d %p %p %p %p ) called.", version, actions, exception_class, ue_header, context);
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
extern "C" void *__cxa_begin_catch(void *thrown_object) noexcept
|
||||
{
|
||||
func("%p", thrown_object);
|
||||
|
||||
__cxa_exception *Exception = (__cxa_exception *)thrown_object - 1;
|
||||
__cxa_eh_globals *Globals = __cxa_get_globals();
|
||||
|
||||
Exception->handlerCount++;
|
||||
Globals->uncaughtExceptions--;
|
||||
|
||||
Exception->nextException = Globals->caughtExceptions;
|
||||
Globals->caughtExceptions = Exception;
|
||||
return Exception + 1;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_end_catch()
|
||||
{
|
||||
fixme("__cxa_end_catch() called.");
|
||||
}
|
||||
|
||||
static __always_inline inline size_t align_exception_allocation_size(size_t a, size_t b)
|
||||
{
|
||||
return (a + b - 1) & ~(b - 1);
|
||||
}
|
||||
|
||||
static __always_inline inline void INIT_EXCEPTION_CLASS(_Unwind_Exception_Class *c)
|
||||
{
|
||||
char *ptr = (char *)c;
|
||||
ptr[0] = 'G';
|
||||
ptr[1] = 'N';
|
||||
ptr[2] = 'U';
|
||||
ptr[3] = 'C';
|
||||
ptr[4] = 'C';
|
||||
ptr[5] = '+';
|
||||
ptr[6] = '+';
|
||||
ptr[7] = '\0';
|
||||
}
|
||||
|
||||
void unexpected_header_stub() { fixme("unexpected() called."); }
|
||||
|
||||
void terminate_header_stub()
|
||||
{
|
||||
if (TaskManager && !TaskManager->IsPanic())
|
||||
{
|
||||
TaskManager->KillThread(thisThread, Tasking::KILL_CXXABI_EXCEPTION);
|
||||
TaskManager->Yield();
|
||||
}
|
||||
|
||||
error("No task manager to kill thread!");
|
||||
CPU::Stop(); /* FIXME: Panic */
|
||||
}
|
||||
|
||||
void exception_cleanup_stub(_Unwind_Reason_Code Code,
|
||||
_Unwind_Exception *Exception)
|
||||
{
|
||||
fixme("exception_cleanup( %d %p ) called.",
|
||||
Code, Exception);
|
||||
}
|
||||
|
||||
extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw()
|
||||
{
|
||||
debug("Allocating exception of size %d.", thrown_size);
|
||||
|
||||
size_t alloc_size = align_exception_allocation_size(thrown_size + sizeof(__cxa_exception), alignof(__cxa_exception));
|
||||
__cxa_exception *Exception = (__cxa_exception *)kmalloc(alloc_size);
|
||||
memset(Exception, 0, alloc_size);
|
||||
return Exception + 1;
|
||||
}
|
||||
|
||||
extern "C" __noreturn void __cxa_throw(void *thrown_object,
|
||||
std::type_info *tinfo,
|
||||
void (*dest)(void *))
|
||||
{
|
||||
trace("Throwing exception of type \"%s\". ( object: %p, destructor: %p )",
|
||||
tinfo->name(), thrown_object, dest);
|
||||
|
||||
__cxa_eh_globals *Globals = __cxa_get_globals();
|
||||
Globals->uncaughtExceptions++;
|
||||
|
||||
__cxa_exception *Exception = (__cxa_exception *)thrown_object - 1;
|
||||
Exception->exceptionType = (std::type_info *)tinfo;
|
||||
Exception->exceptionDestructor = dest;
|
||||
Exception->unexpectedHandler = &unexpected_header_stub;
|
||||
Exception->terminateHandler = &terminate_header_stub;
|
||||
Exception->unwindHeader.exception_cleanup = &exception_cleanup_stub;
|
||||
INIT_EXCEPTION_CLASS(&Exception->unwindHeader.exception_class);
|
||||
Exception->adjustedPtr = thrown_object;
|
||||
|
||||
_Unwind_RaiseException(&Exception->unwindHeader);
|
||||
__cxa_begin_catch(&Exception->unwindHeader);
|
||||
|
||||
error("Uncaught exception!");
|
||||
CPU::Stop(); /* FIXME: Panic */
|
||||
}
|
||||
|
||||
extern "C" void __cxa_rethrow()
|
||||
{
|
||||
fixme("__cxa_rethrow() called.");
|
||||
}
|
||||
|
||||
extern "C" void __cxa_pure_virtual()
|
||||
{
|
||||
fixme("__cxa_pure_virtual() called.");
|
||||
}
|
||||
|
||||
extern "C" void __cxa_throw_bad_array_new_length()
|
||||
{
|
||||
fixme("__cxa_throw_bad_array_new_length() called.");
|
||||
}
|
||||
|
||||
extern "C" void __cxa_free_exception(void *thrown_exception)
|
||||
{
|
||||
fixme("__cxa_free_exception( %p ) called.",
|
||||
thrown_exception);
|
||||
}
|
||||
|
||||
__extension__ typedef int __guard __attribute__((mode(__DI__)));
|
||||
|
||||
extern "C" int __cxa_guard_acquire(__guard *g)
|
||||
{
|
||||
fixme("__cxa_guard_acquire( %p ) called.", g);
|
||||
return !*(char *)(g);
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_release(__guard *g)
|
||||
{
|
||||
fixme("__cxa_guard_release( %p ) called.", g);
|
||||
*(char *)g = 1;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_abort(__guard *g)
|
||||
{
|
||||
fixme("__cxa_guard_abort( %p ) called.", g);
|
||||
}
|
||||
|
||||
extern "C" __noreturn void __cxa_bad_typeid()
|
||||
{
|
||||
fixme("__cxa_bad_typeid() called.");
|
||||
CPU::Stop(); /* FIXME: Crash the system */
|
||||
}
|
||||
|
||||
extern "C" void *__cxa_get_exception_ptr(void *exceptionObject)
|
||||
{
|
||||
stub;
|
||||
return nullptr;
|
||||
}
|
25
Kernel/library/kexcept/dso.c
Normal file
25
Kernel/library/kexcept/dso.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
void __dso_handle_stub()
|
||||
{
|
||||
stub;
|
||||
}
|
||||
|
||||
/* extern */ void *__dso_handle = (void *)&__dso_handle_stub;
|
47
Kernel/library/kexcept/unwind.cpp
Normal file
47
Kernel/library/kexcept/unwind.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <kexcept/unwind.h>
|
||||
#include <kexcept/cxxabi.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
#include <smp.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace __cxxabiv1;
|
||||
|
||||
#if (1) /* Set to 0 to use a library or 1 to use this code */
|
||||
|
||||
extern "C" _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *object)
|
||||
{
|
||||
stub;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
extern "C" void _Unwind_Resume(struct _Unwind_Exception *object)
|
||||
{
|
||||
stub;
|
||||
}
|
||||
|
||||
extern "C" _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *exception_object)
|
||||
{
|
||||
stub;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
#endif // 0 or 1
|
103
Kernel/library/libstdc++/class_type_info.cpp
Normal file
103
Kernel/library/libstdc++/class_type_info.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
#include <debug.h>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
__class_type_info::~__class_type_info() {}
|
||||
|
||||
bool __class_type_info::__do_upcast(const __class_type_info *Destination,
|
||||
const void *Object,
|
||||
__upcast_result &__restrict Result) const
|
||||
{
|
||||
if (*this != *Destination)
|
||||
return false;
|
||||
|
||||
Result.dst_ptr = Object;
|
||||
Result.base_type = nonvirtual_base_type;
|
||||
Result.part2dst = __contained_public;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool __class_type_info::__do_upcast(const __class_type_info *DestinationType,
|
||||
void **ObjectPointer) const
|
||||
{
|
||||
__upcast_result Result(__vmi_class_type_info::__flags_unknown_mask);
|
||||
|
||||
__do_upcast(DestinationType, *ObjectPointer, Result);
|
||||
|
||||
if (!((Result.part2dst &
|
||||
__class_type_info::__contained_public) ==
|
||||
__class_type_info::__contained_public))
|
||||
return false;
|
||||
|
||||
*ObjectPointer = const_cast<void *>(Result.dst_ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool __class_type_info::__do_catch(const type_info *ThrowType,
|
||||
void **ThrowObject,
|
||||
unsigned Outer) const
|
||||
{
|
||||
if (*this == *ThrowType)
|
||||
return true;
|
||||
|
||||
if (Outer >= 4)
|
||||
return false;
|
||||
|
||||
return ThrowType->__do_upcast(this, ThrowObject);
|
||||
}
|
||||
|
||||
bool __class_type_info::__do_dyncast(ptrdiff_t,
|
||||
__sub_kind AccessPath,
|
||||
const __class_type_info *DestinationType,
|
||||
const void *ObjectPointer,
|
||||
const __class_type_info *SourceType,
|
||||
const void *SourcePointer,
|
||||
__dyncast_result &__restrict Result) const
|
||||
{
|
||||
if (ObjectPointer == SourcePointer &&
|
||||
*this == *SourceType)
|
||||
{
|
||||
Result.whole2src = AccessPath;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*this == *DestinationType)
|
||||
{
|
||||
Result.dst_ptr = ObjectPointer;
|
||||
Result.whole2dst = AccessPath;
|
||||
Result.dst2src = __not_contained;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
__class_type_info::__sub_kind __class_type_info::__do_find_public_src(ptrdiff_t,
|
||||
const void *ObjectPointer,
|
||||
const __class_type_info *,
|
||||
const void *SourcePointer) const
|
||||
{
|
||||
if (SourcePointer == ObjectPointer)
|
||||
return __contained_public;
|
||||
|
||||
return __not_contained;
|
||||
}
|
||||
}
|
23
Kernel/library/libstdc++/fundamental_type_info.cpp
Normal file
23
Kernel/library/libstdc++/fundamental_type_info.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
__fundamental_type_info::~__fundamental_type_info() {}
|
||||
}
|
91
Kernel/library/libstdc++/pbase_type_info.cpp
Normal file
91
Kernel/library/libstdc++/pbase_type_info.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
__pbase_type_info::~__pbase_type_info() {}
|
||||
|
||||
bool __pbase_type_info::__do_catch(const type_info *ThrowType,
|
||||
void **ThrowObject,
|
||||
unsigned outer) const
|
||||
{
|
||||
#ifndef __GXX_RTTI
|
||||
UNUSED(ThrowType);
|
||||
UNUSED(ThrowObject);
|
||||
UNUSED(outer);
|
||||
return false;
|
||||
#else
|
||||
if (*this == *ThrowType)
|
||||
return true;
|
||||
|
||||
if (*ThrowType == typeid(nullptr))
|
||||
{
|
||||
if (typeid(*this) == typeid(__pointer_type_info))
|
||||
{
|
||||
*ThrowObject = nullptr;
|
||||
return true;
|
||||
}
|
||||
else if (typeid(*this) == typeid(__pointer_to_member_type_info))
|
||||
{
|
||||
if (this->Pointee->__is_function_p())
|
||||
{
|
||||
using pmf_type = void (__pbase_type_info::*)();
|
||||
static const pmf_type pmf = nullptr;
|
||||
*ThrowObject = const_cast<pmf_type *>(&pmf);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
using pm_type = int __pbase_type_info::*;
|
||||
static const pm_type pm = nullptr;
|
||||
*ThrowObject = const_cast<pm_type *>(&pm);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeid(*this) != typeid(*ThrowType))
|
||||
return false;
|
||||
|
||||
if (!(outer & 1))
|
||||
return false;
|
||||
|
||||
const __pbase_type_info *ThrownType =
|
||||
static_cast<const __pbase_type_info *>(ThrowType);
|
||||
|
||||
unsigned TypeFlags = ThrownType->Flags;
|
||||
|
||||
const unsigned FlagQualificationMask = __transaction_safe_mask | __noexcept_mask;
|
||||
unsigned ThrowFlagQualification = (TypeFlags & FlagQualificationMask);
|
||||
unsigned CatchFlagQualification = (Flags & FlagQualificationMask);
|
||||
if (ThrowFlagQualification & ~CatchFlagQualification)
|
||||
TypeFlags &= CatchFlagQualification;
|
||||
if (CatchFlagQualification & ~ThrowFlagQualification)
|
||||
return false;
|
||||
|
||||
if (TypeFlags & ~Flags)
|
||||
return false;
|
||||
|
||||
if (!(Flags & __const_mask))
|
||||
outer &= ~1;
|
||||
|
||||
return __pointer_catch(ThrownType, ThrowObject, outer);
|
||||
#endif
|
||||
}
|
||||
}
|
45
Kernel/library/libstdc++/pointer_type_info.cpp
Normal file
45
Kernel/library/libstdc++/pointer_type_info.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
__pointer_type_info::~__pointer_type_info() {}
|
||||
|
||||
bool __pointer_type_info::__is_pointer_p() const { return true; }
|
||||
|
||||
bool __pointer_type_info::__pointer_catch(const __pbase_type_info *ThrownType,
|
||||
void **ThrowObject,
|
||||
unsigned Outer) const
|
||||
{
|
||||
#ifndef __GXX_RTTI
|
||||
UNUSED(ThrownType);
|
||||
UNUSED(ThrowObject);
|
||||
UNUSED(Outer);
|
||||
return false;
|
||||
#else
|
||||
if (Outer < 2 && *this->Pointee == typeid(void))
|
||||
return !ThrownType->Pointee->__is_function_p();
|
||||
|
||||
return __pbase_type_info::__pointer_catch(ThrownType,
|
||||
ThrowObject,
|
||||
Outer);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
102
Kernel/library/libstdc++/si_class_type_info.cpp
Normal file
102
Kernel/library/libstdc++/si_class_type_info.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
#include <debug.h>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
template <typename T>
|
||||
inline const T *adjust_pointer(const void *Base,
|
||||
ptrdiff_t Offset)
|
||||
{
|
||||
return reinterpret_cast<const T *>(reinterpret_cast<const char *>(Base) + Offset);
|
||||
}
|
||||
|
||||
__si_class_type_info::~__si_class_type_info() {}
|
||||
|
||||
__class_type_info::__sub_kind __si_class_type_info::
|
||||
__do_find_public_src(ptrdiff_t SourceToDestination,
|
||||
const void *ObjectPointer,
|
||||
const __class_type_info *SourceType,
|
||||
const void *SourcePointer) const
|
||||
{
|
||||
if (SourcePointer == ObjectPointer && *this == *SourceType)
|
||||
return __contained_public;
|
||||
|
||||
return this->BaseType->__do_find_public_src(SourceToDestination,
|
||||
ObjectPointer,
|
||||
SourceType,
|
||||
SourcePointer);
|
||||
}
|
||||
|
||||
bool __si_class_type_info::__do_dyncast(ptrdiff_t SourceToDestination,
|
||||
__sub_kind AccessPath,
|
||||
const __class_type_info *DestinationType,
|
||||
const void *ObjectPointer,
|
||||
const __class_type_info *SourceType,
|
||||
const void *SourcePointer,
|
||||
__dyncast_result &__restrict Result) const
|
||||
{
|
||||
if (*this == *DestinationType)
|
||||
{
|
||||
Result.dst_ptr = ObjectPointer;
|
||||
Result.whole2dst = AccessPath;
|
||||
|
||||
if (SourceToDestination == -2)
|
||||
{
|
||||
Result.dst2src = __not_contained;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SourceToDestination >= 0)
|
||||
{
|
||||
Result.dst2src = adjust_pointer<void>(ObjectPointer,
|
||||
SourceToDestination) == SourcePointer
|
||||
? __contained_public
|
||||
: __not_contained;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ObjectPointer == SourcePointer &&
|
||||
*this == *SourceType)
|
||||
{
|
||||
Result.whole2src = AccessPath;
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->BaseType->__do_dyncast(SourceToDestination,
|
||||
AccessPath,
|
||||
DestinationType,
|
||||
ObjectPointer,
|
||||
SourceType,
|
||||
SourcePointer,
|
||||
Result);
|
||||
}
|
||||
|
||||
bool __si_class_type_info::__do_upcast(const __class_type_info *Destination,
|
||||
const void *ObjectPointer,
|
||||
__upcast_result &__restrict Result) const
|
||||
{
|
||||
if (__class_type_info::__do_upcast(Destination, ObjectPointer, Result))
|
||||
return true;
|
||||
|
||||
return this->BaseType->__do_upcast(Destination, ObjectPointer, Result);
|
||||
}
|
||||
}
|
42
Kernel/library/libstdc++/vmi_class_type_info.cpp
Normal file
42
Kernel/library/libstdc++/vmi_class_type_info.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
#include <debug.h>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
__vmi_class_type_info::~__vmi_class_type_info()
|
||||
{
|
||||
}
|
||||
|
||||
void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
|
||||
{
|
||||
if (__do_upcast(other, &obj))
|
||||
return obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool __vmi_class_type_info::__do_upcast(const __class_type_info *target, void **thrown_object) const
|
||||
{
|
||||
if (this == target)
|
||||
return true;
|
||||
|
||||
stub;
|
||||
return 0;
|
||||
}
|
||||
}
|
257
Kernel/library/md5.c
Normal file
257
Kernel/library/md5.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
|
||||
* and modified slightly to be functionally identical but condensed into control structures.
|
||||
*/
|
||||
|
||||
#include <md5.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <convert.h>
|
||||
|
||||
/*
|
||||
* Constants defined by the MD5 algorithm
|
||||
*/
|
||||
#define A 0x67452301
|
||||
#define B 0xefcdab89
|
||||
#define C 0x98badcfe
|
||||
#define D 0x10325476
|
||||
|
||||
static uint32_t S[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
|
||||
|
||||
static uint32_t K[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
|
||||
|
||||
/*
|
||||
* Bit-manipulation functions defined by the MD5 algorithm
|
||||
*/
|
||||
#define F(X, Y, Z) ((X & Y) | (~X & Z))
|
||||
#define G(X, Y, Z) ((X & Z) | (Y & ~Z))
|
||||
#define H(X, Y, Z) (X ^ Y ^ Z)
|
||||
#define I(X, Y, Z) (Y ^ (X | ~Z))
|
||||
|
||||
/*
|
||||
* Padding used to make the size (in bits) of the input congruent to 448 mod 512
|
||||
*/
|
||||
static uint8_t PADDING[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
/*
|
||||
* Initialize a context
|
||||
*/
|
||||
void md5Init(MD5Context *ctx)
|
||||
{
|
||||
ctx->size = (uint64_t)0;
|
||||
|
||||
ctx->buffer[0] = (uint32_t)A;
|
||||
ctx->buffer[1] = (uint32_t)B;
|
||||
ctx->buffer[2] = (uint32_t)C;
|
||||
ctx->buffer[3] = (uint32_t)D;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add some amount of input to the context
|
||||
*
|
||||
* If the input fills out a block of 512 bits, apply the algorithm (md5Step)
|
||||
* and save the result in the buffer. Also updates the overall size.
|
||||
*/
|
||||
void md5Update(MD5Context *ctx, uint8_t *input_buffer, size_t input_len)
|
||||
{
|
||||
uint32_t input[16];
|
||||
unsigned int offset = ctx->size % 64;
|
||||
ctx->size += (uint64_t)input_len;
|
||||
|
||||
// Copy each byte in input_buffer into the next space in our context input
|
||||
for (unsigned int i = 0; i < input_len; ++i)
|
||||
{
|
||||
ctx->input[offset++] = (uint8_t) * (input_buffer + i);
|
||||
|
||||
// If we've filled our context input, copy it into our local array input
|
||||
// then reset the offset to 0 and fill in a new buffer.
|
||||
// Every time we fill out a chunk, we run it through the algorithm
|
||||
// to enable some back and forth between cpu and i/o
|
||||
if (offset % 64 == 0)
|
||||
{
|
||||
for (unsigned int j = 0; j < 16; ++j)
|
||||
{
|
||||
// Convert to little-endian
|
||||
// The local variable `input` our 512-bit chunk separated into 32-bit words
|
||||
// we can use in calculations
|
||||
input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
|
||||
(uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
|
||||
(uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
|
||||
(uint32_t)(ctx->input[(j * 4)]);
|
||||
}
|
||||
md5Step(ctx->buffer, input);
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pad the current input to get to 448 bytes, append the size in bits to the very end,
|
||||
* and save the result of the final iteration into digest.
|
||||
*/
|
||||
void md5Finalize(MD5Context *ctx)
|
||||
{
|
||||
uint32_t input[16];
|
||||
unsigned int offset = ctx->size % 64;
|
||||
unsigned int padding_length = offset < 56 ? 56 - offset : (56 + 64) - offset;
|
||||
|
||||
// Fill in the padding and do the changes to size that resulted from the update
|
||||
md5Update(ctx, PADDING, padding_length);
|
||||
ctx->size -= (uint64_t)padding_length;
|
||||
|
||||
// Do a final update (internal to this function)
|
||||
// Last two 32-bit words are the two halves of the size (converted from bytes to bits)
|
||||
for (unsigned int j = 0; j < 14; ++j)
|
||||
{
|
||||
input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
|
||||
(uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
|
||||
(uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
|
||||
(uint32_t)(ctx->input[(j * 4)]);
|
||||
}
|
||||
input[14] = (uint32_t)(ctx->size * 8);
|
||||
#ifdef a32
|
||||
input[15] = (uint32_t)((uint64_t)(((uint64_t)ctx->size >> 32) | ((uint64_t)ctx->size << 32)) >> 32);
|
||||
#else
|
||||
input[15] = (uint32_t)((ctx->size * 8) >> 32);
|
||||
#endif
|
||||
|
||||
md5Step(ctx->buffer, input);
|
||||
|
||||
// Move the result into digest (convert from little-endian)
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
ctx->digest[(i * 4) + 0] = (uint8_t)((ctx->buffer[i] & 0x000000FF));
|
||||
ctx->digest[(i * 4) + 1] = (uint8_t)((ctx->buffer[i] & 0x0000FF00) >> 8);
|
||||
ctx->digest[(i * 4) + 2] = (uint8_t)((ctx->buffer[i] & 0x00FF0000) >> 16);
|
||||
ctx->digest[(i * 4) + 3] = (uint8_t)((ctx->buffer[i] & 0xFF000000) >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Step on 512 bits of input with the main MD5 algorithm.
|
||||
*/
|
||||
void md5Step(uint32_t *buffer, uint32_t *input)
|
||||
{
|
||||
uint32_t AA = buffer[0];
|
||||
uint32_t BB = buffer[1];
|
||||
uint32_t CC = buffer[2];
|
||||
uint32_t DD = buffer[3];
|
||||
|
||||
uint32_t E;
|
||||
|
||||
unsigned int j;
|
||||
|
||||
for (unsigned int i = 0; i < 64; ++i)
|
||||
{
|
||||
switch (i / 16)
|
||||
{
|
||||
case 0:
|
||||
E = F(BB, CC, DD);
|
||||
j = i;
|
||||
break;
|
||||
case 1:
|
||||
E = G(BB, CC, DD);
|
||||
j = ((i * 5) + 1) % 16;
|
||||
break;
|
||||
case 2:
|
||||
E = H(BB, CC, DD);
|
||||
j = ((i * 3) + 5) % 16;
|
||||
break;
|
||||
default:
|
||||
E = I(BB, CC, DD);
|
||||
j = (i * 7) % 16;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t temp = DD;
|
||||
DD = CC;
|
||||
CC = BB;
|
||||
BB = BB + rotateLeft(AA + E + K[i] + input[j], S[i]);
|
||||
AA = temp;
|
||||
}
|
||||
|
||||
buffer[0] += AA;
|
||||
buffer[1] += BB;
|
||||
buffer[2] += CC;
|
||||
buffer[3] += DD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions that will return a pointer to the hash of the provided input
|
||||
*/
|
||||
uint8_t *md5String(char *input)
|
||||
{
|
||||
MD5Context ctx;
|
||||
md5Init(&ctx);
|
||||
md5Update(&ctx, (uint8_t *)input, strlen(input));
|
||||
md5Finalize(&ctx);
|
||||
|
||||
uint8_t *result = kmalloc(16);
|
||||
if (result == NULL)
|
||||
return (uint8_t *)"error";
|
||||
memcpy(result, ctx.digest, 16);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t *md5File(uint8_t *buffer, size_t input_len)
|
||||
{
|
||||
char *input_buffer = (char *)buffer;
|
||||
size_t input_size = input_len;
|
||||
|
||||
MD5Context ctx;
|
||||
md5Init(&ctx);
|
||||
|
||||
while (input_size > 0)
|
||||
{
|
||||
size_t chunk_size = input_size > 1024 ? 1024 : input_size;
|
||||
md5Update(&ctx, (uint8_t *)input_buffer, chunk_size);
|
||||
input_buffer += chunk_size;
|
||||
input_size -= chunk_size;
|
||||
}
|
||||
|
||||
// while ((input_size = fread(input_buffer, 1, 1024, file)) > 0)
|
||||
// {
|
||||
// md5Update(&ctx, (uint8_t *)input_buffer, input_size);
|
||||
// }
|
||||
|
||||
md5Finalize(&ctx);
|
||||
|
||||
uint8_t *result = kmalloc(16);
|
||||
if (result == NULL)
|
||||
return (uint8_t *)"error";
|
||||
memcpy(result, ctx.digest, 16);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotates a 32-bit word left by n bits
|
||||
*/
|
||||
uint32_t rotateLeft(uint32_t x, uint32_t n)
|
||||
{
|
||||
return (x << n) | (x >> (32 - n));
|
||||
}
|
351
Kernel/library/memop.c
Normal file
351
Kernel/library/memop.c
Normal file
@ -0,0 +1,351 @@
|
||||
#include <convert.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <limits.h>
|
||||
#include <debug.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
|
||||
/* Some of the functions are from musl library */
|
||||
/* https://www.musl-libc.org/ */
|
||||
/*
|
||||
Copyright © 2005-2020 Rich Felker, et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void *memcpy_unsafe(void *dest, const void *src, size_t n)
|
||||
{
|
||||
unsigned char *d = dest;
|
||||
const unsigned char *s = src;
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define LS >>
|
||||
#define RS <<
|
||||
#else
|
||||
#define LS <<
|
||||
#define RS >>
|
||||
#endif
|
||||
|
||||
typedef uint32_t __attribute__((__may_alias__)) u32;
|
||||
uint32_t w, x;
|
||||
|
||||
for (; (uintptr_t)s % 4 && n; n--)
|
||||
*d++ = *s++;
|
||||
|
||||
if ((uintptr_t)d % 4 == 0)
|
||||
{
|
||||
for (; n >= 16; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
*(u32 *)(d + 0) = *(u32 *)(s + 0);
|
||||
*(u32 *)(d + 4) = *(u32 *)(s + 4);
|
||||
*(u32 *)(d + 8) = *(u32 *)(s + 8);
|
||||
*(u32 *)(d + 12) = *(u32 *)(s + 12);
|
||||
}
|
||||
if (n & 8)
|
||||
{
|
||||
*(u32 *)(d + 0) = *(u32 *)(s + 0);
|
||||
*(u32 *)(d + 4) = *(u32 *)(s + 4);
|
||||
d += 8;
|
||||
s += 8;
|
||||
}
|
||||
if (n & 4)
|
||||
{
|
||||
*(u32 *)(d + 0) = *(u32 *)(s + 0);
|
||||
d += 4;
|
||||
s += 4;
|
||||
}
|
||||
if (n & 2)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
if (n & 1)
|
||||
{
|
||||
*d = *s;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
if (n >= 32)
|
||||
{
|
||||
switch ((uintptr_t)d % 4)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
w = *(u32 *)s;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
n -= 3;
|
||||
for (; n >= 17; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
x = *(u32 *)(s + 1);
|
||||
*(u32 *)(d + 0) = (w LS 24) | (x RS 8);
|
||||
w = *(u32 *)(s + 5);
|
||||
*(u32 *)(d + 4) = (x LS 24) | (w RS 8);
|
||||
x = *(u32 *)(s + 9);
|
||||
*(u32 *)(d + 8) = (w LS 24) | (x RS 8);
|
||||
w = *(u32 *)(s + 13);
|
||||
*(u32 *)(d + 12) = (x LS 24) | (w RS 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
w = *(u32 *)s;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
n -= 2;
|
||||
for (; n >= 18; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
x = *(u32 *)(s + 2);
|
||||
*(u32 *)(d + 0) = (w LS 16) | (x RS 16);
|
||||
w = *(u32 *)(s + 6);
|
||||
*(u32 *)(d + 4) = (x LS 16) | (w RS 16);
|
||||
x = *(u32 *)(s + 10);
|
||||
*(u32 *)(d + 8) = (w LS 16) | (x RS 16);
|
||||
w = *(u32 *)(s + 14);
|
||||
*(u32 *)(d + 12) = (x LS 16) | (w RS 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
w = *(u32 *)s;
|
||||
*d++ = *s++;
|
||||
n -= 1;
|
||||
for (; n >= 19; s += 16, d += 16, n -= 16)
|
||||
{
|
||||
x = *(u32 *)(s + 3);
|
||||
*(u32 *)(d + 0) = (w LS 8) | (x RS 24);
|
||||
w = *(u32 *)(s + 7);
|
||||
*(u32 *)(d + 4) = (x LS 8) | (w RS 24);
|
||||
x = *(u32 *)(s + 11);
|
||||
*(u32 *)(d + 8) = (w LS 8) | (x RS 24);
|
||||
w = *(u32 *)(s + 15);
|
||||
*(u32 *)(d + 12) = (x LS 8) | (w RS 24);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (n & 16)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
if (n & 8)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
if (n & 4)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
if (n & 2)
|
||||
{
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
if (n & 1)
|
||||
{
|
||||
*d = *s;
|
||||
}
|
||||
return dest;
|
||||
#endif
|
||||
|
||||
for (; n; n--)
|
||||
*d++ = *s++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset_unsafe(void *dest, int c, size_t n)
|
||||
{
|
||||
unsigned char *s = dest;
|
||||
size_t k;
|
||||
|
||||
if (!n)
|
||||
return dest;
|
||||
|
||||
s[0] = c;
|
||||
s[n - 1] = c;
|
||||
|
||||
if (n <= 2)
|
||||
return dest;
|
||||
|
||||
s[1] = c;
|
||||
s[2] = c;
|
||||
s[n - 2] = c;
|
||||
s[n - 3] = c;
|
||||
|
||||
if (n <= 6)
|
||||
return dest;
|
||||
|
||||
s[3] = c;
|
||||
s[n - 4] = c;
|
||||
|
||||
if (n <= 8)
|
||||
return dest;
|
||||
|
||||
k = -(uintptr_t)s & 3;
|
||||
s += k;
|
||||
n -= k;
|
||||
n &= -4;
|
||||
|
||||
#ifdef __GNUC__
|
||||
typedef uint32_t __attribute__((__may_alias__)) u32;
|
||||
typedef uint64_t __attribute__((__may_alias__)) u64;
|
||||
|
||||
u32 c32 = ((u32)-1) / 255 * (unsigned char)c;
|
||||
*(u32 *)(s + 0) = c32;
|
||||
*(u32 *)(s + n - 4) = c32;
|
||||
|
||||
if (n <= 8)
|
||||
return dest;
|
||||
|
||||
*(u32 *)(s + 4) = c32;
|
||||
*(u32 *)(s + 8) = c32;
|
||||
*(u32 *)(s + n - 12) = c32;
|
||||
*(u32 *)(s + n - 8) = c32;
|
||||
|
||||
if (n <= 24)
|
||||
return dest;
|
||||
|
||||
*(u32 *)(s + 12) = c32;
|
||||
*(u32 *)(s + 16) = c32;
|
||||
*(u32 *)(s + 20) = c32;
|
||||
*(u32 *)(s + 24) = c32;
|
||||
*(u32 *)(s + n - 28) = c32;
|
||||
*(u32 *)(s + n - 24) = c32;
|
||||
*(u32 *)(s + n - 20) = c32;
|
||||
*(u32 *)(s + n - 16) = c32;
|
||||
|
||||
k = 24 + ((uintptr_t)s & 4);
|
||||
s += k;
|
||||
n -= k;
|
||||
|
||||
u64 c64 = c32 | ((u64)c32 << 32);
|
||||
for (; n >= 32; n -= 32, s += 32)
|
||||
{
|
||||
*(u64 *)(s + 0) = c64;
|
||||
*(u64 *)(s + 8) = c64;
|
||||
*(u64 *)(s + 16) = c64;
|
||||
*(u64 *)(s + 24) = c64;
|
||||
}
|
||||
#else
|
||||
for (; n; n--, s++)
|
||||
*s = c;
|
||||
#endif
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memmove_unsafe(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
typedef __attribute__((__may_alias__)) size_t WT;
|
||||
#define WS (sizeof(WT))
|
||||
#endif
|
||||
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
|
||||
if (d == s)
|
||||
return d;
|
||||
|
||||
if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n)
|
||||
return memcpy(d, s, n);
|
||||
|
||||
if (d < s)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
|
||||
{
|
||||
while ((uintptr_t)d % WS)
|
||||
{
|
||||
if (!n--)
|
||||
return dest;
|
||||
|
||||
*d++ = *s++;
|
||||
}
|
||||
for (; n >= WS; n -= WS, d += WS, s += WS)
|
||||
*(WT *)d = *(WT *)s;
|
||||
}
|
||||
#endif
|
||||
for (; n; n--)
|
||||
*d++ = *s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
|
||||
{
|
||||
while ((uintptr_t)(d + n) % WS)
|
||||
{
|
||||
if (!n--)
|
||||
return dest;
|
||||
|
||||
d[n] = s[n];
|
||||
}
|
||||
while (n >= WS)
|
||||
n -= WS, *(WT *)(d + n) = *(WT *)(s + n);
|
||||
}
|
||||
#endif
|
||||
while (n)
|
||||
n--, d[n] = s[n];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
1592
Kernel/library/printf.c
Normal file
1592
Kernel/library/printf.c
Normal file
File diff suppressed because it is too large
Load Diff
280
Kernel/library/simd_memcpy.cpp
Normal file
280
Kernel/library/simd_memcpy.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <convert.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <limits.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
|
||||
/*
|
||||
TODO: Replace these functions with even more optimized versions.
|
||||
The current versions are fast but not as fast as they could be and also we need implementation for avx, not only sse.
|
||||
*/
|
||||
|
||||
EXTERNC void *memcpy_sse(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
if ((((uintptr_t)d | (uintptr_t)s) & 0xF) == 0)
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movaps (%0), %%xmm0\n"
|
||||
"movaps %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movups (%0), %%xmm0\n"
|
||||
"movups %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
|
||||
memcpy_unsafe(d, s, n);
|
||||
#endif // defined(a64)
|
||||
return dest;
|
||||
}
|
||||
|
||||
EXTERNC void *memcpy_sse2(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
if ((((uintptr_t)d | (uintptr_t)s) & 0xF) == 0)
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqa (%0), %%xmm0\n"
|
||||
"movdqa %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqu (%0), %%xmm0\n"
|
||||
"movdqu %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
|
||||
memcpy_unsafe(d, s, n);
|
||||
#endif // defined(a64)
|
||||
return dest;
|
||||
}
|
||||
|
||||
EXTERNC void *memcpy_sse3(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
if ((((uintptr_t)d | (uintptr_t)s) & 0xF) == 0)
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqa (%0), %%xmm0\n"
|
||||
"movdqa %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqu (%0), %%xmm0\n"
|
||||
"movdqu %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
|
||||
memcpy_unsafe(d, s, n);
|
||||
#endif // defined(a64)
|
||||
return dest;
|
||||
}
|
||||
|
||||
EXTERNC void *memcpy_ssse3(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
if ((((uintptr_t)d | (uintptr_t)s) & 0xF) == 0)
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("lddqu (%0), %%xmm0\n"
|
||||
"movdqa %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("lddqu (%0), %%xmm0\n"
|
||||
"movdqu %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
|
||||
memcpy_unsafe(d, s, n);
|
||||
#endif // defined(a64)
|
||||
return dest;
|
||||
}
|
||||
|
||||
EXTERNC void *memcpy_sse4_1(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
if ((((uintptr_t)d | (uintptr_t)s) & 0xF) == 0)
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqa (%0), %%xmm0\n"
|
||||
"movdqa %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqu (%0), %%xmm0\n"
|
||||
"movdqu %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
|
||||
memcpy_unsafe(d, s, n);
|
||||
#endif // defined(a64)
|
||||
return dest;
|
||||
}
|
||||
|
||||
EXTERNC void *memcpy_sse4_2(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
if ((((uintptr_t)d | (uintptr_t)s) & 0xF) == 0)
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqa (%0), %%xmm0\n"
|
||||
"movdqa %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movdqu (%0), %%xmm0\n"
|
||||
"movdqu %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(s), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
s += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
|
||||
memcpy_unsafe(d, s, n);
|
||||
#endif // defined(a64)
|
||||
return dest;
|
||||
}
|
60
Kernel/library/simd_memmove.cpp
Normal file
60
Kernel/library/simd_memmove.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <convert.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <limits.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
|
||||
/*
|
||||
TODO: Replace these functions with even more optimized versions.
|
||||
The current versions are fast but not as fast as they could be and also we need implementation for avx, not only sse.
|
||||
*/
|
||||
|
||||
// TODO: Implement these functions
|
||||
|
||||
EXTERNC void *memmove_sse(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memmove_unsafe(dest, src, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memmove_sse2(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memmove_sse(dest, src, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memmove_sse3(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memmove_sse(dest, src, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memmove_ssse3(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memmove_sse(dest, src, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memmove_sse4_1(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memmove_sse(dest, src, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memmove_sse4_2(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memmove_sse(dest, src, n);
|
||||
}
|
114
Kernel/library/simd_memset.cpp
Normal file
114
Kernel/library/simd_memset.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <convert.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <limits.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
|
||||
/*
|
||||
TODO: Replace these functions with even more optimized versions.
|
||||
The current versions are fast but not as fast as they could be and also we need implementation for avx, not only sse.
|
||||
*/
|
||||
|
||||
// TODO: Implement these functions
|
||||
|
||||
EXTERNC void *memset_sse(void *dest, int c, size_t n)
|
||||
{
|
||||
return memset_unsafe(dest, c, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memset_sse2(void *dest, int c, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
if ((size_t)dest & (16 - 1))
|
||||
{
|
||||
i = 0;
|
||||
while (((size_t)dest + i) & (16 - 1) && i < n)
|
||||
{
|
||||
asmv("stosb\n"
|
||||
:
|
||||
: "D"((size_t)dest + i),
|
||||
"a"(c));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
for (; i + 64 <= n; i += 64)
|
||||
{
|
||||
asmv("movd %0, %%xmm0\n"
|
||||
"movdqa %%xmm0, (%1)\n"
|
||||
"movdqa %%xmm0, 16(%1)\n"
|
||||
"movdqa %%xmm0, 32(%1)\n"
|
||||
"movdqa %%xmm0, 48(%1)\n"
|
||||
:
|
||||
: "r"(c), "r"(((size_t)dest) + i)
|
||||
: "xmm0");
|
||||
}
|
||||
|
||||
asmv("rep stosb\n" ::"a"((size_t)(c)),
|
||||
"D"(((size_t)dest) + i),
|
||||
"c"(n - i));
|
||||
|
||||
i += n - i;
|
||||
return (void *)(((size_t)dest) + i);
|
||||
}
|
||||
|
||||
EXTERNC void *memset_sse3(void *dest, int c, size_t n)
|
||||
{
|
||||
return memset_sse2(dest, c, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memset_ssse3(void *dest, int c, size_t n)
|
||||
{
|
||||
return memset_sse2(dest, c, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memset_sse4_1(void *dest, int c, size_t n)
|
||||
{
|
||||
return memset_sse2(dest, c, n);
|
||||
}
|
||||
|
||||
EXTERNC void *memset_sse4_2(void *dest, int c, size_t n)
|
||||
{
|
||||
#if defined(a64)
|
||||
char *d = (char *)dest;
|
||||
|
||||
if (((uintptr_t)d & 0xF) == 0)
|
||||
{
|
||||
size_t num_vectors = n / 16;
|
||||
for (size_t i = 0; i < num_vectors; i++)
|
||||
{
|
||||
asmv("movd %0, %%xmm0\n"
|
||||
"pshufd $0, %%xmm0, %%xmm0\n"
|
||||
"movdqa %%xmm0, (%1)\n"
|
||||
:
|
||||
: "r"(c), "r"(d)
|
||||
: "xmm0");
|
||||
d += 16;
|
||||
}
|
||||
n -= num_vectors * 16;
|
||||
}
|
||||
|
||||
memset_unsafe(d, c, n);
|
||||
#endif
|
||||
return dest;
|
||||
}
|
122
Kernel/library/simd_strlen.cpp
Normal file
122
Kernel/library/simd_strlen.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <convert.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <limits.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
|
||||
/*
|
||||
TODO: Replace these functions with even more optimized versions.
|
||||
The current versions are fast but not as fast as they could be and also we need implementation for avx, not only sse.
|
||||
*/
|
||||
|
||||
long unsigned __strlen(const char s[])
|
||||
{
|
||||
size_t ret = (size_t)s;
|
||||
|
||||
asmv("._strlenLoop:"
|
||||
"cmpb $0, 0(%1)\n"
|
||||
"jz ._strlenExit\n"
|
||||
"cmpb $0, 1(%1)\n"
|
||||
"jz .scmp1\n"
|
||||
"cmpb $0, 2(%1)\n"
|
||||
"jz .scmp2\n"
|
||||
"cmpb $0, 3(%1)\n"
|
||||
"jz .scmp3\n"
|
||||
"cmpb $0, 4(%1)\n"
|
||||
"jz .scmp4\n"
|
||||
"cmpb $0, 5(%1)\n"
|
||||
"jz .scmp5\n"
|
||||
"cmpb $0, 6(%1)\n"
|
||||
"jz .scmp6\n"
|
||||
"cmpb $0, 7(%1)\n"
|
||||
"jz .scmp7\n"
|
||||
|
||||
"add $8, %1\n"
|
||||
"jmp ._strlenLoop\n"
|
||||
|
||||
".scmp1:"
|
||||
"inc %1\n"
|
||||
"jmp ._strlenExit\n"
|
||||
".scmp2:"
|
||||
"add $2, %1\n"
|
||||
"jmp ._strlenExit\n"
|
||||
".scmp3:"
|
||||
"add $3, %1\n"
|
||||
"jmp ._strlenExit\n"
|
||||
".scmp4:"
|
||||
"add $4, %1\n"
|
||||
"jmp ._strlenExit\n"
|
||||
".scmp5:"
|
||||
"add $5, %1\n"
|
||||
"jmp ._strlenExit\n"
|
||||
".scmp6:"
|
||||
"add $6, %1\n"
|
||||
"jmp ._strlenExit\n"
|
||||
".scmp7:"
|
||||
"add $7, %1\n"
|
||||
|
||||
"._strlenExit:"
|
||||
"mov %1, %0\n"
|
||||
: "=r"(ret) : "0"(ret));
|
||||
|
||||
return ret - (size_t)s;
|
||||
}
|
||||
|
||||
long unsigned strlen_sse(const char s[])
|
||||
{
|
||||
return __strlen(s);
|
||||
}
|
||||
|
||||
long unsigned strlen_sse2(const char s[])
|
||||
{
|
||||
return __strlen(s);
|
||||
}
|
||||
|
||||
long unsigned strlen_sse3(const char s[])
|
||||
{
|
||||
return __strlen(s);
|
||||
}
|
||||
|
||||
long unsigned strlen_ssse3(const char s[])
|
||||
{
|
||||
return __strlen(s);
|
||||
}
|
||||
|
||||
long unsigned strlen_sse4_1(const char s[])
|
||||
{
|
||||
return __strlen(s);
|
||||
}
|
||||
|
||||
long unsigned strlen_sse4_2(const char s[])
|
||||
{
|
||||
size_t ret;
|
||||
asmv("mov $-16, %0\n"
|
||||
"pxor %%xmm0, %%xmm0\n"
|
||||
".strlen42Loop:"
|
||||
"add $16, %0\n"
|
||||
"pcmpistri $0x08, (%0,%1), %%xmm0\n"
|
||||
"jnz .strlen42Loop\n"
|
||||
"add %2, %0\n"
|
||||
: "=a"(ret)
|
||||
: "d"((size_t)s), "c"((size_t)s));
|
||||
|
||||
return ret;
|
||||
}
|
209
Kernel/library/std/errno.cpp
Normal file
209
Kernel/library/std/errno.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <types.h>
|
||||
#include <debug.h>
|
||||
#include <atomic>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
__aligned(16) static int errno_value = 0;
|
||||
|
||||
EXTERNC int *__errno_location(void)
|
||||
{
|
||||
if (unlikely(!TaskManager || !thisThread))
|
||||
return &errno_value;
|
||||
return &thisThread->ErrorNumber;
|
||||
}
|
||||
|
||||
char *strerror(int errnum)
|
||||
{
|
||||
if (errnum < 0)
|
||||
errnum = -errnum;
|
||||
|
||||
switch (errnum)
|
||||
{
|
||||
case EOK:
|
||||
return (char *)"No error";
|
||||
case E2BIG:
|
||||
return (char *)"Argument list too long";
|
||||
case EACCES:
|
||||
return (char *)"Permission denied";
|
||||
case EADDRINUSE:
|
||||
return (char *)"Address in use";
|
||||
case EADDRNOTAVAIL:
|
||||
return (char *)"Address not available";
|
||||
case EAFNOSUPPORT:
|
||||
return (char *)"Address family not supported";
|
||||
case EAGAIN:
|
||||
return (char *)"Resource unavailable, try again";
|
||||
case EALREADY:
|
||||
return (char *)"Connection already in progress";
|
||||
case EBADF:
|
||||
return (char *)"Bad file descriptor";
|
||||
case EBADMSG:
|
||||
return (char *)"Bad message";
|
||||
case EBUSY:
|
||||
return (char *)"Device or resource busy";
|
||||
case ECANCELED:
|
||||
return (char *)"Operation canceled";
|
||||
case ECHILD:
|
||||
return (char *)"No child processes";
|
||||
case ECONNABORTED:
|
||||
return (char *)"Connection aborted";
|
||||
case ECONNREFUSED:
|
||||
return (char *)"Connection refused";
|
||||
case ECONNRESET:
|
||||
return (char *)"Connection reset";
|
||||
case EDEADLK:
|
||||
return (char *)"Resource deadlock would occur";
|
||||
case EDESTADDRREQ:
|
||||
return (char *)"Destination address required";
|
||||
case EDOM:
|
||||
return (char *)"Mathematics argument out of domain of function";
|
||||
case EDQUOT:
|
||||
return (char *)"Reserved";
|
||||
case EEXIST:
|
||||
return (char *)"File exists";
|
||||
case EFAULT:
|
||||
return (char *)"Bad address";
|
||||
case EFBIG:
|
||||
return (char *)"File too large";
|
||||
case EHOSTUNREACH:
|
||||
return (char *)"Host is unreachable";
|
||||
case EIDRM:
|
||||
return (char *)"Identifier removed";
|
||||
case EILSEQ:
|
||||
return (char *)"Illegal byte sequence";
|
||||
case EINPROGRESS:
|
||||
return (char *)"Operation in progress";
|
||||
case EINTR:
|
||||
return (char *)"Interrupted function";
|
||||
case EINVAL:
|
||||
return (char *)"Invalid argument";
|
||||
case EIO:
|
||||
return (char *)"I/O error";
|
||||
case EISCONN:
|
||||
return (char *)"Socket is connected";
|
||||
case EISDIR:
|
||||
return (char *)"Is a directory";
|
||||
case ELOOP:
|
||||
return (char *)"Too many levels of symbolic links";
|
||||
case EMFILE:
|
||||
return (char *)"File descriptor value too large";
|
||||
case EMLINK:
|
||||
return (char *)"Too many links";
|
||||
case EMSGSIZE:
|
||||
return (char *)"Message too large";
|
||||
case EMULTIHOP:
|
||||
return (char *)"Reserved";
|
||||
case ENAMETOOLONG:
|
||||
return (char *)"Filename too long";
|
||||
case ENETDOWN:
|
||||
return (char *)"Network is down";
|
||||
case ENETRESET:
|
||||
return (char *)"Connection aborted by network";
|
||||
case ENETUNREACH:
|
||||
return (char *)"Network unreachable";
|
||||
case ENFILE:
|
||||
return (char *)"Too many files open in system";
|
||||
case ENOBUFS:
|
||||
return (char *)"No buffer space available";
|
||||
case ENODATA:
|
||||
return (char *)"No message available on the STREAM head read queue";
|
||||
case ENODEV:
|
||||
return (char *)"No such device";
|
||||
case ENOENT:
|
||||
return (char *)"No such file or directory";
|
||||
case ENOEXEC:
|
||||
return (char *)"Executable file format error";
|
||||
case ENOLCK:
|
||||
return (char *)"No locks available";
|
||||
case ENOLINK:
|
||||
return (char *)"Reserved";
|
||||
case ENOMEM:
|
||||
return (char *)"Not enough space";
|
||||
case ENOMSG:
|
||||
return (char *)"No message of the desired type";
|
||||
case ENOPROTOOPT:
|
||||
return (char *)"Protocol not available";
|
||||
case ENOSPC:
|
||||
return (char *)"No space left on device";
|
||||
case ENOSR:
|
||||
return (char *)"No STREAM resources";
|
||||
case ENOSTR:
|
||||
return (char *)"Not a STREAM";
|
||||
case ENOSYS:
|
||||
return (char *)"Functionality not supported";
|
||||
case ENOTCONN:
|
||||
return (char *)"The socket is not connected";
|
||||
case ENOTDIR:
|
||||
return (char *)"Not a directory or a symbolic link to a directory";
|
||||
case ENOTEMPTY:
|
||||
return (char *)"Directory not empty";
|
||||
case ENOTRECOVERABLE:
|
||||
return (char *)"State not recoverable";
|
||||
case ENOTSOCK:
|
||||
return (char *)"Not a socket";
|
||||
case ENOTSUP:
|
||||
return (char *)"Not supported";
|
||||
case ENOTTY:
|
||||
return (char *)"Inappropriate I/O control operation";
|
||||
case ENXIO:
|
||||
return (char *)"No such device or address";
|
||||
case EOPNOTSUPP:
|
||||
return (char *)"Operation not supported on socket";
|
||||
case EOVERFLOW:
|
||||
return (char *)"Value too large to be stored in data type";
|
||||
case EOWNERDEAD:
|
||||
return (char *)"Previous owner died";
|
||||
case EPERM:
|
||||
return (char *)"Operation not permitted";
|
||||
case EPIPE:
|
||||
return (char *)"Broken pipe";
|
||||
case EPROTO:
|
||||
return (char *)"Protocol error";
|
||||
case EPROTONOSUPPORT:
|
||||
return (char *)"Protocol not supported";
|
||||
case EPROTOTYPE:
|
||||
return (char *)"Protocol wrong type for socket";
|
||||
case ERANGE:
|
||||
return (char *)"Result too large";
|
||||
case EROFS:
|
||||
return (char *)"Read-only file system";
|
||||
case ESPIPE:
|
||||
return (char *)"Invalid seek";
|
||||
case ESRCH:
|
||||
return (char *)"No such process";
|
||||
case ESTALE:
|
||||
return (char *)"Reserved";
|
||||
case ETIME:
|
||||
return (char *)"Stream ioctl() timeout";
|
||||
case ETIMEDOUT:
|
||||
return (char *)"Connection timed out";
|
||||
case ETXTBSY:
|
||||
return (char *)"Text file busy";
|
||||
case EWOULDBLOCK:
|
||||
return (char *)"Operation would block";
|
||||
case EXDEV:
|
||||
return (char *)"Cross-device link";
|
||||
default:
|
||||
return (char *)"Unknown error";
|
||||
}
|
||||
}
|
111
Kernel/library/std/mutex.cpp
Normal file
111
Kernel/library/std/mutex.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cpu.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace Tasking;
|
||||
|
||||
namespace std
|
||||
{
|
||||
void mutex::lock()
|
||||
{
|
||||
RetryLock:
|
||||
bool Result = this->Locked.exchange(true, std::memory_order_acquire);
|
||||
|
||||
TCB *tcb = thisThread;
|
||||
assert(tcb != nullptr);
|
||||
if (Result == true)
|
||||
{
|
||||
debug("%#lx: Mutex is locked, blocking task %d (\"%s\" : %d)", this,
|
||||
tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
|
||||
|
||||
this->Waiting.push_back(tcb);
|
||||
tcb->Block();
|
||||
TaskManager->Yield();
|
||||
goto RetryLock;
|
||||
}
|
||||
|
||||
this->Holder = tcb;
|
||||
this->Waiting.remove(tcb);
|
||||
|
||||
debug("%#lx: Mutex locked by task %d (\"%s\" : %d)", this,
|
||||
tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
|
||||
}
|
||||
|
||||
bool mutex::try_lock()
|
||||
{
|
||||
bool Result = this->Locked.exchange(true, std::memory_order_acquire);
|
||||
|
||||
TCB *tcb = thisThread;
|
||||
assert(tcb != nullptr);
|
||||
if (Result == true)
|
||||
{
|
||||
debug("%#lx: Mutex is locked, task %d (\"%s\" : %d) failed to lock", this,
|
||||
tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
|
||||
return false;
|
||||
}
|
||||
|
||||
this->Holder = tcb;
|
||||
this->Waiting.remove(tcb);
|
||||
|
||||
debug("%#lx: Mutex locked by task %d (\"%s\" : %d)", this,
|
||||
tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
void mutex::unlock()
|
||||
{
|
||||
TCB *tcb = thisThread;
|
||||
assert(tcb != nullptr);
|
||||
assert(this->Holder == tcb);
|
||||
|
||||
this->Holder = nullptr;
|
||||
this->Locked.store(false, std::memory_order_release);
|
||||
|
||||
if (this->Waiting.empty())
|
||||
{
|
||||
debug("%#lx: Mutex unlocked, no tasks to unblock", this);
|
||||
return;
|
||||
}
|
||||
|
||||
TCB *Next = this->Waiting.front();
|
||||
this->Waiting.pop_front();
|
||||
|
||||
debug("%#lx: Mutex unlocked, task %d (\"%s\" : %d) unblocked", this,
|
||||
Next->ID, Next->Parent->Name, Next->Parent->ID);
|
||||
|
||||
Next->Unblock();
|
||||
}
|
||||
|
||||
mutex::mutex()
|
||||
{
|
||||
debug("%#lx: Creating mutex", this);
|
||||
}
|
||||
|
||||
mutex::~mutex()
|
||||
{
|
||||
debug("%#lx: Destroying mutex", this);
|
||||
assert(this->Holder == nullptr);
|
||||
assert(this->Waiting.empty());
|
||||
}
|
||||
}
|
82
Kernel/library/std/new.cpp
Normal file
82
Kernel/library/std/new.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
void *operator new(std::size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
++count;
|
||||
|
||||
if (void *ptr = kmalloc(count))
|
||||
return ptr;
|
||||
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
++count;
|
||||
|
||||
if (void *ptr = kmalloc(count))
|
||||
return ptr;
|
||||
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
|
||||
// void *operator new(std::size_t count, std::align_val_t al)
|
||||
// void *operator new[](std::size_t count, std::align_val_t al)
|
||||
|
||||
// void *operator new(std::size_t count, const std::nothrow_t &tag)
|
||||
// void *operator new[](std::size_t count, const std::nothrow_t &tag)
|
||||
// void *operator new(std::size_t count, std::align_val_t al, const std::nothrow_t &)
|
||||
// void *operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t &)
|
||||
|
||||
void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
|
||||
// void *operator new[](std::size_t count, void *ptr) noexcept
|
||||
|
||||
// void *operator new(std::size_t count, ...)
|
||||
// void *operator new[](std::size_t count, ...)
|
||||
// void *operator new(std::size_t count, std::align_val_t al, ...)
|
||||
// void *operator new[](std::size_t count, std::align_val_t al, ...)
|
||||
|
||||
void operator delete(void *ptr) noexcept { kfree(ptr); }
|
||||
|
||||
void operator delete[](void *ptr) noexcept { kfree(ptr); }
|
||||
|
||||
// void operator delete(void *ptr, std::align_val_t al) noexcept
|
||||
// void operator delete[](void *ptr, std::align_val_t al) noexcept
|
||||
void operator delete(void *ptr, std::size_t) noexcept { kfree(ptr); }
|
||||
|
||||
void operator delete[](void *ptr, std::size_t sz) noexcept { kfree(ptr); }
|
||||
void operator delete(void *ptr, std::size_t sz, std::align_val_t al) noexcept { kfree(ptr); }
|
||||
// void operator delete[](void *ptr, std::size_t sz, std::align_val_t al) noexcept
|
||||
|
||||
// void operator delete(void *ptr, const std::nothrow_t &tag) noexcept
|
||||
// void operator delete[](void *ptr, const std::nothrow_t &tag) noexcept
|
||||
// void operator delete(void *ptr, std::align_val_t al, const std::nothrow_t &tag) noexcept
|
||||
// void operator delete[](void *ptr, std::align_val_t al, const std::nothrow_t &tag) noexcept
|
||||
|
||||
// void operator delete(void *ptr, void *place) noexcept
|
||||
// void operator delete[](void *ptr, void *place) noexcept
|
||||
|
||||
// void operator delete(void *ptr, ...)
|
||||
// void operator delete[](void *ptr, ...)
|
41
Kernel/library/std/printf.cpp
Normal file
41
Kernel/library/std/printf.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <printf.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
int sprintf(char *s, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vsprintf(s, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int snprintf(char *s, size_t count, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vsnprintf(s, count, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
}
|
44
Kernel/library/std/typeinfo.cpp
Normal file
44
Kernel/library/std/typeinfo.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
#include <debug.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
type_info::~type_info() {}
|
||||
|
||||
bool type_info::__do_catch(const type_info *ThrowType,
|
||||
void **ThrowObject,
|
||||
unsigned Outer) const
|
||||
{
|
||||
stub;
|
||||
UNUSED(ThrowType);
|
||||
UNUSED(ThrowObject);
|
||||
UNUSED(Outer);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool type_info::__do_upcast(const __cxxabiv1::__class_type_info *Target,
|
||||
void **ObjectPointer) const
|
||||
{
|
||||
stub;
|
||||
UNUSED(Target);
|
||||
UNUSED(ObjectPointer);
|
||||
return false;
|
||||
}
|
||||
}
|
47
Kernel/library/targp.c
Normal file
47
Kernel/library/targp.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <targp.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <convert.h>
|
||||
|
||||
void targp_parse(const char *cmd, char **argv, int *argc)
|
||||
{
|
||||
const char delim[] = " ";
|
||||
|
||||
char *token = strtok((char *)cmd, delim);
|
||||
while (token != NULL)
|
||||
{
|
||||
char *quote = strchr(token, '"');
|
||||
if (quote != NULL)
|
||||
{
|
||||
memmove(quote, quote + 1, strlen(quote));
|
||||
char *endQuote = strchr(quote, '"');
|
||||
if (endQuote != NULL)
|
||||
*endQuote = '\0';
|
||||
}
|
||||
|
||||
char *arg = (char *)kmalloc(strlen(token) + 1);
|
||||
strcpy(arg, token);
|
||||
|
||||
argv[(*argc)++] = arg;
|
||||
|
||||
token = strtok(NULL, delim);
|
||||
}
|
||||
argv[(*argc)] = NULL;
|
||||
}
|
Reference in New Issue
Block a user