//======================== // Allocate a message port //======================== struct MessagePort *AllocMessagePort() { struct MessagePort *temp = (struct MessagePort *)AllocKMem(sizeof(struct MessagePort)); temp->waitingProc = (struct Task *)-1L; temp->msgQueue = 0; return (temp); }
//============================================== // Open the file "path" and assign an FCB to it //============================================== struct FCB *OpenFileByInodeNumber(u_int32_t inode) { struct FCB *fcb = AllocKMem(sizeof(struct FCB)); fcb->inode = AllocKMem(sizeof(struct ext2_inode)); fcb->inodeNumber = inode; GetINode(inode, fcb->inode); fcb->nextFCB = 0; fcb->fileCursor = 0; fcb->bufCursor = 0; fcb->buffer = AllocKMem((size_t)block_size); fcb->bufferIsDirty = 0; fcb->inodeIsDirty = 0; fcb->index1 = fcb->index2 = fcb->index3 = fcb->index4 = 0; fcb->currentBlock = fcb->inode->i_block[0]; ReadBlock(fcb->currentBlock, fcb->buffer); return fcb; }
void InitMem64(void) { PMap = (unsigned short int *) PageMap; firstFreeKMem = (struct MemStruct *) OSHeap; firstFreeKMem->next = 0; firstFreeKMem->size = (long)(PageSize - sizeof(struct MemStruct)); currentTask = (struct Task *) AllocKMem(sizeof(struct Task)); nextpid = 3; runnableTasks = (struct TaskList *) AllocKMem(sizeof(struct TaskList)); runnableTasks->next = NULL; runnableTasks->task = currentTask; allTasks = (struct TaskList *) AllocKMem(sizeof(struct TaskList)); allTasks->task = currentTask; allTasks->next = 0; deadTasks = 0; lowPriTask = NULL; //0L; blockedTasks = NULL; //0L; memorySemaphore = 0; canSwitch = 0; tenths = 0; pass = 0; }
//============================================== // Open the file "path" and assign an FCB to it //============================================== struct FCB *OpenFile(char *path) { struct FCB *fcb = AllocKMem(sizeof(struct FCB)); fcb->inode = AllocKMem(sizeof(struct ext2_inode)); fcb->inodeNumber = GetFileINode(path); if (!fcb->inodeNumber) { DeallocMem(fcb); return (struct FCB *) -ENOENT; } GetINode(fcb->inodeNumber, fcb->inode); fcb->nextFCB = 0; fcb->fileCursor = 0; fcb->bufCursor = 0; fcb->buffer = AllocKMem((size_t)block_size); fcb->bufferIsDirty = 0; fcb->inodeIsDirty = 0; fcb->index1 = fcb->index2 = fcb->index3 = fcb->index4 = 0; fcb->currentBlock = fcb->inode->i_block[0]; ReadBlock(fcb->currentBlock, fcb->buffer); return fcb; }
//================================================ // Read noBytes into buffer from the file fHandle //================================================ long ReadFromFile(struct FCB *fHandle, char *buffer, long noBytes) { long retval = 0; long bytesRead = 0; char done = 0; char *buff; struct Message *FSMsg; if (noBytes == 0) return 0; buff = AllocKMem(PageSize); FSMsg = ALLOCMSG; while (noBytes > PageSize) { FSMsg->nextMessage = 0; FSMsg->byte = READFILE; FSMsg->quad1 = (long) fHandle; FSMsg->quad2 = (long) buff; FSMsg->quad3 = PageSize; SendReceiveMessage(FSPort, FSMsg); copyMem(buff, buffer + bytesRead, (size_t) (FSMsg->quad1)); bytesRead += FSMsg->quad1; noBytes -= PageSize; if (FSMsg->quad1 < PageSize) done = 1; } if (!done) { FSMsg->nextMessage = 0; FSMsg->byte = READFILE; FSMsg->quad1 = (long) fHandle; FSMsg->quad2 = (long) buff; FSMsg->quad3 = noBytes; SendReceiveMessage(FSPort, FSMsg); copyMem(buff, buffer + bytesRead, (size_t) (FSMsg->quad1)); bytesRead += FSMsg->quad1; } retval = bytesRead; DeallocMem(buff); DeallocMem(FSMsg); return (retval); }
//========================================================================= // Fork the current process. // Return the pid of the new process //========================================================================= unsigned short DoFork() { unsigned short pid; struct FCB *fcbin, *fcbout, *fcberr; // Copy task structure, with adjustments struct Task *task = (struct Task *) AllocKMem(sizeof(struct Task)); memcpy((char *) task, (char *) currentTask, sizeof(struct Task)); pid = task->pid = nextpid++; task->currentDirName = AllocKMem( (size_t) strlen(currentTask->currentDirName) + 1); strcpy(task->currentDirName, currentTask->currentDirName); task->parentPort = 0; // Create Page Directory task->cr3 = (long) VCreatePageDir(pid, currentTask->pid); Elf64_Ehdr *header = (Elf64_Ehdr *)UserCode; if ((header->e_ident)[1] != 'E')// Not the best of tests, but good enough CopyPages(UserCode, task); else { Elf64_Phdr *pheadertable = (Elf64_Phdr *)(UserCode + header->e_phoff); int i; for (i = 0; i < header->e_phnum; i++) { if (pheadertable[i].p_type == PT_LOAD) { CopyPages(pheadertable[i].p_vaddr, task); } } } // Copy user stack and kernel stack CopyPages(UserStack, task); //Page Tables to allow access to E1000 /*CreatePTEWithPT((struct PML4 *) task->cr3, registers, (long) registers, 0, 7); CreatePTEWithPT((struct PML4 *) task->cr3, registers + 0x1000, (long) registers + 0x1000, 0, 7); CreatePTEWithPT((struct PML4 *) task->cr3, registers + 0x2000, (long) registers + 0x2000, 0, 7); CreatePTEWithPT((struct PML4 *) task->cr3, registers + 0x3000, (long) registers + 0x3000, 0, 7); CreatePTEWithPT((struct PML4 *) task->cr3, registers + 0x4000, (long) registers + 0x4000, 0, 7); CreatePTEWithPT((struct PML4 *) task->cr3, registers + 0x5000, (long) registers + 0x5000, 0, 7);*/ task->forking = 1; // Create FCBs for STDI, STDOUT, and STDERR // STDIN fcbin = (struct FCB *) AllocKMem(sizeof(struct FCB)); fcbin->fileDescriptor = STDIN; fcbin->deviceType = KBD; task->fcbList = fcbin; // STDOUT fcbout = (struct FCB *) AllocKMem(sizeof(struct FCB)); fcbout->fileDescriptor = STDOUT; fcbout->deviceType = CONS; fcbin->nextFCB = fcbout; //STDERR fcberr = (struct FCB *) AllocKMem(sizeof(struct FCB)); fcberr->fileDescriptor = STDERR; fcberr->deviceType = CONS; fcbout->nextFCB = fcberr; fcberr->nextFCB = 0; task->FDbitmap = 7; // Run the forked process asm("pushf"); asm("cli"); LinkTask(task); asm("popf"); // We want the forked process to return to this point. So we // need to save the registers from here to the new task structure. SaveRegisters(task); // Return 0 to the forked process, the new pid to the forking one. if (pid == currentTask->pid) pid = 0; return pid; }
//=============================================================================== // This loads the program "name" into memory, if it exists. //=============================================================================== long DoExec(char *name, char *environment) { struct FCB *fHandle; long argv, argc; int retval = -ENOEXEC; struct Message *FSMsg = ALLOCMSG; char *kname = AllocKMem((size_t) strlen(name) + 6); // Enough space for "/bin" + name strcpy(kname, "/bin/"); strcat(kname, name); // Open file FSMsg->nextMessage = 0; FSMsg->byte = OPENFILE; FSMsg->quad1 = (long) kname; FSMsg->quad2 = (long) fHandle; SendReceiveMessage(FSPort, FSMsg); fHandle = (struct FCB *) FSMsg->quad1; if ((long) fHandle > 0) { char magic[5]; char executable = 0; (void) SeekFile(FSMsg, fHandle, 10, SEEK_SET); (void) ReadFromFile(fHandle, magic, 4); magic[4] = 0; if (!strcmp(magic, "IJ64")) { (void) SeekFile(FSMsg, fHandle, 0, SEEK_SET); LoadFlat(fHandle); executable = 1; } else { (void) SeekFile(FSMsg, fHandle, 0, SEEK_SET); (void) ReadFromFile(fHandle, magic, 4); if (magic[0] == 0x7F) { (void) SeekFile(FSMsg, fHandle, 0, SEEK_SET); LoadElf(FSMsg, fHandle); executable = 1; } } //Close file and deallocate memory for structures FSMsg->nextMessage = 0; FSMsg->byte = CLOSEFILE; FSMsg->quad1 = (long) fHandle; SendReceiveMessage(FSPort, FSMsg); DeallocMem(kname); DeallocMem(FSMsg); if (executable) { long *l; // Process the arguments for argc and argv // Copy environment string to user data space // It occupies the 81 bytes after the current first free memory currentTask->environment = (void *) currentTask->firstfreemem; memcpy(currentTask->environment, environment, 80); currentTask->firstfreemem += 80; argv = (long) currentTask->environment; argc = ParseEnvironmentString(&argv); argv += 80; // Adjust firstfreemem to point to the first free memory location. currentTask->firstfreemem += argc * sizeof(char *); // Build the first MemStruct struct. Is all this necessary? User tasks don't use the kernel memory allocation, do they? l = (long *) (currentTask->firstfreemem); *l = 0; *(l + 1) = -(long) (((sizeof(struct MemStruct) + currentTask->firstfreemem)) % PageSize); asm("mov %0,%%rdi;" "mov %1,%%rsi": : "r"(argc), "r"(argv):"%rax", "%rdi"); return 0; } else return retval;
//==================================================== // Create a new file. entry for a file of type type // Returns an FCB on success or a negative error code //==================================================== struct FCB *CreateFileWithType(char *name, long type) { char *parentDirectory, *fileName, *dirBuffer; u_int32_t parentINodeNo, inodeNo, i; u_int16_t recLength, sizeOfEntry, sizeOfNewEntry; struct ext2_inode *inode; struct ext2_dir_entry_2 *entry, *newEntry; struct FCB *dirFcb, *fcb; // Does the file already exist? if (GetFileINode(name)) return (struct FCB *) -EEXIST; // Get the INode of the parentdirectory parentDirectory = AllocUMem((size_t)(strlen(name) + 1)); strcpy(parentDirectory, name); fileName = strrchr(parentDirectory, '/'); fileName[0] = 0; fileName++; parentINodeNo = GetFileINode(parentDirectory); if (!parentINodeNo) { DeallocMem(parentDirectory); return (struct FCB *) -ENOENT; } // Create an inode for the new file inode = AllocKMem(sizeof(struct ext2_inode)); memset(inode, 0, sizeof(struct ext2_inode)); inode->i_mode = (u_int16_t)(EXT2_S_IFREG | EXT2_S_IRUSR | EXT2_S_IWUSR | EXT2_S_IRGRP | EXT2_S_IWGRP | EXT2_S_IROTH | EXT2_S_IWOTH); inode->i_atime = inode->i_ctime = inode->i_mtime = (u_int32_t)unixtime; inode->i_dtime = 0; inode->i_links_count = 1; inode->i_blocks = 0; inodeNo = GetFreeINode(0); // Write the new inode to disk PutINode(inodeNo, inode); // Create a directory entry for the new file dirFcb = OpenFileByInodeNumber(parentINodeNo); dirBuffer = AllocUMem(dirFcb->inode->i_size); (void)ReadFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); sizeOfNewEntry = (u_int16_t)(8 + strlen(fileName) + 4 - strlen(fileName) % 4); entry = (struct ext2_dir_entry_2 *) dirBuffer; sizeOfEntry = (u_int16_t)(8 + entry->name_len + 4 - entry->name_len % 4); while (sizeOfEntry + sizeOfNewEntry > entry->rec_len) { entry = (struct ext2_dir_entry_2 *) ((char *) entry + entry->rec_len); sizeOfEntry = (u_int16_t)(8 + entry->name_len + 4 - entry->name_len % 4); } // There's room for the new entry at the end of this record recLength = entry->rec_len; entry->rec_len = sizeOfEntry; newEntry = AllocUMem(sizeof(struct ext2_dir_entry_2)); memset(newEntry, 0, sizeof(struct ext2_dir_entry_2)); newEntry->file_type = (u_int8_t)type; newEntry->inode = (u_int32_t)inodeNo; newEntry->name_len = (u_int8_t)strlen(fileName); newEntry->rec_len = recLength - sizeOfEntry; for (i = 0; i < newEntry->name_len; i++) newEntry->name[i] = fileName[i]; memcpy((char *) entry + sizeOfEntry, newEntry, sizeOfNewEntry); DeallocMem(parentDirectory); // Write the directory buffer back to disk (void)Seek(dirFcb, 0, SEEK_SET); (void)WriteFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); DeallocMem(dirBuffer); (void)CloseFile(dirFcb); // Create a FCB for the new file fcb = AllocKMem(sizeof(struct FCB)); fcb->inode = inode; fcb->inodeNumber = inodeNo; fcb->nextFCB = 0; fcb->fileCursor = 0; fcb->bufCursor = 0; fcb->buffer = AllocKMem((size_t)block_size); fcb->currentBlock = 0; fcb->index1 = fcb->index2 = fcb->index3 = fcb->index4 = 0; return fcb; }
//=============================================== // Delete the file name // Returns 0 on success or a negative error code //=============================================== long DeleteFile(char *name) { char *buffer = AllocKMem(block_size); char *buffer1 = AllocKMem(block_size); __le32 *blocks; __le32 *iblocks; int i, j; char *parentDirectory, *fileName, *dirBuffer; u_int32_t parentINodeNo; struct FCB *fcb, *dirFcb; struct ext2_dir_entry_2 *entry, *prevEntry; // Get the INode of the parentdirectory parentDirectory = AllocUMem((size_t)strlen(name) + 1); strcpy(parentDirectory, name); fileName = strrchr(parentDirectory, '/'); fileName[0] = 0; fileName++; parentINodeNo = GetFileINode(parentDirectory); if (parentINodeNo == (u_int32_t) -ENOENT) { DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); return -ENOENT; } // Now free the blocks allocated to this file fcb = OpenFile(name); if ((long)fcb < 0) { DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); return (long) fcb; } // Delete all direct blocks for (i = 0; i < EXT2_IND_BLOCK; i++) if (fcb->inode->i_block[i]) ClearBlockBitmapBit(fcb->inode->i_block[i]); if (fcb->inode->i_block[EXT2_IND_BLOCK]) { // Delete indirect blocks ReadBlock(fcb->inode->i_block[EXT2_IND_BLOCK], buffer); blocks = (__le32 *) buffer; for (i = 0; i < block_size / sizeof(__le32); i++) if (blocks[i]) ClearBlockBitmapBit(blocks[i]); ClearBlockBitmapBit(fcb->inode->i_block[EXT2_IND_BLOCK]); } if (fcb->inode->i_block[EXT2_DIND_BLOCK]) { // Delete double-indirect blocks ReadBlock(fcb->inode->i_block[EXT2_DIND_BLOCK], buffer); blocks = (__le32 *) buffer; for (i = 0; i < block_size / sizeof(__le32); i++) { if (blocks[i]) { ReadBlock(blocks[i], buffer1); iblocks = (__le32 *) buffer1; for (j = 0; j < block_size / sizeof(__le32); j++) if (iblocks[j]) ClearBlockBitmapBit(iblocks[j]); ClearBlockBitmapBit(blocks[i]); } } ClearBlockBitmapBit(fcb->inode->i_block[EXT2_DIND_BLOCK]); } if (fcb->inode->i_block[EXT2_TIND_BLOCK]) { // Delete triple-indirect blocks } // Find the directory entry for thefile dirFcb = OpenFileByInodeNumber(parentINodeNo); dirBuffer = AllocUMem(dirFcb->inode->i_size); (void)ReadFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); entry = (struct ext2_dir_entry_2 *) dirBuffer; prevEntry = entry; while (strlen(fileName) != entry->name_len || strncmp(entry->name, fileName, entry->name_len)) { if ((long)entry + entry->name_len - (long)dirBuffer > (long)dirFcb->inode->i_size) { DeallocMem(dirBuffer); (void)CloseFile(dirFcb); DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); return -ENOENT; } prevEntry = entry; entry = (struct ext2_dir_entry_2 *) ((char *) entry + entry->rec_len); } // Entry now points to the directory entry for this file, prevEntry to the previous one prevEntry->rec_len += entry->rec_len; (void)Seek(dirFcb, 0, SEEK_SET); (void)WriteFile(dirFcb, dirBuffer, (long)dirFcb->inode->i_size); DeallocMem(dirBuffer); (void)CloseFile(dirFcb); DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); // Finally, delete the inode memset(fcb->inode, 0, sizeof(struct ext2_inode)); PutINode(fcb->inodeNumber, fcb->inode); ClearINodeBitmapBit(fcb->inodeNumber); (void)CloseFile(fcb); return 0; }