Skip to content

Commit 1c4c3f8

Browse files
make module loading actually work, fix a couple of leaks, tie it into filesystem calls to load from device
1 parent c2d51d1 commit 1c4c3f8

11 files changed

Lines changed: 169 additions & 53 deletions

File tree

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ foreach(mod ${MODULE_DIRS})
118118
add_custom_command(OUTPUT ${MOD_OUT}
119119
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/iso/system/modules
120120
COMMAND ${CMAKE_LINKER} -r -o ${MOD_OUT} $<TARGET_OBJECTS:mod_${mod}>
121+
COMMAND ${CMAKE_COMMAND} -E touch ${MOD_OUT}
121122
DEPENDS mod_${mod}
122123
VERBATIM
123124
)

include/module.h

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
#include <kernel.h>
1515
#include <stdbool.h>
1616

17+
/**
18+
* @brief module ABI version the kernel expects
19+
*
20+
* @note If we change the ABI at all, we must bump this by 1.
21+
* It is used in the names of the init/exit functions of each module,
22+
* so an incompatible module is outright rejected before it can wreak
23+
* havoc in the kernel space.
24+
*/
25+
#define KMOD_ABI 100
26+
1727
/* ELF identification */
1828
#define EI_NIDENT 16 /**< Size of e_ident[] array */
1929

@@ -127,8 +137,29 @@ typedef struct elf_rela {
127137
typedef bool (*module_init_fn)(void); /**< Prototype for module initialiser */
128138
typedef void (*module_exit_fn)(void); /**< Prototype for module finaliser */
129139

140+
/**
141+
* @brief Set this prefix on all module_init/module_exit functions in modules
142+
*/
130143
#define EXPORTED __attribute__((visibility("default")))
131144

145+
/**
146+
* @brief helpers to form symbol names
147+
*/
148+
#define MOD_CAT2(a,b) a##b
149+
#define MOD_CAT(a,b) MOD_CAT2(a,b)
150+
#define MOD_INIT_SYM(ver) MOD_CAT(mod_init_v, ver)
151+
#define MOD_EXIT_SYM(ver) MOD_CAT(mod_exit_v, ver)
152+
153+
/* stringification */
154+
#define STR2(x) #x
155+
#define STR(x) STR2(x)
156+
157+
/**
158+
* @brief canonical names as strings
159+
*/
160+
#define MOD_INIT_NAME_STR "mod_init_v" STR(KMOD_ABI)
161+
#define MOD_EXIT_NAME_STR "mod_exit_v" STR(KMOD_ABI)
162+
132163
/**
133164
* @brief Describes a loaded and relocated module image
134165
*
@@ -137,8 +168,9 @@ typedef void (*module_exit_fn)(void); /**< Prototype for module finaliser */
137168
* lookup, and resolves conventional entry points named mod_init and mod_exit
138169
*/
139170
typedef struct module {
140-
char name[64]; /**< Optional friendly name, not set by the loader */
171+
const char* name; /**< Module name */
141172
uint8_t *base; /**< Base of contiguous allocation holding SHF_ALLOC sections */
173+
void* raw_bits; /**< For symbol resolution by other modules */
142174
size_t size; /**< Total size of the contiguous allocation */
143175
const elf_sym *symtab; /**< Pointer to the module's SHT_SYMTAB within the file buffer */
144176
size_t sym_count; /**< Number of entries in symtab */
@@ -156,9 +188,9 @@ typedef struct module {
156188
* @brief Load and relocate a module from an in-memory ELF64 ET_REL buffer, then call its initialiser
157189
*
158190
* Validates the ELF header, allocates a single contiguous region for all SHF_ALLOC sections,
159-
* copies/zeros contents with correct alignment, loads symtab/strtab, applies all SHT_RELA
160-
* relocations, resolves undefined globals against the kernel dynamic symbol table
161-
* (kernel must keep .dynsym/.dynstr), resolves mod_init/mod_exit, then calls mod_init
191+
* copies/zeros contents with correct alignment, applies all SHT_RELA relocations, resolves
192+
* undefined globals against the kernel dynamic symbol table (from kernel.sym),
193+
* resolves versioned mod_init/mod_exit, then calls mod_init
162194
*
163195
* @param file pointer to the ELF bytes
164196
* @param len size of the ELF buffer in bytes
@@ -178,7 +210,7 @@ bool module_load_from_memory(const void *file, size_t len, module *out);
178210
* @param m module descriptor previously returned by module_load_from_memory
179211
* @return true on success, false if @p m is NULL or teardown fails
180212
*/
181-
bool module_unload(module *m);
213+
bool module_internal_unload(module *m);
182214

183215
/**
184216
* @brief Resolve a kernel global by name via the kernel dynamic symbol table
@@ -297,3 +329,34 @@ uintptr_t module_resolve_symbol_addr(const module *m, const elf_sym *s);
297329
* externals should appear as R_X86_64_64 when modules are built with -mcmodel=large -fno-pic -fno-plt
298330
*/
299331
bool module_apply_relocations(const uint8_t *file, const elf_shdr *sh, size_t shnum, module *m);
332+
333+
/**
334+
* @brief Initialise the module registry and loader state
335+
*
336+
* Creates the in-kernel hashmap used to track loaded modules keyed by name
337+
* Must be called once before any other module operations
338+
*/
339+
void init_modules(void);
340+
341+
/**
342+
* @brief Load and start a module by name
343+
*
344+
* Constructs the path /system/modules/<name>.ko, reads the file, relocates it,
345+
* resolves externals against the kernel symbol index, and calls mod_init
346+
* Returns false if the module is already loaded or on any failure
347+
*
348+
* @param name NUL-terminated module base name without extension or path
349+
* @return true on success, false on error
350+
*/
351+
bool load_module(const char *name);
352+
353+
/**
354+
* @brief Stop and unload a loaded module by name
355+
*
356+
* Locates the module in the registry, calls mod_exit if present, frees all
357+
* allocations associated with the image, and removes the entry from the registry
358+
*
359+
* @param name NUL-terminated module base name
360+
* @return true on success, false if not found or unload failed
361+
*/
362+
bool unload_module(const char *name);

modules/test/test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#include <kernel.h>
22

3-
bool EXPORTED mod_init(void) {
3+
bool EXPORTED MOD_INIT_SYM(KMOD_ABI)(void) {
44
dprintf("test.ko: mod_init called!\n");
55
return true;
66
}
77

8-
void EXPORTED mod_exit(void) {
8+
void EXPORTED MOD_EXIT_SYM(KMOD_ABI)(void) {
99
dprintf("test.ko: mod_exit called!\n");
1010
}

src/basic/file_io.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,21 @@ const char* make_full_path(struct basic_ctx* ctx, const char* relative)
88
{
99
uint8_t cpu = logical_cpu_id();
1010
if (*relative == '/') {
11-
dprintf("make_full_path %s -> %s\n", relative, relative);
1211
return relative;
1312
}
1413

1514
const char* csd = proc_cur(cpu)->csd;
1615
char qualified_path[MAX_STRINGLEN];
1716

1817
if (*relative == 0) {
19-
dprintf("make_full_path %s -> %s\n", relative, csd);
2018
return csd;
2119
}
2220

2321
if (*csd == '/' && *(csd+1) == 0) {
2422
snprintf(qualified_path, MAX_STRINGLEN, "%s%s", csd, relative);
25-
dprintf("make_full_path %s -> %s\n", relative, qualified_path);
2623
return gc_strdup(ctx, qualified_path);
2724
}
2825
snprintf(qualified_path, MAX_STRINGLEN, "%s/%s", csd, relative);
29-
dprintf("make_full_path %s -> %s\n", relative, qualified_path);
3026
return gc_strdup(ctx, qualified_path);
3127
}
3228

src/fs/fat32/directory.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ fs_directory_entry_t* parse_fat32_directory(fs_tree_t* tree, fat32_t* info, uint
6969
info->volume_name = strdup(dotless);
7070
highest_lfn_order = -1;
7171
memset(&lfns, 0, sizeof(lfns));
72-
dprintf("volume id\n");
7372
} else if ((entry->attr & ATTR_LONG_NAME) == ATTR_LONG_NAME) {
7473
/* LFN entry: stash by sequence index (mask off 0x40) */
7574
lfn_t* lfn = (lfn_t*)entry;
@@ -80,12 +79,10 @@ fs_directory_entry_t* parse_fat32_directory(fs_tree_t* tree, fat32_t* info, uint
8079
highest_lfn_order = (int16_t)idx;
8180
}
8281
}
83-
dprintf("long name\n");
8482
} else {
8583
/* SFN (regular file/dir) - build entry, optionally with LFN */
8684
char sfn[13];
8785
char sfn_dotless[13];
88-
dprintf("short name\n");
8986
parse_short_name(entry, sfn, sfn_dotless);
9087

9188
fs_directory_entry_t* file = kmalloc(sizeof(fs_directory_entry_t));
@@ -130,8 +127,6 @@ fs_directory_entry_t* parse_fat32_directory(fs_tree_t* tree, fat32_t* info, uint
130127

131128
file->next = list;
132129
list = file;
133-
134-
dprintf("Append name\n");
135130
}
136131

137132
next_entry:

src/fs/filesystem.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ bool make_vfs_path(const char* path, fs_tree_t* node) {
243243
kfree_null(&pathinfo);
244244
find.parent = pathname;
245245
void* new_item = hashmap_set(vfs_hash, &find);
246-
dprintf("VFS tree branch: %s\n", path);
247246
/* If parent doesn't exist, create it */
248247
bool parent_is_root = (strcmp(find.parent, "/") == 0);
249248
if (!find_vfs_path(find.parent)) {
@@ -1004,7 +1003,6 @@ void retrieve_node_from_driver(fs_tree_t* node)
10041003
* delete the old content first to avoid a memleak.
10051004
*/
10061005

1007-
dprintf("retrieve_node_from_driver\n");
10081006
if (node == NULL) {
10091007
return;
10101008
}
@@ -1142,11 +1140,9 @@ uint8_t verify_path(const char* path)
11421140
fs_tree_t* walk_to_node(fs_tree_t* current_node, const char* path)
11431141
{
11441142
if (!verify_path(path)) {
1145-
dprintf("walk_to_node: Verify path failed: %s\n", path);
11461143
return NULL;
11471144
}
11481145
if (!strcmp(path, "/")) {
1149-
dprintf("walk_to_node: returning root of tree: %s\n", path);
11501146
return fs_tree;
11511147
}
11521148
/* First build the dir stack */
@@ -1164,7 +1160,6 @@ fs_tree_t* walk_to_node(fs_tree_t* current_node, const char* path)
11641160
if (*parse == '/') {
11651161
*parse = 0;
11661162
walk->name = strdup(last);
1167-
dprintf("Dirstack part: '%s'\n", walk->name);
11681163
last = parse + 1;
11691164

11701165
dirstack_t* next = kmalloc(sizeof(dirstack_t));
@@ -1179,9 +1174,7 @@ fs_tree_t* walk_to_node(fs_tree_t* current_node, const char* path)
11791174
}
11801175
walk->next = NULL;
11811176
walk->name = strdup(last);
1182-
dprintf("Made dirstack: '%s'\n", path);
11831177
fs_tree_t* result = walk_to_node_internal(current_node, ds);
1184-
dprintf("Walked nodes, got result %p\n", result);
11851178
while (ds) {
11861179
dirstack_t* next = ds->next;
11871180
kfree_null(&ds->name);
@@ -1191,8 +1184,7 @@ fs_tree_t* walk_to_node(fs_tree_t* current_node, const char* path)
11911184
return result;
11921185
}
11931186

1194-
fs_directory_entry_t* find_file_in_dir(fs_tree_t* directory, const char* filename)
1195-
{
1187+
fs_directory_entry_t* find_file_in_dir(fs_tree_t* directory, const char* filename) {
11961188
if (!directory || !filename) {
11971189
fs_set_error(FS_ERR_INVALID_ARG);
11981190
return NULL;
@@ -1511,7 +1503,6 @@ int attach_filesystem(const char* virtual_path, filesystem_t* fs, void* opaque)
15111503
}
15121504
item->responsible_driver = (void*)fs;
15131505
item->name = !strcmp(virtual_path, "/") ? strdup("/") : fs_get_name_part(virtual_path);
1514-
dprintf("Attach virtual path '%s' -> '%s'", virtual_path, item->name ? item->name : "<NULL>");
15151506
item->opaque = opaque;
15161507
item->dirty = 1;
15171508
item->files = NULL;

src/fs/iso9660.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,6 @@ fs_directory_entry_t *parse_directory(fs_tree_t *node, iso9660 *info, uint32_t s
166166
thisentry->filename[j] = 0;
167167
}
168168

169-
dprintf("Retrieved filename: %s\n", thisentry->filename);
170-
171169
thisentry->year = fentry->recording_date.years_since_1900 + 1900;
172170
thisentry->month = fentry->recording_date.month;
173171
thisentry->day = fentry->recording_date.day;

src/init.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ init_func_t init_funcs[] = {
1010
init_acpi, init_idt, boot_aps, init_pci, init_realtime_clock,
1111
init_devicenames, init_keyboard, init_ide, init_ahci,
1212
init_filesystem, init_devfs, init_iso9660, init_fat32,
13-
init_rfs, init_rtl8139, init_e1000,
13+
init_rfs, init_modules, init_rtl8139, init_e1000,
1414
NULL,
1515
};
1616

@@ -19,7 +19,7 @@ char* init_funcs_names[] = {
1919
"idt", "cpus", "pci", "clock",
2020
"devicenames", "keyboard", "ide", "ahci",
2121
"filesystem", "devfs", "iso9660", "fat32",
22-
"rfs", "rtl8139", "e1000",
22+
"rfs", "modules", "rtl8139", "e1000",
2323
NULL,
2424
};
2525

src/kernel.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,7 @@ void kmain()
2828
preboot_fail("Failed to mount boot drive to VFS!");
2929
}
3030

31-
/*module test;
32-
fs_directory_entry_t * f = fs_get_file_info("/system/modules/test.ko");
33-
if (f) {
34-
dprintf("*** MOD TEST: Got info on test.ko size %lu\n", f->size);
35-
void* module_content = kmalloc(f->size);
36-
if (fs_read_file(f, 0, f->size, module_content)) {
37-
dprintf("*** LOADING TEST MODULE test.ko ***\n");
38-
if (module_load_from_memory(module_content, f->size, &test)) {
39-
module_unload(&test);
40-
}
41-
dprintf("*** DONE WITH TEST MODULE test.ko ***\n");
42-
} else {
43-
dprintf("Couldnt read test.ko\n");
44-
}
45-
} else {
46-
dprintf("*** MOD TEST: Cant get info on test.ko\n");
47-
}*/
31+
//load_module("test");
4832

4933
init_process();
5034
}

0 commit comments

Comments
 (0)