summaryrefslogtreecommitdiff
path: root/boot/boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/boot.c')
-rw-r--r--boot/boot.c186
1 files changed, 116 insertions, 70 deletions
diff --git a/boot/boot.c b/boot/boot.c
index 6ed9f86a..869da3e5 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -32,6 +32,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <cthreads.h>
#include <varargs.h>
#include <fcntlbits.h>
+#include <elf.h>
#include "notify_S.h"
#include "exec_S.h"
@@ -56,7 +57,7 @@ auth_t authserver;
spin_lock_t queuelock = SPIN_LOCK_INITIALIZER;
-mach_port_t php_child_name, psmdp_child_name;
+mach_port_t php_child_name, psmdp_child_name, taskname;
task_t child_task;
mach_port_t bootport;
@@ -251,14 +252,13 @@ load_image (task_t t,
char *file)
{
int fd;
- struct exec x;
- char *buf;
- int headercruft;
- vm_address_t base = 0x10000;
- int rndamount, amount;
- vm_address_t bsspagestart, bssstart;
+ union
+ {
+ struct exec a;
+ Elf32_Ehdr e;
+ } hdr;
char msg[] = "cannot open bootstrap file";
- int magic;
+
fd = open (file, 0, 0);
@@ -269,28 +269,63 @@ load_image (task_t t,
uxexit (1);
}
- read (fd, &x, sizeof (struct exec));
- magic = N_MAGIC (x);
-
- headercruft = sizeof (struct exec) * (magic == ZMAGIC);
-
- amount = headercruft + x.a_text + x.a_data;
- rndamount = round_page (amount);
- vm_allocate (mach_task_self (), (u_int *)&buf, rndamount, 1);
- lseek (fd, -headercruft, 1);
- read (fd, buf, amount);
- vm_allocate (t, &base, rndamount, 0);
- vm_write (t, base, (u_int) buf, rndamount);
- if (magic != OMAGIC)
- vm_protect (t, base, trunc_page (headercruft + x.a_text),
- 0, VM_PROT_READ | VM_PROT_EXECUTE);
- vm_deallocate (mach_task_self (), (u_int)buf, rndamount);
-
- bssstart = base + x.a_text + x.a_data + headercruft;
- bsspagestart = round_page (bssstart);
- vm_allocate (t, &bsspagestart, x.a_bss - (bsspagestart - bssstart), 0);
+ read (fd, &hdr, sizeof hdr);
+ if (*(Elf32_Word *) hdr.e.e_ident == *(Elf32_Word *) "\177ELF")
+ {
+ 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 bufsz = round_page (ph->p_filesz);
+ vm_allocate (mach_task_self (), &buf, bufsz, 1);
+ lseek (fd, ph->p_offset, SEEK_SET);
+ read (fd, buf + (ph->p_offset & (ph->p_align - 1)), ph->p_filesz);
+ ph->p_vaddr &= ~(ph->p_align - 1);
+ ph->p_memsz += ph->p_align - 1;
+ ph->p_memsz &= ~(ph->p_align - 1);
+ vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0);
+ vm_write (t, ph->p_vaddr, (vm_address_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);
- return x.a_entry;
+ amount = headercruft + hdr.a.a_text + hdr.a.a_data;
+ rndamount = round_page (amount);
+ vm_allocate (mach_task_self (), (u_int *)&buf, rndamount, 1);
+ lseek (fd, sizeof hdr.a - headercruft, SEEK_SET);
+ read (fd, buf, amount);
+ vm_allocate (t, &base, rndamount, 0);
+ vm_write (t, base, (u_int) buf, rndamount);
+ if (magic != OMAGIC)
+ vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text),
+ 0, VM_PROT_READ | VM_PROT_EXECUTE);
+ vm_deallocate (mach_task_self (), (u_int)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;
+ }
}
@@ -300,12 +335,13 @@ void msg_thread ();
int
main (int argc, char **argv, char **envp)
{
- task_t newtask;
thread_t newthread;
mach_port_t foo;
- vm_address_t startpc;
- char usagemsg[] = "Usage: boot [-qsdn] first-task [disk]";
- char *bootfile;
+ vm_address_t startpc[argc];
+ char usagemsg[] = "Usage: boot [-qsdn] servers... disk";
+ char **bootfiles;
+ int nfiles, i;
+ task_t newtasks[argc];
char c;
struct sigvec vec = { read_reply, 0, 0};
char *newargs;
@@ -313,10 +349,7 @@ main (int argc, char **argv, char **envp)
privileged_host_port = task_by_pid (-1);
master_device_port = task_by_pid (-2);
- if (argc < 2
- || argc > 4
- || (argv[1][0] == '-' && argc < 3)
- || (argv[1][0] != '-' && argc > 3))
+ if (argc < 2 || (argv[1][0] == '-' && argc < 3))
{
write (2, usagemsg, sizeof usagemsg);
uxexit (1);
@@ -325,17 +358,17 @@ main (int argc, char **argv, char **envp)
if (argv[1][0] != '-')
{
bootstrap_args = "-x";
- if (argc == 3)
- bootdevice = argv[2];
- bootfile = argv[1];
+ bootfiles = &argv[1];
}
else
{
bootstrap_args = argv[1];
- bootfile = argv[2];
- if (argc == 4)
- bootdevice = argv[3];
+ bootfiles = &argv[2];
}
+ nfiles = 0;
+ while (bootfiles[nfiles])
+ ++nfiles;
+ bootdevice = bootfiles[nfiles-- - 1];
newargs = malloc (strlen (bootstrap_args) + 2);
strcpy (newargs, bootstrap_args);
@@ -349,11 +382,14 @@ main (int argc, char **argv, char **envp)
else
boot_like_hurd = 1;
- task_create (mach_task_self (), 0, &newtask);
-
- startpc = load_image (newtask, bootfile);
+ for (i = 0; i < nfiles; ++i)
+ {
+ task_create (mach_task_self (), 0, &newtasks[i]);
+ task_suspend (newtasks[i]);
+ startpc[i] = load_image (newtasks[i], bootfiles[i]);
+ }
- fsname = bootfile;
+ fsname = bootfiles[0];
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
&receive_set);
@@ -380,7 +416,7 @@ main (int argc, char **argv, char **envp)
mach_port_insert_right (mach_task_self (), bootport, bootport,
MACH_MSG_TYPE_MAKE_SEND);
- task_set_bootstrap_port (newtask, bootport);
+ task_set_bootstrap_port (newtasks[0], bootport);
mach_port_deallocate (mach_task_self (), bootport);
#if 0
@@ -393,19 +429,23 @@ main (int argc, char **argv, char **envp)
}
else
/* Remove inherited port. The kernel gives none. */
- task_set_bootstrap_port (newtask, MACH_PORT_NULL);
+ task_set_bootstrap_port (newtasks[0], MACH_PORT_NULL);
- child_task = newtask;
+ child_task = newtasks[0];
if (boot_like_kernel || boot_like_hurd)
{
php_child_name = 100;
psmdp_child_name = 101;
- mach_port_insert_right (newtask, php_child_name, privileged_host_port,
+ mach_port_insert_right (newtasks[0], php_child_name,
+ privileged_host_port,
MACH_MSG_TYPE_COPY_SEND);
- mach_port_insert_right (newtask, psmdp_child_name,
+ mach_port_insert_right (newtasks[0], psmdp_child_name,
pseudo_master_device_port,
MACH_MSG_TYPE_MAKE_SEND);
+ taskname = 102;
+ mach_port_insert_right (newtasks[0], taskname, newtasks[1],
+ MACH_MSG_TYPE_COPY_SEND);
}
foo = 1;
@@ -415,32 +455,38 @@ main (int argc, char **argv, char **envp)
sigvec (SIGMSG, &vec, 0);
sigvec (SIGEMSG, &vec, 0);
- thread_create (newtask, &newthread);
-
- if (boot_like_hurd)
- __mach_setup_thread (newtask, newthread, (char *)startpc, &fs_stack_base,
- &fs_stack_size);
- else if (boot_like_kernel)
+ for (i = 0; i < nfiles; ++i)
{
- char hp[20], mdp[20];
- sprintf (hp, "%d", (int) php_child_name);
- sprintf (mdp, "%d", (int) psmdp_child_name);
- set_mach_stack_args (newtask, newthread, (void *) startpc,
- "[BOOTSTRAP fs]", bootstrap_args,
- hp, mdp, bootdevice, 0);
+ thread_create (newtasks[i], &newthread);
+
+ if (boot_like_hurd)
+ __mach_setup_thread (newtasks[0], newthread, (char *)startpc[i],
+ i?0:&fs_stack_base, i?0:&fs_stack_size);
+ else if (boot_like_kernel)
+ {
+ char hp[20], mdp[20], tn[20];
+ sprintf (hp, "%d", (int) php_child_name);
+ sprintf (mdp, "%d", (int) psmdp_child_name);
+ sprintf (tn, "%d", (int) taskname);
+ set_mach_stack_args (newtasks[i], newthread, (void *) startpc[i],
+ "[BOOTSTRAP fs]", bootstrap_args,
+ hp, mdp, tn, bootdevice, 0);
+ }
+ else
+ set_mach_stack_args (newtasks[i], newthread, (char *)startpc[i],
+ "[BOOTSTRAP fs]", bootstrap_args,
+ bootdevice, "/", 0);
+
+ thread_resume (newthread);
}
- else
- set_mach_stack_args (newtask, newthread, (char *)startpc,
- "[BOOTSTRAP fs]", bootstrap_args,
- bootdevice, "/", 0);
if (index (bootstrap_args, 'd'))
{
write (1, "pausing\n", 8);
read (0, &c, 1);
}
- thread_resume (newthread);
-
+ task_resume(newtasks[0]);
+
cthread_detach (cthread_fork ((cthread_fn_t) msg_thread,
(any_t) 0));