Files
nt-lite/code/kernel/ke_boot_config.c

163 lines
5.9 KiB
C

// Kernel boot configuration parser. This file intentionally implements only the boot.ini settings the kernel owns.
#include <kernel/ke_boot_config.h>
#include <ntlite/ddk/debug.h>
#include <stdbool.h>
#include <string.h>
// Returns whether one character is horizontal configuration whitespace.
static bool KiBootConfigSpace(char c) {
return c == ' ' || c == '\t' || c == '\r';
}
// Trims horizontal whitespace from one immutable line span.
static void KiBootConfigTrim(const char** begin, const char** end) {
while (*begin < *end && KiBootConfigSpace(**begin))
++*begin;
while (*end > *begin && KiBootConfigSpace((*end)[-1]))
--*end;
}
// Returns whether one immutable span exactly matches a NUL-terminated string.
static bool KiBootConfigSpanEquals(const char* begin, const char* end, const char* text) {
while (begin < end && *text) {
if (*begin++ != *text++)
return false;
}
return begin == end && *text == '\0';
}
// Parses an unsigned numeric configuration value with an optional inline comment.
static KSTATUS KiBootConfigParseUInt32(const char* begin, const char* end, uint32_t* valueOut) {
KiBootConfigTrim(&begin, &end);
// Numeric debug values support inline comments without changing command-line text semantics.
for (const char* p = begin; p < end; ++p) {
if (*p == ';' || *p == '#') {
end = p;
break;
}
}
KiBootConfigTrim(&begin, &end);
if (begin == end || !valueOut)
return NTLSTATUS_INVALID_PARAMETER;
uint32_t base = 10;
if (end - begin >= 2 && begin[0] == '0' && (begin[1] == 'x' || begin[1] == 'X')) {
base = 16;
begin += 2;
if (begin == end)
return NTLSTATUS_INVALID_PARAMETER;
}
uint32_t value = 0;
for (const char* p = begin; p < end; ++p) {
uint32_t digit;
if (*p >= '0' && *p <= '9') digit = (uint32_t)(*p - '0');
else if (*p >= 'a' && *p <= 'f') digit = (uint32_t)(10 + *p - 'a');
else if (*p >= 'A' && *p <= 'F') digit = (uint32_t)(10 + *p - 'A');
else return NTLSTATUS_INVALID_PARAMETER;
if (digit >= base || value > (UINT32_MAX - digit) / base)
return NTLSTATUS_INVALID_PARAMETER;
value = value * base + digit;
}
*valueOut = value;
return NTLSTATUS_SUCCESS;
}
// Copies one trimmed configuration value into a fixed kernel-owned string.
static KSTATUS KiBootConfigCopyString(const char* begin, const char* end, char* buffer, size_t bufferSize) {
KiBootConfigTrim(&begin, &end);
size_t length = (size_t)(end - begin);
if (!buffer || bufferSize == 0 || length >= bufferSize)
return NTLSTATUS_BUFFER_TOO_SMALL;
memcpy(buffer, begin, length);
buffer[length] = '\0';
return NTLSTATUS_SUCCESS;
}
// Parses the kernel-owned boot.ini settings from the raw bootloader string.
KSTATUS KeParseBootConfiguration(const char* text, size_t length, KE_BOOT_CONFIG* configOut) {
if (!text || !configOut)
return NTLSTATUS_INVALID_PARAMETER;
KE_BOOT_CONFIG config = {0};
bool systemVolumeSeen = false;
char section[32] = {0};
size_t offset = 0;
while (offset < length) {
size_t lineStart = offset;
while (offset < length && text[offset] != '\n')
++offset;
size_t lineEnd = offset;
if (offset < length)
++offset;
const char* begin = text + lineStart;
const char* end = text + lineEnd;
KiBootConfigTrim(&begin, &end);
if (begin == end || *begin == ';' || *begin == '#')
continue;
if (*begin == '[') {
if (end[-1] != ']')
return NTLSTATUS_INVALID_PARAMETER;
const char* sectionBegin = begin + 1;
const char* sectionEnd = end - 1;
KiBootConfigTrim(&sectionBegin, &sectionEnd);
size_t sectionLength = (size_t)(sectionEnd - sectionBegin);
if (sectionLength >= sizeof(section))
return NTLSTATUS_BUFFER_TOO_SMALL;
memcpy(section, sectionBegin, sectionLength);
section[sectionLength] = '\0';
continue;
}
const char* equals = NULL;
for (const char* p = begin; p < end; ++p) {
if (*p == '=') {
equals = p;
break;
}
}
if (!equals)
return NTLSTATUS_INVALID_PARAMETER;
const char* keyBegin = begin;
const char* keyEnd = equals;
const char* valueBegin = equals + 1;
const char* valueEnd = end;
KiBootConfigTrim(&keyBegin, &keyEnd);
if (strcmp(section, "boot") == 0 && KiBootConfigSpanEquals(keyBegin, keyEnd, "system_volume")) {
if (systemVolumeSeen)
return NTLSTATUS_INVALID_PARAMETER;
KSTATUS status = KiBootConfigCopyString(valueBegin, valueEnd,
config.SystemVolume, sizeof(config.SystemVolume));
if (!KSUCCESS(status) || config.SystemVolume[0] == '\0')
return KSUCCESS(status) ? NTLSTATUS_INVALID_PARAMETER : status;
systemVolumeSeen = true;
} else if (strcmp(section, "kernel") == 0 && KiBootConfigSpanEquals(keyBegin, keyEnd, "debug")) {
KSTATUS status = KiBootConfigParseUInt32(valueBegin, valueEnd, &config.Debug);
if (!KSUCCESS(status))
return status;
if (config.Debug & ~KE_DEBUG_VALID_MASK)
return NTLSTATUS_INVALID_PARAMETER;
} else if (strcmp(section, "init") == 0 && KiBootConfigSpanEquals(keyBegin, keyEnd, "commandline")) {
KSTATUS status = KiBootConfigCopyString(valueBegin, valueEnd,
config.CommandLine, sizeof(config.CommandLine));
if (!KSUCCESS(status))
return status;
}
}
if (!systemVolumeSeen)
return NTLSTATUS_NOT_FOUND;
*configOut = config;
return NTLSTATUS_SUCCESS;
}