diff --git a/MP3/MP3_Sources/BIOS-bochs-latest b/MP3/MP3_Sources/BIOS-bochs-latest new file mode 100755 index 0000000..2cb4488 Binary files /dev/null and b/MP3/MP3_Sources/BIOS-bochs-latest differ diff --git a/MP3/MP3_Sources/README.TXT b/MP3/MP3_Sources/README.TXT new file mode 100755 index 0000000..a847cdb --- /dev/null +++ b/MP3/MP3_Sources/README.TXT @@ -0,0 +1,101 @@ +CSCE 410/611/613: MP2 -- README.TXT + +This file describes the content of this directory. +A file marked with (*) may be of some interest to the +student, and he/she may want to have a look at it. +A file marked with (**) is important for this MP, and the +student is strongly encouraged to study the contents of this file. + +BOCH Environment: +================= + +FILE: DESCRIPTION: + +BIOS-bochs-latest BIOS file. +VGABIOS-lgpl-latest BIOS file for the graphics system. +dev_kernel_grub.img Image file of the boot floopy. +bochsrc.bxrc Description file for the system. + Type 'bochs -f bochsrc.bxrc' to + start emulation. + +COMPILATION: +=========== + +FILE: DESCRIPTION: + +makefile (**) Makefile for Linux 64-bit environment. + Works with the provided linux image. + Type "make" to create the kernel. +linker.ld The linker script. + +OS COMPONENTS: +============= + +FILE: DESCRIPTION: + +start.asm (*) The bootloader starts code in this file, which in turn + jumps to the main entry in File "kernel.C". +kernel.C (**) Main file, where the OS components are set up, and the + system gets going. + +assert.H/C Implements the "assert()" utility. +utils.H/C Various utilities (e.g. memcpy, strlen, + port I/O, etc.) +console.H/C Routines to print to the screen. + +machine.H (*) Definitions of some system constants and low-level + machine operations. + (Primarily memory sizes, register set, and + enable/disable interrupts) +gdt.H/C Global Descriptor Table. +gdt_low.asm Low-level GDT code, included in "start.asm". +idt.H/C Interrupt Descriptor Table. +idt_low.asm Low-level IDT code, included in "start.asm". +irq.H/C mapping of IRQ's into the IDT. +irq_low.asm Low-level IRQ stuff. (Primarily the interrupt service + routines and the routine stub that branches out to the + interrupt dispatcher in "interrupts.C". Included in + "start.asm". + +exceptions.H/C (*) The exception dispatcher. +interrupts.H/C The interrupt dispatcher. + +console.H/C Routines to print to the screen. + +simple_timer.H/C (*) Routines to control the periodic interval + timer. This is an example of an interrupt + handler. + +simple_keyboard.H/C(*) Routines to access the keyboard. Primarily as + way to wait until user presses key. + +machine_low.H/asm Various low-level x86 specific stuff. + +paging_low.H/asm (**) Low-level code to control the registers needed for + memory paging. + +page_table.H/C (**) Definition and empty implementation of a + page table manager. In addition to interface, + the .H file defines a few private members that + should guide the implementation. + +cont_frame_pool.H/C(**) Definition and empty implementation of a + physical frame memory manager that + supports contiguous + allocation. NOTE that the comments in + the implementation file give a recipe + of how to implement such a frame pool. + + +UTILITIES: +========== + +FILE: DESCRIPTION: + +copykernel.sh (**) Simple script to copy the kernel onto + the floppy image. + The script mounts the floppy image, copies the kernel + image onto it, and then unmounts the floppy image again. + In rare cases the paths in the file may need to be + edited to make them reflect the student's environment. + diff --git a/MP3/MP3_Sources/VGABIOS-lgpl-latest b/MP3/MP3_Sources/VGABIOS-lgpl-latest new file mode 100755 index 0000000..646216a Binary files /dev/null and b/MP3/MP3_Sources/VGABIOS-lgpl-latest differ diff --git a/MP3/MP3_Sources/assert.C b/MP3/MP3_Sources/assert.C new file mode 100755 index 0000000..e85ae1d --- /dev/null +++ b/MP3/MP3_Sources/assert.C @@ -0,0 +1,45 @@ +/* + File: assert.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + + Date : 05/01/23 + + Implementation of the assert() function. + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" + +#include "utils.H" +#include "console.H" + +/*--------------------------------------------------------------------------*/ +/* _assert() FUNCTION: gets called when assert() macro fails. */ +/*--------------------------------------------------------------------------*/ + +void _assert (const char* _file, const int _line, const char* _message ) { + /* Prints current file, line number, and failed assertion. */ + char temp[15]; + Console::puts("Assertion failed at file: "); + Console::puts(_file); + Console::puts(" line: "); + int2str(_line, temp); + Console::puts(temp); + Console::puts(" assertion: "); + Console::puts(_message); + Console::puts("\n"); + abort(); +}/* end _assert */ diff --git a/MP3/MP3_Sources/assert.H b/MP3/MP3_Sources/assert.H new file mode 100755 index 0000000..33c7a16 --- /dev/null +++ b/MP3/MP3_Sources/assert.H @@ -0,0 +1,56 @@ +/* + File: assert.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + + Date : 05/01/23 + + Header file for the "assert" macro. + + +*/ + +#ifndef __assert_H__ +#define __assert_H__ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "utils.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* "ASSERT" MACRO */ +/*--------------------------------------------------------------------------*/ + +/* NOTE: The "assert" macros can be turned off by giving the -DNDEBUG + argument when compiling. */ + +#ifdef assert +# undef assert +#endif + +void _assert ( const char* _file, const int _line, const char* _message ); + +#ifdef NDEBUG +# define assert( m ) ( ( void ) 0 ) +#else +# define assert( m ) \ + if ( !(m) ) _assert( __FILE__, __LINE__, #m ); +#endif + +#endif diff --git a/MP3/MP3_Sources/bochsrc.bxrc b/MP3/MP3_Sources/bochsrc.bxrc new file mode 100755 index 0000000..310979c --- /dev/null +++ b/MP3/MP3_Sources/bochsrc.bxrc @@ -0,0 +1,48 @@ +############################################################### +# bochsrc.txt file for DLX Linux disk image. +############################################################### + +# how much memory the emulated machine will have +megs: 32 + +# filename of ROM images +romimage: file=BIOS-bochs-latest +vgaromimage: file=VGABIOS-lgpl-latest + +# what disk images will be used +floppya: 1_44=dev_kernel_grub.img, status=inserted +#floppyb: 1_44=floppyb.img, status=inserted + +# hard disk +#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +#ata0-master: type=disk, path="c.img", cylinders=306, heads=4, spt=17 +# choose the boot disk. +boot: floppy + +# default config interface is textconfig. +#config_interface: textconfig +#config_interface: wx + +#display_library: x +# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga + +# where do we send log messages? +log: bochsout.txt + +# disable the mouse +mouse: enabled=0 + +# enable key mapping, using US layout as default. +# +# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows. +# However, the key mapping tables are used in the paste function, so +# in the DLX Linux example I'm enabling keyboard_mapping so that paste +# will work. Cut&Paste is currently implemented on win32 and X windows only. + +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-fr.map +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-de.map +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-es.map + + +clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000 \ No newline at end of file diff --git a/MP3/MP3_Sources/console.C b/MP3/MP3_Sources/console.C new file mode 100755 index 0000000..2fc0899 --- /dev/null +++ b/MP3/MP3_Sources/console.C @@ -0,0 +1,213 @@ +/* + File: Console.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/02/2009 + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +#define CONSOLE_START_ADDRESS (unsigned short *)0xB8000 + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "console.H" + +#include "utils.H" +#include "machine.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS C o n s o l e */ +/*--------------------------------------------------------------------------*/ + +/* -- GLOBAL VARIABLES -- */ + + int Console::attrib; /* background and foreground color */ + int Console::csr_x; /* position of cursor */ + int Console::csr_y; + unsigned short * Console::textmemptr; /* text pointer */ + +/* -- CONSTRUCTOR -- */ + +void Console::init(unsigned char _fore_color, + unsigned char _back_color) { + set_TextColor(_fore_color, _back_color); + csr_x = 0; + csr_y = 0; + textmemptr = CONSOLE_START_ADDRESS; + cls(); +} + + +void Console::scroll() { + + /* A blank is defined as a space... we need to give it + * backcolor too */ + unsigned blank = 0x20 | (attrib << 8); + + /* Row 25 is the end, this means we need to scroll up */ + if(csr_y >= 25) + { + /* Move the current text chunk that makes up the screen + * back in the buffer by a line */ + unsigned temp = csr_y - 25 + 1; + memcpy ((char*)textmemptr, (char*)(textmemptr + temp * 80), (25 - temp) * 80 * 2); + + /* Finally, we set the chunk of memory that occupies + * the last line of text to our 'blank' character */ + memsetw (textmemptr + (25 - temp) * 80, blank, 80); + csr_y = 25 - 1; + } +} + + +void Console::move_cursor() { + + /* The equation for finding the index in a linear + * chunk of memory can be represented by: + * Index = [(y * width) + x] */ + unsigned temp = csr_y * 80 + csr_x; + + /* This sends a command to indicies 14 and 15 in the + * Console Control Register of the VGA controller. These + * are the high and low bytes of the index that show + * where the hardware cursor is to be 'blinking'. To + * learn more, you should look up some VGA specific + * programming documents. A great start to graphics: + * http://www.brackeen.com/home/vga */ + Machine::outportb(0x3D4, (char)14); + //outportb(0x3D5, temp >> 8); + Machine::outportb(0x3D4, 15); + //outportb(0x3D5, (char)temp); +} + +/* Clear the screen */ +void Console::cls() { + + /* Again, we need the 'short' that will be used to + * represent a space with color */ + unsigned blank = 0x20 | (attrib << 8); + + /* Sets the entire screen to spaces in our current + * color */ + for(int i = 0; i < 25; i++) + memsetw (textmemptr + i * 80, blank, 80); + + /* Update out virtual cursor, and then move the + * hardware cursor */ + csr_x = 0; + csr_y = 0; + move_cursor(); +} + +/* Puts a single character on the screen */ +void Console::putch(const char _c){ + + + /* Handle a backspace, by moving the cursor back one space */ + if(_c == 0x08) + { + if(csr_x != 0) csr_x--; + } + /* Handles a tab by incrementing the cursor's x, but only + * to a point that will make it divisible by 8 */ + else if(_c == 0x09) + { + csr_x = (csr_x + 8) & ~(8 - 1); + } + /* Handles a 'Carriage Return', which simply brings the + * cursor back to the margin */ + else if(_c == '\r') + { + csr_x = 0; + } + /* We handle our newlines the way DOS and the BIOS do: we + * treat it as if a 'CR' was also there, so we bring the + * cursor to the margin and we increment the 'y' value */ + else if(_c == '\n') + { + csr_x = 0; + csr_y++; + } + /* Any character greater than and including a space, is a + * printable character. The equation for finding the index + * in a linear chunk of memory can be represented by: + * Index = [(y * width) + x] */ + else if(_c >= ' ') + { + unsigned short * where = textmemptr + (csr_y * 80 + csr_x); + *where = _c | (attrib << 8); /* Character AND attributes: color */ + csr_x++; + } + + /* If the cursor has reached the edge of the screen's width, we + * insert a new line in there */ + if(csr_x >= 80) + { + csr_x = 0; + csr_y++; + } + + /* Scroll the screen if needed, and finally move the cursor */ + scroll(); + move_cursor(); +} + +/* Uses the above routine to output a string... */ +void Console::puts(const char * _s) { + + for (int i = 0; i < strlen(_s); i++) { + putch(_s[i]); + } +} + +void Console::puti(const int _n) { + char foostr[15]; + + int2str(_n, foostr); + puts(foostr); +} + +void Console::putui(const unsigned int _n) { + char foostr[15]; + + uint2str(_n, foostr); + putch('<'); + puts(foostr); + putch('>'); +} + + +/* -- COLOR CONTROL -- */ +void Console::set_TextColor(const unsigned char _forecolor, + const unsigned char _backcolor) { + /* Top 4 bytes are the background, bottom 4 bytes + * are the foreground color */ + attrib = (_backcolor << 4) | (_forecolor & 0x0F); +} + diff --git a/MP3/MP3_Sources/console.H b/MP3/MP3_Sources/console.H new file mode 100755 index 0000000..aa24fda --- /dev/null +++ b/MP3/MP3_Sources/console.H @@ -0,0 +1,113 @@ +/* + File: Console.H + + Author : R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/02/12 + + The class Console encapsulates the output operations ot the console + screen. Since the console is initialized at the very beginning of the + boot-up of the operating system, when no memory management is available + yet, all functions and storage for the console are static. + + The console is initialized with an "init" function instead of a + constructor. (We don't want to deal with constructors that are called + before the "main()" function.) + + By making all functions static, we can access them across all object + files without having to declare a global Console object or pass pointers + to a locally declared object. + +*/ + +#ifndef _Console_H_ // include file only once +#define _Console_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none -- */ + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +typedef enum { + BLACK = 0, + BLUE = 1, + GREEN = 2, + CYAN = 3, + RED = 4, + MAGENTA = 5, + BROWN = 6, + LIGHT_GREY = 7, + DARK_GREY = 8, + LIGHT_BLUE = 9, + LIGHT_GREEN = 10, + LIGHT_CYAN = 11, + LIGHT_RED = 12, + LIGHT_MAGENTA = 13, + LIGHT_BROWN = 14, + WHITE = 15 +} COLOR_CODE; + + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CLASS C o n s o l e */ +/*--------------------------------------------------------------------------*/ + +class Console { +private: + static int attrib; /* background and foreground color */ + static int csr_x; /* position of cursor */ + static int csr_y; + static unsigned short * textmemptr; /* text pointer */ +public: + + /* -- INITIALIZER (we have no constructor, there is no memory mgmt yet.) */ + static void init(unsigned char _fore_color = WHITE, + unsigned char _back_color = BLACK); + + static void scroll(); + + static void move_cursor(); + /* Update the hardware cursor. */ + + static void cls(); + /* Clear the screen. */ + + static void putch(const char _c); + /* Put a single character on the screen. */ + + static void puts(const char * _s); + /* Display a NULL-terminated string on the screen.*/ + + static void puti(const int _i); + /* Display a integer on the screen.*/ + + static void putui(const unsigned int _u); + /* Display a unsigned integer on the screen.*/ + + static void set_TextColor(unsigned char _fore_color, unsigned char _back_color); + /* Set the color of the foreground and background. */ + +}; + + +#endif + + diff --git a/MP3/MP3_Sources/cont_frame_pool.C b/MP3/MP3_Sources/cont_frame_pool.C new file mode 100644 index 0000000..3c1af89 --- /dev/null +++ b/MP3/MP3_Sources/cont_frame_pool.C @@ -0,0 +1,404 @@ +/* + File: ContFramePool.C + + Author: + Date : + + */ + +/*--------------------------------------------------------------------------*/ +/* + POSSIBLE IMPLEMENTATION + ----------------------- + + The class SimpleFramePool in file "simple_frame_pool.H/C" describes an + incomplete vanilla implementation of a frame pool that allocates + *single* frames at a time. Because it does allocate one frame at a time, + it does not guarantee that a sequence of frames is allocated contiguously. + This can cause problems. + + The class ContFramePool has the ability to allocate either single frames, + or sequences of contiguous frames. This affects how we manage the + free frames. In SimpleFramePool it is sufficient to maintain the free + frames. + In ContFramePool we need to maintain free *sequences* of frames. + + This can be done in many ways, ranging from extensions to bitmaps to + free-lists of frames etc. + + IMPLEMENTATION: + + One simple way to manage sequences of free frames is to add a minor + extension to the bitmap idea of SimpleFramePool: Instead of maintaining + whether a frame is FREE or ALLOCATED, which requires one bit per frame, + we maintain whether the frame is FREE, or ALLOCATED, or HEAD-OF-SEQUENCE. + The meaning of FREE is the same as in SimpleFramePool. + If a frame is marked as HEAD-OF-SEQUENCE, this means that it is allocated + and that it is the first such frame in a sequence of frames. Allocated + frames that are not first in a sequence are marked as ALLOCATED. + + NOTE: If we use this scheme to allocate only single frames, then all + frames are marked as either FREE or HEAD-OF-SEQUENCE. + + NOTE: In SimpleFramePool we needed only one bit to store the state of + each frame. Now we need two bits. In a first implementation you can choose + to use one char per frame. This will allow you to check for a given status + without having to do bit manipulations. Once you get this to work, + revisit the implementation and change it to using two bits. You will get + an efficiency penalty if you use one char (i.e., 8 bits) per frame when + two bits do the trick. + + DETAILED IMPLEMENTATION: + + How can we use the HEAD-OF-SEQUENCE state to implement a contiguous + allocator? Let's look a the individual functions: + + Constructor: Initialize all frames to FREE, except for any frames that you + need for the management of the frame pool, if any. + + get_frames(_n_frames): Traverse the "bitmap" of states and look for a + sequence of at least _n_frames entries that are FREE. If you find one, + mark the first one as HEAD-OF-SEQUENCE and the remaining _n_frames-1 as + ALLOCATED. + + release_frames(_first_frame_no): Check whether the first frame is marked as + HEAD-OF-SEQUENCE. If not, something went wrong. If it is, mark it as FREE. + Traverse the subsequent frames until you reach one that is FREE or + HEAD-OF-SEQUENCE. Until then, mark the frames that you traverse as FREE. + + mark_inaccessible(_base_frame_no, _n_frames): This is no different than + get_frames, without having to search for the free sequence. You tell the + allocator exactly which frame to mark as HEAD-OF-SEQUENCE and how many + frames after that to mark as ALLOCATED. + + needed_info_frames(_n_frames): This depends on how many bits you need + to store the state of each frame. If you use a char to represent the state + of a frame, then you need one info frame for each FRAME_SIZE frames. + + A WORD ABOUT RELEASE_FRAMES(): + + When we releae a frame, we only know its frame number. At the time + of a frame's release, we don't know necessarily which pool it came + from. Therefore, the function "release_frame" is static, i.e., + not associated with a particular frame pool. + + This problem is related to the lack of a so-called "placement delete" in + C++. For a discussion of this see Stroustrup's FAQ: + http://www.stroustrup.com/bs_faq2.html#placement-delete + + */ +/*--------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "cont_frame_pool.H" +#include "console.H" +#include "utils.H" +#include "assert.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS C o n t F r a m e P o o l */ +/*--------------------------------------------------------------------------*/ + +ContFramePool* ContFramePool::pools = (ContFramePool *) FRAME_SIZE; // List of frame pools, managed by the class +unsigned int ContFramePool::nPools = 0; // Number of pools being managed + +ContFramePool::ContFramePool(unsigned long _base_frame_no, + unsigned long _n_frames, + unsigned long _info_frame_no, + unsigned long _n_info_frames) +{ + // Bitmap must fit in a single frame! + // NOTE: In theory, we don't need to make the bitmap any larger, + // since as stated in the instructions it is already big enough to + // hold for 128MB of memory with one bit per frame, so should still + // be enough for 64MB of memory with 2 bits per frame. + // Assertion changed to match max size of frames allowed. + assert(_n_frames <= FRAME_SIZE * 4); + + base_frame_no = _base_frame_no; + nframes = _n_frames; + nFreeFrames = _n_frames; + info_frame_no = _info_frame_no; + n_info_frames = _n_info_frames; + + // If _info_frame_no is zero then we keep management info in the first + // frame(s), else we use the provided frame(s) to keep management info + // NOTE: bitmap needs to be allocated with n_info_frames if specified. + if(info_frame_no == 0) + { + bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE); + } + else + { + bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE * n_info_frames); + } + + // Number of frames must "fill" the bitmap! + assert ((nframes % 8 ) == 0); + + + // Everything ok. Proceed to mark all bits in the bitmap + // NOTE: changed to reflect that I need 2 bits per frame now + for(int i=0; i*4 < _n_frames; i++) + { + bitmap[i] = 0xFF; + } + + // Mark the first frame as being used if it is being used + // NOTE: need to mark multiple frames if needed. + if(info_frame_no == 0) + { + bitmap[0] = 0x3F; + nFreeFrames--; + } + else + { + unsigned int i = info_frame_no / 4; + unsigned int r = info_frame_no % 4; + unsigned char mask = 0x80; + mask = mask >> r*2; + + unsigned int c = 0; + while(c < n_info_frames) + { + bitmap[i] = bitmap[i] ^ mask; + bitmap[i] = bitmap[i] ^ (mask >> 1); + if(mask == 0x02) + { + i++; + mask = 0x80; + } + c++; + nFreeFrames--; + } + + } + + pools[nPools] = *this; + nPools += 1; + + Console::puts("Frame Pool initialized\n"); +} + +unsigned long ContFramePool::get_frames(unsigned int _n_frames) +{ + // Are there enough frames left to allocate? + assert(nFreeFrames > _n_frames); + + // Find a frame that is not being used and return its frame index. + // Mark that frame as being used in the bitmap. + // NOTE: Must be updated to find a sequence of contiguous frames + // that are not being used and return the index of the head. + unsigned int frame_no = base_frame_no; + + // i is being used as the frame_no / 4 + // j is frame_no % 4 + // together, they will give the actual frame_no. + // c is used as a counter to count a squence of free frames. + unsigned int i = 0; + unsigned int j = 0; + unsigned int c = 0; + + while (true) + { + unsigned char mask = 0x80 >> (j*2); + // check every 2 bits for a free frame in the bitmap + while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0) + { + if(mask != 0x02) + { + j++; + mask = mask >> 2; + } + else + { + i++; + j = 0; + mask = 0x80; + } + } + // if frame is found, start checking for sequence + unsigned int temp = i; + c++; + while(c < _n_frames) + { + if(mask != 0x02) + { + mask = mask >> 2; + } + else + { + temp++; + mask = 0x80; + } + if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0) + { + c++; + } + else + { + c = 0; + break; + } + } + if(c == _n_frames) + { + nFreeFrames -= _n_frames; + break; + } + } + + frame_no += i*4 + j; + + // Update bitmap + // First: clear most significant bit to mark head of sequence. + bitmap[i] = bitmap[i] ^ (0x80 >> (j*2)); + // Second: clear both bits for all remaining frames in the sequence. + c = 1; + unsigned char mask = 0x80 >> j*2; + unsigned int temp = i; + while(c < _n_frames) + { + if(mask != 0x02) + { + mask = mask >> 2; + } + else + { + temp++; + mask = 0x80; + } + + bitmap[temp] = bitmap[temp] ^ mask; + bitmap[temp] = bitmap[temp] ^ (mask >> 1); + c++; + } + + return (frame_no); +} + +void ContFramePool::mark_inaccessible(unsigned long _base_frame_no, + unsigned long _n_frames) +{ + // Mark all frames in the range as being used. + int i ; + for(i = _base_frame_no; i < _base_frame_no + _n_frames; i++){ + mark_inaccessible(i); + } + nFreeFrames -= _n_frames; +} + +void ContFramePool::mark_inaccessible(unsigned long _frame_no) +{ + // Let's first do a range check. + assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes)); + + unsigned int bitmap_index = (_frame_no - base_frame_no) / 4; + unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 4) * 2; + + // Is the frame being used already? + assert(((bitmap[bitmap_index] & mask) != 0) && (bitmap[bitmap_index] & (mask >> 1)) != 0); + + // Update bitmap + bitmap[bitmap_index] ^= mask; + bitmap[bitmap_index] ^= mask >> 1; + nFreeFrames--; +} + +void ContFramePool::release_frames(unsigned long _frame_no) +{ + unsigned int i = 0; + while(i < nPools) + { + if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes)) + { + i++; + } + else + { + pools[i].release_frames_here(_frame_no); + return; + } + } +} + +void ContFramePool::release_frames_here(unsigned long _first_frame_no) +{ + unsigned char * bitmap = this->bitmap; + + unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4; + unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2; + + if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)) + { + if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0) + { + Console::puts("Error, Frame being released is not being used\n"); + assert(false); + } + Console::puts("Error, Frame being released is not head of sequence\n"); + assert(false); + } + + bitmap[bitmap_index] ^= mask; + nFreeFrames++; + + if(mask != 0x02) + { + mask = mask >> 2; + } + else + { + mask = 0x80; + bitmap_index++; + } + + while(bitmap[bitmap_index] & mask == 0 && (bitmap[bitmap_index] & (mask >> 1)) == 0) + { + bitmap[bitmap_index] ^= mask; + bitmap[bitmap_index] ^= (mask >> 1); + if(mask != 0x02) + { + mask = mask >> 2; + } + else + { + mask = 0x80; + bitmap_index++; + } + nFreeFrames++; + } +} + +unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames) +{ + return (_n_frames / (FRAME_SIZE * 4)) + (_n_frames % (FRAME_SIZE * 4) > 0 ? 1 : 0); +} diff --git a/MP3/MP3_Sources/cont_frame_pool.H b/MP3/MP3_Sources/cont_frame_pool.H new file mode 100755 index 0000000..13c7a07 --- /dev/null +++ b/MP3/MP3_Sources/cont_frame_pool.H @@ -0,0 +1,132 @@ +/* + File: cont_frame_pool.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 17/02/04 + + Description: Management of the CONTIGUOUS Free-Frame Pool. + + As opposed to a non-contiguous free-frame pool, here we can allocate + a sequence of CONTIGUOUS frames. + + */ + +#ifndef _CONT_FRAME_POOL_H_ // include file only once +#define _CONT_FRAME_POOL_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* C o n t F r a m e P o o l */ +/*--------------------------------------------------------------------------*/ + +class ContFramePool { + +private: + /* -- DEFINE YOUR CONT FRAME POOL DATA STRUCTURE(s) HERE. */ + + unsigned char * bitmap; // Remember the bitmap here needs 2 bits per frame + unsigned int nFreeFrames; // + unsigned long base_frame_no; // Where does the frame pool start in phys mem? + unsigned long nframes; // Size of the frame pool + unsigned long info_frame_no; // Where do we store the management information? + unsigned long n_info_frames; // Number of frames needed to store management info + static ContFramePool* pools; // List of frame pools, managed by the class + static unsigned int nPools; // Number of pools being managed + + void mark_inaccessible(unsigned long _frame_no); // Should be a frame marked as + // a head, otherwise fails + void release_frames_here(unsigned long _frame_no); // non-static member function + +public: + + // The frame size is the same as the page size, duh... + static const unsigned int FRAME_SIZE = Machine::PAGE_SIZE; + + ContFramePool(unsigned long _base_frame_no, + unsigned long _n_frames, + unsigned long _info_frame_no, + unsigned long _n_info_frames); + /* + Initializes the data structures needed for the management of this + frame pool. + _base_frame_no: Number of first frame managed by this frame pool. + _n_frames: Size, in frames, of this frame pool. + EXAMPLE: If _base_frame_no is 16 and _n_frames is 4, this frame pool manages + physical frames numbered 16, 17, 18 and 19. + _info_frame_no: Number of the first frame that should be used to store the + management information for the frame pool. + NOTE: If _info_frame_no is 0, the frame pool is free to + choose any frames from the pool to store management information. + _n_info_frames: If _info_frame_no is 0, this argument specifies the + number of consecutive frames needed to store the management information + for the frame pool. + EXAMPLE: If _info_frame_no is 699 and _n_info_frames is 3, + then Frames 699, 700, and 701 are used to store the management information + for the frame pool. + NOTE: This function must be called before the paging system + is initialized. + */ + + unsigned long get_frames(unsigned int _n_frames); + /* + Allocates a number of contiguous frames from the frame pool. + _n_frames: Size of contiguous physical memory to allocate, + in number of frames. + If successful, returns the frame number of the first frame. + If fails, returns 0. + */ + + void mark_inaccessible(unsigned long _base_frame_no, + unsigned long _n_frames); + /* + Marks a contiguous area of physical memory, i.e., a contiguous + sequence of frames, as inaccessible. + _base_frame_no: Number of first frame to mark as inaccessible. + _n_frames: Number of contiguous frames to mark as inaccessible. + */ + + static void release_frames(unsigned long _frame_no); + /* + Releases a previously allocated contiguous sequence of frames + back to its frame pool. + The frame sequence is identified by the number of the first frame. + NOTE: This function is static because there may be more than one frame pool + defined in the system, and it is unclear which one this frame belongs to. + This function must first identify the correct frame pool and then call the frame + pool's release_frame function. + */ + + static unsigned long needed_info_frames(unsigned long _n_frames); + /* + Returns the number of frames needed to manage a frame pool of size _n_frames. + The number returned here depends on the implementation of the frame pool and + on the frame size. + EXAMPLE: For FRAME_SIZE = 4096 and a bitmap with a single bit per frame + (not appropriate for contiguous allocation) one would need one frame to manage a + frame pool with up to 8 * 4096 = 32k frames = 128MB of memory! + This function would therefore return the following value: + _n_frames / 32k + (_n_frames % 32k > 0 ? 1 : 0) (always round up!) + Other implementations need a different number of info frames. + The exact number is computed in this function.. + */ +}; +#endif diff --git a/MP3/MP3_Sources/copykernel.sh b/MP3/MP3_Sources/copykernel.sh new file mode 100755 index 0000000..afd49c3 --- /dev/null +++ b/MP3/MP3_Sources/copykernel.sh @@ -0,0 +1,5 @@ +# Replace "/mnt/floppy" with the whatever directory is appropriate. +sudo mount -o loop dev_kernel_grub.img /mnt/floppy +sudo cp kernel.bin /mnt/floppy +sleep 1s +sudo umount /mnt/floppy diff --git a/MP3/MP3_Sources/dev_kernel_grub.img b/MP3/MP3_Sources/dev_kernel_grub.img new file mode 100755 index 0000000..ed7450c Binary files /dev/null and b/MP3/MP3_Sources/dev_kernel_grub.img differ diff --git a/MP3/MP3_Sources/exceptions.C b/MP3/MP3_Sources/exceptions.C new file mode 100755 index 0000000..6192cb2 --- /dev/null +++ b/MP3/MP3_Sources/exceptions.C @@ -0,0 +1,183 @@ +/* + File: exceptions.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/05 + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "utils.H" +#include "console.H" +#include "idt.H" +#include "exceptions.H" + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* The low-level functions (defined in file 'IDT::low.s') that handle the + 32 Intel-defined CPU exceptions. + These functions are actually merely stubs that put the error code and + the exception code on the stack and then call a low-level function, which + in turn calls the exception dispatcher (defined in 'exceptions.H'). + Yes, there are more efficient ways to handle exceptions, but they require more + code replication. +*/ +extern "C" void isr0(); +extern "C" void isr1(); +extern "C" void isr2(); +extern "C" void isr3(); +extern "C" void isr4(); +extern "C" void isr5(); +extern "C" void isr6(); +extern "C" void isr7(); +extern "C" void isr8(); +extern "C" void isr9(); +extern "C" void isr10(); +extern "C" void isr11(); +extern "C" void isr12(); +extern "C" void isr13(); +extern "C" void isr14(); +extern "C" void isr15(); +extern "C" void isr16(); +extern "C" void isr17(); +extern "C" void isr18(); +extern "C" void isr19(); +extern "C" void isr20(); +extern "C" void isr21(); +extern "C" void isr22(); +extern "C" void isr23(); +extern "C" void isr24(); +extern "C" void isr25(); +extern "C" void isr26(); +extern "C" void isr27(); +extern "C" void isr28(); +extern "C" void isr29(); +extern "C" void isr30(); +extern "C" void isr31(); + +extern "C" void lowlevel_dispatch_exception(REGS * _r) { + ExceptionHandler::dispatch_exception(_r); +} + +/*--------------------------------------------------------------------------*/ +/* STATIC VARIABLES */ +/*--------------------------------------------------------------------------*/ + +ExceptionHandler * ExceptionHandler::handler_table[ExceptionHandler::EXCEPTION_TABLE_SIZE]; + +/*--------------------------------------------------------------------------*/ +/* EXPORTED EXCEPTION DISPATCHER FUNCTIONS */ +/*--------------------------------------------------------------------------*/ + +void ExceptionHandler::init_dispatcher() { + + /* -- INITIALIZE LOW-LEVEL EXCEPTION HANDLERS */ + /* Add any new ISRs to the IDT here using IDT::set_gate */ + IDT::set_gate( 0, (unsigned) isr0, 0x08, 0x8E); + IDT::set_gate( 1, (unsigned) isr1, 0x08, 0x8E); + IDT::set_gate( 2, (unsigned) isr2, 0x08, 0x8E); + IDT::set_gate( 3, (unsigned) isr3, 0x08, 0x8E); + IDT::set_gate( 4, (unsigned) isr4, 0x08, 0x8E); + IDT::set_gate( 5, (unsigned) isr5, 0x08, 0x8E); + IDT::set_gate( 6, (unsigned) isr6, 0x08, 0x8E); + IDT::set_gate( 7, (unsigned) isr7, 0x08, 0x8E); + + IDT::set_gate( 8, (unsigned) isr8, 0x08, 0x8E); + IDT::set_gate( 9, (unsigned) isr9, 0x08, 0x8E); + IDT::set_gate(10, (unsigned)isr10, 0x08, 0x8E); + IDT::set_gate(11, (unsigned)isr11, 0x08, 0x8E); + IDT::set_gate(12, (unsigned)isr12, 0x08, 0x8E); + IDT::set_gate(13, (unsigned)isr13, 0x08, 0x8E); + IDT::set_gate(14, (unsigned)isr14, 0x08, 0x8E); + IDT::set_gate(15, (unsigned)isr15, 0x08, 0x8E); + + IDT::set_gate(16, (unsigned)isr16, 0x08, 0x8E); + IDT::set_gate(17, (unsigned)isr17, 0x08, 0x8E); + IDT::set_gate(18, (unsigned)isr18, 0x08, 0x8E); + IDT::set_gate(19, (unsigned)isr19, 0x08, 0x8E); + IDT::set_gate(20, (unsigned)isr20, 0x08, 0x8E); + IDT::set_gate(21, (unsigned)isr21, 0x08, 0x8E); + IDT::set_gate(22, (unsigned)isr22, 0x08, 0x8E); + IDT::set_gate(23, (unsigned)isr23, 0x08, 0x8E); + + IDT::set_gate(24, (unsigned)isr24, 0x08, 0x8E); + IDT::set_gate(25, (unsigned)isr25, 0x08, 0x8E); + IDT::set_gate(26, (unsigned)isr26, 0x08, 0x8E); + IDT::set_gate(27, (unsigned)isr27, 0x08, 0x8E); + IDT::set_gate(28, (unsigned)isr28, 0x08, 0x8E); + IDT::set_gate(29, (unsigned)isr29, 0x08, 0x8E); + IDT::set_gate(30, (unsigned)isr30, 0x08, 0x8E); + IDT::set_gate(31, (unsigned)isr31, 0x08, 0x8E); + + /* -- INITIALIZE THE HIGH-LEVEL EXCEPTION HANDLER */ + int i; + for(i = 0; i < EXCEPTION_TABLE_SIZE; i++) { + handler_table[i] = NULL; + } +} + +void ExceptionHandler::dispatch_exception(REGS * _r) { + + /* -- EXCEPTION NUMBER */ + unsigned int exc_no = _r->int_no; + + Console::puts("EXCEPTION DISPATCHER: exc_no = "); + Console::putui(exc_no); + Console::puts("\n"); + + assert((exc_no >= 0) && (exc_no < EXCEPTION_TABLE_SIZE)); + + /* -- HAS A HANDLER BEEN REGISTERED FOR THIS EXCEPTION NO? */ + ExceptionHandler * handler = handler_table[exc_no]; + + if (!handler) { + /* --- NO HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */ + Console::puts("NO DEFAULT EXCEPTION HANDLER REGISTERED\n"); + abort(); + } + else { + /* -- HANDLE THE EXCEPTION OR INTERRUPT */ + handler->handle_exception(_r); + } + +} + +void ExceptionHandler::register_handler(unsigned int _isr_code, + ExceptionHandler * _handler) { + + assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE); + + handler_table[_isr_code] = _handler; + + Console::puts("Installed exception handler at ISR "); + Console::putui(_isr_code); + Console::puts("\n"); + +} + +void ExceptionHandler::deregister_handler(unsigned int _isr_code) { + assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE); + + handler_table[_isr_code] = NULL; + + Console::puts("UNINSTALLED exception handler at ISR "); + Console::putui(_isr_code); + Console::puts("\n"); + +} + + diff --git a/MP3/MP3_Sources/exceptions.H b/MP3/MP3_Sources/exceptions.H new file mode 100755 index 0000000..88a683b --- /dev/null +++ b/MP3/MP3_Sources/exceptions.H @@ -0,0 +1,86 @@ +/* + File: exceptions.h + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/05 + + Description: High-level exception handling. + + CPU exceptions are caught by low-level exception and interrupt + handler stubs, which all eventually cause the high-level + exception dispatcher to be called (see 'dispatch_exception() below). + + The dispatcher then looks up the appropriate exception handler + for the given exception, and calls it. + Specific exception handlers are installed by registering an exception handler + object of a class appropriately derived from class 'ExceptionHandler'. The + functionality of the exception handler is then implemented in function + 'handle_exception(REGS * _regs)'. + + +*/ + +#ifndef _exceptions_H_ // include file only once +#define _exceptions_H_ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "machine.H" + +/*--------------------------------------------------------------------------*/ +/* E x c e p t i o n H a n d l e r */ +/*--------------------------------------------------------------------------*/ + +class ExceptionHandler { + + private: + + /* The Exception Handler Table */ + const static int EXCEPTION_TABLE_SIZE = 32; + static ExceptionHandler * handler_table[EXCEPTION_TABLE_SIZE]; + + public: + + /* -- POPULATE DISPATCHER TABLE */ + + static void register_handler(unsigned int _isr_code, + ExceptionHandler * _handler); + /* This function allows to install an exception handler for the given + exception code. The handler is a function pointer defined above. + Interrupt handlers are installed as exception handlers as well. + The 'register_interrupt' function uses irq2isr to map the IRQ + number to the code. */ + + static void deregister_handler(unsigned int _isr_code); + + /* -- DISPATCHER */ + static void init_dispatcher(); + /* This function is called to initialize the high-level exception handling. + No high level exception handlers are installed yet. If an exception + occurs at this point, the system displays an error message and + terminates. */ + + static void dispatch_exception(REGS * _r); + /* This is the high-level exception dispatcher. It dispatches the exception + to the previously registered exception handler. + This function is called by the low-level function + "lowlevel_dispatch_exception(REGS * _r)".*/ + + /* -- MANAGE INSTANCES OF EXCEPTION HANDLERS */ + + virtual void handle_exception(REGS * _regs) { + assert(false); // sometimes pure virtual functions dont link correctly. + } + /* Different exception handlers are derived from the base class ExceptionHandler + and their functionality is implemented in this function.*/ + +}; + +#endif + + diff --git a/MP3/MP3_Sources/gdt.C b/MP3/MP3_Sources/gdt.C new file mode 100755 index 0000000..4e1cb55 --- /dev/null +++ b/MP3/MP3_Sources/gdt.C @@ -0,0 +1,124 @@ +/* + File: gdt.C + + Date : 09/03/02 + + Description: Management of the Global Descriptor Table (GDT) + + The GDT describes memory access priviledges for memory segments. + + While the table is initialized by GRUB already, it may be a good idea to + do this again in the kernel code. + + For details see Section 5 of Brandon Friesen's Tutorial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +* bkerndev - Bran's Kernel Development Tutorial +* By: Brandon F. (friesenb@gmail.com) +* Desc: Interrupt Descriptor Table management +* +* Notes: No warranty expressed or implied. Use at own risk. +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +//#include "assert.H" +#include "utils.H" +#include "gdt.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* Defines a GDT entry. We use the 'packed' directive to prevent the + compiler from optimizing by aligning structure elements at word + boundaries. */ +struct gdt_entry { + unsigned short limit_low; + unsigned short base_low; + unsigned char base_middle; + unsigned char access; + unsigned char granularity; + unsigned char base_high; +} __attribute__((packed)); + +/* Special pointer that includes the limit: The max bytes + taken up by the GDT, minus 1. Again, this NEEDS to be packed. */ +struct gdt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +/*--------------------------------------------------------------------------*/ +/* VARIABLES */ +/*--------------------------------------------------------------------------*/ + +static struct gdt_entry gdt[GDT::SIZE]; +struct gdt_ptr gp; + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* This function is defined in 'gdt_low.asm', which in turn is included in + 'start.asm'. */ +extern "C" void gdt_flush(); + +/*--------------------------------------------------------------------------*/ +/* EXPORTED FUNCTIONS */ +/*--------------------------------------------------------------------------*/ + +/* Use this function to set up an entry in the GDT. */ +void GDT::set_gate(int num, + unsigned long base, unsigned long limit, + unsigned char access, unsigned char gran) { + + /* Setup the descriptor base address */ + gdt[num].base_low = (base & 0xFFFF); + gdt[num].base_middle = (base >> 16) & 0xFF; + gdt[num].base_high = (base >> 24) & 0xFF; + + /* Setup the descriptor limits */ + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = ((limit >> 16) & 0x0F); + + /* Finally, set up the granularity and access flags */ + gdt[num].granularity |= (gran & 0xF0); + gdt[num].access = access; +} + + +/* Installs the GDT */ +void GDT::init() { + + /* Sets up the special GDT pointer. */ + gp.limit = (sizeof (struct gdt_entry) * SIZE) - 1; + gp.base = (unsigned int)&gdt; + + /* Our NULL descriptor */ + set_gate(0, 0, 0, 0, 0); + + /* The second entry is our Code Segment. The base address + is 0, the limit is 4GByte, it uses 4kB granularity, + uses 32-bit opcodes, and is a Code Segment descriptor. + Please check the GDT section in Bran's Kernel Development + tutorial to see exactly what each value means. */ + set_gate(1, 0, 0xFFFFFFFF, 0x9a, 0xCF); + + /* The third entry is our Data Segment. It's EXACTLY the + same as the code segment, but the descriptor type in + this entry's access byte says it's a Data Segment. */ + set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + /* Flush out the old GDT, and install the new changes. */ + gdt_flush(); +} diff --git a/MP3/MP3_Sources/gdt.H b/MP3/MP3_Sources/gdt.H new file mode 100755 index 0000000..ae9eb95 --- /dev/null +++ b/MP3/MP3_Sources/gdt.H @@ -0,0 +1,48 @@ +/* + File: gdt.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/02 + + Description: Management of the Global Descriptor Table (GDT) + + The GDT describes memory access priviledges for memory segments. + + While the table is initialized by GRUB already, it may be a good idea to + do this again in the kernel code. + + For details see Section 5 of Brandon Friesen's Tutotial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +*/ + +#ifndef _GDT_H_ // include file only once +#define _GDT_H_ + +/*--------------------------------------------------------------------------*/ +/* GDT */ +/*--------------------------------------------------------------------------*/ + +class GDT { + +private: + + /* Use this function to set up an entry in the GDT. */ + static void set_gate(int num, + unsigned long base, unsigned long limit, + unsigned char access, unsigned char gran); + +public: + + static const unsigned int SIZE = 3; + + static void init(); + /* Initialize the GDT to have a null segment, a code segment, + and one data segment. */ + +}; + +#endif diff --git a/MP3/MP3_Sources/gdt_low.asm b/MP3/MP3_Sources/gdt_low.asm new file mode 100755 index 0000000..0b15df0 --- /dev/null +++ b/MP3/MP3_Sources/gdt_low.asm @@ -0,0 +1,18 @@ +; This will set up our new segment registers. We need to do +; something special in order to set CS. We do what is called a +; far jump. A jump that includes a segment as well as an offset. +; This is declared in C as 'extern void gdt_flush();' +global _gdt_flush ; Allows the C code to link to this. +extern _gp ; Says that '_gp' is in another file + +_gdt_flush: + lgdt[_gp] ; Load the GDT with our '_gp', a special pointer + mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax +; mov ss, ax + jmp 0x08:flush2 ; 0x08 is the offset to our code segment: FAR JUMP! +flush2: + ret ; Returns back to the C code! diff --git a/MP3/MP3_Sources/idt.C b/MP3/MP3_Sources/idt.C new file mode 100755 index 0000000..76d93ca --- /dev/null +++ b/MP3/MP3_Sources/idt.C @@ -0,0 +1,108 @@ +/* + File: idt.C + + Date : 09/03/02 + +*/ + +/* Based largely on +* bkerndev - Bran's Kernel Development Tutorial +* By: Brandon F. (friesenb@gmail.com) +* Desc: Interrupt Descriptor Table management +* +* Notes: No warranty expressed or implied. Use at own risk. */ + + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +//#include "assert.H" +#include "utils.H" +#include "idt.H" +#include "console.H" + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* Used to load our IDT, defined in 'idt_low.s' */ +extern "C" void idt_load(); + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +struct idt_entry +{ + unsigned short base_lo; + unsigned short sel; + unsigned char always0; + unsigned char flags; + unsigned short base_hi; +} __attribute__((packed)); + +struct idt_ptr +{ + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + + +/*--------------------------------------------------------------------------*/ +/* VARIABLES */ +/*--------------------------------------------------------------------------*/ + + +/* Declare an IDT of IDT_SIZE entries. We use only the first 32 + entries. If any undefined IDT entry is hit, it normally + cause an "Unhandled Interrupt" exception. Any descriptor + for which the 'presence' bit is cleared will generate an + "Unhandled Interrupt" exception. */ +struct idt_entry idt[IDT::SIZE]; +struct idt_ptr idtp; + +/*--------------------------------------------------------------------------*/ +/* HOOKING UP THE LOW-LEVEL EXCEPTION HANDLER TO EXCEPTIONDISPATCHER. */ +/*--------------------------------------------------------------------------*/ + +/* Use this function to set an entry in the IDT. */ +void IDT::set_gate(unsigned char num, unsigned long base, + unsigned short sel, unsigned char flags) { + + Console::puts("Installing handler in IDT position "); + Console::puti((int)num); + Console::puts("\n"); + + /* The interrupt routine's base address */ + idt[num].base_lo = (base & 0xFFFF); + idt[num].base_hi = (base >> 16) & 0xFFFF; + + /* The segment or 'selector' that this IDT entry will use + * is set here, along with any access flags */ + idt[num].sel = sel; + idt[num].always0 = 0; + idt[num].flags = flags; + +} + +/* Installs the IDT */ +void IDT::init() { + + /* Sets the special IDT pointer up. */ + idtp.limit = (sizeof (struct idt_entry) * 256) - 1; + idtp.base = (unsigned int)&idt; + + /* Clear out the entire IDT, initializing it to zeros. */ + memset(&idt, 0, sizeof(struct idt_entry) * 256); + + + /* Points the processor's internal register to the new IDT */ + idt_load(); +} diff --git a/MP3/MP3_Sources/idt.H b/MP3/MP3_Sources/idt.H new file mode 100755 index 0000000..ee0bd54 --- /dev/null +++ b/MP3/MP3_Sources/idt.H @@ -0,0 +1,57 @@ +/* + File: idt.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/02 + + Description: the Interrupt Description Table (IDT) + + The IDT contains pointer to low-level exception and interrupt handlers. + The way the exception handling is set up, all low-level handlers route + the exception to a single exception dispatcher, which in turn + calls a high-level exception dispatcher (see file 'exceptions.H'). + + For details see Section 6 of Brandon Friesen's Tutorial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +*/ + +#ifndef _IDT_H_ // include file only once +#define _IDT_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +//#define IDT_SIZE 256 + +/*--------------------------------------------------------------------------*/ +/* Class IDT */ +/*--------------------------------------------------------------------------*/ + +class IDT { + + public: + + static const int SIZE = 256; + + static void init(); + /* Initialize the IDT, and fill the 32 first entries with pointers to handle + the 32 Intel-defined exceptions. After initializing the IDT, these exceptions + are routed to the exception dispatcher (see 'exceptions.H'). At this point, + no exception handlers are installed yet. + */ + + static void set_gate(unsigned char num, unsigned long base, + unsigned short sel, unsigned char flags); + /* Used to install a low-level exception handler in the IDT. For high-level + exception handlers, use the exception management framework defined in + file 'exceptions.H'. + */ + +}; + +#endif diff --git a/MP3/MP3_Sources/idt_low.asm b/MP3/MP3_Sources/idt_low.asm new file mode 100755 index 0000000..9312d38 --- /dev/null +++ b/MP3/MP3_Sources/idt_low.asm @@ -0,0 +1,279 @@ +; This is the exception de-multiplexer code. +; All low-level exception handling routines do the following: +; 1. disable interrupts +; 2. push error code on the stack (if the exception did not already +; do so! (Some exceptions automatically push the error code onto the +; stack.) +; 3. push the number of the exception onto the stack. +; 4. call the common interrupt service routine function, which then +; branches back out based on the exception number on the stack. +; (We do this because we don't want to replicate again and again the code +; to save the processor state.) +; + +; Here come the interrupt service routines for the 32 exceptions. +global _isr0 +global _isr1 +global _isr2 +global _isr3 +global _isr4 +global _isr5 +global _isr6 +global _isr7 +global _isr8 +global _isr9 +global _isr10 +global _isr11 +global _isr12 +global _isr13 +global _isr14 +global _isr15 +global _isr16 +global _isr17 +global _isr18 +global _isr19 +global _isr20 +global _isr21 +global _isr22 +global _isr23 +global _isr24 +global _isr25 +global _isr26 +global _isr27 +global _isr28 +global _isr29 +global _isr30 +global _isr31 + + +extern _promptA +extern _promptB +extern _promptC + + +; 0: Divide By Zero Exception +_isr0: + push byte 0 + push byte 0 + jmp isr_common_stub + +; 1: Debug Exception +_isr1: + push byte 0 + push byte 1 + jmp isr_common_stub + +; 2: Non Maskable Interrupt Exception +_isr2: + push byte 0 + push byte 2 + jmp isr_common_stub + +; 3: Int 3 Exception +_isr3: + push byte 0 + push byte 3 + jmp isr_common_stub + +; 4: INTO Exception +_isr4: + push byte 0 + push byte 4 + jmp isr_common_stub + +; 5: Out of Bounds Exception +_isr5: + push byte 0 + push byte 5 + jmp isr_common_stub + +; 6: Invalid Opcode Exception +_isr6: + push byte 0 + push byte 6 + jmp isr_common_stub + +; 7: Coprocessor Not Available Exception +_isr7: + push byte 0 + push byte 7 + jmp isr_common_stub + +; 8: Double Fault Exception (With Error Code!) +_isr8: + push byte 8 + jmp isr_common_stub + +; 9: Coprocessor Segment Overrun Exception +_isr9: + push byte 0 + push byte 9 + jmp isr_common_stub + +; 10: Bad TSS Exception (With Error Code!) +_isr10: + push byte 10 + jmp isr_common_stub + +; 11: Segment Not Present Exception (With Error Code!) +_isr11: + push byte 11 + jmp isr_common_stub + +; 12: Stack Fault Exception (With Error Code!) +_isr12: + push byte 12 + jmp isr_common_stub + +; 13: General Protection Fault Exception (With Error Code!) +_isr13: + push byte 13 + jmp isr_common_stub + +; 14: Page Fault Exception (With Error Code!) +_isr14: + push byte 14 + jmp isr_common_stub + +; 15: Reserved Exception +_isr15: + push byte 0 + push byte 15 + jmp isr_common_stub + +; 16: Floating Point Exception +_isr16: + push byte 0 + push byte 16 + jmp isr_common_stub + +; 17: Alignment Check Exception +_isr17: + push byte 0 + push byte 17 + jmp isr_common_stub + +; 18: Machine Check Exception +_isr18: + push byte 0 + push byte 18 + jmp isr_common_stub + +; 19: Reserved +_isr19: + push byte 0 + push byte 19 + jmp isr_common_stub + +; 20: Reserved +_isr20: + push byte 0 + push byte 20 + jmp isr_common_stub + +; 21: Reserved +_isr21: + push byte 0 + push byte 21 + jmp isr_common_stub + +; 22: Reserved +_isr22: + push byte 0 + push byte 22 + jmp isr_common_stub + +; 23: Reserved +_isr23: + push byte 0 + push byte 23 + jmp isr_common_stub + +; 24: Reserved +_isr24: + push byte 0 + push byte 24 + jmp isr_common_stub + +; 25: Reserved +_isr25: + push byte 0 + push byte 25 + jmp isr_common_stub + +; 26: Reserved +_isr26: + push byte 0 + push byte 26 + jmp isr_common_stub + +; 27: Reserved +_isr27: + push byte 0 + push byte 27 + jmp isr_common_stub + +; 28: Reserved +_isr28: + push byte 0 + push byte 28 + jmp isr_common_stub + +; 29: Reserved +_isr29: + push byte 0 + push byte 29 + jmp isr_common_stub + +; 30: Reserved +_isr30: + push byte 0 + push byte 30 + jmp isr_common_stub + +; 31: Reserved +_isr31: + push byte 0 + push byte 31 + jmp isr_common_stub + + + +; The common stub below will pun out into C. Let the +; assembler know that the function is defined in 'exceptions.C'. +extern _lowlevel_dispatch_exception + +; This is the common low-level stub for the exception handler. +; It saves the processor state, sets up for kernel mode +; segments, calls the C-level exception handler, +; and finally restores the stack frame. +isr_common_stub: + pusha + push ds + push es + push fs + push gs + + mov eax, esp ; Push us the stack + push eax + mov eax, _lowlevel_dispatch_exception + call eax ; A special call, preserves the 'eip' register + pop eax + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 ; Ceans up the pushed error code and pushed ISR number + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP1 + + + +; load the IDT defined in '_idtp' into the processor. +; This is declared in C as 'extern void _idt_load();' +; In turn, the variable '_idtp' is defined in file 'idt.C'. +global _idt_load +extern _idtp +_idt_load: + lidt [_idtp] + ret diff --git a/MP3/MP3_Sources/interrupts.C b/MP3/MP3_Sources/interrupts.C new file mode 100755 index 0000000..c67fba5 --- /dev/null +++ b/MP3/MP3_Sources/interrupts.C @@ -0,0 +1,172 @@ +/* + File: interrupts.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/05 + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* (none) */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "utils.H" +#include "console.H" +#include "idt.H" +#include "irq.H" +#include "exceptions.H" +#include "interrupts.H" + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* The low-level functions (defined in file 'irq_low.s') that handle the + 16 PIC-generated interrupts. + These functions are actually merely stubs that put the error code and + the exception code on the stack and then call a low-level function, which + in turn calls the interrupt dispatcher. + Yes, there are more efficient ways to handle exceptions, but they require more + code replication. +*/ + +extern "C" void irq0(); +extern "C" void irq1(); +extern "C" void irq2(); +extern "C" void irq3(); +extern "C" void irq4(); +extern "C" void irq5(); +extern "C" void irq6(); +extern "C" void irq7(); +extern "C" void irq8(); +extern "C" void irq9(); +extern "C" void irq10(); +extern "C" void irq11(); +extern "C" void irq12(); +extern "C" void irq13(); +extern "C" void irq14(); +extern "C" void irq15(); + +extern "C" void lowlevel_dispatch_interrupt(REGS * _r) { + InterruptHandler::dispatch_interrupt(_r); +} + +/*--------------------------------------------------------------------------*/ +/* LOCAL VARIABLES */ +/*--------------------------------------------------------------------------*/ + +InterruptHandler * InterruptHandler::handler_table[InterruptHandler::IRQ_TABLE_SIZE]; + +/*--------------------------------------------------------------------------*/ +/* EXPORTED INTERRUPT DISPATCHER FUNCTIONS */ +/*--------------------------------------------------------------------------*/ + +void InterruptHandler::init_dispatcher() { + + /* -- INITIALIZE LOW-LEVEL INTERRUPT HANDLERS */ + /* Add any new ISRs to the IDT here using IDT::set_gate */ + IDT::set_gate( 0+ IRQ_BASE, (unsigned) irq0, 0x08, 0x8E); + IDT::set_gate( 1+ IRQ_BASE, (unsigned) irq1, 0x08, 0x8E); + IDT::set_gate( 2+ IRQ_BASE, (unsigned) irq2, 0x08, 0x8E); + IDT::set_gate( 3+ IRQ_BASE, (unsigned) irq3, 0x08, 0x8E); + IDT::set_gate( 4+ IRQ_BASE, (unsigned) irq4, 0x08, 0x8E); + IDT::set_gate( 5+ IRQ_BASE, (unsigned) irq5, 0x08, 0x8E); + IDT::set_gate( 6+ IRQ_BASE, (unsigned) irq6, 0x08, 0x8E); + IDT::set_gate( 7+ IRQ_BASE, (unsigned) irq7, 0x08, 0x8E); + + IDT::set_gate( 8+ IRQ_BASE, (unsigned) irq8, 0x08, 0x8E); + IDT::set_gate( 9+ IRQ_BASE, (unsigned) irq9, 0x08, 0x8E); + IDT::set_gate(10+ IRQ_BASE, (unsigned)irq10, 0x08, 0x8E); + IDT::set_gate(11+ IRQ_BASE, (unsigned)irq11, 0x08, 0x8E); + IDT::set_gate(12+ IRQ_BASE, (unsigned)irq12, 0x08, 0x8E); + IDT::set_gate(13+ IRQ_BASE, (unsigned)irq13, 0x08, 0x8E); + IDT::set_gate(14+ IRQ_BASE, (unsigned)irq14, 0x08, 0x8E); + IDT::set_gate(15+ IRQ_BASE, (unsigned)irq15, 0x08, 0x8E); + + /* -- INITIALIZE THE HIGH-LEVEL INTERRUPT HANDLER */ + int i; + for(i = 0; i < IRQ_TABLE_SIZE; i++) { + handler_table[i] = NULL; + } +} + +bool InterruptHandler::generated_by_slave_PIC(unsigned int int_no) { + return int_no > 7; +} + +void InterruptHandler::dispatch_interrupt(REGS * _r) { + + /* -- INTERRUPT NUMBER */ + unsigned int int_no = _r->int_no - IRQ_BASE; + + //Console::puts("INTERRUPT DISPATCHER: int_no = "); + //Console::putui(int_no); + //Console::puts("\n"); + + assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE)); + + /* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */ + + InterruptHandler * handler = handler_table[int_no]; + + if (!handler) { + /* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */ + Console::puts("INTERRUPT NO: "); + Console::puti(int_no); + Console::puts("\n"); + Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n"); + // abort(); + } + else { + /* -- HANDLE THE INTERRUPT */ + handler->handle_interrupt(_r); + } + + /* This is an interrupt that was raised by the interrupt controller. We need + to send and end-of-interrupt (EOI) signal to the controller after the + interrupt has been handled. */ + + /* Check if the interrupt was generated by the slave interrupt controller. + If so, send an End-of-Interrupt (EOI) message to the slave controller. */ + + if (generated_by_slave_PIC(int_no)) { + Machine::outportb(0xA0, 0x20); + } + + /* Send an EOI message to the master interrupt controller. */ + Machine::outportb(0x20, 0x20); + +} + +void InterruptHandler::register_handler(unsigned int _irq_code, + InterruptHandler * _handler) { + assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE); + + handler_table[_irq_code] = _handler; + + Console::puts("Installed interrupt handler at IRQ "); + Console::putui(_irq_code); + Console::puts("\n"); + +} + +void InterruptHandler::deregister_handler(unsigned int _irq_code) { + + assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE); + + handler_table[_irq_code] = NULL; + + Console::puts("UNINSTALLED interrupt handler at IRQ "); + Console::putui(_irq_code); + Console::puts("\n"); + +} diff --git a/MP3/MP3_Sources/interrupts.H b/MP3/MP3_Sources/interrupts.H new file mode 100755 index 0000000..fd35216 --- /dev/null +++ b/MP3/MP3_Sources/interrupts.H @@ -0,0 +1,90 @@ +/* + File: interrupts.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 11/11/10 + + Description: High-level interrupt handling. + + CPU exceptions are caught by low-level exception and interrupt + handler stubs, which all eventually cause the high-level + exception dispatcher to be called (see 'dispatch_exception() below). + + The dispatcher then looks up the appropriate exception handler + for the given exception, and calls it. + Specific exception handlers are installed by registering an exception handler + object of a class appropriately derived from class 'ExceptionHandler'. The + functionality of the exception handler is then implemented in function + 'handle_exception(REGS * _regs)'. +*/ + +#ifndef _interrupts_H_ // include file only once +#define _interrupts_H_ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "machine.H" +#include "exceptions.H" + +/*--------------------------------------------------------------------------*/ +/* I n t e r r u p t H a n d l e r */ +/*--------------------------------------------------------------------------*/ + +class InterruptHandler { + + private: + + /* The Interrupt Handler Table */ + const static int IRQ_TABLE_SIZE = 16; + const static int IRQ_BASE = 32; + + static InterruptHandler * handler_table[IRQ_TABLE_SIZE]; + + static bool generated_by_slave_PIC(unsigned int int_no); + /* Has the particular interupt been generated by the Slave PIC? */ + + public: + + /* -- POPULATE INTERRUPT-DISPATCHER TABLE */ + static void register_handler(unsigned int _irq_code, + InterruptHandler * _handler); + /* This function allows to install an interrupt handler for the given + Interrupt code. The handler is a function pointer defined above. + Interrupt handlers are installed as Interrupt handlers as well. + The 'register_interrupt' function uses irq2isr to map the IRQ + number to the code. */ + + static void deregister_handler(unsigned int _irq_code); + + /* -- INITIALIZER */ + static void init_dispatcher(); + /* This function is called to initialize the high-level interrupt + handling. No high level interrupt handlers are installed yet. + If an interrupt occurs at this point, the system displays an error + message and terminates. */ + + static void dispatch_interrupt(REGS * _r); + /* This is the high-level interrupt dispatcher. It dispatches the interrupt + to the previously registered interrupt handler. + This function is called by the low-level function + "lowlevel_dispatch_interrupt(REGS * _r)".*/ + + /* -- MANAGE INSTANCES OF INTERRUPT HANDLERS */ + + virtual void handle_interrupt(REGS * _regs) { + assert(false); // sometimes pure virtual functions don't link correctly. + } + /* Different interrupt handlers are derived from the base class + InterruptHandler, and their functionality is implemented in + this function.*/ + +}; + +#endif + + diff --git a/MP3/MP3_Sources/irq.C b/MP3/MP3_Sources/irq.C new file mode 100755 index 0000000..44f27c0 --- /dev/null +++ b/MP3/MP3_Sources/irq.C @@ -0,0 +1,60 @@ +/* + File: irq.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/05 + + This code borrows heavily from Brandon Friesen's the code in Brandon + Friesen's OS Development Tutorial. +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +#define IRQ_BASE 32 + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" +#include "irq.H" + +/*--------------------------------------------------------------------------*/ +/* LOCAL FUNCTIONS . */ +/*--------------------------------------------------------------------------*/ + +/* Normally, IRQs 0 to 7 are mapped to IDT entries 8 to 15. + For a variety of reasons it is a good idea to re-map these + IRQs to different locations + We send a sequence of commands to the PICs - 8259's - in order + to have IRQ0 to IRQ15 be remapped to IDT entries 32 to 47. +*/ +static void irq_remap() +{ + Machine::outportb(0x20, 0x11); + Machine::outportb(0xA0, 0x11); + Machine::outportb(0x21, 0x20); + Machine::outportb(0xA1, 0x28); + Machine::outportb(0x21, 0x04); + Machine::outportb(0xA1, 0x02); + Machine::outportb(0x21, 0x01); + Machine::outportb(0xA1, 0x01); + Machine::outportb(0x21, 0x0); + Machine::outportb(0xA1, 0x0); +} + + +/*--------------------------------------------------------------------------*/ +/* EXPORTED FUNCTIONS . */ +/*--------------------------------------------------------------------------*/ + +void IRQ::init() { + + irq_remap(); + + +} diff --git a/MP3/MP3_Sources/irq.H b/MP3/MP3_Sources/irq.H new file mode 100755 index 0000000..0072f9b --- /dev/null +++ b/MP3/MP3_Sources/irq.H @@ -0,0 +1,38 @@ +/* + File: irq.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/02 + + Description: Interrupt Table (IRQ) + + For details see Section 7 of Brandon Friesen's Tutorial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +*/ + +#ifndef _IRQ_H_ // include file only once +#define _IRQ_H_ + + +/*--------------------------------------------------------------------------*/ +/* */ +/*--------------------------------------------------------------------------*/ + +class IRQ { + +public: + + static void init(); + /* Initialize the IRQ handlers, i.e. fill 16 entries with pointers to handle + the PIC generated interrupts. These interrupts are routed to the exception + dispatcher (see 'exceptions.H'). At this point, no exception handlers are + installed yet. + */ + +}; + +#endif diff --git a/MP3/MP3_Sources/irq_low.asm b/MP3/MP3_Sources/irq_low.asm new file mode 100755 index 0000000..e94271c --- /dev/null +++ b/MP3/MP3_Sources/irq_low.asm @@ -0,0 +1,136 @@ +global _irq0 +global _irq1 +global _irq2 +global _irq3 +global _irq4 +global _irq5 +global _irq6 +global _irq7 +global _irq8 +global _irq9 +global _irq10 +global _irq11 +global _irq12 +global _irq13 +global _irq14 +global _irq15 + +; 32: IRQ0 +_irq0: + push byte 0 + push byte 32 + jmp irq_common_stub + +; 33: IRQ1 +_irq1: + push byte 0 + push byte 33 + jmp irq_common_stub + +; 34: IRQ2 +_irq2: + push byte 0 + push byte 34 + jmp irq_common_stub + +; 35: IRQ3 +_irq3: + push byte 0 + push byte 35 + jmp irq_common_stub + +; 36: IRQ4 +_irq4: + push byte 0 + push byte 36 + jmp irq_common_stub + +; 37: IRQ5 +_irq5: + push byte 0 + push byte 37 + jmp irq_common_stub + +; 38: IRQ6 +_irq6: + push byte 0 + push byte 38 + jmp irq_common_stub + +; 39: IRQ7 +_irq7: + push byte 0 + push byte 39 + jmp irq_common_stub + +; 40: IRQ8 +_irq8: + push byte 0 + push byte 40 + jmp irq_common_stub + +; 41: IRQ9 +_irq9: + push byte 0 + push byte 41 + jmp irq_common_stub + +; 42: IRQ10 +_irq10: + push byte 0 + push byte 42 + jmp irq_common_stub + +; 43: IRQ11 +_irq11: + push byte 0 + push byte 43 + jmp irq_common_stub + +; 44: IRQ12 +_irq12: + push byte 0 + push byte 44 + jmp irq_common_stub + +; 45: IRQ13 +_irq13: + push byte 0 + push byte 45 + jmp irq_common_stub + +; 46: IRQ14 +_irq14: + push byte 0 + push byte 46 + jmp irq_common_stub + +; 47: IRQ15 +_irq15: + push byte 0 + push byte 47 + jmp irq_common_stub + +extern _lowlevel_dispatch_interrupt + +irq_common_stub: + pusha + push ds + push es + push fs + push gs + + mov eax, esp + + push eax + mov eax, _lowlevel_dispatch_interrupt + call eax + pop eax + + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 + iret diff --git a/MP3/MP3_Sources/kernel.C b/MP3/MP3_Sources/kernel.C new file mode 100755 index 0000000..884f1f4 --- /dev/null +++ b/MP3/MP3_Sources/kernel.C @@ -0,0 +1,196 @@ +/* + File: kernel.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/03 + + + This file has the main entry point to the operating system. + + */ + + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" /* LOW-LEVEL STUFF */ +#include "console.H" +#include "gdt.H" +#include "idt.H" /* LOW-LEVEL EXCEPTION MGMT. */ +#include "irq.H" +#include "exceptions.H" +#include "interrupts.H" + +#include "simple_keyboard.H" /* SIMPLE KB DRIVER */ +#include "simple_timer.H" /* TIMER MANAGEMENT */ + +#include "page_table.H" +#include "paging_low.H" + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +#define MB * (0x1 << 20) +#define KB * (0x1 << 10) +#define KERNEL_POOL_START_FRAME ((2 MB) / Machine::PAGE_SIZE) +#define KERNEL_POOL_SIZE ((2 MB) / Machine::PAGE_SIZE) +#define PROCESS_POOL_START_FRAME ((4 MB) / Machine::PAGE_SIZE) +#define PROCESS_POOL_SIZE ((28 MB) / Machine::PAGE_SIZE) +/* definition of the kernel and process memory pools */ + +#define MEM_HOLE_START_FRAME ((15 MB) / Machine::PAGE_SIZE) +#define MEM_HOLE_SIZE ((1 MB) / Machine::PAGE_SIZE) +/* we have a 1 MB hole in physical memory starting at address 15 MB */ + +#define FAULT_ADDR (4 MB) +/* used in the code later as address referenced to cause page faults. */ +#define NACCESS ((1 MB) / 4) +/* NACCESS integer access (i.e. 4 bytes in each access) are made starting at address FAULT_ADDR */ + +/*--------------------------------------------------------------------------*/ +/* MAIN ENTRY INTO THE OS */ +/*--------------------------------------------------------------------------*/ + +int main() { + + GDT::init(); + Console::init(); + IDT::init(); + ExceptionHandler::init_dispatcher(); + IRQ::init(); + InterruptHandler::init_dispatcher(); + + + /* -- EXAMPLE OF AN EXCEPTION HANDLER: Division-by-Zero -- */ + + class DBZ_Handler : public ExceptionHandler { + /* We derive Division-by-Zero handler from ExceptionHandler + and overload the method handle_exception. */ + public: + virtual void handle_exception(REGS * _regs) { + Console::puts("DIVISION BY ZERO!\n"); + for(;;); + } + } dbz_handler; + + /* Register the DBZ handler for exception no.0 + with the exception dispatcher. */ + ExceptionHandler::register_handler(0, &dbz_handler); + + + /* -- EXAMPLE OF AN INTERRUPT HANDLER: Very simple timer -- */ + + SimpleTimer timer(100); /* timer ticks every 10ms. */ + + /* ---- Register timer handler for interrupt no.0 + with the interrupt dispatcher. */ + InterruptHandler::register_handler(0, &timer); + + /* NOTE: The timer chip starts periodically firing as + soon as we enable interrupts. + It is important to install a timer handler, as we + would get a lot of uncaptured interrupts otherwise. */ + + /* -- INSTALL INTERRUPT HANDLER FOR SIMPLE KEYBOARD -- */ + + SimpleKeyboard::init(); + + /* NOTE: In the SimpleKeyboard::init() a private static object of + type SimpleKeyboard is created and its interrupt handler is + registered with the interrupt dispatcher. Subsequent calls to the + static function SimpleKeyboard::wait() look until a key is pressed.*/ + + /* -- ENABLE INTERRUPTS -- */ + + Machine::enable_interrupts(); + + /* -- INITIALIZE FRAME POOLS -- */ + + ContFramePool kernel_mem_pool(KERNEL_POOL_START_FRAME, + KERNEL_POOL_SIZE, + 0, + 0); + + unsigned long n_info_frames = ContFramePool::needed_info_frames(PROCESS_POOL_SIZE); + + unsigned long process_mem_pool_info_frame = kernel_mem_pool.get_frames(n_info_frames); + + ContFramePool process_mem_pool(PROCESS_POOL_START_FRAME, + PROCESS_POOL_SIZE, + process_mem_pool_info_frame, + n_info_frames); + + /* Take care of the hole in the memory. */ + process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE); + + /* -- INITIALIZE MEMORY (PAGING) -- */ + + /* ---- INSTALL PAGE FAULT HANDLER -- */ + + class PageFault_Handler : public ExceptionHandler { + /* We derive the page fault handler from ExceptionHandler + and overload the method handle_exception. */ + public: + virtual void handle_exception(REGS * _regs) { + PageTable::handle_fault(_regs); + } + } pagefault_handler; + + /* ---- Register the page fault handler for exception no.14 + with the exception dispatcher. */ + ExceptionHandler::register_handler(14, &pagefault_handler); + + /* ---- INITIALIZE THE PAGE TABLE -- */ + + PageTable::init_paging(&kernel_mem_pool, + &process_mem_pool, + 4 MB); /* We share the first 4MB */ + + PageTable pt; + + pt.load(); + + PageTable::enable_paging(); + + Console::puts("WE TURNED ON PAGING!\n"); + Console::puts("If we see this message, the page tables have been\n"); + Console::puts("set up mostly correctly.\n"); + + /* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */ + + Console::puts("Hello World!\n"); + + /* -- GENERATE MEMORY REFERENCES */ + + int *foo = (int *) FAULT_ADDR; + int i; + + for (i=0; iget_frames(1); // Need to take one frame for page directory. + + //page_directory = (unsigned long *) 0x32000; // Should be the starting address after 1st 2MB + page_directory = (unsigned long *) kernel_mem_pool->get_frames(1); // Should I get the address like this??? + + //unsigned long * page_table = (unsigned long *) 0x33000; // Should be 4kb after the page directory. + unsigned long * page_table = page_directory + 0x1000; // Might be able to just do this. + + unsigned long tempaddr; // Temporary address iterator. + + // We need to map the first 4MB. + for(unsigned int i = 0; i < 1024; i++) + { + page_table[i] = tempaddr | 3; // set bits 0 and 1 to present and read/write respectively + tempaddr += 4096; // 4096 = 4kb + } + + + // Fill first entry of page directory. + page_directory[0] = *page_table; + page_directory[0] = page_directory[0] | 3; + + for(unsigned int j = 1; j < 1024; j++) + { + page_directory[j] = 0 | 2; + } + + current_page_table = this; + + Console::puts("\nConstructed Page Table object\n"); +} + + +void PageTable::load() +{ + write_cr3(*page_directory); + current_page_table = this; + Console::puts("\nLoaded page table\n"); +} + +void PageTable::enable_paging() +{ + write_cr3(*current_page_table->page_directory); + write_cr0(read_cr0() | 0x80000000); + paging_enabled = read_cr0(); + Console::puts("\nEnabled paging\n"); +} + +void PageTable::handle_fault(REGS * _r) +{ + /* + unsigned long tempframe = process_mem_pool->get_frames(1); + Console::puts("\nerror code: "); + Console::puti(_r->err_code); + + unsigned char mask = 0x00; + + + read_cr2(); +*/ + assert(false); + Console::puts("\nhandled page fault\n"); +} + diff --git a/MP3/MP3_Sources/page_table.H b/MP3/MP3_Sources/page_table.H new file mode 100755 index 0000000..f89e5a1 --- /dev/null +++ b/MP3/MP3_Sources/page_table.H @@ -0,0 +1,91 @@ +/* + File: page_table.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 16/12/07 + + Description: Basic Paging. + +*/ + +#ifndef _page_table_H_ // include file only once +#define _page_table_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" +#include "exceptions.H" +#include "cont_frame_pool.H" + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* P A G E - T A B L E */ +/*--------------------------------------------------------------------------*/ + +class PageTable { + +private: + + /* THESE MEMBERS ARE COMMON TO ENTIRE PAGING SUBSYSTEM */ + static PageTable * current_page_table; /* pointer to currently loaded page table object */ + static unsigned int paging_enabled; /* is paging turned on (i.e. are addresses logical)? */ + static ContFramePool * kernel_mem_pool; /* Frame pool for the kernel memory */ + static ContFramePool * process_mem_pool; /* Frame pool for the process memory */ + static unsigned long shared_size; /* size of shared address space */ + + /* DATA FOR CURRENT PAGE TABLE */ + unsigned long * page_directory; /* where is page directory located? */ + +public: + static const unsigned int PAGE_SIZE = Machine::PAGE_SIZE; + /* in bytes */ + static const unsigned int ENTRIES_PER_PAGE = Machine::PT_ENTRIES_PER_PAGE; + /* in entries, duh! */ + + static void init_paging(ContFramePool * _kernel_mem_pool, + ContFramePool * _process_mem_pool, + const unsigned long _shared_size); + /* Set the global parameters for the paging subsystem. */ + + PageTable(); + /* Initializes a page table with a given location for the directory and the + page table proper. + NOTE: The PageTable object still needs to be stored somewhere! + Probably it is best to have it on the stack, as there is no + memory manager yet... + NOTE2: It may also be simpler to create the first page table *before* + paging has been enabled. + */ + + void load(); + /* Makes the given page table the current table. This must be done once during + system startup and whenever the address space is switched (e.g. during + process switching). */ + + static void enable_paging(); + /* Enable paging on the CPU. Typically, a CPU start with paging disabled, and + memory is accessed by addressing physical memory directly. After paging is + enabled, memory is addressed logically. */ + + static void handle_fault(REGS * _r); + /* The page fault handler. */ + +}; + +#endif + diff --git a/MP3/MP3_Sources/paging_low.H b/MP3/MP3_Sources/paging_low.H new file mode 100755 index 0000000..f36603a --- /dev/null +++ b/MP3/MP3_Sources/paging_low.H @@ -0,0 +1,51 @@ +/* + File: paging_low.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/28 + + + Low-level register operations for x86 paging subsystem. + +*/ + +#ifndef _paging_low_H_ // include file only once +#define _paging_low_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- none -- */ + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* LOW-LEVEL PAGING ROUTINES */ +/*--------------------------------------------------------------------------*/ + +/* The low-level functions (defined in file 'paging_low.asm') that handle the + low-level function to manage the page tables. */ + + +/* -- CR0 -- */ +extern "C" unsigned long read_cr0(); +extern "C" void write_cr0(unsigned long _val); + +/* -- CR2 -- */ +extern "C" unsigned long read_cr2(); + +/* -- CR3 -- */ +extern "C" unsigned long read_cr3(); +extern "C" void write_cr3(unsigned long _val); + + +#endif + + diff --git a/MP3/MP3_Sources/paging_low.asm b/MP3/MP3_Sources/paging_low.asm new file mode 100755 index 0000000..071a775 --- /dev/null +++ b/MP3/MP3_Sources/paging_low.asm @@ -0,0 +1,32 @@ +global _read_cr0 +_read_cr0: + mov eax, cr0 + retn + +global _write_cr0 +_write_cr0: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr0, eax + pop ebp + retn + +global _read_cr2 +_read_cr2: + mov eax, cr2 + retn + +global _read_cr3 +_read_cr3: + mov eax, cr3 + retn + +global _write_cr3 +_write_cr3: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr3, eax + pop ebp + retn \ No newline at end of file diff --git a/MP3/MP3_Sources/simple_keyboard.C b/MP3/MP3_Sources/simple_keyboard.C new file mode 100755 index 0000000..f821d80 --- /dev/null +++ b/MP3/MP3_Sources/simple_keyboard.C @@ -0,0 +1,79 @@ +/* + File: simple_keyboard.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 2017/06/30 + + Simple control of the keyboard. + */ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* (none) */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "machine.H" +#include "console.H" +#include "interrupts.H" +#include "simple_keyboard.H" + +/*--------------------------------------------------------------------------*/ +/* CONSTRUCTOR */ +/*--------------------------------------------------------------------------*/ + +SimpleKeyboard::SimpleKeyboard() { + key_pressed = false; +} + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS S i m p l e K e y b o a r d */ +/*--------------------------------------------------------------------------*/ + +void SimpleKeyboard::handle_interrupt(REGS *_r) { + /* What to do when keyboard interrupt occurs? In this case, we update + "key_pressed". */ + + unsigned char status = Machine::inportb(STATUS_PORT); + /* lowest bit of status will be set if buffer is not empty. */ + if (status & 0x01) { + char kc = Machine::inportb(DATA_PORT); + if (kc >= 0) { + key_pressed = true; + key_code = kc; + } + } +} + +void SimpleKeyboard::wait() { + /* Loop until the user presses a key. */ + + kb.key_pressed = false; + + while(kb.key_pressed == false); + +} + +char SimpleKeyboard::read() { + /* Loop until the user presses a key, and then return the keycode. */ + kb.key_pressed = false; + + while (kb.key_pressed == false); + + return kb.key_code; +} + +SimpleKeyboard SimpleKeyboard::kb; + +void SimpleKeyboard::init() { + InterruptHandler::register_handler(1, &kb); +} + + diff --git a/MP3/MP3_Sources/simple_keyboard.H b/MP3/MP3_Sources/simple_keyboard.H new file mode 100755 index 0000000..823c09c --- /dev/null +++ b/MP3/MP3_Sources/simple_keyboard.H @@ -0,0 +1,68 @@ +/* + File: simple_keyboard.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 2017/02/17 + + Implements an interrupt handler for the keyboard. + The function is implemented in 'handle_interrupt'. + +*/ + +#ifndef _SIMPLE_KEYBOARD_H_ +#define _SIMPLE_KEYBOARD_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "interrupts.H" + +/*--------------------------------------------------------------------------*/ +/* S I M P L E K E Y B O A R D */ +/*--------------------------------------------------------------------------*/ + +class SimpleKeyboard : public InterruptHandler { + +public : + + SimpleKeyboard(); + /* Initialize the simple keyboard. */ + + virtual void handle_interrupt(REGS *_r); + /* This must be installed as the interrupt handler for the keyboard + when the system gets initialized. (e.g. in "kernel.C") + */ + + static void init(); + + static void wait(); + /* Wait until keyboard is pressed. The implementation is based + on busy looping! */ + + static char read(); + /* Wait until keyboard is pressed and return the keycode. + Note: The keycode is not the same as the character! + Note2: This is a very "approximate" implementation. Not complete, + and likely not correct. Use only under duress! + The implementation is based on busy looping! */ + +private: + bool key_pressed; + char key_code; + static SimpleKeyboard kb; + + static const unsigned short STATUS_PORT = 0x64; + static const unsigned short DATA_PORT = 0x60; + +}; + +#endif diff --git a/MP3/MP3_Sources/simple_timer.C b/MP3/MP3_Sources/simple_timer.C new file mode 100755 index 0000000..61c9b1c --- /dev/null +++ b/MP3/MP3_Sources/simple_timer.C @@ -0,0 +1,100 @@ +/* + File: simple_timer.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/19 + + Simple control of the +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "utils.H" +#include "console.H" +#include "interrupts.H" +#include "simple_timer.H" + +/*--------------------------------------------------------------------------*/ +/* CONSTRUCTOR */ +/*--------------------------------------------------------------------------*/ + +SimpleTimer::SimpleTimer(int _hz) { + /* How long has the system been running? */ + seconds = 0; + ticks = 0; /* ticks since last "seconds" update. */ + + /* At what frequency do we update the ticks counter? */ + /* hz = 18; */ + /* Actually, by defaults it is 18.22Hz. + In this way, a 16-bit counter wraps + around every hour. */ + set_frequency(_hz); + +} + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS S i m p l e T i m e r */ +/*--------------------------------------------------------------------------*/ + + +void SimpleTimer::handle_interrupt(REGS *_r) { +/* What to do when timer interrupt occurs? In this case, we update "ticks", + and maybe update "seconds". + This must be installed as the interrupt handler for the timer in the + when the system gets initialized. (e.g. in "kernel.C") */ + + /* Increment our "ticks" count */ + ticks++; + + /* Whenever a second is over, we update counter accordingly. */ + if (ticks >= hz ) + { + seconds++; + ticks = 0; + Console::puts("One second has passed\n"); + } +} + + +void SimpleTimer::set_frequency(int _hz) { +/* Set the interrupt frequency for the simple timer. + Preferably set this before installing the timer handler! */ + + hz = _hz; /* Remember the frequency. */ + int divisor = 1193180 / _hz; /* The input clock runs at 1.19MHz */ + Machine::outportb(0x43, 0x34); /* Set command byte to be 0x36. */ + Machine::outportb(0x40, divisor & 0xFF); /* Set low byte of divisor. */ + Machine::outportb(0x40, divisor >> 8); /* Set high byte of divisor. */ +} + +void SimpleTimer::current(unsigned long * _seconds, int * _ticks) { +/* Return the current "time" since the system started. */ + + *_seconds = seconds; + *_ticks = ticks; +} + +void SimpleTimer::wait(unsigned long _seconds) { +/* Wait for a particular time to be passed. This is based on busy looping! */ + + unsigned long now_seconds; + int now_ticks; + current(&now_seconds, &now_ticks); + + unsigned long then_seconds = now_seconds + _seconds; + + while((seconds <= then_seconds) && (ticks < now_ticks)); +} + + diff --git a/MP3/MP3_Sources/simple_timer.H b/MP3/MP3_Sources/simple_timer.H new file mode 100755 index 0000000..ca48a0a --- /dev/null +++ b/MP3/MP3_Sources/simple_timer.H @@ -0,0 +1,70 @@ +/* + File: simple_timer.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/19 + + This is a simple example of a hardware interrupt handler. + As an example, this implements a timer, which in turn + triggers a function to be called at the given frequency. + The function is implemented in 'handle_interrupt'. + +*/ + +#ifndef _SIMPLE_TIMER_H_ +#define _SIMPLE_TIMER_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "interrupts.H" + +/*--------------------------------------------------------------------------*/ +/* S I M P L E T I M E R */ +/*--------------------------------------------------------------------------*/ + +class SimpleTimer : public InterruptHandler { + +private: + + /* How long has the system been running? */ + unsigned long seconds; + int ticks; /* ticks since last "seconds" update. */ + + /* At what frequency do we update the ticks counter? */ + int hz; /* Actually, by defaults it is 18.22Hz. + In this way, a 16-bit counter wraps + around every hour. */ + + void set_frequency(int _hz); + /* Set the interrupt frequency for the simple timer. */ + +public : + + SimpleTimer(int _hz); + /* Initialize the simple timer, and set its frequency. */ + + virtual void handle_interrupt(REGS *_r); + /* This must be installed as the interrupt handler for the timer + when the system gets initialized. (e.g. in "kernel.C") + */ + + void current(unsigned long * _seconds, int * _ticks); + /* Return the current "time" since the system started. */ + + void wait(unsigned long _seconds); + /* Wait for a particular time to be passed. The implementation is based + on busy looping! */ + +}; + +#endif diff --git a/MP3/MP3_Sources/start.asm b/MP3/MP3_Sources/start.asm new file mode 100755 index 0000000..9bbc858 --- /dev/null +++ b/MP3/MP3_Sources/start.asm @@ -0,0 +1,110 @@ +; bkerndev - Bran's Kernel Development Tutorial +; By: Brandon F. (friesenb@gmail.com) +; Desc: Kernel entry point, stack, and Interrupt Service Routines. +; +; Notes: No warranty expressed or implied. Use at own risk. +; +; This is the kernel's entry point. We could either call main here, +; or we can use this to setup the stack or other nice stuff, like +; perhaps setting up the GDT and segments. Please note that interrupts +; are disabled at this point: More on interrupts later! +[BITS 32] +global start +start: + mov esp, _sys_stack ; This points the stack to our new stack area + jmp stublet + +; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4' +ALIGN 4 +mboot: + ; Multiboot macros to make a few lines later more readable + MULTIBOOT_PAGE_ALIGN equ 1<<0 + MULTIBOOT_MEMORY_INFO equ 1<<1 + MULTIBOOT_AOUT_KLUDGE equ 1<<16 + MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 + MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE + MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + EXTERN code, bss, end + + ; This is the GRUB Multiboot header. A boot signature + dd MULTIBOOT_HEADER_MAGIC + dd MULTIBOOT_HEADER_FLAGS + dd MULTIBOOT_CHECKSUM + + ; AOUT kludge - must be physical addresses. Make a note of these: + ; The linker script fills in the data for these ones! + dd mboot ; header_addr: + ; address corresponding to the multiboot header + dd code ; load_addr: + ; physical address of the beginning of the text segment + dd bss ; load_end_addr: + ; physical address of the end of the data segment + ; (load_end_addr - load_addr) specifies how much data to load. + dd end ; bss_end_addr: + ; pysical address of end of bss segment. + ; boot loader initializes this area to zero, + ; and reserves the memory + dd start ; entry_addr: + ; physical address to which the boot loader should jump + ; to start running the OS + +stublet: + +; Initilization of static global objects. This goes through each object +; in the ctors section of the object file, where the global constructors +; created by C++ are put, and calls it. Normally C++ compilers add some code +; to do this, but that code is in the standard library - which we do not +; include +; See linker.ld to see where we tell the linker to put them. + extern start_ctors, end_ctors, start_dtors, end_dtors + +static_ctors_loop: + mov ebx, start_ctors + jmp .test + .body: + call [ebx] + add ebx,4 + .test: + cmp ebx, end_ctors + jb .body + +; Entering the kernel proper. + extern _main + call _main + +; Deinitialization of static global objects. This goes through each object +; in the dtors section of the object file, where the global destructors +; created by C++ are put, and calls it. Normally C++ compilers add some code +; to do this, but that code is in the standard library - which we do not include. +; See linker.ld to see where we tell the linker to put them. + +static_dtors_loop: + mov ebx, start_dtors + jmp .test + .body: + call [ebx] + add ebx,4 + .test: + cmp ebx, end_dtors + jb .body + +; Enter an endless loop here in order to stop. + jmp $ + +; Set up Global Descriptor Table +%include "gdt_low.asm" + +; Set up Low-level Exception Handling +%include "idt_low.asm" + +; Set up Low-level Interrupt Handling +%include "irq_low.asm" + +; Here is the definition of our BSS section. Right now, we'll use +; it just to store the stack. Remember that a stack actually grows +; downwards, so we declare the size of the data before declaring +; the identifier '_sys_stack' +SECTION .bss + resb 8192 ; This reserves 8KBytes of memory here +_sys_stack: + diff --git a/MP3/MP3_Sources/utils.C b/MP3/MP3_Sources/utils.C new file mode 100755 index 0000000..15fd38a --- /dev/null +++ b/MP3/MP3_Sources/utils.C @@ -0,0 +1,167 @@ +/* + File: utils.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + + Date : 09/02/12 + +*/ + +/* Some of the code comes from Brandon Friesens OS Tutorial: +* bkerndev - Bran's Kernel Development Tutorial +* By: Brandon F. (friesenb@gmail.com) +* Desc: Interrupt Descriptor Table management +* +* Notes: No warranty expressed or implied. Use at own risk. */ + + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none ) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "utils.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* ABORT (USED e.g. IN _ASSERT() */ +/*--------------------------------------------------------------------------*/ + +void abort() { + for(;;); +} + +/*--------------------------------------------------------------------------*/ +/* MEMORY OPERATIONS */ +/*--------------------------------------------------------------------------*/ + +void *memcpy(void *dest, const void *src, int count) +{ + const char *sp = (const char *)src; + char *dp = (char *)dest; + for(; count != 0; count--) *dp++ = *sp++; + return dest; +} + +void *memset(void *dest, char val, int count) +{ + char *temp = (char *)dest; + for( ; count != 0; count--) *temp++ = val; + return dest; +} + +unsigned short *memsetw(unsigned short *dest, unsigned short val, int count) +{ + unsigned short *temp = (unsigned short *)dest; + for( ; count != 0; count--) *temp++ = val; + return dest; +} + +/*--------------------------------------------------------------------------*/ +/* STRING OPERATIONS */ +/*--------------------------------------------------------------------------*/ + + +int strlen(const char *_str) { + /* This loops through character array 'str', returning how + * many characters it needs to check before it finds a 0. + * In simple words, it returns the length in bytes of a string */ + int len = 0; + while (*_str != 0) { + _str++; + len++; + } + return len; +} +void strcpy(char* _dst, char* _src) { + while (*_src != 0) { + *_dst = *_src; + _dst++; + _src++; + } + *_dst = 0; // put terminating 0 at end. +} + +void int2str(int _num, char * _str) { + /* -- THIS IMPLEMENTATION IS ONE PRETTY BAD HACK. */ + int i; + char temp[11]; + + temp[0] = '\0'; + for(i = 1; i <= 10; i++) { + temp[i] = _num % 10 + '0'; + _num /= 10; + } + for(i = 10; temp[i] == '0'; i--); + if( i == 0 ) + i++; + while( i >= 0 ) + *_str++ = temp[i--]; +} + + +void uint2str(unsigned int _num, char * _str) { + /* -- THIS IS A BAD HACK AS WELL. */ + int i; + char temp[11]; + + temp[0] = '\0'; + for(i = 1; i <= 10; i++) { + temp[i] = _num % 10 + '0'; + _num /= 10; + } + for(i = 10; temp[i] == '0'; i--); + if( i == 0 ) + i++; + while( i >= 0 ) + *_str++ = temp[i--]; +} + +/*--------------------------------------------------------------------------*/ +/* POERT I/O OPERATIONS */ +/*--------------------------------------------------------------------------*/ + +/* We will use this later on for reading from the I/O ports to get data +* from devices such as the keyboard. We are using what is called +* 'inline assembly' in these routines to actually do the work */ +char inportb (unsigned short _port) { + unsigned char rv; + __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +unsigned short inportw (unsigned short _port) { + unsigned short rv; + __asm__ __volatile__ ("inw %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +/* We will use this to write to I/O ports to send bytes to devices. This +* will be used in the next tutorial for changing the textmode cursor +* position. Again, we use some inline assembly for the stuff that simply +* cannot be done in C */ +void outportb (unsigned short _port, char _data) { + __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); +} + +void outportw (unsigned short _port, unsigned short _data) { + __asm__ __volatile__ ("outw %1, %0" : : "dN" (_port), "a" (_data)); +} diff --git a/MP3/MP3_Sources/utils.H b/MP3/MP3_Sources/utils.H new file mode 100755 index 0000000..71c6c4c --- /dev/null +++ b/MP3/MP3_Sources/utils.H @@ -0,0 +1,62 @@ +/* + File : utils.H + + Author : Riccardo Bettati + Modified : 2017/05/02 + + Description : Various definitions (NULL) and + utility functions (e.g. abort, memory and + string functions). +*/ + +#ifndef _utils_h_ +#define _utils_h_ + +/*---------------------------------------------------------------*/ +/* GENERAL CONSTANTS */ +/*---------------------------------------------------------------*/ + +#ifndef NULL +# define NULL 0 +#endif + +/*---------------------------------------------------------------*/ +/* ABORT */ +/*---------------------------------------------------------------*/ + +void abort(); +/* Stop execution. */ + +/*---------------------------------------------------------------*/ +/* SIMPLE MEMORY OPERATIONS */ +/*---------------------------------------------------------------*/ + +void *memcpy(void *dest, const void *src, int count); +/* Copy _count bytes from _src to _dest. (No check for uverlapping) */ + +void *memset(void *dest, char val, int count); +/* Set _count bytes to value _val, starting from location _dest. */ + +unsigned short *memsetw(unsigned short *dest, unsigned short val, int count); +/* Same as above, but operations are 16-bit wide. */ + +/*---------------------------------------------------------------*/ +/* SIMPLE STRING OPERATIONS (STRINGS ARE NULL-TERMINATED) */ +/*---------------------------------------------------------------*/ + +int strlen(const char * _str); +/* Determine the length of null-terminated string. */ + +void strcpy(char * _dst, char * _src); +/* Copy null-terminated string from _src to _dst. */ + +void int2str(int _num, char * _str); +/* Convert int to null-terminated string. */ + +void uint2str(unsigned int _num, char * _str); +/* Convert unsigned int to null-terminated string. */ + +#endif + + + diff --git a/MP3/__MACOSX/._MP3_Sources b/MP3/__MACOSX/._MP3_Sources new file mode 100644 index 0000000..2d8d9d3 Binary files /dev/null and b/MP3/__MACOSX/._MP3_Sources differ diff --git a/MP3/__MACOSX/MP3_Sources/._BIOS-bochs-latest b/MP3/__MACOSX/MP3_Sources/._BIOS-bochs-latest new file mode 100644 index 0000000..7a70ab4 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._BIOS-bochs-latest differ diff --git a/MP3/__MACOSX/MP3_Sources/._README.TXT b/MP3/__MACOSX/MP3_Sources/._README.TXT new file mode 100644 index 0000000..d7d8917 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._README.TXT differ diff --git a/MP3/__MACOSX/MP3_Sources/._VGABIOS-lgpl-latest b/MP3/__MACOSX/MP3_Sources/._VGABIOS-lgpl-latest new file mode 100644 index 0000000..2848578 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._VGABIOS-lgpl-latest differ diff --git a/MP3/__MACOSX/MP3_Sources/._assert.C b/MP3/__MACOSX/MP3_Sources/._assert.C new file mode 100644 index 0000000..0cfe800 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._assert.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._assert.H b/MP3/__MACOSX/MP3_Sources/._assert.H new file mode 100644 index 0000000..812693d Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._assert.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._bochsrc.bxrc b/MP3/__MACOSX/MP3_Sources/._bochsrc.bxrc new file mode 100644 index 0000000..e4e836e Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._bochsrc.bxrc differ diff --git a/MP3/__MACOSX/MP3_Sources/._console.C b/MP3/__MACOSX/MP3_Sources/._console.C new file mode 100644 index 0000000..5831632 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._console.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._console.H b/MP3/__MACOSX/MP3_Sources/._console.H new file mode 100644 index 0000000..82f9a1d Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._console.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._cont_frame_pool.C b/MP3/__MACOSX/MP3_Sources/._cont_frame_pool.C new file mode 100644 index 0000000..651be91 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._cont_frame_pool.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._cont_frame_pool.H b/MP3/__MACOSX/MP3_Sources/._cont_frame_pool.H new file mode 100644 index 0000000..960b1c7 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._cont_frame_pool.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._copykernel.sh b/MP3/__MACOSX/MP3_Sources/._copykernel.sh new file mode 100644 index 0000000..8f3eaf0 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._copykernel.sh differ diff --git a/MP3/__MACOSX/MP3_Sources/._dev_kernel_grub.img b/MP3/__MACOSX/MP3_Sources/._dev_kernel_grub.img new file mode 100644 index 0000000..c9ab47b Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._dev_kernel_grub.img differ diff --git a/MP3/__MACOSX/MP3_Sources/._exceptions.C b/MP3/__MACOSX/MP3_Sources/._exceptions.C new file mode 100644 index 0000000..0128a69 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._exceptions.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._exceptions.H b/MP3/__MACOSX/MP3_Sources/._exceptions.H new file mode 100644 index 0000000..d3a4c89 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._exceptions.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._gdt.C b/MP3/__MACOSX/MP3_Sources/._gdt.C new file mode 100644 index 0000000..7d3ab79 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._gdt.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._gdt.H b/MP3/__MACOSX/MP3_Sources/._gdt.H new file mode 100644 index 0000000..349b631 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._gdt.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._gdt_low.asm b/MP3/__MACOSX/MP3_Sources/._gdt_low.asm new file mode 100644 index 0000000..7877477 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._gdt_low.asm differ diff --git a/MP3/__MACOSX/MP3_Sources/._idt.C b/MP3/__MACOSX/MP3_Sources/._idt.C new file mode 100644 index 0000000..e47142d Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._idt.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._idt.H b/MP3/__MACOSX/MP3_Sources/._idt.H new file mode 100644 index 0000000..53b2e85 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._idt.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._idt_low.asm b/MP3/__MACOSX/MP3_Sources/._idt_low.asm new file mode 100644 index 0000000..8cd5f48 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._idt_low.asm differ diff --git a/MP3/__MACOSX/MP3_Sources/._interrupts.C b/MP3/__MACOSX/MP3_Sources/._interrupts.C new file mode 100644 index 0000000..4d3d4b6 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._interrupts.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._interrupts.H b/MP3/__MACOSX/MP3_Sources/._interrupts.H new file mode 100644 index 0000000..861dbaf Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._interrupts.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._irq.C b/MP3/__MACOSX/MP3_Sources/._irq.C new file mode 100644 index 0000000..809c47e Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._irq.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._irq.H b/MP3/__MACOSX/MP3_Sources/._irq.H new file mode 100644 index 0000000..c684604 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._irq.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._irq_low.asm b/MP3/__MACOSX/MP3_Sources/._irq_low.asm new file mode 100644 index 0000000..1684262 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._irq_low.asm differ diff --git a/MP3/__MACOSX/MP3_Sources/._kernel.C b/MP3/__MACOSX/MP3_Sources/._kernel.C new file mode 100644 index 0000000..790071a Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._kernel.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._linker.ld b/MP3/__MACOSX/MP3_Sources/._linker.ld new file mode 100644 index 0000000..8470887 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._linker.ld differ diff --git a/MP3/__MACOSX/MP3_Sources/._machine.C b/MP3/__MACOSX/MP3_Sources/._machine.C new file mode 100644 index 0000000..cadd5db Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._machine.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._machine.H b/MP3/__MACOSX/MP3_Sources/._machine.H new file mode 100644 index 0000000..2abc54b Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._machine.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._machine_low.H b/MP3/__MACOSX/MP3_Sources/._machine_low.H new file mode 100644 index 0000000..5079b51 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._machine_low.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._machine_low.asm b/MP3/__MACOSX/MP3_Sources/._machine_low.asm new file mode 100644 index 0000000..41acb68 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._machine_low.asm differ diff --git a/MP3/__MACOSX/MP3_Sources/._makefile b/MP3/__MACOSX/MP3_Sources/._makefile new file mode 100644 index 0000000..d1cfc02 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._makefile differ diff --git a/MP3/__MACOSX/MP3_Sources/._page_table.C b/MP3/__MACOSX/MP3_Sources/._page_table.C new file mode 100644 index 0000000..d5fe730 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._page_table.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._page_table.H b/MP3/__MACOSX/MP3_Sources/._page_table.H new file mode 100644 index 0000000..0ee1b32 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._page_table.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._paging_low.H b/MP3/__MACOSX/MP3_Sources/._paging_low.H new file mode 100644 index 0000000..64c192f Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._paging_low.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._paging_low.asm b/MP3/__MACOSX/MP3_Sources/._paging_low.asm new file mode 100644 index 0000000..a6f3078 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._paging_low.asm differ diff --git a/MP3/__MACOSX/MP3_Sources/._simple_keyboard.C b/MP3/__MACOSX/MP3_Sources/._simple_keyboard.C new file mode 100644 index 0000000..4bfa1b6 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._simple_keyboard.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._simple_keyboard.H b/MP3/__MACOSX/MP3_Sources/._simple_keyboard.H new file mode 100644 index 0000000..f211e5b Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._simple_keyboard.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._simple_timer.C b/MP3/__MACOSX/MP3_Sources/._simple_timer.C new file mode 100644 index 0000000..c529079 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._simple_timer.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._simple_timer.H b/MP3/__MACOSX/MP3_Sources/._simple_timer.H new file mode 100644 index 0000000..e900fde Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._simple_timer.H differ diff --git a/MP3/__MACOSX/MP3_Sources/._start.asm b/MP3/__MACOSX/MP3_Sources/._start.asm new file mode 100644 index 0000000..53ab097 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._start.asm differ diff --git a/MP3/__MACOSX/MP3_Sources/._utils.C b/MP3/__MACOSX/MP3_Sources/._utils.C new file mode 100644 index 0000000..29276e9 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._utils.C differ diff --git a/MP3/__MACOSX/MP3_Sources/._utils.H b/MP3/__MACOSX/MP3_Sources/._utils.H new file mode 100644 index 0000000..0e78739 Binary files /dev/null and b/MP3/__MACOSX/MP3_Sources/._utils.H differ