mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
Stage 6
This commit is contained in:
3
Makefile
3
Makefile
@@ -75,6 +75,8 @@ C_SOURCES := \
|
|||||||
clks/kernel/elf64.c \
|
clks/kernel/elf64.c \
|
||||||
clks/kernel/elfrunner.c \
|
clks/kernel/elfrunner.c \
|
||||||
clks/kernel/syscall.c \
|
clks/kernel/syscall.c \
|
||||||
|
clks/kernel/ramdisk.c \
|
||||||
|
clks/kernel/fs.c \
|
||||||
clks/lib/string.c \
|
clks/lib/string.c \
|
||||||
clks/drivers/serial/serial.c \
|
clks/drivers/serial/serial.c \
|
||||||
clks/drivers/video/framebuffer.c \
|
clks/drivers/video/framebuffer.c \
|
||||||
@@ -243,3 +245,4 @@ help:
|
|||||||
> @echo " make run"
|
> @echo " make run"
|
||||||
> @echo " make debug"
|
> @echo " make debug"
|
||||||
> @echo " make NO_COLOR=1 <target>"
|
> @echo " make NO_COLOR=1 <target>"
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,7 @@ clks_bool clks_boot_base_revision_supported(void);
|
|||||||
const struct limine_framebuffer *clks_boot_get_framebuffer(void);
|
const struct limine_framebuffer *clks_boot_get_framebuffer(void);
|
||||||
const struct limine_memmap_response *clks_boot_get_memmap(void);
|
const struct limine_memmap_response *clks_boot_get_memmap(void);
|
||||||
const struct limine_file *clks_boot_get_executable_file(void);
|
const struct limine_file *clks_boot_get_executable_file(void);
|
||||||
|
u64 clks_boot_get_module_count(void);
|
||||||
|
const struct limine_file *clks_boot_get_module(u64 index);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
24
clks/include/clks/fs.h
Normal file
24
clks/include/clks/fs.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef CLKS_FS_H
|
||||||
|
#define CLKS_FS_H
|
||||||
|
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
enum clks_fs_node_type {
|
||||||
|
CLKS_FS_NODE_FILE = 1,
|
||||||
|
CLKS_FS_NODE_DIR = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clks_fs_node_info {
|
||||||
|
enum clks_fs_node_type type;
|
||||||
|
u64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
void clks_fs_init(void);
|
||||||
|
clks_bool clks_fs_is_ready(void);
|
||||||
|
clks_bool clks_fs_stat(const char *path, struct clks_fs_node_info *out_info);
|
||||||
|
const void *clks_fs_read_all(const char *path, u64 *out_size);
|
||||||
|
u64 clks_fs_count_children(const char *dir_path);
|
||||||
|
clks_bool clks_fs_get_child_name(const char *dir_path, u64 index, char *out_name, usize out_name_size);
|
||||||
|
u64 clks_fs_node_count(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -39,6 +39,14 @@
|
|||||||
0x31eb5d1c5ff23b69ULL \
|
0x31eb5d1c5ff23b69ULL \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LIMINE_MODULE_REQUEST \
|
||||||
|
{ \
|
||||||
|
LIMINE_COMMON_MAGIC, \
|
||||||
|
LIMINE_REQUEST_MAGIC, \
|
||||||
|
0x3e7e279702be32afULL, \
|
||||||
|
0xca1c4f3bd1280ceeULL \
|
||||||
|
}
|
||||||
|
|
||||||
#define LIMINE_MEMMAP_USABLE 0ULL
|
#define LIMINE_MEMMAP_USABLE 0ULL
|
||||||
#define LIMINE_MEMMAP_RESERVED 1ULL
|
#define LIMINE_MEMMAP_RESERVED 1ULL
|
||||||
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2ULL
|
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2ULL
|
||||||
@@ -132,4 +140,16 @@ struct limine_executable_file_request {
|
|||||||
struct limine_executable_file_response *response;
|
struct limine_executable_file_response *response;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct limine_module_response {
|
||||||
|
u64 revision;
|
||||||
|
u64 module_count;
|
||||||
|
struct limine_file **modules;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct limine_module_request {
|
||||||
|
u64 id[4];
|
||||||
|
u64 revision;
|
||||||
|
struct limine_module_response *response;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
24
clks/include/clks/ramdisk.h
Normal file
24
clks/include/clks/ramdisk.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef CLKS_RAMDISK_H
|
||||||
|
#define CLKS_RAMDISK_H
|
||||||
|
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
#define CLKS_RAMDISK_PATH_MAX 192U
|
||||||
|
|
||||||
|
enum clks_ramdisk_entry_type {
|
||||||
|
CLKS_RAMDISK_ENTRY_FILE = 1,
|
||||||
|
CLKS_RAMDISK_ENTRY_DIR = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clks_ramdisk_entry {
|
||||||
|
enum clks_ramdisk_entry_type type;
|
||||||
|
char path[CLKS_RAMDISK_PATH_MAX];
|
||||||
|
const void *data;
|
||||||
|
u64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef clks_bool (*clks_ramdisk_iter_fn)(const struct clks_ramdisk_entry *entry, void *ctx);
|
||||||
|
|
||||||
|
clks_bool clks_ramdisk_iterate(const void *image, u64 image_size, clks_ramdisk_iter_fn iter_fn, void *ctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
572
clks/kernel/fs.c
Normal file
572
clks/kernel/fs.c
Normal file
@@ -0,0 +1,572 @@
|
|||||||
|
#include <clks/boot.h>
|
||||||
|
#include <clks/fs.h>
|
||||||
|
#include <clks/log.h>
|
||||||
|
#include <clks/ramdisk.h>
|
||||||
|
#include <clks/string.h>
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
#define CLKS_FS_MAX_NODES 512U
|
||||||
|
#define CLKS_FS_PATH_MAX CLKS_RAMDISK_PATH_MAX
|
||||||
|
|
||||||
|
struct clks_fs_node {
|
||||||
|
clks_bool used;
|
||||||
|
enum clks_fs_node_type type;
|
||||||
|
u16 parent;
|
||||||
|
u16 reserved;
|
||||||
|
const void *data;
|
||||||
|
u64 size;
|
||||||
|
char path[CLKS_FS_PATH_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clks_fs_build_stats {
|
||||||
|
u64 file_count;
|
||||||
|
u64 dir_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clks_fs_node clks_fs_nodes[CLKS_FS_MAX_NODES];
|
||||||
|
static u16 clks_fs_nodes_used = 0U;
|
||||||
|
static clks_bool clks_fs_ready = CLKS_FALSE;
|
||||||
|
|
||||||
|
static clks_bool clks_fs_normalize_external_path(const char *path, char *out_internal, usize out_size) {
|
||||||
|
usize in_pos = 0;
|
||||||
|
usize out_pos = 0;
|
||||||
|
|
||||||
|
if (path == CLKS_NULL || out_internal == CLKS_NULL || out_size == 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path[0] != '/') {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (path[in_pos] == '/') {
|
||||||
|
in_pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (path[in_pos] != '\0') {
|
||||||
|
usize comp_start = in_pos;
|
||||||
|
usize comp_len;
|
||||||
|
|
||||||
|
while (path[in_pos] != '\0' && path[in_pos] != '/') {
|
||||||
|
in_pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
comp_len = in_pos - comp_start;
|
||||||
|
|
||||||
|
if (comp_len == 0U) {
|
||||||
|
while (path[in_pos] == '/') {
|
||||||
|
in_pos++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp_len == 1U && path[comp_start] == '.') {
|
||||||
|
while (path[in_pos] == '/') {
|
||||||
|
in_pos++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp_len == 2U && path[comp_start] == '.' && path[comp_start + 1U] == '.') {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_pos != 0U) {
|
||||||
|
if (out_pos + 1U >= out_size) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
out_internal[out_pos++] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_pos + comp_len >= out_size) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_memcpy(out_internal + out_pos, path + comp_start, comp_len);
|
||||||
|
out_pos += comp_len;
|
||||||
|
|
||||||
|
while (path[in_pos] == '/') {
|
||||||
|
in_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out_internal[out_pos] = '\0';
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32 clks_fs_find_node_by_internal(const char *internal_path) {
|
||||||
|
u16 i;
|
||||||
|
|
||||||
|
for (i = 0U; i < clks_fs_nodes_used; i++) {
|
||||||
|
if (clks_fs_nodes[i].used == CLKS_FALSE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_strcmp(clks_fs_nodes[i].path, internal_path) == 0) {
|
||||||
|
return (i32)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32 clks_fs_find_node_by_external(const char *external_path) {
|
||||||
|
char internal[CLKS_FS_PATH_MAX];
|
||||||
|
|
||||||
|
if (clks_fs_normalize_external_path(external_path, internal, sizeof(internal)) == CLKS_FALSE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clks_fs_find_node_by_internal(internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *clks_fs_basename(const char *internal_path) {
|
||||||
|
usize len;
|
||||||
|
usize i;
|
||||||
|
|
||||||
|
if (internal_path == CLKS_NULL) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
len = clks_strlen(internal_path);
|
||||||
|
|
||||||
|
if (len == 0U) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = len; i != 0U; i--) {
|
||||||
|
if (internal_path[i - 1U] == '/') {
|
||||||
|
return &internal_path[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return internal_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_fs_split_parent(const char *internal_path, char *parent_out, usize parent_out_size) {
|
||||||
|
usize len;
|
||||||
|
usize i;
|
||||||
|
|
||||||
|
if (internal_path == CLKS_NULL || parent_out == CLKS_NULL || parent_out_size == 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = clks_strlen(internal_path);
|
||||||
|
|
||||||
|
if (len == 0U) {
|
||||||
|
parent_out[0] = '\0';
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = len; i != 0U; i--) {
|
||||||
|
if (internal_path[i - 1U] == '/') {
|
||||||
|
usize parent_len = i - 1U;
|
||||||
|
|
||||||
|
if (parent_len >= parent_out_size) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_memcpy(parent_out, internal_path, parent_len);
|
||||||
|
parent_out[parent_len] = '\0';
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_out[0] = '\0';
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32 clks_fs_create_or_update_node(const char *internal_path,
|
||||||
|
enum clks_fs_node_type type,
|
||||||
|
u16 parent,
|
||||||
|
const void *data,
|
||||||
|
u64 size) {
|
||||||
|
i32 existing;
|
||||||
|
usize path_len;
|
||||||
|
|
||||||
|
if (internal_path == CLKS_NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
path_len = clks_strlen(internal_path);
|
||||||
|
|
||||||
|
if (path_len >= CLKS_FS_PATH_MAX) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
existing = clks_fs_find_node_by_internal(internal_path);
|
||||||
|
|
||||||
|
if (existing >= 0) {
|
||||||
|
struct clks_fs_node *node = &clks_fs_nodes[(u16)existing];
|
||||||
|
|
||||||
|
if (node->type != type) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->parent = parent;
|
||||||
|
|
||||||
|
if (type == CLKS_FS_NODE_FILE) {
|
||||||
|
node->data = data;
|
||||||
|
node->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_nodes_used >= CLKS_FS_MAX_NODES) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_fs_nodes[clks_fs_nodes_used].used = CLKS_TRUE;
|
||||||
|
clks_fs_nodes[clks_fs_nodes_used].type = type;
|
||||||
|
clks_fs_nodes[clks_fs_nodes_used].parent = parent;
|
||||||
|
clks_fs_nodes[clks_fs_nodes_used].reserved = 0U;
|
||||||
|
clks_fs_nodes[clks_fs_nodes_used].data = (type == CLKS_FS_NODE_FILE) ? data : CLKS_NULL;
|
||||||
|
clks_fs_nodes[clks_fs_nodes_used].size = (type == CLKS_FS_NODE_FILE) ? size : 0ULL;
|
||||||
|
clks_memcpy(clks_fs_nodes[clks_fs_nodes_used].path, internal_path, path_len + 1U);
|
||||||
|
|
||||||
|
clks_fs_nodes_used++;
|
||||||
|
return (i32)(clks_fs_nodes_used - 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_fs_ensure_root(void) {
|
||||||
|
if (clks_fs_create_or_update_node("", CLKS_FS_NODE_DIR, 0U, CLKS_NULL, 0ULL) != 0) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_fs_ensure_dir_hierarchy(const char *internal_dir_path) {
|
||||||
|
char prefix[CLKS_FS_PATH_MAX];
|
||||||
|
usize cursor = 0;
|
||||||
|
usize i = 0;
|
||||||
|
u16 current_parent = 0U;
|
||||||
|
|
||||||
|
prefix[0] = '\0';
|
||||||
|
|
||||||
|
if (internal_dir_path == CLKS_NULL) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (internal_dir_path[0] == '\0') {
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (internal_dir_path[i] != '\0') {
|
||||||
|
usize comp_start = i;
|
||||||
|
usize comp_len;
|
||||||
|
i32 node_index;
|
||||||
|
|
||||||
|
while (internal_dir_path[i] != '\0' && internal_dir_path[i] != '/') {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
comp_len = i - comp_start;
|
||||||
|
|
||||||
|
if (comp_len == 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor != 0U) {
|
||||||
|
if (cursor + 1U >= sizeof(prefix)) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
prefix[cursor++] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor + comp_len >= sizeof(prefix)) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_memcpy(prefix + cursor, internal_dir_path + comp_start, comp_len);
|
||||||
|
cursor += comp_len;
|
||||||
|
prefix[cursor] = '\0';
|
||||||
|
|
||||||
|
node_index = clks_fs_find_node_by_internal(prefix);
|
||||||
|
|
||||||
|
if (node_index < 0) {
|
||||||
|
node_index = clks_fs_create_or_update_node(prefix, CLKS_FS_NODE_DIR, current_parent, CLKS_NULL, 0ULL);
|
||||||
|
|
||||||
|
if (node_index < 0) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
} else if (clks_fs_nodes[(u16)node_index].type != CLKS_FS_NODE_DIR) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_parent = (u16)node_index;
|
||||||
|
|
||||||
|
if (internal_dir_path[i] == '/') {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_fs_require_directory(const char *external_path) {
|
||||||
|
i32 node_index = clks_fs_find_node_by_external(external_path);
|
||||||
|
|
||||||
|
if (node_index < 0) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "MISSING REQUIRED DIRECTORY");
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", external_path);
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_nodes[(u16)node_index].type != CLKS_FS_NODE_DIR) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "REQUIRED PATH IS NOT DIRECTORY");
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", external_path);
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_fs_ramdisk_visit(const struct clks_ramdisk_entry *entry, void *ctx) {
|
||||||
|
struct clks_fs_build_stats *stats = (struct clks_fs_build_stats *)ctx;
|
||||||
|
|
||||||
|
if (entry == CLKS_NULL || stats == CLKS_NULL) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->type == CLKS_RAMDISK_ENTRY_DIR) {
|
||||||
|
if (clks_fs_ensure_dir_hierarchy(entry->path) == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats->dir_count++;
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->type == CLKS_RAMDISK_ENTRY_FILE) {
|
||||||
|
char parent[CLKS_FS_PATH_MAX];
|
||||||
|
i32 parent_index;
|
||||||
|
|
||||||
|
if (clks_fs_split_parent(entry->path, parent, sizeof(parent)) == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_ensure_dir_hierarchy(parent) == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_index = clks_fs_find_node_by_internal(parent);
|
||||||
|
|
||||||
|
if (parent_index < 0) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_create_or_update_node(entry->path,
|
||||||
|
CLKS_FS_NODE_FILE,
|
||||||
|
(u16)parent_index,
|
||||||
|
entry->data,
|
||||||
|
entry->size) < 0) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats->file_count++;
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clks_fs_init(void) {
|
||||||
|
const struct limine_file *module;
|
||||||
|
struct clks_fs_build_stats stats;
|
||||||
|
u64 module_count;
|
||||||
|
|
||||||
|
clks_fs_ready = CLKS_FALSE;
|
||||||
|
clks_fs_nodes_used = 0U;
|
||||||
|
clks_memset(clks_fs_nodes, 0, sizeof(clks_fs_nodes));
|
||||||
|
clks_memset(&stats, 0, sizeof(stats));
|
||||||
|
|
||||||
|
if (clks_fs_ensure_root() == CLKS_FALSE) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "FAILED TO CREATE ROOT NODE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_count = clks_boot_get_module_count();
|
||||||
|
|
||||||
|
if (module_count == 0ULL) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "NO RAMDISK MODULE FROM LIMINE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
module = clks_boot_get_module(0ULL);
|
||||||
|
|
||||||
|
if (module == CLKS_NULL || module->address == CLKS_NULL || module->size == 0ULL) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "INVALID RAMDISK MODULE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_ramdisk_iterate(module->address, module->size, clks_fs_ramdisk_visit, &stats) == CLKS_FALSE) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "RAMDISK TAR PARSE FAILED");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_log(CLKS_LOG_INFO, "FS", "RAMDISK VFS ONLINE");
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "FS", "MODULE_SIZE", module->size);
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "FS", "NODE_COUNT", (u64)clks_fs_nodes_used);
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "FS", "FILE_COUNT", stats.file_count);
|
||||||
|
|
||||||
|
if (clks_fs_require_directory("/system") == CLKS_FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_require_directory("/shell") == CLKS_FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_require_directory("/temp") == CLKS_FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_require_directory("/driver") == CLKS_FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_fs_ready = CLKS_TRUE;
|
||||||
|
clks_log(CLKS_LOG_INFO, "FS", "LAYOUT /SYSTEM /SHELL /TEMP /DRIVER OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_bool clks_fs_is_ready(void) {
|
||||||
|
return clks_fs_ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_bool clks_fs_stat(const char *path, struct clks_fs_node_info *out_info) {
|
||||||
|
i32 node_index;
|
||||||
|
|
||||||
|
if (clks_fs_ready == CLKS_FALSE || out_info == CLKS_NULL) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_index = clks_fs_find_node_by_external(path);
|
||||||
|
|
||||||
|
if (node_index < 0) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_info->type = clks_fs_nodes[(u16)node_index].type;
|
||||||
|
out_info->size = clks_fs_nodes[(u16)node_index].size;
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *clks_fs_read_all(const char *path, u64 *out_size) {
|
||||||
|
i32 node_index;
|
||||||
|
|
||||||
|
if (clks_fs_ready == CLKS_FALSE) {
|
||||||
|
return CLKS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_index = clks_fs_find_node_by_external(path);
|
||||||
|
|
||||||
|
if (node_index < 0) {
|
||||||
|
return CLKS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_nodes[(u16)node_index].type != CLKS_FS_NODE_FILE) {
|
||||||
|
return CLKS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_size != CLKS_NULL) {
|
||||||
|
*out_size = clks_fs_nodes[(u16)node_index].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clks_fs_nodes[(u16)node_index].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 clks_fs_count_children(const char *dir_path) {
|
||||||
|
i32 dir_index;
|
||||||
|
u64 count = 0ULL;
|
||||||
|
u16 i;
|
||||||
|
|
||||||
|
if (clks_fs_ready == CLKS_FALSE) {
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir_index = clks_fs_find_node_by_external(dir_path);
|
||||||
|
|
||||||
|
if (dir_index < 0) {
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_nodes[(u16)dir_index].type != CLKS_FS_NODE_DIR) {
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0U; i < clks_fs_nodes_used; i++) {
|
||||||
|
if (clks_fs_nodes[i].used == CLKS_FALSE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((u16)dir_index == i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_nodes[i].parent == (u16)dir_index) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_bool clks_fs_get_child_name(const char *dir_path, u64 index, char *out_name, usize out_name_size) {
|
||||||
|
i32 dir_index;
|
||||||
|
u64 current = 0ULL;
|
||||||
|
u16 i;
|
||||||
|
|
||||||
|
if (clks_fs_ready == CLKS_FALSE || out_name == CLKS_NULL || out_name_size == 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir_index = clks_fs_find_node_by_external(dir_path);
|
||||||
|
|
||||||
|
if (dir_index < 0 || clks_fs_nodes[(u16)dir_index].type != CLKS_FS_NODE_DIR) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0U; i < clks_fs_nodes_used; i++) {
|
||||||
|
const char *base;
|
||||||
|
usize base_len;
|
||||||
|
|
||||||
|
if (clks_fs_nodes[i].used == CLKS_FALSE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((u16)dir_index == i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_fs_nodes[i].parent != (u16)dir_index) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current != index) {
|
||||||
|
current++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = clks_fs_basename(clks_fs_nodes[i].path);
|
||||||
|
base_len = clks_strlen(base);
|
||||||
|
|
||||||
|
if (base_len + 1U > out_name_size) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_memcpy(out_name, base, base_len + 1U);
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 clks_fs_node_count(void) {
|
||||||
|
if (clks_fs_ready == CLKS_FALSE) {
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (u64)clks_fs_nodes_used;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <clks/cpu.h>
|
#include <clks/cpu.h>
|
||||||
#include <clks/elfrunner.h>
|
#include <clks/elfrunner.h>
|
||||||
#include <clks/framebuffer.h>
|
#include <clks/framebuffer.h>
|
||||||
|
#include <clks/fs.h>
|
||||||
#include <clks/heap.h>
|
#include <clks/heap.h>
|
||||||
#include <clks/interrupts.h>
|
#include <clks/interrupts.h>
|
||||||
#include <clks/kernel.h>
|
#include <clks/kernel.h>
|
||||||
@@ -19,8 +20,10 @@ void clks_kernel_main(void) {
|
|||||||
struct clks_pmm_stats pmm_stats;
|
struct clks_pmm_stats pmm_stats;
|
||||||
struct clks_heap_stats heap_stats;
|
struct clks_heap_stats heap_stats;
|
||||||
struct clks_scheduler_stats sched_stats;
|
struct clks_scheduler_stats sched_stats;
|
||||||
|
struct clks_fs_node_info fs_system_dir = {0};
|
||||||
void *heap_probe = CLKS_NULL;
|
void *heap_probe = CLKS_NULL;
|
||||||
u64 syscall_ticks;
|
u64 syscall_ticks;
|
||||||
|
u64 fs_root_children;
|
||||||
|
|
||||||
clks_serial_init();
|
clks_serial_init();
|
||||||
|
|
||||||
@@ -36,7 +39,7 @@ void clks_kernel_main(void) {
|
|||||||
clks_tty_init();
|
clks_tty_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE5 START");
|
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE6 START");
|
||||||
|
|
||||||
if (boot_fb == CLKS_NULL) {
|
if (boot_fb == CLKS_NULL) {
|
||||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||||
@@ -83,6 +86,21 @@ void clks_kernel_main(void) {
|
|||||||
clks_kfree(heap_probe);
|
clks_kfree(heap_probe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clks_fs_init();
|
||||||
|
|
||||||
|
if (clks_fs_is_ready() == CLKS_FALSE) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "RAMDISK FS INIT FAILED");
|
||||||
|
clks_cpu_halt_forever();
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_root_children = clks_fs_count_children("/");
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "FS", "ROOT_CHILDREN", fs_root_children);
|
||||||
|
|
||||||
|
if (clks_fs_stat("/system", &fs_system_dir) == CLKS_FALSE || fs_system_dir.type != CLKS_FS_NODE_DIR) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "FS", "/SYSTEM DIRECTORY CHECK FAILED");
|
||||||
|
clks_cpu_halt_forever();
|
||||||
|
}
|
||||||
|
|
||||||
clks_scheduler_init();
|
clks_scheduler_init();
|
||||||
|
|
||||||
if (clks_scheduler_add_kernel_task("klogd", 4U) == CLKS_FALSE) {
|
if (clks_scheduler_add_kernel_task("klogd", 4U) == CLKS_FALSE) {
|
||||||
@@ -115,3 +133,4 @@ void clks_kernel_main(void) {
|
|||||||
|
|
||||||
clks_cpu_halt_forever();
|
clks_cpu_halt_forever();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ CLKS_USED static volatile struct limine_executable_file_request limine_executabl
|
|||||||
.response = CLKS_NULL,
|
.response = CLKS_NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CLKS_USED static volatile struct limine_module_request limine_module_request
|
||||||
|
__attribute__((section(".limine_requests"))) = {
|
||||||
|
.id = LIMINE_MODULE_REQUEST,
|
||||||
|
.revision = 0,
|
||||||
|
.response = CLKS_NULL,
|
||||||
|
};
|
||||||
|
|
||||||
CLKS_USED static volatile u64 limine_requests_end[]
|
CLKS_USED static volatile u64 limine_requests_end[]
|
||||||
__attribute__((section(".limine_requests_end"))) = LIMINE_REQUESTS_END_MARKER;
|
__attribute__((section(".limine_requests_end"))) = LIMINE_REQUESTS_END_MARKER;
|
||||||
|
|
||||||
@@ -68,3 +75,27 @@ const struct limine_file *clks_boot_get_executable_file(void) {
|
|||||||
|
|
||||||
return request->response->executable_file;
|
return request->response->executable_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 clks_boot_get_module_count(void) {
|
||||||
|
volatile struct limine_module_request *request = &limine_module_request;
|
||||||
|
|
||||||
|
if (request->response == CLKS_NULL) {
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request->response->module_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct limine_file *clks_boot_get_module(u64 index) {
|
||||||
|
volatile struct limine_module_request *request = &limine_module_request;
|
||||||
|
|
||||||
|
if (request->response == CLKS_NULL) {
|
||||||
|
return CLKS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= request->response->module_count) {
|
||||||
|
return CLKS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request->response->modules[index];
|
||||||
|
}
|
||||||
|
|||||||
221
clks/kernel/ramdisk.c
Normal file
221
clks/kernel/ramdisk.c
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
#include <clks/compiler.h>
|
||||||
|
#include <clks/ramdisk.h>
|
||||||
|
#include <clks/string.h>
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
#define CLKS_TAR_BLOCK_SIZE 512ULL
|
||||||
|
|
||||||
|
struct clks_tar_header {
|
||||||
|
char name[100];
|
||||||
|
char mode[8];
|
||||||
|
char uid[8];
|
||||||
|
char gid[8];
|
||||||
|
char size[12];
|
||||||
|
char mtime[12];
|
||||||
|
char chksum[8];
|
||||||
|
char typeflag;
|
||||||
|
char linkname[100];
|
||||||
|
char magic[6];
|
||||||
|
char version[2];
|
||||||
|
char uname[32];
|
||||||
|
char gname[32];
|
||||||
|
char devmajor[8];
|
||||||
|
char devminor[8];
|
||||||
|
char prefix[155];
|
||||||
|
char pad[12];
|
||||||
|
} CLKS_PACKED;
|
||||||
|
|
||||||
|
static clks_bool clks_ramdisk_is_zero_block(const u8 *block) {
|
||||||
|
u64 i;
|
||||||
|
|
||||||
|
for (i = 0; i < CLKS_TAR_BLOCK_SIZE; i++) {
|
||||||
|
if (block[i] != 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static usize clks_ramdisk_field_len(const char *field, usize max_len) {
|
||||||
|
usize i = 0;
|
||||||
|
|
||||||
|
while (i < max_len && field[i] != '\0') {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_ramdisk_parse_octal_u64(const char *field, usize len, u64 *out_value) {
|
||||||
|
usize i = 0;
|
||||||
|
u64 value = 0ULL;
|
||||||
|
|
||||||
|
if (out_value == CLKS_NULL) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < len && (field[i] == ' ' || field[i] == '\0')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < len; i++) {
|
||||||
|
char ch = field[i];
|
||||||
|
|
||||||
|
if (ch == ' ' || ch == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch < '0' || ch > '7') {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > (0xffffffffffffffffULL >> 3)) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (value << 3) + (u64)(ch - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_value = value;
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_ramdisk_build_path(const struct clks_tar_header *hdr, char *out_path, usize out_path_size) {
|
||||||
|
char raw[CLKS_RAMDISK_PATH_MAX];
|
||||||
|
usize prefix_len;
|
||||||
|
usize name_len;
|
||||||
|
usize cursor = 0;
|
||||||
|
usize read_pos = 0;
|
||||||
|
usize out_cursor = 0;
|
||||||
|
|
||||||
|
if (hdr == CLKS_NULL || out_path == CLKS_NULL || out_path_size == 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw[0] = '\0';
|
||||||
|
out_path[0] = '\0';
|
||||||
|
|
||||||
|
prefix_len = clks_ramdisk_field_len(hdr->prefix, sizeof(hdr->prefix));
|
||||||
|
name_len = clks_ramdisk_field_len(hdr->name, sizeof(hdr->name));
|
||||||
|
|
||||||
|
if (name_len == 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix_len != 0U) {
|
||||||
|
if (prefix_len + 1U >= sizeof(raw)) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_memcpy(raw, hdr->prefix, prefix_len);
|
||||||
|
cursor = prefix_len;
|
||||||
|
raw[cursor++] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor + name_len >= sizeof(raw)) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_memcpy(raw + cursor, hdr->name, name_len);
|
||||||
|
cursor += name_len;
|
||||||
|
raw[cursor] = '\0';
|
||||||
|
|
||||||
|
while ((raw[read_pos] == '.' && raw[read_pos + 1U] == '/') || raw[read_pos] == '/') {
|
||||||
|
if (raw[read_pos] == '.') {
|
||||||
|
read_pos += 2U;
|
||||||
|
} else {
|
||||||
|
read_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (raw[read_pos] != '\0' && out_cursor + 1U < out_path_size) {
|
||||||
|
out_path[out_cursor++] = raw[read_pos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw[read_pos] != '\0') {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (out_cursor > 0U && out_path[out_cursor - 1U] == '/') {
|
||||||
|
out_cursor--;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_path[out_cursor] = '\0';
|
||||||
|
|
||||||
|
if (out_cursor == 0U) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_bool clks_ramdisk_iterate(const void *image, u64 image_size, clks_ramdisk_iter_fn iter_fn, void *ctx) {
|
||||||
|
const u8 *bytes = (const u8 *)image;
|
||||||
|
u64 offset = 0ULL;
|
||||||
|
|
||||||
|
if (image == CLKS_NULL || iter_fn == CLKS_NULL) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + CLKS_TAR_BLOCK_SIZE <= image_size) {
|
||||||
|
const struct clks_tar_header *hdr;
|
||||||
|
u64 payload_offset;
|
||||||
|
u64 file_size;
|
||||||
|
u64 aligned_size;
|
||||||
|
struct clks_ramdisk_entry entry;
|
||||||
|
clks_bool emit = CLKS_FALSE;
|
||||||
|
|
||||||
|
hdr = (const struct clks_tar_header *)(bytes + offset);
|
||||||
|
|
||||||
|
if (clks_ramdisk_is_zero_block((const u8 *)hdr) == CLKS_TRUE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_ramdisk_parse_octal_u64(hdr->size, sizeof(hdr->size), &file_size) == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload_offset = offset + CLKS_TAR_BLOCK_SIZE;
|
||||||
|
|
||||||
|
if (payload_offset > image_size) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_size > (image_size - payload_offset)) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_memset(&entry, 0, sizeof(entry));
|
||||||
|
|
||||||
|
if (clks_ramdisk_build_path(hdr, entry.path, sizeof(entry.path)) == CLKS_TRUE) {
|
||||||
|
if (hdr->typeflag == '5') {
|
||||||
|
entry.type = CLKS_RAMDISK_ENTRY_DIR;
|
||||||
|
entry.data = CLKS_NULL;
|
||||||
|
entry.size = 0ULL;
|
||||||
|
emit = CLKS_TRUE;
|
||||||
|
} else if (hdr->typeflag == '\0' || hdr->typeflag == '0') {
|
||||||
|
entry.type = CLKS_RAMDISK_ENTRY_FILE;
|
||||||
|
entry.data = (const void *)(bytes + payload_offset);
|
||||||
|
entry.size = file_size;
|
||||||
|
emit = CLKS_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emit == CLKS_TRUE) {
|
||||||
|
if (iter_fn(&entry, ctx) == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aligned_size = (file_size + (CLKS_TAR_BLOCK_SIZE - 1ULL)) & ~(CLKS_TAR_BLOCK_SIZE - 1ULL);
|
||||||
|
|
||||||
|
if (payload_offset + aligned_size < payload_offset) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = payload_offset + aligned_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
35
docs/stage6.md
Normal file
35
docs/stage6.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# CLeonOS Stage6
|
||||||
|
|
||||||
|
## Stage Goal
|
||||||
|
- Add ramdisk filesystem foundation in CLKS based on the Limine module.
|
||||||
|
- Parse tar-format ramdisk and build hierarchical directory/file nodes.
|
||||||
|
- Provide VFS-style path interfaces for stat/read/list operations.
|
||||||
|
- Enforce required root layout: `/system`, `/shell`, `/temp`, `/driver`.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- Kernel boots and prints `CLEONOS STAGE6 START`.
|
||||||
|
- Filesystem logs `RAMDISK VFS ONLINE` and node/file statistics.
|
||||||
|
- Root layout validation reports `/SYSTEM /SHELL /TEMP /DRIVER OK`.
|
||||||
|
- `clks_fs_count_children("/")` returns non-zero and is logged.
|
||||||
|
- Kernel continues to scheduler/ELF/syscall/interrupt init without panic.
|
||||||
|
|
||||||
|
## Build Targets
|
||||||
|
- `make setup`
|
||||||
|
- `make iso`
|
||||||
|
- `make run`
|
||||||
|
- `make debug`
|
||||||
|
|
||||||
|
## QEMU Command
|
||||||
|
- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio`
|
||||||
|
|
||||||
|
## Common Bugs and Debugging
|
||||||
|
- `NO RAMDISK MODULE FROM LIMINE`:
|
||||||
|
- Verify `module_path: boot():/boot/cleonos_ramdisk.tar` exists in `configs/limine.conf`.
|
||||||
|
- `RAMDISK TAR PARSE FAILED`:
|
||||||
|
- Ensure ramdisk is packed as tar (`make ramdisk`) and module size is not zero.
|
||||||
|
- `MISSING REQUIRED DIRECTORY`:
|
||||||
|
- Confirm ramdisk root contains `/system`, `/shell`, `/temp`, `/driver`.
|
||||||
|
- Filesystem APIs always fail:
|
||||||
|
- Check `clks_fs_init()` is called and `clks_fs_is_ready()` is true.
|
||||||
|
- Build failure on new symbols:
|
||||||
|
- Confirm `ramdisk.c` and `fs.c` are present in `C_SOURCES`.
|
||||||
Reference in New Issue
Block a user