Added comments and help commands to user apps

This commit is contained in:
iDunnoDev
2023-01-13 17:37:43 +00:00
committed by iDunnoDev
parent c23d669858
commit f74cebc12d
11 changed files with 197 additions and 55 deletions

View File

@ -225,8 +225,8 @@ QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
then echo "-gdb tcp::$(GDBPORT)"; \ then echo "-gdb tcp::$(GDBPORT)"; \
else echo "-s -p $(GDBPORT)"; fi) else echo "-s -p $(GDBPORT)"; fi)
ifndef CPUS ifndef CPUS
#CPUS := 2 CPUS := 2
CPUS := 1 # For debugging #CPUS := 1 # For debugging
endif endif
QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA) QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA)

168
console.c
View File

@ -20,7 +20,7 @@
#define MENUWIDTH 27 #define MENUWIDTH 27
// Number of max consoles + 1 for bottom border and another 2 for a space between top and bottom // Number of max consoles + 1 for bottom border and another 2 for a space between top and bottom
#define MENUHEIGHT (MAXVCONSOLES + 3); #define MENUHEIGHT (MAXVCONSOLES + 3);
// Vars to hold the current menu item and menu active bool
static int currentmenuitem = 0; static int currentmenuitem = 0;
static int menuactive = 0; static int menuactive = 0;
@ -36,6 +36,7 @@ struct kbdbuffer inputBuffer;
struct kbdbuffer *input = 0; struct kbdbuffer *input = 0;
// Struct to hold the variables needed for a virtual console
struct vconsole struct vconsole
{ {
uint consoleindex; uint consoleindex;
@ -46,9 +47,11 @@ struct vconsole
int pos; int pos;
int active; int active;
int inuse; int inuse;
// Variables for the title bar, this can be manual set and locked, if not the current process is used
uint titlebgcol; uint titlebgcol;
char proctitle[20]; char proctitle[20];
int titlelocked; int titlelocked;
// Status for possible future use with the title bar to allow a proccess to set messages to print
char status[30]; char status[30];
}; };
@ -80,6 +83,7 @@ static struct
int locking; int locking;
} vcons; } vcons;
// Static function for getting the current count of active consoles
static int getcurrentactiveconsolecount(void) static int getcurrentactiveconsolecount(void)
{ {
int resultcount = 0; int resultcount = 0;
@ -94,6 +98,7 @@ static int getcurrentactiveconsolecount(void)
return resultcount; return resultcount;
} }
// Function to get the menu index of an active console because they might be offset
static int getconsolemenuindex(struct vconsole* consolein) static int getconsolemenuindex(struct vconsole* consolein)
{ {
int resultcount = 0; int resultcount = 0;
@ -112,6 +117,7 @@ static int getconsolemenuindex(struct vconsole* consolein)
return resultcount; return resultcount;
} }
// Function for getting the console at the given menu index
static int getmenuindexconsole(int menuindex) static int getmenuindexconsole(int menuindex)
{ {
int resultcount = 0; int resultcount = 0;
@ -135,6 +141,7 @@ static int getmenuindexconsole(int menuindex)
return resultconsoleindex; return resultconsoleindex;
} }
// Function for getting a consoles index
int getconsoleindex(struct vconsole* consolein) int getconsoleindex(struct vconsole* consolein)
{ {
return consolein->consoleindex; return consolein->consoleindex;
@ -173,6 +180,7 @@ static int itoa(int xx, int base, int sign, char* buf)
return i; return i;
} }
// Function for printing an integer as a string to the screen
static void printint(int xx, int base, int sign) static void printint(int xx, int base, int sign)
{ {
int i = 0; int i = 0;
@ -256,6 +264,8 @@ void cprintf(char *fmt, ...)
} }
} }
// Function to provide the same string manipulation as cprint but saving to the given buffer so it can be used without printing to the screen
// sprintf is the c function that normally does this so i used the same name here
void sprintf(char* strbuffer, char *fmt, ...) void sprintf(char* strbuffer, char *fmt, ...)
{ {
int i, c, si; int i, c, si;
@ -401,28 +411,40 @@ struct vconsole* getvalidprocessconsoleptr(void)
static ushort *crt = (ushort *)P2V(0xb8000); // CGA memory static ushort *crt = (ushort *)P2V(0xb8000); // CGA memory
// Function for drawing the menu onto the screen
static void drawmenu(void) static void drawmenu(void)
{ {
struct vconsole* inconsoleptr = getvalidprocessconsoleptr(); struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
// Rows = the number of active consoles + 1 for the padding at the top, 1 for the padding at the bottom and 1 for the border
int rows = getcurrentactiveconsolecount() + 3; int rows = getcurrentactiveconsolecount() + 3;
int pos = TITLEOFF; int pos = TITLEOFF;
uint c = 0; uint c = 0;
// Small buffer to hold the menu memory
char menulines[MAXVCONSOLES][24]; char menulines[MAXVCONSOLES][24];
// Setup our menu item line strings
int menuindex = 0;
for (int i = 0; i < MAXVCONSOLES; i++) for (int i = 0; i < MAXVCONSOLES; i++)
{ {
if (consoles[i].active) if (consoles[i].active)
{ {
memset(menulines[i], 0, sizeof(menulines[i][0]) * sizeof(menulines[i])); memset(menulines[menuindex], 0, sizeof(menulines[i][0]) * sizeof(menulines[i]));
sprintf(menulines[i], "%d: %s", consoles[i].consoleindex, consoles[i].proctitle); sprintf(menulines[menuindex], "%d: %s", consoles[i].consoleindex, consoles[i].proctitle);
if (consoles[i].inuse)
{
currentmenuitem = menuindex;
}
menuindex++;
} }
} }
// Draw the rows for the menu
for (int y = 0; y < rows; y++) for (int y = 0; y < rows; y++)
{ {
pos = TITLEOFF + (y * SCRWIDTH); pos = TITLEOFF + (y * SCRWIDTH);
for (int x = 0; x < MENUWIDTH; x++) for (int x = 0; x < MENUWIDTH; x++)
{ {
// Top line and the 2nd to last line are padding, we just draw spaces and the first and last x are the border character
if (y == 0 || y == (rows - 2)) if (y == 0 || y == (rows - 2))
{ {
if (x == 0 || x == (MENUWIDTH - 1)) if (x == 0 || x == (MENUWIDTH - 1))
@ -434,10 +456,12 @@ static void drawmenu(void)
c = 0x0720; c = 0x0720;
} }
} }
// The last row is the bottom border, so we can just fill it with the border character
else if (y == (rows - 1)) else if (y == (rows - 1))
{ {
c = 0xB2 | inconsoleptr->titlebgcol; c = 0xB2 | inconsoleptr->titlebgcol;
} }
// Otherwise we draw the border chars and padding space with the console menu item string between
else else
{ {
if (x == 0 || x == (MENUWIDTH - 1)) if (x == 0 || x == (MENUWIDTH - 1))
@ -471,6 +495,7 @@ static void drawmenu(void)
menuactive = 1; menuactive = 1;
} }
// Function that handles the moving of the highlight bar for the menu
static void navigatemenu(int dir) static void navigatemenu(int dir)
{ {
int pos = 0; int pos = 0;
@ -486,14 +511,18 @@ static void navigatemenu(int dir)
newindex = totalactiveconsoles - 1; newindex = totalactiveconsoles - 1;
} }
// make sure the new index isnt just the same as the current selected menu item, we then change the background bits around
// which saves us from redrawing the menu every time the selected item changes
if (newindex != currentmenuitem) if (newindex != currentmenuitem)
{ {
// change the background bits of the last selected item to black
pos = TITLEOFF + ((currentmenuitem + 1) * SCRWIDTH); pos = TITLEOFF + ((currentmenuitem + 1) * SCRWIDTH);
for (int x = 2; x < MENUWIDTH - 2; x++) for (int x = 2; x < MENUWIDTH - 2; x++)
{ {
crt[pos + x] = (crt[pos + x] & 0x00FF) | 0x0700; crt[pos + x] = (crt[pos + x] & 0x00FF) | 0x0700;
} }
// change the background bits of the new selected item to the highlight color
pos = TITLEOFF + ((newindex + 1) * SCRWIDTH); pos = TITLEOFF + ((newindex + 1) * SCRWIDTH);
for (int x = 2; x < MENUWIDTH - 2; x++) for (int x = 2; x < MENUWIDTH - 2; x++)
{ {
@ -504,6 +533,7 @@ static void navigatemenu(int dir)
} }
} }
// Function that closes the menu and reloads the buffer into screen memory
static void closemenu(void) static void closemenu(void)
{ {
loadscreenbuffer(currentconsole->screenbuffer); loadscreenbuffer(currentconsole->screenbuffer);
@ -517,42 +547,51 @@ static void closemenu(void)
menuactive = 0; menuactive = 0;
} }
// Function for drawing the title bar of the current console
static void drawtitle(void) static void drawtitle(void)
{ {
struct vconsole* inconsoleptr = getvalidprocessconsoleptr(); struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
int pos = 0; int pos = 0;
char c = ' '; char c = ' ';
// Setup the title bar strings to print
char menutext[] = "(M)enu"; char menutext[] = "(M)enu";
char consoletitletext[10]; // + (inconsoleptr->consoleindex + 1); char consoletitletext[10]; // + (inconsoleptr->consoleindex + 1);
sprintf(consoletitletext, "Console %d", inconsoleptr->consoleindex); sprintf(consoletitletext, "Console %d", inconsoleptr->consoleindex);
// Loop through the top row and write the current character to the screen buffer
for (pos = 0; pos < SCRWIDTH; pos++) for (pos = 0; pos < SCRWIDTH; pos++)
{ {
int offset = 0; int offset = 0;
// Print the menu text
if (pos < 6) { if (pos < 6) {
c = menutext[pos - offset]; c = menutext[pos - offset];
} }
// Print the console title
else if (pos >= 10 && pos < 20) else if (pos >= 10 && pos < 20)
{ {
offset = 10; offset = 10;
c = consoletitletext[pos - offset]; c = consoletitletext[pos - offset];
} }
// Print the process/title name
else if (pos >= 25 && pos < 45) else if (pos >= 25 && pos < 45)
{ {
offset = 25; offset = 25;
c = inconsoleptr->proctitle[pos - offset]; c = inconsoleptr->proctitle[pos - offset];
} }
// Print the status (not current in use)
else if (pos >= 50 && pos < 80) else if (pos >= 50 && pos < 80)
{ {
offset = 50; offset = 50;
c = inconsoleptr->status[pos - offset]; c = inconsoleptr->status[pos - offset];
} }
// Otherwise print a space character so we still get the background
else else
{ {
c = ' '; c = ' ';
} }
// Print the actual character with the given bg and fg color settings
if (inconsoleptr->inuse) if (inconsoleptr->inuse)
{ {
crt[pos] = (c & 0xff) | inconsoleptr->titlebgcol; crt[pos] = (c & 0xff) | inconsoleptr->titlebgcol;
@ -561,6 +600,7 @@ static void drawtitle(void)
} }
} }
// Function for printing a character to the screen and/or the current console buffer
static void cgaputc(int c) static void cgaputc(int c)
{ {
int pos; int pos;
@ -568,6 +608,7 @@ static void cgaputc(int c)
ushort *currentbuffer = inconsoleptr->screenbuffer; ushort *currentbuffer = inconsoleptr->screenbuffer;
// if the console is inuse we get the hardware cursor position so we can use it
if (inconsoleptr->inuse) if (inconsoleptr->inuse)
{ {
// Cursor position: col + 80*row. // Cursor position: col + 80*row.
@ -576,6 +617,7 @@ static void cgaputc(int c)
outb(CRTPORT, 15); outb(CRTPORT, 15);
pos |= inb(CRTPORT + 1); pos |= inb(CRTPORT + 1);
} }
// If the console is not in use we use the position saved to the console struct
else else
{ {
pos = inconsoleptr->pos; pos = inconsoleptr->pos;
@ -587,6 +629,7 @@ static void cgaputc(int c)
} }
else if (c == BACKSPACE) else if (c == BACKSPACE)
{ {
// Check that the pos is not in the title offset so they cant remove it
if (pos > (TITLEOFF)) if (pos > (TITLEOFF))
{ {
currentbuffer[pos] = 0; // Clear the character from the buffer currentbuffer[pos] = 0; // Clear the character from the buffer
@ -595,19 +638,22 @@ static void cgaputc(int c)
} }
else else
{ {
// int posp = pos; // If the console is inuse print the character to the screen
if (inconsoleptr->inuse) if (inconsoleptr->inuse)
{ {
crt[pos] = (c & 0xff) | 0x0700; // black on white crt[pos] = (c & 0xff) | 0x0700; // black on white
} }
// Save the current character to the console buffer
currentbuffer[pos] = (c & 0xff) | 0x0700; // black on white currentbuffer[pos] = (c & 0xff) | 0x0700; // black on white
pos++; pos++;
} }
// Check that the pos is not in the title area or greater than the screen size
if (pos < TITLEOFF || pos > SCRHEIGHT * SCRWIDTH) if (pos < TITLEOFF || pos > SCRHEIGHT * SCRWIDTH)
{ {
panic("pos under/overflow"); panic("pos under/overflow");
} }
// Handle the overflow scrolling for the screen and buffer
if ((pos / 80) >= 24) if ((pos / 80) >= 24)
{ // Scroll up. { // Scroll up.
memmove(currentbuffer + TITLEOFF, currentbuffer + (SCRWIDTH + TITLEOFF), sizeof(crt[0]) * (SCRHEIGHT - 1) * SCRWIDTH); memmove(currentbuffer + TITLEOFF, currentbuffer + (SCRWIDTH + TITLEOFF), sizeof(crt[0]) * (SCRHEIGHT - 1) * SCRWIDTH);
@ -615,6 +661,7 @@ static void cgaputc(int c)
memset(currentbuffer + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos)); memset(currentbuffer + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos));
if (inconsoleptr->inuse) if (inconsoleptr->inuse)
{ {
// Check if the menu is active, if so we want to offset the scrolling start pos so we dont overwrite the menu in screen memory
int menuoffset = 0; int menuoffset = 0;
if (menuactive) if (menuactive)
{ {
@ -629,6 +676,8 @@ static void cgaputc(int c)
memset(crt + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos)); memset(crt + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos));
} }
} }
// Set the consoles pos to the new pos, if the console was in use also save the hardware cursor pos
inconsoleptr->pos = pos; inconsoleptr->pos = pos;
if (inconsoleptr->inuse) if (inconsoleptr->inuse)
@ -692,20 +741,24 @@ void consoleintr(int (*getc)(void))
int doconsoleswitch = 0; int doconsoleswitch = 0;
int switchto = -1; int switchto = -1;
int doconsolehome = 0; int doconsolehome = 0;
//struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
struct kbdbuffer* consolekbdbuffer = &currentconsole->keybuffer; struct kbdbuffer* consolekbdbuffer = &currentconsole->keybuffer;
acquire(&cons.lock); acquire(&cons.lock);
while ((c = getc()) >= 0) while ((c = getc()) >= 0)
{ {
switch (c) switch (c)
{ {
// Hotkeys for dealing with the menu
// Close the menu
case 27: case 27:
if (menuactive) if (menuactive)
{ {
closemenu(); closemenu();
} }
break; break;
// Menu nav to the previous item
// Up arrow (found in kbd.h) // Up arrow (found in kbd.h)
case 0xE2: case 0xE2:
if (menuactive) if (menuactive)
@ -713,6 +766,7 @@ void consoleintr(int (*getc)(void))
navigatemenu(-1); navigatemenu(-1);
} }
break; break;
// Menu nav to the next item
// Down arrow (found in kbd.h) // Down arrow (found in kbd.h)
case 0xE3: case 0xE3:
if (menuactive) if (menuactive)
@ -740,12 +794,15 @@ void consoleintr(int (*getc)(void))
consputc(BACKSPACE); consputc(BACKSPACE);
} }
break; break;
// Hotkey to switch to the next console
case C('T'): case C('T'):
doconsoleswitch = 1; doconsoleswitch = 1;
break; break;
// Hotkey to switch to the home console
case C('K'): case C('K'):
doconsolehome = 1; doconsolehome = 1;
break; break;
// Hotkey open the menu
case C('M'): case C('M'):
if (!menuactive) if (!menuactive)
{ {
@ -766,31 +823,35 @@ void consoleintr(int (*getc)(void))
// The menu has been sorted we can break from the switch // The menu has been sorted we can break from the switch
break; break;
} }
// if the menu was not active we want the enter to be handled in the default case // if the menu was not active we want the enter to be handled in the default case
default: default:
if (!menuactive) if (!menuactive)
{ {
if (c != 0 && consolekbdbuffer->e - consolekbdbuffer->r < INPUT_BUF) if (inconsoleptr->inuse)
{ {
c = (c == '\r') ? '\n' : c; if (c != 0 && consolekbdbuffer->e - consolekbdbuffer->r < INPUT_BUF)
consolekbdbuffer->buf[consolekbdbuffer->e++ % INPUT_BUF] = c;
consputc(c);
if (c == '\n' || c == C('D') || consolekbdbuffer->e == consolekbdbuffer->r + INPUT_BUF)
{ {
consolekbdbuffer->w = consolekbdbuffer->e; c = (c == '\r') ? '\n' : c;
wakeup(&(consolekbdbuffer->r)); consolekbdbuffer->buf[consolekbdbuffer->e++ % INPUT_BUF] = c;
consputc(c);
if (c == '\n' || c == C('D') || consolekbdbuffer->e == consolekbdbuffer->r + INPUT_BUF)
{
consolekbdbuffer->w = consolekbdbuffer->e;
wakeup(&(consolekbdbuffer->r));
}
} }
} }
} }
break; break;
} }
} }
release(&cons.lock); release(&cons.lock);
if (doprocdump && !menuactive) if (doprocdump && !menuactive)
{ {
procdump(); // now call procdump() wo. cons.lock held procdump(); // now call procdump() wo. cons.lock held
} }
// Handle the home console hotkey
if (doconsolehome) if (doconsolehome)
{ {
if (currentconsole->consoleindex != 0) if (currentconsole->consoleindex != 0)
@ -798,9 +859,11 @@ void consoleintr(int (*getc)(void))
switchtoconsole(getbaseconsoleptr()); switchtoconsole(getbaseconsoleptr());
} }
} }
// Handle the console switch hotkey
if (doconsoleswitch) if (doconsoleswitch)
{ {
struct vconsole* toconsole = 0; struct vconsole* toconsole = 0;
acquire(&vcons.lock);
acquire(&cons.lock); acquire(&cons.lock);
if (switchto == -1) if (switchto == -1)
{ {
@ -822,6 +885,7 @@ void consoleintr(int (*getc)(void))
toconsole = &consoles[getmenuindexconsole(switchto)]; toconsole = &consoles[getmenuindexconsole(switchto)];
} }
release(&cons.lock); release(&cons.lock);
release(&vcons.lock);
if (!toconsole->inuse) if (!toconsole->inuse)
{ {
switchtoconsole(toconsole); switchtoconsole(toconsole);
@ -837,8 +901,7 @@ int consoleread(struct inode *ip, char *dst, int n)
struct kbdbuffer* consolekbdbuffer = &inconsoleptr->keybuffer; struct kbdbuffer* consolekbdbuffer = &inconsoleptr->keybuffer;
iunlock(ip); iunlock(ip);
target = n; target = n;
//acquire(&cons.lock);
acquire(&inconsoleptr->lock); acquire(&inconsoleptr->lock);
while (n > 0) while (n > 0)
{ {
@ -869,8 +932,7 @@ int consoleread(struct inode *ip, char *dst, int n)
{ {
break; break;
} }
} }
//release(&cons.lock);
release(&inconsoleptr->lock); release(&inconsoleptr->lock);
ilock(ip); ilock(ip);
@ -882,14 +944,12 @@ int consolewrite(struct inode *ip, char *buf, int n)
int i; int i;
struct vconsole* inconsoleptr = getvalidprocessconsoleptr(); struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
iunlock(ip); iunlock(ip);
//acquire(&cons.lock);
acquire(&inconsoleptr->lock); acquire(&inconsoleptr->lock);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
consputc(buf[i] & 0xff); consputc(buf[i] & 0xff);
} }
//release(&cons.lock);
release(&inconsoleptr->lock); release(&inconsoleptr->lock);
ilock(ip); ilock(ip);
@ -916,29 +976,34 @@ void testfillbuffer(ushort *bufferin)
} }
} }
// Function to get a pointer to the base console
struct vconsole* getbaseconsoleptr(void) struct vconsole* getbaseconsoleptr(void)
{ {
return &consoles[0]; return &consoles[0];
} }
// Function to clear a given buffer using its pointer/address
void clearconsole(ushort *bufferin) void clearconsole(ushort *bufferin)
{ {
// Flood the screen buffer with blank spaces // Flood the screen buffer with blank spaces
memset(bufferin, 0, sizeof(bufferin[0]) * SCRHEIGHT * SCRWIDTH); memset(bufferin, 0, sizeof(bufferin[0]) * SCRHEIGHT * SCRWIDTH);
} }
// Function for loading an entire buffer into the screen memory using its pointer/address
void loadscreenbuffer(ushort *bufferin) void loadscreenbuffer(ushort *bufferin)
{ {
// Copy the memory from the console buffer to the crt buffer // Copy the memory from the console buffer to the crt buffer
memmove(crt, bufferin, sizeof(bufferin[0]) * SCRHEIGHT * SCRWIDTH); memmove(crt, bufferin, sizeof(bufferin[0]) * SCRHEIGHT * SCRWIDTH);
} }
// Function for saving the current screen memory into a given buffer
void savescreenbuffer(ushort *bufferin) void savescreenbuffer(ushort *bufferin)
{ {
// Copy the memory from the console buffer to the crt buffer // Copy the memory from the console buffer to the crt buffer
memmove(bufferin, crt, sizeof(crt[0]) * SCRHEIGHT * SCRWIDTH); memmove(bufferin, crt, sizeof(crt[0]) * SCRHEIGHT * SCRWIDTH);
} }
// Function for clearing the current screen/buffer
void clearscreen(int prelocked) void clearscreen(int prelocked)
{ {
// Check if a process has actually been created otherwise use the base console // Check if a process has actually been created otherwise use the base console
@ -952,6 +1017,7 @@ void clearscreen(int prelocked)
clearconsole(inconsoleptr->screenbuffer); clearconsole(inconsoleptr->screenbuffer);
inconsoleptr->pos = pos; inconsoleptr->pos = pos;
// If the console is in use load the blank buffer into screen memory and set the cursor position
if (inconsoleptr->inuse) if (inconsoleptr->inuse)
{ {
loadscreenbuffer(inconsoleptr->screenbuffer); loadscreenbuffer(inconsoleptr->screenbuffer);
@ -961,6 +1027,8 @@ void clearscreen(int prelocked)
outb(CRTPORT, 15); outb(CRTPORT, 15);
outb(CRTPORT + 1, pos); outb(CRTPORT + 1, pos);
} }
// Draw the title bar onto the console
drawtitle(); drawtitle();
if (!prelocked) if (!prelocked)
{ {
@ -973,6 +1041,7 @@ void consoleinit(void)
initlock(&cons.lock, "console"); initlock(&cons.lock, "console");
initlock(&vcons.lock, "vconglobal"); initlock(&vcons.lock, "vconglobal");
// Init all of the virtual console buffers
for (int i = 0; i < MAXVCONSOLES; i++) for (int i = 0; i < MAXVCONSOLES; i++)
{ {
consoles[i].consoleindex = i; consoles[i].consoleindex = i;
@ -997,12 +1066,15 @@ void consoleinit(void)
devsw[CONSOLE].read = consoleread; devsw[CONSOLE].read = consoleread;
cons.locking = 1; cons.locking = 1;
// Clear the screen and print the welcome message
clearscreen(0); clearscreen(0);
cprintf("Welcome! you are currently in the base console\n"); cprintf("Welcome! you are currently in the base console\n");
ioapicenable(IRQ_KBD, 0); ioapicenable(IRQ_KBD, 0);
} }
// Function for "creating" a new console, in reality it sets the first non active console to active and setups the struct
// if none are free it returns a nullptr/zero for the calling function to handle
struct vconsole* newconsole(char* title, int bgpreset) struct vconsole* newconsole(char* title, int bgpreset)
{ {
struct vconsole* result = 0; struct vconsole* result = 0;
@ -1034,6 +1106,7 @@ struct vconsole* newconsole(char* title, int bgpreset)
return result; return result;
} }
// Function to "release" all consoles from inuse, this is to stop the chance of one not clearing and causing an issue with 2 being inuse
void releaseallconsoles(void) void releaseallconsoles(void)
{ {
for (int i = 0; i < MAXVCONSOLES; i++) for (int i = 0; i < MAXVCONSOLES; i++)
@ -1042,20 +1115,22 @@ void releaseallconsoles(void)
} }
} }
// Function for switching to another console using the given pointer
int switchtoconsole(struct vconsole* consoleptr) int switchtoconsole(struct vconsole* consoleptr)
{ {
int pos; int pos;
acquire(&vcons.lock); acquire(&vcons.lock);
// Release all consoles before setting the new one to inuse
releaseallconsoles(); releaseallconsoles();
currentconsole = consoleptr; currentconsole = consoleptr;
currentconsole->inuse = 1; currentconsole->inuse = 1;
//input = &currentconsole->keybuffer;
// ioapicenable(IRQ_KBD, 0);
acquire(&cons.lock); acquire(&cons.lock);
// Load the next console into screen memory
loadscreenbuffer(currentconsole->screenbuffer); loadscreenbuffer(currentconsole->screenbuffer);
// Checks if the console was active, if not its most likely the first switch to this so we clear and print the welcome message
if (!currentconsole->active) if (!currentconsole->active)
{ {
clearscreen(1); clearscreen(1);
@ -1064,6 +1139,7 @@ int switchtoconsole(struct vconsole* consoleptr)
} }
else else
{ {
// If it was already active we just set the cursor position to the one saved in the console struct
pos = currentconsole->pos; pos = currentconsole->pos;
outb(CRTPORT, 14); outb(CRTPORT, 14);
@ -1072,7 +1148,7 @@ int switchtoconsole(struct vconsole* consoleptr)
outb(CRTPORT + 1, pos); outb(CRTPORT + 1, pos);
} }
//drawtitle(); // Remove the menu if it was active and set the console as the current menu item
menuactive = 0; menuactive = 0;
currentmenuitem = getconsolemenuindex(currentconsole); currentmenuitem = getconsolemenuindex(currentconsole);
release(&cons.lock); release(&cons.lock);
@ -1080,17 +1156,19 @@ int switchtoconsole(struct vconsole* consoleptr)
return 0; return 0;
} }
// Function for closing the current console
int closeconsole(void) int closeconsole(void)
{ {
struct vconsole* consoleptr = myproc()->consoleptr; struct vconsole* consoleptr = myproc()->consoleptr;
//cprintf("Console Owner PID: %d\n", consoleptr->processowner->pid);
acquire(&vcons.lock); acquire(&vcons.lock);
// Check if the process exiting is the consoles parent process we clear the buffer and set the active to 0
if (myproc() == consoleptr->processowner) if (myproc() == consoleptr->processowner)
{ {
clearconsole(consoleptr->screenbuffer); clearconsole(consoleptr->screenbuffer);
consoleptr->active = 0; consoleptr->active = 0;
// If the console was in use to switch back to the base console
if (consoleptr->inuse) if (consoleptr->inuse)
{ {
consoleptr->inuse = 0; consoleptr->inuse = 0;
@ -1103,6 +1181,7 @@ int closeconsole(void)
return 0; return 0;
} }
// Function for getting the console index of the current inuse console
int getcurrentconsoleindex(void) int getcurrentconsoleindex(void)
{ {
acquire(&vcons.lock); acquire(&vcons.lock);
@ -1118,19 +1197,20 @@ int getcurrentconsoleindex(void)
return -1; return -1;
} }
// Function for setting the title of a console for the title bar and menu
void setconsoleproctitle(struct vconsole* consoleptr, char* newtitle) void setconsoleproctitle(struct vconsole* consoleptr, char* newtitle)
{ {
if (!consoleptr->titlelocked) if (!consoleptr->titlelocked)
{ {
acquire(&consoleptr->lock); acquire(&vcons.lock);
//Clear the current buffer //Clear the current buffer
memset(consoleptr->proctitle, 0, sizeof(consoleptr->proctitle[0]) * sizeof(consoleptr->proctitle)); memset(consoleptr->proctitle, 0, sizeof(consoleptr->proctitle[0]) * sizeof(consoleptr->proctitle));
//Copy the new title into the console title buffer //Copy the new title into the console title buffer
safestrcpy(consoleptr->proctitle, newtitle, sizeof(consoleptr->proctitle)); safestrcpy(consoleptr->proctitle, newtitle, sizeof(consoleptr->proctitle));
//Redraw the title since its been updated now //Redraw the title since its been updated now
drawtitle(); drawtitle();
release(&consoleptr->lock); release(&vcons.lock);
} }
} }

11
count.c
View File

@ -1,6 +1,8 @@
#include "types.h" #include "types.h"
#include "user.h" #include "user.h"
// Simple user app to do a count from 0 to the given number (1000 by defaulf)
// for testing concurrency
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int countto = 1000; int countto = 1000;
@ -8,6 +10,15 @@ int main(int argc, char *argv[]) {
if (strcmp(argv[i], "-c") == 0) { if (strcmp(argv[i], "-c") == 0) {
countto = atoi(argv[i + 1]); countto = atoi(argv[i + 1]);
} }
else if (strcmp(argv[i], "-help") == 0)
{
printf(1, "Counts from 0 to the given number.\n");
printf(1, "Default: 1000\n");
printf(1, "Options:\n");
printf(1, "-c [Number] : Sets the value to count upto.\n");
exit();
return 0;
}
} }
cls(); cls();

1
exec.c
View File

@ -130,6 +130,7 @@ int exec(char *path, char **argv) {
} }
safestrcpy(curproc->name, last, sizeof(curproc->name)); safestrcpy(curproc->name, last, sizeof(curproc->name));
// If the process is tied to a console update the title to the new process name
if (curproc->consoleptr != 0) if (curproc->consoleptr != 0)
{ {
setconsoleproctitle(curproc->consoleptr, curproc->name); setconsoleproctitle(curproc->consoleptr, curproc->name);

11
hello.c
View File

@ -1,7 +1,18 @@
#include "types.h" #include "types.h"
#include "user.h" #include "user.h"
// User app that was from one of the tutorial but i have since changed it to provide useful information about the current process and console
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-help") == 0)
{
printf(1, "Does a system call that returns the current process and console information, used for debugging.\n");
exit();
return 0;
}
}
greeting(); greeting();
exit(); exit();
} }

23
maze.c
View File

@ -1,9 +1,11 @@
#include "types.h" #include "types.h"
#include "user.h" #include "user.h"
// User app for generating a simple maze similar to the c64 version using the border ascii characters
// This doesnt seem to work on the azure server but left in since i did the work on it...
uint rngnumber(void) uint rngnumber(void)
{ {
// Take from http://stackoverflow.com/questions/1167253/implementation-of-rand // Taken from http://stackoverflow.com/questions/1167253/implementation-of-rand
static unsigned int z1 = 12345, z2 = 12345, z3 = 12345, z4 = 12345; static unsigned int z1 = 12345, z2 = 12345, z3 = 12345, z4 = 12345;
unsigned int b; unsigned int b;
b = ((z1 << 6) ^ z1) >> 13; b = ((z1 << 6) ^ z1) >> 13;
@ -44,12 +46,24 @@ int main(int argc, char *argv[]) {
{ {
seed = atoi(argv[i + 1]); seed = atoi(argv[i + 1]);
} }
else if (strcmp(argv[i], "-help") == 0)
{
printf(1, "Generates X lines of random maze.\n");
printf(1, "Options:\n");
printf(1, "-l [Number] : Sets number of lines to generate for the maze.\n");
printf(1, "-s [Number] : Sets the current seed for the random function.\n");
exit();
return 0;
}
} }
cls(); cls();
greeting();
printf(1, "Start Maze\n"); printf(1, "Start Maze (DISABLED)\n");
printf(1, "This does not work on the azure servers, but it would generate a random x lines of characters to look like a maze, similar to the old c64 basic program.\n");
printf(1, "I could have used the slashes but they look aweful in this font so use the count app instead.\n\n");
exit();
char mazeline[80]; char mazeline[80];
for (int y = 0; y < lines; y++) for (int y = 0; y < lines; y++)
{ {
@ -83,5 +97,6 @@ int main(int argc, char *argv[]) {
sleep(10); sleep(10);
} }
printf(1, "Maze Ended\n"); printf(1, "Maze Ended\n");
exit(); exit();
} }

5
proc.c
View File

@ -142,6 +142,7 @@ void userinit(void) {
safestrcpy(p->name, "initcode", sizeof(p->name)); safestrcpy(p->name, "initcode", sizeof(p->name));
p->cwd = namei("/"); p->cwd = namei("/");
// Set the user init console to the base console
p->consoleptr = getbaseconsoleptr(); p->consoleptr = getbaseconsoleptr();
safestrcpy(p->title, "Shell (Root)", sizeof(p->title)); safestrcpy(p->title, "Shell (Root)", sizeof(p->title));
@ -219,6 +220,7 @@ int fork(void) {
acquire(&ptable.lock); acquire(&ptable.lock);
np->state = RUNNABLE; np->state = RUNNABLE;
// Copy the console pointer to the child
np->consoleptr = curproc->consoleptr; np->consoleptr = curproc->consoleptr;
release(&ptable.lock); release(&ptable.lock);
@ -267,11 +269,14 @@ void exit(void) {
} }
} }
// Check if the assigned console is not the base console
if (curproc->consoleptr != getbaseconsoleptr()) if (curproc->consoleptr != getbaseconsoleptr())
{ {
// If so try to close the console, this will only happen if this process is the owner for the console
closeconsole(); closeconsole();
} }
// Update the current process title for its assigned console
if (curproc->consoleptr != 0) if (curproc->consoleptr != 0)
{ {
setconsoleproctitle(curproc->consoleptr, curproc->parent->name); setconsoleproctitle(curproc->consoleptr, curproc->parent->name);

4
proc.h
View File

@ -48,8 +48,8 @@ struct proc {
struct file *ofile[NOFILE]; // Open files struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory struct inode *cwd; // Current directory
char name[16]; // Process name (debugging) char name[16]; // Process name (debugging)
struct vconsole* consoleptr; struct vconsole* consoleptr; // Pointer to the processes assigned console
char title[20]; char title[20]; // the title for the process
}; };
// Process memory is laid out contiguously, low addresses first: // Process memory is laid out contiguously, low addresses first:

View File

@ -23,10 +23,12 @@ int main(int argc, char *argv[]) {
{ {
printf(1, "Creates a new virtual console.\n"); printf(1, "Creates a new virtual console.\n");
printf(1, "Options:\n"); printf(1, "Options:\n");
printf(1, "-bg [0 - 9] : Sets a background preset for the title bar."); printf(1, "-bg [0 - 9] : Sets a background preset for the title bar.\n");
printf(1, "-t [String] : Sets a custom title for the console.\n");
exit(); exit();
return 0; return 0;
} }
// Setup the title, it adds the space seperated strings to the title
else else
{ {
if (accepttitle) if (accepttitle)
@ -50,6 +52,7 @@ int main(int argc, char *argv[]) {
} }
} }
// Set the variable to the selected bg/fg preset option
switch(selopt) switch(selopt)
{ {
case 1: case 1:
@ -81,6 +84,7 @@ int main(int argc, char *argv[]) {
break; break;
} }
// Fork into a new process and create the screen
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
printf(1, "screen: fork failed\n"); printf(1, "screen: fork failed\n");
@ -93,7 +97,7 @@ int main(int argc, char *argv[]) {
} }
else else
{ {
printf(1, "screen: failed to create a new console\n");
} }
} }
exit(); exit();

View File

@ -92,9 +92,10 @@ int sys_uptime(void)
return xticks; return xticks;
} }
// System call i used to debug and test the consoles, it returns useful information in relation to the current console/process
int sys_greeting(void) int sys_greeting(void)
{ {
cprintf("Hello again\n"); cprintf("Hello! here is the info you requested...\n");
cprintf("Using Console: %d\n", getcurrentconsoleindex()); cprintf("Using Console: %d\n", getcurrentconsoleindex());
cprintf("Current PID: %d\n", myproc()->pid); cprintf("Current PID: %d\n", myproc()->pid);
cprintf("Current Parent PID: %d\n", myproc()->parent->pid); cprintf("Current Parent PID: %d\n", myproc()->parent->pid);
@ -102,6 +103,7 @@ int sys_greeting(void)
return 0; return 0;
} }
// System call to shutdown or restart the OS
int sys_shutdown(void) int sys_shutdown(void)
{ {
int restart; int restart;
@ -125,6 +127,7 @@ int sys_shutdown(void)
return 0; return 0;
} }
// System call for handling the new screen user app
int sys_screen(void) int sys_screen(void)
{ {
struct proc *curproc = myproc(); struct proc *curproc = myproc();
@ -133,25 +136,34 @@ int sys_screen(void)
int bgcol; int bgcol;
char *title; char *title;
// Get the background color value
if (argint(1, &bgcol) < 0) if (argint(1, &bgcol) < 0)
{ {
return -1; return -1;
} }
// Get the title arg value
if (argstr(0, &title) < 0) if (argstr(0, &title) < 0)
{ {
return -1; return -1;
} }
// Try to setup an unused console from the pool
if ((consoleptr = newconsole(title, bgcol)) != 0) if ((consoleptr = newconsole(title, bgcol)) != 0)
{ {
// New console was successful, set the pointer and switch to it
curproc->consoleptr = consoleptr; curproc->consoleptr = consoleptr;
switchtoconsole(consoleptr); switchtoconsole(consoleptr);
result = 1; result = 1;
} }
else
{
cprintf("screen: failed to create a new console\n");
}
return result; return result;
} }
// System call to clear the screen
int sys_cls(void) int sys_cls(void)
{ {
clearscreen(0); clearscreen(0);

3
user.h
View File

@ -25,8 +25,11 @@ int sleep(int);
int uptime(void); int uptime(void);
int getch(void); int getch(void);
int greeting(void); int greeting(void);
// function to shutdown
int shutdown(int restart); int shutdown(int restart);
// function to create a new screen
int screen(const char*, int); int screen(const char*, int);
// function to clear the current screen
int cls(void); int cls(void);
// ulib.c // ulib.c