kernel safemode: Add functions to get options early
Add get_safemode_option_early() and get_safemode_boolean_early() to get safemode options before the kernel heap has been initialized. They use a simplified parser.
This commit is contained in:
parent
7a1e706df7
commit
9bdb5e0a92
@ -11,6 +11,9 @@
|
||||
#include <safemode_defs.h>
|
||||
|
||||
|
||||
struct kernel_args;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -19,6 +22,13 @@ extern "C" {
|
||||
status_t get_safemode_option(const char* parameter, char* buffer,
|
||||
size_t* _bufferSize);
|
||||
bool get_safemode_boolean(const char* parameter, bool defaultValue);
|
||||
|
||||
// before driver_settings_init() has been called (limited parsing support)
|
||||
status_t get_safemode_option_early(kernel_args* args, const char* parameter,
|
||||
char* buffer, size_t* _bufferSize);
|
||||
bool get_safemode_boolean_early(kernel_args* args, const char* parameter,
|
||||
bool defaultValue);
|
||||
|
||||
status_t _user_get_safemode_option(const char* parameter, char* buffer,
|
||||
size_t* _bufferSize);
|
||||
|
||||
|
@ -4,59 +4,194 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <safemode.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <safemode.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <kernel.h>
|
||||
#include <syscalls.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _BOOT_MODE
|
||||
|
||||
|
||||
extern "C" status_t
|
||||
get_safemode_option(const char* parameter, char* buffer, size_t* _bufferSize)
|
||||
static status_t
|
||||
get_option_from_kernel_args(kernel_args* args, const char* settingsName,
|
||||
const char* parameter, size_t parameterLength, char* buffer,
|
||||
size_t* _bufferSize)
|
||||
{
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
|
||||
void* handle = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
|
||||
if (handle != NULL) {
|
||||
status = B_NAME_NOT_FOUND;
|
||||
|
||||
const char* value = get_driver_parameter(handle, parameter, NULL, NULL);
|
||||
if (value != NULL) {
|
||||
*_bufferSize = strlcpy(buffer, value, *_bufferSize);
|
||||
status = B_OK;
|
||||
// find the settings in the kernel args
|
||||
const char* settings = NULL;
|
||||
for (driver_settings_file* file = args->driver_settings;
|
||||
file != NULL; file = file->next) {
|
||||
if (strcmp(settingsName, file->name) == 0) {
|
||||
settings = file->buffer;
|
||||
break;
|
||||
}
|
||||
|
||||
unload_driver_settings(handle);
|
||||
}
|
||||
|
||||
if (status != B_OK) {
|
||||
// Try kernel settings file as a fall back
|
||||
handle = load_driver_settings("kernel");
|
||||
if (handle != NULL) {
|
||||
const char* value = get_driver_parameter(handle, parameter, NULL,
|
||||
NULL);
|
||||
if (value != NULL) {
|
||||
*_bufferSize = strlcpy(buffer, value, *_bufferSize);
|
||||
status = B_OK;
|
||||
if (settings == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// Unfortunately we can't just use parse_driver_settings_string(), since
|
||||
// we might not have a working heap yet. So we do very limited parsing
|
||||
// ourselves.
|
||||
const char* settingsEnd = settings + strlen(settings);
|
||||
int32 parameterLevel = 0;
|
||||
|
||||
while (*settings != '\0') {
|
||||
// find end of line
|
||||
const char* lineEnd = strchr(settings, '\n');
|
||||
const char* nextLine;
|
||||
if (lineEnd != NULL)
|
||||
nextLine = lineEnd + 1;
|
||||
else
|
||||
nextLine = lineEnd = settingsEnd;
|
||||
|
||||
// ignore any trailing comments
|
||||
lineEnd = std::find(settings, lineEnd, '#');
|
||||
|
||||
const char* nameStart = NULL;
|
||||
const char* nameEnd = NULL;
|
||||
const char* valueStart = NULL;
|
||||
const char* valueEnd = NULL;
|
||||
const char** elementEnd = NULL;
|
||||
bool sawSeparator = true;
|
||||
|
||||
for (; settings < lineEnd; settings++) {
|
||||
switch (*settings) {
|
||||
case '{':
|
||||
parameterLevel++;
|
||||
sawSeparator = true;
|
||||
break;
|
||||
|
||||
case '}':
|
||||
parameterLevel--;
|
||||
sawSeparator = true;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
// TODO: That's not correct. There should be another loop.
|
||||
sawSeparator = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (parameterLevel != 0)
|
||||
break;
|
||||
|
||||
if (isspace(*settings)) {
|
||||
sawSeparator = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!sawSeparator)
|
||||
break;
|
||||
|
||||
sawSeparator = false;
|
||||
|
||||
if (nameStart == NULL) {
|
||||
nameStart = settings;
|
||||
elementEnd = &nameEnd;
|
||||
} else if (valueStart == NULL) {
|
||||
valueStart = settings;
|
||||
elementEnd = &valueEnd;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
unload_driver_settings(handle);
|
||||
if (sawSeparator && elementEnd != NULL) {
|
||||
*elementEnd = settings;
|
||||
elementEnd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (elementEnd != NULL)
|
||||
*elementEnd = settings;
|
||||
|
||||
if (nameStart != NULL && size_t(nameEnd - nameStart) == parameterLength
|
||||
&& strncmp(parameter, nameStart, parameterLength) == 0) {
|
||||
if (valueStart == NULL)
|
||||
return B_NAME_NOT_FOUND;
|
||||
|
||||
size_t length = valueEnd - valueStart;
|
||||
if (*_bufferSize > 0) {
|
||||
size_t toCopy = std::min(length, *_bufferSize - 1);
|
||||
memcpy(buffer, valueStart, toCopy);
|
||||
buffer[toCopy] = '\0';
|
||||
}
|
||||
|
||||
*_bufferSize = length;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
settings = nextLine;
|
||||
}
|
||||
|
||||
return B_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
#endif // !_BOOT_MODE
|
||||
|
||||
|
||||
static status_t
|
||||
get_option(kernel_args* args, const char* settingsName, const char* parameter,
|
||||
size_t parameterLength, char* buffer, size_t* _bufferSize)
|
||||
{
|
||||
#ifndef _BOOT_MODE
|
||||
if (args != NULL) {
|
||||
return get_option_from_kernel_args(args, settingsName, parameter,
|
||||
parameterLength, buffer, _bufferSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
void* handle = load_driver_settings(settingsName);
|
||||
if (handle == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
status_t status = B_NAME_NOT_FOUND;
|
||||
|
||||
const char* value = get_driver_parameter(handle, parameter, NULL, NULL);
|
||||
if (value != NULL) {
|
||||
*_bufferSize = strlcpy(buffer, value, *_bufferSize);
|
||||
status = B_OK;
|
||||
}
|
||||
|
||||
unload_driver_settings(handle);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
get_option(kernel_args* args, const char* parameter, char* buffer,
|
||||
size_t* _bufferSize)
|
||||
{
|
||||
size_t parameterLength = strlen(parameter);
|
||||
status_t status = get_option(args, B_SAFEMODE_DRIVER_SETTINGS, parameter,
|
||||
parameterLength, buffer, _bufferSize);
|
||||
if (status != B_OK) {
|
||||
// Try kernel settings file as a fall back
|
||||
status = get_option(args, "kernel", parameter, parameterLength, buffer,
|
||||
_bufferSize);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
extern "C" bool
|
||||
get_safemode_boolean(const char* parameter, bool defaultValue)
|
||||
static bool
|
||||
get_boolean(kernel_args* args, const char* parameter, bool defaultValue)
|
||||
{
|
||||
char value[16];
|
||||
size_t length = sizeof(value);
|
||||
|
||||
if (get_safemode_option(parameter, value, &length) != B_OK)
|
||||
if (get_option(args, parameter, value, &length) != B_OK)
|
||||
return defaultValue;
|
||||
|
||||
return !strcasecmp(value, "on") || !strcasecmp(value, "true")
|
||||
@ -65,6 +200,45 @@ get_safemode_boolean(const char* parameter, bool defaultValue)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
get_safemode_option(const char* parameter, char* buffer, size_t* _bufferSize)
|
||||
{
|
||||
return get_option(NULL, parameter, buffer, _bufferSize);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
get_safemode_boolean(const char* parameter, bool defaultValue)
|
||||
{
|
||||
return get_boolean(NULL, parameter, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
#ifndef _BOOT_MODE
|
||||
|
||||
|
||||
status_t
|
||||
get_safemode_option_early(kernel_args* args, const char* parameter,
|
||||
char* buffer, size_t* _bufferSize)
|
||||
{
|
||||
return get_option(args, parameter, buffer, _bufferSize);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
get_safemode_boolean_early(kernel_args* args, const char* parameter,
|
||||
bool defaultValue)
|
||||
{
|
||||
return get_boolean(args, parameter, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
#endif // _BOOT_MODE
|
||||
|
||||
|
||||
// #pragma mark - syscalls
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user