//---------------------------------------------------------------------- // // ProcessGetCodeSizes // // Get the code sizes (stack & data) for a file. A file descriptor // for the named file is returned. This descriptor MUST be closed // (presumably by the caller) at some point. // //---------------------------------------------------------------------- int ProcessGetCodeInfo (const char *file, uint32 *startAddr, uint32 *codeStart, uint32 *codeSize, uint32 *dataStart, uint32 *dataSize) { int fd; int totalsize; char buf[100]; char *pos; // Open the file for reading. If it returns a negative number, the open // didn't work. if ((fd = FsOpen (file, FS_MODE_READ)) < 0) { dbprintf ('f', "ProcessGetCodeInfo: open of %s failed (%d).\n", file, fd); return (-1); } dbprintf ('f', "File descriptor is now %d.\n", fd); if ((totalsize = FsRead (fd, buf, sizeof (buf))) != sizeof (buf)) { dbprintf ('f', "ProcessGetCodeInfo: read got %d (not %d) bytes from %s\n", totalsize, (int)sizeof (buf), file); FsClose (fd); return (-1); } if (dstrstr (buf, "start:") == NULL) { dbprintf ('f', "ProcessGetCodeInfo: %s missing start line (not a DLX executable?)\n", file); return (-1); } pos = (char *)dindex (buf, ':') + 1; // Get the start address and overall size *startAddr = dstrtol (pos, &pos, 16); totalsize = dstrtol (pos, &pos, 16); // Get code & data section start & sizes *codeStart = dstrtol (pos, &pos, 16); *codeSize = dstrtol (pos, &pos, 16); *dataStart = dstrtol (pos, &pos, 16); *dataSize = dstrtol (pos, &pos, 16); // Seek to start of first real line FsSeek (fd, 1 + dindex (buf, '\n') - buf, 0); return (fd); }
int DiskWriteBlock (uint32 blocknum, disk_block *b) { int fsfd = -1; uint32 intrvals = 0; char *filename = NULL; if (blocknum >= DISK_NUMBLOCKS) { printf("DiskWriteBlock: cannot write to block larger than filesystem size\n"); return DISK_FAIL; } // Check that you remembered to rename the filename for your group filename = DISK_FILENAME; if (filename[11] == 'X') { printf("DiskWriteBlock: you didn't change the filesystem filename in include/os/disk.h. Cowardly refusing to do anything.\n"); GracefulExit(); } intrvals = DisableIntrs(); // Open the hard disk file if ((fsfd = FsOpen(DISK_FILENAME, FS_MODE_RW)) < 0) { printf ("DiskWriteBlock: File system %s cannot be opened!\n", DISK_FILENAME); return DISK_FAIL; } /* printf("DiskWriteBlock: fsfd = %d\n", fsfd); */ // Write data to virtual disk FsSeek(fsfd, blocknum * DISK_BLOCKSIZE, FS_SEEK_SET); if (FsWrite(fsfd, b->data, DISK_BLOCKSIZE) != DISK_BLOCKSIZE) { printf ("DiskWriteBlock: Block %d could not be written!\n", blocknum); FsClose (fsfd); return DISK_FAIL; } // Close the hard disk file FsClose (fsfd); RestoreIntrs(intrvals); return DISK_BLOCKSIZE; }
//---------------------------------------------------------------------- // // main // // This routine is called when the OS starts up. It allocates a // PCB for the first process - the one corresponding to the initial // thread of execution. Note that the stack pointer is already // set correctly by _osinit (assembly language code) to point // to the stack for the 0th process. This stack isn't very big, // though, so it should be replaced by the system stack of the // currently running process. // //---------------------------------------------------------------------- void main (int argc, char *argv[]) { int i,j; int n; char buf[120]; char *userprog = (char *)0; int base=0; int numargs=0; char allargs[SIZE_ARG_BUFF]; int allargs_offset = 0; debugstr[0] = '\0'; printf ("Got %d arguments.\n", argc); printf ("Available memory: 0x%x -> 0x%x.\n", (int)lastosaddress, MemoryGetSize ()); printf ("Argument count is %d.\n", argc); for (i = 0; i < argc; i++) { printf ("Argument %d is %s.\n", i, argv[i]); } FsModuleInit (); for (i = 0; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'D': dstrcpy (debugstr, argv[++i]); break; case 'i': n = dstrtol (argv[++i], (void *)0, 0); ditoa (n, buf); printf ("Converted %s to %d=%s\n", argv[i], n, buf); break; case 'f': { int start, codeS, codeL, dataS, dataL, fd, j; int addr = 0; static unsigned char buf[200]; fd = ProcessGetCodeInfo (argv[++i], &start, &codeS, &codeL, &dataS, &dataL); printf ("File %s -> start=0x%08x\n", argv[i], start); printf ("File %s -> code @ 0x%08x (size=0x%08x)\n", argv[i], codeS, codeL); printf ("File %s -> data @ 0x%08x (size=0x%08x)\n", argv[i], dataS, dataL); while ((n = ProcessGetFromFile (fd, buf, &addr, sizeof (buf))) > 0) { for (j = 0; j < n; j += 4) { printf ("%08x: %02x%02x%02x%02x\n", addr + j - n, buf[j], buf[j+1], buf[j+2], buf[j+3]); } } close (fd); break; } case 'u': userprog = argv[++i]; base = i; // Save the location of the user program's name break; default: printf ("Option %s not recognized.\n", argv[i]); break; } if(userprog) break; } } dbprintf ('i', "About to initialize queues.\n"); AQueueModuleInit (); dbprintf ('i', "After initializing queues.\n"); MemoryModuleInit (); dbprintf ('i', "After initializing memory.\n"); ProcessModuleInit (); dbprintf ('i', "After initializing processes.\n"); SynchModuleInit (); dbprintf ('i', "After initializing synchronization tools.\n"); KbdModuleInit (); dbprintf ('i', "After initializing keyboard.\n"); ClkModuleInit (); dbprintf ('i', "After initializing clock.\n"); for (i = 0; i < 100; i++) { buf[i] = 'a'; } i = FsOpen ("vm", FS_MODE_WRITE); dbprintf ('i', "VM Descriptor is %d\n", i); FsSeek (i, 0, FS_SEEK_SET); FsWrite (i, buf, 80); FsClose (i); // Setup command line arguments if (userprog != (char *)0) { numargs=0; allargs_offset = 0; // Move through each of the argv addresses for(i=0; i<argc-base; i++) { // At each argv address, copy the string into allargs, including the '\0' for(j=0; allargs_offset < SIZE_ARG_BUFF; j++) { allargs[allargs_offset++] = argv[i+base][j]; if (argv[i+base][j] == '\0') break; // end of this string } numargs++; } allargs[SIZE_ARG_BUFF-1] = '\0'; // set last char to NULL for safety ProcessFork(0, (uint32)allargs, userprog, 1); } else { dbprintf('i', "No user program passed!\n"); } ClkStart(); dbprintf ('i', "Set timer quantum to %d, about to run first process.\n", processQuantum); intrreturn (); // Should never be called because the scheduler exits when there // are no runnable processes left. exitsim(); // NEVER RETURNS! }
//---------------------------------------------------------------------- // // ProcessGetFromFile // // Inputs: // addr - points to an integer that contains the address of // the byte past that previously returned. If this is the // first call to this routine, *addr should be set to 0. // fd - File descriptor from which to read data. The file format // is the same as that used by the DLX simulator. // buf - points to a buffer that will receive data from the input // file. Note that the data is NOT 0-terminated, and may // include any number of 0 bytes. // max - maximum length of data to return. The routine collects data // until either the address changes or it has read max bytes. // // Returns the number of bytes actually stored into buf. In addition, // *addr is updated to point to the byte following the last byte in // the buffer. // // Load a file into memory. The file format consists of a // leading address, followed by a colon, followed by the data // to go at that address. If the address is omitted, the data // follows that from the previous line of the file. // //---------------------------------------------------------------------- int ProcessGetFromFile (int fd, unsigned char *buf, uint32 *addr, int max) { char localbuf[204]; int nbytes; int seekpos; unsigned char *pos = buf; char *lpos = localbuf; // Remember our position at the start of the routine so we can adjust // it later. seekpos = FsSeek (fd, 0, FS_SEEK_CUR); // The maximum number of characters we could read is limited to the // maximum buffer space available to the caller * 2 because each 2 // characters in the input file result in a single byte of program // info being read in. max = max * 2; // If the callers maximum is greater than the available buffer space, // limit the buffer space further. if (max > (sizeof(localbuf)-4)) { max = sizeof(localbuf)-4; } if ((nbytes = FsRead (fd, localbuf, max)) <= 0) { return (0); } // 'Z' is unused in load file, so use it to mark the end of the buffer // Back up until just after the last newline in the data we read. dbprintf ('f', "Got %d bytes at offset %d ...", nbytes, seekpos); while (localbuf[--nbytes] != '\n') { } localbuf[nbytes+1] = 'Z'; localbuf[nbytes+2] = '\0'; dbprintf ('f', " terminated at %d.\n", nbytes); dbprintf ('f', "Buffer is '%s'\n", localbuf); nbytes = 0; while (dindex (lpos, 'Z') != NULL) { if (dindex (lpos, ':') == NULL) { break; } if (*lpos != ':') { // If we're going to go to a new address, we break out of the // loop and return what we've got already. if (nbytes > 0) { break; } *addr = dstrtol (lpos, &lpos, 16); dbprintf ('f', "New address is 0x%x.\n", (int)(*addr)); } if (*lpos != ':') { break; } lpos++; // skip past colon while (1) { while (((*lpos) == ' ') || (*lpos == '\t')) { lpos++; } if (*lpos == '\n') { lpos++; break; } else if (!(isxdigit (*lpos) && isxdigit (*(lpos+1)))) { // Exit loop if at least one digit isn't a hex digit. break; } pos[nbytes++] = (getxvalue(*lpos) * 16) + getxvalue(*(lpos+1)); lpos += 2; (*addr)++; } } // Seek to just past the last line we read. FsSeek (fd, seekpos + lpos - localbuf, FS_SEEK_SET); dbprintf ('f', "Seeking to %d and returning %d bytes!\n", (int)(seekpos + lpos - localbuf), nbytes); return (nbytes); }
//---------------------------------------------------------------------- // // main // // This routine is called when the OS starts up. It allocates a // PCB for the first process - the one corresponding to the initial // thread of execution. Note that the stack pointer is already // set correctly by _osinit (assembly language code) to point // to the stack for the 0th process. This stack isn't very big, // though, so it should be replaced by the system stack of the // currently running process. // //---------------------------------------------------------------------- main (int argc, char *argv[]) { int i, j; int n; char buf[120]; char *userprog = (char *)0; static PCB temppcb; uint32 addr; extern void SysprocCreateProcesses (); char *param[12]={NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; int base; debugstr[0] = '\0'; MyFuncRetZero(); printf ("Got %d arguments.\n", argc); printf ("Available memory: 0x%x -> 0x%x.\n", lastosaddress, MemoryGetSize ()); printf ("Argument count is %d.\n", argc); for (i = 0; i < argc; i++) { printf ("Argument %d is %s.\n", i, argv[i]); } // *((int *)0xfff00100) = 't'; FsModuleInit (); for (i = 0; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'D': dstrcpy (debugstr, argv[++i]); break; case 'i': n = dstrtol (argv[++i], (void *)0, 0); ditoa (n, buf); printf ("Converted %s to %d=%s\n", argv[i], n, buf); break; case 'f': { int start, codeS, codeL, dataS, dataL, fd, j; int addr = 0; static unsigned char buf[200]; fd = ProcessGetCodeInfo (argv[++i], &start, &codeS, &codeL, &dataS, &dataL); printf ("File %s -> start=0x%08x\n", argv[i], start); printf ("File %s -> code @ 0x%08x (size=0x%08x)\n", argv[i], codeS, codeL); printf ("File %s -> data @ 0x%08x (size=0x%08x)\n", argv[i], dataS, dataL); while ((n = ProcessGetFromFile (fd, buf, &addr, sizeof (buf))) > 0) { for (j = 0; j < n; j += 4) { printf ("%08x: %02x%02x%02x%02x\n", addr + j - n, buf[j], buf[j+1], buf[j+2], buf[j+3]); } } close (fd); break; } case 'u': userprog = argv[++i]; base = i; break; default: printf ("Option %s not recognized.\n", argv[i]); break; } if(userprog) break; } } dbprintf ('i', "About to initialize queues.\n"); QueueModuleInit (); dbprintf ('i', "After initializing queues.\n"); MemoryModuleInit (); dbprintf ('i', "After initializing memory.\n"); ProcessModuleInit (); dbprintf ('i', "After initializing processes.\n"); ShareModuleInit (); dbprintf ('i', "After initializing shared memory.\n"); SynchModuleInit (); dbprintf ('i', "After initializing synchronization tools.\n"); KbdModuleInit (); dbprintf ('i', "After initializing keyboard.\n"); for (i = 0; i < 100; i++) { buf[i] = 'a'; } i = FsOpen ("vm", FS_MODE_WRITE); dbprintf ('i', "VM Descriptor is %d\n", i); FsSeek (i, 0, FS_SEEK_SET); FsWrite (i, buf, 80); FsClose (i); if (userprog != (char *)0) { for(i=base;i<argc&&i-base<11; i++) { param[i-base] = argv[i]; } process_create(0,0,param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7], param[8], param[9], param[10], param[11]); // ProcessFork (0, (uint32)"Help Me man!", userprog, 1); } SysprocCreateProcesses (); dbprintf ('i', "Created processes - about to set timer quantum.\n"); TimerSet (processQuantum); dbprintf ('i', "Set timer quantum to %d, about to run first process.\n", processQuantum); intrreturn (); // Should never be called because the scheduler exits when there // are no runnable processes left. exitsim(); // NEVER RETURNS! }
off_t lseek(int fd, off_t offset, int whence) { return FsSeek((handle_t) fd, offset, whence); }