diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/Makefile | 30 | ||||
| -rw-r--r-- | kernel/defines | 6 | ||||
| -rw-r--r-- | kernel/driver/keyboard.c | 37 | ||||
| -rw-r--r-- | kernel/driver/video.c | 503 | ||||
| -rw-r--r-- | kernel/hal/Makefile | 20 | ||||
| -rw-r--r-- | kernel/hal/counters.c | 17 | ||||
| -rw-r--r-- | kernel/hal/interrupts.c | 230 | ||||
| -rw-r--r-- | kernel/hal/interrupts.h | 92 | ||||
| -rw-r--r-- | kernel/hal/intsupport.asm | 326 | ||||
| -rw-r--r-- | kernel/hal/io.c | 40 | ||||
| -rw-r--r-- | kernel/hal/timer.c | 43 | ||||
| -rw-r--r-- | kernel/hal/timestamp.asm | 19 | ||||
| -rw-r--r-- | kernel/hal/video.h | 15 | ||||
| -rw-r--r-- | kernel/inc/constants.h | 50 | ||||
| -rw-r--r-- | kernel/inc/hal.h | 104 | ||||
| -rw-r--r-- | kernel/inc/kernel.h | 43 | ||||
| -rw-r--r-- | kernel/inc/macros.h | 43 | ||||
| -rw-r--r-- | kernel/inc/rtl.h | 33 | ||||
| -rw-r--r-- | kernel/inc/types.h | 80 | ||||
| -rw-r--r-- | kernel/init/Makefile | 20 | ||||
| -rw-r--r-- | kernel/init/entry.asm | 23 | ||||
| -rw-r--r-- | kernel/init/main.c | 67 | ||||
| -rwxr-xr-x | kernel/kernel.bin | bin | 0 -> 13260 bytes | |||
| -rw-r--r-- | kernel/kernel.map | 370 | ||||
| -rw-r--r-- | kernel/rtl/Makefile | 19 | ||||
| -rw-r--r-- | kernel/rtl/memory.c | 29 | ||||
| -rw-r--r-- | kernel/rtl/string.c | 138 |
27 files changed, 2397 insertions, 0 deletions
diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..b5838d6 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,30 @@ +DEBUGFLAGS=-DDEBUG + +SUBDIR += init +SUBDIR += hal +SUBDIR += rtl + +.include <bsd.port.subdir.mk> + +OBJCOPY= objcopy +OBJCOPY_FLAGS= -R .dynamic -R .note -R .comment +OBJS= init/entry.o init/main.o hal/video.o hal/io.o \ + rtl/string.o rtl/memory.o hal/intsupport.o hal/interrupts.o \ + hal/timer.o hal/keyboard.o hal/timestamp.o hal/counters.o +RM= /bin/rm + +all: kernel.bin + +kernel.bin: kernel.tmp + $(OBJCOPY) $(OBJCOPY_FLAGS) -S -O binary ./kernel.tmp kernel.bin ; \ + mcopy -o ./kernel.bin Q: ; \ + mcopy -o ./kernel.map Q: ; \ + $(RM) -f kernel.tmp + +kernel.tmp: $(OBJS) + $(LD) -M -o kernel.tmp -Ttext 0x00010000 -e StartOfKernelImage $(OBJS) \ + > kernel.map + +clean: + $(RM) -f $(TARGET) $(OBJS) *~ #*# .#* ; \ + mdel Q:\$(TARGET) diff --git a/kernel/defines b/kernel/defines new file mode 100644 index 0000000..dcee875 --- /dev/null +++ b/kernel/defines @@ -0,0 +1,6 @@ +// +// Symbols defined here are globally defined in all Makefiles below +// here. +// +#define KERNEL +#define DEBUG
\ No newline at end of file diff --git a/kernel/driver/keyboard.c b/kernel/driver/keyboard.c new file mode 100644 index 0000000..7410171 --- /dev/null +++ b/kernel/driver/keyboard.c @@ -0,0 +1,37 @@ +//+---------------------------------------------------------------------------- +// +// File: keyboard.c +// +// Module: +// +// Synopsis: +// +// Created: sgasch 21 Oct 2003 +// +//+---------------------------------------------------------------------------- + +#include "kernel.h" +#include "hal.h" +#include "rtl.h" +#include "interrupts.h" + +void +HalKeyboardInt(INTERRUPT_STATE *is) +{ + BYTE c; + BYTE k; + + HalDisableInterrupts(); + + c = in(0x64); + HalIoDelay(); + if (c & 1) + { + k = in(0x60); + HalIoDelay(); + HalVideoPrint("Testing %x.\n\0", 1); + } + + HalEnableInterrupts(); +} + diff --git a/kernel/driver/video.c b/kernel/driver/video.c new file mode 100644 index 0000000..a63331b --- /dev/null +++ b/kernel/driver/video.c @@ -0,0 +1,503 @@ +//+---------------------------------------------------------------------------- +// +// File: video.c +// +// Module: Video driver +// +// Synopsis: low-level interface to video memory +// +// Created: sgasch 5 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#include <stdarg.h> + +#include "kernel.h" +#include "hal.h" +#include "rtl.h" +#include "video.h" + +extern BIOS_HARDWARE_BLOCK g_BiosHardwareBlock; + +// +// Local #defines +// +#define FG_BG_TO_ATTRIB_BYTE(fg,bg) ((fg&0x0F)|((bg&0x0F)<<4)) +#define LINES (0) +#define COLS (1) +#define CRT_ADDR_REG (0x3D4) +#define CRT_DATA_REG (0x3D5) +#define CRT_CURSOR_LOC_HIGH_REG (0x0E) +#define CRT_CURSOR_LOC_LOW_REG (0x0F) +#define ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(L,C)\ + (((g_bScreenResolution[COLS] << 1) * (L)) + ((C) << 1)) +#define ZERO_BASED_LINE_COL_TO_ULONG_OFFSET(L,C)\ + (ZERO_BASED_LINE_COL_TO_BYTE_OFFSET((L),(C)) >> 2) + +// +// Global identifiers +// +BYTE *g_pVideoMemory = NULL; +BYTE g_bScreenResolution[2] = { 0, 0 }; +BYTE g_bSoftCursor[2] = { 0, 0 }; +BYTE g_bColorAttribute = FG_BG_TO_ATTRIB_BYTE(BLACK, WHITE); + +typedef struct _VIDEO_LOOKUP_ENTRY +{ + CHAR *szBoardName; + BYTE *pStartOfVideoMemory; + BYTE uScreenLines[3]; +} +VIDEO_LOOKUP_ENTRY; + +static VIDEO_LOOKUP_ENTRY g_VideoLookupTable[] = +{ + { "No video adapter", + (BYTE *)0x000B0000, + { 25, 25, 25 } }, + { "Monochrome display adapter", + (BYTE *)0x000B0000, + { 25, 25, 25 } }, + { "CGA", + (BYTE *)0x000B8000, + { 25, 25, 25 } }, + { "Code 3: Undefined", + (BYTE *)0x000B0000, + { 25, 25, 25 } }, + { "EGA with color display", + (BYTE *)0x000B8000, + { 43, 25, 25 } }, + { "EGA with mono display", + (BYTE *)0x000B0000, + { 43, 25, 25 } }, + { "Code 6: Undefined", + (BYTE *)0x000B0000, + { 25, 25, 25 } }, + { "VGA with mono display", + (BYTE *)0x000B0000, + { 50, 27, 25 } }, + { "VGA with color display", + (BYTE *)0x000B8000, + { 50, 27, 25 } }, + { "Code 9: Undefined", + (BYTE *)0x000B0000, + { 25, 25, 25 } }, + { "MCGA with digital color", + (BYTE *)0x000B8000, + { 25, 25, 25 } }, + { "MCGA with monochrome", + (BYTE *)0x000B0000, + { 25, 25, 25 } }, + { "MCGA with analog color", + (BYTE *)0x000B8000, + { 25, 25, 25 } } +}; + + +//+---------------------------------------------------------------------------- +// +// Function: VideopInitialize +// +// Synopsis: +// +// Arguments: void +// +// Returns: STATUS +// +//+---------------------------------------------------------------------------- +STATUS +VideopInitialize(void) +{ + BYTE uType = g_BiosHardwareBlock.bDisplayType; + BYTE uIndex = 2; + + // + // Based on the font size (width in pixels), set the index into the + // screen lines lookup table + // + switch(g_BiosHardwareBlock.bFontSize) + { + case 8: + uIndex = 0; + break; + case 14: + uIndex = 1; + break; + case 16: + uIndex = 2; + break; + } + + // + // If the display type returned by BIOS is known to us, use the + // lookup table to populate some globals here. + // + if (uType <= ARRAY_LENGTH(g_VideoLookupTable)) + { + g_pVideoMemory = g_VideoLookupTable[uType].pStartOfVideoMemory; + g_bScreenResolution[LINES] = + g_VideoLookupTable[uType].uScreenLines[uIndex]; + } + + // + // Otherwise make some guesses + // + else + { + g_pVideoMemory = (BYTE *)0x000B8000; + g_bScreenResolution[LINES] = 25; + } + g_bScreenResolution[COLS] = 80; + + // + // Set color to WHITE on BLACK + // + VideoSetCurrentColorAttribute(WHITE, BLACK); + + // + // Clear the screen and thus synchronize the hardware and soft cursor + // position. + // + VideoClearScreen(); + return(STATUS_SUCCESS); +} + + +//+---------------------------------------------------------------------------- +// +// Function: VideoDriverMain +// +// Synopsis: +// +// Arguments: UINT uEvent +// +// Returns: STATUS +// +//+---------------------------------------------------------------------------- +STATUS +VideoDriverMain(UINT uEvent) +{ + switch(uEvent) + { + case DEVICE_DRIVER_INITIALIZATION: + return(VideopInitialize()); + + case DEVICE_DETATCH: + ASSERT(FALSE); + return(STATUS_NOT_SUPPORTED); + + case DEVICE_DRIVER_SHUTDOWN: + g_fVideoEnabled = FALSE; + return(STATUS_SUCCESS); + + default: + } + return(TRUE); +} + +STATUS +VideoDriverRead(UINT uAddress, + void *pBuffer, + UINT uBufferLength); + +STATUS +VideoDriverWrite(UINT uAddress, + void *pBuffer, + UINT uBufferLength); + +STATUS +VideoDriverIoctl(UINT uIoctlCode, + void *pBuffer, + UINT uBufferLength); + + +// +// Move the hardware cursor on the screen to sync up with the software +// cursor position in g_bSoftwareCursor +// +void +VideoSetHardwareCursor(void) +{ + WORD wOffset; // byte offset into video mem + BYTE bOrig; // original port contents holder + + // + // Cursor is zero-based (e.g. line 24 is the last one) + // + ASSERT(g_bSoftCursor[LINES] < g_bScreenResolution[LINES]); + ASSERT(g_bSoftCursor[COLS] < g_bScreenResolution[COLS]); + + wOffset = ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bSoftCursor[LINES], + g_bSoftCursor[COLS]); + ASSERT(wOffset <= (g_bScreenResolution[LINES] * + g_bScreenResolution[COLS]) * 2 - 2); + + // + // Save original contents of CRT address register. + // + bOrig = in(CRT_ADDR_REG); + + // + // Set the high cursor location byte + // + out(CRT_ADDR_REG, CRT_CURSOR_LOC_HIGH_REG); + out(CRT_DATA_REG, (wOffset >> 8) & 0xFF); + IoDelay(); + + // + // Set the low cursor location byte + // + out(CRT_ADDR_REG, CRT_CURSOR_LOC_LOW_REG); + IoDelay(); + out(CRT_DATA_REG, (wOffset & 0xFF)); + IoDelay(); + + // + // Restore contents of the CRT address register + // + out(CRT_ADDR_REG, bOrig); + IoDelay(); +} + +void +VideoSetCurrentColorAttribute(BYTE bFg, BYTE bBg) +{ + bFg &= 0x0F; // restrict these guys to colors + bBg &= 0x0F; // and the high intense bit + + g_bColorAttribute = FG_BG_TO_ATTRIB_BYTE(bFg, bBg); +} + +void +VideoClearScreen(void) +{ + ULONG *p = (ULONG *)g_pVideoMemory; + ULONG uFill; + ULONG uCount; + + // + // Start uCount at the number of ULONGs in visible video memory + // + uCount = ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bScreenResolution[LINES] - 1, + g_bScreenResolution[COLS] - 1); + uCount += 2; + uCount >>= 2; + + // + // Construct a fill ULONG: blank attrib blank attrib + // + uFill = 0; + uFill |= (ULONG)g_bColorAttribute; + uFill |= ((ULONG)g_bColorAttribute) << 16; + + // + // Blast uFills into video memory + // + while(uCount) + { + *p++ = uFill; + uCount--; + } + + // + // Set cursor position to 0,0 + // + g_bSoftCursor[LINES] = g_bSoftCursor[COLS] = 0; + VideoSetHardwareCursor(); +} + + +void +VideoScroll(void) +{ + ULONG *p = (ULONG *)g_pVideoMemory; + ULONG uUlongsPerLine = (g_bScreenResolution[COLS] >> 1); // 2X/4 + ULONG i, j; + ULONG uFill; + + ASSERT(sizeof(ULONG) == 4); + ASSERT(sizeof(BYTE) == 1); + + for (i = 0; + i < (g_bScreenResolution[LINES] - 2); + i++) + { + // + // Start at i, 0. Copy a ULONG up from i+1, 0. Do the whole line i. + // + for (j = 0; + j < uUlongsPerLine; + j++) + { + *p = *(p + uUlongsPerLine); + p++; + } + } + + // + // Construct a fill ULONG: blank attrib blank attrib + // + uFill = 0; + uFill |= (ULONG)g_bColorAttribute; + uFill |= ((ULONG)g_bColorAttribute) << 16; + + // + // Blank the last line + // + p = (ULONG *)(g_pVideoMemory + + ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bScreenResolution[LINES] - 1, 0)); + for (i = 0; + i < uUlongsPerLine; + i++) + { + *p = uFill; + p++; + } +} + +void +VideoPutChar(BYTE c) +{ + BYTE *p = (g_pVideoMemory + + ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bSoftCursor[LINES], + g_bSoftCursor[COLS])); + switch(c) + { + case '\n': + g_bSoftCursor[LINES]++; + if (g_bSoftCursor[LINES] >= g_bScreenResolution[LINES]) + { + VideoScroll(); + g_bSoftCursor[LINES] = g_bScreenResolution[LINES] - 1; + } + g_bSoftCursor[COLS] = 0; + return; + default: + *p = c; + p++; + *p = g_bColorAttribute; + p++; + g_bSoftCursor[COLS]++; + if (g_bSoftCursor[COLS] >= g_bScreenResolution[COLS]) + { + g_bSoftCursor[COLS] = 0; + g_bSoftCursor[LINES]++; + if (g_bSoftCursor[LINES] >= g_bScreenResolution[LINES]) + { + VideoScroll(); + g_bSoftCursor[LINES] = g_bScreenResolution[LINES] - 1; + } + } + } +} + +void +VideoPutNullTerminatedString(BYTE *s) +{ + ULONG uSafety = 0; + + while (*s != 0) + { + VideoPutChar(*s); + s++; + uSafety++; + + if (uSafety > 256) + { + VideoPutNullTerminatedString("RUNAWAYSTRING!?!\n\0"); + break; + } + } + VideoSetHardwareCursor(); +} + +void +VideoSetCursorPosition(BYTE bLine, BYTE bCol) +{ + if (bLine >= g_bScreenResolution[LINES]) + { + bLine = g_bScreenResolution[LINES] - 1; + } + if (bCol >= g_bScreenResolution[COLS]) + { + bCol = g_bScreenResolution[COLS] - 1; + } + + g_bSoftCursor[LINES] = bLine; + g_bSoftCursor[COLS] = bCol; + VideoSetHardwareCursor(); +} + +void +VideoGetCursorPosition(BYTE *pbLine, BYTE *pbCol) +{ + *pbLine = g_bSoftCursor[LINES]; + *pbCol = g_bSoftCursor[COLS]; +} + +void +VideoPrint(CHAR *szFormat, ...) +{ + CHAR *p = szFormat; + CHAR *q; + CHAR buf[32]; + va_list args; + INT iVal; + UINT uVal; + CHAR *szVal; + + va_start(args, szFormat); + while (*p != '\0') + { + switch (*p) + { + case '%': + p++; + switch (*p) + { + case '\0': + goto done; + case '%': + VideoPutChar('%'); + break; + case 'd': + iVal = va_arg(args, int); + q = RtlIntToAscii(iVal, buf, ARRAY_LENGTH(buf), 10); + ASSERT(strlen(q) < 20); + VideoPutNullTerminatedString(q); + break; + case 'u': + uVal = va_arg(args, unsigned int); + q = RtlIntToAscii(uVal, buf, ARRAY_LENGTH(buf), 10); + ASSERT(strlen(q) < 20); + VideoPutNullTerminatedString(q); + break; + case 'x': + uVal = va_arg(args, unsigned int); + q = RtlIntToAscii(uVal, buf, ARRAY_LENGTH(buf), 16); + ASSERT(strlen(q) < 20); + VideoPutNullTerminatedString(q); + break; + case 's': + szVal = va_arg(args, char *); + VideoPutNullTerminatedString(szVal); + break; + case 'c': + iVal = va_arg(args, int); + VideoPutChar(iVal & 0xFF); + break; + default: + VideoPutChar(*p); + break; + } + break; + default: + VideoPutChar(*p); + break; + } + p++; + } + done: + va_end(args); + VideoSetHardwareCursor(); +} diff --git a/kernel/hal/Makefile b/kernel/hal/Makefile new file mode 100644 index 0000000..3725f18 --- /dev/null +++ b/kernel/hal/Makefile @@ -0,0 +1,20 @@ +CC= gcc +CFLAGS= -Wall -imacros ../defines -I../inc +OBJS= video.o io.o interrupts.o intsupport.o keyboard.o timer.o \ + timestamp.o counters.o +RM= /bin/rm +NASM= nasm +NASMFLAGS= -f elf + +.SUFFIXES: .c .o .asm + +all: $(OBJS) + +.c.o: + $(CC) $(CFLAGS) -c $< + +.asm.o: + $(NASM) $(NASMFLAGS) -o $*.o $< + +clean: + $(RM) -f $(OBJS) *~ #*# .#* diff --git a/kernel/hal/counters.c b/kernel/hal/counters.c new file mode 100644 index 0000000..9bd9466 --- /dev/null +++ b/kernel/hal/counters.c @@ -0,0 +1,17 @@ +//+---------------------------------------------------------------------------- +// +// File: counters.c +// +// Module: +// +// Synopsis: +// +// Copyright (C) 2003 Scott Gasch +// +// Created: sgasch 24 Oct 2003 +// +//+---------------------------------------------------------------------------- + +#include "kernel.h" + +UINT64 g_ullTimeStampCounter = 0; diff --git a/kernel/hal/interrupts.c b/kernel/hal/interrupts.c new file mode 100644 index 0000000..94f2528 --- /dev/null +++ b/kernel/hal/interrupts.c @@ -0,0 +1,230 @@ +//+---------------------------------------------------------------------------- +// +// File: interrupts.c +// +// Module: +// +// Synopsis: +// +// Created: sgasch 6 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#include "kernel.h" +#include "hal.h" +#include "rtl.h" +#include "interrupts.h" + +IDT_ENTRY g_IDT[NUM_IDT_ENTRIES]; +INTERRUPT_HANDLER g_InterruptHandlerTable[NUM_IDT_ENTRIES]; +ULONG g_uInterruptsEnabled = 0; + +void +HalEnableInterrupts(void) +{ + g_uInterruptsEnabled++; + ASSERT(g_uInterruptsEnabled == 1); + + __asm__ __volatile__ ( + "sti" + ); +} + +void +HalDisableInterrupts(void) +{ + g_uInterruptsEnabled--; + ASSERT(g_uInterruptsEnabled == 0); + + __asm__ __volatile__ ( + "cli" + ); +} + + +//+---------------------------------------------------------------------------- +// +// Function: DoNothing +// +// Synopsis: The default interrupt handler, do nothing +// +// Arguments: INTERRUPT_STATE *p +// +// Returns: void +// +//+---------------------------------------------------------------------------- +void HalDoNothing(INTERRUPT_STATE *p) +{ + ; +} + + +//+---------------------------------------------------------------------------- +// +// Function: InterruptSendIrqEoi +// +// Synopsis: Send Interrupt ReQuest End Of Interrupt to the PIC. +// +// Arguments: INTERRUPT_STATE *is +// +// Returns: void +// +//+---------------------------------------------------------------------------- +void +HalInterruptSendIrqEoi(INTERRUPT_STATE *is) +{ + ULONG uIrq; + BYTE bCommand; + BYTE *p = (BYTE *)0x000B8000; + + *p = '3'; + *(p + 1) = ' '; + + if ((is->uIntNum >= FIRST_EXTERNAL_INT) && + (is->uIntNum <= LAST_EXTERNAL_INT)) + { + uIrq = (is->uIntNum - FIRST_EXTERNAL_INT); + ASSERT(uIrq >= 0); + ASSERT(uIrq <= 15); + bCommand = 0x60 | (uIrq & 0x7); + + if (uIrq < 8) + { + // EOI to master PIC + out(0x20, bCommand); + HalIoDelay(); + } + else + { + // EOI to slave PIC and cascade line EOI to master PIC + out(0xA0, bCommand); + out(0x20, 0x62); + HalIoDelay(); + } + } + + *p = '4'; + *(p + 1) = ' '; +} + +//+---------------------------------------------------------------------------- +// +// Function: InterruptInitializeGate +// +// Synopsis: Initializes an interrupt gate with given handler address +// and descriptor privilege level. +// +// Arguments: IDT_ENTRY *pEntry, +// void *pPreamble, +// ULONG uDpl +// +// Returns: void +// +//+---------------------------------------------------------------------------- +void +HalInterruptInitializeGate(IDT_ENTRY *pEntry, + void *pPreamble, + ULONG uDpl) +{ + ULONG u = (ULONG)pPreamble; + + pEntry->i.offsetLow = u & 0xffff; + pEntry->i.segmentSelector = (1<<3); + pEntry->i.reserved = 0; + pEntry->i.signature = 0x70; // == 01110000b + pEntry->i.dpl = uDpl; + pEntry->i.present = 1; + pEntry->i.offsetHigh = u >> 16; +} + + +//+---------------------------------------------------------------------------- +// +// Function: InterruptInstallHandler +// +// Synopsis: Installs an interrupt handler routine for a given IRQ number +// +// Arguments: ULONG uInterruptNumber, +// INTERRUPT_HANDLER pHandler +// +// Returns: void +// +//+---------------------------------------------------------------------------- +void +HalInterruptInstallHandler(ULONG uInterruptNumber, + INTERRUPT_HANDLER pHandler) +{ + ASSERT(uInterruptNumber < ARRAY_LENGTH(g_InterruptHandlerTable)); + + g_InterruptHandlerTable[uInterruptNumber] = pHandler; +} + + +//+---------------------------------------------------------------------------- +// +// Function: InterruptInitialize +// +// Synopsis: Initialize the interrupt system +// +// Arguments: void +// +// Returns: void +// +//+---------------------------------------------------------------------------- +void +HalInitializeInterrupts(void) +{ + ULONG uPreambleEntrySize = (ULONG)&HalInterruptHandlerPreambleAfter; + ULONG u; + ULONG uDpl; + USHORT uLimitAndBase[3]; + BYTE *p; + + // + // Determine the size of an interrupt preamble table entry. + // + uPreambleEntrySize -= (ULONG)&HalInterruptHandlerPreambleBefore; + + // + // Set the base interrupt number for each PIC. See comments in + // intsupport.asm. + // + HalInterruptInitializePICs(); + + // + // Build interrupt descriptor table + // + for (u = 0, p = &HalInterruptHandlerPreamble; + u < ARRAY_LENGTH(g_IDT); + u++, p += uPreambleEntrySize) + { + uDpl = (u == 0x2E) ? USER_PRIVILEGE : KERNEL_PRIVILEGE; + + HalInterruptInitializeGate(&(g_IDT[u]), p, uDpl); + HalInterruptInstallHandler(u, HalDoNothing); + } + + // + // Install the IDT + // + u = (ULONG)&(g_IDT); + uLimitAndBase[0] = 8 * NUM_IDT_ENTRIES; + uLimitAndBase[1] = (USHORT)(u & 0xffff); + uLimitAndBase[2] = (USHORT)(u >> 16); + + HalInterruptLoadIDTR((void *)uLimitAndBase); + + // + // Install interrupt handlers + // + HalInterruptInstallHandler(IRQ0, HalTimerInt); + HalInterruptInstallHandler(IRQ1, HalKeyboardInt); + + out(0x21, 0xFC); // turn on keyboard and timer + + // + // Enable interrupts + // + HalEnableInterrupts(); +} + diff --git a/kernel/hal/interrupts.h b/kernel/hal/interrupts.h new file mode 100644 index 0000000..673b13b --- /dev/null +++ b/kernel/hal/interrupts.h @@ -0,0 +1,92 @@ +//+---------------------------------------------------------------------------- +// +// File: interrupts.h +// +// Module: +// +// Synopsis: +// +// Created: sgasch 6 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#ifndef _INTERRUPTS_H_ +#define _INTERRUPTS_H_ + +#define NUM_IDT_ENTRIES (256) + +// Exceptions range from 0x00..0x11 +#define FIRST_EXCEPTION 0x00 +#define LAST_EXCEPTION 0x11 +#define NUM_EXCEPTIONS 18 + +// External IRQs range from 0x30..0x3F +#define FIRST_EXTERNAL_INT 0x30 +#define LAST_EXTERNAL_INT 0x3F +#define IRQ0 0x30 +#define IRQ1 0x31 +#define IRQ2 0x39 +#define IRQ3 0x33 +#define IRQ4 0x34 +#define IRQ5 0x35 +#define IRQ6 0x36 +#define IRQ7 0x37 +#define IRQ8 0x38 +#define IRQ9 0x39 +#define IRQ10 0x3A +#define IRQ11 0x3B +#define IRQ12 0x3C +#define IRQ13 0x3D +#define IRQ14 0x3E +#define IRQ15 0x3F +#define NUM_EXTERNAL_INTS 16 + +typedef struct _INTERRUPT_GATE +{ + USHORT offsetLow; + USHORT segmentSelector; + USHORT reserved : 5; + USHORT signature : 8; + USHORT dpl : 2; + USHORT present : 1; + USHORT offsetHigh; +} +INTERRUPT_GATE; + +typedef union _IDT_ENTRY +{ + INTERRUPT_GATE i; + // In theory we could have members for trap gates + // and task gates if we wanted. +} +IDT_ENTRY; + +// +// Defined in intsupport.asm +// +extern void HalInterruptInitializePICs(void); +extern void HalInterruptLoadIDTR(void *uLimitAndBase); +extern void HalIoDelay(void); +extern BYTE HalInterruptHandlerPreamble; +extern BYTE HalInterruptHandlerPreambleBefore; +extern BYTE HalInterruptHandlerPreambleAfter; + +// +// Defined in interrupts.c +// +extern void HalDisableInterrupts(void); +extern void HalEnableInterrupts(void); + + +// +// Defined in keyboard.c +// +extern void HalKeyboardInt(INTERRUPT_STATE *is); + +// +// Defined in timer.c +// +extern void HalTimerInt(INTERRUPT_STATE *is); + +#endif + diff --git a/kernel/hal/intsupport.asm b/kernel/hal/intsupport.asm new file mode 100644 index 0000000..3d1fcc8 --- /dev/null +++ b/kernel/hal/intsupport.asm @@ -0,0 +1,326 @@ +[BITS 32] + +FIRST_EXTERNAL_INT equ 0x30 +LAST_EXTERNAL_INT equ 0x30+15 + +GLOBAL HalInterruptLoadIDTR +GLOBAL HalInterruptGenericHandler +GLOBAL HalInterruptHandlerPreamble +GLOBAL HalInterruptHandlerPreambleBefore +GLOBAL HalInterruptHandlerPreambleAfter +GLOBAL HalInterruptInitializePICs +GLOBAL HalIoDelay + +EXTERN g_InterruptHandlerTable +EXTERN HalVideoPrint +EXTERN HalInterruptSendIrqEoi + +;; Save registers prior to calling a handler function. +;; This must be kept up to date with: +;; - Interrupt_State struct in int.h +;; - Setup_Initial_Thread_Context() in kthread.c +%macro SAVE_REGISTERS 0 + push eax + push ebx + push ecx + push edx + push esi + push edi + push ebp + push ds + push es + push fs + push gs +%endmacro + +;; Restore registers and clean up the stack after calling a handler function +;; (i.e., just before we return from the interrupt via an iret instruction). +%macro RESTORE_REGISTERS 0 + pop gs + pop fs + pop es + pop ds + pop ebp + pop edi + pop esi + pop edx + pop ecx + pop ebx + pop eax + add esp, 8 +%endmacro + +%macro INT_NO_ERROR 1 +align 8 + push 0xffffffff ; fake the error code + push %1 ; push the int number + jmp HalInterruptGenericHandler; +%endmacro + +%macro INT_WITH_ERROR 1 +align 8 + push %1 ; error code already pushed, just push int num + jmp HalInterruptGenericHandler +%endmacro + +[SECTION .text] +;;; +;;; void +;;; InterruptLoadIDTR(IDT *p) +;;; +;;; Function to load the interrupt descriptor table register (IDTR) +;;; callable from C. +;;; +HalInterruptLoadIDTR: + mov eax, [esp+4] ; p + lidt [eax] + ret + +;;; +;;; The following is code to initialize the master and slave 8259 +;;; programmable interrupt controllers (PICs). +;;; +;;; For ISA machines there are two 8259's, a master and a slave. Each has +;;; eight interrupt request (IR) pins and one interrupt (INT) pin. The +;;; master's INT pin is tied to the INT line of the microprocessor. The +;;; slave's INT pin is tied to the master's IR2 line. Thus the master's +;;; IR0, IR1, and IR3..7 are real devices. But the master's IR2 means +;;; that some IR pin on the slave is asserted. So the system IRQs are: +;;; +;;; (highest default priority) +;;; IRQ0 = master IR0 [IRQ0 = system timer] +;;; IRQ1 = master IR1 [IRQ1 = keyboard] +;;; IRQ2 = master IR2 --> IRQ8..IRQ15 = slave IR0..7 +;;; [IRQ8 = rt. timer][IRQ13 = coproc.] +;;; IRQ3 = master IR3 +;;; IRQ4 = master IR4 +;;; IRQ5 = master IR5 +;;; IRQ6 = master IR6 +;;; IRQ7 = master IR7 +;;; (lowest default priority) +;;; +;;; By default these IRQs raise the following interrupt numbers: +;;; +;;; IRQ0 = int 0x8 [collides with double exception] +;;; IRQ1 = int 0x9 [collides with coprocessor exception] +;;; IRQ2/9 = int 0x71 +;;; IRQ3 = int 0xb [collides with segment not present exception] +;;; IRQ4 = int 0xc [collides with stack fault exception] +;;; IRQ5 = int 0xd [collides with general protection exception] +;;; IRQ6 = int 0xe [collides with page fault] +;;; IRQ7 = int 0xf +;;; IRQ8 = int 0x70 +;;; IRQ10 = int 0x72 +;;; IRQ11 = int 0x73 +;;; IRQ12 = int 0x74 +;;; IRQ13 = int 0x75 +;;; IRQ14 = int 0x76 +;;; IRQ15 = int 0x77 +;;; +;;; So the problem is that IRQ0, IRQ1, IRQ3..6 all, by default, map to +;;; interrupt numbers that collide with interrupts raised by the cpu +;;; as a result of a software exception. The solution to this problem +;;; is to remap what interrupts are raised by these IRQs by reprogramming +;;; the 8259 PICs to raise new interrupt numbers. +;;; +;;; This is accomplished by sending initialization command words (ICWs) +;;; to I/O ports 0x20-0x21 (master PIC) and 0xA0-0xA1 (slave PIC). By doing +;;; so we can remap the interrupt numbers raised by IRQs so that: +;;; +;;; IRQ0 = 0x30 IRQ8 = 0x38 +;;; IRQ1 = 0x31 IRQ10 = 0x3A +;;; IRQ2/9 = 0x39 IRQ11 = 0x3B +;;; IRQ3 = 0x33 IRQ12 = 0x3C +;;; IRQ4 = 0x34 IRQ13 = 0x3D +;;; IRQ5 = 0x35 IRQ14 = 0x3E +;;; IRQ6 = 0x36 IRQ15 = 0x3F +;;; IRQ7 = 0x37 +;;; +;;; ICW1 is the same for both the master and slave PIC. Here's the meaning +;;; of the individual bits in the word: +;;; +;;; F E D C B A 9 8 | 7 6 5 4 3 2 1 0 +;;; (not used) | | | | |__ 1=expect ICW4 +;;; | | | |_____ 0=cascade 1=single +;;; | | |________ 0=interval-4, 1=8 +;;; | |___________ 0=edge triggered +;;; | 1=level triggered +;;; |______________ must be 1 +;;; +;;; +BOTH_ICW1 equ 0x11 ; expect ICW4, cascade mode, call address + ; interval=8, edge triggered mode + +;;; +;;; ICW2 tells the PICs their base interrupt number. For example, the +;;; default base interrupt for the master PIC is 0x8. Thus IRQ0=0x8, +;;; IRQ1=0x9 ... IRQ7=0xF. As stated, we want to relocate these. +;;; +MASTER_ICW2 equ 0x30 ; use ints 0x30..0x37 +SLAVE_ICW2 equ 0x38 ; use ints 0x38..0x3F + +;;; +;;; ICW3 to the master tells it which of its IR pins is connected to the +;;; slave PIC. ICW3 to the slave tells its id number. +;;; +MASTER_ICW3 equ 0x04 ; slave on IR pin 2 +SLAVE_ICW3 equ 0x02 ; slave id=2 + +;;; +;;; ICW4 to both PICs is another bitvector to set some features: +;;; +;;; +;;; F E D C B A 9 8 | 7 6 5 4 3 2 1 0 +;;; (not used) | ---- | |__ 0=MCS80/85 1=8086/88 +;;; | | |_____ 0=normal 1=auto EOI +;;; | |_________ 00=non-buf mode +;;; | 10=buf mode, slave +;;; | 11=buf mode, master +;;; |______________ 0=!nested 1=nested +;;; +BOTH_ICW4 equ 0x01 + +HalInterruptInitializePICs: + mov al, BOTH_ICW1 + out 0x20, al ; ICW1 to master PIC + call HalIoDelay + out 0xA0, al ; ICW1 to slave PIC + call HalIoDelay + + mov al, MASTER_ICW2 + out 0x21, al ; ICW2 to master PIC + call HalIoDelay + mov al, SLAVE_ICW2 + out 0xA1, al ; ICW2 to slave PIC + call HalIoDelay + + mov al, MASTER_ICW3 + out 0x21, al ; ICW3 to master PIC + call HalIoDelay + mov al, SLAVE_ICW3 + out 0xA1, al ; ICW3 to slave PIC + call HalIoDelay + + mov al, BOTH_ICW4 + out 0x21, al ; ICW4 to master PIC + call HalIoDelay + out 0xA1, al ; ICW4 to slave PIC + call HalIoDelay + +;;; +;;; After the four ICW sequence has been completed any subsequent writes +;;; to port 0x21 or 0xA1 set the IRQ mask for the master/slave PIC. If +;;; this mask is 0xFF all IRQs are disabled. If this mask is 0x00 +;;; all IRQs are enabled. +;;; + mov al, 0xff ; slave PIC cannot interrupt + out 0xA1, al + call HalIoDelay + mov al, 0xfb ; mask all IRQs but 2 (the slave PIC) in master + out 0x21, al + call HalIoDelay + ret + +;;; +;;; When doing I/O operations this routine can be used to "delay" long +;;; enough to let the external controller keep up with the cpu. +;;; +HalIoDelay: + jmp .done +.done: ret + +;;; +;;; This is the start of the main interrupt handler code. The first section +;;; of this code is called the InterruptHandlerPreamble. It consists of +;;; 256 entry points in a table (one per possible interrupt number). These +;;; preamble entry points push the interrupt number and (when needed for +;;; interrupt numbers that the processor doesn't automatically push an error +;;; code for) a fake error code. Then they jump to the main generic interrupt +;;; handling routing: InterruptGenericHandler. Thus the stack is always layed +;;; out in the same way when control passes to the generic handler: +;;; +;;; saved ss (pushed by cpu for system calls) +;;; saved esp (pushed by cpu for system calls) +;;; ------------ +;;; saved eflags (pushed by cpu) +;;; saved CS (pushed by cpu) +;;; saved IP (pushed by cpu) +;;; error code (pushed by preamble or cpu) +;;; interrupt number (pushed by preamble) +;;; esp --> return address (pushed by jmp InteruptGenericHandler) +;;; +;;; The first thing InterruptGenericHandler does is push the rest of the +;;; registers onto the stack. +;;; +align 8 +HalInterruptHandlerPreamble: +HalInterruptHandlerPreambleBefore: + INT_NO_ERROR 0 + align 8 +HalInterruptHandlerPreambleAfter: + INT_NO_ERROR 1 + INT_NO_ERROR 2 + INT_NO_ERROR 3 + INT_NO_ERROR 4 + INT_NO_ERROR 5 + INT_NO_ERROR 6 + INT_NO_ERROR 7 + INT_WITH_ERROR 8 + INT_NO_ERROR 9 + INT_WITH_ERROR 10 + INT_WITH_ERROR 11 + INT_WITH_ERROR 12 + INT_WITH_ERROR 13 + INT_WITH_ERROR 14 + INT_NO_ERROR 15 + INT_NO_ERROR 16 + INT_WITH_ERROR 17 + +;;; +;;; The rest of the interrupt numbers are INT_NO_ERRORs. Use nasm's +;;; %rep command to do them all at once. +;;; +%assign intNum 18 +%rep (256 - 18) + INT_NO_ERROR intNum +%assign intNum intNum + 1 +%endrep + +;;; +;;; This is the generic interrupt handler which is called by the preambles +;;; above. It's job is to save the registers on the stack and then transfer +;;; control to a specific per-interrupt handler. It finds the address of +;;; the per-interrupt handler to call by indexing into g_InterruptHandlerTable +;;; +align 8 +HalInterruptGenericHandler: + SAVE_REGISTERS + + ;; Ensure that we're using the kernel data segment + mov ax, (2<<3) + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ;; Get interrupt number the preamble pushed for us + mov esi, [esp+44] + + ;; Get the address of the handler function from the + ;; table of handler functions. + mov eax, g_InterruptHandlerTable + mov ebx, [eax+esi*4] + + ;; Call the handler. The argument passed is a pointer to + ;; INTERRUPT_STATE. Interrupts are enabled at this point + ;; so if the handler is non-reentrant it must disable them. + push esp + call ebx + add esp, 4 + + push esp + call HalInterruptSendIrqEoi + add esp, 4 + + RESTORE_REGISTERS + iret diff --git a/kernel/hal/io.c b/kernel/hal/io.c new file mode 100644 index 0000000..d97a211 --- /dev/null +++ b/kernel/hal/io.c @@ -0,0 +1,40 @@ +#include "kernel.h" + +// Write a byte to an I/O port. +void +out(WORD port, BYTE value ) +{ + __asm__ __volatile__ ( + "outb %b0, %w1" + : + : "a" (value), "Nd" (port) + ); +} + +// Read a byte from an I/O port. +BYTE +in(WORD port) +{ + BYTE value; + + __asm__ __volatile__ ( + "inb %w1, %b0" + : "=a" (value) + : "Nd" (port) + ); + + return value; +} + +// Short delay. May be needed when talking to some +// (slow) I/O devices. +void +iodelay(void) +{ + BYTE value = 0; + __asm__ __volatile__ ( + "outb %0, $0x80" + : + : "a" (value) + ); +} diff --git a/kernel/hal/timer.c b/kernel/hal/timer.c new file mode 100644 index 0000000..3c82691 --- /dev/null +++ b/kernel/hal/timer.c @@ -0,0 +1,43 @@ +//+---------------------------------------------------------------------------- +// +// File: timer.c +// +// Module: +// +// Synopsis: +// +// Created: sgasch 21 Oct 2003 +// +//+---------------------------------------------------------------------------- + +#include "kernel.h" +#include "hal.h" +#include "rtl.h" +#include "interrupts.h" + +void +HalTimerInt(INTERRUPT_STATE *is) +{ + static CHAR whee[] = "|/-\\\0"; + static ULONG u = 0; + static BYTE b = 0; + static unsigned int foo; + BYTE *p = (BYTE *)0x000B8000; + + out(0x61, 0x80); + u++; + + CURRENT_STAMP(&foo); + + if ((u % 500) == 0) + { + b++; + if (whee[b] == '\0') + { + b = 0; + } + *(p + 158) = whee[b]; + *(p + 159) = ' '; + } +} + diff --git a/kernel/hal/timestamp.asm b/kernel/hal/timestamp.asm new file mode 100644 index 0000000..b56bedb --- /dev/null +++ b/kernel/hal/timestamp.asm @@ -0,0 +1,19 @@ + + [BITS 32] + +GLOBAL HalReadTimestampCounter +EXTERN g_ullTimeStampCounter + +[SECTION .text] +;;; +;;; ULONGLONG +;;; HalReadTimestampCounter(void) +;;; +;;; Function to read the processor's timestamp counter +;;; +HalReadTimestampCounter: + ALIGN 4 + rdtsc + mov [g_ullTimeStampCounter], edx + mov [g_ullTimeStampCounter+4], eax + ret diff --git a/kernel/hal/video.h b/kernel/hal/video.h new file mode 100644 index 0000000..dcd7b01 --- /dev/null +++ b/kernel/hal/video.h @@ -0,0 +1,15 @@ +//+---------------------------------------------------------------------------- +// +// File: video.h +// +// Module: +// +// Synopsis: +// +// Created: sgasch 5 Jul 2003 +// +//+---------------------------------------------------------------------------- +#ifndef VIDEO_H +#define VIDEO_H + +#endif // VIDEO_H diff --git a/kernel/inc/constants.h b/kernel/inc/constants.h new file mode 100644 index 0000000..13f47bd --- /dev/null +++ b/kernel/inc/constants.h @@ -0,0 +1,50 @@ +//+---------------------------------------------------------------------------- +// +// File: constants.h +// +// Module: +// +// Synopsis: +// +// Copyright (C) 2003 +// +// Created: sgasch 10 Oct 2003 +// +//+---------------------------------------------------------------------------- + +#ifndef _CONSTANTS_H_ +#define _CONSTANTS_H_ + +// +// Constants +// +#define YES (1) +#define NO (0) +#ifndef TRUE +#define TRUE (YES) +#endif +#ifndef FALSE +#define FALSE (NO) +#endif + +#define NULL ((void *)0) + +#define ASCII_ESC (0x1B) +#define ASCII_BS (0x08) + +#define USER_PRIVILEGE (3) +#define KERNEL_PRIVILEGE (0) + +// +// Device driver constants +// +#define DEVICE_DRIVER_INITIALIZATION (1) +#define DEVICE_IO_CONTROL (2) +#define DEVICE_READ (3) +#define DEVICE_WRITE (4) +#define DEVICE_DETATCH (6) +#define DEVICE_DRIVER_SHUTDOWN (7) + +#endif /* _CONSTANTS_H_ */ + + diff --git a/kernel/inc/hal.h b/kernel/inc/hal.h new file mode 100644 index 0000000..9a52a4e --- /dev/null +++ b/kernel/inc/hal.h @@ -0,0 +1,104 @@ +//+---------------------------------------------------------------------------- +// +// File: hal.h +// +// Module: +// +// Synopsis: +// +// Created: sgasch 5 Jul 2003 +// +//+---------------------------------------------------------------------------- +#ifndef HAL_H +#define HAL_H + +// +// Video/CRT driver +// +#define BLACK (0) +#define BLUE (1) +#define GREEN (2) +#define CYAN (3) +#define RED (4) +#define MAGENTA (5) +#define YELLOW (6) +#define GRAY (7) +#define HIGH (8) +#define WHITE (HIGH | GRAY) + +void +HalVideoSetCurrentColorAttribute(BYTE bFg, BYTE bBg); + +void +HalVideoClearScreen(void); + +void +HalVideoGetCursorPosition(BYTE *pbLine, BYTE *pbCol); + +void +HalVideoSetCursorPosition(BYTE bLine, BYTE bCol); + +void +HalVideoPutNullTerminatedString(BYTE *s); + +void +HalVideoInitialize(BIOS_HARDWARE_BLOCK *phw); + +void +HalVideoPrint(CHAR *szFormat, ...); + +// +// Keyboard driver +// +#define KB_IRQ (1) +typedef WORD KEYCODE; + +typedef struct _INTERRUPT_STATE +{ + // The register contents at the time of the exception. + // We save these explicitly. + ULONG gs; + ULONG fs; + ULONG es; + ULONG ds; + ULONG ebp; + ULONG edi; + ULONG esi; + ULONG edx; + ULONG ecx; + ULONG ebx; + ULONG eax; + + // We explicitly push the interrupt number. + // This makes it easy for the handler function to determine + // which interrupt occurred. + ULONG uIntNum; + + // This may be pushed by the processor; if not, we push + // a dummy error code, so the stack layout is the same + // for every type of interrupt. + ULONG uErrorCode; + + // These are always pushed on the stack by the processor. + ULONG eip; + ULONG cs; + ULONG eflags; +} +INTERRUPT_STATE; + +typedef void (*INTERRUPT_HANDLER)(INTERRUPT_STATE *pState); + +void HalInitializeInterrupts(void); +void HalInterruptInstallHandler(ULONG uIntNum, INTERRUPT_HANDLER p); +void HalInterruptDisable(); +void HalInterruptEnable(); + +void HalIoDelay(); + +void HalTimerInt(INTERRUPT_STATE *p); +void HalKeyboardInt(INTERRUPT_STATE *p); + +extern UINT64 g_ullTimeStampCounter; +ULONG HalReadTimestampCounter(void); + +#endif // HAL_H diff --git a/kernel/inc/kernel.h b/kernel/inc/kernel.h new file mode 100644 index 0000000..7172401 --- /dev/null +++ b/kernel/inc/kernel.h @@ -0,0 +1,43 @@ +//+---------------------------------------------------------------------------- +// +// File: kernel.h +// +// Module: +// +// Synopsis: +// +// Created: sgasch 5 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#ifndef _KERNEL_H_ +#define _KERNEL_H_ + +#include "types.h" +#include "constants.h" +#include "macros.h" + +// +// Shared data structures +// +typedef struct _BIOS_HARDWARE_BLOCK +{ + BYTE bDisplayType; + BYTE bFontSize; + WORD wEquipmentBitvector; + WORD wMemorySize; + WORD wSystemClock; +} +BIOS_HARDWARE_BLOCK; + +// Write a byte to an I/O port. +void +out(WORD port, BYTE value); + +BYTE +in(WORD port); + +void +iodelay(void); + +#endif /* _KERNEL_H_ */ diff --git a/kernel/inc/macros.h b/kernel/inc/macros.h new file mode 100644 index 0000000..21340ad --- /dev/null +++ b/kernel/inc/macros.h @@ -0,0 +1,43 @@ +//+---------------------------------------------------------------------------- +// +// File: macros.h +// +// Module: +// +// Synopsis: +// +// Copyright (C) 2003 +// +// Created: sgasch 10 Oct 2003 +// +//+---------------------------------------------------------------------------- + +#ifndef _MACROS_H_ +#define _MACROS_H_ + +// +// Macros +// +#define ARRAY_LENGTH(a) (sizeof((a)) / sizeof((a)[0])) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#if 1 +void _assert(CHAR *, CHAR *, ULONG); +void VideoPrint(CHAR *, ...); +#define ASSERT(x) if (x) \ + { ; } \ + else \ + { _assert(__FUNCTION__ , \ + __FILE__ , \ + __LINE__); } +#define TRACE(f, ...) VideoPrint("%s:%u> " ##f , __FUNCTION__ , \ + __LINE__ , ##__VA_ARGS__) +#else +#define ASSERT(x) ; +#define TRACE(f, ...) ; +#endif // DEBUG + +#define CURRENT_STAMP(a) asm volatile("rdtsc" : "=a"(((unsigned int *)(a))[0]), "=d"(((unsigned int *)a)[1])) + +#endif /* _MACROS_H_ */ diff --git a/kernel/inc/rtl.h b/kernel/inc/rtl.h new file mode 100644 index 0000000..3aff129 --- /dev/null +++ b/kernel/inc/rtl.h @@ -0,0 +1,33 @@ +//+---------------------------------------------------------------------------- +// +// File: rtl.h +// +// Module: +// +// Synopsis: +// +// Copyright (C) 2003 Scott Gasch +// +// Created: sgasch 5 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#ifndef _RTL_H_ +#define _RTL_H_ + +void +RtlSetMemory(void *pStart, + BYTE bFill, + ULONG uLength); + +CHAR * +RtlIntToAscii(INT i, + CHAR *buf, + ULONG uBufLen, + ULONG uBase); + +#endif /* _RTL_H_ */ + + + + diff --git a/kernel/inc/types.h b/kernel/inc/types.h new file mode 100644 index 0000000..b3379e5 --- /dev/null +++ b/kernel/inc/types.h @@ -0,0 +1,80 @@ +//+---------------------------------------------------------------------------- +// +// File: types.h +// +// Module: +// +// Synopsis: +// +// Created: sgasch 10 Oct 2003 +// +//+---------------------------------------------------------------------------- + +#ifndef _TYPES_H_ +#define _TYPES_H_ + +// +// Datatype wrappers +// +#define MIN_CHAR (0x80) +#define MAX_CHAR (0x7f) +typedef char CHAR; + +#define MIN_BYTE (0x00) +#define MAX_BYTE (0xff) +typedef unsigned char BYTE; + +#define MIN_UCHAR (0x00) +#define MAX_UCHAR (0xff) +typedef unsigned char UCHAR; + +#define MIN_SHORT (0x8000) +#define MAX_SHORT (0x7fff) +typedef signed short SHORT; + +#define MIN_USHORT (0x0000) +#define MAX_USHORT (0xffff) +typedef unsigned short USHORT; + +#define MIN_WORD (0x0000) +#define MAX_WORD (0xffff) +typedef unsigned short WORD; + +#define MIN_INT (0x80000000) +#define MAX_INT (0x7fffffff) +typedef signed int INT; + +#define MIN_UINT (0x00000000) +#define MAX_UINT (0xffffffff) +typedef unsigned int UINT; + +#define MIN_LONG (0x80000000) +#define MAX_LONG (0x7fffffff) +typedef signed int LONG; + +#define MIN_ULONG (0x00000000) +#define MAX_ULONG (0xffffffff) +typedef unsigned long ULONG; + +#define MIN_INT64 (0x8000000000000000) +#define MAX_INT64 (0x7fffffffffffffff) +typedef signed long long INT64; + +#define MIN_UINT64 (0x0000000000000000) +#define MAX_UINT64 (0xffffffffffffffff) +typedef unsigned long long UINT64; + +#define MIN_BITV MIN_UINT +#define MAX_BITV MAX_UINT +typedef unsigned int BITV; + +#define MIN_BOOL MIN_UCHAR +#define MAX_BOOL MAX_UCHAR +typedef unsigned char BOOL; + +typedef unsigned int STATUS; +#define STATUS_SUCCESS (0) + +#define SIZE_T ULONG + +#endif /* _TYPES_H_ */ diff --git a/kernel/init/Makefile b/kernel/init/Makefile new file mode 100644 index 0000000..815dc69 --- /dev/null +++ b/kernel/init/Makefile @@ -0,0 +1,20 @@ +CC= gcc +CFLAGS= -Wall -imacros ../defines -I../inc +OBJS= main.o entry.o +RM= /bin/rm +NASM= nasm +NASMFLAGS= -f elf + +.SUFFIXES: .c .asm .o + +all: $(OBJS) + +.c.o: + $(CC) $(CFLAGS) -c $< + +.asm.o: + $(NASM) $(NASMFLAGS) -o $*.o $< + +clean: + $(RM) -f $(OBJS) *~ #*# .#* + diff --git a/kernel/init/entry.asm b/kernel/init/entry.asm new file mode 100644 index 0000000..afb0434 --- /dev/null +++ b/kernel/init/entry.asm @@ -0,0 +1,23 @@ +[BITS 32] + +EXTERN KernelEntry +GLOBAL StartOfKernelImage +GLOBAL IdleLoop + +;;; +;;; I put "entry.o" first in line at the linker so I am sure this function +;;; gets put first in the kernel image. This is good because: +;;; +;;; 1. We know there is valid code at 0x00010000 when we jump here +;;; 2. We can use the address of this function as the start of image +;;; 3. We don't have to make sure main (or KernelEntry or whatever) +;;; is always the first function in main.c +;;; +StartOfKernelImage: + jmp KernelEntry + ret + +IdleLoop: + sti + hlt + jmp IdleLoop diff --git a/kernel/init/main.c b/kernel/init/main.c new file mode 100644 index 0000000..22fd14a --- /dev/null +++ b/kernel/init/main.c @@ -0,0 +1,67 @@ +//+---------------------------------------------------------------------------- +// +// File: main.c +// +// Module: +// +// Synopsis: +// +// Created: sgasch 4 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#include "kernel.h" +#include "hal.h" +#include "rtl.h" + +extern char __bss_start; +extern char end; + +void +ZeroBSS(void) +{ + BYTE *pBssStart, *pBssEnd; + + pBssStart = &__bss_start; + pBssEnd = &end; + + // Fill .bss section with zero + RtlSetMemory((void *)pBssStart, '\0', (pBssEnd - pBssStart)); +} + +void +_assert(CHAR *szFunction, CHAR *szFile, ULONG uLine) +{ + HalVideoSetCursorPosition(0, 0); + HalVideoPrint("ASSERTION in %s at %s line %u.\n", + szFunction, szFile, uLine); + while(1) + { + ; + } +} + +// +// Entry point of the kernel. Not called main because I don't care to +// listen to gcc's warnings about argc and argv anymore. +// +int +KernelEntry(BIOS_HARDWARE_BLOCK *phw) +{ + ZeroBSS(); + + HalVideoInitialize(phw); + HalInitializeInterrupts(); + + HalVideoPrint("Interrupts initialized.\n"); + + hang: + HalReadTimestampCounter(); + HalVideoPrint("Timestamp Counter: %u%u\n", + ((g_ullTimeStampCounter >> 32) & 0xffffffff), + (g_ullTimeStampCounter & 0xffffffff)); + goto hang; + + return(-1); +} + diff --git a/kernel/kernel.bin b/kernel/kernel.bin Binary files differnew file mode 100755 index 0000000..d6b13b4 --- /dev/null +++ b/kernel/kernel.bin diff --git a/kernel/kernel.map b/kernel/kernel.map new file mode 100644 index 0000000..2d15ed2 --- /dev/null +++ b/kernel/kernel.map @@ -0,0 +1,370 @@ + +Allocating common symbols +Common symbol size file + +g_IDT 0x800 hal/interrupts.o +g_InterruptHandlerTable + 0x400 hal/interrupts.o + +Memory Configuration + +Name Origin Length Attributes +*default* 0x00000000 0xffffffff + +Linker script and memory map + +Address of section .text set to 0x10000 +LOAD init/entry.o +LOAD init/main.o +LOAD hal/video.o +LOAD hal/io.o +LOAD rtl/string.o +LOAD rtl/memory.o +LOAD hal/intsupport.o +LOAD hal/interrupts.o +LOAD hal/timer.o +LOAD hal/keyboard.o +LOAD hal/timestamp.o +LOAD hal/counters.o + 0x08048074 . = (0x8048000 + SIZEOF_HEADERS ) + +.interp + *(.interp) + +.hash + *(.hash) + +.dynsym + *(.dynsym) + +.dynstr + *(.dynstr) + +.gnu.version + *(.gnu.version) + +.gnu.version_d + *(.gnu.version_d) + +.gnu.version_r + *(.gnu.version_r) + +.rel.init + *(.rel.init) + +.rela.init + *(.rela.init) + +.rel.text 0x08048074 0x0 + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + +.rela.text + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + +.rel.fini + *(.rel.fini) + +.rela.fini + *(.rela.fini) + +.rel.rodata + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + +.rela.rodata + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + +.rel.data + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + +.rela.data + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + +.rel.ctors + *(.rel.ctors) + +.rela.ctors + *(.rela.ctors) + +.rel.dtors + *(.rel.dtors) + +.rela.dtors + *(.rela.dtors) + +.rel.got + *(.rel.got) + +.rela.got + *(.rela.got) + +.rel.bss + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + +.rela.bss + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + +.rel.plt + *(.rel.plt) + +.rela.plt + *(.rela.plt) + +.init + *(.init) + +.plt + *(.plt) + +.text 0x00010000 0x20b0 + *(.text .stub .text.* .gnu.linkonce.t.*) + .text 0x00010000 0xa init/entry.o + 0x00010000 StartOfKernelImage + 0x00010006 IdleLoop + *fill* 0x0001000a 0x2 2425393296 + .text 0x0001000c 0x104 init/main.o + 0x0001003c _assert + 0x00010078 KernelEntry + 0x0001000c ZeroBSS + .text 0x00010110 0x814 hal/video.o + 0x000105cc HalVideoGetCursorPosition + 0x00010110 HalVideoSetHardwareCursor + 0x000106b0 HalVideoPrint + 0x00010298 HalVideoClearScreen + 0x0001051c HalVideoPutNullTerminatedString + 0x00010260 HalVideoSetCurrentColorAttribute + 0x0001032c HalVideoScroll + 0x00010578 HalVideoSetCursorPosition + 0x0001044c HalVideoPutChar + 0x000105e8 HalVideoInitialize + .text 0x00010924 0x58 hal/io.o + 0x00010944 in + 0x00010924 out + 0x00010968 iodelay + .text 0x0001097c 0x220 rtl/string.o + 0x00010a10 RtlIntToAscii + 0x0001097c strncpy + 0x000109e0 strlen + .text 0x00010b9c 0x34 rtl/memory.o + 0x00010b9c RtlSetMemory + .text 0x00010bd0 0x10b6 hal/intsupport.o + 0x00011c38 HalInterruptGenericHandler + 0x00010bd8 HalInterruptInitializePICs + 0x00010bd0 HalInterruptLoadIDTR + 0x00010c38 HalInterruptHandlerPreamble + 0x00010c2f HalIoDelay + 0x00010c48 HalInterruptHandlerPreambleAfter + 0x00010c38 HalInterruptHandlerPreambleBefore + *fill* 0x00011c86 0x2 2425393296 + .text 0x00011c88 0x2f4 hal/interrupts.o + 0x00011cbc HalDisableInterrupts + 0x00011e80 HalInitializeInterrupts + 0x00011cf8 HalInterruptSendIrqEoi + 0x00011cf0 HalDoNothing + 0x00011dd8 HalInterruptInitializeGate + 0x00011c88 HalEnableInterrupts + 0x00011e38 HalInterruptInstallHandler + .text 0x00011f7c 0xbc hal/timer.o + 0x00011f7c HalTimerInt + .text 0x00012038 0x5c hal/keyboard.o + 0x00012038 HalKeyboardInt + *fill* 0x00012094 0xc 2425393296 + .text 0x000120a0 0xe hal/timestamp.o + 0x000120a0 HalReadTimestampCounter + *fill* 0x000120ae 0x2 2425393296 + *(.gnu.warning) + +.fini + *(.fini) + 0x000120b0 PROVIDE (__etext, .) + 0x000120b0 PROVIDE (_etext, .) + 0x000120b0 PROVIDE (etext, .) + +.rodata 0x000120c0 0x246 + *(.rodata .rodata.* .gnu.linkonce.r.*) + .rodata 0x000120c0 0x60 init/main.o + .rodata 0x00012120 0x156 hal/video.o + *fill* 0x00012276 0x2 + .rodata 0x00012278 0x18 rtl/string.o + .rodata 0x00012290 0x68 hal/interrupts.o + .rodata 0x000122f8 0xe hal/keyboard.o + +.rodata1 + *(.rodata1) + +.eh_frame_hdr + *(.eh_frame_hdr) + 0x00013306 . = ( ALIGN (0x1000) + (. & 0xfff)) + 0x00012308 . = ALIGN (0x4) + 0x00012306 PROVIDE (__preinit_array_start, .) + +.preinit_array + *(.preinit_array) + 0x00012306 PROVIDE (__preinit_array_end, .) + 0x00012306 PROVIDE (__init_array_start, .) + +.init_array + *(.init_array) + 0x00012306 PROVIDE (__init_array_end, .) + 0x00012306 PROVIDE (__fini_array_start, .) + +.fini_array + *(.fini_array) + 0x00012306 PROVIDE (__fini_array_end, .) + +.data 0x00013308 0xc4 + *(.data .data.* .gnu.linkonce.d.*) + .data 0x00013308 0xa8 hal/video.o + 0x0001330e g_bSoftCursor + 0x00013308 g_pVideoMemory + 0x0001330c g_bScreenResolution + 0x00013310 g_bColorAttribute + .data 0x000133b0 0x4 hal/interrupts.o + 0x000133b0 g_uInterruptsEnabled + .data 0x000133b4 0x10 hal/timer.o + .data 0x000133c4 0x8 hal/counters.o + 0x000133c4 g_ullTimeStampCounter + +.data1 + *(.data1) + +.eh_frame + *(.eh_frame) + +.gcc_except_table + *(.gcc_except_table) + +.dynamic + *(.dynamic) + +.ctors + *crtbegin.o(.ctors) + *(EXCLUDE_FILE(*crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + +.dtors + *crtbegin.o(.dtors) + *(EXCLUDE_FILE(*crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + +.jcr + *(.jcr) + +.got + *(.got.plt) + *(.got) + 0x000133cc _edata = . + 0x000133cc PROVIDE (edata, .) + 0x000133cc __bss_start = . + +.bss 0x000133e0 0xc20 + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + .bss 0x000133e0 0x4 hal/timer.o + *(COMMON) + *fill* 0x000133e4 0x1c + COMMON 0x00013400 0xc00 hal/interrupts.o + 0x0 (size before relaxing) + 0x00013400 g_IDT + 0x00013c00 g_InterruptHandlerTable + 0x00014000 . = ALIGN (0x4) + 0x00014000 . = ALIGN (0x4) + 0x00014000 _end = . + 0x00014000 PROVIDE (end, .) + +.stab + *(.stab) + +.stabstr + *(.stabstr) + +.stab.excl + *(.stab.excl) + +.stab.exclstr + *(.stab.exclstr) + +.stab.index + *(.stab.index) + +.stab.indexstr + *(.stab.indexstr) + +.comment 0x00000000 0x1c5 + *(.comment) + .comment 0x00000000 0x1f init/entry.o + .comment 0x0000001f 0x28 init/main.o + .comment 0x00000047 0x28 hal/video.o + .comment 0x0000006f 0x28 hal/io.o + .comment 0x00000097 0x28 rtl/string.o + .comment 0x000000bf 0x28 rtl/memory.o + .comment 0x000000e7 0x1f hal/intsupport.o + .comment 0x00000106 0x28 hal/interrupts.o + .comment 0x0000012e 0x28 hal/timer.o + .comment 0x00000156 0x28 hal/keyboard.o + .comment 0x0000017e 0x1f hal/timestamp.o + .comment 0x0000019d 0x28 hal/counters.o + +.debug + *(.debug) + +.line + *(.line) + +.debug_srcinfo + *(.debug_srcinfo) + +.debug_sfnames + *(.debug_sfnames) + +.debug_aranges + *(.debug_aranges) + +.debug_pubnames + *(.debug_pubnames) + +.debug_info + *(.debug_info .gnu.linkonce.wi.*) + +.debug_abbrev + *(.debug_abbrev) + +.debug_line + *(.debug_line) + +.debug_frame + *(.debug_frame) + +.debug_str + *(.debug_str) + +.debug_loc + *(.debug_loc) + +.debug_macinfo + *(.debug_macinfo) + +.debug_weaknames + *(.debug_weaknames) + +.debug_funcnames + *(.debug_funcnames) + +.debug_typenames + *(.debug_typenames) + +.debug_varnames + *(.debug_varnames) +OUTPUT(kernel.tmp elf32-i386) + +.note 0x00000000 0xb4 + .note 0x00000000 0x14 init/main.o + .note 0x00000014 0x14 hal/video.o + .note 0x00000028 0x14 hal/io.o + .note 0x0000003c 0x14 rtl/string.o + .note 0x00000050 0x14 rtl/memory.o + .note 0x00000064 0x14 hal/interrupts.o + .note 0x00000078 0x14 hal/timer.o + .note 0x0000008c 0x14 hal/keyboard.o + .note 0x000000a0 0x14 hal/counters.o diff --git a/kernel/rtl/Makefile b/kernel/rtl/Makefile new file mode 100644 index 0000000..1767c0a --- /dev/null +++ b/kernel/rtl/Makefile @@ -0,0 +1,19 @@ +CC= gcc +CFLAGS= -Wall -imacros ../defines -I../inc +OBJS= string.o memory.o +RM= /bin/rm +NASM= nasm +NASMFLAGS= + +.SUFFIXES: .c .o .asm + +all: $(OBJS) + +.c.o: + $(CC) $(CFLAGS) -c $< + +.asm.o: + $(NASM) $(NASMFLAGS) -o $*.o $< + +clean: + $(RM) -f $(OBJS) *~ #*# .#* diff --git a/kernel/rtl/memory.c b/kernel/rtl/memory.c new file mode 100644 index 0000000..f4f845e --- /dev/null +++ b/kernel/rtl/memory.c @@ -0,0 +1,29 @@ +//+---------------------------------------------------------------------------- +// +// File: memory.c +// +// Module: +// +// Synopsis: +// +// Copyright (C) Scott Gasch +// +// Created: sgasch 5 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#include "kernel.h" + +void +RtlSetMemory(void *pStart, + BYTE bFill, + ULONG uLength) +{ + BYTE *p = (BYTE *)pStart; + + while(uLength > 0) + { + *p++ = bFill; + uLength--; + } +} diff --git a/kernel/rtl/string.c b/kernel/rtl/string.c new file mode 100644 index 0000000..da42000 --- /dev/null +++ b/kernel/rtl/string.c @@ -0,0 +1,138 @@ +//+---------------------------------------------------------------------------- +// +// File: string.c +// +// Module: +// +// Synopsis: +// +// Copyright (C) 2003 Scott Gasch +// +// Created: sgasch 5 Jul 2003 +// +//+---------------------------------------------------------------------------- + +#include "kernel.h" + +CHAR * +strncpy(CHAR *pDest, CHAR *pSrc, SIZE_T u) +{ + char *p = pDest; + ULONG v = 0; + + while ((v < u) && (*pSrc)) + { + *pDest = *pSrc; + pDest++; pSrc++; v++; + } + + // + // If we ran out of space, null terminate the dest buffer + // + if ((*pSrc) && (u > 0)) + { + *(pDest - 1) = 0; + } + + return(p); +} + +SIZE_T +strlen(CHAR *p) +{ + ULONG i = 0; + while(*p) + { + i++; + p++; + } + return(i); +} + +CHAR * +RtlIntToAscii(INT i, + CHAR *buf, + ULONG uBufLen, + ULONG uBase) +{ + CHAR *p = (buf + uBufLen); + ULONG uSpaceLeft = uBufLen; + ULONG uMagnitude; + BOOL fNeg = FALSE; + + // + // null terminate the workspace buffer + // + if (uSpaceLeft == 0) + { + return(NULL); + } + *p = '\0'; + p--; + uSpaceLeft--; + + // + // Get the int's sign + // + if (i < 0) + { + fNeg = TRUE; + uMagnitude = -i; + } + else + { + uMagnitude = i; + } + + // + // Based on base, do the conversion. Build the string backwards from + // less significant digits. Stop if we finish or if we run out of + // uSpaceLeft. + // + switch(uBase) + { + case 10: + do + { + *p = (uMagnitude % 10) + '0'; + p--; + uSpaceLeft--; + uMagnitude /= 10; + } + while((uSpaceLeft > 0) && (uMagnitude != 0)); + break; + case 16: + do + { + *p = "0123456789ABCDEF"[uMagnitude & 15]; + p--; + uSpaceLeft--; + uMagnitude >>= 4; + } + while((uSpaceLeft > 0) && (uMagnitude != 0)); + break; + case 8: + do + { + *p = (uMagnitude & 7) + '0'; + p--; + uSpaceLeft--; + uMagnitude >>= 3; + } + while((uSpaceLeft > 0) && (uMagnitude != 0)); + break; + } + + if (TRUE == fNeg) + { + if (uSpaceLeft > 0) + { + *p = '-'; + } + } + else + { + p++; + } + return(p); +} |
