rewrite the device subsystem interfaces (#48)
[lunaix-os.git] / lunaix-os / kernel / lunad.c
1 #include <lunaix/boot_generic.h>
2 #include <lunaix/exec.h>
3 #include <lunaix/foptions.h>
4 #include <lunaix/fs.h>
5 #include <lunaix/fs/twifs.h>
6 #include <lunaix/spike.h>
7 #include <lunaix/syslog.h>
8 #include <lunaix/types.h>
9 #include <lunaix/owloysius.h>
10 #include <lunaix/sched.h>
11 #include <lunaix/kpreempt.h>
12 #include <lunaix/kcmd.h>
13
14 #include <klibc/string.h>
15
16 LOG_MODULE("PROC0")
17
18 void
19 init_platform();
20
21 int
22 mount_bootmedium()
23 {
24     int errno = 0;
25     char* rootfs;
26     struct v_dnode* dn;
27     struct device* dev;
28
29     if (!kcmd_get_option("rootfs", &rootfs)) {
30         ERROR("no rootfs.");
31         return 0;
32     }
33
34     if ((errno = vfs_walk(NULL, rootfs, &dn, NULL, 0))) {
35         ERROR("%s: no such file (%d)", rootfs, errno);
36         return 0;
37     }
38     
39     dev = resolve_device(dn->inode->data);
40     if (!dev) {
41         ERROR("%s: not a device", rootfs);
42         return 0;
43     }
44
45     // unmount the /dev to put old root fs in clear
46     must_success(vfs_unmount("/dev"));
47
48     // re-mount the root fs with our device.
49     if ((errno = vfs_mount_root(NULL, dev))) {
50         ERROR("mount root failed: %s (%d)", rootfs, errno);
51         return 0;
52     }
53
54     return 1;
55 }
56
57 int
58 exec_initd()
59 {
60     int errno = 0;
61     const char* argv[] = { "/init", 0 };
62     const char* envp[] = { 0 };
63
64     kcmd_get_option("init", (char**)&argv[0]);
65
66     if ((errno = exec_kexecve(argv[0], argv, envp))) {
67         goto fail;
68     }
69
70     fail("should not reach");
71
72 fail:
73     ERROR("fail to load initd. (%d)", errno);
74     return 0;
75 }
76
77 static void
78 lunad_do_usr() {
79     // No, these are not preemptive
80     no_preemption();
81
82     if (!exec_initd()) {
83         fail("failed to initd");
84     }
85 }
86
87 /**
88  * @brief LunaixOS的内核进程,该进程永远为可执行。
89  *
90  * 这主要是为了保证调度器在没有进程可调度时依然有事可做。
91  *
92  * 同时,该进程也负责fork出我们的init进程。
93  *
94  */
95 void
96 lunad_main()
97 {
98     spawn_kthread((ptr_t)init_platform);
99
100     /*
101         NOTE Kernel preemption after this point.
102
103         More specifically, it is not a real kernel preemption (as in preemption
104         happened at any point of kernel, except those marked explicitly).
105         In Lunaix, things are designed in an non-preemptive fashion, we implement 
106         kernel preemption the other way around: only selected kernel functions which,
107         of course, with great care of preemptive assumption, will goes into kernel 
108         thread (which is preemptive!)
109     */
110
111     set_preemption();
112     while (1)
113     {
114         cleanup_detached_threads();
115         yield_current();
116     }
117 }
118
119 void
120 init_platform()
121 {    
122     device_postboot_load();
123     invoke_init_function(on_postboot);
124
125     twifs_register_plugins();
126
127     if (!mount_bootmedium()) {
128         ERROR("failed to boot");
129         goto exit;
130     }
131
132     // FIXME Re-design needed!!
133     // sdbg_init();
134     
135     assert(!spawn_process(NULL, (ptr_t)lunad_do_usr, true));
136
137 exit:
138     exit_thread(NULL);
139 }