/branches/tracing/uspace/srv/kbd/Makefile |
---|
83,7 → 83,7 |
.PHONY: all clean depend disasm links |
all: links $(OUTPUT) disasm |
all: links $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
100,9 → 100,11 |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/ns/Makefile |
---|
46,7 → 46,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
59,9 → 59,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/console/Makefile |
---|
59,7 → 59,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
72,9 → 72,11 |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/rd/rd.c |
---|
81,46 → 81,24 |
ipc_call_t call; |
int retval; |
void *fs_va = NULL; |
ipcarg_t offset; |
off_t offset; |
size_t block_size; |
size_t maxblock_size; |
/* |
* We allocate VA for communication per connection. |
* This allows us to potentionally have more clients and work |
* concurrently. |
*/ |
fs_va = as_get_mappable_page(ALIGN_UP(BLOCK_SIZE, PAGE_SIZE)); |
if (!fs_va) { |
/* |
* Hang up the phone if we cannot proceed any further. |
* This is the answer to the call that opened the connection. |
*/ |
ipc_answer_0(iid, EHANGUP); |
return; |
} else { |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
* Return supported block size as ARG1. |
*/ |
ipc_answer_1(iid, EOK, BLOCK_SIZE); |
} |
ipc_answer_0(iid, EOK); |
/* |
* Now we wait for the client to send us its communication as_area. |
*/ |
size_t size; |
int flags; |
if (ipc_share_out_receive(&callid, &size, &flags)) { |
if (size >= BLOCK_SIZE) { |
/* |
* The client sends an as_area that can absorb the whole |
* block. |
*/ |
if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) { |
fs_va = as_get_mappable_page(maxblock_size); |
if (fs_va) { |
(void) ipc_share_out_finalize(callid, fs_va); |
} else { |
/* |
* The client offered as_area too small. |
* Close the connection. |
*/ |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
146,8 → 124,16 |
return; |
case RD_READ_BLOCK: |
offset = IPC_GET_ARG1(call); |
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) { |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Reading past the end of the device. |
*/ |
retval = ELIMIT; |
154,14 → 140,22 |
break; |
} |
futex_down(&rd_futex); |
memcpy(fs_va, rd_addr + offset * BLOCK_SIZE, BLOCK_SIZE); |
memcpy(fs_va, rd_addr + offset * block_size, block_size); |
futex_up(&rd_futex); |
retval = EOK; |
break; |
case RD_WRITE_BLOCK: |
offset = IPC_GET_ARG1(call); |
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) { |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Writing past the end of the device. |
*/ |
retval = ELIMIT; |
168,7 → 162,7 |
break; |
} |
futex_up(&rd_futex); |
memcpy(rd_addr + offset * BLOCK_SIZE, fs_va, BLOCK_SIZE); |
memcpy(rd_addr + offset * block_size, fs_va, block_size); |
futex_down(&rd_futex); |
retval = EOK; |
break; |
/branches/tracing/uspace/srv/rd/rd.h |
---|
43,8 → 43,6 |
#ifndef RD_RD_H_ |
#define RD_RD_H_ |
#define BLOCK_SIZE 1024 /**< Working block size */ |
#define RD_BASE 1024 |
#define RD_READ_BLOCK (RD_BASE + 1) /**< Method for reading block. */ |
#define RD_WRITE_BLOCK (RD_BASE + 2) /**< Method for writing block. */ |
/branches/tracing/uspace/srv/rd/Makefile |
---|
46,7 → 46,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
59,9 → 59,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/loader/elf_load.c |
---|
0,0 → 1,479 |
/* |
* Copyright (c) 2006 Sergey Bondari |
* Copyright (c) 2006 Jakub Jermar |
* 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 generic |
* @{ |
*/ |
/** |
* @file |
* @brief Userspace ELF loader. |
* |
* This module allows loading ELF binaries (both executables and |
* shared objects) from VFS. The current implementation allocates |
* anonymous memory, fills it with segment data and then adjusts |
* the memory areas' flags to the final value. In the future, |
* the segments will be mapped directly from the file. |
*/ |
#include <stdio.h> |
#include <sys/types.h> |
#include <align.h> |
#include <assert.h> |
#include <as.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <smc.h> |
#include <loader/pcb.h> |
#include "elf.h" |
#include "elf_load.h" |
#include "arch.h" |
static char *error_codes[] = { |
"no error", |
"invalid image", |
"address space error", |
"incompatible image", |
"unsupported image type", |
"irrecoverable error" |
}; |
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias); |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry); |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry); |
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry); |
/** Read until the buffer is read in its entirety. */ |
static int my_read(int fd, char *buf, size_t len) |
{ |
int cnt = 0; |
do { |
buf += cnt; |
len -= cnt; |
cnt = read(fd, buf, len); |
} while ((cnt > 0) && ((len - cnt) > 0)); |
return cnt; |
} |
/** Load ELF binary from a file. |
* |
* Load an ELF binary from the specified file. If the file is |
* an executable program, it is loaded unbiased. If it is a shared |
* object, it is loaded with the bias @a so_bias. Some information |
* extracted from the binary is stored in a elf_info_t structure |
* pointed to by @a info. |
* |
* @param file_name Path to the ELF file. |
* @param so_bias Bias to use if the file is a shared object. |
* @param info Pointer to a structure for storing information |
* extracted from the binary. |
* |
* @return EOK on success or negative error code. |
*/ |
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info) |
{ |
elf_ld_t elf; |
int fd; |
int rc; |
// printf("open and read '%s'...\n", file_name); |
fd = open(file_name, O_RDONLY); |
if (fd < 0) { |
printf("failed opening file\n"); |
return -1; |
} |
elf.fd = fd; |
elf.info = info; |
rc = elf_load(&elf, so_bias); |
close(fd); |
return rc; |
} |
/** Run an ELF executable. |
* |
* Transfers control to the entry point of an ELF executable loaded |
* earlier with elf_load_file(). This function does not return. |
* |
* @param info Info structure filled earlier by elf_load_file() |
*/ |
void elf_run(elf_info_t *info, pcb_t *pcb) |
{ |
program_run(info->entry, pcb); |
/* not reached */ |
} |
/** Create the program control block (PCB). |
* |
* Fills the program control block @a pcb with information from |
* @a info. |
* |
* @param info Program info structure |
* @return EOK on success or negative error code |
*/ |
void elf_create_pcb(elf_info_t *info, pcb_t *pcb) |
{ |
pcb->entry = info->entry; |
pcb->dynamic = info->dynamic; |
} |
/** Load an ELF binary. |
* |
* The @a elf structure contains the loader state, including |
* an open file, from which the binary will be loaded, |
* a pointer to the @c info structure etc. |
* |
* @param elf Pointer to loader state buffer. |
* @param so_bias Bias to use if the file is a shared object. |
* @return EE_OK on success or EE_xx error code. |
*/ |
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias) |
{ |
elf_header_t header_buf; |
elf_header_t *header = &header_buf; |
int i, rc; |
rc = my_read(elf->fd, header, sizeof(elf_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
elf->header = header; |
// printf("ELF-load:"); |
/* Identify ELF */ |
if (header->e_ident[EI_MAG0] != ELFMAG0 || |
header->e_ident[EI_MAG1] != ELFMAG1 || |
header->e_ident[EI_MAG2] != ELFMAG2 || |
header->e_ident[EI_MAG3] != ELFMAG3) { |
printf("invalid header\n"); |
return EE_INVALID; |
} |
/* Identify ELF compatibility */ |
if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING || |
header->e_machine != ELF_MACHINE || |
header->e_ident[EI_VERSION] != EV_CURRENT || |
header->e_version != EV_CURRENT || |
header->e_ident[EI_CLASS] != ELF_CLASS) { |
printf("incompatible data/version/class\n"); |
return EE_INCOMPATIBLE; |
} |
if (header->e_phentsize != sizeof(elf_segment_header_t)) { |
printf("e_phentsize:%d != %d\n", header->e_phentsize, |
sizeof(elf_segment_header_t)); |
return EE_INCOMPATIBLE; |
} |
if (header->e_shentsize != sizeof(elf_section_header_t)) { |
printf("e_shentsize:%d != %d\n", header->e_shentsize, |
sizeof(elf_section_header_t)); |
return EE_INCOMPATIBLE; |
} |
/* Check if the object type is supported. */ |
if (header->e_type != ET_EXEC && header->e_type != ET_DYN) { |
printf("Object type %d is not supported\n", header->e_type); |
return EE_UNSUPPORTED; |
} |
/* Shared objects can be loaded with a bias */ |
// printf("Object type: %d\n", header->e_type); |
if (header->e_type == ET_DYN) |
elf->bias = so_bias; |
else |
elf->bias = 0; |
// printf("Bias set to 0x%x\n", elf->bias); |
elf->info->interp = NULL; |
elf->info->dynamic = NULL; |
// printf("parse segments\n"); |
/* Walk through all segment headers and process them. */ |
for (i = 0; i < header->e_phnum; i++) { |
elf_segment_header_t segment_hdr; |
/* Seek to start of segment header */ |
lseek(elf->fd, header->e_phoff |
+ i * sizeof(elf_segment_header_t), SEEK_SET); |
rc = my_read(elf->fd, &segment_hdr, |
sizeof(elf_segment_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
rc = segment_header(elf, &segment_hdr); |
if (rc != EE_OK) |
return rc; |
} |
// printf("parse sections\n"); |
/* Inspect all section headers and proccess them. */ |
for (i = 0; i < header->e_shnum; i++) { |
elf_section_header_t section_hdr; |
/* Seek to start of section header */ |
lseek(elf->fd, header->e_shoff |
+ i * sizeof(elf_section_header_t), SEEK_SET); |
rc = my_read(elf->fd, §ion_hdr, |
sizeof(elf_section_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
rc = section_header(elf, §ion_hdr); |
if (rc != EE_OK) |
return rc; |
} |
elf->info->entry = |
(entry_point_t)((uint8_t *)header->e_entry + elf->bias); |
// printf("done\n"); |
return EE_OK; |
} |
/** Print error message according to error code. |
* |
* @param rc Return code returned by elf_load(). |
* |
* @return NULL terminated description of error. |
*/ |
char *elf_error(unsigned int rc) |
{ |
assert(rc < sizeof(error_codes) / sizeof(char *)); |
return error_codes[rc]; |
} |
/** Process segment header. |
* |
* @param entry Segment header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
switch (entry->p_type) { |
case PT_NULL: |
case PT_PHDR: |
break; |
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_SHLIB: |
case PT_NOTE: |
case PT_LOPROC: |
case PT_HIPROC: |
default: |
printf("segment p_type %d unknown\n", entry->p_type); |
return EE_UNSUPPORTED; |
break; |
} |
return EE_OK; |
} |
/** Load segment described by program header entry. |
* |
* @param elf Loader state. |
* @param entry Program header entry describing segment to be loaded. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
void *a; |
int flags = 0; |
uintptr_t bias; |
uintptr_t base; |
size_t mem_sz; |
int rc; |
// printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr, |
// entry->p_memsz); |
bias = elf->bias; |
if (entry->p_align > 1) { |
if ((entry->p_offset % entry->p_align) != |
(entry->p_vaddr % entry->p_align)) { |
printf("align check 1 failed offset%%align=%d, " |
"vaddr%%align=%d\n", |
entry->p_offset % entry->p_align, |
entry->p_vaddr % entry->p_align |
); |
return EE_INVALID; |
} |
} |
/* Final flags that will be set for the memory area */ |
if (entry->p_flags & PF_X) |
flags |= AS_AREA_EXEC; |
if (entry->p_flags & PF_W) |
flags |= AS_AREA_WRITE; |
if (entry->p_flags & PF_R) |
flags |= AS_AREA_READ; |
flags |= AS_AREA_CACHEABLE; |
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE); |
mem_sz = entry->p_memsz + (entry->p_vaddr - base); |
// printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias, |
// entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE)); |
/* |
* For the course of loading, the area needs to be readable |
* and writeable. |
*/ |
a = as_area_create((uint8_t *)base + bias, mem_sz, |
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE); |
if (a == (void *)(-1)) { |
printf("memory mapping failed\n"); |
return EE_MEMORY; |
} |
// printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n", |
// entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a); |
/* |
* Load segment data |
*/ |
// printf("seek to %d\n", entry->p_offset); |
rc = lseek(elf->fd, entry->p_offset, SEEK_SET); |
if (rc < 0) { |
printf("seek error\n"); |
return EE_INVALID; |
} |
// printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias); |
/* rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/ |
/* Long reads are not possible yet. Load segment picewise */ |
unsigned left, now; |
uint8_t *dp; |
left = entry->p_filesz; |
dp = (uint8_t *)(entry->p_vaddr + bias); |
while (left > 0) { |
now = 16384; |
if (now > left) now = left; |
// printf("read %d...", now); |
rc = my_read(elf->fd, dp, now); |
// printf("->%d\n", rc); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
left -= now; |
dp += now; |
} |
// printf("set area flags to %d\n", flags); |
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags); |
if (rc != 0) { |
printf("failed to set memory area flags\n"); |
return EE_MEMORY; |
} |
if (flags & AS_AREA_EXEC) { |
/* Enforce SMC coherence for the segment */ |
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz)) |
return EE_MEMORY; |
} |
return EE_OK; |
} |
/** Process section header. |
* |
* @param elf Loader state. |
* @param entry Segment header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry) |
{ |
switch (entry->sh_type) { |
case SHT_PROGBITS: |
if (entry->sh_flags & SHF_TLS) { |
/* .tdata */ |
} |
break; |
case SHT_NOBITS: |
if (entry->sh_flags & SHF_TLS) { |
/* .tbss */ |
} |
break; |
case SHT_DYNAMIC: |
/* Record pointer to dynamic section into info structure */ |
elf->info->dynamic = |
(void *)((uint8_t *)entry->sh_addr + elf->bias); |
printf("dynamic section found at 0x%x\n", |
(uintptr_t)elf->info->dynamic); |
break; |
default: |
break; |
} |
return EE_OK; |
} |
/** @} |
*/ |
/branches/tracing/uspace/srv/loader/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 the binary as |
# the program loader. |
# |
.section .interp , "" |
.string "kernel" |
/branches/tracing/uspace/srv/loader/include/arch.h |
---|
0,0 → 1,45 |
/* |
* 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 fs |
* @{ |
*/ |
/** @file |
* @brief |
*/ |
#ifndef LOADER_ARCH_H_ |
#define LOADER_ARCH_H_ |
void program_run(void *entry_point, void *pcb); |
#endif |
/** |
* @} |
*/ |
/branches/tracing/uspace/srv/loader/include/elf_load.h |
---|
0,0 → 1,83 |
/* |
* 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 generic |
* @{ |
*/ |
/** @file |
* @brief ELF loader structures and public functions. |
*/ |
#ifndef ELF_LOAD_H_ |
#define ELF_LOAD_H_ |
#include <arch/elf.h> |
#include <sys/types.h> |
#include <loader/pcb.h> |
#include "elf.h" |
/** |
* Some data extracted from the headers are stored here |
*/ |
typedef struct { |
/** Entry point */ |
entry_point_t entry; |
/** ELF interpreter name or NULL if statically-linked */ |
char *interp; |
/** Pointer to the dynamic section */ |
void *dynamic; |
} elf_info_t; |
/** |
* Holds information about an ELF binary being loaded. |
*/ |
typedef struct { |
/** Filedescriptor of the file from which we are loading */ |
int fd; |
/** Difference between run-time addresses and link-time addresses */ |
uintptr_t bias; |
/** A copy of the ELF file header */ |
elf_header_t *header; |
/** Store extracted info here */ |
elf_info_t *info; |
} elf_ld_t; |
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info); |
void elf_run(elf_info_t *info, pcb_t *pcb); |
void elf_create_pcb(elf_info_t *info, pcb_t *pcb); |
#endif |
/** @} |
*/ |
/branches/tracing/uspace/srv/loader/include/elf.h |
---|
0,0 → 1,344 |
/* |
* Copyright (c) 2006 Sergey Bondari |
* 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 generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef ELF_H_ |
#define ELF_H_ |
#include <arch/elf.h> |
#include <sys/types.h> |
/** |
* current ELF version |
*/ |
#define EV_CURRENT 1 |
/** |
* ELF types |
*/ |
#define ET_NONE 0 /* No type */ |
#define ET_REL 1 /* Relocatable file */ |
#define ET_EXEC 2 /* Executable */ |
#define ET_DYN 3 /* Shared object */ |
#define ET_CORE 4 /* Core */ |
#define ET_LOPROC 0xff00 /* Processor specific */ |
#define ET_HIPROC 0xffff /* Processor specific */ |
/** |
* ELF machine types |
*/ |
#define EM_NO 0 /* No machine */ |
#define EM_SPARC 2 /* SPARC */ |
#define EM_386 3 /* i386 */ |
#define EM_MIPS 8 /* MIPS RS3000 */ |
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 LE */ |
#define EM_PPC 20 /* PPC32 */ |
#define EM_PPC64 21 /* PPC64 */ |
#define EM_ARM 40 /* ARM */ |
#define EM_SPARCV9 43 /* SPARC64 */ |
#define EM_IA_64 50 /* IA-64 */ |
#define EM_X86_64 62 /* AMD64/EMT64 */ |
/** |
* ELF identification indexes |
*/ |
#define EI_MAG0 0 |
#define EI_MAG1 1 |
#define EI_MAG2 2 |
#define EI_MAG3 3 |
#define EI_CLASS 4 /* File class */ |
#define EI_DATA 5 /* Data encoding */ |
#define EI_VERSION 6 /* File version */ |
#define EI_OSABI 7 |
#define EI_ABIVERSION 8 |
#define EI_PAD 9 /* Start of padding bytes */ |
#define EI_NIDENT 16 /* ELF identification table size */ |
/** |
* ELF magic number |
*/ |
#define ELFMAG0 0x7f |
#define ELFMAG1 'E' |
#define ELFMAG2 'L' |
#define ELFMAG3 'F' |
/** |
* ELF file classes |
*/ |
#define ELFCLASSNONE 0 |
#define ELFCLASS32 1 |
#define ELFCLASS64 2 |
/** |
* ELF data encoding types |
*/ |
#define ELFDATANONE 0 |
#define ELFDATA2LSB 1 /* Least significant byte first (little endian) */ |
#define ELFDATA2MSB 2 /* Most signigicant byte first (big endian) */ |
/** |
* ELF error return codes |
*/ |
#define EE_OK 0 /* No error */ |
#define EE_INVALID 1 /* Invalid ELF image */ |
#define EE_MEMORY 2 /* Cannot allocate address space */ |
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */ |
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */ |
#define EE_IRRECOVERABLE 5 |
/** |
* ELF section types |
*/ |
#define SHT_NULL 0 |
#define SHT_PROGBITS 1 |
#define SHT_SYMTAB 2 |
#define SHT_STRTAB 3 |
#define SHT_RELA 4 |
#define SHT_HASH 5 |
#define SHT_DYNAMIC 6 |
#define SHT_NOTE 7 |
#define SHT_NOBITS 8 |
#define SHT_REL 9 |
#define SHT_SHLIB 10 |
#define SHT_DYNSYM 11 |
#define SHT_LOOS 0x60000000 |
#define SHT_HIOS 0x6fffffff |
#define SHT_LOPROC 0x70000000 |
#define SHT_HIPROC 0x7fffffff |
#define SHT_LOUSER 0x80000000 |
#define SHT_HIUSER 0xffffffff |
/** |
* ELF section flags |
*/ |
#define SHF_WRITE 0x1 |
#define SHF_ALLOC 0x2 |
#define SHF_EXECINSTR 0x4 |
#define SHF_TLS 0x400 |
#define SHF_MASKPROC 0xf0000000 |
/** |
* Symbol binding |
*/ |
#define STB_LOCAL 0 |
#define STB_GLOBAL 1 |
#define STB_WEAK 2 |
#define STB_LOPROC 13 |
#define STB_HIPROC 15 |
/** |
* Symbol types |
*/ |
#define STT_NOTYPE 0 |
#define STT_OBJECT 1 |
#define STT_FUNC 2 |
#define STT_SECTION 3 |
#define STT_FILE 4 |
#define STT_LOPROC 13 |
#define STT_HIPROC 15 |
/** |
* Program segment types |
*/ |
#define PT_NULL 0 |
#define PT_LOAD 1 |
#define PT_DYNAMIC 2 |
#define PT_INTERP 3 |
#define PT_NOTE 4 |
#define PT_SHLIB 5 |
#define PT_PHDR 6 |
#define PT_LOPROC 0x70000000 |
#define PT_HIPROC 0x7fffffff |
/** |
* Program segment attributes. |
*/ |
#define PF_X 1 |
#define PF_W 2 |
#define PF_R 4 |
/** |
* ELF data types |
* |
* These types are found to be identical in both 32-bit and 64-bit |
* ELF object file specifications. They are the only types used |
* in ELF header. |
*/ |
typedef uint64_t elf_xword; |
typedef int64_t elf_sxword; |
typedef uint32_t elf_word; |
typedef int32_t elf_sword; |
typedef uint16_t elf_half; |
/** |
* 32-bit ELF data types. |
* |
* These types are specific for 32-bit format. |
*/ |
typedef uint32_t elf32_addr; |
typedef uint32_t elf32_off; |
/** |
* 64-bit ELF data types. |
* |
* These types are specific for 64-bit format. |
*/ |
typedef uint64_t elf64_addr; |
typedef uint64_t elf64_off; |
/** ELF header */ |
struct elf32_header { |
uint8_t e_ident[EI_NIDENT]; |
elf_half e_type; |
elf_half e_machine; |
elf_word e_version; |
elf32_addr e_entry; |
elf32_off e_phoff; |
elf32_off e_shoff; |
elf_word e_flags; |
elf_half e_ehsize; |
elf_half e_phentsize; |
elf_half e_phnum; |
elf_half e_shentsize; |
elf_half e_shnum; |
elf_half e_shstrndx; |
}; |
struct elf64_header { |
uint8_t e_ident[EI_NIDENT]; |
elf_half e_type; |
elf_half e_machine; |
elf_word e_version; |
elf64_addr e_entry; |
elf64_off e_phoff; |
elf64_off e_shoff; |
elf_word e_flags; |
elf_half e_ehsize; |
elf_half e_phentsize; |
elf_half e_phnum; |
elf_half e_shentsize; |
elf_half e_shnum; |
elf_half e_shstrndx; |
}; |
/* |
* ELF segment header. |
* Segments headers are also known as program headers. |
*/ |
struct elf32_segment_header { |
elf_word p_type; |
elf32_off p_offset; |
elf32_addr p_vaddr; |
elf32_addr p_paddr; |
elf_word p_filesz; |
elf_word p_memsz; |
elf_word p_flags; |
elf_word p_align; |
}; |
struct elf64_segment_header { |
elf_word p_type; |
elf_word p_flags; |
elf64_off p_offset; |
elf64_addr p_vaddr; |
elf64_addr p_paddr; |
elf_xword p_filesz; |
elf_xword p_memsz; |
elf_xword p_align; |
}; |
/* |
* ELF section header |
*/ |
struct elf32_section_header { |
elf_word sh_name; |
elf_word sh_type; |
elf_word sh_flags; |
elf32_addr sh_addr; |
elf32_off sh_offset; |
elf_word sh_size; |
elf_word sh_link; |
elf_word sh_info; |
elf_word sh_addralign; |
elf_word sh_entsize; |
}; |
struct elf64_section_header { |
elf_word sh_name; |
elf_word sh_type; |
elf_xword sh_flags; |
elf64_addr sh_addr; |
elf64_off sh_offset; |
elf_xword sh_size; |
elf_word sh_link; |
elf_word sh_info; |
elf_xword sh_addralign; |
elf_xword sh_entsize; |
}; |
/* |
* ELF symbol table entry |
*/ |
struct elf32_symbol { |
elf_word st_name; |
elf32_addr st_value; |
elf_word st_size; |
uint8_t st_info; |
uint8_t st_other; |
elf_half st_shndx; |
}; |
struct elf64_symbol { |
elf_word st_name; |
uint8_t st_info; |
uint8_t st_other; |
elf_half st_shndx; |
elf64_addr st_value; |
elf_xword st_size; |
}; |
#ifdef __32_BITS__ |
typedef struct elf32_header elf_header_t; |
typedef struct elf32_segment_header elf_segment_header_t; |
typedef struct elf32_section_header elf_section_header_t; |
typedef struct elf32_symbol elf_symbol_t; |
#endif |
#ifdef __64_BITS__ |
typedef struct elf64_header elf_header_t; |
typedef struct elf64_segment_header elf_segment_header_t; |
typedef struct elf64_section_header elf_section_header_t; |
typedef struct elf64_symbol elf_symbol_t; |
#endif |
extern char *elf_error(unsigned int rc); |
#endif |
/** @} |
*/ |
/branches/tracing/uspace/srv/loader/main.c |
---|
0,0 → 1,332 |
/* |
* 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 loader |
* @brief Loads and runs programs from VFS. |
* @{ |
*/ |
/** |
* @file |
* @brief Loads and runs programs from VFS. |
* |
* The program loader is a special init binary. Its image is used |
* to create a new task upon a @c task_spawn syscall. The syscall |
* returns the id of a phone connected to the newly created task. |
* |
* The caller uses this phone to send the pathname and various other |
* information to the loader. This is normally done by the C library |
* and completely hidden from applications. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/loader.h> |
#include <loader/pcb.h> |
#include <errno.h> |
#include <async.h> |
#include <as.h> |
#include <elf.h> |
#include <elf_load.h> |
/** |
* Bias used for loading the dynamic linker. This will be soon replaced |
* by automatic placement. |
*/ |
#define RTLD_BIAS 0x80000 |
/** Pathname of the file that will be loaded */ |
static char *pathname = NULL; |
/** The Program control block */ |
static pcb_t pcb; |
/** Number of arguments */ |
static int argc = 0; |
/** Argument vector */ |
static char **argv = NULL; |
/** Buffer holding all arguments */ |
static char *arg_buf = NULL; |
/** Receive a call setting pathname of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t len; |
char *name_buf; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
name_buf = malloc(len + 1); |
if (!name_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, name_buf, len); |
ipc_answer_0(rid, EOK); |
if (pathname != NULL) { |
free(pathname); |
pathname = NULL; |
} |
name_buf[len] = '\0'; |
pathname = name_buf; |
} |
/** Receive a call setting arguments of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t buf_len, arg_len; |
char *p; |
int n; |
if (!ipc_data_write_receive(&callid, &buf_len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (arg_buf != NULL) { |
free(arg_buf); |
arg_buf = NULL; |
} |
if (argv != NULL) { |
free(argv); |
argv = NULL; |
} |
arg_buf = malloc(buf_len + 1); |
if (!arg_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, arg_buf, buf_len); |
ipc_answer_0(rid, EOK); |
arg_buf[buf_len] = '\0'; |
/* |
* Count number of arguments |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
arg_len = strlen(p); |
p = p + arg_len + 1; |
++n; |
} |
/* Allocate argv */ |
argv = malloc((n + 1) * sizeof(char *)); |
if (argv == NULL) { |
free(arg_buf); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* Fill argv with argument pointers |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
argv[n] = p; |
arg_len = strlen(p); |
p = p + arg_len + 1; |
++n; |
} |
argc = n; |
argv[n] = NULL; |
} |
/** Load and run the previously selected program. |
* |
* @param rid |
* @param request |
* @return 0 on success, !0 on error. |
*/ |
static int loader_run(ipc_callid_t rid, ipc_call_t *request) |
{ |
int rc; |
elf_info_t prog_info; |
elf_info_t interp_info; |
// printf("Load program '%s'\n", pathname); |
rc = elf_load_file(pathname, 0, &prog_info); |
if (rc < 0) { |
printf("failed to load program\n"); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
// printf("Create PCB\n"); |
elf_create_pcb(&prog_info, &pcb); |
pcb.argc = argc; |
pcb.argv = argv; |
if (prog_info.interp == NULL) { |
/* Statically linked program */ |
// printf("Run statically linked program\n"); |
// printf("entry point: 0x%llx\n", prog_info.entry); |
ipc_answer_0(rid, EOK); |
close_console(); |
elf_run(&prog_info, &pcb); |
return 0; |
} |
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"); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
/* |
* Provide dynamic linker with some useful data |
*/ |
pcb.rtld_dynamic = interp_info.dynamic; |
pcb.rtld_bias = RTLD_BIAS; |
printf("run dynamic linker\n"); |
printf("entry point: 0x%llx\n", interp_info.entry); |
close_console(); |
ipc_answer_0(rid, EOK); |
elf_run(&interp_info, &pcb); |
/* Not reached */ |
return 0; |
} |
/** Handle loader connection. |
* |
* Receive and carry out commands (of which the last one should be |
* to execute the loaded program). |
*/ |
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
/* Ignore parameters, the connection is already open */ |
(void)iid; (void)icall; |
while (1) { |
callid = async_get_call(&call); |
// printf("received call from phone %d, method=%d\n", |
// call.in_phone_hash, IPC_GET_METHOD(call)); |
switch (IPC_GET_METHOD(call)) { |
case LOADER_SET_PATHNAME: |
loader_set_pathname(callid, &call); |
continue; |
case LOADER_SET_ARGS: |
loader_set_args(callid, &call); |
case LOADER_RUN: |
loader_run(callid, &call); |
exit(0); |
continue; |
default: |
retval = ENOENT; |
break; |
} |
if ((callid & IPC_CALLID_NOTIFICATION) == 0 && |
IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) { |
printf("responding EINVAL to method %d\n", |
IPC_GET_METHOD(call)); |
ipc_answer_0(callid, EINVAL); |
} |
} |
} |
/** Program loader main function. |
*/ |
int main(int argc, char *argv[]) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t phone_hash; |
/* The first call only communicates the incoming phone hash */ |
callid = ipc_wait_for_call(&call); |
if (IPC_GET_METHOD(call) != LOADER_HELLO) { |
if (IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) |
ipc_answer_0(callid, EINVAL); |
return 1; |
} |
ipc_answer_0(callid, EOK); |
phone_hash = call.in_phone_hash; |
/* |
* Up until now async must not be used as it couldn't |
* handle incoming requests. (Which means e.g. printf() |
* cannot be used) |
*/ |
async_new_connection(phone_hash, 0, NULL, loader_connection); |
async_manager(); |
/* not reached */ |
return 0; |
} |
/** @} |
*/ |
/branches/tracing/uspace/srv/loader/Makefile |
---|
0,0 → 1,94 |
# |
# Copyright (c) 2005 Martin Decky |
# 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. |
# |
include ../../../version |
include ../../Makefile.config |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include arch/$(ARCH)/Makefile.inc |
CFLAGS += -Iinclude |
LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
ifdef REVISION |
DEFS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
## Sources |
# |
OUTPUT = loader |
GENERIC_SOURCES = \ |
main.c \ |
elf_load.c \ |
interp.s |
SOURCES := $(GENERIC_SOURCES) $(ARCH_SOURCES) |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(ARCH)/_link.ld Makefile.depend |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) arch/$(ARCH)/_link.ld |
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in |
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/tracing/uspace/srv/loader/arch/sparc64/_link.ld.in |
---|
0,0 → 1,59 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70004000 + SIZEOF_HEADERS; |
.init : { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
.data : { |
*(.data); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/tracing/uspace/srv/loader/arch/sparc64/sparc64.s |
---|
0,0 → 1,42 |
# |
# 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. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %o0 contains entry_point |
# %o1 contains pcb |
# |
# Jump to a program entry point |
program_run: |
# Pass pcb pointer to entry point in %o1. As it is already |
# there, no action is needed. |
call %o0 |
nop |
# fixme: use branch instead of call |
/branches/tracing/uspace/srv/loader/arch/sparc64/Makefile.inc |
---|
0,0 → 1,30 |
# |
# 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. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/sparc64.s |
/branches/tracing/uspace/srv/loader/arch/ia64/_link.ld.in |
---|
0,0 → 1,66 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x00084000 + SIZEOF_HEADERS; |
.init : { |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
*(.init); |
} : text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
.data : { |
*(.opd); |
*(.data .data.*); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(.scommon); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/tracing/uspace/srv/loader/arch/ia64/ia64.s |
---|
0,0 → 1,43 |
# |
# 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. |
# |
.text |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# in0 (r32) contains entry_point |
# in1 (r33) contains pcb |
# |
# Jump to a program entry point |
program_run: |
# Pass pcb to the entry point in r2 |
mov b6 = r32 |
mov r2 = r33 ;; |
br b6 ;; |
/branches/tracing/uspace/srv/loader/arch/ia64/Makefile.inc |
---|
0,0 → 1,31 |
# |
# 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. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ia64.s |
AFLAGS += -xexplicit |
/branches/tracing/uspace/srv/loader/arch/arm32/_link.ld.in |
---|
0,0 → 1,59 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} : interp |
. = 0x70001000; |
.init ALIGN(0x1000): SUBALIGN(0x1000) { |
*(.init); |
} : text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.opd); |
*(.data .data.*); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(.scommon); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/tracing/uspace/srv/loader/arch/arm32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# 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. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/arm32.s |
/branches/tracing/uspace/srv/loader/arch/arm32/arm32.s |
---|
0,0 → 1,39 |
# |
# 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. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# r0 contains entry_point |
# r1 contains pcb |
# |
# Jump to a program entry point |
program_run: |
# pcb is passed to the entry point in r1 (where it already is) |
mov r15, r0 |
/branches/tracing/uspace/srv/loader/arch/ppc32/_link.ld.in |
---|
0,0 → 1,57 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/tracing/uspace/srv/loader/arch/ppc32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# 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. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ppc32.s |
/branches/tracing/uspace/srv/loader/arch/ppc32/ppc32.s |
---|
0,0 → 1,40 |
# |
# 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. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %r3 contains entry_point |
# %r4 contains pcb |
# |
# Jump to a program entry point |
program_run: |
mtctr %r3 |
mr %r3, %r4 # Pass pcb to the entry point in %r3 |
bctr |
/branches/tracing/uspace/srv/loader/arch/amd64/_link.ld.in |
---|
0,0 → 1,52 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} : interp |
/* . = 0x0000700000001000;*/ |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/tracing/uspace/srv/loader/arch/amd64/Makefile.inc |
---|
0,0 → 1,30 |
# |
# 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. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/amd64.s |
/branches/tracing/uspace/srv/loader/arch/amd64/amd64.s |
---|
0,0 → 1,43 |
# |
# 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. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %rdi contains entry_point |
# %rsi contains pcb |
# |
# Jump to a program entry point |
program_run: |
# pcb must be passed in %rdi, use %rdx as a scratch register |
mov %rdi, %rdx |
mov %rsi, %rdi |
# jump to entry point |
jmp %rdx |
/branches/tracing/uspace/srv/loader/arch/mips32/_link.ld.in |
---|
0,0 → 1,66 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70004000; |
.init ALIGN(0x4000) : SUBALIGN(0x4000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data : { |
*(.data); |
*(.data.rel*); |
} :data |
.got : { |
_gp = .; |
*(.got); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.sbss : { |
*(.scommon); |
*(.sbss); |
} |
.bss : { |
*(.bss); |
*(COMMON); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/tracing/uspace/srv/loader/arch/mips32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# 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. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/mips32.s |
/branches/tracing/uspace/srv/loader/arch/mips32/mips32.s |
---|
0,0 → 1,49 |
# |
# 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. |
# |
.text |
.section .text |
.global program_run |
.set noreorder |
## void program_run(void *entry_point, void *pcb); |
# |
# $a0 (=$4) contains entry_point |
# $a1 (=$5) contains pcb |
# |
# Jump to a program entry point |
.ent program_run |
program_run: |
# tmp := entry_point |
move $25, $a0 |
# Pass pcb to the entry point in $a0 |
move $a0, $a1 |
jr $25 |
nop |
.end |
/branches/tracing/uspace/srv/loader/arch/ia32/_link.ld.in |
---|
0,0 → 1,55 |
/* |
* 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 { |
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) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/tracing/uspace/srv/loader/arch/ia32/ia32.s |
---|
0,0 → 1,49 |
# |
# 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. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# Jump to a program entry point |
program_run: |
# Use standard ia32 prologue not to confuse anybody |
push %ebp |
movl %esp, %ebp |
# %eax := entry_point |
movl 0x8(%ebp), %eax |
# %ebx := pcb |
# pcb is passed to the entry point int %ebx |
mov 0xc(%ebp), %ebx |
# Save a tiny bit of stack space |
pop %ebp |
jmp %eax |
/branches/tracing/uspace/srv/loader/arch/ia32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# 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. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ia32.s |
/branches/tracing/uspace/srv/fb/main.c |
---|
37,6 → 37,7 |
#include "fb.h" |
#include "ega.h" |
#include "msim.h" |
#include "main.h" |
#define NAME "fb" |
58,20 → 59,26 |
printf(NAME ": HelenOS Framebuffer service\n"); |
ipcarg_t phonead; |
int initialized = 0; |
bool initialized = false; |
#ifdef FB_ENABLED |
if (sysinfo_value("fb.kind") == 1) { |
if (fb_init() == 0) |
initialized = 1; |
initialized = true; |
} |
#endif |
#ifdef EGA_ENABLED |
if (!initialized && sysinfo_value("fb.kind") == 2) { |
if ((!initialized) && (sysinfo_value("fb.kind") == 2)) { |
if (ega_init() == 0) |
initialized = 1; |
initialized = true; |
} |
#endif |
#ifdef MSIM_ENABLED |
if ((!initialized) && (sysinfo_value("fb.kind") == 3)) { |
if (msim_init() == 0) |
initialized = true; |
} |
#endif |
if (!initialized) |
return -1; |
/branches/tracing/uspace/srv/fb/msim.c |
---|
0,0 → 1,227 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 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. |
*/ |
/** @defgroup msimfb MSIM text console |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <ipc/fb.h> |
#include <ipc/ipc.h> |
#include <libc.h> |
#include <errno.h> |
#include <string.h> |
#include <libc.h> |
#include <stdio.h> |
#include <ipc/fb.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <align.h> |
#include <ddi.h> |
#include "msim.h" |
#define WIDTH 80 |
#define HEIGHT 25 |
#define MAX_CONTROL 20 |
/* Allow only 1 connection */ |
static int client_connected = 0; |
static char *virt_addr; |
static void msim_putc(const char c) |
{ |
*virt_addr = c; |
} |
static void msim_puts(char *str) |
{ |
while (*str) |
*virt_addr = *(str++); |
} |
static void msim_clrscr(void) |
{ |
msim_puts("\033[2J"); |
} |
static void msim_goto(const unsigned int row, const unsigned int col) |
{ |
if ((row > HEIGHT) || (col > WIDTH)) |
return; |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1); |
msim_puts(control); |
} |
static void msim_set_style(const unsigned int mode) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%um", mode); |
msim_puts(control); |
} |
static void msim_cursor_disable(void) |
{ |
msim_puts("\033[?25l"); |
} |
static void msim_cursor_enable(void) |
{ |
msim_puts("\033[?25h"); |
} |
static void msim_scroll(int i) |
{ |
if (i > 0) { |
msim_goto(HEIGHT - 1, 0); |
while (i--) |
msim_puts("\033D"); |
} else if (i < 0) { |
msim_goto(0, 0); |
while (i++) |
msim_puts("\033M"); |
} |
} |
static void msim_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
ipc_callid_t callid; |
ipc_call_t call; |
char c; |
int lastcol = 0; |
int lastrow = 0; |
int newcol; |
int newrow; |
int fgcolor; |
int bgcolor; |
int i; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
client_connected = 1; |
ipc_answer_0(iid, EOK); |
/* Clear the terminal, set scrolling region |
to 0 - 25 lines */ |
msim_clrscr(); |
msim_goto(0, 0); |
msim_puts("\033[0;25r"); |
while (true) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
client_connected = 0; |
ipc_answer_0(callid, EOK); |
return; |
case FB_PUTCHAR: |
c = IPC_GET_ARG1(call); |
newrow = IPC_GET_ARG2(call); |
newcol = IPC_GET_ARG3(call); |
if ((lastcol != newcol) || (lastrow != newrow)) |
msim_goto(newrow, newcol); |
lastcol = newcol + 1; |
lastrow = newrow; |
msim_putc(c); |
retval = 0; |
break; |
case FB_CURSOR_GOTO: |
newrow = IPC_GET_ARG1(call); |
newcol = IPC_GET_ARG2(call); |
msim_goto(newrow, newcol); |
lastrow = newrow; |
lastcol = newcol; |
retval = 0; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, HEIGHT, WIDTH); |
continue; |
case FB_CLEAR: |
msim_clrscr(); |
retval = 0; |
break; |
case FB_SET_STYLE: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
if (fgcolor < bgcolor) |
msim_set_style(0); |
else |
msim_set_style(7); |
retval = 0; |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if ((i > HEIGHT) || (i < -HEIGHT)) { |
retval = EINVAL; |
break; |
} |
msim_scroll(i); |
msim_goto(lastrow, lastcol); |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
msim_cursor_enable(); |
else |
msim_cursor_disable(); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
ipc_answer_0(callid, retval); |
} |
} |
int msim_init(void) |
{ |
void *phys_addr = (void *) sysinfo_value("fb.address.physical"); |
virt_addr = (char *) as_get_mappable_page(1); |
physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE); |
async_set_client_connection(msim_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/tracing/uspace/srv/fb/msim.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup msimfb |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_MSIM_H_ |
#define FB_MSIM_H_ |
extern int msim_init(void); |
#endif |
/** @} |
*/ |
/branches/tracing/uspace/srv/fb/Makefile |
---|
50,7 → 50,6 |
font-8x16.c |
CFLAGS += -DFB_ENABLED |
endif |
ifeq ($(ARCH), ia32) |
SOURCES += ega.c |
CFLAGS += -DEGA_ENABLED |
60,7 → 59,8 |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(ARCH), mips32) |
CFLAGS += -DFB_INVERT_ENDIAN |
SOURCES += msim.c |
CFLAGS += -DMSIM_ENABLED -DFB_INVERT_ENDIAN |
endif |
CFLAGS += -D$(ARCH) |
70,7 → 70,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
83,9 → 83,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs.h |
---|
44,6 → 44,12 |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
typedef enum { |
TMPFS_NONE, |
TMPFS_FILE, |
TMPFS_DIRECTORY |
} tmpfs_dentry_type_t; |
typedef struct tmpfs_dentry { |
fs_index_t index; /**< TMPFS node index. */ |
link_t dh_link; /**< Dentries hash table link. */ |
50,11 → 56,7 |
struct tmpfs_dentry *sibling; |
struct tmpfs_dentry *child; |
hash_table_t names; /**< All names linking to this TMPFS node. */ |
enum { |
TMPFS_NONE, |
TMPFS_FILE, |
TMPFS_DIRECTORY |
} type; |
tmpfs_dentry_type_t type; |
unsigned lnkcnt; /**< Link count. */ |
size_t size; /**< File size if type is TMPFS_FILE. */ |
void *data; /**< File content's if type is TMPFS_FILE. */ |
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
39,6 → 39,7 |
#include "tmpfs.h" |
#include "../../vfs/vfs.h" |
#include <ipc/ipc.h> |
#include <async.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <string.h> |
50,9 → 51,7 |
#include <sys/mman.h> |
#include <byteorder.h> |
#define BLOCK_SIZE 1024 // FIXME |
#define RD_BASE 1024 // FIXME |
#define RD_READ_BLOCK (RD_BASE + 1) |
#define TMPFS_BLOCK_SIZE 1024 |
struct rdentry { |
uint8_t type; |
60,48 → 59,9 |
} __attribute__((packed)); |
static bool |
tmpfs_blockread(int phone, void *buffer, size_t *bufpos, size_t *buflen, |
size_t *pos, void *dst, size_t size) |
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen, |
off_t *pos, tmpfs_dentry_t *parent) |
{ |
size_t offset = 0; |
size_t left = size; |
while (left > 0) { |
size_t rd; |
if (*bufpos + left < *buflen) |
rd = left; |
else |
rd = *buflen - *bufpos; |
if (rd > 0) { |
memcpy(dst + offset, buffer + *bufpos, rd); |
offset += rd; |
*bufpos += rd; |
*pos += rd; |
left -= rd; |
} |
if (*bufpos == *buflen) { |
ipcarg_t retval; |
int rc = ipc_call_sync_2_1(phone, RD_READ_BLOCK, |
*pos / BLOCK_SIZE, BLOCK_SIZE, |
&retval); |
if ((rc != EOK) || (retval != EOK)) |
return false; |
*bufpos = 0; |
*buflen = BLOCK_SIZE; |
} |
} |
return true; |
} |
static bool |
tmpfs_restore_recursion(int phone, void *block, size_t *bufpos, size_t *buflen, |
size_t *pos, tmpfs_dentry_t *parent) |
{ |
struct rdentry entry; |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
110,16 → 70,16 |
tmpfs_dentry_t *node; |
uint32_t size; |
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos, &entry, |
sizeof(entry))) |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, &entry, |
sizeof(entry), TMPFS_BLOCK_SIZE)) |
return false; |
entry.len = uint32_t_le2host(entry.len); |
switch (entry.type) { |
case 0: |
case TMPFS_NONE: |
break; |
case 1: |
case TMPFS_FILE: |
fname = malloc(entry.len + 1); |
if (fname == NULL) |
return false; |
130,8 → 90,8 |
return false; |
} |
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len)) { |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
145,8 → 105,8 |
} |
free(fname); |
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos, |
&size, sizeof(size))) |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
&size, sizeof(size), TMPFS_BLOCK_SIZE)) |
return false; |
size = uint32_t_le2host(size); |
156,12 → 116,12 |
return false; |
node->size = size; |
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos, |
node->data, size)) |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
node->data, size, TMPFS_BLOCK_SIZE)) |
return false; |
break; |
case 2: |
case TMPFS_DIRECTORY: |
fname = malloc(entry.len + 1); |
if (fname == NULL) |
return false; |
172,8 → 132,8 |
return false; |
} |
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len)) { |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
195,7 → 155,7 |
default: |
return false; |
} |
} while (entry.type != 0); |
} while (entry.type != TMPFS_NONE); |
return true; |
} |
204,7 → 164,7 |
{ |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
void *block = mmap(NULL, BLOCK_SIZE, |
void *block = mmap(NULL, TMPFS_BLOCK_SIZE, |
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (block == NULL) |
214,7 → 174,7 |
DEVMAP_CONNECT_TO_DEVICE, dev); |
if (phone < 0) { |
munmap(block, BLOCK_SIZE); |
munmap(block, TMPFS_BLOCK_SIZE); |
return false; |
} |
222,12 → 182,13 |
EOK) |
goto error; |
size_t bufpos = 0; |
off_t bufpos = 0; |
size_t buflen = 0; |
size_t pos = 0; |
off_t pos = 0; |
char tag[6]; |
if (!tmpfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5)) |
if (!libfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE)) |
goto error; |
tag[5] = 0; |
239,12 → 200,12 |
goto error; |
ipc_hangup(phone); |
munmap(block, BLOCK_SIZE); |
munmap(block, TMPFS_BLOCK_SIZE); |
return true; |
error: |
ipc_hangup(phone); |
munmap(block, BLOCK_SIZE); |
munmap(block, TMPFS_BLOCK_SIZE); |
return false; |
} |
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
233,7 → 233,7 |
hash_table_destroy(&dentries); |
return false; |
} |
root->lnkcnt = 1; |
root->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
405,11 → 405,12 |
if (dev_handle >= 0) { |
if (tmpfs_restore(dev_handle)) |
ipc_answer_0(rid, EOK); |
ipc_answer_3(rid, EOK, root->index, root->size, |
root->lnkcnt); |
else |
ipc_answer_0(rid, ELIMIT); |
} else { |
ipc_answer_0(rid, EOK); |
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt); |
} |
} |
/branches/tracing/uspace/srv/fs/tmpfs/Makefile |
---|
51,7 → 51,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
64,9 → 64,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/fs/fat/fat.h |
---|
222,6 → 222,7 |
extern void fat_mounted(ipc_callid_t, ipc_call_t *); |
extern void fat_mount(ipc_callid_t, ipc_call_t *); |
extern void fat_lookup(ipc_callid_t, ipc_call_t *); |
extern void fat_read(ipc_callid_t, ipc_call_t *); |
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned); |
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t); |
/branches/tracing/uspace/srv/fs/fat/fat.c |
---|
107,6 → 107,9 |
case VFS_LOOKUP: |
fat_lookup(callid, &call); |
break; |
case VFS_READ: |
fat_read(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
/branches/tracing/uspace/srv/fs/fat/fat_ops.c |
---|
39,6 → 39,8 |
#include "../../vfs/vfs.h" |
#include <libfs.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
#include <async.h> |
#include <errno.h> |
#include <string.h> |
47,8 → 49,10 |
#include <libadt/list.h> |
#include <assert.h> |
#include <futex.h> |
#include <sys/mman.h> |
#define BS_BLOCK 0 |
#define BS_SIZE 512 |
/** Futex protecting the list of cached free FAT nodes. */ |
static futex_t ffn_futex = FUTEX_INITIALIZER; |
66,15 → 70,15 |
#define FAT_DENTRY_DOT 0x2e |
#define FAT_DENTRY_ERASED 0xe5 |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
static void dentry_name_canonify(fat_dentry_t *d, char *buf) |
{ |
int i; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
if (d->name[i] == FAT_PAD) { |
buf++; |
if (d->name[i] == FAT_PAD) |
break; |
} |
if (d->name[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
92,21 → 96,55 |
else |
*buf++ = d->ext[i]; |
} |
*buf = '\0'; |
} |
static int dev_phone = -1; /* FIXME */ |
static void *dev_buffer = NULL; /* FIXME */ |
/* TODO move somewhere else */ |
typedef struct { |
void *data; |
size_t size; |
} block_t; |
static block_t *block_get(dev_handle_t dev_handle, off_t offset) |
static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs) |
{ |
return NULL; /* TODO */ |
/* FIXME */ |
block_t *b; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = offset * bs; |
assert(dev_phone != -1); |
assert(dev_buffer); |
b = malloc(sizeof(block_t)); |
if (!b) |
return NULL; |
b->data = malloc(bs); |
if (!b->data) { |
free(b); |
return NULL; |
} |
b->size = bs; |
if (!libfs_blockread(dev_phone, dev_buffer, &bufpos, &buflen, &pos, |
b->data, bs, bs)) { |
free(b->data); |
free(b); |
return NULL; |
} |
return b; |
} |
static void block_put(block_t *block) |
{ |
/* TODO */ |
/* FIXME */ |
free(block->data); |
free(block); |
} |
#define FAT_BS(b) ((fat_bs_t *)((b)->data)) |
143,7 → 181,7 |
fat_cluster_t clst = firstc; |
unsigned i; |
bb = block_get(dev_handle, BS_BLOCK); |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
spc = FAT_BS(bb)->spc; |
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
159,7 → 197,7 |
if (firstc == FAT_CLST_ROOT) { |
/* root directory special case */ |
assert(offset < rds); |
b = block_get(dev_handle, rscnt + fatcnt * sf + offset); |
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps); |
return b; |
} |
172,7 → 210,7 |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec); |
b = block_get(dev_handle, rscnt + fsec, bps); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
assert(clst < FAT_CLST_LAST1); |
180,11 → 218,58 |
} |
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc + |
offset % spc); |
offset % spc, bps); |
return b; |
} |
/** Return number of blocks allocated to a file. |
* |
* @param dev_handle Device handle of the device with the file. |
* @param firstc First cluster of the file. |
* |
* @return Number of blocks allocated to the file. |
*/ |
static uint16_t |
_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc) |
{ |
block_t *bb; |
block_t *b; |
unsigned bps; |
unsigned spc; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned clusters = 0; |
fat_cluster_t clst = firstc; |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
spc = FAT_BS(bb)->spc; |
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
block_put(bb); |
if (firstc == FAT_CLST_RES0) { |
/* No space allocated to the file. */ |
return 0; |
} |
while (clst < FAT_CLST_LAST1) { |
unsigned fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST); |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec, bps); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
block_put(b); |
clusters++; |
} |
return clusters * spc; |
} |
static void fat_node_initialize(fat_node_t *node) |
{ |
futex_initialize(&node->lock, 1); |
202,7 → 287,7 |
block_t *bb; |
uint16_t bps; |
bb = block_get(dev_handle, BS_BLOCK); |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
assert(bb != NULL); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
block_put(bb); |
253,7 → 338,7 |
{ |
block_t *b; |
fat_dentry_t *d; |
fat_node_t *nodep; |
fat_node_t *nodep = NULL; |
unsigned bps; |
unsigned dps; |
264,7 → 349,7 |
*/ |
futex_down(&idxp->nodep->lock); |
if (!idxp->nodep->refcnt++) |
list_remove(&nodep->ffn_link); |
list_remove(&idxp->nodep->ffn_link); |
futex_up(&idxp->nodep->lock); |
return idxp->nodep; |
} |
320,11 → 405,18 |
* and initialized elsewhere. |
*/ |
nodep->type = FAT_DIRECTORY; |
/* |
* Unfortunately, the 'size' field of the FAT dentry is not |
* defined for the directory entry type. We must determine the |
* size of the directory by walking the FAT. |
*/ |
nodep->size = bps * _fat_blcks_get(idxp->dev_handle, |
uint16_t_le2host(d->firstc)); |
} else { |
nodep->type = FAT_FILE; |
nodep->size = uint32_t_le2host(d->size); |
} |
nodep->firstc = uint16_t_le2host(d->firstc); |
nodep->size = uint32_t_le2host(d->size); |
nodep->lnkcnt = 1; |
nodep->refcnt = 1; |
421,7 → 513,7 |
dentry_name_canonify(d, name); |
break; |
} |
if (strcmp(name, component) == 0) { |
if (stricmp(name, component) == 0) { |
/* hit */ |
void *node; |
/* |
567,16 → 659,56 |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
block_t *bb; |
uint16_t bps; |
uint16_t rde; |
int rc; |
/* |
* For now, we don't bother to remember dev_handle, dev_phone or |
* dev_buffer in some data structure. We use global variables because we |
* know there will be at most one mount on this file system. |
* Of course, this is a huge TODO item. |
*/ |
dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE, |
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!dev_buffer) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev_handle); |
if (dev_phone < 0) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, dev_phone); |
return; |
} |
rc = ipc_share_out_start(dev_phone, dev_buffer, |
AS_AREA_READ | AS_AREA_WRITE); |
if (rc != EOK) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, rc); |
return; |
} |
/* Read the number of root directory entries. */ |
bb = block_get(dev_handle, BS_BLOCK); |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
block_put(bb); |
if (bps != BS_SIZE) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
rc = fat_idx_init_by_dev_handle(dev_handle); |
if (rc != EOK) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, rc); |
return; |
} |
584,6 → 716,7 |
/* Initialize the root node. */ |
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!rootp) { |
munmap(dev_buffer, BS_SIZE); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
592,6 → 725,7 |
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0); |
if (!ridxp) { |
munmap(dev_buffer, BS_SIZE); |
free(rootp); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
603,6 → 737,7 |
rootp->type = FAT_DIRECTORY; |
rootp->firstc = FAT_CLST_ROOT; |
rootp->refcnt = 1; |
rootp->lnkcnt = 0; /* FS root is not linked */ |
rootp->size = rde * sizeof(fat_dentry_t); |
rootp->idx = ridxp; |
ridxp->nodep = rootp; |
609,7 → 744,7 |
futex_up(&ridxp->lock); |
ipc_answer_0(rid, EOK); |
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); |
} |
void fat_mount(ipc_callid_t rid, ipc_call_t *request) |
622,6 → 757,96 |
libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_read(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
uint16_t bps = fat_bps_get(dev_handle); |
size_t bytes; |
block_t *b; |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_read_receive(&callid, &len)) { |
fat_node_put(nodep); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (nodep->type == FAT_FILE) { |
/* |
* Our strategy for regular file reads is to read one block at |
* most and make use of the possibility to return less data than |
* requested. This keeps the code very simple. |
*/ |
bytes = min(len, bps - pos % bps); |
b = fat_block_get(nodep, pos / bps); |
(void) ipc_data_read_finalize(callid, b->data + pos % bps, |
bytes); |
block_put(b); |
} else { |
unsigned bnum; |
off_t spos = pos; |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
fat_dentry_t *d; |
assert(nodep->type == FAT_DIRECTORY); |
assert(nodep->size % bps == 0); |
assert(bps % sizeof(fat_dentry_t) == 0); |
/* |
* Our strategy for readdir() is to use the position pointer as |
* an index into the array of all dentries. On entry, it points |
* to the first unread dentry. If we skip any dentries, we bump |
* the position pointer accordingly. |
*/ |
bnum = (pos * sizeof(fat_dentry_t)) / bps; |
while (bnum < nodep->size / bps) { |
off_t o; |
b = fat_block_get(nodep, bnum); |
for (o = pos % (bps / sizeof(fat_dentry_t)); |
o < bps / sizeof(fat_dentry_t); |
o++, pos++) { |
d = ((fat_dentry_t *)b->data) + o; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
goto miss; |
default: |
case FAT_DENTRY_VALID: |
dentry_name_canonify(d, name); |
block_put(b); |
goto hit; |
} |
} |
block_put(b); |
bnum++; |
} |
miss: |
fat_node_put(nodep); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
hit: |
(void) ipc_data_read_finalize(callid, name, strlen(name) + 1); |
bytes = (pos - spos) + 1; |
} |
fat_node_put(nodep); |
ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
} |
/** |
* @} |
*/ |
/branches/tracing/uspace/srv/fs/fat/Makefile |
---|
51,7 → 51,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
64,9 → 64,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/devmap/Makefile |
---|
50,7 → 50,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
63,9 → 63,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/vfs/vfs_ops.c |
---|
71,8 → 71,11 |
{ |
dev_handle_t dev_handle; |
vfs_node_t *mp_node = NULL; |
ipc_callid_t callid; |
ipc_call_t data; |
int rc; |
int phone; |
size_t size; |
/* |
* We expect the library to do the device-name to device-handle |
86,9 → 89,6 |
* carry mount options in the future. |
*/ |
ipc_callid_t callid; |
size_t size; |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
115,15 → 115,30 |
fs_name[size] = '\0'; |
/* |
* Wait for IPC_M_PING so that we can return an error if we don't know |
* fs_name. |
*/ |
callid = async_get_call(&data); |
if (IPC_GET_METHOD(data) != IPC_M_PING) { |
ipc_answer_0(callid, ENOTSUP); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
if (!fs_handle) { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* Acknowledge that we know fs_name. */ |
ipc_answer_0(callid, EOK); |
/* Now, we want the client to send us the mount point. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
190,6 → 205,12 |
} else { |
/* We still don't have the root file system mounted. */ |
if ((size == 1) && (buf[0] == '/')) { |
vfs_lookup_res_t mr_res; |
vfs_node_t *mr_node; |
ipcarg_t rindex; |
ipcarg_t rsize; |
ipcarg_t rlnkcnt; |
/* |
* For this simple, but important case, |
* we are almost done. |
198,16 → 219,30 |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
rc = async_req_1_0(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle); |
rc = async_req_1_3(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
vfs_release_phone(phone); |
if (rc == EOK) { |
if (rc != EOK) { |
futex_up(&rootfs_futex); |
ipc_answer_0(rid, rc); |
return; |
} |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = (fs_index_t) rindex; |
mr_res.size = (size_t) rsize; |
mr_res.lnkcnt = (unsigned) rlnkcnt; |
rootfs.fs_handle = fs_handle; |
rootfs.dev_handle = dev_handle; |
} |
futex_up(&rootfs_futex); |
futex_up(&rootfs_futex); |
/* Add reference to the mounted root. */ |
mr_node = vfs_node_get(&mr_res); |
assert(mr_node); |
ipc_answer_0(rid, rc); |
return; |
} else { |
374,13 → 409,9 |
void vfs_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
if (fd >= MAX_OPEN_FILES) { |
ipc_answer_0(rid, EBADF); |
return; |
int rc = vfs_fd_free(fd); |
ipc_answer_0(rid, rc); |
} |
vfs_fd_free(fd); |
ipc_answer_0(rid, EOK); |
} |
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) |
{ |
/branches/tracing/uspace/srv/vfs/vfs.h |
---|
282,7 → 282,7 |
extern bool vfs_files_init(void); |
extern vfs_file_t *vfs_file_get(int); |
extern int vfs_fd_alloc(void); |
extern void vfs_fd_free(int); |
extern int vfs_fd_free(int); |
extern void vfs_file_addref(vfs_file_t *); |
extern void vfs_file_delref(vfs_file_t *); |
/branches/tracing/uspace/srv/vfs/Makefile |
---|
52,7 → 52,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
65,9 → 65,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/tracing/uspace/srv/vfs/vfs_file.c |
---|
97,13 → 97,17 |
/** Release file descriptor. |
* |
* @param fd File descriptor being released. |
* |
* @return EOK on success or EBADF if fd is an invalid file |
* descriptor. |
*/ |
void vfs_fd_free(int fd) |
int vfs_fd_free(int fd) |
{ |
assert(fd < MAX_OPEN_FILES); |
assert(files[fd] != NULL); |
if ((fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) |
return EBADF; |
vfs_file_delref(files[fd]); |
files[fd] = NULL; |
return EOK; |
} |
/** Increment reference count of VFS file structure. |