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>
20
21 #include <sys/exec.h>
22 #include <sys/module.h>
23 #include "common.h"
24
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[];
32
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),
46 };
47
48 /*
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.
52 */
init_module_subsystem(struct elf_module * module)53 void init_module_subsystem(struct elf_module *module)
54 {
55 list_add(&module->list, &modules_head);
56 }
57
start_ldlinux(int argc,char ** argv)58 __export int start_ldlinux(int argc, char **argv)
59 {
60 int rv;
61
62 again:
63 rv = spawn_load(LDLINUX, argc, argv);
64 if (rv == EEXIST) {
65 /*
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.
70 *
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.
74 */
75 struct elf_module *ldlinux;
76 FILE *f;
77
78 f = findpath(LDLINUX);
79 if (!f)
80 return ENOENT;
81
82 fclose(f);
83 ldlinux = unload_modules_since(LDLINUX);
84
85 /*
86 * Finally unload LDLINUX.
87 *
88 * We'll reload it when we jump to 'again' which will
89 * cause all the initialsation steps to be executed
90 * again.
91 */
92 module_unload(ldlinux);
93 goto again;
94 }
95
96 return rv;
97 }
98
99 /* note to self: do _*NOT*_ use static key word on this function */
load_env32(com32sys_t * regs __unused)100 void load_env32(com32sys_t * regs __unused)
101 {
102 struct file_info *fp;
103 int fd;
104 char *argv[] = { LDLINUX, NULL };
105 char realname[FILENAME_MAX];
106 size_t size;
107
108 static const char *search_directories[] = {
109 "/boot/isolinux",
110 "/isolinux",
111 "/boot/syslinux",
112 "/syslinux",
113 "/",
114 NULL
115 };
116
117 static const char *filenames[] = {
118 LDLINUX,
119 NULL
120 };
121
122 dprintf("Starting %s elf module subsystem...\n", ELF_MOD_SYS);
123
124 if (strlen(CurrentDirName) && !path_add(CurrentDirName)) {
125 printf("Couldn't allocate memory for PATH\n");
126 goto out;
127 }
128
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;
134
135 init_module_subsystem(&core_module);
136
137 start_ldlinux(1, argv);
138
139 /*
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.
144 */
145 fd = opendev(&__file_dev, NULL, O_RDONLY);
146 if (fd < 0)
147 goto out;
148
149 fp = &__file_info[fd];
150
151 if (!search_dirs(&fp->i.fd, search_directories, filenames, realname)) {
152 char path[FILENAME_MAX];
153
154 /*
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.
158 */
159 if (!core_getcwd(path, sizeof(path)))
160 goto out;
161
162 if (!path_add(path)) {
163 printf("Couldn't allocate memory for PATH\n");
164 goto out;
165 }
166
167 start_ldlinux(1, argv);
168 }
169
170 out:
171 writestr("\nFailed to load ");
172 writestr(LDLINUX);
173 }
174
175 static const char *__cmdline;
com32_cmdline(void)176 __export const char *com32_cmdline(void)
177 {
178 return __cmdline;
179 }
180
create_args_and_load(char * cmdline)181 __export int create_args_and_load(char *cmdline)
182 {
183 char *p, **argv;
184 int argc;
185 int i;
186
187 if (!cmdline)
188 return -1;
189
190 for (argc = 0, p = cmdline; *p; argc++) {
191 /* Find the end of this arg */
192 while(*p && !isspace(*p))
193 p++;
194
195 /*
196 * Now skip all whitespace between arguments.
197 */
198 while (*p && isspace(*p))
199 p++;
200 }
201
202 /*
203 * Generate a copy of argv on the stack as this is
204 * traditionally where process arguments go.
205 *
206 * argv[0] must be the command name. Remember to allocate
207 * space for the sentinel NULL.
208 */
209 argv = alloca((argc + 1) * sizeof(char *));
210
211 for (i = 0, p = cmdline; i < argc; i++) {
212 char *start;
213 int len = 0;
214
215 start = p;
216
217 /* Find the end of this arg */
218 while(*p && !isspace(*p)) {
219 p++;
220 len++;
221 }
222
223 argv[i] = malloc(len + 1);
224 strncpy(argv[i], start, len);
225 argv[i][len] = '\0';
226
227 /*
228 * Now skip all whitespace between arguments.
229 */
230 while (*p && isspace(*p))
231 p++;
232
233 /*
234 * Point __cmdline at "argv[1] ... argv[argc-1]"
235 */
236 if (i == 0)
237 __cmdline = p;
238 }
239
240 /* NUL-terminate */
241 argv[argc] = NULL;
242
243 return spawn_load(argv[0], argc, argv);
244 }
245
pm_env32_run(com32sys_t * regs)246 void pm_env32_run(com32sys_t *regs)
247 {
248 char *cmdline;
249
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");
253 }
254