PageRenderTime 70ms CodeModel.GetById 5ms RepoModel.GetById 0ms app.codeStats 0ms

/main.c

https://gitlab.com/adam.lukaitis/osdev
C | 560 lines | 505 code | 22 blank | 33 comment | 106 complexity | 5ceb919b5e363b0eaab100d3eba06053 MD5 | raw file
  1. /** @author Levente Kurusa <levex@linux.com> **/
  2. #if !defined(__cplusplus)
  3. #include <stdbool.h> /* C-ben alapbol nincsenek is bool-ok. */
  4. #endif
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include "include/string.h"
  8. #include "include/memory.h"
  9. #include "include/display.h"
  10. #include "display/textmode/dispi_textmode.h"
  11. #include "include/x86/gdt.h"
  12. #include "include/x86/idt.h"
  13. #include "include/pit.h"
  14. #include "include/pic.h"
  15. #include "include/hal.h"
  16. #include "include/tasking.h"
  17. #include "include/levos.h"
  18. #include "include/keyboard.h"
  19. #include "include/device.h"
  20. #include "include/rtc.h"
  21. #include "include/x86/v86.h"
  22. #include "include/floppy.h"
  23. #include "include/ext2.h"
  24. #include "include/proc.h"
  25. #include "include/ata.h"
  26. #include "include/vfs.h"
  27. #include "include/proc.h"
  28. #include "include/devfs.h"
  29. #include "include/loader.h"
  30. #include "include/module.h"
  31. #include "include/elf.h"
  32. #include "include/pci.h"
  33. static DISPLAY* disp = 0;
  34. MODULE("MAIN");
  35. void _test();
  36. int levex_id = 0;
  37. extern uint32_t kernel_end;
  38. extern uint32_t kernel_base;
  39. static char* hostname = "levex-levos";
  40. static char* username = "root";
  41. void __login()
  42. {
  43. uint8_t *buffer = (uint8_t*)malloc(64);
  44. int l = 0;
  45. char c = 0;
  46. kprintf(" _ ____ _____ _ _ \n"
  47. " | | / __ \\ / ____| || | \n"
  48. " | | _____ _| | | | (___ | || |_ \n"
  49. " | | / _ \\ \\ / / | | |\\___ \\|__ _|\n"
  50. " | |___| __/\\ V /| |__| |____) | | | \n"
  51. " |______\\___| \\_/ \\____/|_____/ |_| \n");
  52. retry:
  53. memset(buffer, 0, 64);
  54. kprintf("\n%s login: ", hostname);
  55. c = 0;
  56. l = 0;
  57. while(1)
  58. {
  59. c = keyboard_get_key();
  60. if(!c) { schedule_noirq(); continue;}
  61. if(c == '\n')
  62. {
  63. if(strcmp((char *)buffer, "root") == 0)
  64. {
  65. break;
  66. }
  67. goto retry;
  68. }
  69. buffer[l++] = c;
  70. buffer[l] = 0;
  71. disp->putc(c);
  72. }
  73. memset(buffer, 0, 64);
  74. kprintf("\n%s@%s password: ", username, hostname);
  75. l = 0;
  76. c = 0;
  77. while(1)
  78. {
  79. c = keyboard_get_key();
  80. if(!c) { schedule_noirq(); continue;}
  81. if(c == '\n')
  82. {
  83. if(strcmp((char *)buffer, "toor") == 0)
  84. {
  85. disp->putc('\n');
  86. _kill();
  87. } else goto retry;
  88. }
  89. buffer[l] = c;
  90. buffer[l + 1] = 0;
  91. l++;
  92. }
  93. }
  94. void __cursor_updater()
  95. {
  96. uint16_t lastpos = 0;
  97. while(1)
  98. {
  99. uint16_t pos = disp->con.cy*80 + disp->con.cx;
  100. if(pos == lastpos) { schedule_noirq(); continue; }
  101. lastpos = pos;
  102. outportb(0x3D4, 0x0F);
  103. outportb(0x3D5, (uint8_t)pos&0xFF);
  104. outportb(0x3D4, 0x0E);
  105. outportb(0x3D5, (uint8_t)(pos>>8)&0xFF);
  106. schedule_noirq();
  107. }
  108. _kill();
  109. }
  110. void test_device_read(uint8_t* buffer, uint32_t offset UNUSED, uint32_t len, device_t *dev UNUSED)
  111. {
  112. len --;
  113. while(len--)
  114. {
  115. switch(len%5)
  116. {
  117. case 0:
  118. *buffer++ = 'X';
  119. break;
  120. case 1:
  121. *buffer++ = 'E';
  122. break;
  123. case 2:
  124. *buffer++ = 'V';
  125. break;
  126. case 3:
  127. *buffer++ = 'E';
  128. break;
  129. case 4:
  130. *buffer++ = 'L';
  131. break;
  132. }
  133. }
  134. *buffer = 0;
  135. }
  136. void create_test_device()
  137. {
  138. device_t *testdev = 0;
  139. testdev = (device_t*)malloc(sizeof(device_t));
  140. testdev->name = "/dev/levex";
  141. testdev->unique_id = 0x1337;
  142. testdev->dev_type = DEVICE_CHAR;
  143. testdev->read = (uint8_t(*)(uint8_t*, uint32_t, uint32_t, device_t*))test_device_read;
  144. levex_id = device_add(testdev);
  145. _kill();
  146. }
  147. void __read()
  148. {
  149. uint8_t* buffer = (uint8_t*)malloc(32);
  150. device_t *testdev = device_get(levex_id);
  151. testdev->read(buffer, 0, 32, testdev);
  152. kprintf("%s\n", buffer);
  153. _kill();
  154. }
  155. void __malloc_bug()
  156. {
  157. malloc(0x1FFFFFFF);
  158. _kill();
  159. }
  160. void __ps()
  161. {
  162. tasking_print_all();
  163. _kill();
  164. }
  165. void sig_test()
  166. {
  167. asm volatile("movl $0, %eax\n"
  168. "idiv %eax");
  169. }
  170. #if defined(__cplusplus)
  171. extern "C" /* ha C++ compiler, akkor ez a függvény legyen C99es linkage-ű. */
  172. #endif
  173. void kernel_main()
  174. {
  175. int eax;
  176. asm("movl %%eax, %0": "=m"(eax));
  177. /* We create a textmode display driver, register it, then set it as current */
  178. display_setcurrent(display_register(textmode_init()));
  179. disp = display_getcurrent();
  180. mprint("Welcome to LevOS 4.0, very unstable!\n");
  181. mprint("Kernel base is 0x%x, end is 0x%x\n", &kernel_base, &kernel_end);
  182. if(eax == 0x1337) { mprint("Assembly link established.\n"); }
  183. else panic("Couldn't establish assembly link!");
  184. /* Setup memory manager */
  185. mm_init(&kernel_end);
  186. /* So far good, we have a display running,
  187. * but we are *very* early, set up arch-specific
  188. * tables, timers and memory to continue to tasking.
  189. */
  190. gdt_init();
  191. /* Now, we have the GDT setup, let's load the IDT as well */
  192. idt_init();
  193. exceptions_init();
  194. /* Next step, setup PIT. */
  195. hal_init();
  196. pic_init();
  197. pit_init();
  198. /* Enabling interrupts early... */
  199. asm volatile("sti");
  200. mprint("Interrupts were enabled, beware.\n");
  201. /* Setup paging. */
  202. paging_init();
  203. /* Good job ladies and gentleman, we are now alive.
  204. * Safe and sound, on the way to tasking!
  205. * Let's roll.
  206. */
  207. syscall_init();
  208. tasking_init();
  209. /* Tasking should have started late_init(),
  210. * if not, we are screwed as no peripherials are in
  211. * an operating state. Tell the user that we ran away
  212. * in terror.
  213. */
  214. panic("Reached end of main(), but tasking was not started.");
  215. for(;;);
  216. }
  217. void __test()
  218. {
  219. kprintf("Module system test.\n");
  220. }
  221. /* This function is ought to setup peripherials and such,
  222. * while also starting somekind of /bin/sh
  223. */
  224. int cu_pid = 0;
  225. void late_init()
  226. {
  227. /* From now, we are preemptible. Setup peripherials */
  228. int pid = 0;
  229. pid = START("kbd_init", keyboard_init);
  230. pid = START("vfs_init", vfs_init);
  231. pid = START("loader_init", loader_init);
  232. cu_pid = START("cursor_update", __cursor_updater);
  233. pid = START("devicemm", device_init);
  234. while(is_pid_running(pid))schedule_noirq();
  235. pid = START("testdev", create_test_device);
  236. pid = START("elf_init", elf_init);
  237. pid = START("rtc_init", rtc_init);
  238. START_AND_WAIT("fdc_init", fdc_init);
  239. START_AND_WAIT("ata_init", ata_init);
  240. pid = START("mod_init", module_init);
  241. pid = START("pci_init", pci_init);
  242. /* We now wait till all the late_inits have finished */
  243. while(is_pid_running(pid))schedule_noirq();
  244. EXPORT_SYMBOL(__test);
  245. /* Once they are done, pass control to the kernel terminal,
  246. * so that it will (eventually) start a /init or /bin/sh
  247. */
  248. START_AND_WAIT("login", __login);
  249. /* We cannot die as we are the idle thread.
  250. * schedule away so that we don't starve others
  251. */
  252. while(1) {
  253. START_AND_WAIT("_test", _test);
  254. kerror("\n\nThe terminal has crashed. Restarting it...\n\n");
  255. }
  256. panic("Reached end of late_init()\n");
  257. }
  258. static char c = 0;
  259. static char* buffer = 0;
  260. static uint16_t loc = 0;
  261. static char *wd = 0;
  262. static int root_mounted = 0;
  263. static char *ls_buffer = 0;
  264. static uint8_t *file_buf = 0;
  265. void _test()
  266. {
  267. buffer = (char*)malloc(256);
  268. ls_buffer = (char *)malloc(1024);
  269. file_buf = (uint8_t *)malloc(524288);
  270. if(!file_buf) panic("Kernel terminal has no memory available!\n");
  271. uint8_t *write_buf = (uint8_t *)malloc(512);
  272. char* prompt = "(kernel) $ ";
  273. uint8_t prompt_size = strlen(prompt);
  274. kprintf("Welcome to LevOS 4.0\nThis is a very basic terminal.\nDon't do anything stupid.\n");
  275. prompt:
  276. if(!root_mounted)
  277. kprintf(prompt);
  278. else
  279. kprintf("%s@%s:%s$ ", username, hostname, wd);
  280. memset(buffer, 0, 256);
  281. while(1) {
  282. if(!keyboard_enabled()){ schedule_noirq(); continue; }
  283. c = keyboard_get_key();
  284. if(!c) continue;
  285. if(c == '\r')
  286. {
  287. if(disp->con.cx <= prompt_size) continue;
  288. disp->con.cx --;
  289. disp->putc(' ');
  290. disp->con.cx --;
  291. buffer[loc--] = 0;
  292. continue;
  293. }
  294. if(c == '\n')
  295. {
  296. disp->putc(c);
  297. buffer[loc] = 0;
  298. loc = 0;
  299. uint32_t n = strsplit(buffer, ' ');
  300. if(strcmp(buffer, "help") == 0)
  301. {
  302. kprintf("LevOS4.0\nThis is the kernel terminal.\nDon't do anything stupid.\n");
  303. kprintf("Commands available: help; reboot; read; malloc; ps; fl; cd; ls\n"
  304. "clear; reset; time; v; kill\n");
  305. goto prompt;
  306. }
  307. if(strcmp(buffer, "reboot") == 0)
  308. {
  309. outportb(0x64, 0xFE);
  310. goto prompt;
  311. }
  312. if(strcmp(buffer, "read") == 0)
  313. {
  314. START_AND_WAIT("read", __read);
  315. goto prompt;
  316. }
  317. if(strcmp(buffer, "malloc") == 0)
  318. {
  319. uint8_t *mem = (uint8_t *)malloc(1337);
  320. free(mem);
  321. mem = (uint8_t *)malloc(1337);
  322. goto prompt;
  323. }
  324. if(strcmp(buffer, "mount") == 0)
  325. {
  326. list_mount();
  327. goto prompt;
  328. //kprintf("wd=0x%x", wd);
  329. }
  330. if(strcmp(buffer, "uname") == 0)
  331. {
  332. if(!root_mounted)
  333. goto prompt;
  334. vfs_read("/proc/os/full", file_buf);
  335. kprintf("%s\n", file_buf);
  336. memset(file_buf, 0, 512);
  337. goto prompt;
  338. }
  339. if(strcmp(buffer, "cat") == 0)
  340. {
  341. if(!n || n == 1)
  342. {
  343. kprintf("FATAL: no parameter.\n");
  344. goto prompt;
  345. }
  346. char *arg = (char *)(buffer + strlen(buffer) + 1);
  347. memset(file_buf, 0, 512);
  348. if(vfs_read(arg, file_buf))
  349. {
  350. kprintf("%s\n", file_buf);
  351. } else kprintf("File not found.\n");
  352. goto prompt;
  353. }
  354. if(strcmp(buffer, "ps") == 0)
  355. {
  356. START_AND_WAIT("ps", __ps);
  357. goto prompt;
  358. }
  359. if(strcmp(buffer, "time") == 0)
  360. {
  361. START_AND_WAIT("time", rtc_print_time_as_proc);
  362. goto prompt;
  363. }
  364. if(strcmp(buffer, "clear") == 0 || strcmp(buffer, "reset") == 0)
  365. {
  366. disp->clear();
  367. goto prompt;
  368. }
  369. if(strcmp(buffer, "v") == 0)
  370. {
  371. module_call_func("__test");
  372. goto prompt;
  373. }
  374. if(strcmp(buffer, "kill") == 0)
  375. {
  376. kill(cu_pid);
  377. while(is_pid_running(cu_pid)) {schedule_noirq(); continue;}
  378. goto prompt;
  379. }
  380. if(strcmp(buffer, "ls") == 0)
  381. {
  382. if(!root_mounted)
  383. {
  384. kprintf("FATAL: No root directory. Mount with 'fl'.\n");
  385. goto prompt;
  386. }
  387. if(!vfs_ls(wd, ls_buffer))
  388. {
  389. kprintf("Error.\n");
  390. goto prompt;
  391. }
  392. goto prompt;
  393. }
  394. if(strcmp(buffer, "mem") == 0)
  395. {
  396. mm_print_out();
  397. goto prompt;
  398. }
  399. if(strcmp(buffer, "cd") == 0)
  400. {
  401. if(!root_mounted)
  402. {
  403. kprintf("FATAL: No root directory. Mount with 'fl'.\n");
  404. goto prompt;
  405. }
  406. if(!n || n == 1)
  407. {
  408. kprintf("FATAL: no parameter.\n");
  409. goto prompt;
  410. }
  411. char *arg = (char *)(buffer + strlen(buffer) + 1);
  412. if(strcmp(arg, ".") == 0) goto prompt;
  413. if(strcmp(arg, "..") == 0)
  414. {
  415. if(strlen(wd) == 1)
  416. {
  417. goto prompt;
  418. } else {
  419. str_backspace(wd, '/');
  420. prompt_size = strlen(username) + strlen(hostname) + 4 + strlen(wd);
  421. goto prompt;
  422. }
  423. }
  424. if(vfs_exist_in_dir(wd, arg))
  425. {
  426. size_t size = strlen(wd) + strlen(arg) + 2;
  427. char *_w = (char *)malloc(size);
  428. memset(_w, 0, size);
  429. memcpy(_w, wd, strlen(wd));
  430. memcpy(_w + strlen(wd), arg, strlen(arg));
  431. memcpy(_w + strlen(_w), "/\0", 2);
  432. memcpy(wd, _w, strlen(_w) + 1);
  433. free(_w);
  434. prompt_size = strlen(username) + strlen(hostname) + 4 + strlen(wd);
  435. }
  436. goto prompt;
  437. }
  438. if(strcmp(buffer, "devinfo") == 0)
  439. {
  440. device_print_out();
  441. goto prompt;
  442. }
  443. if(strcmp(buffer, "fl") == 0)
  444. {
  445. if(!n || n == 1)
  446. {
  447. kprintf("FATAL: No id parameter, select root with devinfo\n");
  448. goto prompt;
  449. }
  450. char *arg = (char *)(buffer + strlen(buffer) + 1);
  451. int devid = 0;
  452. atoi(arg, &devid);
  453. kprintf("arg: %d\n", devid);
  454. device_t *dev = device_get(devid);
  455. if(!dev) {
  456. kprintf("Unable to locate medium!\n");
  457. goto prompt;
  458. }
  459. if(device_try_to_mount(dev, "/")) {
  460. kprintf("Mounted / on %s (%d) with %s\n", dev->name, dev->unique_id, dev->fs->name);
  461. root_mounted = 1;
  462. wd = (char *)malloc(512);
  463. memcpy(wd, "/", 2);
  464. prompt_size = strlen(username) + strlen(hostname) + 4 + strlen(wd);
  465. //goto prompt;
  466. device_try_to_mount(device_get_by_id(19), "/mnt/");
  467. START_AND_WAIT("proc_init", proc_init);
  468. START_AND_WAIT("devfs_init", devfs_init);
  469. }
  470. else kprintf("Unable to mount / on %s (%d)!\n", dev->name, dev->unique_id);
  471. goto prompt;
  472. }
  473. if(strcmp(buffer, "write") == 0)
  474. {
  475. if(!n || n == 1)
  476. {
  477. kprintf("FATAL: No argument supplied.\n");
  478. goto prompt;
  479. }
  480. device_t *dev = device_get_by_id(19);
  481. char *arg = (char *)(buffer + strlen(buffer) + 1);
  482. char *f = (char *)malloc(strlen(wd) + strlen(arg) + 1);
  483. memcpy(f, wd, strlen(wd));
  484. memcpy(f + strlen(wd), arg, strlen(arg) + 1);
  485. f[strlen(wd) + strlen(arg) + 1] = 0;
  486. kprintf("Writing 'levex is epic' to %s\n", f);
  487. char *my_buf = "levex is epic";
  488. dev->fs->writefile(f, my_buf, strlen(my_buf) + 1, dev, dev->fs->priv_data);
  489. free(f);
  490. goto prompt;
  491. }
  492. if(strcmp(buffer, "lev") == 0)
  493. {
  494. if(vfs_read("/bin/hw", file_buf)) {
  495. int pid = 0;
  496. if(pid = exec_start(file_buf))
  497. {
  498. while(is_pid_running(pid)) schedule_noirq();
  499. }
  500. } else {
  501. kprintf("Unable to read /bin/hw\n");
  502. }
  503. goto prompt;
  504. }
  505. if(strcmp(buffer, "touch") == 0)
  506. {
  507. if(!n || n == 1)
  508. {
  509. kprintf("FATAL: No argument supplied.\n");
  510. goto prompt;
  511. }
  512. device_t *dev = device_get_by_id(19);
  513. char *arg = (char *)(buffer + strlen(buffer) + 1);
  514. char *f = (char *)malloc(strlen(wd) + strlen(arg) + 1);
  515. memcpy(f, wd, strlen(wd));
  516. memcpy(f + strlen(wd), arg, strlen(arg) + 1);
  517. f[strlen(wd) + strlen(arg) + 1] = 0;
  518. kprintf("Touching %s\n", f);
  519. dev->fs->touch(f, dev, dev->fs->priv_data);
  520. free(f);
  521. goto prompt;
  522. }
  523. if(!*buffer) goto prompt;
  524. if(vfs_read(buffer, file_buf))
  525. {
  526. int pid = 0;
  527. if(pid = exec_start(file_buf))
  528. {
  529. while(is_pid_running(pid)) schedule_noirq();
  530. }
  531. }
  532. goto prompt;
  533. }
  534. buffer[loc++] = c;
  535. buffer[loc] = 0;
  536. disp->putc(c);
  537. }
  538. }