From 91ecd00cc83cf701fe7f73b1aa244c27174e8386 Mon Sep 17 00:00:00 2001 From: Kacper Date: Tue, 16 Dec 2025 00:36:30 +0100 Subject: Add init prog, chroot syscall and fix menuconfig build --- boot/Kbuild | 1 + boot/init/Kbuild | 3 ++ boot/init/init | Bin 0 -> 145432 bytes boot/init/init.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 boot/Kbuild create mode 100644 boot/init/Kbuild create mode 100755 boot/init/init create mode 100644 boot/init/init.c (limited to 'boot') 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 new file mode 100755 index 00000000..87e091d3 Binary files /dev/null and b/boot/init/init differ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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"); +} -- cgit v1.2.3