diff options
| author | Kacper <kacper@mail.openlinux.dev> | 2025-12-16 00:36:30 +0100 |
|---|---|---|
| committer | Kacper <kacper@mail.openlinux.dev> | 2025-12-16 00:36:30 +0100 |
| commit | 91ecd00cc83cf701fe7f73b1aa244c27174e8386 (patch) | |
| tree | c38ffefaa73e671fd917ca0b94b8adec53456a06 /boot | |
| parent | 01cf24ec66c663e3f40be1d5c703aa9666effc85 (diff) | |
Add init prog, chroot syscall and fix menuconfig build
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/Kbuild | 1 | ||||
| -rw-r--r-- | boot/init/Kbuild | 3 | ||||
| -rwxr-xr-x | boot/init/init | bin | 0 -> 145432 bytes | |||
| -rw-r--r-- | boot/init/init.c | 126 |
4 files changed, 130 insertions, 0 deletions
diff --git a/boot/Kbuild b/boot/Kbuild new file mode 100644 index 00000000..01daa04b --- /dev/null +++ b/boot/Kbuild @@ -0,0 +1 @@ +obj-y += init/ diff --git a/boot/init/Kbuild b/boot/init/Kbuild new file mode 100644 index 00000000..461a0101 --- /dev/null +++ b/boot/init/Kbuild @@ -0,0 +1,3 @@ +bin-y := init +obj-y := init.o +libs-y := $(srctree)/lib/libc/libc.a diff --git a/boot/init/init b/boot/init/init Binary files differnew file mode 100755 index 00000000..87e091d3 --- /dev/null +++ b/boot/init/init diff --git a/boot/init/init.c b/boot/init/init.c new file mode 100644 index 00000000..4e643a34 --- /dev/null +++ b/boot/init/init.c @@ -0,0 +1,126 @@ +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <linux/fs.h> +#include <stdio.h> +#include <string.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <unistd.h> + +struct rootfs { + char *dev; + int flags; +}; + +int get_rootfs(struct rootfs *root) +{ + int fd; + ssize_t len; + char buf[1024]; + + root->dev = NULL; + root->flags = 0; + + fd = open("/proc/cmdline", O_RDONLY); + if (fd < 0) { + return -1; + } + + len = read(fd, buf, sizeof(buf) - 1); + if (len < 0) { + close(fd); + return -1; + } + buf[len] = '\0'; + close(fd); + + // Read cmdline by words + // not using strtok + char *p = buf; + while (*p) { + while (*p == ' ') + p++; + + if (*p == '\0') + break; + + char *start = p; + while (*p && *p != ' ') + p++; + size_t word_len = p - start; + + if (strncmp(start, "root=", 5) == 0) { + size_t dev_len = word_len - 5; + root->dev = strndup(start + 5, dev_len); + } else if (strncmp(start, "ro", 2) == 0) { + root->flags |= MS_RDONLY; + } else if (strncmp(start, "rw", 2) == 0) { + root->flags &= ~MS_RDONLY; + } + } + + return 0; +} + +int main(void) +{ + struct rootfs root; + char *const argv[] = { "/bin/init", NULL }; + + if (mkdir("/dev", 0755) < 0 && errno != EEXIST) { + perror("mkdir /dev"); + return -1; + } + + if (mount("devtmpfs", "/dev", "devtmpfs", 0, NULL) < 0) { + perror("mount devtmpfs"); + return -1; + } + + if (mkdir("/proc", 0755) < 0 && errno != EEXIST) { + perror("mkdir /proc"); + return -1; + } + + if (mount("proc", "/proc", "proc", 0, NULL) < 0) { + perror("mount proc"); + return -1; + } + + /* Get root filesystem info from kernel cmdline */ + if (get_rootfs(&root) < 0) { + err(1, "init: get rootfs info"); + } + + if (mount(root.dev, "/root", "ext4", root.flags, NULL) < 0) + err(1, "init: mount rootfs %s", root.dev); + + if (mkdir("/root/dev", 0755) < 0) + err(1, "init: mkdir /root/dev"); + + if (mount("/dev", "/root/dev", NULL, MS_BIND | MS_REC, NULL) < 0) + err(1, "init: mount --bind /dev"); + + if (mkdir("/root/proc", 0755) < 0) + err(1, "init: chdir /root"); + + if (mount("/proc", "/root/proc", NULL, MS_BIND | MS_REC, NULL) < 0) + err(1, "init: mount --bind /proc"); + + if (mkdir("/root/sys", 0755) < 0) + err(1, "init: chdir /root"); + + if (mount("sysfs", "/root/sys", "sysfs", 0, NULL) < 0) + err(1, "init: mount --bind /sys"); + + if (chroot("/root") < 0) + err(1, "init: chroot /root"); + + if (chdir("/") < 0) + err(1, "init: chdir /"); + + execve("/bin/init", argv, NULL); + err(1, "init: execve /bin/init"); +} |
