Merging upstream version 5.01+dfsg.
[syslinux-debian/hramrach.git] / core / elflink / load_env32.c
blob3ddbfec3e9148f0ba8515e44e3cad89fe2f4bca6
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 #define LDLINUX "ldlinux.c32"
27 extern char __dynstr_start[];
28 extern char __dynstr_len[], __dynsym_len[];
29 extern char __dynsym_start[];
30 extern char __got_start[];
31 extern Elf32_Dyn __dynamic_start[];
32 extern Elf32_Word __gnu_hash_start[];
34 struct elf_module core_module = {
35 .name = "(core)",
36 .shallow = true,
37 .required = LIST_HEAD_INIT((core_module.required)),
38 .dependants = LIST_HEAD_INIT((core_module.dependants)),
39 .list = LIST_HEAD_INIT((core_module.list)),
40 .module_addr = (void *)0x0,
41 .base_addr = (Elf32_Addr) 0x0,
42 .ghash_table = __gnu_hash_start,
43 .str_table = __dynstr_start,
44 .sym_table = __dynsym_start,
45 .got = __got_start,
46 .dyn_table = __dynamic_start,
47 .strtable_size = (size_t) __dynstr_len,
48 .syment_size = sizeof(Elf32_Sym),
49 .symtable_size = (size_t) __dynsym_len
53 * Initializes the module subsystem by taking the core module
54 * (preinitialized shallow module) and placing it on top of the
55 * modules_head_list.
57 void init_module_subsystem(struct elf_module *module)
59 list_add(&module->list, &modules_head);
62 __export int start_ldlinux(char **argv)
64 int rv;
66 again:
67 rv = spawn_load(LDLINUX, 1, argv);
68 if (rv == EEXIST) {
70 * If a COM32 module calls execute() we may need to
71 * unload all the modules loaded since ldlinux.c32,
72 * and restart initialisation. This is especially
73 * important for config files.
75 * But before we do that, try our best to make sure
76 * that spawn_load() is gonna succeed, e.g. that we
77 * can find LDLINUX it in PATH.
79 struct elf_module *ldlinux;
80 FILE *f;
82 f = findpath(LDLINUX);
83 if (!f)
84 return ENOENT;
86 fclose(f);
87 ldlinux = unload_modules_since(LDLINUX);
90 * Finally unload LDLINUX.
92 * We'll reload it when we jump to 'again' which will
93 * cause all the initialsation steps to be executed
94 * again.
96 module_unload(ldlinux);
97 goto again;
100 return rv;
103 /* note to self: do _*NOT*_ use static key word on this function */
104 void load_env32(com32sys_t * regs __unused)
106 struct file_info *fp;
107 int fd;
108 char *argv[] = { LDLINUX, NULL };
109 char realname[FILENAME_MAX];
111 static const char *search_directories[] = {
112 "/boot/isolinux",
113 "/isolinux",
114 "/boot/syslinux",
115 "/syslinux",
116 "/",
117 NULL
120 static const char *filenames[] = {
121 LDLINUX,
122 NULL
125 dprintf("Starting 32 bit elf module subsystem...\n");
127 PATH = malloc(strlen(CurrentDirName) + 1);
128 if (!PATH) {
129 printf("Couldn't allocate memory for PATH\n");
130 goto out;
133 strcpy(PATH, CurrentDirName);
135 init_module_subsystem(&core_module);
137 start_ldlinux(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 free(PATH);
146 fd = opendev(&__file_dev, NULL, O_RDONLY);
147 if (fd < 0)
148 return;
150 fp = &__file_info[fd];
152 if (!search_dirs(&fp->i.fd, search_directories, filenames, realname)) {
153 char path[FILENAME_MAX];
156 * search_dirs() sets the current working directory if
157 * it successfully opens the file. Set PATH to the
158 * directory in which we found ldlinux.c32.
160 if (!core_getcwd(path, sizeof(path)))
161 goto out;
163 PATH = malloc(strlen(path) + 1);
164 if (!PATH) {
165 printf("Couldn't allocate memory for PATH\n");
166 goto out;
169 strcpy(PATH, path);
171 start_ldlinux(argv);
174 out:
175 writestr("\nFailed to load ldlinux.c32");
178 __export int create_args_and_load(char *cmdline)
180 char *p, **argv;
181 int argc;
182 int i;
184 if (!cmdline)
185 return -1;
187 for (argc = 0, p = cmdline; *p; argc++) {
188 /* Find the end of this arg */
189 while(*p && !isspace(*p))
190 p++;
193 * Now skip all whitespace between arguments.
195 while (*p && isspace(*p))
196 p++;
200 * Generate a copy of argv on the stack as this is
201 * traditionally where process arguments go.
203 * argv[0] must be the command name. Remember to allocate
204 * space for the sentinel NULL.
206 argv = alloca((argc + 1) * sizeof(char *));
208 for (i = 0, p = cmdline; i < argc; i++) {
209 char *start;
210 int len = 0;
212 start = p;
214 /* Find the end of this arg */
215 while(*p && !isspace(*p)) {
216 p++;
217 len++;
220 argv[i] = malloc(len + 1);
221 strncpy(argv[i], start, len);
222 argv[i][len] = '\0';
225 * Now skip all whitespace between arguments.
227 while (*p && isspace(*p))
228 p++;
231 /* NUL-terminate */
232 argv[argc] = NULL;
234 return spawn_load(argv[0], argc, argv);
237 void pm_env32_run(com32sys_t *regs)
239 char *cmdline;
241 cmdline = MK_PTR(regs->es, regs->ebx.w[0]);
242 if (create_args_and_load(cmdline) < 0)
243 printf("Failed to run com32 module\n");