1/*
2 * Copyright 2008, Rene Gollent, rene@gollent.com. All rights reserved.
3 * Copyright 2005-2009, Axel D��rfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include "load_driver_settings.h"
9
10#include <errno.h>
11#include <string.h>
12#include <unistd.h>
13
14#include <OS.h>
15#include <drivers/driver_settings.h>
16
17#include <safemode_defs.h>
18
19#include <boot/driver_settings.h>
20#include <boot/kernel_args.h>
21#include <boot/stage2.h>
22#include <boot/platform.h>
23
24
25static status_t
26load_driver_settings_file(Directory* directory, const char* name)
27{
28	int fd = open_from(directory, name, O_RDONLY);
29	if (fd < 0)
30		return fd;
31
32	struct stat stat;
33	if (fstat(fd, &stat) < 0)
34		return errno;
35
36	char* buffer = (char*)kernel_args_malloc(stat.st_size + 1);
37	if (buffer == NULL)
38		return B_NO_MEMORY;
39
40	if (read(fd, buffer, stat.st_size) != stat.st_size) {
41		kernel_args_free(buffer);
42		return B_IO_ERROR;
43	}
44
45	driver_settings_file* file = (driver_settings_file*)kernel_args_malloc(
46		sizeof(driver_settings_file));
47	if (file == NULL) {
48		kernel_args_free(buffer);
49		return B_NO_MEMORY;
50	}
51
52	buffer[stat.st_size] = '\0';
53		// null terminate the buffer
54
55	strlcpy(file->name, name, sizeof(file->name));
56	file->buffer = buffer;
57	file->size = stat.st_size;
58
59	// add it to the list
60	file->next = gKernelArgs.driver_settings;
61	gKernelArgs.driver_settings = file;
62
63	return B_OK;
64}
65
66
67static void
68apply_boot_settings(void* kernelSettings, void* safemodeSettings)
69{
70#if B_HAIKU_PHYSICAL_BITS > 32
71	if ((kernelSettings != NULL
72			&& get_driver_boolean_parameter(kernelSettings,
73				B_SAFEMODE_4_GB_MEMORY_LIMIT, false, false))
74		|| (safemodeSettings != NULL
75			&& get_driver_boolean_parameter(safemodeSettings,
76				B_SAFEMODE_4_GB_MEMORY_LIMIT, false, false))) {
77		ignore_physical_memory_ranges_beyond_4gb();
78	}
79#endif
80}
81
82
83//	#pragma mark -
84
85
86status_t
87load_driver_settings(stage2_args* /*args*/, Directory* volume)
88{
89	int fd = open_from(volume, "home/config/settings/kernel/drivers", O_RDONLY);
90	if (fd < B_OK)
91		return fd;
92
93	Directory* settings = (Directory*)get_node_from(fd);
94	if (settings == NULL)
95		return B_ENTRY_NOT_FOUND;
96
97	void* cookie;
98	if (settings->Open(&cookie, O_RDONLY) == B_OK) {
99		char name[B_FILE_NAME_LENGTH];
100		while (settings->GetNextEntry(cookie, name, sizeof(name)) == B_OK) {
101			if (!strcmp(name, ".") || !strcmp(name, ".."))
102				continue;
103
104			status_t status = load_driver_settings_file(settings, name);
105			if (status != B_OK)
106				dprintf("Could not load \"%s\" error %" B_PRIx32 "\n", name, status);
107		}
108
109		settings->Close(cookie);
110	}
111
112	return B_OK;
113}
114
115
116status_t
117add_stage2_driver_settings(stage2_args* args)
118{
119	// TODO: split more intelligently
120	for (const char** arg = args->arguments;
121			arg != NULL && args->arguments_count-- && arg[0] != NULL; arg++) {
122		dprintf("adding args: '%s'\n", arg[0]);
123		add_safe_mode_settings((char*)arg[0]);
124	}
125	return B_OK;
126}
127
128
129status_t
130add_safe_mode_settings(const char* settings)
131{
132	if (settings == NULL || settings[0] == '\0')
133		return B_OK;
134
135	size_t length = strlen(settings);
136	char* buffer = (char*)kernel_args_malloc(length + 1);
137	if (buffer == NULL)
138		return B_NO_MEMORY;
139
140	driver_settings_file* file = (driver_settings_file*)kernel_args_malloc(
141		sizeof(driver_settings_file));
142	if (file == NULL) {
143		kernel_args_free(buffer);
144		return B_NO_MEMORY;
145	}
146
147	strlcpy(file->name, B_SAFEMODE_DRIVER_SETTINGS, sizeof(file->name));
148	memcpy(buffer, settings, length + 1);
149	file->buffer = buffer;
150	file->size = length;
151
152	// add it to the list
153	file->next = gKernelArgs.driver_settings;
154	gKernelArgs.driver_settings = file;
155
156	return B_OK;
157}
158
159
160void
161apply_boot_settings()
162{
163	void* kernelSettings = load_driver_settings("kernel");
164	void* safemodeSettings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
165
166	apply_boot_settings(kernelSettings, safemodeSettings);
167
168	if (safemodeSettings != NULL)
169		unload_driver_settings(safemodeSettings);
170	if (kernelSettings)
171		unload_driver_settings(kernelSettings);
172}
173