Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3001 → Rev 3004

/branches/dynload/kernel/generic/include/proc/task.h
120,7 → 120,7
extern void task_destroy(task_t *t);
extern task_t *task_create_from_as(as_t *as, uintptr_t entry_addr, char *name);
extern int task_parse_initial(void *program_addr, char *name, task_t **task);
extern task_t *task_create_from_loader(char *name);
extern int task_create_from_loader(char *name, task_t **task);
extern void task_ready(task_t *t);
extern task_t *task_find_by_id(task_id_t id);
extern int task_kill(task_id_t id);
139,7 → 139,7
#endif
 
extern unative_t sys_task_get_id(task_id_t *uspace_task_id);
extern unative_t sys_task_spawn(task_id_t *uspace_task_id);
extern unative_t sys_task_spawn(int *uspace_phone_id);
 
#endif
 
/branches/dynload/kernel/generic/src/proc/task.c
50,6 → 50,7
#include <adt/btree.h>
#include <adt/list.h>
#include <ipc/ipc.h>
#include <ipc/ipcrsc.h>
#include <security/cap.h>
#include <memstr.h>
#include <print.h>
323,27 → 324,33
 
/** Create a task from the program loader image.
*
* @param program_addr Address of program executable image.
* @param name Program name.
* @param t Buffer for storing pointer to the newly created task.
*
* @return Task of the running program or NULL on error.
*/
task_t *task_create_from_loader(char *name)
int task_create_from_loader(char *name, task_t **t)
{
as_t *as;
unsigned int rc;
void *loader;
 
as = as_create(0);
ASSERT(as);
 
loader = program_loader;
if (!loader) return ENOENT;
 
rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER);
if (rc != EE_OK) {
as_destroy(as);
return NULL;
return ENOENT;
}
 
return task_create_from_as(
*t = task_create_from_as(
as, ((elf_header_t *) program_loader)->e_entry, name);
 
return EOK;
}
 
/** Make task ready.
379,33 → 386,44
 
/** Syscall for creating a new task from userspace.
*
* Creates a new task from the program loader image and stores its
* task id into the provided buffer.
* Creates a new task from the program loader image, connects a phone
* to it and stores the phone id into the provided buffer.
*
* @param uspace_task_id Userspace address of 8-byte buffer where to store
* current task ID.
* @param uspace_phone_id Userspace address where to store the phone id.
*
* @return 0 on success or an error code from @ref errno.h.
*/
unative_t sys_task_spawn(task_id_t *uspace_task_id)
unative_t sys_task_spawn(int *uspace_phone_id)
{
task_t *t;
task_id_t fake_id;
int fake_id;
int rc;
int phone_id;
 
fake_id = 0;
 
/* Before we even try creating the task, see if we can write the id */
rc = (unative_t) copy_to_uspace(uspace_task_id, &fake_id,
rc = (unative_t) copy_to_uspace(uspace_phone_id, &fake_id,
sizeof(fake_id));
if (rc != 0)
return rc;
 
t = task_create_from_loader("loader");
phone_id = phone_alloc();
if (phone_id < 0)
return ELIMIT;
 
rc = task_create_from_loader("loader", &t);
if (rc != 0)
return rc;
 
phone_connect(phone_id, &t->answerbox);
 
/* No need to aquire lock before task_ready() */
rc = (unative_t) copy_to_uspace(uspace_task_id, &t->taskid,
sizeof(t->taskid));
rc = (unative_t) copy_to_uspace(uspace_phone_id, &phone_id,
sizeof(phone_id));
if (rc != 0) {
/* Ooops */
ipc_phone_hangup(&TASK->phones[phone_id]);
task_kill(t->taskid);
return rc;
}
/branches/dynload/uspace/app/dltest/arch/ia32/_link.ld.in
2,11 → 2,16
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} :interp
 
. = 0x1000;
 
.init ALIGN(0x1000) : SUBALIGN(0x1000) {
33,9 → 38,6
*(.plt);
} :text
 
.interp : {
*(.interp);
} :text
 
.dynamic ALIGN(0x1000) : {
*(.dynamic);
/branches/dynload/uspace/app/iloader/interp.s
0,0 → 1,7
#
# Provide a string to be included in a special DT_INTERP header, even though
# this is a statically-linked executable. This will mark te binary as
# the program loader.
#
.section .interp , ""
.string "kernel"
/branches/dynload/uspace/app/iloader/include/elf_load.h
48,8 → 48,11
/** Entry point */
entry_point_t entry;
 
/** ELF interpreter name or NULL if statically-linked */
char *interp;
 
/** Pointer to the dynamic section */
void *dynamic;
void *dynamic;
} elf_info_t;
 
/**
/branches/dynload/uspace/app/iloader/main.c
35,9 → 35,12
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <ipc/ipc.h>
#include <errno.h>
#include <as.h>
 
#include <elf.h>
46,21 → 49,54
 
#define RTLD_BIAS 0x80000
 
int main(int argc, char *argv[])
static char *pathname = NULL;
 
void iloader_set_pathname(ipc_callid_t rid, ipc_call_t *request)
{
// ipc_callid_t callid;
size_t len;
char *name_buf;
 
/* printf("iloader_set_pathname\n");
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
*/
len = IPC_GET_ARG2(*request);
printf("alloc %d bytes\n", len+1);
 
name_buf = malloc(len + 1);
if (!name_buf) {
// ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
 
printf("write_finalize\n");
ipc_data_write_finalize(rid, name_buf, len);
// ipc_answer_0(rid, EOK);
 
if (pathname != NULL) {
free(pathname);
pathname = NULL;
}
 
pathname = name_buf;
}
 
int iloader_run(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
pcb_t *pcb;
 
elf_info_t prog_info;
elf_info_t interp_info;
char *file_name;
pcb_t *pcb;
int rc;
 
printf("This is loader\n");
getchar();
printf("Load program '%s'\n", pathname);
 
printf("Load program\n");
 
rc = elf_load_file("/dltest", 0, &prog_info);
// rc = elf_load_file("/tetris", 0, &prog_info);
rc = elf_load_file(pathname, 0, &prog_info);
if (rc < 0) {
printf("failed to load program\n");
return 1;
69,14 → 105,15
printf("Create PCB\n");
if (elf_create_pcb(&prog_info) < 0) return 1;
 
// elf_run(&prog_info);
if (prog_info.interp == NULL) {
/* Statically linked program */
printf("Run statically linked program\n");
elf_run(&prog_info);
return 0;
}
 
// getchar();
 
printf("Load dynamic linker\n");
file_name = "/rtld.so";
printf("open and read '%s'...\n", file_name);
rc = elf_load_file(file_name, RTLD_BIAS, &interp_info);
printf("Load dynamic linker '%s'\n", prog_info.interp);
rc = elf_load_file("/rtld.so", RTLD_BIAS, &interp_info);
if (rc < 0) {
printf("failed to load dynamic linker\n");
return 1;
83,7 → 120,7
}
 
/*
* Provide rtld with some useful data
* Provide dynamic linker with some useful data
*/
pcb = (pcb_t *)PCB_ADDRESS;
pcb->rtld_dynamic = interp_info.dynamic;
92,6 → 129,35
printf("run dynamic linker\n");
elf_run(&interp_info);
 
return 0;
}
 
int main(int argc, char *argv[])
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
int len;
 
while (1) {
callid = ipc_wait_for_call(&call);
printf("received call, method=%d\n", IPC_GET_METHOD(call));
switch (IPC_GET_METHOD(call)) {
case IPC_M_DATA_WRITE:
iloader_set_pathname(callid, &call);
iloader_run(callid, &call);
exit(0);
continue;
default:
retval = ENOENT;
break;
}
if ((callid & IPC_CALLID_NOTIFICATION) == 0) {
printf("responding EINVAL to method %d\n", IPC_GET_METHOD(call));
ipc_answer_0(callid, EINVAL);
}
}
 
/* not reached */
return 0;
}
/branches/dynload/uspace/app/iloader/elf_load.c
181,6 → 181,8
elf->bias = 0;
 
printf("Bias set to 0x%x\n", elf->bias);
elf->info->interp = NULL;
elf->info->dynamic = NULL;
 
printf("parse segments\n");
 
201,7 → 203,6
}
 
printf("parse sections\n");
elf->info->dynamic = NULL;
 
/* Inspect all section headers and proccess them. */
for (i = 0; i < header->e_shnum; i++) {
256,8 → 257,11
case PT_LOAD:
return load_segment(elf, entry);
break;
case PT_INTERP:
/* Assume silently interp == "/rtld.so" */
elf->info->interp = "/rtld.so";
break;
case PT_DYNAMIC:
case PT_INTERP:
case PT_SHLIB:
case PT_NOTE:
case PT_LOPROC:
/branches/dynload/uspace/app/iloader/Makefile
40,7 → 40,7
 
CFLAGS += -Iinclude -D__32_BITS__
 
LIBS = $(LIBC_PREFIX)/libc.a
LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a
DEFS += -DRELEASE=\"$(RELEASE)\"
 
ifdef REVISION
57,7 → 57,8
OUTPUT = iloader
SOURCES = \
main.c \
elf_load.c
elf_load.c \
interp.s
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
78,7 → 79,7
 
$(OUTPUT): $(OBJECTS) $(LIBS) arch/$(ARCH)/_link.ld
# $(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
$(LD) -T arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
/branches/dynload/uspace/app/iloader/arch/ia32/_link.ld.in
1,16 → 1,21
/*
* The only difference from _link.ld.in for regular statically-linked apps
* is the base address.
* The difference from _link.ld.in for regular statically-linked apps
* is the base address and the special interp section.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
text PT_LOAD FLAGS(5);
interp PT_INTERP;
text PT_LOAD FILEHDR PHDRS FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} : interp
 
. = 0x70001000;
 
.init ALIGN(0x1000) : SUBALIGN(0x1000) {
/branches/dynload/uspace/app/iramfs/data.h
49,6 → 49,10
extern const size_t libc_size;
extern const char libc_filename[];
 
extern const uint8_t tetris[];
extern const size_t tetris_size;
extern const char tetris_filename[];
 
#endif
 
/** @}
/branches/dynload/uspace/app/iramfs/main.c
89,6 → 89,7
if (write_file(rtld, rtld_size, rtld_filename) < 0) return 1;
if (write_file(dltest, dltest_size, dltest_filename) < 0) return 1;
if (write_file(libc, libc_size, libc_filename) < 0) return 1;
if (write_file(tetris, tetris_size, tetris_filename) < 0) return 1;
 
printf("done\n");
getchar();
/branches/dynload/uspace/app/iramfs/Makefile
87,7 → 87,8
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
 
data.c: ../../lib/rtld/rtld.so ../dltest/dltest ../../lib/libc-shared/libc.so.0
data.c: ../../lib/rtld/rtld.so ../dltest/dltest ../../lib/libc-shared/libc.so.0 ../tetris/tetris
../../../tools/bin2c.py ../../lib/rtld/rtld.so rtld.so rtld >$@
../../../tools/bin2c.py ../dltest/dltest dltest dltest >>$@
../../../tools/bin2c.py ../../lib/libc-shared/libc.so.0 libc.so.0 libc >>$@
../../../tools/bin2c.py ../tetris/tetris tetris tetris >>$@
/branches/dynload/uspace/app/cli/cli.c
0,0 → 1,93
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup cli cli
* @brief Trivial command-line interface for running programs.
* @{
*/
/**
* @file
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <task.h>
 
#define LINE_BUFFER_SIZE 128
static char line_buffer[LINE_BUFFER_SIZE];
 
void read_line(char *buffer, int n)
{
char c;
int chars;
 
printf("> ");
 
chars = 0;
while (chars < n - 1) {
c = getchar();
if (c == '\n') break;
if (c == '\b') {
if (chars > 0) {
putchar('\b');
--chars;
}
continue;
}
putchar(c);
buffer[chars++] = c;
}
 
putchar('\n');
buffer[chars] = '\0';
}
 
 
int main(int argc, char *argv[])
{
printf("This is CLI\n");
 
while (1) {
read_line(line_buffer, LINE_BUFFER_SIZE);
printf("'%s'\n", line_buffer);
if (strcmp(line_buffer, "exit") == 0)
break;
printf("spawn task\n");
if (line_buffer[0] != '\0')
task_spawn(line_buffer, NULL);
}
 
printf("Bye\n");
return 0;
}
 
/** @}
*/
 
/branches/dynload/uspace/app/cli/Makefile
0,0 → 1,86
#
# Copyright (c) 2005 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
include ../../Makefile.config
 
## Setup toolchain
#
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=\"$(RELEASE)\"
 
ifdef REVISION
DEFS += "-DREVISION=\"$(REVISION)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
## Sources
#
 
OUTPUT = cli
SOURCES = \
cli.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dynload/uspace/lib/rtld/arch/ppc32/src/runtime.c
42,7 → 42,7
{
asm volatile (
"mr %%r3, %0\n"
"li %%r9, 30\n"
"li %%r9, 31\n"
"sc\n"
:
: "r" (i)
/branches/dynload/uspace/lib/rtld/arch/ppc32/src/bootstrap.c
49,7 → 49,7
{
asm volatile (
"mr %%r3, %0\n"
"li %%r9, 30\n"
"li %%r9, 31\n"
"sc\n"
:
: "r" (i)
/branches/dynload/uspace/lib/rtld/arch/ia32/src/runtime.c
42,7 → 42,7
{
unsigned dummy;
asm volatile (
"movl $30, %%eax;"
"movl $31, %%eax;"
"int $0x30"
: "=d" (dummy) /* output - %edx clobbered */
: "d" (i) /* input */
/branches/dynload/uspace/lib/rtld/arch/ia32/src/bootstrap.c
46,7 → 46,7
{
unsigned dummy;
asm volatile (
"movl $30, %%eax;"
"movl $31, %%eax;"
"int $0x30"
: "=d" (dummy) /* output - %edx clobbered */
: "d" (i) /* input */
/branches/dynload/uspace/lib/libc/include/task.h
40,6 → 40,7
typedef uint64_t task_id_t;
 
extern task_id_t task_get_id(void);
task_id_t task_spawn(const char *path, const char *argv[]);
 
#endif
 
/branches/dynload/uspace/lib/libc/generic/task.c
33,7 → 33,9
*/
 
#include <task.h>
#include <libc.h>
#include <ipc/ipc.h>
#include <async.h>
#include <errno.h>
 
task_id_t task_get_id(void)
{
44,5 → 46,50
return task_id;
}
 
static int task_spawn_loader(void)
{
int phone_id, rc;
 
rc = __SYSCALL1(SYS_TASK_SPAWN, (sysarg_t) &phone_id);
if (rc != 0)
return rc;
 
return phone_id;
}
#include <stdio.h>
#include <unistd.h>
task_id_t task_spawn(const char *path, const char *argv[])
{
int phone_id;
ipc_call_t answer;
aid_t req;
int rc;
phone_id = task_spawn_loader();
if (phone_id < 0) return 0;
printf("phone_id:%d\n", phone_id);
 
// getchar();
 
// req = async_send_0(phone_id, 1024, &answer);
rc = ipc_data_write_start(phone_id, (void *)path, strlen(path));
printf("->%d\n", rc);
if (rc != EOK) {
// async_wait_for(req, NULL);
return 1;
}
// async_wait_for(req, &rc);
 
if (rc != EOK) return 0;
// rc = async_req_0_0(phone_id, 1025);
// printf("->%d\n", rc);
// if (rc != EOK) return 0;
 
// ipc_hangup(phone_id);
 
return 1;
}
 
/** @}
*/
/branches/dynload/uspace/Makefile
53,6 → 53,7
app/tester \
app/dltest \
app/iramfs \
app/cli \
app/klog \
app/init
 
/branches/dynload/boot/arch/ia32/grub/menu.lst
15,7 → 15,8
# module /boot/fat
module /boot/devmap
# module /boot/tetris
# module /boot/tester
module /boot/tester
module /boot/iramfs
module /boot/iloader
module /boot/cli
module /boot/klog
/branches/dynload/boot/arch/ia32/Makefile.inc
41,6 → 41,7
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/iramfs/iramfs \
$(USPACEDIR)/app/iloader/iloader \
$(USPACEDIR)/app/cli/cli \
$(USPACEDIR)/app/klog/klog
 
build: $(BASE)/image.iso