core, bios: Move __syslinux_shuffler_size to assembly
[syslinux/sherbszt.git] / core / elflink / load_env32.c
blob492cc095ee676434855c30a8b3b29fc2c20ea9ef
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <console.h>
6 #include <dprintf.h>
7 #include <com32.h>
8 #include <syslinux/adv.h>
9 #include <syslinux/config.h>
10 #include <setjmp.h>
11 #include <linux/list.h>
12 #include <netinet/in.h>
13 #include <sys/cpu.h>
14 #include <core.h>
15 #include <fcntl.h>
16 #include <sys/file.h>
17 #include <fs.h>
18 #include <ctype.h>
19 #include <alloca.h>
21 #include <sys/exec.h>
22 #include <sys/module.h>
23 #include "common.h"
25 extern char __dynstr_start[];
26 extern char __dynstr_end[], __dynsym_end[];
27 extern char __dynsym_start[];
28 extern char __got_start[];
29 extern Elf_Dyn __dynamic_start[];
30 extern Elf_Word __gnu_hash_start[];
31 extern char __module_start[];
33 struct elf_module core_module = {
34 .name = "(core)",
35 .shallow = true,
36 .required = LIST_HEAD_INIT((core_module.required)),
37 .dependants = LIST_HEAD_INIT((core_module.dependants)),
38 .list = LIST_HEAD_INIT((core_module.list)),
39 .module_addr = (void *)0x0,
40 .ghash_table = __gnu_hash_start,
41 .str_table = __dynstr_start,
42 .sym_table = __dynsym_start,
43 .got = __got_start,
44 .dyn_table = __dynamic_start,
45 .syment_size = sizeof(Elf_Sym),
49 * Initializes the module subsystem by taking the core module
50 * (preinitialized shallow module) and placing it on top of the
51 * modules_head_list.
53 void init_module_subsystem(struct elf_module *module)
55 list_add(&module->list, &modules_head);
58 __export int start_ldlinux(int argc, char **argv)
60 int rv;
62 again:
63 rv = spawn_load(LDLINUX, argc, argv);
64 if (rv == EEXIST) {
66 * If a COM32 module calls execute() we may need to
67 * unload all the modules loaded since ldlinux.*,
68 * and restart initialisation. This is especially
69 * important for config files.
71 * But before we do that, try our best to make sure
72 * that spawn_load() is gonna succeed, e.g. that we
73 * can find LDLINUX it in PATH.
75 struct elf_module *ldlinux;
76 FILE *f;
78 f = findpath(LDLINUX);
79 if (!f)
80 return ENOENT;
82 fclose(f);
83 ldlinux = unload_modules_since(LDLINUX);
86 * Finally unload LDLINUX.
88 * We'll reload it when we jump to 'again' which will
89 * cause all the initialsation steps to be executed
90 * again.
92 module_unload(ldlinux);
93 goto again;
96 return rv;
99 /* note to self: do _*NOT*_ use static key word on this function */
100 void load_env32(com32sys_t * regs __unused)
102 struct file_info *fp;
103 int fd;
104 char *argv[] = { LDLINUX, NULL };
105 char realname[FILENAME_MAX];
106 size_t size;
108 static const char *search_directories[] = {
109 "/boot/isolinux",
110 "/isolinux",
111 "/boot/syslinux",
112 "/syslinux",
113 "/",
114 NULL
117 static const char *filenames[] = {
118 LDLINUX,
119 NULL
122 dprintf("Starting %s elf module subsystem...\n", ELF_MOD_SYS);
124 if (strlen(CurrentDirName) && !path_add(CurrentDirName)) {
125 printf("Couldn't allocate memory for PATH\n");
126 goto out;
129 size = (size_t)__dynstr_end - (size_t)__dynstr_start;
130 core_module.strtable_size = size;
131 size = (size_t)__dynsym_end - (size_t)__dynsym_start;
132 core_module.symtable_size = size;
133 core_module.base_addr = (Elf_Addr)__module_start;
135 init_module_subsystem(&core_module);
137 start_ldlinux(1, argv);
140 * If we failed to load LDLINUX it could be because our
141 * current working directory isn't the install directory. Try
142 * a bit harder to find LDLINUX. If search_dirs() succeeds
143 * in finding LDLINUX it will set the cwd.
145 fd = opendev(&__file_dev, NULL, O_RDONLY);
146 if (fd < 0)
147 goto out;
149 fp = &__file_info[fd];
151 if (!search_dirs(&fp->i.fd, search_directories, filenames, realname)) {
152 char path[FILENAME_MAX];
155 * search_dirs() sets the current working directory if
156 * it successfully opens the file. Add the directory
157 * in which we found ldlinux.* to PATH.
159 if (!core_getcwd(path, sizeof(path)))
160 goto out;
162 if (!path_add(path)) {
163 printf("Couldn't allocate memory for PATH\n");
164 goto out;
167 start_ldlinux(1, argv);
170 out:
171 writestr("\nFailed to load ");
172 writestr(LDLINUX);
175 static const char *__cmdline;
176 __export const char *com32_cmdline(void)
178 return __cmdline;
181 __export int create_args_and_load(char *cmdline)
183 char *p, **argv;
184 int argc;
185 int i;
187 if (!cmdline)
188 return -1;
190 for (argc = 0, p = cmdline; *p; argc++) {
191 /* Find the end of this arg */
192 while(*p && !isspace(*p))
193 p++;
196 * Now skip all whitespace between arguments.
198 while (*p && isspace(*p))
199 p++;
203 * Generate a copy of argv on the stack as this is
204 * traditionally where process arguments go.
206 * argv[0] must be the command name. Remember to allocate
207 * space for the sentinel NULL.
209 argv = alloca((argc + 1) * sizeof(char *));
211 for (i = 0, p = cmdline; i < argc; i++) {
212 char *start;
213 int len = 0;
215 start = p;
217 /* Find the end of this arg */
218 while(*p && !isspace(*p)) {
219 p++;
220 len++;
223 argv[i] = malloc(len + 1);
224 strncpy(argv[i], start, len);
225 argv[i][len] = '\0';
228 * Now skip all whitespace between arguments.
230 while (*p && isspace(*p))
231 p++;
234 * Point __cmdline at "argv[1] ... argv[argc-1]"
236 if (i == 0)
237 __cmdline = p;
240 /* NUL-terminate */
241 argv[argc] = NULL;
243 return spawn_load(argv[0], argc, argv);
246 void pm_env32_run(com32sys_t *regs)
248 char *cmdline;
250 cmdline = MK_PTR(regs->es, regs->ebx.w[0]);
251 if (create_args_and_load(cmdline) < 0)
252 printf("Failed to run com32 module\n");