preinit.c (2674B)
1 #include <string.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <fcntl.h> 5 #include <sys/mount.h> 6 #include <sys/wait.h> 7 #include <string.h> 8 #include <stdint.h> 9 #include <errno.h> 10 11 #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ 12 13 void parseopts(char * cmdline, char **root, char **rootfstype); 14 15 #define ERR(x) write(2, x, strlen(x)) 16 #define AVER(c) do { if(c < 0) { ERR("failed: " #c ": error=0x" ); pr_u32(errno); ERR("\n"); } } while(0) 17 18 char * pr_u32(int32_t input); 19 20 static void die() { 21 /* if init exits, it causes a kernel panic. On the Turris 22 * Omnia (and maybe other hardware, I don't know), the kernel 23 * panics _before_ any of the messages from AVER are printed, 24 * which makes it really hard to tell what went wrong. So 25 * let's wait a little here to give the console a chance to 26 * catch up. 27 * 28 * Yes, I know that file descriptor IO is supposedly 29 * non-buffered. Empirical observation suggests that there 30 * must be a buffer of some kind somewhere though. 31 */ 32 33 sleep(10); 34 exit(1); 35 } 36 37 static int fork_exec(char * command, char *args[]) 38 { 39 int fork_pid = fork(); 40 AVER(fork_pid); 41 if(fork_pid > 0) 42 return wait(NULL); 43 else 44 return execve(command, args, NULL); 45 } 46 47 char banner[] = "Running pre-init...\n"; 48 char buf[COMMAND_LINE_SIZE]; 49 50 int main(int argc, char *argv[], char *envp[]) 51 { 52 char *rootdevice = 0; 53 char *rootfstype = 0; 54 55 write(1, banner, strlen(banner)); 56 57 AVER(mount("none", "/proc", "proc", 0, NULL)); 58 AVER(mount("none", "/dev", "devtmpfs", 0, NULL)); 59 60 int cmdline = open("/proc/cmdline", O_RDONLY, 0); 61 62 if(cmdline>=0) { 63 int len = read(cmdline, buf, sizeof buf - 1); 64 buf[len]='\0'; 65 while(buf[len-1]=='\n') { 66 buf[len-1]='\0'; 67 len--; 68 } 69 write(1, "cmdline: \"", 10); 70 write(1, buf, len); 71 write(1, "\"\n", 2); 72 } else { 73 ERR("failed: open(\"/proc/cmdline\")\n"); 74 die(); 75 } 76 parseopts(buf, &rootdevice, &rootfstype); 77 78 if(rootdevice) { 79 if(!rootfstype) rootfstype = "jffs2"; /* backward compatibility */ 80 write(1, "rootdevice ", 11); 81 write(1, rootdevice, strlen(rootdevice)); 82 write(1, " (", 2); 83 write(1, rootfstype, strlen(rootfstype)); 84 write(1, ")\n", 2); 85 AVER(mount(rootdevice, "/target/persist", rootfstype, 0, NULL)); 86 AVER(mount("/target/persist/nix", "/target/nix", 87 "bind", MS_BIND, NULL)); 88 89 char *exec_args[] = { "activate", "/target", NULL }; 90 AVER(fork_exec("/target/persist/activate", exec_args)); 91 AVER(chdir("/target")); 92 93 AVER(mount("/target", "/", "bind", MS_BIND | MS_REC, NULL)); 94 AVER(chroot(".")); 95 96 argv[0] = "init"; 97 argv[1] = NULL; 98 AVER(execve("/persist/init", argv, envp)); 99 } 100 die(); 101 }