/* * copy_file_image * Function: Copies a file image to physical memory * Inputs: fname, charstring of filename to copy * Outputs: none * Effect: Copies the file to the physical memory specified for image start address */ uint32_t copy_file_image(uint8_t* fname) { dentry_t dentry_curr; read_dentry_by_name(fname, &dentry_curr); uint32_t fsize=inodes_array[dentry_curr.inode].length; uint8_t buf[ inodes_array[dentry_curr.inode].length]; read_data(dentry_curr.inode, 0, buf, fsize); uint8_t* image_start_addr=(uint8_t*) IMAGE_START; memcpy(image_start_addr,buf,fsize); return 0; }
/* int32_t open(const uint8_t* filename) * calls open jump table * * */ int32_t open(const uint8_t* filename) { // uint32_t flags; // cli_and_save(flags); /* Get the current process */ pcb_t* cur_PCB = curr_process; file_t* farray = cur_PCB->file_fds; /* Find next open slot in the file array */ uint32_t fd = 0; while(farray[fd].flags == 1) fd++; /* Check if there's space for the file and open a valid dentry*/ dentry_t dentry; if(fd > 7 || -1 == read_dentry_by_name(filename, &dentry)) return -1; file_t* cur_file = &(farray[fd]); // Fill the file array entry switch(dentry.file_type) { case 0: // RTC if(-1 == rtc_open(cur_file, filename)) return -1; break; case 1: // Directory if(-1 == dir_open(cur_file, filename)) return -1; break; case 2: // File if(-1 == file_open(cur_file, filename)) return -1; break; default: // Invalid type return -1; } return fd; }
/* * open_file() * Function: Checks if a file is valid and opens it * Inputs: fname, charstring of the dentry to search for * Effect: Initializes the file_array[8] depending on the file to be opened * Returns: fd, the index of the newly created file descriptor (success) * -1, if we could not find a empty file decriptor in file_array[8] */ uint32_t open_file(const uint8_t *fname) { int check_file=read_dentry_by_name(fname, &dentry); //checks for valid file if (dentry.fname == NULL || check_file == -1) { return -1; } uint32_t fd = find_free_fd( current_pcb ); if(fd==-1) return -1; if(dentry.ftype==FILE_TYPE_RTC) //user level access to rtc { ((current_pcb->file_array)[fd]).file_ops = &rtc_ops; current_pcb->file_array[fd].inode_ptr=0; current_pcb->file_array[fd].file_position=0; current_pcb->file_array[fd].flags=FILE_IN_USE; } else if(dentry.ftype==FILE_TYPE_DIR) //file type is directory { ((current_pcb->file_array)[fd]).file_ops = &file_ops; current_pcb->file_array[fd].inode_ptr=0; current_pcb->file_array[fd].file_position=0; current_pcb->file_array[fd].flags=FILE_IN_USE; } else if(dentry.ftype==FILE_TYPE_REG) //file type is regular { ((current_pcb->file_array)[fd]).file_ops = &file_ops; current_pcb->file_array[fd].inode_ptr=(int32_t*)&inodes_array[dentry.inode]; current_pcb->file_array[fd].file_position=0; current_pcb->file_array[fd].flags=FILE_IN_USE; } return fd; }
int32_t execute(const uint8_t* command) { pcb_t* previous_pcb = curr_process; char* cmd = (char*)command; uint8_t* fname = (uint8_t*)parse(cmd); get_arg((char *)command, (int)strlen(cmd)); /* Looking for processes */ uint8_t process_mask = MASK; // Calculating the process mask, which keeps track of open processes. Here we search for a 0 in the mask // and set it to 1, giving the index in the bitmap to process_id int i = 0; for(i = 0; i < 7; i++) { if((process_mask & open_processes) == 0) { open_processes |= process_mask; process_id = i; break; } else process_mask >>= 1; } // if(num_processes + 1 > 2) // { // cout("PROCESS LIMIT EXCEEDED. NOT ALLOWED TO EXECUTE\n"); // //num_processes--; // sti(); // asm volatile("jmp ret_halt"); // } // Check if(i == 7) { printf("Too many processes!\n"); return 1; } /* Executable check */ uint8_t elf_check[4]; dentry_t dentry_temp; if(-1 == read_dentry_by_name(fname, &dentry_temp)) { return -1; } if(-1 == read_data(dentry_temp.inode_num, 0, elf_check, 4)) { return -1; } if(!(elf_check[0] == 0x7f && elf_check[1] == 0x45 && elf_check[2] == 0x4c && elf_check[3] == 0x46)) { return -1; } /* Find the address of the file's first instruction */ uint8_t buf_temp[4]; if(-1 == read_data(dentry_temp.inode_num, 24, buf_temp, 4)) { return -1; } int k = 0; uint32_t entry_addr = 0; for(k = 0; k < 4; k++) entry_addr |= (buf_temp[k] << 8*k); /* Set up paging */ PDE_t* PD_ptr = task_mem_init(process_id); if(PD_ptr == NULL) { printf("Too many processes!\n"); return 1; } // Load program image into memory if(-1 == program_load(fname, PGRM_IMG)) { return -1; } k_bp = _8MB - (_8KB)*(process_id) - 4; curr_process = (pcb_t *) (k_bp & 0xFFFFE000); // k_bp = _8MB - (_8KB)*(process_id); // curr_process = (pcb_t *) ((k_bp - 1) & 0xFFFFE000); curr_process->process_id = process_id; curr_process->PD_ptr = PD_ptr; curr_process->k_bp = k_bp; curr_process->k_sp = k_bp; // If initial shell, case should be handeled by making parent process the same shell if(initial_shell) { curr_process->parent_process = curr_process; curr_process->child_flag = 0; curr_process->parent_process->child = -1; initial_shell = 0; } else { curr_process->parent_process = previous_pcb; curr_process->parent_process->child_flag = 1; curr_process->parent_process->child = process_id; } // Initialize file descriptors for(i = 0; i < 8; i++) { curr_process->file_fds[i].file_op = NULL; curr_process->file_fds[i].inode_ptr = NULL; curr_process->file_fds[i].file_pos = 0; curr_process->file_fds[i].flags = 0; } task_queue[next_available] = process_id; next_available = (next_available + 1) % 7; stdin(0); //kernel should automatically open stdin and stdout stdout(1); //which correspond to fd 0 and 1 respectively task_queue[next_available] = process_id; next_available = (next_available + 1) % 7; // Setting TSS tss.esp0 = curr_process->k_sp; // This is good code tss.ss0 = KERNEL_DS; if(previous_pcb != NULL) { asm volatile("movl %%esp, %0":"=g"(previous_pcb->k_sp)); asm volatile("movl %%ebp, %0":"=g"(previous_pcb->k_bp)); } // Jump to program and being executions jump_to_userspace(entry_addr); // Halt jumps here for finishing execute asm volatile("ret_halt:\n\t"); return retval; }