Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3535 → Rev 3536

/branches/tracing/kernel/generic/include/stdarg.h
45,7 → 45,7
#define va_start(ap, last) __builtin_va_start(ap, last)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_end(ap) __builtin_va_end(ap)
#define va_copy(dst,src) __builtin_va_copy(dst,src)
#define va_copy(dst, src) __builtin_va_copy(dst, src)
 
#endif
 
/branches/tracing/kernel/generic/src/ipc/kbox.c
45,6 → 45,7
 
void ipc_kbox_cleanup(void)
{
ipl_t ipl;
bool have_kb_thread;
 
/* Only hold kb_cleanup_lock while setting kb_finished - this is enough */
63,6 → 64,17
* wake up and terminate.
*/
ipc_answerbox_slam_phones(&TASK->kernel_box, have_kb_thread);
 
/*
* If the task was being debugged, clean up debugging session.
* This is necessarry as slamming the phones won't force
* kbox thread to clean it up since sender != debugger.
*/
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
udebug_task_cleanup(TASK);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
if (have_kb_thread) {
LOG("join kb_thread..\n");
79,13 → 91,75
spinlock_unlock(&TASK->kernel_box.lock);
}
 
/** Handle hangup message in kbox.
*
* @param call The IPC_M_PHONE_HUNGUP call structure.
* @param last Output, the function stores @c true here if
* this was the last phone, @c false otherwise.
**/
static void kbox_proc_phone_hungup(call_t *call, bool *last)
{
ipl_t ipl;
 
LOG("kbox_proc_phone_hungup()\n");
 
/* Was it our debugger, who hung up? */
if (call->sender == TASK->udebug.debugger) {
/* Terminate debugging session (if any) */
LOG("kbox: terminate debug session\n");
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
udebug_task_cleanup(TASK);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
} else {
LOG("kbox: was not debugger\n");
}
 
LOG("kbox: continue with hangup message\n");
IPC_SET_RETVAL(call->data, 0);
ipc_answer(&TASK->kernel_box, call);
 
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
spinlock_lock(&TASK->answerbox.lock);
if (list_empty(&TASK->answerbox.connected_phones)) {
/*
* Last phone has been disconnected. Detach this thread so it
* gets freed and signal to the caller.
*/
 
/* Only detach kbox thread unless already terminating. */
mutex_lock(&TASK->kb_cleanup_lock);
if (&TASK->kb_finished == false) {
/* Detach kbox thread so it gets freed from memory. */
thread_detach(TASK->kb_thread);
TASK->kb_thread = NULL;
}
mutex_unlock(&TASK->kb_cleanup_lock);
 
LOG("phone list is empty\n");
*last = true;
} else {
*last = false;
}
 
spinlock_unlock(&TASK->answerbox.lock);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
}
 
/** Implementing function for the kbox thread.
*
* This function listens for debug requests. It terminates
* when all phones are disconnected from the kbox.
*
* @param arg Ignored.
*/
static void kbox_thread_proc(void *arg)
{
call_t *call;
int method;
bool done;
ipl_t ipl;
 
(void)arg;
LOG("kbox_thread_proc()\n");
95,46 → 169,28
call = ipc_wait_for_call(&TASK->kernel_box, SYNCH_NO_TIMEOUT,
SYNCH_FLAGS_NONE);
 
if (call != NULL) {
method = IPC_GET_METHOD(call->data);
if (call == NULL)
continue; /* Try again. */
 
if (method == IPC_M_DEBUG_ALL) {
udebug_call_receive(call);
}
switch (IPC_GET_METHOD(call->data)) {
 
if (method == IPC_M_PHONE_HUNGUP) {
LOG("kbox: handle hangup message\n");
case IPC_M_DEBUG_ALL:
/* Handle debug call. */
udebug_call_receive(call);
break;
 
/* Was it our debugger, who hung up? */
if (call->sender == TASK->udebug.debugger) {
/* Terminate debugging session (if any) */
LOG("kbox: terminate debug session\n");
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
udebug_task_cleanup(TASK);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
} else {
LOG("kbox: was not debugger\n");
}
case IPC_M_PHONE_HUNGUP:
/*
* Process the hangup call. If this was the last
* phone, done will be set to true and the
* while loop will terminate.
*/
kbox_proc_phone_hungup(call, &done);
break;
 
LOG("kbox: continue with hangup message\n");
IPC_SET_RETVAL(call->data, 0);
ipc_answer(&TASK->kernel_box, call);
 
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
spinlock_lock(&TASK->answerbox.lock);
if (list_empty(&TASK->answerbox.connected_phones)) {
/* Last phone has been disconnected */
TASK->kb_thread = NULL;
done = true;
LOG("phone list is empty\n");
}
spinlock_unlock(&TASK->answerbox.lock);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
}
default:
/* Ignore */
break;
}
}
 
/branches/tracing/kernel/generic/src/ipc/sysipc.c
822,12 → 822,16
 
ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
 
if (!(call->flags & IPC_CALL_DISCARD_ANSWER))
atomic_dec(&TASK->active_calls);
 
if (call->flags & IPC_CALL_DISCARD_ANSWER) {
ipc_call_free(call);
goto restart;
} else {
/*
* Decrement the counter of active calls only if the
* call is not an answer to IPC_M_PHONE_HUNGUP,
* which doesn't contribute to the counter.
*/
atomic_dec(&TASK->active_calls);
}
 
STRUCT_TO_USPACE(&calldata->args, &call->data.args);
/branches/tracing/kernel/generic/src/ipc/ipc.c
508,7 → 508,8
interrupts_restore(ipl);
 
/* Free unused call */
if (call) ipc_call_free(call);
if (call)
ipc_call_free(call);
}
 
/** Cleans up all IPC communication of the current task.
573,6 → 574,11
(call->flags & IPC_CALL_NOTIF));
ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
/*
* Record the receipt of this call in the current task's counter
* of active calls. IPC_M_PHONE_HUNGUP calls do not contribute
* to this counter so do not record answers to them either.
*/
if (!(call->flags & IPC_CALL_DISCARD_ANSWER))
atomic_dec(&TASK->active_calls);
ipc_call_free(call);
/branches/tracing/kernel/Makefile
44,7 → 44,7
 
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \
-nostdlib -nostdinc
-nostdlib -nostdinc -pipe
 
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \
-fno-builtin -Wall -Wmissing-prototypes -Werror \
365,7 → 365,7
ln -sfn ../../genarch/include/ generic/include/genarch
 
depend: archlinks
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in
$(GCC) $(DEFS) $(GCC_CFLAGS) -D__ASM__ -D__LINKER__ -E -x c $< | grep -v "^\#" > $@
/branches/tracing/kernel/arch/sparc64/include/trap/regwin.h
39,6 → 39,7
 
#include <arch/stack.h>
#include <arch/arch.h>
#include <align.h>
 
#define TT_CLEAN_WINDOW 0x24
#define TT_SPILL_0_NORMAL 0x80 /* kernel spills */
72,6 → 73,11
#define I6_OFFSET 112
#define I7_OFFSET 120
 
/* Uspace Window Buffer constants. */
#define UWB_SIZE ((NWINDOWS - 1) * STACK_WINDOW_SAVE_AREA_SIZE)
#define UWB_ALIGNMENT 1024
#define UWB_ASIZE ALIGN_UP(UWB_SIZE, UWB_ALIGNMENT)
 
#ifdef __ASM__
 
/*
/branches/tracing/kernel/arch/sparc64/src/proc/thread.c
34,9 → 34,8
 
#include <proc/thread.h>
#include <arch/proc/thread.h>
#include <mm/frame.h>
#include <mm/page.h>
#include <arch/mm/page.h>
#include <mm/slab.h>
#include <arch/trap/regwin.h>
#include <align.h>
 
void thr_constructor_arch(thread_t *t)
50,12 → 49,12
void thr_destructor_arch(thread_t *t)
{
if (t->arch.uspace_window_buffer) {
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer;
/*
* Mind the possible alignment of the userspace window buffer
* belonging to a killed thread.
*/
frame_free(KA2PA(ALIGN_DOWN((uintptr_t)
t->arch.uspace_window_buffer, PAGE_SIZE)));
free((uint8_t *) ALIGN_DOWN(uw_buf, UWB_ALIGNMENT));
}
}
 
67,7 → 66,7
* The thread needs userspace window buffer and the object
* returned from the slab allocator doesn't have any.
*/
t->arch.uspace_window_buffer = frame_alloc(ONE_FRAME, FRAME_KA);
t->arch.uspace_window_buffer = malloc(UWB_ASIZE, 0);
} else {
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer;
 
76,7 → 75,7
* belonging to a killed thread.
*/
t->arch.uspace_window_buffer = (uint8_t *) ALIGN_DOWN(uw_buf,
PAGE_SIZE);
UWB_ASIZE);
}
}
 
/branches/tracing/kernel/arch/sparc64/src/trap/trap_table.S
748,9 → 748,8
* Fill all windows stored in the buffer.
*/
clr %g4
set PAGE_SIZE - 1, %g5
0: andcc %g7, %g5, %g0 ! PAGE_SIZE alignment check
bz 0f ! %g7 is page-aligned, no more windows to refill
0: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check
bz 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
nop
 
add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
/branches/tracing/kernel/arch/ia64/include/asm.h
44,21 → 44,50
 
static inline void outb(uint64_t port,uint8_t v)
{
*((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
*((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outw(uint64_t port,uint16_t v)
{
*((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outl(uint64_t port,uint32_t v)
{
*((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
 
 
static inline uint8_t inb(uint64_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
}
 
static inline uint16_t inw(uint64_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xffE) | ( (port >> 2) << 12 ))));
}
 
static inline uint32_t inl(uint64_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
}
 
 
 
/** Return base address of current stack
*
* Return the base address of the current stack.
/branches/tracing/kernel/arch/amd64/include/syscall.h
35,8 → 35,6
#ifndef KERN_amd64_SYSCALL_H_
#define KERN_amd64_SYSCALL_H_
 
#include <arch/types.h>
 
extern void syscall_setup_cpu(void);
 
#endif
/branches/tracing/kernel/arch/ia32/include/syscall.h
0,0 → 1,0
link ../../amd64/include/syscall.h
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/tracing/kernel/arch/ia32/include/asm.h
247,6 → 247,22
return v;
}
 
/** Write to MSR */
static inline void write_msr(uint32_t msr, uint64_t value)
{
asm volatile ("wrmsr" : : "c" (msr), "a" ((uint32_t)(value)),
"d" ((uint32_t)(value >> 32)));
}
 
static inline uint64_t read_msr(uint32_t msr)
{
uint32_t ax, dx;
 
asm volatile ("rdmsr" : "=a"(ax), "=d"(dx) : "c" (msr));
return ((uint64_t)dx << 32) | ax;
}
 
 
/** Return base address of current stack
*
* Return the base address of the current stack.
/branches/tracing/kernel/arch/ia32/include/cpu.h
35,12 → 35,21
#ifndef KERN_ia32_CPU_H_
#define KERN_ia32_CPU_H_
 
#define EFLAGS_IF (1 << 9)
#define EFLAGS_RF (1 << 16)
 
#define CR4_OSFXSR_MASK (1<<9)
 
/* Support for SYSENTER and SYSEXIT */
#define IA32_MSR_SYSENTER_CS 0x174
#define IA32_MSR_SYSENTER_ESP 0x175
#define IA32_MSR_SYSENTER_EIP 0x176
 
#ifndef __ASM__
 
#include <arch/pm.h>
#include <arch/asm.h>
 
#define EFLAGS_IF (1 << 9)
#define EFLAGS_RF (1 << 16)
 
typedef struct {
int vendor;
int family;
51,9 → 60,8
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
} cpu_arch_t;
 
#endif
 
#define CR4_OSFXSR_MASK (1<<9)
 
#define DR6_BT (1<<15)
#define DR6_BS (1<<14)
#define DR6_BD (1<<13)
/branches/tracing/kernel/arch/ia32/Makefile.inc
160,10 → 160,10
arch/$(ARCH)/src/boot/boot.S \
arch/$(ARCH)/src/boot/memmap.c \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/debugger.c
arch/$(ARCH)/src/debugger.c \
arch/$(ARCH)/src/syscall.c
 
ifeq ($(CONFIG_UDEBUG),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/breakpoint.c
endif
/branches/tracing/kernel/arch/ia32/src/asm.S
147,6 → 147,45
popfl
.endm
 
/*
* The SYSENTER syscall mechanism can be used for syscalls with
* four or fewer arguments. To pass these four arguments, we
* use four registers: EDX, ECX, EBX, ESI. The syscall number
* is passed in EAX. We use EDI to remember the return address
* and EBP to remember the stack. The INT-based syscall mechanism
* can actually handle six arguments plus the syscall number
* entirely in registers.
*/
.global sysenter_handler
sysenter_handler:
pushl %ebp # remember user stack
pushl %edi # remember return user address
 
pushl %gs # remember TLS
 
pushl %eax # syscall number
subl $8, %esp # unused sixth and fifth argument
pushl %esi # fourth argument
pushl %ebx # third argument
pushl %ecx # second argument
pushl %edx # first argument
 
movw $16, %ax
movw %ax, %ds
movw %ax, %es
 
cld
call syscall_handler
addl $28, %esp # remove arguments from stack
 
pop %gs # restore TLS
 
pop %edx # prepare return EIP for SYSEXIT
pop %ecx # prepare userspace ESP for SYSEXIT
 
sysexit # return to userspace
 
 
## Declare interrupt handlers
#
# Declare interrupt handlers for n interrupt
/branches/tracing/kernel/arch/ia32/src/cpu/cpu.c
42,6 → 42,7
#include <fpu_context.h>
 
#include <arch/smp/apic.h>
#include <arch/syscall.h>
 
/*
* Identification of CPUs.
123,6 → 124,9
: "i" (CR4_OSFXSR_MASK|(1<<10))
);
}
/* Setup fast SYSENTER/SYSEXIT syscalls */
syscall_setup_cpu();
}
 
void cpu_identify(void)
/branches/tracing/kernel/arch/ia32/src/syscall.c
0,0 → 1,53
/*
* Copyright (c) 2008 Jakub Jermar
* 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 ia32
* @{
*/
/** @file
*/
 
#include <arch/syscall.h>
#include <arch/cpu.h>
#include <arch/asm.h>
#include <arch/types.h>
#include <arch/pm.h>
 
/** Enable & setup support for SYSENTER/SYSEXIT */
void syscall_setup_cpu(void)
{
extern void sysenter_handler(void);
 
/* set kernel mode CS selector */
write_msr(IA32_MSR_SYSENTER_CS, selector(KTEXT_DES));
/* set kernel mode entry point */
write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler);
}
 
/** @}
*/
/branches/tracing/kernel/arch/ia32/src/proc/scheduler.c
58,8 → 58,14
*/
void before_thread_runs_arch(void)
{
CPU->arch.tss->esp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
uintptr_t kstk = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
SP_DELTA];
 
/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */
write_msr(IA32_MSR_SYSENTER_ESP, kstk);
 
/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */
CPU->arch.tss->esp0 = kstk;
CPU->arch.tss->ss0 = selector(KDATA_DES);
 
/* Set up TLS in GS register */
/branches/tracing/tools/mkfat.sh
File deleted
Property changes:
Deleted: svn:executable
-*
\ No newline at end of property
/branches/tracing/tools/mkfat.py
34,7 → 34,273
import os
import random
import xstruct
import array
 
def align_up(size, alignment):
"Return size aligned up to alignment"
if (size % alignment == 0):
return size
return (((size / alignment) + 1) * alignment)
 
def subtree_size(root, cluster_size, dirent_size):
"Recursive directory walk and calculate size"
size = 0
files = 2
for name in os.listdir(root):
canon = os.path.join(root, name)
if (os.path.isfile(canon)):
size += align_up(os.path.getsize(canon), cluster_size)
files += 1
if (os.path.isdir(canon)):
size += subtree_size(canon, cluster_size, dirent_size)
files += 1
return size + align_up(files * dirent_size, cluster_size)
 
def root_entries(root):
"Return number of root directory entries"
return len(os.listdir(root))
 
def write_file(path, outf, cluster_size, data_start, fat, reserved_clusters):
"Store the contents of a file"
size = os.path.getsize(path)
prev = -1
first = 0
inf = file(path, "r")
rd = 0;
while (rd < size):
empty_cluster = fat.index(0)
fat[empty_cluster] = 0xffff
if (prev != -1):
fat[prev] = empty_cluster
else:
first = empty_cluster
prev = empty_cluster
data = inf.read(cluster_size);
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
outf.write(data)
rd += len(data)
inf.close()
return first, size
 
def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster):
"Store the contents of a directory"
length = len(directory)
size = length * dirent_size
prev = -1
first = 0
i = 0
rd = 0;
while (rd < size):
if (prev != -1):
empty_cluster = fat.index(0)
fat[empty_cluster] = 0xffff
fat[prev] = empty_cluster
else:
first = empty_cluster
prev = empty_cluster
data = ''
data_len = 0
while ((i < length) and (data_len < cluster_size)):
if (i == 0):
directory[i].cluster = empty_cluster
data += directory[i].pack()
data_len += dirent_size
i += 1
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
outf.write(data)
rd += len(data)
return first, size
 
DIR_ENTRY = """little:
char name[8] /* file name */
char ext[3] /* file extension */
uint8_t attr /* file attributes */
padding[1] /* reserved for NT */
uint8_t ctime_fine /* create time (fine resolution) */
uint16_t ctime /* create time */
uint16_t cdate /* create date */
uint16_t adate /* access date */
padding[2] /* EA-index */
uint16_t mtime /* modification time */
uint16_t mdate /* modification date */
uint16_t cluster /* first cluster */
uint32_t size /* file size */
"""
 
DOT_DIR_ENTRY = """little:
uint8_t signature /* 0x2e signature */
char name[7] /* empty */
char ext[3] /* empty */
uint8_t attr /* file attributes */
padding[1] /* reserved for NT */
uint8_t ctime_fine /* create time (fine resolution) */
uint16_t ctime /* create time */
uint16_t cdate /* create date */
uint16_t adate /* access date */
padding[2] /* EA-index */
uint16_t mtime /* modification time */
uint16_t mdate /* modification date */
uint16_t cluster /* first cluster */
uint32_t size /* file size */
"""
 
DOTDOT_DIR_ENTRY = """little:
uint8_t signature[2] /* 0x2e signature */
char name[6] /* empty */
char ext[3] /* empty */
uint8_t attr /* file attributes */
padding[1] /* reserved for NT */
uint8_t ctime_fine /* create time (fine resolution) */
uint16_t ctime /* create time */
uint16_t cdate /* create date */
uint16_t adate /* access date */
padding[2] /* EA-index */
uint16_t mtime /* modification time */
uint16_t mdate /* modification date */
uint16_t cluster /* first cluster */
uint32_t size /* file size */
"""
 
def mangle_fname(name):
# FIXME: filter illegal characters
parts = name.split('.')
if (len(parts) > 0):
fname = parts[0]
else:
fname = ''
return (fname + ' ').upper()[0:8]
 
def mangle_ext(name):
# FIXME: filter illegal characters
parts = name.split('.')
if (len(parts) > 1):
ext = parts[1]
else:
ext = ''
return (ext + ' ').upper()[0:3]
 
def create_dirent(name, directory, cluster, size):
dir_entry = xstruct.create(DIR_ENTRY)
dir_entry.name = mangle_fname(name)
dir_entry.ext = mangle_ext(name)
if (directory):
dir_entry.attr = 0x30
else:
dir_entry.attr = 0x20
dir_entry.ctime_fine = 0 # FIXME
dir_entry.ctime = 0 # FIXME
dir_entry.cdate = 0 # FIXME
dir_entry.adate = 0 # FIXME
dir_entry.mtime = 0 # FIXME
dir_entry.mdate = 0 # FIXME
dir_entry.cluster = cluster
if (directory):
dir_entry.size = 0
else:
dir_entry.size = size
return dir_entry
 
def create_dot_dirent(empty_cluster):
dir_entry = xstruct.create(DOT_DIR_ENTRY)
dir_entry.signature = 0x2e
dir_entry.name = ' '
dir_entry.ext = ' '
dir_entry.attr = 0x10
dir_entry.ctime_fine = 0 # FIXME
dir_entry.ctime = 0 # FIXME
dir_entry.cdate = 0 # FIXME
dir_entry.adate = 0 # FIXME
dir_entry.mtime = 0 # FIXME
dir_entry.mdate = 0 # FIXME
dir_entry.cluster = empty_cluster
dir_entry.size = 0
return dir_entry
 
def create_dotdot_dirent(parent_cluster):
dir_entry = xstruct.create(DOTDOT_DIR_ENTRY)
dir_entry.signature = [0x2e, 0x2e]
dir_entry.name = ' '
dir_entry.ext = ' '
dir_entry.attr = 0x10
dir_entry.ctime_fine = 0 # FIXME
dir_entry.ctime = 0 # FIXME
dir_entry.cdate = 0 # FIXME
dir_entry.adate = 0 # FIXME
dir_entry.mtime = 0 # FIXME
dir_entry.mdate = 0 # FIXME
dir_entry.cluster = parent_cluster
dir_entry.size = 0
return dir_entry
 
def recursion(head, root, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, parent_cluster):
"Recursive directory walk"
directory = []
if (not head):
# Directory cluster preallocation
empty_cluster = fat.index(0)
fat[empty_cluster] = 0xffff
directory.append(create_dot_dirent(empty_cluster))
directory.append(create_dotdot_dirent(parent_cluster))
else:
empty_cluster = 0
for name in os.listdir(root):
canon = os.path.join(root, name)
if (os.path.isfile(canon)):
rv = write_file(canon, outf, cluster_size, data_start, fat, reserved_clusters)
directory.append(create_dirent(name, False, rv[0], rv[1]))
if (os.path.isdir(canon)):
rv = recursion(False, canon, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
directory.append(create_dirent(name, True, rv[0], rv[1]))
if (head):
outf.seek(root_start)
for dir_entry in directory:
outf.write(dir_entry.pack())
else:
return write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
 
BOOT_SECTOR = """little:
uint8_t jmp[3] /* jump instruction */
char oem[8] /* OEM string */
62,6 → 328,14
uint8_t boot_signature[2] /* boot signature */
"""
 
EMPTY_SECTOR = """little:
padding[512] /* empty sector data */
"""
 
FAT_ENTRY = """little:
uint16_t next /* FAT16 entry */
"""
 
def usage(prname):
"Print usage syntax"
print prname + " <PATH> <IMAGE>"
76,27 → 350,60
print "<PATH> must be a directory"
return
fat16_clusters = 4096
min_cluster_size = 1024
sector_size = 512
cluster_size = 4096
dirent_size = 32
fatent_size = 2
fat_count = 2
reserved_clusters = 2
# Make sure the filesystem is large enought for FAT16
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
while (size / cluster_size < fat16_clusters):
if (cluster_size > min_cluster_size):
cluster_size /= 2
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
else:
size = fat16_clusters * cluster_size + reserved_clusters * cluster_size
root_size = align_up(root_entries(path) * dirent_size, cluster_size)
fat_size = align_up(align_up(size, cluster_size) / cluster_size * fatent_size, sector_size)
sectors = (cluster_size + fat_count * fat_size + root_size + size) / sector_size
root_start = cluster_size + fat_count * fat_size
data_start = root_start + root_size
outf = file(sys.argv[2], "w")
boot_sector = xstruct.create(BOOT_SECTOR)
boot_sector.jmp = [0xEB, 0x3C, 0x90]
boot_sector.oem = "MSDOS5.0"
boot_sector.sector = 512
boot_sector.cluster = 8 # 4096 bytes per cluster
boot_sector.reserved = 1
boot_sector.fats = 2
boot_sector.rootdir = 224 # FIXME: root directory should be sector aligned
boot_sector.sectors = 0 # FIXME
boot_sector.sector = sector_size
boot_sector.cluster = cluster_size / sector_size
boot_sector.reserved = cluster_size / sector_size
boot_sector.fats = fat_count
boot_sector.rootdir = root_size / dirent_size
if (sectors <= 65535):
boot_sector.sectors = sectors
else:
boot_sector.sectors = 0
boot_sector.descriptor = 0xF8
boot_sector.fat_sectors = 0 # FIXME
boot_sector.track_sectors = 0 # FIXME
boot_sector.heads = 0 # FIXME
boot_sector.fat_sectors = fat_size / sector_size
boot_sector.track_sectors = 63
boot_sector.heads = 6
boot_sector.hidden = 0
boot_sector.sectors_big = 0 # FIXME
if (sectors > 65535):
boot_sector.sectors_big = sectors
else:
boot_sector.sectors_big = 0
boot_sector.drive = 0
boot_sector.drive = 0x80
boot_sector.extboot_signature = 0x29
boot_sector.serial = random.randint(0, 0xFFFFFFFF)
boot_sector.serial = random.randint(0, 0x7fffffff)
boot_sector.label = "HELENOS"
boot_sector.fstype = "FAT16 "
boot_sector.boot_signature = [0x55, 0xAA]
103,6 → 410,39
outf.write(boot_sector.pack())
empty_sector = xstruct.create(EMPTY_SECTOR)
# Reserved sectors
for i in range(1, cluster_size / sector_size):
outf.write(empty_sector.pack())
# FAT tables
for i in range(0, fat_count):
for j in range(0, fat_size / sector_size):
outf.write(empty_sector.pack())
# Root directory
for i in range(0, root_size / sector_size):
outf.write(empty_sector.pack())
# Data
for i in range(0, size / sector_size):
outf.write(empty_sector.pack())
fat = array.array('L', [0] * (fat_size / fatent_size))
fat[0] = 0xfff8
fat[1] = 0xffff
recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0)
# Store FAT
fat_entry = xstruct.create(FAT_ENTRY)
for i in range(0, fat_count):
outf.seek(cluster_size + i * fat_size)
for j in range(0, fat_size / fatent_size):
fat_entry.next = fat[j]
outf.write(fat_entry.pack())
outf.close()
if __name__ == '__main__':
/branches/tracing/uspace/app/bdsh/cmds/modules/cat/cat.c
103,13 → 103,11
}
 
do {
memset(buff, 0, sizeof(buff));
bytes = read(fd, buff, blen);
if (bytes > 0) {
count += bytes;
if (bytes < blen)
buff[bytes] = '\0';
printf(buff);
buff[bytes] = '\0';
printf("%s", buff);
reads++;
}
} while (bytes > 0);
/branches/tracing/uspace/app/bdsh/util.c
70,125 → 70,6
return (char *) memcpy(ret, s1, len);
}
 
/*
* Take a previously allocated string (s1), re-size it to accept s2 and copy
* the contents of s2 into s1.
* Return -1 on failure, or the length of the copied string on success.
*/
int cli_redup(char **s1, const char *s2)
{
size_t len = strlen(s2) + 1;
 
if (! len)
return -1;
 
*s1 = realloc(*s1, len);
 
if (*s1 == NULL) {
cli_errno = CL_ENOMEM;
return -1;
}
 
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, s2, len);
cli_errno = CL_EOK;
return (int) len;
}
 
/* An asprintf() for formatting paths, similar to asprintf() but ensures
* the returned allocated string is <= PATH_MAX. On failure, an attempt
* is made to return the original string (if not null) unmodified.
*
* Returns: Length of the new string on success, 0 if the string was handed
* back unmodified, -1 on failure. On failure, cli_errno is set.
*
* We do not use POSIX_PATH_MAX, as it is typically much smaller than the
* PATH_MAX defined by the kernel.
*
* Use this like:
* if (1 > cli_psprintf(&char, "%s/%s", foo, bar)) {
* cli_error(cli_errno, "Failed to format path");
* stop_what_your_doing_as_your_out_of_memory();
* }
*/
 
int cli_psprintf(char **s1, const char *fmt, ...)
{
va_list ap;
size_t needed, base = PATH_MAX + 1;
int skipped = 0;
char *orig = NULL;
char *tmp = (char *) malloc(base);
 
/* Don't even touch s1, not enough memory */
if (NULL == tmp) {
cli_errno = CL_ENOMEM;
return -1;
}
 
/* If re-allocating s1, save a copy in case we fail */
if (NULL != *s1)
orig = cli_strdup(*s1);
 
/* Print the string to tmp so we can determine the size that
* we actually need */
memset(tmp, 0, sizeof(tmp));
va_start(ap, fmt);
/* vsnprintf will return the # of bytes not written */
skipped = vsnprintf(tmp, base, fmt, ap);
va_end(ap);
 
/* realloc/alloc s1 to be just the size that we need */
needed = strlen(tmp) + 1;
*s1 = realloc(*s1, needed);
 
if (NULL == *s1) {
/* No string lived here previously, or we failed to
* make a copy of it, either way there's nothing we
* can do. */
if (NULL == *orig) {
cli_errno = CL_ENOMEM;
return -1;
}
/* We can't even allocate enough size to restore the
* saved copy, just give up */
*s1 = realloc(*s1, strlen(orig) + 1);
if (NULL == *s1) {
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return -1;
}
/* Give the string back as we found it */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, orig, strlen(orig) + 1);
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return 0;
}
 
/* Ok, great, we have enough room */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, tmp, needed);
free(tmp);
 
/* Free tmp only if s1 was reallocated instead of allocated */
if (NULL != orig)
free(orig);
 
if (skipped) {
/* s1 was bigger than PATH_MAX when expanded, however part
* of the string was printed. Tell the caller not to use it */
cli_errno = CL_ETOOBIG;
return -1;
}
 
/* Success! */
cli_errno = CL_EOK;
return (int) needed;
}
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * cli_strtok_r(char *s, const char *delim, char **last)
{
273,10 → 154,7
if (NULL == usr->cwd)
snprintf(usr->cwd, PATH_MAX, "(unknown)");
 
if (1 < cli_psprintf(&usr->prompt, "%s # ", usr->cwd)) {
cli_error(cli_errno, "Failed to set prompt");
return 1;
}
asprintf(&usr->prompt, "%s # ", usr->cwd);
 
return 0;
}
/branches/tracing/uspace/app/bdsh/util.h
5,8 → 5,6
 
/* Internal string handlers */
extern char * cli_strdup(const char *);
extern int cli_redup(char **, const char *);
extern int cli_psprintf(char **, const char *, ...);
extern char * cli_strtok_r(char *, const char *, char **);
extern char * cli_strtok(char *, const char *);
 
/branches/tracing/uspace/app/bdsh/exec.c
117,7 → 117,7
tmp = cli_strdup(find_command(cmd));
free(found);
 
tid = task_spawn((const char *)tmp, (const char **)argv);
tid = task_spawn((const char *)tmp, argv);
free(tmp);
 
if (tid == 0) {
/branches/tracing/uspace/app/debug/main.c
35,7 → 35,7
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syscall.h>
#include <libarch/syscall.h>
#include <ipc/ipc.h>
#include <fibril.h>
#include <loader/loader.h>
/branches/tracing/uspace/app/tester/tester.c
148,6 → 148,8
}
}
 
return 0;
}
 
/** @}
/branches/tracing/uspace/app/tester/ipc/send_sync.c
35,7 → 35,6
{
int phoneid;
int res;
static int msgid = 1;
char c;
 
printf("Select phoneid to send msg: 2-9 (q to skip)\n");
/branches/tracing/uspace/app/trace/trace.c
35,7 → 35,6
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syscall.h>
#include <ipc/ipc.h>
#include <fibril.h>
#include <errno.h>
44,6 → 43,8
#include <task.h>
#include <loader/loader.h>
 
#include <libc.h>
 
// Temporary: service and method names
#include "proto.h"
#include <ipc/services.h>
/branches/tracing/uspace/lib/libfs/libfs.c
36,7 → 36,6
 
#include "libfs.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <errno.h>
#include <async.h>
#include <ipc/ipc.h>
331,62 → 330,5
ops->node_put(tmp);
}
 
/** Read data from a block device.
*
* @param phone Phone to be used to communicate with the device.
* @param buffer Communication buffer shared with the device.
* @param bufpos Pointer to the first unread valid offset within the
* communication buffer.
* @param buflen Pointer to the number of unread bytes that are ready in
* the communication buffer.
* @param pos Device position to be read.
* @param dst Destination buffer.
* @param size Size of the destination buffer.
* @param block_size Block size to be used for the transfer.
*
* @return True on success, false on failure.
*/
bool libfs_blockread(int phone, void *buffer, off_t *bufpos, size_t *buflen,
off_t *pos, void *dst, size_t size, size_t block_size)
{
off_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) {
/*
* Copy the contents of the communication buffer to the
* destination buffer.
*/
memcpy(dst + offset, buffer + *bufpos, rd);
offset += rd;
*bufpos += rd;
*pos += rd;
left -= rd;
}
if (*bufpos == *buflen) {
/* Refill the communication buffer with a new block. */
ipcarg_t retval;
int rc = async_req_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;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libfs/libfs.h
69,9 → 69,6
 
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
 
extern bool libfs_blockread(int, void *, off_t *, size_t *, off_t *, void *,
size_t, size_t);
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libfs/Makefile
57,7 → 57,7
find . -name '*.o' -follow -exec rm \{\} \;
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
libfs.a: depend $(OBJECTS)
$(AR) rc libfs.a $(OBJECTS)
/branches/tracing/uspace/lib/softfloat/Makefile
66,7 → 66,7
find generic/ -name '*.o' -follow -exec rm \{\} \;
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libsoftfloat.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libsoftfloat.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
/branches/tracing/uspace/lib/libblock/libblock.c
0,0 → 1,298
/*
* Copyright (c) 2008 Jakub Jermar
* 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 libblock
* @{
*/
/**
* @file
* @brief
*/
 
#include "libblock.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <ipc/devmap.h>
#include <ipc/services.h>
#include <errno.h>
#include <sys/mman.h>
#include <async.h>
#include <ipc/ipc.h>
#include <as.h>
#include <assert.h>
#include <futex.h>
#include <libadt/list.h>
 
/** Lock protecting the device connection list */
static futex_t dcl_lock = FUTEX_INITIALIZER;
/** Device connection list head. */
static LIST_INITIALIZE(dcl_head);
 
typedef struct {
link_t link;
int dev_handle;
int dev_phone;
void *com_area;
size_t com_size;
void *bb_buf;
off_t bb_off;
size_t bb_size;
} devcon_t;
 
static devcon_t *devcon_search(dev_handle_t dev_handle)
{
link_t *cur;
 
futex_down(&dcl_lock);
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
devcon_t *devcon = list_get_instance(cur, devcon_t, link);
if (devcon->dev_handle == dev_handle) {
futex_up(&dcl_lock);
return devcon;
}
}
futex_up(&dcl_lock);
return NULL;
}
 
static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
size_t com_size, void *bb_buf, off_t bb_off, size_t bb_size)
{
link_t *cur;
devcon_t *devcon;
 
devcon = malloc(sizeof(devcon_t));
if (!devcon)
return ENOMEM;
link_initialize(&devcon->link);
devcon->dev_handle = dev_handle;
devcon->dev_phone = dev_phone;
devcon->com_area = com_area;
devcon->com_size = com_size;
devcon->bb_buf = bb_buf;
devcon->bb_off = bb_off;
devcon->bb_size = bb_size;
 
futex_down(&dcl_lock);
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
devcon_t *d = list_get_instance(cur, devcon_t, link);
if (d->dev_handle == dev_handle) {
futex_up(&dcl_lock);
free(devcon);
return EEXIST;
}
}
list_append(&devcon->link, &dcl_head);
futex_up(&dcl_lock);
return EOK;
}
 
static void devcon_remove(devcon_t *devcon)
{
futex_down(&dcl_lock);
list_remove(&devcon->link);
futex_up(&dcl_lock);
}
 
int
block_init(dev_handle_t dev_handle, size_t com_size, off_t bb_off,
size_t bb_size)
{
int rc;
int dev_phone;
void *com_area;
void *bb_buf;
bb_buf = malloc(bb_size);
if (!bb_buf)
return ENOMEM;
com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (!com_area) {
free(bb_buf);
return ENOMEM;
}
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
if (dev_phone < 0) {
free(bb_buf);
munmap(com_area, com_size);
return dev_phone;
}
 
rc = ipc_share_out_start(dev_phone, com_area,
AS_AREA_READ | AS_AREA_WRITE);
if (rc != EOK) {
free(bb_buf);
munmap(com_area, com_size);
ipc_hangup(dev_phone);
return rc;
}
rc = devcon_add(dev_handle, dev_phone, com_area, com_size, bb_buf,
bb_off, bb_size);
if (rc != EOK) {
free(bb_buf);
munmap(com_area, com_size);
ipc_hangup(dev_phone);
return rc;
}
 
off_t bufpos = 0;
size_t buflen = 0;
if (!block_read(dev_handle, &bufpos, &buflen, &bb_off,
bb_buf, bb_size, bb_size)) {
block_fini(dev_handle);
return EIO; /* XXX real error code */
}
return EOK;
}
 
void block_fini(dev_handle_t dev_handle)
{
devcon_t *devcon = devcon_search(dev_handle);
assert(devcon);
devcon_remove(devcon);
 
free(devcon->bb_buf);
munmap(devcon->com_area, devcon->com_size);
ipc_hangup(devcon->dev_phone);
 
free(devcon);
}
 
void *block_bb_get(dev_handle_t dev_handle)
{
devcon_t *devcon = devcon_search(dev_handle);
assert(devcon);
return devcon->bb_buf;
}
 
/** Read data from a block device.
*
* @param dev_handle Device handle of the block device.
* @param bufpos Pointer to the first unread valid offset within the
* communication buffer.
* @param buflen Pointer to the number of unread bytes that are ready in
* the communication buffer.
* @param pos Device position to be read.
* @param dst Destination buffer.
* @param size Size of the destination buffer.
* @param block_size Block size to be used for the transfer.
*
* @return True on success, false on failure.
*/
bool
block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst,
size_t size, size_t block_size)
{
off_t offset = 0;
size_t left = size;
devcon_t *devcon = devcon_search(dev_handle);
assert(devcon);
while (left > 0) {
size_t rd;
if (*bufpos + left < *buflen)
rd = left;
else
rd = *buflen - *bufpos;
if (rd > 0) {
/*
* Copy the contents of the communication buffer to the
* destination buffer.
*/
memcpy(dst + offset, devcon->com_area + *bufpos, rd);
offset += rd;
*bufpos += rd;
*pos += rd;
left -= rd;
}
if (*bufpos == *buflen) {
/* Refill the communication buffer with a new block. */
ipcarg_t retval;
int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
*pos / block_size, block_size, &retval);
if ((rc != EOK) || (retval != EOK))
return false;
*bufpos = 0;
*buflen = block_size;
}
}
return true;
}
 
block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
{
/* FIXME */
block_t *b;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = offset * bs;
 
b = malloc(sizeof(block_t));
if (!b)
return NULL;
b->data = malloc(bs);
if (!b->data) {
free(b);
return NULL;
}
b->size = bs;
 
if (!block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
bs, bs)) {
free(b->data);
free(b);
return NULL;
}
 
return b;
}
 
void block_put(block_t *block)
{
/* FIXME */
free(block->data);
free(block);
}
 
/** @}
*/
/branches/tracing/uspace/lib/libblock/libblock.h
0,0 → 1,83
/*
* Copyright (c) 2008 Jakub Jermar
* 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 libblock
* @{
*/
/**
* @file
*/
 
#ifndef LIBBLOCK_LIBBLOCK_H_
#define LIBBLOCK_LIBBLOCK_H_
 
#include <stdint.h>
#include "../../srv/vfs/vfs.h"
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
 
typedef struct block {
/** Futex protecting the reference count. */
futex_t lock;
/** Number of references to the block_t structure. */
unsigned refcnt;
/** If true, the block needs to be written back to the block device. */
bool dirty;
/** Readers / Writer lock protecting the contents of the block. */
rwlock_t contents_lock;
/** Handle of the device where the block resides. */
dev_handle_t dev_handle;
/** Block offset on the block device. Counted in 'size'-byte blocks. */
off_t boff;
/** Size of the block. */
size_t size;
/** Link for placing the block into the free block list. */
link_t free_link;
/** Link for placing the block into the block hash table. */
link_t hash_link;
/** Buffer with the block data. */
void *data;
} block_t;
 
extern int block_init(dev_handle_t, size_t, off_t, size_t);
extern void block_fini(dev_handle_t);
extern void *block_bb_get(dev_handle_t);
 
extern block_t *block_get(dev_handle_t, off_t, size_t);
extern void block_put(block_t *);
 
extern bool block_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t);
 
#endif
 
/** @}
*/
 
/branches/tracing/uspace/lib/libblock/Makefile
0,0 → 1,66
#
# Copyright (c) 2005 Martin Decky
# Copyright (c) 2007 Jakub Jermar
# 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.
#
 
## Common compiler flags
#
 
LIBC_PREFIX = ../libc
## Setup toolchain
#
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -Iinclude
 
## Sources
#
 
SOURCES = \
libblock.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend
 
all: libblock.a
 
-include Makefile.depend
 
clean:
-rm -f libblock.a Makefile.depend
find . -name '*.o' -follow -exec rm \{\} \;
 
depend:
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
libblock.a: depend $(OBJECTS)
$(AR) rc libblock.a $(OBJECTS)
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/tracing/uspace/lib/softint/Makefile
58,7 → 58,7
find generic/ -name '*.o' -follow -exec rm \{\} \;
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libsoftint.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libsoftint.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
/branches/tracing/uspace/lib/libc/include/align.h
35,21 → 35,28
#ifndef LIBC_ALIGN_H_
#define LIBC_ALIGN_H_
 
/** Align to the nearest lower address.
/** Align to the nearest lower address which is a power of two.
*
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
*/
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1))
 
 
/** Align to the nearest higher address.
/** Align to the nearest higher address which is a power of two.
*
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
*/
#define ALIGN_UP(s, a) ((long)((s) + ((a) - 1)) & ~((long) (a) - 1))
 
/** Round up to the nearest higher boundary.
*
* @param n Number to be aligned.
* @param b Boundary, arbitrary unsigned number.
*/
#define ROUND_UP(n, b) (((n) / (b) + ((n) % (b) != 0)) * (b))
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/include/byteorder.h
52,6 → 52,14
#define uint32_t_be2host(n) (n)
#define uint64_t_be2host(n) (n)
 
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_be(n) (n)
#define host2uint32_t_be(n) (n)
#define host2uint64_t_be(n) (n)
 
#else
 
#define uint16_t_le2host(n) (n)
62,6 → 70,14
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n)
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_le(n) (n)
#define host2uint32_t_le(n) (n)
#define host2uint64_t_le(n) (n)
 
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n)
 
#endif
 
static inline uint64_t uint64_t_byteorder_swap(uint64_t n)
/branches/tracing/uspace/lib/libc/include/syscall.h
32,15 → 32,28
/**
* @file
* @brief Syscall function declaration for architectures that don't
* inline syscalls.
* inline syscalls or architectures that handle syscalls
* according to the number of arguments.
*/
 
#ifndef LIBC_SYSCALL_H_
#define LIBC_SYSCALL_H_
 
#ifndef LIBARCH_SYSCALL_GENERIC
#error "You can't include this file directly."
#endif
 
#include <sys/types.h>
#include <kernel/syscall/syscall.h>
 
#define __syscall0 __syscall
#define __syscall1 __syscall
#define __syscall2 __syscall
#define __syscall3 __syscall
#define __syscall4 __syscall
#define __syscall5 __syscall
#define __syscall6 __syscall
 
extern sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2,
const sysarg_t p3, const sysarg_t p4, const sysarg_t p5, const sysarg_t p6,
const syscall_t id);
/branches/tracing/uspace/lib/libc/include/libc.h
39,14 → 39,14
#include <kernel/syscall/syscall.h>
#include <libarch/syscall.h>
 
#define __SYSCALL0(id) __syscall(0, 0, 0, 0, 0, 0, id)
#define __SYSCALL1(id, p1) __syscall(p1, 0, 0, 0, 0, 0, id)
#define __SYSCALL2(id, p1, p2) __syscall(p1, p2, 0, 0, 0, 0, id)
#define __SYSCALL3(id, p1, p2, p3) __syscall(p1, p2, p3, 0, 0, 0, id)
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall(p1, p2, p3, p4, 0, 0, id)
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall(p1, p2, p3, p4, p5, 0, id)
#define __SYSCALL0(id) __syscall0(0, 0, 0, 0, 0, 0, id)
#define __SYSCALL1(id, p1) __syscall1(p1, 0, 0, 0, 0, 0, id)
#define __SYSCALL2(id, p1, p2) __syscall2(p1, p2, 0, 0, 0, 0, id)
#define __SYSCALL3(id, p1, p2, p3) __syscall3(p1, p2, p3, 0, 0, 0, id)
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall4(p1, p2, p3, p4, 0, 0, id)
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall5(p1, p2, p3, p4, p5, 0, id)
#define __SYSCALL6(id, p1, p2, p3, p4, p5, p6) \
__syscall(p1, p2, p3, p4, p5, p6,id)
__syscall6(p1, p2, p3, p4, p5, p6, id)
 
extern void __main(void *pcb_ptr);
extern void __exit(void);
/branches/tracing/uspace/lib/libc/include/loader/loader.h
36,6 → 36,8
#ifndef LIBC_LOADER_H_
#define LIBC_LOADER_H_
 
#include <task.h>
 
/** Abstraction of a loader connection */
typedef struct {
/** ID of the phone connected to the loader. */
/branches/tracing/uspace/lib/libc/include/ipc/ipc.h
283,8 → 283,9
extern int ipc_share_out_finalize(ipc_callid_t callid, void *dst);
extern int ipc_data_read_start(int phoneid, void *dst, size_t size);
extern int ipc_data_read_receive(ipc_callid_t *callid, size_t *size);
extern int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size);
extern int ipc_data_write_start(int phoneid, void *src, size_t size);
extern int ipc_data_read_finalize(ipc_callid_t callid, const void *src,
size_t size);
extern int ipc_data_write_start(int phoneid, const void *src, size_t size);
extern int ipc_data_write_receive(ipc_callid_t *callid, size_t *size);
extern int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size);
 
/branches/tracing/uspace/lib/libc/include/errno.h
46,6 → 46,7
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
 
#endif
 
/branches/tracing/uspace/lib/libc/Makefile.toolchain
27,7 → 27,7
#
 
DEFS = -DARCH=$(ARCH)
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -I$(LIBC_PREFIX)/include
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -I$(LIBC_PREFIX)/include -pipe
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS =
#-Werror
/branches/tracing/uspace/lib/libc/generic/time.c
47,6 → 47,8
#include <as.h>
#include <ddi.h>
 
#include <time.h>
 
/* Pointers to public variables with time */
struct {
volatile sysarg_t seconds1;
/branches/tracing/uspace/lib/libc/generic/tls.c
116,7 → 116,7
tcb_t *tcb;
size = ALIGN_UP(size, &_tls_alignment);
*data = memalign(&_tls_alignment, sizeof(tcb_t) + size);
*data = memalign((uintptr_t) &_tls_alignment, sizeof(tcb_t) + size);
 
tcb = (tcb_t *) (*data + size);
tcb->self = tcb;
/branches/tracing/uspace/lib/libc/generic/loader.c
35,6 → 35,7
#include <ipc/ipc.h>
#include <ipc/loader.h>
#include <libc.h>
#include <task.h>
#include <string.h>
#include <stdlib.h>
#include <async.h>
93,7 → 94,7
 
/* Get task ID. */
req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id));
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
/branches/tracing/uspace/lib/libc/generic/ipc.c
847,7 → 847,7
*
* @return Zero on success or a value from @ref errno.h on failure.
*/
int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size)
int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
{
return ipc_answer_2(callid, EOK, (ipcarg_t) src, (ipcarg_t) size);
}
860,7 → 860,7
*
* @return Zero on success or a negative error code from errno.h.
*/
int ipc_data_write_start(int phoneid, void *src, size_t size)
int ipc_data_write_start(int phoneid, const void *src, size_t size)
{
return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
(ipcarg_t) size);
/branches/tracing/uspace/lib/libc/generic/udebug.c
34,7 → 34,6
 
#include <udebug.h>
#include <sys/types.h>
#include <syscall.h>
#include <ipc/ipc.h>
#include <async.h>
 
/branches/tracing/uspace/lib/libc/generic/vfs/vfs.c
116,7 → 116,7
return vfs_phone;
}
 
static int device_get_handle(char *name, dev_handle_t *handle)
static int device_get_handle(const char *name, dev_handle_t *handle)
{
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT,
0);
364,9 → 364,9
}
}
off_t newoffs;
ipcarg_t newoffs;
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
(ipcarg_t)&newoffs);
&newoffs);
 
async_serialize_end();
futex_up(&vfs_phone_futex);
374,7 → 374,7
if (rc != EOK)
return (off_t) -1;
return newoffs;
return (off_t) newoffs;
}
 
int ftruncate(int fildes, off_t length)
/branches/tracing/uspace/lib/libc/generic/vfs/canonify.c
36,6 → 36,7
*/
 
#include <stdlib.h>
#include <vfs/canonify.h>
 
/** Token types used for tokenization of path. */
typedef enum {
/branches/tracing/uspace/lib/libc/generic/smc.c
34,6 → 34,7
 
#include <libc.h>
#include <sys/types.h>
#include <smc.h>
 
int smc_coherence(void *address, size_t size)
{
/branches/tracing/uspace/lib/libc/Makefile
106,7 → 106,7
find generic/ arch/$(ARCH)/ -name '*.o' -follow -exec rm \{\} \;
 
depend: kerninc
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
/branches/tracing/uspace/lib/libc/arch/sparc64/include/syscall.h
38,6 → 38,14
#include <sys/types.h>
#include <kernel/syscall/syscall.h>
 
#define __syscall0 __syscall
#define __syscall1 __syscall
#define __syscall2 __syscall
#define __syscall3 __syscall
#define __syscall4 __syscall
#define __syscall5 __syscall
#define __syscall6 __syscall
 
static inline sysarg_t
__syscall(const sysarg_t p1, const sysarg_t p2, const sysarg_t p3,
const sysarg_t p4, const sysarg_t p5, const sysarg_t p6, const syscall_t id)
/branches/tracing/uspace/lib/libc/arch/ia64/include/syscall.h
36,6 → 36,8
#ifndef LIBC_ia64_SYSCALL_H_
#define LIBC_ia64_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/tracing/uspace/lib/libc/arch/arm32/include/syscall.h
30,12 → 30,14
* @{
*/
/** @file
* @brief Empty.
* @brief
*/
 
#ifndef LIBC_arm32_SYSCALL_H_
#define LIBC_arm32_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/tracing/uspace/lib/libc/arch/ppc32/include/syscall.h
36,6 → 36,8
#ifndef LIBC_ppc32_SYSCALL_H_
#define LIBC_ppc32_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/tracing/uspace/lib/libc/arch/amd64/include/syscall.h
36,6 → 36,8
#ifndef LIBC_amd64_SYSCALL_H_
#define LIBC_amd64_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/tracing/uspace/lib/libc/arch/ppc64/include/syscall.h
36,6 → 36,8
#ifndef LIBC_ppc64_SYSCALL_H_
#define LIBC_ppc64_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/tracing/uspace/lib/libc/arch/mips32/include/syscall.h
36,6 → 36,8
#ifndef LIBC_mips32_SYSCALL_H_
#define LIBC_mips32_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/tracing/uspace/lib/libc/arch/ia32/include/syscall.h
36,8 → 36,25
#ifndef LIBC_ia32_SYSCALL_H_
#define LIBC_ia32_SYSCALL_H_
 
#include <syscall.h>
#include <sys/types.h>
#include <kernel/syscall/syscall.h>
 
#define __syscall0 __syscall_sysenter
#define __syscall1 __syscall_sysenter
#define __syscall2 __syscall_sysenter
#define __syscall3 __syscall_sysenter
#define __syscall4 __syscall_sysenter
#define __syscall5 __syscall_int
#define __syscall6 __syscall_int
 
extern sysarg_t
__syscall_sysenter(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t,
const sysarg_t, const sysarg_t, const syscall_t);
 
extern sysarg_t
__syscall_int(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t,
const sysarg_t, const sysarg_t, const syscall_t);
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/arch/ia32/src/syscall.S
28,14 → 28,14
 
.text
 
/** Syscall wrapper.
/** Syscall wrapper - INT $0x30 version.
*
* Mind the order of arguments. First two arguments and the syscall number go to
* scratch registers. An optimized version of this wrapper for fewer arguments
* could benefit from this and not save unused registers on the stack.
*/
.global __syscall
__syscall:
.global __syscall_int
__syscall_int:
pushl %ebx
pushl %esi
pushl %edi
53,3 → 53,38
popl %esi
popl %ebx
ret
 
 
/** Syscall wrapper - SYSENTER version.
*
* This is an optimized version of syscall for four or less arguments. Note
* that EBP and EDI are used to remember user stack address and the return
* address. The kernel part doesn't save DS, ES and FS so the handler restores
* these to the selector immediately following CS (it must be the flat data
* segment, otherwise the SYSENTER wouldn't work in the first place).
*/
.global __syscall_sysenter
__syscall_sysenter:
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
mov %esp, %ebp
lea ra, %edi
movl 20(%esp), %edx # First argument.
movl 24(%esp), %ecx # Second argument.
movl 28(%esp), %ebx # Third argument.
movl 32(%esp), %esi # Fourth argument.
movl 44(%esp), %eax # Syscall number.
sysenter
ra:
movw %cs, %cx
addw $8, %cx
movw %cx, %ds
movw %cx, %es
movw %cx, %fs
popl %ebp
popl %edi
popl %esi
popl %ebx
ret
/branches/tracing/uspace/srv/loader/main.c
100,7 → 100,7
 
if (len > sizeof(task_id)) len = sizeof(task_id);
 
ipc_data_write_finalize(callid, &task_id, len);
ipc_data_read_finalize(callid, &task_id, len);
ipc_answer_0(rid, EOK);
}
 
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_dump.c
38,17 → 38,12
 
#include "tmpfs.h"
#include "../../vfs/vfs.h"
#include <ipc/ipc.h>
#include <async.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <as.h>
#include <libfs.h>
#include <ipc/services.h>
#include <ipc/devmap.h>
#include <sys/mman.h>
#include <libblock.h>
#include <byteorder.h>
 
#define TMPFS_BLOCK_SIZE 1024
59,8 → 54,8
} __attribute__((packed));
 
static bool
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen,
off_t *pos, tmpfs_dentry_t *parent)
tmpfs_restore_recursion(int dev, off_t *bufpos, size_t *buflen, off_t *pos,
tmpfs_dentry_t *parent)
{
struct rdentry entry;
libfs_ops_t *ops = &tmpfs_libfs_ops;
70,8 → 65,8
tmpfs_dentry_t *node;
uint32_t size;
if (!libfs_blockread(phone, block, bufpos, buflen, pos, &entry,
sizeof(entry), TMPFS_BLOCK_SIZE))
if (!block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
TMPFS_BLOCK_SIZE))
return false;
entry.len = uint32_t_le2host(entry.len);
90,8 → 85,8
return false;
}
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
if (!block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE)) {
ops->destroy((void *) node);
free(fname);
return false;
105,8 → 100,8
}
free(fname);
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
&size, sizeof(size), TMPFS_BLOCK_SIZE))
if (!block_read(dev, bufpos, buflen, pos, &size,
sizeof(size), TMPFS_BLOCK_SIZE))
return false;
size = uint32_t_le2host(size);
116,8 → 111,8
return false;
node->size = size;
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
node->data, size, TMPFS_BLOCK_SIZE))
if (!block_read(dev, bufpos, buflen, pos, node->data,
size, TMPFS_BLOCK_SIZE))
return false;
break;
132,7 → 127,7
return false;
}
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
if (!block_read(dev, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
ops->destroy((void *) node);
free(fname);
147,8 → 142,8
}
free(fname);
if (!tmpfs_restore_recursion(phone, block, bufpos,
buflen, pos, node))
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
node))
return false;
break;
163,31 → 158,18
bool tmpfs_restore(dev_handle_t dev)
{
libfs_ops_t *ops = &tmpfs_libfs_ops;
int rc;
 
void *block = mmap(NULL, TMPFS_BLOCK_SIZE,
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
rc = block_init(dev, TMPFS_BLOCK_SIZE, 0, 0);
if (rc != EOK)
return false;
if (block == NULL)
return false;
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev);
 
if (phone < 0) {
munmap(block, TMPFS_BLOCK_SIZE);
return false;
}
if (ipc_share_out_start(phone, block, AS_AREA_READ | AS_AREA_WRITE) !=
EOK)
goto error;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = 0;
char tag[6];
if (!libfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5,
if (!block_read(dev, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE))
goto error;
195,17 → 177,15
if (strcmp(tag, "TMPFS") != 0)
goto error;
if (!tmpfs_restore_recursion(phone, block, &bufpos, &buflen, &pos,
if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos,
ops->root_get(dev)))
goto error;
ipc_hangup(phone);
munmap(block, TMPFS_BLOCK_SIZE);
block_fini(dev);
return true;
error:
ipc_hangup(phone);
munmap(block, TMPFS_BLOCK_SIZE);
block_fini(dev);
return false;
}
 
/branches/tracing/uspace/srv/fs/tmpfs/Makefile
31,12 → 31,16
 
LIBC_PREFIX = ../../../lib/libc
LIBFS_PREFIX = ../../../lib/libfs
LIBBLOCK_PREFIX = ../../../lib/libblock
SOFTINT_PREFIX = ../../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I $(LIBFS_PREFIX)
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX)
 
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a
LIBS = \
$(LIBFS_PREFIX)/libfs.a \
$(LIBBLOCK_PREFIX)/libblock.a \
$(LIBC_PREFIX)/libc.a
 
## Sources
#
/branches/tracing/uspace/srv/fs/fat/fat.h
33,6 → 33,7
#ifndef FAT_FAT_H_
#define FAT_FAT_H_
 
#include "fat_fat.h"
#include <ipc/ipc.h>
#include <libfs.h>
#include <atomic.h>
44,7 → 45,12
#define dprintf(...) printf(__VA_ARGS__)
#endif
 
typedef struct {
#define min(a, b) ((a) < (b) ? (a) : (b))
 
#define BS_BLOCK 0
#define BS_SIZE 512
 
typedef struct fat_bs {
uint8_t ji[3]; /**< Jump instruction. */
uint8_t oem_name[8];
/* BIOS Parameter Block */
115,34 → 121,6
};
} __attribute__ ((packed)) fat_bs_t;
 
#define FAT_ATTR_RDONLY (1 << 0)
#define FAT_ATTR_VOLLABEL (1 << 3)
#define FAT_ATTR_SUBDIR (1 << 4)
 
typedef struct {
uint8_t name[8];
uint8_t ext[3];
uint8_t attr;
uint8_t reserved;
uint8_t ctime_fine;
uint16_t ctime;
uint16_t cdate;
uint16_t adate;
union {
uint16_t eaidx; /* FAT12/FAT16 */
uint16_t firstc_hi; /* FAT32 */
};
uint16_t mtime;
uint16_t mdate;
union {
uint16_t firstc; /* FAT12/FAT16 */
uint16_t firstc_lo; /* FAT32 */
};
uint32_t size;
} __attribute__ ((packed)) fat_dentry_t;
 
typedef uint16_t fat_cluster_t;
 
typedef enum {
FAT_INVALID,
FAT_DIRECTORY,
223,6 → 201,7
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 void fat_write(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_dentry.c
0,0 → 1,100
/*
* Copyright (c) 2008 Jakub Jermar
* 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 fat_dentry.c
* @brief Functions that work with FAT directory entries.
*/
 
#include "fat_dentry.h"
 
#define FAT_PAD ' '
 
#define FAT_DENTRY_UNUSED 0x00
#define FAT_DENTRY_E5_ESC 0x05
#define FAT_DENTRY_DOT 0x2e
#define FAT_DENTRY_ERASED 0xe5
 
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)
break;
if (d->name[i] == FAT_DENTRY_E5_ESC)
*buf++ = 0xe5;
else
*buf++ = d->name[i];
}
if (d->ext[0] != FAT_PAD)
*buf++ = '.';
for (i = 0; i < FAT_EXT_LEN; i++) {
if (d->ext[i] == FAT_PAD) {
*buf = '\0';
return;
}
if (d->ext[i] == FAT_DENTRY_E5_ESC)
*buf++ = 0xe5;
else
*buf++ = d->ext[i];
}
*buf = '\0';
}
 
fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d)
{
if (d->attr & FAT_ATTR_VOLLABEL) {
/* volume label entry */
return FAT_DENTRY_SKIP;
}
if (d->name[0] == FAT_DENTRY_ERASED) {
/* not-currently-used entry */
return FAT_DENTRY_SKIP;
}
if (d->name[0] == FAT_DENTRY_UNUSED) {
/* never used entry */
return FAT_DENTRY_LAST;
}
if (d->name[0] == FAT_DENTRY_DOT) {
/*
* Most likely '.' or '..'.
* It cannot occur in a regular file name.
*/
return FAT_DENTRY_SKIP;
}
return FAT_DENTRY_VALID;
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/fat_dentry.h
0,0 → 1,80
/*
* Copyright (c) 2008 Jakub Jermar
* 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
* @{
*/
 
#ifndef FAT_FAT_DENTRY_H_
#define FAT_FAT_DENTRY_H_
 
#include <stdint.h>
 
#define FAT_NAME_LEN 8
#define FAT_EXT_LEN 3
 
#define FAT_ATTR_RDONLY (1 << 0)
#define FAT_ATTR_VOLLABEL (1 << 3)
#define FAT_ATTR_SUBDIR (1 << 4)
 
typedef enum {
FAT_DENTRY_SKIP,
FAT_DENTRY_LAST,
FAT_DENTRY_VALID
} fat_dentry_clsf_t;
 
typedef struct {
uint8_t name[8];
uint8_t ext[3];
uint8_t attr;
uint8_t reserved;
uint8_t ctime_fine;
uint16_t ctime;
uint16_t cdate;
uint16_t adate;
union {
uint16_t eaidx; /* FAT12/FAT16 */
uint16_t firstc_hi; /* FAT32 */
};
uint16_t mtime;
uint16_t mdate;
union {
uint16_t firstc; /* FAT12/FAT16 */
uint16_t firstc_lo; /* FAT32 */
};
uint32_t size;
} __attribute__ ((packed)) fat_dentry_t;
 
extern void dentry_name_canonify(fat_dentry_t *, char *);
extern fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *);
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/fat_fat.c
0,0 → 1,384
/*
* Copyright (c) 2008 Jakub Jermar
* 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 fat_fat.c
* @brief Functions that manipulate the File Allocation Tables.
*/
 
#include "fat_fat.h"
#include "fat_dentry.h"
#include "fat.h"
#include "../../vfs/vfs.h"
#include <libfs.h>
#include <libblock.h>
#include <errno.h>
#include <byteorder.h>
#include <align.h>
#include <assert.h>
#include <futex.h>
 
/**
* The fat_alloc_lock futex protects all copies of the File Allocation Table
* during allocation of clusters. The lock does not have to be held durring
* deallocation of clusters.
*/
static futex_t fat_alloc_lock = FUTEX_INITIALIZER;
 
/** Read block from file located on a FAT file system.
*
* @param bs Buffer holding the boot sector of the file system.
* @param dev_handle Device handle of the file system.
* @param firstc First cluster used by the file. Can be zero if the file
* is empty.
* @param offset Offset in blocks.
*
* @return Block structure holding the requested block.
*/
block_t *
_fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
off_t offset)
{
block_t *b;
unsigned bps;
unsigned spc;
unsigned rscnt; /* block address of the first FAT */
unsigned fatcnt;
unsigned rde;
unsigned rds; /* root directory size */
unsigned sf;
unsigned ssa; /* size of the system area */
unsigned clusters;
fat_cluster_t clst = firstc;
unsigned i;
 
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
rscnt = uint16_t_le2host(bs->rscnt);
fatcnt = bs->fatcnt;
rde = uint16_t_le2host(bs->root_ent_max);
sf = uint16_t_le2host(bs->sec_per_fat);
 
rds = (sizeof(fat_dentry_t) * rde) / bps;
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
ssa = rscnt + fatcnt * sf + rds;
 
if (firstc == FAT_CLST_ROOT) {
/* root directory special case */
assert(offset < rds);
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps);
return b;
}
 
clusters = offset / spc;
for (i = 0; i < clusters; i++) {
unsigned fsec; /* sector offset relative to FAT1 */
unsigned fidx; /* FAT1 entry index */
 
assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD);
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);
assert(clst < FAT_CLST_LAST1);
block_put(b);
}
 
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc +
offset % spc, bps);
 
return b;
}
 
/** Return number of blocks allocated to a file.
*
* @param bs Buffer holding the boot sector for the file.
* @param dev_handle Device handle of the device with the file.
* @param firstc First cluster of the file.
* @param lastc If non-NULL, output argument holding the
* last cluster.
*
* @return Number of blocks allocated to the file.
*/
uint16_t
_fat_blcks_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
fat_cluster_t *lastc)
{
block_t *b;
unsigned bps;
unsigned spc;
unsigned rscnt; /* block address of the first FAT */
unsigned clusters = 0;
fat_cluster_t clst = firstc;
 
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
rscnt = uint16_t_le2host(bs->rscnt);
 
if (firstc == FAT_CLST_RES0) {
/* No space allocated to the file. */
if (lastc)
*lastc = firstc;
return 0;
}
 
while (clst < FAT_CLST_LAST1) {
unsigned fsec; /* sector offset relative to FAT1 */
unsigned fidx; /* FAT1 entry index */
 
assert(clst >= FAT_CLST_FIRST);
if (lastc)
*lastc = clst; /* remember the last cluster */
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++;
}
 
if (lastc)
*lastc = clst;
return clusters * spc;
}
 
/** Fill the gap between EOF and a new file position.
*
* @param bs Buffer holding the boot sector for nodep.
* @param nodep FAT node with the gap.
* @param mcl First cluster in an independent cluster chain that will
* be later appended to the end of the node's own cluster
* chain. If pos is still in the last allocated cluster,
* this argument is ignored.
* @param pos Position in the last node block.
*/
void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
{
uint16_t bps;
unsigned spc;
block_t *b;
off_t o, boundary;
 
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
boundary = ROUND_UP(nodep->size, bps * spc);
 
/* zero out already allocated space */
for (o = nodep->size - 1; o < pos && o < boundary;
o = ALIGN_DOWN(o + bps, bps)) {
b = fat_block_get(bs, nodep, o / bps);
memset(b->data + o % bps, 0, bps - o % bps);
b->dirty = true; /* need to sync node */
block_put(b);
}
if (o >= pos)
return;
/* zero out the initial part of the new cluster chain */
for (o = boundary; o < pos; o += bps) {
b = _fat_block_get(bs, nodep->idx->dev_handle, mcl,
(o - boundary) / bps);
memset(b->data, 0, min(bps, pos - o));
b->dirty = true; /* need to sync node */
block_put(b);
}
}
 
/** Mark cluster in one instance of FAT.
*
* @param bs Buffer holding the boot sector for the file system.
* @param dev_handle Device handle for the file system.
* @param fatno Number of the FAT instance where to make the change.
* @param clst Cluster which is to be marked.
* @param value Value mark the cluster with.
*/
void
fat_mark_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno,
fat_cluster_t clst, fat_cluster_t value)
{
block_t *b;
uint16_t bps;
uint16_t rscnt;
uint16_t sf;
fat_cluster_t *cp;
 
bps = uint16_t_le2host(bs->bps);
rscnt = uint16_t_le2host(bs->rscnt);
sf = uint16_t_le2host(bs->sec_per_fat);
 
assert(fatno < bs->fatcnt);
b = block_get(dev_handle, rscnt + sf * fatno +
(clst * sizeof(fat_cluster_t)) / bps, bps);
cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
*cp = host2uint16_t_le(value);
b->dirty = true; /* need to sync block */
block_put(b);
}
 
/** Replay the allocatoin of clusters in all shadow instances of FAT.
*
* @param bs Buffer holding the boot sector of the file system.
* @param dev_handle Device handle of the file system.
* @param lifo Chain of allocated clusters.
* @param nclsts Number of clusters in the lifo chain.
*/
void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle,
fat_cluster_t *lifo, unsigned nclsts)
{
uint8_t fatno;
unsigned c;
 
for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
for (c = 0; c < nclsts; c++) {
fat_mark_cluster(bs, dev_handle, fatno, lifo[c],
c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
}
}
}
 
/** Allocate clusters in FAT1.
*
* This function will attempt to allocate the requested number of clusters in
* the first FAT instance. The FAT will be altered so that the allocated
* clusters form an independent chain (i.e. a chain which does not belong to any
* file yet).
*
* @param bs Buffer holding the boot sector of the file system.
* @param dev_handle Device handle of the file system.
* @param nclsts Number of clusters to allocate.
* @param mcl Output parameter where the first cluster in the chain
* will be returned.
* @param lcl Output parameter where the last cluster in the chain
* will be returned.
*
* @return EOK on success, a negative error code otherwise.
*/
int
fat_alloc_clusters(fat_bs_t *bs, dev_handle_t dev_handle, unsigned nclsts,
fat_cluster_t *mcl, fat_cluster_t *lcl)
{
uint16_t bps;
uint16_t rscnt;
uint16_t sf;
block_t *blk;
fat_cluster_t *lifo; /* stack for storing free cluster numbers */
unsigned found = 0; /* top of the free cluster number stack */
unsigned b, c, cl;
 
lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
if (lifo)
return ENOMEM;
bps = uint16_t_le2host(bs->bps);
rscnt = uint16_t_le2host(bs->rscnt);
sf = uint16_t_le2host(bs->sec_per_fat);
/*
* Search FAT1 for unused clusters.
*/
futex_down(&fat_alloc_lock);
for (b = 0, cl = 0; b < sf; blk++) {
blk = block_get(dev_handle, rscnt + b, bps);
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
/*
* The cluster is free. Put it into our stack
* of found clusters and mark it as non-free.
*/
lifo[found] = cl;
*clst = (found == 0) ?
host2uint16_t_le(FAT_CLST_LAST1) :
host2uint16_t_le(lifo[found - 1]);
blk->dirty = true; /* need to sync block */
if (++found == nclsts) {
/* we are almost done */
block_put(blk);
/* update the shadow copies of FAT */
fat_alloc_shadow_clusters(bs,
dev_handle, lifo, nclsts);
*mcl = lifo[found - 1];
*lcl = lifo[0];
free(lifo);
futex_up(&fat_alloc_lock);
return EOK;
}
}
}
block_put(blk);
}
futex_up(&fat_alloc_lock);
 
/*
* We could not find enough clusters. Now we need to free the clusters
* we have allocated so far.
*/
while (found--) {
fat_mark_cluster(bs, dev_handle, FAT1, lifo[found],
FAT_CLST_RES0);
}
free(lifo);
return ENOSPC;
}
 
/** Append a cluster chain to the last file cluster in all FATs.
*
* @param bs Buffer holding boot sector of the file system.
* @param nodep Node representing the file.
* @param mcl First cluster of the cluster chain to append.
*/
void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl)
{
dev_handle_t dev_handle = nodep->idx->dev_handle;
fat_cluster_t lcl;
uint8_t fatno;
 
if (_fat_blcks_get(bs, dev_handle, nodep->firstc, &lcl) == 0) {
nodep->firstc = host2uint16_t_le(mcl);
nodep->dirty = true; /* need to sync node */
return;
}
 
for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
fat_mark_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl);
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/fat_fat.h
0,0 → 1,83
/*
* Copyright (c) 2008 Jakub Jermar
* 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
* @{
*/
 
#ifndef FAT_FAT_FAT_H_
#define FAT_FAT_FAT_H_
 
#include "../../vfs/vfs.h"
#include <stdint.h>
 
#define FAT1 0
 
#define FAT_CLST_RES0 0x0000
#define FAT_CLST_RES1 0x0001
#define FAT_CLST_FIRST 0x0002
#define FAT_CLST_BAD 0xfff7
#define FAT_CLST_LAST1 0xfff8
#define FAT_CLST_LAST8 0xffff
 
/* internally used to mark root directory's parent */
#define FAT_CLST_ROOTPAR FAT_CLST_RES0
/* internally used to mark root directory */
#define FAT_CLST_ROOT FAT_CLST_RES1
 
/* forward declarations */
struct block;
struct fat_node;
struct fat_bs;
 
typedef uint16_t fat_cluster_t;
 
#define fat_block_get(bs, np, off) \
_fat_block_get((bs), (np)->idx->dev_handle, (np)->firstc, (off))
extern struct block *_fat_block_get(struct fat_bs *, dev_handle_t,
fat_cluster_t, off_t);
extern uint16_t _fat_blcks_get(struct fat_bs *, dev_handle_t, fat_cluster_t,
fat_cluster_t *);
extern void fat_append_clusters(struct fat_bs *, struct fat_node *,
fat_cluster_t);
extern int fat_alloc_clusters(struct fat_bs *, dev_handle_t, unsigned,
fat_cluster_t *, fat_cluster_t *);
extern void fat_alloc_shadow_clusters(struct fat_bs *, dev_handle_t,
fat_cluster_t *, unsigned);
extern void fat_mark_cluster(struct fat_bs *, dev_handle_t, unsigned,
fat_cluster_t, fat_cluster_t);
extern void fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
off_t);
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/fat.c
110,6 → 110,9
case VFS_READ:
fat_read(callid, &call);
break;
case VFS_WRITE:
fat_write(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/tracing/uspace/srv/fs/fat/fat_ops.c
36,8 → 36,11
*/
 
#include "fat.h"
#include "fat_dentry.h"
#include "fat_fat.h"
#include "../../vfs/vfs.h"
#include <libfs.h>
#include <libblock.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/devmap.h>
50,10 → 53,8
#include <assert.h>
#include <futex.h>
#include <sys/mman.h>
#include <align.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;
 
60,216 → 61,6
/** List of cached free FAT nodes. */
static LIST_INITIALIZE(ffn_head);
 
#define FAT_NAME_LEN 8
#define FAT_EXT_LEN 3
 
#define FAT_PAD ' '
 
#define FAT_DENTRY_UNUSED 0x00
#define FAT_DENTRY_E5_ESC 0x05
#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)
break;
if (d->name[i] == FAT_DENTRY_E5_ESC)
*buf++ = 0xe5;
else
*buf++ = d->name[i];
}
if (d->ext[0] != FAT_PAD)
*buf++ = '.';
for (i = 0; i < FAT_EXT_LEN; i++) {
if (d->ext[i] == FAT_PAD) {
*buf = '\0';
return;
}
if (d->ext[i] == FAT_DENTRY_E5_ESC)
*buf++ = 0xe5;
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, size_t bs)
{
/* 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)
{
/* FIXME */
free(block->data);
free(block);
}
 
#define FAT_BS(b) ((fat_bs_t *)((b)->data))
 
#define FAT_CLST_RES0 0x0000
#define FAT_CLST_RES1 0x0001
#define FAT_CLST_FIRST 0x0002
#define FAT_CLST_BAD 0xfff7
#define FAT_CLST_LAST1 0xfff8
#define FAT_CLST_LAST8 0xffff
 
/* internally used to mark root directory's parent */
#define FAT_CLST_ROOTPAR FAT_CLST_RES0
/* internally used to mark root directory */
#define FAT_CLST_ROOT FAT_CLST_RES1
 
#define fat_block_get(np, off) \
_fat_block_get((np)->idx->dev_handle, (np)->firstc, (off))
 
static block_t *
_fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset)
{
block_t *bb;
block_t *b;
unsigned bps;
unsigned spc;
unsigned rscnt; /* block address of the first FAT */
unsigned fatcnt;
unsigned rde;
unsigned rds; /* root directory size */
unsigned sf;
unsigned ssa; /* size of the system area */
unsigned clusters;
fat_cluster_t clst = firstc;
unsigned i;
 
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);
fatcnt = FAT_BS(bb)->fatcnt;
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);
sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);
block_put(bb);
 
rds = (sizeof(fat_dentry_t) * rde) / bps;
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
ssa = rscnt + fatcnt * sf + rds;
 
if (firstc == FAT_CLST_ROOT) {
/* root directory special case */
assert(offset < rds);
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps);
return b;
}
 
clusters = offset / spc;
for (i = 0; i < clusters; i++) {
unsigned fsec; /* sector offset relative to FAT1 */
unsigned fidx; /* FAT1 entry index */
 
assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD);
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);
assert(clst < FAT_CLST_LAST1);
block_put(b);
}
 
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * 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);
282,54 → 73,35
node->dirty = false;
}
 
static uint16_t fat_bps_get(dev_handle_t dev_handle)
static void fat_node_sync(fat_node_t *node)
{
block_t *bb;
block_t *b;
fat_bs_t *bs;
fat_dentry_t *d;
uint16_t bps;
unsigned dps;
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
assert(bb != NULL);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
block_put(bb);
assert(node->dirty);
 
return bps;
}
bs = block_bb_get(node->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc,
(node->idx->pdi * sizeof(fat_dentry_t)) / bps);
 
typedef enum {
FAT_DENTRY_SKIP,
FAT_DENTRY_LAST,
FAT_DENTRY_VALID
} fat_dentry_clsf_t;
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
 
static fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d)
{
if (d->attr & FAT_ATTR_VOLLABEL) {
/* volume label entry */
return FAT_DENTRY_SKIP;
}
if (d->name[0] == FAT_DENTRY_ERASED) {
/* not-currently-used entry */
return FAT_DENTRY_SKIP;
}
if (d->name[0] == FAT_DENTRY_UNUSED) {
/* never used entry */
return FAT_DENTRY_LAST;
}
if (d->name[0] == FAT_DENTRY_DOT) {
/*
* Most likely '.' or '..'.
* It cannot occur in a regular file name.
*/
return FAT_DENTRY_SKIP;
}
return FAT_DENTRY_VALID;
d->firstc = host2uint16_t_le(node->firstc);
if (node->type == FAT_FILE)
d->size = host2uint32_t_le(node->size);
/* TODO: update other fields? (e.g time fields, attr field) */
b->dirty = true; /* need to sync block */
block_put(b);
}
 
static void fat_node_sync(fat_node_t *node)
{
/* TODO */
}
 
/** Internal version of fat_node_get().
*
* @param idxp Locked index structure.
337,6 → 109,7
static void *fat_node_get_core(fat_idx_t *idxp)
{
block_t *b;
fat_bs_t *bs;
fat_dentry_t *d;
fat_node_t *nodep = NULL;
unsigned bps;
389,11 → 162,12
}
fat_node_initialize(nodep);
 
bps = fat_bps_get(idxp->dev_handle);
bs = block_bb_get(idxp->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
 
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(idxp->dev_handle, idxp->pfc,
b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc,
(idxp->pdi * sizeof(fat_dentry_t)) / bps);
assert(b);
 
410,8 → 184,8
* 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));
nodep->size = bps * _fat_blcks_get(bs, idxp->dev_handle,
uint16_t_le2host(d->firstc), NULL);
} else {
nodep->type = FAT_FILE;
nodep->size = uint32_t_le2host(d->size);
479,6 → 253,7
 
static void *fat_match(void *prnt, const char *component)
{
fat_bs_t *bs;
fat_node_t *parentp = (fat_node_t *)prnt;
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
unsigned i, j;
489,17 → 264,13
block_t *b;
 
futex_down(&parentp->idx->lock);
bps = fat_bps_get(parentp->idx->dev_handle);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
blocks = parentp->size / bps + (parentp->size % bps != 0);
blocks = parentp->size / bps;
for (i = 0; i < blocks; i++) {
unsigned dentries;
b = fat_block_get(parentp, i);
dentries = (i == blocks - 1) ?
parentp->size % sizeof(fat_dentry_t) :
dps;
for (j = 0; j < dentries; j++) {
b = fat_block_get(bs, parentp, i);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
542,6 → 313,7
}
block_put(b);
}
 
futex_up(&parentp->idx->lock);
return NULL;
}
566,6 → 338,7
 
static bool fat_has_children(void *node)
{
fat_bs_t *bs;
fat_node_t *nodep = (fat_node_t *)node;
unsigned bps;
unsigned dps;
575,22 → 348,19
 
if (nodep->type != FAT_DIRECTORY)
return false;
 
futex_down(&nodep->idx->lock);
bps = fat_bps_get(nodep->idx->dev_handle);
bs = block_bb_get(nodep->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
 
blocks = nodep->size / bps + (nodep->size % bps != 0);
blocks = nodep->size / bps;
 
for (i = 0; i < blocks; i++) {
unsigned dentries;
fat_dentry_t *d;
b = fat_block_get(nodep, i);
dentries = (i == blocks - 1) ?
nodep->size % sizeof(fat_dentry_t) :
dps;
for (j = 0; j < dentries; j++) {
b = fat_block_get(bs, nodep, i);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
658,50 → 428,27
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
block_t *bb;
fat_bs_t *bs;
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);
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE, BS_BLOCK * BS_SIZE, BS_SIZE);
if (rc != EOK) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, rc);
ipc_answer_0(rid, 0);
return;
}
 
/* get the buffer with the boot sector */
bs = block_bb_get(dev_handle);
/* Read the number of root directory entries. */
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);
bps = uint16_t_le2host(bs->bps);
rde = uint16_t_le2host(bs->root_ent_max);
 
if (bps != BS_SIZE) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
ipc_answer_0(rid, ENOTSUP);
return;
}
708,7 → 455,7
 
rc = fat_idx_init_by_dev_handle(dev_handle);
if (rc != EOK) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
ipc_answer_0(rid, rc);
return;
}
716,7 → 463,7
/* Initialize the root node. */
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
725,7 → 472,7
 
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
if (!ridxp) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
free(rootp);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
763,7 → 510,8
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);
fat_bs_t *bs;
uint16_t bps;
size_t bytes;
block_t *b;
 
781,6 → 529,9
return;
}
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
 
if (nodep->type == FAT_FILE) {
/*
* Our strategy for regular file reads is to read one block at
787,11 → 538,18
* 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);
if (pos >= nodep->size) {
/* reading beyond the EOF */
bytes = 0;
(void) ipc_data_read_finalize(callid, NULL, 0);
} else {
bytes = min(len, bps - pos % bps);
bytes = min(bytes, nodep->size - pos);
b = fat_block_get(bs, nodep, pos / bps);
(void) ipc_data_read_finalize(callid, b->data + pos % bps,
bytes);
block_put(b);
}
} else {
unsigned bnum;
off_t spos = pos;
812,7 → 570,7
while (bnum < nodep->size / bps) {
off_t o;
 
b = fat_block_get(nodep, bnum);
b = fat_block_get(bs, nodep, bnum);
for (o = pos % (bps / sizeof(fat_dentry_t));
o < bps / sizeof(fat_dentry_t);
o++, pos++) {
847,6 → 605,116
ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
}
 
void fat_write(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);
fat_bs_t *bs;
size_t bytes;
block_t *b;
uint16_t bps;
unsigned spc;
off_t boundary;
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
/* XXX remove me when you are ready */
{
ipc_answer_0(rid, ENOTSUP);
fat_node_put(nodep);
return;
}
 
ipc_callid_t callid;
size_t len;
if (!ipc_data_write_receive(&callid, &len)) {
fat_node_put(nodep);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
/*
* In all scenarios, we will attempt to write out only one block worth
* of data at maximum. There might be some more efficient approaches,
* but this one greatly simplifies fat_write(). Note that we can afford
* to do this because the client must be ready to handle the return
* value signalizing a smaller number of bytes written.
*/
bytes = min(len, bps - pos % bps);
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
boundary = ROUND_UP(nodep->size, bps * spc);
if (pos < boundary) {
/*
* This is the easier case - we are either overwriting already
* existing contents or writing behind the EOF, but still within
* the limits of the last cluster. The node size may grow to the
* next block size boundary.
*/
fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos);
b = fat_block_get(bs, nodep, pos / bps);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
b->dirty = true; /* need to sync block */
block_put(b);
if (pos + bytes > nodep->size) {
nodep->size = pos + bytes;
nodep->dirty = true; /* need to sync node */
}
fat_node_put(nodep);
ipc_answer_1(rid, EOK, bytes);
return;
} else {
/*
* This is the more difficult case. We must allocate new
* clusters for the node and zero them out.
*/
int status;
unsigned nclsts;
fat_cluster_t mcl, lcl;
nclsts = (ROUND_UP(pos + bytes, bps * spc) - boundary) /
bps * spc;
/* create an independent chain of nclsts clusters in all FATs */
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl,
&lcl);
if (status != EOK) {
/* could not allocate a chain of nclsts clusters */
fat_node_put(nodep);
ipc_answer_0(callid, status);
ipc_answer_0(rid, status);
return;
}
/* zero fill any gaps */
fat_fill_gap(bs, nodep, mcl, pos);
b = _fat_block_get(bs, dev_handle, lcl,
(pos / bps) % spc);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
b->dirty = true; /* need to sync block */
block_put(b);
/*
* Append the cluster chain starting in mcl to the end of the
* node's cluster chain.
*/
fat_append_clusters(bs, nodep, mcl);
nodep->size = pos + bytes;
nodep->dirty = true; /* need to sync node */
fat_node_put(nodep);
ipc_answer_1(rid, EOK, bytes);
return;
}
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/Makefile
31,12 → 31,16
 
LIBC_PREFIX = ../../../lib/libc
LIBFS_PREFIX = ../../../lib/libfs
LIBBLOCK_PREFIX = ../../../lib/libblock
SOFTINT_PREFIX = ../../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I $(LIBFS_PREFIX)
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX)
 
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a
LIBS = \
$(LIBFS_PREFIX)/libfs.a \
$(LIBBLOCK_PREFIX)/libblock.a \
$(LIBC_PREFIX)/libc.a
 
## Sources
#
45,7 → 49,9
SOURCES = \
fat.c \
fat_ops.c \
fat_idx.c
fat_idx.c \
fat_dentry.c \
fat_fat.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
/branches/tracing/uspace/srv/vfs/vfs.c
49,8 → 49,6
 
#define NAME "vfs"
 
#define dprintf(...) printf(__VA_ARGS__)
 
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
bool keep_on_going = 1;
/branches/tracing/uspace/srv/vfs/vfs_ops.c
153,7 → 153,7
return;
}
/* Allocate buffer for the mount point data being received. */
uint8_t *buf;
char *buf;
buf = malloc(size + 1);
if (!buf) {
ipc_answer_0(callid, ENOMEM);
/branches/tracing/uspace/Makefile
34,6 → 34,7
DIRS = \
lib/libc \
lib/libfs \
lib/libblock \
lib/softint \
lib/softfloat \
srv/ns \
/branches/tracing/boot/boot.config
82,3 → 82,6
@ "tmpfs" TMPFS image
@ "fat" FAT16 image
! RDFMT (choice)
 
# External ramdisk
! [ARCH=sparc64] CONFIG_RD_EXTERNAL (y/n)
/branches/tracing/boot/arch/sparc64/Makefile.inc
26,18 → 26,27
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
TMP=distroot
TMP = distroot
 
build: $(BASE)/image.iso
 
ifeq ($(CONFIG_RD_EXTERNAL),y)
SILO_CONF_FILTER = cat
else
SILO_CONF_FILTER = grep -v initrd
endif
 
$(BASE)/image.iso: depend arch/$(ARCH)/loader/image.boot
mkdir -p $(TMP)/boot
mkdir -p $(TMP)/HelenOS
cat arch/$(ARCH)/silo/silo.tar.gz | (cd $(TMP)/boot; tar xvfz -)
cp arch/$(ARCH)/silo/README arch/$(ARCH)/silo/COPYING arch/$(ARCH)/silo/silo.conf $(TMP)/boot
cp arch/$(ARCH)/silo/README arch/$(ARCH)/silo/COPYING $(TMP)/boot
cat arch/$(ARCH)/silo/silo.conf | $(SILO_CONF_FILTER) >$(TMP)/boot/silo.conf
cp arch/$(ARCH)/loader/image.boot $(TMP)/HelenOS/image.boot
gzip -f $(TMP)/HelenOS/image.boot
ifeq ($(CONFIG_RD_EXTERNAL),y)
cp arch/$(ARCH)/loader/initrd.img $(TMP)/HelenOS/initrd.img
endif
mkisofs -f -G $(TMP)/boot/isofs.b -B ... -r -o $(BASE)/image.iso $(TMP)/
 
depend:
/branches/tracing/boot/arch/sparc64/loader/Makefile
57,7 → 57,7
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
endif
 
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=ultrasparc -m64 -mno-fpu
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=ultrasparc -m64 -mno-fpu -pipe
 
ifdef REVISION
CFLAGS += "-DREVISION=\"$(REVISION)\""
79,6 → 79,9
asm.S \
boot.S
 
#
# All components that go to image.boot without the ramdisk.
#
COMPONENTS = \
$(KERNELDIR)/kernel.bin \
$(USPACEDIR)/srv/ns/ns \
94,6 → 97,14
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
#
# Final list of all components that go to image.boot.
#
ALL_COMPONENTS = $(COMPONENTS)
ifeq ($(CONFIG_RD_EXTERNAL),n)
ALL_COMPONENTS += ./initrd.img
endif
 
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
110,7 → 121,7
$(USPACEDIR)/app/klog/klog
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS))))
ALL_COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(ALL_COMPONENTS))))
 
.PHONY: all clean depend
 
118,11 → 129,11
 
-include Makefile.depend
 
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS)
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@
image.boot: depend _components.h _link.ld $(ALL_COMPONENT_OBJECTS) $(OBJECTS)
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(ALL_COMPONENT_OBJECTS) $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-for file in $(RD_SRVS) ; do \
131,9 → 142,9
-for file in $(RD_APPS) ; do \
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
done
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) initrd.img image.boot image.map image.disasm Makefile.depend
-rm -f _components.h _components.c _link.ld $(ALL_COMPONENT_OBJECTS) $(OBJECTS) initrd.img image.boot image.map image.disasm Makefile.depend
 
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in
_components.h _components.c _link.ld $(ALL_COMPONENT_OBJECTS): $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in
for file in $(RD_SRVS) ; do \
cp $$file $(USPACEDIR)/dist/srv/ ; \
done
144,11 → 155,11
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 16384 initrd.fs initrd.img
rm initrd.fs
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 1 "unsigned long" $(COMPONENTS)
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 1 "unsigned long" $(ALL_COMPONENTS)
 
%.o: %.S
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/tracing/boot/arch/ia64/loader/Makefile
68,7 → 68,7
endif
 
#-mno-pic means do not use gp + imm22 to address data
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -I../../../../kernel/generic/include -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -I../../../../kernel/generic/include -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic -pipe
 
ifdef REVISION
CFLAGS += "-DREVISION=\"$(REVISION)\""
123,7 → 123,7
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot image.map image.disasm Makefile.depend ../../../../image.bin ../../../../hello.efi
/branches/tracing/boot/arch/arm32/loader/Makefile
57,7 → 57,7
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
endif
 
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../.. -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../.. -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -pipe
 
ifdef REVISION
CFLAGS += "-DREVISION=\"$(REVISION)\""
123,7 → 123,7
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-for file in $(RD_SRVS) ; do \
145,7 → 145,7
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 4096 initrd.fs initrd.img
rm initrd.fs
/branches/tracing/boot/arch/ppc32/loader/Makefile
57,7 → 57,7
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
endif
 
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=powerpc -msoft-float -m32
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=powerpc -msoft-float -m32 -pipe
 
ifdef REVISION
CFLAGS += "-DREVISION=\"$(REVISION)\""
118,7 → 118,7
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-for file in $(RD_SRVS) ; do \
140,7 → 140,7
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 4096 initrd.fs initrd.img
rm initrd.fs
/branches/tracing/boot/arch/amd64/Makefile.inc
80,7 → 80,7
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
ifeq ($(RDFMT),fat)
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img
rm arch/$(ARCH)/iso/boot/initrd.fs
/branches/tracing/boot/arch/ppc64/loader/Makefile
57,7 → 57,7
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
endif
 
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=powerpc64 -msoft-float -m64
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=powerpc64 -msoft-float -m64 -pipe
 
ifdef REVISION
CFLAGS += "-DREVISION=\"$(REVISION)\""
105,7 → 105,7
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend
/branches/tracing/boot/arch/mips32/loader/Makefile
63,7 → 63,7
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
endif
 
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mhard-float -mips3
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mhard-float -mips3 -pipe
 
ifdef REVISION
CFLAGS += "-DREVISION=\"$(REVISION)\""
124,7 → 124,7
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-for file in $(RD_SRVS) ; do \
146,7 → 146,7
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 16384 initrd.fs initrd.img
rm initrd.fs
/branches/tracing/boot/arch/ia32/Makefile.inc
80,7 → 80,7
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
ifeq ($(RDFMT),fat)
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img
rm arch/$(ARCH)/iso/boot/initrd.fs