# Build INITRD_FILES list: <elf>:<rootfs-path>
FSTAB := rootfs/etc/fstab
+RCS := rootfs/etc/init.d/rcS
INITRD_FILES := $(FULLTEST_ELF):sbin/fulltest \
$(USER_BUILD)/cmds/init/init.elf:sbin/init \
$(foreach cmd,$(USER_BIN_NAMES),$(USER_BUILD)/cmds/$(cmd)/$(cmd).elf:bin/$(cmd)) \
$(LDSO_ELF):lib/ld.so $(ULIBC_SO):lib/libc.so \
$(PIE_SO):lib/libpietest.so $(PIE_ELF):bin/pie_test \
- $(FSTAB):etc/fstab
+ $(FSTAB):etc/fstab $(RCS):etc/init.d/rcS
-INITRD_DEPS := $(MKINITRD) $(FULLTEST_ELF) $(USER_CMD_ELFS) $(LDSO_ELF) $(ULIBC_SO) $(PIE_SO) $(PIE_ELF) $(FSTAB)
+INITRD_DEPS := $(MKINITRD) $(FULLTEST_ELF) $(USER_CMD_ELFS) $(LDSO_ELF) $(ULIBC_SO) $(PIE_SO) $(PIE_ELF) $(FSTAB) $(RCS)
# doom (build via 'make doom', included in initrd if present)
doom: $(DOOM_SENTINEL) $(ULIBC_LIB) $(ULIBC_SO)
--- /dev/null
+#!/bin/sh
+# /etc/init.d/rcS — System initialization script (run by init)
+# Virtual filesystems (/dev, /proc, /tmp) are mounted by init directly
+# via mount() syscalls before this script runs.
+# Add additional startup commands below.
}
}
}
+ /* Create mount-point directories and mount virtual filesystems.
+ * When /sbin/init runs in userspace it re-mounts these (vfs_mount
+ * replaces existing entries, so it is a harmless no-op). When a
+ * different init= binary is used (e.g. fulltest), these kernel-side
+ * mounts ensure the system is functional. */
{
int rc;
rc = vfs_mkdir("/dev");
tty_init();
pty_init();
+ /* Mount devfs — kernel-side fallback so that any init= binary
+ * (including fulltest) has /dev available. When /sbin/init runs
+ * it re-mounts devfs via mount() syscall; vfs_mount replaces the
+ * existing entry so this is a harmless overlap. */
fs_node_t* dev = devfs_create_root();
if (dev) {
(void)vfs_mount("/dev", dev);
kdev[sizeof(kdev)-1] = '\0';
ktype[sizeof(ktype)-1] = '\0';
+ /* Virtual filesystems — no device argument needed */
if (strcmp(ktype, "tmpfs") == 0) {
fs_node_t* tmp = tmpfs_create_root();
if (!tmp) { sc_ret(regs) = (uint32_t)-ENOMEM; return; }
+ (void)vfs_mkdir(kmp); /* auto-create mountpoint */
sc_ret(regs) = (uint32_t)vfs_mount(kmp, tmp);
return;
}
+ if (strcmp(ktype, "devfs") == 0) {
+ extern fs_node_t* devfs_create_root(void);
+ fs_node_t* dev = devfs_create_root();
+ if (!dev) { sc_ret(regs) = (uint32_t)-ENOMEM; return; }
+ (void)vfs_mkdir(kmp);
+ sc_ret(regs) = (uint32_t)vfs_mount(kmp, dev);
+ return;
+ }
+ if (strcmp(ktype, "procfs") == 0) {
+ extern fs_node_t* procfs_create_root(void);
+ fs_node_t* proc = procfs_create_root();
+ if (!proc) { sc_ret(regs) = (uint32_t)-ENOMEM; return; }
+ (void)vfs_mkdir(kmp);
+ sc_ret(regs) = (uint32_t)vfs_mount(kmp, proc);
+ return;
+ }
/* Disk-based: parse /dev/hdX -> drive number */
const char* devname = kdev;
if (drive < 0) { sc_ret(regs) = (uint32_t)-ENODEV; return; }
extern int init_mount_fs(const char* fstype, int drive, uint32_t lba, const char* mountpoint);
+ (void)vfs_mkdir(kmp); /* auto-create mountpoint */
int rc = init_mount_fs(ktype, drive, 0, kmp);
sc_ret(regs) = (uint32_t)(rc < 0 ? -EIO : 0);
return;
#include <fcntl.h>
#include <signal.h>
#include <time.h>
+#include <sys/mount.h>
#define MAX_ENTRIES 32
#define LINE_MAX 256
}
/* Default behavior when no inittab exists */
+/* Mount virtual filesystems (migrated from kernel-space).
+ * These must be done before spawning the shell since /dev/console
+ * is needed for terminal I/O. */
+static void mount_virtual_fs(void) {
+ if (mount("none", "/dev", "devfs", 0, NULL) < 0)
+ fprintf(stderr, "init: mount devfs on /dev failed\n");
+ if (mount("none", "/proc", "procfs", 0, NULL) < 0)
+ fprintf(stderr, "init: mount procfs on /proc failed\n");
+ if (mount("none", "/tmp", "tmpfs", 0, NULL) < 0)
+ fprintf(stderr, "init: mount tmpfs on /tmp failed\n");
+}
+
static void default_init(void) {
+ /* Mount virtual filesystems before anything else */
+ mount_virtual_fs();
+
/* Run /etc/init.d/rcS if it exists */
if (access("/etc/init.d/rcS", 0) == 0) {
run_and_wait("/etc/init.d/rcS");
printf("init: loaded %d inittab entries, runlevel %d\n",
nentries, current_runlevel);
+ /* Mount virtual filesystems before running any inittab entries */
+ mount_virtual_fs();
+
/* Phase 1: sysinit entries */
run_action(ACT_SYSINIT, 1);