/branches/network/kernel/generic/src/mm/as.c |
---|
82,7 → 82,6 |
#include <arch/mm/cache.h> |
#endif /* CONFIG_VIRT_IDX_DCACHE */ |
#ifndef __OBJC__ |
/** |
* Each architecture decides what functions will be used to carry out |
* address space operations such as creating or locking page tables. |
93,7 → 92,6 |
* Slab for as_t objects. |
*/ |
static slab_cache_t *as_slab; |
#endif |
/** |
* This lock serializes access to the ASID subsystem. |
113,13 → 111,11 |
/** Kernel address space. */ |
as_t *AS_KERNEL = NULL; |
static int area_flags_to_page_flags(int aflags); |
static as_area_t *find_area_and_lock(as_t *as, uintptr_t va); |
static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
as_area_t *avoid_area); |
static void sh_info_remove_reference(share_info_t *sh_info); |
static int area_flags_to_page_flags(int); |
static as_area_t *find_area_and_lock(as_t *, uintptr_t); |
static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *); |
static void sh_info_remove_reference(share_info_t *); |
#ifndef __OBJC__ |
static int as_constructor(void *obj, int flags) |
{ |
as_t *as = (as_t *) obj; |
126,7 → 122,7 |
int rc; |
link_initialize(&as->inactive_as_with_asid_link); |
mutex_initialize(&as->lock); |
mutex_initialize(&as->lock, MUTEX_PASSIVE); |
rc = as_constructor_arch(as, flags); |
139,7 → 135,6 |
return as_destructor_arch(as); |
} |
#endif |
/** Initialize address space subsystem. */ |
void as_init(void) |
146,10 → 141,8 |
{ |
as_arch_init(); |
#ifndef __OBJC__ |
as_slab = slab_cache_create("as_slab", sizeof(as_t), 0, |
as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED); |
#endif |
AS_KERNEL = as_create(FLAG_AS_KERNEL); |
if (!AS_KERNEL) |
159,20 → 152,14 |
/** Create address space. |
* |
* @param flags Flags that influence way in wich the address space is created. |
* @param flags Flags that influence the way in wich the address space |
* is created. |
*/ |
as_t *as_create(int flags) |
{ |
as_t *as; |
#ifdef __OBJC__ |
as = [as_t new]; |
link_initialize(&as->inactive_as_with_asid_link); |
mutex_initialize(&as->lock); |
(void) as_constructor_arch(as, flags); |
#else |
as = (as_t *) slab_alloc(as_slab, 0); |
#endif |
(void) as_create_arch(as, 0); |
btree_create(&as->as_area_btree); |
199,6 → 186,8 |
* zero), the address space can be destroyed. |
* |
* We know that we don't hold any spinlock. |
* |
* @param as Address space to be destroyed. |
*/ |
void as_destroy(as_t *as) |
{ |
263,11 → 252,7 |
interrupts_restore(ipl); |
#ifdef __OBJC__ |
[as free]; |
#else |
slab_free(as_slab, as); |
#endif |
} |
/** Create address space area of common attributes. |
312,7 → 297,7 |
a = (as_area_t *) malloc(sizeof(as_area_t), 0); |
mutex_initialize(&a->lock); |
mutex_initialize(&a->lock, MUTEX_PASSIVE); |
a->as = as; |
a->flags = flags; |
324,8 → 309,7 |
if (backend_data) |
a->backend_data = *backend_data; |
else |
memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data), |
0); |
memsetb(&a->backend_data, sizeof(a->backend_data), 0); |
btree_create(&a->used_space); |
340,9 → 324,10 |
/** Find address space area and change it. |
* |
* @param as Address space. |
* @param address Virtual address belonging to the area to be changed. Must be |
* page-aligned. |
* @param size New size of the virtual memory block starting at address. |
* @param address Virtual address belonging to the area to be changed. |
* Must be page-aligned. |
* @param size New size of the virtual memory block starting at |
* address. |
* @param flags Flags influencing the remap operation. Currently unused. |
* |
* @return Zero on success or a value from @ref errno.h otherwise. |
431,7 → 416,7 |
uintptr_t b = node->key[node->keys - 1]; |
count_t c = |
(count_t) node->value[node->keys - 1]; |
int i = 0; |
unsigned int i = 0; |
if (overlaps(b, c * PAGE_SIZE, area->base, |
pages * PAGE_SIZE)) { |
527,7 → 512,7 |
/** Destroy address space area. |
* |
* @param as Address space. |
* @param address Address withing the area to be deleted. |
* @param address Address within the area to be deleted. |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
561,7 → 546,7 |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
int i; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
633,11 → 618,12 |
* @param dst_base Target base address. |
* @param dst_flags_mask Destination address space area flags mask. |
* |
* @return Zero on success or ENOENT if there is no such task or if there is no |
* such address space area, EPERM if there was a problem in accepting the area |
* or ENOMEM if there was a problem in allocating destination address space |
* area. ENOTSUP is returned if the address space area backend does not support |
* sharing. |
* @return Zero on success or ENOENT if there is no such task or if |
* there is no such address space area, EPERM if there was |
* a problem in accepting the area or ENOMEM if there was a |
* problem in allocating destination address space area. |
* ENOTSUP is returned if the address space area backend |
* does not support sharing. |
*/ |
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask) |
698,7 → 684,7 |
sh_info = src_area->sh_info; |
if (!sh_info) { |
sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0); |
mutex_initialize(&sh_info->lock); |
mutex_initialize(&sh_info->lock, MUTEX_PASSIVE); |
sh_info->refcount = 2; |
btree_create(&sh_info->pagemap); |
src_area->sh_info = sh_info; |
759,7 → 745,8 |
* @param area Address space area. |
* @param access Access mode. |
* |
* @return False if access violates area's permissions, true otherwise. |
* @return False if access violates area's permissions, true |
* otherwise. |
*/ |
bool as_area_check_access(as_area_t *area, pf_access_t access) |
{ |
775,21 → 762,181 |
return true; |
} |
/** Change adress space area flags. |
* |
* The idea is to have the same data, but with a different access mode. |
* This is needed e.g. for writing code into memory and then executing it. |
* In order for this to work properly, this may copy the data |
* into private anonymous memory (unless it's already there). |
* |
* @param as Address space. |
* @param flags Flags of the area memory. |
* @param address Address withing the area to be changed. |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int as_area_change_flags(as_t *as, int flags, uintptr_t address) |
{ |
as_area_t *area; |
uintptr_t base; |
link_t *cur; |
ipl_t ipl; |
int page_flags; |
uintptr_t *old_frame; |
index_t frame_idx; |
count_t used_pages; |
/* Flags for the new memory mapping */ |
page_flags = area_flags_to_page_flags(flags); |
ipl = interrupts_disable(); |
mutex_lock(&as->lock); |
area = find_area_and_lock(as, address); |
if (!area) { |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
if (area->sh_info || area->backend != &anon_backend) { |
/* Copying shared areas not supported yet */ |
/* Copying non-anonymous memory not supported yet */ |
mutex_unlock(&area->lock); |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return ENOTSUP; |
} |
base = area->base; |
/* |
* Compute total number of used pages in the used_space B+tree |
*/ |
used_pages = 0; |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
used_pages += (count_t) node->value[i]; |
} |
} |
/* An array for storing frame numbers */ |
old_frame = malloc(used_pages * sizeof(uintptr_t), 0); |
/* |
* Start TLB shootdown sequence. |
*/ |
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages); |
/* |
* Remove used pages from page tables and remember their frame |
* numbers. |
*/ |
frame_idx = 0; |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
uintptr_t b = node->key[i]; |
count_t j; |
pte_t *pte; |
for (j = 0; j < (count_t) node->value[i]; j++) { |
page_table_lock(as, false); |
pte = page_mapping_find(as, b + j * PAGE_SIZE); |
ASSERT(pte && PTE_VALID(pte) && |
PTE_PRESENT(pte)); |
old_frame[frame_idx++] = PTE_GET_FRAME(pte); |
/* Remove old mapping */ |
page_mapping_remove(as, b + j * PAGE_SIZE); |
page_table_unlock(as, false); |
} |
} |
} |
/* |
* Finish TLB shootdown sequence. |
*/ |
tlb_invalidate_pages(as->asid, area->base, area->pages); |
/* |
* Invalidate potential software translation caches (e.g. TSB on |
* sparc64). |
*/ |
as_invalidate_translation_cache(as, area->base, area->pages); |
tlb_shootdown_finalize(); |
/* |
* Set the new flags. |
*/ |
area->flags = flags; |
/* |
* Map pages back in with new flags. This step is kept separate |
* so that the memory area could not be accesed with both the old and |
* the new flags at once. |
*/ |
frame_idx = 0; |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
uintptr_t b = node->key[i]; |
count_t j; |
for (j = 0; j < (count_t) node->value[i]; j++) { |
page_table_lock(as, false); |
/* Insert the new mapping */ |
page_mapping_insert(as, b + j * PAGE_SIZE, |
old_frame[frame_idx++], page_flags); |
page_table_unlock(as, false); |
} |
} |
} |
free(old_frame); |
mutex_unlock(&area->lock); |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return 0; |
} |
/** Handle page fault within the current address space. |
* |
* This is the high-level page fault handler. It decides |
* whether the page fault can be resolved by any backend |
* and if so, it invokes the backend to resolve the page |
* fault. |
* This is the high-level page fault handler. It decides whether the page fault |
* can be resolved by any backend and if so, it invokes the backend to resolve |
* the page fault. |
* |
* Interrupts are assumed disabled. |
* |
* @param page Faulting page. |
* @param access Access mode that caused the fault (i.e. read/write/exec). |
* @param istate Pointer to interrupted state. |
* @param access Access mode that caused the page fault (i.e. |
* read/write/exec). |
* @param istate Pointer to the interrupted state. |
* |
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the |
* fault was caused by copy_to_uspace() or copy_from_uspace(). |
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or |
* AS_PF_DEFER if the fault was caused by copy_to_uspace() |
* or copy_from_uspace(). |
*/ |
int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate) |
{ |
835,9 → 982,8 |
page_table_lock(AS, false); |
/* |
* To avoid race condition between two page faults |
* on the same address, we need to make sure |
* the mapping has not been already inserted. |
* To avoid race condition between two page faults on the same address, |
* we need to make sure the mapping has not been already inserted. |
*/ |
if ((pte = page_mapping_find(AS, page))) { |
if (PTE_PRESENT(pte)) { |
1004,23 → 1150,20 |
/** Create page table. |
* |
* Depending on architecture, create either address space |
* private or global page table. |
* Depending on architecture, create either address space private or global page |
* table. |
* |
* @param flags Flags saying whether the page table is for kernel address space. |
* @param flags Flags saying whether the page table is for the kernel |
* address space. |
* |
* @return First entry of the page table. |
*/ |
pte_t *page_table_create(int flags) |
{ |
#ifdef __OBJC__ |
return [as_t page_table_create: flags]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_create); |
return as_operations->page_table_create(flags); |
#endif |
} |
/** Destroy page table. |
1031,14 → 1174,10 |
*/ |
void page_table_destroy(pte_t *page_table) |
{ |
#ifdef __OBJC__ |
return [as_t page_table_destroy: page_table]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_destroy); |
as_operations->page_table_destroy(page_table); |
#endif |
} |
/** Lock page table. |
1055,14 → 1194,10 |
*/ |
void page_table_lock(as_t *as, bool lock) |
{ |
#ifdef __OBJC__ |
[as page_table_lock: lock]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_lock); |
as_operations->page_table_lock(as, lock); |
#endif |
} |
/** Unlock page table. |
1072,14 → 1207,10 |
*/ |
void page_table_unlock(as_t *as, bool unlock) |
{ |
#ifdef __OBJC__ |
[as page_table_unlock: unlock]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_unlock); |
as_operations->page_table_unlock(as, unlock); |
#endif |
} |
1090,14 → 1221,14 |
* @param as Address space. |
* @param va Virtual address. |
* |
* @return Locked address space area containing va on success or NULL on |
* failure. |
* @return Locked address space area containing va on success or |
* NULL on failure. |
*/ |
as_area_t *find_area_and_lock(as_t *as, uintptr_t va) |
{ |
as_area_t *a; |
btree_node_t *leaf, *lnode; |
int i; |
unsigned int i; |
a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf); |
if (a) { |
1150,12 → 1281,12 |
* |
* @return True if there is no conflict, false otherwise. |
*/ |
bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
as_area_t *avoid_area) |
bool |
check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area) |
{ |
as_area_t *a; |
btree_node_t *leaf, *node; |
int i; |
unsigned int i; |
/* |
* We don't want any area to have conflicts with NULL page. |
1258,13 → 1389,13 |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* |
* @return 0 on failure and 1 on success. |
* @return Zero on failure and non-zero on success. |
*/ |
int used_space_insert(as_area_t *a, uintptr_t page, count_t count) |
{ |
btree_node_t *leaf, *node; |
count_t pages; |
int i; |
unsigned int i; |
ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE)); |
ASSERT(count); |
1528,8 → 1659,8 |
} |
} |
panic("Inconsistency detected while adding %d pages of used space at " |
"%p.\n", count, page); |
panic("Inconsistency detected while adding %" PRIc " pages of used " |
"space at %p.\n", count, page); |
} |
/** Mark portion of address space area as unused. |
1540,13 → 1671,13 |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* |
* @return 0 on failure and 1 on success. |
* @return Zero on failure and non-zero on success. |
*/ |
int used_space_remove(as_area_t *a, uintptr_t page, count_t count) |
{ |
btree_node_t *leaf, *node; |
count_t pages; |
int i; |
unsigned int i; |
ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE)); |
ASSERT(count); |
1707,8 → 1838,8 |
} |
error: |
panic("Inconsistency detected while removing %d pages of used space " |
"from %p.\n", count, page); |
panic("Inconsistency detected while removing %" PRIc " pages of used " |
"space from %p.\n", count, page); |
} |
/** Remove reference to address space area share info. |
1734,7 → 1865,7 |
for (cur = sh_info->pagemap.leaf_head.next; |
cur != &sh_info->pagemap.leaf_head; cur = cur->next) { |
btree_node_t *node; |
int i; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) |
1770,6 → 1901,12 |
return (unative_t) as_area_resize(AS, address, size, 0); |
} |
/** Wrapper for as_area_change_flags(). */ |
unative_t sys_as_area_change_flags(uintptr_t address, int flags) |
{ |
return (unative_t) as_area_change_flags(AS, flags, address); |
} |
/** Wrapper for as_area_destroy(). */ |
unative_t sys_as_area_destroy(uintptr_t address) |
{ |
1795,14 → 1932,14 |
node = list_get_instance(cur, btree_node_t, leaf_link); |
int i; |
unsigned int i; |
for (i = 0; i < node->keys; i++) { |
as_area_t *area = node->value[i]; |
mutex_lock(&area->lock); |
printf("as_area: %p, base=%p, pages=%d (%p - %p)\n", |
area, area->base, area->pages, area->base, |
area->base + area->pages*PAGE_SIZE); |
printf("as_area: %p, base=%p, pages=%" PRIc |
" (%p - %p)\n", area, area->base, area->pages, |
area->base, area->base + FRAMES2SIZE(area->pages)); |
mutex_unlock(&area->lock); |
} |
} |
/branches/network/kernel/generic/src/mm/backend_anon.c |
---|
78,7 → 78,6 |
int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access) |
{ |
uintptr_t frame; |
bool dirty = false; |
if (!as_area_check_access(area, access)) |
return AS_PF_FAULT; |
98,7 → 97,7 |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf); |
if (!frame) { |
bool allocate = true; |
int i; |
unsigned int i; |
/* |
* Zero can be returned as a valid frame address. |
106,7 → 105,7 |
*/ |
for (i = 0; i < leaf->keys; i++) { |
if (leaf->key[i] == |
ALIGN_DOWN(addr, PAGE_SIZE)) { |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base) { |
allocate = false; |
break; |
} |
113,8 → 112,7 |
} |
if (allocate) { |
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); |
memsetb(PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
/* |
* Insert the address of the newly allocated |
144,8 → 142,7 |
* the different causes |
*/ |
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); |
memsetb(PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
} |
/* |
193,13 → 190,13 |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
int i; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
uintptr_t base = node->key[i]; |
count_t count = (count_t) node->value[i]; |
int j; |
unsigned int j; |
for (j = 0; j < count; j++) { |
pte_t *pte; |
/branches/network/kernel/generic/src/mm/backend_elf.c |
---|
48,6 → 48,7 |
#include <memstr.h> |
#include <macros.h> |
#include <arch.h> |
#include <arch/barrier.h> |
#ifdef CONFIG_VIRT_IDX_DCACHE |
#include <arch/mm/cache.h> |
69,10 → 70,11 |
* |
* @param area Pointer to the address space area. |
* @param addr Faulting virtual address. |
* @param access Access mode that caused the fault (i.e. read/write/exec). |
* @param access Access mode that caused the fault (i.e. |
* read/write/exec). |
* |
* @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e. |
* serviced). |
* @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK |
* on success (i.e. serviced). |
*/ |
int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access) |
{ |
79,7 → 81,7 |
elf_header_t *elf = area->backend_data.elf; |
elf_segment_header_t *entry = area->backend_data.segment; |
btree_node_t *leaf; |
uintptr_t base, frame; |
uintptr_t base, frame, page, start_anon; |
index_t i; |
bool dirty = false; |
86,12 → 88,18 |
if (!as_area_check_access(area, access)) |
return AS_PF_FAULT; |
ASSERT((addr >= entry->p_vaddr) && |
ASSERT((addr >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) && |
(addr < entry->p_vaddr + entry->p_memsz)); |
i = (addr - entry->p_vaddr) >> PAGE_WIDTH; |
base = (uintptr_t) (((void *) elf) + entry->p_offset); |
ASSERT(ALIGN_UP(base, FRAME_SIZE) == base); |
i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH; |
base = (uintptr_t) |
(((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE)); |
/* Virtual address of faulting page*/ |
page = ALIGN_DOWN(addr, PAGE_SIZE); |
/* Virtual address of the end of initialized part of segment */ |
start_anon = entry->p_vaddr + entry->p_filesz; |
if (area->sh_info) { |
bool found = false; |
101,9 → 109,9 |
mutex_lock(&area->sh_info->lock); |
frame = (uintptr_t) btree_search(&area->sh_info->pagemap, |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf); |
page - area->base, &leaf); |
if (!frame) { |
int i; |
unsigned int i; |
/* |
* Workaround for valid NULL address. |
110,8 → 118,7 |
*/ |
for (i = 0; i < leaf->keys; i++) { |
if (leaf->key[i] == |
ALIGN_DOWN(addr, PAGE_SIZE)) { |
if (leaf->key[i] == page - area->base) { |
found = true; |
break; |
} |
121,8 → 128,7 |
frame_reference_add(ADDR2PFN(frame)); |
page_mapping_insert(AS, addr, frame, |
as_area_get_flags(area)); |
if (!used_space_insert(area, |
ALIGN_DOWN(addr, PAGE_SIZE), 1)) |
if (!used_space_insert(area, page, 1)) |
panic("Could not insert used space.\n"); |
mutex_unlock(&area->sh_info->lock); |
return AS_PF_OK; |
133,9 → 139,7 |
* The area is either not shared or the pagemap does not contain the |
* mapping. |
*/ |
if (ALIGN_DOWN(addr, PAGE_SIZE) + PAGE_SIZE < |
entry->p_vaddr + entry->p_filesz) { |
if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) { |
/* |
* Initialized portion of the segment. The memory is backed |
* directly by the content of the ELF image. Pages are |
148,20 → 152,15 |
frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
memcpy((void *) PA2KA(frame), |
(void *) (base + i * FRAME_SIZE), FRAME_SIZE); |
if (entry->p_flags & PF_X) { |
smc_coherence_block((void *) PA2KA(frame), |
FRAME_SIZE); |
} |
dirty = true; |
if (area->sh_info) { |
frame_reference_add(ADDR2PFN(frame)); |
btree_insert(&area->sh_info->pagemap, |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base, |
(void *) frame, leaf); |
} |
} else { |
frame = KA2PA(base + i*FRAME_SIZE); |
} |
} else if (ALIGN_DOWN(addr, PAGE_SIZE) >= |
ALIGN_UP(entry->p_vaddr + entry->p_filesz, PAGE_SIZE)) { |
} else if (page >= start_anon) { |
/* |
* This is the uninitialized portion of the segment. |
* It is not physically present in the ELF image. |
169,44 → 168,52 |
* and cleared. |
*/ |
frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
memsetb(PA2KA(frame), FRAME_SIZE, 0); |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
if (area->sh_info) { |
frame_reference_add(ADDR2PFN(frame)); |
btree_insert(&area->sh_info->pagemap, |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base, |
(void *) frame, leaf); |
} |
} else { |
size_t size; |
size_t pad_lo, pad_hi; |
/* |
* The mixed case. |
* The lower part is backed by the ELF image and |
* the upper part is anonymous memory. |
* |
* The middle part is backed by the ELF image and |
* the lower and upper parts are anonymous memory. |
* (The segment can be and often is shorter than 1 page). |
*/ |
size = entry->p_filesz - (i<<PAGE_WIDTH); |
if (page < entry->p_vaddr) |
pad_lo = entry->p_vaddr - page; |
else |
pad_lo = 0; |
if (start_anon < page + PAGE_SIZE) |
pad_hi = page + PAGE_SIZE - start_anon; |
else |
pad_hi = 0; |
frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
memsetb(PA2KA(frame) + size, FRAME_SIZE - size, 0); |
memcpy((void *) PA2KA(frame), (void *) (base + i * FRAME_SIZE), |
size); |
memcpy((void *) (PA2KA(frame) + pad_lo), |
(void *) (base + i * FRAME_SIZE + pad_lo), |
FRAME_SIZE - pad_lo - pad_hi); |
if (entry->p_flags & PF_X) { |
smc_coherence_block((void *) (PA2KA(frame) + pad_lo), |
FRAME_SIZE - pad_lo - pad_hi); |
} |
memsetb((void *) PA2KA(frame), pad_lo, 0); |
memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi, |
0); |
dirty = true; |
} |
if (area->sh_info) { |
if (dirty && area->sh_info) { |
frame_reference_add(ADDR2PFN(frame)); |
btree_insert(&area->sh_info->pagemap, |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base, |
btree_insert(&area->sh_info->pagemap, page - area->base, |
(void *) frame, leaf); |
} |
} |
if (area->sh_info) |
mutex_unlock(&area->sh_info->lock); |
page_mapping_insert(AS, addr, frame, as_area_get_flags(area)); |
if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1)) |
if (!used_space_insert(area, page, 1)) |
panic("Could not insert used space.\n"); |
return AS_PF_OK; |
217,7 → 224,8 |
* The address space area and page tables must be already locked. |
* |
* @param area Pointer to the address space area. |
* @param page Page that is mapped to frame. Must be aligned to PAGE_SIZE. |
* @param page Page that is mapped to frame. Must be aligned to |
* PAGE_SIZE. |
* @param frame Frame to be released. |
* |
*/ |
225,17 → 233,17 |
{ |
elf_header_t *elf = area->backend_data.elf; |
elf_segment_header_t *entry = area->backend_data.segment; |
uintptr_t base; |
uintptr_t base, start_anon; |
index_t i; |
ASSERT((page >= entry->p_vaddr) && |
ASSERT((page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) && |
(page < entry->p_vaddr + entry->p_memsz)); |
i = (page - entry->p_vaddr) >> PAGE_WIDTH; |
base = (uintptr_t) (((void *) elf) + entry->p_offset); |
ASSERT(ALIGN_UP(base, FRAME_SIZE) == base); |
i = (page - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH; |
base = (uintptr_t) (((void *) elf) + |
ALIGN_DOWN(entry->p_offset, FRAME_SIZE)); |
start_anon = entry->p_vaddr + entry->p_filesz; |
if (page + PAGE_SIZE < |
ALIGN_UP(entry->p_vaddr + entry->p_filesz, PAGE_SIZE)) { |
if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) { |
if (entry->p_flags & PF_W) { |
/* |
* Free the frame with the copy of writable segment |
290,7 → 298,7 |
mutex_lock(&area->sh_info->lock); |
for (cur = &node->leaf_link; cur != &area->used_space.leaf_head; |
cur = cur->next) { |
int i; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
297,7 → 305,7 |
for (i = 0; i < node->keys; i++) { |
uintptr_t base = node->key[i]; |
count_t count = (count_t) node->value[i]; |
int j; |
unsigned int j; |
/* |
* Skip read-only areas of used space that are backed |
304,7 → 312,8 |
* by the ELF image. |
*/ |
if (!(area->flags & AS_AREA_WRITE)) |
if (base + count * PAGE_SIZE <= start_anon) |
if (base >= entry->p_vaddr && |
base + count * PAGE_SIZE <= start_anon) |
continue; |
for (j = 0; j < count; j++) { |
315,7 → 324,8 |
* ELF image. |
*/ |
if (!(area->flags & AS_AREA_WRITE)) |
if (base + (j + 1) * PAGE_SIZE <= |
if (base >= entry->p_vaddr && |
base + (j + 1) * PAGE_SIZE <= |
start_anon) |
continue; |
/branches/network/kernel/generic/src/mm/frame.c |
---|
58,6 → 58,8 |
#include <debug.h> |
#include <adt/list.h> |
#include <synch/spinlock.h> |
#include <synch/mutex.h> |
#include <synch/condvar.h> |
#include <arch/asm.h> |
#include <arch.h> |
#include <print.h> |
103,6 → 105,14 |
static zones_t zones; |
/* |
* Synchronization primitives used to sleep when there is no memory |
* available. |
*/ |
mutex_t mem_avail_mtx; |
condvar_t mem_avail_cv; |
unsigned long mem_avail_frames = 0; /**< Number of available frames. */ |
unsigned long mem_avail_gen = 0; /**< Generation counter. */ |
/********************/ |
/* Helper functions */ |
120,7 → 130,7 |
static inline int frame_index_valid(zone_t *zone, index_t index) |
{ |
return (index >= 0) && (index < zone->count); |
return (index < zone->count); |
} |
/** Compute pfn_t from frame_t pointer & zone pointer */ |
129,10 → 139,8 |
return (frame - zone->frames); |
} |
/** Initialize frame structure |
/** Initialize frame structure. |
* |
* Initialize frame structure. |
* |
* @param frame Frame structure to be initialized. |
*/ |
static void frame_initialize(frame_t *frame) |
145,11 → 153,10 |
/* Zoneinfo functions */ |
/**********************/ |
/** |
* Insert-sort zone into zones list |
/** Insert-sort zone into zones list. |
* |
* @param newzone New zone to be inserted into zone list |
* @return zone number on success, -1 on error |
* @param newzone New zone to be inserted into zone list. |
* @return Zone number on success, -1 on error. |
*/ |
static int zones_add_zone(zone_t *newzone) |
{ |
171,7 → 178,8 |
for (i = 0; i < zones.count; i++) { |
/* Check for overflow */ |
z = zones.info[i]; |
if (overlaps(newzone->base, newzone->count, z->base, z->count)) { |
if (overlaps(newzone->base, newzone->count, z->base, |
z->count)) { |
printf("Zones overlap!\n"); |
return -1; |
} |
192,15 → 200,14 |
return i; |
} |
/** |
* Try to find a zone where can we find the frame |
/** Try to find a zone where can we find the frame. |
* |
* Assume interrupts are disabled. |
* |
* @param frame Frame number contained in zone |
* @param pzone If not null, it is used as zone hint. Zone index |
* is filled into the variable on success. |
* @return Pointer to locked zone containing frame |
* @param frame Frame number contained in zone. |
* @param pzone If not null, it is used as zone hint. Zone index is |
* filled into the variable on success. |
* @return Pointer to locked zone containing frame. |
*/ |
static zone_t * find_zone_and_lock(pfn_t frame, unsigned int *pzone) |
{ |
210,7 → 217,7 |
spinlock_lock(&zones.lock); |
if (hint >= zones.count || hint < 0) |
if (hint >= zones.count) |
hint = 0; |
i = hint; |
245,16 → 252,21 |
* |
* Assume interrupts are disabled. |
* |
* @param order Size (2^order) of free space we are trying to find |
* @param pzone Pointer to preferred zone or NULL, on return contains zone |
* number |
* @param order Size (2^order) of free space we are trying to find. |
* @param flags Required flags of the target zone. |
* @param pzone Pointer to preferred zone or NULL, on return contains |
* zone number. |
*/ |
static zone_t * find_free_zone_and_lock(uint8_t order, unsigned int *pzone) |
static zone_t * |
find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone) |
{ |
unsigned int i; |
zone_t *z; |
unsigned int hint = pzone ? *pzone : 0; |
/* Mask off flags that are not applicable. */ |
flags &= FRAME_LOW_4_GiB; |
spinlock_lock(&zones.lock); |
if (hint >= zones.count) |
hint = 0; |
264,7 → 276,13 |
spinlock_lock(&z->lock); |
/* Check if the zone has 2^order frames area available */ |
/* |
* Check whether the zone meets the search criteria. |
*/ |
if ((z->flags & flags) == flags) { |
/* |
* Check if the zone has 2^order frames area available. |
*/ |
if (zone_can_alloc(z, order)) { |
spinlock_unlock(&zones.lock); |
if (pzone) |
271,6 → 289,7 |
*pzone = i; |
return z; |
} |
} |
spinlock_unlock(&z->lock); |
if (++i >= zones.count) |
i = 0; |
283,12 → 302,13 |
/* Buddy system functions */ |
/**************************/ |
/** Buddy system find_block implementation |
/** Buddy system find_block implementation. |
* |
* Find block that is parent of current list. |
* That means go to lower addresses, until such block is found |
* |
* @param order - Order of parent must be different then this parameter!! |
* @param order Order of parent must be different then this |
* parameter!! |
*/ |
static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child, |
uint8_t order) |
309,24 → 329,12 |
return NULL; |
} |
static void zone_buddy_print_id(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame; |
zone_t *zone; |
index_t index; |
frame = list_get_instance(block, frame_t, buddy_link); |
zone = (zone_t *) b->data; |
index = frame_index(zone, frame); |
printf("%zd", index); |
} |
/** Buddy system find_buddy implementation |
/** Buddy system find_buddy implementation. |
* |
* @param b Buddy system. |
* @param block Block for which buddy should be found |
* @param block Block for which buddy should be found. |
* |
* @return Buddy for given block if found |
* @return Buddy for given block if found. |
*/ |
static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block) |
{ |
345,9 → 353,11 |
ASSERT(is_left ^ is_right); |
if (is_left) { |
index = (frame_index(zone, frame)) + (1 << frame->buddy_order); |
index = (frame_index(zone, frame)) + |
(1 << frame->buddy_order); |
} else { /* if (is_right) */ |
index = (frame_index(zone, frame)) - (1 << frame->buddy_order); |
index = (frame_index(zone, frame)) - |
(1 << frame->buddy_order); |
} |
if (frame_index_valid(zone, index)) { |
360,14 → 370,15 |
return NULL; |
} |
/** Buddy system bisect implementation |
/** Buddy system bisect implementation. |
* |
* @param b Buddy system. |
* @param block Block to bisect |
* @param block Block to bisect. |
* |
* @return right block |
* @return Right block. |
*/ |
static link_t * zone_buddy_bisect(buddy_system_t *b, link_t *block) { |
static link_t *zone_buddy_bisect(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame_l, *frame_r; |
frame_l = list_get_instance(block, frame_t, buddy_link); |
376,13 → 387,14 |
return &frame_r->buddy_link; |
} |
/** Buddy system coalesce implementation |
/** Buddy system coalesce implementation. |
* |
* @param b Buddy system. |
* @param block_1 First block |
* @param block_2 First block's buddy |
* @param block_1 First block. |
* @param block_2 First block's buddy. |
* |
* @return Coalesced block (actually block that represents lower address) |
* @return Coalesced block (actually block that represents lower |
* address). |
*/ |
static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1, |
link_t *block_2) |
395,39 → 407,41 |
return frame1 < frame2 ? block_1 : block_2; |
} |
/** Buddy system set_order implementation |
/** Buddy system set_order implementation. |
* |
* @param b Buddy system. |
* @param block Buddy system block |
* @param order Order to set |
* @param block Buddy system block. |
* @param order Order to set. |
*/ |
static void zone_buddy_set_order(buddy_system_t *b, link_t *block, |
uint8_t order) { |
uint8_t order) |
{ |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->buddy_order = order; |
} |
/** Buddy system get_order implementation |
/** Buddy system get_order implementation. |
* |
* @param b Buddy system. |
* @param block Buddy system block |
* @param block Buddy system block. |
* |
* @return Order of block |
* @return Order of block. |
*/ |
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block) { |
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
return frame->buddy_order; |
} |
/** Buddy system mark_busy implementation |
/** Buddy system mark_busy implementation. |
* |
* @param b Buddy system |
* @param block Buddy system block |
* |
* @param b Buddy system. |
* @param block Buddy system block. |
*/ |
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { |
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) |
{ |
frame_t * frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
434,13 → 448,13 |
frame->refcount = 1; |
} |
/** Buddy system mark_available implementation |
/** Buddy system mark_available implementation. |
* |
* @param b Buddy system |
* @param block Buddy system block |
* |
* @param b Buddy system. |
* @param block Buddy system block. |
*/ |
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block) { |
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->refcount = 0; |
454,8 → 468,7 |
.get_order = zone_buddy_get_order, |
.mark_busy = zone_buddy_mark_busy, |
.mark_available = zone_buddy_mark_available, |
.find_block = zone_buddy_find_block, |
.print_id = zone_buddy_print_id |
.find_block = zone_buddy_find_block |
}; |
/******************/ |
462,15 → 475,15 |
/* Zone functions */ |
/******************/ |
/** Allocate frame in particular zone |
/** Allocate frame in particular zone. |
* |
* Assume zone is locked |
* Assume zone is locked. |
* Panics if allocation is impossible. |
* |
* @param zone Zone to allocate from. |
* @param order Allocate exactly 2^order frames. |
* |
* @return Frame index in zone |
* @return Frame index in zone. |
* |
*/ |
static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order) |
496,12 → 509,12 |
return v; |
} |
/** Free frame from zone |
/** Free frame from zone. |
* |
* Assume zone is locked |
* Assume zone is locked. |
* |
* @param zone Pointer to zone from which the frame is to be freed |
* @param frame_idx Frame index relative to zone |
* @param zone Pointer to zone from which the frame is to be freed. |
* @param frame_idx Frame index relative to zone. |
*/ |
static void zone_frame_free(zone_t *zone, index_t frame_idx) |
{ |
524,7 → 537,7 |
} |
} |
/** Return frame from zone */ |
/** Return frame from zone. */ |
static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx) |
{ |
ASSERT(frame_idx < zone->count); |
531,7 → 544,7 |
return &zone->frames[frame_idx]; |
} |
/** Mark frame in zone unavailable to allocation */ |
/** Mark frame in zone unavailable to allocation. */ |
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx) |
{ |
frame_t *frame; |
544,18 → 557,21 |
&frame->buddy_link); |
ASSERT(link); |
zone->free_count--; |
mutex_lock(&mem_avail_mtx); |
mem_avail_frames--; |
mutex_unlock(&mem_avail_mtx); |
} |
/** |
* Join 2 zones |
/** Join two zones. |
* |
* Expect zone_t *z to point to space at least zone_conf_size large |
* Expect zone_t *z to point to space at least zone_conf_size large. |
* |
* Assume z1 & z2 are locked |
* Assume z1 & z2 are locked. |
* |
* @param z Target zone structure pointer |
* @param z1 Zone to merge |
* @param z2 Zone to merge |
* @param z Target zone structure pointer. |
* @param z1 Zone to merge. |
* @param z2 Zone to merge. |
*/ |
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) |
{ |
629,7 → 645,7 |
} |
} |
/** Return old configuration frames into the zone |
/** Return old configuration frames into the zone. |
* |
* We have several cases |
* - the conf. data is outside of zone -> exit, shall we call frame_free?? |
636,9 → 652,9 |
* - the conf. data was created by zone_create or |
* updated with reduce_region -> free every frame |
* |
* @param newzone The actual zone where freeing should occur |
* @param newzone The actual zone where freeing should occur. |
* @param oldzone Pointer to old zone configuration data that should |
* be freed from new zone |
* be freed from new zone. |
*/ |
static void return_config_frames(zone_t *newzone, zone_t *oldzone) |
{ |
662,7 → 678,7 |
} |
} |
/** Reduce allocated block to count of order 0 frames |
/** Reduce allocated block to count of order 0 frames. |
* |
* The allocated block need 2^order frames of space. Reduce all frames |
* in block to order 0 and free the unneeded frames. This means, that |
670,8 → 686,8 |
* you have to free every frame. |
* |
* @param zone |
* @param frame_idx Index to block |
* @param count Allocated space in block |
* @param frame_idx Index to block. |
* @param count Allocated space in block. |
*/ |
static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count) |
{ |
698,7 → 714,7 |
} |
} |
/** Merge zones z1 and z2 |
/** Merge zones z1 and z2. |
* |
* - the zones must be 2 zones with no zone existing in between, |
* which means that z2 = z1+1 |
719,7 → 735,7 |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (z1 < 0 || z1 >= zones.count || z2 < 0 || z2 >= zones.count) |
if ((z1 >= zones.count) || (z2 >= zones.count)) |
goto errout; |
/* We can join only 2 zones with none existing inbetween */ |
if (z2-z1 != 1) |
773,8 → 789,7 |
interrupts_restore(ipl); |
} |
/** |
* Merge all zones into one big zone |
/** Merge all zones into one big zone. |
* |
* It is reasonable to do this on systems whose bios reports parts in chunks, |
* so that we could have 1 zone (it's faster). |
789,13 → 804,11 |
} |
} |
/** Create frame zone |
/** Create new frame zone. |
* |
* Create new frame zone. |
* |
* @param start Physical address of the first frame within the zone. |
* @param count Count of frames in zone |
* @param z Address of configuration information of zone |
* @param count Count of frames in zone. |
* @param z Address of configuration information of zone. |
* @param flags Zone flags. |
* |
* @return Initialized zone. |
808,7 → 821,15 |
spinlock_initialize(&z->lock, "zone_lock"); |
z->base = start; |
z->count = count; |
/* Mask off flags that are calculated automatically. */ |
flags &= ~FRAME_LOW_4_GiB; |
/* Determine calculated flags. */ |
if (z->base + count < (1ULL << (32 - FRAME_WIDTH))) /* 4 GiB */ |
flags |= FRAME_LOW_4_GiB; |
z->flags = flags; |
z->free_count = count; |
z->busy_count = 0; |
819,8 → 840,7 |
z->buddy_system = (buddy_system_t *)&z[1]; |
buddy_system_create(z->buddy_system, max_order, |
&zone_buddy_system_operations, |
(void *) z); |
&zone_buddy_system_operations, (void *) z); |
/* Allocate frames _after_ the conframe */ |
/* Check sizes */ |
837,10 → 857,10 |
} |
} |
/** Compute configuration data size for zone |
/** Compute configuration data size for zone. |
* |
* @param count Size of zone in frames |
* @return Size of zone configuration info (in bytes) |
* @param count Size of zone in frames. |
* @return Size of zone configuration info (in bytes). |
*/ |
uintptr_t zone_conf_size(count_t count) |
{ |
852,20 → 872,20 |
return size; |
} |
/** Create and add zone to system |
/** Create and add zone to system. |
* |
* @param start First frame number (absolute) |
* @param count Size of zone in frames |
* @param start First frame number (absolute). |
* @param count Size of zone in frames. |
* @param confframe Where configuration frames are supposed to be. |
* Automatically checks, that we will not disturb the |
* kernel and possibly init. |
* If confframe is given _outside_ this zone, it is expected, |
* that the area is already marked BUSY and big enough |
* to contain zone_conf_size() amount of data. |
* If the confframe is inside the area, the zone free frame |
* information is modified not to include it. |
* kernel and possibly init. If confframe is given |
* _outside_ this zone, it is expected, that the area is |
* already marked BUSY and big enough to contain |
* zone_conf_size() amount of data. If the confframe is |
* inside the area, the zone free frame information is |
* modified not to include it. |
* |
* @return Zone number or -1 on error |
* @return Zone number or -1 on error. |
*/ |
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) |
{ |
919,11 → 939,16 |
if (znum == -1) |
return -1; |
mutex_lock(&mem_avail_mtx); |
mem_avail_frames += count; |
mutex_unlock(&mem_avail_mtx); |
/* If confdata in zone, mark as unavailable */ |
if (confframe >= start && confframe < start + count) |
for (i = confframe; i < confframe + confcount; i++) { |
zone_mark_unavailable(z, i - z->base); |
} |
return znum; |
} |
930,7 → 955,7 |
/***************************************/ |
/* Frame functions */ |
/** Set parent of frame */ |
/** Set parent of frame. */ |
void frame_set_parent(pfn_t pfn, void *data, unsigned int hint) |
{ |
zone_t *zone = find_zone_and_lock(pfn, &hint); |
957,7 → 982,7 |
* |
* @param order Allocate exactly 2^order frames. |
* @param flags Flags for host zone selection and address processing. |
* @param pzone Preferred zone |
* @param pzone Preferred zone. |
* |
* @return Physical address of the allocated frame. |
* |
968,6 → 993,7 |
int freed; |
pfn_t v; |
zone_t *zone; |
unsigned long gen = 0; |
loop: |
ipl = interrupts_disable(); |
975,7 → 1001,7 |
/* |
* First, find suitable frame zone. |
*/ |
zone = find_free_zone_and_lock(order, pzone); |
zone = find_free_zone_and_lock(order, flags, pzone); |
/* If no memory, reclaim some slab memory, |
if it does not help, reclaim all */ |
982,23 → 1008,51 |
if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
freed = slab_reclaim(0); |
if (freed) |
zone = find_free_zone_and_lock(order, pzone); |
zone = find_free_zone_and_lock(order, flags, pzone); |
if (!zone) { |
freed = slab_reclaim(SLAB_RECLAIM_ALL); |
if (freed) |
zone = find_free_zone_and_lock(order, pzone); |
zone = find_free_zone_and_lock(order, flags, |
pzone); |
} |
} |
if (!zone) { |
/* |
* TODO: Sleep until frames are available again. |
* Sleep until some frames are available again. |
*/ |
if (flags & FRAME_ATOMIC) { |
interrupts_restore(ipl); |
if (flags & FRAME_ATOMIC) |
return 0; |
} |
panic("Sleep not implemented.\n"); |
#ifdef CONFIG_DEBUG |
unsigned long avail; |
mutex_lock(&mem_avail_mtx); |
avail = mem_avail_frames; |
mutex_unlock(&mem_avail_mtx); |
printf("Thread %" PRIu64 " waiting for %u frames, " |
"%u available.\n", THREAD->tid, 1ULL << order, avail); |
#endif |
mutex_lock(&mem_avail_mtx); |
while ((mem_avail_frames < (1ULL << order)) || |
gen == mem_avail_gen) |
condvar_wait(&mem_avail_cv, &mem_avail_mtx); |
gen = mem_avail_gen; |
mutex_unlock(&mem_avail_mtx); |
#ifdef CONFIG_DEBUG |
mutex_lock(&mem_avail_mtx); |
avail = mem_avail_frames; |
mutex_unlock(&mem_avail_mtx); |
printf("Thread %" PRIu64 " woken up, %u frames available.\n", |
THREAD->tid, avail); |
#endif |
interrupts_restore(ipl); |
goto loop; |
} |
1006,6 → 1060,11 |
v += zone->base; |
spinlock_unlock(&zone->lock); |
mutex_lock(&mem_avail_mtx); |
mem_avail_frames -= (1ULL << order); |
mutex_unlock(&mem_avail_mtx); |
interrupts_restore(ipl); |
if (flags & FRAME_KA) |
1019,7 → 1078,7 |
* Decrement frame reference count. |
* If it drops to zero, move the frame structure to free list. |
* |
* @param Frame Physical Address of of the frame to be freed. |
* @param frame Physical Address of of the frame to be freed. |
*/ |
void frame_free(uintptr_t frame) |
{ |
1038,6 → 1097,16 |
zone_frame_free(zone, pfn-zone->base); |
spinlock_unlock(&zone->lock); |
/* |
* Signal that some memory has been freed. |
*/ |
mutex_lock(&mem_avail_mtx); |
mem_avail_frames++; |
mem_avail_gen++; |
condvar_broadcast(&mem_avail_cv); |
mutex_unlock(&mem_avail_mtx); |
interrupts_restore(ipl); |
} |
1069,7 → 1138,7 |
interrupts_restore(ipl); |
} |
/** Mark given range unavailable in frame zones */ |
/** Mark given range unavailable in frame zones. */ |
void frame_mark_unavailable(pfn_t start, count_t count) |
{ |
unsigned int i; |
1086,15 → 1155,14 |
} |
} |
/** Initialize physical memory management |
* |
* Initialize physical memory managemnt. |
*/ |
/** Initialize physical memory management. */ |
void frame_init(void) |
{ |
if (config.cpu_active == 1) { |
zones.count = 0; |
spinlock_initialize(&zones.lock, "zones.lock"); |
mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE); |
condvar_initialize(&mem_avail_cv); |
} |
/* Tell the architecture to create some memory */ |
frame_arch_init(); |
1122,10 → 1190,9 |
} |
/** Return total size of all zones |
* |
*/ |
uint64_t zone_total_size(void) { |
/** Return total size of all zones. */ |
uint64_t zone_total_size(void) |
{ |
zone_t *zone = NULL; |
unsigned int i; |
ipl_t ipl; |
1147,53 → 1214,86 |
return total; |
} |
/** Prints list of zones. */ |
void zone_print_list(void) |
{ |
zone_t *zone = NULL; |
unsigned int i; |
ipl_t ipl; |
#ifdef __32_BITS__ |
printf("# base address free frames busy frames\n"); |
printf("-- ------------ ------------ ------------\n"); |
#endif |
/** Prints list of zones |
#ifdef __64_BITS__ |
printf("# base address free frames busy frames\n"); |
printf("-- -------------------- ------------ ------------\n"); |
#endif |
/* |
* Because printing may require allocation of memory, we may not hold |
* the frame allocator locks when printing zone statistics. Therefore, |
* we simply gather the statistics under the protection of the locks and |
* print the statistics when the locks have been released. |
* |
* When someone adds/removes zones while we are printing the statistics, |
* we may end up with inaccurate output (e.g. a zone being skipped from |
* the listing). |
*/ |
void zone_print_list(void) { |
zone_t *zone = NULL; |
unsigned int i; |
ipl_t ipl; |
for (i = 0; ; i++) { |
uintptr_t base; |
count_t free_count; |
count_t busy_count; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (sizeof(void *) == 4) { |
printf("# base address free frames busy frames\n"); |
printf("-- ------------ ------------ ------------\n"); |
} else { |
printf("# base address free frames busy frames\n"); |
printf("-- -------------------- ------------ ------------\n"); |
if (i >= zones.count) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
break; |
} |
for (i = 0; i < zones.count; i++) { |
zone = zones.info[i]; |
spinlock_lock(&zone->lock); |
if (sizeof(void *) == 4) |
printf("%-2d %#10zx %12zd %12zd\n", i, PFN2ADDR(zone->base), |
zone->free_count, zone->busy_count); |
else |
printf("%-2d %#18zx %12zd %12zd\n", i, PFN2ADDR(zone->base), |
zone->free_count, zone->busy_count); |
base = PFN2ADDR(zone->base); |
free_count = zone->free_count; |
busy_count = zone->busy_count; |
spinlock_unlock(&zone->lock); |
} |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
#ifdef __32_BITS__ |
printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base, |
free_count, busy_count); |
#endif |
#ifdef __64_BITS__ |
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base, |
free_count, busy_count); |
#endif |
} |
} |
/** Prints zone details. |
* |
* @param num Zone base address or zone number. |
*/ |
void zone_print_one(unsigned int num) { |
void zone_print_one(unsigned int num) |
{ |
zone_t *zone = NULL; |
ipl_t ipl; |
unsigned int i; |
uintptr_t base; |
count_t count; |
count_t busy_count; |
count_t free_count; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
1205,26 → 1305,28 |
} |
} |
if (!zone) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
printf("Zone not found.\n"); |
goto out; |
return; |
} |
spinlock_lock(&zone->lock); |
printf("Memory zone information\n"); |
printf("Zone base address: %#.*p\n", sizeof(uintptr_t) * 2, |
PFN2ADDR(zone->base)); |
printf("Zone size: %zd frames (%zd KB)\n", zone->count, |
SIZE2KB(FRAMES2SIZE(zone->count))); |
printf("Allocated space: %zd frames (%zd KB)\n", zone->busy_count, |
SIZE2KB(FRAMES2SIZE(zone->busy_count))); |
printf("Available space: %zd frames (%zd KB)\n", zone->free_count, |
SIZE2KB(FRAMES2SIZE(zone->free_count))); |
buddy_system_structure_print(zone->buddy_system, FRAME_SIZE); |
base = PFN2ADDR(zone->base); |
count = zone->count; |
busy_count = zone->busy_count; |
free_count = zone->free_count; |
spinlock_unlock(&zone->lock); |
out: |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
printf("Zone base address: %p\n", base); |
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count, |
SIZE2KB(FRAMES2SIZE(count))); |
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n", |
busy_count, SIZE2KB(FRAMES2SIZE(busy_count))); |
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n", |
free_count, SIZE2KB(FRAMES2SIZE(free_count))); |
} |
/** @} |
/branches/network/kernel/generic/src/mm/buddy.c |
---|
35,8 → 35,7 |
* @brief Buddy allocator framework. |
* |
* This file contains buddy system allocator framework. |
* Specialized functions are needed for this abstract framework |
* to be useful. |
* Specialized functions are needed for this abstract framework to be useful. |
*/ |
#include <mm/buddy.h> |
44,8 → 43,9 |
#include <arch/types.h> |
#include <debug.h> |
#include <print.h> |
#include <macros.h> |
/** Return size needed for the buddy configuration data */ |
/** Return size needed for the buddy configuration data. */ |
size_t buddy_conf_size(int max_order) |
{ |
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t); |
52,7 → 52,7 |
} |
/** Create buddy system |
/** Create buddy system. |
* |
* Allocate memory for and initialize new buddy system. |
* |
63,10 → 63,9 |
* |
* @return New buddy system. |
*/ |
void buddy_system_create(buddy_system_t *b, |
uint8_t max_order, |
buddy_system_operations_t *op, |
void *data) |
void |
buddy_system_create(buddy_system_t *b, uint8_t max_order, |
buddy_system_operations_t *op, void *data) |
{ |
int i; |
80,7 → 79,7 |
ASSERT(op->mark_busy); |
/* |
* Use memory after our own structure |
* Use memory after our own structure. |
*/ |
b->order = (link_t *) (&b[1]); |
92,14 → 91,15 |
b->data = data; |
} |
/** Check if buddy system can allocate block |
/** Check if buddy system can allocate block. |
* |
* @param b Buddy system pointer |
* @param i Size of the block (2^i) |
* @param b Buddy system pointer. |
* @param i Size of the block (2^i). |
* |
* @return True if block can be allocated |
* @return True if block can be allocated. |
*/ |
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) { |
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) |
{ |
uint8_t k; |
/* |
106,7 → 106,8 |
* If requested block is greater then maximal block |
* we know immediatly that we cannot satisfy the request. |
*/ |
if (i > b->max_order) return false; |
if (i > b->max_order) |
return false; |
/* |
* Check if any bigger or equal order has free elements |
118,12 → 119,11 |
} |
return false; |
} |
/** Allocate PARTICULAR block from buddy system |
/** Allocate PARTICULAR block from buddy system. |
* |
* @ return Block of data or NULL if no such block was found |
* @return Block of data or NULL if no such block was found. |
*/ |
link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block) |
{ |
217,7 → 217,6 |
buddy_system_free(b, hlp); |
return res; |
} |
/** Return block to buddy system. |
267,7 → 266,8 |
b->op->set_order(b, hlp, i + 1); |
/* |
* Recursively add the coalesced block to the list of order i + 1. |
* Recursively add the coalesced block to the list of |
* order i + 1. |
*/ |
buddy_system_free(b, hlp); |
return; |
278,46 → 278,7 |
* Insert block into the list of order i. |
*/ |
list_append(block, &b->order[i]); |
} |
/** Prints out structure of buddy system |
* |
* @param b Pointer to buddy system |
* @param elem_size Element size |
*/ |
void buddy_system_structure_print(buddy_system_t *b, size_t elem_size) { |
index_t i; |
count_t cnt, elem_count = 0, block_count = 0; |
link_t * cur; |
printf("Order\tBlocks\tSize \tBlock size\tElems per block\n"); |
printf("-----\t------\t--------\t----------\t---------------\n"); |
for (i=0;i <= b->max_order; i++) { |
cnt = 0; |
if (!list_empty(&b->order[i])) { |
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) |
cnt++; |
} |
printf("#%zd\t%5zd\t%7zdK\t%8zdK\t%6zd\t", i, cnt, (cnt * (1 << i) * elem_size) >> 10, ((1 << i) * elem_size) >> 10, 1 << i); |
if (!list_empty(&b->order[i])) { |
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) { |
b->op->print_id(b, cur); |
printf(" "); |
} |
} |
printf("\n"); |
block_count += cnt; |
elem_count += (1 << i) * cnt; |
} |
printf("-----\t------\t--------\t----------\t---------------\n"); |
printf("Buddy system contains %zd free elements (%zd blocks)\n" , elem_count, block_count); |
} |
/** @} |
*/ |
/branches/network/kernel/generic/src/mm/slab.c |
---|
172,7 → 172,7 |
void *data; |
slab_t *slab; |
size_t fsize; |
int i; |
unsigned int i; |
unsigned int zone = 0; |
data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone); |
191,7 → 191,7 |
} |
/* Fill in slab structures */ |
for (i=0; i < (1 << cache->order); i++) |
for (i = 0; i < ((unsigned int) 1 << cache->order); i++) |
frame_set_parent(ADDR2PFN(KA2PA(data))+i, slab, zone); |
slab->start = data; |
239,8 → 239,7 |
* |
* @return Number of freed pages |
*/ |
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj, |
slab_t *slab) |
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab) |
{ |
int freed = 0; |
301,7 → 300,8 |
return NULL; |
spinlock_lock(&cache->slablock); |
} else { |
slab = list_get_instance(cache->partial_slabs.next, slab_t, link); |
slab = list_get_instance(cache->partial_slabs.next, slab_t, |
link); |
list_remove(&slab->link); |
} |
obj = slab->start + slab->nextavail * cache->size; |
332,8 → 332,7 |
* |
* @param first If true, return first, else last mag |
*/ |
static slab_magazine_t * get_mag_from_cache(slab_cache_t *cache, |
int first) |
static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache, int first) |
{ |
slab_magazine_t *mag = NULL; |
link_t *cur; |
368,10 → 367,9 |
* |
* @return Number of freed pages |
*/ |
static count_t magazine_destroy(slab_cache_t *cache, |
slab_magazine_t *mag) |
static count_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag) |
{ |
int i; |
unsigned int i; |
count_t frames = 0; |
for (i=0;i < mag->busy; i++) { |
527,19 → 525,20 |
/* Slab cache functions */ |
/** Return number of objects that fit in certain cache size */ |
static int comp_objects(slab_cache_t *cache) |
static unsigned int comp_objects(slab_cache_t *cache) |
{ |
if (cache->flags & SLAB_CACHE_SLINSIDE) |
return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) / cache->size; |
return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) / |
cache->size; |
else |
return (PAGE_SIZE << cache->order) / cache->size; |
} |
/** Return wasted space in slab */ |
static int badness(slab_cache_t *cache) |
static unsigned int badness(slab_cache_t *cache) |
{ |
int objects; |
int ssize; |
unsigned int objects; |
unsigned int ssize; |
objects = comp_objects(cache); |
ssize = PAGE_SIZE << cache->order; |
553,14 → 552,14 |
*/ |
static void make_magcache(slab_cache_t *cache) |
{ |
int i; |
unsigned int i; |
ASSERT(_slab_initialized >= 2); |
cache->mag_cache = malloc(sizeof(slab_mag_cache_t)*config.cpu_count,0); |
cache->mag_cache = malloc(sizeof(slab_mag_cache_t) * config.cpu_count, |
0); |
for (i=0; i < config.cpu_count; i++) { |
memsetb((uintptr_t)&cache->mag_cache[i], |
sizeof(cache->mag_cache[i]), 0); |
memsetb(&cache->mag_cache[i], sizeof(cache->mag_cache[i]), 0); |
spinlock_initialize(&cache->mag_cache[i].lock, |
"slab_maglock_cpu"); |
} |
568,18 → 567,14 |
/** Initialize allocated memory as a slab cache */ |
static void |
_slab_cache_create(slab_cache_t *cache, |
char *name, |
size_t size, |
size_t align, |
int (*constructor)(void *obj, int kmflag), |
int (*destructor)(void *obj), |
_slab_cache_create(slab_cache_t *cache, char *name, size_t size, size_t align, |
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj), |
int flags) |
{ |
int pages; |
ipl_t ipl; |
memsetb((uintptr_t)cache, sizeof(*cache), 0); |
memsetb(cache, sizeof(*cache), 0); |
cache->name = name; |
if (align < sizeof(unative_t)) |
631,11 → 626,9 |
} |
/** Create slab cache */ |
slab_cache_t * slab_cache_create(char *name, |
size_t size, |
size_t align, |
int (*constructor)(void *obj, int kmflag), |
int (*destructor)(void *obj), |
slab_cache_t * |
slab_cache_create(char *name, size_t size, size_t align, |
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj), |
int flags) |
{ |
slab_cache_t *cache; |
654,7 → 647,7 |
*/ |
static count_t _slab_reclaim(slab_cache_t *cache, int flags) |
{ |
int i; |
unsigned int i; |
slab_magazine_t *mag; |
count_t frames = 0; |
int magcount; |
719,8 → 712,8 |
_slab_reclaim(cache, SLAB_RECLAIM_ALL); |
/* All slabs must be empty */ |
if (!list_empty(&cache->full_slabs) \ |
|| !list_empty(&cache->partial_slabs)) |
if (!list_empty(&cache->full_slabs) || |
!list_empty(&cache->partial_slabs)) |
panic("Destroying cache that is not empty."); |
if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) |
728,8 → 721,7 |
slab_free(&slab_cache_cache, cache); |
} |
/** Allocate new object from cache - if no flags given, always returns |
memory */ |
/** Allocate new object from cache - if no flags given, always returns memory */ |
void * slab_alloc(slab_cache_t *cache, int flags) |
{ |
ipl_t ipl; |
759,9 → 751,8 |
ipl = interrupts_disable(); |
if ((cache->flags & SLAB_CACHE_NOMAGAZINE) \ |
|| magazine_obj_put(cache, obj)) { |
if ((cache->flags & SLAB_CACHE_NOMAGAZINE) || |
magazine_obj_put(cache, obj)) { |
slab_obj_destroy(cache, obj, slab); |
} |
788,7 → 779,8 |
* memory allocation from interrupts can deadlock. |
*/ |
for (cur = slab_cache_list.next;cur!=&slab_cache_list; cur=cur->next) { |
for (cur = slab_cache_list.next; cur != &slab_cache_list; |
cur = cur->next) { |
cache = list_get_instance(cur, slab_cache_t, link); |
frames += _slab_reclaim(cache, flags); |
} |
802,23 → 794,78 |
/* Print list of slabs */ |
void slab_print_list(void) |
{ |
int skip = 0; |
printf("slab name size pages obj/pg slabs cached allocated" |
" ctl\n"); |
printf("---------------- -------- ------ ------ ------ ------ ---------" |
" ---\n"); |
while (true) { |
slab_cache_t *cache; |
link_t *cur; |
ipl_t ipl; |
int i; |
/* |
* We must not hold the slab_cache_lock spinlock when printing |
* the statistics. Otherwise we can easily deadlock if the print |
* needs to allocate memory. |
* |
* Therefore, we walk through the slab cache list, skipping some |
* amount of already processed caches during each iteration and |
* gathering statistics about the first unprocessed cache. For |
* the sake of printing the statistics, we realese the |
* slab_cache_lock and reacquire it afterwards. Then the walk |
* starts again. |
* |
* This limits both the efficiency and also accuracy of the |
* obtained statistics. The efficiency is decreased because the |
* time complexity of the algorithm is quadratic instead of |
* linear. The accuracy is impacted because we drop the lock |
* after processing one cache. If there is someone else |
* manipulating the cache list, we might omit an arbitrary |
* number of caches or process one cache multiple times. |
* However, we don't bleed for this algorithm for it is only |
* statistics. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&slab_cache_lock); |
printf("slab name size pages obj/pg slabs cached allocated ctl\n"); |
printf("---------------- -------- ------ ------ ------ ------ --------- ---\n"); |
for (cur = slab_cache_list.next; cur != &slab_cache_list; cur = cur->next) { |
for (i = 0, cur = slab_cache_list.next; |
i < skip && cur != &slab_cache_list; |
i++, cur = cur->next) |
; |
if (cur == &slab_cache_list) { |
spinlock_unlock(&slab_cache_lock); |
interrupts_restore(ipl); |
break; |
} |
skip++; |
cache = list_get_instance(cur, slab_cache_t, link); |
printf("%-16s %8zd %6zd %6zd %6zd %6zd %9zd %-3s\n", cache->name, cache->size, (1 << cache->order), cache->objects, atomic_get(&cache->allocated_slabs), atomic_get(&cache->cached_objs), atomic_get(&cache->allocated_objs), cache->flags & SLAB_CACHE_SLINSIDE ? "in" : "out"); |
} |
char *name = cache->name; |
uint8_t order = cache->order; |
size_t size = cache->size; |
unsigned int objects = cache->objects; |
long allocated_slabs = atomic_get(&cache->allocated_slabs); |
long cached_objs = atomic_get(&cache->cached_objs); |
long allocated_objs = atomic_get(&cache->allocated_objs); |
int flags = cache->flags; |
spinlock_unlock(&slab_cache_lock); |
interrupts_restore(ipl); |
printf("%-16s %8" PRIs " %6d %6u %6ld %6ld %9ld %-3s\n", |
name, size, (1 << order), objects, allocated_slabs, |
cached_objs, allocated_objs, |
flags & SLAB_CACHE_SLINSIDE ? "in" : "out"); |
} |
} |
void slab_cache_init(void) |
{ |
825,31 → 872,23 |
int i, size; |
/* Initialize magazine cache */ |
_slab_cache_create(&mag_cache, |
"slab_magazine", |
_slab_cache_create(&mag_cache, "slab_magazine", |
sizeof(slab_magazine_t)+SLAB_MAG_SIZE*sizeof(void*), |
sizeof(uintptr_t), |
NULL, NULL, |
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE); |
sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE | |
SLAB_CACHE_SLINSIDE); |
/* Initialize slab_cache cache */ |
_slab_cache_create(&slab_cache_cache, |
"slab_cache", |
sizeof(slab_cache_cache), |
sizeof(uintptr_t), |
NULL, NULL, |
_slab_cache_create(&slab_cache_cache, "slab_cache", |
sizeof(slab_cache_cache), sizeof(uintptr_t), NULL, NULL, |
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE); |
/* Initialize external slab cache */ |
slab_extern_cache = slab_cache_create("slab_extern", |
sizeof(slab_t), |
0, NULL, NULL, |
SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED); |
slab_extern_cache = slab_cache_create("slab_extern", sizeof(slab_t), 0, |
NULL, NULL, SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED); |
/* Initialize structures for malloc */ |
for (i=0, size=(1<<SLAB_MIN_MALLOC_W); |
i < (SLAB_MAX_MALLOC_W-SLAB_MIN_MALLOC_W+1); |
i++, size <<= 1) { |
malloc_caches[i] = slab_cache_create(malloc_names[i], |
size, 0, |
malloc_caches[i] = slab_cache_create(malloc_names[i], size, 0, |
NULL,NULL, SLAB_CACHE_MAGDEFERRED); |
} |
#ifdef CONFIG_DEBUG |
875,9 → 914,11 |
spinlock_lock(&slab_cache_lock); |
for (cur=slab_cache_list.next; cur != &slab_cache_list;cur=cur->next){ |
for (cur = slab_cache_list.next; cur != &slab_cache_list; |
cur = cur->next){ |
s = list_get_instance(cur, slab_cache_t, link); |
if ((s->flags & SLAB_CACHE_MAGDEFERRED) != SLAB_CACHE_MAGDEFERRED) |
if ((s->flags & SLAB_CACHE_MAGDEFERRED) != |
SLAB_CACHE_MAGDEFERRED) |
continue; |
make_magcache(s); |
s->flags &= ~SLAB_CACHE_MAGDEFERRED; |
/branches/network/kernel/generic/src/mm/page.c |
---|
40,11 → 40,28 |
* They however, define the single interface. |
*/ |
/* |
* Note on memory prefetching and updating memory mappings, also described in: |
* AMD x86-64 Architecture Programmer's Manual, Volume 2, System Programming, |
* 7.2.1 Special Coherency Considerations. |
* |
* The processor which modifies a page table mapping can access prefetched data |
* from the old mapping. In order to prevent this, we place a memory barrier |
* after a mapping is updated. |
* |
* We assume that the other processors are either not using the mapping yet |
* (i.e. during the bootstrap) or are executing the TLB shootdown code. While |
* we don't care much about the former case, the processors in the latter case |
* will do an implicit serialization by virtue of running the TLB shootdown |
* interrupt handler. |
*/ |
#include <mm/page.h> |
#include <arch/mm/page.h> |
#include <arch/mm/asid.h> |
#include <mm/as.h> |
#include <mm/frame.h> |
#include <arch/barrier.h> |
#include <arch/types.h> |
#include <arch/asm.h> |
#include <memstr.h> |
76,8 → 93,11 |
cnt = length / PAGE_SIZE + (length % PAGE_SIZE > 0); |
for (i = 0; i < cnt; i++) |
page_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE, s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE); |
page_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE, |
s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE); |
/* Repel prefetched accesses to the old mapping. */ |
memory_barrier(); |
} |
/** Insert mapping of page to frame. |
89,7 → 109,8 |
* |
* @param as Address space to wich page belongs. |
* @param page Virtual address of the page to be mapped. |
* @param frame Physical address of memory frame to which the mapping is done. |
* @param frame Physical address of memory frame to which the mapping is |
* done. |
* @param flags Flags to be used for mapping. |
*/ |
void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags) |
98,6 → 119,9 |
ASSERT(page_mapping_operations->mapping_insert); |
page_mapping_operations->mapping_insert(as, page, frame, flags); |
/* Repel prefetched accesses to the old mapping. */ |
memory_barrier(); |
} |
/** Remove mapping of page. |
117,6 → 141,9 |
ASSERT(page_mapping_operations->mapping_remove); |
page_mapping_operations->mapping_remove(as, page); |
/* Repel prefetched accesses to the old mapping. */ |
memory_barrier(); |
} |
/** Find mapping for virtual page |
128,7 → 155,8 |
* @param as Address space to wich page belongs. |
* @param page Virtual page. |
* |
* @return NULL if there is no such mapping; requested mapping otherwise. |
* @return NULL if there is no such mapping; requested mapping |
* otherwise. |
*/ |
pte_t *page_mapping_find(as_t *as, uintptr_t page) |
{ |
/branches/network/kernel/generic/src/mm/tlb.c |
---|
81,7 → 81,7 |
void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, |
uintptr_t page, count_t count) |
{ |
int i; |
unsigned int i; |
CPU->tlb_active = 0; |
spinlock_lock(&tlblock); |
144,7 → 144,7 |
asid_t asid; |
uintptr_t page; |
count_t count; |
int i; |
unsigned int i; |
ASSERT(CPU); |
/branches/network/kernel/generic/src/ipc/sysipc.c |
---|
164,11 → 164,11 |
{ |
int phoneid; |
if (IPC_GET_RETVAL(answer->data) == EHANGUP) { |
if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) { |
/* In case of forward, hangup the forwared phone, |
* not the originator |
*/ |
spinlock_lock(&answer->data.phone->lock); |
mutex_lock(&answer->data.phone->lock); |
spinlock_lock(&TASK->answerbox.lock); |
if (answer->data.phone->state == IPC_PHONE_CONNECTED) { |
list_remove(&answer->data.phone->link); |
175,7 → 175,7 |
answer->data.phone->state = IPC_PHONE_SLAMMED; |
} |
spinlock_unlock(&TASK->answerbox.lock); |
spinlock_unlock(&answer->data.phone->lock); |
mutex_unlock(&answer->data.phone->lock); |
} |
if (!olddata) |
243,7 → 243,7 |
uintptr_t dst = IPC_GET_ARG1(*olddata); |
size_t max_size = IPC_GET_ARG2(*olddata); |
size_t size = IPC_GET_ARG2(answer->data); |
if (size <= max_size) { |
if (size && size <= max_size) { |
/* |
* Copy the destination VA so that this piece of |
* information is not lost. |
258,6 → 258,8 |
free(answer->buffer); |
answer->buffer = NULL; |
} |
} else if (!size) { |
IPC_SET_RETVAL(answer->data, EOK); |
} else { |
IPC_SET_RETVAL(answer->data, ELIMIT); |
} |
268,12 → 270,12 |
/* The recipient agreed to receive data. */ |
int rc; |
uintptr_t dst; |
uintptr_t size; |
uintptr_t max_size; |
size_t size; |
size_t max_size; |
dst = IPC_GET_ARG1(answer->data); |
size = IPC_GET_ARG2(answer->data); |
max_size = IPC_GET_ARG2(*olddata); |
dst = (uintptr_t)IPC_GET_ARG1(answer->data); |
size = (size_t)IPC_GET_ARG2(answer->data); |
max_size = (size_t)IPC_GET_ARG2(*olddata); |
if (size <= max_size) { |
rc = copy_to_uspace((void *) dst, |
354,7 → 356,7 |
*/ |
static void process_answer(call_t *call) |
{ |
if (IPC_GET_RETVAL(call->data) == EHANGUP && |
if (((native_t) IPC_GET_RETVAL(call->data) == EHANGUP) && |
(call->flags & IPC_CALL_FORWARDED)) |
IPC_SET_RETVAL(call->data, EFORWARD); |
440,7 → 442,9 |
IPC_SET_ARG5(call.data, 0); |
if (!(res = request_preprocess(&call))) { |
ipc_call_sync(phone, &call); |
rc = ipc_call_sync(phone, &call); |
if (rc != EOK) |
return rc; |
process_answer(&call); |
} else { |
IPC_SET_RETVAL(call.data, res); |
478,7 → 482,9 |
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
if (!(res = request_preprocess(&call))) { |
ipc_call_sync(phone, &call); |
rc = ipc_call_sync(phone, &call); |
if (rc != EOK) |
return rc; |
process_answer(&call); |
} else |
IPC_SET_RETVAL(call.data, res); |
/branches/network/kernel/generic/src/ipc/ipc.c |
---|
37,7 → 37,9 |
* First the answerbox, then the phone. |
*/ |
#include <synch/synch.h> |
#include <synch/spinlock.h> |
#include <synch/mutex.h> |
#include <synch/waitq.h> |
#include <synch/synch.h> |
#include <ipc/ipc.h> |
64,7 → 66,7 |
*/ |
static void _ipc_call_init(call_t *call) |
{ |
memsetb((uintptr_t) call, sizeof(*call), 0); |
memsetb(call, sizeof(*call), 0); |
call->callerbox = &TASK->answerbox; |
call->sender = TASK; |
call->buffer = NULL; |
85,6 → 87,7 |
call_t *call; |
call = slab_alloc(ipc_call_slab, flags); |
if (call) |
_ipc_call_init(call); |
return call; |
117,8 → 120,9 |
/** Initialize an answerbox structure. |
* |
* @param box Answerbox structure to be initialized. |
* @param task Task to which the answerbox belongs. |
*/ |
void ipc_answerbox_init(answerbox_t *box) |
void ipc_answerbox_init(answerbox_t *box, task_t *task) |
{ |
spinlock_initialize(&box->lock, "ipc_box_lock"); |
spinlock_initialize(&box->irq_lock, "ipc_box_irqlock"); |
129,7 → 133,7 |
list_initialize(&box->answers); |
list_initialize(&box->irq_notifs); |
list_initialize(&box->irq_head); |
box->task = TASK; |
box->task = task; |
} |
/** Connect a phone to an answerbox. |
139,7 → 143,7 |
*/ |
void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
{ |
spinlock_lock(&phone->lock); |
mutex_lock(&phone->lock); |
phone->state = IPC_PHONE_CONNECTED; |
phone->callee = box; |
148,7 → 152,7 |
list_append(&phone->link, &box->connected_phones); |
spinlock_unlock(&box->lock); |
spinlock_unlock(&phone->lock); |
mutex_unlock(&phone->lock); |
} |
/** Initialize a phone structure. |
157,7 → 161,7 |
*/ |
void ipc_phone_init(phone_t *phone) |
{ |
spinlock_initialize(&phone->lock, "phone_lock"); |
mutex_initialize(&phone->lock, MUTEX_PASSIVE); |
phone->callee = NULL; |
phone->state = IPC_PHONE_FREE; |
atomic_set(&phone->active_calls, 0); |
167,18 → 171,23 |
* |
* @param phone Destination kernel phone structure. |
* @param request Call structure with request. |
* |
* @return EOK on success or EINTR if the sleep was interrupted. |
*/ |
void ipc_call_sync(phone_t *phone, call_t *request) |
int ipc_call_sync(phone_t *phone, call_t *request) |
{ |
answerbox_t sync_box; |
ipc_answerbox_init(&sync_box); |
ipc_answerbox_init(&sync_box, TASK); |
/* We will receive data in a special box. */ |
request->callerbox = &sync_box; |
ipc_call(phone, request); |
ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, |
SYNCH_FLAGS_INTERRUPTIBLE)) |
return EINTR; |
return EOK; |
} |
/** Answer a message which was not dispatched and is not listed in any queue. |
191,6 → 200,13 |
call->flags |= IPC_CALL_ANSWERED; |
if (call->flags & IPC_CALL_FORWARDED) { |
if (call->data.caller_phone) { |
/* Demasquerade the caller phone. */ |
call->data.phone = call->data.caller_phone; |
} |
} |
spinlock_lock(&callerbox->lock); |
list_append(&call->link, &callerbox->answers); |
spinlock_unlock(&callerbox->lock); |
260,9 → 276,9 |
{ |
answerbox_t *box; |
spinlock_lock(&phone->lock); |
mutex_lock(&phone->lock); |
if (phone->state != IPC_PHONE_CONNECTED) { |
spinlock_unlock(&phone->lock); |
mutex_unlock(&phone->lock); |
if (call->flags & IPC_CALL_FORWARDED) { |
IPC_SET_RETVAL(call->data, EFORWARD); |
_ipc_answer_free_call(call); |
277,7 → 293,7 |
box = phone->callee; |
_ipc_call(phone, box, call); |
spinlock_unlock(&phone->lock); |
mutex_unlock(&phone->lock); |
return 0; |
} |
296,11 → 312,11 |
answerbox_t *box; |
call_t *call; |
spinlock_lock(&phone->lock); |
mutex_lock(&phone->lock); |
if (phone->state == IPC_PHONE_FREE || |
phone->state == IPC_PHONE_HUNGUP || |
phone->state == IPC_PHONE_CONNECTING) { |
spinlock_unlock(&phone->lock); |
mutex_unlock(&phone->lock); |
return -1; |
} |
box = phone->callee; |
319,7 → 335,7 |
} |
phone->state = IPC_PHONE_HUNGUP; |
spinlock_unlock(&phone->lock); |
mutex_unlock(&phone->lock); |
return 0; |
} |
343,8 → 359,11 |
list_remove(&call->link); |
spinlock_unlock(&oldbox->lock); |
if (mode & IPC_FF_ROUTE_FROM_ME) |
if (mode & IPC_FF_ROUTE_FROM_ME) { |
if (!call->data.caller_phone) |
call->data.caller_phone = call->data.phone; |
call->data.phone = newphone; |
} |
return ipc_call(newphone, call); |
} |
448,7 → 467,7 |
while (!list_empty(&TASK->answerbox.connected_phones)) { |
phone = list_get_instance(TASK->answerbox.connected_phones.next, |
phone_t, link); |
if (!spinlock_trylock(&phone->lock)) { |
if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { |
spinlock_unlock(&TASK->answerbox.lock); |
DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
goto restart_phones; |
459,7 → 478,7 |
phone->state = IPC_PHONE_SLAMMED; |
list_remove(&phone->link); |
spinlock_unlock(&phone->lock); |
mutex_unlock(&phone->lock); |
} |
/* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
534,7 → 553,10 |
/* Print opened phones & details */ |
printf("PHONE:\n"); |
for (i = 0; i < IPC_MAX_PHONES; i++) { |
spinlock_lock(&task->phones[i].lock); |
if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { |
printf("%d: mutex busy\n", i); |
continue; |
} |
if (task->phones[i].state != IPC_PHONE_FREE) { |
printf("%d: ", i); |
switch (task->phones[i].state) { |
556,10 → 578,10 |
default: |
break; |
} |
printf("active: %d\n", |
printf("active: %ld\n", |
atomic_get(&task->phones[i].active_calls)); |
} |
spinlock_unlock(&task->phones[i].lock); |
mutex_unlock(&task->phones[i].lock); |
} |
569,8 → 591,9 |
for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
"A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid, |
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
582,8 → 605,9 |
tmp != &task->answerbox.dispatched_calls; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
"A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid, |
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
594,7 → 618,8 |
for (tmp = task->answerbox.answers.next; tmp != &task->answerbox.answers; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid:%p M:%d A1:%d A2:%d A3:%d A4:%d A5:%d Flags:%x\n", |
printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun |
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", |
call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
/branches/network/kernel/generic/src/ipc/ipcrsc.c |
---|
170,7 → 170,6 |
int i; |
spinlock_lock(&TASK->lock); |
for (i = 0; i < IPC_MAX_PHONES; i++) { |
if (TASK->phones[i].state == IPC_PHONE_HUNGUP && |
atomic_get(&TASK->phones[i].active_calls) == 0) |
183,8 → 182,9 |
} |
spinlock_unlock(&TASK->lock); |
if (i >= IPC_MAX_PHONES) |
if (i == IPC_MAX_PHONES) |
return -1; |
return i; |
} |
/branches/network/kernel/generic/src/ipc/irq.c |
---|
65,7 → 65,7 |
*/ |
static void code_execute(call_t *call, irq_code_t *code) |
{ |
int i; |
unsigned int i; |
unative_t dstval = 0; |
if (!code) |
/branches/network/kernel/generic/src/main/kinit.c |
---|
47,6 → 47,7 |
#include <proc/scheduler.h> |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <proc/program.h> |
#include <panic.h> |
#include <func.h> |
#include <cpu.h> |
146,7 → 147,8 |
/* |
* Create kernel console. |
*/ |
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole", false); |
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole", |
false); |
if (t) |
thread_ready(t); |
else |
154,38 → 156,52 |
interrupts_enable(); |
count_t i; |
for (i = 0; i < init.cnt; i++) { |
/* |
* Run user tasks, load RAM disk images. |
* Create user tasks, load RAM disk images. |
*/ |
count_t i; |
program_t programs[CONFIG_INIT_TASKS]; |
for (i = 0; i < init.cnt; i++) { |
if (init.tasks[i].addr % FRAME_SIZE) { |
printf("init[%d].addr is not frame aligned", i); |
printf("init[%" PRIc "].addr is not frame aligned", i); |
continue; |
} |
task_t *utask = task_run_program((void *) init.tasks[i].addr, |
"uspace"); |
int rc = program_create_from_image((void *) init.tasks[i].addr, |
&programs[i]); |
if (utask) { |
if (rc == 0 && programs[i].task != NULL) { |
/* |
* Set capabilities to init userspace tasks. |
*/ |
cap_set(utask, CAP_CAP | CAP_MEM_MANAGER | |
cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER | |
CAP_IO_MANAGER | CAP_PREEMPT_CONTROL | CAP_IRQ_REG); |
if (!ipc_phone_0) |
ipc_phone_0 = &utask->answerbox; |
ipc_phone_0 = &programs[i].task->answerbox; |
} else if (rc == 0) { |
/* It was the program loader and was registered */ |
} else { |
int rd = init_rd((rd_header *) init.tasks[i].addr, |
/* RAM disk image */ |
int rd = init_rd((rd_header_t *) init.tasks[i].addr, |
init.tasks[i].size); |
if (rd != RE_OK) |
printf("Init binary %zd not used, error code %d.\n", i, rd); |
printf("Init binary %" PRIc " not used, error " |
"code %d.\n", i, rd); |
} |
} |
/* |
* Run user tasks with reasonable delays |
*/ |
for (i = 0; i < init.cnt; i++) { |
if (programs[i].task != NULL) { |
thread_usleep(50000); |
program_ready(&programs[i]); |
} |
} |
if (!stdin) { |
while (1) { |
/branches/network/kernel/generic/src/main/main.c |
---|
57,9 → 57,11 |
#include <proc/scheduler.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/tasklet.h> |
#include <main/kinit.h> |
#include <main/version.h> |
#include <console/kconsole.h> |
#include <console/console.h> |
#include <cpu.h> |
#include <align.h> |
#include <interrupt.h> |
77,16 → 79,16 |
#include <ipc/ipc.h> |
#include <macros.h> |
#include <adt/btree.h> |
#include <console/klog.h> |
#include <smp/smp.h> |
#include <ddi/ddi.h> |
/** Global configuration structure. */ |
config_t config; |
/** Initial user-space tasks */ |
init_t init = { |
0 |
.cnt = 0 |
}; |
/** Boot allocations. */ |
102,15 → 104,16 |
* the linker or the low level assembler code with |
* appropriate sizes and addresses. |
*/ |
uintptr_t hardcoded_load_address = 0; /**< Virtual address of where the kernel |
* is loaded. */ |
size_t hardcoded_ktext_size = 0; /**< Size of the kernel code in bytes. |
*/ |
size_t hardcoded_kdata_size = 0; /**< Size of the kernel data in bytes. |
*/ |
uintptr_t stack_safe = 0; /**< Lowest safe stack virtual address. |
*/ |
/**< Virtual address of where the kernel is loaded. */ |
uintptr_t hardcoded_load_address = 0; |
/**< Size of the kernel code in bytes. */ |
size_t hardcoded_ktext_size = 0; |
/**< Size of the kernel data in bytes. */ |
size_t hardcoded_kdata_size = 0; |
/**< Lowest safe stack virtual address. */ |
uintptr_t stack_safe = 0; |
void main_bsp(void); |
void main_ap(void); |
129,9 → 132,11 |
/** Main kernel routine for bootstrap CPU. |
* |
* Initializes the kernel by bootstrap CPU. |
* This function passes control directly to |
* main_bsp_separated_stack(). |
* The code here still runs on the boot stack, which knows nothing about |
* preemption counts. Because of that, this function cannot directly call |
* functions that disable or enable preemption (e.g. spinlock_lock()). The |
* primary task of this function is to calculate address of a new stack and |
* switch to it. |
* |
* Assuming interrupts_disable(). |
* |
184,89 → 189,93 |
*/ |
void main_bsp_separated_stack(void) |
{ |
task_t *k; |
thread_t *t; |
count_t i; |
/* Keep this the first thing. */ |
the_initialize(THE); |
LOG(); |
version_print(); |
LOG("\nconfig.base=%#" PRIp " config.kernel_size=%" PRIs |
"\nconfig.stack_base=%#" PRIp " config.stack_size=%" PRIs, |
config.base, config.kernel_size, config.stack_base, |
config.stack_size); |
/* |
* kconsole data structures must be initialized very early |
* because other subsystems will register their respective |
* commands. |
*/ |
kconsole_init(); |
LOG_EXEC(kconsole_init()); |
/* |
* Exception handler initialization, before architecture |
* starts adding its own handlers |
*/ |
exc_init(); |
LOG_EXEC(exc_init()); |
/* |
* Memory management subsystems initialization. |
*/ |
arch_pre_mm_init(); |
frame_init(); |
LOG_EXEC(arch_pre_mm_init()); |
LOG_EXEC(frame_init()); |
/* Initialize at least 1 memory segment big enough for slab to work. */ |
slab_cache_init(); |
btree_init(); |
as_init(); |
page_init(); |
tlb_init(); |
ddi_init(); |
arch_post_mm_init(); |
LOG_EXEC(slab_cache_init()); |
LOG_EXEC(btree_init()); |
LOG_EXEC(as_init()); |
LOG_EXEC(page_init()); |
LOG_EXEC(tlb_init()); |
LOG_EXEC(ddi_init()); |
LOG_EXEC(tasklet_init()); |
LOG_EXEC(arch_post_mm_init()); |
LOG_EXEC(arch_pre_smp_init()); |
LOG_EXEC(smp_init()); |
version_print(); |
printf("kernel: %.*p hardcoded_ktext_size=%zd KB, " |
"hardcoded_kdata_size=%zd KB\n", sizeof(uintptr_t) * 2, |
config.base, SIZE2KB(hardcoded_ktext_size), |
SIZE2KB(hardcoded_kdata_size)); |
printf("stack: %.*p size=%zd KB\n", sizeof(uintptr_t) * 2, |
config.stack_base, SIZE2KB(config.stack_size)); |
arch_pre_smp_init(); |
smp_init(); |
/* Slab must be initialized after we know the number of processors. */ |
slab_enable_cpucache(); |
LOG_EXEC(slab_enable_cpucache()); |
printf("Detected %zu CPU(s), %llu MB free memory\n", |
printf("Detected %" PRIc " CPU(s), %" PRIu64" MiB free memory\n", |
config.cpu_count, SIZE2MB(zone_total_size())); |
cpu_init(); |
calibrate_delay_loop(); |
clock_counter_init(); |
timeout_init(); |
scheduler_init(); |
task_init(); |
thread_init(); |
futex_init(); |
klog_init(); |
LOG_EXEC(cpu_init()); |
LOG_EXEC(calibrate_delay_loop()); |
LOG_EXEC(clock_counter_init()); |
LOG_EXEC(timeout_init()); |
LOG_EXEC(scheduler_init()); |
LOG_EXEC(task_init()); |
LOG_EXEC(thread_init()); |
LOG_EXEC(futex_init()); |
if (init.cnt > 0) { |
count_t i; |
for (i = 0; i < init.cnt; i++) |
printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i, |
sizeof(uintptr_t) * 2, init.tasks[i].addr, i, |
printf("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc |
"].size=%#" PRIs "\n", i, init.tasks[i].addr, i, |
init.tasks[i].size); |
} else |
printf("No init binaries found\n"); |
ipc_init(); |
LOG_EXEC(ipc_init()); |
LOG_EXEC(klog_init()); |
/* |
* Create kernel task. |
*/ |
k = task_create(AS_KERNEL, "kernel"); |
if (!k) |
panic("can't create kernel task\n"); |
task_t *kernel = task_create(AS_KERNEL, "kernel"); |
if (!kernel) |
panic("Can't create kernel task\n"); |
/* |
* Create the first thread. |
*/ |
t = thread_create(kinit, NULL, k, 0, "kinit", true); |
if (!t) |
panic("can't create kinit thread\n"); |
thread_ready(t); |
thread_t *kinit_thread = thread_create(kinit, NULL, kernel, 0, "kinit", |
true); |
if (!kinit_thread) |
panic("Can't create kinit thread\n"); |
LOG_EXEC(thread_ready(kinit_thread)); |
/* |
* This call to scheduler() will return to kinit, |
/branches/network/kernel/generic/src/proc/task.c |
---|
35,10 → 35,8 |
* @brief Task management. |
*/ |
#include <main/uinit.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/uarg.h> |
#include <mm/as.h> |
#include <mm/slab.h> |
#include <atomic.h> |
45,23 → 43,17 |
#include <synch/spinlock.h> |
#include <synch/waitq.h> |
#include <arch.h> |
#include <panic.h> |
#include <arch/barrier.h> |
#include <adt/avl.h> |
#include <adt/btree.h> |
#include <adt/list.h> |
#include <ipc/ipc.h> |
#include <security/cap.h> |
#include <memstr.h> |
#include <ipc/ipcrsc.h> |
#include <print.h> |
#include <lib/elf.h> |
#include <errno.h> |
#include <func.h> |
#include <syscall/copy.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
#define LOADED_PROG_STACK_PAGES_NO 1 |
#endif |
/** Spinlock protecting the tasks_tree AVL tree. */ |
SPINLOCK_INITIALIZE(tasks_lock); |
79,11 → 71,7 |
static task_id_t task_counter = 0; |
/** Initialize tasks |
* |
* Initialize kernel tasks support. |
* |
*/ |
/** Initialize kernel tasks support. */ |
void task_init(void) |
{ |
TASK = NULL; |
91,7 → 79,8 |
} |
/* |
* The idea behind this walker is to remember a single task different from TASK. |
* The idea behind this walker is to remember a single task different from |
* TASK. |
*/ |
static bool task_done_walker(avltree_node_t *node, void *arg) |
{ |
106,9 → 95,7 |
return true; /* continue the walk */ |
} |
/** Kill all tasks except the current task. |
* |
*/ |
/** Kill all tasks except the current task. */ |
void task_done(void) |
{ |
task_t *t; |
128,7 → 115,7 |
interrupts_restore(ipl); |
#ifdef CONFIG_DEBUG |
printf("Killing task %llu\n", id); |
printf("Killing task %" PRIu64 "\n", id); |
#endif |
task_kill(id); |
thread_usleep(10000); |
140,14 → 127,12 |
} while (t != NULL); |
} |
/** Create new task |
/** Create new task with no threads. |
* |
* Create new task with no threads. |
* |
* @param as Task's address space. |
* @param name Symbolic name. |
* |
* @return New task's structure |
* @return New task's structure. |
* |
*/ |
task_t *task_create(as_t *as, char *name) |
171,7 → 156,7 |
ta->capabilities = 0; |
ta->cycles = 0; |
ipc_answerbox_init(&ta->answerbox); |
ipc_answerbox_init(&ta->answerbox, ta); |
for (i = 0; i < IPC_MAX_PHONES; i++) |
ipc_phone_init(&ta->phones[i]); |
if ((ipc_phone_0) && (context_check(ipc_phone_0->task->context, |
179,7 → 164,7 |
ipc_phone_connect(&ta->phones[0], ipc_phone_0); |
atomic_set(&ta->active_calls, 0); |
mutex_initialize(&ta->futexes_lock); |
mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE); |
btree_create(&ta->futexes); |
ipl = interrupts_disable(); |
233,73 → 218,18 |
TASK = NULL; |
} |
/** Create new task with 1 thread and run it |
* |
* @param program_addr Address of program executable image. |
* @param name Program name. |
* |
* @return Task of the running program or NULL on error. |
*/ |
task_t *task_run_program(void *program_addr, char *name) |
{ |
as_t *as; |
as_area_t *a; |
int rc; |
thread_t *t; |
task_t *task; |
uspace_arg_t *kernel_uarg; |
as = as_create(0); |
ASSERT(as); |
rc = elf_load((elf_header_t *) program_addr, as); |
if (rc != EE_OK) { |
as_destroy(as); |
return NULL; |
} |
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
kernel_uarg->uspace_entry = |
(void *) ((elf_header_t *) program_addr)->e_entry; |
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
kernel_uarg->uspace_thread_function = NULL; |
kernel_uarg->uspace_thread_arg = NULL; |
kernel_uarg->uspace_uarg = NULL; |
task = task_create(as, name); |
ASSERT(task); |
/* |
* Create the data as_area. |
*/ |
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, |
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS, |
AS_AREA_ATTR_NONE, &anon_backend, NULL); |
/* |
* Create the main thread. |
*/ |
t = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, |
"uinit", false); |
ASSERT(t); |
thread_ready(t); |
return task; |
} |
/** Syscall for reading task ID from userspace. |
* |
* @param uspace_task_id Userspace address of 8-byte buffer where to store |
* current task ID. |
* @param uspace_task_id userspace address of 8-byte buffer |
* where to store current task ID. |
* |
* @return 0 on success or an error code from @ref errno.h. |
* @return Zero on success or an error code from @ref errno.h. |
*/ |
unative_t sys_task_get_id(task_id_t *uspace_task_id) |
{ |
/* |
* No need to acquire lock on TASK because taskid |
* remains constant for the lifespan of the task. |
* No need to acquire lock on TASK because taskid remains constant for |
* the lifespan of the task. |
*/ |
return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
sizeof(TASK->taskid)); |
307,16 → 237,15 |
/** Find task structure corresponding to task ID. |
* |
* The tasks_lock must be already held by the caller of this function |
* and interrupts must be disabled. |
* The tasks_lock must be already held by the caller of this function and |
* interrupts must be disabled. |
* |
* @param id Task ID. |
* |
* @return Task structure address or NULL if there is no such task ID. |
* @return Task structure address or NULL if there is no such task |
* ID. |
*/ |
task_t *task_find_by_id(task_id_t id) |
{ |
avltree_node_t *node; |
task_t *task_find_by_id(task_id_t id) { avltree_node_t *node; |
node = avltree_search(&tasks_tree, (avltree_key_t) id); |
327,11 → 256,13 |
/** Get accounting data of given task. |
* |
* Note that task lock of 't' must be already held and |
* interrupts must be already disabled. |
* Note that task lock of 't' must be already held and interrupts must be |
* already disabled. |
* |
* @param t Pointer to thread. |
* |
* @return Number of cycles used by the task and all its threads |
* so far. |
*/ |
uint64_t task_get_accounting(task_t *t) |
{ |
365,7 → 296,7 |
* |
* @param id ID of the task to be killed. |
* |
* @return 0 on success or an error code from errno.h |
* @return Zero on success or an error code from errno.h. |
*/ |
int task_kill(task_id_t id) |
{ |
386,7 → 317,7 |
spinlock_unlock(&tasks_lock); |
/* |
* Interrupt all threads except ktaskclnp. |
* Interrupt all threads. |
*/ |
spinlock_lock(&ta->lock); |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
421,17 → 352,21 |
char suffix; |
order(task_get_accounting(t), &cycles, &suffix); |
if (sizeof(void *) == 4) |
printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd %6zd", |
t->taskid, t->name, t->context, t, t->as, cycles, suffix, |
t->refcount, atomic_get(&t->active_calls)); |
else |
printf("%-6llu %-10s %-3ld %#18zx %#18zx %9llu%c %7zd %6zd", |
t->taskid, t->name, t->context, t, t->as, cycles, suffix, |
t->refcount, atomic_get(&t->active_calls)); |
#ifdef __32_BITS__ |
printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %10p %10p %9" PRIu64 |
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
#endif |
#ifdef __64_BITS__ |
printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %18p %18p %9" PRIu64 |
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
#endif |
for (j = 0; j < IPC_MAX_PHONES; j++) { |
if (t->phones[j].callee) |
printf(" %zd:%#zx", j, t->phones[j].callee); |
printf(" %d:%p", j, t->phones[j].callee); |
} |
printf("\n"); |
448,17 → 383,19 |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
if (sizeof(void *) == 4) { |
#ifdef __32_BITS__ |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ---------- --- ---------- ---------- " |
"---------- ------- ------ ------>\n"); |
} else { |
#endif |
#ifdef __64_BITS__ |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ---------- --- ------------------ ------------------ " |
"---------- ------- ------ ------>\n"); |
} |
#endif |
avltree_walk(&tasks_tree, task_print_walker, NULL); |
/branches/network/kernel/generic/src/proc/thread.c |
---|
67,9 → 67,13 |
#include <main/uinit.h> |
#include <syscall/copy.h> |
#include <errno.h> |
#include <console/klog.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
#define LOADED_PROG_STACK_PAGES_NO 1 |
#endif |
/** Thread states */ |
char *thread_states[] = { |
"Invalid", |
87,7 → 91,7 |
*/ |
SPINLOCK_INITIALIZE(threads_lock); |
/** ALV tree of all threads. |
/** AVL tree of all threads. |
* |
* When a thread is found in the threads_tree AVL tree, it is guaranteed to |
* exist as long as the threads_lock is held. |
267,7 → 271,9 |
* |
* @param func Thread's implementing function. |
* @param arg Thread's implementing function argument. |
* @param task Task to which the thread belongs. |
* @param task Task to which the thread belongs. The caller must |
* guarantee that the task won't cease to exist during the |
* call. The task's lock may not be held. |
* @param flags Thread flags. |
* @param name Symbolic name. |
* @param uncounted Thread's accounting doesn't affect accumulated task |
287,8 → 293,7 |
return NULL; |
/* Not needed, but good for debugging */ |
memsetb((uintptr_t) t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, |
0); |
memsetb(t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0); |
ipl = interrupts_disable(); |
spinlock_lock(&tidlock); |
442,8 → 447,7 |
if (THREAD->flags & THREAD_FLAG_USPACE) { |
ipc_cleanup(); |
futex_cleanup(); |
klog_printf("Cleanup of task %llu completed.", |
TASK->taskid); |
LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid); |
} |
} |
579,33 → 583,37 |
static bool thread_walker(avltree_node_t *node, void *arg) |
{ |
thread_t *t; |
thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node); |
t = avltree_get_instance(node, thread_t, threads_tree_node); |
uint64_t cycles; |
char suffix; |
order(t->cycles, &cycles, &suffix); |
if (sizeof(void *) == 4) |
printf("%-6llu %-10s %#10zx %-8s %#10zx %-3ld %#10zx %#10zx %9llu%c ", |
#ifdef __32_BITS__ |
printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" PRIu64 "%c ", |
t->tid, t->name, t, thread_states[t->state], t->task, |
t->task->context, t->thread_code, t->kstack, cycles, suffix); |
else |
printf("%-6llu %-10s %#18zx %-8s %#18zx %-3ld %#18zx %#18zx %9llu%c ", |
#endif |
#ifdef __64_BITS__ |
printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" PRIu64 "%c ", |
t->tid, t->name, t, thread_states[t->state], t->task, |
t->task->context, t->thread_code, t->kstack, cycles, suffix); |
#endif |
if (t->cpu) |
printf("%-4zd", t->cpu->id); |
printf("%-4u", t->cpu->id); |
else |
printf("none"); |
if (t->state == Sleeping) { |
if (sizeof(uintptr_t) == 4) |
printf(" %#10zx", t->sleep_queue); |
else |
printf(" %#18zx", t->sleep_queue); |
#ifdef __32_BITS__ |
printf(" %10p", t->sleep_queue); |
#endif |
#ifdef __64_BITS__ |
printf(" %18p", t->sleep_queue); |
#endif |
} |
printf("\n"); |
622,7 → 630,7 |
ipl = interrupts_disable(); |
spinlock_lock(&threads_lock); |
if (sizeof(uintptr_t) == 4) { |
#ifdef __32_BITS__ |
printf("tid name address state task " |
"ctx code stack cycles cpu " |
"waitqueue\n"); |
629,7 → 637,9 |
printf("------ ---------- ---------- -------- ---------- " |
"--- ---------- ---------- ---------- ---- " |
"----------\n"); |
} else { |
#endif |
#ifdef __64_BITS__ |
printf("tid name address state task " |
"ctx code stack cycles cpu " |
"waitqueue\n"); |
636,7 → 646,7 |
printf("------ ---------- ------------------ -------- ------------------ " |
"--- ------------------ ------------------ ---------- ---- " |
"------------------\n"); |
} |
#endif |
avltree_walk(&threads_tree, thread_walker, NULL); |
662,7 → 672,6 |
return node != NULL; |
} |
/** Update accounting of current thread. |
* |
* Note that thread_lock on THREAD must be already held and |
/branches/network/kernel/generic/src/proc/program.c |
---|
0,0 → 1,239 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genericproc |
* @{ |
*/ |
/** |
* @file |
* @brief Running userspace programs. |
*/ |
#include <main/uinit.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/uarg.h> |
#include <mm/as.h> |
#include <mm/slab.h> |
#include <arch.h> |
#include <adt/list.h> |
#include <ipc/ipc.h> |
#include <ipc/ipcrsc.h> |
#include <security/cap.h> |
#include <lib/elf.h> |
#include <errno.h> |
#include <print.h> |
#include <syscall/copy.h> |
#include <proc/program.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
#define LOADED_PROG_STACK_PAGES_NO 1 |
#endif |
/** |
* Points to the binary image used as the program loader. All non-initial |
* tasks are created from this executable image. |
*/ |
void *program_loader = NULL; |
/** Create a program using an existing address space. |
* |
* @param as Address space containing a binary program image. |
* @param entry_addr Program entry-point address in program address space. |
* @param p Buffer for storing program information. |
*/ |
void program_create(as_t *as, uintptr_t entry_addr, program_t *p) |
{ |
as_area_t *a; |
uspace_arg_t *kernel_uarg; |
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
kernel_uarg->uspace_entry = (void *) entry_addr; |
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
kernel_uarg->uspace_thread_function = NULL; |
kernel_uarg->uspace_thread_arg = NULL; |
kernel_uarg->uspace_uarg = NULL; |
p->task = task_create(as, "app"); |
ASSERT(p->task); |
/* |
* Create the data as_area. |
*/ |
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, |
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS, |
AS_AREA_ATTR_NONE, &anon_backend, NULL); |
/* |
* Create the main thread. |
*/ |
p->main_thread = thread_create(uinit, kernel_uarg, p->task, |
THREAD_FLAG_USPACE, "uinit", false); |
ASSERT(p->main_thread); |
} |
/** Parse an executable image in the kernel memory. |
* |
* If the image belongs to a program loader, it is registered as such, |
* (and *task is set to NULL). Otherwise a task is created from the |
* executable image. The task is returned in *task. |
* |
* @param image_addr Address of an executable program image. |
* @param p Buffer for storing program info. If image_addr |
* points to a loader image, p->task will be set to |
* NULL and EOK will be returned. |
* |
* @return EOK on success or negative error code. |
*/ |
int program_create_from_image(void *image_addr, program_t *p) |
{ |
as_t *as; |
unsigned int rc; |
as = as_create(0); |
ASSERT(as); |
rc = elf_load((elf_header_t *) image_addr, as, 0); |
if (rc != EE_OK) { |
as_destroy(as); |
p->task = NULL; |
p->main_thread = NULL; |
if (rc != EE_LOADER) |
return ENOTSUP; |
/* Register image as the program loader */ |
ASSERT(program_loader == NULL); |
program_loader = image_addr; |
printf("Registered program loader at 0x%" PRIp "\n", |
image_addr); |
return EOK; |
} |
program_create(as, ((elf_header_t *) image_addr)->e_entry, p); |
return EOK; |
} |
/** Create a task from the program loader image. |
* |
* @param p Buffer for storing program info. |
* @return EOK on success or negative error code. |
*/ |
int program_create_loader(program_t *p) |
{ |
as_t *as; |
unsigned int rc; |
void *loader; |
as = as_create(0); |
ASSERT(as); |
loader = program_loader; |
if (!loader) { |
printf("Cannot spawn loader as none was registered\n"); |
return ENOENT; |
} |
rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER); |
if (rc != EE_OK) { |
as_destroy(as); |
return ENOENT; |
} |
program_create(as, ((elf_header_t *) program_loader)->e_entry, p); |
return EOK; |
} |
/** Make program ready. |
* |
* Switch program's main thread to the ready state. |
* |
* @param p Program to make ready. |
*/ |
void program_ready(program_t *p) |
{ |
thread_ready(p->main_thread); |
} |
/** Syscall for creating a new loader instance from userspace. |
* |
* Creates a new task from the program loader image, connects a phone |
* to it and stores the phone id into the provided buffer. |
* |
* @param uspace_phone_id Userspace address where to store the phone id. |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_program_spawn_loader(int *uspace_phone_id) |
{ |
program_t p; |
int fake_id; |
int rc; |
int phone_id; |
fake_id = 0; |
/* Before we even try creating the task, see if we can write the id */ |
rc = (unative_t) copy_to_uspace(uspace_phone_id, &fake_id, |
sizeof(fake_id)); |
if (rc != 0) |
return rc; |
phone_id = phone_alloc(); |
if (phone_id < 0) |
return ELIMIT; |
rc = program_create_loader(&p); |
if (rc != 0) |
return rc; |
phone_connect(phone_id, &p.task->answerbox); |
/* No need to aquire lock before task_ready() */ |
rc = (unative_t) copy_to_uspace(uspace_phone_id, &phone_id, |
sizeof(phone_id)); |
if (rc != 0) { |
/* Ooops */ |
ipc_phone_hangup(&TASK->phones[phone_id]); |
task_kill(p.task->taskid); |
return rc; |
} |
// FIXME: control the capabilities |
cap_set(p.task, cap_get(TASK)); |
program_ready(&p); |
return EOK; |
} |
/** @} |
*/ |
/branches/network/kernel/generic/src/proc/scheduler.c |
---|
451,8 → 451,8 |
/* |
* Entering state is unexpected. |
*/ |
panic("tid%llu: unexpected state %s\n", THREAD->tid, |
thread_states[THREAD->state]); |
panic("tid%" PRIu64 ": unexpected state %s\n", |
THREAD->tid, thread_states[THREAD->state]); |
break; |
} |
504,9 → 504,9 |
THREAD->state = Running; |
#ifdef SCHEDULER_VERBOSE |
printf("cpu%d: tid %llu (priority=%d, ticks=%llu, nrdy=%ld)\n", |
CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, |
atomic_get(&CPU->nrdy)); |
printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64 |
", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority, |
THREAD->ticks, atomic_get(&CPU->nrdy)); |
#endif |
/* |
640,9 → 640,9 |
*/ |
spinlock_lock(&t->lock); |
#ifdef KCPULB_VERBOSE |
printf("kcpulb%d: TID %llu -> cpu%d, nrdy=%ld, " |
"avg=%nd\n", CPU->id, t->tid, CPU->id, |
atomic_get(&CPU->nrdy), |
printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, " |
"nrdy=%ld, avg=%ld\n", CPU->id, t->tid, |
CPU->id, atomic_get(&CPU->nrdy), |
atomic_get(&nrdy) / config.cpu_active); |
#endif |
t->flags |= THREAD_FLAG_STOLEN; |
708,7 → 708,7 |
continue; |
spinlock_lock(&cpus[cpu].lock); |
printf("cpu%d: address=%p, nrdy=%ld, needs_relink=%ld\n", |
printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIc "\n", |
cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy), |
cpus[cpu].needs_relink); |
719,11 → 719,11 |
spinlock_unlock(&r->lock); |
continue; |
} |
printf("\trq[%d]: ", i); |
printf("\trq[%u]: ", i); |
for (cur = r->rq_head.next; cur != &r->rq_head; |
cur = cur->next) { |
t = list_get_instance(cur, thread_t, rq_link); |
printf("%llu(%s) ", t->tid, |
printf("%" PRIu64 "(%s) ", t->tid, |
thread_states[t->state]); |
} |
printf("\n"); |
/branches/network/kernel/generic/src/proc/tasklet.c |
---|
0,0 → 1,64 |
/* |
* Copyright (c) 2007 Jan Hudecek |
* 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 genericproc |
* @{ |
*/ |
/** @file tasklet.c |
* @brief Tasklet implementation |
*/ |
#include <proc/tasklet.h> |
#include <synch/spinlock.h> |
#include <mm/slab.h> |
#include <config.h> |
/** Spinlock protecting list of tasklets */ |
SPINLOCK_INITIALIZE(tasklet_lock); |
/** Array of tasklet lists for every CPU */ |
tasklet_descriptor_t **tasklet_list; |
void tasklet_init(void) |
{ |
unsigned int i; |
tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0); |
if (!tasklet_list) |
panic("Error initializing tasklets"); |
for (i = 0; i < config.cpu_count; i++) |
tasklet_list[i] = NULL; |
spinlock_initialize(&tasklet_lock, "tasklet_lock"); |
} |
/** @} |
*/ |
/branches/network/kernel/generic/src/lib/objc_ext.c |
---|
File deleted |
/branches/network/kernel/generic/src/lib/objc.c |
---|
File deleted |
/branches/network/kernel/generic/src/lib/memstr.c |
---|
59,7 → 59,7 |
*/ |
void *_memcpy(void * dst, const void *src, size_t cnt) |
{ |
int i, j; |
unsigned int i, j; |
if (ALIGN_UP((uintptr_t) src, sizeof(unative_t)) != (uintptr_t) src || |
ALIGN_UP((uintptr_t) dst, sizeof(unative_t)) != (uintptr_t) dst) { |
74,7 → 74,7 |
((uint8_t *)(((unative_t *) dst) + i))[j] = ((uint8_t *)(((unative_t *) src) + i))[j]; |
} |
return (char *) src; |
return (char *) dst; |
} |
/** Fill block of memory |
87,9 → 87,9 |
* @param x Value to fill. |
* |
*/ |
void _memsetb(uintptr_t dst, size_t cnt, uint8_t x) |
void _memsetb(void *dst, size_t cnt, uint8_t x) |
{ |
int i; |
unsigned int i; |
uint8_t *p = (uint8_t *) dst; |
for (i = 0; i < cnt; i++) |
106,9 → 106,9 |
* @param x Value to fill. |
* |
*/ |
void _memsetw(uintptr_t dst, size_t cnt, uint16_t x) |
void _memsetw(void *dst, size_t cnt, uint16_t x) |
{ |
int i; |
unsigned int i; |
uint16_t *p = (uint16_t *) dst; |
for (i = 0; i < cnt; i++) |
/branches/network/kernel/generic/src/lib/rd.c |
---|
38,11 → 38,10 |
*/ |
#include <lib/rd.h> |
#include <arch/byteorder.h> |
#include <byteorder.h> |
#include <mm/frame.h> |
#include <sysinfo/sysinfo.h> |
#include <ddi/ddi.h> |
#include <print.h> |
#include <align.h> |
static parea_t rd_parea; /**< Physical memory area for rd. */ |
49,10 → 48,10 |
/** |
* RAM disk initialization routine. At this point, the RAM disk memory is shared |
* and information about the share is provided as sysinfo values to the userspace |
* tasks. |
* and information about the share is provided as sysinfo values to the |
* userspace tasks. |
*/ |
int init_rd(rd_header * header, size_t size) |
int init_rd(rd_header_t *header, size_t size) |
{ |
/* Identify RAM disk */ |
if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) || |
81,9 → 80,6 |
if ((hsize % FRAME_SIZE) || (dsize % FRAME_SIZE)) |
return RE_UNSUPPORTED; |
if (dsize % FRAME_SIZE) |
return RE_UNSUPPORTED; |
if (hsize > size) |
return RE_INVALID; |
90,7 → 86,8 |
if ((uint64_t) hsize + dsize > size) |
dsize = size - hsize; |
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize), FRAME_SIZE); |
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize), |
FRAME_SIZE); |
rd_parea.vbase = (uintptr_t) ((void *) header + hsize); |
rd_parea.frames = SIZE2FRAMES(dsize); |
rd_parea.cacheable = true; |
99,8 → 96,8 |
sysinfo_set_item_val("rd", NULL, true); |
sysinfo_set_item_val("rd.header_size", NULL, hsize); |
sysinfo_set_item_val("rd.size", NULL, dsize); |
sysinfo_set_item_val("rd.address.physical", NULL, (unative_t) |
KA2PA((void *) header + hsize)); |
sysinfo_set_item_val("rd.address.physical", NULL, |
(unative_t) KA2PA((void *) header + hsize)); |
return RE_OK; |
} |
/branches/network/kernel/generic/src/lib/elf.c |
---|
57,7 → 57,7 |
}; |
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, |
as_t *as); |
as_t *as, int flags); |
static int section_header(elf_section_header_t *entry, elf_header_t *elf, |
as_t *as); |
static int load_segment(elf_segment_header_t *entry, elf_header_t *elf, |
67,9 → 67,10 |
* |
* @param header Pointer to ELF header in memory |
* @param as Created and properly mapped address space |
* @param flags A combination of ELD_F_* |
* @return EE_OK on success |
*/ |
int elf_load(elf_header_t *header, as_t * as) |
unsigned int elf_load(elf_header_t *header, as_t * as, int flags) |
{ |
int i, rc; |
100,6 → 101,10 |
if (header->e_type != ET_EXEC) |
return EE_UNSUPPORTED; |
/* Check if the ELF image starts on a page boundary */ |
if (ALIGN_UP((uintptr_t)header, PAGE_SIZE) != (uintptr_t)header) |
return EE_UNSUPPORTED; |
/* Walk through all segment headers and process them. */ |
for (i = 0; i < header->e_phnum; i++) { |
elf_segment_header_t *seghdr; |
106,7 → 111,7 |
seghdr = &((elf_segment_header_t *)(((uint8_t *) header) + |
header->e_phoff))[i]; |
rc = segment_header(seghdr, header, as); |
rc = segment_header(seghdr, header, as, flags); |
if (rc != EE_OK) |
return rc; |
} |
131,7 → 136,7 |
* |
* @return NULL terminated description of error. |
*/ |
char *elf_error(int rc) |
char *elf_error(unsigned int rc) |
{ |
ASSERT(rc < sizeof(error_codes) / sizeof(char *)); |
147,8 → 152,10 |
* @return EE_OK on success, error code otherwise. |
*/ |
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, |
as_t *as) |
as_t *as, int flags) |
{ |
char *interp; |
switch (entry->p_type) { |
case PT_NULL: |
case PT_PHDR: |
158,6 → 165,16 |
break; |
case PT_DYNAMIC: |
case PT_INTERP: |
interp = (char *)elf + entry->p_offset; |
/* FIXME */ |
/*if (memcmp((uintptr_t)interp, (uintptr_t)ELF_INTERP_ZSTR, |
ELF_INTERP_ZLEN) != 0) { |
return EE_UNSUPPORTED; |
}*/ |
if ((flags & ELD_F_LOADER) == 0) { |
return EE_LOADER; |
} |
break; |
case PT_SHLIB: |
case PT_NOTE: |
case PT_LOPROC: |
182,6 → 199,8 |
as_area_t *a; |
int flags = 0; |
mem_backend_data_t backend_data; |
uintptr_t base; |
size_t mem_sz; |
backend_data.elf = elf; |
backend_data.segment = entry; |
202,12 → 221,13 |
flags |= AS_AREA_CACHEABLE; |
/* |
* Check if the virtual address starts on page boundary. |
* Align vaddr down, inserting a little "gap" at the beginning. |
* Adjust area size, so that its end remains in place. |
*/ |
if (ALIGN_UP(entry->p_vaddr, PAGE_SIZE) != entry->p_vaddr) |
return EE_UNSUPPORTED; |
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE); |
mem_sz = entry->p_memsz + (entry->p_vaddr - base); |
a = as_area_create(as, flags, entry->p_memsz, entry->p_vaddr, |
a = as_area_create(as, flags, mem_sz, base, |
AS_AREA_ATTR_NONE, &elf_backend, &backend_data); |
if (!a) |
return EE_MEMORY; |
/branches/network/kernel/generic/src/lib/func.c |
---|
73,7 → 73,7 |
} |
#endif |
if (CPU) |
printf("cpu%d: halted\n", CPU->id); |
printf("cpu%u: halted\n", CPU->id); |
else |
printf("cpu: halted\n"); |
cpu_halt(); |
139,9 → 139,9 |
*/ |
int strncmp(const char *src, const char *dst, size_t len) |
{ |
int i; |
unsigned int i; |
for (i = 0; *src && *dst && i < len; src++, dst++, i++) { |
for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) { |
if (*src < *dst) |
return -1; |
if (*src > *dst) |
168,7 → 168,7 |
*/ |
void strncpy(char *dest, const char *src, size_t len) |
{ |
int i; |
unsigned int i; |
for (i = 0; i < len; i++) { |
if (!(dest[i] = src[i])) |
return; |
/branches/network/kernel/generic/src/lib/sort.c |
---|
96,13 → 96,16 |
void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot) |
{ |
if (n > 4) { |
int i = 0, j = n - 1; |
unsigned int i = 0, j = n - 1; |
memcpy(pivot, data, e_size); |
while (1) { |
while ((cmp(data + i * e_size, pivot) < 0) && i < n) i++; |
while ((cmp(data + j * e_size, pivot) >=0) && j > 0) j--; |
while ((cmp(data + i * e_size, pivot) < 0) && (i < n)) |
i++; |
while ((cmp(data + j * e_size, pivot) >= 0) && (j > 0)) |
j--; |
if (i<j) { |
memcpy(tmp, data + i * e_size, e_size); |
memcpy(data + i * e_size, data + j * e_size, e_size); |
/branches/network/kernel/generic/src/sysinfo/sysinfo.c |
---|
244,7 → 244,7 |
break; |
} |
printf("%s %s val:%d(%x) sub:%s\n", root->name, vtype, val, |
printf("%s %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val, |
val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ? |
"NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ? |
"TAB" : "FUN")); |
281,10 → 281,15 |
return ret; |
} |
#define SYSINFO_MAX_LEN 1024 |
unative_t sys_sysinfo_valid(unative_t ptr, unative_t len) |
{ |
char *str; |
sysinfo_rettype_t ret = {0, 0}; |
if (len > SYSINFO_MAX_LEN) |
return ret.valid; |
str = malloc(len + 1, 0); |
ASSERT(str); |
299,6 → 304,9 |
{ |
char *str; |
sysinfo_rettype_t ret = {0, 0}; |
if (len > SYSINFO_MAX_LEN) |
return ret.val; |
str = malloc(len + 1, 0); |
ASSERT(str); |
/branches/network/kernel/generic/src/synch/smc.c |
---|
0,0 → 1,60 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sync |
* @{ |
*/ |
/** |
* @file |
* @brief Self-modifying code barriers. |
*/ |
#include <arch.h> |
#include <macros.h> |
#include <errno.h> |
#include <arch/barrier.h> |
#include <synch/smc.h> |
unative_t sys_smc_coherence(uintptr_t va, size_t size) |
{ |
if (overlaps(va, size, NULL, PAGE_SIZE)) |
return EINVAL; |
if (!KERNEL_ADDRESS_SPACE_SHADOWED) { |
if (overlaps(va, size, KERNEL_ADDRESS_SPACE_START, |
KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START)) |
return EINVAL; |
} |
smc_coherence_block((void *) va, size); |
return 0; |
} |
/** @} |
*/ |
/branches/network/kernel/generic/src/synch/rwlock.c |
---|
82,7 → 82,7 |
*/ |
void rwlock_initialize(rwlock_t *rwl) { |
spinlock_initialize(&rwl->lock, "rwlock_t"); |
mutex_initialize(&rwl->exclusive); |
mutex_initialize(&rwl->exclusive, MUTEX_PASSIVE); |
rwl->readers_in = 0; |
} |
/branches/network/kernel/generic/src/synch/mutex.c |
---|
38,21 → 38,21 |
#include <synch/mutex.h> |
#include <synch/semaphore.h> |
#include <synch/synch.h> |
#include <debug.h> |
/** Initialize mutex |
/** Initialize mutex. |
* |
* Initialize mutex. |
* |
* @param mtx Mutex. |
* @param type Type of the mutex. |
*/ |
void mutex_initialize(mutex_t *mtx) |
void mutex_initialize(mutex_t *mtx, mutex_type_t type) |
{ |
mtx->type = type; |
semaphore_initialize(&mtx->sem, 1); |
} |
/** Acquire mutex |
/** Acquire mutex. |
* |
* Acquire mutex. |
* Timeout mode and non-blocking mode can be requested. |
* |
* @param mtx Mutex. |
66,13 → 66,25 |
*/ |
int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags) |
{ |
return _semaphore_down_timeout(&mtx->sem, usec, flags); |
int rc; |
if (mtx->type == MUTEX_PASSIVE) { |
rc = _semaphore_down_timeout(&mtx->sem, usec, flags); |
} else { |
ASSERT(mtx->type == MUTEX_ACTIVE); |
ASSERT(usec == SYNCH_NO_TIMEOUT); |
ASSERT(!(flags & SYNCH_FLAGS_INTERRUPTIBLE)); |
do { |
rc = semaphore_trydown(&mtx->sem); |
} while (SYNCH_FAILED(rc) && |
!(flags & SYNCH_FLAGS_NON_BLOCKING)); |
} |
/** Release mutex |
return rc; |
} |
/** Release mutex. |
* |
* Release mutex. |
* |
* @param mtx Mutex. |
*/ |
void mutex_unlock(mutex_t *mtx) |
/branches/network/kernel/generic/src/synch/condvar.c |
---|
50,9 → 50,8 |
waitq_initialize(&cv->wq); |
} |
/** |
* Signal the condition has become true |
* to the first waiting thread by waking it up. |
/** Signal the condition has become true to the first waiting thread by waking |
* it up. |
* |
* @param cv Condition variable. |
*/ |
61,9 → 60,8 |
waitq_wakeup(&cv->wq, WAKEUP_FIRST); |
} |
/** |
* Signal the condition has become true |
* to all waiting threads by waking them up. |
/** Signal the condition has become true to all waiting threads by waking |
* them up. |
* |
* @param cv Condition variable. |
*/ |
79,10 → 77,10 |
* @param usec Timeout value in microseconds. |
* @param flags Select mode of operation. |
* |
* For exact description of meaning of possible combinations |
* of usec and flags, see comment for waitq_sleep_timeout(). |
* Note that when SYNCH_FLAGS_NON_BLOCKING is specified here, |
* ESYNCH_WOULD_BLOCK is always returned. |
* For exact description of meaning of possible combinations of usec and flags, |
* see comment for waitq_sleep_timeout(). Note that when |
* SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always |
* returned. |
* |
* @return See comment for waitq_sleep_timeout(). |
*/ |
/branches/network/kernel/generic/src/synch/spinlock.c |
---|
106,9 → 106,8 |
continue; |
#endif |
if (i++ > DEADLOCK_THRESHOLD) { |
printf("cpu%d: looping on spinlock %.*p:%s, " |
"caller=%.*p", CPU->id, sizeof(uintptr_t) * 2, sl, |
sl->name, sizeof(uintptr_t) * 2, CALLER); |
printf("cpu%u: looping on spinlock %" PRIp ":%s, caller=%" PRIp, |
CPU->id, sl, sl->name, CALLER); |
symbol = get_symtab_entry(CALLER); |
if (symbol) |
printf("(%s)", symbol); |
119,7 → 118,7 |
} |
if (deadlock_reported) |
printf("cpu%d: not deadlocked\n", CPU->id); |
printf("cpu%u: not deadlocked\n", CPU->id); |
/* |
* Prevent critical section code from bleeding out this way up. |
/branches/network/kernel/generic/src/synch/waitq.c |
---|
54,7 → 54,7 |
#include <context.h> |
#include <adt/list.h> |
static void waitq_timeouted_sleep(void *data); |
static void waitq_sleep_timed_out(void *data); |
/** Initialize wait queue |
* |
71,7 → 71,7 |
/** Handle timeout during waitq_sleep_timeout() call |
* |
* This routine is called when waitq_sleep_timeout() timeouts. |
* This routine is called when waitq_sleep_timeout() times out. |
* Interrupts are disabled. |
* |
* It is supposed to try to remove 'its' thread from the wait queue; |
81,7 → 81,7 |
* |
* @param data Pointer to the thread that called waitq_sleep_timeout(). |
*/ |
void waitq_timeouted_sleep(void *data) |
void waitq_sleep_timed_out(void *data) |
{ |
thread_t *t = (thread_t *) data; |
waitq_t *wq; |
200,11 → 200,12 |
* If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is set in flags, the |
* call will immediately return, reporting either success or failure. |
* |
* @return One of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, ESYNCH_INTERRUPTED, |
* ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED. |
* @return Returns one of ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, |
* ESYNCH_INTERRUPTED, ESYNCH_OK_ATOMIC and |
* ESYNCH_OK_BLOCKED. |
* |
* @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time of the |
* call there was no pending wakeup. |
* @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time of |
* the call there was no pending wakeup. |
* |
* @li ESYNCH_TIMEOUT means that the sleep timed out. |
* |
291,8 → 292,8 |
/** Internal implementation of waitq_sleep_timeout(). |
* |
* This function implements logic of sleeping in a wait queue. |
* This call must be preceeded by a call to waitq_sleep_prepare() |
* and followed by a call to waitq_slee_finish(). |
* This call must be preceded by a call to waitq_sleep_prepare() |
* and followed by a call to waitq_sleep_finish(). |
* |
* @param wq See waitq_sleep_timeout(). |
* @param usec See waitq_sleep_timeout(). |
355,7 → 356,7 |
} |
THREAD->timeout_pending = true; |
timeout_register(&THREAD->sleep_timeout, (uint64_t) usec, |
waitq_timeouted_sleep, THREAD); |
waitq_sleep_timed_out, THREAD); |
} |
list_append(&THREAD->wq_link, &wq->head); |
405,10 → 406,10 |
* assumes wq->lock is already locked and interrupts are already disabled. |
* |
* @param wq Pointer to wait queue. |
* @param mode If mode is WAKEUP_FIRST, then the longest waiting thread, |
* if any, is woken up. If mode is WAKEUP_ALL, then all |
* waiting threads, if any, are woken up. If there are no |
* waiting threads to be woken up, the missed wakeup is |
* @param mode If mode is WAKEUP_FIRST, then the longest waiting |
* thread, if any, is woken up. If mode is WAKEUP_ALL, then |
* all waiting threads, if any, are woken up. If there are |
* no waiting threads to be woken up, the missed wakeup is |
* recorded in the wait queue. |
*/ |
void _waitq_wakeup_unsafe(waitq_t *wq, wakeup_mode_t mode) |
431,7 → 432,7 |
* Lock the thread prior to removing it from the wq. |
* This is not necessary because of mutual exclusion |
* (the link belongs to the wait queue), but because |
* of synchronization with waitq_timeouted_sleep() |
* of synchronization with waitq_sleep_timed_out() |
* and thread_interrupt_sleep(). |
* |
* In order for these two functions to work, the following |
/branches/network/kernel/generic/src/synch/futex.c |
---|
324,7 → 324,7 |
for (cur = TASK->futexes.leaf_head.next; |
cur != &TASK->futexes.leaf_head; cur = cur->next) { |
btree_node_t *node; |
int i; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
/branches/network/kernel/generic/src/syscall/syscall.c |
---|
38,6 → 38,7 |
#include <syscall/syscall.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/program.h> |
#include <mm/as.h> |
#include <print.h> |
#include <putchar.h> |
46,19 → 47,19 |
#include <debug.h> |
#include <ipc/sysipc.h> |
#include <synch/futex.h> |
#include <synch/smc.h> |
#include <ddi/ddi.h> |
#include <security/cap.h> |
#include <syscall/copy.h> |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <console/klog.h> |
/** Print using kernel facility |
* |
* Some simulators can print only through kernel. Userspace can use |
* this syscall to facilitate it. |
* Print to kernel log. |
* |
*/ |
static unative_t sys_io(int fd, const void * buf, size_t count) |
static unative_t sys_klog(int fd, const void * buf, size_t count) |
{ |
size_t i; |
char *data; |
67,6 → 68,7 |
if (count > PAGE_SIZE) |
return ELIMIT; |
if (count > 0) { |
data = (char *) malloc(count, 0); |
if (!data) |
return ENOMEM; |
80,6 → 82,8 |
for (i = 0; i < count; i++) |
putchar(data[i]); |
free(data); |
} else |
klog_update(); |
return count; |
} |
100,8 → 104,7 |
if (id < SYSCALL_END) |
rc = syscall_table[id](a1, a2, a3, a4, a5, a6); |
else { |
klog_printf("TASK %llu: Unknown syscall id %llx", TASK->taskid, |
id); |
printf("Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id); |
task_kill(TASK->taskid); |
thread_exit(); |
} |
113,7 → 116,7 |
} |
syshandler_t syscall_table[SYSCALL_END] = { |
(syshandler_t) sys_io, |
(syshandler_t) sys_klog, |
(syshandler_t) sys_tls_set, |
/* Thread and task related syscalls. */ |
120,15 → 123,19 |
(syshandler_t) sys_thread_create, |
(syshandler_t) sys_thread_exit, |
(syshandler_t) sys_thread_get_id, |
(syshandler_t) sys_task_get_id, |
(syshandler_t) sys_program_spawn_loader, |
/* Synchronization related syscalls. */ |
(syshandler_t) sys_futex_sleep_timeout, |
(syshandler_t) sys_futex_wakeup, |
(syshandler_t) sys_smc_coherence, |
/* Address space related syscalls. */ |
(syshandler_t) sys_as_area_create, |
(syshandler_t) sys_as_area_resize, |
(syshandler_t) sys_as_area_change_flags, |
(syshandler_t) sys_as_area_destroy, |
/* IPC related syscalls. */ |
/branches/network/kernel/generic/src/console/klog.c |
---|
File deleted |
/branches/network/kernel/generic/src/console/kconsole.c |
---|
257,7 → 257,8 |
if (c == '\n') { |
putchar(c); |
break; |
} if (c == '\b') { /* Backspace */ |
} |
if (c == '\b') { /* Backspace */ |
if (position == 0) |
continue; |
for (i = position; i < curlen; i++) |
543,7 → 544,8 |
buf = (char *) cmd->argv[i].buffer; |
strncpy(buf, (const char *) &cmdline[start], |
min((end - start) + 2, cmd->argv[i].len)); |
buf[min((end - start) + 1, cmd->argv[i].len - 1)] = '\0'; |
buf[min((end - start) + 1, cmd->argv[i].len - 1)] = |
'\0'; |
break; |
case ARG_TYPE_INT: |
if (parse_int_arg(cmdline + start, end - start + 1, |
560,8 → 562,8 |
'\0'; |
cmd->argv[i].intval = (unative_t) buf; |
cmd->argv[i].vartype = ARG_TYPE_STRING; |
} else if (!parse_int_arg(cmdline + start, end - start + 1, |
&cmd->argv[i].intval)) { |
} else if (!parse_int_arg(cmdline + start, |
end - start + 1, &cmd->argv[i].intval)) { |
cmd->argv[i].vartype = ARG_TYPE_INT; |
} else { |
printf("Unrecognized variable argument.\n"); |
/branches/network/kernel/generic/src/console/console.c |
---|
35,30 → 35,56 |
#include <console/console.h> |
#include <console/chardev.h> |
#include <sysinfo/sysinfo.h> |
#include <synch/waitq.h> |
#include <synch/spinlock.h> |
#include <arch/types.h> |
#include <ddi/device.h> |
#include <ddi/irq.h> |
#include <ddi/ddi.h> |
#include <ipc/irq.h> |
#include <arch.h> |
#include <func.h> |
#include <print.h> |
#include <atomic.h> |
#define BUFLEN 2048 |
static char debug_buffer[BUFLEN]; |
static size_t offset = 0; |
/** Initialize stdout to something that does not print, but does not fail |
* |
* Save data in some buffer so that it could be retrieved in the debugger |
#define KLOG_SIZE PAGE_SIZE |
#define KLOG_LATENCY 8 |
/**< Kernel log cyclic buffer */ |
static char klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE))); |
/**< Kernel log initialized */ |
static bool klog_inited = false; |
/**< First kernel log characters */ |
static index_t klog_start = 0; |
/**< Number of valid kernel log characters */ |
static size_t klog_len = 0; |
/**< Number of stored (not printed) kernel log characters */ |
static size_t klog_stored = 0; |
/**< Number of stored kernel log characters for uspace */ |
static size_t klog_uspace = 0; |
/**< Kernel log spinlock */ |
SPINLOCK_INITIALIZE(klog_lock); |
/** Physical memory area used for klog buffer */ |
static parea_t klog_parea; |
/* |
* For now, we use 0 as INR. |
* However, it is therefore desirable to have architecture specific |
* definition of KLOG_VIRT_INR in the future. |
*/ |
static void null_putchar(chardev_t *d, const char ch) |
{ |
if (offset >= BUFLEN) |
offset = 0; |
debug_buffer[offset++] = ch; |
} |
#define KLOG_VIRT_INR 0 |
static irq_t klog_irq; |
static chardev_operations_t null_stdout_ops = { |
.write = null_putchar |
.suspend = NULL, |
.resume = NULL, |
.write = NULL, |
.read = NULL |
}; |
chardev_t null_stdout = { |
66,10 → 92,58 |
.op = &null_stdout_ops |
}; |
/** Standard input character device. */ |
/** Allways refuse IRQ ownership. |
* |
* This is not a real IRQ, so we always decline. |
* |
* @return Always returns IRQ_DECLINE. |
*/ |
static irq_ownership_t klog_claim(void) |
{ |
return IRQ_DECLINE; |
} |
/** Standard input character device */ |
chardev_t *stdin = NULL; |
chardev_t *stdout = &null_stdout; |
/** Initialize kernel logging facility |
* |
* The shared area contains kernel cyclic buffer. Userspace application may |
* be notified on new data with indication of position and size |
* of the data within the circular buffer. |
*/ |
void klog_init(void) |
{ |
void *faddr = (void *) KA2PA(klog); |
ASSERT((uintptr_t) faddr % FRAME_SIZE == 0); |
ASSERT(KLOG_SIZE % FRAME_SIZE == 0); |
devno_t devno = device_assign_devno(); |
klog_parea.pbase = (uintptr_t) faddr; |
klog_parea.vbase = (uintptr_t) klog; |
klog_parea.frames = SIZE2FRAMES(KLOG_SIZE); |
klog_parea.cacheable = true; |
ddi_parea_register(&klog_parea); |
sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr); |
sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(KLOG_SIZE)); |
sysinfo_set_item_val("klog.devno", NULL, devno); |
sysinfo_set_item_val("klog.inr", NULL, KLOG_VIRT_INR); |
irq_initialize(&klog_irq); |
klog_irq.devno = devno; |
klog_irq.inr = KLOG_VIRT_INR; |
klog_irq.claim = klog_claim; |
irq_register(&klog_irq); |
spinlock_lock(&klog_lock); |
klog_inited = true; |
spinlock_unlock(&klog_lock); |
} |
/** Get character from character device. Do not echo character. |
* |
* @param chardev Character device. |
90,7 → 164,7 |
return chardev->op->read(chardev); |
/* no other way of interacting with user, halt */ |
if (CPU) |
printf("cpu%d: ", CPU->id); |
printf("cpu%u: ", CPU->id); |
else |
printf("cpu: "); |
printf("halted - no kconsole\n"); |
159,11 → 233,61 |
return ch; |
} |
void klog_update(void) |
{ |
spinlock_lock(&klog_lock); |
if ((klog_inited) && (klog_irq.notif_cfg.notify) && (klog_uspace > 0)) { |
ipc_irq_send_msg_3(&klog_irq, klog_start, klog_len, klog_uspace); |
klog_uspace = 0; |
} |
spinlock_unlock(&klog_lock); |
} |
void putchar(char c) |
{ |
spinlock_lock(&klog_lock); |
if ((klog_stored > 0) && (stdout->op->write)) { |
/* Print charaters stored in kernel log */ |
index_t i; |
for (i = klog_len - klog_stored; i < klog_len; i++) |
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE]); |
klog_stored = 0; |
} |
/* Store character in the cyclic kernel log */ |
klog[(klog_start + klog_len) % KLOG_SIZE] = c; |
if (klog_len < KLOG_SIZE) |
klog_len++; |
else |
klog_start = (klog_start + 1) % KLOG_SIZE; |
if (stdout->op->write) |
stdout->op->write(stdout, c); |
else { |
/* The character is just in the kernel log */ |
if (klog_stored < klog_len) |
klog_stored++; |
} |
/* The character is stored for uspace */ |
if (klog_uspace < klog_len) |
klog_uspace++; |
/* Check notify uspace to update */ |
bool update; |
if ((klog_uspace > KLOG_LATENCY) || (c == '\n')) |
update = true; |
else |
update = false; |
spinlock_unlock(&klog_lock); |
if (update) |
klog_update(); |
} |
/** @} |
*/ |
/branches/network/kernel/generic/src/console/cmd.c |
---|
563,7 → 563,7 |
/* This doesn't have to be very accurate */ |
unative_t sec = uptime->seconds1; |
printf("Up %u days, %u hours, %u minutes, %u seconds\n", |
printf("Up %" PRIun " days, %" PRIun " hours, %" PRIun " minutes, %" PRIun " seconds\n", |
sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60); |
return 1; |
632,7 → 632,7 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling %s() (%.*p)\n", symbol, sizeof(uintptr_t) * 2, symaddr); |
printf("Calling %s() (%p)\n", symbol, symaddr); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
640,7 → 640,7 |
#else |
f = (unative_t (*)(void)) symaddr; |
#endif |
printf("Result: %#zx\n", f()); |
printf("Result: %#" PRIxn "\n", f()); |
} |
return 1; |
698,7 → 698,7 |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol); |
printf("Calling f(%#" PRIxn "): %p: %s\n", arg1, symaddr, symbol); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
706,7 → 706,7 |
#else |
f = (unative_t (*)(unative_t,...)) symaddr; |
#endif |
printf("Result: %#zx\n", f(arg1)); |
printf("Result: %#" PRIxn "\n", f(arg1)); |
} |
return 1; |
735,8 → 735,8 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling f(0x%zx,0x%zx): %.*p: %s\n", |
arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol); |
printf("Calling f(%#" PRIxn ", %#" PRIxn "): %p: %s\n", |
arg1, arg2, symaddr, symbol); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
744,7 → 744,7 |
#else |
f = (unative_t (*)(unative_t,unative_t,...)) symaddr; |
#endif |
printf("Result: %#zx\n", f(arg1, arg2)); |
printf("Result: %#" PRIxn "\n", f(arg1, arg2)); |
} |
return 1; |
774,8 → 774,8 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n", |
arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol); |
printf("Calling f(%#" PRIxn ",%#" PRIxn ", %#" PRIxn "): %p: %s\n", |
arg1, arg2, arg3, symaddr, symbol); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
783,7 → 783,7 |
#else |
f = (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr; |
#endif |
printf("Result: %#zx\n", f(arg1, arg2, arg3)); |
printf("Result: %#" PRIxn "\n", f(arg1, arg2, arg3)); |
} |
return 1; |
856,7 → 856,7 |
} else { |
if (pointer) |
addr = (uint32_t *)(*(unative_t *)addr); |
printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr); |
printf("Writing %#" PRIx64 " -> %p\n", arg1, addr); |
*addr = arg1; |
} |
1025,7 → 1025,7 |
char suffix; |
order(dt, &cycles, &suffix); |
printf("Time: %llu%c cycles\n", cycles, suffix); |
printf("Time: %" PRIu64 "%c cycles\n", cycles, suffix); |
if (ret == NULL) { |
printf("Test passed\n"); |
1053,7 → 1053,7 |
} |
for (i = 0; i < cnt; i++) { |
printf("%s (%d/%d) ... ", test->name, i + 1, cnt); |
printf("%s (%u/%u) ... ", test->name, i + 1, cnt); |
/* Update and read thread accounting |
for benchmarking */ |
1081,7 → 1081,7 |
data[i] = dt; |
order(dt, &cycles, &suffix); |
printf("OK (%llu%c cycles)\n", cycles, suffix); |
printf("OK (%" PRIu64 "%c cycles)\n", cycles, suffix); |
} |
if (ret) { |
1094,7 → 1094,7 |
} |
order(sum / (uint64_t) cnt, &cycles, &suffix); |
printf("Average\t\t%llu%c\n", cycles, suffix); |
printf("Average\t\t%" PRIu64 "%c\n", cycles, suffix); |
} |
free(data); |
/branches/network/kernel/generic/src/cpu/cpu.c |
---|
67,7 → 67,7 |
panic("malloc/cpus"); |
/* initialize everything */ |
memsetb((uintptr_t) cpus, sizeof(cpu_t) * config.cpu_count, 0); |
memsetb(cpus, sizeof(cpu_t) * config.cpu_count, 0); |
for (i = 0; i < config.cpu_count; i++) { |
cpus[i].stack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | FRAME_ATOMIC); |
104,7 → 104,7 |
if (cpus[i].active) |
cpu_print_report(&cpus[i]); |
else |
printf("cpu%d: not active\n", i); |
printf("cpu%u: not active\n", i); |
} |
} |
/branches/network/kernel/generic/src/adt/hash_table.c |
---|
63,7 → 63,7 |
if (!h->entry) { |
panic("cannot allocate memory for hash table\n"); |
} |
memsetb((uintptr_t) h->entry, m * sizeof(link_t), 0); |
memsetb(h->entry, m * sizeof(link_t), 0); |
for (i = 0; i < m; i++) |
list_initialize(&h->entry[i]); |
/branches/network/kernel/generic/src/adt/btree.c |
---|
124,7 → 124,7 |
lnode = leaf_node; |
if (!lnode) { |
if (btree_search(t, key, &lnode)) { |
panic("B-tree %p already contains key %d\n", t, key); |
panic("B-tree %p already contains key %" PRIu64 "\n", t, key); |
} |
} |
224,7 → 224,7 |
lnode = leaf_node; |
if (!lnode) { |
if (!btree_search(t, key, &lnode)) { |
panic("B-tree %p does not contain key %d\n", t, key); |
panic("B-tree %p does not contain key %" PRIu64 "\n", t, key); |
} |
} |
524,7 → 524,7 |
return; |
} |
} |
panic("node %p does not contain key %d\n", node, key); |
panic("node %p does not contain key %" PRIu64 "\n", node, key); |
} |
/** Remove key and its right subtree pointer from B-tree node. |
551,7 → 551,7 |
return; |
} |
} |
panic("node %p does not contain key %d\n", node, key); |
panic("node %p does not contain key %" PRIu64 "\n", node, key); |
} |
/** Split full B-tree node and insert new key-value-right-subtree triplet. |
970,7 → 970,7 |
printf("("); |
for (i = 0; i < node->keys; i++) { |
printf("%llu%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : ""); |
if (node->depth && node->subtree[i]) { |
list_append(&node->subtree[i]->bfs_link, &head); |
} |
992,7 → 992,7 |
printf("("); |
for (i = 0; i < node->keys; i++) |
printf("%llu%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf(")"); |
} |
printf("\n"); |
/branches/network/kernel/generic/src/debug/symtab.c |
---|
36,9 → 36,11 |
*/ |
#include <symtab.h> |
#include <arch/byteorder.h> |
#include <byteorder.h> |
#include <func.h> |
#include <print.h> |
#include <arch/types.h> |
#include <typedefs.h> |
/** Return entry that seems most likely to correspond to argument. |
* |
70,7 → 72,7 |
*/ |
static char * symtab_search_one(const char *name, int *startpos) |
{ |
int namelen = strlen(name); |
unsigned int namelen = strlen(name); |
char *curname; |
int i,j; |
int colonoffset = -1; |
139,7 → 141,7 |
while (symtab_search_one(name, &i)) { |
addr = uint64_t_le2host(symbol_table[i].address_le); |
realname = symbol_table[i].symbol_name; |
printf("%.*p: %s\n", sizeof(uintptr_t) * 2, addr, realname); |
printf("%p: %s\n", addr, realname); |
i++; |
} |
} |
174,7 → 176,8 |
if (!found) |
strncpy(output, foundtxt, strlen(foundtxt)+1); |
else { |
for (i=0; output[i] && foundtxt[i] && output[i]==foundtxt[i]; i++) |
for (i = 0; output[i] && foundtxt[i] && |
output[i] == foundtxt[i]; i++) |
; |
output[i] = '\0'; |
} |
/branches/network/kernel/generic/src/printf/vprintf.c |
---|
37,6 → 37,8 |
#include <putchar.h> |
#include <synch/spinlock.h> |
#include <arch/asm.h> |
#include <arch/types.h> |
#include <typedefs.h> |
SPINLOCK_INITIALIZE(printf_lock); /**< vprintf spinlock */ |
/branches/network/kernel/generic/src/printf/printf_core.c |
---|
75,7 → 75,6 |
PrintfQualifierInt, |
PrintfQualifierLong, |
PrintfQualifierLongLong, |
PrintfQualifierNative, |
PrintfQualifierPointer |
} qualifier_t; |
177,8 → 176,8 |
* |
* @return Number of characters printed, negative value on failure. |
*/ |
static int print_string(char *s, int width, int precision, uint64_t flags, |
struct printf_spec *ps) |
static int print_string(char *s, int width, unsigned int precision, |
uint64_t flags, struct printf_spec *ps) |
{ |
int counter = 0; |
size_t size; |
432,7 → 431,6 |
* - "" Signed or unsigned int (default value).@n |
* - "l" Signed or unsigned long int.@n |
* - "ll" Signed or unsigned long long int.@n |
* - "z" unative_t (non-standard extension).@n |
* |
* |
* CONVERSION:@n |
585,9 → 583,6 |
qualifier = PrintfQualifierLongLong; |
} |
break; |
case 'z': /* unative_t */ |
qualifier = PrintfQualifierNative; |
break; |
default: |
/* default type */ |
qualifier = PrintfQualifierInt; |
686,18 → 681,12 |
break; |
case PrintfQualifierLongLong: |
size = sizeof(unsigned long long); |
number = (uint64_t)va_arg(ap, |
unsigned long long); |
number = (uint64_t) va_arg(ap, unsigned long long); |
break; |
case PrintfQualifierPointer: |
size = sizeof(void *); |
number = (uint64_t)(unsigned long)va_arg(ap, |
void *); |
number = (uint64_t) (unsigned long) va_arg(ap, void *); |
break; |
case PrintfQualifierNative: |
size = sizeof(unative_t); |
number = (uint64_t)va_arg(ap, unative_t); |
break; |
default: /* Unknown qualifier */ |
counter = -counter; |
goto out; |
744,7 → 733,6 |
} |
out: |
return counter; |
} |
/branches/network/kernel/generic/src/interrupt/interrupt.c |
---|
103,18 → 103,21 |
/** kconsole cmd - print all exceptions */ |
static int exc_print_cmd(cmd_arg_t *argv) |
{ |
#if (IVT_ITEMS > 0) |
unsigned int i; |
char *symbol; |
spinlock_lock(&exctbl_lock); |
if (sizeof(void *) == 4) { |
#ifdef __32_BITS__ |
printf("Exc Description Handler Symbol\n"); |
printf("--- -------------------- ---------- --------\n"); |
} else { |
#endif |
#ifdef __64_BITS__ |
printf("Exc Description Handler Symbol\n"); |
printf("--- -------------------- ------------------ --------\n"); |
} |
#endif |
for (i = 0; i < IVT_ITEMS; i++) { |
symbol = get_symtab_entry((unative_t) exc_table[i].f); |
121,12 → 124,15 |
if (!symbol) |
symbol = "not found"; |
if (sizeof(void *) == 4) |
printf("%-3u %-20s %#10zx %s\n", i + IVT_FIRST, exc_table[i].name, |
#ifdef __32_BITS__ |
printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name, |
exc_table[i].f, symbol); |
else |
printf("%-3u %-20s %#18zx %s\n", i + IVT_FIRST, exc_table[i].name, |
#endif |
#ifdef __64_BITS__ |
printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name, |
exc_table[i].f, symbol); |
#endif |
if (((i + 1) % 20) == 0) { |
printf(" -- Press any key to continue -- "); |
138,6 → 144,7 |
} |
spinlock_unlock(&exctbl_lock); |
#endif |
return 1; |
} |
/branches/network/kernel/generic/src/time/timeout.c |
---|
95,13 → 95,13 |
* time microseconds (or slightly more). |
* |
* @param t Timeout structure. |
* @param time Number of usec in the future to execute |
* the handler. |
* @param time Number of usec in the future to execute the handler. |
* @param f Timeout handler function. |
* @param arg Timeout handler argument. |
* |
*/ |
void timeout_register(timeout_t *t, uint64_t time, timeout_handler_t f, void *arg) |
void |
timeout_register(timeout_t *t, uint64_t time, timeout_handler_t f, void *arg) |
{ |
timeout_t *hlp = NULL; |
link_t *l, *m; |
167,7 → 167,7 |
* |
* @param t Timeout to unregister. |
* |
* @return true on success, false on failure. |
* @return True on success, false on failure. |
*/ |
bool timeout_unregister(timeout_t *t) |
{ |
/branches/network/kernel/generic/src/time/clock.c |
---|
137,7 → 137,7 |
timeout_handler_t f; |
void *arg; |
count_t missed_clock_ticks = CPU->missed_clock_ticks; |
int i; |
unsigned int i; |
/* |
* To avoid lock ordering problems, |
/branches/network/kernel/generic/include/ipc/ipc.h |
---|
205,6 → 205,8 |
#define IPC_MAX_PHONES 16 |
#include <synch/spinlock.h> |
#include <synch/mutex.h> |
#include <synch/waitq.h> |
struct answerbox; |
225,7 → 227,7 |
/** Structure identifying phone (in TASK structure) */ |
typedef struct { |
SPINLOCK_DECLARE(lock); |
mutex_t lock; |
link_t link; |
struct answerbox *callee; |
ipc_phone_state_t state; |
258,6 → 260,12 |
typedef struct { |
unative_t args[IPC_CALL_LEN]; |
phone_t *phone; |
/* |
* The forward operation can masquerade the caller phone. For those |
* cases, we must keep it aside so that the answer is processed |
* correctly. |
*/ |
phone_t *caller_phone; |
} ipc_data_t; |
typedef struct { |
282,23 → 290,22 |
} call_t; |
extern void ipc_init(void); |
extern call_t * ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags); |
extern void ipc_answer(answerbox_t *box, call_t *request); |
extern int ipc_call(phone_t *phone, call_t *call); |
extern void ipc_call_sync(phone_t *phone, call_t *request); |
extern void ipc_phone_init(phone_t *phone); |
extern void ipc_phone_connect(phone_t *phone, answerbox_t *box); |
extern void ipc_call_free(call_t *call); |
extern call_t * ipc_call_alloc(int flags); |
extern void ipc_answerbox_init(answerbox_t *box); |
extern void ipc_call_static_init(call_t *call); |
extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int); |
extern void ipc_answer(answerbox_t *, call_t *); |
extern int ipc_call(phone_t *, call_t *); |
extern int ipc_call_sync(phone_t *, call_t *); |
extern void ipc_phone_init(phone_t *); |
extern void ipc_phone_connect(phone_t *, answerbox_t *); |
extern void ipc_call_free(call_t *); |
extern call_t * ipc_call_alloc(int); |
extern void ipc_answerbox_init(answerbox_t *, struct task *); |
extern void ipc_call_static_init(call_t *); |
extern void task_print_list(void); |
extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, |
int mode); |
extern int ipc_forward(call_t *, phone_t *, answerbox_t *, int); |
extern void ipc_cleanup(void); |
extern int ipc_phone_hangup(phone_t *phone); |
extern void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err); |
extern void ipc_print_task(task_id_t taskid); |
extern int ipc_phone_hangup(phone_t *); |
extern void ipc_backsend_err(phone_t *, call_t *, unative_t); |
extern void ipc_print_task(task_id_t); |
extern answerbox_t *ipc_phone_0; |
/branches/network/kernel/generic/include/errno.h |
---|
56,6 → 56,7 |
#define EINVAL -13 /* Invalid value */ |
#define EBUSY -14 /* Resource is busy */ |
#define EOVERFLOW -15 /* The result does not fit its size. */ |
#define EINTR -16 /* Operation was interrupted. */ |
#endif |
/branches/network/kernel/generic/include/lib/objc_ext.h |
---|
File deleted |
/branches/network/kernel/generic/include/lib/objc.h |
---|
File deleted |
/branches/network/kernel/generic/include/lib/elf.h |
---|
114,7 → 114,8 |
#define EE_MEMORY 2 /* Cannot allocate address space */ |
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */ |
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */ |
#define EE_IRRECOVERABLE 5 |
#define EE_LOADER 5 /* The image is actually a program loader */ |
#define EE_IRRECOVERABLE 6 |
/** |
* ELF section types |
336,8 → 337,12 |
typedef struct elf64_symbol elf_symbol_t; |
#endif |
extern char *elf_error(int rc); |
extern char *elf_error(unsigned int rc); |
/* Interpreter string used to recognize the program loader */ |
#define ELF_INTERP_ZSTR "kernel" |
#define ELF_INTERP_ZLEN sizeof(ELF_INTERP_ZSTR) |
#endif |
/** @} |
/branches/network/kernel/generic/include/lib/rd.h |
---|
66,16 → 66,18 |
#define RE_UNSUPPORTED 2 /* Non-supported image (e.g. wrong version) */ |
/** RAM disk header */ |
typedef struct { |
struct rd_header { |
uint8_t magic[RD_MAGIC_SIZE]; |
uint8_t version; |
uint8_t data_type; |
uint32_t header_size; |
uint64_t data_size; |
} rd_header; |
} __attribute__ ((packed)); |
extern int init_rd(rd_header * addr, size_t size); |
typedef struct rd_header rd_header_t; |
extern int init_rd(rd_header_t *addr, size_t size); |
#endif |
/** @} |
/branches/network/kernel/generic/include/mm/as.h |
---|
53,10 → 53,6 |
#include <adt/btree.h> |
#include <lib/elf.h> |
#ifdef __OBJC__ |
#include <lib/objc.h> |
#endif |
/** |
* Defined to be true if user address space and kernel address space shadow each |
* other. |
84,47 → 80,6 |
/** The page fault was caused by memcpy_from_uspace() or memcpy_to_uspace(). */ |
#define AS_PF_DEFER 2 |
#ifdef __OBJC__ |
@interface as_t : base_t { |
@public |
/** Protected by asidlock. */ |
link_t inactive_as_with_asid_link; |
/** |
* Number of processors on wich is this address space active. |
* Protected by asidlock. |
*/ |
count_t cpu_refcount; |
/** |
* Address space identifier. |
* Constant on architectures that do not support ASIDs. |
* Protected by asidlock. |
*/ |
asid_t asid; |
/** Number of references (i.e tasks that reference this as). */ |
atomic_t refcount; |
mutex_t lock; |
/** B+tree of address space areas. */ |
btree_t as_area_btree; |
/** Non-generic content. */ |
as_genarch_t genarch; |
/** Architecture specific content. */ |
as_arch_t arch; |
} |
+ (pte_t *) page_table_create: (int) flags; |
+ (void) page_table_destroy: (pte_t *) page_table; |
- (void) page_table_lock: (bool) _lock; |
- (void) page_table_unlock: (bool) unlock; |
@end |
#else |
/** Address space structure. |
* |
* as_t contains the list of as_areas of userspace accessible |
168,7 → 123,6 |
void (* page_table_lock)(as_t *as, bool lock); |
void (* page_table_unlock)(as_t *as, bool unlock); |
} as_operations_t; |
#endif |
/** |
* This structure contains information associated with the shared address space |
249,10 → 203,7 |
extern as_t *AS_KERNEL; |
#ifndef __OBJC__ |
extern as_operations_t *as_operations; |
#endif |
extern link_t inactive_as_with_asid_head; |
extern void as_init(void); |
269,6 → 220,7 |
extern int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags); |
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask); |
extern int as_area_change_flags(as_t *as, int flags, uintptr_t address); |
extern int as_area_get_flags(as_area_t *area); |
extern bool as_area_check_access(as_area_t *area, pf_access_t access); |
299,11 → 251,19 |
extern mem_backend_t elf_backend; |
extern mem_backend_t phys_backend; |
extern int elf_load(elf_header_t *header, as_t *as); |
/** |
* This flags is passed when running the loader, otherwise elf_load() |
* would return with a EE_LOADER error code. |
*/ |
#define ELD_F_NONE 0 |
#define ELD_F_LOADER 1 |
extern unsigned int elf_load(elf_header_t *header, as_t *as, int flags); |
/* Address space area related syscalls. */ |
extern unative_t sys_as_area_create(uintptr_t address, size_t size, int flags); |
extern unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags); |
extern unative_t sys_as_area_change_flags(uintptr_t address, int flags); |
extern unative_t sys_as_area_destroy(uintptr_t address); |
/* Introspection functions. */ |
/branches/network/kernel/generic/include/mm/page.h |
---|
39,11 → 39,6 |
#include <mm/as.h> |
#include <memstr.h> |
/** |
* Macro for computing page color. |
*/ |
#define PAGE_COLOR(va) (((va) >> PAGE_WIDTH) & ((1 << PAGE_COLOR_BITS) - 1)) |
/** Operations to manipulate page mappings. */ |
typedef struct { |
void (* mapping_insert)(as_t *as, uintptr_t page, uintptr_t frame, |
/branches/network/kernel/generic/include/mm/frame.h |
---|
57,9 → 57,6 |
/** Maximum number of zones in system. */ |
#define ZONES_MAX 16 |
/** If possible, merge with neighbouring zones. */ |
#define ZONE_JOIN 0x1 |
/** Convert the frame address to kernel va. */ |
#define FRAME_KA 0x1 |
/** Do not panic and do not sleep on failure. */ |
66,6 → 63,8 |
#define FRAME_ATOMIC 0x2 |
/** Do not start reclaiming when no free memory. */ |
#define FRAME_NO_RECLAIM 0x4 |
/** Do not allocate above 4 GiB. */ |
#define FRAME_LOW_4_GiB 0x8 |
static inline uintptr_t PFN2ADDR(pfn_t frame) |
{ |
104,16 → 103,16 |
frame_alloc_generic(order, flags, NULL) |
extern void frame_init(void); |
extern void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone); |
extern void frame_free(uintptr_t frame); |
extern void frame_reference_add(pfn_t pfn); |
extern void *frame_alloc_generic(uint8_t, int, unsigned int *); |
extern void frame_free(uintptr_t); |
extern void frame_reference_add(pfn_t); |
extern int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags); |
extern void *frame_get_parent(pfn_t frame, unsigned int hint); |
extern void frame_set_parent(pfn_t frame, void *data, unsigned int hint); |
extern void frame_mark_unavailable(pfn_t start, count_t count); |
extern uintptr_t zone_conf_size(count_t count); |
extern void zone_merge(unsigned int z1, unsigned int z2); |
extern int zone_create(pfn_t, count_t, pfn_t, int); |
extern void *frame_get_parent(pfn_t, unsigned int); |
extern void frame_set_parent(pfn_t, void *, unsigned int); |
extern void frame_mark_unavailable(pfn_t, count_t); |
extern uintptr_t zone_conf_size(count_t); |
extern void zone_merge(unsigned int, unsigned int); |
extern void zone_merge_all(void); |
extern uint64_t zone_total_size(void); |
121,7 → 120,7 |
* Console functions |
*/ |
extern void zone_print_list(void); |
extern void zone_print_one(unsigned int znum); |
extern void zone_print_one(unsigned int); |
#endif |
/branches/network/kernel/generic/include/mm/buddy.h |
---|
66,7 → 66,6 |
void (*mark_available)(struct buddy_system *, link_t *); |
/** Find parent of block that has given order */ |
link_t *(* find_block)(struct buddy_system *, link_t *, uint8_t); |
void (* print_id)(struct buddy_system *, link_t *); |
} buddy_system_operations_t; |
typedef struct buddy_system { |
78,14 → 77,13 |
void *data; |
} buddy_system_t; |
extern void buddy_system_create(buddy_system_t *b, uint8_t max_order, |
buddy_system_operations_t *op, void *data); |
extern link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i); |
extern bool buddy_system_can_alloc(buddy_system_t *b, uint8_t order); |
extern void buddy_system_free(buddy_system_t *b, link_t *block); |
extern void buddy_system_structure_print(buddy_system_t *b, size_t elem_size); |
extern size_t buddy_conf_size(int max_order); |
extern link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block); |
extern void buddy_system_create(buddy_system_t *, uint8_t, |
buddy_system_operations_t *, void *); |
extern link_t *buddy_system_alloc(buddy_system_t *, uint8_t); |
extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t); |
extern void buddy_system_free(buddy_system_t *, link_t *); |
extern size_t buddy_conf_size(int); |
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *); |
#endif |
/branches/network/kernel/generic/include/mm/slab.h |
---|
53,7 → 53,8 |
#define SLAB_INSIDE_SIZE (PAGE_SIZE >> 3) |
/** Maximum wasted space we allow for cache */ |
#define SLAB_MAX_BADNESS(cache) ((PAGE_SIZE << (cache)->order) >> 2) |
#define SLAB_MAX_BADNESS(cache) \ |
(((unsigned int) PAGE_SIZE << (cache)->order) >> 2) |
/* slab_reclaim constants */ |
100,7 → 101,7 |
/* Computed values */ |
uint8_t order; /**< Order of frames to be allocated */ |
int objects; /**< Number of objects that fit in */ |
unsigned int objects; /**< Number of objects that fit in */ |
/* Statistics */ |
atomic_t allocated_slabs; |
121,14 → 122,13 |
slab_mag_cache_t *mag_cache; |
} slab_cache_t; |
extern slab_cache_t * slab_cache_create(char *name, size_t size, size_t align, |
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj), |
int flags); |
extern void slab_cache_destroy(slab_cache_t *cache); |
extern slab_cache_t *slab_cache_create(char *, size_t, size_t, |
int (*)(void *, int), int (*)(void *), int); |
extern void slab_cache_destroy(slab_cache_t *); |
extern void * slab_alloc(slab_cache_t *cache, int flags); |
extern void slab_free(slab_cache_t *cache, void *obj); |
extern count_t slab_reclaim(int flags); |
extern void * slab_alloc(slab_cache_t *, int); |
extern void slab_free(slab_cache_t *, void *); |
extern count_t slab_reclaim(int); |
/* slab subsytem initialization */ |
extern void slab_cache_init(void); |
138,9 → 138,9 |
extern void slab_print_list(void); |
/* malloc support */ |
extern void * malloc(unsigned int size, int flags); |
extern void * realloc(void *ptr, unsigned int size, int flags); |
extern void free(void *ptr); |
extern void *malloc(unsigned int, int); |
extern void *realloc(void *, unsigned int, int); |
extern void free(void *); |
#endif |
/** @} |
/branches/network/kernel/generic/include/macros.h |
---|
40,8 → 40,8 |
#define isdigit(d) (((d) >= '0') && ((d) <= '9')) |
#define islower(c) (((c) >= 'a') && ((c) <= 'z')) |
#define isupper(c) (((c) >= 'A') && ((c) <= 'Z')) |
#define isalpha(c) (is_lower(c) || is_upper(c)) |
#define isalphanum(c) (is_alpha(c) || is_digit(c)) |
#define isalpha(c) (is_lower((c)) || is_upper((c))) |
#define isalphanum(c) (is_alpha((c)) || is_digit((c))) |
#define isspace(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || \ |
((c) == '\r')) |
48,7 → 48,7 |
#define min(a,b) ((a) < (b) ? (a) : (b)) |
#define max(a,b) ((a) > (b) ? (a) : (b)) |
/** Return true if the interlvals overlap. |
/** Return true if the intervals overlap. |
* |
* @param s1 Start address of the first interval. |
* @param sz1 Size of the first interval. |
64,11 → 64,15 |
} |
/* Compute overlapping of physical addresses */ |
#define PA_overlaps(x, szx, y, szy) overlaps(KA2PA(x), szx, KA2PA(y), szy) |
#define PA_overlaps(x, szx, y, szy) \ |
overlaps(KA2PA((x)), (szx), KA2PA((y)), (szy)) |
#define SIZE2KB(size) (size >> 10) |
#define SIZE2MB(size) (size >> 20) |
#define SIZE2KB(size) ((size) >> 10) |
#define SIZE2MB(size) ((size) >> 20) |
#define KB2SIZE(kb) ((kb) << 10) |
#define MB2SIZE(mb) ((mb) << 20) |
#define STRING(arg) STRING_ARG(arg) |
#define STRING_ARG(arg) #arg |
/branches/network/kernel/generic/include/config.h |
---|
40,8 → 40,6 |
#define STACK_SIZE PAGE_SIZE |
#define CONFIG_MEMORY_SIZE (8 * 1024 * 1024) |
#define CONFIG_INIT_TASKS 32 |
typedef struct { |
/branches/network/kernel/generic/include/proc/task.h |
---|
116,7 → 116,6 |
extern void task_done(void); |
extern task_t *task_create(as_t *as, char *name); |
extern void task_destroy(task_t *t); |
extern task_t *task_run_program(void *program_addr, char *name); |
extern task_t *task_find_by_id(task_id_t id); |
extern int task_kill(task_id_t id); |
extern uint64_t task_get_accounting(task_t *t); |
/branches/network/kernel/generic/include/proc/program.h |
---|
0,0 → 1,65 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genericproc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_PROGRAM_H_ |
#define KERN_PROGRAM_H_ |
#include <arch/types.h> |
struct task; |
struct thread; |
/** Program info structure. |
* |
* A program is an abstraction of a freshly created (not yet running) |
* userspace task containing a main thread along with its userspace stack. |
*/ |
typedef struct program { |
struct task *task; /**< Program task */ |
struct thread *main_thread; /**< Program main thread */ |
} program_t; |
extern void *program_loader; |
extern void program_create(as_t *as, uintptr_t entry_addr, program_t *p); |
extern int program_create_from_image(void *image_addr, program_t *p); |
extern int program_create_loader(program_t *p); |
extern void program_ready(program_t *p); |
extern unative_t sys_program_spawn_loader(int *uspace_phone_id); |
#endif |
/** @} |
*/ |
/branches/network/kernel/generic/include/proc/tasklet.h |
---|
0,0 → 1,73 |
/* |
* Copyright (c) 2007 Jan Hudecek |
* 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 genericproc |
* @{ |
*/ |
/** @file tasklet.h |
* @brief Tasklets declarations |
*/ |
#ifndef KERN_TASKLET_H_ |
#define KERN_TASKLET_H_ |
#include <adt/list.h> |
/** Tasklet callback type */ |
typedef void (* tasklet_callback_t)(void *arg); |
/** Tasklet state */ |
typedef enum { |
NotActive, |
Scheduled, |
InProgress, |
Disabled |
} tasklet_state_t; |
/** Structure describing a tasklet */ |
typedef struct tasklet_descriptor { |
link_t link; |
/** Callback to call */ |
tasklet_callback_t callback; |
/** Argument passed to the callback */ |
void *arg; |
/** State of the tasklet */ |
tasklet_state_t state; |
} tasklet_descriptor_t; |
extern void tasklet_init(void); |
#endif |
/** @} |
*/ |
/branches/network/kernel/generic/include/synch/smc.h |
---|
0,0 → 1,43 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sync |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_SMC_H_ |
#define KERN_SMC_H_ |
extern unative_t sys_smc_coherence(uintptr_t va, size_t size); |
#endif |
/** @} |
*/ |
/branches/network/kernel/generic/include/synch/mutex.h |
---|
39,7 → 39,13 |
#include <synch/semaphore.h> |
#include <synch/synch.h> |
typedef enum { |
MUTEX_PASSIVE, |
MUTEX_ACTIVE |
} mutex_type_t; |
typedef struct { |
mutex_type_t type; |
semaphore_t sem; |
} mutex_t; |
50,9 → 56,9 |
#define mutex_lock_timeout(mtx, usec) \ |
_mutex_lock_timeout((mtx), (usec), SYNCH_FLAGS_NON_BLOCKING) |
extern void mutex_initialize(mutex_t *mtx); |
extern int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags); |
extern void mutex_unlock(mutex_t *mtx); |
extern void mutex_initialize(mutex_t *, mutex_type_t); |
extern int _mutex_lock_timeout(mutex_t *, uint32_t, int); |
extern void mutex_unlock(mutex_t *); |
#endif |
/branches/network/kernel/generic/include/synch/spinlock.h |
---|
110,8 → 110,8 |
#define DEADLOCK_PROBE(pname, value) \ |
if ((pname)++ > (value)) { \ |
(pname) = 0; \ |
printf("Deadlock probe %s: exceeded threshold %d\n", \ |
"cpu%d: function=%s, line=%d\n", \ |
printf("Deadlock probe %s: exceeded threshold %u\n", \ |
"cpu%u: function=%s, line=%u\n", \ |
#pname, (value), CPU->id, __func__, __LINE__); \ |
} |
#else |
/branches/network/kernel/generic/include/syscall/syscall.h |
---|
36,17 → 36,25 |
#define KERN_SYSCALL_H_ |
typedef enum { |
SYS_IO = 0, |
SYS_KLOG = 0, |
SYS_TLS_SET = 1, /* Hardcoded in AMD64, IA32 uspace - fibril.S */ |
SYS_THREAD_CREATE, |
SYS_THREAD_EXIT, |
SYS_THREAD_GET_ID, |
SYS_TASK_GET_ID, |
SYS_PROGRAM_SPAWN_LOADER, |
SYS_FUTEX_SLEEP, |
SYS_FUTEX_WAKEUP, |
SYS_SMC_COHERENCE, |
SYS_AS_AREA_CREATE, |
SYS_AS_AREA_RESIZE, |
SYS_AS_AREA_CHANGE_FLAGS, |
SYS_AS_AREA_DESTROY, |
SYS_IPC_CALL_SYNC_FAST, |
SYS_IPC_CALL_SYNC_SLOW, |
SYS_IPC_CALL_ASYNC_FAST, |
58,13 → 66,17 |
SYS_IPC_HANGUP, |
SYS_IPC_REGISTER_IRQ, |
SYS_IPC_UNREGISTER_IRQ, |
SYS_CAP_GRANT, |
SYS_CAP_REVOKE, |
SYS_PHYSMEM_MAP, |
SYS_IOSPACE_ENABLE, |
SYS_PREEMPT_CONTROL, |
SYS_SYSINFO_VALID, |
SYS_SYSINFO_VALUE, |
SYS_DEBUG_ENABLE_CONSOLE, |
SYSCALL_END |
} syscall_t; |
/branches/network/kernel/generic/include/memstr.h |
---|
42,8 → 42,8 |
* Architecture independent variants. |
*/ |
extern void *_memcpy(void *dst, const void *src, size_t cnt); |
extern void _memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void _memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void _memsetb(void *dst, size_t cnt, uint8_t x); |
extern void _memsetw(void *dst, size_t cnt, uint16_t x); |
extern char *strcpy(char *dest, const char *src); |
#endif |
/branches/network/kernel/generic/include/typedefs.h |
---|
35,8 → 35,22 |
#ifndef KERN_TYPEDEFS_H_ |
#define KERN_TYPEDEFS_H_ |
#include <arch/types.h> |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef void (* function)(); |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#endif |
/** @} |
/branches/network/kernel/generic/include/console/klog.h |
---|
File deleted |
/branches/network/kernel/generic/include/console/console.h |
---|
41,6 → 41,9 |
extern chardev_t *stdin; |
extern chardev_t *stdout; |
extern void klog_init(void); |
extern void klog_update(void); |
extern uint8_t getc(chardev_t *chardev); |
uint8_t _getc(chardev_t *chardev); |
extern count_t gets(chardev_t *chardev, char *buf, size_t buflen); |
/branches/network/kernel/generic/include/interrupt.h |
---|
40,7 → 40,6 |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <console/klog.h> |
#include <ddi/irq.h> |
typedef void (* iroutine)(int n, istate_t *istate); |
49,8 → 48,8 |
{ \ |
if (istate_from_uspace(istate)) { \ |
task_t *task = TASK; \ |
klog_printf("Task %llu killed due to an exception at %p.", task->taskid, istate_get_pc(istate)); \ |
klog_printf(" " cmd, ##__VA_ARGS__); \ |
printf("Task %" PRIu64 " killed due to an exception at %p.", task->taskid, istate_get_pc(istate)); \ |
printf(" " cmd, ##__VA_ARGS__); \ |
task_kill(task->taskid); \ |
thread_exit(); \ |
} \ |
/branches/network/kernel/generic/include/ddi/device.h |
---|
35,6 → 35,9 |
#ifndef KERN_DEVICE_H_ |
#define KERN_DEVICE_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
extern devno_t device_assign_devno(void); |
#endif |
/branches/network/kernel/generic/include/adt/list.h |
---|
36,6 → 36,7 |
#define KERN_LIST_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
/** Doubly linked list head and link type. */ |
typedef struct link { |
/branches/network/kernel/generic/include/adt/avl.h |
---|
36,6 → 36,7 |
#define KERN_AVLTREE_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
/** |
* Macro for getting a pointer to the structure which contains the avltree |
/branches/network/kernel/generic/include/debug.h |
---|
55,12 → 55,51 |
* |
*/ |
#ifdef CONFIG_DEBUG |
# define ASSERT(expr) if (!(expr)) { panic("assertion failed (%s), caller=%.*p\n", #expr, sizeof(uintptr_t) * 2, CALLER); } |
# define ASSERT(expr) \ |
if (!(expr)) { \ |
panic("assertion failed (%s), caller=%p\n", #expr, CALLER); \ |
} |
#else |
# define ASSERT(expr) |
#endif |
/** Extensive debugging output macro |
* |
* If CONFIG_EDEBUG is set, the LOG() macro |
* will print whatever message is indicated plus |
* an information about the location. |
* |
*/ |
#ifdef CONFIG_EDEBUG |
# define LOG(format, ...) \ |
printf("%s() at %s:%u: " format "\n", __func__, __FILE__, \ |
__LINE__, ##__VA_ARGS__); |
#else |
# define LOG(format, ...) |
#endif |
/** Extensive debugging execute macro |
* |
* If CONFIG_EDEBUG is set, the LOG_EXEC() macro |
* will print an information about calling a given |
* function and call it. |
* |
*/ |
#ifdef CONFIG_EDEBUG |
# define LOG_EXEC(fnc) \ |
{ \ |
printf("%s() at %s:%u: " #fnc "\n", __func__, __FILE__, \ |
__LINE__); \ |
fnc; \ |
} |
#else |
# define LOG_EXEC(fnc) fnc |
#endif |
#endif |
/** @} |
*/ |
/branches/network/kernel/generic/include/panic.h |
---|
37,7 → 37,7 |
#ifdef CONFIG_DEBUG |
#define panic(format, ...) \ |
panic_printf("Kernel panic in %s() at %s on line %d: " format, __func__, \ |
panic_printf("Kernel panic in %s() at %s:%u: " format, __func__, \ |
__FILE__, __LINE__, ##__VA_ARGS__); |
#else |
#define panic(format, ...) \ |
/branches/network/kernel/generic/include/byteorder.h |
---|
35,6 → 35,34 |
#ifndef KERN_BYTEORDER_H_ |
#define KERN_BYTEORDER_H_ |
#include <arch/byteorder.h> |
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN)) |
#error The architecture must be either big-endian or little-endian. |
#endif |
#ifdef ARCH_IS_BIG_ENDIAN |
#define uint16_t_le2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_be2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#endif |
static inline uint64_t uint64_t_byteorder_swap(uint64_t n) |
{ |
return ((n & 0xff) << 56) | |
55,6 → 83,12 |
((n & 0xff000000) >> 24); |
} |
static inline uint16_t uint16_t_byteorder_swap(uint16_t n) |
{ |
return ((n & 0xff) << 8) | |
((n & 0xff00) >> 8); |
} |
#endif |
/** @} |
/branches/network/kernel/arch/ia32/include/atomic.h |
---|
41,17 → 41,17 |
static inline void atomic_inc(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock incl %0\n" : "=m" (val->count)); |
asm volatile ("lock incl %0\n" : "+m" (val->count)); |
#else |
asm volatile ("incl %0\n" : "=m" (val->count)); |
asm volatile ("incl %0\n" : "+m" (val->count)); |
#endif /* CONFIG_SMP */ |
} |
static inline void atomic_dec(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock decl %0\n" : "=m" (val->count)); |
asm volatile ("lock decl %0\n" : "+m" (val->count)); |
#else |
asm volatile ("decl %0\n" : "=m" (val->count)); |
asm volatile ("decl %0\n" : "+m" (val->count)); |
#endif /* CONFIG_SMP */ |
} |
61,7 → 61,7 |
asm volatile ( |
"lock xaddl %1, %0\n" |
: "=m" (val->count), "+r" (r) |
: "+m" (val->count), "+r" (r) |
); |
return r; |
73,7 → 73,7 |
asm volatile ( |
"lock xaddl %1, %0\n" |
: "=m" (val->count), "+r"(r) |
: "+m" (val->count), "+r"(r) |
); |
return r; |
88,7 → 88,7 |
asm volatile ( |
"movl $1, %0\n" |
"xchgl %0, %1\n" |
: "=r" (v),"=m" (val->count) |
: "=r" (v),"+m" (val->count) |
); |
return v; |
101,19 → 101,19 |
preemption_disable(); |
asm volatile ( |
"0:;" |
"0:\n" |
#ifdef CONFIG_HT |
"pause;" /* Pentium 4's HT love this instruction */ |
"pause\n" /* Pentium 4's HT love this instruction */ |
#endif |
"mov %0, %1;" |
"testl %1, %1;" |
"jnz 0b;" /* Lightweight looping on locked spinlock */ |
"mov %0, %1\n" |
"testl %1, %1\n" |
"jnz 0b\n" /* lightweight looping on locked spinlock */ |
"incl %1;" /* now use the atomic operation */ |
"xchgl %0, %1;" |
"testl %1, %1;" |
"jnz 0b;" |
: "=m"(val->count),"=r"(tmp) |
"incl %1\n" /* now use the atomic operation */ |
"xchgl %0, %1\n" |
"testl %1, %1\n" |
"jnz 0b\n" |
: "+m" (val->count), "=&r"(tmp) |
); |
/* |
* Prevent critical section code from bleeding out this way up. |
/branches/network/kernel/arch/ia32/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
128,6 → 126,8 |
#include <mm/mm.h> |
#include <arch/interrupt.h> |
#include <arch/types.h> |
#include <typedefs.h> |
/* Page fault error codes. */ |
/branches/network/kernel/arch/ia32/include/barrier.h |
---|
84,6 → 84,15 |
# endif |
#endif |
/* |
* On ia32, the hardware takes care about instruction and data cache coherence, |
* even on SMP systems. We issue a write barrier to be sure that writes |
* queueing in the store buffer drain to the memory (even though it would be |
* sufficient for them to drain to the D-cache). |
*/ |
#define smc_coherence(a) write_barrier() |
#define smc_coherence_block(a, l) write_barrier() |
#endif |
/** @} |
/branches/network/kernel/arch/ia32/include/memstr.h |
---|
35,116 → 35,13 |
#ifndef KERN_ia32_MEMSTR_H_ |
#define KERN_ia32_MEMSTR_H_ |
/** Copy memory |
* |
* Copy a given number of bytes (3rd argument) |
* from the memory location defined by 2nd argument |
* to the memory location defined by 1st argument. |
* The memory areas cannot overlap. |
* |
* @param dst Destination |
* @param src Source |
* @param cnt Number of bytes |
* @return Destination |
*/ |
static inline void * memcpy(void * dst, const void * src, size_t cnt) |
{ |
unative_t d0, d1, d2; |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
asm volatile( |
/* copy all full dwords */ |
"rep movsl\n\t" |
/* load count again */ |
"movl %4, %%ecx\n\t" |
/* ecx = ecx mod 4 */ |
"andl $3, %%ecx\n\t" |
/* are there last <=3 bytes? */ |
"jz 1f\n\t" |
/* copy last <=3 bytes */ |
"rep movsb\n\t" |
/* exit from asm block */ |
"1:\n" |
: "=&c" (d0), "=&D" (d1), "=&S" (d2) |
: "0" ((unative_t) (cnt / 4)), "g" ((unative_t) cnt), "1" ((unative_t) dst), "2" ((unative_t) src) |
: "memory"); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
return dst; |
} |
extern int memcmp(const void *a, const void *b, size_t cnt); |
/** Compare memory regions for equality |
* |
* Compare a given number of bytes (3rd argument) |
* at memory locations defined by 1st and 2nd argument |
* for equality. If bytes are equal function returns 0. |
* |
* @param src Region 1 |
* @param dst Region 2 |
* @param cnt Number of bytes |
* @return Zero if bytes are equal, non-zero otherwise |
*/ |
static inline int memcmp(const void * src, const void * dst, size_t cnt) |
{ |
uint32_t d0, d1, d2; |
int ret; |
asm ( |
"repe cmpsb\n\t" |
"je 1f\n\t" |
"movl %3, %0\n\t" |
"addl $1, %0\n\t" |
"1:\n" |
: "=a" (ret), "=%S" (d0), "=&D" (d1), "=&c" (d2) |
: "0" (0), "1" ((unative_t) src), "2" ((unative_t) dst), "3" ((unative_t) cnt) |
); |
return ret; |
} |
/** Fill memory with words |
* Fill a given number of words (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of words |
* @param x Value to fill |
*/ |
static inline void memsetw(uintptr_t dst, size_t cnt, uint16_t x) |
{ |
uint32_t d0, d1; |
asm volatile ( |
"rep stosw\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" (cnt), "2" (x) |
: "memory" |
); |
} |
/** Fill memory with bytes |
* Fill a given number of bytes (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of bytes |
* @param x Value to fill |
*/ |
static inline void memsetb(uintptr_t dst, size_t cnt, uint8_t x) |
{ |
uint32_t d0, d1; |
asm volatile ( |
"rep stosb\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" (cnt), "2" (x) |
: "memory" |
); |
} |
#endif |
/** @} |
/branches/network/kernel/arch/ia32/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ia32_TYPES_H_ |
#define KERN_ia32_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed long int32_t; |
61,14 → 57,29 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
#define PRIp "x" /**< Format for uintptr_t. */ |
#define PRIs "u" /**< Format for size_t. */ |
#define PRIc "u" /**< Format for count_t. */ |
#define PRIi "u" /**< Format for index_t. */ |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "d" /**< Format for int32_t. */ |
#define PRId64 "lld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "llu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
/** Page Table Entry. */ |
typedef struct { |
unsigned present : 1; |
/branches/network/kernel/arch/ia32/include/byteorder.h |
---|
35,15 → 35,9 |
#ifndef KERN_ia32_BYTEORDER_H_ |
#define KERN_ia32_BYTEORDER_H_ |
#include <byteorder.h> |
/* IA-32 is little-endian */ |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define ARCH_IS_LITTLE_ENDIAN |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#endif |
/** @} |
/branches/network/kernel/arch/ia32/include/context_offset.h |
---|
0,0 → 1,83 |
/* |
* Copyright (c) 2008 Josef Cejka |
* 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 |
*/ |
#ifndef KERN_ia32_CONTEXT_OFFSET_H_ |
#define KERN_ia32_CONTEXT_OFFSET_H_ |
#define OFFSET_SP 0x0 |
#define OFFSET_PC 0x4 |
#define OFFSET_EBX 0x8 |
#define OFFSET_ESI 0xC |
#define OFFSET_EDI 0x10 |
#define OFFSET_EBP 0x14 |
#ifdef KERNEL |
# define OFFSET_IPL 0x18 |
#else |
# define OFFSET_TLS 0x18 |
#endif |
#ifdef __ASM__ |
# ctx: address of the structure with saved context |
# pc: return address |
.macro CONTEXT_SAVE_ARCH_CORE ctx:req pc:req |
movl %esp,OFFSET_SP(\ctx) # %esp -> ctx->sp |
movl \pc,OFFSET_PC(\ctx) # %eip -> ctx->pc |
movl %ebx,OFFSET_EBX(\ctx) # %ebx -> ctx->ebx |
movl %esi,OFFSET_ESI(\ctx) # %esi -> ctx->esi |
movl %edi,OFFSET_EDI(\ctx) # %edi -> ctx->edi |
movl %ebp,OFFSET_EBP(\ctx) # %ebp -> ctx->ebp |
.endm |
# ctx: address of the structure with saved context |
.macro CONTEXT_RESTORE_ARCH_CORE ctx:req pc:req |
movl OFFSET_SP(\ctx),%esp # ctx->sp -> %esp |
movl OFFSET_PC(\ctx),\pc # ctx->pc -> \pc |
movl OFFSET_EBX(\ctx),%ebx # ctx->ebx -> %ebx |
movl OFFSET_ESI(\ctx),%esi # ctx->esi -> %esi |
movl OFFSET_EDI(\ctx),%edi # ctx->edi -> %edi |
movl OFFSET_EBP(\ctx),%ebp # ctx->ebp -> %ebp |
.endm |
#endif /* __ASM__ */ |
#endif |
/** @} |
*/ |
/branches/network/kernel/arch/ia32/include/context.h |
---|
35,6 → 35,7 |
#ifndef KERN_ia32_CONTEXT_H_ |
#define KERN_ia32_CONTEXT_H_ |
#ifdef KERNEL |
#include <arch/types.h> |
#define STACK_ITEM_SIZE 4 |
47,6 → 48,8 |
*/ |
#define SP_DELTA (8 + STACK_ITEM_SIZE) |
#endif /* KERNEL */ |
/* |
* Only save registers that must be preserved across |
* function calls. |
/branches/network/kernel/arch/ia32/Makefile.inc |
---|
29,11 → 29,15 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-i386 |
BFD_ARCH = i386 |
BFD = binary |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/i686 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686 |
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__ |
46,7 → 50,8 |
# |
ifeq ($(MACHINE),athlon-xp) |
CMN2 = -march=athlon-xp -mmmx -msse -m3dnow |
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-3dnow |
CMN2 = -march=athlon-xp |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
SUNCC_CFLAGS += -xarch=ssea |
55,7 → 60,8 |
CONFIG_HT = n |
endif |
ifeq ($(MACHINE),athlon-mp) |
CMN2 = -march=athlon-mp -mmmx -msse -m3dnow |
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-3dnow |
CMN2 = -march=athlon-mp |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
SUNCC_CFLAGS += xarch=ssea |
63,7 → 69,8 |
CONFIG_HT = n |
endif |
ifeq ($(MACHINE),pentium3) |
CMN2 = -march=pentium3 -mmmx -msse |
FPU_NO_CFLAGS = -mno-mmx -mno-sse |
CMN2 = -march=pentium3 |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
SUNCC_CFLAGS += -xarch=sse |
71,7 → 78,8 |
CONFIG_HT = n |
endif |
ifeq ($(MACHINE),core) |
CMN2 = -march=prescott -mfpmath=sse -mmmx -msse -msse2 -msse3 |
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2 -mno-sse3 |
CMN2 = -march=prescott |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
SUNCC_CFLAGS += -xarch=sse3 |
78,7 → 86,8 |
DEFS += -DCONFIG_FENCES_P4 |
endif |
ifeq ($(MACHINE),pentium4) |
GCC_CFLAGS += -march=pentium4 -mfpmath=sse -mmmx -msse -msse2 |
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2 |
GCC_CFLAGS += -march=pentium4 |
ICC_CFLAGS += -march=pentium4 |
SUNCC_CFLAGS += -xarch=sse2 |
DEFS += -DCONFIG_FENCES_P4 |
120,7 → 129,7 |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/context.s \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/debug/panic.s \ |
arch/$(ARCH)/src/delay.s \ |
arch/$(ARCH)/src/asm.S \ |
/branches/network/kernel/arch/ia32/src/context.s |
---|
File deleted |
/branches/network/kernel/arch/ia32/src/asm.S |
---|
37,6 → 37,8 |
.global paging_on |
.global enable_l_apic_in_msr |
.global interrupt_handlers |
.global memsetb |
.global memsetw |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_from_uspace_failover_address |
44,6 → 46,15 |
.global memcpy_to_uspace_failover_address |
# Wrapper for generic memsetb |
memsetb: |
jmp _memsetb |
# Wrapper for generic memsetw |
memsetw: |
jmp _memsetw |
#define MEMCPY_DST 4 |
#define MEMCPY_SRC 8 |
#define MEMCPY_SIZE 12 |
60,7 → 71,7 |
* @param MEMCPY_SRC(%esp) Source address. |
* @param MEMCPY_SIZE(%esp) Size. |
* |
* @return MEMCPY_SRC(%esp) on success and 0 on failure. |
* @return MEMCPY_DST(%esp) on success and 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
85,7 → 96,7 |
0: |
movl %edx, %edi |
movl %eax, %esi |
movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */ |
movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */ |
ret |
/* |
173,6 → 184,7 |
movw %ax, %ds |
movw %ax, %es |
cld |
sti |
# syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) |
call syscall_handler |
233,6 → 245,8 |
movw %ax, %ds |
movw %ax, %es |
cld |
pushl %esp # *istate |
pushl $(\i) # intnum |
call exc_dispatch # excdispatch(intnum, *istate) |
/branches/network/kernel/arch/ia32/src/mm/as.c |
---|
39,9 → 39,7 |
/** Architecture dependent address space init. */ |
void as_arch_init(void) |
{ |
#ifndef __OBJC__ |
as_operations = &as_pt_operations; |
#endif |
} |
/** @} |
/branches/network/kernel/arch/ia32/src/drivers/ega.c |
---|
93,12 → 93,6 |
sysinfo_set_item_val("fb.width", NULL, ROW); |
sysinfo_set_item_val("fb.height", NULL, ROWS); |
sysinfo_set_item_val("fb.address.physical", NULL, VIDEORAM); |
sysinfo_set_item_val("fb.address.color", NULL, PAGE_COLOR((uintptr_t) |
videoram)); |
#ifndef CONFIG_FB |
putchar('\n'); |
#endif |
} |
static void ega_display_char(char ch) |
115,7 → 109,7 |
return; |
memcpy((void *) videoram, (void *) (videoram + ROW * 2), (SCREEN - ROW) * 2); |
memsetw((uintptr_t) (videoram + (SCREEN - ROW) * 2), ROW, 0x0720); |
memsetw(videoram + (SCREEN - ROW) * 2, ROW, 0x0720); |
ega_cursor = ega_cursor - ROW; |
} |
/branches/network/kernel/arch/ia32/src/userspace.c |
---|
70,6 → 70,10 |
"pushl %3\n" |
"pushl %4\n" |
"movl %5, %%eax\n" |
/* %ebx is defined to hold pcb_ptr - set it to 0 */ |
"xorl %%ebx, %%ebx\n" |
"iret\n" |
: |
: "i" (selector(UDATA_DES) | PL_USER), |
/branches/network/kernel/arch/ia32/src/smp/smp.c |
---|
155,13 → 155,12 |
* Prepare new GDT for CPU in question. |
*/ |
gdt_new = (struct descriptor *) malloc(GDT_ITEMS * |
sizeof(struct descriptor), FRAME_ATOMIC); |
sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB); |
if (!gdt_new) |
panic("couldn't allocate memory for GDT\n"); |
memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(struct descriptor)); |
memsetb((uintptr_t)(&gdt_new[TSS_DES]), |
sizeof(struct descriptor), 0); |
memsetb(&gdt_new[TSS_DES], sizeof(struct descriptor), 0); |
protected_ap_gdtr.limit = GDT_ITEMS * sizeof(struct descriptor); |
protected_ap_gdtr.base = KA2PA((uintptr_t) gdt_new); |
gdtr.base = (uintptr_t) gdt_new; |
/branches/network/kernel/arch/ia32/src/smp/ap.S |
---|
45,7 → 45,7 |
KTEXT=8 |
KDATA=16 |
# This piece of code is real-mode and is meant to be alligned at 4K boundary. |
# This piece of code is real-mode and is meant to be aligned at 4K boundary. |
# The requirement for such an alignment comes from MP Specification's STARTUP IPI |
# requirements. |
/branches/network/kernel/arch/ia32/src/pm.c |
---|
112,7 → 112,7 |
void tss_initialize(tss_t *t) |
{ |
memsetb((uintptr_t) t, sizeof(struct tss), 0); |
memsetb(t, sizeof(struct tss), 0); |
} |
/* |
240,7 → 240,7 |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb((uintptr_t) idt, sizeof(idt), 0); |
memsetb(idt, sizeof(idt), 0); |
ptr_16_32_t idtr; |
idtr.limit = sizeof(idt); |
/branches/network/kernel/arch/ia32/src/boot/boot.S |
---|
50,6 → 50,7 |
.long multiboot_image_start |
multiboot_image_start: |
cld |
movl $START_STACK, %esp # initialize stack pointer |
lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register |
85,7 → 86,6 |
mov $vesa_init, %esi |
mov $VESA_INIT_SEGMENT << 4, %edi |
mov $e_vesa_init - vesa_init, %ecx |
cld |
rep movsb |
mov $VESA_INIT_SEGMENT << 4, %edi |
206,7 → 206,6 |
movl $BOOT_OFFSET, %esi |
movl $AP_BOOT_OFFSET, %edi |
movl $_hardcoded_unmapped_size, %ecx |
cld |
rep movsb |
#endif |
279,7 → 278,6 |
addl %eax, %edi |
movw $0x0c00, %ax # black background, light red foreground |
cld |
ploop: |
lodsb |
/branches/network/kernel/arch/ia32/src/context.S |
---|
0,0 → 1,67 |
# |
# Copyright (c) 2001-2004 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. |
# |
#include <arch/context_offset.h> |
.text |
.global context_save_arch |
.global context_restore_arch |
## Save current CPU context |
# |
# Save CPU context to the context_t variable |
# pointed by the 1st argument. Returns 1 in EAX. |
# |
context_save_arch: |
movl 0(%esp),%eax # save pc value into eax |
movl 4(%esp),%edx # address of the context variable to save context to |
# save registers to given structure |
CONTEXT_SAVE_ARCH_CORE %edx %eax |
xorl %eax,%eax # context_save returns 1 |
incl %eax |
ret |
## Restore saved CPU context |
# |
# Restore CPU context from context_t variable |
# pointed by the 1st argument. Returns 0 in EAX. |
# |
context_restore_arch: |
movl 4(%esp),%eax # address of the context variable to restore context from |
# restore registers from given structure |
CONTEXT_RESTORE_ARCH_CORE %eax %edx |
movl %edx,0(%esp) # put saved pc on stack |
xorl %eax,%eax # context_restore returns 0 |
ret |
/branches/network/kernel/arch/amd64/include/atomic.h |
---|
41,17 → 41,17 |
static inline void atomic_inc(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock incq %0\n" : "=m" (val->count)); |
asm volatile ("lock incq %0\n" : "+m" (val->count)); |
#else |
asm volatile ("incq %0\n" : "=m" (val->count)); |
asm volatile ("incq %0\n" : "+m" (val->count)); |
#endif /* CONFIG_SMP */ |
} |
static inline void atomic_dec(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock decq %0\n" : "=m" (val->count)); |
asm volatile ("lock decq %0\n" : "+m" (val->count)); |
#else |
asm volatile ("decq %0\n" : "=m" (val->count)); |
asm volatile ("decq %0\n" : "+m" (val->count)); |
#endif /* CONFIG_SMP */ |
} |
61,7 → 61,7 |
asm volatile ( |
"lock xaddq %1, %0\n" |
: "=m" (val->count), "+r" (r) |
: "+m" (val->count), "+r" (r) |
); |
return r; |
73,7 → 73,7 |
asm volatile ( |
"lock xaddq %1, %0\n" |
: "=m" (val->count), "+r" (r) |
: "+m" (val->count), "+r" (r) |
); |
return r; |
88,7 → 88,7 |
asm volatile ( |
"movq $1, %0\n" |
"xchgq %0, %1\n" |
: "=r" (v),"=m" (val->count) |
: "=r" (v), "+m" (val->count) |
); |
return v; |
102,19 → 102,19 |
preemption_disable(); |
asm volatile ( |
"0:;" |
"0:\n" |
#ifdef CONFIG_HT |
"pause;" |
"pause\n" |
#endif |
"mov %0, %1;" |
"testq %1, %1;" |
"jnz 0b;" /* Lightweight looping on locked spinlock */ |
"mov %0, %1\n" |
"testq %1, %1\n" |
"jnz 0b\n" /* lightweight looping on locked spinlock */ |
"incq %1;" /* now use the atomic operation */ |
"xchgq %0, %1;" |
"testq %1, %1;" |
"jnz 0b;" |
: "=m"(val->count),"=r"(tmp) |
"incq %1\n" /* now use the atomic operation */ |
"xchgq %0, %1\n" |
"testq %1, %1\n" |
"jnz 0b\n" |
: "+m" (val->count), "=&r" (tmp) |
); |
/* |
* Prevent critical section code from bleeding out this way up. |
/branches/network/kernel/arch/amd64/include/mm/page.h |
---|
52,8 → 52,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/network/kernel/arch/amd64/include/memstr.h |
---|
35,110 → 35,13 |
#ifndef KERN_amd64_MEMSTR_H_ |
#define KERN_amd64_MEMSTR_H_ |
/** Copy memory |
* |
* Copy a given number of bytes (3rd argument) |
* from the memory location defined by 2nd argument |
* to the memory location defined by 1st argument. |
* The memory areas cannot overlap. |
* |
* @param dst Destination |
* @param src Source |
* @param cnt Number of bytes |
* @return Destination |
*/ |
static inline void * memcpy(void * dst, const void * src, size_t cnt) |
{ |
unative_t d0, d1, d2; |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
asm volatile( |
"rep movsq\n\t" |
"movq %4, %%rcx\n\t" |
"andq $7, %%rcx\n\t" |
"jz 1f\n\t" |
"rep movsb\n\t" |
"1:\n" |
: "=&c" (d0), "=&D" (d1), "=&S" (d2) |
: "0" ((unative_t)(cnt / 8)), "g" ((unative_t)cnt), "1" ((unative_t) dst), "2" ((unative_t) src) |
: "memory"); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
return dst; |
} |
extern int memcmp(const void *a, const void *b, size_t cnt); |
/** Compare memory regions for equality |
* |
* Compare a given number of bytes (3rd argument) |
* at memory locations defined by 1st and 2nd argument |
* for equality. If bytes are equal function returns 0. |
* |
* @param src Region 1 |
* @param dst Region 2 |
* @param cnt Number of bytes |
* @return Zero if bytes are equal, non-zero otherwise |
*/ |
static inline int memcmp(const void * src, const void * dst, size_t cnt) |
{ |
unative_t d0, d1, d2; |
unative_t ret; |
asm ( |
"repe cmpsb\n\t" |
"je 1f\n\t" |
"movq %3, %0\n\t" |
"addq $1, %0\n\t" |
"1:\n" |
: "=a" (ret), "=%S" (d0), "=&D" (d1), "=&c" (d2) |
: "0" (0), "1" (src), "2" (dst), "3" ((unative_t)cnt) |
); |
return ret; |
} |
/** Fill memory with words |
* Fill a given number of words (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of words |
* @param x Value to fill |
*/ |
static inline void memsetw(uintptr_t dst, size_t cnt, uint16_t x) |
{ |
unative_t d0, d1; |
asm volatile ( |
"rep stosw\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" ((unative_t)cnt), "2" (x) |
: "memory" |
); |
} |
/** Fill memory with bytes |
* Fill a given number of bytes (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of bytes |
* @param x Value to fill |
*/ |
static inline void memsetb(uintptr_t dst, size_t cnt, uint8_t x) |
{ |
unative_t d0, d1; |
asm volatile ( |
"rep stosb\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" ((unative_t)cnt), "2" (x) |
: "memory" |
); |
} |
#endif |
/** @} |
/branches/network/kernel/arch/amd64/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_amd64_TYPES_H_ |
#define KERN_amd64_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,14 → 57,31 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
/**< Formats for uintptr_t, size_t, count_t and index_t */ |
#define PRIp "llx" |
#define PRIs "llu" |
#define PRIc "llu" |
#define PRIi "llu" |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */ |
#define PRId8 "d" |
#define PRId16 "d" |
#define PRId32 "d" |
#define PRId64 "lld" |
#define PRIdn "lld" |
#define PRIu8 "u" |
#define PRIu16 "u" |
#define PRIu32 "u" |
#define PRIu64 "llu" |
#define PRIun "llu" |
#define PRIx8 "x" |
#define PRIx16 "x" |
#define PRIx32 "x" |
#define PRIx64 "llx" |
#define PRIxn "llx" |
/** Page Table Entry. */ |
typedef struct { |
unsigned present : 1; |
/branches/network/kernel/arch/amd64/include/byteorder.h |
---|
35,15 → 35,9 |
#ifndef KERN_amd64_BYTEORDER_H_ |
#define KERN_amd64_BYTEORDER_H_ |
#include <byteorder.h> |
/* AMD64 is little-endian */ |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define ARCH_IS_LITTLE_ENDIAN |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#endif |
/** @} |
/branches/network/kernel/arch/amd64/include/cpu.h |
---|
36,6 → 36,7 |
#define KERN_amd64_CPU_H_ |
#define RFLAGS_IF (1 << 9) |
#define RFLAGS_DF (1 << 10) |
#define RFLAGS_RF (1 << 16) |
#define EFER_MSR_NUM 0xc0000080 |
/branches/network/kernel/arch/amd64/include/context_offset.h |
---|
37,6 → 37,43 |
#define OFFSET_R13 0x28 |
#define OFFSET_R14 0x30 |
#define OFFSET_R15 0x38 |
#ifdef KERNEL |
#define OFFSET_IPL 0x40 |
#else |
# define OFFSET_TLS 0x40 |
#endif |
#ifdef __ASM__ |
# ctx: address of the structure with saved context |
# pc: return address |
.macro CONTEXT_SAVE_ARCH_CORE ctx:req pc:req |
movq \pc, OFFSET_PC(\ctx) |
movq %rsp, OFFSET_SP(\ctx) |
movq %rbx, OFFSET_RBX(\ctx) |
movq %rbp, OFFSET_RBP(\ctx) |
movq %r12, OFFSET_R12(\ctx) |
movq %r13, OFFSET_R13(\ctx) |
movq %r14, OFFSET_R14(\ctx) |
movq %r15, OFFSET_R15(\ctx) |
.endm |
# ctx: address of the structure with saved context |
.macro CONTEXT_RESTORE_ARCH_CORE ctx:req pc:req |
movq OFFSET_R15(\ctx), %r15 |
movq OFFSET_R14(\ctx), %r14 |
movq OFFSET_R13(\ctx), %r13 |
movq OFFSET_R12(\ctx), %r12 |
movq OFFSET_RBP(\ctx), %rbp |
movq OFFSET_RBX(\ctx), %rbx |
movq OFFSET_SP(\ctx), %rsp # ctx->sp -> %rsp |
movq OFFSET_PC(\ctx), \pc |
.endm |
#endif |
#endif |
/branches/network/kernel/arch/amd64/include/context.h |
---|
35,6 → 35,8 |
#ifndef KERN_amd64_CONTEXT_H_ |
#define KERN_amd64_CONTEXT_H_ |
#ifdef KERNEL |
#include <arch/types.h> |
/* According to ABI the stack MUST be aligned on |
43,6 → 45,8 |
*/ |
#define SP_DELTA 16 |
#endif /* KERNEL */ |
/* We include only registers that must be preserved |
* during function call |
*/ |
/branches/network/kernel/arch/amd64/Makefile.inc |
---|
29,12 → 29,17 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-x86-64 |
BFD_ARCH = i386:x86-64 |
BFD = binary |
TARGET = amd64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/amd64 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64 |
FPU_NO_CFLAGS = -mno-sse -mno-sse2 |
CMN1 = -m64 -mcmodel=kernel -mno-red-zone -fno-unwind-tables |
GCC_CFLAGS += $(CMN1) |
ICC_CFLAGS += $(CMN1) |
/branches/network/kernel/arch/amd64/src/asm_utils.S |
---|
65,6 → 65,8 |
.global get_cycle |
.global read_efer_flag |
.global set_efer_flag |
.global memsetb |
.global memsetw |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
71,6 → 73,14 |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
# Wrapper for generic memsetb |
memsetb: |
jmp _memsetb |
# Wrapper for generic memsetw |
memsetw: |
jmp _memsetw |
#define MEMCPY_DST %rdi |
#define MEMCPY_SRC %rsi |
#define MEMCPY_SIZE %rdx |
88,12 → 98,12 |
* @param MEMCPY_SRC Source address. |
* @param MEMCPY_SIZE Number of bytes to copy. |
* |
* @retrun MEMCPY_SRC on success, 0 on failure. |
* @retrun MEMCPY_DST on success, 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
movq MEMCPY_SRC, %rax |
movq MEMCPY_DST, %rax |
movq MEMCPY_SIZE, %rcx |
shrq $3, %rcx /* size / 8 */ |
248,6 → 258,7 |
.endif |
save_all_gpr |
cld |
movq $(\i), %rdi # %rdi - first parameter |
movq %rsp, %rsi # %rsi - pointer to istate |
/branches/network/kernel/arch/amd64/src/userspace.c |
---|
61,6 → 61,8 |
"pushq %3\n" |
"pushq %4\n" |
"movq %5, %%rax\n" |
/* %rdi is defined to hold pcb_ptr - set it to 0 */ |
"xorq %%rdi, %%rdi\n" |
"iretq\n" |
: : |
"i" (gdtselector(UDATA_DES) | PL_USER), |
/branches/network/kernel/arch/amd64/src/debugger.c |
---|
107,24 → 107,32 |
unsigned int i; |
char *symbol; |
if (sizeof(void *) == 4) { |
#ifdef __32_BITS__ |
printf("# Count Address In symbol\n"); |
printf("-- ----- ---------- ---------\n"); |
} else { |
#endif |
#ifdef __64_BITS__ |
printf("# Count Address In symbol\n"); |
printf("-- ----- ------------------ ---------\n"); |
} |
#endif |
for (i = 0; i < BKPOINTS_MAX; i++) |
if (breakpoints[i].address) { |
symbol = get_symtab_entry(breakpoints[i].address); |
if (sizeof(void *) == 4) |
printf("%-2u %-5d %#10zx %s\n", i, breakpoints[i].counter, |
breakpoints[i].address, symbol); |
else |
printf("%-2u %-5d %#18zx %s\n", i, breakpoints[i].counter, |
breakpoints[i].address, symbol); |
#ifdef __32_BITS__ |
printf("%-2u %-5d %#10zx %s\n", i, |
breakpoints[i].counter, breakpoints[i].address, |
symbol); |
#endif |
#ifdef __64_BITS__ |
printf("%-2u %-5d %#18zx %s\n", i, |
breakpoints[i].counter, breakpoints[i].address, |
symbol); |
#endif |
} |
return 1; |
} |
162,10 → 170,14 |
if ((flags & BKPOINT_INSTR)) { |
; |
} else { |
if (sizeof(int) == 4) |
#ifdef __32_BITS__ |
dr7 |= ((unative_t) 0x3) << (18 + 4*curidx); |
else /* 8 */ |
#endif |
#ifdef __64_BITS__ |
dr7 |= ((unative_t) 0x2) << (18 + 4*curidx); |
#endif |
if ((flags & BKPOINT_WRITE)) |
dr7 |= ((unative_t) 0x1) << (16 + 4*curidx); |
246,7 → 258,7 |
if ((breakpoints[slot].flags & BKPOINT_CHECK_ZERO)) { |
if (*((unative_t *) breakpoints[slot].address) != 0) |
return; |
printf("**** Found ZERO on address %lx (slot %d) ****\n", |
printf("*** Found ZERO on address %lx (slot %d) ***\n", |
breakpoints[slot].address, slot); |
} else { |
printf("Data watchpoint - new data: %lx\n", |
292,7 → 304,8 |
/** Remove breakpoint from table */ |
int cmd_del_breakpoint(cmd_arg_t *argv) |
{ |
if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) { |
unative_t bpno = argv->intval; |
if (bpno > BKPOINTS_MAX) { |
printf("Invalid breakpoint number.\n"); |
return 0; |
} |
346,7 → 359,9 |
} |
#ifdef CONFIG_SMP |
static void debug_ipi(int n __attribute__((unused)), istate_t *istate __attribute__((unused))) |
static void |
debug_ipi(int n __attribute__((unused)), |
istate_t *istate __attribute__((unused))) |
{ |
int i; |
383,11 → 398,9 |
panic("could not register command %s\n", addwatchp_info.name); |
#endif |
exc_register(VECTOR_DEBUG, "debugger", |
debug_exception); |
exc_register(VECTOR_DEBUG, "debugger", debug_exception); |
#ifdef CONFIG_SMP |
exc_register(VECTOR_DEBUG_IPI, "debugger_smp", |
debug_ipi); |
exc_register(VECTOR_DEBUG_IPI, "debugger_smp", debug_ipi); |
#endif |
} |
/branches/network/kernel/arch/amd64/src/pm.c |
---|
155,7 → 155,7 |
void tss_initialize(tss_t *t) |
{ |
memsetb((uintptr_t) t, sizeof(tss_t), 0); |
memsetb(t, sizeof(tss_t), 0); |
} |
/* |
239,7 → 239,7 |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb((uintptr_t) idt, sizeof(idt), 0); |
memsetb(idt, sizeof(idt), 0); |
idtr_load(&idtr); |
interrupts_restore(ipl); |
/branches/network/kernel/arch/amd64/src/syscall.c |
---|
62,9 → 62,11 |
write_msr(AMD_MSR_LSTAR, (uint64_t)syscall_entry); |
/* Mask RFLAGS on syscall |
* - disable interrupts, until we exchange the stack register |
* (mask the IE bit) |
* (mask the IF bit) |
* - clear DF so that the string instructions operate in |
* the right direction |
*/ |
write_msr(AMD_MSR_SFMASK, 0x200); |
write_msr(AMD_MSR_SFMASK, RFLAGS_IF | RFLAGS_DF); |
} |
/** @} |
/branches/network/kernel/arch/amd64/src/boot/boot.S |
---|
54,6 → 54,7 |
.long multiboot_image_start |
multiboot_image_start: |
cld |
movl $START_STACK, %esp # initialize stack pointer |
lgdtl bootstrap_gdtr # initialize Global Descriptor Table register |
126,7 → 127,6 |
mov $vesa_init, %esi |
mov $VESA_INIT_SEGMENT << 4, %edi |
mov $e_vesa_init - vesa_init, %ecx |
cld |
rep movsb |
mov $VESA_INIT_SEGMENT << 4, %edi |
282,7 → 282,6 |
movq $BOOT_OFFSET, %rsi |
movq $AP_BOOT_OFFSET, %rdi |
movq $_hardcoded_unmapped_size, %rcx |
cld |
rep movsb |
#endif |
556,7 → 555,6 |
addl %eax, %edi |
movw $0x0c00, %ax # black background, light red foreground |
cld |
ploop: |
lodsb |
/branches/network/kernel/arch/amd64/src/cpu/cpu.c |
---|
124,7 → 124,8 |
void cpu_arch_init(void) |
{ |
CPU->arch.tss = tss_p; |
CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((uint8_t *) CPU->arch.tss); |
CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - |
((uint8_t *) CPU->arch.tss); |
CPU->fpu_owner = NULL; |
} |
139,7 → 140,9 |
/* |
* Check for AMD processor. |
*/ |
if (info.cpuid_ebx==AMD_CPUID_EBX && info.cpuid_ecx==AMD_CPUID_ECX && info.cpuid_edx==AMD_CPUID_EDX) { |
if (info.cpuid_ebx == AMD_CPUID_EBX && |
info.cpuid_ecx == AMD_CPUID_ECX && |
info.cpuid_edx == AMD_CPUID_EDX) { |
CPU->arch.vendor = VendorAMD; |
} |
146,7 → 149,9 |
/* |
* Check for Intel processor. |
*/ |
if (info.cpuid_ebx==INTEL_CPUID_EBX && info.cpuid_ecx==INTEL_CPUID_ECX && info.cpuid_edx==INTEL_CPUID_EDX) { |
if (info.cpuid_ebx == INTEL_CPUID_EBX && |
info.cpuid_ecx == INTEL_CPUID_ECX && |
info.cpuid_edx == INTEL_CPUID_EDX) { |
CPU->arch.vendor = VendorIntel; |
} |
160,8 → 165,8 |
void cpu_print_report(cpu_t* m) |
{ |
printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n", |
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping, |
m->frequency_mhz); |
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, |
m->arch.stepping, m->frequency_mhz); |
} |
/** @} |
/branches/network/kernel/arch/amd64/src/context.S |
---|
40,17 → 40,10 |
# |
context_save_arch: |
movq (%rsp), %rdx # the caller's return %eip |
# In %edi is passed 1st argument |
movq %rdx, OFFSET_PC(%rdi) |
movq %rsp, OFFSET_SP(%rdi) |
CONTEXT_SAVE_ARCH_CORE %rdi %rdx |
movq %rbx, OFFSET_RBX(%rdi) |
movq %rbp, OFFSET_RBP(%rdi) |
movq %r12, OFFSET_R12(%rdi) |
movq %r13, OFFSET_R13(%rdi) |
movq %r14, OFFSET_R14(%rdi) |
movq %r15, OFFSET_R15(%rdi) |
xorq %rax,%rax # context_save returns 1 |
incq %rax |
ret |
62,16 → 55,9 |
# pointed by the 1st argument. Returns 0 in EAX. |
# |
context_restore_arch: |
movq OFFSET_R15(%rdi), %r15 |
movq OFFSET_R14(%rdi), %r14 |
movq OFFSET_R13(%rdi), %r13 |
movq OFFSET_R12(%rdi), %r12 |
movq OFFSET_RBP(%rdi), %rbp |
movq OFFSET_RBX(%rdi), %rbx |
movq OFFSET_SP(%rdi), %rsp # ctx->sp -> %rsp |
CONTEXT_RESTORE_ARCH_CORE %rdi %rdx |
movq OFFSET_PC(%rdi), %rdx |
movq %rdx,(%rsp) |
xorq %rax,%rax # context_restore returns 0 |
/branches/network/kernel/arch/amd64/src/mm/page.c |
---|
82,7 → 82,7 |
void page_arch_init(void) |
{ |
uintptr_t cur; |
int i; |
unsigned int i; |
int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE; |
if (config.cpu_active == 1) { |
/branches/network/kernel/arch/sparc64/include/atomic.h |
---|
37,6 → 37,7 |
#include <arch/barrier.h> |
#include <arch/types.h> |
#include <preemption.h> |
/** Atomic add operation. |
* |
56,7 → 57,8 |
a = *((uint64_t *) x); |
b = a + i; |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), "+r" (b) : "r" (a)); |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), |
"+r" (b) : "r" (a)); |
} while (a != b); |
return a; |
97,7 → 99,8 |
uint64_t v = 1; |
volatile uintptr_t x = (uint64_t) &val->count; |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), "+r" (v) : "r" (0)); |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), |
"+r" (v) : "r" (0)); |
return v; |
} |
109,6 → 112,8 |
volatile uintptr_t x = (uint64_t) &val->count; |
preemption_disable(); |
asm volatile ( |
"0:\n" |
"casx %0, %3, %1\n" |
/branches/network/kernel/arch/sparc64/include/mm/page.h |
---|
53,11 → 53,6 |
#define MMU_PAGES_PER_PAGE (1 << (PAGE_WIDTH - MMU_PAGE_WIDTH)) |
/* |
* With 16K pages, there is only one page color. |
*/ |
#define PAGE_COLOR_BITS 0 /**< 14 - 14; 2^14 == 16K == alias boundary. */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/network/kernel/arch/sparc64/include/mm/tlb.h |
---|
160,7 → 160,7 |
static inline void mmu_primary_context_write(uint64_t v) |
{ |
asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v); |
flush(); |
flush_pipeline(); |
} |
/** Read MMU Secondary Context Register. |
179,7 → 179,7 |
static inline void mmu_secondary_context_write(uint64_t v) |
{ |
asi_u64_write(ASI_DMMU, VA_SECONDARY_CONTEXT_REG, v); |
flush(); |
flush_pipeline(); |
} |
/** Read IMMU TLB Data Access Register. |
209,7 → 209,7 |
reg.value = 0; |
reg.tlb_entry = entry; |
asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value); |
flush(); |
flush_pipeline(); |
} |
/** Read DMMU TLB Data Access Register. |
279,7 → 279,7 |
static inline void itlb_tag_access_write(uint64_t v) |
{ |
asi_u64_write(ASI_IMMU, VA_IMMU_TAG_ACCESS, v); |
flush(); |
flush_pipeline(); |
} |
/** Read IMMU TLB Tag Access Register. |
318,7 → 318,7 |
static inline void itlb_data_in_write(uint64_t v) |
{ |
asi_u64_write(ASI_ITLB_DATA_IN_REG, 0, v); |
flush(); |
flush_pipeline(); |
} |
/** Write DMMU TLB Data in Register. |
347,7 → 347,7 |
static inline void itlb_sfsr_write(uint64_t v) |
{ |
asi_u64_write(ASI_IMMU, VA_IMMU_SFSR, v); |
flush(); |
flush_pipeline(); |
} |
/** Read DTLB Synchronous Fault Status Register. |
400,7 → 400,7 |
asi_u64_write(ASI_IMMU_DEMAP, da.value, 0); /* da.value is the |
* address within the |
* ASI */ |
flush(); |
flush_pipeline(); |
} |
/** Perform DMMU TLB Demap Operation. |
/branches/network/kernel/arch/sparc64/include/mm/cache_spec.h |
---|
0,0 → 1,57 |
/* |
* 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 sparc64mm |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_sparc64_CACHE_SPEC_H_ |
#define KERN_sparc64_CACHE_SPEC_H_ |
/* |
* The following macros are valid for the following processors: |
* |
* UltraSPARC, UltraSPARC II, UltraSPARC IIi |
* |
* Should we support other UltraSPARC processors, we need to make sure that |
* the macros are defined correctly for them. |
*/ |
#define DCACHE_SIZE (16 * 1024) |
#define DCACHE_LINE_SIZE 32 |
#define ICACHE_SIZE (16 * 1024) |
#define ICACHE_WAYS 2 |
#define ICACHE_LINE_SIZE 32 |
#endif |
/** @} |
*/ |
/branches/network/kernel/arch/sparc64/include/barrier.h |
---|
57,8 → 57,11 |
#define write_barrier() \ |
asm volatile ("membar #StoreStore\n" ::: "memory") |
/** Flush Instruction Memory instruction. */ |
static inline void flush(void) |
#define flush(a) \ |
asm volatile ("flush %0\n" :: "r" ((a)) : "memory") |
/** Flush Instruction pipeline. */ |
static inline void flush_pipeline(void) |
{ |
/* |
* The FLUSH instruction takes address parameter. |
79,6 → 82,21 |
asm volatile ("membar #Sync\n"); |
} |
#define smc_coherence(a) \ |
{ \ |
write_barrier(); \ |
flush((a)); \ |
} |
#define FLUSH_INVAL_MIN 4 |
#define smc_coherence_block(a, l) \ |
{ \ |
unsigned long i; \ |
write_barrier(); \ |
for (i = 0; i < (l); i += FLUSH_INVAL_MIN) \ |
flush((void *)(a) + i); \ |
} |
#endif |
/** @} |
/branches/network/kernel/arch/sparc64/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/network/kernel/arch/sparc64/include/asm.h |
---|
37,6 → 37,7 |
#include <arch/arch.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <align.h> |
#include <arch/register.h> |
#include <config.h> |
/branches/network/kernel/arch/sparc64/include/cpu.h |
---|
36,6 → 36,7 |
#define KERN_sparc64_CPU_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#include <arch/register.h> |
#include <arch/asm.h> |
/branches/network/kernel/arch/sparc64/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_sparc64_TYPES_H_ |
#define KERN_sparc64_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,13 → 57,31 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
/**< Formats for uintptr_t, size_t, count_t and index_t */ |
#define PRIp "llx" |
#define PRIs "llu" |
#define PRIc "llu" |
#define PRIi "llu" |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */ |
#define PRId8 "d" |
#define PRId16 "d" |
#define PRId32 "d" |
#define PRId64 "lld" |
#define PRIdn "lld" |
#define PRIu8 "u" |
#define PRIu16 "u" |
#define PRIu32 "u" |
#define PRIu64 "llu" |
#define PRIun "llu" |
#define PRIx8 "x" |
#define PRIx16 "x" |
#define PRIx32 "x" |
#define PRIx64 "llx" |
#define PRIxn "llx" |
typedef uint8_t asi_t; |
#endif |
/branches/network/kernel/arch/sparc64/include/context_offset.h |
---|
48,4 → 48,60 |
#define OFFSET_L6 0x80 |
#define OFFSET_L7 0x88 |
#ifndef KERNEL |
# define OFFSET_TP 0x90 |
#endif |
#ifdef __ASM__ |
.macro CONTEXT_SAVE_ARCH_CORE ctx:req |
stx %sp, [\ctx + OFFSET_SP] |
stx %o7, [\ctx + OFFSET_PC] |
stx %i0, [\ctx + OFFSET_I0] |
stx %i1, [\ctx + OFFSET_I1] |
stx %i2, [\ctx + OFFSET_I2] |
stx %i3, [\ctx + OFFSET_I3] |
stx %i4, [\ctx + OFFSET_I4] |
stx %i5, [\ctx + OFFSET_I5] |
stx %fp, [\ctx + OFFSET_FP] |
stx %i7, [\ctx + OFFSET_I7] |
stx %l0, [\ctx + OFFSET_L0] |
stx %l1, [\ctx + OFFSET_L1] |
stx %l2, [\ctx + OFFSET_L2] |
stx %l3, [\ctx + OFFSET_L3] |
stx %l4, [\ctx + OFFSET_L4] |
stx %l5, [\ctx + OFFSET_L5] |
stx %l6, [\ctx + OFFSET_L6] |
stx %l7, [\ctx + OFFSET_L7] |
#ifndef KERNEL |
stx %g7, [\ctx + OFFSET_TP] |
#endif |
.endm |
.macro CONTEXT_RESTORE_ARCH_CORE ctx:req |
ldx [\ctx + OFFSET_SP], %sp |
ldx [\ctx + OFFSET_PC], %o7 |
ldx [\ctx + OFFSET_I0], %i0 |
ldx [\ctx + OFFSET_I1], %i1 |
ldx [\ctx + OFFSET_I2], %i2 |
ldx [\ctx + OFFSET_I3], %i3 |
ldx [\ctx + OFFSET_I4], %i4 |
ldx [\ctx + OFFSET_I5], %i5 |
ldx [\ctx + OFFSET_FP], %fp |
ldx [\ctx + OFFSET_I7], %i7 |
ldx [\ctx + OFFSET_L0], %l0 |
ldx [\ctx + OFFSET_L1], %l1 |
ldx [\ctx + OFFSET_L2], %l2 |
ldx [\ctx + OFFSET_L3], %l3 |
ldx [\ctx + OFFSET_L4], %l4 |
ldx [\ctx + OFFSET_L5], %l5 |
ldx [\ctx + OFFSET_L6], %l6 |
ldx [\ctx + OFFSET_L7], %l7 |
#ifndef KERNEL |
ldx [\ctx + OFFSET_TP], %g7 |
#endif |
.endm |
#endif /* __ASM__ */ |
#endif |
/branches/network/kernel/arch/sparc64/include/byteorder.h |
---|
35,14 → 35,8 |
#ifndef KERN_sparc64_BYTEORDER_H_ |
#define KERN_sparc64_BYTEORDER_H_ |
#include <byteorder.h> |
#define ARCH_IS_BIG_ENDIAN |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#endif |
/** @} |
/branches/network/kernel/arch/sparc64/Makefile.inc |
---|
29,11 → 29,15 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-sparc |
BFD_ARCH = sparc |
BFD = binary |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/sparc64 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64 |
GCC_CFLAGS += -m64 -mcpu=ultrasparc |
SUNCC_CFLAGS += -m64 -xarch=sparc -xregs=appl,no%float |
/branches/network/kernel/arch/sparc64/src/asm.S |
---|
41,6 → 41,7 |
*/ |
.global memcpy |
memcpy: |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
59,7 → 60,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
93,7 → 94,7 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
/* |
* Almost the same as memcpy() except the loads are from userspace. |
100,6 → 101,7 |
*/ |
.global memcpy_from_uspace |
memcpy_from_uspace: |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
118,7 → 120,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
152,7 → 154,7 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
/* |
* Almost the same as memcpy() except the stores are to userspace. |
159,6 → 161,7 |
*/ |
.global memcpy_to_uspace |
memcpy_to_uspace: |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
177,7 → 180,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
211,7 → 214,7 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
274,6 → 277,8 |
wrpr %g0, 0, %cleanwin ! avoid information leak |
mov %i2, %o0 ! uarg |
xor %o1, %o1, %o1 ! %o1 is defined to hold pcb_ptr |
! set it to 0 |
clr %i2 |
clr %i3 |
/branches/network/kernel/arch/sparc64/src/mm/cache.S |
---|
27,10 → 27,8 |
*/ |
#include <arch/arch.h> |
#include <arch/mm/cache_spec.h> |
#define DCACHE_SIZE (16 * 1024) |
#define DCACHE_LINE_SIZE 32 |
#define DCACHE_TAG_SHIFT 2 |
.register %g2, #scratch |
/branches/network/kernel/arch/sparc64/src/mm/as.c |
---|
76,7 → 76,7 |
as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT * |
sizeof(tsb_entry_t)); |
memsetb((uintptr_t) as->arch.itsb, |
memsetb(as->arch.itsb, |
(ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0); |
#endif |
return 0; |
/branches/network/kernel/arch/sparc64/src/mm/tlb.c |
---|
490,7 → 490,7 |
*/ |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
{ |
int i; |
unsigned int i; |
tlb_context_reg_t pc_save, ctx; |
/* switch to nucleus because we are mapped by the primary context */ |
/branches/network/kernel/arch/sparc64/src/mm/frame.c |
---|
48,7 → 48,7 |
*/ |
void frame_arch_init(void) |
{ |
int i; |
unsigned int i; |
pfn_t confdata; |
if (config.cpu_active == 1) { |
/branches/network/kernel/arch/sparc64/src/mm/page.c |
---|
66,7 → 66,7 |
} else { |
#ifdef CONFIG_SMP |
int i; |
unsigned int i; |
/* |
* Copy locked DTLB entries from the BSP. |
98,7 → 98,7 |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
unsigned int order; |
int i; |
unsigned int i; |
ASSERT(config.cpu_active == 1); |
/branches/network/kernel/arch/sparc64/src/smp/smp.c |
---|
99,7 → 99,7 |
waking_up_mid = mid; |
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) |
printf("%s: waiting for processor (mid = %d) timed out\n", |
printf("%s: waiting for processor (mid = %" PRIu32 ") timed out\n", |
__func__, mid); |
} |
} |
/branches/network/kernel/arch/sparc64/src/smp/ipi.c |
---|
116,7 → 116,7 |
*/ |
void ipi_broadcast_arch(int ipi) |
{ |
int i; |
unsigned int i; |
void (* func)(void); |
/branches/network/kernel/arch/sparc64/src/trap/exception.c |
---|
45,9 → 45,9 |
void dump_istate(istate_t *istate) |
{ |
printf("TSTATE=%#llx\n", istate->tstate); |
printf("TPC=%#llx (%s)\n", istate->tpc, get_symtab_entry(istate->tpc)); |
printf("TNPC=%#llx (%s)\n", istate->tnpc, get_symtab_entry(istate->tnpc)); |
printf("TSTATE=%#" PRIx64 "\n", istate->tstate); |
printf("TPC=%#" PRIx64 " (%s)\n", istate->tpc, get_symtab_entry(istate->tpc)); |
printf("TNPC=%#" PRIx64 " (%s)\n", istate->tnpc, get_symtab_entry(istate->tnpc)); |
} |
/** Handle instruction_access_exception. (0x8) */ |
/branches/network/kernel/arch/sparc64/src/trap/interrupt.c |
---|
97,8 → 97,8 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (intrcv=%#llx, " |
"data0=%#llx)\n", CPU->id, intrcv, data0); |
printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64 |
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0); |
#endif |
} |
/branches/network/kernel/arch/sparc64/src/context.S |
---|
36,55 → 36,15 |
* functions. |
*/ |
#include <arch/context_offset.h> |
.text |
.global context_save_arch |
.global context_restore_arch |
.macro CONTEXT_STORE r |
stx %sp, [\r + OFFSET_SP] |
stx %o7, [\r + OFFSET_PC] |
stx %i0, [\r + OFFSET_I0] |
stx %i1, [\r + OFFSET_I1] |
stx %i2, [\r + OFFSET_I2] |
stx %i3, [\r + OFFSET_I3] |
stx %i4, [\r + OFFSET_I4] |
stx %i5, [\r + OFFSET_I5] |
stx %fp, [\r + OFFSET_FP] |
stx %i7, [\r + OFFSET_I7] |
stx %l0, [\r + OFFSET_L0] |
stx %l1, [\r + OFFSET_L1] |
stx %l2, [\r + OFFSET_L2] |
stx %l3, [\r + OFFSET_L3] |
stx %l4, [\r + OFFSET_L4] |
stx %l5, [\r + OFFSET_L5] |
stx %l6, [\r + OFFSET_L6] |
stx %l7, [\r + OFFSET_L7] |
.endm |
.macro CONTEXT_LOAD r |
ldx [\r + OFFSET_SP], %sp |
ldx [\r + OFFSET_PC], %o7 |
ldx [\r + OFFSET_I0], %i0 |
ldx [\r + OFFSET_I1], %i1 |
ldx [\r + OFFSET_I2], %i2 |
ldx [\r + OFFSET_I3], %i3 |
ldx [\r + OFFSET_I4], %i4 |
ldx [\r + OFFSET_I5], %i5 |
ldx [\r + OFFSET_FP], %fp |
ldx [\r + OFFSET_I7], %i7 |
ldx [\r + OFFSET_L0], %l0 |
ldx [\r + OFFSET_L1], %l1 |
ldx [\r + OFFSET_L2], %l2 |
ldx [\r + OFFSET_L3], %l3 |
ldx [\r + OFFSET_L4], %l4 |
ldx [\r + OFFSET_L5], %l5 |
ldx [\r + OFFSET_L6], %l6 |
ldx [\r + OFFSET_L7], %l7 |
.endm |
context_save_arch: |
CONTEXT_STORE %o0 |
CONTEXT_SAVE_ARCH_CORE %o0 |
retl |
mov 1, %o0 ! context_save_arch returns 1 |
98,6 → 58,6 |
# |
flushw |
CONTEXT_LOAD %o0 |
CONTEXT_RESTORE_ARCH_CORE %o0 |
retl |
xor %o0, %o0, %o0 ! context_restore_arch returns 0 |
/branches/network/kernel/arch/ia64/Makefile.inc |
---|
29,10 → 29,14 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-little |
BFD_ARCH = ia64-elf64 |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ia64 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64 |
INIT0_ADDRESS = 0xe000000004404000 |
INIT0_SIZE = 0x100000 |
/branches/network/kernel/arch/ia64/src/asm.S |
---|
51,7 → 51,7 |
adds r14 = 7, in1 |
mov r2 = ar.lc |
mov r8 = in1 ;; |
mov r8 = in0 |
and r14 = -8, r14 ;; |
cmp.ne p6, p7 = r14, in1 |
(p7) br.cond.dpnt 3f ;; |
63,7 → 63,7 |
(p6) mov r17 = r0 ;; |
(p6) mov ar.lc = r14 |
1: |
add r14 = r16, r8 |
add r14 = r16, in1 |
add r15 = r16, in0 |
adds r17 = 1, r17 ;; |
ld1 r14 = [r14] |
72,7 → 72,6 |
br.cloop.sptk.few 1b ;; |
2: |
mov ar.lc = r2 |
mov ar.pfs = loc0 |
br.ret.sptk.many rp |
3: |
90,7 → 89,7 |
4: |
shladd r14 = r16, 3, r0 |
adds r16 = 1, r17 ;; |
add r15 = r8, r14 |
add r15 = in1, r14 |
add r14 = in0, r14 |
mov r17 = r16 ;; |
ld8 r15 = [r15] ;; |
104,7 → 103,7 |
cmp.eq p6, p7 = 0, r15 |
add in0 = r14, in0 |
adds r15 = -1, r15 |
add r17 = r14, r8 |
add r17 = r14, in1 |
(p6) br.cond.dpnt 2b ;; |
mov ar.lc = r15 |
6: |
116,7 → 115,6 |
st1 [r15] = r14 |
br.cloop.sptk.few 6b ;; |
mov ar.lc = r2 |
mov ar.pfs = loc0 |
br.ret.sptk.many rp |
163,6 → 161,9 |
xor r1 = r1, r1 |
/* r2 is defined to hold pcb_ptr - set it to 0 */ |
xor r2 = r2, r2 |
mov loc1 = cr.ifs |
movl loc2 = PFM_MASK ;; |
and loc1 = loc2, loc1 ;; |
/branches/network/kernel/arch/ia64/src/mm/vhpt.c |
---|
81,7 → 81,7 |
void vhpt_invalidate_all() |
{ |
memsetb((uintptr_t) vhpt_base, 1 << VHPT_WIDTH, 0); |
memsetb(vhpt_base, 1 << VHPT_WIDTH, 0); |
} |
void vhpt_invalidate_asid(asid_t asid) |
/branches/network/kernel/arch/ia64/src/mm/tlb.c |
---|
59,7 → 59,7 |
uintptr_t adr; |
uint32_t count1, count2, stride1, stride2; |
int i, j; |
unsigned int i, j; |
adr = PAL_PTCE_INFO_BASE(); |
count1 = PAL_PTCE_INFO_COUNT1(); |
/branches/network/kernel/arch/ia64/src/drivers/ega.c |
---|
71,7 → 71,7 |
/* |
* Clear the screen. |
*/ |
_memsetw((uintptr_t) videoram, SCREEN, 0x0720); |
_memsetw(videoram, SCREEN, 0x0720); |
chardev_initialize("ega_out", &ega_console, &ega_ops); |
stdout = &ega_console; |
102,7 → 102,7 |
return; |
memcpy((void *) videoram, (void *) (videoram + ROW * 2), (SCREEN - ROW) * 2); |
_memsetw((uintptr_t) (videoram + (SCREEN - ROW) * 2), ROW, 0x0720); |
_memsetw(videoram + (SCREEN - ROW) * 2, ROW, 0x0720); |
ega_cursor = ega_cursor - ROW; |
} |
/branches/network/kernel/arch/ia64/src/ia64.c |
---|
62,10 → 62,11 |
/* Setup usermode init tasks. */ |
//#ifdef I460GX |
int i; |
unsigned int i; |
init.cnt = bootinfo->taskmap.count; |
for(i=0;i<init.cnt;i++) |
{ |
for (i = 0; i < init.cnt; i++) { |
init.tasks[i].addr = ((unsigned long)bootinfo->taskmap.tasks[i].addr)|VRN_MASK; |
init.tasks[i].size = bootinfo->taskmap.tasks[i].size; |
} |
/branches/network/kernel/arch/ia64/include/mm/page.h |
---|
41,8 → 41,6 |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
/** Bit width of the TLB-locked portion of kernel address space. */ |
/branches/network/kernel/arch/ia64/include/barrier.h |
---|
45,9 → 45,33 |
#define read_barrier() memory_barrier() |
#define write_barrier() memory_barrier() |
#define srlz_i() asm volatile (";; srlz.i ;;\n" ::: "memory") |
#define srlz_d() asm volatile (";; srlz.d\n" ::: "memory") |
#define srlz_i() \ |
asm volatile (";; srlz.i ;;\n" ::: "memory") |
#define srlz_d() \ |
asm volatile (";; srlz.d\n" ::: "memory") |
#define fc_i(a) \ |
asm volatile ("fc.i %0\n" :: "r" ((a)) : "memory") |
#define sync_i() \ |
asm volatile (";; sync.i\n" ::: "memory") |
#define smc_coherence(a) \ |
{ \ |
fc_i((a)); \ |
sync_i(); \ |
srlz_i(); \ |
} |
#define FC_INVAL_MIN 32 |
#define smc_coherence_block(a, l) \ |
{ \ |
unsigned long i; \ |
for (i = 0; i < (l); i += FC_INVAL_MIN) \ |
fc_i((void *)(a) + i); \ |
sync_i(); \ |
srlz_i(); \ |
} |
#endif |
/** @} |
/branches/network/kernel/arch/ia64/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/network/kernel/arch/ia64/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ia64_TYPES_H_ |
#define KERN_ia64_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
69,14 → 65,29 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
#define PRIp "lx" /**< Format for uintptr_t. */ |
#define PRIs "lu" /**< Format for size_t. */ |
#define PRIc "lu" /**< Format for count_t. */ |
#define PRIi "lu" /**< Format for index_t. */ |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "d" /**< Format for int32_t. */ |
#define PRId64 "ld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "lu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "lx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
#endif |
/** @} |
/branches/network/kernel/arch/ia64/include/byteorder.h |
---|
35,15 → 35,9 |
#ifndef KERN_ia64_BYTEORDER_H_ |
#define KERN_ia64_BYTEORDER_H_ |
#include <byteorder.h> |
/* IA-64 is little-endian */ |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define ARCH_IS_LITTLE_ENDIAN |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#endif |
/** @} |
/branches/network/kernel/arch/arm32/Makefile.inc |
---|
29,17 → 29,21 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-littlearm |
BFD_ARCH = arm |
BFD = binary |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = /usr/local/arm |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm |
KERNEL_LOAD_ADDRESS = 0x80200000 |
ifeq ($(MACHINE), gxemul_testarm) |
# ifeq ($(MACHINE), gxemul_testarm) |
DMACHINE = MACHINE_GXEMUL_TESTARM |
endif |
# endif |
ATSIGN = % |
90,7 → 94,7 |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/mm/page_fault.c |
ifeq ($(MACHINE), gxemul_testarm) |
# ifeq ($(MACHINE), gxemul_testarm) |
ARCH_SOURCES += arch/$(ARCH)/src/drivers/gxemul.c |
endif |
# endif |
/branches/network/kernel/arch/arm32/src/asm.S |
---|
45,7 → 45,8 |
add r3, r1, #3 |
bic r3, r3, #3 |
cmp r1, r3 |
stmdb sp!, {r4, lr} |
stmdb sp!, {r4, r5, lr} |
mov r5, r0 /* save dst */ |
beq 4f |
1: |
cmp r2, #0 |
58,8 → 59,8 |
cmp ip, r2 |
bne 2b |
3: |
mov r0, r1 |
ldmia sp!, {r4, pc} |
mov r0, r5 |
ldmia sp!, {r4, r5, pc} |
4: |
add r3, r0, #3 |
bic r3, r3, #3 |
95,4 → 96,4 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
mov r0, #0 |
ldmia sp!, {r4, pc} |
ldmia sp!, {r4, r5, pc} |
/branches/network/kernel/arch/arm32/src/userspace.c |
---|
70,8 → 70,11 |
/* set first parameter */ |
ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg; |
/* %r1 is defined to hold pcb_ptr - set it to 0 */ |
ustate.r1 = 0; |
/* clear other registers */ |
ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 = |
ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 = |
ustate.r6 = ustate.r7 = ustate.r8 = ustate.r9 = ustate.r10 = |
ustate.r11 = ustate.r12 = ustate.lr = 0; |
/branches/network/kernel/arch/arm32/src/exception.c |
---|
40,6 → 40,7 |
#include <interrupt.h> |
#include <arch/machine.h> |
#include <arch/mm/page_fault.h> |
#include <arch/barrier.h> |
#include <print.h> |
#include <syscall/syscall.h> |
219,6 → 220,7 |
/* make it LDR instruction and store at exception vector */ |
*vector = handler_address_ptr | LDR_OPCODE; |
smc_coherence(*vector); |
/* store handler's address */ |
*(vector + EXC_VECTORS) = handler_addr; |
226,31 → 228,31 |
} |
/** Low-level Reset Exception handler. */ |
static void reset_exception_entry() |
static void reset_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_RESET); |
} |
/** Low-level Software Interrupt Exception handler. */ |
static void swi_exception_entry() |
static void swi_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_SWI); |
} |
/** Low-level Undefined Instruction Exception handler. */ |
static void undef_instr_exception_entry() |
static void undef_instr_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_UNDEF_INSTR); |
} |
/** Low-level Fast Interrupt Exception handler. */ |
static void fiq_exception_entry() |
static void fiq_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_FIQ); |
} |
/** Low-level Prefetch Abort Exception handler. */ |
static void prefetch_abort_exception_entry() |
static void prefetch_abort_exception_entry(void) |
{ |
asm("sub lr, lr, #4"); |
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT); |
257,7 → 259,7 |
} |
/** Low-level Data Abort Exception handler. */ |
static void data_abort_exception_entry() |
static void data_abort_exception_entry(void) |
{ |
asm("sub lr, lr, #8"); |
PROCESS_EXCEPTION(EXC_DATA_ABORT); |
269,7 → 271,7 |
* because of possible occurence of nested interrupt exception, which |
* would overwrite (and thus spoil) stack pointer. |
*/ |
static void irq_exception_entry() |
static void irq_exception_entry(void) |
{ |
asm("sub lr, lr, #4"); |
setup_stack_and_save_regs(); |
/branches/network/kernel/arch/arm32/src/mm/page_fault.c |
---|
40,6 → 40,7 |
#include <genarch/mm/page_pt.h> |
#include <arch.h> |
#include <interrupt.h> |
#include <print.h> |
/** Returns value stored in fault status register. |
* |
173,7 → 174,8 |
*/ |
void data_abort(int exc_no, istate_t *istate) |
{ |
fault_status_t fsr = read_fault_status_register(); |
fault_status_t fsr __attribute__ ((unused)) = |
read_fault_status_register(); |
uintptr_t badvaddr = read_fault_address_register(); |
pf_access_t access = get_memory_access_type(istate->pc, badvaddr); |
/branches/network/kernel/arch/arm32/src/arm32.c |
---|
55,7 → 55,7 |
/** Performs arm32 specific initialization before main_bsp() is called. */ |
void arch_pre_main(void) |
{ |
int i; |
unsigned int i; |
init.cnt = bootinfo.cnt; |
/branches/network/kernel/arch/arm32/src/debug/print.c |
---|
56,10 → 56,10 |
*/ |
static int debug_write(const char *str, size_t count, void *unused) |
{ |
int i; |
for (i = 0; i < count; ++i) { |
unsigned int i; |
for (i = 0; i < count; ++i) |
putc(str[i]); |
} |
return i; |
} |
/branches/network/kernel/arch/arm32/src/cpu/cpu.c |
---|
56,7 → 56,7 |
}; |
/** Length of the #imp_data array */ |
static int imp_data_length = sizeof(imp_data) / sizeof(char *); |
static unsigned int imp_data_length = sizeof(imp_data) / sizeof(char *); |
/** Architecture names */ |
static char *arch_data[] = { |
71,7 → 71,7 |
}; |
/** Length of the #arch_data array */ |
static int arch_data_length = sizeof(arch_data) / sizeof(char *); |
static unsigned int arch_data_length = sizeof(arch_data) / sizeof(char *); |
/** Retrieves processor identification from CP15 register 0. |
/branches/network/kernel/arch/arm32/include/mm/page.h |
---|
43,8 → 43,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifndef __ASM__ |
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000) |
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000) |
/branches/network/kernel/arch/arm32/include/barrier.h |
---|
46,6 → 46,9 |
#define read_barrier() asm volatile ("" ::: "memory") |
#define write_barrier() asm volatile ("" ::: "memory") |
#define smc_coherence(a) |
#define smc_coherence_block(a, l) |
#endif |
/** @} |
/branches/network/kernel/arch/arm32/include/memstr.h |
---|
38,10 → 38,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/network/kernel/arch/arm32/include/types.h |
---|
42,10 → 42,6 |
# define ATTRIBUTE_PACKED |
#endif |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed long int32_t; |
68,15 → 64,29 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
#define PRIp "x" /**< Format for uintptr_t. */ |
#define PRIs "u" /**< Format for size_t. */ |
#define PRIc "u" /**< Format for count_t. */ |
#define PRIi "u" /**< Format for index_t. */ |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "d" /**< Format for int32_t. */ |
#define PRId64 "lld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "llu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
/** Page table entry. |
* |
* We have different structs for level 0 and level 1 page table entries. |
/branches/network/kernel/arch/arm32/include/byteorder.h |
---|
36,24 → 36,10 |
#ifndef KERN_arm32_BYTEORDER_H_ |
#define KERN_arm32_BYTEORDER_H_ |
#include <byteorder.h> |
#ifdef BIG_ENDIAN |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define ARCH_IS_BIG_ENDIAN |
#else |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
#endif |
/branches/network/kernel/arch/ppc32/Makefile.inc |
---|
29,11 → 29,15 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-powerpc |
BFD_ARCH = powerpc:common |
BFD = binary |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc |
GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32 |
AFLAGS += -a32 |
/branches/network/kernel/arch/ppc32/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/network/kernel/arch/ppc32/include/mm/tlb.h |
---|
36,6 → 36,8 |
#define KERN_ppc32_TLB_H_ |
#include <arch/interrupt.h> |
#include <arch/types.h> |
#include <typedefs.h> |
typedef struct { |
unsigned v : 1; /**< Valid */ |
/branches/network/kernel/arch/ppc32/include/barrier.h |
---|
42,6 → 42,43 |
#define read_barrier() asm volatile ("sync" ::: "memory") |
#define write_barrier() asm volatile ("eieio" ::: "memory") |
/* |
* The IMB sequence used here is valid for all possible cache models |
* on uniprocessor. SMP might require a different sequence. |
* See PowerPC Programming Environment for 32-Bit Microprocessors, |
* chapter 5.1.5.2 |
*/ |
static inline void smc_coherence(void *addr) |
{ |
asm volatile ( |
"dcbst 0, %0\n" |
"sync\n" |
"icbi 0, %0\n" |
"isync\n" |
:: "r" (addr) |
); |
} |
#define COHERENCE_INVAL_MIN 4 |
static inline void smc_coherence_block(void *addr, unsigned long len) |
{ |
unsigned long i; |
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) { |
asm volatile ("dcbst 0, %0\n" :: "r" (addr + i)); |
} |
asm volatile ("sync"); |
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) { |
asm volatile ("icbi 0, %0\n" :: "r" (addr + i)); |
} |
asm volatile ("isync"); |
} |
#endif |
/** @} |
/branches/network/kernel/arch/ppc32/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/network/kernel/arch/ppc32/include/exception.h |
---|
82,6 → 82,7 |
{ |
istate->pc = retaddr; |
} |
/** Return true if exception happened while in userspace */ |
#include <panic.h> |
static inline int istate_from_uspace(istate_t *istate) |
89,6 → 90,7 |
panic("istate_from_uspace not yet implemented"); |
return 0; |
} |
static inline unative_t istate_get_pc(istate_t *istate) |
{ |
return istate->pc; |
/branches/network/kernel/arch/ppc32/include/boot/boot.h |
---|
38,7 → 38,7 |
#define BOOT_OFFSET 0x8000 |
/* Temporary stack size for boot process */ |
#define TEMP_STACK_SIZE 0x100 |
#define TEMP_STACK_SIZE 0x1000 |
#define TASKMAP_MAX_RECORDS 32 |
#define MEMMAP_MAX_RECORDS 32 |
/branches/network/kernel/arch/ppc32/include/drivers/cuda.h |
---|
36,6 → 36,7 |
#define KERN_ppc32_CUDA_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
extern void cuda_init(devno_t devno, uintptr_t base, size_t size); |
extern int cuda_get_scancode(void); |
/branches/network/kernel/arch/ppc32/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ppc32_TYPES_H_ |
#define KERN_ppc32_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,14 → 57,31 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
/**< Formats for uintptr_t, size_t, count_t and index_t */ |
#define PRIp "x" |
#define PRIs "u" |
#define PRIc "u" |
#define PRIi "u" |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */ |
#define PRId8 "d" |
#define PRId16 "d" |
#define PRId32 "d" |
#define PRId64 "lld" |
#define PRIdn "d" |
#define PRIu8 "u" |
#define PRIu16 "u" |
#define PRIu32 "u" |
#define PRIu64 "llu" |
#define PRIun "u" |
#define PRIx8 "x" |
#define PRIx16 "x" |
#define PRIx32 "x" |
#define PRIx64 "llx" |
#define PRIxn "x" |
/** Page Table Entry. */ |
typedef struct { |
unsigned p : 1; /**< Present bit. */ |
/branches/network/kernel/arch/ppc32/include/context_offset.h |
---|
73,4 → 73,59 |
#define OFFSET_FR31 0x88 |
#define OFFSET_FPSCR 0x90 |
#ifdef __ASM__ |
# include <arch/asm/regname.h> |
# ctx: address of the structure with saved context |
.macro CONTEXT_SAVE_ARCH_CORE ctx:req |
stw sp, OFFSET_SP(\ctx) |
stw r2, OFFSET_R2(\ctx) |
stw r13, OFFSET_R13(\ctx) |
stw r14, OFFSET_R14(\ctx) |
stw r15, OFFSET_R15(\ctx) |
stw r16, OFFSET_R16(\ctx) |
stw r17, OFFSET_R17(\ctx) |
stw r18, OFFSET_R18(\ctx) |
stw r19, OFFSET_R19(\ctx) |
stw r20, OFFSET_R20(\ctx) |
stw r21, OFFSET_R21(\ctx) |
stw r22, OFFSET_R22(\ctx) |
stw r23, OFFSET_R23(\ctx) |
stw r24, OFFSET_R24(\ctx) |
stw r25, OFFSET_R25(\ctx) |
stw r26, OFFSET_R26(\ctx) |
stw r27, OFFSET_R27(\ctx) |
stw r28, OFFSET_R28(\ctx) |
stw r29, OFFSET_R29(\ctx) |
stw r30, OFFSET_R30(\ctx) |
stw r31, OFFSET_R31(\ctx) |
.endm |
# ctx: address of the structure with saved context |
.macro CONTEXT_RESTORE_ARCH_CORE ctx:req |
lwz sp, OFFSET_SP(\ctx) |
lwz r2, OFFSET_R2(\ctx) |
lwz r13, OFFSET_R13(\ctx) |
lwz r14, OFFSET_R14(\ctx) |
lwz r15, OFFSET_R15(\ctx) |
lwz r16, OFFSET_R16(\ctx) |
lwz r17, OFFSET_R17(\ctx) |
lwz r18, OFFSET_R18(\ctx) |
lwz r19, OFFSET_R19(\ctx) |
lwz r20, OFFSET_R20(\ctx) |
lwz r21, OFFSET_R21(\ctx) |
lwz r22, OFFSET_R22(\ctx) |
lwz r23, OFFSET_R23(\ctx) |
lwz r24, OFFSET_R24(\ctx) |
lwz r25, OFFSET_R25(\ctx) |
lwz r26, OFFSET_R26(\ctx) |
lwz r27, OFFSET_R27(\ctx) |
lwz r28, OFFSET_R28(\ctx) |
lwz r29, OFFSET_R29(\ctx) |
lwz r30, OFFSET_R30(\ctx) |
lwz r31, OFFSET_R31(\ctx) |
.endm |
#endif /* __ASM__ */ |
#endif |
/branches/network/kernel/arch/ppc32/include/byteorder.h |
---|
35,14 → 35,8 |
#ifndef KERN_ppc32_BYTEORDER_H_ |
#define KERN_ppc32_BYTEORDER_H_ |
#include <byteorder.h> |
#define ARCH_IS_BIG_ENDIAN |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#endif |
/** @} |
/branches/network/kernel/arch/ppc32/src/asm.S |
---|
66,6 → 66,10 |
mr sp, r4 |
# %r3 is defined to hold pcb_ptr - set it to 0 |
xor r3, r3, r3 |
# jump to userspace |
rfi |
199,48 → 203,8 |
rfi |
memsetb: |
rlwimi r5, r5, 8, 16, 23 |
rlwimi r5, r5, 16, 0, 15 |
b _memsetb |
addi r14, r3, -4 |
cmplwi 0, r4, 4 |
blt 7f |
stwu r5, 4(r14) |
beqlr |
andi. r15, r14, 3 |
add r4, r15, r4 |
subf r14, r15, r14 |
srwi r15, r4, 2 |
mtctr r15 |
bdz 6f |
1: |
stwu r5, 4(r14) |
bdnz 1b |
6: |
andi. r4, r4, 3 |
7: |
cmpwi 0, r4, 0 |
beqlr |
mtctr r4 |
addi r6, r6, 3 |
8: |
stbu r5, 1(r14) |
bdnz 8b |
blr |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
308,4 → 272,6 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
b memcpy_from_uspace_failover_address |
# return zero, failure |
xor r3, r3, r3 |
blr |
/branches/network/kernel/arch/ppc32/src/mm/tlb.c |
---|
52,11 → 52,14 |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
* @param pfrc Pointer to variable where as_page_fault() return code |
* will be stored. |
* @return PTE on success, NULL otherwise. |
* |
*/ |
static pte_t *find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) |
static pte_t * |
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, |
istate_t *istate, int *pfrc) |
{ |
/* |
* Check if the mapping exists in page tables. |
114,7 → 117,8 |
s = get_symtab_entry(istate->lr); |
if (s) |
sym2 = s; |
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); |
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, |
istate->pc, symbol, sym2); |
} |
147,7 → 151,8 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) { |
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && |
(phte[base + i].api == api))) { |
found = true; |
break; |
} |
160,7 → 165,9 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) { |
if ((!phte[base2 + i].v) || |
((phte[base2 + i].vsid == vsid) && |
(phte[base2 + i].api == api))) { |
found = true; |
base = base2; |
h = 1; |
214,7 → 221,9 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) { |
if ((!phte_physical[base + i].v) || |
((phte_physical[base + i].vsid == vsid) && |
(phte_physical[base + i].api == api))) { |
found = true; |
break; |
} |
227,7 → 236,9 |
/* Find unused or colliding |
PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) { |
if ((!phte_physical[base2 + i].v) || |
((phte_physical[base2 + i].vsid == vsid) && |
(phte_physical[base2 + i].api == api))) { |
found = true; |
base = base2; |
h = 1; |
284,7 → 295,8 |
page_table_lock(as, lock); |
pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
pte = find_mapping_and_check(as, lock, badvaddr, |
PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
case AS_PF_FAULT: |
373,7 → 385,8 |
uint32_t i; |
for (i = 0; i < 8192; i++) { |
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && (phte[i].vsid < ((asid << 4) + 16))) |
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && |
(phte[i].vsid < ((asid << 4) + 16))) |
phte[i].v = 0; |
} |
tlb_invalidate_all(); |
407,7 → 420,11 |
} \ |
} else \ |
length = 0; \ |
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, lower & 0xffff0000, length, mask, ((upper >> 1) & 1) ? " supervisor" : "", (upper & 1) ? " user" : ""); |
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \ |
sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \ |
lower & 0xffff0000, length, mask, \ |
((upper >> 1) & 1) ? " supervisor" : "", \ |
(upper & 1) ? " user" : ""); |
void tlb_print(void) |
421,7 → 438,10 |
: "=r" (vsid) |
: "r" (sr << 28) |
); |
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, ((vsid >> 30) & 1) ? " supervisor" : "", ((vsid >> 29) & 1) ? " user" : ""); |
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, |
sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, |
((vsid >> 30) & 1) ? " supervisor" : "", |
((vsid >> 29) & 1) ? " user" : ""); |
} |
uint32_t upper; |
/branches/network/kernel/arch/ppc32/src/mm/page.c |
---|
47,13 → 47,16 |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > |
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%" PRIs " bytes)", |
physaddr, size) |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), |
physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); |
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); |
/branches/network/kernel/arch/ppc32/src/interrupt.c |
---|
80,7 → 80,7 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
/branches/network/kernel/arch/ppc32/src/context.S |
---|
26,7 → 26,6 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#include <arch/asm/regname.h> |
#include <arch/context_offset.h> |
.text |
34,56 → 33,8 |
.global context_save_arch |
.global context_restore_arch |
.macro CONTEXT_STORE r |
stw sp, OFFSET_SP(\r) |
stw r2, OFFSET_R2(\r) |
stw r13, OFFSET_R13(\r) |
stw r14, OFFSET_R14(\r) |
stw r15, OFFSET_R15(\r) |
stw r16, OFFSET_R16(\r) |
stw r17, OFFSET_R17(\r) |
stw r18, OFFSET_R18(\r) |
stw r19, OFFSET_R19(\r) |
stw r20, OFFSET_R20(\r) |
stw r21, OFFSET_R21(\r) |
stw r22, OFFSET_R22(\r) |
stw r23, OFFSET_R23(\r) |
stw r24, OFFSET_R24(\r) |
stw r25, OFFSET_R25(\r) |
stw r26, OFFSET_R26(\r) |
stw r27, OFFSET_R27(\r) |
stw r28, OFFSET_R28(\r) |
stw r29, OFFSET_R29(\r) |
stw r30, OFFSET_R30(\r) |
stw r31, OFFSET_R31(\r) |
.endm |
.macro CONTEXT_LOAD r |
lwz sp, OFFSET_SP(\r) |
lwz r2, OFFSET_R2(\r) |
lwz r13, OFFSET_R13(\r) |
lwz r14, OFFSET_R14(\r) |
lwz r15, OFFSET_R15(\r) |
lwz r16, OFFSET_R16(\r) |
lwz r17, OFFSET_R17(\r) |
lwz r18, OFFSET_R18(\r) |
lwz r19, OFFSET_R19(\r) |
lwz r20, OFFSET_R20(\r) |
lwz r21, OFFSET_R21(\r) |
lwz r22, OFFSET_R22(\r) |
lwz r23, OFFSET_R23(\r) |
lwz r24, OFFSET_R24(\r) |
lwz r25, OFFSET_R25(\r) |
lwz r26, OFFSET_R26(\r) |
lwz r27, OFFSET_R27(\r) |
lwz r28, OFFSET_R28(\r) |
lwz r29, OFFSET_R29(\r) |
lwz r30, OFFSET_R30(\r) |
lwz r31, OFFSET_R31(\r) |
.endm |
context_save_arch: |
CONTEXT_STORE r3 |
CONTEXT_SAVE_ARCH_CORE r3 |
mflr r4 |
stw r4, OFFSET_PC(r3) |
96,7 → 47,7 |
blr |
context_restore_arch: |
CONTEXT_LOAD r3 |
CONTEXT_RESTORE_ARCH_CORE r3 |
lwz r4, OFFSET_CR(r3) |
mtcr r4 |
/branches/network/kernel/arch/ia32xen/Makefile.inc |
---|
29,11 → 29,15 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-i386 |
BFD_ARCH = i386 |
BFD = elf32-i386 |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/i686 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686 |
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__ |
111,7 → 115,7 |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/context.s \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/debug/panic.s \ |
arch/$(ARCH)/src/delay.s \ |
arch/$(ARCH)/src/asm.S \ |
/branches/network/kernel/arch/ia32xen/src/context.s |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/network/kernel/arch/ia32xen/src/asm.S |
---|
67,7 → 67,7 |
* @param MEMCPY_SRC(%esp) Source address. |
* @param MEMCPY_SIZE(%esp) Size. |
* |
* @return MEMCPY_SRC(%esp) on success and 0 on failure. |
* @return MEMCPY_DST(%esp) on success and 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
92,7 → 92,7 |
0: |
movl %edx, %edi |
movl %eax, %esi |
movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */ |
movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */ |
ret |
/* |
/branches/network/kernel/arch/ia32xen/src/userspace.c |
---|
68,6 → 68,10 |
"pushl %3\n" |
"pushl %4\n" |
"movl %5, %%eax\n" |
/* %ebx is defined to hold pcb_ptr - set it to 0 */ |
"xorl %%ebx, %%ebx\n" |
"iret\n" |
: |
: "i" (selector(UDATA_DES) | PL_USER), |
/branches/network/kernel/arch/ia32xen/src/ia32xen.c |
---|
69,7 → 69,7 |
void arch_pre_main(void) |
{ |
pte_t pte; |
memsetb((uintptr_t) &pte, sizeof(pte), 0); |
memsetb(&pte, sizeof(pte), 0); |
pte.present = 1; |
pte.writeable = 1; |
103,7 → 103,7 |
uintptr_t tpa = PFN2ADDR(meminfo.start + meminfo.reserved); |
uintptr_t tva = PA2KA(tpa); |
memsetb(tva, PAGE_SIZE, 0); |
memsetb((void *) tva, PAGE_SIZE, 0); |
pte_t *tptl3 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(start_info.ptl0, PTL0_INDEX(tva))); |
SET_FRAME_ADDRESS(tptl3, PTL3_INDEX(tva), 0); |
/branches/network/kernel/arch/ia32xen/src/pm.c |
---|
98,7 → 98,7 |
void tss_initialize(tss_t *t) |
{ |
memsetb((uintptr_t) t, sizeof(struct tss), 0); |
memsetb(t, sizeof(struct tss), 0); |
} |
static void trap(void) |
/branches/network/kernel/arch/ia32xen/src/smp/smp.c |
---|
98,7 → 98,7 |
*/ |
void kmp(void *arg) |
{ |
int i; |
unsigned int i; |
ASSERT(ops != NULL); |
146,7 → 146,7 |
panic("couldn't allocate memory for GDT\n"); |
memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(struct descriptor)); |
memsetb((uintptr_t)(&gdt_new[TSS_DES]), sizeof(struct descriptor), 0); |
memsetb(&gdt_new[TSS_DES], sizeof(struct descriptor), 0); |
gdtr.base = (uintptr_t) gdt_new; |
if (l_apic_send_init_ipi(ops->cpu_apic_id(i))) { |
/branches/network/kernel/arch/ia32xen/src/smp/mps.c |
---|
77,11 → 77,11 |
struct __io_intr_entry *io_intr_entries = NULL; |
struct __l_intr_entry *l_intr_entries = NULL; |
int processor_entry_cnt = 0; |
int bus_entry_cnt = 0; |
int io_apic_entry_cnt = 0; |
int io_intr_entry_cnt = 0; |
int l_intr_entry_cnt = 0; |
unsigned int processor_entry_cnt = 0; |
unsigned int bus_entry_cnt = 0; |
unsigned int io_apic_entry_cnt = 0; |
unsigned int io_intr_entry_cnt = 0; |
unsigned int l_intr_entry_cnt = 0; |
waitq_t ap_completion_wq; |
417,7 → 417,7 |
int mps_irq_to_pin(unsigned int irq) |
{ |
int i; |
unsigned int i; |
for (i = 0; i < io_intr_entry_cnt; i++) { |
if (io_intr_entries[i].src_bus_irq == irq && io_intr_entries[i].intr_type == 0) |
/branches/network/kernel/arch/ia32xen/src/context.S |
---|
0,0 → 1,0 |
link ../../ia32/src/context.S |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/network/kernel/arch/ia32xen/src/mm/tlb.c |
---|
65,7 → 65,7 |
*/ |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
{ |
int i; |
unsigned int i; |
for (i = 0; i < cnt; i++) |
invlpg(page + i * PAGE_SIZE); |
/branches/network/kernel/arch/ia32xen/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/network/kernel/arch/ia32xen/include/types.h |
---|
61,14 → 61,6 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/** Page Table Entry. */ |
typedef struct { |
unsigned present : 1; |
/branches/network/kernel/arch/ia32xen/include/context_offset.h |
---|
0,0 → 1,0 |
link ../../ia32/include/context_offset.h |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/network/kernel/arch/ppc64/Makefile.inc |
---|
29,11 → 29,15 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-powerpc |
BFD_ARCH = powerpc:common64 |
BFD = binary |
TARGET = ppc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc64 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64 |
GCC_CFLAGS += -mcpu=powerpc64 -msoft-float -m64 |
AFLAGS += -a64 |
/branches/network/kernel/arch/ppc64/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/network/kernel/arch/ppc64/include/barrier.h |
---|
42,6 → 42,9 |
#define read_barrier() asm volatile ("sync" ::: "memory") |
#define write_barrier() asm volatile ("eieio" ::: "memory") |
#define smc_coherence(a) |
#define smc_coherence_block(a, l) |
#endif |
/** @} |
/branches/network/kernel/arch/ppc64/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/network/kernel/arch/ppc64/include/exception.h |
---|
82,6 → 82,7 |
{ |
istate->pc = retaddr; |
} |
/** Return true if exception happened while in userspace */ |
#include <panic.h> |
static inline int istate_from_uspace(istate_t *istate) |
89,6 → 90,7 |
panic("istate_from_uspace not yet implemented"); |
return 0; |
} |
static inline unative_t istate_get_pc(istate_t *istate) |
{ |
return istate->pc; |
/branches/network/kernel/arch/ppc64/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ppc64_TYPES_H_ |
#define KERN_ppc64_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,14 → 57,6 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/** Page Table Entry. */ |
typedef struct { |
unsigned p : 1; /**< Present bit. */ |
/branches/network/kernel/arch/ppc64/include/context_offset.h |
---|
73,4 → 73,60 |
#define OFFSET_FR31 0x88 |
#define OFFSET_FPSCR 0x90 |
#ifdef __ASM__ |
# include <arch/asm/regname.h> |
# ctx: address of the structure with saved context |
.macro CONTEXT_SAVE_ARCH_CORE ctx:req |
stw sp, OFFSET_SP(\ctx) |
stw r2, OFFSET_R2(\ctx) |
stw r13, OFFSET_R13(\ctx) |
stw r14, OFFSET_R14(\ctx) |
stw r15, OFFSET_R15(\ctx) |
stw r16, OFFSET_R16(\ctx) |
stw r17, OFFSET_R17(\ctx) |
stw r18, OFFSET_R18(\ctx) |
stw r19, OFFSET_R19(\ctx) |
stw r20, OFFSET_R20(\ctx) |
stw r21, OFFSET_R21(\ctx) |
stw r22, OFFSET_R22(\ctx) |
stw r23, OFFSET_R23(\ctx) |
stw r24, OFFSET_R24(\ctx) |
stw r25, OFFSET_R25(\ctx) |
stw r26, OFFSET_R26(\ctx) |
stw r27, OFFSET_R27(\ctx) |
stw r28, OFFSET_R28(\ctx) |
stw r29, OFFSET_R29(\ctx) |
stw r30, OFFSET_R30(\ctx) |
stw r31, OFFSET_R31(\ctx) |
.endm |
# ctx: address of the structure with saved context |
.macro CONTEXT_RESTORE_ARCH_CORE ctx:req |
lwz sp, OFFSET_SP(\ctx) |
lwz r2, OFFSET_R2(\ctx) |
lwz r13, OFFSET_R13(\ctx) |
lwz r14, OFFSET_R14(\ctx) |
lwz r15, OFFSET_R15(\ctx) |
lwz r16, OFFSET_R16(\ctx) |
lwz r17, OFFSET_R17(\ctx) |
lwz r18, OFFSET_R18(\ctx) |
lwz r19, OFFSET_R19(\ctx) |
lwz r20, OFFSET_R20(\ctx) |
lwz r21, OFFSET_R21(\ctx) |
lwz r22, OFFSET_R22(\ctx) |
lwz r23, OFFSET_R23(\ctx) |
lwz r24, OFFSET_R24(\ctx) |
lwz r25, OFFSET_R25(\ctx) |
lwz r26, OFFSET_R26(\ctx) |
lwz r27, OFFSET_R27(\ctx) |
lwz r28, OFFSET_R28(\ctx) |
lwz r29, OFFSET_R29(\ctx) |
lwz r30, OFFSET_R30(\ctx) |
lwz r31, OFFSET_R31(\ctx) |
.endm |
#endif /* __ASM__ */ |
#endif |
/branches/network/kernel/arch/ppc64/include/byteorder.h |
---|
35,14 → 35,8 |
#ifndef KERN_ppc64_BYTEORDER_H_ |
#define KERN_ppc64_BYTEORDER_H_ |
#include <byteorder.h> |
#define ARCH_IS_BIG_ENDIAN |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#endif |
/** @} |
/branches/network/kernel/arch/ppc64/src/asm.S |
---|
66,6 → 66,10 |
mr sp, r4 |
# %r3 is defined to hold pcb_ptr - set it to 0 |
xor r3, r3, r3 |
# jump to userspace |
rfi |
/branches/network/kernel/arch/ppc64/src/mm/page.c |
---|
252,7 → 252,7 |
void pht_init(void) |
{ |
memsetb((uintptr_t) phte, 1 << PHT_BITS, 0); |
memsetb(phte, 1 << PHT_BITS, 0); |
} |
289,7 → 289,7 |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
panic("Unable to map physical memory %p (%" PRIs " bytes)", physaddr, size) |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
/branches/network/kernel/arch/ppc64/src/cpu/cpu.c |
---|
53,7 → 53,7 |
void cpu_print_report(cpu_t *m) |
{ |
printf("cpu%d: version=%d, revision=%d\n", m->id, m->arch.version, m->arch.revision); |
printf("cpu%u: version=%d, revision=%d\n", m->id, m->arch.version, m->arch.revision); |
} |
/** @} |
/branches/network/kernel/arch/ppc64/src/interrupt.c |
---|
80,7 → 80,7 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
/branches/network/kernel/arch/ppc64/src/context.S |
---|
34,56 → 34,8 |
.global context_save_arch |
.global context_restore_arch |
.macro CONTEXT_STORE r |
stw sp, OFFSET_SP(\r) |
stw r2, OFFSET_R2(\r) |
stw r13, OFFSET_R13(\r) |
stw r14, OFFSET_R14(\r) |
stw r15, OFFSET_R15(\r) |
stw r16, OFFSET_R16(\r) |
stw r17, OFFSET_R17(\r) |
stw r18, OFFSET_R18(\r) |
stw r19, OFFSET_R19(\r) |
stw r20, OFFSET_R20(\r) |
stw r21, OFFSET_R21(\r) |
stw r22, OFFSET_R22(\r) |
stw r23, OFFSET_R23(\r) |
stw r24, OFFSET_R24(\r) |
stw r25, OFFSET_R25(\r) |
stw r26, OFFSET_R26(\r) |
stw r27, OFFSET_R27(\r) |
stw r28, OFFSET_R28(\r) |
stw r29, OFFSET_R29(\r) |
stw r30, OFFSET_R30(\r) |
stw r31, OFFSET_R31(\r) |
.endm |
.macro CONTEXT_LOAD r |
lwz sp, OFFSET_SP(\r) |
lwz r2, OFFSET_R2(\r) |
lwz r13, OFFSET_R13(\r) |
lwz r14, OFFSET_R14(\r) |
lwz r15, OFFSET_R15(\r) |
lwz r16, OFFSET_R16(\r) |
lwz r17, OFFSET_R17(\r) |
lwz r18, OFFSET_R18(\r) |
lwz r19, OFFSET_R19(\r) |
lwz r20, OFFSET_R20(\r) |
lwz r21, OFFSET_R21(\r) |
lwz r22, OFFSET_R22(\r) |
lwz r23, OFFSET_R23(\r) |
lwz r24, OFFSET_R24(\r) |
lwz r25, OFFSET_R25(\r) |
lwz r26, OFFSET_R26(\r) |
lwz r27, OFFSET_R27(\r) |
lwz r28, OFFSET_R28(\r) |
lwz r29, OFFSET_R29(\r) |
lwz r30, OFFSET_R30(\r) |
lwz r31, OFFSET_R31(\r) |
.endm |
context_save_arch: |
CONTEXT_STORE r3 |
CONTEXT_SAVE_ARCH_CORE r3 |
mflr r4 |
stw r4, OFFSET_PC(r3) |
96,7 → 48,7 |
blr |
context_restore_arch: |
CONTEXT_LOAD r3 |
CONTEXT_RESTORE_ARCH_CORE r3 |
lwz r4, OFFSET_CR(r3) |
mtcr r4 |
/branches/network/kernel/arch/mips32/Makefile.inc |
---|
29,9 → 29,13 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_ARCH = mips |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = /usr/local/mipsel |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel |
KERNEL_LOAD_ADDRESS = 0x80100000 |
INIT_ADDRESS = 0x81000000 |
56,20 → 60,6 |
## Accepted MACHINEs |
# |
ifeq ($(MACHINE),indy) |
# GCC 4.0.1 compiled for mipsEL has problems compiling in |
# BigEndian mode with the swl/swr/lwl/lwr instructions. |
# We have to compile it with mips-sgi-irix5 to get it right. |
BFD_NAME = elf32-bigmips |
BFD = ecoff-bigmips --impure |
TARGET = mips-sgi-irix5 |
TOOLCHAIN_DIR = /usr/local/mips/bin |
KERNEL_LOAD_ADDRESS = 0x88002000 |
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -march=r4600 |
INIT_ADDRESS = 0 |
INIT_SIZE = 0 |
endif |
ifeq ($(MACHINE),lgxemul) |
BFD_NAME = elf32-tradlittlemips |
BFD = binary |
79,7 → 69,7 |
BFD_NAME = elf32-bigmips |
BFD = ecoff-bigmips |
TARGET = mips-sgi-irix5 |
TOOLCHAIN_DIR = /usr/local/mips/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin |
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -mips3 |
INIT_ADDRESS = 0x81800000 |
endif |
123,7 → 113,6 |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/fpu_context.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/drivers/arc.c \ |
arch/$(ARCH)/src/drivers/msim.c \ |
arch/$(ARCH)/src/drivers/serial.c \ |
arch/$(ARCH)/src/smp/order.c |
/branches/network/kernel/arch/mips32/src/asm.S |
---|
71,6 → 71,7 |
and $v0,$v0,$v1 |
beq $a1,$v0,3f |
move $t0,$a0 |
move $t2,$a0 # save dst |
0: |
beq $a2,$zero,2f |
86,7 → 87,7 |
2: |
jr $ra |
move $v0,$a1 |
move $v0,$t2 |
3: |
addiu $v0,$a0,3 |
126,7 → 127,7 |
sb $a0,0($v1) |
jr $ra |
move $v0,$a1 |
move $v0,$t2 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
/branches/network/kernel/arch/mips32/src/mm/frame.c |
---|
32,27 → 32,238 |
/** @file |
*/ |
#include <macros.h> |
#include <arch/mm/frame.h> |
#include <arch/mm/tlb.h> |
#include <interrupt.h> |
#include <mm/frame.h> |
#include <mm/asid.h> |
#include <config.h> |
#include <arch/drivers/arc.h> |
#include <arch/drivers/msim.h> |
#include <arch/drivers/serial.h> |
#include <print.h> |
#define ZERO_PAGE_MASK TLB_PAGE_MASK_256K |
#define ZERO_FRAMES 2048 |
#define ZERO_PAGE_WIDTH 18 /* 256K */ |
#define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH) |
#define ZERO_PAGE_ASID ASID_INVALID |
#define ZERO_PAGE_TLBI 0 |
#define ZERO_PAGE_ADDR 0 |
#define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1) |
#define ZERO_PAGE_VALUE (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET]) |
#define ZERO_PAGE_VALUE_KSEG1(frame) (((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET]) |
#define MAX_REGIONS 32 |
typedef struct { |
pfn_t start; |
pfn_t count; |
} phys_region_t; |
static count_t phys_regions_count = 0; |
static phys_region_t phys_regions[MAX_REGIONS]; |
/** Check whether frame is available |
* |
* Returns true if given frame is generally available for use. |
* Returns false if given frame is used for physical memory |
* mapped devices and cannot be used. |
* |
*/ |
static bool frame_available(pfn_t frame) |
{ |
#if MACHINE == msim |
/* MSIM device (dprinter) */ |
if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH)) |
return false; |
/* MSIM device (dkeyboard) */ |
if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH)) |
return false; |
#endif |
#if MACHINE == simics |
/* Simics device (serial line) */ |
if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH)) |
return false; |
#endif |
#if (MACHINE == lgxemul) || (MACHINE == bgxemul) |
/* gxemul devices */ |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
0x10000000, MB2SIZE(256))) |
return false; |
#endif |
return true; |
} |
/** Check whether frame is safe to write |
* |
* Returns true if given frame is safe for read/write test. |
* Returns false if given frame should not be touched. |
* |
*/ |
static bool frame_safe(pfn_t frame) |
{ |
/* Kernel structures */ |
if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base)) |
return false; |
/* Kernel */ |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
KA2PA(config.base), config.kernel_size)) |
return false; |
/* Kernel stack */ |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
KA2PA(config.stack_base), config.stack_size)) |
return false; |
/* Init tasks */ |
bool safe = true; |
count_t i; |
for (i = 0; i < init.cnt; i++) |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
KA2PA(init.tasks[i].addr), init.tasks[i].size)) { |
safe = false; |
break; |
} |
return safe; |
} |
static void frame_add_region(pfn_t start_frame, pfn_t end_frame) |
{ |
if (end_frame > start_frame) { |
/* Convert 1M frames to 16K frames */ |
pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH); |
pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH); |
/* Interrupt vector frame is blacklisted */ |
pfn_t conf_frame; |
if (first == 0) |
conf_frame = 1; |
else |
conf_frame = first; |
zone_create(first, count, conf_frame, 0); |
if (phys_regions_count < MAX_REGIONS) { |
phys_regions[phys_regions_count].start = first; |
phys_regions[phys_regions_count].count = count; |
phys_regions_count++; |
} |
} |
} |
/** Create memory zones |
* |
* If ARC is known, read information from ARC, otherwise |
* assume some defaults. |
* - blacklist first FRAME because there is an exception vector |
* Walk through available 256 KB chunks of physical |
* memory and create zones. |
* |
* Note: It is assumed that the TLB is not yet being |
* used in any way, thus there is no interference. |
* |
*/ |
void frame_arch_init(void) |
{ |
if (!arc_frame_init()) { |
zone_create(0, ADDR2PFN(CONFIG_MEMORY_SIZE), 1, 0); |
/* |
* Blacklist interrupt vector |
*/ |
ipl_t ipl = interrupts_disable(); |
/* Clear and initialize TLB */ |
cp0_pagemask_write(ZERO_PAGE_MASK); |
cp0_entry_lo0_write(0); |
cp0_entry_lo1_write(0); |
cp0_entry_hi_write(0); |
count_t i; |
for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
cp0_index_write(i); |
tlbwi(); |
} |
pfn_t start_frame = 0; |
pfn_t frame; |
bool avail = true; |
/* Walk through all 1 MB frames */ |
for (frame = 0; frame < ZERO_FRAMES; frame++) { |
if (!frame_available(frame)) |
avail = false; |
else { |
if (frame_safe(frame)) { |
entry_lo_t lo0; |
entry_lo_t lo1; |
entry_hi_t hi; |
tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12)); |
tlb_prepare_entry_lo(&lo1, false, false, false, false, 0); |
tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR); |
cp0_pagemask_write(ZERO_PAGE_MASK); |
cp0_entry_lo0_write(lo0.value); |
cp0_entry_lo1_write(lo1.value); |
cp0_entry_hi_write(hi.value); |
cp0_index_write(ZERO_PAGE_TLBI); |
tlbwi(); |
ZERO_PAGE_VALUE = 0; |
if (ZERO_PAGE_VALUE != 0) |
avail = false; |
else { |
ZERO_PAGE_VALUE = 0xdeadbeef; |
if (ZERO_PAGE_VALUE != 0xdeadbeef) |
avail = false; |
#if (MACHINE == lgxemul) || (MACHINE == bgxemul) |
else { |
ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd; |
if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd) |
avail = false; |
} |
#endif |
} |
} |
} |
if (!avail) { |
frame_add_region(start_frame, frame); |
start_frame = frame + 1; |
avail = true; |
} |
} |
frame_add_region(start_frame, frame); |
/* Blacklist interrupt vector frame */ |
frame_mark_unavailable(0, 1); |
/* Cleanup */ |
cp0_pagemask_write(ZERO_PAGE_MASK); |
cp0_entry_lo0_write(0); |
cp0_entry_lo1_write(0); |
cp0_entry_hi_write(0); |
cp0_index_write(ZERO_PAGE_TLBI); |
tlbwi(); |
interrupts_restore(ipl); |
} |
void physmem_print(void) |
{ |
printf("Base Size\n"); |
printf("---------- ----------\n"); |
count_t i; |
for (i = 0; i < phys_regions_count; i++) { |
printf("%#010x %10u\n", |
PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count)); |
} |
} |
/** @} |
*/ |
/branches/network/kernel/arch/mips32/src/mm/tlb.c |
---|
53,9 → 53,6 |
static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc); |
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn); |
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr); |
/** Initialize TLB |
* |
* Initialize TLB. |
77,7 → 74,6 |
tlbwi(); |
} |
/* |
* The kernel is going to make use of some wired |
* entries (e.g. mapping kernel stacks in kseg3). |
131,8 → 127,8 |
*/ |
pte->a = 1; |
prepare_entry_hi(&hi, asid, badvaddr); |
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
tlb_prepare_entry_hi(&hi, asid, badvaddr); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
/* |
* New entry is to be inserted into TLB |
178,7 → 174,7 |
* Locate the faulting entry in TLB. |
*/ |
hi.value = cp0_entry_hi_read(); |
prepare_entry_hi(&hi, hi.asid, badvaddr); |
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr); |
cp0_entry_hi_write(hi.value); |
tlbp(); |
index.value = cp0_index_read(); |
221,7 → 217,7 |
*/ |
pte->a = 1; |
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
/* |
* The entry is to be updated in TLB. |
262,7 → 258,7 |
* Locate the faulting entry in TLB. |
*/ |
hi.value = cp0_entry_hi_read(); |
prepare_entry_hi(&hi, hi.asid, badvaddr); |
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr); |
cp0_entry_hi_write(hi.value); |
tlbp(); |
index.value = cp0_index_read(); |
312,7 → 308,7 |
pte->a = 1; |
pte->d = 1; |
prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn); |
/* |
* The entry is to be updated in TLB. |
445,7 → 441,7 |
} |
} |
void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn) |
void tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn) |
{ |
lo->value = 0; |
lo->g = g; |
455,7 → 451,7 |
lo->pfn = pfn; |
} |
void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr) |
void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr) |
{ |
hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2); |
hi->asid = asid; |
572,7 → 568,7 |
*/ |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
{ |
int i; |
unsigned int i; |
ipl_t ipl; |
entry_lo_t lo0, lo1; |
entry_hi_t hi, hi_save; |
585,7 → 581,7 |
for (i = 0; i < cnt+1; i+=2) { |
hi.value = 0; |
prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE); |
tlb_prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE); |
cp0_entry_hi_write(hi.value); |
tlbp(); |
/branches/network/kernel/arch/mips32/src/drivers/arc.c |
---|
File deleted |
/branches/network/kernel/arch/mips32/src/drivers/msim.c |
---|
39,12 → 39,9 |
#include <arch/cp0.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <ddi/ddi.h> |
/** Address of devices. */ |
#define MSIM_VIDEORAM 0xB0000000 |
#define MSIM_KBD_ADDRESS 0xB0000000 |
#define MSIM_KBD_IRQ 2 |
static parea_t msim_parea; |
static chardev_t console; |
static irq_t msim_irq; |
158,6 → 155,16 |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, MSIM_KBD_IRQ); |
sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS); |
msim_parea.pbase = KA2PA(MSIM_VIDEORAM); |
msim_parea.vbase = MSIM_VIDEORAM; |
msim_parea.frames = 1; |
msim_parea.cacheable = false; |
ddi_parea_register(&msim_parea); |
sysinfo_set_item_val("fb", NULL, true); |
sysinfo_set_item_val("fb.kind", NULL, 3); |
sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(MSIM_VIDEORAM)); |
} |
/** @} |
/branches/network/kernel/arch/mips32/src/console.c |
---|
34,19 → 34,16 |
#include <console/console.h> |
#include <arch/console.h> |
#include <arch/drivers/arc.h> |
#include <arch/drivers/serial.h> |
#include <arch/drivers/msim.h> |
void console_init(devno_t devno) |
{ |
if (!arc_console()) { |
if (serial_init()) |
serial_console(devno); |
else |
msim_console(devno); |
} |
} |
/** Acquire console back for kernel |
* |
/branches/network/kernel/arch/mips32/src/mips32.c |
---|
48,8 → 48,8 |
#include <sysinfo/sysinfo.h> |
#include <arch/interrupt.h> |
#include <arch/drivers/arc.h> |
#include <console/chardev.h> |
#include <arch/barrier.h> |
#include <arch/debugger.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
96,18 → 96,21 |
/* Initialize dispatch table */ |
exception_init(); |
arc_init(); |
/* Copy the exception vectors to the right places */ |
memcpy(TLB_EXC, (char *) tlb_refill_entry, EXCEPTION_JUMP_SIZE); |
smc_coherence_block(TLB_EXC, EXCEPTION_JUMP_SIZE); |
memcpy(NORM_EXC, (char *) exception_entry, EXCEPTION_JUMP_SIZE); |
smc_coherence_block(NORM_EXC, EXCEPTION_JUMP_SIZE); |
memcpy(CACHE_EXC, (char *) cache_error_entry, EXCEPTION_JUMP_SIZE); |
smc_coherence_block(CACHE_EXC, EXCEPTION_JUMP_SIZE); |
/* |
* Switch to BEV normal level so that exception vectors point to the kernel. |
* Clear the error level. |
* Switch to BEV normal level so that exception vectors point to the |
* kernel. Clear the error level. |
*/ |
cp0_status_write(cp0_status_read() & ~(cp0_status_bev_bootstrap_bit|cp0_status_erl_error_bit)); |
cp0_status_write(cp0_status_read() & |
~(cp0_status_bev_bootstrap_bit | cp0_status_erl_error_bit)); |
/* |
* Mask all interrupts |
122,7 → 125,8 |
interrupt_init(); |
console_init(device_assign_devno()); |
#ifdef CONFIG_FB |
fb_init(0x12000000, 640, 480, 1920, VISUAL_RGB_8_8_8); // gxemul framebuffer |
/* GXemul framebuffer */ |
fb_init(0x12000000, 640, 480, 1920, VISUAL_RGB_8_8_8); |
#endif |
sysinfo_set_item_val("machine." STRING(MACHINE), NULL, 1); |
} |
149,7 → 153,8 |
(uintptr_t) kernel_uarg->uspace_uarg, |
(uintptr_t) kernel_uarg->uspace_entry); |
while (1); |
while (1) |
; |
} |
/** Perform mips32 specific tasks needed before the new task is run. */ |
160,7 → 165,8 |
/** Perform mips32 specific tasks needed before the new thread is scheduled. */ |
void before_thread_runs_arch(void) |
{ |
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA]; |
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - |
SP_DELTA]; |
} |
void after_thread_ran_arch(void) |
179,10 → 185,10 |
void arch_reboot(void) |
{ |
if (!arc_reboot()) |
___halt(); |
while (1); |
while (1) |
; |
} |
/** @} |
/branches/network/kernel/arch/mips32/src/interrupt.c |
---|
38,7 → 38,6 |
#include <arch.h> |
#include <arch/cp0.h> |
#include <time/clock.h> |
#include <arch/drivers/arc.h> |
#include <ipc/sysipc.h> |
#include <ddi/device.h> |
/branches/network/kernel/arch/mips32/src/start.S |
---|
350,4 → 350,6 |
add $sp, $a0, 0 |
add $v0, $a1, 0 |
add $t9, $a2, 0 # Set up correct entry into PIC code |
xor $a0, $a0, $a0 # $a0 is defined to hold pcb_ptr |
# set it to 0 |
eret |
/branches/network/kernel/arch/mips32/src/debugger.c |
---|
33,6 → 33,7 |
*/ |
#include <arch/debugger.h> |
#include <arch/barrier.h> |
#include <memstr.h> |
#include <console/kconsole.h> |
#include <console/cmd.h> |
72,7 → 73,8 |
}; |
static cmd_info_t addbkpt_info = { |
.name = "addbkpt", |
.description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.", |
.description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch " |
"insts unsupported.", |
.func = cmd_add_breakpoint, |
.argc = 1, |
.argv = &add_argv |
84,7 → 86,8 |
}; |
static cmd_info_t addbkpte_info = { |
.name = "addbkpte", |
.description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).", |
.description = "addebkpte <&symbol> <&func> - new bkpoint. Call " |
"func(or Nothing if 0).", |
.func = cmd_add_breakpoint, |
.argc = 2, |
.argv = adde_argv |
157,9 → 160,11 |
printf("Duplicate breakpoint %d.\n", i); |
spinlock_unlock(&bkpoints_lock); |
return 0; |
} else if (breakpoints[i].address == (uintptr_t)argv->intval + sizeof(unative_t) || \ |
breakpoints[i].address == (uintptr_t)argv->intval - sizeof(unative_t)) { |
printf("Adjacent breakpoints not supported, conflict with %d.\n", i); |
} else if (breakpoints[i].address == (uintptr_t)argv->intval + |
sizeof(unative_t) || breakpoints[i].address == |
(uintptr_t)argv->intval - sizeof(unative_t)) { |
printf("Adjacent breakpoints not supported, conflict " |
"with %d.\n", i); |
spinlock_unlock(&bkpoints_lock); |
return 0; |
} |
193,6 → 198,7 |
/* Set breakpoint */ |
*((unative_t *)cur->address) = 0x0d; |
smc_coherence(cur->address); |
spinlock_unlock(&bkpoint_lock); |
interrupts_restore(ipl); |
200,8 → 206,6 |
return 1; |
} |
/** Remove breakpoint from table */ |
int cmd_del_breakpoint(cmd_arg_t *argv) |
{ |
208,7 → 212,7 |
bpinfo_t *cur; |
ipl_t ipl; |
if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) { |
if (argv->intval > BKPOINTS_MAX) { |
printf("Invalid breakpoint number.\n"); |
return 0; |
} |
229,7 → 233,9 |
return 0; |
} |
((uint32_t *)cur->address)[0] = cur->instruction; |
smc_coherence(((uint32_t *)cur->address)[0]); |
((uint32_t *)cur->address)[1] = cur->nextinstruction; |
smc_coherence(((uint32_t *)cur->address)[1]); |
cur->address = NULL; |
253,10 → 259,10 |
printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i, |
breakpoints[i].counter, breakpoints[i].address, |
((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : "false"), |
((breakpoints[i].flags & BKPOINT_ONESHOT) ? "true" : "false"), |
((breakpoints[i].flags & BKPOINT_FUNCCALL) ? "true" : "false"), |
symbol); |
((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : |
"false"), ((breakpoints[i].flags & BKPOINT_ONESHOT) |
? "true" : "false"), ((breakpoints[i].flags & |
BKPOINT_FUNCCALL) ? "true" : "false"), symbol); |
} |
return 1; |
} |
307,14 → 313,14 |
spinlock_lock(&bkpoint_lock); |
for (i=0; i<BKPOINTS_MAX; i++) { |
/* Normal breakpoint */ |
if (fireaddr == breakpoints[i].address \ |
&& !(breakpoints[i].flags & BKPOINT_REINST)) { |
if (fireaddr == breakpoints[i].address && |
!(breakpoints[i].flags & BKPOINT_REINST)) { |
cur = &breakpoints[i]; |
break; |
} |
/* Reinst only breakpoint */ |
if ((breakpoints[i].flags & BKPOINT_REINST) \ |
&& (fireaddr ==breakpoints[i].address+sizeof(unative_t))) { |
if ((breakpoints[i].flags & BKPOINT_REINST) && |
(fireaddr == breakpoints[i].address + sizeof(unative_t))) { |
cur = &breakpoints[i]; |
break; |
} |
323,8 → 329,10 |
if (cur->flags & BKPOINT_REINST) { |
/* Set breakpoint on first instruction */ |
((uint32_t *)cur->address)[0] = 0x0d; |
smc_coherence(((uint32_t *)cur->address)[0]); |
/* Return back the second */ |
((uint32_t *)cur->address)[1] = cur->nextinstruction; |
smc_coherence(((uint32_t *)cur->address)[1]); |
cur->flags &= ~BKPOINT_REINST; |
spinlock_unlock(&bkpoint_lock); |
return; |
333,11 → 341,12 |
printf("Warning: breakpoint recursion\n"); |
if (!(cur->flags & BKPOINT_FUNCCALL)) |
printf("***Breakpoint %d: %p in %s.\n", i, |
fireaddr, get_symtab_entry(istate->epc)); |
printf("***Breakpoint %d: %p in %s.\n", i, fireaddr, |
get_symtab_entry(istate->epc)); |
/* Return first instruction back */ |
((uint32_t *)cur->address)[0] = cur->instruction; |
smc_coherence(cur->address); |
if (! (cur->flags & BKPOINT_ONESHOT)) { |
/* Set Breakpoint on next instruction */ |
/branches/network/kernel/arch/mips32/src/exception.c |
---|
161,7 → 161,7 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i); |
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, i); |
#endif |
} |
} |
/branches/network/kernel/arch/mips32/src/context.S |
---|
26,7 → 26,6 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#include <arch/asm/regname.h> |
#include <arch/context_offset.h> |
.text |
38,41 → 37,9 |
.global context_save_arch |
.global context_restore_arch |
.macro CONTEXT_STORE r |
sw $s0,OFFSET_S0(\r) |
sw $s1,OFFSET_S1(\r) |
sw $s2,OFFSET_S2(\r) |
sw $s3,OFFSET_S3(\r) |
sw $s4,OFFSET_S4(\r) |
sw $s5,OFFSET_S5(\r) |
sw $s6,OFFSET_S6(\r) |
sw $s7,OFFSET_S7(\r) |
sw $s8,OFFSET_S8(\r) |
sw $gp,OFFSET_GP(\r) |
sw $ra,OFFSET_PC(\r) |
sw $sp,OFFSET_SP(\r) |
.endm |
.macro CONTEXT_LOAD r |
lw $s0,OFFSET_S0(\r) |
lw $s1,OFFSET_S1(\r) |
lw $s2,OFFSET_S2(\r) |
lw $s3,OFFSET_S3(\r) |
lw $s4,OFFSET_S4(\r) |
lw $s5,OFFSET_S5(\r) |
lw $s6,OFFSET_S6(\r) |
lw $s7,OFFSET_S7(\r) |
lw $s8,OFFSET_S8(\r) |
lw $gp,OFFSET_GP(\r) |
lw $ra,OFFSET_PC(\r) |
lw $sp,OFFSET_SP(\r) |
.endm |
context_save_arch: |
CONTEXT_STORE $a0 |
CONTEXT_SAVE_ARCH_CORE $a0 |
# context_save returns 1 |
j $31 |
79,7 → 46,7 |
li $2, 1 |
context_restore_arch: |
CONTEXT_LOAD $a0 |
CONTEXT_RESTORE_ARCH_CORE $a0 |
# context_restore returns 0 |
j $31 |
/branches/network/kernel/arch/mips32/src/cpu/cpu.c |
---|
104,12 → 104,11 |
void cpu_print_report(cpu_t *m) |
{ |
struct data_t *data; |
int i; |
unsigned int i; |
if (m->arch.imp_num & 0x80) { |
/* Count records */ |
for (i=0;imp_data80[i].vendor;i++) |
; |
for (i = 0; imp_data80[i].vendor; i++); |
if ((m->arch.imp_num & 0x7f) >= i) { |
printf("imp=%d\n",m->arch.imp_num); |
return; |
116,8 → 115,7 |
} |
data = &imp_data80[m->arch.imp_num & 0x7f]; |
} else { |
for (i=0;imp_data[i].vendor;i++) |
; |
for (i = 0; imp_data[i].vendor; i++); |
if (m->arch.imp_num >= i) { |
printf("imp=%d\n",m->arch.imp_num); |
return; |
/branches/network/kernel/arch/mips32/include/drivers/arc.h |
---|
File deleted |
/branches/network/kernel/arch/mips32/include/drivers/serial.h |
---|
37,6 → 37,8 |
#include <console/chardev.h> |
#define SERIAL_ADDRESS 0x98000000 |
#define SERIAL_MAX 4 |
#define SERIAL_COM1 0x3f8 |
#define SERIAL_COM1_IRQ 4 |
43,16 → 45,19 |
#define SERIAL_COM2 0x2f8 |
#define SERIAL_COM2_IRQ 3 |
#define P_WRITEB(where,what) (*((volatile char *) (0xB8000000+where))=what) |
#define P_READB(where) (*((volatile char *)(0xB8000000+where))) |
#define P_WRITEB(where, what) (*((volatile char *) (SERIAL_ADDRESS + where)) = what) |
#define P_READB(where) (*((volatile char *) (SERIAL_ADDRESS + where))) |
#define SERIAL_READ(x) P_READB(x) |
#define SERIAL_WRITE(x,c) P_WRITEB(x,c) |
/* Interrupt enable register */ |
#define SERIAL_READ_IER(x) (P_READB((x) + 1)) |
#define SERIAL_WRITE_IER(x,c) (P_WRITEB((x)+1,c)) |
/* Interrupt identification register */ |
#define SERIAL_READ_IIR(x) (P_READB((x) + 2)) |
/* Line status register */ |
#define SERIAL_READ_LSR(x) (P_READB((x) + 5)) |
#define TRANSMIT_EMPTY_BIT 5 |
/branches/network/kernel/arch/mips32/include/drivers/msim.h |
---|
35,6 → 35,11 |
#ifndef KERN_mips32_MSIM_H_ |
#define KERN_mips32_MSIM_H_ |
/** Address of devices. */ |
#define MSIM_VIDEORAM 0x90000000 |
#define MSIM_KBD_ADDRESS 0x90000000 |
#define MSIM_KBD_IRQ 2 |
#include <console/chardev.h> |
void msim_console(devno_t devno); |
/branches/network/kernel/arch/mips32/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifndef __ASM__ |
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000) |
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000) |
/branches/network/kernel/arch/mips32/include/mm/tlb.h |
---|
35,6 → 35,9 |
#ifndef KERN_mips32_TLB_H_ |
#define KERN_mips32_TLB_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#include <arch/mm/asid.h> |
#include <arch/exception.h> |
#ifdef TLBCNT |
46,7 → 49,13 |
#define TLB_WIRED 1 |
#define TLB_KSTACK_WIRED_INDEX 0 |
#define TLB_PAGE_MASK_16K (0x3<<13) |
#define TLB_PAGE_MASK_4K (0x000 << 13) |
#define TLB_PAGE_MASK_16K (0x003 << 13) |
#define TLB_PAGE_MASK_64K (0x00f << 13) |
#define TLB_PAGE_MASK_256K (0x03f << 13) |
#define TLB_PAGE_MASK_1M (0x0ff << 13) |
#define TLB_PAGE_MASK_4M (0x3ff << 13) |
#define TLB_PAGE_MASK_16M (0xfff << 13) |
#define PAGE_UNCACHED 2 |
#define PAGE_CACHEABLE_EXC_WRITE 5 |
159,6 → 168,8 |
extern void tlb_invalid(istate_t *istate); |
extern void tlb_refill(istate_t *istate); |
extern void tlb_modified(istate_t *istate); |
extern void tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn); |
extern void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr); |
#endif |
/branches/network/kernel/arch/mips32/include/mm/as.h |
---|
38,7 → 38,7 |
#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH 0 |
#define KERNEL_ADDRESS_SPACE_START_ARCH (unsigned long) 0x80000000 |
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0xffffffff |
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0x9fffffff |
#define USER_ADDRESS_SPACE_START_ARCH (unsigned long) 0x00000000 |
#define USER_ADDRESS_SPACE_END_ARCH (unsigned long) 0x7fffffff |
/branches/network/kernel/arch/mips32/include/atomic.h |
---|
58,13 → 58,13 |
asm volatile ( |
"1:\n" |
" ll %0, %1\n" |
" addiu %0, %0, %3\n" /* same as addi, but never traps on overflow */ |
" addu %0, %0, %3\n" /* same as addi, but never traps on overflow */ |
" move %2, %0\n" |
" sc %0, %1\n" |
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */ |
" nop\n" |
: "=r" (tmp), "=m" (val->count), "=r" (v) |
: "i" (i), "i" (0) |
: "=&r" (tmp), "+m" (val->count), "=&r" (v) |
: "r" (i), "i" (0) |
); |
return v; |
/branches/network/kernel/arch/mips32/include/barrier.h |
---|
45,6 → 45,9 |
#define read_barrier() asm volatile ("" ::: "memory") |
#define write_barrier() asm volatile ("" ::: "memory") |
#define smc_coherence(a) |
#define smc_coherence_block(a, l) |
#endif |
/** @} |
/branches/network/kernel/arch/mips32/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/network/kernel/arch/mips32/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_mips32_TYPES_H_ |
#define KERN_mips32_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed long int32_t; |
61,14 → 57,29 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
#define PRIp "x" /**< Format for uintptr_t. */ |
#define PRIs "u" /**< Format for size_t. */ |
#define PRIc "u" /**< Format for count_t. */ |
#define PRIi "u" /**< Format for index_t. */ |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "ld" /**< Format for int32_t. */ |
#define PRId64 "lld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "llu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
/** Page Table Entry. */ |
typedef struct { |
unsigned g : 1; /**< Global bit. */ |
/branches/network/kernel/arch/mips32/include/byteorder.h |
---|
35,24 → 35,10 |
#ifndef KERN_mips32_BYTEORDER_H_ |
#define KERN_mips32_BYTEORDER_H_ |
#include <byteorder.h> |
#ifdef BIG_ENDIAN |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define ARCH_IS_BIG_ENDIAN |
#else |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
#endif |
/branches/network/kernel/arch/mips32/include/context_offset.h |
---|
42,6 → 42,24 |
#define OFFSET_S8 0x28 |
#define OFFSET_GP 0x2c |
#ifdef KERNEL |
# define OFFSET_IPL 0x30 |
#else |
# define OFFSET_TLS 0x30 |
# define OFFSET_F20 0x34 |
# define OFFSET_F21 0x38 |
# define OFFSET_F22 0x3c |
# define OFFSET_F23 0x40 |
# define OFFSET_F24 0x44 |
# define OFFSET_F25 0x48 |
# define OFFSET_F26 0x4c |
# define OFFSET_F27 0x50 |
# define OFFSET_F28 0x54 |
# define OFFSET_F29 0x58 |
# define OFFSET_F30 0x5c |
#endif /* KERNEL */ |
/* istate_t */ |
#define EOFFSET_AT 0x0 |
#define EOFFSET_V0 0x4 |
79,4 → 97,122 |
#define EOFFSET_K1 0x84 |
#define REGISTER_SPACE 136 |
#ifdef __ASM__ |
#include <arch/asm/regname.h> |
# ctx: address of the structure with saved context |
.macro CONTEXT_SAVE_ARCH_CORE ctx:req |
sw $s0,OFFSET_S0(\ctx) |
sw $s1,OFFSET_S1(\ctx) |
sw $s2,OFFSET_S2(\ctx) |
sw $s3,OFFSET_S3(\ctx) |
sw $s4,OFFSET_S4(\ctx) |
sw $s5,OFFSET_S5(\ctx) |
sw $s6,OFFSET_S6(\ctx) |
sw $s7,OFFSET_S7(\ctx) |
sw $s8,OFFSET_S8(\ctx) |
sw $gp,OFFSET_GP(\ctx) |
#ifndef KERNEL |
sw $k1,OFFSET_TLS(\ctx) |
# ifdef CONFIG_MIPS_FPU |
mfc1 $t0,$20 |
sw $t0, OFFSET_F20(\ctx) |
mfc1 $t0,$21 |
sw $t0, OFFSET_F21(\ctx) |
mfc1 $t0,$22 |
sw $t0, OFFSET_F22(\ctx) |
mfc1 $t0,$23 |
sw $t0, OFFSET_F23(\ctx) |
mfc1 $t0,$24 |
sw $t0, OFFSET_F24(\ctx) |
mfc1 $t0,$25 |
sw $t0, OFFSET_F25(\ctx) |
mfc1 $t0,$26 |
sw $t0, OFFSET_F26(\ctx) |
mfc1 $t0,$27 |
sw $t0, OFFSET_F27(\ctx) |
mfc1 $t0,$28 |
sw $t0, OFFSET_F28(\ctx) |
mfc1 $t0,$29 |
sw $t0, OFFSET_F29(\ctx) |
mfc1 $t0,$30 |
sw $t0, OFFSET_F30(\ctx) |
# endif /* CONFIG_MIPS_FPU */ |
#endif /* KERNEL */ |
sw $ra,OFFSET_PC(\ctx) |
sw $sp,OFFSET_SP(\ctx) |
.endm |
# ctx: address of the structure with saved context |
.macro CONTEXT_RESTORE_ARCH_CORE ctx:req |
lw $s0,OFFSET_S0(\ctx) |
lw $s1,OFFSET_S1(\ctx) |
lw $s2,OFFSET_S2(\ctx) |
lw $s3,OFFSET_S3(\ctx) |
lw $s4,OFFSET_S4(\ctx) |
lw $s5,OFFSET_S5(\ctx) |
lw $s6,OFFSET_S6(\ctx) |
lw $s7,OFFSET_S7(\ctx) |
lw $s8,OFFSET_S8(\ctx) |
lw $gp,OFFSET_GP(\ctx) |
#ifndef KERNEL |
lw $k1,OFFSET_TLS(\ctx) |
# ifdef CONFIG_MIPS_FPU |
lw $t0, OFFSET_F20(\ctx) |
mtc1 $t0,$20 |
lw $t0, OFFSET_F21(\ctx) |
mtc1 $t0,$21 |
lw $t0, OFFSET_F22(\ctx) |
mtc1 $t0,$22 |
lw $t0, OFFSET_F23(\ctx) |
mtc1 $t0,$23 |
lw $t0, OFFSET_F24(\ctx) |
mtc1 $t0,$24 |
lw $t0, OFFSET_F25(\ctx) |
mtc1 $t0,$25 |
lw $t0, OFFSET_F26(\ctx) |
mtc1 $t0,$26 |
lw $t0, OFFSET_F27(\ctx) |
mtc1 $t0,$27 |
lw $t0, OFFSET_F28(\ctx) |
mtc1 $t0,$28 |
lw $t0, OFFSET_F29(\ctx) |
mtc1 $t0,$29 |
lw $t0, OFFSET_F30(\ctx) |
mtc1 $t0,$30 |
# endif /* CONFIG_MIPS_FPU */ |
#endif /* KERNEL */ |
lw $ra,OFFSET_PC(\ctx) |
lw $sp,OFFSET_SP(\ctx) |
.endm |
#endif |
#endif |
/branches/network/kernel/doc/BUGS_FOUND |
---|
File deleted |
/branches/network/kernel/doc/AUTHORS |
---|
1,12 → 1,12 |
Jakub Jermar <jermar@helenos.eu> |
Martin Decky <decky@helenos.eu> |
Ondrej Palkovsky <palkovsky@helenos.eu> |
Jakub Vana <vana@helenos.eu> |
Josef Cejka <cejka@helenos.eu> |
Michal Kebrt <michalek.k@seznam.cz> |
Sergey Bondari <bondari@helenos.eu> |
Pavel Jancik <alfik.009@seznam.cz> |
Petr Stepan <stepan.petr@volny.cz> |
Michal Konopa <mkonopa@seznam.cz> |
Jakub Jermar |
Martin Decky |
Ondrej Palkovsky |
Jiri Svoboda |
Jakub Vana |
Josef Cejka |
Michal Kebrt |
Sergey Bondari |
Pavel Jancik |
Petr Stepan |
Michal Konopa |
Vojtech Mencl |
/branches/network/kernel/doc/arch/mips32 |
---|
3,11 → 3,9 |
mips32 is the second port of SPARTAN kernel originally written by Jakub Jermar. |
It was first developed to run on MIPS R4000 32-bit simulator. |
Now it can run on real hardware as well. |
It can be compiled and run either as little- or big-endian. |
HARDWARE REQUIREMENTS |
o SGI Indy R4600 |
o emulated MIPS 4K CPU |
CPU |
/branches/network/kernel/kernel.config |
---|
1,3 → 1,31 |
# |
# Copyright (c) 2006 Ondrej Palkovsky |
# 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. |
# |
## General configuration directives |
# Architecture |
53,16 → 81,10 |
@ "simics" Virtutech Simics simulator |
@ "lgxemul" GXEmul Little Endian |
@ "bgxemul" GXEmul Big Endian |
@ "indy" SGI Indy |
! [ARCH=mips32] MACHINE (choice) |
# Machine type |
@ "gxemul_testarm" GXEmul testarm |
! [ARCH=arm32] MACHINE (choice) |
# Framebuffer support |
! [(ARCH=mips32&MACHINE=lgxemul)|(ARCH=mips32&MACHINE=bgxemul)|(ARCH=ia32)|(ARCH=amd64)|(ARCH=arm32&MACHINE=gxemul_testarm)] CONFIG_FB (y/n) |
! [(ARCH=mips32&MACHINE=lgxemul)|(ARCH=mips32&MACHINE=bgxemul)|(ARCH=ia32)|(ARCH=amd64)|(ARCH=arm32)] CONFIG_FB (y/n) |
# Framebuffer width |
@ "640" |
128,6 → 150,9 |
# General debuging and assert checking |
! CONFIG_DEBUG (y/n) |
# Extensive debugging output |
! [CONFIG_DEBUG=y] CONFIG_EDEBUG (n/y) |
# Deadlock detection support for spinlocks |
! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n) |
142,9 → 167,3 |
# Compile kernel tests |
! CONFIG_TEST (y/n) |
## Experimental features |
# Enable experimental features |
! CONFIG_EXPERIMENTAL (n/y) |
/branches/network/kernel/genarch/include/mm/page_pt.h |
---|
116,9 → 116,7 |
#define PTE_WRITABLE(p) PTE_WRITABLE_ARCH((p)) |
#define PTE_EXECUTABLE(p) PTE_EXECUTABLE_ARCH((p)) |
#ifndef __OBJC__ |
extern as_operations_t as_pt_operations; |
#endif |
extern page_mapping_operations_t pt_mapping_operations; |
extern void page_mapping_insert_pt(as_t *as, uintptr_t page, uintptr_t frame, |
/branches/network/kernel/genarch/include/ofw/ofw_tree.h |
---|
30,6 → 30,7 |
#define KERN_OFW_TREE_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#define OFW_TREE_PROPERTY_MAX_NAMELEN 32 |
/branches/network/kernel/genarch/src/mm/as_pt.c |
---|
52,31 → 52,6 |
static void pt_lock(as_t *as, bool lock); |
static void pt_unlock(as_t *as, bool unlock); |
#ifdef __OBJC__ |
@implementation as_t |
+ (pte_t *) page_table_create: (int) flags |
{ |
return ptl0_create(flags); |
} |
+ (void) page_table_destroy: (pte_t *) page_table |
{ |
ptl0_destroy(page_table); |
} |
- (void) page_table_lock: (bool) _lock |
{ |
pt_lock(self, _lock); |
} |
- (void) page_table_unlock: (bool) unlock |
{ |
pt_unlock(self, unlock); |
} |
@end |
#else |
as_operations_t as_pt_operations = { |
.page_table_create = ptl0_create, |
.page_table_destroy = ptl0_destroy, |
83,7 → 58,6 |
.page_table_lock = pt_lock, |
.page_table_unlock = pt_unlock |
}; |
#endif |
/** Create PTL0. |
* |
103,7 → 77,7 |
table_size = FRAME_SIZE << PTL0_SIZE; |
if (flags & FLAG_AS_KERNEL) { |
memsetb((uintptr_t) dst_ptl0, table_size, 0); |
memsetb(dst_ptl0, table_size, 0); |
} else { |
uintptr_t src, dst; |
118,7 → 92,7 |
src = (uintptr_t) &src_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)]; |
dst = (uintptr_t) &dst_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)]; |
memsetb((uintptr_t) dst_ptl0, table_size, 0); |
memsetb(dst_ptl0, table_size, 0); |
memcpy((void *) dst, (void *) src, table_size - (src - (uintptr_t) src_ptl0)); |
mutex_unlock(&AS_KERNEL->lock); |
interrupts_restore(ipl); |
/branches/network/kernel/genarch/src/mm/as_ht.c |
---|
72,7 → 72,7 |
{ |
if (flags & FLAG_AS_KERNEL) { |
hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations); |
mutex_initialize(&page_ht_lock); |
mutex_initialize(&page_ht_lock, MUTEX_PASSIVE); |
} |
return NULL; |
} |
/branches/network/kernel/genarch/src/mm/page_pt.c |
---|
76,7 → 76,7 |
if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) { |
newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA); |
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL1_SIZE, 0); |
memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0); |
SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt)); |
SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); |
} |
85,7 → 85,7 |
if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) { |
newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA); |
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL2_SIZE, 0); |
memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0); |
SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt)); |
SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); |
} |
94,7 → 94,7 |
if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) { |
newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA); |
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL3_SIZE, 0); |
memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0); |
SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt)); |
SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); |
} |
146,7 → 146,7 |
ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); |
/* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */ |
memsetb((uintptr_t) &ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); |
/* |
* Second, free all empty tables along the way from PTL3 down to PTL0. |
166,11 → 166,11 |
*/ |
frame_free(KA2PA((uintptr_t) ptl3)); |
if (PTL2_ENTRIES) |
memsetb((uintptr_t) &ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0); |
else if (PTL1_ENTRIES) |
memsetb((uintptr_t) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
else |
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} else { |
/* |
* PTL3 is not empty. |
195,9 → 195,9 |
*/ |
frame_free(KA2PA((uintptr_t) ptl2)); |
if (PTL1_ENTRIES) |
memsetb((uintptr_t) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
else |
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} |
else { |
/* |
223,7 → 223,7 |
* Release the frame and remove PTL1 pointer from preceding table. |
*/ |
frame_free(KA2PA((uintptr_t) ptl1)); |
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} |
} |
/branches/network/kernel/genarch/src/acpi/madt.c |
---|
184,15 → 184,15 |
case MADT_IO_SAPIC: |
case MADT_L_SAPIC: |
case MADT_PLATFORM_INTR_SRC: |
printf("MADT: skipping %s entry (type=%zd)\n", entry[h->type], h->type); |
printf("MADT: skipping %s entry (type=%" PRIu8 ")\n", entry[h->type], h->type); |
break; |
default: |
if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) { |
printf("MADT: skipping reserved entry (type=%zd)\n", h->type); |
printf("MADT: skipping reserved entry (type=%" PRIu8 ")\n", h->type); |
} |
if (h->type >= MADT_RESERVED_OEM_BEGIN) { |
printf("MADT: skipping OEM entry (type=%zd)\n", h->type); |
printf("MADT: skipping OEM entry (type=%" PRIu8 ")\n", h->type); |
} |
break; |
} |
234,7 → 234,7 |
void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index) |
{ |
ASSERT(override->source < sizeof(isa_irq_map)/sizeof(int)); |
printf("MADT: ignoring %s entry: bus=%zd, source=%zd, global_int=%zd, flags=%#hx\n", |
printf("MADT: ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8 ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n", |
entry[override->header.type], override->bus, override->source, |
override->global_int, override->flags); |
} |
/branches/network/kernel/genarch/src/acpi/acpi.c |
---|
105,7 → 105,7 |
if (!acpi_sdt_check((uint8_t *) h)) |
goto next; |
*signature_map[j].sdt_ptr = h; |
printf("%#zp: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
printf("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
} |
} |
next: |
126,7 → 126,7 |
if (!acpi_sdt_check((uint8_t *) h)) |
goto next; |
*signature_map[j].sdt_ptr = h; |
printf("%#zp: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
printf("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
} |
} |
next: |
160,7 → 160,7 |
return; |
rsdp_found: |
printf("%#zp: ACPI Root System Description Pointer\n", acpi_rsdp); |
printf("%p: ACPI Root System Description Pointer\n", acpi_rsdp); |
acpi_rsdt = (struct acpi_rsdt *) (unative_t) acpi_rsdp->rsdt_address; |
if (acpi_rsdp->revision) acpi_xsdt = (struct acpi_xsdt *) ((uintptr_t) acpi_rsdp->xsdt_address); |
169,11 → 169,11 |
if (acpi_xsdt) map_sdt((struct acpi_sdt_header *) acpi_xsdt); |
if (acpi_rsdt && !acpi_sdt_check((uint8_t *) acpi_rsdt)) { |
printf("RSDT: %s\n", "bad checksum"); |
printf("RSDT: bad checksum\n"); |
return; |
} |
if (acpi_xsdt && !acpi_sdt_check((uint8_t *) acpi_xsdt)) { |
printf("XSDT: %s\n", "bad checksum"); |
printf("XSDT: bad checksum\n"); |
return; |
} |
/branches/network/kernel/genarch/src/ofw/ebus.c |
---|
57,7 → 57,7 |
ranges = prop->size / sizeof(ofw_ebus_range_t); |
range = prop->value; |
int i; |
unsigned int i; |
for (i = 0; i < ranges; i++) { |
if (reg->space != range[i].child_space) |
102,7 → 102,7 |
uint32_t addr = reg->addr & intr_mask->addr_mask; |
uint32_t intr = interrupt & intr_mask->intr_mask; |
int i; |
unsigned int i; |
for (i = 0; i < count; i++) { |
if ((intr_map[i].space == space) && (intr_map[i].addr == addr) |
&& (intr_map[i].intr == intr)) |
/branches/network/kernel/genarch/src/ofw/fhc.c |
---|
55,7 → 55,7 |
ranges = prop->size / sizeof(ofw_fhc_range_t); |
range = prop->value; |
int i; |
unsigned int i; |
for (i = 0; i < ranges; i++) { |
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) { |
97,7 → 97,7 |
ranges = prop->size / sizeof(ofw_central_range_t); |
range = prop->value; |
int i; |
unsigned int i; |
for (i = 0; i < ranges; i++) { |
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) { |
/branches/network/kernel/genarch/src/ofw/ofw_tree.c |
---|
61,7 → 61,7 |
*/ |
ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name) |
{ |
int i; |
unsigned int i; |
for (i = 0; i < node->properties; i++) { |
if (strcmp(node->property[i].name, name) == 0) |
/branches/network/kernel/genarch/src/ofw/pci.c |
---|
65,7 → 65,7 |
ranges = prop->size / sizeof(ofw_pci_range_t); |
range = prop->value; |
int i; |
unsigned int i; |
for (i = 0; i < ranges; i++) { |
if ((reg->space & PCI_SPACE_MASK) != (range[i].space & PCI_SPACE_MASK)) |
100,7 → 100,7 |
assigned_addresses = prop->size / sizeof(ofw_pci_reg_t); |
assigned_address = prop->value; |
int i; |
unsigned int i; |
for (i = 0; i < assigned_addresses; i++) { |
if ((assigned_address[i].space & PCI_REG_MASK) == (reg->space & PCI_REG_MASK)) { |
/branches/network/kernel/genarch/src/ofw/sbus.c |
---|
61,7 → 61,7 |
ranges = prop->size / sizeof(ofw_sbus_range_t); |
range = prop->value; |
int i; |
unsigned int i; |
for (i = 0; i < ranges; i++) { |
if (overlaps(reg->addr, reg->size, range[i].child_base, |
/branches/network/kernel/Makefile |
---|
43,11 → 43,11 |
-DKERNEL |
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \ |
-fno-builtin -fomit-frame-pointer -Wall -Wmissing-prototypes -Werror \ |
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \ |
-nostdlib -nostdinc |
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \ |
-fno-builtin -fomit-frame-pointer -Wall -Wmissing-prototypes -Werror \ |
-fno-builtin -Wall -Wmissing-prototypes -Werror \ |
-nostdlib -nostdinc \ |
-wd170 |
90,6 → 90,10 |
DEFS += -DCONFIG_DEBUG |
endif |
ifeq ($(CONFIG_EDEBUG),y) |
DEFS += -DCONFIG_EDEBUG |
endif |
ifeq ($(CONFIG_DEBUG_SPINLOCK),y) |
DEFS += -DCONFIG_DEBUG_SPINLOCK |
endif |
217,7 → 221,6 |
generic/src/console/chardev.c \ |
generic/src/console/console.c \ |
generic/src/console/kconsole.c \ |
generic/src/console/klog.c \ |
generic/src/console/cmd.c \ |
generic/src/cpu/cpu.c \ |
generic/src/ddi/ddi.c \ |
229,10 → 232,12 |
generic/src/main/uinit.c \ |
generic/src/main/version.c \ |
generic/src/main/shutdown.c \ |
generic/src/proc/program.c \ |
generic/src/proc/scheduler.c \ |
generic/src/proc/thread.c \ |
generic/src/proc/task.c \ |
generic/src/proc/the.c \ |
generic/src/proc/tasklet.c \ |
generic/src/syscall/syscall.c \ |
generic/src/syscall/copy.c \ |
generic/src/mm/buddy.c \ |
266,6 → 271,7 |
generic/src/synch/rwlock.c \ |
generic/src/synch/mutex.c \ |
generic/src/synch/semaphore.c \ |
generic/src/synch/smc.c \ |
generic/src/synch/waitq.c \ |
generic/src/synch/futex.c \ |
generic/src/smp/ipi.c \ |
311,16 → 317,6 |
test/sysinfo/sysinfo1.c |
endif |
## Experimental features |
# |
ifeq ($(CONFIG_EXPERIMENTAL),y) |
GENERIC_SOURCES += generic/src/lib/objc_ext.c \ |
generic/src/lib/objc.c |
EXTRA_OBJECTS = $(LIBDIR)/libobjc.a |
EXTRA_FLAGS += -x objective-c |
endif |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES))) |
389,5 → 385,15 |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
# |
# The FPU tests are the only objects for which we allow the compiler to generate |
# FPU instructions. |
# |
test/fpu/%.o: test/fpu/%.c |
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c $< -o $@ |
# |
# Ordinary objects. |
# |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c $< -o $@ |
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS) -c $< -o $@ |
/branches/network/kernel/test/mm/slab2.c |
---|
68,8 → 68,8 |
slab_free(cache2, data2); |
break; |
} |
memsetb((uintptr_t) data1, ITEM_SIZE, 0); |
memsetb((uintptr_t) data2, ITEM_SIZE, 0); |
memsetb(data1, ITEM_SIZE, 0); |
memsetb(data2, ITEM_SIZE, 0); |
*((void **) data1) = olddata1; |
*((void **) data2) = olddata2; |
olddata1 = data1; |
100,7 → 100,7 |
printf("Incorrect memory size - use another test."); |
return; |
} |
memsetb((uintptr_t) data1, ITEM_SIZE, 0); |
memsetb(data1, ITEM_SIZE, 0); |
*((void **) data1) = olddata1; |
olddata1 = data1; |
} |
108,7 → 108,7 |
data1 = slab_alloc(cache1, FRAME_ATOMIC); |
if (!data1) |
break; |
memsetb((uintptr_t) data1, ITEM_SIZE, 0); |
memsetb(data1, ITEM_SIZE, 0); |
*((void **) data1) = olddata1; |
olddata1 = data1; |
} |
150,11 → 150,11 |
mutex_unlock(&starter_mutex); |
if (!sh_quiet) |
printf("Starting thread #%llu...\n",THREAD->tid); |
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
/* Alloc all */ |
if (!sh_quiet) |
printf("Thread #%llu allocating...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
while (1) { |
/* Call with atomic to detect end of memory */ |
166,7 → 166,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu releasing...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
176,7 → 176,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu allocating...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
while (1) { |
/* Call with atomic to detect end of memory */ |
188,7 → 188,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu releasing...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
198,7 → 198,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu finished\n", THREAD->tid); |
printf("Thread #%" PRIu64 " finished\n", THREAD->tid); |
slab_print_list(); |
semaphore_up(&thr_sem); |
216,7 → 216,7 |
printf("Running stress test with size %d\n", size); |
condvar_initialize(&thread_starter); |
mutex_initialize(&starter_mutex); |
mutex_initialize(&starter_mutex, MUTEX_PASSIVE); |
thr_cache = slab_cache_create("thread_cache", size, 0, NULL, NULL, 0); |
semaphore_initialize(&thr_sem,0); |
/branches/network/kernel/test/mm/slab1.c |
---|
53,7 → 53,7 |
for (i = 0; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb((uintptr_t) data[i], size, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
71,7 → 71,7 |
for (i = 0; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb((uintptr_t) data[i], size, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
89,7 → 89,7 |
for (i = count / 2; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb((uintptr_t) data[i], size, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
137,7 → 137,7 |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("Starting thread #%llu...\n", THREAD->tid); |
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
for (j = 0; j < 10; j++) { |
for (i = 0; i < THR_MEM_COUNT; i++) |
151,7 → 151,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu finished\n", THREAD->tid); |
printf("Thread #%" PRIu64 " finished\n", THREAD->tid); |
semaphore_up(&thr_sem); |
} |
/branches/network/kernel/test/mm/falloc2.c |
---|
55,10 → 55,10 |
uint8_t val = THREAD->tid % THREADS; |
index_t k; |
uintptr_t * frames = (uintptr_t *) malloc(MAX_FRAMES * sizeof(uintptr_t), FRAME_ATOMIC); |
void **frames = (void **) malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC); |
if (frames == NULL) { |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Unable to allocate frames\n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Unable to allocate frames\n", THREAD->tid, CPU->id); |
atomic_inc(&thread_fail); |
atomic_dec(&thread_count); |
return; |
69,11 → 69,11 |
for (run = 0; run < THREAD_RUNS; run++) { |
for (order = 0; order <= MAX_ORDER; order++) { |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
printf("Thread #%" PRIu64 " (cpu%u): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
allocated = 0; |
for (i = 0; i < (MAX_FRAMES >> order); i++) { |
frames[allocated] = (uintptr_t)frame_alloc(order, FRAME_ATOMIC | FRAME_KA); |
frames[allocated] = frame_alloc(order, FRAME_ATOMIC | FRAME_KA); |
if (frames[allocated]) { |
memsetb(frames[allocated], FRAME_SIZE << order, val); |
allocated++; |
82,16 → 82,16 |
} |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
printf("Thread #%" PRIu64 " (cpu%u): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Deallocating ... \n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Deallocating ... \n", THREAD->tid, CPU->id); |
for (i = 0; i < allocated; i++) { |
for (k = 0; k <= ((FRAME_SIZE << order) - 1); k++) { |
for (k = 0; k <= (((index_t) FRAME_SIZE << order) - 1); k++) { |
if (((uint8_t *) frames[i])[k] != val) { |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Unexpected data (%d) in block %p offset %#zx\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k); |
printf("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %#" PRIi "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k); |
atomic_inc(&thread_fail); |
goto cleanup; |
} |
100,7 → 100,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Finished run.\n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Finished run.\n", THREAD->tid, CPU->id); |
} |
} |
108,7 → 108,7 |
free(frames); |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Exiting\n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Exiting\n", THREAD->tid, CPU->id); |
atomic_dec(&thread_count); |
} |
124,7 → 124,7 |
thread_t * thrd = thread_create(falloc, NULL, TASK, 0, "falloc", false); |
if (!thrd) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
printf("Could not create thread %u\n", i); |
break; |
} |
thread_ready(thrd); |
132,7 → 132,7 |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %d\n", atomic_get(&thread_count)); |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/network/kernel/test/avltree/avltree1.c |
---|
48,7 → 48,8 |
static int test_tree_balance(avltree_node_t *node); |
static avltree_node_t *test_tree_parents(avltree_node_t *node); |
static void print_tree_structure_flat (avltree_node_t *node, int level); |
static void print_tree_structure_flat (avltree_node_t *node, int level) |
__attribute__ ((used)); |
static avltree_node_t *alloc_avltree_node(void); |
static avltree_node_t *test_tree_parents(avltree_node_t *node) |
61,14 → 62,15 |
if (node->lft) { |
tmp = test_tree_parents(node->lft); |
if (tmp != node) { |
printf("Bad parent pointer key: %d, address: %p\n", |
tmp->key, node->lft); |
printf("Bad parent pointer key: %" PRIu64 |
", address: %p\n", tmp->key, node->lft); |
} |
} |
if (node->rgt) { |
tmp = test_tree_parents(node->rgt); |
if (tmp != node) { |
printf("Bad parent pointer key: %d, address: %p\n", |
printf("Bad parent pointer key: %" PRIu64 |
", address: %p\n", |
tmp->key,node->rgt); |
} |
} |
94,7 → 96,8 |
* Prints the structure of the node, which is level levels from the top of the |
* tree. |
*/ |
static void print_tree_structure_flat(avltree_node_t *node, int level) |
static void |
print_tree_structure_flat(avltree_node_t *node, int level) |
{ |
/* |
* You can set the maximum level as high as you like. |
109,7 → 112,7 |
if (node == NULL) |
return; |
printf("%d[%d]", node->key, node->balance); |
printf("%" PRIu64 "[%" PRIu8 "]", node->key, node->balance); |
if (node->lft != NULL || node->rgt != NULL) { |
printf("("); |
130,6 → 133,7 |
for (i = 0; i < NODE_COUNT - 1; i++) { |
avltree_nodes[i].par = &avltree_nodes[i + 1]; |
} |
avltree_nodes[i].par = NULL; |
/* |
* Node keys which will be used for insertion. Up to NODE_COUNT size of |
169,7 → 173,6 |
for (i = 21; i < NODE_COUNT; i++) |
avltree_nodes[i].key = i * 3; |
avltree_nodes[i].par = NULL; |
first_free_node = &avltree_nodes[0]; |
} |
191,7 → 194,7 |
avltree_create(tree); |
if (!quiet) |
printf("Inserting %d nodes...", node_count); |
printf("Inserting %" PRIc " nodes...", node_count); |
for (i = 0; i < node_count; i++) { |
newnode = alloc_avltree_node(); |
246,7 → 249,7 |
static void test_tree_delmin(avltree_t *tree, count_t node_count, bool quiet) |
{ |
int i = 0; |
unsigned int i = 0; |
if (!quiet) |
printf("Deleting minimum nodes..."); |
/branches/network/kernel/test/synch/rwlock3.c |
---|
45,14 → 45,14 |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("cpu%d, tid %llu: trying to lock rwlock for reading....\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for reading....\n", CPU->id, THREAD->tid); |
rwlock_read_lock(&rwlock); |
rwlock_read_unlock(&rwlock); |
if (!sh_quiet) { |
printf("cpu%d, tid %llu: success\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu: trying to lock rwlock for writing....\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for writing....\n", CPU->id, THREAD->tid); |
} |
rwlock_write_lock(&rwlock); |
59,7 → 59,7 |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %llu: success\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
88,7 → 88,7 |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %d\n", atomic_get(&thread_count)); |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/network/kernel/test/synch/rwlock4.c |
---|
74,18 → 74,18 |
to = random(40000); |
if (!sh_quiet) |
printf("cpu%d, tid %llu w+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%u, tid %" PRIu64 " w+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = rwlock_write_lock_timeout(&rwlock, to); |
if (SYNCH_FAILED(rc)) { |
if (!sh_quiet) |
printf("cpu%d, tid %llu w!\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " w!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%d, tid %llu w=\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " w=\n", CPU->id, THREAD->tid); |
if (rwlock.readers_in) { |
if (!sh_quiet) |
106,7 → 106,7 |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %llu w-\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " w-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
119,24 → 119,24 |
to = random(2000); |
if (!sh_quiet) |
printf("cpu%d, tid %llu r+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%u, tid %" PRIu64 " r+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = rwlock_read_lock_timeout(&rwlock, to); |
if (SYNCH_FAILED(rc)) { |
if (!sh_quiet) |
printf("cpu%d, tid %llu r!\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " r!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%d, tid %llu r=\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " r=\n", CPU->id, THREAD->tid); |
thread_usleep(30000); |
rwlock_read_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %llu r-\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " r-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
159,8 → 159,8 |
context_save(&ctx); |
if (!quiet) { |
printf("sp=%#x, readers_in=%d\n", ctx.sp, rwlock.readers_in); |
printf("Creating %d readers\n", rd); |
printf("sp=%#x, readers_in=%" PRIc "\n", ctx.sp, rwlock.readers_in); |
printf("Creating %" PRIu32 " readers\n", rd); |
} |
for (i = 0; i < rd; i++) { |
168,11 → 168,11 |
if (thrd) |
thread_ready(thrd); |
else if (!quiet) |
printf("Could not create reader %d\n", i); |
printf("Could not create reader %" PRIu32 "\n", i); |
} |
if (!quiet) |
printf("Creating %d writers\n", wr); |
printf("Creating %" PRIu32 " writers\n", wr); |
for (i = 0; i < wr; i++) { |
thrd = thread_create(writer, NULL, TASK, 0, "writer", false); |
179,7 → 179,7 |
if (thrd) |
thread_ready(thrd); |
else if (!quiet) |
printf("Could not create writer %d\n", i); |
printf("Could not create writer %" PRIu32 "\n", i); |
} |
thread_usleep(20000); |
187,7 → 187,7 |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %d\n", atomic_get(&thread_count)); |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/network/kernel/test/synch/semaphore2.c |
---|
67,18 → 67,18 |
waitq_sleep(&can_start); |
to = random(20000); |
printf("cpu%d, tid %llu down+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%u, tid %" PRIu64 " down+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = semaphore_down_timeout(&sem, to); |
if (SYNCH_FAILED(rc)) { |
printf("cpu%d, tid %llu down!\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " down!\n", CPU->id, THREAD->tid); |
return; |
} |
printf("cpu%d, tid %llu down=\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " down=\n", CPU->id, THREAD->tid); |
thread_usleep(random(30000)); |
semaphore_up(&sem); |
printf("cpu%d, tid %llu up\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " up\n", CPU->id, THREAD->tid); |
} |
char * test_semaphore2(bool quiet) |
91,7 → 91,7 |
thread_t *thrd; |
k = random(7) + 1; |
printf("Creating %d consumers\n", k); |
printf("Creating %" PRIu32 " consumers\n", k); |
for (i = 0; i < k; i++) { |
thrd = thread_create(consumer, NULL, TASK, 0, "consumer", false); |
if (thrd) |
/branches/network/kernel/test/synch/rwlock5.c |
---|
69,7 → 69,7 |
char * test_rwlock5(bool quiet) |
{ |
int i, j, k; |
count_t readers, writers; |
long readers, writers; |
waitq_initialize(&can_start); |
rwlock_initialize(&rwlock); |
108,7 → 108,7 |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while ((items_read.count != readers) || (items_written.count != writers)) { |
printf("%zd readers remaining, %zd writers remaining, readers_in=%zd\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in); |
printf("%d readers remaining, %d writers remaining, readers_in=%d\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in); |
thread_usleep(100000); |
} |
} |
/branches/network/kernel/test/test.h |
---|
36,6 → 36,7 |
#define KERN_TEST_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
typedef char * (* test_entry_t)(bool); |
/branches/network/kernel/test/thread/thread1.c |
---|
48,7 → 48,7 |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%llu ", THREAD->tid); |
printf("%" PRIu64 " ", THREAD->tid); |
thread_usleep(100000); |
} |
atomic_inc(&threads_finished); |
78,7 → 78,7 |
thread_sleep(10); |
atomic_set(&finish, 0); |
while (atomic_get(&threads_finished) < total) { |
while (atomic_get(&threads_finished) < ((long) total)) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_finished)); |
thread_sleep(1); |
/branches/network/kernel/test/fpu/mips2.c |
---|
72,7 → 72,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
104,7 → 104,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
123,7 → 123,7 |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %d threads... ", 2 * THREADS); |
printf("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
130,7 → 130,7 |
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i); |
printf("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
138,7 → 138,7 |
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i + 1); |
printf("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
151,7 → 151,7 |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != total) { |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
/branches/network/kernel/test/fpu/fpu1.c |
---|
126,7 → 126,7 |
if ((int) (100000000 * e) != E_10e8) { |
if (!sh_quiet) |
printf("tid%llu: e*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
printf("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
161,7 → 161,7 |
#ifdef KERN_ia64_ARCH_H_ |
if ((int) (1000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%llu: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); |
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); |
atomic_inc(&threads_fault); |
break; |
} |
168,7 → 168,7 |
#else |
if ((int) (100000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%llu: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); |
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
187,7 → 187,7 |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %d threads... ", 2 * THREADS); |
printf("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
194,7 → 194,7 |
if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i); |
printf("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
202,7 → 202,7 |
if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i + 1); |
printf("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
215,7 → 215,7 |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != total) { |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
/branches/network/kernel/test/fpu/sse1.c |
---|
72,7 → 72,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
104,7 → 104,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
123,7 → 123,7 |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %d threads... ", 2 * THREADS); |
printf("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
130,7 → 130,7 |
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i); |
printf("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
138,7 → 138,7 |
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i + 1); |
printf("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
151,7 → 151,7 |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != total) { |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
/branches/network/kernel/test/print/print1.c |
---|
49,7 → 49,7 |
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",-1, -1, -1, -1, -1 ); |
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n",17, 17, 17, 17, 17 ); |
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#zx'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" ); |
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#" PRIxn "'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" ); |
printf(" Print to NULL '%s'\n", NULL); |
/branches/network/kernel/test/test.c |
---|
58,7 → 58,11 |
#include <print/print1.def> |
#include <thread/thread1.def> |
#include <sysinfo/sysinfo1.def> |
{NULL, NULL, NULL} |
{ |
.name = NULL, |
.desc = NULL, |
.entry = NULL |
} |
}; |
/** @} |
/branches/network/uspace/app/ash/exec.c |
---|
File deleted |
/branches/network/uspace/app/ash/cd.c |
---|
File deleted |
/branches/network/uspace/app/ash/bltin/echo.1 |
---|
File deleted |
/branches/network/uspace/app/ash/bltin/bltin.h |
---|
File deleted |
/branches/network/uspace/app/ash/bltin/echo.c |
---|
File deleted |
/branches/network/uspace/app/ash/bltin/test.c |
---|
File deleted |
/branches/network/uspace/app/ash/bltin/times.c |
---|
File deleted |
/branches/network/uspace/app/ash/alias.c |
---|
File deleted |
/branches/network/uspace/app/ash/memalloc.c |
---|
File deleted |
/branches/network/uspace/app/ash/exec.h |
---|
File deleted |
/branches/network/uspace/app/ash/cd.h |
---|
File deleted |
/branches/network/uspace/app/ash/nodes.c.pat |
---|
File deleted |
/branches/network/uspace/app/ash/parser.c |
---|
File deleted |
/branches/network/uspace/app/ash/jobs.c |
---|
File deleted |
/branches/network/uspace/app/ash/memalloc.h |
---|
File deleted |
/branches/network/uspace/app/ash/alias.h |
---|
File deleted |
/branches/network/uspace/app/ash/output.c |
---|
File deleted |
/branches/network/uspace/app/ash/parser.h |
---|
File deleted |
/branches/network/uspace/app/ash/jobs.h |
---|
File deleted |
/branches/network/uspace/app/ash/output.h |
---|
File deleted |
/branches/network/uspace/app/ash/builtins.def |
---|
File deleted |
/branches/network/uspace/app/ash/mystring.c |
---|
File deleted |
/branches/network/uspace/app/ash/histedit.c |
---|
File deleted |
/branches/network/uspace/app/ash/tags |
---|
File deleted |
/branches/network/uspace/app/ash/show.c |
---|
File deleted |
/branches/network/uspace/app/ash/mystring.h |
---|
File deleted |
/branches/network/uspace/app/ash/show.h |
---|
File deleted |
/branches/network/uspace/app/ash/myhistedit.h |
---|
File deleted |
/branches/network/uspace/app/ash/arith_lex.l |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/suspend |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/dirs |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/popd |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/newgrp |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/pushd |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/cmv |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/login |
---|
File deleted |
/branches/network/uspace/app/ash/funcs/kill |
---|
File deleted |
/branches/network/uspace/app/ash/input.c |
---|
File deleted |
/branches/network/uspace/app/ash/input.h |
---|
File deleted |
/branches/network/uspace/app/ash/redir.c |
---|
File deleted |
/branches/network/uspace/app/ash/trap.c |
---|
File deleted |
/branches/network/uspace/app/ash/arith.c |
---|
File deleted |
/branches/network/uspace/app/ash/redir.h |
---|
File deleted |
/branches/network/uspace/app/ash/trap.h |
---|
File deleted |
/branches/network/uspace/app/ash/arith.h |
---|
File deleted |
/branches/network/uspace/app/ash/expand.c |
---|
File deleted |
/branches/network/uspace/app/ash/mail.c |
---|
File deleted |
/branches/network/uspace/app/ash/miscbltin.c |
---|
File deleted |
/branches/network/uspace/app/ash/expand.h |
---|
File deleted |
/branches/network/uspace/app/ash/main.c |
---|
File deleted |
/branches/network/uspace/app/ash/mail.h |
---|
File deleted |
/branches/network/uspace/app/ash/eval.c |
---|
File deleted |
/branches/network/uspace/app/ash/var.c |
---|
File deleted |
/branches/network/uspace/app/ash/miscbltin.h |
---|
File deleted |
/branches/network/uspace/app/ash/main.h |
---|
File deleted |
/branches/network/uspace/app/ash/options.c |
---|
File deleted |
/branches/network/uspace/app/ash/eval.h |
---|
File deleted |
/branches/network/uspace/app/ash/var.h |
---|
File deleted |
/branches/network/uspace/app/ash/arith.y |
---|
File deleted |
/branches/network/uspace/app/ash/setmode.c |
---|
File deleted |
/branches/network/uspace/app/ash/options.h |
---|
File deleted |
/branches/network/uspace/app/ash/mkbuiltins |
---|
File deleted |
/branches/network/uspace/app/ash/fake.c |
---|
File deleted |
/branches/network/uspace/app/ash/init.h |
---|
File deleted |
/branches/network/uspace/app/ash/fake.h |
---|
File deleted |
/branches/network/uspace/app/ash/tools/mksyntax.c |
---|
File deleted |
/branches/network/uspace/app/ash/tools/mksignames.c |
---|
File deleted |
/branches/network/uspace/app/ash/tools/mknodes.c |
---|
File deleted |
/branches/network/uspace/app/ash/tools/mkinit.c |
---|
File deleted |
/branches/network/uspace/app/ash/tools/Makefile |
---|
File deleted |
/branches/network/uspace/app/ash/lex.yy.c |
---|
File deleted |
/branches/network/uspace/app/ash/sh.1 |
---|
File deleted |
/branches/network/uspace/app/ash/nodetypes |
---|
File deleted |
/branches/network/uspace/app/ash/error.c |
---|
File deleted |
/branches/network/uspace/app/ash/Makefile |
---|
File deleted |
/branches/network/uspace/app/ash/error.h |
---|
File deleted |
/branches/network/uspace/app/ash/machdep.h |
---|
File deleted |
/branches/network/uspace/app/ash/hetio.c |
---|
File deleted |
/branches/network/uspace/app/ash/TOUR |
---|
File deleted |
/branches/network/uspace/app/ash/mktokens |
---|
File deleted |
/branches/network/uspace/app/ash/shell.h |
---|
File deleted |
/branches/network/uspace/app/ash/hetio.h |
---|
File deleted |
/branches/network/uspace/app/bdsh/scli.c |
---|
0,0 → 1,105 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include "config.h" |
#include "scli.h" |
#include "input.h" |
#include "util.h" |
#include "errors.h" |
#include "cmds/cmds.h" |
/* See scli.h */ |
static cliuser_t usr; |
/* Globals that are modified during start-up that modules/builtins |
* should be aware of. */ |
volatile unsigned int cli_quit = 0; |
volatile unsigned int cli_interactive = 1; |
volatile unsigned int cli_verbocity = 1; |
/* The official name of this program |
* (change to your liking in configure.ac and re-run autoconf) */ |
const char *progname = PACKAGE_NAME; |
/* These are not exposed, even to builtins */ |
static int cli_init(cliuser_t *usr); |
static void cli_finit(cliuser_t *usr); |
/* Constructor */ |
static int cli_init(cliuser_t *usr) |
{ |
usr->line = (char *) NULL; |
usr->name = "root"; |
usr->home = "/"; |
usr->cwd = (char *) NULL; |
usr->prompt = (char *) NULL; |
chdir(usr->home); |
usr->lasterr = 0; |
return (int) cli_set_prompt(usr); |
} |
/* Destructor */ |
static void cli_finit(cliuser_t *usr) |
{ |
if (NULL != usr->line) |
free(usr->line); |
if (NULL != usr->prompt) |
free(usr->prompt); |
if (NULL != usr->cwd) |
free(usr->cwd); |
} |
int main(int argc, char *argv[]) |
{ |
int ret = 0; |
if (cli_init(&usr)) |
exit(EXIT_FAILURE); |
printf("Welcome to %s - %s\nType `help' at any time for usage information.\n", |
progname, PACKAGE_STRING); |
while (!cli_quit) { |
get_input(&usr); |
if (NULL != usr.line) { |
ret = tok_input(&usr); |
usr.lasterr = ret; |
} |
} |
goto finit; |
finit: |
cli_finit(&usr); |
return ret; |
} |
/branches/network/uspace/app/bdsh/scli.h |
---|
0,0 → 1,16 |
#ifndef SCLI_H |
#define SCLI_H |
#include "config.h" |
#include <stdint.h> |
typedef struct { |
char *name; |
char *home; |
char *line; |
char *cwd; |
char *prompt; |
int lasterr; |
} cliuser_t; |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtins/cd/cd.c |
---|
0,0 → 1,106 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <string.h> |
#include <errno.h> |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "cmds.h" |
#include "cd.h" |
static char * cmdname = "cd"; |
void * help_cmd_cd(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' changes the current working directory.\n", cmdname); |
} else { |
printf( |
" %s <directory>\n" |
" Change directory to <directory>, e.g `%s /sbin'\n", |
cmdname, cmdname); |
} |
return CMD_VOID; |
} |
/* This is a very rudamentary 'cd' command. It is not 'link smart' (yet) */ |
int * cmd_cd(char **argv, cliuser_t *usr) |
{ |
int argc, rc = 0; |
argc = cli_count_args(argv); |
/* We don't yet play nice with whitespace, a getopt implementation should |
* protect "quoted\ destination" as a single argument. Its not our job to |
* look for && || or redirection as the tokenizer should have done that |
* (currently, it does not) */ |
if (argc > 2) { |
cli_error(CL_EFAIL, "Too many arguments to `%s'", cmdname); |
return CMD_FAILURE; |
} |
if (argc < 2) { |
printf("%s - no directory specified. Try `help %s extended'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
/* We have the correct # of arguments |
* TODO: handle tidle (~) expansion? */ |
rc = chdir(argv[1]); |
if (rc == 0) { |
cli_set_prompt(usr); |
return CMD_SUCCESS; |
} else { |
switch (rc) { |
case ENOMEM: |
cli_error(CL_EFAIL, "Destination path too long"); |
break; |
case ENOENT: |
cli_error(CL_ENOENT, "Invalid directory `%s'", argv[1]); |
break; |
default: |
cli_error(CL_EFAIL, "Unable to change to `%s'", argv[1]); |
break; |
} |
} |
return CMD_FAILURE; |
} |
/branches/network/uspace/app/bdsh/cmds/builtins/cd/cd_def.h |
---|
0,0 → 1,14 |
{ |
"cd", |
"Change the current working directory", |
&cmd_cd, |
&help_cmd_cd, |
-1 |
}, |
{ |
"chdir", |
NULL, |
&cmd_cd, |
&help_cmd_cd, |
-1 |
}, |
/branches/network/uspace/app/bdsh/cmds/builtins/cd/entry.h |
---|
0,0 → 1,12 |
#ifndef CD_ENTRY_H_ |
#define CD_ENTRY_H_ |
#include "scli.h" |
/* Entry points for the cd command */ |
extern void * help_cmd_cd(unsigned int); |
extern int * cmd_cd(char **, cliuser_t *); |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtins/cd/cd.h |
---|
0,0 → 1,7 |
#ifndef CD_H |
#define CD_H |
/* Prototypes for the cd command (excluding entry points) */ |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtins/builtins.h |
---|
0,0 → 1,13 |
#ifndef BUILTINS_H |
#define BUILTINS_H |
#include "config.h" |
#include "cd/entry.h" |
builtin_t builtins[] = { |
#include "cd/cd_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtins/README |
---|
0,0 → 1,21 |
Commands that need to modify the running user structure defined in scli.h |
should reside here. They (will) have a slightly different prototype that |
allows passing the user structure to them for ease of modifications. |
Examples of what should be a built-in and not a module would be: |
cd (cliuser_t->cwd needs to be updated) |
In the future, more user preferences will be set via built-in commands, |
such as the formatting of the prompt string (HelenOS doesn't yet have |
an environment, much less PS*, even if it did we'd likely do it a little |
differently). |
.... etc. |
Anything that does _not_ need to use this structure should be included |
as a module, not a built in. If you want to include a new command, there |
is a 99% chance that you want it to be a module. |
/branches/network/uspace/app/bdsh/cmds/builtins/builtin_aliases.h |
---|
0,0 → 1,11 |
#ifndef BUILTIN_ALIASES_H |
#define BUILTIN_ALIASES_H |
/* See modules/module_aliases.h for an explanation of this file */ |
char *builtin_aliases[] = { |
"chdir", "cd", |
NULL, NULL |
}; |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch.c |
---|
0,0 → 1,107 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
*/ |
/* TODO: Options that people would expect, such as not creating the file if |
* it doesn't exist, specifying the access time, etc */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <sys/types.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
#include "entry.h" |
#include "touch.h" |
#include "cmds.h" |
static char *cmdname = "touch"; |
/* Dispays help for touch in various levels */ |
void * help_cmd_touch(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' updates access times for files\n", cmdname); |
} else { |
help_cmd_touch(HELP_SHORT); |
printf(" `%s' <file>, if the file does not exist it will be " |
"created\n", cmdname); |
} |
return CMD_VOID; |
} |
/* Main entry point for touch, accepts an array of arguments */ |
int * cmd_touch(char **argv) |
{ |
unsigned int argc, i = 0, ret = 0; |
int fd; |
char *buff = NULL; |
DIR *dirp; |
argc = cli_count_args(argv); |
if (argc == 1) { |
printf("%s - incorrect number of arguments. Try `help %s extended'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
for (i = 1; i < argc; i ++) { |
buff = cli_strdup(argv[i]); |
dirp = opendir(buff); |
if (dirp) { |
cli_error(CL_ENOTSUP, "%s is a directory", buff); |
closedir(dirp); |
ret ++; |
continue; |
} |
fd = open(buff, O_RDWR | O_CREAT); |
if (fd < 0) { |
cli_error(CL_EFAIL, "Could not update / create %s ", buff); |
ret ++; |
continue; |
} else |
close(fd); |
free(buff); |
} |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch_def.h |
---|
0,0 → 1,8 |
{ |
"touch", |
"Create files or update access times", |
&cmd_touch, |
&help_cmd_touch, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/touch/entry.h |
---|
0,0 → 1,9 |
#ifndef TOUCH_ENTRY_H |
#define TOUCH_ENTRY_H |
/* Entry points for the touch command */ |
extern int * cmd_touch(char **); |
extern void * help_cmd_touch(unsigned int); |
#endif /* TOUCH_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch.h |
---|
0,0 → 1,8 |
#ifndef TOUCH_H |
#define TOUCH_H |
/* Prototypes for the touch command, excluding entry points */ |
#endif /* TOUCH_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c |
---|
0,0 → 1,251 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <getopt.h> |
#include <stdarg.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
#include "entry.h" |
#include "mkdir.h" |
#include "cmds.h" |
#define MKDIR_VERSION "0.0.1" |
static char *cmdname = "mkdir"; |
static struct option const long_options[] = { |
{"parents", no_argument, 0, 'p'}, |
{"verbose", no_argument, 0, 'v'}, |
{"mode", required_argument, 0, 'm'}, |
{"help", no_argument, 0, 'h'}, |
{"version", no_argument, 0, 'V'}, |
{"follow", no_argument, 0, 'f'}, |
{0, 0, 0, 0} |
}; |
void * help_cmd_mkdir(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' creates a new directory\n", cmdname); |
} else { |
help_cmd_mkdir(HELP_SHORT); |
printf( |
"Usage: %s [options] <path>\n" |
"Options:\n" |
" -h, --help A short option summary\n" |
" -V, --version Print version information and exit\n" |
" -p, --parents Create needed parents for <path>\n" |
" -m, --mode Set permissions to [mode] (UNUSED)\n" |
" -v, --verbose Be extremely noisy about what is happening\n" |
" -f, --follow Go to the new directory once created\n" |
"Currently, %s is under development, some options don't work.\n", |
cmdname, cmdname); |
} |
return CMD_VOID; |
} |
/* This is kind of clunky, but effective for now */ |
static unsigned int |
create_directory(const char *path, unsigned int p) |
{ |
DIR *dirp; |
char *tmp = NULL, *buff = NULL, *wdp = NULL; |
char *dirs[255]; |
unsigned int absolute = 0, i = 0, ret = 0; |
/* Its a good idea to allocate path, plus we (may) need a copy of |
* path to tokenize if parents are specified */ |
if (NULL == (tmp = cli_strdup(path))) { |
cli_error(CL_ENOMEM, "%s: path too big?", cmdname); |
return 1; |
} |
if (NULL == (wdp = (char *) malloc(PATH_MAX))) { |
cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname); |
free(tmp); |
return 1; |
} |
/* The only reason for wdp is to be (optionally) verbose */ |
getcwd(wdp, PATH_MAX); |
/* Typical use without specifying the creation of parents */ |
if (p == 0) { |
dirp = opendir(tmp); |
if (dirp) { |
cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path); |
closedir(dirp); |
goto finit; |
} |
if (-1 == (mkdir(tmp, 0))) { |
cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path); |
goto finit; |
} |
} |
/* Parents need to be created, path has to be broken up */ |
/* See if path[0] is a slash, if so we have to remember to append it */ |
if (tmp[0] == '/') |
absolute = 1; |
/* TODO: Canonify the path prior to tokenizing it, see below */ |
dirs[i] = cli_strtok(tmp, "/"); |
while (dirs[i] && i < 255) |
dirs[++i] = cli_strtok(NULL, "/"); |
if (NULL == dirs[0]) |
return 1; |
if (absolute == 1) { |
asprintf(&buff, "/%s", dirs[0]); |
mkdir(buff, 0); |
chdir(buff); |
free(buff); |
getcwd(wdp, PATH_MAX); |
i = 1; |
} else { |
i = 0; |
} |
while (dirs[i] != NULL) { |
/* Sometimes make or scripts conjoin odd paths. Account for something |
* like this: ../../foo/bar/../foo/foofoo/./bar */ |
if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) { |
if (0 != (chdir(dirs[i]))) { |
cli_error(CL_EFAIL, "%s: impossible path: %s", |
cmdname, path); |
ret ++; |
goto finit; |
} |
getcwd(wdp, PATH_MAX); |
} else { |
if (-1 == (mkdir(dirs[i], 0))) { |
cli_error(CL_EFAIL, |
"%s: failed at %s/%s", wdp, dirs[i]); |
ret ++; |
goto finit; |
} |
if (0 != (chdir(dirs[i]))) { |
cli_error(CL_EFAIL, "%s: failed creating %s\n", |
cmdname, dirs[i]); |
ret ++; |
break; |
} |
} |
i++; |
} |
goto finit; |
finit: |
free(wdp); |
free(tmp); |
return ret; |
} |
int * cmd_mkdir(char **argv) |
{ |
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0; |
unsigned int verbose = 0; |
int c, opt_ind; |
char *cwd; |
argc = cli_count_args(argv); |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind); |
switch (c) { |
case 'p': |
create_parents = 1; |
break; |
case 'v': |
verbose = 1; |
break; |
case 'h': |
help_cmd_mkdir(HELP_LONG); |
return CMD_SUCCESS; |
case 'V': |
printf("%s\n", MKDIR_VERSION); |
return CMD_SUCCESS; |
case 'f': |
follow = 1; |
break; |
case 'm': |
printf("%s: [W] Ignoring mode %s\n", cmdname, optarg); |
break; |
} |
} |
argc -= optind; |
if (argc < 1) { |
printf("%s - incorrect number of arguments. Try `%s --help'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
if (NULL == (cwd = (char *) malloc(PATH_MAX))) { |
cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname); |
return CMD_FAILURE; |
} |
memset(cwd, 0, sizeof(cwd)); |
getcwd(cwd, PATH_MAX); |
for (i = optind; argv[i] != NULL; i++) { |
if (verbose == 1) |
printf("%s: creating %s%s\n", |
cmdname, argv[i], |
create_parents ? " (and all parents)" : ""); |
ret += create_directory(argv[i], create_parents); |
} |
if (follow == 0) |
chdir(cwd); |
free(cwd); |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h |
---|
0,0 → 1,16 |
{ |
"mkdir", |
"Create new directories", |
&cmd_mkdir, |
&help_cmd_mkdir, |
0 |
}, |
{ |
"md", |
NULL, |
&cmd_mkdir, |
&help_cmd_mkdir, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir.h |
---|
0,0 → 1,8 |
#ifndef MKDIR_H |
#define MKDIR_H |
/* Prototypes for the mkdir command, excluding entry points */ |
static unsigned int create_directory(const char *, unsigned int); |
#endif /* MKDIR_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/entry.h |
---|
0,0 → 1,9 |
#ifndef MKDIR_ENTRY_H |
#define MKDIR_ENTRY_H |
/* Entry points for the mkdir command */ |
extern int * cmd_mkdir(char **); |
extern void * help_cmd_mkdir(unsigned int); |
#endif /* MKDIR_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat.c |
---|
0,0 → 1,186 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <getopt.h> |
#include <string.h> |
#include <fcntl.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "cat.h" |
#include "cmds.h" |
static char *cmdname = "cat"; |
#define CAT_VERSION "0.0.1" |
#define CAT_DEFAULT_BUFLEN 1024 |
static char *cat_oops = "That option is not yet supported\n"; |
static struct option const long_options[] = { |
{ "help", no_argument, 0, 'h' }, |
{ "version", no_argument, 0, 'v' }, |
{ "head", required_argument, 0, 'H' }, |
{ "tail", required_argument, 0, 't' }, |
{ "buffer", required_argument, 0, 'b' }, |
{ "more", no_argument, 0, 'm' }, |
{ 0, 0, 0, 0 } |
}; |
/* Dispays help for cat in various levels */ |
void * help_cmd_cat(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' shows the contents of files\n", cmdname); |
} else { |
help_cmd_cat(HELP_SHORT); |
printf( |
"Usage: %s [options] <file1> [file2] [...]\n" |
"Options:\n" |
" -h, --help A short option summary\n" |
" -v, --version Print version information and exit\n" |
" -H, --head ## Print only the first ## bytes\n" |
" -t, --tail ## Print only the last ## bytes\n" |
" -b, --buffer ## Set the read buffer size to ##\n" |
" -m, --more Pause after each screen full\n" |
"Currently, %s is under development, some options don't work.\n", |
cmdname, cmdname); |
} |
return CMD_VOID; |
} |
static unsigned int cat_file(const char *fname, size_t blen) |
{ |
int fd, bytes = 0, count = 0, reads = 0; |
off_t total = 0; |
char *buff = NULL; |
if (-1 == (fd = open(fname, O_RDONLY))) { |
printf("Unable to open %s\n", fname); |
return 1; |
} |
total = lseek(fd, 0, SEEK_END); |
lseek(fd, 0, SEEK_SET); |
if (NULL == (buff = (char *) malloc(blen + 1))) { |
close(fd); |
printf("Unable to allocate enough memory to read %s\n", |
fname); |
return 1; |
} |
do { |
memset(buff, 0, sizeof(buff)); |
bytes = read(fd, buff, blen); |
if (bytes > 0) { |
count += bytes; |
if (bytes < blen) |
buff[bytes] = '\0'; |
printf(buff); |
reads++; |
} |
} while (bytes > 0); |
close(fd); |
if (bytes == -1) { |
printf("Error reading %s\n", fname); |
free(buff); |
return 1; |
} |
/* Debug stuff, newline not added purposefully */ |
printf("** %s is a file with the size of %ld bytes\n", |
fname, total); |
printf( "** %d bytes were read in a buffer of %d bytes in %d reads\n", |
count, blen, reads); |
printf("** Read %s\n", count == total ? "Succeeded" : "Failed"); |
free(buff); |
return 0; |
} |
/* Main entry point for cat, accepts an array of arguments */ |
int * cmd_cat(char **argv) |
{ |
unsigned int argc, i, ret = 0, buffer = 0; |
int c, opt_ind; |
argc = cli_count_args(argv); |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "hvmH:t:b:", long_options, &opt_ind); |
switch (c) { |
case 'h': |
help_cmd_cat(HELP_LONG); |
return CMD_SUCCESS; |
case 'v': |
printf("%s\n", CAT_VERSION); |
return CMD_SUCCESS; |
case 'H': |
printf(cat_oops); |
return CMD_FAILURE; |
case 't': |
printf(cat_oops); |
return CMD_FAILURE; |
case 'b': |
printf(cat_oops); |
break; |
case 'm': |
printf(cat_oops); |
return CMD_FAILURE; |
} |
} |
argc -= optind; |
if (argc < 1) { |
printf("%s - incorrect number of arguments. Try `%s --help'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
if (buffer <= 0) |
buffer = CAT_DEFAULT_BUFLEN; |
for (i = optind; argv[i] != NULL; i++) |
ret += cat_file(argv[i], buffer); |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat_def.h |
---|
0,0 → 1,8 |
{ |
"cat", |
"Show the contents of a file", |
&cmd_cat, |
&help_cmd_cat, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat.h |
---|
0,0 → 1,9 |
#ifndef CAT_H |
#define CAT_H |
/* Prototypes for the cat command, excluding entry points */ |
static unsigned int cat_file(const char *, size_t); |
#endif /* CAT_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/cat/entry.h |
---|
0,0 → 1,9 |
#ifndef CAT_ENTRY_H |
#define CAT_ENTRY_H |
/* Entry points for the cat command */ |
extern int * cmd_cat(char **); |
extern void * help_cmd_cat(unsigned int); |
#endif /* CAT_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/help/help.c |
---|
0,0 → 1,162 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "config.h" |
#include "entry.h" |
#include "help.h" |
#include "cmds.h" |
#include "modules.h" |
#include "builtins.h" |
#include "errors.h" |
#include "util.h" |
static char *cmdname = "help"; |
extern const char *progname; |
#define HELP_IS_MODULE 1 |
#define HELP_IS_BUILTIN 0 |
#define HELP_IS_RUBBISH -1 |
volatile int mod_switch = -1; |
/* Just use a pointer here, no need for mod_switch */ |
static int is_mod_or_builtin(char *cmd) |
{ |
int rc = HELP_IS_RUBBISH; |
rc = is_builtin(cmd); |
if (rc > -1) { |
mod_switch = rc; |
return HELP_IS_BUILTIN; |
} |
rc = is_module(cmd); |
if (rc > -1) { |
mod_switch = rc; |
return HELP_IS_MODULE; |
} |
return HELP_IS_RUBBISH; |
} |
void *help_cmd_help(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf( |
"\n %s [command] <extended>\n" |
" Use help [command] extended for detailed help on [command] " |
", even `help'\n\n", cmdname); |
} else { |
printf( |
"\n `%s' - shows help for commands\n" |
" Examples:\n" |
" %s [command] Show help for [command]\n" |
" %s [command] extended Show extended help for [command]\n" |
"\n If no argument is given to %s, a list of commands are shown\n\n", |
cmdname, cmdname, cmdname, cmdname); |
} |
return CMD_VOID; |
} |
int *cmd_help(char *argv[]) |
{ |
module_t *mod; |
builtin_t *cmd; |
unsigned int i = 0; |
int rc = 0; |
int argc; |
int level = HELP_SHORT; |
argc = cli_count_args(argv); |
if (argc > 3) { |
printf("\nToo many arguments to `%s', try:\n", cmdname); |
help_cmd_help(HELP_SHORT); |
return CMD_FAILURE; |
} |
if (argc == 3) { |
if (!strcmp("extended", argv[2])) |
level = HELP_LONG; |
else |
level = HELP_SHORT; |
} |
if (argc > 1) { |
rc = is_mod_or_builtin(argv[1]); |
switch (rc) { |
case HELP_IS_RUBBISH: |
printf("Invalid command %s\n", argv[1]); |
return CMD_FAILURE; |
case HELP_IS_MODULE: |
help_module(mod_switch, level); |
return CMD_SUCCESS; |
case HELP_IS_BUILTIN: |
help_builtin(mod_switch, level); |
return CMD_SUCCESS; |
} |
} |
printf("\n Available commands are:\n"); |
printf(" ------------------------------------------------------------\n"); |
/* First, show a list of built in commands that are available in this mode */ |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (!builtin_is_restricted(i)) { |
if (is_builtin_alias(cmd->name)) |
printf(" %-16s\tAlias for `%s'\n", cmd->name, |
alias_for_builtin(cmd->name)); |
else |
printf(" %-16s\t%s\n", cmd->name, cmd->desc); |
} |
} |
i = 0; |
/* Now, show a list of module commands that are available in this mode */ |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (!module_is_restricted(i)) { |
if (is_module_alias(mod->name)) |
printf(" %-16s\tAlias for `%s'\n", mod->name, |
alias_for_module(mod->name)); |
else |
printf(" %-16s\t%s\n", mod->name, mod->desc); |
} |
} |
printf("\n Try %s %s for more information on how `%s' works.\n\n", |
cmdname, cmdname, cmdname); |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/help/help_def.h |
---|
0,0 → 1,7 |
{ |
"help", |
"Show help for commands", |
&cmd_help, |
&help_cmd_help, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/help/help.h |
---|
0,0 → 1,7 |
#ifndef HELP_H |
#define HELP_H |
/* Prototypes for the help command (excluding entry points) */ |
static int is_mod_or_builtin(char *); |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/help/entry.h |
---|
0,0 → 1,8 |
#ifndef HELP_ENTRY_H_ |
#define HELP_ENTRY_H_ |
/* Entry points for the help command */ |
extern void * help_cmd_help(unsigned int); |
extern int * cmd_help(char *[]); |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
0,0 → 1,196 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
*/ |
/* NOTE: |
* This is a bit of an ugly hack, working around the absence of fstat / etc. |
* As more stuff is completed and exposed in libc, this will improve */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <string.h> |
#include "errors.h" |
#include "config.h" |
#include "util.h" |
#include "entry.h" |
#include "ls.h" |
#include "cmds.h" |
static char *cmdname = "ls"; |
static unsigned int ls_scope(const char *path) |
{ |
int fd; |
DIR *dirp; |
dirp = opendir(path); |
if (dirp) { |
closedir(dirp); |
return LS_DIR; |
} |
fd = open(path, O_RDONLY); |
if (fd > 0) { |
close(fd); |
return LS_FILE; |
} |
return LS_BOGUS; |
} |
static void ls_scan_dir(const char *d, DIR *dirp) |
{ |
struct dirent *dp; |
unsigned int scope; |
char *buff; |
if (! dirp) |
return; |
buff = (char *)malloc(PATH_MAX); |
if (NULL == buff) { |
cli_error(CL_ENOMEM, "ls: failed to scan %s", d); |
return; |
} |
while ((dp = readdir(dirp))) { |
memset(buff, 0, sizeof(buff)); |
/* Don't worry if inserting a double slash, this will be fixed by |
* absolutize() later with subsequent calls to open() or readdir() */ |
snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_DIR: |
ls_print_dir(dp->d_name); |
break; |
case LS_FILE: |
ls_print_file(dp->d_name); |
break; |
case LS_BOGUS: |
/* Odd chance it was deleted from the time readdir() found |
* it and the time that it was scoped */ |
printf("ls: skipping bogus node %s\n", dp->d_name); |
break; |
} |
} |
free(buff); |
return; |
} |
/* ls_print_* currently does nothing more than print the entry. |
* in the future, we will likely pass the absolute path, and |
* some sort of ls_options structure that controls how each |
* entry is printed and what is printed about it. |
* |
* Now we just print basic DOS style lists */ |
static void ls_print_dir(const char *d) |
{ |
printf("%-40s\t<DIR>\n", d); |
return; |
} |
static void ls_print_file(const char *f) |
{ |
printf("%-40s\n", f); |
return; |
} |
void * help_cmd_ls(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' lists files and directories.\n", cmdname); |
} else { |
help_cmd_ls(HELP_SHORT); |
printf(" `%s' [path], if no path is given the current " |
"working directory is used.\n", cmdname); |
} |
return CMD_VOID; |
} |
int * cmd_ls(char **argv) |
{ |
unsigned int argc; |
unsigned int scope; |
char *buff; |
DIR *dirp; |
argc = cli_count_args(argv); |
buff = (char *) malloc(PATH_MAX); |
if (NULL == buff) { |
cli_error(CL_ENOMEM, "%s: ", cmdname); |
return CMD_FAILURE; |
} |
memset(buff, 0, sizeof(buff)); |
if (argc == 1) |
getcwd(buff, PATH_MAX); |
else |
strncpy(buff, argv[1], PATH_MAX); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_BOGUS: |
cli_error(CL_ENOENT, buff); |
free(buff); |
return CMD_FAILURE; |
case LS_FILE: |
ls_print_file(buff); |
break; |
case LS_DIR: |
dirp = opendir(buff); |
if (! dirp) { |
/* May have been deleted between scoping it and opening it */ |
cli_error(CL_EFAIL, "Could not stat %s", buff); |
free(buff); |
return CMD_FAILURE; |
} |
ls_scan_dir(buff, dirp); |
closedir(dirp); |
break; |
} |
free(buff); |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls_def.h |
---|
0,0 → 1,16 |
{ |
"ls", |
"List files and directories", |
&cmd_ls, |
&help_cmd_ls, |
0 |
}, |
{ |
"dir", |
NULL, |
&cmd_ls, |
&help_cmd_ls, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.h |
---|
0,0 → 1,16 |
#ifndef LS_H |
#define LS_H |
/* Various values that can be returned by ls_scope() */ |
#define LS_BOGUS 0 |
#define LS_FILE 1 |
#define LS_DIR 2 |
static unsigned int ls_scope(const char *); |
static void ls_scan_dir(const char *, DIR *); |
static void ls_print_dir(const char *); |
static void ls_print_file(const char *); |
#endif /* LS_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/ls/entry.h |
---|
0,0 → 1,9 |
#ifndef LS_ENTRY_H |
#define LS_ENTRY_H |
/* Entry points for the ls command */ |
extern int * cmd_ls(char **); |
extern void * help_cmd_ls(unsigned int); |
#endif /* LS_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm.c |
---|
0,0 → 1,254 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <assert.h> |
#include <getopt.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
#include "entry.h" |
#include "rm.h" |
#include "cmds.h" |
static char *cmdname = "rm"; |
#define RM_VERSION "0.0.1" |
static rm_job_t rm; |
static struct option const long_options[] = { |
{ "help", no_argument, 0, 'h' }, |
{ "version", no_argument, 0, 'v' }, |
{ "recursive", no_argument, 0, 'r' }, |
{ "force", no_argument, 0, 'f' }, |
{ "safe", no_argument, 0, 's' }, |
{ 0, 0, 0, 0 } |
}; |
static unsigned int rm_start(rm_job_t *rm) |
{ |
rm->recursive = 0; |
rm->force = 0; |
rm->safe = 0; |
/* Make sure we can allocate enough memory to store |
* what is needed in the job structure */ |
if (NULL == (rm->nwd = (char *) malloc(PATH_MAX))) |
return 0; |
memset(rm->nwd, 0, sizeof(rm->nwd)); |
if (NULL == (rm->owd = (char *) malloc(PATH_MAX))) |
return 0; |
memset(rm->owd, 0, sizeof(rm->owd)); |
if (NULL == (rm->cwd = (char *) malloc(PATH_MAX))) |
return 0; |
memset(rm->cwd, 0, sizeof(rm->cwd)); |
chdir("."); |
if (NULL == (getcwd(rm->owd, PATH_MAX))) |
return 0; |
return 1; |
} |
static void rm_end(rm_job_t *rm) |
{ |
if (NULL != rm->nwd) |
free(rm->nwd); |
if (NULL != rm->owd) |
free(rm->owd); |
if (NULL != rm->cwd) |
free(rm->cwd); |
return; |
} |
static unsigned int rm_recursive(const char *path) |
{ |
int rc; |
/* First see if it will just go away */ |
rc = rmdir(path); |
if (rc == 0) |
return 0; |
/* Its not empty, recursively scan it */ |
cli_error(CL_ENOTSUP, |
"Can not remove %s, directory not empty", path); |
return 1; |
} |
static unsigned int rm_single(const char *path) |
{ |
if (unlink(path)) { |
cli_error(CL_EFAIL, "rm: could not remove file %s", path); |
return 1; |
} |
return 0; |
} |
static unsigned int rm_scope(const char *path) |
{ |
int fd; |
DIR *dirp; |
dirp = opendir(path); |
if (dirp) { |
closedir(dirp); |
return RM_DIR; |
} |
fd = open(path, O_RDONLY); |
if (fd > 0) { |
close(fd); |
return RM_FILE; |
} |
return RM_BOGUS; |
} |
/* Dispays help for rm in various levels */ |
void * help_cmd_rm(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' removes files and directories.\n", cmdname); |
} else { |
help_cmd_rm(HELP_SHORT); |
printf( |
"Usage: %s [options] <path>\n" |
"Options:\n" |
" -h, --help A short option summary\n" |
" -v, --version Print version information and exit\n" |
" -r, --recursive Recursively remove sub directories\n" |
" -f, --force Do not prompt prior to removing files\n" |
" -s, --safe Stop if directories change during removal\n\n" |
"Currently, %s is under development, some options don't work.\n", |
cmdname, cmdname); |
} |
return CMD_VOID; |
} |
/* Main entry point for rm, accepts an array of arguments */ |
int * cmd_rm(char **argv) |
{ |
unsigned int argc; |
unsigned int i, scope, ret = 0; |
int c, opt_ind; |
size_t len; |
char *buff = NULL; |
argc = cli_count_args(argv); |
if (argc < 2) { |
cli_error(CL_EFAIL, |
"%s: insufficient arguments. Try %s --help", cmdname, cmdname); |
return CMD_FAILURE; |
} |
if (!rm_start(&rm)) { |
cli_error(CL_ENOMEM, "%s: could not initialize", cmdname); |
rm_end(&rm); |
return CMD_FAILURE; |
} |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind); |
switch (c) { |
case 'h': |
help_cmd_rm(HELP_LONG); |
return CMD_SUCCESS; |
case 'v': |
printf("%s\n", RM_VERSION); |
return CMD_SUCCESS; |
case 'r': |
rm.recursive = 1; |
break; |
case 'f': |
rm.force = 1; |
break; |
case 's': |
rm.safe = 1; |
break; |
} |
} |
if (optind == argc) { |
cli_error(CL_EFAIL, |
"%s: insufficient arguments. Try %s --help", cmdname, cmdname); |
rm_end(&rm); |
return CMD_FAILURE; |
} |
i = optind; |
while (NULL != argv[i]) { |
len = strlen(argv[i]) + 2; |
buff = (char *) realloc(buff, len); |
assert(buff != NULL); |
memset(buff, 0, sizeof(buff)); |
snprintf(buff, len, argv[i]); |
scope = rm_scope(buff); |
switch (scope) { |
case RM_BOGUS: /* FIXME */ |
case RM_FILE: |
ret += rm_single(buff); |
break; |
case RM_DIR: |
if (! rm.recursive) { |
printf("%s is a directory, use -r to remove it.\n", buff); |
ret ++; |
} else { |
ret += rm_recursive(buff); |
} |
break; |
} |
i++; |
} |
if (NULL != buff) |
free(buff); |
rm_end(&rm); |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm_def.h |
---|
0,0 → 1,16 |
{ |
"rm", |
"Remove files and directories", |
&cmd_rm, |
&help_cmd_rm, |
0 |
}, |
{ |
"del", |
NULL, |
&cmd_rm, |
&help_cmd_rm, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm.h |
---|
0,0 → 1,43 |
#ifndef RM_H |
#define RM_H |
/* Return values for rm_scope() */ |
#define RM_BOGUS 0 |
#define RM_FILE 1 |
#define RM_DIR 2 |
/* Flags for rm_update() */ |
#define _RM_ENTRY 0 |
#define _RM_ADVANCE 1 |
#define _RM_REWIND 2 |
#define _RM_EXIT 3 |
/* A simple job structure */ |
typedef struct { |
/* Options set at run time */ |
unsigned int force; /* -f option */ |
unsigned int recursive; /* -r option */ |
unsigned int safe; /* -s option */ |
/* Keeps track of the job in progress */ |
int advance; /* How far deep we've gone since entering */ |
DIR *entry; /* Entry point to the tree being removed */ |
char *owd; /* Where we were when we invoked rm */ |
char *cwd; /* Current directory being transversed */ |
char *nwd; /* Next directory to be transversed */ |
/* Counters */ |
int f_removed; /* Number of files unlinked */ |
int d_removed; /* Number of directories unlinked */ |
} rm_job_t; |
/* Prototypes for the rm command, excluding entry points */ |
static unsigned int rm_start(rm_job_t *); |
static void rm_end(rm_job_t *rm); |
static unsigned int rm_recursive(const char *); |
static unsigned int rm_single(const char *); |
static unsigned int rm_scope(const char *); |
#endif /* RM_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/rm/entry.h |
---|
0,0 → 1,9 |
#ifndef RM_ENTRY_H |
#define RM_ENTRY_H |
/* Entry points for the rm command */ |
extern int * cmd_rm(char **); |
extern void * help_cmd_rm(unsigned int); |
#endif /* RM_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/quit/quit_def.h |
---|
0,0 → 1,14 |
{ |
"quit", |
"Exit the console", |
&cmd_quit, |
&help_cmd_quit, |
-1 |
}, |
{ |
"exit", |
NULL, |
&cmd_quit, |
&help_cmd_quit, |
-1 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/quit/quit.c |
---|
0,0 → 1,55 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "entry.h" |
#include "quit.h" |
#include "cmds.h" |
static char *cmdname = "quit"; |
extern volatile unsigned int cli_quit; |
extern const char *progname; |
void * help_cmd_quit(unsigned int level) |
{ |
printf("Type `%s' to exit %s\n", cmdname, progname); |
return CMD_VOID; |
} |
/* Quits the program and returns the status of whatever command |
* came before invoking 'quit' */ |
int * cmd_quit(char *argv[]) |
{ |
/* Inform that we're outta here */ |
cli_quit = 1; |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/quit/entry.h |
---|
0,0 → 1,10 |
#ifndef QUIT_ENTRY_H_ |
#define QUIT_ENTRY_H_ |
/* Entry points for the quit command */ |
extern void * help_cmd_quit(unsigned int); |
extern int * cmd_quit(char *[]); |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/quit/quit.h |
---|
0,0 → 1,6 |
#ifndef QUIT_H |
#define QUIT_H |
/* Prototypes for the quit command (excluding entry points) */ |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h |
---|
0,0 → 1,7 |
{ |
"pwd", |
"Prints the current working directory", |
&cmd_pwd, |
&help_cmd_pwd, |
-1 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd.h |
---|
0,0 → 1,6 |
#ifndef PWD_H_ |
#define PWD_H_ |
/* Prototypes for the pwd command (excluding entry points) */ |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/pwd/entry.h |
---|
0,0 → 1,12 |
#ifndef PWD_ENTRY_H |
#define PWD_ENTRY_H |
#include "scli.h" |
/* Entry points for the pwd command */ |
extern void * help_cmd_pwd(unsigned int); |
extern int * cmd_pwd(char **); |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd.c |
---|
0,0 → 1,71 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "config.h" |
#include "errors.h" |
#include "entry.h" |
#include "cmds.h" |
#include "pwd.h" |
static char * cmdname = "pwd"; |
void * help_cmd_pwd(unsigned int level) |
{ |
printf("`%s' prints your current working directory.\n", cmdname); |
return CMD_VOID; |
} |
int * cmd_pwd(char *argv[]) |
{ |
char *buff; |
buff = (char *) malloc(PATH_MAX); |
if (NULL == buff) { |
cli_error(CL_ENOMEM, "%s:", cmdname); |
return CMD_FAILURE; |
} |
memset(buff, 0, sizeof(buff)); |
getcwd(buff, PATH_MAX); |
if (! buff) { |
cli_error(CL_EFAIL, |
"Unable to determine the current working directory"); |
free(buff); |
return CMD_FAILURE; |
} else { |
printf("%s\n", buff); |
free(buff); |
return CMD_SUCCESS; |
} |
} |
/branches/network/uspace/app/bdsh/cmds/modules/modules.h |
---|
0,0 → 1,45 |
#ifndef MODULES_H |
#define MODULES_H |
/* Each built in function has two files, one being an entry.h file which |
* prototypes the run/help entry functions, the other being a .def file |
* which fills the modules[] array according to the cmd_t structure |
* defined in cmds.h. |
* |
* To add or remove a module, just make a new directory in cmds/modules |
* for it and copy the 'show' example for basics, then include it here. |
* (or reverse the process to remove one) |
* |
* NOTE: See module_ aliases.h as well, this is where aliases (commands that |
* share an entry point with others) are indexed */ |
#include "config.h" |
/* Prototypes for each module's entry (help/exec) points */ |
#include "help/entry.h" |
#include "quit/entry.h" |
#include "mkdir/entry.h" |
#include "rm/entry.h" |
#include "cat/entry.h" |
#include "touch/entry.h" |
#include "ls/entry.h" |
#include "pwd/entry.h" |
/* Each .def function fills the module_t struct with the individual name, entry |
* point, help entry point, etc. You can use config.h to control what modules |
* are loaded based on what libraries exist on the system. */ |
module_t modules[] = { |
#include "help/help_def.h" |
#include "quit/quit_def.h" |
#include "mkdir/mkdir_def.h" |
#include "rm/rm_def.h" |
#include "cat/cat_def.h" |
#include "touch/touch_def.h" |
#include "ls/ls_def.h" |
#include "pwd/pwd_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/README |
---|
0,0 → 1,15 |
Modules are commands or full programs (anything can be made into a module |
that can return int type) should go here. Note, modules do not (can not) |
update or read cliuser_t. |
Stuff that needs to write to the user structures contained in scli.h should |
be made as built-in commands, not modules, but there are very few times when |
you would want to do that. |
See the README file in the bdsh root directory for a quick overview of how to |
write a new command, or convert an existig stand-alone program into a module |
for BDSH. |
/branches/network/uspace/app/bdsh/cmds/modules/module_aliases.h |
---|
0,0 → 1,22 |
#ifndef MODULE_ALIASES_H |
#define MODULE_ALIASES_H |
/* Modules that declare multiple names for themselves but use the |
* same entry functions are aliases. This array helps to determine if |
* a module is an alias, as such it can be invoked differently. |
* format is alias , real_name */ |
/* So far, this is only used in the help display but could be used to |
* handle a module differently even prior to reaching its entry code. |
* For instance, 'exit' could behave differently than 'quit', prior to |
* the entry point being reached. */ |
char *mod_aliases[] = { |
"exit", "quit", |
"md", "mkdir", |
"del", "rm", |
"dir", "ls", |
NULL, NULL |
}; |
#endif |
/branches/network/uspace/app/bdsh/cmds/mknewcmd |
---|
0,0 → 1,347 |
#!/bin/sh |
# Copyright (C) 2008 Tim Post - 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. |
# |
# Neither the name of the original program's authors nor the names of its |
# contributors may be used to endorse or promote products derived from this |
# software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
# Script to generate skeletal files for a new command |
# Uses `getopt', not quite a bash-ism but might be |
# lacking on some legacy systems. |
# If your shell does not support eval, shift (x) or |
# here-now documents, sorry :) |
usage() |
{ |
def="$DEFAULT_COMMAND" |
cat << EOF |
\`$PROGNAME' generates skeletal command files to simplify adding commands |
Usage: $PROGNAME [options] <location> |
Options: |
-n, --name Name of the command (default: ${def}) |
-d, --desc Short (20 30 chars) description of the command |
(def: "The $def command") |
-e, --entry Entry function of the command (def: cmd_${def}) |
-h, --help-entry Entry function for command help (def: help_cmd_${def}) |
-a, --alias Alias (nickname) for this command (def: none) |
-r, --restrict Restriction level (interactive, non-interactive, both) |
(def: module is both, builtin is interactive only) |
-t, --type Type of command (module or builtin) (def: module) |
-H, --help This help summary |
-V, --version Print $PROGNAME version and exit normally |
Notes: |
You must supply at least the name of the command. |
If you do not specify a location (i.e. modules/foo), the command will be |
created in modules/command_name or builtins/command_name depending on your |
selection. |
This script will only create skeletal files and inform you what headers |
need to be modified to incorporate the command. You will also have to |
manually update the main Makefile. |
This script is intended only to be a convenience for developers. Example use: |
$PROGNAME -n foo -d "Foo power" -a bar -r both -t module modules/foo |
The example would generate a modular command named 'foo', which is also |
reached by typing 'bar' and available in either interactive or noninteractive |
mode. |
Skeletal files do *not* depend on the autoconf generated "config.h" unless you |
include it. This may or may not be desirable depending on your use. |
Report bugs to $PROGMAINT |
EOF |
} |
# Convert a string to all uppercase |
toupper() |
{ |
local str="$1" |
echo "${str}" | tr 'a-z' 'A-Z' |
} |
# Template stored `here-now' style, this generates all files needed |
# for a new command according to arguments passed. |
generate_code() |
{ |
echo "Creating ${OUTDIR}/${CMDNAME}_def.h ..." |
cat << EOF > ${OUTDIR}/${CMDNAME}_def.h |
{ |
"${CMDNAME}", |
"${CMDDESC}", |
&${CMDENTRY}, |
&${HELPENTRY}, |
${CMDRESTRICT} |
}, |
EOF |
[ -n "${CMDALIAS}" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}_def.h |
{ |
"${CMDALIAS}", |
NULL, |
&${CMDENTRY}, |
&${HELPENTRY}, |
${CMDRESTRICT} |
}, |
EOF |
local defname=$(toupper "${CMDNAME}") |
echo "Creating ${OUTDIR}/entry.h ..." |
cat << EOF > ${OUTDIR}/entry.h |
#ifndef ${defname}_ENTRY_H |
#define ${defname}_ENTRY_H |
EOF |
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h |
/* Entry points for the ${CMDNAME} command */ |
extern int * ${CMDENTRY}(char **); |
extern void * ${HELPENTRY}(unsigned int); |
#endif /* ${defname}_ENTRY_H */ |
EOF |
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/entry.h |
/* Pick up cliuser_t */ |
#include "scli.h" |
/* Entry points for the ${CMDNAME} command */ |
extern int * ${CMDENTRY}(char **, cliuser_t *); |
extern void * ${HELPENTRY}(unsigned int); |
#endif /* ${defname}_ENTRY_H */ |
EOF |
echo "Creating ${OUTDIR}/${CMDNAME}.h ..." |
cat << EOF > ${OUTDIR}/${CMDNAME}.h |
#ifndef ${defname}_H |
#define ${defname}_H |
/* Prototypes for the ${CMDNAME} command, excluding entry points */ |
#endif /* ${defname}_H */ |
EOF |
echo "Creating ${OUTDIR}/${CMDNAME}.c ..." |
cat << EOF > ${OUTDIR}/${CMDNAME}.c |
/* Automatically generated by ${PROGNAME} on ${TIMESTAMP} |
* This is machine generated output. The author of ${PROGNAME} claims no |
* copyright over the contents of this file. Where legally permitted, the |
* contents herein are donated to the public domain. |
* |
* You should apply any license and copyright that you wish to this file, |
* replacing this header in its entirety. */ |
#include <stdio.h> |
#include <stdlib.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "${CMDNAME}.h" |
#include "cmds.h" |
static char *cmdname = "${CMDNAME}"; |
/* Dispays help for ${CMDNAME} in various levels */ |
void * ${HELPENTRY}(unsigned int level) |
{ |
printf("This is the %s help for '%s'.\n", |
level ? EXT_HELP : SHORT_HELP, cmdname); |
return CMD_VOID; |
} |
EOF |
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
/* Main entry point for ${CMDNAME}, accepts an array of arguments */ |
int * ${CMDENTRY}(char **argv) |
EOF |
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
/* Main entry point for ${CMDNAME}, accepts an array of arguments and a |
* pointer to the cliuser_t structure */ |
int * ${CMDENTRY}(char **argv, cliuser_t *usr) |
EOF |
cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
{ |
unsigned int argc; |
unsigned int i; |
/* Count the arguments */ |
for (argc = 0; argv[argc] != NULL; argc ++); |
printf("%s %s\n", TEST_ANNOUNCE, cmdname); |
printf("%d arguments passed to %s", argc - 1, cmdname); |
if (argc < 2) { |
printf("\n"); |
return CMD_SUCCESS; |
} |
printf(":\n"); |
for (i = 1; i < argc; i++) |
printf("[%d] -> %s\n", i, argv[i]); |
return CMD_SUCCESS; |
} |
EOF |
printf "Done.\n\nYou should now modify %ss/%ss.h and ../Makefile" \ |
"${CMDTYPE}" "${CMDTYPE}" |
printf " to include your new command.\n" |
[ -n "$CMDALIAS" ] && { |
printf "\nYou should also modify %ss/%s_aliases.h and " \ |
"${CMDTYPE}" "${CMDTYPE}" |
printf "add %s as an alias for %s\n" \ |
"${CMDALIAS}" "${CMDNAME}" |
} |
printf "\nOnce completed, re-run make\n\n" |
} |
# Main program |
TIMESTAMP="$(date)" |
PROGNAME=$(basename $0) |
PROGVER="0.0.1" |
PROGMAINT="Tim Post <echo@echoreply.us>" |
DEFAULT_COMMAND="cmdname" |
# We need at least one |
[ $# = 0 ] && usage && exit 1; |
TEMP=$(getopt -o n:d:e:h:a:r:t:HV \ |
--long name:,desc:,entry:,help-entry:,alias:,restrict:,type:,help,version \ |
-- "$@") || { |
echo "Try $PROGNAME --help for help" |
} |
eval set -- "$TEMP" |
while true; do |
case "$1" in |
-n | --name) |
CMDNAME="$2" |
shift 2 |
continue |
;; |
-d | --desc) |
CMDDESC="$2" |
shift 2 |
continue |
;; |
-e | --entry) |
CMDENTRY="$2" |
shift 2 |
continue |
;; |
-h | --help-entry) |
HELPENTRY="$2" |
shift 2 |
continue |
;; |
-a | --alias) |
CMDALIAS="$2" |
shift 2 |
continue |
;; |
-r | --restrict) |
CMDRESTRICT="$2" |
shift 2 |
continue |
;; |
-t | --type) |
CMDTYPE="$2" |
shift 2 |
continue |
;; |
-H | --help) |
usage |
exit 0 |
;; |
-V | --version) |
echo "$PROGVER" |
exit 0 |
;; |
--) |
break |
;; |
esac |
done |
# Pick up a location if one was specified |
eval set -- "$*" |
[ -n "$2" ] && OUTDIR="$2" |
# Fill in defaults for whatever was not specified |
[ -n "$CMDNAME" ] || CMDNAME="$DEFAULT_COMMAND" |
[ -n "$CMDDESC" ] || CMDDESC="The $CMDNAME command" |
[ -n "$CMDENTRY" ] || CMDENTRY="cmd_${CMDNAME}" |
[ -n "$HELPENTRY" ] || HELPENTRY="help_cmd_${CMDNAME}" |
[ -n "$CMDTYPE" ] || CMDTYPE="module" |
[ -n "$OUTDIR" ] || OUTDIR="${CMDTYPE}s/${CMDNAME}" |
# Builtins typically only need to be available in interactive mode, |
# set the default accordingly. |
[ -n "$CMDRESTRICT" ] || { |
[ "$CMDTYPE" = "module" ] && CMDRESTRICT="both" |
[ "$CMDTYPE" = "builtin" ] && CMDRESTRICT="interactive" |
} |
# Set the restriction level as the structure expects to see it |
case "$CMDRESTRICT" in |
0 | both) |
CMDRESTRICT="0" |
;; |
1 | non-interactive) |
CMDRESTRICT="1" |
;; |
-1 | interactive) |
CMDRESTRICT="-1" |
;; |
*) |
usage |
exit 1 |
;; |
esac |
# Do a little sanity |
[ -d $OUTDIR ] && { |
echo "$OUTDIR already exists, remove it to proceed." |
exit 1 |
} |
mkdir -p ${OUTDIR} >/dev/null 2>&1 || { |
echo "Could not create ${OUTDIR}, aborting!" |
exit 1 |
} |
# Generate the files and inform on how to include them based on options |
generate_code |
exit 0 |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/network/uspace/app/bdsh/cmds/mod_cmds.c |
---|
0,0 → 1,156 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
*/ |
/* NOTES: |
* module_* functions are pretty much identical to builtin_* functions at this |
* point. On the surface, it would appear that making each function dual purpose |
* would be economical. |
* |
* These are kept separate because the structures (module_t and builtin_t) may |
* grow apart and become rather different, even though they're identical at this |
* point. |
* |
* To keep things easy to hack, everything is separated. In reality this only adds |
* 6 - 8 extra functions, but keeps each function very easy to read and modify. */ |
/* TODO: |
* Many of these could be unsigned, provided the modules and builtins themselves |
* can follow suit. Long term goal. */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "errors.h" |
#include "cmds.h" |
#include "module_aliases.h" |
extern volatile unsigned int cli_interactive; |
int module_is_restricted(int pos) |
{ |
/* Restriction Levels: |
* -1 -> Available only in interactive mode |
* 0 -> Available in any mode |
* 1 -> Available only in non-interactive mode */ |
module_t *mod = modules; |
mod += pos; |
/* We're interactive, and the module is OK to run */ |
if (cli_interactive && mod->restricted <= 0) |
return 0; |
/* We're not interactive, and the module is OK to run */ |
if (!cli_interactive && mod->restricted >= 0) |
return 0; |
/* Anything else is just a big fat no :) */ |
return 1; |
} |
/* Checks if an entry function matching command exists in modules[], if so |
* its position in the array is returned */ |
int is_module(const char *command) |
{ |
module_t *mod; |
unsigned int i = 0; |
if (NULL == command) |
return -2; |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (!strcmp(mod->name, command)) |
return i; |
} |
return -1; |
} |
/* Checks if a module is an alias (sharing an entry point with another |
* module). Returns 1 if so */ |
int is_module_alias(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return -1; |
for(i=0; mod_aliases[i] != NULL; i+=2) { |
if (!strcmp(mod_aliases[i], command)) |
return 1; |
} |
return 0; |
} |
/* Returns the name of the module that an alias points to */ |
char *alias_for_module(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return (char *)NULL; |
for(i=0; mod_aliases[i] != NULL; i++) { |
if (!strcmp(mod_aliases[i], command)) |
return (char *)mod_aliases[++i]; |
i++; |
} |
return (char *)NULL; |
} |
/* Invokes the 'help' entry function for the module at position (int) module, |
* which wants an unsigned int to determine brief or extended display. */ |
int help_module(int module, unsigned int extended) |
{ |
module_t *mod = modules; |
mod += module; |
if (NULL != mod->help) { |
mod->help(extended); |
return CL_EOK; |
} else |
return CL_ENOENT; |
} |
/* Invokes the module entry point modules[module], passing argv[] as an argument |
* stack. */ |
int run_module(int module, char *argv[]) |
{ |
module_t *mod = modules; |
mod += module; |
if (NULL != mod->entry) |
return ((int)mod->entry(argv)); |
return CL_ENOENT; |
} |
/branches/network/uspace/app/bdsh/cmds/cmds.h |
---|
0,0 → 1,73 |
#ifndef CMDS_H |
#define CMDS_H |
#include "config.h" |
#include "scli.h" |
/* Temporary to store strings */ |
#define EXT_HELP "extended" |
#define SHORT_HELP "short" |
#define TEST_ANNOUNCE "Hello, this is :" |
/* Simple levels of help displays */ |
#define HELP_SHORT 0 |
#define HELP_LONG 1 |
/* Acceptable buffer sizes (for strn functions) */ |
/* TODO: Move me, other files duplicate these needlessly */ |
#define BUFF_LARGE 1024 |
#define BUFF_SMALL 255 |
/* Return macros for int type entry points */ |
#define CMD_FAILURE (int*)1 |
#define CMD_SUCCESS 0 |
#define CMD_VOID (void *)NULL |
/* Types for module command entry and help */ |
typedef int * (* mod_entry_t)(char **); |
typedef void * (* mod_help_t)(unsigned int); |
/* Built-in commands need to be able to modify cliuser_t */ |
typedef int * (* builtin_entry_t)(char **, cliuser_t *); |
typedef void * (* builtin_help_t)(unsigned int); |
/* Module structure */ |
typedef struct { |
char *name; /* Name of the command */ |
char *desc; /* Description of the command */ |
mod_entry_t entry; /* Command (exec) entry function */ |
mod_help_t help; /* Command (help) entry function */ |
int restricted; /* Restricts to interactive/non-interactive only */ |
} module_t; |
/* Builtin structure, same as modules except different types of entry points */ |
typedef struct { |
char *name; |
char *desc; |
builtin_entry_t entry; |
builtin_help_t help; |
int restricted; |
} builtin_t; |
/* Declared in cmds/modules/modules.h and cmds/builtins/builtins.h |
* respectively */ |
extern module_t modules[]; |
extern builtin_t builtins[]; |
/* Prototypes for module launchers */ |
extern int module_is_restricted(int); |
extern int is_module(const char *); |
extern int is_module_alias(const char *); |
extern char * alias_for_module(const char *); |
extern int help_module(int, unsigned int); |
extern int run_module(int, char *[]); |
/* Prototypes for builtin launchers */ |
extern int builtin_is_restricted(int); |
extern int is_builtin(const char *); |
extern int is_builtin_alias(const char *); |
extern char * alias_for_builtin(const char *); |
extern int help_builtin(int, unsigned int); |
extern int run_builtin(int, char *[], cliuser_t *); |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtin_cmds.c |
---|
0,0 → 1,126 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
*/ |
/* Almost identical (for now) to mod_cmds.c , however this will not be the case |
* soon as builtin_t is going to grow way beyond module_t */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "errors.h" |
#include "cmds.h" |
#include "builtin_aliases.h" |
extern volatile unsigned int cli_interactive; |
int builtin_is_restricted(int pos) |
{ |
builtin_t *cmd = builtins; |
cmd += pos; |
if (cli_interactive && cmd->restricted <= 0) |
return 0; |
if (!cli_interactive && cmd->restricted >= 0) |
return 0; |
return 1; |
} |
int is_builtin(const char *command) |
{ |
builtin_t *cmd; |
unsigned int i = 0; |
if (NULL == command) |
return -2; |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (!strcmp(cmd->name, command)) |
return i; |
} |
return -1; |
} |
int is_builtin_alias(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return -1; |
for(i=0; builtin_aliases[i] != NULL; i+=2) { |
if (!strcmp(builtin_aliases[i], command)) |
return 1; |
} |
return 0; |
} |
char *alias_for_builtin(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return (char *)NULL; |
for(i=0; builtin_aliases[i] != NULL; i++) { |
if (!strcmp(builtin_aliases[i], command)) |
return (char *)builtin_aliases[++i]; |
i++; |
} |
return (char *)NULL; |
} |
int help_builtin(int builtin, unsigned int extended) |
{ |
builtin_t *cmd = builtins; |
cmd += builtin; |
if (NULL != cmd->help) { |
cmd->help(extended); |
return CL_EOK; |
} else |
return CL_ENOENT; |
} |
int run_builtin(int builtin, char *argv[], cliuser_t *usr) |
{ |
builtin_t *cmd = builtins; |
cmd += builtin; |
if (NULL != cmd->entry) |
return((int)cmd->entry(argv, usr)); |
return CL_ENOENT; |
} |
/branches/network/uspace/app/bdsh/util.c |
---|
0,0 → 1,284 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com> |
* Copyright (c) 1988, 1993 The Regents of the University of California. |
* All rights reserved by all copyright holders. |
* |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
*/ |
/* NOTES: |
* 1 - Various functions were adapted from FreeBSD (copyright holders noted above) |
* these functions are identified with comments. |
* |
* 2 - Some of these have since appeared in libc. They remain here for various |
* reasons, such as the eventual integration of garbage collection for things |
* that allocate memory and don't automatically free it. |
* |
* 3 - Things that expect a pointer to an allocated string do _no_ sanity checking |
* if developing on a simulator with no debugger, take care :) |
*/ |
#include <stdio.h> |
#include <string.h> |
#include <stdarg.h> |
#include <stdlib.h> |
#include <stdarg.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
extern volatile int cli_errno; |
/* some platforms do not have strdup, implement it here. |
* Returns a pointer to an allocated string or NULL on failure */ |
char * cli_strdup(const char *s1) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) { |
cli_errno = CL_ENOMEM; |
return (char *) NULL; |
} |
cli_errno = CL_EOK; |
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) |
{ |
char *spanp, *tok; |
int c, sc; |
if (s == NULL && (s = *last) == NULL) { |
cli_errno = CL_EFAIL; |
return (NULL); |
} |
cont: |
c = *s++; |
for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
if (c == sc) |
goto cont; |
} |
if (c == 0) { /* no non-delimiter characters */ |
*last = NULL; |
return (NULL); |
} |
tok = s - 1; |
for (;;) { |
c = *s++; |
spanp = (char *)delim; |
do { |
if ((sc = *spanp++) == c) { |
if (c == 0) |
s = NULL; |
else |
s[-1] = '\0'; |
*last = s; |
return (tok); |
} |
} while (sc != 0); |
} |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * cli_strtok(char *s, const char *delim) |
{ |
static char *last; |
return (cli_strtok_r(s, delim, &last)); |
} |
/* Count and return the # of elements in an array */ |
unsigned int cli_count_args(char **args) |
{ |
unsigned int i; |
for (i=0; args[i] != NULL; i++); |
return i; |
} |
/* (re)allocates memory to store the current working directory, gets |
* and updates the current working directory, formats the prompt |
* string */ |
unsigned int cli_set_prompt(cliuser_t *usr) |
{ |
usr->prompt = (char *) realloc(usr->prompt, PATH_MAX); |
if (NULL == usr->prompt) { |
cli_error(CL_ENOMEM, "Can not allocate prompt"); |
cli_errno = CL_ENOMEM; |
return 1; |
} |
memset(usr->prompt, 0, sizeof(usr->prompt)); |
usr->cwd = (char *) realloc(usr->cwd, PATH_MAX); |
if (NULL == usr->cwd) { |
cli_error(CL_ENOMEM, "Can not allocate cwd"); |
cli_errno = CL_ENOMEM; |
return 1; |
} |
memset(usr->cwd, 0, sizeof(usr->cwd)); |
usr->cwd = getcwd(usr->cwd, PATH_MAX - 1); |
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; |
} |
return 0; |
} |
/branches/network/uspace/app/bdsh/util.h |
---|
0,0 → 1,17 |
#ifndef UTIL_H |
#define UTIL_H |
#include "scli.h" |
/* 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 *); |
/* Utility functions */ |
extern unsigned int cli_count_args(char **); |
extern unsigned int cli_set_prompt(cliuser_t *usr); |
#endif |
/branches/network/uspace/app/bdsh/Makefile |
---|
0,0 → 1,134 |
# Copyright (c) 2005, Martin Decky |
# All rights reserved. |
# Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
# 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. |
# |
# Neither the name of the original program's authors nor the names of its |
# contributors may be used to endorse or promote products derived from this |
# software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
# POSSIBILITY OF SUCH DAMAGE. |
include ../../../version |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
LIBS = $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
ifdef REVISION |
DEFS += "-DREVISION=\"$(TIMESTAMP)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
PROGRAM = bdsh |
# Any directory that cleaning targets should know about |
SUBDIRS = \ |
./ \ |
cmds/ \ |
cmds/modules/ \ |
cmds/modules/help/ \ |
cmds/modules/quit/ \ |
cmds/modules/mkdir/ \ |
cmds/modules/rm/ \ |
cmds/modules/cat/ \ |
cmds/modules/touch/ \ |
cmds/modules/ls/ \ |
cmds/modules/pwd/ \ |
cmds/builtins/ \ |
cmds/builtins/cd/ |
SOURCES = \ |
cmds/modules/help/help.c \ |
cmds/modules/quit/quit.c \ |
cmds/modules/mkdir/mkdir.c \ |
cmds/modules/rm/rm.c \ |
cmds/modules/cat/cat.c \ |
cmds/modules/touch/touch.c \ |
cmds/modules/ls/ls.c \ |
cmds/modules/pwd/pwd.c \ |
cmds/builtins/cd/cd.c \ |
cmds/mod_cmds.c \ |
cmds/builtin_cmds.c \ |
errors.c \ |
input.c \ |
util.c \ |
exec.c \ |
scli.c |
CFLAGS += -I. -Icmds/ -Icmds/builtins -Icmds/modules |
OBJECTS = $(SOURCES:.c=.o) |
# For easy cleaning, *.o is already handled |
CLEANDIRS := $(addsuffix *~,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.bak,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.tmp,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.out,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.d,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.gch,$(SUBDIRS) ) |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(CFLAGS) $(INC) -c $< -o $@ |
@$(CC) -M $(CFLAGS) $(INC) $*.c > $*.d |
$(PROGRAM): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map |
# Everything else is a phony target |
.PHONY: all clean distclean depend disasm |
all: $(PROGRAM) disasm |
clean: |
@-rm -f $(OBJECTS) |
@-rm -f $(PROGRAM) |
@-rm -f $(PROGRAM).map |
@-rm -f $(PROGRAM).disasm |
@-rm -f $(CLEANDIRS) |
depend: |
@echo '' |
disasm: |
$(OBJDUMP) -d $(PROGRAM) >$(PROGRAM).disasm |
distclean: clean |
# Do not delete - dependencies |
-include $(OBJECTS:.o=.d) |
/branches/network/uspace/app/bdsh/input.c |
---|
0,0 → 1,177 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* Copyright (c) 2008, Jiri Svoboda - All Rights Reserved |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <io/stream.h> |
#include "config.h" |
#include "util.h" |
#include "scli.h" |
#include "input.h" |
#include "errors.h" |
#include "exec.h" |
extern volatile unsigned int cli_interactive; |
/* Not exposed in input.h */ |
static void cli_restricted(char *); |
static void read_line(char *, int); |
/* More than a macro than anything */ |
static void cli_restricted(char *cmd) |
{ |
printf("%s is not available in %s mode\n", cmd, |
cli_interactive ? "interactive" : "non-interactive"); |
return; |
} |
/* Tokenizes input from console, sees if the first word is a built-in, if so |
* invokes the built-in entry point (a[0]) passing all arguments in a[] to |
* the handler */ |
int tok_input(cliuser_t *usr) |
{ |
char *cmd[WORD_MAX]; |
int n = 0, i = 0; |
int rc = 0; |
char *tmp; |
if (NULL == usr->line) |
return CL_EFAIL; |
tmp = cli_strdup(usr->line); |
/* Break up what the user typed, space delimited */ |
/* TODO: Protect things in quotes / ticks, expand wildcards */ |
cmd[n] = cli_strtok(tmp, " "); |
while (cmd[n] && n < WORD_MAX) { |
cmd[++n] = cli_strtok(NULL, " "); |
} |
/* We have rubbish */ |
if (NULL == cmd[0]) { |
rc = CL_ENOENT; |
goto finit; |
} |
/* Its a builtin command */ |
if ((i = (is_builtin(cmd[0]))) > -1) { |
/* Its not available in this mode, see what try_exec() thinks */ |
if (builtin_is_restricted(i)) { |
rc = try_exec(cmd[0], cmd); |
if (rc) |
/* No external matching it could be found, tell the |
* user that the command does exist, but is not |
* available in this mode. */ |
cli_restricted(cmd[0]); |
goto finit; |
} |
/* Its a builtin, its available, run it */ |
rc = run_builtin(i, cmd, usr); |
goto finit; |
/* We repeat the same dance for modules */ |
} else if ((i = (is_module(cmd[0]))) > -1) { |
if (module_is_restricted(i)) { |
rc = try_exec(cmd[0], cmd); |
if (rc) |
cli_restricted(cmd[0]); |
goto finit; |
} |
rc = run_module(i, cmd); |
goto finit; |
} else { |
/* Its not a module or builtin, restricted or otherwise. |
* See what try_exec() thinks of it and just pass its return |
* value back to the caller */ |
rc = try_exec(cmd[0], cmd); |
goto finit; |
} |
finit: |
if (NULL != usr->line) { |
free(usr->line); |
usr->line = (char *) NULL; |
} |
if (NULL != tmp) |
free(tmp); |
return rc; |
} |
/* Borrowed from Jiri Svoboda's 'cli' uspace app */ |
static void read_line(char *buffer, int n) |
{ |
char c; |
int chars; |
chars = 0; |
while (chars < n - 1) { |
c = getchar(); |
if (c < 0) |
return; |
if (c == '\n') |
break; |
if (c == '\b') { |
if (chars > 0) { |
putchar('\b'); |
--chars; |
} |
continue; |
} |
putchar(c); |
buffer[chars++] = c; |
} |
putchar('\n'); |
buffer[chars] = '\0'; |
} |
/* TODO: |
* Implement something like editline() / readline(), if even |
* just for command history and making arrows work. */ |
void get_input(cliuser_t *usr) |
{ |
char line[INPUT_MAX]; |
size_t len = 0; |
printf("%s", usr->prompt); |
read_line(line, INPUT_MAX); |
len = strlen(line); |
/* Make sure we don't have rubbish or a C/R happy user */ |
if (len == 0 || line[0] == '\n') |
return; |
usr->line = cli_strdup(line); |
return; |
} |
/branches/network/uspace/app/bdsh/input.h |
---|
0,0 → 1,11 |
#ifndef INPUT_H |
#define INPUT_H |
#include "cmds/cmds.h" |
/* prototypes */ |
extern void get_input(cliuser_t *); |
extern int tok_input(cliuser_t *); |
#endif |
/branches/network/uspace/app/bdsh/exec.c |
---|
0,0 → 1,129 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
*/ |
/* The VERY basics of execute in place support. These are buggy, leaky |
* and not nearly done. Only here for beta testing!! You were warned!! |
* TODO: |
* Hash command lookups to save time |
* Create a running pointer to **path and advance/rewind it as we go */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <string.h> |
#include <fcntl.h> |
#include "config.h" |
#include "util.h" |
#include "exec.h" |
#include "errors.h" |
/* FIXME: Just have find_command() return an allocated string */ |
char *found; |
static char *find_command(char *); |
static unsigned int try_access(const char *); |
/* work-around for access() */ |
static unsigned int try_access(const char *f) |
{ |
int fd; |
fd = open(f, O_RDONLY); |
if (fd > -1) { |
close(fd); |
return 0; |
} else |
return -1; |
} |
/* Returns the full path of "cmd" if cmd is found, else just hand back |
* cmd as it was presented */ |
static char *find_command(char *cmd) |
{ |
char *path_tok; |
char *path[PATH_MAX]; |
int n = 0, i = 0; |
size_t x = strlen(cmd) + 2; |
found = (char *)malloc(PATH_MAX); |
/* The user has specified a full or relative path, just give it back. */ |
if (-1 != try_access(cmd)) { |
return (char *) cmd; |
} |
path_tok = cli_strdup(PATH); |
/* Extract the PATH env to a path[] array */ |
path[n] = cli_strtok(path_tok, PATH_DELIM); |
while (NULL != path[n]) { |
if ((strlen(path[n]) + x ) > PATH_MAX) { |
cli_error(CL_ENOTSUP, |
"Segment %d of path is too large, search ends at segment %d", |
n, n-1); |
break; |
} |
path[++n] = cli_strtok(NULL, PATH_DELIM); |
} |
/* We now have n places to look for the command */ |
for (i=0; path[i]; i++) { |
memset(found, 0, sizeof(found)); |
snprintf(found, PATH_MAX, "%s/%s", path[i], cmd); |
if (-1 != try_access(found)) { |
free(path_tok); |
return (char *) found; |
} |
} |
/* We didn't find it, just give it back as-is. */ |
free(path_tok); |
return (char *) cmd; |
} |
unsigned int try_exec(char *cmd, char **argv) |
{ |
task_id_t tid; |
char *tmp; |
tmp = cli_strdup(find_command(cmd)); |
free(found); |
tid = task_spawn((const char *)tmp, (const char **)argv); |
free(tmp); |
if (tid == 0) { |
cli_error(CL_EEXEC, "Can not spawn %s", cmd); |
return 1; |
} else { |
return 0; |
} |
} |
/branches/network/uspace/app/bdsh/exec.h |
---|
0,0 → 1,7 |
#ifndef EXEC_H |
#define EXEC_H |
#include <task.h> |
extern unsigned int try_exec(char *, char **); |
#endif |
/branches/network/uspace/app/bdsh/README |
---|
0,0 → 1,268 |
BDSH - The Brain Dead Shell | Design Documentation |
-------------------------------------------------- |
Overview: |
========= |
BDSH was written as a drop in command line interface for HelenOS to permit |
interactive access to persistent file systems in development. BDSH was |
written from scratch with a very limited userspace standard C library in |
mind. Much like the popular Busybox program, BDSH provides a very limited |
shell with limited common UNIX creature comforts built in. |
Porting Busybox (and by extension ASH) would have taken much longer to |
complete, much less make stable due to stark differences between Linux and |
Spartan with regards to IPC, term I/O and process creation. BDSH was written |
and made stable within the space of less than 30 days. |
BDSH will eventually evolve and be refined into the HelenOS equivalent |
of Busybox. While BDSH is now very intrinsic to HelenOS, its structure and |
use of strictly lower level functions makes it extremely easy to port. |
Design: |
======= |
BDSH is made up of three basic components: |
1. Main i/o, error handling and task management |
2. The builtin sub system |
3. The module sub system |
The main part handles user input, reports errors, spawns external tasks and |
provides a convenient entry point for built-in and modular commands. A simple |
structure, cliuser_t keeps track of the user's vitals, such as their current |
working directory (and eventually uid, home directory, etc if they apply). |
This part defines and exposes all functions that are not intrinsic to a |
certain built in or modular command. For instance: string handlers, |
module/builtin search and launch functions, error handlers and other things |
can be found here. |
Builtin commands are commands that must have access to cliuser_t, which is |
not exposed to modular commands. For instance, the 'cd' command must update |
the current working directory, which is stored in cliuser_t. As such, the |
entry types for builtin commands are slightly different. |
Modular commands do not need anything more than the basic functions that are |
exposed by default. They do not need to modify cliuser_t, they are just self |
contained. A modular command could very easily be made into a stand alone |
program, likewise any stand alone program could easily become a modular |
command. |
Both modular and builtin commands share two things in common. Both must have |
two entry points, one to invoke the command and one to invoke a help display |
for the command. Exec (main()) entry points are int * and are expected to |
return a value. Help entry points are void *, no return value is expected. |
They are typed as such (from cmds.h): |
/* Types for module command entry and help */ |
typedef int * (* mod_entry_t)(char **); |
typedef void * (* mod_help_t)(unsigned int); |
/* Built-in commands need to be able to modify cliuser_t */ |
typedef int * (* builtin_entry_t)(char **, cliuser_t *); |
typedef void * (* builtin_help_t)(unsigned int); |
As you can see, both modular and builtin commands expect an array of |
arguments, however bulitins also expect to be pointed to cliuser_t. |
Both are defined with the same simple structure: |
/* Module structure */ |
typedef struct { |
char *name; /* Name of the command */ |
char *desc; /* Description of the command */ |
mod_entry_t entry; /* Command (exec) entry function */ |
mod_help_t help; /* Command (help) entry function */ |
int restricted; /* Restricts to interactive/non-interactive only */ |
} module_t; |
NOTE: Builtin commands may grow in this respect, that is why they are |
defined separately. |
Builtins, of course, would use the builtin_entry_t type. The name of the |
command is used to associate user input to a possible entry point. The |
description is a short (40 - 60 chars) summary of what the command does. Both |
entry points are then defined, and the restrict value is used to determine a |
commands availability. |
Restriction levels are easy, a command is either available exclusively within |
interactive mode, exclusively within non-interactive mode or both. If you are |
looking at a prompt, you are in interactive mode. If you issue a command like |
this: |
/sbin/bdsh command [arg1] [arg2] |
... you are in non interactive mode. This is done when you need to force the |
parent shell to be the one who actually handles the command, or ensure that |
/sbin/ls was used in lieu of the built in 'ls' when in non-interactive mode. |
The values are: |
0 : Unrestricted |
-1 : Interactive only |
1 : Non-interactive only |
A script to generate skeletal files for a new command is included, it can be |
found in cmds/mknewcmd. To generate a new modular command named 'foo', which |
should also be reachable by typing 'f00', you would issue this command: |
./mknewcmd -n foo -a f00 -t module |
This generates all needed files and instructs you on how to include your new |
command in the build and make it accessible. By default, the command will be |
unrestricted. Builtin commands can be created by changing 'module' to |
'builtin' |
There are more options to mknewcmd, which allow you to specify the |
description, entry point, help entry point, or restriction. By default, names |
just follow the command such as cmd_foo(), help_cmd_foo(), 'The foo command', |
etc. If you want to see the options and explanations in detail, use |
./mknewcmd --help. |
When working with commands, keep in mind that only the main and help entry |
points need to be exposed. If commands share the same functions, put them |
where they are exposed to all commands, without the potential oops of those |
functions going away if the command is eliminated in favor of a stand alone |
external program. |
The util.c file is a great place to put those types of functions. |
Also, be careful with globals, option structures, etc. The compiler will |
generally tell you if you've made a mistake, however declaring: |
volatile int foo |
... in a command will allow for anything else to pick it up. Sometimes |
this could be desirable .. other times not. When communicating between |
builtins and the main system, try to use cliuser_t. The one exception |
for this is the cli_quit global, since everything may at some point |
need to check it. Modules should only communicate their return value. |
Symbolic constants that everything needs should go in the config.h file, |
however this is not the place to define shared macros. |
Making a program into a module |
============================== |
If you have some neat program that would be useful as a modular command, |
converting it is not very hard. The following steps should get you through |
the process easily (assuming your program is named 'foo'): |
1: Use mknewcmd to generate the skeletal files. |
2: Change your "usage()" command as shown: |
-- void usage(...) |
++ void * help_cmd_foo(unsigned int level) |
-- return; |
++ retrn CMD_VOID; |
'level' is either 0 or 1, indicating the level of help requested. |
If the help / usage function currently exits based on how it is |
called, you'll need to change it. |
3: Change the programs "main()" as shown: |
-- int main(int argc, char **argv) |
++ int * cmd_foo(char **argv) |
-- return 1; |
++ return CMD_FAILURE; |
-- return 0; |
++ return CMD_SUCCESS; |
If main() returns an int that is not 1 or 0 (e.g. 127), cast it as |
such: |
-- return 127; |
++ return (int *) 127; |
NOTE: _ONLY_ the main and help entry points need to return int * or |
void *, respectively. Also take note that argc has changed. The type |
for entry points may soon change. |
NOTE: If main is void, you'll need to change it and ensure that its |
expecting an array of arguments, even if they'll never be read or |
used. I.e.: |
-- void main(void) |
++ int * cmd_foo(char **argv) |
Similararly, do not try to return CMD_VOID within the modules main |
entry point. If somehow you escape the compiler yelling at you, you |
will surely see pretty blue and yellow fireworks once its reached. |
4: Don't expose more than the entry and help points: |
-- void my_function(int n) |
++ static void my_function(int n) |
5: Copy/paste to the stub generated by mknewcmd then add your files to the |
Makefile. Be sure to add any directories that you made to the SUBDIRS so |
that a 'make clean' will clean them. |
Provided that all functions that your calling are available in the |
userspace C library, your program should compile just fine and appear |
as a modular command. |
Overcoming userspace libc obstacles |
=================================== |
A quick glance through the util.c file will reveal functions like |
cli_strdup(), cli_strtok(), cli_strtok_r() and more. Those are functions |
that were missing from userspace libc when BDSH was born. Later, after |
porting what was needed from FBSD/NBSD, the real functions appeared in |
the userspace libc after being tested in their cli_* implementations. |
Those functions remain because they guarantee that bdsh will work even |
on systems that lack them. Additionally, more BDSH specific stuff can |
go into them, such as error handling and reporting when malloc() fails. |
You will also notice that FILE, fopen() (and all friends), ato*() and |
other common things might be missing. The HelenOS userspace C library is |
still very young, you are sure to run into something that you want/need |
which is missing. |
When that happens, you have three options: |
1 - Implement it internally in util.c , when its tested and stable send a |
patch to HelenOS asking for your function to be included in libc. This is |
the best option, as you not only improve BDSH .. but HelenOS as a whole. |
2 - Work around it. Not everyone can implement / port fopen() and all of |
its friends. Make open(), read(), write() (etc) work if at all possible. |
3 - Send an e-mail to the HelenOS development mailing list. Explain why you |
need the function and what its absence is holding up. |
If what you need is part of a library that is typically a shared object, try |
to implement a 'mini' version of it. Currently, all userspace applications |
are statically linked. Giving up creature comforts for size while avoiding |
temporary 'band aids' is never frowned upon. |
Most of all, don't get discouraged .. ask for some help prior to giving up |
if you just can't accomplish something with the limited means provided. |
Contributing |
============ |
I will take any well written patch that sanely improves or expands BDSH. Send |
me a patch against the trunk revision, or, if you like a Mercurial repository |
is also maintained at http://echoreply.us/hg/bdsh.hg and kept in sync with |
the trunk. |
Please be sure to follow the simple coding standards outlined at |
http://www.helenos.eu/cstyle (mostly just regarding formatting), test your |
changes and make sure your patch applies cleanly against the latest revision. |
All patches submitted must be your original code, or a derivative work of |
something licensed under the same 3 clause BSD license as BDSH. See LICENSE |
for more information. |
When sending patches, you agree that your work will be published under the |
same 3 clause BSD license as BDSH itself. Failure to ensure that anything |
you used is not under the same or less restrictive license could cause major |
issues for BDSH in the future .. please be sure. Also, please don't forget |
to add yourself in the AUTHORS file, as I am horrible about keeping such |
things up to date. |
/branches/network/uspace/app/bdsh/errors.c |
---|
0,0 → 1,87 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* 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. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <string.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <stdarg.h> |
#include "config.h" |
#include "errors.h" |
#include "errstr.h" |
volatile int cli_errno = CL_EOK; |
extern volatile unsigned int cli_quit; |
/* Error printing, translation and handling functions */ |
/* Look up errno in cl_errors and return the corresponding string. |
* Return NULL if not found */ |
static char *err2str(int err) |
{ |
if (NULL != cl_errors[err]) |
return cl_errors[err]; |
return (char *)NULL; |
} |
/* Print an error report signifying errno, which is translated to |
* its corresponding human readable string. If errno > 0, raise the |
* cli_quit int that tells the main program loop to exit immediately */ |
void cli_error(int err, const char *fmt, ...) |
{ |
va_list vargs; |
va_start(vargs, fmt); |
vprintf(fmt, vargs); |
va_end(vargs); |
if (NULL != err2str(err)) |
printf(" (%s)\n", err2str(err)); |
else |
printf(" (Unknown Error %d)\n", err); |
/* If fatal, raise cli_quit so that we try to exit |
* gracefully. This will break the main loop and |
* invoke the destructor */ |
if (err == CL_EFATAL) |
cli_quit = 1; |
return; |
} |
/branches/network/uspace/app/bdsh/errors.h |
---|
0,0 → 1,22 |
#ifndef ERRORS_H |
#define ERRORS_H |
/* Various error levels */ |
#define CL_EFATAL -1 |
#define CL_EOK 0 |
#define CL_EFAIL 1 |
#define CL_EBUSY 2 |
#define CL_ENOENT 3 |
#define CL_ENOMEM 4 |
#define CL_EPERM 5 |
#define CL_ENOTSUP 6 |
#define CL_EEXEC 7 |
#define CL_EEXISTS 8 |
#define CL_ETOOBIG 9 |
/* Just like 'errno' */ |
extern volatile int cli_errno; |
extern void cli_error(int, const char *, ...); |
#endif |
/branches/network/uspace/app/bdsh/errstr.h |
---|
0,0 → 1,23 |
#ifndef ERRSTR_H |
#define ERRSTR_H |
/* Simple array to translate error codes to meaningful strings */ |
static char *cl_errors[] = { |
"Success", |
"Failure", |
"Busy", |
"No Such Entry", |
"Not Enough Memory", |
"Permission Denied", |
"Method Not Supported", |
"Bad command or file name", |
"Entry already exists", |
"Object too large", |
NULL |
}; |
static char *err2str(int); |
#endif |
/branches/network/uspace/app/bdsh/TODO |
---|
0,0 → 1,57 |
This is a very brain dead shell. It needs some love, coffee or perhaps beer. |
Currently, you can't even really call it a shell, its more of a CLI that |
offers some shell like creature comforts. |
This was written in a hurry to provide some means of testing persistent file |
systems in HelenOS. It does its job, its nowhere near complete but it is |
actively developed. If your reading this, its likely that you're looking for |
some functionality that is not yet present. Prior to filing a bug report, |
please make sure that what you want is not on the list below. |
A list of things to do: |
----------------------- |
* rm: add support for recursively removing directories and files therein |
* Port an editor (vim?) |
* Finish cat / cp |
* Support basic redirection (i.e ls > foo.txt) |
* Expand wildcards (i.e. *.txt), don't worry about variables for now |
* Basic scripting |
* Hash previously found commands |
* Improve input, add history / etc (port libedit?) |
* Add wrappers for signal, sigaction to make ports to modules easier |
* Add 'echo' and 'printf' modules. |
Regarding POSIX: |
---------------- |
POSIX is a standard for Unix-like operating systems. HelenOS is (mostly) just |
a kernel at this point with a few userspace programs that facilitate testing |
of the kernel and file systems. |
HelenOS is not a Unix-like operating system. HelenOS is its own thing, a modern |
microkernel OS and many directions are not yet set. |
Please do not e-mail me to point out that modular implementations that resemble |
typical core utilities do not conform to some POSIX standard, these are temporary |
and serve the useful purpose of testing persistent file systems. |
Contributing: |
------------- |
If you feel like doing any of the above to-do items, I am echo@echoreply.us. Please |
e-mail me and let me know your working on something so that I do not unwittingly |
duplicate your efforts. You can also e-mail the HelenOS list directly: |
HelenOS development mailing list <helenos-devel@lists.modry.cz> |
Subscribe here if you like: http://lists.modry.cz/cgi-bin/listinfo/helenos-devel |
Cheers and happy hacking! |
--Tim |
/branches/network/uspace/app/bdsh/config.h |
---|
0,0 → 1,33 |
/* Various things that are used in many files |
* Various temporary port work-arounds are addressed in __HELENOS__ , this |
* serves as a convenience and later as a guide to make "phony.h" for future |
* ports */ |
/* Specific port work-arounds : */ |
#define PATH_MAX 255 |
#define EXIT_SUCCESS 0 |
#define EXIT_FAILURE 0 |
/* Work around for getenv() */ |
#define PATH "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" |
#define PATH_DELIM ":" |
/* Used in many places */ |
#define SMALL_BUFLEN 256 |
#define LARGE_BUFLEN 1024 |
/* How many words (arguments) are permitted, how big can a whole |
* sentence be? Similar to ARG_MAX */ |
#define WORD_MAX 255 |
#define INPUT_MAX 1024 |
/* Leftovers from Autoconf */ |
#define PACKAGE_MAINTAINER "Tim Post" |
#define PACKAGE_BUGREPORT "echo@echoreply.us" |
#define PACKAGE_NAME "bdsh" |
#define PACKAGE_STRING "The brain dead shell" |
#define PACKAGE_TARNAME "scli" |
#define PACKAGE_VERSION "0.0.1" |
/branches/network/uspace/app/bdsh/AUTHORS |
---|
0,0 → 1,17 |
Written by Tim Post <echo@echoreply.us> to serve as a primitive shell |
for HelenOS, or as a template to make a command line interface that |
offers shell like creature comforts. |
This program was mostly written from scratch, some existing code was |
used from other various free software projects: |
* Based on the HelenOS testing sub-system written by Martin Decky |
* cli_strtok() and cli_strtok_r() (util.c) were adapted from the FreeBSD |
strtok() and strtok_r() functions written by Wes Peters. |
* read_line() (input.c) was written by Jiri Svoboda |
Individual author copyrights are listed in the headers of each file. |
/branches/network/uspace/app/bdsh/LICENSE |
---|
0,0 → 1,28 |
Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
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. |
Neither the name of the original program's authors nor the names of its |
contributors may be used to endorse or promote products derived from this |
software without specific prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. |
/branches/network/uspace/app/init/init.c |
---|
34,30 → 34,88 |
* @file |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include <vfs/vfs.h> |
#include <bool.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <task.h> |
#include <malloc.h> |
#include "init.h" |
#include "version.h" |
#include <stdio.h> |
static void test_console(void) |
static void console_wait(void) |
{ |
int c; |
while (get_cons_phone() < 0) |
usleep(50000); // FIXME |
} |
while ((c = getchar()) != EOF) |
putchar(c); |
static bool mount_fs(const char *fstype) |
{ |
int rc = -1; |
while (rc < 0) { |
rc = mount(fstype, "/", "initrd"); |
switch (rc) { |
case EOK: |
printf(NAME ": Root filesystem mounted\n"); |
break; |
case EBUSY: |
printf(NAME ": Root filesystem already mounted\n"); |
break; |
case ELIMIT: |
printf(NAME ": Unable to mount root filesystem\n"); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (%s)\n", fstype); |
return false; |
default: |
sleep(5); // FIXME |
} |
} |
return true; |
} |
static void spawn(char *fname) |
{ |
char *argv[2]; |
printf(NAME ": Spawning %s\n", fname); |
argv[0] = fname; |
argv[1] = NULL; |
if (task_spawn(fname, argv) != 0) { |
/* Success */ |
sleep(1); |
} |
} |
int main(int argc, char *argv[]) |
{ |
version_print(); |
info_print(); |
sleep(5); // FIXME |
printf("This is init\n"); |
if (!mount_fs("tmpfs") && !mount_fs("fat")) { |
printf(NAME ": Exiting\n"); |
return -1; |
} |
test_console(); |
// FIXME: spawn("/sbin/pci"); |
spawn("/sbin/fb"); |
spawn("/sbin/kbd"); |
spawn("/sbin/console"); |
printf("\nBye.\n"); |
console_wait(); |
version_print(); |
spawn("/sbin/bdsh"); |
return 0; |
} |
/** @} |
*/ |
/branches/network/uspace/app/init/Makefile |
---|
61,7 → 61,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
74,9 → 74,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/app/init/version.c |
---|
35,6 → 35,7 |
#include <unistd.h> |
#include <stdio.h> |
#include "init.h" |
#include "version.h" |
char *release = RELEASE; |
51,6 → 52,11 |
char *timestamp = ""; |
#endif |
void info_print(void) |
{ |
printf(NAME ": HelenOS init\n"); |
} |
/** Print version information. */ |
void version_print(void) |
{ |
/branches/network/uspace/app/init/init.h |
---|
36,7 → 36,7 |
#ifndef __INIT_H__ |
#define __INIT_H__ |
#include "version.h" |
#define NAME "init" |
#endif |
/branches/network/uspace/app/init/version.h |
---|
36,6 → 36,7 |
#ifndef __VERSION_H__ |
#define __VERSION_H__ |
extern void info_print(void); |
extern void version_print(void); |
#endif |
/branches/network/uspace/app/tetris/input.c |
---|
96,6 → 96,7 |
struct timeval starttv, endtv, *s; |
static ipc_call_t charcall; |
ipcarg_t rc; |
int cons_phone; |
/* |
* Someday, select() will do this for us. |
110,8 → 111,11 |
s = NULL; |
if (!lastchar) { |
if (!getchar_inprog) |
getchar_inprog = async_send_2(1,CONSOLE_GETCHAR,0,0,&charcall); |
if (!getchar_inprog) { |
cons_phone = get_cons_phone(); |
getchar_inprog = async_send_2(cons_phone, |
CONSOLE_GETCHAR, 0, 0, &charcall); |
} |
if (!s) |
async_wait_for(getchar_inprog, &rc); |
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) { |
/branches/network/uspace/app/tetris/Makefile |
---|
10,7 → 10,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
22,9 → 22,12 |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend *.o |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/app/tester/tester.c |
---|
78,8 → 78,24 |
static void run_safe_tests(void) |
{ |
test_t *test; |
unsigned int i = 0; |
unsigned int n = 0; |
printf("\n*** Running all safe tests ***\n\n"); |
for (test = tests; test->name != NULL; test++) { |
if (test->safe) { |
if (run_test(test)) |
i++; |
else |
n++; |
} |
} |
printf("\nSafe tests completed, %u tests run, %u passed.\n\n", i + n, i); |
} |
static void list_tests(void) |
{ |
test_t *test; |
91,8 → 107,17 |
printf("*\t\t\tRun all safe tests\n"); |
} |
int main(void) |
int main(int argc, char **argv) |
{ |
printf("Number of arguments: %d\n", argc); |
if (argv) { |
printf("Arguments:"); |
while (*argv) { |
printf(" '%s'", *argv++); |
} |
printf("\n"); |
} |
while (1) { |
char c; |
test_t *test; |
112,12 → 137,17 |
printf("Unknown test\n\n"); |
else |
run_test(test); |
} else if (c == '*') |
} else if (c == '*') { |
run_safe_tests(); |
else |
} else if (c < 0) { |
/* got EOF */ |
break; |
} else { |
printf("Invalid test\n\n"); |
} |
} |
} |
/** @} |
*/ |
/branches/network/uspace/app/tester/Makefile |
---|
59,7 → 59,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
72,9 → 72,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/app/tester/devmap/devmap1.c |
---|
32,7 → 32,7 |
#include <ipc/services.h> |
#include <async.h> |
#include <errno.h> |
#include <../../../srv/devmap/devmap.h> |
#include <ipc/devmap.h> |
#include "../tester.h" |
#include <time.h> |
/branches/network/uspace/app/tester/vfs/vfs1.c |
---|
30,7 → 30,7 |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <vfs.h> |
#include <vfs/vfs.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
43,10 → 43,23 |
char *test_vfs1(bool quiet) |
{ |
if (mount("tmpfs", "/", "nulldev0") != EOK) |
return "mount() failed.\n"; |
int rc; |
rc = mount("tmpfs", "/", "nulldev0"); |
switch (rc) { |
case EOK: |
if (!quiet) |
printf("mounted tmpfs on /.\n"); |
printf("mounted tmpfs on /\n"); |
break; |
case EBUSY: |
if (!quiet) |
printf("(INFO) something is already mounted on /\n"); |
break; |
default: |
if (!quiet) |
printf("(INFO) IPC returned errno %d\n", rc); |
return "mount() failed."; |
} |
if (mkdir("/mydir", 0) != 0) |
return "mkdir() failed.\n"; |
73,23 → 86,57 |
char buf[10]; |
cnt = read(fd0, buf, sizeof(buf)); |
while ((cnt = read(fd0, buf, sizeof(buf)))) { |
if (cnt < 0) |
return "read() failed.\n"; |
if (!quiet) |
printf("read %d bytes: \"%.*s\", fd=%d\n", cnt, cnt, buf, fd0); |
printf("read %d bytes: \"%.*s\", fd=%d\n", cnt, cnt, |
buf, fd0); |
} |
close(fd0); |
DIR *dirp; |
struct dirent *dp; |
if (!quiet) |
printf("scanning the root directory...\n"); |
dirp = opendir("/"); |
if (!dirp) |
return "opendir() failed."; |
return "opendir() failed\n"; |
while ((dp = readdir(dirp))) |
printf("discovered node %s in /\n", dp->d_name); |
closedir(dirp); |
if (rename("/mydir/myfile", "/mydir/yourfile")) |
return "rename() failed.\n"; |
if (!quiet) |
printf("renamed /mydir/myfile to /mydir/yourfile\n"); |
if (unlink("/mydir/yourfile")) |
return "unlink() failed.\n"; |
if (!quiet) |
printf("unlinked file /mydir/yourfile\n"); |
if (rmdir("/mydir")) |
return "rmdir() failed.\n"; |
if (!quiet) |
printf("removed directory /mydir\n"); |
if (!quiet) |
printf("scanning the root directory...\n"); |
dirp = opendir("/"); |
if (!dirp) |
return "opendir() failed\n"; |
while ((dp = readdir(dirp))) |
printf("discovered node %s in /\n", dp->d_name); |
closedir(dirp); |
return NULL; |
} |
/branches/network/uspace/app/tester/ipc/hangup.c |
---|
37,9 → 37,11 |
int res; |
int phoneid; |
printf("Select phoneid to hangup: 2-9\n"); |
printf("Select phoneid to hangup: 2-9 (q to skip)\n"); |
do { |
c = getchar(); |
if ((c == 'Q') || (c == 'q')) |
return TEST_SKIPPED; |
} while (c < '2' || c > '9'); |
phoneid = c - '0'; |
/branches/network/uspace/app/tester/ipc/send_sync.c |
---|
38,9 → 38,11 |
static int msgid = 1; |
char c; |
printf("Select phoneid to send msg: 2-9\n"); |
printf("Select phoneid to send msg: 2-9 (q to skip)\n"); |
do { |
c = getchar(); |
if ((c == 'Q') || (c == 'q')) |
return TEST_SKIPPED; |
} while (c < '2' || c > '9'); |
phoneid = c - '0'; |
/branches/network/uspace/app/tester/ipc/send_async.c |
---|
41,9 → 41,11 |
static int msgid = 1; |
char c; |
printf("Select phoneid to send msg: 2-9\n"); |
printf("Select phoneid to send msg: 2-9 (q to skip)\n"); |
do { |
c = getchar(); |
if ((c == 'Q') || (c == 'q')) |
return TEST_SKIPPED; |
} while (c < '2' || c > '9'); |
phoneid = c - '0'; |
/branches/network/uspace/app/tester/ipc/connect.c |
---|
36,9 → 36,11 |
int svc; |
int phid; |
printf("Choose one service: 0:10000....9:10009\n"); |
printf("Choose one service: 0:10000....9:10009 (q to skip)\n"); |
do { |
c = getchar(); |
if ((c == 'Q') || (c == 'q')) |
return TEST_SKIPPED; |
} while (c < '0' || c > '9'); |
svc = IPC_TEST_START + c - '0'; |
/branches/network/uspace/app/tester/tester.h |
---|
42,6 → 42,7 |
#define IPC_TEST_START 10000 |
#define MAX_PHONES 20 |
#define MAX_CONNECTIONS 50 |
#define TEST_SKIPPED "Test Skipped" |
extern int myservice; |
extern int phones[MAX_PHONES]; |
/branches/network/uspace/app/klog/Makefile |
---|
47,7 → 47,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
60,9 → 60,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/app/klog/klog.c |
---|
40,46 → 40,62 |
#include <ipc/services.h> |
#include <as.h> |
#include <sysinfo.h> |
#include <io/stream.h> |
#include <errno.h> |
#define NAME "klog" |
#define KLOG_SIZE PAGE_SIZE |
/* Pointer to klog area */ |
static char *klog; |
static void console_wait(void) |
{ |
while (get_cons_phone() < 0) |
usleep(50000); // FIXME |
} |
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
int i; |
async_serialize_start(); |
async_serialize_start(); |
for (i=0; klog[i + IPC_GET_ARG1(*call)] && i < IPC_GET_ARG2(*call); i++) |
putchar(klog[i + IPC_GET_ARG1(*call)]); |
putchar('\n'); |
size_t klog_start = (size_t) IPC_GET_ARG1(*call); |
size_t klog_len = (size_t) IPC_GET_ARG2(*call); |
size_t klog_stored = (size_t) IPC_GET_ARG3(*call); |
size_t i; |
for (i = klog_len - klog_stored; i < klog_len; i++) |
putchar(klog[(klog_start + i) % KLOG_SIZE]); |
async_serialize_end(); |
} |
int main(int argc, char *argv[]) |
{ |
int res; |
void *mapping; |
console_wait(); |
printf("Kernel console output.\n"); |
klog = (char *) as_get_mappable_page(KLOG_SIZE); |
if (klog == NULL) { |
printf(NAME ": Error allocating memory area\n"); |
return -1; |
} |
mapping = as_get_mappable_page(PAGE_SIZE); |
res = ipc_share_in_start_1_0(PHONE_NS, mapping, PAGE_SIZE, |
int res = ipc_share_in_start_1_0(PHONE_NS, (void *) klog, KLOG_SIZE, |
SERVICE_MEM_KLOG); |
if (res) { |
printf("Failed to initialize klog memarea\n"); |
_exit(1); |
if (res != EOK) { |
printf(NAME ": Error initializing memory area\n"); |
return -1; |
} |
klog = mapping; |
int inr = sysinfo_value("klog.inr"); |
int devno = sysinfo_value("klog.devno"); |
if (ipc_register_irq(inr, devno, 0, NULL)) { |
printf("Error registering for klog service.\n"); |
return 0; |
if (ipc_register_irq(inr, devno, 0, NULL) != EOK) { |
printf(NAME ": Error registering klog notifications\n"); |
return -1; |
} |
async_set_interrupt_received(interrupt_received); |
klog_update(); |
async_manager(); |
return 0; |
/branches/network/uspace/lib/libc/arch/ia64/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ia64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin |
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16 |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
/branches/network/uspace/lib/libc/arch/ia64/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/ia64/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 14 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/network/uspace/lib/libc/arch/ia64/include/byteorder.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2005 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 libcia64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_ia64_BYTEORDER_H_ |
#define LIBC_ia64_BYTEORDER_H_ |
/* IA-64 is little-endian */ |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/ia64/src/entry.s |
---|
31,27 → 31,17 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# r2 contains the PCB pointer |
# |
__entry: |
alloc loc0 = ar.pfs, 0, 1, 2, 0 |
mov r1 = _gp |
br.call.sptk.many b0 = __main |
0: |
br.call.sptk.many b0 = __io_init |
1: |
br.call.sptk.many b0 = main |
2: |
br.call.sptk.many b0 = __exit |
__entry_driver: |
alloc loc0 = ar.pfs, 0, 1, 2, 0 |
mov r1 = _gp |
# Pass PCB pointer as the first argument to __main |
mov out0 = r2 |
br.call.sptk.many b0 = __main |
0: |
br.call.sptk.many b0 = main |
1: |
br.call.sptk.many b0 = __exit |
/branches/network/uspace/lib/libc/arch/ia64/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x4000; |
. = 0x4000 + SIZEOF_HEADERS; |
.init ALIGN(0x4000): SUBALIGN(0x4000) { |
.init : { |
*(.init); |
} : text |
.text : { |
17,7 → 17,9 |
*(.rodata*); |
} :text |
.got ALIGN(0x4000) : SUBALIGN(0x4000) { |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
/branches/network/uspace/lib/libc/arch/arm32/Makefile.inc |
---|
30,8 → 30,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = /usr/local/arm/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin |
CFLAGS += -ffixed-r9 -mtp=soft |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
/branches/network/uspace/lib/libc/arch/arm32/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/arm32/include/config.h |
---|
38,7 → 38,6 |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/network/uspace/lib/libc/arch/arm32/include/byteorder.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2005 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 libcarm32 |
* @{ |
*/ |
/** @file |
* @brief Endianness definitions. |
*/ |
#ifndef LIBC_arm32_BYTEORDER_H_ |
#define LIBC_arm32_BYTEORDER_H_ |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/arm32/src/entry.s |
---|
31,19 → 31,14 |
.org 0 |
.global __entry |
.global __entry_driver |
## User-space task entry point |
# |
# r1 contains the PCB pointer |
# |
__entry: |
# Pass pcb_ptr to __main as the first argument (in r0) |
mov r0, r1 |
bl __main |
bl __io_init |
bl main |
bl __exit |
__entry_driver: |
bl __main |
bl main |
bl __exit |
/branches/network/uspace/lib/libc/arch/arm32/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x1000; |
. = 0x1000 + SIZEOF_HEADERS; |
.init ALIGN(0x1000): SUBALIGN(0x1000) { |
.init : { |
*(.init); |
} : text |
.text : { |
17,7 → 17,9 |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
. = . + 0x1000; |
.data : { |
*(.opd); |
*(.data .data.*); |
*(.sdata); |
/branches/network/uspace/lib/libc/arch/mips32eb/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = mips-sgi-irix5 |
TOOLCHAIN_DIR = /usr/local/mips/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin |
CFLAGS += -mips3 |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
/branches/network/uspace/lib/libc/arch/mips32eb/include/context_offset.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/network/uspace/lib/libc/arch/mips32eb/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/mips32eb/include/byteorder.h |
---|
0,0 → 1,43 |
/* |
* Copyright (c) 2005 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 libcmips32 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_mips32eb_BYTEORDER_H_ |
#define LIBC_mips32eb_BYTEORDER_H_ |
#define ARCH_IS_BIG_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/ppc32/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
/branches/network/uspace/lib/libc/arch/ppc32/include/context_offset.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/ppc32/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/ppc32/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/network/uspace/lib/libc/arch/ppc32/include/byteorder.h |
---|
0,0 → 1,43 |
/* |
* Copyright (c) 2005 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 libcppc32 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_ppc32_BYTEORDER_H_ |
#define LIBC_ppc32_BYTEORDER_H_ |
#define ARCH_IS_BIG_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/ppc32/src/entry.s |
---|
31,18 → 31,14 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# r3 contains the PCB pointer |
# |
__entry: |
# Pass the PCB pointer to __main() as the first argument. |
# Since the first argument is passed in r3, no operation is needed. |
bl __main |
bl __io_init |
bl main |
bl __exit |
__entry_driver: |
bl __main |
bl main |
bl __exit |
/branches/network/uspace/lib/libc/arch/ppc32/src/fibril.S |
---|
32,58 → 32,10 |
.global context_restore |
#include <libarch/regname.h> |
#include <libarch/context_offset.h> |
#include <arch/context_offset.h> |
.macro CONTEXT_STORE r |
stw sp, OFFSET_SP(\r) |
stw r2, OFFSET_R2(\r) |
stw r13, OFFSET_R13(\r) |
stw r14, OFFSET_R14(\r) |
stw r15, OFFSET_R15(\r) |
stw r16, OFFSET_R16(\r) |
stw r17, OFFSET_R17(\r) |
stw r18, OFFSET_R18(\r) |
stw r19, OFFSET_R19(\r) |
stw r20, OFFSET_R20(\r) |
stw r21, OFFSET_R21(\r) |
stw r22, OFFSET_R22(\r) |
stw r23, OFFSET_R23(\r) |
stw r24, OFFSET_R24(\r) |
stw r25, OFFSET_R25(\r) |
stw r26, OFFSET_R26(\r) |
stw r27, OFFSET_R27(\r) |
stw r28, OFFSET_R28(\r) |
stw r29, OFFSET_R29(\r) |
stw r30, OFFSET_R30(\r) |
stw r31, OFFSET_R31(\r) |
.endm |
.macro CONTEXT_LOAD r |
lwz sp, OFFSET_SP(\r) |
lwz r2, OFFSET_R2(\r) |
lwz r13, OFFSET_R13(\r) |
lwz r14, OFFSET_R14(\r) |
lwz r15, OFFSET_R15(\r) |
lwz r16, OFFSET_R16(\r) |
lwz r17, OFFSET_R17(\r) |
lwz r18, OFFSET_R18(\r) |
lwz r19, OFFSET_R19(\r) |
lwz r20, OFFSET_R20(\r) |
lwz r21, OFFSET_R21(\r) |
lwz r22, OFFSET_R22(\r) |
lwz r23, OFFSET_R23(\r) |
lwz r24, OFFSET_R24(\r) |
lwz r25, OFFSET_R25(\r) |
lwz r26, OFFSET_R26(\r) |
lwz r27, OFFSET_R27(\r) |
lwz r28, OFFSET_R28(\r) |
lwz r29, OFFSET_R29(\r) |
lwz r30, OFFSET_R30(\r) |
lwz r31, OFFSET_R31(\r) |
.endm |
context_save: |
CONTEXT_STORE r3 |
CONTEXT_SAVE_ARCH_CORE r3 |
mflr r4 |
stw r4, OFFSET_PC(r3) |
97,7 → 49,7 |
context_restore: |
CONTEXT_LOAD r3 |
CONTEXT_RESTORE_ARCH_CORE r3 |
lwz r4, OFFSET_CR(r3) |
mtcr r4 |
/branches/network/uspace/lib/libc/arch/ppc32/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x1000; |
. = 0x1000 + SIZEOF_HEADERS; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
.init : { |
*(.init); |
} :text |
.text : { |
17,7 → 17,9 |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
. = . + 0x1000; |
.data : { |
*(.data); |
*(.sdata); |
} :data |
/branches/network/uspace/lib/libc/arch/amd64/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = amd64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/amd64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
/branches/network/uspace/lib/libc/arch/amd64/include/context_offset.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/amd64/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/amd64/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/network/uspace/lib/libc/arch/amd64/include/atomic.h |
---|
38,11 → 38,11 |
#define LIBC_amd64_ATOMIC_H_ |
static inline void atomic_inc(atomic_t *val) { |
asm volatile ("lock incq %0\n" : "=m" (val->count)); |
asm volatile ("lock incq %0\n" : "+m" (val->count)); |
} |
static inline void atomic_dec(atomic_t *val) { |
asm volatile ("lock decq %0\n" : "=m" (val->count)); |
asm volatile ("lock decq %0\n" : "+m" (val->count)); |
} |
static inline long atomic_postinc(atomic_t *val) |
52,7 → 52,7 |
asm volatile ( |
"movq $1, %0\n" |
"lock xaddq %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
65,7 → 65,7 |
asm volatile ( |
"movq $-1, %0\n" |
"lock xaddq %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
/branches/network/uspace/lib/libc/arch/amd64/include/byteorder.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2005 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 libcamd64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_amd64_BYTEORDER_H_ |
#define LIBC_amd64_BYTEORDER_H_ |
/* AMD64 is little-endian */ |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/amd64/src/entry.s |
---|
31,18 → 31,14 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# %rdi contains the PCB pointer |
# |
__entry: |
# %rdi was deliberately chosen as the first argument is also in %rdi |
# Pass PCB pointer to __main (no operation) |
call __main |
call __io_init |
call main |
call __exit |
__entry_driver: |
call __main |
call main |
call __exit |
/branches/network/uspace/lib/libc/arch/amd64/src/fibril.S |
---|
31,7 → 31,7 |
.global context_save |
.global context_restore |
#include <libarch/context_offset.h> |
#include <kernel/arch/context_offset.h> |
## Save current CPU context |
# |
40,17 → 40,10 |
# |
context_save: |
movq (%rsp), %rdx # the caller's return %eip |
# In %edi is passed 1st argument |
movq %rdx, OFFSET_PC(%rdi) |
movq %rsp, OFFSET_SP(%rdi) |
CONTEXT_SAVE_ARCH_CORE %rdi %rdx |
movq %rbx, OFFSET_RBX(%rdi) |
movq %rbp, OFFSET_RBP(%rdi) |
movq %r12, OFFSET_R12(%rdi) |
movq %r13, OFFSET_R13(%rdi) |
movq %r14, OFFSET_R14(%rdi) |
movq %r15, OFFSET_R15(%rdi) |
# Save TLS |
movq %fs:0, %rax |
movq %rax, OFFSET_TLS(%rdi) |
66,16 → 59,9 |
# pointed by the 1st argument. Returns 0 in EAX. |
# |
context_restore: |
movq OFFSET_R15(%rdi), %r15 |
movq OFFSET_R14(%rdi), %r14 |
movq OFFSET_R13(%rdi), %r13 |
movq OFFSET_R12(%rdi), %r12 |
movq OFFSET_RBP(%rdi), %rbp |
movq OFFSET_RBX(%rdi), %rbx |
movq OFFSET_SP(%rdi), %rsp # ctx->sp -> %rsp |
CONTEXT_RESTORE_ARCH_CORE %rdi %rdx |
movq OFFSET_PC(%rdi), %rdx |
movq %rdx,(%rsp) |
# Set thread local storage |
/branches/network/uspace/lib/libc/arch/amd64/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x1000; |
. = 0x1000 + SIZEOF_HEADERS; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
.init : { |
*(.init); |
} :text |
.text : { |
17,7 → 17,9 |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
. = . + 0x1000; |
.data : { |
*(.data); |
} :data |
.tdata : { |
/branches/network/uspace/lib/libc/arch/ppc64/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = ppc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
/branches/network/uspace/lib/libc/arch/ppc64/include/context_offset.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/ppc64/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/ppc64/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/network/uspace/lib/libc/arch/ppc64/include/byteorder.h |
---|
0,0 → 1,43 |
/* |
* Copyright (c) 2005 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 libcppc64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_ppc64_BYTEORDER_H_ |
#define LIBC_ppc64_BYTEORDER_H_ |
#define ARCH_IS_BIG_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/ppc64/src/entry.s |
---|
31,7 → 31,6 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
38,11 → 37,4 |
# |
__entry: |
bl __main |
bl __io_init |
bl main |
bl __exit |
__entry_driver: |
bl __main |
bl main |
bl __exit |
/branches/network/uspace/lib/libc/arch/ppc64/src/fibril.S |
---|
32,58 → 32,10 |
.global context_restore |
#include <libarch/regname.h> |
#include <libarch/context_offset.h> |
#include <kernel/arch/context_offset.h> |
.macro CONTEXT_STORE r |
stw sp, OFFSET_SP(\r) |
stw r2, OFFSET_R2(\r) |
stw r13, OFFSET_R13(\r) |
stw r14, OFFSET_R14(\r) |
stw r15, OFFSET_R15(\r) |
stw r16, OFFSET_R16(\r) |
stw r17, OFFSET_R17(\r) |
stw r18, OFFSET_R18(\r) |
stw r19, OFFSET_R19(\r) |
stw r20, OFFSET_R20(\r) |
stw r21, OFFSET_R21(\r) |
stw r22, OFFSET_R22(\r) |
stw r23, OFFSET_R23(\r) |
stw r24, OFFSET_R24(\r) |
stw r25, OFFSET_R25(\r) |
stw r26, OFFSET_R26(\r) |
stw r27, OFFSET_R27(\r) |
stw r28, OFFSET_R28(\r) |
stw r29, OFFSET_R29(\r) |
stw r30, OFFSET_R30(\r) |
stw r31, OFFSET_R31(\r) |
.endm |
.macro CONTEXT_LOAD r |
lwz sp, OFFSET_SP(\r) |
lwz r2, OFFSET_R2(\r) |
lwz r13, OFFSET_R13(\r) |
lwz r14, OFFSET_R14(\r) |
lwz r15, OFFSET_R15(\r) |
lwz r16, OFFSET_R16(\r) |
lwz r17, OFFSET_R17(\r) |
lwz r18, OFFSET_R18(\r) |
lwz r19, OFFSET_R19(\r) |
lwz r20, OFFSET_R20(\r) |
lwz r21, OFFSET_R21(\r) |
lwz r22, OFFSET_R22(\r) |
lwz r23, OFFSET_R23(\r) |
lwz r24, OFFSET_R24(\r) |
lwz r25, OFFSET_R25(\r) |
lwz r26, OFFSET_R26(\r) |
lwz r27, OFFSET_R27(\r) |
lwz r28, OFFSET_R28(\r) |
lwz r29, OFFSET_R29(\r) |
lwz r30, OFFSET_R30(\r) |
lwz r31, OFFSET_R31(\r) |
.endm |
context_save: |
CONTEXT_STORE r3 |
CONTEXT_SAVE_ARCH_CORE r3 |
mflr r4 |
stw r4, OFFSET_PC(r3) |
97,7 → 49,7 |
context_restore: |
CONTEXT_LOAD r3 |
CONTEXT_RESTORE_ARCH_CORE r3 |
lwz r4, OFFSET_CR(r3) |
mtcr r4 |
/branches/network/uspace/lib/libc/arch/ppc64/src/syscall.c |
---|
36,13 → 36,16 |
#include <libc.h> |
sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2, const sysarg_t p3, const sysarg_t p4, const syscall_t id) |
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) |
{ |
register sysarg_t __ppc32_reg_r3 asm("3") = p1; |
register sysarg_t __ppc32_reg_r4 asm("4") = p2; |
register sysarg_t __ppc32_reg_r5 asm("5") = p3; |
register sysarg_t __ppc32_reg_r6 asm("6") = p4; |
register sysarg_t __ppc32_reg_r7 asm("7") = id; |
register sysarg_t __ppc32_reg_r7 asm("7") = p5; |
register sysarg_t __ppc32_reg_r8 asm("8") = p6; |
register sysarg_t __ppc32_reg_r9 asm("9") = id; |
asm volatile ( |
"sc\n" |
51,7 → 54,9 |
"r" (__ppc32_reg_r4), |
"r" (__ppc32_reg_r5), |
"r" (__ppc32_reg_r6), |
"r" (__ppc32_reg_r7) |
"r" (__ppc32_reg_r7), |
"r" (__ppc32_reg_r8), |
"r" (__ppc32_reg_r9) |
); |
return __ppc32_reg_r3; |
/branches/network/uspace/lib/libc/arch/ppc64/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x1000; |
. = 0x1000 + SIZEOF_HEADERS; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
.init : { |
*(.init); |
} :text |
.text : { |
18,7 → 18,9 |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
. = . + 0x1000; |
.data : { |
*(.opd); |
*(.data*); |
*(.sdata); |
/branches/network/uspace/lib/libc/arch/mips32/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = /usr/local/mipsel/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin |
CFLAGS += -mips3 |
-include ../../Makefile.config |
/branches/network/uspace/lib/libc/arch/mips32/include/context_offset.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/mips32/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/mips32/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 14 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/network/uspace/lib/libc/arch/mips32/include/atomic.h |
---|
64,7 → 64,7 |
" sc %0, %1\n" |
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */ |
/* nop */ /* nop is inserted automatically by compiler */ |
: "=r" (tmp), "=m" (val->count), "=r" (v) |
: "=&r" (tmp), "+m" (val->count), "=&r" (v) |
: "i" (i), "i" (0) |
); |
/branches/network/uspace/lib/libc/arch/mips32/include/byteorder.h |
---|
0,0 → 1,43 |
/* |
* Copyright (c) 2005 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 libcmips32 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_mips32_BYTEORDER_H_ |
#define LIBC_mips32_BYTEORDER_H_ |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/mips32/src/entry.s |
---|
35,6 → 35,7 |
## User-space task entry point |
# |
# $a0 ($4) contains the PCB pointer |
# |
.ent __entry |
__entry: |
41,7 → 42,6 |
.frame $sp, 32, $31 |
.cpload $25 |
# Mips o32 may store its arguments on stack, make space (16 bytes), |
# so that it could work with -O0 |
# Make space additional 16 bytes for the stack frame |
49,41 → 49,17 |
addiu $sp, -32 |
.cprestore 16 # Allow PIC code |
# Pass pcb_ptr to __main() as the first argument. pcb_ptr is already |
# in $a0. As the first argument is passed in $a0, no operation |
# is needed. |
jal __main |
nop |
jal __io_init |
nop |
jal main |
nop |
jal __exit |
nop |
.end |
.ent __entry_driver |
__entry_driver: |
.frame $sp, 32, $31 |
.cpload $25 |
# Mips o32 may store its arguments on stack, make space (16 bytes), |
# so that it could work with -O0 |
# Make space additional 16 bytes for the stack frame |
addiu $sp, -32 |
.cprestore 16 # Allow PIC code |
jal __main |
nop |
jal main |
nop |
jal __exit |
nop |
.end |
# Alignment of output section data to 0x4000 |
.section .data |
.align 14 |
/branches/network/uspace/lib/libc/arch/mips32/src/fibril.S |
---|
31,119 → 31,13 |
.set noat |
.set noreorder |
#include <arch/context_offset.h> |
#include <arch/asm/regname.h> |
#include <libarch/context_offset.h> |
.global context_save |
.global context_restore |
.macro CONTEXT_STORE r |
sw $s0,OFFSET_S0(\r) |
sw $s1,OFFSET_S1(\r) |
sw $s2,OFFSET_S2(\r) |
sw $s3,OFFSET_S3(\r) |
sw $s4,OFFSET_S4(\r) |
sw $s5,OFFSET_S5(\r) |
sw $s6,OFFSET_S6(\r) |
sw $s7,OFFSET_S7(\r) |
sw $s8,OFFSET_S8(\r) |
sw $gp,OFFSET_GP(\r) |
sw $k1,OFFSET_TLS(\r) |
#ifdef CONFIG_MIPS_FPU |
mfc1 $t0,$20 |
sw $t0, OFFSET_F20(\r) |
mfc1 $t0,$21 |
sw $t0, OFFSET_F21(\r) |
mfc1 $t0,$22 |
sw $t0, OFFSET_F22(\r) |
mfc1 $t0,$23 |
sw $t0, OFFSET_F23(\r) |
mfc1 $t0,$24 |
sw $t0, OFFSET_F24(\r) |
mfc1 $t0,$25 |
sw $t0, OFFSET_F25(\r) |
mfc1 $t0,$26 |
sw $t0, OFFSET_F26(\r) |
mfc1 $t0,$27 |
sw $t0, OFFSET_F27(\r) |
mfc1 $t0,$28 |
sw $t0, OFFSET_F28(\r) |
mfc1 $t0,$29 |
sw $t0, OFFSET_F29(\r) |
mfc1 $t0,$30 |
sw $t0, OFFSET_F30(\r) |
#endif |
sw $ra,OFFSET_PC(\r) |
sw $sp,OFFSET_SP(\r) |
.endm |
.macro CONTEXT_LOAD r |
lw $s0,OFFSET_S0(\r) |
lw $s1,OFFSET_S1(\r) |
lw $s2,OFFSET_S2(\r) |
lw $s3,OFFSET_S3(\r) |
lw $s4,OFFSET_S4(\r) |
lw $s5,OFFSET_S5(\r) |
lw $s6,OFFSET_S6(\r) |
lw $s7,OFFSET_S7(\r) |
lw $s8,OFFSET_S8(\r) |
lw $gp,OFFSET_GP(\r) |
lw $k1,OFFSET_TLS(\r) |
#ifdef CONFIG_MIPS_FPU |
lw $t0, OFFSET_F20(\r) |
mtc1 $t0,$20 |
lw $t0, OFFSET_F21(\r) |
mtc1 $t0,$21 |
lw $t0, OFFSET_F22(\r) |
mtc1 $t0,$22 |
lw $t0, OFFSET_F23(\r) |
mtc1 $t0,$23 |
lw $t0, OFFSET_F24(\r) |
mtc1 $t0,$24 |
lw $t0, OFFSET_F25(\r) |
mtc1 $t0,$25 |
lw $t0, OFFSET_F26(\r) |
mtc1 $t0,$26 |
lw $t0, OFFSET_F27(\r) |
mtc1 $t0,$27 |
lw $t0, OFFSET_F28(\r) |
mtc1 $t0,$28 |
lw $t0, OFFSET_F29(\r) |
mtc1 $t0,$29 |
lw $t0, OFFSET_F30(\r) |
mtc1 $t0,$30 |
#endif |
lw $ra,OFFSET_PC(\r) |
lw $sp,OFFSET_SP(\r) |
.endm |
context_save: |
CONTEXT_STORE $a0 |
CONTEXT_SAVE_ARCH_CORE $a0 |
# context_save returns 1 |
j $ra |
150,7 → 44,7 |
li $v0, 1 |
context_restore: |
CONTEXT_LOAD $a0 |
CONTEXT_RESTORE_ARCH_CORE $a0 |
# Just for the jump into first function, but one instruction |
# should not bother us |
/branches/network/uspace/lib/libc/arch/mips32/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x4000; |
. = 0x4000 + SIZEOF_HEADERS; |
.init ALIGN(0x4000) : SUBALIGN(0x4000) { |
.init : { |
*(.init); |
} :text |
.text : { |
17,6 → 17,8 |
*(.rodata*); |
} :text |
. = . + 0x4000; |
.data : { |
*(.data); |
*(.data.rel*); |
/branches/network/uspace/lib/libc/arch/ia32/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/i686/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
/branches/network/uspace/lib/libc/arch/ia32/include/setjmp.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/ia32/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/ia32/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/network/uspace/lib/libc/arch/ia32/include/atomic.h |
---|
36,11 → 36,11 |
#define LIBC_ia32_ATOMIC_H_ |
static inline void atomic_inc(atomic_t *val) { |
asm volatile ("lock incl %0\n" : "=m" (val->count)); |
asm volatile ("lock incl %0\n" : "+m" (val->count)); |
} |
static inline void atomic_dec(atomic_t *val) { |
asm volatile ("lock decl %0\n" : "=m" (val->count)); |
asm volatile ("lock decl %0\n" : "+m" (val->count)); |
} |
static inline long atomic_postinc(atomic_t *val) |
50,7 → 50,7 |
asm volatile ( |
"movl $1, %0\n" |
"lock xaddl %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
63,7 → 63,7 |
asm volatile ( |
"movl $-1, %0\n" |
"lock xaddl %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
/branches/network/uspace/lib/libc/arch/ia32/include/byteorder.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2005 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 libcia32 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_ia32_BYTEORDER_H_ |
#define LIBC_ia32_BYTEORDER_H_ |
/* IA-32 is little-endian */ |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/ia32/src/entry.s |
---|
31,10 → 31,10 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# %ebx contains the PCB pointer |
# |
__entry: |
mov %ss, %ax |
43,18 → 43,8 |
mov %ax, %fs |
# Do not set %gs, it contains descriptor that can see TLS |
# Pass the PCB pointer to __main as the first argument |
pushl %ebx |
call __main |
call __io_init |
call main |
call __exit |
__entry_driver: |
mov %ss, %ax |
mov %ax, %ds |
mov %ax, %es |
mov %ax, %fs |
# Do not set %gs, it contains descriptor that can see TLS |
call __main |
call main |
call __exit |
/branches/network/uspace/lib/libc/arch/ia32/src/syscall.S |
---|
53,4 → 53,3 |
popl %esi |
popl %ebx |
ret |
/branches/network/uspace/lib/libc/arch/ia32/src/setjmp.S |
---|
26,6 → 26,8 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#include <kernel/arch/context_offset.h> |
.text |
.global setjmp |
.global longjmp |
32,18 → 34,13 |
.type setjmp,@function |
setjmp: |
movl 0(%esp), %ecx # save current pc |
leal 4(%esp), %edx # save stack pointer |
movl (%edx), %eax # get jmp_buf pointer |
movl 0(%esp),%eax # save pc value into eax |
movl 4(%esp),%edx # address of the jmp_buf structure to save context to |
# Save registers |
movl %ebx, 0(%eax) |
movl %esi, 4(%eax) |
movl %edi, 8(%eax) |
movl %ebp, 12(%eax) |
movl %edx, 16(%eax) |
# save registers to the jmp_buf structure |
CONTEXT_SAVE_ARCH_CORE %edx %eax |
movl %ecx, 20(%eax) # save pc |
xorl %eax,%eax # set_jmp returns 0 |
ret |
.type longjmp,@function |
52,12 → 49,9 |
movl 4(%esp), %ecx # put address of jmp_buf into ecx |
movl 8(%esp), %eax # put return value into eax |
# restore all registers |
movl 0(%ecx), %ebx |
movl 4(%ecx), %esi |
movl 8(%ecx), %edi |
movl 12(%ecx), %ebp |
movl 16(%ecx), %esp |
# restore registers from the jmp_buf structure |
CONTEXT_RESTORE_ARCH_CORE %ecx %edx |
movl 20(%ecx), %edx # saved return address |
jmp *%edx |
movl %edx,0(%esp) # put saved pc on stack |
ret |
/branches/network/uspace/lib/libc/arch/ia32/src/fibril.S |
---|
26,6 → 26,8 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#include <kernel/arch/context_offset.h> |
.text |
.global context_save |
41,16 → 43,12 |
movl 0(%esp),%eax # the caller's return %eip |
movl 4(%esp),%edx # address of the context variable to save context to |
movl %esp,0(%edx) # %esp -> ctx->sp |
movl %eax,4(%edx) # %eip -> ctx->pc |
movl %ebx,8(%edx) # %ebx -> ctx->ebx |
movl %esi,12(%edx) # %esi -> ctx->esi |
movl %edi,16(%edx) # %edi -> ctx->edi |
movl %ebp,20(%edx) # %ebp -> ctx->ebp |
# save registers to the context structure |
CONTEXT_SAVE_ARCH_CORE %edx %eax |
# Save TLS |
movl %gs:0, %eax |
movl %eax, 24(%edx) # tls -> ctx->tls |
movl %eax, OFFSET_TLS(%edx) # tls -> ctx->tls |
xorl %eax,%eax # context_save returns 1 |
incl %eax |
64,18 → 62,15 |
# |
context_restore: |
movl 4(%esp),%eax # address of the context variable to restore context from |
movl 0(%eax),%esp # ctx->sp -> %esp |
movl 4(%eax),%edx # ctx->pc -> %edx |
movl 8(%eax),%ebx # ctx->ebx -> %ebx |
movl 12(%eax),%esi # ctx->esi -> %esi |
movl 16(%eax),%edi # ctx->edi -> %edi |
movl 20(%eax),%ebp # ctx->ebp -> %ebp |
# restore registers from the context structure |
CONTEXT_RESTORE_ARCH_CORE %eax %edx |
movl %edx,0(%esp) # ctx->pc -> saver's return %eip |
# Set thread local storage |
pushl %edx |
movl 24(%eax), %edx # Set arg1 to TLS addr |
movl OFFSET_TLS(%eax), %edx # Set arg1 to TLS addr |
movl $1, %eax # Syscall SYS_TLS_SET |
int $0x30 |
popl %edx |
/branches/network/uspace/lib/libc/arch/ia32/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x1000; |
. = 0x1000 + SIZEOF_HEADERS; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
.init : { |
*(.init); |
} :text |
.text : { |
17,7 → 17,9 |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
. = . + 0x1000; |
.data : { |
*(.data); |
} :data |
.tdata : { |
/branches/network/uspace/lib/libc/arch/sparc64/Makefile.inc |
---|
29,8 → 29,12 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/sparc64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
/branches/network/uspace/lib/libc/arch/sparc64/include/context_offset.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/sparc64/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/arch/sparc64/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 14 |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /**< Only one page color. */ |
#endif |
/branches/network/uspace/lib/libc/arch/sparc64/include/byteorder.h |
---|
0,0 → 1,43 |
/* |
* Copyright (c) 2005 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 libcsparc64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_sparc64_BYTEORDER_H_ |
#define LIBC_sparc64_BYTEORDER_H_ |
#define ARCH_IS_BIG_ENDIAN |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/arch/sparc64/src/entry.s |
---|
31,27 → 31,18 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# %o0 contains uarg |
# %o1 contains pcb_ptr |
# |
__entry: |
# Pass pcb_ptr as the first argument to __main() |
mov %o1, %o0 |
sethi %hi(_gp), %l7 |
call __main |
or %l7, %lo(_gp), %l7 |
call __io_init |
nop |
call main |
nop |
call __exit |
nop |
__entry_driver: |
sethi %hi(_gp), %l7 |
call __main |
or %l7, %lo(_gp), %l7 |
call main |
nop |
call __exit |
nop |
/branches/network/uspace/lib/libc/arch/sparc64/src/fibril.S |
---|
26,7 → 26,7 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#include <libarch/context_offset.h> |
#include <kernel/arch/context_offset.h> |
.text |
33,52 → 33,8 |
.global context_save |
.global context_restore |
.macro CONTEXT_STORE r |
stx %sp, [\r + OFFSET_SP] |
stx %o7, [\r + OFFSET_PC] |
stx %i0, [\r + OFFSET_I0] |
stx %i1, [\r + OFFSET_I1] |
stx %i2, [\r + OFFSET_I2] |
stx %i3, [\r + OFFSET_I3] |
stx %i4, [\r + OFFSET_I4] |
stx %i5, [\r + OFFSET_I5] |
stx %fp, [\r + OFFSET_FP] |
stx %i7, [\r + OFFSET_I7] |
stx %l0, [\r + OFFSET_L0] |
stx %l1, [\r + OFFSET_L1] |
stx %l2, [\r + OFFSET_L2] |
stx %l3, [\r + OFFSET_L3] |
stx %l4, [\r + OFFSET_L4] |
stx %l5, [\r + OFFSET_L5] |
stx %l6, [\r + OFFSET_L6] |
stx %l7, [\r + OFFSET_L7] |
stx %g7, [\r + OFFSET_TP] |
.endm |
.macro CONTEXT_LOAD r |
ldx [\r + OFFSET_SP], %sp |
ldx [\r + OFFSET_PC], %o7 |
ldx [\r + OFFSET_I0], %i0 |
ldx [\r + OFFSET_I1], %i1 |
ldx [\r + OFFSET_I2], %i2 |
ldx [\r + OFFSET_I3], %i3 |
ldx [\r + OFFSET_I4], %i4 |
ldx [\r + OFFSET_I5], %i5 |
ldx [\r + OFFSET_FP], %fp |
ldx [\r + OFFSET_I7], %i7 |
ldx [\r + OFFSET_L0], %l0 |
ldx [\r + OFFSET_L1], %l1 |
ldx [\r + OFFSET_L2], %l2 |
ldx [\r + OFFSET_L3], %l3 |
ldx [\r + OFFSET_L4], %l4 |
ldx [\r + OFFSET_L5], %l5 |
ldx [\r + OFFSET_L6], %l6 |
ldx [\r + OFFSET_L7], %l7 |
ldx [\r + OFFSET_TP], %g7 |
.endm |
context_save: |
CONTEXT_STORE %o0 |
CONTEXT_SAVE_ARCH_CORE %o0 |
retl |
mov 1, %o0 ! context_save_arch returns 1 |
92,6 → 48,6 |
# |
flushw |
CONTEXT_LOAD %o0 |
CONTEXT_RESTORE_ARCH_CORE %o0 |
retl |
xor %o0, %o0, %o0 ! context_restore_arch returns 0 |
/branches/network/uspace/lib/libc/arch/sparc64/_link.ld.in |
---|
7,9 → 7,9 |
} |
SECTIONS { |
. = 0x4000; |
. = 0x4000 + SIZEOF_HEADERS; |
.init ALIGN(0x4000) : SUBALIGN(0x4000) { |
.init : { |
*(.init); |
} :text |
.text : { |
17,11 → 17,13 |
*(.rodata*); |
} :text |
.got ALIGN(0x4000) : SUBALIGN(0x4000) { |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
.data ALIGN(0x4000) : SUBALIGN(0x4000) { |
.data : { |
*(.data); |
*(.sdata); |
} :data |
/branches/network/uspace/lib/libc/generic/vfs.c |
---|
File deleted |
/branches/network/uspace/lib/libc/generic/io/asprintf.c |
---|
0,0 → 1,79 |
/* |
* Copyright (c) 2006 Josef Cejka |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#include <stdarg.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <io/printf_core.h> |
static int asprintf_prewrite(const char *str, size_t count, void *unused) |
{ |
return count; |
} |
/** Allocate and print to string. |
* |
* @param strp Address of the pointer where to store the address of |
* the newly allocated string. |
* @fmt Format strin. |
* |
* @return Number of characters printed or a negative error code. |
*/ |
int asprintf(char **strp, const char *fmt, ...) |
{ |
struct printf_spec ps = { |
asprintf_prewrite, |
NULL |
}; |
int ret; |
va_list args; |
va_start(args, fmt); |
ret = printf_core(fmt, &ps, args); |
va_end(args); |
if (ret > 0) { |
*strp = malloc(ret + 20); |
if (!*strp) |
return -1; |
va_start(args, fmt); |
vsprintf(*strp, fmt, args); |
va_end(args); |
} |
return ret; |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/io/vsnprintf.c |
---|
44,16 → 44,21 |
}; |
/** Write string to given buffer. |
* Write at most data->size characters including trailing zero. According to C99 has snprintf to return number |
* of characters that would have been written if enough space had been available. Hence the return value is not |
* number of really printed characters but size of input string. Number of really used characters |
* is stored in data->len. |
* @param str source string to print |
* @param count size of source string |
* @param data structure with destination string, counter of used space and total string size. |
* @return number of characters to print (not characters really printed!) |
* Write at most data->size characters including trailing zero. According to C99 |
* has snprintf to return number of characters that would have been written if |
* enough space had been available. Hence the return value is not number of |
* really printed characters but size of input string. Number of really used |
* characters is stored in data->len. |
* |
* @param str Source string to print. |
* @param count Size of the source string. |
* @param data Structure with destination string, counter of used space |
* and total string size. |
* @return Number of characters to print (not characters really |
* printed!) |
*/ |
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
static int |
vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
{ |
size_t i; |
i = data->size - data->len; |
63,7 → 68,10 |
} |
if (i == 1) { |
/* We have only one free byte left in buffer => write there trailing zero */ |
/* |
* We have only one free byte left in buffer => write there |
* trailing zero. |
*/ |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
70,7 → 78,10 |
} |
if (i <= count) { |
/* We have not enought space for whole string with the trailing zero => print only a part of string */ |
/* |
* We have not enought space for whole string with the trailing |
* zero => print only a part of string. |
*/ |
memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
data->string[data->size - 1] = 0; |
data->len = data->size; |
80,7 → 91,10 |
/* Buffer is big enought to print whole string */ |
memcpy((void *)(data->string + data->len), (void *)str, count); |
data->len += count; |
/* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */ |
/* |
* Put trailing zero at end, but not count it into data->len so it could |
* be rewritten next time. |
*/ |
data->string[data->len] = 0; |
return count; |
87,17 → 101,22 |
} |
/** Print formatted to the given buffer with limited size. |
* @param str buffer |
* @param size buffer size |
* @param fmt format string |
* @param str Buffer. |
* @param size Bffer size. |
* @param fmt Format string. |
* \see For more details about format string see printf_core. |
*/ |
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) |
{ |
struct vsnprintf_data data = {size, 0, str}; |
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vsnprintf_write, &data}; |
struct printf_spec ps = { |
(int(*)(void *, size_t, void *)) vsnprintf_write, |
&data |
}; |
/* Print 0 at end of string - fix the case that nothing will be printed */ |
/* |
* Print 0 at end of string - fix the case that nothing will be printed. |
*/ |
if (size > 0) |
str[0] = 0; |
/branches/network/uspace/lib/libc/generic/io/sprintf.c |
---|
48,7 → 48,6 |
va_start(args, fmt); |
ret = vsprintf(str, fmt, args); |
va_end(args); |
return ret; |
/branches/network/uspace/lib/libc/generic/io/printf_core.c |
---|
94,12 → 94,9 |
if (str == NULL) |
return printf_putnchars("(NULL)", 6, ps); |
for (count = 0; str[count] != 0; count++); |
count = strlen(str); |
if (ps->write((void *) str, count, ps->data) == count) |
return 0; |
return EOF; |
return ps->write((void *) str, count, ps->data); |
} |
/** Print one character to output |
/branches/network/uspace/lib/libc/generic/io/stream.c |
---|
56,21 → 56,26 |
ssize_t read_stdin(void *buf, size_t count) |
{ |
open_console(); |
if (console_phone >= 0) { |
ipcarg_t r0, r1; |
size_t i = 0; |
while (i < count) { |
if (async_req_0_2(console_phone, CONSOLE_GETCHAR, &r0, |
&r1) < 0) { |
if (async_req_0_2(console_phone, CONSOLE_GETCHAR, &r0, &r1) < 0) |
return -1; |
} |
((char *) buf)[i++] = r0; |
} |
return i; |
} else { |
return -1; |
} |
} |
ssize_t write_stdout(const void *buf, size_t count) |
{ |
open_console(); |
if (console_phone >= 0) { |
int i; |
for (i = 0; i < count; i++) |
78,30 → 83,36 |
((const char *) buf)[i]); |
return count; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count); |
} |
void open_stdin(void) |
void open_console(void) |
{ |
if (console_phone < 0) { |
while ((console_phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0)) < 0) { |
usleep(10000); |
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0, 0); |
if (phone >= 0) |
console_phone = phone; |
} |
} |
} |
void open_stdout(void) |
void close_console(void) |
{ |
if (console_phone < 0) { |
while ((console_phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0)) < 0) { |
usleep(10000); |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) { |
console_phone = -1; |
} |
} |
} |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
} |
int get_cons_phone(void) |
{ |
open_console(); |
return console_phone; |
} |
/branches/network/uspace/lib/libc/generic/getopt.c |
---|
0,0 → 1,478 |
/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */ |
/*- |
* Copyright (c) 2000 The NetBSD Foundation, Inc. |
* All rights reserved. |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* by Dieter Baron and Thomas Klausner. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. 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. |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``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 FOUNDATION OR CONTRIBUTORS |
* 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. |
*/ |
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */ |
#include <assert.h> |
#include <stdarg.h> |
#include <err.h> |
#include <errno.h> |
#include <getopt.h> |
#include <stdlib.h> |
#include <string.h> |
/* HelenOS Port : We're incorporating only the modern getopt_long with wrappers |
* to keep legacy getopt() usage from breaking. All references to REPLACE_GETOPT |
* are dropped, we just include the code */ |
int opterr = 1; /* if error message should be printed */ |
int optind = 1; /* index into parent argv vector */ |
int optopt = '?'; /* character checked for validity */ |
int optreset; /* reset getopt */ |
char *optarg; /* argument associated with option */ |
#define IGNORE_FIRST (*options == '-' || *options == '+') |
#define PRINT_ERROR ((opterr) && ((*options != ':') \ |
|| (IGNORE_FIRST && options[1] != ':'))) |
/*HelenOS Port - POSIXLY_CORRECT is always false */ |
#define IS_POSIXLY_CORRECT 0 |
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) |
/* XXX: GNU ignores PC if *options == '-' */ |
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') |
/* return values */ |
#define BADCH (int)'?' |
#define BADARG ((IGNORE_FIRST && options[1] == ':') \ |
|| (*options == ':') ? (int)':' : (int)'?') |
#define INORDER (int)1 |
#define EMSG "" |
static int getopt_internal(int, char **, const char *); |
static int gcd(int, int); |
static void permute_args(int, int, int, char **); |
static const char *place = EMSG; /* option letter processing */ |
/* XXX: set optreset to 1 rather than these two */ |
static int nonopt_start = -1; /* first non option argument (for permute) */ |
static int nonopt_end = -1; /* first option after non options (for permute) */ |
/* Error messages */ |
/* HelenOS Port: Calls to warnx() were eliminated (as we have no stderr that |
* may be redirected) and replaced with printf. As such, error messages now |
* end in a newline */ |
static const char recargchar[] = "option requires an argument -- %c\n"; |
static const char recargstring[] = "option requires an argument -- %s\n"; |
static const char ambig[] = "ambiguous option -- %.*s\n"; |
static const char noarg[] = "option doesn't take an argument -- %.*s\n"; |
static const char illoptchar[] = "unknown option -- %c\n"; |
static const char illoptstring[] = "unknown option -- %s\n"; |
/* |
* Compute the greatest common divisor of a and b. |
*/ |
static int |
gcd(a, b) |
int a; |
int b; |
{ |
int c; |
c = a % b; |
while (c != 0) { |
a = b; |
b = c; |
c = a % b; |
} |
return b; |
} |
/* |
* Exchange the block from nonopt_start to nonopt_end with the block |
* from nonopt_end to opt_end (keeping the same order of arguments |
* in each block). |
*/ |
static void |
permute_args(panonopt_start, panonopt_end, opt_end, nargv) |
int panonopt_start; |
int panonopt_end; |
int opt_end; |
char **nargv; |
{ |
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
char *swap; |
assert(nargv != NULL); |
/* |
* compute lengths of blocks and number and size of cycles |
*/ |
nnonopts = panonopt_end - panonopt_start; |
nopts = opt_end - panonopt_end; |
ncycle = gcd(nnonopts, nopts); |
cyclelen = (opt_end - panonopt_start) / ncycle; |
for (i = 0; i < ncycle; i++) { |
cstart = panonopt_end+i; |
pos = cstart; |
for (j = 0; j < cyclelen; j++) { |
if (pos >= panonopt_end) |
pos -= nnonopts; |
else |
pos += nopts; |
swap = nargv[pos]; |
nargv[pos] = nargv[cstart]; |
nargv[cstart] = swap; |
} |
} |
} |
/* |
* getopt_internal -- |
* Parse argc/argv argument vector. Called by user level routines. |
* Returns -2 if -- is found (can be long option or end of options marker). |
*/ |
static int |
getopt_internal(nargc, nargv, options) |
int nargc; |
char **nargv; |
const char *options; |
{ |
char *oli; /* option letter list index */ |
int optchar; |
assert(nargv != NULL); |
assert(options != NULL); |
optarg = NULL; |
/* |
* XXX Some programs (like rsyncd) expect to be able to |
* XXX re-initialize optind to 0 and have getopt_long(3) |
* XXX properly function again. Work around this braindamage. |
*/ |
if (optind == 0) |
optind = 1; |
if (optreset) |
nonopt_start = nonopt_end = -1; |
start: |
if (optreset || !*place) { /* update scanning pointer */ |
optreset = 0; |
if (optind >= nargc) { /* end of argument vector */ |
place = EMSG; |
if (nonopt_end != -1) { |
/* do permutation, if we have to */ |
permute_args(nonopt_start, nonopt_end, |
optind, nargv); |
optind -= nonopt_end - nonopt_start; |
} |
else if (nonopt_start != -1) { |
/* |
* If we skipped non-options, set optind |
* to the first of them. |
*/ |
optind = nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((*(place = nargv[optind]) != '-') |
|| (place[1] == '\0')) { /* found non-option */ |
place = EMSG; |
if (IN_ORDER) { |
/* |
* GNU extension: |
* return non-option as argument to option 1 |
*/ |
optarg = nargv[optind++]; |
return INORDER; |
} |
if (!PERMUTE) { |
/* |
* if no permutation wanted, stop parsing |
* at first non-option |
*/ |
return -1; |
} |
/* do permutation */ |
if (nonopt_start == -1) |
nonopt_start = optind; |
else if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, |
optind, nargv); |
nonopt_start = optind - |
(nonopt_end - nonopt_start); |
nonopt_end = -1; |
} |
optind++; |
/* process next argument */ |
goto start; |
} |
if (nonopt_start != -1 && nonopt_end == -1) |
nonopt_end = optind; |
if (place[1] && *++place == '-') { /* found "--" */ |
place++; |
return -2; |
} |
} |
if ((optchar = (int)*place++) == (int)':' || |
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
/* option letter unknown or ':' */ |
if (!*place) |
++optind; |
if (PRINT_ERROR) |
printf(illoptchar, optchar); |
optopt = optchar; |
return BADCH; |
} |
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ |
/* XXX: what if no long options provided (called by getopt)? */ |
if (*place) |
return -2; |
if (++optind >= nargc) { /* no arg */ |
place = EMSG; |
if (PRINT_ERROR) |
printf(recargchar, optchar); |
optopt = optchar; |
return BADARG; |
} else /* white space */ |
place = nargv[optind]; |
/* |
* Handle -W arg the same as --arg (which causes getopt to |
* stop parsing). |
*/ |
return -2; |
} |
if (*++oli != ':') { /* doesn't take argument */ |
if (!*place) |
++optind; |
} else { /* takes (optional) argument */ |
optarg = NULL; |
if (*place) /* no white space */ |
optarg = *place; |
/* XXX: disable test for :: if PC? (GNU doesn't) */ |
else if (oli[1] != ':') { /* arg not optional */ |
if (++optind >= nargc) { /* no arg */ |
place = EMSG; |
if (PRINT_ERROR) |
printf(recargchar, optchar); |
optopt = optchar; |
return BADARG; |
} else |
optarg = nargv[optind]; |
} |
place = EMSG; |
++optind; |
} |
/* dump back option letter */ |
return optchar; |
} |
/* |
* getopt -- |
* Parse argc/argv argument vector. |
*/ |
int |
getopt(nargc, nargv, options) |
int nargc; |
char * const *nargv; |
const char *options; |
{ |
int retval; |
assert(nargv != NULL); |
assert(options != NULL); |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
++optind; |
/* |
* We found an option (--), so if we skipped non-options, |
* we have to permute. |
*/ |
if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, optind, |
(char **)nargv); |
optind -= nonopt_end - nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
retval = -1; |
} |
return retval; |
} |
/* |
* getopt_long -- |
* Parse argc/argv argument vector. |
*/ |
int |
getopt_long(nargc, nargv, options, long_options, idx) |
int nargc; |
char * const *nargv; |
const char *options; |
const struct option *long_options; |
int *idx; |
{ |
int retval; |
#define IDENTICAL_INTERPRETATION(_x, _y) \ |
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ |
long_options[(_x)].flag == long_options[(_y)].flag && \ |
long_options[(_x)].val == long_options[(_y)].val) |
assert(nargv != NULL); |
assert(options != NULL); |
assert(long_options != NULL); |
/* idx may be NULL */ |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
char *current_argv, *has_equal; |
size_t current_argv_len; |
int i, ambiguous, match; |
current_argv = (char *)place; |
match = -1; |
ambiguous = 0; |
optind++; |
place = EMSG; |
if (*current_argv == '\0') { /* found "--" */ |
/* |
* We found an option (--), so if we skipped |
* non-options, we have to permute. |
*/ |
if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, |
optind, (char **)nargv); |
optind -= nonopt_end - nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((has_equal = strchr(current_argv, '=')) != NULL) { |
/* argument found (--option=arg) */ |
current_argv_len = has_equal - current_argv; |
has_equal++; |
} else |
current_argv_len = strlen(current_argv); |
for (i = 0; long_options[i].name; i++) { |
/* find matching long option */ |
if (strncmp(current_argv, long_options[i].name, |
current_argv_len)) |
continue; |
if (strlen(long_options[i].name) == |
(unsigned)current_argv_len) { |
/* exact match */ |
match = i; |
ambiguous = 0; |
break; |
} |
if (match == -1) /* partial match */ |
match = i; |
else if (!IDENTICAL_INTERPRETATION(i, match)) |
ambiguous = 1; |
} |
if (ambiguous) { |
/* ambiguous abbreviation */ |
if (PRINT_ERROR) |
printf(ambig, (int)current_argv_len, |
current_argv); |
optopt = 0; |
return BADCH; |
} |
if (match != -1) { /* option found */ |
if (long_options[match].has_arg == no_argument |
&& has_equal) { |
if (PRINT_ERROR) |
printf(noarg, (int)current_argv_len, |
current_argv); |
/* |
* XXX: GNU sets optopt to val regardless of |
* flag |
*/ |
if (long_options[match].flag == NULL) |
optopt = long_options[match].val; |
else |
optopt = 0; |
return BADARG; |
} |
if (long_options[match].has_arg == required_argument || |
long_options[match].has_arg == optional_argument) { |
if (has_equal) |
optarg = has_equal; |
else if (long_options[match].has_arg == |
required_argument) { |
/* |
* optional argument doesn't use |
* next nargv |
*/ |
optarg = nargv[optind++]; |
} |
} |
if ((long_options[match].has_arg == required_argument) |
&& (optarg == NULL)) { |
/* |
* Missing argument; leading ':' |
* indicates no error should be generated |
*/ |
if (PRINT_ERROR) |
printf(recargstring, current_argv); |
/* |
* XXX: GNU sets optopt to val regardless |
* of flag |
*/ |
if (long_options[match].flag == NULL) |
optopt = long_options[match].val; |
else |
optopt = 0; |
--optind; |
return BADARG; |
} |
} else { /* unknown option */ |
if (PRINT_ERROR) |
printf(illoptstring, current_argv); |
optopt = 0; |
return BADCH; |
} |
if (long_options[match].flag) { |
*long_options[match].flag = long_options[match].val; |
retval = 0; |
} else |
retval = long_options[match].val; |
if (idx) |
*idx = match; |
} |
return retval; |
#undef IDENTICAL_INTERPRETATION |
} |
/branches/network/uspace/lib/libc/generic/ipc.c |
---|
682,7 → 682,7 |
{ |
int res; |
sysarg_t tmp_flags; |
res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, |
res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, |
(ipcarg_t) size, arg, NULL, &tmp_flags); |
if (flags) |
*flags = tmp_flags; |
742,7 → 742,7 |
*/ |
int ipc_share_out_start(int phoneid, void *src, int flags) |
{ |
return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0, |
return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0, |
(ipcarg_t) flags); |
} |
770,7 → 770,7 |
assert(flags); |
*callid = async_get_call(&data); |
if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE) |
if (IPC_GET_METHOD(data) != IPC_M_SHARE_OUT) |
return 0; |
*size = (size_t) IPC_GET_ARG2(data); |
*flags = (int) IPC_GET_ARG3(data); |
803,7 → 803,7 |
*/ |
int ipc_data_read_start(int phoneid, void *dst, size_t size) |
{ |
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst, |
return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst, |
(ipcarg_t) size); |
} |
862,7 → 862,7 |
*/ |
int ipc_data_write_start(int phoneid, void *src, size_t size) |
{ |
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, |
return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, |
(ipcarg_t) size); |
} |
/branches/network/uspace/lib/libc/generic/vfs/canonify.c |
---|
0,0 → 1,340 |
/* |
* 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 libc |
* @{ |
*/ |
/** |
* @file |
* @brief |
*/ |
#include <stdlib.h> |
/** Token types used for tokenization of path. */ |
typedef enum { |
TK_INVALID, |
TK_SLASH, |
TK_DOT, |
TK_DOTDOT, |
TK_COMP, |
TK_NUL |
} tokval_t; |
typedef struct { |
tokval_t kind; |
char *start; |
char *stop; |
} token_t; |
/** Fake up the TK_SLASH token. */ |
static token_t slash_token(char *start) |
{ |
token_t ret; |
ret.kind = TK_SLASH; |
ret.start = start; |
ret.stop = start; |
return ret; |
} |
/** Given a token, return the next token. */ |
static token_t next_token(token_t *cur) |
{ |
token_t ret; |
if (cur->stop[1] == '\0') { |
ret.kind = TK_NUL; |
ret.start = cur->stop + 1; |
ret.stop = ret.start; |
return ret; |
} |
if (cur->stop[1] == '/') { |
ret.kind = TK_SLASH; |
ret.start = cur->stop + 1; |
ret.stop = ret.start; |
return ret; |
} |
if (cur->stop[1] == '.' && (!cur->stop[2] || cur->stop[2] == '/')) { |
ret.kind = TK_DOT; |
ret.start = cur->stop + 1; |
ret.stop = ret.start; |
return ret; |
} |
if (cur->stop[1] == '.' && cur->stop[2] == '.' && |
(!cur->stop[3] || cur->stop[3] == '/')) { |
ret.kind = TK_DOTDOT; |
ret.start = cur->stop + 1; |
ret.stop = cur->stop + 2; |
return ret; |
} |
unsigned i; |
for (i = 1; cur->stop[i] && cur->stop[i] != '/'; i++) |
; |
ret.kind = TK_COMP; |
ret.start = &cur->stop[1]; |
ret.stop = &cur->stop[i - 1]; |
return ret; |
} |
/** States used by canonify(). */ |
typedef enum { |
S_INI, |
S_A, |
S_B, |
S_C, |
S_ACCEPT, |
S_RESTART, |
S_REJECT |
} state_t; |
typedef struct { |
state_t s; |
void (* f)(token_t *, token_t *, token_t *); |
} change_state_t; |
/* |
* Actions that can be performed when transitioning from one |
* state of canonify() to another. |
*/ |
static void set_first_slash(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
*tfsl = *t; |
*tlcomp = *t; |
} |
static void save_component(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
*tlcomp = *t; |
} |
static void terminate_slash(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
if (tfsl->stop[1]) /* avoid writing to a well-formatted path */ |
tfsl->stop[1] = '\0'; |
} |
static void remove_trailing_slash(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
t->start[-1] = '\0'; |
} |
/** Eat the extra '/'.. |
* |
* @param t The current TK_SLASH token. |
*/ |
static void shift_slash(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
char *p = t->start; |
char *q = t->stop + 1; |
while ((*p++ = *q++)) |
; |
} |
/** Eat the extra '.'. |
* |
* @param t The current TK_DOT token. |
*/ |
static void shift_dot(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
char *p = t->start; |
char *q = t->stop + 1; |
while ((*p++ = *q++)) |
; |
} |
/** Collapse the TK_COMP TK_SLASH TK_DOTDOT pattern. |
* |
* @param t The current TK_DOTDOT token. |
* @param tlcomp The last TK_COMP token. |
*/ |
static void shift_dotdot(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
char *p = tlcomp->start; |
char *q = t->stop + 1; |
while ((*p++ = *q++)) |
; |
} |
/** Transition function for canonify(). */ |
static change_state_t trans[4][6] = { |
[S_INI] = { |
[TK_SLASH] = { |
.s = S_A, |
.f = set_first_slash, |
}, |
[TK_DOT] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
[TK_DOTDOT] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
[TK_COMP] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
[TK_NUL] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
[TK_INVALID] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
}, |
[S_A] = { |
[TK_SLASH] = { |
.s = S_A, |
.f = set_first_slash, |
}, |
[TK_DOT] = { |
.s = S_A, |
.f = NULL, |
}, |
[TK_DOTDOT] = { |
.s = S_A, |
.f = NULL, |
}, |
[TK_COMP] = { |
.s = S_B, |
.f = save_component, |
}, |
[TK_NUL] = { |
.s = S_ACCEPT, |
.f = terminate_slash, |
}, |
[TK_INVALID] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
}, |
[S_B] = { |
[TK_SLASH] = { |
.s = S_C, |
.f = NULL, |
}, |
[TK_DOT] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
[TK_DOTDOT] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
[TK_COMP] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
[TK_NUL] = { |
.s = S_ACCEPT, |
.f = NULL, |
}, |
[TK_INVALID] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
}, |
[S_C] = { |
[TK_SLASH] = { |
.s = S_RESTART, |
.f = shift_slash, |
}, |
[TK_DOT] = { |
.s = S_RESTART, |
.f = shift_dot, |
}, |
[TK_DOTDOT] = { |
.s = S_RESTART, |
.f = shift_dotdot, |
}, |
[TK_COMP] = { |
.s = S_B, |
.f = save_component, |
}, |
[TK_NUL] = { |
.s = S_ACCEPT, |
.f = remove_trailing_slash, |
}, |
[TK_INVALID] = { |
.s = S_REJECT, |
.f = NULL, |
}, |
} |
}; |
/** Canonify a file system path. |
* |
* A file system path is canonical, if the following holds: |
* 1) the path is absolute (i.e. a/b/c is not canonical) |
* 2) there is no trailing slash in the path (i.e. /a/b/c is not canonical) |
* 3) there is no extra slash in the path (i.e. /a//b/c is not canonical) |
* 4) there is no '.' component in the path (i.e. /a/./b/c is not canonical) |
* 5) there is no '..' component in the path (i.e. /a/b/../c is not canonical) |
* |
* This function makes a potentially non-canonical file system path canonical. |
* It works in-place and requires a NULL-terminated input string. |
* |
* @param path Path to be canonified. |
* @param lenp Pointer where the length of the final path will be |
* stored. Can be NULL. |
* |
* @return Canonified path or NULL on failure. |
*/ |
char *canonify(char *path, size_t *lenp) |
{ |
state_t state; |
token_t t; |
token_t tfsl; /* first slash */ |
token_t tlcomp; /* last component */ |
if (*path != '/') |
return NULL; |
tfsl = slash_token(path); |
restart: |
state = S_INI; |
t = tfsl; |
tlcomp = tfsl; |
while (state != S_ACCEPT && state != S_RESTART && state != S_REJECT) { |
if (trans[state][t.kind].f) |
trans[state][t.kind].f(&t, &tfsl, &tlcomp); |
state = trans[state][t.kind].s; |
t = next_token(&t); |
} |
switch (state) { |
case S_RESTART: |
goto restart; |
case S_REJECT: |
return NULL; |
case S_ACCEPT: |
if (lenp) |
*lenp = (size_t)((tlcomp.stop - tfsl.start) + 1); |
return tfsl.start; |
default: |
abort(); |
} |
} |
/** |
* @} |
*/ |
/branches/network/uspace/lib/libc/generic/vfs/vfs.c |
---|
0,0 → 1,619 |
/* |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#include <vfs/vfs.h> |
#include <vfs/canonify.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <sys/stat.h> |
#include <stdio.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <async.h> |
#include <atomic.h> |
#include <futex.h> |
#include <errno.h> |
#include <string.h> |
#include <ipc/devmap.h> |
#include "../../srv/vfs/vfs.h" |
int vfs_phone = -1; |
futex_t vfs_phone_futex = FUTEX_INITIALIZER; |
futex_t cwd_futex = FUTEX_INITIALIZER; |
DIR *cwd_dir = NULL; |
char *cwd_path = NULL; |
size_t cwd_len = 0; |
char *absolutize(const char *path, size_t *retlen) |
{ |
char *ncwd_path; |
char *ncwd_path_nc; |
futex_down(&cwd_futex); |
size_t len = strlen(path); |
if (*path != '/') { |
if (!cwd_path) { |
futex_up(&cwd_futex); |
return NULL; |
} |
ncwd_path_nc = malloc(cwd_len + 1 + len + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
} |
strcpy(ncwd_path_nc, cwd_path); |
ncwd_path_nc[cwd_len] = '/'; |
ncwd_path_nc[cwd_len + 1] = '\0'; |
} else { |
ncwd_path_nc = malloc(len + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
} |
ncwd_path_nc[0] = '\0'; |
} |
strcat(ncwd_path_nc, path); |
ncwd_path = canonify(ncwd_path_nc, retlen); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
free(ncwd_path_nc); |
return NULL; |
} |
/* |
* We need to clone ncwd_path because canonify() works in-place and thus |
* the address in ncwd_path need not be the same as ncwd_path_nc, even |
* though they both point into the same dynamically allocated buffer. |
*/ |
ncwd_path = strdup(ncwd_path); |
free(ncwd_path_nc); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
return NULL; |
} |
futex_up(&cwd_futex); |
return ncwd_path; |
} |
static int vfs_connect(void) |
{ |
if (vfs_phone < 0) |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
return vfs_phone; |
} |
static int device_get_handle(char *name, dev_handle_t *handle) |
{ |
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, |
0); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
ipc_hangup(phone); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (retval == EOK) { |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
} |
ipc_hangup(phone); |
return retval; |
} |
int mount(const char *fs_name, const char *mp, const char *dev) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
dev_handle_t dev_handle; |
res = device_get_handle(dev, &dev_handle); |
if (res != EOK) |
return res; |
size_t mpa_len; |
char *mpa = absolutize(mp, &mpa_len); |
if (!mpa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
/* Ask VFS whether it likes fs_name. */ |
rc = async_req_0_0(vfs_phone, IPC_M_PING); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
static int _open(const char *path, int lflag, int oflag, ...) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
if (rc != EOK) |
return (int) rc; |
return (int) IPC_GET_ARG1(answer); |
} |
int open(const char *path, int oflag, ...) |
{ |
return _open(path, L_FILE, oflag); |
} |
int close(int fildes) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int)rc; |
} |
ssize_t read(int fildes, void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer); |
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (ssize_t) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return rc; |
} |
ssize_t write(int fildes, const void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer); |
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (ssize_t) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
} |
off_t lseek(int fildes, off_t offset, int whence) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
off_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence, |
(ipcarg_t)&newoffs); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc != EOK) |
return (off_t) -1; |
return newoffs; |
} |
int ftruncate(int fildes, off_t length) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int) rc; |
} |
DIR *opendir(const char *dirname) |
{ |
DIR *dirp = malloc(sizeof(DIR)); |
if (!dirp) |
return NULL; |
dirp->fd = _open(dirname, L_DIRECTORY, 0); |
if (dirp->fd < 0) { |
free(dirp); |
return NULL; |
} |
return dirp; |
} |
struct dirent *readdir(DIR *dirp) |
{ |
ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1); |
if (len <= 0) |
return NULL; |
return &dirp->res; |
} |
void rewinddir(DIR *dirp) |
{ |
(void) lseek(dirp->fd, 0, SEEK_SET); |
} |
int closedir(DIR *dirp) |
{ |
(void) close(dirp->fd); |
free(dirp); |
return 0; |
} |
int mkdir(const char *path, mode_t mode) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return rc; |
} |
static int _unlink(const char *path, int lflag) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
req = async_send_0(vfs_phone, VFS_UNLINK, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return rc; |
} |
int unlink(const char *path) |
{ |
return _unlink(path, L_NONE); |
} |
int rmdir(const char *path) |
{ |
return _unlink(path, L_DIRECTORY); |
} |
int rename(const char *old, const char *new) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
size_t olda_len; |
char *olda = absolutize(old, &olda_len); |
if (!olda) |
return ENOMEM; |
size_t newa_len; |
char *newa = absolutize(new, &newa_len); |
if (!newa) { |
free(olda); |
return ENOMEM; |
} |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(olda); |
free(newa); |
return res; |
} |
} |
req = async_send_0(vfs_phone, VFS_RENAME, NULL); |
rc = ipc_data_write_start(vfs_phone, olda, olda_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(olda); |
free(newa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, newa, newa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(olda); |
free(newa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(olda); |
free(newa); |
return rc; |
} |
int chdir(const char *path) |
{ |
size_t pa_len; |
char *pa = absolutize(path, &pa_len); |
if (!pa) |
return ENOMEM; |
DIR *d = opendir(pa); |
if (!d) { |
free(pa); |
return ENOENT; |
} |
futex_down(&cwd_futex); |
if (cwd_dir) { |
closedir(cwd_dir); |
cwd_dir = NULL; |
free(cwd_path); |
cwd_path = NULL; |
cwd_len = 0; |
} |
cwd_dir = d; |
cwd_path = pa; |
cwd_len = pa_len; |
futex_up(&cwd_futex); |
} |
char *getcwd(char *buf, size_t size) |
{ |
if (!size) |
return NULL; |
futex_down(&cwd_futex); |
if (size < cwd_len + 1) { |
futex_up(&cwd_futex); |
return NULL; |
} |
strcpy(buf, cwd_path); |
futex_up(&cwd_futex); |
return buf; |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/task.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
33,7 → 34,14 |
*/ |
#include <task.h> |
#include <ipc/ipc.h> |
#include <ipc/loader.h> |
#include <libc.h> |
#include <string.h> |
#include <stdlib.h> |
#include <async.h> |
#include <errno.h> |
#include <vfs/vfs.h> |
task_id_t task_get_id(void) |
{ |
44,5 → 52,136 |
return task_id; |
} |
static int task_spawn_loader(void) |
{ |
int phone_id, rc; |
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id); |
if (rc != 0) |
return rc; |
return phone_id; |
} |
static int loader_set_args(int phone_id, const char *argv[]) |
{ |
aid_t req; |
ipc_call_t answer; |
ipcarg_t rc; |
const char **ap; |
char *dp; |
char *arg_buf; |
size_t buffer_size; |
size_t len; |
/* |
* Serialize the arguments into a single array. First |
* compute size of the buffer needed. |
*/ |
ap = argv; |
buffer_size = 0; |
while (*ap != NULL) { |
buffer_size += strlen(*ap) + 1; |
++ap; |
} |
arg_buf = malloc(buffer_size); |
if (arg_buf == NULL) return ENOMEM; |
/* Now fill the buffer with null-terminated argument strings */ |
ap = argv; |
dp = arg_buf; |
while (*ap != NULL) { |
strcpy(dp, *ap); |
dp += strlen(*ap) + 1; |
++ap; |
} |
/* Send serialized arguments to the loader */ |
req = async_send_0(phone_id, LOADER_SET_ARGS, &answer); |
rc = ipc_data_write_start(phone_id, (void *)arg_buf, buffer_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
async_wait_for(req, &rc); |
if (rc != EOK) return rc; |
/* Free temporary buffer */ |
free(arg_buf); |
return EOK; |
} |
/** Create a new task by running an executable from VFS. |
* |
* @param path pathname of the binary to execute |
* @param argv command-line arguments |
* @return ID of the newly created task or zero on error. |
*/ |
task_id_t task_spawn(const char *path, const char *argv[]) |
{ |
int phone_id; |
ipc_call_t answer; |
aid_t req; |
int rc; |
ipcarg_t retval; |
char *pa; |
size_t pa_len; |
pa = absolutize(path, &pa_len); |
if (!pa) |
return 0; |
/* Spawn a program loader */ |
phone_id = task_spawn_loader(); |
if (phone_id < 0) |
return 0; |
/* |
* Say hello so that the loader knows the incoming connection's |
* phone hash. |
*/ |
rc = async_req_0_0(phone_id, LOADER_HELLO); |
if (rc != EOK) |
return 0; |
/* Send program pathname */ |
req = async_send_0(phone_id, LOADER_SET_PATHNAME, &answer); |
rc = ipc_data_write_start(phone_id, (void *)pa, pa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return 1; |
} |
async_wait_for(req, &retval); |
if (retval != EOK) |
goto error; |
/* Send arguments */ |
rc = loader_set_args(phone_id, argv); |
if (rc != EOK) |
goto error; |
/* Request loader to start the program */ |
rc = async_req_0_0(phone_id, LOADER_RUN); |
if (rc != EOK) |
goto error; |
/* Success */ |
ipc_hangup(phone_id); |
return 1; |
/* Error exit */ |
error: |
ipc_hangup(phone_id); |
return 0; |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/string.c |
---|
38,8 → 38,8 |
#include <limits.h> |
#include <align.h> |
#include <sys/types.h> |
#include <malloc.h> |
/* Dummy implementation of mem/ functions */ |
void *memset(void *s, int c, size_t n) |
66,9 → 66,10 |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j]; |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) src; |
return (char *) dst; |
} |
void *memcpy(void *dst, const void *src, size_t n) |
75,7 → 76,8 |
{ |
int i, j; |
if (((long) dst & (sizeof(long) - 1)) || ((long) src & (sizeof(long) - 1))) |
if (((long) dst & (sizeof(long) - 1)) || |
((long) src & (sizeof(long) - 1))) |
return unaligned_memcpy(dst, src, n); |
for (i = 0; i < n / sizeof(unsigned long); i++) |
82,9 → 84,10 |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j]; |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) src; |
return (char *) dst; |
} |
void *memmove(void *dst, const void *src, size_t n) |
95,12 → 98,13 |
return memcpy(dst, src, n); |
for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--) |
((unsigned char *) ((unsigned long *) dst))[j] = ((unsigned char *) ((unsigned long *) src))[j]; |
((unsigned char *) ((unsigned long *) dst))[j] = |
((unsigned char *) ((unsigned long *) src))[j]; |
for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
return (char *) src; |
return (char *) dst; |
} |
/** Compare two memory areas. |
107,10 → 111,10 |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have the same |
* length. |
* @return If len is 0, return zero. If the areas match, return zero. |
* Otherwise return non-zero. |
* @param len Size of the first area in bytes. Both areas must have |
* the same length. |
* @return If len is 0, return zero. If the areas match, return |
* zero. Otherwise return non-zero. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
120,8 → 124,9 |
} |
/** Count the number of characters in the string, not including terminating 0. |
* @param str string |
* @return number of characters in string. |
* |
* @param str String. |
* @return Number of characters in string. |
*/ |
size_t strlen(const char *str) |
{ |
141,7 → 146,6 |
c++; |
return (a[c] - b[c]); |
} |
int strncmp(const char *a, const char *b, size_t n) |
155,10 → 159,22 |
} |
/** Return pointer to the first occurence of character c in string |
* @param str scanned string |
* @param c searched character (taken as one byte) |
* @return pointer to the matched character or NULL if it is not found in given string. |
int stricmp(const char *a, const char *b) |
{ |
int c = 0; |
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c])))) |
c++; |
return (tolower(a[c]) - tolower(b[c])); |
} |
/** Return pointer to the first occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strchr(const char *str, int c) |
{ |
171,10 → 187,12 |
return NULL; |
} |
/** Return pointer to the last occurence of character c in string |
* @param str scanned string |
* @param c searched character (taken as one byte) |
* @return pointer to the matched character or NULL if it is not found in given string. |
/** Return pointer to the last occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strrchr(const char *str, int c) |
{ |
191,13 → 209,16 |
/** Convert string to a number. |
* Core of strtol and strtoul functions. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @param sgn its set to 1 if minus found |
* @return result of conversion. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character. |
* @param base Zero or number between 2 and 36 inclusive. |
* @param sgn It's set to 1 if minus found. |
* @return Result of conversion. |
*/ |
static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn) |
static unsigned long |
_strtoul(const char *nptr, char **endptr, int base, char *sgn) |
{ |
unsigned char c; |
unsigned long result = 0; |
219,7 → 240,8 |
/* FIXME: set errno to EINVAL */ |
return 0; |
} |
if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) { |
if ((base == 16) && (*str == '0') && ((str[1] == 'x') || |
(str[1] == 'X'))) { |
str += 2; |
} |
} else { |
238,7 → 260,8 |
while (*str) { |
c = *str; |
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : (c <= '9' ? c - '0' : 0xff))); |
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : |
(c <= '9' ? c - '0' : 0xff))); |
if (c > base) { |
break; |
} |
257,7 → 280,10 |
} |
if (str == tmpptr) { |
/* no number was found => first invalid character is the first character of the string */ |
/* |
* No number was found => first invalid character is the first |
* character of the string. |
*/ |
/* FIXME: set errno to EINVAL */ |
str = nptr; |
result = 0; |
275,14 → 301,17 |
} |
/** Convert initial part of string to long int according to given base. |
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-'). |
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one. |
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8). |
* Otherwise the base 0 is taken as decimal. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @return result of conversion. |
* The number may begin with an arbitrary number of whitespaces followed by |
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be |
* inserted and the number will be taken as hexadecimal one. If the base is 0 |
* and the number begin with a zero, number will be taken as octal one (as with |
* base 8). Otherwise the base 0 is taken as decimal. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character. |
* @param base Zero or number between 2 and 36 inclusive. |
* @return Result of conversion. |
*/ |
long int strtol(const char *nptr, char **endptr, int base) |
{ |
305,14 → 334,17 |
/** Convert initial part of string to unsigned long according to given base. |
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-'). |
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one. |
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8). |
* Otherwise the base 0 is taken as decimal. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @return result of conversion. |
* The number may begin with an arbitrary number of whitespaces followed by |
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be |
* inserted and the number will be taken as hexadecimal one. If the base is 0 |
* and the number begin with a zero, number will be taken as octal one (as with |
* base 8). Otherwise the base 0 is taken as decimal. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character |
* @param base Zero or number between 2 and 36 inclusive. |
* @return Result of conversion. |
*/ |
unsigned long strtoul(const char *nptr, char **endptr, int base) |
{ |
328,7 → 360,8 |
{ |
char *orig = dest; |
while ((*(dest++) = *(src++))); |
while ((*(dest++) = *(src++))) |
; |
return orig; |
} |
336,9 → 369,32 |
{ |
char *orig = dest; |
while ((*(dest++) = *(src++)) && --n); |
while ((*(dest++) = *(src++)) && --n) |
; |
return orig; |
} |
char *strcat(char *dest, const char *src) |
{ |
char *orig = dest; |
while (*dest++) |
; |
--dest; |
while ((*dest++ = *src++)) |
; |
return orig; |
} |
char * strdup(const char *s1) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) |
return (char *) NULL; |
return (char *) memcpy(ret, s1, len); |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/as.c |
---|
85,6 → 85,20 |
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t ) address); |
} |
/** Change address-space area flags. |
* |
* @param address Virtual address pointing into the address space area being |
* modified. |
* @param flags New flags describing type of the area. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
*/ |
int as_area_change_flags(void *address, int flags) |
{ |
return __SYSCALL2(SYS_AS_AREA_CHANGE_FLAGS, (sysarg_t) address, |
(sysarg_t) flags); |
} |
static size_t heapsize = 0; |
static size_t maxheapsize = (size_t) (-1); |
/branches/network/uspace/lib/libc/generic/pcb.c |
---|
0,0 → 1,40 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <loader/pcb.h> |
pcb_t *__pcb; |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/libc.c |
---|
48,8 → 48,10 |
#include <ipc/ipc.h> |
#include <async.h> |
#include <as.h> |
#include <loader/pcb.h> |
extern char _heap; |
extern int main(int argc, char *argv[]); |
void _exit(int status) |
{ |
56,20 → 58,31 |
thread_exit(status); |
} |
void __main(void) |
void __main(void *pcb_ptr) |
{ |
fibril_t *f; |
int argc; |
char **argv; |
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ); |
_async_init(); |
f = fibril_setup(); |
__tcb_set(f->tcb); |
open_console(); |
/* Save the PCB pointer */ |
__pcb = (pcb_t *)pcb_ptr; |
if (__pcb == NULL) { |
argc = 0; |
argv = NULL; |
} else { |
argc = __pcb->argc; |
argv = __pcb->argv; |
} |
void __io_init(void) |
{ |
open_stdin(); |
open_stdout(); |
main(argc, argv); |
} |
void __exit(void) |
/branches/network/uspace/lib/libc/generic/smc.c |
---|
0,0 → 1,45 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <libc.h> |
#include <sys/types.h> |
int smc_coherence(void *address, size_t size) |
{ |
return __SYSCALL2(SYS_SMC_COHERENCE, (sysarg_t) address, |
(sysarg_t) size); |
} |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/async.c |
---|
1012,4 → 1012,3 |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/fibril.c |
---|
342,4 → 342,3 |
/** @} |
*/ |
/branches/network/uspace/lib/libc/generic/libadt/hash_table.c |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
47,12 → 47,13 |
/** Create chained hash table. |
* |
* @param h Hash table structure. Will be initialized by this call. |
* @param m Number of slots in the hash table. |
* @param m Number of hash table buckets. |
* @param max_keys Maximal number of keys needed to identify an item. |
* @param op Hash table operations structure. |
* @return true on success |
* @return True on success |
*/ |
int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys, hash_table_operations_t *op) |
int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys, |
hash_table_operations_t *op) |
{ |
hash_count_t i; |
76,8 → 77,19 |
return true; |
} |
/** Insert item into hash table. |
/** Destroy a hash table instance. |
* |
* @param h Hash table to be destroyed. |
*/ |
void hash_table_destroy(hash_table_t *h) |
{ |
assert(h); |
assert(h->entry); |
free(h->entry); |
} |
/** Insert item into a hash table. |
* |
* @param h Hash table. |
* @param key Array of all keys necessary to compute hash index. |
* @param item Item to be inserted into the hash table. |
112,7 → 124,8 |
chain = h->op->hash(key); |
assert(chain < h->entries); |
for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) { |
for (cur = h->entry[chain].next; cur != &h->entry[chain]; |
cur = cur->next) { |
if (h->op->compare(key, h->max_keys, cur)) { |
/* |
* The entry is there. |
129,7 → 142,8 |
* For each removed item, h->remove_callback() is called. |
* |
* @param h Hash table. |
* @param key Array of keys that will be compared against items of the hash table. |
* @param key Array of keys that will be compared against items of |
* the hash table. |
* @param keys Number of keys in the 'key' array. |
*/ |
void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys) |
137,13 → 151,15 |
hash_index_t chain; |
link_t *cur; |
assert(h && h->op && h->op->hash && h->op->compare && h->op->remove_callback); |
assert(h && h->op && h->op->hash && h->op->compare && |
h->op->remove_callback); |
assert(keys <= h->max_keys); |
if (keys == h->max_keys) { |
/* |
* All keys are known, hash_table_find() can be used to find the entry. |
* All keys are known, hash_table_find() can be used to find the |
* entry. |
*/ |
cur = hash_table_find(h, key); |
159,7 → 175,8 |
* Any partially matching entries are to be removed. |
*/ |
for (chain = 0; chain < h->entries; chain++) { |
for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) { |
for (cur = h->entry[chain].next; cur != &h->entry[chain]; |
cur = cur->next) { |
if (h->op->compare(key, keys, cur)) { |
link_t *hlp; |
/branches/network/uspace/lib/libc/include/endian.h |
---|
File deleted |
/branches/network/uspace/lib/libc/include/vfs.h |
---|
File deleted |
/branches/network/uspace/lib/libc/include/stdio.h |
---|
49,24 → 49,27 |
int n; \ |
n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \ |
if (n > 0) \ |
(void) __SYSCALL3(SYS_IO, 1, (sysarg_t) buf, strlen(buf)); \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, strlen(buf)); \ |
} |
extern int getchar(void); |
extern int puts(const char * str); |
extern int putchar(int c); |
extern int puts(const char *); |
extern int putchar(int); |
extern int printf(const char *fmt, ...); |
extern int sprintf(char *str, const char *fmt, ...); |
extern int snprintf(char *str, size_t size, const char *fmt, ...); |
extern int printf(const char *, ...); |
extern int asprintf(char **, const char *, ...); |
extern int sprintf(char *, const char *fmt, ...); |
extern int snprintf(char *, size_t , const char *, ...); |
extern int vprintf(const char *fmt, va_list ap); |
extern int vsprintf(char *str, const char *fmt, va_list ap); |
extern int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); |
extern int vprintf(const char *, va_list); |
extern int vsprintf(char *, const char *, va_list); |
extern int vsnprintf(char *, size_t, const char *, va_list); |
#define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__) |
extern int rename(const char *, const char *); |
#endif |
/** @} |
/branches/network/uspace/lib/libc/include/getopt.h |
---|
0,0 → 1,71 |
/* $NetBSD: getopt.h,v 1.10.6.1 2008/05/18 12:30:09 yamt Exp $ */ |
/*- |
* Copyright (c) 2000 The NetBSD Foundation, Inc. |
* All rights reserved. |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* by Dieter Baron and Thomas Klausner. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. 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. |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``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 FOUNDATION OR CONTRIBUTORS |
* 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. |
*/ |
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */ |
#ifndef _GETOPT_H_ |
#define _GETOPT_H_ |
#include <unistd.h> |
/* |
* Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions |
*/ |
#define no_argument 0 |
#define required_argument 1 |
#define optional_argument 2 |
struct option { |
/* name of long option */ |
const char *name; |
/* |
* one of no_argument, required_argument, and optional_argument: |
* whether option takes an argument |
*/ |
int has_arg; |
/* if not NULL, set *flag to val when option found */ |
int *flag; |
/* if flag not NULL, value to set *flag to; else return value */ |
int val; |
}; |
/* HelenOS Port - These need to be exposed for legacy getopt() */ |
extern char *optarg; |
extern int optind, opterr, optopt; |
extern int optreset; |
int getopt_long(int, char * const *, const char *, |
const struct option *, int *); |
/* HelenOS Port : Expose legacy getopt() */ |
int getopt(int, char * const [], const char *); |
#endif /* !_GETOPT_H_ */ |
/branches/network/uspace/lib/libc/include/vfs/vfs.h |
---|
0,0 → 1,47 |
/* |
* 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_VFS_H_ |
#define LIBC_VFS_H_ |
#include <sys/types.h> |
extern char *absolutize(const char *, size_t *); |
extern int mount(const char *, const char *, const char *); |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/vfs/canonify.h |
---|
0,0 → 1,45 |
/* |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_VFS_CANONIFY_H_ |
#define LIBC_VFS_CANONIFY_H_ |
#include <sys/types.h> |
extern char *canonify(char *, size_t *); |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/string.h |
---|
39,26 → 39,31 |
#define bzero(ptr, len) memset((ptr), 0, (len)) |
void * memset(void *s, int c, size_t n); |
void * memcpy(void *dest, const void *src, size_t n); |
void * memmove(void *dest, const void *src, size_t n); |
extern void * memset(void *, int, size_t); |
extern void * memcpy(void *, const void *, size_t); |
extern void * memmove(void *, const void *, size_t); |
int bcmp(const char *s1, const char *s2, size_t n); |
extern int bcmp(const char *, const char *, size_t); |
int strcmp(const char *, const char *); |
int strncmp(const char *, const char *, size_t n); |
extern int strcmp(const char *, const char *); |
extern int strncmp(const char *, const char *, size_t); |
extern int stricmp(const char *, const char *); |
char *strcpy(char *dest, const char *src); |
char *strncpy(char *dest, const char *src, size_t n); |
extern char *strcpy(char *, const char *); |
extern char *strncpy(char *, const char *, size_t); |
size_t strlen(const char *str); |
extern char *strcat(char *, const char *); |
char *strchr(const char *str, int c); |
char *strrchr(const char *str, int c); |
extern size_t strlen(const char *); |
long int strtol(const char *nptr, char **endptr, int base); |
unsigned long strtoul(const char *nptr, char **endptr, int base); |
extern char *strdup(const char *); |
extern char *strchr(const char *, int); |
extern char *strrchr(const char *, int); |
extern long int strtol(const char *, char **, int); |
extern unsigned long strtoul(const char *, char **, int); |
#endif |
/** @} |
/branches/network/uspace/lib/libc/include/ctype.h |
---|
76,6 → 76,14 |
} |
} |
static inline int tolower(int c) |
{ |
if (isupper(c)) |
return (c + ('a' - 'A' > 0 ? 'a' - 'A' : 'A' - 'a')); |
else |
return c; |
} |
#endif |
/** @} |
/branches/network/uspace/lib/libc/include/as.h |
---|
42,6 → 42,7 |
extern void *as_area_create(void *address, size_t size, int flags); |
extern int as_area_resize(void *address, size_t size, int flags); |
extern int as_area_change_flags(void *address, int flags); |
extern int as_area_destroy(void *address); |
extern void *set_maxheapsize(size_t mhs); |
extern void * as_get_mappable_page(size_t sz); |
/branches/network/uspace/lib/libc/include/task.h |
---|
40,6 → 40,7 |
typedef uint64_t task_id_t; |
extern task_id_t task_get_id(void); |
extern task_id_t task_spawn(const char *path, const char *argv[]); |
#endif |
/branches/network/uspace/lib/libc/include/libc.h |
---|
48,8 → 48,7 |
#define __SYSCALL6(id, p1, p2, p3, p4, p5, p6) \ |
__syscall(p1, p2, p3, p4, p5, p6,id) |
extern void __main(void); |
extern void __io_init(void); |
extern void __main(void *pcb_ptr); |
extern void __exit(void); |
#endif |
/branches/network/uspace/lib/libc/include/loader/pcb.h |
---|
0,0 → 1,74 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** @file |
* @brief Program Control Block interface. |
*/ |
#ifndef LIBC_PCB_H_ |
#define LIBC_PCB_H_ |
#include <sys/types.h> |
typedef void (*entry_point_t)(void); |
/** |
* Holds pointers to data passed from the program loader to the program |
* and/or to the dynamic linker. This includes the program entry point, |
* arguments, environment variables etc. |
*/ |
typedef struct { |
/** Program entry point */ |
entry_point_t entry; |
/** Number of command-line arguments */ |
int argc; |
/** Command-line arguments */ |
char **argv; |
/* |
* ELF-specific data |
*/ |
/** Pointer to ELF dynamic section of the program */ |
void *dynamic; |
/** Pointer to dynamic section of the runtime linker */ |
void *rtld_dynamic; |
/** Runtime-linker load bias */ |
uintptr_t rtld_bias; |
} pcb_t; |
extern pcb_t *__pcb; |
#endif |
/** |
* @} |
*/ |
/branches/network/uspace/lib/libc/include/io/stream.h |
---|
39,8 → 39,9 |
#define EMFILE -17 |
extern void open_stdin(void); |
extern void open_stdout(void); |
extern void open_console(void); |
extern void close_console(void); |
extern void klog_update(void); |
extern ssize_t read_stdin(void *, size_t); |
extern ssize_t write_stdout(const void *, size_t); |
/branches/network/uspace/lib/libc/include/smc.h |
---|
0,0 → 1,45 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_SMC_H_ |
#define LIBC_SMC_H_ |
#include <sys/types.h> |
extern int smc_coherence(void *address, size_t size); |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/ipc/loader.h |
---|
0,0 → 1,50 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_LOADER_H_ |
#define LIBC_LOADER_H_ |
#include <ipc/ipc.h> |
typedef enum { |
LOADER_HELLO = IPC_FIRST_USER_METHOD, |
LOADER_SET_PATHNAME, |
LOADER_SET_ARGS, |
LOADER_RUN |
} fb_request_t; |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/ipc/devmap.h |
---|
0,0 → 1,99 |
/* |
* Copyright (c) 2007 Josef Cejka |
* 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 devmap |
* @{ |
*/ |
#ifndef DEVMAP_DEVMAP_H_ |
#define DEVMAP_DEVMAP_H_ |
#include <ipc/ipc.h> |
#include <libadt/list.h> |
#define DEVMAP_NAME_MAXLEN 512 |
typedef enum { |
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD, |
DEVMAP_DRIVER_UNREGISTER, |
DEVMAP_DEVICE_REGISTER, |
DEVMAP_DEVICE_UNREGISTER, |
DEVMAP_DEVICE_GET_NAME, |
DEVMAP_DEVICE_GET_HANDLE |
} devmap_request_t; |
/** Representation of device driver. |
* Each driver is responsible for a set of devices. |
*/ |
typedef struct { |
/** Pointers to previous and next drivers in linked list */ |
link_t drivers; |
/** Pointer to the linked list of devices controlled by |
* this driver */ |
link_t devices; |
/** Phone asociated with this driver */ |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Futex for list of devices owned by this driver */ |
atomic_t devices_futex; |
} devmap_driver_t; |
/** Info about registered device |
* |
*/ |
typedef struct { |
/** Pointer to the previous and next device in the list of all devices */ |
link_t devices; |
/** Pointer to the previous and next device in the list of devices |
owned by one driver */ |
link_t driver_devices; |
/** Unique device identifier */ |
int handle; |
/** Device name */ |
char *name; |
/** Device driver handling this device */ |
devmap_driver_t *driver; |
} devmap_device_t; |
/** Interface provided by devmap. |
* Every process that connects to devmap must ask one of following |
* interfaces otherwise connection will be refused. |
*/ |
typedef enum { |
/** Connect as device driver */ |
DEVMAP_DRIVER = 1, |
/** Connect as client */ |
DEVMAP_CLIENT, |
/** Create new connection to instance of device that |
* is specified by second argument of call. */ |
DEVMAP_CONNECT_TO_DEVICE |
} devmap_interface_t; |
#endif |
/branches/network/uspace/lib/libc/include/ipc/services.h |
---|
42,7 → 42,6 |
SERVICE_KEYBOARD, |
SERVICE_VIDEO, |
SERVICE_CONSOLE, |
SERVICE_RD, |
SERVICE_VFS, |
SERVICE_DEVMAP |
} services_t; |
/branches/network/uspace/lib/libc/include/ipc/ipc.h |
---|
130,26 → 130,26 |
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \ |
(res1), (res2), (res3), (res4), (res5)) |
#define ipc_call_sync_4_0(phoneid, method, arg1, arg2, arg3, arg4) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
0, 0, 0, 0, 0) |
#define ipc_call_sync_4_1(phoneid, method, arg1, arg2, arg3, arg4, res1) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
(res1), 0, 0, 0, 0) |
#define ipc_call_sync_4_2(phoneid, method, arg1, arg2, arg3, arg4, res1, res2) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \ |
(res1), (res2), 0, 0, 0) |
#define ipc_call_sync_4_3(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \ |
res3) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), (res1), (res2), (res3), 0, 0) |
(arg4), 0, (res1), (res2), (res3), 0, 0) |
#define ipc_call_sync_4_4(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \ |
res3, res4) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), (res1), (res2), (res3), (res4), 0) |
(arg4), 0, (res1), (res2), (res3), (res4), 0) |
#define ipc_call_sync_4_5(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \ |
res3, res4, res5) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), (res1), (res2), (res3), (res4), (res5)) |
(arg4), 0, (res1), (res2), (res3), (res4), (res5)) |
#define ipc_call_sync_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \ |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), 0, 0, 0, 0, 0) |
/branches/network/uspace/lib/libc/include/libadt/list.h |
---|
112,6 → 112,18 |
head->prev = link; |
} |
/** Insert item before another item in doubly-linked circular list. */ |
static inline void list_insert_before(link_t *l, link_t *r) |
{ |
list_append(l, r); |
} |
/** Insert item after another item in doubly-linked circular list. */ |
static inline void list_insert_after(link_t *r, link_t *l) |
{ |
list_prepend(l, r); |
} |
/** Remove item from doubly-linked circular list |
* |
* Remove item from doubly-linked circular list. |
/branches/network/uspace/lib/libc/include/libadt/hash_table.h |
---|
86,6 → 86,7 |
extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *); |
extern link_t *hash_table_find(hash_table_t *, unsigned long []); |
extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t); |
extern void hash_table_destroy(hash_table_t *); |
#endif |
/branches/network/uspace/lib/libc/include/byteorder.h |
---|
0,0 → 1,96 |
/* |
* Copyright (c) 2005 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_BYTEORDER_H_ |
#define LIBC_BYTEORDER_H_ |
#include <libarch/byteorder.h> |
#include <stdint.h> |
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN)) |
#error The architecture must be either big-endian or little-endian. |
#endif |
#ifdef ARCH_IS_BIG_ENDIAN |
#define uint16_t_le2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_be2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#endif |
static inline uint64_t uint64_t_byteorder_swap(uint64_t n) |
{ |
return ((n & 0xff) << 56) | |
((n & 0xff00) << 40) | |
((n & 0xff0000) << 24) | |
((n & 0xff000000LL) << 8) | |
((n & 0xff00000000LL) >> 8) | |
((n & 0xff0000000000LL) >> 24) | |
((n & 0xff000000000000LL) >> 40) | |
((n & 0xff00000000000000LL) >> 56); |
} |
static inline uint32_t uint32_t_byteorder_swap(uint32_t n) |
{ |
return ((n & 0xff) << 24) | |
((n & 0xff00) << 8) | |
((n & 0xff0000) >> 8) | |
((n & 0xff000000) >> 24); |
} |
static inline uint16_t uint16_t_byteorder_swap(uint16_t n) |
{ |
return ((n & 0xff) << 8) | |
((n & 0xff00) >> 8); |
} |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/setjmp.h |
---|
0,0 → 1,49 |
/* |
* Copyright (c) 2008 Josef Cejka |
* 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 libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_SETJMP_H_ |
#define LIBC_SETJMP_H_ |
#include <libarch/fibril.h> |
typedef context_t jmp_buf; |
extern int setjmp(jmp_buf env); |
extern void longjmp(jmp_buf env,int val) __attribute__((__noreturn__)); |
#endif |
/** @} |
*/ |
/branches/network/uspace/lib/libc/include/unistd.h |
---|
38,7 → 38,10 |
#include <sys/types.h> |
#include <libarch/config.h> |
#ifndef NULL |
#define NULL 0 |
#endif |
#define getpagesize() (PAGE_SIZE) |
#define SEEK_SET 0 |
50,6 → 53,10 |
extern off_t lseek(int, off_t, int); |
extern int ftruncate(int, off_t); |
extern int close(int); |
extern int unlink(const char *); |
extern int rmdir(const char *); |
extern int chdir(const char *); |
extern char *getcwd(char *buf, size_t); |
extern void _exit(int status); |
extern void *sbrk(ssize_t incr); |
/branches/network/uspace/lib/libc/include/errno.h |
---|
42,6 → 42,10 |
#define ENOTDIR (-258) |
#define ENOSPC (-259) |
#define EEXIST (-260) |
#define ENOTEMPTY (-261) |
#define EBADF (-262) |
#define ERANGE (-263) |
#define EXDEV (-264) |
#endif |
/branches/network/uspace/lib/libc/Makefile |
---|
51,10 → 51,13 |
generic/cap.c \ |
generic/string.c \ |
generic/fibril.c \ |
generic/pcb.c \ |
generic/smc.c \ |
generic/thread.c \ |
generic/tls.c \ |
generic/task.c \ |
generic/futex.c \ |
generic/io/asprintf.c \ |
generic/io/io.c \ |
generic/io/printf.c \ |
generic/io/stream.c \ |
68,6 → 71,7 |
generic/sysinfo.c \ |
generic/ipc.c \ |
generic/async.c \ |
generic/getopt.c \ |
generic/libadt/list.o \ |
generic/libadt/hash_table.o \ |
generic/time.c \ |
74,7 → 78,8 |
generic/err.c \ |
generic/stdlib.c \ |
generic/mman.c \ |
generic/vfs.c |
generic/vfs/vfs.c \ |
generic/vfs/canonify.c |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/entry.s \ |
/branches/network/uspace/lib/libfs/libfs.c |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2007 Jakub Jermar |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
36,10 → 36,13 |
#include "libfs.h" |
#include "../../srv/vfs/vfs.h" |
#include "../../srv/rd/rd.h" |
#include <errno.h> |
#include <async.h> |
#include <ipc/ipc.h> |
#include <as.h> |
#include <assert.h> |
#include <dirent.h> |
/** Register file system server. |
* |
120,5 → 123,270 |
return IPC_GET_RETVAL(answer); |
} |
/** Lookup VFS triplet by name in the file system name space. |
* |
* The path passed in the PLB must be in the canonical file system path format |
* as returned by the canonify() function. |
* |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param fs_handle File system handle of the file system where to perform |
* the lookup. |
* @param rid Request ID of the VFS_LOOKUP request. |
* @param request VFS_LOOKUP request data itself. |
*/ |
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
unsigned next = IPC_GET_ARG1(*request); |
unsigned last = IPC_GET_ARG2(*request); |
dev_handle_t dev_handle = IPC_GET_ARG3(*request); |
int lflag = IPC_GET_ARG4(*request); |
fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */ |
char component[NAME_MAX + 1]; |
int len; |
if (last < next) |
last += PLB_SIZE; |
void *par = NULL; |
void *cur = ops->root_get(dev_handle); |
void *tmp = NULL; |
if (ops->plb_get_char(next) == '/') |
next++; /* eat slash */ |
while (next <= last && ops->has_children(cur)) { |
/* collect the component */ |
len = 0; |
while ((next <= last) && (ops->plb_get_char(next) != '/')) { |
if (len + 1 == NAME_MAX) { |
/* component length overflow */ |
ipc_answer_0(rid, ENAMETOOLONG); |
goto out; |
} |
component[len++] = ops->plb_get_char(next); |
next++; /* process next character */ |
} |
assert(len); |
component[len] = '\0'; |
next++; /* eat slash */ |
/* match the component */ |
tmp = ops->match(cur, component); |
/* handle miss: match amongst siblings */ |
if (!tmp) { |
if (next <= last) { |
/* there are unprocessed components */ |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
/* miss in the last component */ |
if (lflag & (L_CREATE | L_LINK)) { |
/* request to create a new link */ |
if (!ops->is_directory(cur)) { |
ipc_answer_0(rid, ENOTDIR); |
goto out; |
} |
void *nodep; |
if (lflag & L_CREATE) |
nodep = ops->create(lflag); |
else |
nodep = ops->node_get(dev_handle, |
index); |
if (nodep) { |
if (!ops->link(cur, nodep, component)) { |
if (lflag & L_CREATE) { |
(void)ops->destroy( |
nodep); |
} |
ipc_answer_0(rid, ENOSPC); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
} |
goto out; |
} else if (lflag & L_PARENT) { |
/* return parent */ |
ipc_answer_5(rid, EOK, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), |
ops->lnkcnt_get(cur)); |
} |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
if (par) |
ops->node_put(par); |
/* descend one level */ |
par = cur; |
cur = tmp; |
tmp = NULL; |
} |
/* handle miss: excessive components */ |
if (next <= last && !ops->has_children(cur)) { |
if (lflag & (L_CREATE | L_LINK)) { |
if (!ops->is_directory(cur)) { |
ipc_answer_0(rid, ENOTDIR); |
goto out; |
} |
/* collect next component */ |
len = 0; |
while (next <= last) { |
if (ops->plb_get_char(next) == '/') { |
/* more than one component */ |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
if (len + 1 == NAME_MAX) { |
/* component length overflow */ |
ipc_answer_0(rid, ENAMETOOLONG); |
goto out; |
} |
component[len++] = ops->plb_get_char(next); |
next++; /* process next character */ |
} |
assert(len); |
component[len] = '\0'; |
void *nodep; |
if (lflag & L_CREATE) |
nodep = ops->create(lflag); |
else |
nodep = ops->node_get(dev_handle, index); |
if (nodep) { |
if (!ops->link(cur, nodep, component)) { |
if (lflag & L_CREATE) |
(void)ops->destroy(nodep); |
ipc_answer_0(rid, ENOSPC); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
} |
goto out; |
} |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
/* handle hit */ |
if (lflag & L_PARENT) { |
ops->node_put(cur); |
cur = par; |
par = NULL; |
if (!cur) { |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
} |
if (lflag & L_UNLINK) { |
unsigned old_lnkcnt = ops->lnkcnt_get(cur); |
int res = ops->unlink(par, cur); |
ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), old_lnkcnt); |
goto out; |
} |
if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || |
(lflag & L_LINK)) { |
ipc_answer_0(rid, EEXIST); |
goto out; |
} |
if ((lflag & L_FILE) && (ops->is_directory(cur))) { |
ipc_answer_0(rid, EISDIR); |
goto out; |
} |
if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { |
ipc_answer_0(rid, ENOTDIR); |
goto out; |
} |
ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur), |
ops->size_get(cur), ops->lnkcnt_get(cur)); |
out: |
if (par) |
ops->node_put(par); |
if (cur) |
ops->node_put(cur); |
if (tmp) |
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/network/uspace/lib/libfs/libfs.h |
---|
42,6 → 42,24 |
#include <async.h> |
typedef struct { |
void * (* match)(void *, const char *); |
void * (* node_get)(dev_handle_t, fs_index_t); |
void (* node_put)(void *); |
void * (* create)(int); |
int (* destroy)(void *); |
bool (* link)(void *, void *, const char *); |
int (* unlink)(void *, void *); |
fs_index_t (* index_get)(void *); |
size_t (* size_get)(void *); |
unsigned (* lnkcnt_get)(void *); |
bool (* has_children)(void *); |
void *(* root_get)(dev_handle_t); |
char (* plb_get_char)(unsigned pos); |
bool (* is_directory)(void *); |
bool (* is_file)(void *); |
} libfs_ops_t; |
typedef struct { |
int fs_handle; /**< File system handle. */ |
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */ |
uint8_t *plb_ro; /**< Read-only PLB view. */ |
49,12 → 67,11 |
extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t); |
extern int block_read(int, unsigned long, void *); |
extern int block_write(int, unsigned long, void *); |
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
extern void node_add_mp(int, unsigned long); |
extern void node_del_mp(int, unsigned long); |
extern bool node_is_mp(int, unsigned long); |
extern bool libfs_blockread(int, void *, off_t *, size_t *, off_t *, void *, |
size_t, size_t); |
#endif |
/** @} |
/branches/network/uspace/lib/softfloat/include/sftypes.h |
---|
35,7 → 35,7 |
#ifndef __SFTYPES_H__ |
#define __SFTYPES_H__ |
#include <endian.h> |
#include <byteorder.h> |
#include <stdint.h> |
typedef union { |
43,11 → 43,11 |
uint32_t binary; |
struct { |
#if __BYTE_ORDER == __BIG_ENDIAN |
#if defined(ARCH_IS_BIG_ENDIAN) |
uint32_t sign:1; |
uint32_t exp:8; |
uint32_t fraction:23; |
#elif __BYTE_ORDER == __LITTLE_ENDIAN |
#elif defined(ARCH_IS_LITTLE_ENDIAN) |
uint32_t fraction:23; |
uint32_t exp:8; |
uint32_t sign:1; |
62,11 → 62,11 |
uint64_t binary; |
struct { |
#if __BYTE_ORDER == __BIG_ENDIAN |
#if defined(ARCH_IS_BIG_ENDIAN) |
uint64_t sign:1; |
uint64_t exp:11; |
uint64_t fraction:52; |
#elif __BYTE_ORDER == __LITTLE_ENDIAN |
#elif defined(ARCH_IS_LITTLE_ENDIAN) |
uint64_t fraction:52; |
uint64_t exp:11; |
uint64_t sign:1; |
81,7 → 81,10 |
#define FLOAT64_MAX |
#define FLOAT64_MIN |
/* For recognizing NaNs or infinity use isFloat32NaN and is Float32Inf, comparing with this constants is not sufficient */ |
/* |
* For recognizing NaNs or infinity use isFloat32NaN and is Float32Inf, |
* comparing with these constants is not sufficient. |
*/ |
#define FLOAT32_NAN 0x7FC00001 |
#define FLOAT32_SIGNAN 0x7F800001 |
#define FLOAT32_INF 0x7F800000 |
/branches/network/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
45,24 → 45,102 |
#include <stdlib.h> |
#include <string.h> |
#include <stdio.h> |
#include <dirent.h> |
#include <assert.h> |
#include <sys/types.h> |
#include <libadt/hash_table.h> |
#include <as.h> |
#include <libfs.h> |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
#define PLB_GET_CHAR(i) (tmpfs_reg.plb_ro[(i) % PLB_SIZE]) |
#define DENTRIES_BUCKETS 256 |
#define NAMES_BUCKETS 4 |
/* |
* Hash table of all directory entries. |
* For now, we don't distinguish between different dev_handles/instances. All |
* requests resolve to the only instance, rooted in the following variable. |
*/ |
static tmpfs_dentry_t *root; |
/* |
* Implementation of the libfs interface. |
*/ |
/* Forward declarations of static functions. */ |
static void *tmpfs_match(void *, const char *); |
static void *tmpfs_node_get(dev_handle_t, fs_index_t); |
static void tmpfs_node_put(void *); |
static void *tmpfs_create_node(int); |
static bool tmpfs_link_node(void *, void *, const char *); |
static int tmpfs_unlink_node(void *, void *); |
static int tmpfs_destroy_node(void *); |
/* Implementation of helper functions. */ |
static fs_index_t tmpfs_index_get(void *nodep) |
{ |
return ((tmpfs_dentry_t *) nodep)->index; |
} |
static size_t tmpfs_size_get(void *nodep) |
{ |
return ((tmpfs_dentry_t *) nodep)->size; |
} |
static unsigned tmpfs_lnkcnt_get(void *nodep) |
{ |
return ((tmpfs_dentry_t *) nodep)->lnkcnt; |
} |
static bool tmpfs_has_children(void *nodep) |
{ |
return ((tmpfs_dentry_t *) nodep)->child != NULL; |
} |
static void *tmpfs_root_get(dev_handle_t dev_handle) |
{ |
return root; |
} |
static char tmpfs_plb_get_char(unsigned pos) |
{ |
return tmpfs_reg.plb_ro[pos % PLB_SIZE]; |
} |
static bool tmpfs_is_directory(void *nodep) |
{ |
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_DIRECTORY; |
} |
static bool tmpfs_is_file(void *nodep) |
{ |
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_FILE; |
} |
/** libfs operations */ |
libfs_ops_t tmpfs_libfs_ops = { |
.match = tmpfs_match, |
.node_get = tmpfs_node_get, |
.node_put = tmpfs_node_put, |
.create = tmpfs_create_node, |
.destroy = tmpfs_destroy_node, |
.link = tmpfs_link_node, |
.unlink = tmpfs_unlink_node, |
.index_get = tmpfs_index_get, |
.size_get = tmpfs_size_get, |
.lnkcnt_get = tmpfs_lnkcnt_get, |
.has_children = tmpfs_has_children, |
.root_get = tmpfs_root_get, |
.plb_get_char = tmpfs_plb_get_char, |
.is_directory = tmpfs_is_directory, |
.is_file = tmpfs_is_file |
}; |
/** Hash table of all directory entries. */ |
hash_table_t dentries; |
/* Implementation of hash table interface for the dentries hash table. */ |
static hash_index_t dentries_hash(unsigned long *key) |
{ |
return *key % DENTRIES_BUCKETS; |
87,255 → 165,282 |
.remove_callback = dentries_remove_callback |
}; |
unsigned tmpfs_next_index = 1; |
fs_index_t tmpfs_next_index = 1; |
static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentry) |
typedef struct { |
char *name; |
tmpfs_dentry_t *parent; |
link_t link; |
} tmpfs_name_t; |
/* Implementation of hash table interface for the names hash table. */ |
static hash_index_t names_hash(unsigned long *key) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key; |
return dentry->index % NAMES_BUCKETS; |
} |
static int names_compare(unsigned long *key, hash_count_t keys, link_t *item) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key; |
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t, |
link); |
return dentry == namep->parent; |
} |
static void names_remove_callback(link_t *item) |
{ |
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t, |
link); |
free(namep->name); |
free(namep); |
} |
/** TMPFS node names hash table operations. */ |
static hash_table_operations_t names_ops = { |
.hash = names_hash, |
.compare = names_compare, |
.remove_callback = names_remove_callback |
}; |
static void tmpfs_name_initialize(tmpfs_name_t *namep) |
{ |
namep->name = NULL; |
namep->parent = NULL; |
link_initialize(&namep->link); |
} |
static bool tmpfs_dentry_initialize(tmpfs_dentry_t *dentry) |
{ |
dentry->index = 0; |
dentry->parent = NULL; |
dentry->sibling = NULL; |
dentry->child = NULL; |
dentry->name = NULL; |
dentry->type = TMPFS_NONE; |
dentry->lnkcnt = 0; |
dentry->size = 0; |
dentry->data = NULL; |
link_initialize(&dentry->dh_link); |
return (bool)hash_table_create(&dentry->names, NAMES_BUCKETS, 1, |
&names_ops); |
} |
/* |
* For now, we don't distinguish between different dev_handles/instances. All |
* requests resolve to the only instance, rooted in the following variable. |
*/ |
static tmpfs_dentry_t *root; |
static bool tmpfs_init(void) |
{ |
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops)) |
return false; |
root = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t)); |
if (!root) |
root = (tmpfs_dentry_t *) tmpfs_create_node(L_DIRECTORY); |
if (!root) { |
hash_table_destroy(&dentries); |
return false; |
tmpfs_dentry_initialize(root); |
root->index = tmpfs_next_index++; |
root->name = ""; |
root->type = TMPFS_DIRECTORY; |
hash_table_insert(&dentries, &root->index, &root->dh_link); |
} |
root->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
/** Compare one component of path to a directory entry. |
* |
* @param dentry Directory entry to compare the path component with. |
* @param parentp Pointer to node from which we descended. |
* @param childp Pointer to node to compare the path component with. |
* @param component Array of characters holding component name. |
* |
* @return True on match, false otherwise. |
*/ |
static bool match_component(tmpfs_dentry_t *dentry, const char *component) |
static bool |
tmpfs_match_one(tmpfs_dentry_t *parentp, tmpfs_dentry_t *childp, |
const char *component) |
{ |
return !strcmp(dentry->name, component); |
unsigned long key = (unsigned long) parentp; |
link_t *hlp = hash_table_find(&childp->names, &key); |
assert(hlp); |
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, link); |
return !strcmp(namep->name, component); |
} |
static unsigned long create_node(tmpfs_dentry_t *dentry, |
const char *component, int lflag) |
void *tmpfs_match(void *prnt, const char *component) |
{ |
assert(dentry->type == TMPFS_DIRECTORY); |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; |
tmpfs_dentry_t *childp = parentp->child; |
while (childp && !tmpfs_match_one(parentp, childp, component)) |
childp = childp->sibling; |
return (void *) childp; |
} |
void * |
tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
unsigned long key = index; |
link_t *lnk = hash_table_find(&dentries, &key); |
if (!lnk) |
return NULL; |
return hash_table_get_instance(lnk, tmpfs_dentry_t, dh_link); |
} |
void tmpfs_node_put(void *node) |
{ |
/* nothing to do */ |
} |
void *tmpfs_create_node(int lflag) |
{ |
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); |
tmpfs_dentry_t *node = malloc(sizeof(tmpfs_dentry_t)); |
if (!node) |
return 0; |
size_t len = strlen(component); |
char *name = malloc(len + 1); |
if (!name) { |
return NULL; |
if (!tmpfs_dentry_initialize(node)) { |
free(node); |
return 0; |
return NULL; |
} |
strcpy(name, component); |
tmpfs_dentry_initialize(node); |
node->index = tmpfs_next_index++; |
node->name = name; |
node->parent = dentry; |
if (lflag & L_DIRECTORY) |
node->type = TMPFS_DIRECTORY; |
else |
node->type = TMPFS_FILE; |
/* Insert the new node into the dentry hash table. */ |
unsigned long key = node->index; |
hash_table_insert(&dentries, &key, &node->dh_link); |
return (void *) node; |
} |
bool tmpfs_link_node(void *prnt, void *chld, const char *nm) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; |
tmpfs_dentry_t *childp = (tmpfs_dentry_t *) chld; |
assert(parentp->type == TMPFS_DIRECTORY); |
tmpfs_name_t *namep = malloc(sizeof(tmpfs_name_t)); |
if (!namep) |
return false; |
tmpfs_name_initialize(namep); |
size_t len = strlen(nm); |
namep->name = malloc(len + 1); |
if (!namep->name) { |
free(namep); |
return false; |
} |
strcpy(namep->name, nm); |
namep->parent = parentp; |
childp->lnkcnt++; |
unsigned long key = (unsigned long) parentp; |
hash_table_insert(&childp->names, &key, &namep->link); |
/* Insert the new node into the namespace. */ |
if (dentry->child) { |
tmpfs_dentry_t *tmp = dentry->child; |
if (parentp->child) { |
tmpfs_dentry_t *tmp = parentp->child; |
while (tmp->sibling) |
tmp = tmp->sibling; |
tmp->sibling = node; |
tmp->sibling = childp; |
} else { |
dentry->child = node; |
parentp->child = childp; |
} |
/* Insert the new node into the dentry hash table. */ |
hash_table_insert(&dentries, &node->index, &node->dh_link); |
return node->index; |
return true; |
} |
static int destroy_component(tmpfs_dentry_t *dentry) |
int tmpfs_unlink_node(void *prnt, void *chld) |
{ |
return EPERM; |
} |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *)prnt; |
tmpfs_dentry_t *childp = (tmpfs_dentry_t *)chld; |
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
unsigned next = IPC_GET_ARG1(*request); |
unsigned last = IPC_GET_ARG2(*request); |
int dev_handle = IPC_GET_ARG3(*request); |
int lflag = IPC_GET_ARG4(*request); |
if (!parentp) |
return EBUSY; |
if (last < next) |
last += PLB_SIZE; |
if (childp->child) |
return ENOTEMPTY; |
/* |
* Initialize TMPFS. |
*/ |
if (!root && !tmpfs_init()) { |
ipc_answer_0(rid, ENOMEM); |
return; |
if (parentp->child == childp) { |
parentp->child = childp->sibling; |
} else { |
/* TODO: consider doubly linked list for organizing siblings. */ |
tmpfs_dentry_t *tmp = parentp->child; |
while (tmp->sibling != childp) |
tmp = tmp->sibling; |
tmp->sibling = childp->sibling; |
} |
childp->sibling = NULL; |
tmpfs_dentry_t *dtmp = root->child; |
tmpfs_dentry_t *dcur = root; |
unsigned long key = (unsigned long) parentp; |
hash_table_remove(&childp->names, &key, 1); |
if (PLB_GET_CHAR(next) == '/') |
next++; /* eat slash */ |
childp->lnkcnt--; |
char component[NAME_MAX + 1]; |
int len = 0; |
while (dtmp && next <= last) { |
/* collect the component */ |
if (PLB_GET_CHAR(next) != '/') { |
if (len + 1 == NAME_MAX) { |
/* comopnent length overflow */ |
ipc_answer_0(rid, ENAMETOOLONG); |
return; |
return EOK; |
} |
component[len++] = PLB_GET_CHAR(next); |
next++; /* process next character */ |
if (next <= last) |
continue; |
} |
assert(len); |
component[len] = '\0'; |
next++; /* eat slash */ |
len = 0; |
int tmpfs_destroy_node(void *nodep) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep; |
/* match the component */ |
while (dtmp && !match_component(dtmp, component)) |
dtmp = dtmp->sibling; |
assert(!dentry->lnkcnt); |
assert(!dentry->child); |
assert(!dentry->sibling); |
/* handle miss: match amongst siblings */ |
if (!dtmp) { |
if ((next > last) && (lflag & L_CREATE)) { |
/* no components left and L_CREATE specified */ |
if (dcur->type != TMPFS_DIRECTORY) { |
ipc_answer_0(rid, ENOTDIR); |
return; |
} |
unsigned long index = create_node(dcur, |
component, lflag); |
if (index > 0) { |
ipc_answer_4(rid, EOK, |
tmpfs_reg.fs_handle, dev_handle, |
index, 0); |
} else { |
ipc_answer_0(rid, ENOSPC); |
} |
return; |
} |
ipc_answer_0(rid, ENOENT); |
return; |
} |
unsigned long key = dentry->index; |
hash_table_remove(&dentries, &key, 1); |
/* descend one level */ |
dcur = dtmp; |
dtmp = dtmp->child; |
} |
hash_table_destroy(&dentry->names); |
/* handle miss: excessive components */ |
if (!dtmp && next <= last) { |
if (lflag & L_CREATE) { |
if (dcur->type != TMPFS_DIRECTORY) { |
ipc_answer_0(rid, ENOTDIR); |
return; |
if (dentry->type == TMPFS_FILE) |
free(dentry->data); |
free(dentry); |
return EOK; |
} |
/* collect next component */ |
while (next <= last) { |
if (PLB_GET_CHAR(next) == '/') { |
/* more than one component */ |
ipc_answer_0(rid, ENOENT); |
void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
/* Initialize TMPFS. */ |
if (!root && !tmpfs_init()) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if (len + 1 == NAME_MAX) { |
/* component length overflow */ |
ipc_answer_0(rid, ENAMETOOLONG); |
return; |
} |
component[len++] = PLB_GET_CHAR(next); |
next++; /* process next character */ |
} |
assert(len); |
component[len] = '\0'; |
len = 0; |
unsigned long index; |
index = create_node(dcur, component, lflag); |
if (index) { |
ipc_answer_4(rid, EOK, tmpfs_reg.fs_handle, |
dev_handle, index, 0); |
if (dev_handle >= 0) { |
if (tmpfs_restore(dev_handle)) |
ipc_answer_3(rid, EOK, root->index, root->size, |
root->lnkcnt); |
else |
ipc_answer_0(rid, ELIMIT); |
} else { |
ipc_answer_0(rid, ENOSPC); |
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt); |
} |
return; |
} |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* handle hit */ |
if (lflag & L_DESTROY) { |
int res = destroy_component(dcur); |
ipc_answer_0(rid, res); |
return; |
void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t mp_index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request); |
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request); |
ipc_answer_0(rid, ENOTSUP); |
} |
if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) { |
ipc_answer_0(rid, EEXIST); |
return; |
} |
if ((lflag & L_FILE) && (dcur->type != TMPFS_FILE)) { |
ipc_answer_0(rid, EISDIR); |
return; |
} |
if ((lflag & L_DIRECTORY) && (dcur->type != TMPFS_DIRECTORY)) { |
ipc_answer_0(rid, ENOTDIR); |
return; |
} |
ipc_answer_4(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index, |
dcur->size); |
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_read(ipc_callid_t rid, ipc_call_t *request) |
{ |
int dev_handle = IPC_GET_ARG1(*request); |
unsigned long index = IPC_GET_ARG2(*request); |
off_t pos = IPC_GET_ARG3(*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); |
/* |
* Lookup the respective dentry. |
*/ |
link_t *hlp; |
hlp = hash_table_find(&dentries, &index); |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
361,7 → 466,7 |
bytes); |
} else { |
int i; |
tmpfs_dentry_t *cur = dentry->child; |
tmpfs_dentry_t *cur; |
assert(dentry->type == TMPFS_DIRECTORY); |
380,8 → 485,14 |
return; |
} |
(void) ipc_data_read_finalize(callid, cur->name, |
strlen(cur->name) + 1); |
unsigned long key = (unsigned long) dentry; |
link_t *hlp = hash_table_find(&cur->names, &key); |
assert(hlp); |
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, |
link); |
(void) ipc_data_read_finalize(callid, namep->name, |
strlen(namep->name) + 1); |
bytes = 1; |
} |
393,15 → 504,16 |
void tmpfs_write(ipc_callid_t rid, ipc_call_t *request) |
{ |
int dev_handle = IPC_GET_ARG1(*request); |
unsigned long index = IPC_GET_ARG2(*request); |
off_t pos = IPC_GET_ARG3(*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); |
/* |
* Lookup the respective dentry. |
*/ |
link_t *hlp; |
hlp = hash_table_find(&dentries, &index); |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
453,15 → 565,16 |
void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
{ |
int dev_handle = IPC_GET_ARG1(*request); |
unsigned long index = IPC_GET_ARG2(*request); |
size_t size = IPC_GET_ARG3(*request); |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
size_t size = (off_t)IPC_GET_ARG3(*request); |
/* |
* Lookup the respective dentry. |
*/ |
link_t *hlp; |
hlp = hash_table_find(&dentries, &index); |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
488,6 → 601,25 |
ipc_answer_0(rid, EOK); |
} |
void tmpfs_destroy(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); |
int rc; |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
rc = tmpfs_destroy_node(dentry); |
ipc_answer_0(rid, rc); |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
0,0 → 1,214 |
/* |
* 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 fs |
* @{ |
*/ |
/** |
* @file tmpfs_dump.c |
* @brief Support for loading TMPFS file system dump. |
*/ |
#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 <byteorder.h> |
#define TMPFS_BLOCK_SIZE 1024 |
struct rdentry { |
uint8_t type; |
uint32_t len; |
} __attribute__((packed)); |
static bool |
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen, |
off_t *pos, tmpfs_dentry_t *parent) |
{ |
struct rdentry entry; |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
do { |
char *fname; |
tmpfs_dentry_t *node; |
uint32_t size; |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, &entry, |
sizeof(entry), TMPFS_BLOCK_SIZE)) |
return false; |
entry.len = uint32_t_le2host(entry.len); |
switch (entry.type) { |
case TMPFS_NONE: |
break; |
case TMPFS_FILE: |
fname = malloc(entry.len + 1); |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(L_FILE); |
if (node == NULL) { |
free(fname); |
return false; |
} |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
if (!ops->link((void *) parent, (void *) node, fname)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
free(fname); |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
&size, sizeof(size), TMPFS_BLOCK_SIZE)) |
return false; |
size = uint32_t_le2host(size); |
node->data = malloc(size); |
if (node->data == NULL) |
return false; |
node->size = size; |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
node->data, size, TMPFS_BLOCK_SIZE)) |
return false; |
break; |
case TMPFS_DIRECTORY: |
fname = malloc(entry.len + 1); |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(L_DIRECTORY); |
if (node == NULL) { |
free(fname); |
return false; |
} |
if (!libfs_blockread(phone, block, bufpos, buflen, pos, |
fname, entry.len, TMPFS_BLOCK_SIZE)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
if (!ops->link((void *) parent, (void *) node, fname)) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
free(fname); |
if (!tmpfs_restore_recursion(phone, block, bufpos, |
buflen, pos, node)) |
return false; |
break; |
default: |
return false; |
} |
} while (entry.type != TMPFS_NONE); |
return true; |
} |
bool tmpfs_restore(dev_handle_t dev) |
{ |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
void *block = mmap(NULL, TMPFS_BLOCK_SIZE, |
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
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, |
TMPFS_BLOCK_SIZE)) |
goto error; |
tag[5] = 0; |
if (strcmp(tag, "TMPFS") != 0) |
goto error; |
if (!tmpfs_restore_recursion(phone, block, &bufpos, &buflen, &pos, |
ops->root_get(dev))) |
goto error; |
ipc_hangup(phone); |
munmap(block, TMPFS_BLOCK_SIZE); |
return true; |
error: |
ipc_hangup(phone); |
munmap(block, TMPFS_BLOCK_SIZE); |
return false; |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/fs/tmpfs/tmpfs.h |
---|
40,20 → 40,24 |
#include <bool.h> |
#include <libadt/hash_table.h> |
#ifndef dprintf |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
typedef enum { |
TMPFS_NONE, |
TMPFS_FILE, |
TMPFS_DIRECTORY |
} tmpfs_dentry_type_t; |
typedef struct tmpfs_dentry { |
unsigned long index; /**< TMPFS node index. */ |
fs_index_t index; /**< TMPFS node index. */ |
link_t dh_link; /**< Dentries hash table link. */ |
struct tmpfs_dentry *parent; |
struct tmpfs_dentry *sibling; |
struct tmpfs_dentry *child; |
char *name; |
enum { |
TMPFS_NONE, |
TMPFS_FILE, |
TMPFS_DIRECTORY |
} type; |
hash_table_t names; /**< All names linking to this TMPFS node. */ |
tmpfs_dentry_type_t type; |
unsigned lnkcnt; /**< Link count. */ |
size_t size; /**< File size if type is TMPFS_FILE. */ |
void *data; /**< File content's if type is TMPFS_FILE. */ |
} tmpfs_dentry_t; |
60,11 → 64,18 |
extern fs_reg_t tmpfs_reg; |
extern libfs_ops_t tmpfs_libfs_ops; |
extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_mount(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_read(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_write(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *); |
extern bool tmpfs_restore(dev_handle_t); |
#endif |
/** |
/branches/network/uspace/srv/fs/tmpfs/Makefile |
---|
44,13 → 44,14 |
OUTPUT = tmpfs |
SOURCES = \ |
tmpfs.c \ |
tmpfs_ops.c |
tmpfs_ops.c \ |
tmpfs_dump.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
63,9 → 64,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/fs/tmpfs/tmpfs.c |
---|
50,23 → 50,20 |
#include <libfs.h> |
#include "../../vfs/vfs.h" |
#define NAME "tmpfs" |
vfs_info_t tmpfs_vfs_info = { |
.name = "tmpfs", |
.ops = { |
[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_OPEN)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_CLOSE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_READ)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_WRITE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_RENAME)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_OPENDIR)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_READDIR)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_CLOSEDIR)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_UNLINK)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNTED)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_DESTROY)] = VFS_OP_DEFINED, |
} |
}; |
109,6 → 106,12 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
tmpfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
tmpfs_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
tmpfs_lookup(callid, &call); |
break; |
118,6 → 121,12 |
case VFS_WRITE: |
tmpfs_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
tmpfs_truncate(callid, &call); |
break; |
case VFS_DESTROY: |
tmpfs_destroy(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
129,7 → 138,7 |
{ |
int vfs_phone; |
printf("TMPFS: HelenOS TMPFS file system server.\n"); |
printf(NAME ": HelenOS TMPFS file system server\n"); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
while (vfs_phone < EOK) { |
141,13 → 150,11 |
rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info, |
tmpfs_connection); |
if (rc != EOK) { |
printf("Failed to register the TMPFS file system (%d)\n", rc); |
printf(NAME ": Failed to register file system (%d)\n", rc); |
return rc; |
} |
dprintf("TMPFS filesystem registered, fs_handle=%d.\n", |
tmpfs_reg.fs_handle); |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* not reached */ |
return 0; |
/branches/network/uspace/srv/fs/fat/fat_ops.c |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2007 Jakub Jermar |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
37,12 → 37,29 |
#include "fat.h" |
#include "../../vfs/vfs.h" |
#include <libfs.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
#include <async.h> |
#include <errno.h> |
#include <string.h> |
#include <byteorder.h> |
#include <libadt/hash_table.h> |
#include <libadt/list.h> |
#include <assert.h> |
#include <futex.h> |
#include <sys/mman.h> |
#define PLB_GET_CHAR(i) (fat_reg.plb_ro[(i) % PLB_SIZE]) |
#define BS_BLOCK 0 |
#define BS_SIZE 512 |
/** Futex protecting the list of cached free FAT nodes. */ |
static futex_t ffn_futex = FUTEX_INITIALIZER; |
/** List of cached free FAT nodes. */ |
static LIST_INITIALIZE(ffn_head); |
#define FAT_NAME_LEN 8 |
#define FAT_EXT_LEN 3 |
53,90 → 70,783 |
#define FAT_DENTRY_DOT 0x2e |
#define FAT_DENTRY_ERASED 0xe5 |
/** Compare one component of path to a directory entry. |
#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 dentry Directory entry to compare the path component with. |
* @param start Index into PLB where the path component starts. |
* @param last Index of the last character of the path in PLB. |
* @param dev_handle Device handle of the device with the file. |
* @param firstc First cluster of the file. |
* |
* @return Zero on failure or delta such that (index + delta) % |
* PLB_SIZE points to a new path component in PLB. |
* @return Number of blocks allocated to the file. |
*/ |
static unsigned match_path_component(fat_dentry_t *dentry, unsigned start, |
unsigned last) |
static uint16_t |
_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc) |
{ |
unsigned cur; /* current position in PLB */ |
int pos; /* current position in dentry->name or dentry->ext */ |
bool name_processed = false; |
bool dot_processed = false; |
bool ext_processed = false; |
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; |
if (last < start) |
last += PLB_SIZE; |
for (pos = 0, cur = start; (cur <= last) && (PLB_GET_CHAR(cur) != '/'); |
pos++, cur++) { |
if (!name_processed) { |
if ((pos == FAT_NAME_LEN - 1) || |
(dentry->name[pos + 1] == FAT_PAD)) { |
/* this is the last character in name */ |
name_processed = true; |
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; |
} |
if (dentry->name[0] == FAT_PAD) { |
/* name is empty */ |
name_processed = true; |
} else if ((pos == 0) && (dentry->name[pos] == |
FAT_DENTRY_E5_ESC)) { |
if (PLB_GET_CHAR(cur) == 0xe5) |
continue; |
else |
return 0; /* character mismatch */ |
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); |
node->idx = NULL; |
node->type = 0; |
link_initialize(&node->ffn_link); |
node->size = 0; |
node->lnkcnt = 0; |
node->refcnt = 0; |
node->dirty = false; |
} |
static uint16_t fat_bps_get(dev_handle_t dev_handle) |
{ |
block_t *bb; |
uint16_t bps; |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
assert(bb != NULL); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
block_put(bb); |
return bps; |
} |
typedef enum { |
FAT_DENTRY_SKIP, |
FAT_DENTRY_LAST, |
FAT_DENTRY_VALID |
} fat_dentry_clsf_t; |
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; |
} |
static void fat_node_sync(fat_node_t *node) |
{ |
/* TODO */ |
} |
/** Internal version of fat_node_get(). |
* |
* @param idxp Locked index structure. |
*/ |
static void *fat_node_get_core(fat_idx_t *idxp) |
{ |
block_t *b; |
fat_dentry_t *d; |
fat_node_t *nodep = NULL; |
unsigned bps; |
unsigned dps; |
if (idxp->nodep) { |
/* |
* We are lucky. |
* The node is already instantiated in memory. |
*/ |
futex_down(&idxp->nodep->lock); |
if (!idxp->nodep->refcnt++) |
list_remove(&idxp->nodep->ffn_link); |
futex_up(&idxp->nodep->lock); |
return idxp->nodep; |
} |
/* |
* We must instantiate the node from the file system. |
*/ |
assert(idxp->pfc); |
futex_down(&ffn_futex); |
if (!list_empty(&ffn_head)) { |
/* Try to use a cached free node structure. */ |
fat_idx_t *idxp_tmp; |
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); |
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK) |
goto skip_cache; |
idxp_tmp = nodep->idx; |
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) { |
futex_up(&nodep->lock); |
goto skip_cache; |
} |
list_remove(&nodep->ffn_link); |
futex_up(&ffn_futex); |
if (nodep->dirty) |
fat_node_sync(nodep); |
idxp_tmp->nodep = NULL; |
futex_up(&nodep->lock); |
futex_up(&idxp_tmp->lock); |
} else { |
if (PLB_GET_CHAR(cur) == dentry->name[pos]) |
skip_cache: |
/* Try to allocate a new node structure. */ |
futex_up(&ffn_futex); |
nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!nodep) |
return NULL; |
} |
fat_node_initialize(nodep); |
bps = fat_bps_get(idxp->dev_handle); |
dps = bps / sizeof(fat_dentry_t); |
/* Read the block that contains the dentry of interest. */ |
b = _fat_block_get(idxp->dev_handle, idxp->pfc, |
(idxp->pdi * sizeof(fat_dentry_t)) / bps); |
assert(b); |
d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps); |
if (d->attr & FAT_ATTR_SUBDIR) { |
/* |
* The only directory which does not have this bit set is the |
* root directory itself. The root directory node is handled |
* and initialized elsewhere. |
*/ |
nodep->type = FAT_DIRECTORY; |
/* |
* Unfortunately, the 'size' field of the FAT dentry is not |
* defined for the directory entry type. We must determine the |
* size of the directory by walking the FAT. |
*/ |
nodep->size = bps * _fat_blcks_get(idxp->dev_handle, |
uint16_t_le2host(d->firstc)); |
} else { |
nodep->type = FAT_FILE; |
nodep->size = uint32_t_le2host(d->size); |
} |
nodep->firstc = uint16_t_le2host(d->firstc); |
nodep->lnkcnt = 1; |
nodep->refcnt = 1; |
block_put(b); |
/* Link the idx structure with the node structure. */ |
nodep->idx = idxp; |
idxp->nodep = nodep; |
return nodep; |
} |
/** Instantiate a FAT in-core node. */ |
static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
void *node; |
fat_idx_t *idxp; |
idxp = fat_idx_get_by_index(dev_handle, index); |
if (!idxp) |
return NULL; |
/* idxp->lock held */ |
node = fat_node_get_core(idxp); |
futex_up(&idxp->lock); |
return node; |
} |
static void fat_node_put(void *node) |
{ |
fat_node_t *nodep = (fat_node_t *)node; |
futex_down(&nodep->lock); |
if (!--nodep->refcnt) { |
futex_down(&ffn_futex); |
list_append(&nodep->ffn_link, &ffn_head); |
futex_up(&ffn_futex); |
} |
futex_up(&nodep->lock); |
} |
static void *fat_create(int flags) |
{ |
return NULL; /* not supported at the moment */ |
} |
static int fat_destroy(void *node) |
{ |
return ENOTSUP; /* not supported at the moment */ |
} |
static bool fat_link(void *prnt, void *chld, const char *name) |
{ |
return false; /* not supported at the moment */ |
} |
static int fat_unlink(void *prnt, void *chld) |
{ |
return ENOTSUP; /* not supported at the moment */ |
} |
static void *fat_match(void *prnt, const char *component) |
{ |
fat_node_t *parentp = (fat_node_t *)prnt; |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
unsigned i, j; |
unsigned bps; /* bytes per sector */ |
unsigned dps; /* dentries per sector */ |
unsigned blocks; |
fat_dentry_t *d; |
block_t *b; |
futex_down(&parentp->idx->lock); |
bps = fat_bps_get(parentp->idx->dev_handle); |
dps = bps / sizeof(fat_dentry_t); |
blocks = parentp->size / bps + (parentp->size % bps != 0); |
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++) { |
d = ((fat_dentry_t *)b->data) + j; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
continue; |
else |
return 0; /* character mismatch */ |
case FAT_DENTRY_LAST: |
block_put(b); |
futex_up(&parentp->idx->lock); |
return NULL; |
default: |
case FAT_DENTRY_VALID: |
dentry_name_canonify(d, name); |
break; |
} |
if (stricmp(name, component) == 0) { |
/* hit */ |
void *node; |
/* |
* Assume tree hierarchy for locking. We |
* already have the parent and now we are going |
* to lock the child. Never lock in the oposite |
* order. |
*/ |
fat_idx_t *idx = fat_idx_get_by_pos( |
parentp->idx->dev_handle, parentp->firstc, |
i * dps + j); |
futex_up(&parentp->idx->lock); |
if (!idx) { |
/* |
* Can happen if memory is low or if we |
* run out of 32-bit indices. |
*/ |
block_put(b); |
return NULL; |
} |
if (!dot_processed) { |
dot_processed = true; |
pos = -1; |
if (PLB_GET_CHAR(cur) != '.') |
node = fat_node_get_core(idx); |
futex_up(&idx->lock); |
block_put(b); |
return node; |
} |
} |
block_put(b); |
} |
futex_up(&parentp->idx->lock); |
return NULL; |
} |
static fs_index_t fat_index_get(void *node) |
{ |
fat_node_t *fnodep = (fat_node_t *)node; |
if (!fnodep) |
return 0; |
continue; |
return fnodep->idx->index; |
} |
if (!ext_processed) { |
if ((pos == FAT_EXT_LEN - 1) || |
(dentry->ext[pos + 1] == FAT_PAD)) { |
/* this is the last character in ext */ |
ext_processed = true; |
static size_t fat_size_get(void *node) |
{ |
return ((fat_node_t *)node)->size; |
} |
if (dentry->ext[0] == FAT_PAD) { |
/* ext is empty; the match will fail */ |
ext_processed = true; |
} else if (PLB_GET_CHAR(cur) == dentry->ext[pos]) { |
static unsigned fat_lnkcnt_get(void *node) |
{ |
return ((fat_node_t *)node)->lnkcnt; |
} |
static bool fat_has_children(void *node) |
{ |
fat_node_t *nodep = (fat_node_t *)node; |
unsigned bps; |
unsigned dps; |
unsigned blocks; |
block_t *b; |
unsigned i, j; |
if (nodep->type != FAT_DIRECTORY) |
return false; |
futex_down(&nodep->idx->lock); |
bps = fat_bps_get(nodep->idx->dev_handle); |
dps = bps / sizeof(fat_dentry_t); |
blocks = nodep->size / bps + (nodep->size % bps != 0); |
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++) { |
d = ((fat_dentry_t *)b->data) + j; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
continue; |
} else { |
/* character mismatch */ |
return 0; |
case FAT_DENTRY_LAST: |
block_put(b); |
futex_up(&nodep->idx->lock); |
return false; |
default: |
case FAT_DENTRY_VALID: |
block_put(b); |
futex_up(&nodep->idx->lock); |
return true; |
} |
block_put(b); |
futex_up(&nodep->idx->lock); |
return true; |
} |
return 0; /* extra characters in the component */ |
block_put(b); |
} |
if (ext_processed || (name_processed && dentry->ext[0] == FAT_PAD)) |
return cur - start; |
else |
return 0; |
futex_up(&nodep->idx->lock); |
return false; |
} |
static void *fat_root_get(dev_handle_t dev_handle) |
{ |
return fat_node_get(dev_handle, 0); |
} |
static char fat_plb_get_char(unsigned pos) |
{ |
return fat_reg.plb_ro[pos % PLB_SIZE]; |
} |
static bool fat_is_directory(void *node) |
{ |
return ((fat_node_t *)node)->type == FAT_DIRECTORY; |
} |
static bool fat_is_file(void *node) |
{ |
return ((fat_node_t *)node)->type == FAT_FILE; |
} |
/** libfs operations */ |
libfs_ops_t fat_libfs_ops = { |
.match = fat_match, |
.node_get = fat_node_get, |
.node_put = fat_node_put, |
.create = fat_create, |
.destroy = fat_destroy, |
.link = fat_link, |
.unlink = fat_unlink, |
.index_get = fat_index_get, |
.size_get = fat_size_get, |
.lnkcnt_get = fat_lnkcnt_get, |
.has_children = fat_has_children, |
.root_get = fat_root_get, |
.plb_get_char = fat_plb_get_char, |
.is_directory = fat_is_directory, |
.is_file = fat_is_file |
}; |
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; |
uint16_t bps; |
uint16_t rde; |
int rc; |
/* |
* For now, we don't bother to remember dev_handle, dev_phone or |
* dev_buffer in some data structure. We use global variables because we |
* know there will be at most one mount on this file system. |
* Of course, this is a huge TODO item. |
*/ |
dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE, |
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!dev_buffer) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev_handle); |
if (dev_phone < 0) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, dev_phone); |
return; |
} |
rc = ipc_share_out_start(dev_phone, dev_buffer, |
AS_AREA_READ | AS_AREA_WRITE); |
if (rc != EOK) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, rc); |
return; |
} |
/* Read the number of root directory entries. */ |
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
block_put(bb); |
if (bps != BS_SIZE) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
rc = fat_idx_init_by_dev_handle(dev_handle); |
if (rc != EOK) { |
munmap(dev_buffer, BS_SIZE); |
ipc_answer_0(rid, rc); |
return; |
} |
/* Initialize the root node. */ |
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!rootp) { |
munmap(dev_buffer, BS_SIZE); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
fat_node_initialize(rootp); |
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0); |
if (!ridxp) { |
munmap(dev_buffer, BS_SIZE); |
free(rootp); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
assert(ridxp->index == 0); |
/* ridxp->lock held */ |
rootp->type = FAT_DIRECTORY; |
rootp->firstc = FAT_CLST_ROOT; |
rootp->refcnt = 1; |
rootp->lnkcnt = 0; /* FS root is not linked */ |
rootp->size = rde * sizeof(fat_dentry_t); |
rootp->idx = ridxp; |
ridxp->nodep = rootp; |
futex_up(&ridxp->lock); |
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); |
} |
void fat_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
void fat_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
int first = IPC_GET_ARG1(*request); |
int second = IPC_GET_ARG2(*request); |
int dev_handle = IPC_GET_ARG3(*request); |
libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_read(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
uint16_t bps = fat_bps_get(dev_handle); |
size_t bytes; |
block_t *b; |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_read_receive(&callid, &len)) { |
fat_node_put(nodep); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (nodep->type == FAT_FILE) { |
/* |
* Our strategy for regular file reads is to read one block at |
* most and make use of the possibility to return less data than |
* requested. This keeps the code very simple. |
*/ |
bytes = min(len, bps - pos % bps); |
b = fat_block_get(nodep, pos / bps); |
(void) ipc_data_read_finalize(callid, b->data + pos % bps, |
bytes); |
block_put(b); |
} else { |
unsigned bnum; |
off_t spos = pos; |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
fat_dentry_t *d; |
assert(nodep->type == FAT_DIRECTORY); |
assert(nodep->size % bps == 0); |
assert(bps % sizeof(fat_dentry_t) == 0); |
/* |
* Our strategy for readdir() is to use the position pointer as |
* an index into the array of all dentries. On entry, it points |
* to the first unread dentry. If we skip any dentries, we bump |
* the position pointer accordingly. |
*/ |
bnum = (pos * sizeof(fat_dentry_t)) / bps; |
while (bnum < nodep->size / bps) { |
off_t o; |
b = fat_block_get(nodep, bnum); |
for (o = pos % (bps / sizeof(fat_dentry_t)); |
o < bps / sizeof(fat_dentry_t); |
o++, pos++) { |
d = ((fat_dentry_t *)b->data) + o; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
goto miss; |
default: |
case FAT_DENTRY_VALID: |
dentry_name_canonify(d, name); |
block_put(b); |
goto hit; |
} |
} |
block_put(b); |
bnum++; |
} |
miss: |
fat_node_put(nodep); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
hit: |
(void) ipc_data_read_finalize(callid, name, strlen(name) + 1); |
bytes = (pos - spos) + 1; |
} |
fat_node_put(nodep); |
ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/fs/fat/fat.h |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2007 Jakub Jermar |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
38,8 → 38,11 |
#include <atomic.h> |
#include <sys/types.h> |
#include <bool.h> |
#include "../../vfs/vfs.h" |
#ifndef dprintf |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
typedef struct { |
uint8_t ji[3]; /**< Jump instruction. */ |
47,17 → 50,17 |
/* BIOS Parameter Block */ |
uint16_t bps; /**< Bytes per sector. */ |
uint8_t spc; /**< Sectors per cluster. */ |
uint16_t rsc; /**< Reserved sector count. */ |
uint16_t rscnt; /**< Reserved sector count. */ |
uint8_t fatcnt; /**< Number of FATs. */ |
uint16_t root_ent_max; /**< Maximum number of root directory |
entries. */ |
uint16_t totsec; /**< Total sectors. */ |
uint16_t totsec16; /**< Total sectors. 16-bit version. */ |
uint8_t mdesc; /**< Media descriptor. */ |
uint16_t sec_per_fat; /**< Sectors per FAT12/FAT16. */ |
uint16_t sec_per_track; /**< Sectors per track. */ |
uint16_t headcnt; /**< Number of heads. */ |
uint32_t hidden_sec; /**< Hidden sectors. */ |
uint32_t total_sec; /**< Total sectors. */ |
uint32_t totsec32; /**< Total sectors. 32-bit version. */ |
union { |
struct { |
101,7 → 104,7 |
/** Serial number. */ |
uint32_t id; |
/** Volume label. */ |
uint8_t label; |
uint8_t label[11]; |
/** FAT type. */ |
uint8_t type[8]; |
/** Boot code. */ |
112,6 → 115,10 |
}; |
} __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]; |
134,10 → 141,97 |
uint32_t size; |
} __attribute__ ((packed)) fat_dentry_t; |
typedef uint16_t fat_cluster_t; |
typedef enum { |
FAT_INVALID, |
FAT_DIRECTORY, |
FAT_FILE |
} fat_node_type_t; |
struct fat_node; |
/** FAT index structure. |
* |
* This structure exists to help us to overcome certain limitations of the FAT |
* file system design. The problem with FAT is that it is hard to find |
* an entity which could represent a VFS index. There are two candidates: |
* |
* a) number of the node's first cluster |
* b) the pair of the parent directory's first cluster and the dentry index |
* within the parent directory |
* |
* We need VFS indices to be: |
* A) unique |
* B) stable in time, at least until the next mount |
* |
* Unfortunately a) does not meet the A) criterion because zero-length files |
* will have the first cluster field cleared. And b) does not meet the B) |
* criterion because unlink() and rename() will both free up the original |
* dentry, which contains all the essential info about the file. |
* |
* Therefore, a completely opaque indices are used and the FAT server maintains |
* a mapping between them and otherwise nice b) variant. On rename(), the VFS |
* index stays unaltered, while the internal FAT "physical tree address" |
* changes. The unlink case is also handled this way thanks to an in-core node |
* pointer embedded in the index structure. |
*/ |
typedef struct { |
/** Used indices (position) hash table link. */ |
link_t uph_link; |
/** Used indices (index) hash table link. */ |
link_t uih_link; |
futex_t lock; |
dev_handle_t dev_handle; |
fs_index_t index; |
/** |
* Parent node's first cluster. |
* Zero is used if this node is not linked, in which case nodep must |
* contain a pointer to the in-core node structure. |
* One is used when the parent is the root directory. |
*/ |
fat_cluster_t pfc; |
/** Directory entry index within the parent node. */ |
unsigned pdi; |
/** Pointer to in-core node instance. */ |
struct fat_node *nodep; |
} fat_idx_t; |
/** FAT in-core node. */ |
typedef struct fat_node { |
futex_t lock; |
fat_node_type_t type; |
fat_idx_t *idx; |
/** |
* Node's first cluster. |
* Zero is used for zero-length nodes. |
* One is used to mark root directory. |
*/ |
fat_cluster_t firstc; |
/** FAT in-core node free list link. */ |
link_t ffn_link; |
size_t size; |
unsigned lnkcnt; |
unsigned refcnt; |
bool dirty; |
} fat_node_t; |
extern fs_reg_t fat_reg; |
extern void fat_mounted(ipc_callid_t, ipc_call_t *); |
extern void fat_mount(ipc_callid_t, ipc_call_t *); |
extern void fat_lookup(ipc_callid_t, ipc_call_t *); |
extern void fat_read(ipc_callid_t, ipc_call_t *); |
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned); |
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t); |
extern int fat_idx_init(void); |
extern void fat_idx_fini(void); |
extern int fat_idx_init_by_dev_handle(dev_handle_t); |
extern void fat_idx_fini_by_dev_handle(dev_handle_t); |
#endif |
/** |
/branches/network/uspace/srv/fs/fat/fat.c |
---|
51,17 → 51,11 |
.name = "fat", |
.ops = { |
[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_OPEN)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_CLOSE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_READ)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_WRITE)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_RENAME)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_OPENDIR)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_READDIR)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_CLOSEDIR)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_UNLINK)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNTED)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL, |
} |
}; |
104,9 → 98,18 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
fat_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
fat_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
fat_lookup(callid, &call); |
break; |
case VFS_READ: |
fat_read(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
117,9 → 120,14 |
int main(int argc, char **argv) |
{ |
int vfs_phone; |
int rc; |
printf("FAT: HelenOS FAT file system server.\n"); |
rc = fat_idx_init(); |
if (rc != EOK) |
goto err; |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
while (vfs_phone < EOK) { |
usleep(10000); |
126,11 → 134,10 |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
} |
int rc; |
rc = fs_register(vfs_phone, &fat_reg, &fat_vfs_info, fat_connection); |
if (rc != EOK) { |
printf("Failed to register the FAT file system (%d)\n", rc); |
return rc; |
fat_idx_fini(); |
goto err; |
} |
dprintf("FAT filesystem registered, fs_handle=%d.\n", |
139,6 → 146,10 |
async_manager(); |
/* not reached */ |
return 0; |
err: |
printf("Failed to register the FAT file system (%d)\n", rc); |
return rc; |
} |
/** |
/branches/network/uspace/srv/fs/fat/Makefile |
---|
44,13 → 44,14 |
OUTPUT = fat |
SOURCES = \ |
fat.c \ |
fat_ops.c |
fat_ops.c \ |
fat_idx.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
63,9 → 64,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/fs/fat/fat_idx.c |
---|
0,0 → 1,467 |
/* |
* 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_idx.c |
* @brief Layer for translating FAT entities to VFS node indices. |
*/ |
#include "fat.h" |
#include "../../vfs/vfs.h" |
#include <errno.h> |
#include <string.h> |
#include <libadt/hash_table.h> |
#include <libadt/list.h> |
#include <assert.h> |
#include <futex.h> |
/** Each instance of this type describes one interval of freed VFS indices. */ |
typedef struct { |
link_t link; |
fs_index_t first; |
fs_index_t last; |
} freed_t; |
/** |
* Each instance of this type describes state of all VFS indices that |
* are currently unused. |
*/ |
typedef struct { |
link_t link; |
dev_handle_t dev_handle; |
/** Next unassigned index. */ |
fs_index_t next; |
/** Number of remaining unassigned indices. */ |
uint64_t remaining; |
/** Sorted list of intervals of freed indices. */ |
link_t freed_head; |
} unused_t; |
/** Futex protecting the list of unused structures. */ |
static futex_t unused_futex = FUTEX_INITIALIZER; |
/** List of unused structures. */ |
static LIST_INITIALIZE(unused_head); |
static void unused_initialize(unused_t *u, dev_handle_t dev_handle) |
{ |
link_initialize(&u->link); |
u->dev_handle = dev_handle; |
u->next = 0; |
u->remaining = ((uint64_t)((fs_index_t)-1)) + 1; |
list_initialize(&u->freed_head); |
} |
static unused_t *unused_find(dev_handle_t dev_handle, bool lock) |
{ |
unused_t *u; |
link_t *l; |
if (lock) |
futex_down(&unused_futex); |
for (l = unused_head.next; l != &unused_head; l = l->next) { |
u = list_get_instance(l, unused_t, link); |
if (u->dev_handle == dev_handle) |
return u; |
} |
if (lock) |
futex_up(&unused_futex); |
return NULL; |
} |
/** Futex protecting the up_hash and ui_hash. */ |
static futex_t used_futex = FUTEX_INITIALIZER; |
/** |
* Global hash table of all used fat_idx_t structures. |
* The index structures are hashed by the dev_handle, parent node's first |
* cluster and index within the parent directory. |
*/ |
static hash_table_t up_hash; |
#define UPH_BUCKETS_LOG 12 |
#define UPH_BUCKETS (1 << UPH_BUCKETS_LOG) |
#define UPH_DH_KEY 0 |
#define UPH_PFC_KEY 1 |
#define UPH_PDI_KEY 2 |
static hash_index_t pos_hash(unsigned long key[]) |
{ |
dev_handle_t dev_handle = (dev_handle_t)key[UPH_DH_KEY]; |
fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY]; |
unsigned pdi = (unsigned)key[UPH_PDI_KEY]; |
hash_index_t h; |
/* |
* The least significant half of all bits are the least significant bits |
* of the parent node's first cluster. |
* |
* The least significant half of the most significant half of all bits |
* are the least significant bits of the node's dentry index within the |
* parent directory node. |
* |
* The most significant half of the most significant half of all bits |
* are the least significant bits of the device handle. |
*/ |
h = pfc & ((1 << (UPH_BUCKETS_LOG / 2)) - 1); |
h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << |
(UPH_BUCKETS_LOG / 2); |
h |= (dev_handle & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << |
(3 * (UPH_BUCKETS_LOG / 4)); |
return h; |
} |
static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
dev_handle_t dev_handle = (dev_handle_t)key[UPH_DH_KEY]; |
fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY]; |
unsigned pdi = (unsigned)key[UPH_PDI_KEY]; |
fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uph_link); |
return (dev_handle == fidx->dev_handle) && (pfc == fidx->pfc) && |
(pdi == fidx->pdi); |
} |
static void pos_remove_callback(link_t *item) |
{ |
/* nothing to do */ |
} |
static hash_table_operations_t uph_ops = { |
.hash = pos_hash, |
.compare = pos_compare, |
.remove_callback = pos_remove_callback, |
}; |
/** |
* Global hash table of all used fat_idx_t structures. |
* The index structures are hashed by the dev_handle and index. |
*/ |
static hash_table_t ui_hash; |
#define UIH_BUCKETS_LOG 12 |
#define UIH_BUCKETS (1 << UIH_BUCKETS_LOG) |
#define UIH_DH_KEY 0 |
#define UIH_INDEX_KEY 1 |
static hash_index_t idx_hash(unsigned long key[]) |
{ |
dev_handle_t dev_handle = (dev_handle_t)key[UIH_DH_KEY]; |
fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY]; |
hash_index_t h; |
h = dev_handle & ((1 << (UIH_BUCKETS_LOG / 2)) - 1); |
h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) << |
(UIH_BUCKETS_LOG / 2); |
return h; |
} |
static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
dev_handle_t dev_handle = (dev_handle_t)key[UIH_DH_KEY]; |
fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY]; |
fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link); |
return (dev_handle == fidx->dev_handle) && (index == fidx->index); |
} |
static void idx_remove_callback(link_t *item) |
{ |
/* nothing to do */ |
} |
static hash_table_operations_t uih_ops = { |
.hash = idx_hash, |
.compare = idx_compare, |
.remove_callback = idx_remove_callback, |
}; |
/** Allocate a VFS index which is not currently in use. */ |
static bool fat_idx_alloc(dev_handle_t dev_handle, fs_index_t *index) |
{ |
unused_t *u; |
assert(index); |
u = unused_find(dev_handle, true); |
if (!u) |
return false; |
if (list_empty(&u->freed_head)) { |
if (u->remaining) { |
/* |
* There are no freed indices, allocate one directly |
* from the counter. |
*/ |
*index = u->next++; |
--u->remaining; |
futex_up(&unused_futex); |
return true; |
} |
} else { |
/* There are some freed indices which we can reuse. */ |
freed_t *f = list_get_instance(u->freed_head.next, freed_t, |
link); |
*index = f->first; |
if (f->first++ == f->last) { |
/* Destroy the interval. */ |
list_remove(&f->link); |
free(f); |
} |
futex_up(&unused_futex); |
return true; |
} |
/* |
* We ran out of indices, which is extremely unlikely with FAT16, but |
* theoretically still possible (e.g. too many open unlinked nodes or |
* too many zero-sized nodes). |
*/ |
futex_up(&unused_futex); |
return false; |
} |
/** If possible, coalesce two intervals of freed indices. */ |
static void try_coalesce_intervals(link_t *l, link_t *r, link_t *cur) |
{ |
freed_t *fl = list_get_instance(l, freed_t, link); |
freed_t *fr = list_get_instance(r, freed_t, link); |
if (fl->last + 1 == fr->first) { |
if (cur == l) { |
fl->last = fr->last; |
list_remove(r); |
free(r); |
} else { |
fr->first = fl->first; |
list_remove(l); |
free(l); |
} |
} |
} |
/** Free a VFS index, which is no longer in use. */ |
static void fat_idx_free(dev_handle_t dev_handle, fs_index_t index) |
{ |
unused_t *u; |
u = unused_find(dev_handle, true); |
assert(u); |
if (u->next == index + 1) { |
/* The index can be returned directly to the counter. */ |
u->next--; |
u->remaining++; |
} else { |
/* |
* The index must be returned either to an existing freed |
* interval or a new interval must be created. |
*/ |
link_t *lnk; |
freed_t *n; |
for (lnk = u->freed_head.next; lnk != &u->freed_head; |
lnk = lnk->next) { |
freed_t *f = list_get_instance(lnk, freed_t, link); |
if (f->first == index + 1) { |
f->first--; |
if (lnk->prev != &u->freed_head) |
try_coalesce_intervals(lnk->prev, lnk, |
lnk); |
futex_up(&unused_futex); |
return; |
} |
if (f->last == index - 1) { |
f->last++; |
if (lnk->next != &u->freed_head) |
try_coalesce_intervals(lnk, lnk->next, |
lnk); |
futex_up(&unused_futex); |
return; |
} |
if (index > f->first) { |
n = malloc(sizeof(freed_t)); |
/* TODO: sleep until allocation succeeds */ |
assert(n); |
link_initialize(&n->link); |
n->first = index; |
n->last = index; |
list_insert_before(&n->link, lnk); |
futex_up(&unused_futex); |
return; |
} |
} |
/* The index will form the last interval. */ |
n = malloc(sizeof(freed_t)); |
/* TODO: sleep until allocation succeeds */ |
assert(n); |
link_initialize(&n->link); |
n->first = index; |
n->last = index; |
list_append(&n->link, &u->freed_head); |
} |
futex_up(&unused_futex); |
} |
fat_idx_t * |
fat_idx_get_by_pos(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi) |
{ |
fat_idx_t *fidx; |
link_t *l; |
unsigned long pkey[] = { |
[UPH_DH_KEY] = dev_handle, |
[UPH_PFC_KEY] = pfc, |
[UPH_PDI_KEY] = pdi, |
}; |
futex_down(&used_futex); |
l = hash_table_find(&up_hash, pkey); |
if (l) { |
fidx = hash_table_get_instance(l, fat_idx_t, uph_link); |
} else { |
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
if (!fidx) { |
futex_up(&used_futex); |
return NULL; |
} |
if (!fat_idx_alloc(dev_handle, &fidx->index)) { |
free(fidx); |
futex_up(&used_futex); |
return NULL; |
} |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
[UIH_INDEX_KEY] = fidx->index, |
}; |
link_initialize(&fidx->uph_link); |
link_initialize(&fidx->uih_link); |
futex_initialize(&fidx->lock, 1); |
fidx->dev_handle = dev_handle; |
fidx->pfc = pfc; |
fidx->pdi = pdi; |
fidx->nodep = NULL; |
hash_table_insert(&up_hash, pkey, &fidx->uph_link); |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
} |
futex_down(&fidx->lock); |
futex_up(&used_futex); |
return fidx; |
} |
fat_idx_t * |
fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index) |
{ |
fat_idx_t *fidx = NULL; |
link_t *l; |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
[UIH_INDEX_KEY] = index, |
}; |
futex_down(&used_futex); |
l = hash_table_find(&ui_hash, ikey); |
if (l) { |
fidx = hash_table_get_instance(l, fat_idx_t, uih_link); |
futex_down(&fidx->lock); |
} |
futex_up(&used_futex); |
return fidx; |
} |
int fat_idx_init(void) |
{ |
if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops)) |
return ENOMEM; |
if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) { |
hash_table_destroy(&up_hash); |
return ENOMEM; |
} |
return EOK; |
} |
void fat_idx_fini(void) |
{ |
/* We assume the hash tables are empty. */ |
hash_table_destroy(&up_hash); |
hash_table_destroy(&ui_hash); |
} |
int fat_idx_init_by_dev_handle(dev_handle_t dev_handle) |
{ |
unused_t *u; |
int rc = EOK; |
u = (unused_t *) malloc(sizeof(unused_t)); |
if (!u) |
return ENOMEM; |
unused_initialize(u, dev_handle); |
futex_down(&unused_futex); |
if (!unused_find(dev_handle, false)) |
list_append(&u->link, &unused_head); |
else |
rc = EEXIST; |
futex_up(&unused_futex); |
return rc; |
} |
void fat_idx_fini_by_dev_handle(dev_handle_t dev_handle) |
{ |
unused_t *u; |
u = unused_find(dev_handle, true); |
assert(u); |
list_remove(&u->link); |
futex_up(&unused_futex); |
while (!list_empty(&u->freed_head)) { |
freed_t *f; |
f = list_get_instance(u->freed_head.next, freed_t, link); |
list_remove(&f->link); |
free(f); |
} |
free(u); |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/vfs/vfs_ops.c |
---|
35,6 → 35,7 |
* @brief Operations that VFS offers to its clients. |
*/ |
#include "vfs.h" |
#include <ipc/ipc.h> |
#include <async.h> |
#include <errno.h> |
49,9 → 50,11 |
#include <ctype.h> |
#include <fcntl.h> |
#include <assert.h> |
#include <atomic.h> |
#include "vfs.h" |
#include <vfs/canonify.h> |
/* Forward declarations of static functions. */ |
static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t); |
/** |
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a |
* concurrent VFS operation which modifies the file system namespace. |
58,28 → 61,21 |
*/ |
RWLOCK_INITIALIZE(namespace_rwlock); |
atomic_t rootfs_futex = FUTEX_INITIALIZER; |
vfs_triplet_t rootfs = { |
futex_t rootfs_futex = FUTEX_INITIALIZER; |
vfs_pair_t rootfs = { |
.fs_handle = 0, |
.dev_handle = 0, |
.index = 0, |
.dev_handle = 0 |
}; |
static int lookup_root(int fs_handle, int dev_handle, vfs_lookup_res_t *result) |
{ |
vfs_pair_t altroot = { |
.fs_handle = fs_handle, |
.dev_handle = dev_handle, |
}; |
return vfs_lookup_internal("/", strlen("/"), L_DIRECTORY, result, |
&altroot); |
} |
void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
int dev_handle; |
dev_handle_t dev_handle; |
vfs_node_t *mp_node = NULL; |
ipc_callid_t callid; |
ipc_call_t data; |
int rc; |
int phone; |
size_t size; |
/* |
* We expect the library to do the device-name to device-handle |
86,7 → 82,7 |
* translation for us, thus the device handle will arrive as ARG1 |
* in the request. |
*/ |
dev_handle = IPC_GET_ARG1(*request); |
dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
/* |
* For now, don't make use of ARG2 and ARG3, but they can be used to |
93,9 → 89,6 |
* carry mount options in the future. |
*/ |
ipc_callid_t callid; |
size_t size; |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
122,15 → 115,30 |
fs_name[size] = '\0'; |
/* |
* Wait for IPC_M_PING so that we can return an error if we don't know |
* fs_name. |
*/ |
callid = async_get_call(&data); |
if (IPC_GET_METHOD(data) != IPC_M_PING) { |
ipc_answer_0(callid, ENOTSUP); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
int fs_handle = fs_name_to_handle(fs_name, true); |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
if (!fs_handle) { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* Acknowledge that we know fs_name. */ |
ipc_answer_0(callid, EOK); |
/* Now, we want the client to send us the mount point. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
146,7 → 154,7 |
} |
/* Allocate buffer for the mount point data being received. */ |
uint8_t *buf; |
buf = malloc(size); |
buf = malloc(size + 1); |
if (!buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
155,41 → 163,27 |
/* Deliver the mount point. */ |
(void) ipc_data_write_finalize(callid, buf, size); |
buf[size] = '\0'; |
/* |
* Lookup the root node of the filesystem being mounted. |
* In this case, we don't need to take the namespace_futex as the root |
* node cannot be removed. However, we do take a reference to it so |
* that we can track how many times it has been mounted. |
*/ |
int rc; |
vfs_lookup_res_t mr_res; |
rc = lookup_root(fs_handle, dev_handle, &mr_res); |
if (rc != EOK) { |
free(buf); |
ipc_answer_0(rid, rc); |
return; |
} |
vfs_node_t *mr_node = vfs_node_get(&mr_res); |
if (!mr_node) { |
free(buf); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* Finally, we need to resolve the path to the mountpoint. */ |
/* Resolve the path to the mountpoint. */ |
vfs_lookup_res_t mp_res; |
futex_down(&rootfs_futex); |
if (rootfs.fs_handle) { |
/* We already have the root FS. */ |
rwlock_write_lock(&namespace_rwlock); |
rc = vfs_lookup_internal(buf, size, L_DIRECTORY, &mp_res, |
NULL); |
if ((size == 1) && (buf[0] == '/')) { |
/* Trying to mount root FS over root FS */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
free(buf); |
ipc_answer_0(rid, EBUSY); |
return; |
} |
rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL); |
if (rc != EOK) { |
/* The lookup failed for some reason. */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
vfs_node_put(mr_node); /* failed -> drop reference */ |
free(buf); |
ipc_answer_0(rid, rc); |
return; |
198,7 → 192,6 |
if (!mp_node) { |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
vfs_node_put(mr_node); /* failed -> drop reference */ |
free(buf); |
ipc_answer_0(rid, ENOMEM); |
return; |
212,12 → 205,46 |
} else { |
/* We still don't have the root file system mounted. */ |
if ((size == 1) && (buf[0] == '/')) { |
/* For this simple, but important case, we are done. */ |
rootfs = mr_res.triplet; |
vfs_lookup_res_t mr_res; |
vfs_node_t *mr_node; |
ipcarg_t rindex; |
ipcarg_t rsize; |
ipcarg_t rlnkcnt; |
/* |
* For this simple, but important case, |
* we are almost done. |
*/ |
free(buf); |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
rc = async_req_1_3(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
vfs_release_phone(phone); |
if (rc != EOK) { |
futex_up(&rootfs_futex); |
free(buf); |
ipc_answer_0(rid, EOK); |
ipc_answer_0(rid, rc); |
return; |
} |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = (fs_index_t) rindex; |
mr_res.size = (size_t) rsize; |
mr_res.lnkcnt = (unsigned) rlnkcnt; |
rootfs.fs_handle = fs_handle; |
rootfs.dev_handle = dev_handle; |
futex_up(&rootfs_futex); |
/* Add reference to the mounted root. */ |
mr_node = vfs_node_get(&mr_res); |
assert(mr_node); |
ipc_answer_0(rid, rc); |
return; |
} else { |
/* |
* We can't resolve this without the root filesystem |
225,7 → 252,6 |
*/ |
futex_up(&rootfs_futex); |
free(buf); |
vfs_node_put(mr_node); /* failed -> drop reference */ |
ipc_answer_0(rid, ENOENT); |
return; |
} |
236,40 → 262,24 |
/* |
* At this point, we have all necessary pieces: file system and device |
* handles, and we know the mount point VFS node and also the root node |
* of the file system being mounted. |
* handles, and we know the mount point VFS node. |
*/ |
int phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
/* Later we can use ARG3 to pass mode/flags. */ |
aid_t req1 = async_send_3(phone, VFS_MOUNT, |
phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
rc = async_req_4_0(phone, VFS_MOUNT, |
(ipcarg_t) mp_res.triplet.dev_handle, |
(ipcarg_t) mp_res.triplet.index, 0, NULL); |
/* The second call uses the same method. */ |
aid_t req2 = async_send_3(phone, VFS_MOUNT, |
(ipcarg_t) mr_res.triplet.fs_handle, |
(ipcarg_t) mr_res.triplet.dev_handle, |
(ipcarg_t) mr_res.triplet.index, NULL); |
(ipcarg_t) mp_res.triplet.index, |
(ipcarg_t) fs_handle, |
(ipcarg_t) dev_handle); |
vfs_release_phone(phone); |
ipcarg_t rc1; |
ipcarg_t rc2; |
async_wait_for(req1, &rc1); |
async_wait_for(req2, &rc2); |
if ((rc1 != EOK) || (rc2 != EOK)) { |
/* Mount failed, drop references to mr_node and mp_node. */ |
vfs_node_put(mr_node); |
if (rc != EOK) { |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
} |
if (rc2 == EOK) |
ipc_answer_0(rid, rc1); |
else if (rc1 == EOK) |
ipc_answer_0(rid, rc2); |
else |
ipc_answer_0(rid, rc1); |
ipc_answer_0(rid, rc); |
} |
void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
304,21 → 314,12 |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* |
* Now we are on the verge of accepting the path. |
* |
* There is one optimization we could do in the future: copy the path |
* directly into the PLB using some kind of a callback. |
*/ |
char *path = malloc(len); |
char *path = malloc(len + 1); |
if (!path) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
325,6 → 326,7 |
free(path); |
return; |
} |
path[len] = '\0'; |
/* |
* Avoid the race condition in which the file can be deleted before we |
338,7 → 340,7 |
/* The path is now populated and we can call vfs_lookup_internal(). */ |
vfs_lookup_res_t lr; |
rc = vfs_lookup_internal(path, len, lflag, &lr, NULL); |
rc = vfs_lookup_internal(path, lflag, &lr, NULL); |
if (rc) { |
if (lflag & L_CREATE) |
rwlock_write_unlock(&namespace_rwlock); |
349,7 → 351,7 |
return; |
} |
/** Path is no longer needed. */ |
/* Path is no longer needed. */ |
free(path); |
vfs_node_t *node = vfs_node_get(&lr); |
358,6 → 360,23 |
else |
rwlock_read_unlock(&namespace_rwlock); |
/* Truncate the file if requested and if necessary. */ |
if (oflag & O_TRUNC) { |
rwlock_write_lock(&node->contents_rwlock); |
if (node->size) { |
rc = vfs_truncate_internal(node->fs_handle, |
node->dev_handle, node->index, 0); |
if (rc) { |
rwlock_write_unlock(&node->contents_rwlock); |
vfs_node_put(node); |
ipc_answer_0(rid, rc); |
return; |
} |
node->size = 0; |
} |
rwlock_write_unlock(&node->contents_rwlock); |
} |
/* |
* Get ourselves a file descriptor and the corresponding vfs_file_t |
* structure. |
387,6 → 406,13 |
ipc_answer_1(rid, EOK, fd); |
} |
void vfs_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
int rc = vfs_fd_free(fd); |
ipc_answer_0(rid, rc); |
} |
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) |
{ |
549,11 → 575,25 |
ipc_answer_0(rid, EINVAL); |
} |
int |
vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle, |
fs_index_t index, size_t size) |
{ |
ipcarg_t rc; |
int fs_phone; |
fs_phone = vfs_grab_phone(fs_handle); |
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)dev_handle, |
(ipcarg_t)index, (ipcarg_t)size); |
vfs_release_phone(fs_phone); |
return (int)rc; |
} |
void vfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
size_t size = IPC_GET_ARG2(*request); |
ipcarg_t rc; |
int rc; |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
563,24 → 603,21 |
futex_down(&file->lock); |
rwlock_write_lock(&file->node->contents_rwlock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, |
(ipcarg_t)file->node->dev_handle, (ipcarg_t)file->node->index, |
(ipcarg_t)size); |
vfs_release_phone(fs_phone); |
rc = vfs_truncate_internal(file->node->fs_handle, |
file->node->dev_handle, file->node->index, size); |
if (rc == EOK) |
file->node->size = size; |
rwlock_write_unlock(&file->node->contents_rwlock); |
futex_up(&file->lock); |
ipc_answer_0(rid, rc); |
ipc_answer_0(rid, (ipcarg_t)rc); |
} |
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request) |
{ |
int mode = IPC_GET_ARG1(*request); |
size_t len; |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, &len)) { |
588,21 → 625,12 |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* |
* Now we are on the verge of accepting the path. |
* |
* There is one optimization we could do in the future: copy the path |
* directly into the PLB using some kind of a callback. |
*/ |
char *path = malloc(len); |
char *path = malloc(len + 1); |
if (!path) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
609,15 → 637,234 |
free(path); |
return; |
} |
path[len] = '\0'; |
rwlock_write_lock(&namespace_rwlock); |
int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE; |
rc = vfs_lookup_internal(path, len, lflag, NULL, NULL); |
rc = vfs_lookup_internal(path, lflag, NULL, NULL); |
rwlock_write_unlock(&namespace_rwlock); |
free(path); |
ipc_answer_0(rid, rc); |
} |
void vfs_unlink(ipc_callid_t rid, ipc_call_t *request) |
{ |
int lflag = IPC_GET_ARG1(*request); |
size_t len; |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *path = malloc(len + 1); |
if (!path) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
int rc; |
if ((rc = ipc_data_write_finalize(callid, path, len))) { |
ipc_answer_0(rid, rc); |
free(path); |
return; |
} |
path[len] = '\0'; |
rwlock_write_lock(&namespace_rwlock); |
lflag &= L_DIRECTORY; /* sanitize lflag */ |
vfs_lookup_res_t lr; |
rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL); |
free(path); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
/* |
* The name has already been unlinked by vfs_lookup_internal(). |
* We have to get and put the VFS node to ensure that it is |
* VFS_DESTROY'ed after the last reference to it is dropped. |
*/ |
vfs_node_t *node = vfs_node_get(&lr); |
futex_down(&nodes_futex); |
node->lnkcnt--; |
futex_up(&nodes_futex); |
rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(node); |
ipc_answer_0(rid, EOK); |
} |
void vfs_rename(ipc_callid_t rid, ipc_call_t *request) |
{ |
size_t len; |
ipc_callid_t callid; |
int rc; |
/* Retrieve the old path. */ |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *old = malloc(len + 1); |
if (!old) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if ((rc = ipc_data_write_finalize(callid, old, len))) { |
ipc_answer_0(rid, rc); |
free(old); |
return; |
} |
old[len] = '\0'; |
/* Retrieve the new path. */ |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(old); |
return; |
} |
char *new = malloc(len + 1); |
if (!new) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(old); |
return; |
} |
if ((rc = ipc_data_write_finalize(callid, new, len))) { |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
new[len] = '\0'; |
char *oldc = canonify(old, &len); |
char *newc = canonify(new, NULL); |
if (!oldc || !newc) { |
ipc_answer_0(rid, EINVAL); |
free(old); |
free(new); |
return; |
} |
if (!strncmp(newc, oldc, len)) { |
/* oldc is a prefix of newc */ |
ipc_answer_0(rid, EINVAL); |
free(old); |
free(new); |
return; |
} |
vfs_lookup_res_t old_lr; |
vfs_lookup_res_t new_lr; |
vfs_lookup_res_t new_par_lr; |
rwlock_write_lock(&namespace_rwlock); |
/* Lookup the node belonging to the old file name. */ |
rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
vfs_node_t *old_node = vfs_node_get(&old_lr); |
if (!old_node) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOMEM); |
free(old); |
free(new); |
return; |
} |
/* Lookup parent of the new file name. */ |
rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
/* Check whether linking to the same file system instance. */ |
if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) || |
(old_node->dev_handle != new_par_lr.triplet.dev_handle)) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, EXDEV); /* different file systems */ |
free(old); |
free(new); |
return; |
} |
/* Destroy the old link for the new name. */ |
vfs_node_t *new_node = NULL; |
rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL); |
switch (rc) { |
case ENOENT: |
/* simply not in our way */ |
break; |
case EOK: |
new_node = vfs_node_get(&new_lr); |
if (!new_node) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOMEM); |
free(old); |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
new_node->lnkcnt--; |
futex_up(&nodes_futex); |
break; |
default: |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, ENOTEMPTY); |
free(old); |
free(new); |
return; |
} |
/* Create the new link for the new name. */ |
rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
if (new_node) |
vfs_node_put(new_node); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
old_node->lnkcnt++; |
futex_up(&nodes_futex); |
/* Destroy the link for the old name. */ |
rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(old_node); |
if (new_node) |
vfs_node_put(new_node); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
old_node->lnkcnt--; |
futex_up(&nodes_futex); |
rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(old_node); |
if (new_node) |
vfs_node_put(new_node); |
free(old); |
free(new); |
ipc_answer_0(rid, EOK); |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/vfs/vfs.h |
---|
35,29 → 35,29 |
#include <ipc/ipc.h> |
#include <libadt/list.h> |
#include <atomic.h> |
#include <futex.h> |
#include <rwlock.h> |
#include <sys/types.h> |
#include <bool.h> |
#define dprintf(...) printf(__VA_ARGS__) |
// FIXME: according to CONFIG_DEBUG |
// #define dprintf(...) printf(__VA_ARGS__) |
#define dprintf(...) |
#define VFS_FIRST IPC_FIRST_USER_METHOD |
#define IPC_METHOD_TO_VFS_OP(m) ((m) - VFS_FIRST) |
/* Basic types. */ |
typedef int16_t fs_handle_t; |
typedef int16_t dev_handle_t; |
typedef uint32_t fs_index_t; |
typedef enum { |
VFS_OPEN = VFS_FIRST, |
VFS_CLOSE, |
VFS_READ, |
VFS_READ = VFS_FIRST, |
VFS_WRITE, |
VFS_TRUNCATE, |
VFS_RENAME, |
VFS_OPENDIR, |
VFS_READDIR, |
VFS_CLOSEDIR, |
VFS_MKDIR, |
VFS_UNLINK, |
VFS_MOUNT, |
VFS_UNMOUNT, |
VFS_LAST_CMN, /* keep this the last member of this enum */ |
65,12 → 65,19 |
typedef enum { |
VFS_LOOKUP = VFS_LAST_CMN, |
VFS_MOUNTED, |
VFS_DESTROY, |
VFS_LAST_CLNT, /* keep this the last member of this enum */ |
} vfs_request_clnt_t; |
typedef enum { |
VFS_REGISTER = VFS_LAST_CMN, |
VFS_OPEN, |
VFS_CLOSE, |
VFS_SEEK, |
VFS_MKDIR, |
VFS_UNLINK, |
VFS_RENAME, |
VFS_LAST_SRV, /* keep this the last member of this enum */ |
} vfs_request_srv_t; |
108,8 → 115,8 |
typedef struct { |
link_t fs_link; |
vfs_info_t vfs_info; |
int fs_handle; |
atomic_t phone_futex; /**< Phone serializing futex. */ |
fs_handle_t fs_handle; |
futex_t phone_futex; /**< Phone serializing futex. */ |
ipcarg_t phone; |
} fs_info_t; |
117,8 → 124,8 |
* VFS_PAIR uniquely represents a file system instance. |
*/ |
#define VFS_PAIR \ |
int fs_handle; \ |
int dev_handle; |
fs_handle_t fs_handle; \ |
dev_handle_t dev_handle; |
/** |
* VFS_TRIPLET uniquely identifies a file system node (e.g. directory, file) but |
129,7 → 136,7 |
*/ |
#define VFS_TRIPLET \ |
VFS_PAIR; \ |
uint64_t index; |
fs_index_t index; |
typedef struct { |
VFS_PAIR; |
143,6 → 150,10 |
* Lookup flags. |
*/ |
/** |
* No lookup flags used. |
*/ |
#define L_NONE 0 |
/** |
* Lookup will succeed only if the object is a regular file. If L_CREATE is |
* specified, an empty file will be created. This flag is mutually exclusive |
* with L_DIRECTORY. |
164,15 → 175,25 |
*/ |
#define L_CREATE 8 |
/** |
* L_DESTROY is used to remove leaves from the file system namespace. This flag |
* L_LINK is used for linking to an already existing nodes. |
*/ |
#define L_LINK 16 |
/** |
* L_UNLINK is used to remove leaves from the file system namespace. This flag |
* cannot be passed directly by the client, but will be set by VFS during |
* VFS_UNLINK. |
*/ |
#define L_DESTROY 16 |
#define L_UNLINK 32 |
/** |
* L_PARENT performs a lookup but returns the triplet of the parent node. |
* This flag may not be combined with any other lookup flag. |
*/ |
#define L_PARENT 64 |
typedef struct { |
vfs_triplet_t triplet; |
size_t size; |
unsigned lnkcnt; |
} vfs_lookup_res_t; |
/** |
181,9 → 202,18 |
*/ |
typedef struct { |
VFS_TRIPLET; /**< Identity of the node. */ |
unsigned refcnt; /**< Usage counter. */ |
/** |
* Usage counter. This includes, but is not limited to, all vfs_file_t |
* structures that reference this node. |
*/ |
unsigned refcnt; |
/** Number of names this node has in the file system namespace. */ |
unsigned lnkcnt; |
link_t nh_link; /**< Node hash-table link. */ |
size_t size; /**< Cached size of the file. */ |
size_t size; /**< Cached size if the node is a file. */ |
/** |
* Holding this rwlock prevents modifications of the node's contents. |
211,9 → 241,11 |
off_t pos; |
} vfs_file_t; |
extern futex_t nodes_futex; |
extern link_t fs_head; /**< List of registered file systems. */ |
extern vfs_triplet_t rootfs; /**< Root node of the root file system. */ |
extern vfs_pair_t rootfs; /**< Root file system. */ |
#define MAX_PATH_LEN (64 * 1024) |
226,7 → 258,7 |
size_t len; /**< Number of characters in this PLB entry. */ |
} plb_entry_t; |
extern atomic_t plb_futex; /**< Futex protecting plb and plb_head. */ |
extern futex_t plb_futex; /**< Futex protecting plb and plb_head. */ |
extern uint8_t *plb; /**< Path Lookup Buffer */ |
extern link_t plb_head; /**< List of active PLB entries. */ |
233,13 → 265,13 |
/** Holding this rwlock prevents changes in file system namespace. */ |
extern rwlock_t namespace_rwlock; |
extern int vfs_grab_phone(int); |
extern int vfs_grab_phone(fs_handle_t); |
extern void vfs_release_phone(int); |
extern int fs_name_to_handle(char *, bool); |
extern fs_handle_t fs_name_to_handle(char *, bool); |
extern int vfs_lookup_internal(char *, size_t, int, vfs_lookup_res_t *, |
vfs_pair_t *); |
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *, |
...); |
extern bool vfs_nodes_init(void); |
extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *); |
250,7 → 282,7 |
extern bool vfs_files_init(void); |
extern vfs_file_t *vfs_file_get(int); |
extern int vfs_fd_alloc(void); |
extern void vfs_fd_free(int); |
extern int vfs_fd_free(int); |
extern void vfs_file_addref(vfs_file_t *); |
extern void vfs_file_delref(vfs_file_t *); |
261,11 → 293,14 |
extern void vfs_register(ipc_callid_t, ipc_call_t *); |
extern void vfs_mount(ipc_callid_t, ipc_call_t *); |
extern void vfs_open(ipc_callid_t, ipc_call_t *); |
extern void vfs_close(ipc_callid_t, ipc_call_t *); |
extern void vfs_read(ipc_callid_t, ipc_call_t *); |
extern void vfs_write(ipc_callid_t, ipc_call_t *); |
extern void vfs_seek(ipc_callid_t, ipc_call_t *); |
extern void vfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void vfs_mkdir(ipc_callid_t, ipc_call_t *); |
extern void vfs_unlink(ipc_callid_t, ipc_call_t *); |
extern void vfs_rename(ipc_callid_t, ipc_call_t *); |
#endif |
/branches/network/uspace/srv/vfs/vfs_file.c |
---|
97,13 → 97,17 |
/** Release file descriptor. |
* |
* @param fd File descriptor being released. |
* |
* @return EOK on success or EBADF if fd is an invalid file |
* descriptor. |
*/ |
void vfs_fd_free(int fd) |
int vfs_fd_free(int fd) |
{ |
assert(fd < MAX_OPEN_FILES); |
assert(files[fd] != NULL); |
if ((fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) |
return EBADF; |
vfs_file_delref(files[fd]); |
files[fd] = NULL; |
return EOK; |
} |
/** Increment reference count of VFS file structure. |
130,7 → 134,7 |
{ |
if (file->refcnt-- == 1) { |
/* |
* Lost last reference to a file, need to drop our reference |
* Lost the last reference to a file, need to drop our reference |
* to the underlying VFS node. |
*/ |
vfs_node_delref(file->node); |
/branches/network/uspace/srv/vfs/Makefile |
---|
52,7 → 52,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
65,9 → 65,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/vfs/vfs_lookup.c |
---|
35,26 → 35,27 |
* @brief |
*/ |
#include "vfs.h" |
#include <ipc/ipc.h> |
#include <async.h> |
#include <errno.h> |
#include <string.h> |
#include <stdarg.h> |
#include <bool.h> |
#include <futex.h> |
#include <libadt/list.h> |
#include <atomic.h> |
#include "vfs.h" |
#include <vfs/canonify.h> |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
atomic_t plb_futex = FUTEX_INITIALIZER; |
futex_t plb_futex = FUTEX_INITIALIZER; |
link_t plb_head; /**< PLB entry ring buffer. */ |
uint8_t *plb = NULL; |
/** Perform a path lookup. |
* |
* @param path Path to be resolved; it needn't be an ASCIIZ string. |
* @param len Number of path characters pointed by path. |
* @param path Path to be resolved; it must be a NULL-terminated |
* string. |
* @param lflag Flags to be used during lookup. |
* @param result Empty structure where the lookup result will be stored. |
* Can be NULL. |
63,22 → 64,33 |
* |
* @return EOK on success or an error code from errno.h. |
*/ |
int vfs_lookup_internal(char *path, size_t len, int lflag, |
vfs_lookup_res_t *result, vfs_pair_t *altroot) |
int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result, |
vfs_pair_t *altroot, ...) |
{ |
vfs_pair_t *root; |
if (!len) |
return EINVAL; |
if (altroot) |
root = altroot; |
else |
root = (vfs_pair_t *) &rootfs; |
root = &rootfs; |
if (!root->fs_handle) |
return ENOENT; |
size_t len; |
path = canonify(path, &len); |
if (!path) |
return EINVAL; |
fs_index_t index = 0; |
if (lflag & L_LINK) { |
va_list ap; |
va_start(ap, altroot); |
index = va_arg(ap, fs_index_t); |
va_end(ap); |
} |
futex_down(&plb_futex); |
plb_entry_t entry; |
146,9 → 158,10 |
ipc_call_t answer; |
int phone = vfs_grab_phone(root->fs_handle); |
aid_t req = async_send_4(phone, VFS_LOOKUP, (ipcarg_t) first, |
aid_t req = async_send_5(phone, VFS_LOOKUP, (ipcarg_t) first, |
(ipcarg_t) (first + len - 1) % PLB_SIZE, |
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, &answer); |
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index, |
&answer); |
vfs_release_phone(phone); |
ipcarg_t rc; |
164,10 → 177,11 |
futex_up(&plb_futex); |
if ((rc == EOK) && result) { |
result->triplet.fs_handle = (int) IPC_GET_ARG1(answer); |
result->triplet.dev_handle = (int) IPC_GET_ARG2(answer); |
result->triplet.index = (int) IPC_GET_ARG3(answer); |
result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer); |
result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG2(answer); |
result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer); |
result->size = (size_t) IPC_GET_ARG4(answer); |
result->lnkcnt = (unsigned) IPC_GET_ARG5(answer); |
} |
return rc; |
/branches/network/uspace/srv/vfs/vfs.c |
---|
47,6 → 47,8 |
#include <atomic.h> |
#include "vfs.h" |
#define NAME "vfs" |
#define dprintf(...) printf(__VA_ARGS__) |
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall) |
53,8 → 55,6 |
{ |
bool keep_on_going = 1; |
printf("Connection opened from %p\n", icall->in_phone_hash); |
/* |
* The connection was opened via the IPC_CONNECT_ME_TO call. |
* This call needs to be answered. |
77,8 → 77,6 |
callid = async_get_call(&call); |
printf("Received call, method=%d\n", IPC_GET_METHOD(call)); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
keep_on_going = false; |
93,6 → 91,9 |
case VFS_OPEN: |
vfs_open(callid, &call); |
break; |
case VFS_CLOSE: |
vfs_close(callid, &call); |
break; |
case VFS_READ: |
vfs_read(callid, &call); |
break; |
108,6 → 109,12 |
case VFS_MKDIR: |
vfs_mkdir(callid, &call); |
break; |
case VFS_UNLINK: |
vfs_unlink(callid, &call); |
break; |
case VFS_RENAME: |
vfs_rename(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
122,7 → 129,7 |
{ |
ipcarg_t phonead; |
printf("VFS: HelenOS VFS server\n"); |
printf(NAME ": HelenOS VFS server\n"); |
/* |
* Initialize the list of registered file systems. |
133,7 → 140,7 |
* Initialize VFS node hash table. |
*/ |
if (!vfs_nodes_init()) { |
printf("Failed to initialize the VFS node hash table.\n"); |
printf(NAME ": Failed to initialize VFS node hash table\n"); |
return ENOMEM; |
} |
143,12 → 150,12 |
list_initialize(&plb_head); |
plb = as_get_mappable_page(PLB_SIZE); |
if (!plb) { |
printf("Cannot allocate a mappable piece of address space\n"); |
printf(NAME ": Cannot allocate a mappable piece of address space\n"); |
return ENOMEM; |
} |
if (as_area_create(plb, PLB_SIZE, AS_AREA_READ | AS_AREA_WRITE | |
AS_AREA_CACHEABLE) != plb) { |
printf("Cannot create address space area.\n"); |
printf(NAME ": Cannot create address space area\n"); |
return ENOMEM; |
} |
memset(plb, 0, PLB_SIZE); |
166,6 → 173,7 |
/* |
* Start accepting connections. |
*/ |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
return 0; |
} |
/branches/network/uspace/srv/vfs/vfs_register.c |
---|
106,14 → 106,6 |
dprintf("Operation VFS_LOOKUP not defined by the client.\n"); |
return false; |
} |
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_OPEN)] != VFS_OP_DEFINED) { |
dprintf("Operation VFS_OPEN not defined by the client.\n"); |
return false; |
} |
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_CLOSE)] != VFS_OP_DEFINED) { |
dprintf("Operation VFS_CLOSE not defined by the client.\n"); |
return false; |
} |
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_READ)] != VFS_OP_DEFINED) { |
dprintf("Operation VFS_READ not defined by the client.\n"); |
return false; |
213,6 → 205,7 |
} |
futex_down(&fs_head_futex); |
fibril_inc_sercount(); |
/* |
* Check for duplicit registrations. |
222,6 → 215,7 |
* We already register a fs like this. |
*/ |
dprintf("FS is already registered.\n"); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
free(fs_info); |
ipc_answer_0(callid, EEXISTS); |
244,6 → 238,7 |
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) { |
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call)); |
list_remove(&fs_info->fs_link); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
free(fs_info); |
ipc_answer_0(callid, EINVAL); |
262,6 → 257,7 |
if (!ipc_share_in_receive(&callid, &size)) { |
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call)); |
list_remove(&fs_info->fs_link); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
ipc_hangup(fs_info->phone); |
free(fs_info); |
276,6 → 272,7 |
if (size != PLB_SIZE) { |
dprintf("Client suggests wrong size of PFB, size = %d\n", size); |
list_remove(&fs_info->fs_link); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
ipc_hangup(fs_info->phone); |
free(fs_info); |
297,9 → 294,10 |
* In reply to the VFS_REGISTER request, we assign the client file |
* system a global file system handle. |
*/ |
fs_info->fs_handle = (int) atomic_postinc(&fs_handle_next); |
fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next); |
ipc_answer_1(rid, EOK, (ipcarg_t) fs_info->fs_handle); |
fibril_dec_sercount(); |
futex_up(&fs_head_futex); |
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n", |
313,7 → 311,7 |
* @return Phone over which a multi-call request can be safely |
* sent. Return 0 if no phone was found. |
*/ |
int vfs_grab_phone(int handle) |
int vfs_grab_phone(fs_handle_t handle) |
{ |
/* |
* For now, we don't try to be very clever and very fast. |
388,7 → 386,7 |
* |
* @return File system handle or zero if file system not found. |
*/ |
int fs_name_to_handle(char *name, bool lock) |
fs_handle_t fs_name_to_handle(char *name, bool lock) |
{ |
int handle = 0; |
/branches/network/uspace/srv/vfs/vfs_node.c |
---|
38,14 → 38,15 |
#include "vfs.h" |
#include <stdlib.h> |
#include <string.h> |
#include <atomic.h> |
#include <futex.h> |
#include <rwlock.h> |
#include <libadt/hash_table.h> |
#include <assert.h> |
#include <async.h> |
#include <errno.h> |
/** Futex protecting the VFS node hash table. */ |
atomic_t nodes_futex = FUTEX_INITIALIZER; |
futex_t nodes_futex = FUTEX_INITIALIZER; |
#define NODES_BUCKETS_LOG 8 |
#define NODES_BUCKETS (1 << NODES_BUCKETS_LOG) |
101,8 → 102,15 |
*/ |
void vfs_node_delref(vfs_node_t *node) |
{ |
bool free_vfs_node = false; |
bool free_fs_node = false; |
futex_down(&nodes_futex); |
if (node->refcnt-- == 1) { |
/* |
* We are dropping the last reference to this node. |
* Remove it from the VFS node hash table. |
*/ |
unsigned long key[] = { |
[KEY_FS_HANDLE] = node->fs_handle, |
[KEY_DEV_HANDLE] = node->dev_handle, |
109,9 → 117,27 |
[KEY_INDEX] = node->index |
}; |
hash_table_remove(&nodes, key, 3); |
free_vfs_node = true; |
if (!node->lnkcnt) |
free_fs_node = true; |
} |
futex_up(&nodes_futex); |
if (free_fs_node) { |
/* |
* The node is not visible in the file system namespace. |
* Free up its resources. |
*/ |
int phone = vfs_grab_phone(node->fs_handle); |
ipcarg_t rc; |
rc = async_req_2_0(phone, VFS_DESTROY, |
(ipcarg_t)node->dev_handle, (ipcarg_t)node->index); |
assert(rc == EOK); |
vfs_release_phone(phone); |
} |
if (free_vfs_node) |
free(node); |
} |
/** Find VFS node. |
* |
145,9 → 171,10 |
} |
memset(node, 0, sizeof(vfs_node_t)); |
node->fs_handle = result->triplet.fs_handle; |
node->dev_handle = result->triplet.fs_handle; |
node->dev_handle = result->triplet.dev_handle; |
node->index = result->triplet.index; |
node->size = result->size; |
node->lnkcnt = result->lnkcnt; |
link_initialize(&node->nh_link); |
rwlock_initialize(&node->contents_rwlock); |
hash_table_insert(&nodes, key, &node->nh_link); |
156,6 → 183,7 |
} |
assert(node->size == result->size); |
assert(node->lnkcnt == result->lnkcnt); |
_vfs_node_addref(node); |
futex_up(&nodes_futex); |
194,8 → 222,6 |
void nodes_remove_callback(link_t *item) |
{ |
vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link); |
free(node); |
} |
/** |
/branches/network/uspace/srv/loader/elf_load.c |
---|
0,0 → 1,479 |
/* |
* Copyright (c) 2006 Sergey Bondari |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Userspace ELF loader. |
* |
* This module allows loading ELF binaries (both executables and |
* shared objects) from VFS. The current implementation allocates |
* anonymous memory, fills it with segment data and then adjusts |
* the memory areas' flags to the final value. In the future, |
* the segments will be mapped directly from the file. |
*/ |
#include <stdio.h> |
#include <sys/types.h> |
#include <align.h> |
#include <assert.h> |
#include <as.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <smc.h> |
#include <loader/pcb.h> |
#include "elf.h" |
#include "elf_load.h" |
#include "arch.h" |
static char *error_codes[] = { |
"no error", |
"invalid image", |
"address space error", |
"incompatible image", |
"unsupported image type", |
"irrecoverable error" |
}; |
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias); |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry); |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry); |
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry); |
/** Read until the buffer is read in its entirety. */ |
static int my_read(int fd, char *buf, size_t len) |
{ |
int cnt = 0; |
do { |
buf += cnt; |
len -= cnt; |
cnt = read(fd, buf, len); |
} while ((cnt > 0) && ((len - cnt) > 0)); |
return cnt; |
} |
/** Load ELF binary from a file. |
* |
* Load an ELF binary from the specified file. If the file is |
* an executable program, it is loaded unbiased. If it is a shared |
* object, it is loaded with the bias @a so_bias. Some information |
* extracted from the binary is stored in a elf_info_t structure |
* pointed to by @a info. |
* |
* @param file_name Path to the ELF file. |
* @param so_bias Bias to use if the file is a shared object. |
* @param info Pointer to a structure for storing information |
* extracted from the binary. |
* |
* @return EOK on success or negative error code. |
*/ |
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info) |
{ |
elf_ld_t elf; |
int fd; |
int rc; |
// printf("open and read '%s'...\n", file_name); |
fd = open(file_name, O_RDONLY); |
if (fd < 0) { |
printf("failed opening file\n"); |
return -1; |
} |
elf.fd = fd; |
elf.info = info; |
rc = elf_load(&elf, so_bias); |
close(fd); |
return rc; |
} |
/** Run an ELF executable. |
* |
* Transfers control to the entry point of an ELF executable loaded |
* earlier with elf_load_file(). This function does not return. |
* |
* @param info Info structure filled earlier by elf_load_file() |
*/ |
void elf_run(elf_info_t *info, pcb_t *pcb) |
{ |
program_run(info->entry, pcb); |
/* not reached */ |
} |
/** Create the program control block (PCB). |
* |
* Fills the program control block @a pcb with information from |
* @a info. |
* |
* @param info Program info structure |
* @return EOK on success or negative error code |
*/ |
void elf_create_pcb(elf_info_t *info, pcb_t *pcb) |
{ |
pcb->entry = info->entry; |
pcb->dynamic = info->dynamic; |
} |
/** Load an ELF binary. |
* |
* The @a elf structure contains the loader state, including |
* an open file, from which the binary will be loaded, |
* a pointer to the @c info structure etc. |
* |
* @param elf Pointer to loader state buffer. |
* @param so_bias Bias to use if the file is a shared object. |
* @return EE_OK on success or EE_xx error code. |
*/ |
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias) |
{ |
elf_header_t header_buf; |
elf_header_t *header = &header_buf; |
int i, rc; |
rc = my_read(elf->fd, header, sizeof(elf_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
elf->header = header; |
// printf("ELF-load:"); |
/* Identify ELF */ |
if (header->e_ident[EI_MAG0] != ELFMAG0 || |
header->e_ident[EI_MAG1] != ELFMAG1 || |
header->e_ident[EI_MAG2] != ELFMAG2 || |
header->e_ident[EI_MAG3] != ELFMAG3) { |
printf("invalid header\n"); |
return EE_INVALID; |
} |
/* Identify ELF compatibility */ |
if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING || |
header->e_machine != ELF_MACHINE || |
header->e_ident[EI_VERSION] != EV_CURRENT || |
header->e_version != EV_CURRENT || |
header->e_ident[EI_CLASS] != ELF_CLASS) { |
printf("incompatible data/version/class\n"); |
return EE_INCOMPATIBLE; |
} |
if (header->e_phentsize != sizeof(elf_segment_header_t)) { |
printf("e_phentsize:%d != %d\n", header->e_phentsize, |
sizeof(elf_segment_header_t)); |
return EE_INCOMPATIBLE; |
} |
if (header->e_shentsize != sizeof(elf_section_header_t)) { |
printf("e_shentsize:%d != %d\n", header->e_shentsize, |
sizeof(elf_section_header_t)); |
return EE_INCOMPATIBLE; |
} |
/* Check if the object type is supported. */ |
if (header->e_type != ET_EXEC && header->e_type != ET_DYN) { |
printf("Object type %d is not supported\n", header->e_type); |
return EE_UNSUPPORTED; |
} |
/* Shared objects can be loaded with a bias */ |
// printf("Object type: %d\n", header->e_type); |
if (header->e_type == ET_DYN) |
elf->bias = so_bias; |
else |
elf->bias = 0; |
// printf("Bias set to 0x%x\n", elf->bias); |
elf->info->interp = NULL; |
elf->info->dynamic = NULL; |
// printf("parse segments\n"); |
/* Walk through all segment headers and process them. */ |
for (i = 0; i < header->e_phnum; i++) { |
elf_segment_header_t segment_hdr; |
/* Seek to start of segment header */ |
lseek(elf->fd, header->e_phoff |
+ i * sizeof(elf_segment_header_t), SEEK_SET); |
rc = my_read(elf->fd, &segment_hdr, |
sizeof(elf_segment_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
rc = segment_header(elf, &segment_hdr); |
if (rc != EE_OK) |
return rc; |
} |
// printf("parse sections\n"); |
/* Inspect all section headers and proccess them. */ |
for (i = 0; i < header->e_shnum; i++) { |
elf_section_header_t section_hdr; |
/* Seek to start of section header */ |
lseek(elf->fd, header->e_shoff |
+ i * sizeof(elf_section_header_t), SEEK_SET); |
rc = my_read(elf->fd, §ion_hdr, |
sizeof(elf_section_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
rc = section_header(elf, §ion_hdr); |
if (rc != EE_OK) |
return rc; |
} |
elf->info->entry = |
(entry_point_t)((uint8_t *)header->e_entry + elf->bias); |
// printf("done\n"); |
return EE_OK; |
} |
/** Print error message according to error code. |
* |
* @param rc Return code returned by elf_load(). |
* |
* @return NULL terminated description of error. |
*/ |
char *elf_error(unsigned int rc) |
{ |
assert(rc < sizeof(error_codes) / sizeof(char *)); |
return error_codes[rc]; |
} |
/** Process segment header. |
* |
* @param entry Segment header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
switch (entry->p_type) { |
case PT_NULL: |
case PT_PHDR: |
break; |
case PT_LOAD: |
return load_segment(elf, entry); |
break; |
case PT_INTERP: |
/* Assume silently interp == "/rtld.so" */ |
elf->info->interp = "/rtld.so"; |
break; |
case PT_DYNAMIC: |
case PT_SHLIB: |
case PT_NOTE: |
case PT_LOPROC: |
case PT_HIPROC: |
default: |
printf("segment p_type %d unknown\n", entry->p_type); |
return EE_UNSUPPORTED; |
break; |
} |
return EE_OK; |
} |
/** Load segment described by program header entry. |
* |
* @param elf Loader state. |
* @param entry Program header entry describing segment to be loaded. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
void *a; |
int flags = 0; |
uintptr_t bias; |
uintptr_t base; |
size_t mem_sz; |
int rc; |
// printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr, |
// entry->p_memsz); |
bias = elf->bias; |
if (entry->p_align > 1) { |
if ((entry->p_offset % entry->p_align) != |
(entry->p_vaddr % entry->p_align)) { |
printf("align check 1 failed offset%%align=%d, " |
"vaddr%%align=%d\n", |
entry->p_offset % entry->p_align, |
entry->p_vaddr % entry->p_align |
); |
return EE_INVALID; |
} |
} |
/* Final flags that will be set for the memory area */ |
if (entry->p_flags & PF_X) |
flags |= AS_AREA_EXEC; |
if (entry->p_flags & PF_W) |
flags |= AS_AREA_WRITE; |
if (entry->p_flags & PF_R) |
flags |= AS_AREA_READ; |
flags |= AS_AREA_CACHEABLE; |
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE); |
mem_sz = entry->p_memsz + (entry->p_vaddr - base); |
// printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias, |
// entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE)); |
/* |
* For the course of loading, the area needs to be readable |
* and writeable. |
*/ |
a = as_area_create((uint8_t *)base + bias, mem_sz, |
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE); |
if (a == (void *)(-1)) { |
printf("memory mapping failed\n"); |
return EE_MEMORY; |
} |
// printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n", |
// entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a); |
/* |
* Load segment data |
*/ |
// printf("seek to %d\n", entry->p_offset); |
rc = lseek(elf->fd, entry->p_offset, SEEK_SET); |
if (rc < 0) { |
printf("seek error\n"); |
return EE_INVALID; |
} |
// printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias); |
/* rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/ |
/* Long reads are not possible yet. Load segment picewise */ |
unsigned left, now; |
uint8_t *dp; |
left = entry->p_filesz; |
dp = (uint8_t *)(entry->p_vaddr + bias); |
while (left > 0) { |
now = 16384; |
if (now > left) now = left; |
// printf("read %d...", now); |
rc = my_read(elf->fd, dp, now); |
// printf("->%d\n", rc); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
left -= now; |
dp += now; |
} |
// printf("set area flags to %d\n", flags); |
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags); |
if (rc != 0) { |
printf("failed to set memory area flags\n"); |
return EE_MEMORY; |
} |
if (flags & AS_AREA_EXEC) { |
/* Enforce SMC coherence for the segment */ |
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz)) |
return EE_MEMORY; |
} |
return EE_OK; |
} |
/** Process section header. |
* |
* @param elf Loader state. |
* @param entry Segment header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry) |
{ |
switch (entry->sh_type) { |
case SHT_PROGBITS: |
if (entry->sh_flags & SHF_TLS) { |
/* .tdata */ |
} |
break; |
case SHT_NOBITS: |
if (entry->sh_flags & SHF_TLS) { |
/* .tbss */ |
} |
break; |
case SHT_DYNAMIC: |
/* Record pointer to dynamic section into info structure */ |
elf->info->dynamic = |
(void *)((uint8_t *)entry->sh_addr + elf->bias); |
printf("dynamic section found at 0x%x\n", |
(uintptr_t)elf->info->dynamic); |
break; |
default: |
break; |
} |
return EE_OK; |
} |
/** @} |
*/ |
/branches/network/uspace/srv/loader/interp.s |
---|
0,0 → 1,7 |
# |
# Provide a string to be included in a special DT_INTERP header, even though |
# this is a statically-linked executable. This will mark the binary as |
# the program loader. |
# |
.section .interp , "" |
.string "kernel" |
/branches/network/uspace/srv/loader/include/arch.h |
---|
0,0 → 1,45 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** @file |
* @brief |
*/ |
#ifndef LOADER_ARCH_H_ |
#define LOADER_ARCH_H_ |
void program_run(void *entry_point, void *pcb); |
#endif |
/** |
* @} |
*/ |
/branches/network/uspace/srv/loader/include/elf_load.h |
---|
0,0 → 1,83 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
* @brief ELF loader structures and public functions. |
*/ |
#ifndef ELF_LOAD_H_ |
#define ELF_LOAD_H_ |
#include <arch/elf.h> |
#include <sys/types.h> |
#include <loader/pcb.h> |
#include "elf.h" |
/** |
* Some data extracted from the headers are stored here |
*/ |
typedef struct { |
/** Entry point */ |
entry_point_t entry; |
/** ELF interpreter name or NULL if statically-linked */ |
char *interp; |
/** Pointer to the dynamic section */ |
void *dynamic; |
} elf_info_t; |
/** |
* Holds information about an ELF binary being loaded. |
*/ |
typedef struct { |
/** Filedescriptor of the file from which we are loading */ |
int fd; |
/** Difference between run-time addresses and link-time addresses */ |
uintptr_t bias; |
/** A copy of the ELF file header */ |
elf_header_t *header; |
/** Store extracted info here */ |
elf_info_t *info; |
} elf_ld_t; |
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info); |
void elf_run(elf_info_t *info, pcb_t *pcb); |
void elf_create_pcb(elf_info_t *info, pcb_t *pcb); |
#endif |
/** @} |
*/ |
/branches/network/uspace/srv/loader/include/elf.h |
---|
0,0 → 1,344 |
/* |
* Copyright (c) 2006 Sergey Bondari |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef ELF_H_ |
#define ELF_H_ |
#include <arch/elf.h> |
#include <sys/types.h> |
/** |
* current ELF version |
*/ |
#define EV_CURRENT 1 |
/** |
* ELF types |
*/ |
#define ET_NONE 0 /* No type */ |
#define ET_REL 1 /* Relocatable file */ |
#define ET_EXEC 2 /* Executable */ |
#define ET_DYN 3 /* Shared object */ |
#define ET_CORE 4 /* Core */ |
#define ET_LOPROC 0xff00 /* Processor specific */ |
#define ET_HIPROC 0xffff /* Processor specific */ |
/** |
* ELF machine types |
*/ |
#define EM_NO 0 /* No machine */ |
#define EM_SPARC 2 /* SPARC */ |
#define EM_386 3 /* i386 */ |
#define EM_MIPS 8 /* MIPS RS3000 */ |
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 LE */ |
#define EM_PPC 20 /* PPC32 */ |
#define EM_PPC64 21 /* PPC64 */ |
#define EM_ARM 40 /* ARM */ |
#define EM_SPARCV9 43 /* SPARC64 */ |
#define EM_IA_64 50 /* IA-64 */ |
#define EM_X86_64 62 /* AMD64/EMT64 */ |
/** |
* ELF identification indexes |
*/ |
#define EI_MAG0 0 |
#define EI_MAG1 1 |
#define EI_MAG2 2 |
#define EI_MAG3 3 |
#define EI_CLASS 4 /* File class */ |
#define EI_DATA 5 /* Data encoding */ |
#define EI_VERSION 6 /* File version */ |
#define EI_OSABI 7 |
#define EI_ABIVERSION 8 |
#define EI_PAD 9 /* Start of padding bytes */ |
#define EI_NIDENT 16 /* ELF identification table size */ |
/** |
* ELF magic number |
*/ |
#define ELFMAG0 0x7f |
#define ELFMAG1 'E' |
#define ELFMAG2 'L' |
#define ELFMAG3 'F' |
/** |
* ELF file classes |
*/ |
#define ELFCLASSNONE 0 |
#define ELFCLASS32 1 |
#define ELFCLASS64 2 |
/** |
* ELF data encoding types |
*/ |
#define ELFDATANONE 0 |
#define ELFDATA2LSB 1 /* Least significant byte first (little endian) */ |
#define ELFDATA2MSB 2 /* Most signigicant byte first (big endian) */ |
/** |
* ELF error return codes |
*/ |
#define EE_OK 0 /* No error */ |
#define EE_INVALID 1 /* Invalid ELF image */ |
#define EE_MEMORY 2 /* Cannot allocate address space */ |
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */ |
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */ |
#define EE_IRRECOVERABLE 5 |
/** |
* ELF section types |
*/ |
#define SHT_NULL 0 |
#define SHT_PROGBITS 1 |
#define SHT_SYMTAB 2 |
#define SHT_STRTAB 3 |
#define SHT_RELA 4 |
#define SHT_HASH 5 |
#define SHT_DYNAMIC 6 |
#define SHT_NOTE 7 |
#define SHT_NOBITS 8 |
#define SHT_REL 9 |
#define SHT_SHLIB 10 |
#define SHT_DYNSYM 11 |
#define SHT_LOOS 0x60000000 |
#define SHT_HIOS 0x6fffffff |
#define SHT_LOPROC 0x70000000 |
#define SHT_HIPROC 0x7fffffff |
#define SHT_LOUSER 0x80000000 |
#define SHT_HIUSER 0xffffffff |
/** |
* ELF section flags |
*/ |
#define SHF_WRITE 0x1 |
#define SHF_ALLOC 0x2 |
#define SHF_EXECINSTR 0x4 |
#define SHF_TLS 0x400 |
#define SHF_MASKPROC 0xf0000000 |
/** |
* Symbol binding |
*/ |
#define STB_LOCAL 0 |
#define STB_GLOBAL 1 |
#define STB_WEAK 2 |
#define STB_LOPROC 13 |
#define STB_HIPROC 15 |
/** |
* Symbol types |
*/ |
#define STT_NOTYPE 0 |
#define STT_OBJECT 1 |
#define STT_FUNC 2 |
#define STT_SECTION 3 |
#define STT_FILE 4 |
#define STT_LOPROC 13 |
#define STT_HIPROC 15 |
/** |
* Program segment types |
*/ |
#define PT_NULL 0 |
#define PT_LOAD 1 |
#define PT_DYNAMIC 2 |
#define PT_INTERP 3 |
#define PT_NOTE 4 |
#define PT_SHLIB 5 |
#define PT_PHDR 6 |
#define PT_LOPROC 0x70000000 |
#define PT_HIPROC 0x7fffffff |
/** |
* Program segment attributes. |
*/ |
#define PF_X 1 |
#define PF_W 2 |
#define PF_R 4 |
/** |
* ELF data types |
* |
* These types are found to be identical in both 32-bit and 64-bit |
* ELF object file specifications. They are the only types used |
* in ELF header. |
*/ |
typedef uint64_t elf_xword; |
typedef int64_t elf_sxword; |
typedef uint32_t elf_word; |
typedef int32_t elf_sword; |
typedef uint16_t elf_half; |
/** |
* 32-bit ELF data types. |
* |
* These types are specific for 32-bit format. |
*/ |
typedef uint32_t elf32_addr; |
typedef uint32_t elf32_off; |
/** |
* 64-bit ELF data types. |
* |
* These types are specific for 64-bit format. |
*/ |
typedef uint64_t elf64_addr; |
typedef uint64_t elf64_off; |
/** ELF header */ |
struct elf32_header { |
uint8_t e_ident[EI_NIDENT]; |
elf_half e_type; |
elf_half e_machine; |
elf_word e_version; |
elf32_addr e_entry; |
elf32_off e_phoff; |
elf32_off e_shoff; |
elf_word e_flags; |
elf_half e_ehsize; |
elf_half e_phentsize; |
elf_half e_phnum; |
elf_half e_shentsize; |
elf_half e_shnum; |
elf_half e_shstrndx; |
}; |
struct elf64_header { |
uint8_t e_ident[EI_NIDENT]; |
elf_half e_type; |
elf_half e_machine; |
elf_word e_version; |
elf64_addr e_entry; |
elf64_off e_phoff; |
elf64_off e_shoff; |
elf_word e_flags; |
elf_half e_ehsize; |
elf_half e_phentsize; |
elf_half e_phnum; |
elf_half e_shentsize; |
elf_half e_shnum; |
elf_half e_shstrndx; |
}; |
/* |
* ELF segment header. |
* Segments headers are also known as program headers. |
*/ |
struct elf32_segment_header { |
elf_word p_type; |
elf32_off p_offset; |
elf32_addr p_vaddr; |
elf32_addr p_paddr; |
elf_word p_filesz; |
elf_word p_memsz; |
elf_word p_flags; |
elf_word p_align; |
}; |
struct elf64_segment_header { |
elf_word p_type; |
elf_word p_flags; |
elf64_off p_offset; |
elf64_addr p_vaddr; |
elf64_addr p_paddr; |
elf_xword p_filesz; |
elf_xword p_memsz; |
elf_xword p_align; |
}; |
/* |
* ELF section header |
*/ |
struct elf32_section_header { |
elf_word sh_name; |
elf_word sh_type; |
elf_word sh_flags; |
elf32_addr sh_addr; |
elf32_off sh_offset; |
elf_word sh_size; |
elf_word sh_link; |
elf_word sh_info; |
elf_word sh_addralign; |
elf_word sh_entsize; |
}; |
struct elf64_section_header { |
elf_word sh_name; |
elf_word sh_type; |
elf_xword sh_flags; |
elf64_addr sh_addr; |
elf64_off sh_offset; |
elf_xword sh_size; |
elf_word sh_link; |
elf_word sh_info; |
elf_xword sh_addralign; |
elf_xword sh_entsize; |
}; |
/* |
* ELF symbol table entry |
*/ |
struct elf32_symbol { |
elf_word st_name; |
elf32_addr st_value; |
elf_word st_size; |
uint8_t st_info; |
uint8_t st_other; |
elf_half st_shndx; |
}; |
struct elf64_symbol { |
elf_word st_name; |
uint8_t st_info; |
uint8_t st_other; |
elf_half st_shndx; |
elf64_addr st_value; |
elf_xword st_size; |
}; |
#ifdef __32_BITS__ |
typedef struct elf32_header elf_header_t; |
typedef struct elf32_segment_header elf_segment_header_t; |
typedef struct elf32_section_header elf_section_header_t; |
typedef struct elf32_symbol elf_symbol_t; |
#endif |
#ifdef __64_BITS__ |
typedef struct elf64_header elf_header_t; |
typedef struct elf64_segment_header elf_segment_header_t; |
typedef struct elf64_section_header elf_section_header_t; |
typedef struct elf64_symbol elf_symbol_t; |
#endif |
extern char *elf_error(unsigned int rc); |
#endif |
/** @} |
*/ |
/branches/network/uspace/srv/loader/main.c |
---|
0,0 → 1,332 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup loader |
* @brief Loads and runs programs from VFS. |
* @{ |
*/ |
/** |
* @file |
* @brief Loads and runs programs from VFS. |
* |
* The program loader is a special init binary. Its image is used |
* to create a new task upon a @c task_spawn syscall. The syscall |
* returns the id of a phone connected to the newly created task. |
* |
* The caller uses this phone to send the pathname and various other |
* information to the loader. This is normally done by the C library |
* and completely hidden from applications. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/loader.h> |
#include <loader/pcb.h> |
#include <errno.h> |
#include <async.h> |
#include <as.h> |
#include <elf.h> |
#include <elf_load.h> |
/** |
* Bias used for loading the dynamic linker. This will be soon replaced |
* by automatic placement. |
*/ |
#define RTLD_BIAS 0x80000 |
/** Pathname of the file that will be loaded */ |
static char *pathname = NULL; |
/** The Program control block */ |
static pcb_t pcb; |
/** Number of arguments */ |
static int argc = 0; |
/** Argument vector */ |
static char **argv = NULL; |
/** Buffer holding all arguments */ |
static char *arg_buf = NULL; |
/** Receive a call setting pathname of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t len; |
char *name_buf; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
name_buf = malloc(len + 1); |
if (!name_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, name_buf, len); |
ipc_answer_0(rid, EOK); |
if (pathname != NULL) { |
free(pathname); |
pathname = NULL; |
} |
name_buf[len] = '\0'; |
pathname = name_buf; |
} |
/** Receive a call setting arguments of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t buf_len, arg_len; |
char *p; |
int n; |
if (!ipc_data_write_receive(&callid, &buf_len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (arg_buf != NULL) { |
free(arg_buf); |
arg_buf = NULL; |
} |
if (argv != NULL) { |
free(argv); |
argv = NULL; |
} |
arg_buf = malloc(buf_len + 1); |
if (!arg_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, arg_buf, buf_len); |
ipc_answer_0(rid, EOK); |
arg_buf[buf_len] = '\0'; |
/* |
* Count number of arguments |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
arg_len = strlen(p); |
p = p + arg_len + 1; |
++n; |
} |
/* Allocate argv */ |
argv = malloc((n + 1) * sizeof(char *)); |
if (argv == NULL) { |
free(arg_buf); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* Fill argv with argument pointers |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
argv[n] = p; |
arg_len = strlen(p); |
p = p + arg_len + 1; |
++n; |
} |
argc = n; |
argv[n] = NULL; |
} |
/** Load and run the previously selected program. |
* |
* @param rid |
* @param request |
* @return 0 on success, !0 on error. |
*/ |
static int loader_run(ipc_callid_t rid, ipc_call_t *request) |
{ |
int rc; |
elf_info_t prog_info; |
elf_info_t interp_info; |
// printf("Load program '%s'\n", pathname); |
rc = elf_load_file(pathname, 0, &prog_info); |
if (rc < 0) { |
printf("failed to load program\n"); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
// printf("Create PCB\n"); |
elf_create_pcb(&prog_info, &pcb); |
pcb.argc = argc; |
pcb.argv = argv; |
if (prog_info.interp == NULL) { |
/* Statically linked program */ |
// printf("Run statically linked program\n"); |
// printf("entry point: 0x%llx\n", prog_info.entry); |
ipc_answer_0(rid, EOK); |
close_console(); |
elf_run(&prog_info, &pcb); |
return 0; |
} |
printf("Load dynamic linker '%s'\n", prog_info.interp); |
rc = elf_load_file("/rtld.so", RTLD_BIAS, &interp_info); |
if (rc < 0) { |
printf("failed to load dynamic linker\n"); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
/* |
* Provide dynamic linker with some useful data |
*/ |
pcb.rtld_dynamic = interp_info.dynamic; |
pcb.rtld_bias = RTLD_BIAS; |
printf("run dynamic linker\n"); |
printf("entry point: 0x%llx\n", interp_info.entry); |
close_console(); |
ipc_answer_0(rid, EOK); |
elf_run(&interp_info, &pcb); |
/* Not reached */ |
return 0; |
} |
/** Handle loader connection. |
* |
* Receive and carry out commands (of which the last one should be |
* to execute the loaded program). |
*/ |
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
/* Ignore parameters, the connection is already open */ |
(void)iid; (void)icall; |
while (1) { |
callid = async_get_call(&call); |
// printf("received call from phone %d, method=%d\n", |
// call.in_phone_hash, IPC_GET_METHOD(call)); |
switch (IPC_GET_METHOD(call)) { |
case LOADER_SET_PATHNAME: |
loader_set_pathname(callid, &call); |
continue; |
case LOADER_SET_ARGS: |
loader_set_args(callid, &call); |
case LOADER_RUN: |
loader_run(callid, &call); |
exit(0); |
continue; |
default: |
retval = ENOENT; |
break; |
} |
if ((callid & IPC_CALLID_NOTIFICATION) == 0 && |
IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) { |
printf("responding EINVAL to method %d\n", |
IPC_GET_METHOD(call)); |
ipc_answer_0(callid, EINVAL); |
} |
} |
} |
/** Program loader main function. |
*/ |
int main(int argc, char *argv[]) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t phone_hash; |
/* The first call only communicates the incoming phone hash */ |
callid = ipc_wait_for_call(&call); |
if (IPC_GET_METHOD(call) != LOADER_HELLO) { |
if (IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) |
ipc_answer_0(callid, EINVAL); |
return 1; |
} |
ipc_answer_0(callid, EOK); |
phone_hash = call.in_phone_hash; |
/* |
* Up until now async must not be used as it couldn't |
* handle incoming requests. (Which means e.g. printf() |
* cannot be used) |
*/ |
async_new_connection(phone_hash, 0, NULL, loader_connection); |
async_manager(); |
/* not reached */ |
return 0; |
} |
/** @} |
*/ |
/branches/network/uspace/srv/loader/Makefile |
---|
0,0 → 1,94 |
# |
# Copyright (c) 2005 Martin Decky |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
include ../../../version |
include ../../Makefile.config |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include arch/$(ARCH)/Makefile.inc |
CFLAGS += -Iinclude |
LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
ifdef REVISION |
DEFS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
## Sources |
# |
OUTPUT = loader |
GENERIC_SOURCES = \ |
main.c \ |
elf_load.c \ |
interp.s |
SOURCES := $(GENERIC_SOURCES) $(ARCH_SOURCES) |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(ARCH)/_link.ld Makefile.depend |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) arch/$(ARCH)/_link.ld |
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in |
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/network/uspace/srv/loader/arch/sparc64/_link.ld.in |
---|
0,0 → 1,59 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70004000 + SIZEOF_HEADERS; |
.init : { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
.data : { |
*(.data); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/uspace/srv/loader/arch/sparc64/sparc64.s |
---|
0,0 → 1,42 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %o0 contains entry_point |
# %o1 contains pcb |
# |
# Jump to a program entry point |
program_run: |
# Pass pcb pointer to entry point in %o1. As it is already |
# there, no action is needed. |
call %o0 |
nop |
# fixme: use branch instead of call |
/branches/network/uspace/srv/loader/arch/sparc64/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/sparc64.s |
/branches/network/uspace/srv/loader/arch/ia64/_link.ld.in |
---|
0,0 → 1,66 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x00084000 + SIZEOF_HEADERS; |
.init : { |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
LONG(0); |
*(.init); |
} : text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
.data : { |
*(.opd); |
*(.data .data.*); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(.scommon); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/uspace/srv/loader/arch/ia64/ia64.s |
---|
0,0 → 1,43 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# in0 (r32) contains entry_point |
# in1 (r33) contains pcb |
# |
# Jump to a program entry point |
program_run: |
# Pass pcb to the entry point in r2 |
mov b6 = r32 |
mov r2 = r33 ;; |
br b6 ;; |
/branches/network/uspace/srv/loader/arch/ia64/Makefile.inc |
---|
0,0 → 1,31 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ia64.s |
AFLAGS += -xexplicit |
/branches/network/uspace/srv/loader/arch/arm32/_link.ld.in |
---|
0,0 → 1,59 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} : interp |
. = 0x70001000; |
.init ALIGN(0x1000): SUBALIGN(0x1000) { |
*(.init); |
} : text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.opd); |
*(.data .data.*); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(.scommon); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/uspace/srv/loader/arch/arm32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/arm32.s |
/branches/network/uspace/srv/loader/arch/arm32/arm32.s |
---|
0,0 → 1,39 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# r0 contains entry_point |
# r1 contains pcb |
# |
# Jump to a program entry point |
program_run: |
# pcb is passed to the entry point in r1 (where it already is) |
mov r15, r0 |
/branches/network/uspace/srv/loader/arch/ppc32/_link.ld.in |
---|
0,0 → 1,57 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/uspace/srv/loader/arch/ppc32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ppc32.s |
/branches/network/uspace/srv/loader/arch/ppc32/ppc32.s |
---|
0,0 → 1,40 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %r3 contains entry_point |
# %r4 contains pcb |
# |
# Jump to a program entry point |
program_run: |
mtctr %r3 |
mr %r3, %r4 # Pass pcb to the entry point in %r3 |
bctr |
/branches/network/uspace/srv/loader/arch/amd64/_link.ld.in |
---|
0,0 → 1,52 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} : interp |
/* . = 0x0000700000001000;*/ |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/uspace/srv/loader/arch/amd64/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/amd64.s |
/branches/network/uspace/srv/loader/arch/amd64/amd64.s |
---|
0,0 → 1,43 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %rdi contains entry_point |
# %rsi contains pcb |
# |
# Jump to a program entry point |
program_run: |
# pcb must be passed in %rdi, use %rdx as a scratch register |
mov %rdi, %rdx |
mov %rsi, %rdi |
# jump to entry point |
jmp %rdx |
/branches/network/uspace/srv/loader/arch/mips32/_link.ld.in |
---|
0,0 → 1,66 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70004000; |
.init ALIGN(0x4000) : SUBALIGN(0x4000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data : { |
*(.data); |
*(.data.rel*); |
} :data |
.got : { |
_gp = .; |
*(.got); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.sbss : { |
*(.scommon); |
*(.sbss); |
} |
.bss : { |
*(.bss); |
*(COMMON); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/uspace/srv/loader/arch/mips32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/mips32.s |
/branches/network/uspace/srv/loader/arch/mips32/mips32.s |
---|
0,0 → 1,49 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.section .text |
.global program_run |
.set noreorder |
## void program_run(void *entry_point, void *pcb); |
# |
# $a0 (=$4) contains entry_point |
# $a1 (=$5) contains pcb |
# |
# Jump to a program entry point |
.ent program_run |
program_run: |
# tmp := entry_point |
move $25, $a0 |
# Pass pcb to the entry point in $a0 |
move $a0, $a1 |
jr $25 |
nop |
.end |
/branches/network/uspace/srv/loader/arch/ia32/_link.ld.in |
---|
0,0 → 1,55 |
/* |
* The difference from _link.ld.in for regular statically-linked apps |
* is the base address and the special interp section. |
*/ |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FILEHDR PHDRS FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/uspace/srv/loader/arch/ia32/ia32.s |
---|
0,0 → 1,49 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# Jump to a program entry point |
program_run: |
# Use standard ia32 prologue not to confuse anybody |
push %ebp |
movl %esp, %ebp |
# %eax := entry_point |
movl 0x8(%ebp), %eax |
# %ebx := pcb |
# pcb is passed to the entry point int %ebx |
mov 0xc(%ebp), %ebx |
# Save a tiny bit of stack space |
pop %ebp |
jmp %eax |
/branches/network/uspace/srv/loader/arch/ia32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(ARCH)/ia32.s |
/branches/network/uspace/srv/rd/rd.c |
---|
51,8 → 51,12 |
#include <align.h> |
#include <async.h> |
#include <futex.h> |
#include <stdio.h> |
#include <ipc/devmap.h> |
#include "rd.h" |
#define NAME "rd" |
/** Pointer to the ramdisk's image. */ |
static void *rd_addr; |
/** Size of the ramdisk. */ |
77,45 → 81,24 |
ipc_call_t call; |
int retval; |
void *fs_va = NULL; |
ipcarg_t offset; |
off_t offset; |
size_t block_size; |
size_t maxblock_size; |
/* |
* We allocate VA for communication per connection. |
* This allows us to potentionally have more clients and work |
* concurrently. |
*/ |
fs_va = as_get_mappable_page(ALIGN_UP(BLOCK_SIZE, PAGE_SIZE)); |
if (!fs_va) { |
/* |
* Hang up the phone if we cannot proceed any further. |
* This is the answer to the call that opened the connection. |
*/ |
ipc_answer_0(iid, EHANGUP); |
return; |
} else { |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
* Return supported block size as ARG1. |
*/ |
ipc_answer_1(iid, EOK, BLOCK_SIZE); |
} |
ipc_answer_0(iid, EOK); |
/* |
* Now we wait for the client to send us its communication as_area. |
*/ |
size_t size; |
if (ipc_share_out_receive(&callid, &size, NULL)) { |
if (size >= BLOCK_SIZE) { |
/* |
* The client sends an as_area that can absorb the whole |
* block. |
*/ |
int flags; |
if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) { |
fs_va = as_get_mappable_page(maxblock_size); |
if (fs_va) { |
(void) ipc_share_out_finalize(callid, fs_va); |
} else { |
/* |
* The client offered as_area too small. |
* Close the connection. |
*/ |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
141,8 → 124,16 |
return; |
case RD_READ_BLOCK: |
offset = IPC_GET_ARG1(call); |
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) { |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Reading past the end of the device. |
*/ |
retval = ELIMIT; |
149,14 → 140,22 |
break; |
} |
futex_down(&rd_futex); |
memcpy(fs_va, rd_addr + offset, BLOCK_SIZE); |
memcpy(fs_va, rd_addr + offset * block_size, block_size); |
futex_up(&rd_futex); |
retval = EOK; |
break; |
case RD_WRITE_BLOCK: |
offset = IPC_GET_ARG1(call); |
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) { |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Writing past the end of the device. |
*/ |
retval = ELIMIT; |
163,7 → 162,7 |
break; |
} |
futex_up(&rd_futex); |
memcpy(rd_addr + offset, fs_va, BLOCK_SIZE); |
memcpy(rd_addr + offset * block_size, fs_va, block_size); |
futex_down(&rd_futex); |
retval = EOK; |
break; |
181,39 → 180,115 |
} |
} |
static int driver_register(char *name) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
int phone; |
ipcarg_t callback_phonehash; |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
while (phone < 0) { |
usleep(10000); |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_DRIVER, 0); |
} |
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(phone, (char *) name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return -1; |
} |
async_set_client_connection(rd_connection); |
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash); |
async_wait_for(req, &retval); |
return phone; |
} |
static int device_register(int driver_phone, char *name, int *handle) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(driver_phone, (char *) name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (EOK == retval) { |
if (NULL != handle) |
*handle = (int) IPC_GET_ARG1(answer); |
} |
return retval; |
} |
/** Prepare the ramdisk image for operation. */ |
static bool rd_init(void) |
{ |
int retval, flags; |
rd_size = sysinfo_value("rd.size"); |
void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical"); |
if (rd_size == 0) |
if (rd_size == 0) { |
printf(NAME ": No RAM disk found\n"); |
return false; |
} |
rd_addr = as_get_mappable_page(rd_size); |
flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE; |
retval = physmem_map(rd_ph_addr, rd_addr, |
int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE; |
int retval = physmem_map(rd_ph_addr, rd_addr, |
ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags); |
if (retval < 0) |
if (retval < 0) { |
printf(NAME ": Error mapping RAM disk\n"); |
return false; |
} |
printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size); |
int driver_phone = driver_register(NAME); |
if (driver_phone < 0) { |
printf(NAME ": Unable to register driver\n"); |
return false; |
} |
int dev_handle; |
if (EOK != device_register(driver_phone, "initrd", &dev_handle)) { |
ipc_hangup(driver_phone); |
printf(NAME ": Unable to register device\n"); |
return false; |
} |
return true; |
} |
int main(int argc, char **argv) |
{ |
if (rd_init()) { |
ipcarg_t phonead; |
printf(NAME ": HelenOS RAM disk server\n"); |
async_set_client_connection(rd_connection); |
/* Register service at nameserver */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_RD, 0, 0, &phonead) != 0) |
if (!rd_init()) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
220,9 → 295,6 |
return 0; |
} |
return -1; |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/rd/rd.h |
---|
43,8 → 43,6 |
#ifndef RD_RD_H_ |
#define RD_RD_H_ |
#define BLOCK_SIZE 1024 /**< Working block size */ |
#define RD_BASE 1024 |
#define RD_READ_BLOCK (RD_BASE + 1) /**< Method for reading block. */ |
#define RD_WRITE_BLOCK (RD_BASE + 2) /**< Method for writing block. */ |
/branches/network/uspace/srv/rd/Makefile |
---|
46,7 → 46,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
57,11 → 57,13 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/fb/sysio.h |
---|
File deleted |
/branches/network/uspace/srv/fb/sysio.c |
---|
File deleted |
/branches/network/uspace/srv/fb/msim.c |
---|
0,0 → 1,227 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @defgroup msimfb MSIM text console |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <ipc/fb.h> |
#include <ipc/ipc.h> |
#include <libc.h> |
#include <errno.h> |
#include <string.h> |
#include <libc.h> |
#include <stdio.h> |
#include <ipc/fb.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <align.h> |
#include <ddi.h> |
#include "msim.h" |
#define WIDTH 80 |
#define HEIGHT 25 |
#define MAX_CONTROL 20 |
/* Allow only 1 connection */ |
static int client_connected = 0; |
static char *virt_addr; |
static void msim_putc(const char c) |
{ |
*virt_addr = c; |
} |
static void msim_puts(char *str) |
{ |
while (*str) |
*virt_addr = *(str++); |
} |
static void msim_clrscr(void) |
{ |
msim_puts("\033[2J"); |
} |
static void msim_goto(const unsigned int row, const unsigned int col) |
{ |
if ((row > HEIGHT) || (col > WIDTH)) |
return; |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1); |
msim_puts(control); |
} |
static void msim_set_style(const unsigned int mode) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%um", mode); |
msim_puts(control); |
} |
static void msim_cursor_disable(void) |
{ |
msim_puts("\033[?25l"); |
} |
static void msim_cursor_enable(void) |
{ |
msim_puts("\033[?25h"); |
} |
static void msim_scroll(int i) |
{ |
if (i > 0) { |
msim_goto(HEIGHT - 1, 0); |
while (i--) |
msim_puts("\033D"); |
} else if (i < 0) { |
msim_goto(0, 0); |
while (i++) |
msim_puts("\033M"); |
} |
} |
static void msim_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
ipc_callid_t callid; |
ipc_call_t call; |
char c; |
int lastcol = 0; |
int lastrow = 0; |
int newcol; |
int newrow; |
int fgcolor; |
int bgcolor; |
int i; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
client_connected = 1; |
ipc_answer_0(iid, EOK); |
/* Clear the terminal, set scrolling region |
to 0 - 25 lines */ |
msim_clrscr(); |
msim_goto(0, 0); |
msim_puts("\033[0;25r"); |
while (true) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
client_connected = 0; |
ipc_answer_0(callid, EOK); |
return; |
case FB_PUTCHAR: |
c = IPC_GET_ARG1(call); |
newrow = IPC_GET_ARG2(call); |
newcol = IPC_GET_ARG3(call); |
if ((lastcol != newcol) || (lastrow != newrow)) |
msim_goto(newrow, newcol); |
lastcol = newcol + 1; |
lastrow = newrow; |
msim_putc(c); |
retval = 0; |
break; |
case FB_CURSOR_GOTO: |
newrow = IPC_GET_ARG1(call); |
newcol = IPC_GET_ARG2(call); |
msim_goto(newrow, newcol); |
lastrow = newrow; |
lastcol = newcol; |
retval = 0; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, HEIGHT, WIDTH); |
continue; |
case FB_CLEAR: |
msim_clrscr(); |
retval = 0; |
break; |
case FB_SET_STYLE: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
if (fgcolor < bgcolor) |
msim_set_style(0); |
else |
msim_set_style(7); |
retval = 0; |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if ((i > HEIGHT) || (i < -HEIGHT)) { |
retval = EINVAL; |
break; |
} |
msim_scroll(i); |
msim_goto(lastrow, lastcol); |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
msim_cursor_enable(); |
else |
msim_cursor_disable(); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
ipc_answer_0(callid, retval); |
} |
} |
int msim_init(void) |
{ |
void *phys_addr = (void *) sysinfo_value("fb.address.physical"); |
virt_addr = (char *) as_get_mappable_page(1); |
physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE); |
async_set_client_connection(msim_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/network/uspace/srv/fb/main.c |
---|
33,12 → 33,15 |
#include <as.h> |
#include <align.h> |
#include <errno.h> |
#include <stdio.h> |
#include "fb.h" |
#include "sysio.h" |
#include "ega.h" |
#include "msim.h" |
#include "main.h" |
#define NAME "fb" |
void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area) |
{ |
void *dest; |
53,28 → 56,37 |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Framebuffer service\n"); |
ipcarg_t phonead; |
int initialized = 0; |
bool initialized = false; |
#ifdef FB_ENABLED |
if (sysinfo_value("fb.kind") == 1) { |
if (fb_init() == 0) |
initialized = 1; |
initialized = true; |
} |
#endif |
#ifdef EGA_ENABLED |
if (!initialized && sysinfo_value("fb.kind") == 2) { |
if ((!initialized) && (sysinfo_value("fb.kind") == 2)) { |
if (ega_init() == 0) |
initialized = 1; |
initialized = true; |
} |
#endif |
#ifdef MSIM_ENABLED |
if ((!initialized) && (sysinfo_value("fb.kind") == 3)) { |
if (msim_init() == 0) |
initialized = true; |
} |
#endif |
if (!initialized) |
sysio_init(); |
return -1; |
if (ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
/branches/network/uspace/srv/fb/msim.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup msimfb |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_MSIM_H_ |
#define FB_MSIM_H_ |
extern int msim_init(void); |
#endif |
/** @} |
*/ |
/branches/network/uspace/srv/fb/Makefile |
---|
43,7 → 43,6 |
OUTPUT = fb |
SOURCES = \ |
main.c \ |
sysio.c \ |
ppm.c |
ifneq ($(ARCH), ia64) |
51,7 → 50,6 |
font-8x16.c |
CFLAGS += -DFB_ENABLED |
endif |
ifeq ($(ARCH), ia32) |
SOURCES += ega.c |
CFLAGS += -DEGA_ENABLED |
61,7 → 59,8 |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(ARCH), mips32) |
CFLAGS += -DFB_INVERT_ENDIAN |
SOURCES += msim.c |
CFLAGS += -DMSIM_ENABLED -DFB_INVERT_ENDIAN |
endif |
CFLAGS += -D$(ARCH) |
71,7 → 70,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
82,11 → 81,13 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/kbd/Makefile |
---|
72,11 → 72,9 |
genarch/src/kbd.c |
endif |
ifeq ($(ARCH), arm32) |
ifeq ($(MACHINE), gxemul_testarm) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/kbd_gxemul.c |
endif |
endif |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
85,7 → 83,7 |
.PHONY: all clean depend disasm links |
all: links $(OUTPUT) disasm |
all: links $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
100,11 → 98,13 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/kbd/generic/kbd.c |
---|
50,7 → 50,7 |
#include <async.h> |
#include <keys.h> |
#define NAME "KBD" |
#define NAME "kbd" |
int cons_connected = 0; |
int phone2cons = -1; |
121,6 → 121,8 |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS Keyboard service\n"); |
ipcarg_t phonead; |
/* Initialize arch dependent parts */ |
136,6 → 138,7 |
if (ipc_connect_to_me(PHONE_NS, SERVICE_KEYBOARD, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
145,4 → 148,3 |
/** |
* @} |
*/ |
/branches/network/uspace/srv/ns/Makefile |
---|
46,7 → 46,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
57,11 → 57,13 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/ns/ns.c |
---|
50,7 → 50,7 |
#include <ddi.h> |
#include <as.h> |
#define NAME "NS" |
#define NAME "ns" |
#define NS_HASH_TABLE_CHAINS 20 |
104,6 → 104,8 |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS IPC Naming Service\n"); |
ipc_call_t call; |
ipc_callid_t callid; |
111,9 → 113,11 |
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, |
&ns_hash_table_ops)) { |
printf(NAME ": No memory available\n"); |
return ENOMEM; |
} |
printf(NAME ": Accepting connections\n"); |
while (1) { |
callid = ipc_wait_for_call(&call); |
switch (IPC_GET_METHOD(call)) { |
156,6 → 160,9 |
ipc_answer_0(callid, retval); |
} |
} |
/* Not reached */ |
return 0; |
} |
/** Register service. |
/branches/network/uspace/srv/console/Makefile |
---|
59,7 → 59,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
70,11 → 70,13 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/console/console.c |
---|
46,12 → 46,13 |
#include <libadt/fifo.h> |
#include <screenbuffer.h> |
#include <sys/mman.h> |
#include <stdio.h> |
#include "gcons.h" |
#define MAX_KEYREQUESTS_BUFFERED 32 |
#define NAME "CONSOLE" |
#define NAME "console" |
/** Index of currently used virtual console. |
*/ |
474,6 → 475,8 |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Console service\n"); |
ipcarg_t phonehash; |
int kbd_phone; |
int i; |
550,10 → 553,11 |
connections[active_console].screenbuffer.is_cursor_visible); |
/* Register at NS */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) { |
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) |
return -1; |
} |
// FIXME: avoid connectiong to itself, keep using klog |
// printf(NAME ": Accepting connections\n"); |
async_manager(); |
return 0; |
/branches/network/uspace/srv/devmap/devmap.h |
---|
File deleted |
/branches/network/uspace/srv/devmap/Makefile |
---|
50,7 → 50,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
63,9 → 63,11 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/uspace/srv/devmap/devmap.c |
---|
44,8 → 44,9 |
#include <futex.h> |
#include <stdlib.h> |
#include <string.h> |
#include <ipc/devmap.h> |
#include "devmap.h" |
#define NAME "devmap" |
LIST_INITIALIZE(devices_list); |
112,10 → 113,8 |
item = item->next; |
} |
if (item == &devices_list) { |
printf("DEVMAP: no device named %s.\n", name); |
if (item == &devices_list) |
return NULL; |
} |
device = list_get_instance(item, devmap_device_t, devices); |
return device; |
203,7 → 202,6 |
* Get driver name |
*/ |
if (!ipc_data_write_receive(&callid, &name_size)) { |
printf("Unexpected request.\n"); |
free(driver); |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
211,8 → 209,6 |
} |
if (name_size > DEVMAP_NAME_MAXLEN) { |
printf("Too logn name: %u: maximum is %u.\n", name_size, |
DEVMAP_NAME_MAXLEN); |
free(driver); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
223,7 → 219,6 |
* Allocate buffer for device name. |
*/ |
if (NULL == (driver->name = (char *)malloc(name_size + 1))) { |
printf("Cannot allocate space for driver name.\n"); |
free(driver); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
234,7 → 229,6 |
* Send confirmation to sender and get data into buffer. |
*/ |
if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) { |
printf("Cannot read driver name.\n"); |
free(driver->name); |
free(driver); |
ipc_answer_0(iid, EREFUSED); |
243,8 → 237,6 |
driver->name[name_size] = 0; |
printf("Read driver name: '%s'.\n", driver->name); |
/* Initialize futex for list of devices owned by this driver */ |
futex_initialize(&(driver->devices_futex), 1); |
259,8 → 251,6 |
callid = async_get_call(&call); |
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) { |
printf("DEVMAP: Unexpected method: %u.\n", |
IPC_GET_METHOD(call)); |
ipc_answer_0(callid, ENOTSUP); |
free(driver->name); |
288,10 → 278,8 |
futex_up(&drivers_list_futex); |
ipc_answer_0(iid, EOK); |
printf("Driver registered.\n"); |
*odriver = driver; |
return; |
} |
/** Unregister device driver, unregister all its devices and free driver |
301,12 → 289,9 |
{ |
devmap_device_t *device; |
if (NULL == driver) { |
printf("Error: driver == NULL.\n"); |
if (NULL == driver) |
return EEXISTS; |
} |
printf("Unregister driver '%s'.\n", driver->name); |
futex_down(&drivers_list_futex); |
ipc_hangup(driver->phone); |
322,7 → 307,6 |
while (!list_empty(&(driver->devices))) { |
device = list_get_instance(driver->devices.next, |
devmap_device_t, driver_devices); |
printf("Unregister device '%s'.\n", device->name); |
devmap_device_unregister_core(device); |
} |
337,8 → 321,6 |
free(driver); |
printf("Driver unregistered.\n"); |
return EOK; |
} |
354,7 → 336,6 |
devmap_device_t *device; |
if (NULL == driver) { |
printf("Invalid driver registration.\n"); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
362,7 → 343,6 |
/* Create new device entry */ |
if (NULL == |
(device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) { |
printf("Cannot allocate new device.\n"); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
370,13 → 350,11 |
/* Get device name */ |
if (!ipc_data_write_receive(&callid, &size)) { |
free(device); |
printf("Cannot read device name.\n"); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (size > DEVMAP_NAME_MAXLEN) { |
printf("Too long device name: %u.\n", size); |
free(device); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
387,7 → 365,6 |
device->name = (char *)malloc(size + 1); |
if (NULL == device->name) { |
printf("Cannot read device name.\n"); |
free(device); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
404,7 → 381,7 |
/* Check that device with such name is not already registered */ |
if (NULL != devmap_device_find_name(device->name)) { |
printf("Device '%s' already registered.\n", device->name); |
printf(NAME ": Device '%s' already registered\n", device->name); |
futex_up(&devices_list_futex); |
free(device->name); |
free(device); |
428,10 → 405,7 |
futex_up(&device->driver->devices_futex); |
futex_up(&devices_list_futex); |
printf("Device '%s' registered.\n", device->name); |
ipc_answer_1(iid, EOK, device->handle); |
return; |
} |
/** |
461,8 → 435,6 |
dev = devmap_device_find_handle(handle); |
if (NULL == dev) { |
printf("DEVMAP: No registered device with handle %d.\n", |
handle); |
ipc_answer_0(callid, ENOENT); |
return; |
} |
469,7 → 441,6 |
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle), |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
return; |
} |
/** Find handle for device instance identified by name. |
484,7 → 455,6 |
ipc_callid_t callid; |
ipcarg_t retval; |
/* |
* Wait for incoming message with device name (but do not |
* read the name itself until the buffer is allocated). |
528,16 → 498,11 |
* Device was not found. |
*/ |
if (NULL == dev) { |
printf("DEVMAP: device %s has not been registered.\n", name); |
ipc_answer_0(iid, ENOENT); |
return; |
} |
printf("DEVMAP: device %s has handler %d.\n", name, dev->handle); |
ipc_answer_1(iid, EOK, dev->handle); |
return; |
} |
/** Find name of device identified by id and send it to caller. |
574,15 → 539,12 |
} |
*/ |
/* TODO: send name in response */ |
return; |
} |
/** Handle connection with device driver. |
* |
*/ |
static void |
devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
593,10 → 555,8 |
devmap_driver_register(&driver); |
if (NULL == driver) { |
printf("DEVMAP: driver registration failed.\n"); |
if (NULL == driver) |
return; |
} |
while (cont) { |
callid = async_get_call(&call); |
603,13 → 563,10 |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("DEVMAP: connection hung up.\n"); |
cont = false; |
continue; /* Exit thread */ |
case DEVMAP_DRIVER_UNREGISTER: |
printf("DEVMAP: unregister driver.\n"); |
if (NULL == driver) { |
printf("DEVMAP: driver was not registered!\n"); |
ipc_answer_0(callid, ENOENT); |
} else { |
ipc_answer_0(callid, EOK); |
649,8 → 606,7 |
/** Handle connection with device client. |
* |
*/ |
static void |
devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
663,7 → 619,6 |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("DEVMAP: connection hung up.\n"); |
cont = false; |
continue; /* Exit thread */ |
686,12 → 641,8 |
/** Function for handling connections to devmap |
* |
*/ |
static void |
devmap_connection(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
printf("DEVMAP: new connection.\n"); |
/* Select interface */ |
switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) { |
case DEVMAP_DRIVER: |
702,20 → 653,13 |
break; |
case DEVMAP_CONNECT_TO_DEVICE: |
/* Connect client to selected device */ |
printf("DEVMAP: connect to device %d.\n", |
IPC_GET_ARG2(*icall)); |
devmap_forward(iid, icall); |
break; |
default: |
ipc_answer_0(iid, ENOENT); /* No such interface */ |
printf("DEVMAP: Unknown interface %u.\n", |
(ipcarg_t)(IPC_GET_ARG1(*icall))); |
} |
/* Cleanup */ |
printf("DEVMAP: connection closed.\n"); |
return; |
} |
/** |
723,12 → 667,12 |
*/ |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Device Mapper\n"); |
ipcarg_t phonead; |
printf("DEVMAP: HelenOS device mapper.\n"); |
if (devmap_init() != 0) { |
printf("Error while initializing DEVMAP service.\n"); |
printf(NAME ": Error while initializing service\n"); |
return -1; |
} |
739,6 → 683,7 |
if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
747,4 → 692,3 |
/** |
* @} |
*/ |
/branches/network/uspace/srv/pci/update-ids |
---|
13,4 → 13,3 |
"" |
}; |
EOF |
/branches/network/uspace/Makefile |
---|
37,6 → 37,7 |
lib/softint \ |
lib/softfloat \ |
srv/ns \ |
srv/loader \ |
srv/fb \ |
srv/kbd \ |
srv/console \ |
48,7 → 49,8 |
app/tetris \ |
app/tester \ |
app/klog \ |
app/init |
app/init \ |
app/bdsh |
ifeq ($(ARCH), amd64) |
DIRS += srv/pci |
/branches/network/uspace/dist/etc/inittab |
---|
--- uspace/uspace.config (revision 3384) |
+++ uspace/uspace.config (revision 3386) |
@@ -1,3 +1,31 @@ |
+# |
+# Copyright (c) 2006 Ondrej Palkovsky |
+# 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. |
+# |
+ |
## General configuration directives |
# Architecture |
/branches/network/contrib/toolchain/toolchain.ppc32.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="ppc" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/toolchain/toolchain.amd64.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="amd64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/toolchain/toolchain.ppc64.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="ppc64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/toolchain/toolchain.ia32.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="i686" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-pc-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/toolchain/toolchain.mipsel32.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="mipsel" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/toolchain/toolchain.ia64.sh |
---|
15,16 → 15,18 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
INCLUDES="ia64-pc-gnu-linux_includes.tar.bz2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
GCC_CPP="gcc-g++-${GCC_VERSION}.tar.bz2" |
INCLUDES_SOURCE="http://download.decky.cz/" |
BINUTILS_SOURCE="ftp://ftp.gnu.org/gnu/binutils/" |
GCC_SOURCE="ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/" |
31,7 → 33,7 |
PLATFORM="ia64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-pc-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
INCLUDESDIR="${WORKDIR}/include" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
39,10 → 41,6 |
echo ">>> Downloading tarballs" |
if [ ! -f "${INCLUDES}" ]; then |
wget -c "${INCLUDES_SOURCE}${INCLUDES}" |
check_error $? "Error downloading includes." |
fi |
if [ ! -f "${BINUTILS}" ]; then |
wget -c "${BINUTILS_SOURCE}${BINUTILS}" |
check_error $? "Error downloading binutils." |
75,8 → 73,6 |
fi |
echo ">>> Unpacking tarballs" |
tar -xvjf "${INCLUDES}" |
check_error $? "Error unpacking includes." |
tar -xvzf "${BINUTILS}" |
check_error $? "Error unpacking binutils." |
tar -xvjf "${GCC_CORE}" |
97,7 → 93,7 |
echo ">>> Compiling and installing GCC" |
cd "${OBJDIR}" |
check_error $? "Change directory failed." |
"${GCCDIR}/configure" "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,objc,c++,obj-c++ --disable-multilib --disable-libgcj "--with-headers=${INCLUDESDIR}" --disable-shared |
"${GCCDIR}/configure" "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,objc,c++,obj-c++ --disable-multilib --disable-libgcj --disable-shared |
check_error $? "Error configuring GCC." |
PATH="${PATH}:${PREFIX}/bin" make all-gcc install-gcc |
check_error $? "Error compiling/installing GCC." |
/branches/network/contrib/toolchain/toolchain.arm32.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="arm" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/toolchain/toolchain.mipseb32.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="mips" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-sgi-irix5" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/toolchain/toolchain.sparc64.sh |
---|
15,8 → 15,12 |
fi |
} |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.3" |
GCC_VERSION="4.3.1" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="sparc64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/network/contrib/conf/SPMIPS.simics |
---|
File deleted |
/branches/network/contrib/conf/HelenOS.amd64.simics |
---|
File deleted |
/branches/network/contrib/conf/spmips.conf |
---|
File deleted |
/branches/network/contrib/conf/HelenOS.sparc64.simics |
---|
File deleted |
/branches/network/contrib/conf/bootindy |
---|
File deleted |
/branches/network/contrib/conf/simics.conf |
---|
File deleted |
/branches/network/contrib/conf/dot.bochsrc |
---|
File deleted |
/branches/network/contrib/conf/vmware.conf |
---|
File deleted |
/branches/network/contrib/conf/HelenOS.ppc32.simics |
---|
File deleted |
/branches/network/contrib/conf/msim.conf |
---|
2,12 → 2,14 |
# MSIM configuration script |
# |
add dcpu mips1 |
add dcpu cpu0 |
add rwm mainmem 0x00000000 8M |
add rwm mainmem 0x00000000 |
mainmem generic 16M |
mainmem load "/dev/zero" |
add rom bootmem 0x1fc00000 2048k |
add rom bootmem 0x1fc00000 |
bootmem generic 4096k |
bootmem load "image.boot" |
add dprinter printer 0x10000000 |
/branches/network/boot/arch/ia64/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/network/boot/arch/ia64/loader/Makefile |
---|
32,8 → 32,14 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-ia64-little |
BFD_ARCH = ia64 |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ia64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
41,6 → 47,7 |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
GEFI_PREXIX = |
endif |
ifeq ($(COMPILER),icc_native) |
57,6 → 64,7 |
LD = $(TOOLCHAIN_DIR)/$(TARGET)-ld |
OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy |
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump |
GEFI_PREFIX = $(TOOLCHAIN_DIR)/$(TARGET)- |
endif |
#-mno-pic means do not use gp + imm22 to address data |
75,6 → 83,7 |
../../../generic/printf.c \ |
../../../generic/string.c \ |
../../../genarch/balloc.c \ |
_components.c \ |
asm.S \ |
boot.S |
81,6 → 90,7 |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
93,7 → 103,6 |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
103,25 → 112,25 |
-include Makefile.depend |
hello.efi: image.boot |
make -C gefi/HelenOS |
make -C gefi/HelenOS PREFIX=$(GEFI_PREFIX) |
cp gefi/HelenOS/hello.efi ../../../../ |
cp gefi/HelenOS/hello.efi /boot/efi/ |
cp gefi/HelenOS/image.bin /boot/efi/ |
# cp gefi/HelenOS/hello.efi /boot/efi/ |
cp gefi/HelenOS/image.bin ../../../../ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -Map boot.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
$(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 |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot boot.disasm Makefile.depend |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot image.map image.disasm Makefile.depend ../../../../image.bin ../../../../hello.efi |
make -C gefi clean |
make -C gefi/HelenOS clean |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) _link.ld.in |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 16384 "unsigned long" $(COMPONENTS) |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
130,4 → 139,4 |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
disasm: image.boot |
$(OBJDUMP) -d image.boot > boot.disasm |
$(OBJDUMP) -d image.boot > image.disasm |
/branches/network/boot/arch/ia64/loader/gefi/apps/Makefile |
---|
28,7 → 28,7 |
CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o |
LDSCRIPT = ../gnuefi/elf_$(ARCH)_efi.lds |
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS) |
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) |
LOADLIBES = -lefi -lgnuefi |
FORMAT = efi-app-$(ARCH) |
TARGETS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi printenv.efi t7.efi |
/branches/network/boot/arch/ia64/loader/gefi/HelenOS/Makefile |
---|
20,7 → 20,7 |
# Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
# 02111-1307, USA. |
# |
prefix=$(PREFIX) |
include ../Make.defaults |
CDIR=$(TOPDIR)/.. |
LINUX_HEADERS = /usr/src/sys/build |
28,15 → 28,15 |
CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o |
LDSCRIPT = ../gnuefi/elf_$(ARCH)_efi.lds |
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS) |
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) |
LOADLIBES = -lefi -lgnuefi |
FORMAT = efi-app-$(ARCH) |
all: hello.efi |
all: gefi hello.efi |
clean: |
rm -f *.efi *~ *.o *.so |
rm -f *.efi *~ *.o *.so *.map *.disass *.bin |
.PHONY: install |
43,7 → 43,7 |
hello.efi: hello.so |
$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ |
-j .rela -j .reloc --target=$(FORMAT) hello.so hello.efi |
objdump -d hello.efi > hello.disass |
$(OBJDUMP) -d hello.efi > hello.disass |
hello.so: hello.o image.o |
$(LD) $(LDFLAGS) -Map hello.map hello.o -o hello.so $(LOADLIBES) |
52,8 → 52,9 |
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c hello.c -o hello.o |
image.o: ../../image.boot |
objcopy -O binary ../../image.boot image.bin |
objcopy -I binary -O elf64-ia64-little -B ia64 image.bin image.o |
$(OBJCOPY) -O binary ../../image.boot image.bin |
$(OBJCOPY) -I binary -O elf64-ia64-little -B ia64 image.bin image.o |
gefi: |
make -C .. prefix=$(PREFIX) |
/branches/network/boot/arch/ia64/loader/gefi/Make.defaults |
---|
38,8 → 38,7 |
GCC_VERSION=$(shell $(CROSS_COMPILE)$(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') |
ifeq ($(ARCH),ia64) |
prefix = |
# prefix = |
CC = $(prefix)gcc |
AS = $(prefix)as |
LD = $(prefix)ld |
46,6 → 45,7 |
AR = $(prefix)ar |
RANLIB = $(prefix)ranlib |
OBJCOPY = $(prefix)objcopy |
OBJDUMP = $(prefix)objdump |
ifneq ($(GCC_VERSION),2) |
54,22 → 54,3 |
CFLAGS += -mfixed-range=f32-f127 |
else |
ifeq ($(ARCH),ia32) |
# |
# gcc-3.x is required |
# |
prefix = |
ifneq ($(GCC_VERSION),2) |
CC = $(prefix)gcc |
else |
CC = $(prefix)gcc3 #must have gcc 3.x |
endif |
AS = $(prefix)as |
LD = $(prefix)ld |
AR = $(prefix)ar |
RANLIB = $(prefix)ranlib |
OBJCOPY = $(prefix)objcopy |
endif |
endif |
/branches/network/boot/arch/ia64/loader/_link.ld.in |
---|
0,0 → 1,26 |
OUTPUT_FORMAT("elf64-ia64-little") |
ENTRY(start) |
SECTIONS { |
.boot 0x4400000: AT (0x4400000) { |
*(BOOTSTRAP); |
[[COMPONENTS]] |
. = ALIGN (16384); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
_got = . ; |
*(.got .got.*); |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); |
} |
/DISCARD/ : { |
*(.comment); |
*(.note*); |
} |
} |
/branches/network/boot/arch/arm32/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/network/boot/arch/arm32/loader/Makefile |
---|
27,21 → 27,29 |
# |
include ../../../../version |
include ../../../../Makefile.config |
include ../../../Makefile.config |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-littlearm |
BFD_ARCH = arm |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = /usr/local/arm/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin |
ifeq ($(COMPILER),native) |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
else |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
LD = $(TOOLCHAIN_DIR)/$(TARGET)-ld |
68,28 → 76,36 |
boot.S \ |
asm.S \ |
mm.c \ |
print/gxemul.c \ |
_components.c \ |
../../../generic/printf.c \ |
../../../genarch/division.c |
ifeq ($(MACHINE), gxemul_testarm) |
SOURCES += print/gxemul.c |
endif |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_TASKS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/tetris/tetris |
$(USPACEDIR)/app/bdsh/bdsh |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
100,17 → 116,31 |
-include Makefile.depend |
image.boot: depend _components.h _link.ld $(OBJECTS) $(COMPONENT_OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(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 |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
-for task in $(RD_TASKS) ; do \ |
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \ |
done |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) _link.ld.in |
for task in $(RD_TASKS) ; do \ |
cp $$task $(USPACEDIR)/dist/sbin/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 4096 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS) ./initrd.img |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/boot/arch/arm32/loader/asm.S |
---|
35,7 → 35,8 |
add r3, r1, #3 |
bic r3, r3, #3 |
cmp r1, r3 |
stmdb sp!, {r4, lr} |
stmdb sp!, {r4, r5, lr} |
mov r5, r0 |
beq 4f |
1: |
cmp r2, #0 |
48,8 → 49,8 |
cmp ip, r2 |
bne 2b |
3: |
mov r0, r1 |
ldmia sp!, {r4, pc} |
mov r0, r5 |
ldmia sp!, {r4, r5, pc} |
4: |
add r3, r0, #3 |
bic r3, r3, #3 |
/branches/network/boot/arch/arm32/loader/boot.S |
---|
39,6 → 39,11 |
b bootstrap |
jump_to_kernel: |
# |
# TODO |
# Make sure that the I-cache, D-cache and memory are mutually coherent |
# before passing control to the copied code. |
# |
bx r0 |
/branches/network/boot/arch/arm32/loader/_link.ld.in |
---|
0,0 → 1,24 |
OUTPUT_FORMAT("elf32-littlearm") |
ENTRY(start) |
SECTIONS { |
.boot 0x0: AT (0) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.reginfo); |
. = 0x4000; |
*(PT); /* page table placed at 0x4000 */ |
[[COMPONENTS]] |
} |
} |
/branches/network/boot/arch/arm32/loader/main.c |
---|
76,9 → 76,10 |
version_print(); |
component_t components[COMPONENTS]; |
bootinfo_t bootinfo; |
init_components(components); |
bootinfo_t bootinfo; |
printf("\nMemory statistics\n"); |
printf(" kernel entry point at %L\n", KERNEL_VIRTUAL_ADDRESS); |
printf(" %L: boot info structure\n", &bootinfo); |
/branches/network/boot/arch/ppc32/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/network/boot/arch/ppc32/loader/Makefile |
---|
32,8 → 32,14 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-powerpc |
BFD_ARCH = powerpc:common |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
43,14 → 49,6 |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),icc_native) |
CC = icc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
72,6 → 70,7 |
SOURCES = \ |
main.c \ |
ofwarch.c \ |
_components.c \ |
../../../genarch/ofw.c \ |
../../../generic/printf.c \ |
asm.S \ |
80,17 → 79,28 |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_TASKS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/bdsh/bdsh |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
101,17 → 111,31 |
-include Makefile.depend |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(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 |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
-for task in $(RD_TASKS) ; do \ |
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \ |
done |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_TASKS) _link.ld.in |
for task in $(RD_TASKS) ; do \ |
cp $$task $(USPACEDIR)/dist/sbin/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 4096 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS) ./initrd.img |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/boot/arch/ppc32/loader/_link.ld.in |
---|
0,0 → 1,21 |
OUTPUT_FORMAT("elf32-powerpc") |
OUTPUT_ARCH(powerpc:common) |
ENTRY(start) |
SECTIONS { |
.boot 0x10000000: AT (0) { |
*(BOOTSTRAP); |
*(REALMODE); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
[[COMPONENTS]] |
} |
} |
/branches/network/boot/arch/ppc32/loader/main.c |
---|
96,10 → 96,10 |
{ |
version_print(); |
init_components(); |
component_t components[COMPONENTS]; |
init_components(components); |
unsigned int i; |
for (i = 0; i < COMPONENTS; i++) |
check_align(components[i].start, components[i].name); |
/branches/network/boot/arch/ppc64/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/network/boot/arch/ppc64/loader/Makefile |
---|
32,8 → 32,14 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-powerpc |
BFD_ARCH = powerpc:common64 |
TARGET = ppc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
43,14 → 49,6 |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),icc_native) |
CC = icc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
72,6 → 70,7 |
SOURCES = \ |
main.c \ |
ofwarch.c \ |
_components.c \ |
../../../genarch/ofw.c \ |
../../../generic/printf.c \ |
asm.S \ |
108,10 → 107,10 |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) _link.ld.in |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned long" $(COMPONENTS) |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/boot/arch/ppc64/loader/_link.ld.in |
---|
0,0 → 1,27 |
OUTPUT_FORMAT("elf64-powerpc") |
OUTPUT_ARCH(powerpc:common64) |
ENTRY(start) |
SECTIONS { |
.boot 0x0000000010000000: AT (0) { |
*(BOOTSTRAP); |
*(REALMODE); |
*(.text); |
*(.toc); |
*(.opd); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
[[COMPONENTS]] |
} |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/network/boot/arch/ppc64/loader/main.c |
---|
96,7 → 96,8 |
{ |
version_print(); |
init_components(); |
component_t components[COMPONENTS]; |
init_components(components); |
unsigned int i; |
/branches/network/boot/arch/mips32/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/network/boot/arch/mips32/loader/Makefile |
---|
32,8 → 32,20 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
ifeq ($(IMAGE),binary) |
LD_IN = binary |
endif |
ifeq ($(IMAGE),ecoff) |
LD_IN = ecoff |
endif |
BFD_NAME = elf32-tradlittlemips |
BFD_ARCH = mips |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = /usr/local/mipsel/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
43,14 → 55,6 |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),icc_native) |
CC = icc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
72,6 → 76,7 |
SOURCES = \ |
main.c \ |
msim.c \ |
_components.c \ |
../../../generic/printf.c \ |
asm.S \ |
boot.S |
79,18 → 84,30 |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_TASKS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/bdsh/bdsh \ |
$(USPACEDIR)/app/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
100,18 → 117,35 |
-include Makefile.depend |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(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 |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
-for task in $(RD_TASKS) ; do \ |
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \ |
done |
-rm -f _components.h _components.c _link.ld _link.ld.in $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) _link.ld.in |
for task in $(RD_TASKS) ; do \ |
cp $$task $(USPACEDIR)/dist/sbin/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 16384 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 16384 "unsigned int" $(COMPONENTS) ./initrd.img |
_link.ld.in: _link.ld.in.$(LD_IN) |
cp $< $@ |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/network/boot/arch/mips32/loader/asm.S |
---|
48,6 → 48,7 |
and $v0,$v0,$v1 |
beq $a1,$v0,3f |
move $t0,$a0 |
move $t2,$a0 # save dst |
0: |
beq $a2,$zero,2f |
63,7 → 64,7 |
2: |
jr $ra |
move $v0,$a1 |
move $v0,$t2 |
3: |
addiu $v0,$a0,3 |
103,9 → 104,13 |
sb $a0,0($v1) |
jr $ra |
move $v0,$a1 |
move $v0,$t2 |
jump_to_kernel: |
# .word 0x39 |
# |
# TODO |
# Make sure that the I-cache, D-cache and memory are mutually coherent |
# before passing control to the copied code. |
# |
j $a0 |
nop |
/branches/network/boot/arch/mips32/loader/_link.ld.in.ecoff |
---|
0,0 → 1,21 |
OUTPUT_FORMAT("ecoff-littlemips") |
ENTRY(start) |
SECTIONS { |
.boot 0xbfc00000: AT (0) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.reginfo); |
[[COMPONENTS]] |
} |
} |
/branches/network/boot/arch/mips32/loader/_link.ld.in.binary |
---|
0,0 → 1,21 |
OUTPUT_FORMAT("binary") |
ENTRY(start) |
SECTIONS { |
.boot 0xbfc00000: AT (0) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.reginfo); |
[[COMPONENTS]] |
} |
} |
/branches/network/boot/arch/mips32/loader/main.c |
---|
59,9 → 59,10 |
version_print(); |
component_t components[COMPONENTS]; |
bootinfo_t bootinfo; |
init_components(components); |
bootinfo_t bootinfo; |
printf("\nMemory statistics\n"); |
printf(" kernel entry point at %L\n", KERNEL_VIRTUAL_ADDRESS); |
printf(" %L: boot info structure\n", &bootinfo); |
/branches/network/boot/arch/sparc64/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/network/boot/arch/sparc64/loader/Makefile |
---|
32,8 → 32,14 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-sparc |
BFD_ARCH = sparc |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/sparc64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
43,14 → 49,6 |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),icc_native) |
CC = icc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
71,6 → 69,7 |
SOURCES = \ |
main.c \ |
_components.c \ |
../../../generic/printf.c \ |
../../../generic/string.c \ |
../../../genarch/balloc.c \ |
83,16 → 82,27 |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_TASKS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/bdsh/bdsh \ |
$(USPACEDIR)/app/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
104,17 → 114,31 |
-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 $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@ |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot boot.disasm Makefile.depend |
-for task in $(RD_TASKS) ; do \ |
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \ |
done |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot image.map image.disasm Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_TASKS) _link.ld.in |
for task in $(RD_TASKS) ; do \ |
cp $$task $(USPACEDIR)/dist/sbin/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.sh $(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) ./initrd.img |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
123,4 → 147,4 |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
disasm: image.boot |
$(OBJDUMP) -d image.boot > boot.disasm |
$(OBJDUMP) -d image.boot > image.disasm |
/branches/network/boot/arch/sparc64/loader/asm.S |
---|
30,6 → 30,9 |
#include <stack.h> |
#include <register.h> |
.register %g2, #scratch |
.register %g3, #scratch |
.text |
.global halt |
41,8 → 44,7 |
nop |
memcpy: |
.register %g2, #scratch |
.register %g3, #scratch |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
61,7 → 63,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
95,9 → 97,19 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
jump_to_kernel: |
/* |
* We have copied code and now we need to guarantee cache coherence. |
* 1. Make sure that the code we have moved has drained to main memory. |
* 2. Invalidate I-cache. |
* 3. Flush instruction pipeline. |
*/ |
call icache_flush |
membar #StoreStore |
flush %i7 |
mov %o0, %l1 |
mov %o1, %o0 |
mov %o2, %o1 |
105,6 → 117,24 |
jmp %l1 ! jump to kernel |
nop |
#define ICACHE_SIZE 8192 |
#define ICACHE_LINE_SIZE 32 |
#define ICACHE_SET_BIT (1 << 13) |
#define ASI_ICACHE_TAG 0x67 |
# Flush I-cache |
icache_flush: |
set ((ICACHE_SIZE - ICACHE_LINE_SIZE) | ICACHE_SET_BIT), %g1 |
stxa %g0, [%g1] ASI_ICACHE_TAG |
0: membar #Sync |
subcc %g1, ICACHE_LINE_SIZE, %g1 |
bnz,pt %xcc, 0b |
stxa %g0, [%g1] ASI_ICACHE_TAG |
membar #Sync |
retl |
! SF Erratum #51 |
nop |
.global ofw |
ofw: |
save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp |
/branches/network/boot/arch/sparc64/loader/ofwarch.c |
---|
69,18 → 69,23 |
uint64_t current_mid; |
asm volatile ("ldxa [%1] %2, %0\n" : "=r" (current_mid) : "r" (0), "i" (ASI_UPA_CONFIG)); |
asm volatile ("ldxa [%1] %2, %0\n" |
: "=r" (current_mid) |
: "r" (0), "i" (ASI_UPA_CONFIG)); |
current_mid >>= UPA_CONFIG_MID_SHIFT; |
current_mid &= UPA_CONFIG_MID_MASK; |
int cpus; |
for (cpus = 0; node != 0 && node != -1; node = ofw_get_peer_node(node), cpus++) { |
if (ofw_get_property(node, "device_type", type_name, sizeof(type_name)) > 0) { |
for (cpus = 0; node != 0 && node != -1; node = ofw_get_peer_node(node), |
cpus++) { |
if (ofw_get_property(node, "device_type", type_name, |
sizeof(type_name)) > 0) { |
if (strcmp(type_name, "cpu") == 0) { |
uint32_t mid; |
if (ofw_get_property(node, "upa-portid", &mid, sizeof(mid)) <= 0) |
if (ofw_get_property(node, "upa-portid", &mid, |
sizeof(mid)) <= 0) |
continue; |
if (current_mid != mid) { |
87,9 → 92,10 |
/* |
* Start secondary processor. |
*/ |
(void) ofw_call("SUNW,start-cpu", 3, 1, NULL, node, |
KERNEL_VIRTUAL_ADDRESS, |
bootinfo.physmem_start | AP_PROCESSOR); |
(void) ofw_call("SUNW,start-cpu", 3, 1, |
NULL, node, KERNEL_VIRTUAL_ADDRESS, |
bootinfo.physmem_start | |
AP_PROCESSOR); |
} |
} |
} |
/branches/network/boot/arch/sparc64/loader/_link.ld.in |
---|
0,0 → 1,23 |
OUTPUT_FORMAT("elf64-sparc") |
ENTRY(start) |
SECTIONS { |
.boot 0x4000: AT (0x4000) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); |
[[COMPONENTS]] |
} |
/DISCARD/ : { |
*(.comment); |
*(.note*); |
} |
} |
/branches/network/boot/arch/sparc64/Makefile.inc |
---|
36,6 → 36,7 |
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)/loader/image.boot $(TMP)/HelenOS/image.boot |
gzip -f $(TMP)/HelenOS/image.boot |
mkisofs -f -G $(TMP)/boot/isofs.b -B ... -r -o $(BASE)/image.iso $(TMP)/ |
depend: |
/branches/network/boot/arch/sparc64/silo/silo.conf |
---|
1,3 → 1,3 |
timeout = 0 |
image = /HelenOS/image.boot |
image = /HelenOS/image.boot.gz |
label = HelenOS |
/branches/network/boot/arch/amd64/Makefile.inc |
---|
26,33 → 26,63 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
TASKS = \ |
INIT_TASKS = \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_TASKS = \ |
$(USPACEDIR)/srv/pci/pci \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/bdsh/bdsh \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat |
build: $(BASE)/image.iso |
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(TASKS) |
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_TASKS) |
mkdir -p arch/$(ARCH)/iso/boot/grub |
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/ |
cp arch/$(ARCH)/grub/menu.lst arch/$(ARCH)/iso/boot/grub/ |
ifneq ($(RDFMT),tmpfs) |
cat arch/$(ARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(ARCH)/iso/boot/grub/menu.lst |
endif |
ifneq ($(RDFMT),fat) |
cat arch/$(ARCH)/grub/menu.lst | grep -v "fat" >arch/$(ARCH)/iso/boot/grub/menu.lst |
endif |
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/ |
for task in $(TASKS) ; do \ |
for task in $(INIT_TASKS) ; do \ |
cp $$task arch/$(ARCH)/iso/boot/ ; \ |
done |
for task in $(RD_TASKS) ; do \ |
cp $$task $(USPACEDIR)/dist/sbin/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
$(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 |
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 |
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(ARCH)/iso/ |
clean: |
-for task in $(RD_TASKS) ; do \ |
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \ |
done |
-rm -fr arch/$(ARCH)/iso |
-rm -f $(BASE)/image.iso |
/branches/network/boot/arch/amd64/grub/menu.lst |
---|
6,14 → 6,10 |
kernel /boot/kernel.bin |
module /boot/ns |
module /boot/init |
module /boot/pci |
module /boot/fb |
module /boot/kbd |
module /boot/console |
module /boot/tetris |
module /boot/tester |
module /boot/klog |
module /boot/devmap |
module /boot/rd |
module /boot/vfs |
module /boot/tmpfs |
module /boot/fat |
module /boot/vfs |
module /boot/devmap |
module /boot/loader |
module /boot/initrd.img |
/branches/network/boot/arch/ia32/Makefile.inc |
---|
26,33 → 26,62 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
TASKS = \ |
INIT_TASKS = \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_TASKS = \ |
$(USPACEDIR)/srv/pci/pci \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/bdsh/bdsh |
build: $(BASE)/image.iso |
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(TASKS) |
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_TASKS) |
mkdir -p arch/$(ARCH)/iso/boot/grub |
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/ |
cp arch/$(ARCH)/grub/menu.lst arch/$(ARCH)/iso/boot/grub/ |
ifneq ($(RDFMT),tmpfs) |
cat arch/$(ARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(ARCH)/iso/boot/grub/menu.lst |
endif |
ifneq ($(RDFMT),fat) |
cat arch/$(ARCH)/grub/menu.lst | grep -v "fat" >arch/$(ARCH)/iso/boot/grub/menu.lst |
endif |
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/ |
for task in $(TASKS) ; do \ |
for task in $(INIT_TASKS) ; do \ |
cp $$task arch/$(ARCH)/iso/boot/ ; \ |
done |
for task in $(RD_TASKS) ; do \ |
cp $$task $(USPACEDIR)/dist/sbin/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
$(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 |
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 |
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(ARCH)/iso/ |
clean: |
-for task in $(RD_TASKS) ; do \ |
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \ |
done |
-rm -fr arch/$(ARCH)/iso |
-rm -f $(BASE)/image.iso |
/branches/network/boot/arch/ia32/grub/menu.lst |
---|
6,14 → 6,10 |
kernel /boot/kernel.bin |
module /boot/ns |
module /boot/init |
module /boot/pci |
module /boot/fb |
module /boot/kbd |
module /boot/console |
module /boot/devmap |
module /boot/rd |
module /boot/vfs |
module /boot/tmpfs |
module /boot/fat |
module /boot/devmap |
module /boot/tetris |
module /boot/tester |
module /boot/klog |
module /boot/loader |
module /boot/initrd.img |
/branches/network/boot/boot.config |
---|
1,3 → 1,31 |
# |
# Copyright (c) 2006 Ondrej Palkovsky |
# 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. |
# |
## General configuration directives |
# Architecture |
50,3 → 78,7 |
@ "ecoff" Ecoff image (GXEmul) |
! [ARCH=mips32] IMAGE (choice) |
# Ramdisk format |
@ "tmpfs" TMPFS image |
@ "fat" FAT16 image |
! RDFMT (choice) |
/branches/network/boot/tools/pack.py |
---|
0,0 → 1,132 |
#!/usr/bin/env python |
# |
# 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. |
# |
""" |
Binary package creator |
""" |
import sys |
import os |
import subprocess |
def usage(prname): |
"Print usage syntax" |
print prname + " <OBJCOPY> <FORMAT> <ARCH> <ALIGNMENT> <UINTPTR>" |
def main(): |
if (len(sys.argv) < 6): |
usage(sys.argv[0]) |
return |
if (not sys.argv[4].isdigit()): |
print "<ALIGNMENT> must be a number" |
return |
objcopy = sys.argv[1] |
format = sys.argv[2] |
arch = sys.argv[3] |
align = int(sys.argv[4], 0) |
uintptr = sys.argv[5] |
workdir = os.getcwd() |
header = file("_components.h", "w") |
data = file("_components.c", "w") |
header.write("#ifndef ___COMPONENTS_H__\n") |
header.write("#define ___COMPONENTS_H__\n\n") |
data.write("#include \"_components.h\"\n\n") |
data.write("void init_components(component_t *components)\n") |
data.write("{\n") |
cnt = 0 |
link = "" |
for task in sys.argv[6:]: |
basename = os.path.basename(task) |
plainname = os.path.splitext(basename)[0] |
path = os.path.dirname(task) |
object = plainname + ".o" |
symbol = "_binary_" + basename.replace(".", "_") |
macro = plainname.upper() |
print task + " -> " + object |
if (align > 1): |
link += "\t\t. = ALIGN(" + ("%d" % align) + ");\n" |
link += "\t\t*(." + plainname + "_image);\n" |
header.write("extern int " + symbol + "_start;\n") |
header.write("extern int " + symbol + "_end;\n\n") |
header.write("#define " + macro + "_START ((void *) &" + symbol + "_start)\n") |
header.write("#define " + macro + "_END ((void *) &" + symbol + "_end)\n") |
header.write("#define " + macro + "_SIZE ((" + uintptr + ") " + macro + "_END - (" + uintptr + ") " + macro + "_START)\n\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].name = \"" + plainname + "\";\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].start = " + macro + "_START;\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].end = " + macro + "_END;\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].size = " + macro + "_SIZE;\n\n") |
os.chdir(path) |
subprocess.call([objcopy, |
"-I", "binary", |
"-O", format, |
"-B", arch, |
"--rename-section", ".data=." + plainname + "_image", |
basename, os.path.join(workdir, object)]) |
os.chdir(workdir) |
cnt += 1 |
header.write("#define COMPONENTS " + ("%d" % cnt) + "\n\n") |
header.write("typedef struct {\n") |
header.write("\tchar *name;\n\n") |
header.write("\tvoid *start;\n") |
header.write("\tvoid *end;\n") |
header.write("\t" + uintptr + " size;\n") |
header.write("} component_t;\n\n") |
header.write("extern void init_components(component_t *components);\n\n") |
header.write("#endif\n") |
data.write("}\n") |
header.close() |
data.close() |
linkname = "_link.ld" |
link_in = file(linkname + ".in", "r") |
template = link_in.read(os.path.getsize(linkname + ".in")) |
link_in.close() |
link_out = file(linkname, "w") |
link_out.write(template.replace("[[COMPONENTS]]", link)) |
link_out.close() |
if __name__ == '__main__': |
main() |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/network/tools/cygwin_symlink_patch.sh |
---|
File deleted |
/branches/network/tools/build |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/network/tools/xstruct.py |
---|
0,0 → 1,110 |
# |
# 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. |
# |
""" |
Convert descriptive structure definitions to structure object |
""" |
import struct |
class Struct: |
def size(self): |
return struct.calcsize(self._format_) |
def pack(self): |
args = [] |
for variable in self._args_: |
if (isinstance(self.__dict__[variable], list)): |
for item in self.__dict__[variable]: |
args.append(item) |
else: |
args.append(self.__dict__[variable]) |
return struct.pack(self._format_, *args) |
def create(definition): |
"Create structure object" |
tokens = definition.split(None) |
# Initial byte order tag |
format = { |
"little:": lambda: "<", |
"big:": lambda: ">", |
"network:": lambda: "!" |
}[tokens[0]]() |
inst = Struct() |
args = [] |
# Member tags |
comment = False |
variable = None |
for token in tokens[1:]: |
if (comment): |
if (token == "*/"): |
comment = False |
continue |
if (token == "/*"): |
comment = True |
continue |
if (variable != None): |
subtokens = token.split("[") |
if (len(subtokens) > 1): |
format += "%d" % int(subtokens[1].split("]")[0]) |
format += variable |
inst.__dict__[subtokens[0]] = None |
args.append(subtokens[0]) |
variable = None |
continue |
if (token[0:8] == "padding["): |
size = token[8:].split("]")[0] |
format += "%dx" % int(size) |
continue |
variable = { |
"char": lambda: "s", |
"uint8_t": lambda: "B", |
"uint16_t": lambda: "H", |
"uint32_t": lambda: "L", |
"uint64_t": lambda: "Q", |
"int8_t": lambda: "b", |
"int16_t": lambda: "h", |
"int32_t": lambda: "l", |
"int64_t": lambda: "q" |
}[token]() |
inst.__dict__['_format_'] = format |
inst.__dict__['_args_'] = args |
return inst |
/branches/network/tools/mkfat.py |
---|
0,0 → 1,109 |
#!/usr/bin/env python |
# |
# 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. |
# |
""" |
FAT creator |
""" |
import sys |
import os |
import random |
import xstruct |
BOOT_SECTOR = """little: |
uint8_t jmp[3] /* jump instruction */ |
char oem[8] /* OEM string */ |
uint16_t sector /* bytes per sector */ |
uint8_t cluster /* sectors per cluster */ |
uint16_t reserved /* reserved sectors */ |
uint8_t fats /* number of FATs */ |
uint16_t rootdir /* root directory entries */ |
uint16_t sectors /* total number of sectors */ |
uint8_t descriptor /* media descriptor */ |
uint16_t fat_sectors /* sectors per single FAT */ |
uint16_t track_sectors /* sectors per track */ |
uint16_t heads /* number of heads */ |
uint32_t hidden /* hidden sectors */ |
uint32_t sectors_big /* total number of sectors (if sectors == 0) */ |
/* Extended BIOS Parameter Block */ |
uint8_t drive /* physical drive number */ |
padding[1] /* reserved (current head) */ |
uint8_t extboot_signature /* extended boot signature */ |
uint32_t serial /* serial number */ |
char label[11] /* volume label */ |
char fstype[8] /* filesystem type */ |
padding[448] /* boot code */ |
uint8_t boot_signature[2] /* boot signature */ |
""" |
def usage(prname): |
"Print usage syntax" |
print prname + " <PATH> <IMAGE>" |
def main(): |
if (len(sys.argv) < 3): |
usage(sys.argv[0]) |
return |
path = os.path.abspath(sys.argv[1]) |
if (not os.path.isdir(path)): |
print "<PATH> must be a directory" |
return |
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.descriptor = 0xF8 |
boot_sector.fat_sectors = 0 # FIXME |
boot_sector.track_sectors = 0 # FIXME |
boot_sector.heads = 0 # FIXME |
boot_sector.hidden = 0 |
boot_sector.sectors_big = 0 # FIXME |
boot_sector.drive = 0 |
boot_sector.extboot_signature = 0x29 |
boot_sector.serial = random.randint(0, 0xFFFFFFFF) |
boot_sector.label = "HELENOS" |
boot_sector.fstype = "FAT16 " |
boot_sector.boot_signature = [0x55, 0xAA] |
outf.write(boot_sector.pack()) |
outf.close() |
if __name__ == '__main__': |
main() |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/network/tools/mktmpfs.py |
---|
0,0 → 1,136 |
#!/usr/bin/env python |
# |
# 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. |
# |
""" |
TMPFS creator |
""" |
import sys |
import os |
import xstruct |
HEADER = """little: |
char tag[5] /* 'TMPFS' */ |
""" |
DENTRY_NONE = """little: |
uint8_t kind /* NONE */ |
uint32_t fname_len /* 0 */ |
""" |
DENTRY_FILE = """little: |
uint8_t kind /* FILE */ |
uint32_t fname_len /* filename length */ |
char fname[%d] /* filename */ |
uint32_t flen /* file length */ |
""" |
DENTRY_DIRECTORY = """little: |
uint8_t kind /* DIRECTORY */ |
uint32_t fname_len /* filename length */ |
char fname[%d] /* filename */ |
""" |
TMPFS_NONE = 0 |
TMPFS_FILE = 1 |
TMPFS_DIRECTORY = 2 |
def usage(prname): |
"Print usage syntax" |
print prname + " <PATH> <IMAGE>" |
def recursion(root, outf): |
"Recursive directory walk" |
for name in os.listdir(root): |
canon = os.path.join(root, name) |
if (os.path.isfile(canon)): |
size = os.path.getsize(canon) |
dentry = xstruct.create(DENTRY_FILE % len(name)) |
dentry.kind = TMPFS_FILE |
dentry.fname_len = len(name) |
dentry.fname = name |
dentry.flen = size |
outf.write(dentry.pack()) |
inf = file(canon, "r") |
rd = 0; |
while (rd < size): |
data = inf.read(4096); |
outf.write(data) |
rd += len(data) |
inf.close() |
if (os.path.isdir(canon)): |
dentry = xstruct.create(DENTRY_DIRECTORY % len(name)) |
dentry.kind = TMPFS_DIRECTORY |
dentry.fname_len = len(name) |
dentry.fname = name |
outf.write(dentry.pack()) |
recursion(canon, outf) |
dentry = xstruct.create(DENTRY_NONE) |
dentry.kind = TMPFS_NONE |
dentry.fname_len = 0 |
outf.write(dentry.pack()) |
def main(): |
if (len(sys.argv) < 3): |
usage(sys.argv[0]) |
return |
path = os.path.abspath(sys.argv[1]) |
if (not os.path.isdir(path)): |
print "<PATH> must be a directory" |
return |
outf = file(sys.argv[2], "w") |
header = xstruct.create(HEADER) |
header.tag = "TMPFS" |
outf.write(header.pack()) |
recursion(path, outf) |
dentry = xstruct.create(DENTRY_NONE) |
dentry.kind = TMPFS_NONE |
dentry.fname_len = 0 |
outf.write(dentry.pack()) |
outf.close() |
if __name__ == '__main__': |
main() |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/network/tools/mkhord.py |
---|
0,0 → 1,104 |
#!/usr/bin/env python |
# |
# 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. |
# |
""" |
HORD encapsulator |
""" |
import sys |
import os |
import xstruct |
HEADER = """little: |
char tag[4] /* 'HORD' */ |
uint8_t version /* version */ |
uint8_t encoding /* encoding */ |
uint32_t header_size /* header size */ |
uint64_t payload_size /* payload size */ |
""" |
HORD_LSB = 1 |
def align_up(size, alignment): |
"Align upwards to a given alignment" |
return (((size) + ((alignment) - 1)) & ~((alignment) - 1)) |
def usage(prname): |
"Print usage syntax" |
print prname + " <ALIGNMENT> <FS_IMAGE> <HORD_IMAGE>" |
def main(): |
if (len(sys.argv) < 4): |
usage(sys.argv[0]) |
return |
if (not sys.argv[1].isdigit()): |
print "<ALIGNMENT> must be a number" |
return |
align = int(sys.argv[1], 0) |
if (align <= 0): |
print "<ALIGNMENT> must be positive" |
return |
fs_image = os.path.abspath(sys.argv[2]) |
if (not os.path.isfile(fs_image)): |
print "<FS_IMAGE> must be a file" |
return |
inf = file(fs_image, "rb") |
outf = file(sys.argv[3], "wb") |
header = xstruct.create(HEADER) |
header_size = header.size() |
payload_size = os.path.getsize(fs_image) |
header_size_aligned = align_up(header_size, align) |
payload_size_aligned = align_up(payload_size, align) |
header.tag = "HORD" |
header.version = 1 |
header.encoding = HORD_LSB |
header.header_size = header_size_aligned |
header.payload_size = payload_size_aligned |
outf.write(header.pack()) |
outf.write(xstruct.create("little: padding[%d]" % (header_size_aligned - header_size)).pack()) |
outf.write(inf.read()) |
padding = payload_size_aligned - payload_size |
if (padding > 0): |
outf.write(xstruct.create("little: padding[%d]" % padding).pack()) |
inf.close() |
outf.close() |
if __name__ == '__main__': |
main() |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/network/tools/mkfat.sh |
---|
0,0 → 1,73 |
#!/bin/bash |
# |
# 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. |
# |
MFORMAT=`which mformat` |
MCOPY=`which mcopy` |
if [ `which mformat` == "" ]; then |
echo "Please install mtools." |
exit 1 |
fi |
if [ `which mcopy` == "" ]; then |
echo "Please install mtools." |
exit 1 |
fi |
if [ $# -ne 2 ]; then |
echo "Usage: $0 <PATH> <IMAGE>" |
exit 1 |
fi |
if [ ! -d $1 ]; then |
echo "Usage: $0 <PATH> <IMAGE>" |
exit 1 |
fi |
BPS=512 |
SPC=4 |
FAT16_MIN_SEC=$((4085 * $SPC)) |
HEADS=2 |
TRACKS=16 |
BYTES=`du -sb $1 | cut -f 1` |
SECTORS=$(($BYTES / $BPS)) |
SPTPH=$((($SECTORS + $FAT16_MIN_SEC) / ($HEADS * $TRACKS))) |
# Format the image as FAT16 |
$MFORMAT -h $HEADS -t $TRACKS -s $SPTPH -M $BPS -c $SPC -v "FAT16HORD" -B /dev/zero -C -i $2 :: |
if [ $? -ne 0 ]; then |
echo "$MFORMAT failed: $?" |
exit $? |
fi |
# Copy the subtree to the image |
$MCOPY -vspQmi $2 $1/* :: |
exit $? |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/network/tools/fix_symlinks.sh |
---|
0,0 → 1,24 |
#!/bin/bash |
# by Alf |
# This script solves malfunction of symlinks in cygwin |
# |
# Download sources from repository and than run this script to correct symlinks |
# to be able compile project |
if uname | grep 'CYGWIN' > /dev/null; then |
echo "Good ... you have cygwin" |
else |
echo "Wrong. This script is only for cygwin" |
exit |
fi |
for linkName in `find . ! -iwholename '.*svn*' ! -type d -print`; do |
if head -n 1 $linkName | grep '^link' > /dev/null; then |
linkTarget=`head -n 1 $linkName | sed 's/^link //'` |
echo $linkName " -> " $linkTarget |
rm $linkName |
ln -s "$linkTarget" "$linkName" |
fi |
done |
/branches/network/tools/config.py |
---|
1,4 → 1,31 |
#!/usr/bin/env python |
# |
# Copyright (c) 2006 Ondrej Palkovsky |
# 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. |
# |
""" |
HelenOS configuration script |
""" |
/branches/network/Makefile |
---|
82,12 → 82,7 |
UARCH = mips32 |
IMAGE = ecoff |
endif |
ifeq ($(MACHINE),indy) |
UARCH = mips32eb |
IMAGE = ecoff |
endif |
endif |
ifeq ($(PLATFORM),ppc32) |
KARCH = ppc32 |
113,7 → 108,7 |
BARCH = ia32xen |
endif |
.PHONY: all build config distclean clean |
.PHONY: all build config distclean clean cscope |
all: |
tools/config.py HelenOS.config default $(PLATFORM) $(COMPILER) $(CONFIG_DEBUG) |
139,9 → 134,14 |
-$(MAKE) -C kernel distclean |
-$(MAKE) -C uspace distclean |
-$(MAKE) -C boot distclean |
-rm Makefile.config |
rm -f Makefile.config tools/*.pyc |
clean: |
-$(MAKE) -C kernel clean |
-$(MAKE) -C uspace clean |
-$(MAKE) -C boot clean |
cscope: |
find kernel boot uspace -regex '^.*\.[chsS]$$' -print > srclist |
rm -f cscope.out |
cscope -bi srclist |
/branches/network/HelenOS.config |
---|
1,3 → 1,31 |
# |
# Copyright (c) 2006 Ondrej Palkovsky |
# 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. |
# |
## General configuration directives |
# Platform |
16,8 → 44,7 |
@ "msim" MSIM |
@ "simics" Simics |
@ "bgxemul" GXEmul big endian |
@ "lgxemul" GXEmul little endia |
@ "indy" Sgi Indy |
@ "lgxemul" GXEmul little endian |
! [PLATFORM=mips32] MACHINE (choice) |
# Machine type |
25,10 → 52,6 |
@ "i460GX" i460GX chipset machine |
! [PLATFORM=ia64] MACHINE (choice) |
# Machine |
@ "gxemul_testarm" GXEmul testarm |
! [PLATFORM=arm32] MACHINE (choice) |
# Compiler |
@ "gcc_cross" GCC Cross-compiler |
@ "gcc_native" GCC Native |
/branches/network/version |
---|
1,8 → 1,8 |
VERSION = 0 |
PATCHLEVEL = 2 |
PATCHLEVEL = 3 |
SUBLEVEL = 0 |
EXTRAVERSION = 5 |
NAME = Twilight |
#EXTRAVERSION = 0 |
NAME = Tartare |
ifdef EXTRAVERSION |
RELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL).$(EXTRAVERSION) |