Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright 2014, NICTA
- *
- * This software may be distributed and modified according to the terms of
- * the BSD 2-Clause license. Note that NO WARRANTY is provided.
- * See "LICENSE_BSD2.txt" for details.
- *
- * @TAG(NICTA_BSD)
- */
- #include <sel4/sel4.h>
- #include <elf/elf.h>
- #include <string.h>
- #include <assert.h>
- #include <cspace/cspace.h>
- #include "elf.h"
- #include <vmem_layout.h>
- #include <ut_manager/ut.h>
- #include <mapping.h>
- #define verbose 0
- #include <sys/debug.h>
- #include <sys/panic.h>
- #include <frametable.h>
- /* Minimum of two values. */
- #define MIN(a,b) (((a)<(b))?(a):(b))
- #define PAGESIZE (1 << (seL4_PageBits))
- #define PAGEMASK ((PAGESIZE) - 1)
- #define PAGE_ALIGN(addr) ((addr) & ~(PAGEMASK))
- #define IS_PAGESIZE_ALIGNED(addr) !((addr) & (PAGEMASK))
- extern seL4_ARM_PageDirectory dest_as;
- /*
- * Convert ELF permissions into seL4 permissions.
- */
- static inline seL4_Word get_sel4_rights_from_elf(unsigned long permissions) {
- seL4_Word result = 0;
- if (permissions & PF_R)
- result |= seL4_CanRead;
- if (permissions & PF_X)
- result |= seL4_CanRead;
- if (permissions & PF_W)
- result |= seL4_CanWrite;
- return result;
- }
- /*
- * Inject data into the given vspace.
- * TODO: Don't keep these pages mapped in
- */
- /* Overview of ELF segment loading
- dst: destination base virtual address of the segment being loaded
- segment_size: obvious
- So the segment range to "load" is [dst, dst + segment_size).
- The content to load is either zeros or the content of the ELF
- file itself, or both.
- The split between file content and zeros is a follows.
- File content: [dst, dst + file_size)
- Zeros: [dst + file_size, dst + segment_size)
- Note: if file_size == segment_size, there is no zero-filled region.
- Note: if file_size == 0, the whole segment is just zero filled.
- The code below relies on seL4's frame allocator already
- zero-filling a newly allocated frame.
- */
- void nfs_read_elf(uintptr_t token, enum nfs_stat status,
- fattr_t *fattr, int count, void* data){
- struct nfs_event *event = (struct nfs_event*)token;
- assert(event != NULL);
- printf("bytes READ = %d\n IN READ CALLBACK WOO\n", count);
- printf("status is %d\n", status);
- printf("file size is %d bytes\n", fattr->size);
- // assert(count != 0);
- if (status == NFS_OK){
- event->fsize = fattr->size;
- event->token = token;
- event->stat = status;
- event->count -= count;
- if (fattr->size != 0){
- printf("PERFORMING MEMCPY\n");
- /* Copies directly into static buffer */
- memcpy(event->user_ptr, (char *)data, count);
- }
- // Increment the file offset.
- event->bufoffset += count;
- event->offset += count;
- } else {
- assert(!"nfs write callback failed\n");
- event->attr = NULL;
- }
- add_event(&event_list, event);
- }
- static int load_segment_into_vspace(seL4_ARM_PageDirectory dest_as,
- struct addrspace *as,
- //char *src,
- int offset_into_file,
- //
- unsigned long segment_size,
- unsigned long file_size,
- unsigned long dst,
- unsigned long permissions,
- struct nfs_event *event) {
- assert(file_size <= segment_size);
- unsigned long pos;
- /* We work a page at a time in the destination vspace. */
- pos = 0;
- event->bufoffset = 0;
- event->offset = offset_into_file;
- while(pos < segment_size) {
- seL4_Word sos_vaddr, kdst;
- seL4_CPtr sos_cap; //tty_cap;
- seL4_Word vpage, kvpage;
- unsigned long p;
- int nbytes;
- int err;
- //get a page
- sos_cap = frame_alloc(&sos_vaddr);
- pin_page(&sos_vaddr);
- vpage = PAGE_ALIGN(dst);
- kvpage = PAGE_ALIGN(sos_vaddr);
- //map the page
- sos_cap = cspace_copy_cap(cur_cspace, cur_cspace, sos_cap, seL4_AllRights);
- struct page_dir * pd = pgdir_walk(as, vpage, &p);
- //update page table with frame entry
- frame_alloc_update(sos_vaddr, get_page_entry(vpage, pd));
- err = sos_map_page(pd,
- kvpage,//sos_vaddr,
- sos_cap,
- dest_as,
- vpage,
- permissions,
- seL4_ARM_Default_VMAttributes);
- assert(!err);
- nbytes = PAGESIZE - (dst & PAGEMASK);
- kdst = kvpage + (dst & PAGEMASK);
- event->count = MIN(nbytes, file_size - pos);
- printf("event->count %d\n", event->count);
- event->user_ptr = kdst;
- /* read the first 4k into the page elf_file */
- err = nfs_read(&event->handle,
- event->offset,
- event->count,
- &nfs_read_elf,
- event);
- yield_coro(event->cr);
- // read from offset into the page
- // kdst = kvpage + (dst & PAGEMASK);
- // if (pos < file_size){
- // memcpy((void*)kdst, (void*)src, MIN(nbytes, file_size - pos));
- // }
- /* Not observable to I-cache yet so flush the frame */
- seL4_ARM_Page_Unify_Instruction(sos_cap, 0, PAGESIZE);
- //update offset
- pos += nbytes;
- dst += nbytes;
- // offset_into_file += nbytes;
- }
- return 0;
- }
- int elf_load(seL4_ARM_PageDirectory dest_as, struct addrspace *as,
- char *path, struct nfs_event *event) {
- int num_headers;
- int err;
- int i;
- /* Perform the lookup */
- printf("call_process_create: Doing nfs_lookup on %s\n", path);
- err = nfs_lookup(&mnt_point, path, &nfs_lookup_callback, event);
- printf("yielding\n");
- yield_coro(event->cr);
- printf("finished lookup\n");
- if (err != RPC_OK || event->attr == NULL || &event->handle == NULL){
- assert(!"call_process_create: nfs_lookup err\n");
- }
- seL4_Word elf_file;
- frame_alloc(&elf_file);
- /* set up event */
- event->bufoffset = 0;
- event->count = PAGEMASK;
- event->user_ptr = elf_file;
- event->offset = 0;
- /* read the first 4k into the page elf_file */
- err = nfs_read(&event->handle,
- event->offset,
- event->count,
- &nfs_read_elf,
- event);
- yield_coro(event->cr);
- /* Ensure that the ELF file looks sane. */
- if (elf_checkFile(elf_file)){
- assert(!"elf failed\n");
- return seL4_InvalidArgument;
- }
- //add heap
- struct region * new_region = define_region(0x20000000, PAGESIZE, seL4_CanWrite);
- append_region(as, new_region);
- //add stack
- new_region = define_region(0x80000000, 0x10000000, seL4_CanWrite);
- append_region(as, new_region);
- num_headers = elf_getNumProgramHeaders(elf_file);
- int offset;
- for (i = 0; i < num_headers; i++) {
- char *source_addr;
- unsigned long flags, file_size, segment_size, vaddr;
- /* Skip non-loadable segments (such as debugging data). */
- if (elf_getProgramHeaderType(elf_file, i) != PT_LOAD)
- continue;
- /* Fetch information about this segment. */
- source_addr = elf_file + elf_getProgramHeaderOffset(elf_file, i);
- offset = source_addr - elf_file;
- printf("OFFSET >>>> %x\n", source_addr - elf_file);
- printf("SADDR >>>>> %x\n", source_addr);
- file_size = elf_getProgramHeaderFileSize(elf_file, i);
- printf("file size = %d\n", file_size);
- segment_size = elf_getProgramHeaderMemorySize(elf_file, i);
- printf("segment size = %d\n", segment_size);
- vaddr = elf_getProgramHeaderVaddr(elf_file, i);
- printf("vaddr = %x\n", vaddr);
- flags = elf_getProgramHeaderFlags(elf_file, i);
- printf("flags = %x\n", flags);
- // Define and Append region to AS
- new_region = define_region(PAGE_ALIGN(vaddr),
- segment_size,
- get_sel4_rights_from_elf(flags) & seL4_AllRights);
- append_region(as, new_region);
- /* Copy it across into the vspace. */
- printf(" * Loading segment %08x-->%08x\n",(int)vaddr, (int)(vaddr + segment_size));
- err = load_segment_into_vspace(dest_as,
- as,
- offset,
- segment_size,
- file_size,
- vaddr,
- get_sel4_rights_from_elf(flags) & seL4_AllRights,
- event);
- conditional_panic(err != 0, "Elf loading failed!\n");
- }
- frame_free(&elf_file);
- printf("LOADING SEGMENT FINISHED\n");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement