The Pedigree Project  0.1
modules/system/config/main.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "modules/Module.h"
21 #include "pedigree/kernel/BootstrapInfo.h"
22 #include "pedigree/kernel/Log.h"
23 #include "pedigree/kernel/linker/KernelElf.h"
24 #include "pedigree/kernel/panic.h"
25 #include "pedigree/kernel/processor/MemoryRegion.h"
26 #include "pedigree/kernel/processor/PhysicalMemoryManager.h"
27 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
28 #include "pedigree/kernel/processor/types.h"
29 #include "pedigree/kernel/utilities/utility.h"
30 #include "sqlite3/sqlite3.h"
31 
32 extern BootstrapStruct_t *g_pBootstrapInfo;
33 
34 sqlite3 *g_pSqlite = 0;
35 
36 static uint8_t *g_pFile = 0;
37 static size_t g_FileSz = 0;
38 
39 extern "C" {
40 void log_(unsigned long a);
41 int atoi(const char *str);
42 }
43 
44 extern "C" void log_(unsigned long a)
45 {
46  NOTICE("Int: " << a);
47 }
48 
49 extern "C" int atoi(const char *str)
50 {
51  return StringToUnsignedLong(str, 0, 10);
52 }
53 
54 extern "C" struct tm *gmtime(struct tm *timep)
55 {
56  return 0;
57 }
58 
59 extern "C" size_t
60 strftime(char *s, size_t max, const char *format, const struct tm *tm)
61 {
62  return 0;
63 }
64 
65 static int xClose(sqlite3_file *file)
66 {
67  return 0;
68 }
69 
70 static int xRead(sqlite3_file *file, void *ptr, int iAmt, sqlite3_int64 iOfst)
71 {
72  int ret = 0;
73  if ((static_cast<size_t>(iOfst + iAmt)) >= g_FileSz)
74  {
75  if (static_cast<size_t>(iAmt) > g_FileSz)
76  iAmt = g_FileSz;
77  ByteSet(ptr, 0, iAmt);
78  iAmt = g_FileSz - iOfst;
79  ret = SQLITE_IOERR_SHORT_READ;
80  }
81  MemoryCopy(ptr, &g_pFile[iOfst], iAmt);
82  return ret;
83 }
84 
85 static int
86 xReadFail(sqlite3_file *file, void *ptr, int iAmt, sqlite3_int64 iOfst)
87 {
88  ByteSet(ptr, 0, iAmt);
89  return SQLITE_IOERR_SHORT_READ;
90 }
91 
92 static int
93 xWrite(sqlite3_file *file, const void *ptr, int iAmt, sqlite3_int64 iOfst)
94 {
95  // Write past the end of the file?
96  if (static_cast<size_t>(iOfst + iAmt) >= g_FileSz)
97  {
99  return SQLITE_IOERR_WRITE;
100  }
101 
102  MemoryCopy(&g_pFile[iOfst], ptr, iAmt);
103  return 0;
104 }
105 
106 static int
107 xWriteFail(sqlite3_file *file, const void *ptr, int iAmt, sqlite3_int64 iOfst)
108 {
109  return 0;
110 }
111 
112 static int xTruncate(sqlite3_file *file, sqlite3_int64 size)
113 {
114  return 0;
115 }
116 
117 static int xSync(sqlite3_file *file, int flags)
118 {
119  return 0;
120 }
121 
122 static int xFileSize(sqlite3_file *file, sqlite3_int64 *pSize)
123 {
124  *pSize = g_FileSz;
125  return 0;
126 }
127 
128 static int xLock(sqlite3_file *file, int a)
129 {
130  return 0;
131 }
132 
133 static int xUnlock(sqlite3_file *file, int a)
134 {
135  return 0;
136 }
137 
138 static int xCheckReservedLock(sqlite3_file *file, int *pResOut)
139 {
140  *pResOut = 0;
141  return 0;
142 }
143 
144 static int xFileControl(sqlite3_file *file, int op, void *pArg)
145 {
146  return 0;
147 }
148 
149 static int xSectorSize(sqlite3_file *file)
150 {
151  return 1;
152 }
153 
154 static int xDeviceCharacteristics(sqlite3_file *file)
155 {
156  return 0;
157 }
158 
159 static struct sqlite3_io_methods theio = {1,
160  &xClose,
161  &xRead,
162  &xWrite,
163  &xTruncate,
164  &xSync,
165  &xFileSize,
166  &xLock,
167  &xUnlock,
168  &xCheckReservedLock,
169  &xFileControl,
170  &xSectorSize,
171  &xDeviceCharacteristics,
172  0,
173  0,
174  0,
175  0,
176  0,
177  0};
178 
179 static struct sqlite3_io_methods theio_fail = {1,
180  &xClose,
181  &xReadFail,
182  &xWriteFail,
183  &xTruncate,
184  &xSync,
185  &xFileSize,
186  &xLock,
187  &xUnlock,
188  &xCheckReservedLock,
189  &xFileControl,
190  &xSectorSize,
191  &xDeviceCharacteristics,
192  0,
193  0,
194  0,
195  0,
196  0,
197  0};
198 
199 static int xOpen(
200  sqlite3_vfs *vfs, const char *zName, sqlite3_file *file, int flags,
201  int *pOutFlags)
202 {
203  if (StringCompare(zName, "root»/.pedigree-root"))
204  {
205  // Assume journal file, return failure functions.
206  file->pMethods = &theio_fail;
207  return 0;
208  }
209 
210  if (!g_pBootstrapInfo->isDatabaseLoaded())
211  {
212  FATAL("Config database not loaded!");
213  }
214 
215  file->pMethods = &theio;
216  return 0;
217 }
218 
219 static int xDelete(sqlite3_vfs *vfs, const char *zName, int syncDir)
220 {
221  return 0;
222 }
223 
224 static int xAccess(sqlite3_vfs *vfs, const char *zName, int flags, int *pResOut)
225 {
226  return 0;
227 }
228 
229 static int
230 xFullPathname(sqlite3_vfs *vfs, const char *zName, int nOut, char *zOut)
231 {
232  StringCopyN(zOut, zName, nOut);
233  return 0;
234 }
235 
236 static void *xDlOpen(sqlite3_vfs *vfs, const char *zFilename)
237 {
238  return 0;
239 }
240 
241 static void xDlError(sqlite3_vfs *vfs, int nByte, char *zErrMsg)
242 {
243 }
244 
245 static void (*xDlSym(sqlite3_vfs *vfs, void *p, const char *zSymbol))(void)
246 {
247  return 0;
248 }
249 
250 static void xDlClose(sqlite3_vfs *vfs, void *v)
251 {
252 }
253 
254 static int xRandomness(sqlite3_vfs *vfs, int nByte, char *zOut)
255 {
256  return 0;
257 }
258 
259 static int xSleep(sqlite3_vfs *vfs, int microseconds)
260 {
261  return 0;
262 }
263 
264 static int xCurrentTime(sqlite3_vfs *vfs, sqlite3_int64 *)
265 {
266  return 0;
267 }
268 
269 static int xGetLastError(sqlite3_vfs *vfs, int i, char *c)
270 {
271  return 0;
272 }
273 
274 static struct sqlite3_vfs thevfs = {1,
275  sizeof(void *),
276  32,
277  0,
278  "no-vfs",
279  0,
280  &xOpen,
281  &xDelete,
282  &xAccess,
283  &xFullPathname,
284  &xDlOpen,
285  &xDlError,
286  &xDlSym,
287  &xDlClose,
288  &xRandomness,
289  &xSleep,
290  &xCurrentTime,
291  &xGetLastError,
292  0,
293  0,
294  0,
295  0};
296 
297 int sqlite3_os_init()
298 {
299  sqlite3_vfs_register(&thevfs, 1);
300  return 0;
301 }
302 
303 int sqlite3_os_end()
304 {
305  return 0;
306 }
307 
308 static void xCallback0(sqlite3_context *context, int n, sqlite3_value **values)
309 {
310  const unsigned char *text = sqlite3_value_text(values[0]);
311 
312  if (!text)
313  return;
314 
315  uintptr_t x;
316  if (text[0] == '0')
317  {
318  x = StringToUnsignedLong(reinterpret_cast<const char *>(text), 0, 16);
319  }
320  else
321  {
323  reinterpret_cast<const char *>(text));
324  if (!x)
325  {
326  ERROR(
327  "Couldn't trigger callback `"
328  << reinterpret_cast<const char *>(text)
329  << "': symbol not found.");
330  return;
331  }
332  }
333 
334  void (*func)(void) = reinterpret_cast<void (*)(void)>(x);
335  func();
336  sqlite3_result_int(context, 0);
337 }
338 
339 static void xCallback1(sqlite3_context *context, int n, sqlite3_value **values)
340 {
341  const char *text =
342  reinterpret_cast<const char *>(sqlite3_value_text(values[0]));
343 
344  if (!text)
345  return;
346 
347  uintptr_t x;
348  if (text[0] == '0')
349  {
350  x = StringToUnsignedLong(text, 0, 16);
351  }
352  else
353  {
354  x = KernelElf::instance().lookupSymbol(text);
355  if (!x)
356  {
357  ERROR(
358  "Couldn't trigger callback `" << text
359  << "': symbol not found.");
360  return;
361  }
362  }
363 
364  void (*func)(const char *) = reinterpret_cast<void (*)(const char *)>(x);
365  func(reinterpret_cast<const char *>(sqlite3_value_text(values[1])));
366  sqlite3_result_int(context, 0);
367 }
368 
369 static void xCallback2(sqlite3_context *context, int n, sqlite3_value **values)
370 {
371  const char *text =
372  reinterpret_cast<const char *>(sqlite3_value_text(values[0]));
373 
374  if (!text)
375  return;
376 
377  uintptr_t x;
378  if (text[0] == '0')
379  {
380  x = StringToUnsignedLong(text, 0, 16);
381  }
382  else
383  {
384  x = KernelElf::instance().lookupSymbol(text);
385  if (!x)
386  {
387  ERROR(
388  "Couldn't trigger callback `" << text
389  << "': symbol not found.");
390  return;
391  }
392  }
393 
394  void (*func)(const char *, const char *) =
395  reinterpret_cast<void (*)(const char *, const char *)>(x);
396  func(
397  reinterpret_cast<const char *>(sqlite3_value_text(values[1])),
398  reinterpret_cast<const char *>(sqlite3_value_text(values[2])));
399  sqlite3_result_int(context, 0);
400 }
401 
402 #ifdef STATIC_DRIVERS
403 #include "config_database.h"
404 #elif !defined(HOSTED)
405 // Memory region containing the config database.
406 MemoryRegion region("Config");
407 #endif
408 
409 // Entry point for --gc-sections.
410 static bool init()
411 {
412 #ifndef STATIC_DRIVERS
413  if (!g_pBootstrapInfo->isDatabaseLoaded())
414  FATAL("Database not loaded, cannot continue.");
415 
416  uint8_t *pPhys = g_pBootstrapInfo->getDatabaseAddress();
417  size_t sSize = g_pBootstrapInfo->getDatabaseSize();
418 
419  if ((reinterpret_cast<physical_uintptr_t>(pPhys) &
421  panic("Config: Alignment issues");
422 
423 #ifdef HOSTED
424  g_pFile = new uint8_t[sSize];
425  MemoryCopy(g_pFile, pPhys, sSize);
426  g_FileSz = sSize;
427 #else
428  if (PhysicalMemoryManager::instance().allocateRegion(
429  region,
430  (sSize + PhysicalMemoryManager::getPageSize() - 1) /
433  reinterpret_cast<physical_uintptr_t>(pPhys)) == false)
434  {
435  ERROR("Config: allocateRegion failed.");
436  return false;
437  }
438 
439  g_pFile = reinterpret_cast<uint8_t *>(region.virtualAddress());
440  g_FileSz = sSize;
441 #endif // HOSTED
442 #else
443  g_pFile = file;
444  g_FileSz = sizeof file;
445 #endif
446 
447  sqlite3_initialize();
448  int ret = sqlite3_open("root»/.pedigree-root", &g_pSqlite);
449  if (ret)
450  {
451  FATAL("sqlite3 error: " << sqlite3_errmsg(g_pSqlite));
452  }
453 
454  sqlite3_create_function(
455  g_pSqlite, "pedigree_callback", 1, SQLITE_ANY, 0, &xCallback0, 0, 0);
456  sqlite3_create_function(
457  g_pSqlite, "pedigree_callback", 2, SQLITE_ANY, 0, &xCallback1, 0, 0);
458  sqlite3_create_function(
459  g_pSqlite, "pedigree_callback", 3, SQLITE_ANY, 0, &xCallback2, 0, 0);
460 
461  return true;
462 }
463 
464 static void destroy()
465 {
466  // Shut down sqlite, cleaning up the opened file along the way.
467  sqlite3_close(g_pSqlite);
468  sqlite3_shutdown();
469 
470 #if !defined(STATIC_DRIVERS) && !defined(HOSTED)
471  region.free();
472 #endif
473 }
474 
475 MODULE_INFO("config", &init, &destroy);
Bootstrap structure passed to the kernel entry point.
static PhysicalMemoryManager & instance()
const char * lookupSymbol(uintptr_t addr, uintptr_t *startAddr, T *symbolTable)
Definition: linker/Elf.cc:1164
static KernelElf & instance()
Definition: KernelElf.h:129
#define NOTICE(text)
Definition: Log.h:74
Special memory entity in the kernel&#39;s virtual address space.
Definition: MemoryRegion.h:35
Definition: sqlite3.c:17890
void * virtualAddress() const
Definition: MemoryRegion.cc:39
#define ERROR(text)
Definition: Log.h:82
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition: panic.cc:121
#define FATAL(text)
Definition: Log.h:89