diff --git a/include/xhyve/firmware/fbsd.h b/include/xhyve/firmware/fbsd.h index 30d4388..8930da1 100644 --- a/include/xhyve/firmware/fbsd.h +++ b/include/xhyve/firmware/fbsd.h @@ -97,6 +97,5 @@ struct loader_callbacks { const char * (*getenv)(void *arg, int num); }; -void fbsd_init(char *userboot_path, char *bootvolume_path, char *kernelenv, - char *cons); +int fbsd_init(char *opts[]); uint64_t fbsd_load(void); diff --git a/include/xhyve/firmware/kexec.h b/include/xhyve/firmware/kexec.h index 791d963..40e0ca9 100644 --- a/include/xhyve/firmware/kexec.h +++ b/include/xhyve/firmware/kexec.h @@ -85,5 +85,5 @@ struct zero_page { } __attribute__((packed)); #pragma clang diagnostic pop -void kexec_init(char *kernel_path, char *initrd_path, char *cmdline); +int kexec_init(char *opts[]); uint64_t kexec(void); diff --git a/src/firmware/fbsd.c b/src/firmware/fbsd.c index 6a2d2bc..c687e6f 100644 --- a/src/firmware/fbsd.c +++ b/src/firmware/fbsd.c @@ -929,14 +929,15 @@ disk_open(char *path) return (err); } -void -fbsd_init(char *userboot_path, char *bootvolume_path, char *kernelenv, - char *cons) +int +fbsd_init(char *opts[]) { - config.userboot = userboot_path; - config.bootvolume = bootvolume_path; - config.kernelenv = kernelenv; - config.cons = cons; + config.userboot = opts[0]; + config.bootvolume = opts[1]; + config.kernelenv = opts[2]; + config.cons = opts[3]; + + return 0; } uint64_t diff --git a/src/firmware/kexec.c b/src/firmware/kexec.c index 61aeebb..59921a5 100644 --- a/src/firmware/kexec.c +++ b/src/firmware/kexec.c @@ -211,11 +211,13 @@ kexec_load_ramdisk(char *path) { return 0; } -void -kexec_init(char *kernel_path, char *initrd_path, char *cmdline) { - config.kernel = kernel_path; - config.initrd = initrd_path; - config.cmdline = cmdline; +int +kexec_init(char *opts[]) { + config.kernel = opts[0]; + config.initrd = opts[1]; + config.cmdline = opts[2]; + + return 0; } uint64_t diff --git a/src/xhyve.c b/src/xhyve.c index 7efc1cb..4827aa1 100644 --- a/src/xhyve.c +++ b/src/xhyve.c @@ -112,6 +112,15 @@ static struct bhyvestats { uint64_t cpu_switch_direct; } stats; +static const struct loader { + char *name; + int (*init)(char *opts[]); + uint64_t (*load)(); +} *fw_loader, fw_loaders[] = { + { "kexec", kexec_init, kexec }, + { "fbsd", fbsd_init, fbsd_load } +}; + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" static struct mt_vmm_info { @@ -120,8 +129,6 @@ static struct mt_vmm_info { } mt_vmm_info[VM_MAXCPU]; #pragma clang diagnostic pop -static uint64_t (*fw_func)(void); - __attribute__ ((noreturn)) static void usage(int code) { @@ -257,7 +264,7 @@ vcpu_thread(void *param) assert(error == 0); if (vcpu == BSP) { - rip_entry = fw_func(); + rip_entry = fw_loader->load(); } else { rip_entry = vmexit[vcpu].rip; spinup_ap_realmode(vcpu, &rip_entry); @@ -723,50 +730,37 @@ parse_memsize(const char *opt, size_t *ret_memsize) static int firmware_parse(const char *opt) { - char *fw, *opt1, *opt2, *opt3, *cp; + int ret, i; + char *cp, *opts[16] = { NULL }; - fw = strdup(opt); - - if (strncmp(fw, "kexec", strlen("kexec")) == 0) { - fw_func = kexec; - } else if (strncmp(fw, "fbsd", strlen("fbsd")) == 0) { - fw_func = fbsd_load; - } else { + cp = strdup(opt); + + /* Find method */ + for (i = 0; i < (int) nitems(fw_loaders); i++) { + if (strncmp(cp, fw_loaders[i].name, strlen(fw_loaders[i].name)) == 0) { + fw_loader = &fw_loaders[i]; + break; + } + } + + if (fw_loader == NULL) goto fail; + + /* Split arguments */ + for (i = 0; i < (int) nitems(opts) - 1; i++) { + cp = strchr(cp, ','); + if (cp != NULL) { + *cp = '\0'; + opts[i] = ++cp; + } + else + break; } - if ((cp = strchr(fw, ',')) != NULL) { - *cp = '\0'; - opt1 = cp + 1; - } else { - goto fail; - } - - if ((cp = strchr(opt1, ',')) != NULL) { - *cp = '\0'; - opt2 = cp + 1; - } else { - goto fail; - } - - if ((cp = strchr(opt2, ',')) != NULL) { - *cp = '\0'; - opt3 = cp + 1; - } else { - goto fail; - } - - opt2 = strlen(opt2) ? opt2 : NULL; - opt3 = strlen(opt3) ? opt3 : NULL; - - if (fw_func == kexec) { - kexec_init(opt1, opt2, opt3); - } else if (fw_func == fbsd_load) { - /* FIXME: let user set boot-loader serial device */ - fbsd_init(opt1, opt2, opt3, NULL); - } else { + /* Initialize loader */ + ret = fw_loader->init(opts); + if (ret) goto fail; - } return 0; @@ -836,7 +830,7 @@ fail: int main(int argc, char *argv[]) { - int c, error, gdb_port, bvmcons, fw; + int c, error, gdb_port, bvmcons; int dump_guest_memory, max_vcpus, mptgen; int rtc_localtime; uint64_t rip; @@ -851,7 +845,6 @@ main(int argc, char *argv[]) memsize = 256 * MB; mptgen = 1; rtc_localtime = 1; - fw = 0; while ((c = getopt(argc, argv, "behvuwxMACHPWY:f:F:g:c:s:m:l:U:")) != -1) { switch (c) { @@ -870,9 +863,6 @@ main(int argc, char *argv[]) case 'f': if (firmware_parse(optarg) != 0) { exit (1); - } else { - fw = 1; - break; } case 'F': pidfile = optarg; @@ -935,7 +925,7 @@ main(int argc, char *argv[]) } } - if (fw != 1) + if (fw_loader == NULL) usage(1); error = xh_vm_create();