summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorJustus Winter <justus@gnupg.org>2016-11-01 13:40:53 +0100
committerJustus Winter <justus@gnupg.org>2016-11-01 15:18:19 +0100
commit411806400bcc72e9f6004c40b3af8960df452be5 (patch)
tree04a9a0ed677a8e1e0ebeeead85744c19e60fd6c7 /boot
parent6511afff053bab1e7e0542119ff1331813ea19e2 (diff)
boot: Move bootscript callbacks.
* boot/boot.c (useropen, load_image, boot_script_exec_cmd): Move... * boot/userland-boot.c: ... here.
Diffstat (limited to 'boot')
-rw-r--r--boot/boot.c208
-rw-r--r--boot/userland-boot.c211
2 files changed, 212 insertions, 207 deletions
diff --git a/boot/boot.c b/boot/boot.c
index 234ccd8b..69c30333 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -24,7 +24,6 @@
#include <mach.h>
#include <mach/notify.h>
#include <device/device.h>
-#include <a.out.h>
#include <mach/message.h>
#include <mach/mig_errors.h>
#include <stdlib.h>
@@ -32,10 +31,8 @@
#include <stdio.h>
#include <pthread.h>
#include <fcntl.h>
-#include <elf.h>
#include <mach/mig_support.h>
#include <mach/default_pager.h>
-#include <mach/machine/vm_param.h> /* For VM_XXX_ADDRESS */
#include <argp.h>
#include <hurd/store.h>
#include <sys/mman.h>
@@ -131,29 +128,7 @@ void safe_gets (char *buf, int buf_len)
fgets (buf, buf_len, stdin);
}
-char *useropen_dir;
-
-int
-useropen (const char *name, int flags, int mode)
-{
- if (useropen_dir)
- {
- static int dlen;
- if (!dlen) dlen = strlen (useropen_dir);
- {
- int len = strlen (name);
- char try[dlen + 1 + len + 1];
- int fd;
- memcpy (try, useropen_dir, dlen);
- try[dlen] = '/';
- memcpy (&try[dlen + 1], name, len + 1);
- fd = open (try, flags, mode);
- if (fd >= 0)
- return fd;
- }
- }
- return open (name, flags, mode);
-}
+extern char *useropen_dir;
/* XXX: glibc should provide mig_reply_setup but does not. */
/* Fill in default response. */
@@ -206,190 +181,9 @@ boot_demuxer (mach_msg_header_t *inp,
return FALSE;
}
-vm_address_t
-load_image (task_t t,
- char *file)
-{
- int fd;
- union
- {
- struct exec a;
- Elf32_Ehdr e;
- } hdr;
- char msg[] = ": cannot open bootstrap file\n";
-
- fd = useropen (file, O_RDONLY, 0);
-
- if (fd == -1)
- {
- write (2, file, strlen (file));
- write (2, msg, sizeof msg - 1);
- task_terminate (t);
- host_exit (1);
- }
-
- read (fd, &hdr, sizeof hdr);
- /* File must have magic ELF number. */
- if (hdr.e.e_ident[0] == 0177 && hdr.e.e_ident[1] == 'E' &&
- hdr.e.e_ident[2] == 'L' && hdr.e.e_ident[3] == 'F')
- {
- Elf32_Phdr phdrs[hdr.e.e_phnum], *ph;
- lseek (fd, hdr.e.e_phoff, SEEK_SET);
- read (fd, phdrs, sizeof phdrs);
- for (ph = phdrs; ph < &phdrs[sizeof phdrs/sizeof phdrs[0]]; ++ph)
- if (ph->p_type == PT_LOAD)
- {
- vm_address_t buf;
- vm_size_t offs = ph->p_offset & (ph->p_align - 1);
- vm_size_t bufsz = round_page (ph->p_filesz + offs);
-
- buf = (vm_address_t) mmap (0, bufsz,
- PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
-
- lseek (fd, ph->p_offset, SEEK_SET);
- read (fd, (void *)(buf + offs), ph->p_filesz);
-
- ph->p_memsz = ((ph->p_vaddr + ph->p_memsz + ph->p_align - 1)
- & ~(ph->p_align - 1));
- ph->p_vaddr &= ~(ph->p_align - 1);
- ph->p_memsz -= ph->p_vaddr;
-
- vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0);
- vm_write (t, ph->p_vaddr, buf, bufsz);
- munmap ((caddr_t) buf, bufsz);
- vm_protect (t, ph->p_vaddr, ph->p_memsz, 0,
- ((ph->p_flags & PF_R) ? VM_PROT_READ : 0) |
- ((ph->p_flags & PF_W) ? VM_PROT_WRITE : 0) |
- ((ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0));
- }
- return hdr.e.e_entry;
- }
- else
- {
- /* a.out */
- int magic = N_MAGIC (hdr.a);
- int headercruft;
- vm_address_t base = 0x10000;
- int rndamount, amount;
- vm_address_t bsspagestart, bssstart;
- char *buf;
-
- headercruft = sizeof (struct exec) * (magic == ZMAGIC);
-
- amount = headercruft + hdr.a.a_text + hdr.a.a_data;
- rndamount = round_page (amount);
- buf = mmap (0, rndamount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
- lseek (fd, sizeof hdr.a - headercruft, SEEK_SET);
- read (fd, buf, amount);
- vm_allocate (t, &base, rndamount, 0);
- vm_write (t, base, (vm_address_t) buf, rndamount);
- if (magic != OMAGIC)
- vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text),
- 0, VM_PROT_READ | VM_PROT_EXECUTE);
- munmap ((caddr_t) buf, rndamount);
-
- bssstart = base + hdr.a.a_text + hdr.a.a_data + headercruft;
- bsspagestart = round_page (bssstart);
- vm_allocate (t, &bsspagestart,
- hdr.a.a_bss - (bsspagestart - bssstart), 0);
-
- return hdr.a.a_entry;
- }
-}
-
-
void read_reply ();
void * msg_thread (void *);
-/* Callbacks for boot_script.c; see boot_script.h. */
-int
-boot_script_exec_cmd (void *hook,
- mach_port_t task, char *path, int argc,
- char **argv, char *strings, int stringlen)
-{
- char *args, *p;
- int arg_len, i;
- size_t reg_size;
- void *arg_pos;
- vm_offset_t stack_start, stack_end;
- vm_address_t startpc, str_start;
- thread_t thread;
-
- write (2, path, strlen (path));
- for (i = 1; i < argc; ++i)
- {
- int quote = !! index (argv[i], ' ') || !! index (argv[i], '\t');
- write (2, " ", 1);
- if (quote)
- write (2, "\"", 1);
- write (2, argv[i], strlen (argv[i]));
- if (quote)
- write (2, "\"", 1);
- }
- write (2, "\r\n", 2);
-
- startpc = load_image (task, path);
- arg_len = stringlen + (argc + 2) * sizeof (char *) + sizeof (integer_t);
- arg_len += 5 * sizeof (int);
- stack_end = VM_MAX_ADDRESS;
- stack_start = VM_MAX_ADDRESS - 16 * 1024 * 1024;
- vm_allocate (task, &stack_start, stack_end - stack_start, FALSE);
- arg_pos = (void *) ((stack_end - arg_len) & ~(sizeof (natural_t) - 1));
- args = mmap (0, stack_end - trunc_page ((vm_offset_t) arg_pos),
- PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
- str_start = ((vm_address_t) arg_pos
- + (argc + 2) * sizeof (char *) + sizeof (integer_t));
- p = args + ((vm_address_t) arg_pos & (vm_page_size - 1));
- *(int *) p = argc;
- p = (void *) p + sizeof (int);
- for (i = 0; i < argc; i++)
- {
- *(char **) p = argv[i] - strings + (char *) str_start;
- p = (void *) p + sizeof (char *);
- }
- *(char **) p = 0;
- p = (void *) p + sizeof (char *);
- *(char **) p = 0;
- p = (void *) p + sizeof (char *);
- memcpy (p, strings, stringlen);
- memset (args, 0, (vm_offset_t)arg_pos & (vm_page_size - 1));
- vm_write (task, trunc_page ((vm_offset_t) arg_pos), (vm_address_t) args,
- stack_end - trunc_page ((vm_offset_t) arg_pos));
- munmap ((caddr_t) args,
- stack_end - trunc_page ((vm_offset_t) arg_pos));
-
- thread_create (task, &thread);
-#ifdef i386_THREAD_STATE_COUNT
- {
- struct i386_thread_state regs;
- reg_size = i386_THREAD_STATE_COUNT;
- thread_get_state (thread, i386_THREAD_STATE,
- (thread_state_t) &regs, &reg_size);
- regs.eip = (int) startpc;
- regs.uesp = (int) arg_pos;
- thread_set_state (thread, i386_THREAD_STATE,
- (thread_state_t) &regs, reg_size);
- }
-#elif defined(ALPHA_THREAD_STATE_COUNT)
- {
- struct alpha_thread_state regs;
- reg_size = ALPHA_THREAD_STATE_COUNT;
- thread_get_state (thread, ALPHA_THREAD_STATE,
- (thread_state_t) &regs, &reg_size);
- regs.r30 = (natural_t) arg_pos;
- regs.pc = (natural_t) startpc;
- thread_set_state (thread, ALPHA_THREAD_STATE,
- (thread_state_t) &regs, reg_size);
- }
-#else
-# error needs to be ported
-#endif
-
- thread_resume (thread);
- mach_port_deallocate (mach_task_self (), thread);
- return 0;
-}
-
const char *argp_program_version = STANDARD_HURD_VERSION (boot);
static struct argp_option options[] =
diff --git a/boot/userland-boot.c b/boot/userland-boot.c
index 7b856147..583078f1 100644
--- a/boot/userland-boot.c
+++ b/boot/userland-boot.c
@@ -17,11 +17,19 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <a.out.h>
+#include <elf.h>
+#include <fcntl.h>
#include <mach.h>
+#include <mach/machine/vm_param.h> /* For VM_XXX_ADDRESS */
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include <errno.h>
#include <error.h>
+
#include "boot_script.h"
void *
@@ -115,3 +123,206 @@ boot_script_insert_task_port (struct cmd *cmd, task_t task, mach_port_t *name)
{
return boot_script_insert_right (cmd, task, name);
}
+
+char *useropen_dir;
+
+static int
+useropen (const char *name, int flags, int mode)
+{
+ if (useropen_dir)
+ {
+ static int dlen;
+ if (!dlen) dlen = strlen (useropen_dir);
+ {
+ int len = strlen (name);
+ char try[dlen + 1 + len + 1];
+ int fd;
+ memcpy (try, useropen_dir, dlen);
+ try[dlen] = '/';
+ memcpy (&try[dlen + 1], name, len + 1);
+ fd = open (try, flags, mode);
+ if (fd >= 0)
+ return fd;
+ }
+ }
+ return open (name, flags, mode);
+}
+
+static vm_address_t
+load_image (task_t t,
+ char *file)
+{
+ int fd;
+ union
+ {
+ struct exec a;
+ Elf32_Ehdr e;
+ } hdr;
+ char msg[] = ": cannot open bootstrap file\n";
+
+ fd = useropen (file, O_RDONLY, 0);
+
+ if (fd == -1)
+ {
+ write (2, file, strlen (file));
+ write (2, msg, sizeof msg - 1);
+ task_terminate (t);
+ exit (1);
+ }
+
+ read (fd, &hdr, sizeof hdr);
+ /* File must have magic ELF number. */
+ if (hdr.e.e_ident[0] == 0177 && hdr.e.e_ident[1] == 'E' &&
+ hdr.e.e_ident[2] == 'L' && hdr.e.e_ident[3] == 'F')
+ {
+ Elf32_Phdr phdrs[hdr.e.e_phnum], *ph;
+ lseek (fd, hdr.e.e_phoff, SEEK_SET);
+ read (fd, phdrs, sizeof phdrs);
+ for (ph = phdrs; ph < &phdrs[sizeof phdrs/sizeof phdrs[0]]; ++ph)
+ if (ph->p_type == PT_LOAD)
+ {
+ vm_address_t buf;
+ vm_size_t offs = ph->p_offset & (ph->p_align - 1);
+ vm_size_t bufsz = round_page (ph->p_filesz + offs);
+
+ buf = (vm_address_t) mmap (0, bufsz,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+
+ lseek (fd, ph->p_offset, SEEK_SET);
+ read (fd, (void *)(buf + offs), ph->p_filesz);
+
+ ph->p_memsz = ((ph->p_vaddr + ph->p_memsz + ph->p_align - 1)
+ & ~(ph->p_align - 1));
+ ph->p_vaddr &= ~(ph->p_align - 1);
+ ph->p_memsz -= ph->p_vaddr;
+
+ vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0);
+ vm_write (t, ph->p_vaddr, buf, bufsz);
+ munmap ((caddr_t) buf, bufsz);
+ vm_protect (t, ph->p_vaddr, ph->p_memsz, 0,
+ ((ph->p_flags & PF_R) ? VM_PROT_READ : 0) |
+ ((ph->p_flags & PF_W) ? VM_PROT_WRITE : 0) |
+ ((ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0));
+ }
+ return hdr.e.e_entry;
+ }
+ else
+ {
+ /* a.out */
+ int magic = N_MAGIC (hdr.a);
+ int headercruft;
+ vm_address_t base = 0x10000;
+ int rndamount, amount;
+ vm_address_t bsspagestart, bssstart;
+ char *buf;
+
+ headercruft = sizeof (struct exec) * (magic == ZMAGIC);
+
+ amount = headercruft + hdr.a.a_text + hdr.a.a_data;
+ rndamount = round_page (amount);
+ buf = mmap (0, rndamount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ lseek (fd, sizeof hdr.a - headercruft, SEEK_SET);
+ read (fd, buf, amount);
+ vm_allocate (t, &base, rndamount, 0);
+ vm_write (t, base, (vm_address_t) buf, rndamount);
+ if (magic != OMAGIC)
+ vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text),
+ 0, VM_PROT_READ | VM_PROT_EXECUTE);
+ munmap ((caddr_t) buf, rndamount);
+
+ bssstart = base + hdr.a.a_text + hdr.a.a_data + headercruft;
+ bsspagestart = round_page (bssstart);
+ vm_allocate (t, &bsspagestart,
+ hdr.a.a_bss - (bsspagestart - bssstart), 0);
+
+ return hdr.a.a_entry;
+ }
+}
+
+int
+boot_script_exec_cmd (void *hook,
+ mach_port_t task, char *path, int argc,
+ char **argv, char *strings, int stringlen)
+{
+ char *args, *p;
+ int arg_len, i;
+ size_t reg_size;
+ void *arg_pos;
+ vm_offset_t stack_start, stack_end;
+ vm_address_t startpc, str_start;
+ thread_t thread;
+
+ write (2, path, strlen (path));
+ for (i = 1; i < argc; ++i)
+ {
+ int quote = !! index (argv[i], ' ') || !! index (argv[i], '\t');
+ write (2, " ", 1);
+ if (quote)
+ write (2, "\"", 1);
+ write (2, argv[i], strlen (argv[i]));
+ if (quote)
+ write (2, "\"", 1);
+ }
+ write (2, "\r\n", 2);
+
+ startpc = load_image (task, path);
+ arg_len = stringlen + (argc + 2) * sizeof (char *) + sizeof (integer_t);
+ arg_len += 5 * sizeof (int);
+ stack_end = VM_MAX_ADDRESS;
+ stack_start = VM_MAX_ADDRESS - 16 * 1024 * 1024;
+ vm_allocate (task, &stack_start, stack_end - stack_start, FALSE);
+ arg_pos = (void *) ((stack_end - arg_len) & ~(sizeof (natural_t) - 1));
+ args = mmap (0, stack_end - trunc_page ((vm_offset_t) arg_pos),
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ str_start = ((vm_address_t) arg_pos
+ + (argc + 2) * sizeof (char *) + sizeof (integer_t));
+ p = args + ((vm_address_t) arg_pos & (vm_page_size - 1));
+ *(int *) p = argc;
+ p = (void *) p + sizeof (int);
+ for (i = 0; i < argc; i++)
+ {
+ *(char **) p = argv[i] - strings + (char *) str_start;
+ p = (void *) p + sizeof (char *);
+ }
+ *(char **) p = 0;
+ p = (void *) p + sizeof (char *);
+ *(char **) p = 0;
+ p = (void *) p + sizeof (char *);
+ memcpy (p, strings, stringlen);
+ memset (args, 0, (vm_offset_t)arg_pos & (vm_page_size - 1));
+ vm_write (task, trunc_page ((vm_offset_t) arg_pos), (vm_address_t) args,
+ stack_end - trunc_page ((vm_offset_t) arg_pos));
+ munmap ((caddr_t) args,
+ stack_end - trunc_page ((vm_offset_t) arg_pos));
+
+ thread_create (task, &thread);
+#ifdef i386_THREAD_STATE_COUNT
+ {
+ struct i386_thread_state regs;
+ reg_size = i386_THREAD_STATE_COUNT;
+ thread_get_state (thread, i386_THREAD_STATE,
+ (thread_state_t) &regs, &reg_size);
+ regs.eip = (int) startpc;
+ regs.uesp = (int) arg_pos;
+ thread_set_state (thread, i386_THREAD_STATE,
+ (thread_state_t) &regs, reg_size);
+ }
+#elif defined(ALPHA_THREAD_STATE_COUNT)
+ {
+ struct alpha_thread_state regs;
+ reg_size = ALPHA_THREAD_STATE_COUNT;
+ thread_get_state (thread, ALPHA_THREAD_STATE,
+ (thread_state_t) &regs, &reg_size);
+ regs.r30 = (natural_t) arg_pos;
+ regs.pc = (natural_t) startpc;
+ thread_set_state (thread, ALPHA_THREAD_STATE,
+ (thread_state_t) &regs, reg_size);
+ }
+#else
+# error needs to be ported
+#endif
+
+ thread_resume (thread);
+ mach_port_deallocate (mach_task_self (), thread);
+ return 0;
+}