- VMM cluster: XJ3-E/LIN-E/VMM-E/VMX-E/EPT-E/IPC-E/VVB-E (124 sites) - kernel cluster: TST-E/MM-E/UTRW-E/LAPIC-E/IDT-E/SAS-E/PRB-E/NETST-E/DKM-E (117 sites) - whitelist fixes: vmm_init env probes E10-E14 fallback, disk_log read-only block path, DSL-E05 non-FAT32 device 0 probe - QEMU smoke: wizard -> USER.CONF -> login -> desktop ready, zero spurious panic
493 lines
17 KiB
C
493 lines
17 KiB
C
#include <utsm/dkm.h>
|
||
#include <utsm/log.h>
|
||
#include <utsm/panic.h>
|
||
#include <utsm/types.h>
|
||
#include "../arch/x86_64/limine.h"
|
||
#include "../kernel/ini_parser.h"
|
||
|
||
/* 前向声明:带 FUCK [drivers] 过滤的加载入口(定义见下文) */
|
||
void dsm_load_by_manifest_ex(const ini_config *cfg);
|
||
|
||
#define DSM_MAX_DRIVERS_PER_STAGE 8
|
||
#define DSM_MAX_STAGES 4
|
||
#define DSM_MAX_DEPENDS 4
|
||
#define DSM_MAX_PROVIDES 4
|
||
|
||
typedef struct dsm_driver_entry {
|
||
char name[32];
|
||
char path[64];
|
||
u32 class_id;
|
||
u32 required;
|
||
char depends[DSM_MAX_DEPENDS][32];
|
||
u32 depend_count;
|
||
char provides[DSM_MAX_PROVIDES][32];
|
||
u32 provide_count;
|
||
struct limine_file *boot_module;
|
||
int loaded;
|
||
} dsm_driver_entry;
|
||
|
||
typedef struct dsm_stage_entry {
|
||
u32 id;
|
||
char name[16];
|
||
u32 required;
|
||
dsm_driver_entry drivers[DSM_MAX_DRIVERS_PER_STAGE];
|
||
u32 driver_count;
|
||
} dsm_stage_entry;
|
||
|
||
static dsm_stage_entry g_stages[DSM_MAX_STAGES];
|
||
static u32 g_stage_count;
|
||
|
||
extern volatile struct limine_module_request g_module_request;
|
||
|
||
static int dsm_skip_ws(const char **p) {
|
||
while (**p == ' ' || **p == '\t' || **p == '\n' || **p == '\r') { (*p)++; }
|
||
return 0;
|
||
}
|
||
|
||
static int dsm_expect(const char **p, char c) {
|
||
dsm_skip_ws(p);
|
||
if (**p == c) { (*p)++; return 0; }
|
||
return -1;
|
||
}
|
||
|
||
static int dsm_read_string(const char **p, char *out, u32 max_len) {
|
||
dsm_skip_ws(p);
|
||
if (**p != '"') return -1;
|
||
(*p)++;
|
||
u32 i = 0;
|
||
while (**p && **p != '"' && i + 1 < max_len) {
|
||
out[i++] = **p;
|
||
(*p)++;
|
||
}
|
||
out[i] = 0;
|
||
if (**p != '"') return -1;
|
||
(*p)++;
|
||
return 0;
|
||
}
|
||
|
||
static int dsm_skip_value(const char **p) {
|
||
dsm_skip_ws(p);
|
||
if (**p == '"') {
|
||
char tmp[256];
|
||
return dsm_read_string(p, tmp, sizeof(tmp));
|
||
}
|
||
if (**p == '{') {
|
||
(*p)++;
|
||
int depth = 1;
|
||
while (depth > 0 && **p) {
|
||
if (**p == '{') depth++;
|
||
else if (**p == '}') depth--;
|
||
else if (**p == '"') { (*p)++; while (**p && **p != '"') (*p)++; if (**p) (*p)++; continue; }
|
||
if (depth > 0) (*p)++;
|
||
}
|
||
return 0;
|
||
}
|
||
if (**p == '[') {
|
||
(*p)++;
|
||
int depth = 1;
|
||
while (depth > 0 && **p) {
|
||
if (**p == '[') depth++;
|
||
else if (**p == ']') depth--;
|
||
else if (**p == '"') { (*p)++; while (**p && **p != '"') (*p)++; if (**p) (*p)++; continue; }
|
||
if (depth > 0) (*p)++;
|
||
}
|
||
return 0;
|
||
}
|
||
while (**p && **p != ',' && **p != '}' && **p != ']') (*p)++;
|
||
return 0;
|
||
}
|
||
|
||
static struct limine_file *dsm_find_boot_module(const char *path) {
|
||
struct limine_module_response *rsp = g_module_request.response;
|
||
if (!rsp) return 0;
|
||
for (u64 i = 0; i < rsp->module_count; i++) {
|
||
struct limine_file *f = rsp->modules[i];
|
||
if (f && f->path) {
|
||
const char *fp = f->path;
|
||
while (*fp == '/') fp++;
|
||
usize j = 0;
|
||
usize k = 0;
|
||
while (fp[j]) j++;
|
||
while (path[k]) k++;
|
||
if (j == k) {
|
||
int match = 1;
|
||
for (usize x = 0; x < j; x++) {
|
||
if (fp[x] != path[x]) { match = 0; break; }
|
||
}
|
||
if (match) return f;
|
||
}
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int streq_static(const char *a, const char *b) {
|
||
usize i = 0;
|
||
while (a[i] && b[i]) {
|
||
if (a[i] != b[i]) return 0;
|
||
i++;
|
||
}
|
||
return a[i] == b[i];
|
||
}
|
||
|
||
static void dsm_parse_driver(const char **p, dsm_driver_entry *drv) {
|
||
drv->depend_count = 0;
|
||
drv->provide_count = 0;
|
||
drv->required = 1;
|
||
drv->boot_module = 0;
|
||
drv->loaded = 0;
|
||
drv->class_id = 0;
|
||
|
||
if (dsm_expect(p, '{') != 0) return;
|
||
while (**p && **p != '}') {
|
||
dsm_skip_ws(p);
|
||
if (**p == '}') break;
|
||
char key[32];
|
||
if (dsm_read_string(p, key, sizeof(key)) != 0) return;
|
||
dsm_expect(p, ':');
|
||
|
||
if (streq_static(key, "name")) {
|
||
dsm_read_string(p, drv->name, sizeof(drv->name));
|
||
} else if (streq_static(key, "path")) {
|
||
dsm_read_string(p, drv->path, sizeof(drv->path));
|
||
} else if (streq_static(key, "class")) {
|
||
char cls[32];
|
||
dsm_read_string(p, cls, sizeof(cls));
|
||
if (streq_static(cls, "platform")) drv->class_id = 1;
|
||
else if (streq_static(cls, "bus")) drv->class_id = 2;
|
||
else if (streq_static(cls, "interrupt")) drv->class_id = 3;
|
||
else if (streq_static(cls, "timer")) drv->class_id = 4;
|
||
else if (streq_static(cls, "console")) drv->class_id = 5;
|
||
else if (streq_static(cls, "storage")) drv->class_id = 6;
|
||
else if (streq_static(cls, "fs")) drv->class_id = 7;
|
||
else if (streq_static(cls, "fs-core")) drv->class_id = 8;
|
||
else if (streq_static(cls, "net")) drv->class_id = 9;
|
||
else if (streq_static(cls, "input")) drv->class_id = 10;
|
||
} else if (streq_static(key, "required")) {
|
||
dsm_skip_ws(p);
|
||
if (**p == 't') { drv->required = 1; (*p) += 4; }
|
||
else if (**p == 'f') { drv->required = 0; (*p) += 5; }
|
||
} else if (streq_static(key, "depends")) {
|
||
if (dsm_expect(p, '[') != 0) return;
|
||
while (**p && **p != ']') {
|
||
dsm_skip_ws(p);
|
||
if (**p == ']') break;
|
||
if (drv->depend_count < DSM_MAX_DEPENDS) {
|
||
dsm_read_string(p, drv->depends[drv->depend_count], 32);
|
||
drv->depend_count++;
|
||
} else { dsm_skip_value(p); }
|
||
dsm_skip_ws(p);
|
||
if (**p == ',') { (*p)++; continue; }
|
||
if (**p == ']') break;
|
||
}
|
||
dsm_expect(p, ']');
|
||
} else if (streq_static(key, "provides")) {
|
||
if (dsm_expect(p, '[') != 0) return;
|
||
while (**p && **p != ']') {
|
||
dsm_skip_ws(p);
|
||
if (**p == ']') break;
|
||
if (drv->provide_count < DSM_MAX_PROVIDES) {
|
||
dsm_read_string(p, drv->provides[drv->provide_count], 32);
|
||
drv->provide_count++;
|
||
} else { dsm_skip_value(p); }
|
||
dsm_skip_ws(p);
|
||
if (**p == ',') { (*p)++; continue; }
|
||
if (**p == ']') break;
|
||
}
|
||
dsm_expect(p, ']');
|
||
} else {
|
||
dsm_skip_value(p);
|
||
}
|
||
dsm_skip_ws(p);
|
||
if (**p == ',') (*p)++;
|
||
}
|
||
dsm_expect(p, '}');
|
||
}
|
||
|
||
static void dsm_parse_stage(const char **p, dsm_stage_entry *stage) {
|
||
stage->driver_count = 0;
|
||
if (dsm_expect(p, '{') != 0) return;
|
||
while (**p && **p != '}') {
|
||
dsm_skip_ws(p);
|
||
if (**p == '}') break;
|
||
char key[32];
|
||
if (dsm_read_string(p, key, sizeof(key)) != 0) return;
|
||
dsm_expect(p, ':');
|
||
|
||
if (streq_static(key, "id")) {
|
||
dsm_skip_ws(p);
|
||
u32 val = 0;
|
||
while (**p >= '0' && **p <= '9') { val = val * 10 + (u32)(**p - '0'); (*p)++; }
|
||
stage->id = val;
|
||
} else if (streq_static(key, "name")) {
|
||
dsm_read_string(p, stage->name, sizeof(stage->name));
|
||
} else if (streq_static(key, "required")) {
|
||
dsm_skip_ws(p);
|
||
if (**p == 't') { stage->required = 1; (*p) += 4; }
|
||
else if (**p == 'f') { stage->required = 0; (*p) += 5; }
|
||
} else if (streq_static(key, "drivers")) {
|
||
if (dsm_expect(p, '[') != 0) return;
|
||
while (**p && **p != ']') {
|
||
dsm_skip_ws(p);
|
||
if (**p == ']') break;
|
||
if (stage->driver_count < DSM_MAX_DRIVERS_PER_STAGE) {
|
||
dsm_parse_driver(p, &stage->drivers[stage->driver_count]);
|
||
stage->driver_count++;
|
||
} else {
|
||
dsm_skip_value(p);
|
||
}
|
||
dsm_skip_ws(p);
|
||
if (**p == ',') { (*p)++; continue; }
|
||
if (**p == ']') break;
|
||
}
|
||
dsm_expect(p, ']');
|
||
} else {
|
||
dsm_skip_value(p);
|
||
}
|
||
dsm_skip_ws(p);
|
||
if (**p == ',') (*p)++;
|
||
}
|
||
dsm_expect(p, '}');
|
||
}
|
||
|
||
static int dsm_parse_manifest(const char *text, u64 size) {
|
||
g_stage_count = 0;
|
||
const char *p = text;
|
||
const char *end = text + size;
|
||
|
||
while (p < end && *p) {
|
||
dsm_skip_ws(&p);
|
||
if (p >= end || !*p) break;
|
||
if (*p == '{' || *p == '}') { p++; continue; }
|
||
if (*p == ',' || *p == ':') { p++; continue; }
|
||
if (*p == '[' || *p == ']') { p++; continue; }
|
||
|
||
char key[32];
|
||
if (dsm_read_string(&p, key, sizeof(key)) != 0) break;
|
||
dsm_expect(&p, ':');
|
||
|
||
if (streq_static(key, "stages")) {
|
||
if (dsm_expect(&p, '[') != 0) {
|
||
/* 严格错误策略插桩:stage 解析失败零降级(DKM-E08) */
|
||
panic_full("DKM-E08 MANIFEST STAGES PARSE FAILED",
|
||
"dsm_parse_manifest: stages array malformed", 0);
|
||
return -1;
|
||
}
|
||
while (p < end && *p) {
|
||
dsm_skip_ws(&p);
|
||
if (*p == ']') { p++; break; }
|
||
if (g_stage_count < DSM_MAX_STAGES) {
|
||
dsm_parse_stage(&p, &g_stages[g_stage_count]);
|
||
g_stage_count++;
|
||
}
|
||
dsm_skip_ws(&p);
|
||
if (*p == ',') p++;
|
||
}
|
||
} else {
|
||
dsm_skip_value(&p);
|
||
}
|
||
dsm_skip_ws(&p);
|
||
if (*p == ',' || *p == '}' || *p == ']') p++;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void dsm_load_by_manifest(void) {
|
||
dsm_load_by_manifest_ex(NULL);
|
||
}
|
||
|
||
static int dsm_ensure_manifest(void) {
|
||
struct limine_module_response *rsp;
|
||
struct limine_file *manifest_file;
|
||
u64 i;
|
||
|
||
if (g_stage_count) return 0;
|
||
rsp = g_module_request.response;
|
||
if (!rsp) {
|
||
log_warn("[DSM] no Limine module response");
|
||
/* 严格错误策略插桩:manifest 缺失零降级(DKM-E09) */
|
||
panic_full("DKM-E09 NO LIMINE MODULE RESPONSE",
|
||
"dsm_ensure_manifest: no Limine module response", 0);
|
||
return -1;
|
||
}
|
||
|
||
manifest_file = 0;
|
||
for (i = 0; i < rsp->module_count; i++) {
|
||
struct limine_file *f = rsp->modules[i];
|
||
if (f && f->path && f->cmdline && streq_static(f->cmdline, "dkm:manifest")) {
|
||
manifest_file = f;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!manifest_file) {
|
||
log_warn("[DSM] manifest not found in boot modules");
|
||
/* 严格错误策略插桩:manifest 缺失零降级(DKM-E10) */
|
||
panic_full("DKM-E10 MANIFEST NOT FOUND",
|
||
"dsm_ensure_manifest: dkm:manifest boot module missing", 0);
|
||
return -1;
|
||
}
|
||
|
||
log_info("[DSM] parsing manifest");
|
||
dsm_parse_manifest((const char *)manifest_file->address, manifest_file->size);
|
||
log_info("[DSM] manifest parsed");
|
||
log_hex64("[DSM] stages=", (u64)g_stage_count);
|
||
return 0;
|
||
}
|
||
|
||
static void dsm_load_stage_range(const ini_config *cfg, int limit_stage, u32 max_stage_id) {
|
||
if (dsm_ensure_manifest() != 0) return;
|
||
|
||
for (u32 si = 0; si < g_stage_count; si++) {
|
||
dsm_stage_entry *stage = &g_stages[si];
|
||
if (limit_stage && stage->id > max_stage_id) continue;
|
||
log_info("[DSM] stage begin");
|
||
log_info(stage->name);
|
||
log_hex64("[DSM] driver count=", stage->driver_count);
|
||
|
||
for (u32 di = 0; di < stage->driver_count; di++) {
|
||
dsm_driver_entry *drv = &stage->drivers[di];
|
||
struct limine_file *f;
|
||
struct dkm_symbol_scan symbols;
|
||
int result;
|
||
|
||
if (drv->loaded) continue;
|
||
|
||
/* === FUCK [drivers] 驱动开关检查 === */
|
||
if (cfg) {
|
||
int enabled = ini_get_bool(cfg, "drivers", drv->name, 1);
|
||
if (!enabled) {
|
||
log_info("[DSM] driver disabled by FUCK: ");
|
||
log_info(drv->name);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
drv->boot_module = dsm_find_boot_module(drv->path);
|
||
if (!drv->boot_module) {
|
||
log_info("[DSM] module not found");
|
||
log_info(drv->name);
|
||
if (drv->required && stage->required) {
|
||
/* 严格错误策略插桩:required 驱动缺模块零降级(DKM-E04) */
|
||
panic_full("DKM-E04 REQUIRED DRIVER MODULE MISSING",
|
||
"required driver boot module not found in manifest stage", 0);
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
f = drv->boot_module;
|
||
log_info("[DSM] loading driver");
|
||
log_info(drv->name);
|
||
|
||
if (dkm_check_elf64(f->address, f->size) != 0) {
|
||
log_error("[DSM] ELF check failed");
|
||
if (drv->required && stage->required) {
|
||
panic_full("DKM-E05 REQUIRED DRIVER ELF INVALID",
|
||
"required driver boot module failed ELF64 check", 0);
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (dkm_scan_symbols(f->address, f->size, &symbols) != 0) {
|
||
log_error("[DSM] symbol scan failed");
|
||
if (drv->required && stage->required) {
|
||
panic_full("DKM-E06 REQUIRED DRIVER SYMBOL SCAN FAILED",
|
||
"required driver symbol scan failed", 0);
|
||
}
|
||
continue;
|
||
}
|
||
|
||
result = dkm_load_elf_rel(f->address, f->size, &symbols);
|
||
if (result != 0) {
|
||
log_error("[DSM] load failed");
|
||
if (drv->required && stage->required) {
|
||
/* 严格错误策略插桩:required 驱动加载失败零降级(DKM-E07) */
|
||
panic_full("DKM-E07 REQUIRED DRIVER LOAD FAILED",
|
||
"required driver relocation/load failed", 0);
|
||
break;
|
||
}
|
||
} else {
|
||
drv->loaded = 1;
|
||
}
|
||
}
|
||
log_info("[DSM] stage end");
|
||
}
|
||
}
|
||
|
||
void dsm_load_by_manifest_upto(const ini_config *cfg, u32 max_stage_id) {
|
||
dsm_load_stage_range(cfg, 1, max_stage_id);
|
||
}
|
||
|
||
void dsm_load_named(const ini_config *cfg, const char *name) {
|
||
if (!name || dsm_ensure_manifest() != 0) {
|
||
/* 严格错误策略插桩:按名加载 manifest 缺失零降级(DKM-E11) */
|
||
panic_full("DKM-E11 NAMED LOAD MANIFEST MISSING",
|
||
"dsm_load_named: null name or manifest unavailable", 0);
|
||
return;
|
||
}
|
||
|
||
for (u32 si = 0; si < g_stage_count; si++) {
|
||
dsm_stage_entry *stage = &g_stages[si];
|
||
for (u32 di = 0; di < stage->driver_count; di++) {
|
||
dsm_driver_entry *drv = &stage->drivers[di];
|
||
struct limine_file *f;
|
||
struct dkm_symbol_scan symbols;
|
||
int result;
|
||
|
||
if (!streq_static(drv->name, name)) continue;
|
||
if (drv->loaded) return;
|
||
if (cfg && !ini_get_bool(cfg, "drivers", drv->name, 1)) {
|
||
log_info("[DSM] driver disabled by FUCK: ");
|
||
log_info(drv->name);
|
||
return;
|
||
}
|
||
drv->boot_module = dsm_find_boot_module(drv->path);
|
||
if (!drv->boot_module) {
|
||
log_warn("[DSM] named module not found");
|
||
log_info(name);
|
||
/* 严格错误策略插桩:named 驱动缺模块零降级(DKM-E12) */
|
||
panic_full("DKM-E12 NAMED DRIVER MODULE MISSING",
|
||
"dsm_load_named: named driver boot module not found", 0);
|
||
return;
|
||
}
|
||
f = drv->boot_module;
|
||
log_info("[DSM] loading named driver");
|
||
log_info(drv->name);
|
||
if (dkm_check_elf64(f->address, f->size) != 0) {
|
||
log_error("[DSM] ELF check failed");
|
||
/* 严格错误策略插桩:named 驱动 ELF 校验失败零降级(DKM-E13) */
|
||
panic_full("DKM-E13 NAMED DRIVER ELF INVALID",
|
||
"dsm_load_named: named driver failed ELF64 check", 0);
|
||
return;
|
||
}
|
||
if (dkm_scan_symbols(f->address, f->size, &symbols) != 0) {
|
||
log_error("[DSM] symbol scan failed");
|
||
/* 严格错误策略插桩:named 驱动符号扫描失败零降级(DKM-E14) */
|
||
panic_full("DKM-E14 NAMED DRIVER SYMBOL SCAN FAILED",
|
||
"dsm_load_named: named driver symbol scan failed", 0);
|
||
return;
|
||
}
|
||
result = dkm_load_elf_rel(f->address, f->size, &symbols);
|
||
if (result != 0) {
|
||
log_error("[DSM] load failed");
|
||
/* 严格错误策略插桩:named 驱动加载失败零降级(DKM-E15) */
|
||
panic_full("DKM-E15 NAMED DRIVER LOAD FAILED",
|
||
"dsm_load_named: named driver relocation/load failed", 0);
|
||
return;
|
||
}
|
||
drv->loaded = 1;
|
||
return;
|
||
}
|
||
}
|
||
log_warn("[DSM] named driver not in manifest");
|
||
log_info(name);
|
||
/* 严格错误策略插桩:named 驱动不在 manifest 零降级(DKM-E16) */
|
||
panic_full("DKM-E16 NAMED DRIVER NOT IN MANIFEST",
|
||
"dsm_load_named: named driver not found in manifest", 0);
|
||
}
|
||
|
||
void dsm_load_by_manifest_ex(const ini_config *cfg) {
|
||
dsm_load_stage_range(cfg, 0, 0);
|
||
}
|