98 lines
2.9 KiB
C
98 lines
2.9 KiB
C
// System root volume selection. This file keeps boot-volume identity in one place so loaders do not guess.
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <kernel/ke_system_root.h>
|
|
#include <kernel/ke_debug.h>
|
|
#include <kernel/io_file.h>
|
|
|
|
static uint8_t gSystemRootDrive;
|
|
static bool gSystemRootReady;
|
|
|
|
// Builds a drive-qualified path without depending on any process CWD.
|
|
static bool KiBuildDrivePath(uint8_t drive, const char* relative, char* out, size_t outSize) {
|
|
if (!relative || !out || drive >= KE_SYSTEM_ROOT_MAX_DRIVES)
|
|
return false;
|
|
|
|
size_t relLen = strlen(relative);
|
|
if (relLen + 4 > outSize)
|
|
return false;
|
|
|
|
out[0] = (char)('0' + drive);
|
|
out[1] = ':';
|
|
out[2] = '/';
|
|
memcpy(out + 3, relative, relLen + 1);
|
|
return true;
|
|
}
|
|
|
|
// Returns true when the candidate volume looks like the volume that booted the kernel.
|
|
static bool KiDriveLooksLikeSystemRoot(uint8_t drive) {
|
|
static const char* required[] = {
|
|
"system/colonel.exe",
|
|
"system/hal.dll",
|
|
"drivers/drivers.ini",
|
|
};
|
|
|
|
char path[1024];
|
|
for (size_t i = 0; i < sizeof(required) / sizeof(required[0]); i++) {
|
|
if (!KiBuildDrivePath(drive, required[i], path, sizeof(path)))
|
|
return false;
|
|
|
|
FILE_OBJECT* file = NULL;
|
|
KSTATUS s = IoOpenFile(SysSvFromCstr(path), &file);
|
|
if (!KSUCCESS(s))
|
|
return false;
|
|
IoCloseFile(file);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Selects the mounted volume that contains the kernel/system tree.
|
|
KSTATUS KeInitializeSystemRootVolume(void) {
|
|
for (uint8_t drive = 0; drive < KE_SYSTEM_ROOT_MAX_DRIVES; drive++) {
|
|
if (!IoFilesystemPresent(drive))
|
|
continue;
|
|
if (!KiDriveLooksLikeSystemRoot(drive))
|
|
continue;
|
|
|
|
gSystemRootDrive = drive;
|
|
gSystemRootReady = true;
|
|
DbgPrint("System root: drive=%u\n", drive);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return STATUS_NOT_FOUND;
|
|
}
|
|
|
|
// Returns whether the system root volume has been selected.
|
|
bool KeSystemRootReady(void) {
|
|
return gSystemRootReady;
|
|
}
|
|
|
|
// Returns the selected system root drive, or zero before discovery.
|
|
uint8_t KeGetSystemRootDrive(void) {
|
|
return gSystemRootReady ? gSystemRootDrive : 0;
|
|
}
|
|
|
|
// Builds an absolute path rooted at the selected system volume.
|
|
bool KeBuildSystemRootPath(const char* relative, char* out, size_t outSize) {
|
|
if (!gSystemRootReady)
|
|
return false;
|
|
return KiBuildDrivePath(gSystemRootDrive, relative, out, outSize);
|
|
}
|
|
|
|
// Opens a file rooted at the selected system volume.
|
|
KSTATUS KeOpenSystemRootFile(const char* relative, FILE_OBJECT** out) {
|
|
if (!out)
|
|
return STATUS_INVALID_PARAMETER;
|
|
*out = NULL;
|
|
|
|
char path[1024];
|
|
if (!KeBuildSystemRootPath(relative, path, sizeof(path)))
|
|
return STATUS_NOT_FOUND;
|
|
return IoOpenFile(SysSvFromCstr(path), out);
|
|
}
|