source: bootcd/isolinux/syslinux-6.03/core/elflink/load_env32.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 5.3 KB
Line 
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
25extern char __dynstr_start[];
26extern char __dynstr_end[], __dynsym_end[];
27extern char __dynsym_start[];
28extern char __got_start[];
29extern Elf_Dyn __dynamic_start[];
30extern Elf_Word __gnu_hash_start[];
31extern char __module_start[];
32
33struct 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 */
53void init_module_subsystem(struct elf_module *module)
54{
55    list_add(&module->list, &modules_head);
56}
57
58__export int start_ldlinux(int argc, char **argv)
59{
60        int rv;
61
62again:
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 */
100void 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
170out:
171        writestr("\nFailed to load ");
172        writestr(LDLINUX);
173}
174
175static const char *__cmdline;
176__export const char *com32_cmdline(void)
177{
178        return __cmdline;
179}
180
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
246void 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}
Note: See TracBrowser for help on using the repository browser.