void io_libraryRelease(io_library_t *library) { spinlock_lock(&library->lock); if((-- library->refCount) == 0) { struct io_dependency_s *dependency = list_first(library->dependencies); while(dependency) { io_libraryRelease(dependency->library); dependency = dependency->next; } io_storeRemoveLibrary(library); if(library->vmemory) vm_free(vm_getKernelDirectory(), library->vmemory, library->pages); if(library->pmemory) pm_free(library->pmemory, library->pages); hfree(NULL, library->path); list_destroy(library->dependencies); return; } spinlock_unlock(&library->lock); }
void dma_free(dma_t *dma) { for(size_t i=0; i<dma->pfragmentCount; i++) { pm_free(dma->pfragments[i], dma->pfragmentPages[i]); } if(dma->vaddress) vm_free(vm_getKernelDirectory(), dma->vaddress, dma->pages); hfree(NULL, dma); }
bool ir_trampoline_init(void *UNUSED(unused)) { // Map the trampoline area into memory vm_mapPageRange(vm_getKernelDirectory(), (uintptr_t)IR_TRAMPOLINE_PHYSICAL, (vm_address_t)IR_TRAMPOLINE_BEGIN, IR_TRAMPOLINE_PAGES, VM_FLAGS_KERNEL); // Copy the IDT section into the trampoline vm_address_t _idt_sectionBegin = (vm_address_t)&idt_sectionBegin; vm_address_t _idt_sectionEnd = (vm_address_t)&idt_sectionEnd; vm_address_t _idt_entryHandler = (vm_address_t)&idt_entry_handler; memcpy(ir_trampoline_map->base, &idt_sectionBegin, _idt_sectionEnd - _idt_sectionBegin); ir_trampolineFixEntryCall(_idt_entryHandler - _idt_sectionBegin, _idt_sectionEnd - _idt_entryHandler); // Set IDT and GDT straight ir_idt_init(ir_trampoline_map->idt, IR_TRAMPOLINE_BEGIN - _idt_sectionBegin); gdt_init(ir_trampoline_map->gdt, &ir_trampoline_map->tss); return true; }
io_library_t *io_libraryCreate(const char *path, uint8_t *buffer, size_t UNUSED(length)) { io_library_t *library = halloc(NULL, sizeof(io_library_t)); if(library) { // Setup the library memset(library, 0, sizeof(io_library_t)); library->lock = SPINLOCK_INIT; library->refCount = 1; library->path = halloc(NULL, strlen(path) + 1); library->dependencies = list_create(sizeof(struct io_dependency_s), offsetof(struct io_dependency_s, next), offsetof(struct io_dependency_s, prev)); if(!library->path || !library->dependencies) { if(library->path) hfree(NULL, library->path); if(library->dependencies) list_destroy(library->dependencies); dbg("iolink: Couldn't allocate enough memory for %s\n", path); return NULL; } strcpy(library->path, path); library->name = (char *)sys_fileWithoutPath(library->path); // Get the basic ELF info elf_header_t *header = (elf_header_t *)buffer; if(strncmp((const char *)header->e_ident, ELF_MAGIC, strlen(ELF_MAGIC)) != 0 || header->e_type != ET_DYN) { hfree(NULL, library->path); list_destroy(library->dependencies); dbg("iolink: %s is not a valid binary!\n", path); return NULL; } // Parse the program header elf_program_header_t *programHeader = (elf_program_header_t *)(buffer + header->e_phoff); elf_program_header_t *ptload[2]; vm_address_t minAddress = -1; vm_address_t maxAddress = 0; size_t segments = 0; // Calculate the needed size for(int i=0; i<header->e_phnum; i++) { elf_program_header_t *program = &programHeader[i]; if(program->p_type == PT_LOAD) { if(program->p_paddr < minAddress) minAddress = program->p_paddr; if(program->p_paddr + program->p_memsz > maxAddress) maxAddress = program->p_paddr + program->p_memsz; ptload[segments ++] = program; } if(program->p_type == PT_DYNAMIC) library->dynamic = (elf_dyn_t *)program->p_vaddr; } // Reserve enough memory and copy the .text section library->pages = pageCount(maxAddress - minAddress); library->pmemory = pm_alloc(library->pages); if(!library->pmemory) { io_libraryRelease(library); return NULL; } library->vmemory = vm_alloc(vm_getKernelDirectory(), (uintptr_t)library->pmemory, library->pages, VM_FLAGS_KERNEL); if(!library->vmemory) { io_libraryRelease(library); return NULL; } uint8_t *target = (uint8_t *)library->vmemory; uint8_t *source = buffer; memset(target, 0, library->pages * VM_PAGE_SIZE); for(size_t i=0; i<segments; i++) { elf_program_header_t *program = ptload[i]; memcpy(&target[program->p_vaddr - minAddress], &source[program->p_offset], program->p_filesz); } library->relocBase = library->vmemory - minAddress; // Verify if(library->dynamic) { library->dynamic = (elf_dyn_t *)(library->relocBase + ((uintptr_t)library->dynamic)); io_libraryDigestDynamic(library); } } return library; }
ld_exectuable_t *ld_exectuableCreate(vm_page_directory_t pdirectory, uint8_t *begin, size_t UNUSED(size)) { elf_header_t *header = (elf_header_t *)begin; if(strncmp((const char *)header->e_ident, ELF_MAGIC, strlen(ELF_MAGIC)) != 0) return NULL; ld_exectuable_t *executable = halloc(NULL, sizeof(ld_exectuable_t)); if(executable) { // Initialize the executable executable->useCount = 1; executable->entry = header->e_entry; executable->pdirectory = pdirectory; elf_program_header_t *programHeader = (elf_program_header_t *)(begin + header->e_phoff); vm_address_t minAddress = -1; vm_address_t maxAddress = 0; size_t pages = 0; // Calculate the needed size for(int i=0; i<header->e_phnum; i++) { elf_program_header_t *program = &programHeader[i]; if(program->p_type == PT_LOAD) { if(program->p_paddr < minAddress) minAddress = program->p_paddr; if(program->p_paddr + program->p_memsz > maxAddress) maxAddress = program->p_paddr + program->p_memsz; } } // Calculate the starting address and the number of pages we need to allocate minAddress = round4kDown(minAddress); pages = pageCount(maxAddress - minAddress); // Memory allocation uint8_t *memory = (uint8_t *)pm_alloc(pages); uint8_t *target = (uint8_t *)vm_alloc(vm_getKernelDirectory(), (uintptr_t)memory, pages, VM_FLAGS_KERNEL); uint8_t *source = begin; memset(target, 0, pages * VM_PAGE_SIZE); // Copy the data from the image for(int i=0; i<header->e_phnum; i++) { elf_program_header_t *program = &programHeader[i]; if(program->p_type == PT_LOAD) { memcpy(&target[program->p_vaddr - minAddress], &source[program->p_offset], program->p_filesz); } } vm_free(vm_getKernelDirectory(), (vm_address_t)target, pages); vm_mapPageRange(pdirectory, (uintptr_t)memory, minAddress, pages, VM_FLAGS_USERLAND_R); executable->pimage = (uintptr_t)memory; executable->vimage = (vm_address_t)minAddress; executable->imagePages = pages; } return executable; }