#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" extern char __dynstr_start[]; extern char __dynstr_end[], __dynsym_end[]; extern char __dynsym_start[]; extern char __got_start[]; extern Elf_Dyn __dynamic_start[]; extern Elf_Word __gnu_hash_start[]; extern char __module_start[]; struct elf_module core_module = { .name = "(core)", .shallow = true, .required = LIST_HEAD_INIT((core_module.required)), .dependants = LIST_HEAD_INIT((core_module.dependants)), .list = LIST_HEAD_INIT((core_module.list)), .module_addr = (void *)0x0, .ghash_table = __gnu_hash_start, .str_table = __dynstr_start, .sym_table = __dynsym_start, .got = __got_start, .dyn_table = __dynamic_start, .syment_size = sizeof(Elf_Sym), }; /* * Initializes the module subsystem by taking the core module * (preinitialized shallow module) and placing it on top of the * modules_head_list. */ void init_module_subsystem(struct elf_module *module) { list_add(&module->list, &modules_head); } __export int start_ldlinux(int argc, char **argv) { int rv; again: rv = spawn_load(LDLINUX, argc, argv); if (rv == EEXIST) { /* * If a COM32 module calls execute() we may need to * unload all the modules loaded since ldlinux.*, * and restart initialisation. This is especially * important for config files. * * But before we do that, try our best to make sure * that spawn_load() is gonna succeed, e.g. that we * can find LDLINUX it in PATH. */ struct elf_module *ldlinux; FILE *f; f = findpath(LDLINUX); if (!f) return ENOENT; fclose(f); ldlinux = unload_modules_since(LDLINUX); /* * Finally unload LDLINUX. * * We'll reload it when we jump to 'again' which will * cause all the initialsation steps to be executed * again. */ module_unload(ldlinux); goto again; } return rv; } /* note to self: do _*NOT*_ use static key word on this function */ void load_env32(com32sys_t * regs __unused) { struct file_info *fp; int fd; char *argv[] = { LDLINUX, NULL }; char realname[FILENAME_MAX]; size_t size; static const char *search_directories[] = { "/boot/isolinux", "/isolinux", "/boot/syslinux", "/syslinux", "/", NULL }; static const char *filenames[] = { LDLINUX, NULL }; dprintf("Starting %s elf module subsystem...\n", ELF_MOD_SYS); if (strlen(CurrentDirName) && !path_add(CurrentDirName)) { printf("Couldn't allocate memory for PATH\n"); goto out; } size = (size_t)__dynstr_end - (size_t)__dynstr_start; core_module.strtable_size = size; size = (size_t)__dynsym_end - (size_t)__dynsym_start; core_module.symtable_size = size; core_module.base_addr = (Elf_Addr)__module_start; init_module_subsystem(&core_module); start_ldlinux(1, argv); /* * If we failed to load LDLINUX it could be because our * current working directory isn't the install directory. Try * a bit harder to find LDLINUX. If search_dirs() succeeds * in finding LDLINUX it will set the cwd. */ fd = opendev(&__file_dev, NULL, O_RDONLY); if (fd < 0) goto out; fp = &__file_info[fd]; if (!search_dirs(&fp->i.fd, search_directories, filenames, realname)) { char path[FILENAME_MAX]; /* * search_dirs() sets the current working directory if * it successfully opens the file. Add the directory * in which we found ldlinux.* to PATH. */ if (!core_getcwd(path, sizeof(path))) goto out; if (!path_add(path)) { printf("Couldn't allocate memory for PATH\n"); goto out; } start_ldlinux(1, argv); } out: writestr("\nFailed to load "); writestr(LDLINUX); } static const char *__cmdline; __export const char *com32_cmdline(void) { return __cmdline; } __export int create_args_and_load(char *cmdline) { char *p, **argv; int argc; int i; if (!cmdline) return -1; for (argc = 0, p = cmdline; *p; argc++) { /* Find the end of this arg */ while(*p && !isspace(*p)) p++; /* * Now skip all whitespace between arguments. */ while (*p && isspace(*p)) p++; } /* * Generate a copy of argv on the stack as this is * traditionally where process arguments go. * * argv[0] must be the command name. Remember to allocate * space for the sentinel NULL. */ argv = alloca((argc + 1) * sizeof(char *)); for (i = 0, p = cmdline; i < argc; i++) { char *start; int len = 0; start = p; /* Find the end of this arg */ while(*p && !isspace(*p)) { p++; len++; } argv[i] = malloc(len + 1); strncpy(argv[i], start, len); argv[i][len] = '\0'; /* * Now skip all whitespace between arguments. */ while (*p && isspace(*p)) p++; /* * Point __cmdline at "argv[1] ... argv[argc-1]" */ if (i == 0) __cmdline = p; } /* NUL-terminate */ argv[argc] = NULL; return spawn_load(argv[0], argc, argv); } void pm_env32_run(com32sys_t *regs) { char *cmdline; cmdline = MK_PTR(regs->es, regs->ebx.w[0]); if (create_args_and_load(cmdline) < 0) printf("Failed to run com32 module\n"); }