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