PROGRAM := kvm
GUEST_INIT := guest/init
+GUEST_INIT_S2 := guest/init_stage2
OBJS += builtin-balloon.o
OBJS += builtin-debug.o
CFLAGS += $(WARNINGS)
-all: $(PROGRAM) $(GUEST_INIT)
+all: $(PROGRAM) $(GUEST_INIT) $(GUEST_INIT_S2)
KVMTOOLS-VERSION-FILE:
@$(SHELL_PATH) util/KVMTOOLS-VERSION-GEN $(OUTPUT)
$(E) " LINK " $@
$(Q) $(CC) -static guest/init.c -o $@
+$(GUEST_INIT_S2): guest/init_stage2.c
+ $(E) " LINK " $@
+ $(Q) $(CC) -static guest/init_stage2.c -o $@
+
$(DEPS):
%.d: %.c
$(E) " NM " $@
$(Q) cd bios && sh gen-offsets.sh > bios-rom.h && cd ..
-check: $(PROGRAM)
+check: all
$(MAKE) -C tests
./$(PROGRAM) run tests/pit/tick.bin
./$(PROGRAM) run -d tests/boot/boot_test.iso -p "init=init"
$(Q) rm -f bios/bios-rom.h
$(Q) rm -f tests/boot/boot_test.iso
$(Q) rm -rf tests/boot/rootfs/
- $(Q) rm -f $(DEPS) $(OBJS) $(PROGRAM) $(GUEST_INIT)
+ $(Q) rm -f $(DEPS) $(OBJS) $(PROGRAM) $(GUEST_INIT) $(GUEST_INIT_S2)
$(Q) rm -f cscope.*
$(Q) rm -f $(KVM_INCLUDE)/common-cmds.h
$(Q) rm -f KVMTOOLS-VERSION-FILE
usage_with_options(run_usage, options);
}
+static int kvm_custom_stage2(void)
+{
+ char tmp[PATH_MAX], dst[PATH_MAX], *src;
+ const char *rootfs;
+ int r;
+
+ src = realpath("guest/init_stage2", NULL);
+ if (src == NULL)
+ return -ENOMEM;
+
+ if (image_filename[0] == NULL)
+ rootfs = "default";
+ else
+ rootfs = image_filename[0];
+
+ snprintf(tmp, PATH_MAX, "%s%s/virt/init_stage2", kvm__get_dir(), rootfs);
+ remove(tmp);
+
+ snprintf(dst, PATH_MAX, "/host/%s", src);
+ r = symlink(dst, tmp);
+ free(src);
+
+ return r;
+}
+
int kvm_cmd_run(int argc, const char **argv, const char *prefix)
{
static char real_cmdline[2048], default_name[20];
strcat(real_cmdline, " init=/virt/init");
if (!no_dhcp)
strcat(real_cmdline, " ip=dhcp");
+ if (kvm_custom_stage2())
+ die("Failed linking stage 2 of init.");
}
} else if (!strstr(real_cmdline, "root=")) {
strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline));
/*
- * This is a simple init for shared rootfs guests. It brings up critical
- * mountpoints and then launches /bin/sh.
+ * This is a simple init for shared rootfs guests. This part should be limited
+ * to doing mounts and running stage 2 of the init process.
*/
#include <sys/mount.h>
#include <string.h>
do_mounts();
- /* get session leader */
- setsid();
-
- /* set controlling terminal */
- ioctl (0, TIOCSCTTY, 1);
-
- puts("Starting '/bin/sh'...");
-
- run_process("/bin/sh");
+ run_process("/virt/init_stage2");
printf("Init failed: %s\n", strerror(errno));
--- /dev/null
+/*
+ * This is a stage 2 of the init. This part should do all the heavy
+ * lifting such as setting up the console and calling /bin/sh.
+ */
+#include <sys/mount.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+static int run_process(char *filename)
+{
+ char *new_argv[] = { filename, NULL };
+ char *new_env[] = { "TERM=linux", NULL };
+
+ return execve(filename, new_argv, new_env);
+}
+
+int main(int argc, char *argv[])
+{
+ /* get session leader */
+ setsid();
+
+ /* set controlling terminal */
+ ioctl(0, TIOCSCTTY, 1);
+
+ puts("Starting '/bin/sh'...");
+
+ run_process("/bin/sh");
+
+ printf("Init failed: %s\n", strerror(errno));
+
+ return 0;
+}