- initramfs.img, rootfs.img for AArch64 Linux guest - mkdisk.py for disk image creation - initramfs and rootfs directories
144 lines
3.9 KiB
C
144 lines
3.9 KiB
C
/*
|
|
* Minimal /init for UniversalisOS initramfs.
|
|
*
|
|
* This is the first userspace program executed by Linux after mounting
|
|
* the rootfs. It demonstrates that the hypervisor can boot a real Linux
|
|
* kernel to userspace via virtio-blk.
|
|
*
|
|
* Features:
|
|
* - Mounts /proc, /sys, /dev (tmpfs)
|
|
* - Prints system information from /proc/cpuinfo
|
|
* - Runs a minimal shell loop (echo + wait)
|
|
* - Demonstrates the full hypervisor -> Linux -> userspace path
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/sysmacros.h>
|
|
#include <sys/reboot.h>
|
|
#include <linux/reboot.h>
|
|
|
|
#define BANNER \
|
|
"\r\n" \
|
|
"============================================\r\n" \
|
|
" UniversalisOS Linux Guest Boot Successful!\r\n" \
|
|
"============================================\r\n" \
|
|
"\r\n"
|
|
|
|
static void mount_proc(void) {
|
|
mkdir("/proc", 0755);
|
|
if (mount("proc", "/proc", "proc", 0, NULL) == 0) {
|
|
printf("[init] /proc mounted\r\n");
|
|
} else {
|
|
printf("[init] /proc mount failed\r\n");
|
|
}
|
|
}
|
|
|
|
static void mount_sys(void) {
|
|
mkdir("/sys", 0755);
|
|
if (mount("sysfs", "/sys", "sysfs", 0, NULL) == 0) {
|
|
printf("[init] /sys mounted\r\n");
|
|
} else {
|
|
printf("[init] /sys mount failed\r\n");
|
|
}
|
|
}
|
|
|
|
static void mount_dev(void) {
|
|
mkdir("/dev", 0755);
|
|
if (mount("tmpfs", "/dev", "tmpfs", 0, "size=64M") == 0) {
|
|
printf("[init] /dev mounted (tmpfs)\r\n");
|
|
} else {
|
|
printf("[init] /dev mount failed\r\n");
|
|
}
|
|
}
|
|
|
|
static void print_cpuinfo(void) {
|
|
FILE *f = fopen("/proc/cpuinfo", "r");
|
|
if (f) {
|
|
char line[256];
|
|
printf("[init] CPU info:\r\n");
|
|
while (fgets(line, sizeof(line), f)) {
|
|
if (strncmp(line, "Processor", 9) == 0 ||
|
|
strncmp(line, "model name", 10) == 0 ||
|
|
strncmp(line, "CPU implementer", 14) == 0 ||
|
|
strncmp(line, "CPU variant", 10) == 0 ||
|
|
strncmp(line, "BogoMIPS", 8) == 0) {
|
|
printf(" %s", line);
|
|
}
|
|
}
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
static void print_uptime(void) {
|
|
FILE *f = fopen("/proc/uptime", "r");
|
|
if (f) {
|
|
double uptime;
|
|
if (fscanf(f, "%lf", &uptime) == 1) {
|
|
printf("[init] System uptime: %.1f seconds\r\n", uptime);
|
|
}
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
static void print_memory(void) {
|
|
FILE *f = fopen("/proc/meminfo", "r");
|
|
if (f) {
|
|
char line[256];
|
|
printf("[init] Memory info:\r\n");
|
|
while (fgets(line, sizeof(line), f)) {
|
|
if (strncmp(line, "MemTotal", 8) == 0 ||
|
|
strncmp(line, "MemFree", 7) == 0 ||
|
|
strncmp(line, "MemAvailable", 12) == 0) {
|
|
printf(" %s", line);
|
|
}
|
|
}
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
printf(BANNER);
|
|
printf("[init] UniversalisOS Linux Guest Init\r\n");
|
|
printf("[init] PID=%d\r\n", getpid());
|
|
|
|
/* Mount essential filesystems */
|
|
mount_dev();
|
|
mount_proc();
|
|
mount_sys();
|
|
|
|
/* Create basic device nodes */
|
|
mknod("/dev/console", 0600 | S_IFCHR, makedev(5, 1));
|
|
mknod("/dev/null", 0666 | S_IFCHR, makedev(1, 3));
|
|
mknod("/dev/zero", 0666 | S_IFCHR, makedev(1, 5));
|
|
|
|
/* Print system information */
|
|
print_cpuinfo();
|
|
print_uptime();
|
|
print_memory();
|
|
|
|
/* Print mount info */
|
|
FILE *f = fopen("/proc/mounts", "r");
|
|
if (f) {
|
|
char line[256];
|
|
printf("[init] Mounts:\r\n");
|
|
while (fgets(line, sizeof(line), f)) {
|
|
printf(" %s", line);
|
|
}
|
|
fclose(f);
|
|
}
|
|
|
|
printf("\r\n[init] System ready. Entering idle loop.\r\n");
|
|
printf("[init] To shutdown: echo 1 > /proc/sys/kernel/sysrq && echo o > /proc/sysrq-trigger\r\n");
|
|
|
|
/* Idle loop — in a real system this would run a shell or service manager */
|
|
while (1) {
|
|
sleep(10);
|
|
printf("[init] heartbeat\r\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|