• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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