nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
crt0.c
Go to the documentation of this file.
1 #include <sys/types.h>
2 #include <stdio.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <stddef.h>
7 #include <stdarg.h>
8 #include <stdint.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <limits.h>
12 #include <pthread.h>
13 #include <assert.h>
14 
15 #include <object.h>
16 #include <list.h>
17 #include <thread.h>
18 #include <crt0.h>
19 #include <malloc0.h>
20 #include <pthread0.h>
21 
22 #include <arch.h>
23 #include <vfs.h>
24 
25 #include <cpu_node.h>
26 #include <interrupt.h>
27 #include <zone.h>
28 #include <page_frame.h>
29 #include <paging.h>
30 #include <segment.h> /* for the definition of IO_BITMAP_SIZE */
31 #include <x86.h>
32 
33 #include <debug.h>
34 #include <initm.h>
35 
36 #include <onetime_map.h>
37 #include <fat.h>
38 
39 typedef void (*exec_entry)(char *args, char *envs, unsigned long kpma);
40 
41 struct arg_t {
42  int argc;
43  char *argv[MAX_IDX];
44 };
45 
52 extern unsigned long end;
53 
54 
55 #if !defined(NDEBUG)
56 static inline void tree_vfs(void)
57 {
58  struct stack *item;
59  struct ninfo *ninfo;
60  struct ninfo *tmp;
61  int depth;
62  register int i;
63  LIST_HEAD(stack);
64  struct stack {
65  struct list_head head;
66  struct ninfo *node;
67  int depth;
68  };
69 
70  depth = 0;
71  ninfo = vfs_get_ninfo(NULL, NULL, "/");
72  printf("Root ninfo: %p\n", ninfo);
73  while (ninfo) {
74  for (i = 0; i < depth; i ++) {
75  printf(" ");
76  }
77  printf(ninfo->type == NINFO_TYPE_FOLDER ?
78  "[%s]\n" : "%s\n",
79  ninfo->name ? ninfo->name : "(root)");
80 
81  tmp = vfs_get_ninfo_child(ninfo);
82  if (tmp) {
83  item = malloc(sizeof(*item));
84  if (!item) {
85  return;
86  }
87 
88  item->node = ninfo;
89  item->depth = depth;
90  list_add_tail(&item->head, &stack);
91 
92  ninfo = tmp;
93  depth += 4;
94  continue;
95  }
96 
97  ninfo = vfs_get_ninfo_next_sibling(ninfo);
98  if (ninfo) {
99  continue;
100  }
101 
102  while (!ninfo) {
103  if (stack.prev == &stack) {
104  ninfo = NULL;
105  break;
106  }
107 
108  item = list_entry(stack.prev, struct stack, head);
109  list_del(&item->head);
110  ninfo = item->node;
111  depth = item->depth;
112  free(item);
113 
114  ninfo = vfs_get_ninfo_next_sibling(ninfo);
115  }
116  }
117 }
118 #else
119 #define tree_vfs()
120 #endif
121 
122 static inline int vfs_build_dev(void)
123 {
124  struct ninfo *root;
125  struct ninfo *dev;
126 
127  root = vfs_get_ninfo(NULL, NULL, "/");
128  if (!root) {
129  return -EFAULT;
130  }
131 
132  dev = vfs_new_ninfo(root->si, root, "dev", NULL);
133  if (!dev) {
134  return -EFAULT;
135  }
136 
137  dev->type = NINFO_TYPE_FOLDER;
138 
139  return 0;
140 }
141 
142 static inline
143 int fill_env(struct env_t *envt, int idx, char *env, int *aidx)
144 {
145  switch (idx) {
146  case STDIN_IDX:
147  envt->dev_stdin = env;
148  break;
149  case STDOUT_IDX:
150  envt->dev_stdout = env;
151  break;
152  case STDERR_IDX:
153  envt->dev_stderr = env;
154  break;
155  case MEMBASE_IDX: /* membase */
156  envt->membase[*aidx] = atoi(env);
157  break;
158  case MEMSIZE_IDX: /* memsize */
159  envt->memsize[*aidx] = atoi(env);
160  (*aidx)++;
161  break;
162  case KVMA_IDX:
163  envt->kvma = atoi(env);
164  break;
165  case MEMCNT_IDX: /* memcnt */
166  envt->memcnt = atoi(env);
167  if (envt->memcnt > MAX_MRD) {
168  dbg_printf("Too many MRD found %d\n", envt->memcnt);
169  while (1) {
170  }
171  }
172  break;
173  default:
174  return -ENOENT;
175  }
176 
177  return 0;
178 }
179 
180 static inline int fill_map(struct memmap *map, int idx, char *env)
181 {
182 
183  switch (idx) {
184  case HEAP_SZ_IDX: /* heap_sz */
185  map->heap_size = atoi(env);
186  break;
187  case INITM_IDX: /* initm */
188  map->initm = (char *)atoi(env);
189  break;
190  case KERNEL_SZ_IDX:
191  map->kernel_size = atoi(env);
192  break;
193  case ENV_SZ_IDX:
194  map->env_size = atoi(env);
195  break;
196  case TCB_SZ_IDX:
197  map->tcb_size = atoi(env);
198  break;
199  case INITM_SZ_IDX:
200  map->initm_size = atoi(env);
201  break;
202  case TCB_IDX:
203  map->tcb = (char *)atoi(env);
204  break;
205  case STACK_SZ_IDX:
206  map->stack_size = atoi(env);
207  break;
208  case KPMA_IDX:
209  map->kernel = (char *)atoi(env);
210  break;
211  default:
212  return -ENOENT;
213  }
214 
215  return 0;
216 }
217 
218 static inline
219 void parse_env(char *env, struct env_t *envt, struct memmap *map)
220 {
221  int idx;
222  int token_idx;
223  int i;
224  int array_idx;
236  char label[][10] = {
237  { "stdin" },
238  { "stdout" },
239  { "stderr" },
240  { "membase" },
241  { "memsize" },
242  { "memcnt" },
243 
244  { "kvma" },
245  { "heap_sz" },
246  { "initm" },
247  { "kernel_sz" },
248  { "env_sz" },
249  { "tcb_sz" },
250  { "initm_sz" },
251  { "tcb" },
252  { "stack_sz" },
253  { "kpma" },
254  { '\0', },
255  };
256 
257  map->env = env;
258 
259  idx = 0;
260  i = 0;
261  token_idx = 0;
262  array_idx = 0;
263  while (*env && idx < MAX_IDX) {
264  if (label[token_idx][0]) {
265  if (label[token_idx][i] != *env) {
266  /* Check the next label */
267  env -= i;
268  i = 0;
269  token_idx++;
270  continue;
271  }
272 
273  i++;
274  env++;
275 
276  if (label[token_idx][i] != '\0' || *env != '=') {
277  continue;
278  }
279 
280  /* Skip '=' */
281  i++;
282  env++;
283 
284  if (fill_env(envt, token_idx, env, &array_idx) == 0) {
285  continue;
286  }
287 
288  if (fill_map(map, token_idx, env) == 0) {
289  continue;
290  }
291  }
292 
293  envt->envp[idx++] = env - i;
294  i = 0;
295  token_idx = 0;
296 
301  while (*env++) {
302  }
303  }
304 
305  envt->envp[idx] = NULL;
306  return;
307 }
308 
309 static inline void parse_arg(char *arg, struct arg_t *argt)
310 {
311  argt->argc = 0;
312  argt->argv[argt->argc] = arg;
313  while (*arg++) {
314  if (*arg != '\0') {
315  continue;
316  }
317 
318  argt->argc++;
319  if (argt->argc == MAX_IDX) {
320  break;
321  }
322 
323  arg++;
324  argt->argv[argt->argc] = arg;
325  }
326 
327  /* 개수를 의미한다 */
328  argt->argc++;
329 }
330 
334 static inline void setup_default_thread(struct memmap *map)
335 {
336  pthread_attr_t thattr;
337  int ret;
338 
339  ret = pthread_attr_init(&thattr);
340  if (ret < 0) {
341  dbg_printf("Failed to initialize the attribute\n");
342  return;
343  }
344 
345  ret = pthread_attr_setstack(&thattr,
346  (void*)(0xFFFFFFFF - (map->tcb_size + map->stack_size) + 1 - (0x01 << 20)),
347  map->stack_size + map->tcb_size);
348  if (ret < 0) {
349  dbg_printf("Failed to set stack info\n");
350  pthread_attr_destroy(&thattr);
351  return;
352  }
353 
354  ret = pthread_init(&thattr);
355  if (ret < 0) {
356  dbg_printf("Failed to initialize a thread\n");
357  /* Keep going, to finish this */
358  }
359 
366  ret = pthread_attr_destroy(&thattr);
367  if (ret < 0) {
368  dbg_printf("Failed to destroy the attribute\n");
369  }
370 }
371 
372 static inline void test_thread(void)
373 {
374  pthread_t thid;
375 
376  thid = pthread_self();
377  if (thid) {
378  printf("THID: %p\n", thid);
379  } else {
380  printf("Failed to find a THID\n");
381  }
382  printf("test_thread\n");
383 }
384 
385 static inline void dump_map(struct memmap *map)
386 {
387  dbg_printf("Dump memmap begin\n");
388  dbg_printf("TCB %p - %d\n", map->tcb, map->tcb_size);
389  dbg_printf("ENV %p - %d\n", map->env, map->env_size);
390  dbg_printf("Kernel %p - %d\n", map->kernel, map->kernel_size);
391  dbg_printf("initm %p - %d\n", map->initm, map->initm_size);
392  dbg_printf("Heap: %d\n", map->heap_size);
393  dbg_printf("Stack: %d\n", map->stack_size);
394  dbg_printf("Dump memmap end\n");
395 }
396 
397 static inline void transfer_to_vma(struct memmap *map, void *vma_kernel)
398 {
399  char *vma_initm;
400 
401  vma_initm = (char *)vma_kernel + map->env_size + map->kernel_size;
402 
403  initm_set_pma((void *)map->initm);
404  initm_set_vma(vma_initm);
405  map->initm = initm_vma();
406  map->tcb = (char *)(0xFFFFFFFF - map->tcb_size - (0x01 << 20) + 1);
407 
420 }
421 
422 static inline void frame_init(void)
423 {
424  struct thread *tcb;
425  struct pgde *pgd;
426  struct pgte *pgt;
427  struct x86_arch_data *arch_data;
428  register int pgt_idx;
429  register int page_idx;
430  void *page;
431  const unsigned long pagesize = sysconf(_SC_PAGESIZE);
432 
433  tcb = pthread_self();
434  assert(tcb && "thread is not valid");
435 
436  arch_data = tcb->arch_data;
437  assert(arch_data && "arch_data is not valid");
438 
439  pgd = onetime_map(arch_data->pma_pgd);
440  assert(pgd && "Failed to do onetime mapping");
441 
442  page_frame_manage(ZONE_SYSTEM, arch_data->pma_pgd, 1);
443 
444  for (pgt_idx = 0; pgt_idx < NR_TABLES; pgt_idx++) {
445  if (!pgd[pgt_idx].p) {
446  continue;
447  }
448 
449  pgt = (struct pgte *)(pgd[pgt_idx].pt_base * pagesize);
450  assert(pgt && "page table is not valid");
452 
453  pgt = onetime_map(pgt);
454  assert(pgt && "onetime map failed");
455 
456  for (page_idx = 0; page_idx < NR_PAGES; page_idx++) {
457  if (!pgt[page_idx].p) {
458  continue;
459  }
460 
461  page = (void *)(pgt[page_idx].page_base * pagesize);
462  page_frame_manage(ZONE_SYSTEM, page, 1);
463  }
464 
465  pgt = onetime_unmap(pgt);
466  assert(pgt && "onetime unmap");
467  }
468 }
469 
470 static inline void vfs_attach_root(void)
471 {
472  struct ninfo *root;
473  struct ninfo *fat_root;
474 
475  root = vfs_get_ninfo(NULL, NULL, "/");
476  if (!root) {
477  dbg_printf("Failed to get root node\n");
478  return;
479  }
480 
481  fat_root = fat_load(root, "/dev/fda");
482  if (!fat_root) {
483  dbg_printf("Failed to get FAT sinfo\n");
484  }
485 }
486 
487 static void _start_on_vma(char *args, char *envs, unsigned long kpma)
488 {
489  struct env_t envt;
490  struct arg_t argt;
491  struct memmap map;
492  int ret;
493 
494  if (!vm_is_enabled()) {
495  panic("Paging is not enabled");
496  return;
497  }
498 
499  parse_arg(args, &argt);
500  parse_env(envs, &envt, &map);
501 
506  environ = (char **)envt.envp;
507 
508  transfer_to_vma(&map, (void *)envs);
509  vm_init_done(&map, kpma);
510 
511  malloc_init((uint32_t)map.env + map.env_size +
512  map.kernel_size + map.initm_size, map.heap_size);
513 
514  vm_frame_init(envt.memcnt, envt.membase, envt.memsize);
515  arch_init();
516  vfs_init();
517 
518  if (vfs_build_dev() < 0) {
519  dbg_printf("Failed to build VFS DEV tree");
520  while (1) {
521  }
522  }
523 
524  drivers_init();
525 
526  setup_default_thread(&map);
527 
529  (void *)(0xFFFFFFFF - (0x01 << 20) + 1),
530  (void *)0xFFFFFFFF);
531 
532  frame_init();
533 
534  dbg_printf("INITM_FREE %d\n", initm_free_size((void *)map.initm));
535  dbg_printf("argc: %d, argv: %p, envp: %p\n", argt.argc, argt.argv, envt.envp);
536 
538 
539  vfs_attach_root();
540 
541  test_thread();
542  tree_vfs();
543 
544  ret = main(argt.argc, argt.argv, envt.envp);
545  panic("End of a function (ret:%d)", ret);
546  return;
547 }
548 
549 void _start(char *args, char *env)
550 {
551  /* register volatile uint32_t *esp asm ("esp"); */
552  uint32_t *esp;
553  uint32_t vma_args;
554  uint32_t vma_start;
555  struct env_t envt;
556  struct memmap map;
557 
558  if (vm_is_enabled()) {
559  dbg_printf("Paging is already enabled\n");
560  while(1);
561  }
562 
563  parse_env(env, &envt, &map);
564 
565  vma_args = envt.kvma + ((uint32_t)args - (uint32_t)map.env);
566  vma_start = envt.kvma + ((uint32_t)_start_on_vma - (uint32_t)map.env);
567 
568  if (initm_init(map.initm, map.initm_size) < 0) {
569  dbg_printf("Failed to init initm");
570  while (1) {
571  }
572  }
573 
574  if (vm_init(&map, envt.kvma) < 0) {
575  dbg_printf("Failed to init vm");
576  while (1) {
577  }
578  }
579 
585  esp = (uint32_t *)(0xFFFFFFFF - map.tcb_size + 1 - (0x01 << 20));
586  esp -= 3;
587  esp[0] = vma_args;
588  esp[1] = envt.kvma;
589  esp[2] = (uint32_t)map.env;
590  asm volatile (
591  "movl %0, %%esp;"
592  "call *%1"
593  :
594  : "m"(esp), "m"(vma_start)
595  : "esp"
596  );
597 
598  /* Could not be reach to here */
599  dbg_printf("Failed to transfer to VMA\n");
600  while (1) {
601  }
602 }
603 
604 /* End of a file */