Advertisement
Guest User

Untitled

a guest
Oct 27th, 2016
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.34 KB | None | 0 0
  1. /*
  2. * Copyright 2014, NICTA
  3. *
  4. * This software may be distributed and modified according to the terms of
  5. * the BSD 2-Clause license. Note that NO WARRANTY is provided.
  6. * See "LICENSE_BSD2.txt" for details.
  7. *
  8. * @TAG(NICTA_BSD)
  9. */
  10.  
  11. #include <sel4/sel4.h>
  12. #include <elf/elf.h>
  13. #include <string.h>
  14. #include <assert.h>
  15. #include <cspace/cspace.h>
  16.  
  17. #include "elf.h"
  18.  
  19. #include <vmem_layout.h>
  20. #include <ut_manager/ut.h>
  21. #include <mapping.h>
  22.  
  23. #define verbose 0
  24. #include <sys/debug.h>
  25. #include <sys/panic.h>
  26. #include <frametable.h>
  27. /* Minimum of two values. */
  28. #define MIN(a,b) (((a)<(b))?(a):(b))
  29.  
  30. #define PAGESIZE (1 << (seL4_PageBits))
  31. #define PAGEMASK ((PAGESIZE) - 1)
  32. #define PAGE_ALIGN(addr) ((addr) & ~(PAGEMASK))
  33. #define IS_PAGESIZE_ALIGNED(addr) !((addr) & (PAGEMASK))
  34.  
  35.  
  36. extern seL4_ARM_PageDirectory dest_as;
  37.  
  38. /*
  39. * Convert ELF permissions into seL4 permissions.
  40. */
  41. static inline seL4_Word get_sel4_rights_from_elf(unsigned long permissions) {
  42. seL4_Word result = 0;
  43.  
  44. if (permissions & PF_R)
  45. result |= seL4_CanRead;
  46. if (permissions & PF_X)
  47. result |= seL4_CanRead;
  48. if (permissions & PF_W)
  49. result |= seL4_CanWrite;
  50.  
  51. return result;
  52. }
  53.  
  54. /*
  55. * Inject data into the given vspace.
  56. * TODO: Don't keep these pages mapped in
  57. */
  58. /* Overview of ELF segment loading
  59.  
  60. dst: destination base virtual address of the segment being loaded
  61. segment_size: obvious
  62.  
  63. So the segment range to "load" is [dst, dst + segment_size).
  64.  
  65. The content to load is either zeros or the content of the ELF
  66. file itself, or both.
  67.  
  68. The split between file content and zeros is a follows.
  69.  
  70. File content: [dst, dst + file_size)
  71. Zeros: [dst + file_size, dst + segment_size)
  72.  
  73. Note: if file_size == segment_size, there is no zero-filled region.
  74. Note: if file_size == 0, the whole segment is just zero filled.
  75.  
  76. The code below relies on seL4's frame allocator already
  77. zero-filling a newly allocated frame.
  78.  
  79. */
  80.  
  81. void nfs_read_elf(uintptr_t token, enum nfs_stat status,
  82. fattr_t *fattr, int count, void* data){
  83. struct nfs_event *event = (struct nfs_event*)token;
  84. assert(event != NULL);
  85. printf("bytes READ = %d\n IN READ CALLBACK WOO\n", count);
  86. printf("status is %d\n", status);
  87. printf("file size is %d bytes\n", fattr->size);
  88. // assert(count != 0);
  89.  
  90. if (status == NFS_OK){
  91.  
  92. event->fsize = fattr->size;
  93.  
  94. event->token = token;
  95. event->stat = status;
  96. event->count -= count;
  97.  
  98. if (fattr->size != 0){
  99. printf("PERFORMING MEMCPY\n");
  100. /* Copies directly into static buffer */
  101. memcpy(event->user_ptr, (char *)data, count);
  102. }
  103.  
  104. // Increment the file offset.
  105. event->bufoffset += count;
  106. event->offset += count;
  107. } else {
  108. assert(!"nfs write callback failed\n");
  109. event->attr = NULL;
  110. }
  111. add_event(&event_list, event);
  112. }
  113.  
  114. static int load_segment_into_vspace(seL4_ARM_PageDirectory dest_as,
  115. struct addrspace *as,
  116. //char *src,
  117. int offset_into_file,
  118. //
  119. unsigned long segment_size,
  120. unsigned long file_size,
  121. unsigned long dst,
  122. unsigned long permissions,
  123. struct nfs_event *event) {
  124.  
  125. assert(file_size <= segment_size);
  126.  
  127. unsigned long pos;
  128.  
  129. /* We work a page at a time in the destination vspace. */
  130. pos = 0;
  131.  
  132. event->bufoffset = 0;
  133. event->offset = offset_into_file;
  134.  
  135. while(pos < segment_size) {
  136. seL4_Word sos_vaddr, kdst;
  137. seL4_CPtr sos_cap; //tty_cap;
  138. seL4_Word vpage, kvpage;
  139. unsigned long p;
  140. int nbytes;
  141. int err;
  142.  
  143. //get a page
  144. sos_cap = frame_alloc(&sos_vaddr);
  145. pin_page(&sos_vaddr);
  146. vpage = PAGE_ALIGN(dst);
  147. kvpage = PAGE_ALIGN(sos_vaddr);
  148.  
  149. //map the page
  150. sos_cap = cspace_copy_cap(cur_cspace, cur_cspace, sos_cap, seL4_AllRights);
  151. struct page_dir * pd = pgdir_walk(as, vpage, &p);
  152. //update page table with frame entry
  153. frame_alloc_update(sos_vaddr, get_page_entry(vpage, pd));
  154.  
  155. err = sos_map_page(pd,
  156. kvpage,//sos_vaddr,
  157. sos_cap,
  158. dest_as,
  159. vpage,
  160. permissions,
  161. seL4_ARM_Default_VMAttributes);
  162. assert(!err);
  163.  
  164.  
  165.  
  166. nbytes = PAGESIZE - (dst & PAGEMASK);
  167. kdst = kvpage + (dst & PAGEMASK);
  168.  
  169. event->count = MIN(nbytes, file_size - pos);
  170. printf("event->count %d\n", event->count);
  171. event->user_ptr = kdst;
  172.  
  173. /* read the first 4k into the page elf_file */
  174. err = nfs_read(&event->handle,
  175. event->offset,
  176. event->count,
  177. &nfs_read_elf,
  178. event);
  179.  
  180. yield_coro(event->cr);
  181.  
  182. // read from offset into the page
  183. // kdst = kvpage + (dst & PAGEMASK);
  184.  
  185. // if (pos < file_size){
  186. // memcpy((void*)kdst, (void*)src, MIN(nbytes, file_size - pos));
  187. // }
  188. /* Not observable to I-cache yet so flush the frame */
  189. seL4_ARM_Page_Unify_Instruction(sos_cap, 0, PAGESIZE);
  190.  
  191.  
  192. //update offset
  193. pos += nbytes;
  194. dst += nbytes;
  195. // offset_into_file += nbytes;
  196. }
  197.  
  198. return 0;
  199. }
  200.  
  201. int elf_load(seL4_ARM_PageDirectory dest_as, struct addrspace *as,
  202. char *path, struct nfs_event *event) {
  203.  
  204. int num_headers;
  205. int err;
  206. int i;
  207.  
  208. /* Perform the lookup */
  209. printf("call_process_create: Doing nfs_lookup on %s\n", path);
  210. err = nfs_lookup(&mnt_point, path, &nfs_lookup_callback, event);
  211. printf("yielding\n");
  212. yield_coro(event->cr);
  213.  
  214. printf("finished lookup\n");
  215. if (err != RPC_OK || event->attr == NULL || &event->handle == NULL){
  216. assert(!"call_process_create: nfs_lookup err\n");
  217. }
  218.  
  219. seL4_Word elf_file;
  220. frame_alloc(&elf_file);
  221.  
  222. /* set up event */
  223. event->bufoffset = 0;
  224. event->count = PAGEMASK;
  225. event->user_ptr = elf_file;
  226. event->offset = 0;
  227.  
  228. /* read the first 4k into the page elf_file */
  229. err = nfs_read(&event->handle,
  230. event->offset,
  231. event->count,
  232. &nfs_read_elf,
  233. event);
  234. yield_coro(event->cr);
  235.  
  236. /* Ensure that the ELF file looks sane. */
  237. if (elf_checkFile(elf_file)){
  238. assert(!"elf failed\n");
  239. return seL4_InvalidArgument;
  240. }
  241.  
  242. //add heap
  243. struct region * new_region = define_region(0x20000000, PAGESIZE, seL4_CanWrite);
  244. append_region(as, new_region);
  245.  
  246. //add stack
  247. new_region = define_region(0x80000000, 0x10000000, seL4_CanWrite);
  248. append_region(as, new_region);
  249.  
  250. num_headers = elf_getNumProgramHeaders(elf_file);
  251. int offset;
  252. for (i = 0; i < num_headers; i++) {
  253. char *source_addr;
  254. unsigned long flags, file_size, segment_size, vaddr;
  255.  
  256. /* Skip non-loadable segments (such as debugging data). */
  257. if (elf_getProgramHeaderType(elf_file, i) != PT_LOAD)
  258. continue;
  259.  
  260. /* Fetch information about this segment. */
  261. source_addr = elf_file + elf_getProgramHeaderOffset(elf_file, i);
  262. offset = source_addr - elf_file;
  263. printf("OFFSET >>>> %x\n", source_addr - elf_file);
  264. printf("SADDR >>>>> %x\n", source_addr);
  265. file_size = elf_getProgramHeaderFileSize(elf_file, i);
  266. printf("file size = %d\n", file_size);
  267. segment_size = elf_getProgramHeaderMemorySize(elf_file, i);
  268. printf("segment size = %d\n", segment_size);
  269. vaddr = elf_getProgramHeaderVaddr(elf_file, i);
  270. printf("vaddr = %x\n", vaddr);
  271. flags = elf_getProgramHeaderFlags(elf_file, i);
  272. printf("flags = %x\n", flags);
  273. // Define and Append region to AS
  274. new_region = define_region(PAGE_ALIGN(vaddr),
  275. segment_size,
  276. get_sel4_rights_from_elf(flags) & seL4_AllRights);
  277. append_region(as, new_region);
  278.  
  279. /* Copy it across into the vspace. */
  280. printf(" * Loading segment %08x-->%08x\n",(int)vaddr, (int)(vaddr + segment_size));
  281. err = load_segment_into_vspace(dest_as,
  282. as,
  283. offset,
  284. segment_size,
  285. file_size,
  286. vaddr,
  287. get_sel4_rights_from_elf(flags) & seL4_AllRights,
  288. event);
  289.  
  290. conditional_panic(err != 0, "Elf loading failed!\n");
  291. }
  292. frame_free(&elf_file);
  293. printf("LOADING SEGMENT FINISHED\n");
  294. return 0;
  295. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement