15 Commits
Author SHA1 Message Date
josh 311b8afc83 Import backup from 2004-01-26 2017-07-25 22:23:46 -04:00
josh 21e3943b5e Import backup from 2004-01-20 2017-07-25 22:23:46 -04:00
josh 10fd7102ca Import backup from 2004-01-18 2017-07-25 22:23:46 -04:00
josh 7de4f94423 Import backup from 2004-01-15 2017-07-25 22:23:46 -04:00
josh 0a546f1467 Import backup from 2004-01-07 2017-07-25 22:23:45 -04:00
josh af6087ecec Import backup from 2004-01-04 2017-07-25 22:23:45 -04:00
josh c613002307 Import backup from 2003-12-31 2017-07-25 22:23:45 -04:00
josh 76398df125 Import backup from 2003-12-30 2017-07-25 22:23:45 -04:00
josh e83408ce83 Import backup from 2003-12-29 2017-07-25 22:23:45 -04:00
josh 715bb9341a Import backup from 2003-12-28 2017-07-25 22:23:45 -04:00
josh e82bf2ecdf Import backup from 2003-12-25 2017-07-25 22:23:45 -04:00
josh 528527a7ed Import backup from 2003-12-23_2 2017-07-25 22:23:45 -04:00
josh 71aaa7a598 Import backup from 2003-12-23 2017-07-25 22:23:45 -04:00
josh 9070a76b18 Import backup from 2003-12-22_2 2017-07-25 22:23:45 -04:00
josh 5048a93ff7 Import backup from 2003-12-22 2017-07-25 22:23:45 -04:00
41 changed files with 1942 additions and 1109 deletions

No files matched your search

+137 -7
View File
@@ -38,6 +38,69 @@ inline void disable_ints()
asm("cli"); asm("cli");
}; };
char *strcat(char *dest, char *src)
{
strcpy(dest+strlen(dest), src);
}
//converts a binary-coded-decimal byte to its decimal equivalent
inline byte bcd2byte(byte bcd)
{
return (10* ((bcd & 0xF0) >> 4)) + (bcd & 0x0F);
}
//converts a binary-coded-decimal byte to its decimal equivalent
inline byte byte2bcd(byte bite)
{
return ((bite / 10) << 4) | (bite % 10);
}
void rtrim(char *str)
{
str += strlen(str); //now points to the null character at the end of the string
str--;
for (;;)
{
if ((*str == ' ') || (*str == '\t') || (*str == '\n'))
*str-- = 0;
else
break;
}
}
char *ucase(char *str)
{
char *ret = str;
for (;;)
{
if (*str == 0)
break;
if ((*str >= 'a') && (*str <= 'z'))
*str = (*str) - 32;
str++;
}
return ret;
}
char *lcase(char *str)
{
char *ret = str;
for (;;)
{
if (*str == 0)
break;
if ((*str >= 'A') && (*str <= 'Z'))
*str = (*str) + 32;
str++;
}
return ret;
}
//Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address //Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address
void remap_pics(int pic1, int pic2) void remap_pics(int pic1, int pic2)
{ {
@@ -74,6 +137,7 @@ inline void pic2_mask(byte mask)
//Restarts the computer //Restarts the computer
inline void restart() inline void restart()
{ {
enable_ints();
byte temp; byte temp;
do do
{ {
@@ -107,13 +171,6 @@ inline void init_timer()
outportb(0x40, 0x2e); //msb outportb(0x40, 0x2e); //msb
} }
//Invalidates the page tables to re-cache the Translation Lookaside Buffer
/*inline void invlpg()
{
asm("invlpg");
}*/
//Signals an End Of Interrupt signal to the first PIC //Signals an End Of Interrupt signal to the first PIC
inline void eoi() inline void eoi()
{ {
@@ -137,6 +194,79 @@ inline dword kernel_size()
} }
//These functions are for reading and writing various values stored on the CMOS Real Time Clock
byte rtc_readDay()
{
outportb(0x70, 7);
return bcd2byte(inportb(0x71));
}
byte rtc_readMonth()
{
outportb(0x70, 8);
return bcd2byte(inportb(0x71));
}
byte rtc_readYear()
{
outportb(0x70, 9);
return bcd2byte(inportb(0x71));
}
byte rtc_readSecond()
{
outportb(0x70, 0);
return bcd2byte(inportb(0x71));
}
byte rtc_readMinute()
{
outportb(0x70, 2);
return bcd2byte(inportb(0x71));
}
byte rtc_readHour()
{
outportb(0x70, 4);
return bcd2byte(inportb(0x71));
}
void rtc_setDay(byte day)
{
outportb(0x70, 7);
outportb(0x71, byte2bcd(day));
}
void rtc_setMonth(byte month)
{
outportb(0x70, 8);
outportb(0x71, byte2bcd(month));
}
void rtc_setYear(byte year)
{
outportb(0x70, 9);
outportb(0x71, byte2bcd(year));
}
void rtc_setSecond(byte second)
{
outportb(0x70, 0);
outportb(0x71, byte2bcd(second));
}
void rtc_setMinute(byte minute)
{
outportb(0x70, 2);
outportb(0x71, byte2bcd(minute));
}
void rtc_setHour(byte hour)
{
outportb(0x70, 4);
outportb(0x71, byte2bcd(hour));
}
+426 -1
View File
@@ -1,7 +1,20 @@
; asmfuncs.asm ; asmfuncs.asm
; Josh Holtrop ; Josh Holtrop
; 10/23/03 ; Created: 10/23/03
; Modified: 12/25/03
[extern _putc]
[extern _console_memory]
[extern _cursorPosition]
[extern _video_drawConsole]
[extern _videoMode]
%macro jzfar 1
jnz %%skip
jmp %1
%%skip:
%endmacro
;stores the parameter to the CR0 register ;stores the parameter to the CR0 register
;extern dword write_cr0(dword cr0); ;extern dword write_cr0(dword cr0);
@@ -32,6 +45,16 @@ _write_cr3:
pop ebp pop ebp
ret ret
;returns the value in the CR2 register
;extern dword read_cr2();
[global _read_cr2]
_read_cr2:
mov eax, cr2;
ret
;returns the value in the CR3 register ;returns the value in the CR3 register
;extern dword read_cr3(); ;extern dword read_cr3();
[global _read_cr3] [global _read_cr3]
@@ -40,6 +63,408 @@ _read_cr3:
ret ret
;compares one string to another
;returns 0 if the strings are different
;extern dword strcmp(char *str1, char *str2);
[global _strcmp]
_strcmp:
push ebp
mov ebp, esp
push esi
push edi
mov esi, [ebp+8]
mov edi, [ebp+12]
strcmp_loop1:
lodsb
mov ah, [edi]
inc edi
cmp ah, al
jnz strcmp_ne
or al, al
jz strcmp_e
jmp strcmp_loop1
strcmp_e:
mov eax, 1
jmp short strcmp_done
strcmp_ne:
xor eax, eax
strcmp_done:
pop edi
pop esi
pop ebp
ret
;copies a string from the source to the destination parameter
;extern void strcpy(char *dest, char *src);
[global _strcpy]
_strcpy:
push ebp
mov ebp, esp
push esi
push edi
mov edi, [ebp+8]
mov esi, [ebp+12]
strcpyloop:
lodsb
stosb
or al, al
jnz strcpyloop
pop edi
pop esi
pop ebp
ret
;copies memory of n bytes from src to destination
;extern void memcpy(dword dest, dword src, dword n);
[global _memcpy]
_memcpy:
push ebp
mov ebp, esp
push esi
push edi
push ecx
mov edi, [ebp+8]
mov esi, [ebp+12]
mov ecx, [ebp+16]
rep movsb
pop ecx
pop edi
pop esi
pop ebp
ret
;returns the number of characters in a string
;extern dword strlen(char *str);
[global _strlen]
_strlen:
push ebp
mov ebp, esp
push esi
push ebx
mov esi, [ebp+8]
xor ebx, ebx
strlenloop:
lodsb
or al, al
jz strlendone
inc ebx
jmp strlenloop
strlendone:
mov eax, ebx
pop ebx
pop esi
pop ebp
ret
;this function invalidates the page directory/table entry that
; would be used to access the memory address given in the parameter
;extern void invlpg(dword addr);
[global _invlpg]
_invlpg:
mov eax, [esp+4]
invlpg [eax]
ret
;
;void writeCursorPosition(word pos)
;
[global _writeCursorPosition]
_writeCursorPosition:
push ebp
mov ebp, esp
push eax
push ebx
push edx
mov eax, [ebp+8] ;cursor position in ax
mov bl, al
mov dx, 0x03D4
mov al, 0x0E
out dx, al
inc dx
mov al, ah
out dx, al
dec dx
mov al, 0x0F
out dx, al
inc dx
mov al, bl
out dx, al
pop edx
pop ebx
pop eax
pop ebp
ret
;
;word getCursorPosition()
;
[global _getCursorPosition]
_getCursorPosition:
push ebx
push edx
xor eax, eax
mov dx, 0x03D4
mov al, 0x0E
out dx, al
inc dx
in al, dx
mov bl, al
dec dx
mov al, 0x0F
out dx, al
inc dx
in al, dx
mov ah, bl
pop edx
pop ebx
ret
;
;void console_scroll()
;
[global _console_scroll]
_console_scroll:
pusha
mov esi, _console_memory+160
mov edi, _console_memory
mov ecx, 960 ;(2000-80)/2
rep movsd
mov ax, 0x0720
mov ecx, 80
rep stosw
mov esi, _console_memory
mov edi, 0xC00B8000
mov ecx, 1000
rep movsd
mov eax, [_videoMode]
cmp eax, 0
jz _console_scroll_end
call _video_drawConsole
_console_scroll_end:
popa
ret
;
;void console_cls()
;
[global _console_cls]
_console_cls:
pusha
mov edi, _console_memory
mov ax, 0x0720
mov ecx, 2000
rep stosw
push dword 0
call _writeCursorPosition
add esp, 4
mov [_cursorPosition], dword 0
mov esi, _console_memory
mov edi, 0xC00B8000
mov ecx, 1000
rep movsd
popa
ret
;
;int puts(char *str)
;
[global _puts]
_puts:
push ebp
mov ebp, esp
push esi
push eax
mov esi, [ebp+8] ;esi = to string
puts_loop:
lodsb
cmp al, 0
jz puts_done
push eax
call _putc
add esp, 4
jmp puts_loop
puts_done:
pop eax
pop esi
pop ebp
ret
[global _putDecu]
_putDecu:
push ebp
mov ebp, esp
sub esp, 24
mov DWORD [ebp-4], 1
mov BYTE [ebp-5], 0
L2:
mov edx, DWORD [ebp+8]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
cmp eax, DWORD [ebp-4]
jae L4
jmp L3
L4:
mov eax, DWORD [ebp-4]
mov edx, eax
sal edx, 2
add edx, eax
lea eax, [edx+edx]
mov DWORD [ebp-4], eax
jmp L2
L3:
nop
L5:
cmp DWORD [ebp-4], 1
ja L7
jmp L6
L7:
mov edx, DWORD [ebp+8]
mov eax, edx
mov edx, 0
div DWORD [ebp-4]
mov DWORD [ebp-12], eax
mov al, BYTE [ebp-12]
mov BYTE [ebp-5], al
mov eax, 0
mov al, BYTE [ebp-5]
imul eax, DWORD [ebp-4]
sub DWORD [ebp+8], eax
mov edx, DWORD [ebp-4]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
mov DWORD [ebp-4], eax
lea eax, [ebp-5]
add BYTE [eax], 48
sub esp, 12
mov eax, 0
mov al, BYTE [ebp-5]
push eax
call _putc
add esp, 16
jmp L5
L6:
sub esp, 12
mov al, BYTE [ebp+8]
add eax, 48
and eax, 255
push eax
call _putc
add esp, 16
leave
ret
[global _putDec]
_putDec:
push ebp
mov ebp, esp
sub esp, 24
cmp DWORD [ebp+8], 0
jns L9
sub esp, 12
push 45
call _putc
add esp, 16
neg DWORD [ebp+8]
L9:
mov DWORD [ebp-4], 1
mov BYTE [ebp-5], 0
L10:
mov eax, DWORD [ebp+8]
cmp eax, DWORD [ebp-4]
jae L12
jmp L11
L12:
mov eax, DWORD [ebp-4]
mov edx, eax
sal edx, 2
add edx, eax
lea eax, [edx+edx]
mov DWORD [ebp-4], eax
jmp L10
L11:
mov edx, DWORD [ebp-4]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
mov DWORD [ebp-4], eax
L13:
cmp DWORD [ebp-4], 1
ja L15
jmp L14
L15:
mov edx, DWORD [ebp+8]
mov eax, edx
mov edx, 0
div DWORD [ebp-4]
mov DWORD [ebp-12], eax
mov al, BYTE [ebp-12]
mov BYTE [ebp-5], al
mov eax, 0
mov al, BYTE [ebp-5]
imul eax, DWORD [ebp-4]
sub DWORD [ebp+8], eax
mov edx, DWORD [ebp-4]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
mov DWORD [ebp-4], eax
lea eax, [ebp-5]
add BYTE [eax], 48
sub esp, 12
mov eax, 0
mov al, BYTE [ebp-5]
push eax
call _putc
add esp, 16
jmp L13
L14:
sub esp, 12
mov al, BYTE [ebp+8]
add eax, 48
and eax, 255
push eax
call _putc
add esp, 16
leave
ret
-7
View File
@@ -2,7 +2,6 @@
echo Backing up to .\Backup\%1 echo Backing up to .\Backup\%1
mkdir .\Backup\%1 mkdir .\Backup\%1
mkdir .\Backup\%1\lib
copy *.h .\Backup\%1 copy *.h .\Backup\%1
copy *.c .\Backup\%1 copy *.c .\Backup\%1
@@ -11,9 +10,3 @@ copy *.asm .\Backup\%1
copy *.ld .\Backup\%1 copy *.ld .\Backup\%1
copy *.bat .\Backup\%1 copy *.bat .\Backup\%1
copy .\lib\*.h .\Backup\%1\lib
copy .\lib\*.c .\Backup\%1\lib
copy .\lib\*.inc .\Backup\%1\lib
copy .\lib\*.asm .\Backup\%1\lib
copy .\lib\*.ld .\Backup\%1\lib
copy .\lib\*.bat .\Backup\%1\lib
+2 -2
View File
@@ -1,12 +1,12 @@
%define VERSION "0.12" ;HOS version %define VERSION "0.13" ;HOS version
%define BOOT_FAT_SEG 0x07E0 ;right after boot sector %define BOOT_FAT_SEG 0x07E0 ;right after boot sector
%define BOOT_ROOT_SEG 0x0900 ;right after FAT %define BOOT_ROOT_SEG 0x0900 ;right after FAT
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR %define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG %define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
%define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at %define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at
%define BOOT_KERNEL_ADD 0x104000 ;final pmode kernel destination - physical %define BOOT_KERNEL_ADD 0x106000 ;final pmode kernel destination - physical
%define BOOT_RD_ADD 0x200000 ;2mb for ram disk %define BOOT_RD_ADD 0x200000 ;2mb for ram disk
%define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here %define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
+345
View File
@@ -0,0 +1,345 @@
// fat12.c
// Author: Josh Holtrop
// Created: 01/04/04
// Modified: 01/14/04
byte *fat12_readFile(char *fileName, DiskDevice *dd)
{
char *fileNameUCase = malloc(strlen(fileName) + 1);
strcpy(fileNameUCase, fileName);
ucase(fileNameUCase);
dword iMadeClusterChain = getClusterChain(dd);
Fat12Entry fe;
if (fat12_getFileHandle(fileNameUCase, dd, &fe))
{
free(fileNameUCase);
if (iMadeClusterChain)
{
free(clusterChain);
clusterChain = 0;
}
return 0;
}
byte *fp = (byte *)fat12_readClusterChain(dd, &fe);
free(fileNameUCase);
if (iMadeClusterChain)
{
free(clusterChain);
clusterChain = 0;
}
return fp;
}
dword fat12_getFileHandle(char *fileName, DiskDevice *dd, Fat12Entry *destination)
{
if (strlen(fileName) < 1)
return 1;
if (fileName[strlen(fileName)-1] == '/')
return 2;
dword iMadeClusterChain = getClusterChain(dd);
int fileName_length = strlen(fileName);
int a;
int entries = 1;
for (a = 0; a < fileName_length; a++)
{
if (fileName[a] == '/')
{
fileName[a] = 0;
entries++;
}
}
char *pointer = fileName;
Fat12Entry *workingDirectory = 0;
Fat12Entry workingDir;
for (a = 0; a < (entries - 1); a++)
{
if (fat12_getDirectoryHandle(pointer, dd, workingDirectory, &workingDir)) //an error occurred if this returns nonzero
{
if (iMadeClusterChain)
{
free(clusterChain);
clusterChain = 0;
}
return 3;
}
workingDirectory = &workingDir;
for (;;) //advance to the next dir name
{
pointer++;
if (*pointer == 0)
{
pointer++;
break;
}
}
}
if (fat12_getFileHandleInDirectory(pointer, dd, workingDirectory, destination)) //an error occurred if this returns nonzero
{
if (iMadeClusterChain)
{
free(clusterChain);
clusterChain = 0;
}
return 4;
}
if (iMadeClusterChain)
{
free(clusterChain);
clusterChain = 0;
}
return 0;
}
dword fat12_getFileHandleInDirectory(char *fileName, DiskDevice *dd, Fat12Entry *currDir, Fat12Entry *destination)
{
if (!currDir) // we are working in the root directory
{
Fat12Entry *rootDir = malloc(14*512); //root directory is 14 sectors long
vfs_readSector(dd, 19, (byte *)rootDir, 14);
int a;
for (a = 0; a < 224; a++) //224 max root directory entries in 14 sectors
{
if (rootDir[a].fileName[0] == 0)
break;
if ((byte)rootDir[a].fileName[0] != 0xE5)
{
if ((rootDir[a].attributes & 0x18) == 0) //this entry is a directory
{
char dirName[9];
char dirExt[4];
memcpy(dirName, rootDir[a].fileName, 8);
dirName[8] = 0;
memcpy(dirExt, rootDir[a].ext, 3);
dirExt[3] = 0;
rtrim(dirName);
rtrim(dirExt);
char dirWhole[14];
strcpy(dirWhole, dirName);
if (strlen(dirExt) > 0) //the directory has an extension
{
strcat(dirWhole, ".");
strcat(dirWhole, dirExt);
}
if (strcmp(dirWhole, fileName)) //the entry found is a match
{
free(rootDir);
*destination = rootDir[a];
return 0;
}
}
}
}
free(rootDir);
return 1; //no match found
}
dword retVal = 2;
dword iMadeClusterChain = getClusterChain(dd);
Fat12Entry *subDirectory = fat12_readClusterChain(dd, currDir);
if (!subDirectory)
return 5;
dword numberOfClusters = fat12_readClusterChainCount(dd, currDir);
int a;
for (a = 0; a < (numberOfClusters * 16); a++)
{
if (subDirectory[a].fileName[0] == 0)
break;
if ((byte)subDirectory[a].fileName[0] != 0xE5)
{
if ((subDirectory[a].attributes & 0x18) == 0) //this entry is a directory
{
char dirName[9];
char dirExt[4];
memcpy(dirName, subDirectory[a].fileName, 8);
dirName[8] = 0;
memcpy(dirExt, subDirectory[a].ext, 3);
dirExt[3] = 0;
rtrim(dirName);
rtrim(dirExt);
char dirWhole[14];
strcpy(dirWhole, dirName);
if (strlen(dirExt) > 0) //the directory has an extension
{
strcat(dirWhole, ".");
strcat(dirWhole, dirExt);
}
if (strcmp(dirWhole, fileName)) //the entry found is a match
{
*destination = subDirectory[a];
retVal = 0;
break;
}
}
}
}
free(subDirectory);
if (iMadeClusterChain)
{
free(clusterChain);
clusterChain = 0;
}
return retVal;
}
dword fat12_getDirectoryHandle(char *directory, DiskDevice *dd, Fat12Entry *currDir, Fat12Entry *destination)
{
if (!currDir) // we are working in the root directory
{
Fat12Entry *rootDir = malloc(14*512); //root directory is 14 sectors long
vfs_readSector(dd, 19, (byte *)rootDir, 14);
int a;
for (a = 0; a < 224; a++) //224 max root directory entries in 14 sectors
{
if (rootDir[a].fileName[0] == 0)
break;
if ((byte)rootDir[a].fileName[0] != 0xE5)
{
if ((rootDir[a].attributes & 0x18) == 0x10) //this entry is a directory
{
char dirName[9];
char dirExt[4];
memcpy(dirName, rootDir[a].fileName, 8);
dirName[8] = 0;
memcpy(dirExt, rootDir[a].ext, 3);
dirExt[3] = 0;
rtrim(dirName);
rtrim(dirExt);
char dirWhole[14];
strcpy(dirWhole, dirName);
if (strlen(dirExt) > 0) //the directory has an extension
{
strcat(dirWhole, ".");
strcat(dirWhole, dirExt);
}
if (strcmp(dirWhole, directory)) //the entry found is a match
{
free(rootDir);
*destination = rootDir[a];
return 0;
}
}
}
}
free(rootDir);
return 1; //no match found
}
dword retVal = 2;
dword iMadeClusterChain = getClusterChain(dd);
Fat12Entry *subDirectory = fat12_readClusterChain(dd, currDir);
if (!subDirectory)
return 5;
dword numberOfClusters = fat12_readClusterChainCount(dd, currDir);
int a;
for (a = 0; a < (numberOfClusters * 16); a++)
{
if (subDirectory[a].fileName[0] == 0)
break;
if ((byte)subDirectory[a].fileName[0] != 0xE5)
{
if ((subDirectory[a].attributes & 0x18) == 0x10) //this entry is a directory
{
char dirName[9];
char dirExt[4];
memcpy(dirName, subDirectory[a].fileName, 8);
dirName[8] = 0;
memcpy(dirExt, subDirectory[a].ext, 3);
dirExt[3] = 0;
rtrim(dirName);
rtrim(dirExt);
char dirWhole[14];
strcpy(dirWhole, dirName);
if (strlen(dirExt) > 0) //the directory has an extension
{
strcat(dirWhole, ".");
strcat(dirWhole, dirExt);
}
if (strcmp(dirWhole, directory)) //the entry found is a match
{
*destination = subDirectory[a];
retVal = 0;
break;
}
}
}
}
free(subDirectory);
if (iMadeClusterChain)
{
free(clusterChain);
clusterChain = 0;
}
return retVal;
}
Fat12Entry *fat12_readClusterChain(DiskDevice *dd, Fat12Entry *directory)
{
dword numberOfClusters = fat12_readClusterChainCount(dd, directory);
if (numberOfClusters == 0)
return 0;
byte *bp = malloc(numberOfClusters * 512);
Fat12Entry *retVal = (Fat12Entry *)bp;
dword cluster = directory->firstCluster;
while (cluster < 0xFF0)
{
vfs_readSector(dd, cluster + 31, bp, 1);
cluster = fat12_getNextCluster(cluster);
bp += 512;
}
return retVal;
}
dword fat12_readClusterChainCount(DiskDevice *dd, Fat12Entry *directory)
{
dword numberOfClusters = 0;
dword cluster = directory->firstCluster;
if (cluster == 0)
return 0;
while (cluster < 0xFF0)
{
cluster = fat12_getNextCluster(cluster);
numberOfClusters++;
}
return numberOfClusters;
}
dword fat12_getNextCluster(dword thisCluster)
{
dword nextCluster = *(word *)((dword)clusterChain + ((thisCluster * 3) >> 1));
if (thisCluster & 0x01) //this is an odd cluster
return nextCluster >> 4;
else //this is an even cluster
return nextCluster & 0x0FFF;
}
dword fat12_getFileSize(char *fileName, DiskDevice *dd)
{
Fat12Entry fe;
if (fat12_getFileHandle(fileName, dd, &fe))
return 0xFFFFFFFF;
return fe.fileSize;
}
dword getClusterChain(DiskDevice *dd)
{
if (!clusterChain)
{
clusterChain = malloc(9*512); //9 sectors for File Allocation Table (cluster chain)
vfs_readSector(dd, 1, clusterChain, 9); //sectors 1 through 9 contain the first FAT
return 1; //this call created the cluster chain
}
else
return 0; //this call did not create the cluster chain
}
+58
View File
@@ -0,0 +1,58 @@
// fat12.h
// Author: Josh Holtrop
// Created: 01/04/04
typedef struct {
char fileName[8];
char ext[3];
byte attributes;
dword createTime;
word createDate;
word accessDate;
word unused0;
word modifiedDate;
word modifiedTime;
word firstCluster;
dword fileSize;
} __attribute__((packed)) Fat12Entry;
typedef struct {
byte jump[3];
byte sysName[8];
word bytesPerSector;
byte sectorsPerCluster;
word reservedSectors;
byte FATcount;
word maxRootEntries;
word totalSectors1;
byte mediaDescriptor;
word sectorsPerFAT;
word sectorsPerTrack;
word headCount;
dword hiddenSectors;
dword totalSectors2;
byte driveNumber;
byte reserved1;
byte extBootSignature;
dword volumeSerial;
char volumeLabel[11];
char fileSystemID[8];
} __attribute__((packed)) Fat12BootSector;
byte *fat12_readFile(char *fileName, DiskDevice *dd);
dword fat12_getFileHandle(char *fileName, DiskDevice *dd, Fat12Entry *destination);
dword fat12_getDirectoryHandle(char *directory, DiskDevice *dd, Fat12Entry *currDir, Fat12Entry *destination);
Fat12Entry *fat12_readClusterChain(DiskDevice *dd, Fat12Entry *directory);
dword fat12_getFileHandleInDirectory(char *fileName, DiskDevice *dd, Fat12Entry *currDir, Fat12Entry *destination);
dword fat12_readClusterChainCount(DiskDevice *dd, Fat12Entry *directory);
dword fat12_getFileSize(char *fileName, DiskDevice *dd);
dword getClusterChain(DiskDevice *dd);
dword fat12_getNextCluster(dword thisCluster);
byte *clusterChain = 0;
+18 -4
View File
@@ -21,10 +21,24 @@ inline void eoi();
inline void eoi2(); inline void eoi2();
inline dword kernel_size(); inline dword kernel_size();
inline void init_timer(); inline void init_timer();
//inline void invlpg(); char *strcat(char *dest, char *src);
void rtrim(char *str);
char *ucase(char *str);
char *lcase(char *str);
inline byte bcd2byte(byte bcd);
inline byte byte2bcd(byte bite);
byte rtc_readDay();
byte rtc_readMonth();
byte rtc_readYear();
byte rtc_readSecond();
byte rtc_readMinute();
byte rtc_readHour();
void rtc_setDay(byte dat);
void rtc_setMonth(byte month);
void rtc_setYear(byte year);
void rtc_setSecond(byte second);
void rtc_setMinute(byte minute);
void rtc_setHour(byte hour);
Executable
+1
View File
@@ -0,0 +1 @@
gcc -S kernel.c -masm=intel -fno-builtin
+1 -1
View File
@@ -5,7 +5,7 @@
gdtr: gdtr:
dw gdt_end-gdt-1 dw gdt_end-gdt-1
dd GDT dd GDT_P
gdt: gdt:
dd 0 dd 0
dd 0 dd 0
+22 -1
View File
@@ -5,11 +5,12 @@
idtr: idtr:
dw 50*8-1 ;size of idt dw 50*8-1 ;size of idt
dd IDT ;address of idt dd IDT_V ;address of idt
%macro isr_label 1 %macro isr_label 1
isr_%1: isr_%1:
push eax
mov eax, %1 mov eax, %1
jmp isr_main jmp isr_main
%endmacro %endmacro
@@ -66,6 +67,9 @@ isr_label 48
isr_label 49 isr_label 49
isr_main: isr_main:
cmp eax, 0x30
jz isr_syscall
pusha pusha
push ds push ds
push es push es
@@ -79,10 +83,27 @@ isr_main:
pop es pop es
pop ds pop ds
popa popa
pop eax
iret iret
isr_syscall:
pop eax ;syscall function number
pusha
push ds
push es
push ebx
call _putc
add esp, 4
pop es
pop ds
popa
iret
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -29,7 +29,7 @@
#define YELLOW_TXT 0x0E #define YELLOW_TXT 0x0E
#define BRWHITE_TXT 0x0F #define BRWHITE_TXT 0x0F
#define FREERAM_START 0x268000 #define FREERAM_START 0x368000 // 0x368000 is first available byte (this is right after the initrd @ 2mb, 1440kb.
#define MAX_RAM 0x40000000 //1gb maximum RAM supported #define MAX_RAM 0x40000000 //1gb maximum RAM supported
#define PID_KERNEL 0x02 //kernel's PID #define PID_KERNEL 0x02 //kernel's PID
+42 -8
View File
@@ -2,21 +2,55 @@
;Author: Josh Holtrop ;Author: Josh Holtrop
;Modified: 10/30/03 ;Modified: 10/30/03
%include "bootdef.inc" %define GDT_P 0x100000; ;1mb physical - Global Descriptor Table space
%define GDT_V GDT_P+0xC0000000
%define GDT 0x100000 %define IDT_P 0x102000 ;1mb+8kb - Interrupt Descriptor Table space
%define IDT 0x102000 %define IDT_V IDT_P+0xC0000000
%define PDBR_P 0x104000 ;1mb+16kb - Page Directory Base Register (first PD)
%define PDBR_V PDBR_P+0xC0000000
%define LOPT_P 0x105000 ;1mb+20kb - LOw Page Table for mapping first 4mb
%define LOPT_V LOPT_P+0xC0000000
%define KERNEL_P 0x106000 ;1mb+24kb - the kernel's physical address
%define KERNEL_V KERNEL_P+0xC0000000 ;3gb+1mb+24kb, the virtual address of the kernel
[global start] [global start]
[extern _isr] [extern _isr]
[extern _k_init] [extern _k_init]
[extern _putc]
bits 32 bits 32
;This is where the kernel begins execution ;This is where the kernel begins execution
;At this point, the temporary gdt is set up to "map" 0xC000_0000 to 0x0.
;We must enable paging with the first 4mb mapped 1:1 virtual:physical
; and with the 4mb starting at 0xC000_0000 mapped to the first 4mb physical.
;Then we can start using our "real" gdt, then unmap the lower 4mb.
start: start:
cli ;if they weren't already off cli ;if they weren't already off
mov edi, GDT
xor eax, eax
mov edi, PDBR_V
mov ecx, 1024 ;clear the PDBR
rep stosd
mov [PDBR_V], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
mov [PDBR_V+0xC00], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
mov edi, LOPT_V
mov ecx, 1024
mov eax, 0x03 ;starting physical address = 0x0 (read/write, present flags)
fill_lopt_loop: ;fill the page table
stosd
add eax, 4096 ;increment next phsyical address by 4kb
loop fill_lopt_loop
mov eax, PDBR_P
mov cr3, eax ;store the Page Directory Base Address
mov eax, cr0
or eax, 0x80000000 ;set page enable bit
mov cr0, eax ;now paging is active!
mov edi, GDT_V
mov esi, gdt mov esi, gdt
mov ecx, gdt_end-gdt mov ecx, gdt_end-gdt
copy_gdt: copy_gdt:
@@ -24,7 +58,7 @@ copy_gdt:
stosb stosb
loop copy_gdt loop copy_gdt
mov edi, IDT ;destination mov edi, IDT_V ;destination
mov esi, isr_0 ;address of isr0 mov esi, isr_0 ;address of isr0
mov edx, isr_1-isr_0 ;distance between isr labels mov edx, isr_1-isr_0 ;distance between isr labels
mov ecx, 50 ;number of isrlabels mov ecx, 50 ;number of isrlabels
@@ -42,7 +76,7 @@ fill_idt:
mov esi, ebx mov esi, ebx
add esi, edx add esi, edx
loop fill_idt loop fill_idt
mov word [IDT+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges mov word [IDT_V+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
lgdt [gdtr] ;load gdt lgdt [gdtr] ;load gdt
jmp KERNEL_CODE:newgdtcontinue jmp KERNEL_CODE:newgdtcontinue
@@ -53,7 +87,7 @@ newgdtcontinue:
mov gs, ax mov gs, ax
mov fs, ax mov fs, ax
mov ss, ax mov ss, ax
mov esp, 0x1ffffc ;stack just under 2mb, moves downward mov esp, 0xc01ffffc ;stack just under 3gb+2mb, moves downward
lidt [idtr] ;load idt lidt [idtr] ;load idt
call _k_init call _k_init
+58 -28
View File
@@ -2,12 +2,10 @@
//08/13/03 Josh Holtrop //08/13/03 Josh Holtrop
//Holtrop's Operating System //Holtrop's Operating System
//Version: 0.12 //Version: 0.12
//Modified: 11/12/03 //Modified: 12/30/03
#include "k_defines.h" //#DEFINE's for kernel #include "k_defines.h" //#DEFINE's for kernel
#include "lib/string.h" //library string functions
#include "lib/io.h" //library input/output functions
#include "functions.h" //general functions #include "functions.h" //general functions
#include "video.h" //video functions #include "video.h" //video functions
@@ -17,14 +15,35 @@
#include "mouse.h" //generic ps/2 mouse driver & functions #include "mouse.h" //generic ps/2 mouse driver & functions
#include "fdc.h" //Floppy Disk Controller functions #include "fdc.h" //Floppy Disk Controller functions
#include "stdfont.h" //Standard font bitmask array #include "stdfont.h" //Standard font bitmask array
#include "kio.h"
#include "vfs.h"
#include "rd.h"
#include "fat12.h"
void isr(dword num); void isr(dword num);
void k_init(); void k_init();
/* These functions are defined in asmfuncs.asm */
extern dword write_cr0(dword cr0); extern dword write_cr0(dword cr0);
extern dword read_cr0(); extern dword read_cr0();
extern dword write_cr3(dword cr3); extern dword write_cr3(dword cr3);
extern dword read_cr2();
extern dword read_cr3(); extern dword read_cr3();
extern void writeCursorPosition(dword pos);
extern dword getCursorPosition();
extern void console_scroll();
extern void console_cls();
extern int puts(char *str);
extern int putDec(int number);
extern int putDecu(dword number);
extern void strcpy(char *dest, char *src);
extern void memcpy(void *dest, void *src, dword n);
extern dword strlen(char *str);
#include "fat12.c"
#include "rd.c"
#include "vfs.c"
#include "kio.c"
#include "fdc.c" #include "fdc.c"
#include "mouse.c" #include "mouse.c"
#include "keyboard.c" #include "keyboard.c"
@@ -34,7 +53,6 @@ extern dword read_cr3();
#include "video.c" #include "video.c"
dword timer = 0; dword timer = 0;
dword *videoMode;
//Main kernel initialization method //Main kernel initialization method
void k_init() void k_init()
@@ -42,39 +60,46 @@ void k_init()
// ===== Initialization // ===== Initialization
fdc_sendDOR(0x0C); //turn off floppy motor!! fdc_sendDOR(0x0C); //turn off floppy motor!!
console_cls(); console_cls();
video_init();
mm_init();
vmm_init();
remap_pics(0x20, 0x28); remap_pics(0x20, 0x28);
init_timer(); init_timer();
mm_init();
videoMode = (dword *)0x90002;
if (*videoMode)
video_init((ModeInfoBlock *) 0x90306);
vmm_init();
mouse_init(); mouse_init();
vmm_enable_paging();
pic1_mask(0); //unmask IRQ's 0-7 pic1_mask(0); //unmask IRQ's 0-7
pic2_mask(0); //unmask IRQ's 8-15 pic2_mask(0); //unmask IRQ's 8-15
vfs_init();
enable_ints(); enable_ints();
kbd_resetLEDs(); //after enabling interrupts!! kbd_resetLEDs(); //after enabling interrupts!!
if (videoMode)
char *bmpptr = (char *)0x108000+54;
int a = 0;
int x = 0;
int y = 479;
for (a=0; a < 640*480; a++)
{ {
video_pset(x, y, *(dword *)bmpptr); int p = video_mode.XResolution*video_mode.YResolution-1;
bmpptr += 3; for (; p >= 0; p--)
x++; video_psetp(p, 0x00000044);
if (x == 640) video_drawConsole();
{
x = 0;
y--;
}
} }
printf("HOS 0.12 - Kernel Size: %d kb\n", kernel_size()/1024); printf("HOS 0.13 - Kernel File Size: %u kb\tData Size: %u bytes\n", kernel_size()>>10, (dword)(&_end)-(dword)(&_code));
printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem); printf("Memory available to OS: %u MB (%u bytes)\n", mm_megabytes, mm_totalmem);
printf("Free memory: %d bytes\n", mm_freemem()); printf("Free memory: %u bytes (%u pages)\n", mm_freemem(), mm_freemem()>>12);
printf("%d/%d/%d\t%d:%d:%d\n", rtc_readMonth(), rtc_readDay(), rtc_readYear(), rtc_readHour(), rtc_readMinute(), rtc_readSecond());
printf("Root Directory: %s/\n", rootDevice->id);
/* int a;
byte *addr = 0;
for (a = 0; a < 5; a++)
{
byte *app = mm_palloc();
vmm_map1((dword)addr, (dword)app);
addr += 4096;
}
addr = vfs_readFile("/bin/hash.hos");
memcpy(0, addr, 4192);
asm("call 0");
free(addr);
*/
dword key = 0; dword key = 0;
for (;;) for (;;)
@@ -90,9 +115,13 @@ void isr(dword num)
{ {
switch(num) switch(num)
{ {
case 14:
printf("Page fault, CR2 = 0x%x\n", read_cr2());
halt();
break;
case 0x20: // IRQ0 - timer interrupt case 0x20: // IRQ0 - timer interrupt
timer++; timer++;
(*(byte *)(0xb8000))++; (*(byte *)(0xc00b8000))++;
eoi(); eoi();
break; break;
case 0x21: // IRQ1 - keyboard interrupt case 0x21: // IRQ1 - keyboard interrupt
@@ -104,6 +133,7 @@ void isr(dword num)
break; break;
default: default:
printf("Interrupt %d (0x%x) Unhandled!!\n", num, num); printf("Interrupt %d (0x%x) Unhandled!!\n", num, num);
halt();
break; break;
} }
} }
+133
View File
@@ -0,0 +1,133 @@
//kio.c
// Author: Josh Holtrop
// Created: 12/25/03
// Modified: 12/25/03
// This is the main output routine, it uses a format string and a variable
// number of arguments to print formatted text
void printf(char *fmt, ...)
{
dword *params = ((dword *)(&fmt)) + 1; //points to the first paramater
int i;
int special = 0;
for (i = 0; ; i++)
{
if (special)
{
special = 0;
switch (fmt[i])
{
case 0:
return;
case '%':
putc('%');
break;
case 's': case 'S':
puts((char *)*params);
params++;
break;
case 'c': case 'C':
putc(*params);
params++;
break;
case 'd': case 'D':
putDec(*params);
params++;
break;
case 'u': case 'U':
putDecu(*params);
params++;
break;
case 'x': case 'X':
putHex(*params);
params++;
break;
}
}
else
{
switch (fmt[i])
{
case '%':
special = 1;
break;
case 0:
return;
default:
putc(fmt[i]);
}
}
}
}
// This function draws a single character
void putc(dword chr)
{
char charac = (char)chr;
word *vidmem = (word *)0xC00B8000;
if (charac == '\n')
{
if (cursorPosition % 80)
cursorPosition = cursorPosition + 80 - (cursorPosition % 80);
else
cursorPosition += 80;
}
else if (charac == '\t')
{
if (cursorPosition % 8)
cursorPosition = cursorPosition + 8 - (cursorPosition % 8);
else
cursorPosition += 8;
}
else
{
if (videoMode)
{
console_memory[cursorPosition] = charac | 0x0700;
video_drawConsoleChar(cursorPosition);
}
else
{
console_memory[cursorPosition] = charac | 0x0700;
vidmem[cursorPosition] = charac | 0x0700;
}
cursorPosition++;
}
if (cursorPosition >= 2000)
{
console_scroll();
cursorPosition = 2000-80;
if (videoMode)
video_drawConsole();
}
if (!videoMode)
writeCursorPosition(cursorPosition);
}
// This function displays a number in hexadecimal
int putHex(dword number)
{
int hitNum = 0;
int i;
for (i = 7; i >= 0; i--)
{
dword val = (number >> (i*4)) & 0xF;
if ((val != 0) || (i == 0))
hitNum = 1;
if (hitNum)
{
val = val + '0';
if (val > '9')
val = val + ('A' - '9' - 1);
putc(val);
}
}
}
+15
View File
@@ -0,0 +1,15 @@
//kio.h
// Author: Josh Holtrop
// Created: 12/25/03
// Modified: 12/25/03
void printf(char *fmt, ...);
void putc(dword chr);
int putHex(dword number);
dword cursorPosition = 0; //Caches the current cursor position
-2
View File
@@ -1,2 +0,0 @@
del hlibc.a
ar -r hlibc.a *.o
-1
View File
@@ -1 +0,0 @@
gcc -ffreestanding -fno-builtin -c *.c
-2
View File
@@ -1,2 +0,0 @@
nasmw -f aout -l io.lst io.asm -o io_a.o
nasmw -f aout -l misc.lst misc.asm -o misc.o
-7
View File
@@ -1,7 +0,0 @@
typedef unsigned int dword;
typedef unsigned short word;
typedef unsigned char byte;
-532
View File
@@ -1,532 +0,0 @@
%macro jzfar 1
jnz %%skip
jmp %1
%%skip:
%endmacro
[global _writeCursorPosition]
[global _getCursorPosition]
[global _putc]
[global _puts]
[global _printf]
[global _console_scroll]
[global _console_cls]
[global _putHex]
[global _putDec]
[global _putDecu]
;
;void writeCursorPosition(word pos)
;
_writeCursorPosition:
push ebp
mov ebp, esp
push eax
push ebx
push edx
mov eax, [ebp+8] ;cursor position in ax
mov bl, al
mov dx, 0x03D4
mov al, 0x0E
out dx, al
inc dx
mov al, ah
out dx, al
dec dx
mov al, 0x0F
out dx, al
inc dx
mov al, bl
out dx, al
pop edx
pop ebx
pop eax
pop ebp
ret
;
;word getCursorPosition()
;
_getCursorPosition:
push ebx
push edx
xor eax, eax
mov dx, 0x03D4
mov al, 0x0E
out dx, al
inc dx
in al, dx
mov bl, al
dec dx
mov al, 0x0F
out dx, al
inc dx
in al, dx
mov ah, bl
pop edx
pop ebx
ret
;
;int putc(int chr)
;
_putc:
push ebp
mov ebp, esp
push ebx
push ecx
push edx
call _getCursorPosition
mov ebx, eax
mov ecx, ebx
mov eax, [ebp+8] ;al=character
cmp al, 10 ;newline
jz putc_newline
cmp al, 9 ;tab
jz putc_tab
shl ebx, 1
add ebx, 0xb8000
mov ah, 0x07
mov [ebx], ax
mov eax, ecx
inc eax
cmp eax, 2000
jnz putc_writeit2
call _console_scroll
mov eax, 2000-80
putc_writeit2:
push eax
call _writeCursorPosition
add esp, 4
jmp putc_done
putc_newline:
mov eax, ebx ;eax = cursor position
mov ebx, 80
xor edx, edx
div bx ;ax=dx:ax/bx, dx=remainder
mov bx, 80
sub bx, dx
mov eax, ecx
add eax, ebx ;eax = new cursor position
cmp eax, 2000
jnz putc_newline_writeit2
call _console_scroll
mov eax, 2000-80 ;beginning of last row
putc_newline_writeit2:
push eax
call _writeCursorPosition
add esp, 4
jmp putc_done
putc_tab:
mov eax, ebx ;eax = cursor position
mov ebx, 8
div bl ;al=ax/bl, ah=remainder
xor edx, edx
mov dl, ah
mov bx, 8
sub bx, dx
mov eax, ecx
add eax, ebx ;eax = new cursor position
cmp eax, 2000
jnz putc_tab_writeit2
call _console_scroll
mov eax, 2000-80 ;beginning of last row
putc_tab_writeit2:
push eax
call _writeCursorPosition
add esp, 4
putc_done:
pop edx
pop ecx
pop ebx
pop ebp
ret
;
;void printf(char *fmt, ... )
;
_printf:
push ebp
mov ebp, esp
pusha
mov ebx, [ebp+8] ;ebx = position in format string
mov esi, ebp
add esi, 12 ;esi = to next variable arg
xor ecx, ecx ;ecx used if we encounter a '%'
printf_loop:
mov al, [ebx]
inc ebx
cmp al, 0
jzfar printf_done
cmp ecx, 1
jz printf_special
cmp al, '%'
jzfar printf_percent
push eax
call _putc
add esp, 4
jmp printf_loop
printf_special:
xor ecx, ecx
cmp al, 'd'
jz printf_decimal
cmp al, 'u'
jz printf_decimalu
cmp al, 'x'
jz printf_hex
cmp al, '%'
jz printf_ppercent
cmp al, 's'
jz printf_string
cmp al, 'c'
jz printf_char
jmp printf_special_done
printf_decimal:
mov eax, [esi]
push eax
call _putDec
add esp, 4
jmp printf_special_done
printf_decimalu:
mov eax, [esi]
push eax
call _putDecu
add esp, 4
jmp printf_special_done
printf_hex:
mov eax, [esi]
push eax
call _putHex
add esp, 4
jmp printf_special_done
printf_ppercent:
push eax
call _putc
add esp, 4
jmp printf_special_done
printf_string:
mov eax, [esi]
push eax
call _puts
add esp, 4
jmp printf_special_done
printf_char:
mov eax, [esi]
push eax
call _putc
add esp, 4
jmp printf_special_done
printf_special_done
add esi, 4 ;point to next extra argument
jmp printf_loop
printf_percent:
mov ecx, 1
jmp printf_loop
printf_done:
popa
pop ebp
ret
;
;void console_scroll()
;
_console_scroll:
pusha
mov esi, 0xb8000+160
mov edi, 0xb8000
mov ecx, 960 ;(2000-80)/2
console_scroll_loop:
lodsd
stosd
loop console_scroll_loop
mov ax, 0x0720
mov ecx, 80
console_scroll_loop2:
stosw
loop console_scroll_loop2
popa
ret
;
;void console_cls()
;
_console_cls:
pusha
mov edi, 0xb8000
mov ax, 0x0720
mov ecx, 2000
console_cls_loop:
stosw
loop console_cls_loop
push dword 0
call _writeCursorPosition
add esp, 4
popa
ret
;
;int putHex(dword number)
;
_putHex:
push ebp
mov ebp, esp
pusha
mov eax, [ebp+8] ;eax = number to print
xor ebx, ebx ;we have not printed a character yet
mov ecx, 8 ;counter for number of characters
putHex_loop:
push eax
push ecx
dec ecx
shl ecx, 2 ;edx=counter*4 (amount to shift by)
shr eax, cl
and eax, 0x0F
cmp cl, 0
jz putHex_notzero ;if number is 0
cmp al, 0
jnz putHex_notzero
cmp bl, 0
jz putHex_loop_end
putHex_notzero:
mov bl, 1
add eax, '0'
cmp eax, '9'
jbe putHex_dontadjust
add eax, 'A'-'9'-1
putHex_dontadjust:
push eax
call _putc
add esp, 4
putHex_loop_end:
pop ecx
pop eax
loop putHex_loop
popa
pop ebp
ret
;
;int puts(char *str)
;
_puts:
push ebp
mov ebp, esp
push esi
push eax
mov esi, [ebp+8] ;esi = to string
puts_loop:
lodsb
cmp al, 0
jz puts_done
push eax
call _putc
add esp, 4
jmp puts_loop
puts_done:
pop eax
pop esi
pop ebp
ret
_putDecu:
push ebp
mov ebp, esp
sub esp, 24
mov DWORD [ebp-4], 1
mov BYTE [ebp-5], 0
L2:
mov edx, DWORD [ebp+8]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
cmp eax, DWORD [ebp-4]
jae L4
jmp L3
L4:
mov eax, DWORD [ebp-4]
mov edx, eax
sal edx, 2
add edx, eax
lea eax, [edx+edx]
mov DWORD [ebp-4], eax
jmp L2
L3:
nop
L5:
cmp DWORD [ebp-4], 1
ja L7
jmp L6
L7:
mov edx, DWORD [ebp+8]
mov eax, edx
mov edx, 0
div DWORD [ebp-4]
mov DWORD [ebp-12], eax
mov al, BYTE [ebp-12]
mov BYTE [ebp-5], al
mov eax, 0
mov al, BYTE [ebp-5]
imul eax, DWORD [ebp-4]
sub DWORD [ebp+8], eax
mov edx, DWORD [ebp-4]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
mov DWORD [ebp-4], eax
lea eax, [ebp-5]
add BYTE [eax], 48
sub esp, 12
mov eax, 0
mov al, BYTE [ebp-5]
push eax
call _putc
add esp, 16
jmp L5
L6:
sub esp, 12
mov al, BYTE [ebp+8]
add eax, 48
and eax, 255
push eax
call _putc
add esp, 16
leave
ret
_putDec:
push ebp
mov ebp, esp
sub esp, 24
cmp DWORD [ebp+8], 0
jns L9
sub esp, 12
push 45
call _putc
add esp, 16
neg DWORD [ebp+8]
L9:
mov DWORD [ebp-4], 1
mov BYTE [ebp-5], 0
L10:
mov eax, DWORD [ebp+8]
cmp eax, DWORD [ebp-4]
jae L12
jmp L11
L12:
mov eax, DWORD [ebp-4]
mov edx, eax
sal edx, 2
add edx, eax
lea eax, [edx+edx]
mov DWORD [ebp-4], eax
jmp L10
L11:
mov edx, DWORD [ebp-4]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
mov DWORD [ebp-4], eax
L13:
cmp DWORD [ebp-4], 1
ja L15
jmp L14
L15:
mov edx, DWORD [ebp+8]
mov eax, edx
mov edx, 0
div DWORD [ebp-4]
mov DWORD [ebp-12], eax
mov al, BYTE [ebp-12]
mov BYTE [ebp-5], al
mov eax, 0
mov al, BYTE [ebp-5]
imul eax, DWORD [ebp-4]
sub DWORD [ebp+8], eax
mov edx, DWORD [ebp-4]
mov eax, -858993459
mul edx
mov eax, edx
shr eax, 3
mov DWORD [ebp-4], eax
lea eax, [ebp-5]
add BYTE [eax], 48
sub esp, 12
mov eax, 0
mov al, BYTE [ebp-5]
push eax
call _putc
add esp, 16
jmp L13
L14:
sub esp, 12
mov al, BYTE [ebp+8]
add eax, 48
and eax, 255
push eax
call _putc
add esp, 16
leave
ret
-18
View File
@@ -1,18 +0,0 @@
#ifndef __HIO_H__
#define __HIO_H__ __HIO_H__
void writeCursorPosition(dword pos);
dword getCursorPosition();
int putc(dword chr);
int printf(char *fmt, ...);
int puts(char *str);
int putDec(int number);
int putDecu(dword number);
int putHex(dword number);
void console_cls();
void console_scroll();
#endif
-25
View File
@@ -1,25 +0,0 @@
;void memcpy(dword src, dword dest, dword length)
[global _memcpy]
_memcpy:
push ebp
mov ebp, esp
push esi
push edi
push ecx
mov esi, [ebp+8]
mov edi, [ebp+12]
mov ecx, [ebp+14]
rep movsb
pop ecx
pop edi
pop esi
pop ebp
ret
-8
View File
@@ -1,8 +0,0 @@
#ifndef __HMISC_H__
#define __HMISC_H__ __HMISC_H__
void memcpy(dword src, dword dest, dword length);
#endif
-13
View File
@@ -1,13 +0,0 @@
#include "string.h"
int strlen(char *str)
{
int retn = 0;
while (*str++ != 0)
retn++;
return retn;
}
-8
View File
@@ -1,8 +0,0 @@
#ifndef __HSTRING_H__
#define __HSTRING_H__ __HSTRING_H__
int strlen(char *str);
#endif
+1 -1
View File
@@ -1 +1 @@
ld -nodefaultlibs -nostdlib -T link.ld -o kernel.bin -Map .\lst\LDout.doc ks.o kernel.o asmfuncs.o .\lib\hlibc.a ld -nodefaultlibs -nostdlib -T link.ld -o kernel.bin -Map .\lst\LDout.doc ks.o kernel.o asmfuncs.o
+1 -1
View File
@@ -2,7 +2,7 @@ OUTPUT_FORMAT("binary")
ENTRY(start) ENTRY(start)
SECTIONS SECTIONS
{ {
.text 0x104000 : { .text 0xC0106000 : {
code = .; _code = .; __code = .; code = .; _code = .; __code = .;
*(.text) *(.text)
. = ALIGN(4096); . = ALIGN(4096);
+67 -228
View File
@@ -1,273 +1,112 @@
// mm.c // mm.c
// 09/01/03 Josh Holtrop // Author: Josh Holtrop
// Created: 09/01/03
// Modified: 12/28/03
// 0x368000 is first available byte (this is right after the kernel @ 1mb and the initrd @ 2mb, 1440kb.
//Pointer to the first pageblock in the linked list
pageblock *first_pageblock = (pageblock *) 0;
//The total amount of physical memory available (bytes) //The total amount of physical memory available (bytes)
dword mm_totalmem = 0x100000; //start counting from 1mb #define BITMAP_SIZE 0x20000
//The highest physical address dword mm_totalmem = 0;
dword mm_highestAddress = 0; dword mm_megabytes;
byte page_bitmap[BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available
//0x20000*(8 bits/byte)=0x100000 pages in 4gb total
//This function initializes the memory manager's linked list, filling it with the //This function initializes the memory manager's linked list, filling it with the
// memory areas returned by bios interrupt 0x8E20 // memory areas returned by bios interrupt 0x8E20
void mm_init() void mm_init()
{ {
dword *memmap_entries = (dword *) 0x9040A; dword memmap_entries = *(dword *)0xC009040A;
memmap_entry *maps = (memmap_entry *) 0x92000; memmap_entry *maps = (memmap_entry *) 0xC0092000;
dword a; dword a;
for (a=0;a<(*memmap_entries);a++) for (a = 0; a < BITMAP_SIZE; a++)
{
page_bitmap[a] = 0xFF; //all pages used
}
for (a = 0; a < memmap_entries; a++)
{ {
if (maps[a].attributes == 1) // (1) mem free to OS if (maps[a].attributes == 1) // (1) mem free to OS
{ {
mm_totalmem += maps[a].limit.lowdword; mm_totalmem += maps[a].limit.lowdword;
if (mm_highestAddress < (maps[a].base.lowdword + maps[a].limit.lowdword)) if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram
mm_highestAddress = maps[a].base.lowdword + maps[a].limit.lowdword;
if ((maps[a].base.lowdword + maps[a].limit.lowdword) > (FREERAM_START+8192)) //goes past where we start freeram
{ {
if (maps[a].base.lowdword < FREERAM_START) if (maps[a].base.lowdword < FREERAM_START)
{ {
maps[a].limit.lowdword = maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword); mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
maps[a].base.lowdword = FREERAM_START; //block at least 4kb, starts >= FREERAM_START
} }
if (first_pageblock == 0) //no pageblock page set up yet, so set it up here
{
first_pageblock = (pageblock *) maps[a].base.lowdword;
maps[a].base.lowdword += 4096;
maps[a].limit.lowdword -= 4096;
mm_init_pageblockpage(first_pageblock);
first_pageblock->base = maps[a].base.lowdword;
first_pageblock->length = maps[a].limit.lowdword / 4096;
first_pageblock->pid = MM_PB_AVAIL;
}
else //first_pageblock already set up, add on segment
{
pageblock *pb = first_pageblock;
for (;;)
{
if (pb->pid == MM_PB_NP)
break;
else else
pb++;
}
pb->base = maps[a].base.lowdword;
pb->length = maps[a].limit.lowdword / 4096;
pb->pid = MM_PB_AVAIL;
}
}
}
}
if (first_pageblock == 0)
{ {
printf("ERROR! NO INITIAL PAGE BLOCK CREATED."); mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
asm("cli");
asm("hlt");
for (;;)
;
} }
} }
}
}
if (mm_totalmem % 0x100000)
//This function initializes a pageblock to be full of empty pointers mm_megabytes = (mm_totalmem >> 20) + 1;
void mm_init_pageblockpage(pageblock *pbp)
{
int a;
for (a=0; a<256; a++) // 256 pageblock entries * 16 bytes per page block entry = 4096 bytes (1 page of pageblock entries)
{
pbp[a].base = 0;
pbp[a].length = 0;
pbp[a].pid = MM_PB_NP;
if (a<255)
pbp[a].link = (dword)(&pbp[a+1]);
else else
pbp[a].link = 0; mm_megabytes = mm_totalmem >> 20;
}
// This function frees a certain number of pages starting at the address
// specified in base for a length of pages pages
void mm_pfreen(dword base, dword pages)
{
dword a;
dword max = base + (pages << 12);
for (a = base; a < max; a += 4096)
{
mm_pfree(a);
} }
} }
//This function allocates a certain number of physical pages for a particular process // This function frees a single page
//Returns: void mm_pfree(dword base)
// 0 - no free mem, invalied PID
// void* - physical address of allocated pages
void *mm_palloc(dword numpages, dword proc_pid)
{ {
if (proc_pid < PID_KERNEL) // dword pageNumber = base >> 12; // >>12 == /4096
return 0; dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
pageblock *pb = first_pageblock; dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
if (mm_freeentries() < 2) page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
{
if(mm_new_pageblock_page() == 0)
return 0;
}
pageblock *newentry = mm_nextpageblockentry();
for (;;)
{
if ((pb->pid == MM_PB_AVAIL) && (pb->length >= numpages))
break;
if (pb->link == 0)
return 0;
pb = (pageblock *)pb->link;
}
if (pb->length == numpages) //dont need a new entry, just mark this one as used :)
{
pb->pid = proc_pid;
return (void *)pb->base;
}
else //subtract out allocated number of pages from length
{
newentry->base = pb->base;
newentry->length = numpages;
newentry->pid = proc_pid;
pb->base += (numpages * 4096);
pb->length -= numpages;
return (void *)newentry->base;
}
} }
//This method returns the number of free pageblock entries at the end of the linked list // This function allocates a single page, returning its physical address
dword mm_freeentries() void *mm_palloc()
{ {
pageblock *pb = first_pageblock; dword bite;
dword counter = 0; for (bite = 0; bite < BITMAP_SIZE; bite++)
for (;;)
{ {
if (pb->pid == MM_PB_NP) if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
counter++; {
if (pb->link == 0) int bit;
return counter; for (bit = 0; bit < 8; bit++)
pb = (pageblock *) pb->link; {
if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
{
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
return (void *)((bite << 15) | (bit << 12));
} }
} }
}
}
return 0; //no free page
}
//This method creates a new page used to hold more pageblock entries at the end of the linked list // This function reports the number of bytes of free physical memory
//Returns:
// 0 - no free pages
// pageblock* - address of pageblock page
pageblock *mm_new_pageblock_page() //as of 09/26/03 this method leaks 4kb main memory per call, unrecoverable
{
pageblock *pb = first_pageblock;
for (;;)
{
if ((pb->pid == MM_PB_AVAIL) && (pb->length > 1))
{
pageblock *retval = (pageblock *)pb->base;
pb->base += 4096;
pb->length--;
mm_init_pageblockpage(retval); //zeros out, links new pageblock page
mm_lastpageblockentry()->link = (dword)retval; //set up link to new pageblock page
return retval;
}
pb = (pageblock *) pb->link;
if (pb == 0)
return 0;
}
}
//This method frees a physical page
//Returns:
// 2 - pointer to free was a null pointer
// 1 - address not found
// 0 - all went well
int mm_pfree(void *ptr)
{
if (ptr == 0)
return 2;
pageblock *pb = first_pageblock;
dword tofree = (dword) ptr;
for (;;)
{
if (pb->base == tofree) // && (pb->pid == MM_PB_USED))
{
pb->pid = MM_PB_AVAIL; //found block, mark available / coalesce it
mm_coalesce(pb);
return 0;
}
if (pb->link == 0)
return 1;
pb = (pageblock *) pb->link;
}
}
//This method returns a pointer to the last pageblock in the linked list
pageblock *mm_lastpageblockentry()
{
pageblock *pb = first_pageblock;
for (;;)
{
if (pb->link == 0)
return pb;
pb = (pageblock *)pb->link;
}
}
//This method returns the next available-for-use pageblock entry
// or 0, if they are all used
pageblock *mm_nextpageblockentry()
{
pageblock *pb = first_pageblock;
for (;;)
{
if (pb->pid == MM_PB_NP)
return pb;
if (pb->link == 0)
return 0;
pb = (pageblock *)pb->link;
}
}
//This method returns the amount of free physical RAM
dword mm_freemem() dword mm_freemem()
{ {
dword amount = 0; dword a;
pageblock *pb = first_pageblock; dword pages = 0;
for (;;) for (a = 0; a < BITMAP_SIZE; a++)
{ {
if (pb->pid == MM_PB_AVAIL) int bit;
amount += (pb->length)*4096; for (bit = 0; bit < 8; bit++)
if (pb->link == 0)
return amount;
pb = (pageblock *) pb->link;
}
}
//This method "walks" through the linked list of pageblock entries and
// combines any two entries that are adjacent and of the same type
void mm_coalesce(pageblock *pb)
{ {
pageblock *pbc = first_pageblock; if (!(page_bitmap[a] & (1 << bit)))
for (;;) pages++;
{
if (pbc->pid == pb->pid) //pid fields must match, both same process, both avail, or both not present
{
if ((pbc->base + (pbc->length * 4096)) == pb->base) //pbc ends where pb starts
{
pbc->length += pb->length;
pb->pid = MM_PB_NP;
mm_coalesce(pbc); //recursion: checks for any more page blocks to coalesce if one found
return; //exit this recursion...
}
if ((pb->base + (pb->length * 4096)) == pbc->base) //pb ends where pbc starts
{
pb->length += pbc->length;
pbc->pid = MM_PB_NP;
mm_coalesce(pb);
return;
} }
} }
if (pbc->link == 0) return pages << 12;
return;
pbc = (pageblock *)pbc->link;
}
} }
+5 -19
View File
@@ -7,28 +7,14 @@ typedef struct {
} __attribute__((packed)) memmap_entry; } __attribute__((packed)) memmap_entry;
typedef struct {
dword base;
dword length; //in pages
dword pid; //normally PID of process, use NP, AVAIL for special flags
dword link; //leave dword instead of pointer so i dont have to worry about pointer arithmetic
} __attribute__ ((packed)) pageblock; //16 byte pageblock entry - 256 entries = 1 page
void mm_init(); void mm_init();
void mm_init_pageblockpage(pageblock *pbp); void mm_pfreen(dword base, dword pages);
void *mm_palloc(dword numpages, dword proc_pid); void mm_pfree(dword base);
void mm_coalesce(pageblock *pb); void *mm_palloc();
int mm_pfree(void *ptr);
dword mm_freeentries();
dword mm_freemem(); dword mm_freemem();
pageblock *mm_new_pageblock_page();
pageblock *mm_lastpageblockentry();
pageblock *mm_nextpageblockentry();
#define MM_PB_NP 0x00 //00000000
#define MM_PB_AVAIL 0x01 //00000001
-8
View File
@@ -28,8 +28,6 @@ void mouse_init()
void isr_mouse() void isr_mouse()
{ {
byte inb = inportb(0x60); //read mouse byte byte inb = inportb(0x60); //read mouse byte
//printf("InB: %x\n", inb);
//return;
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
return; return;
mouse_inbuffer[mouse_bytesRead] = inb; mouse_inbuffer[mouse_bytesRead] = inb;
@@ -50,15 +48,9 @@ void isr_mouse()
if (mouse_y >= video_mode.YResolution) if (mouse_y >= video_mode.YResolution)
mouse_y = video_mode.YResolution - 1; mouse_y = video_mode.YResolution - 1;
if (mouse_inbuffer[0] & 0x01) //left button if (mouse_inbuffer[0] & 0x01) //left button
{
video_pset(mouse_x, mouse_y, 0x00FF8800); video_pset(mouse_x, mouse_y, 0x00FF8800);
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
}
else else
{
video_pset(mouse_x, mouse_y, 0x00FFFFFF); video_pset(mouse_x, mouse_y, 0x00FFFFFF);
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
}
} }
} }
+14
View File
@@ -0,0 +1,14 @@
// rd.c
// Author: Josh Holtrop
// Created: 12/31/03
// Modified: 01/04/04
byte *rd_readSector(DiskDevice *rd, dword sector, byte *dest)
{
memcpy(dest, (void *)(rd->location + (sector * 512)), 512);
return dest;
}
+9
View File
@@ -0,0 +1,9 @@
// rd.h
// Author: Josh Holtrop
// Created: 12/31/03
// Modified: 01/04/04
byte *rd_readSector(DiskDevice *rd, dword sector, byte *dest);
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 900 KiB

+65 -15
View File
@@ -148,29 +148,43 @@ got_rd:
mov [ds:BOOT_HASRD], al mov [ds:BOOT_HASRD], al
pop ds ;ds=0 pop ds ;ds=0
cmp al, 0 ;dont load rd cmp al, 0 ;dont load rd
jz no_rd jnz yes_rd
jmp no_rd
yes_rd:
mov cx, 80 mov cx, 80
mov edi, 0xb8000+160*4 mov edi, 0xb8000+160*4
filler_loop: filler_loop: ;draw a red bar
mov word [ds:edi], 0x0400+177 mov word [ds:edi], 0x0400+177
inc edi inc edi
inc edi inc edi
loop filler_loop loop filler_loop
mov cx, 80 ;80 cylinders to read mov cx, 80 ;80 cylinders to read
xor si, si xor si, si ;start at cylinder 0
mov edi, BOOT_RD_ADD ;ram disk address mov edi, BOOT_RD_ADD ;ram disk address
read_cylinder: read_cylinder:
push cx push cx
mov bx, 0x0100
mov bx, 0x0100 ;read sectors from head 0
mov es, bx mov es, bx
xor bx, bx xor bx, bx ;es:bx = data buffer for read
mov ax, 0x0224 mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
mov cx, si mov cx, si ;what cyl. we are on is now in cx
mov ch, cl mov ch, cl ;ch = cyl. number
mov cl, 1 mov cl, 1 ;cl = sector number 1-63
xor dx, dx xor dx, dx ;dh = head number
mov dl, [gs:BOOT_DRIVE] mov dl, [gs:BOOT_DRIVE] ;dl = drive number
int 0x13
mov bx, 0x0100 ;now read sectors from head 1
mov es, bx
mov bx, 9216 ;es:bx = data buffer for read
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
mov cx, si ;what cyl. we are on is now in cx
mov ch, cl ;ch = cyl. number
mov cl, 1 ;cl = sector number 1-63
mov dh, 1 ;dh = head number
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
int 0x13 int 0x13
mov ebx, 0xb8000 mov ebx, 0xb8000
@@ -890,11 +904,43 @@ KERNEL_DATA equ $-gdt
db 0x00 db 0x00
db 0x00 db 0x00
db 0x92 db 0x92
db 0xcf ;cf db 0xcf
db 0x00 db 0x00
gdt_end: gdt_end:
;-------------------------------------------------------
gdtr32:
dw gdt_end32-gdt32-1
dd gdt32
gdt32:
dd 0
dd 0
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
KERNEL_CODE32 equ $-gdt32
db 0xff ;limit 7:0
db 0xff ;limit 15:8
db 0x00 ;base 7:0
db 0x00 ;base 15:8
db 0x00 ;base 23:16
db 0x9a ;access
db 0xcf ;flags / limit 19:16
db 0x40 ;base 31:24
KERNEL_DATA32 equ $-gdt32
db 0xff ;segment 16 = 4gb data
db 0xff
db 0x00
db 0x00
db 0x00
db 0x92
db 0xcf
db 0x40
gdt_end32:
;------------------------------------------------------ ;------------------------------------------------------
go_pm: go_pm:
xor ax, ax xor ax, ax
@@ -909,12 +955,16 @@ go_pm:
bits 32 bits 32
pmode: pmode:
mov ax, KERNEL_DATA lgdt [gdtr32]
jmp KERNEL_CODE32:pmode_offsetted+0xC0000000
pmode_offsetted:
mov ax, KERNEL_DATA32
mov es, ax mov es, ax
mov ds, ax mov ds, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
jmp KERNEL_CODE:BOOT_KERNEL_ADD jmp KERNEL_CODE:BOOT_KERNEL_ADD+0xC0000000
kernel: db "KERNEL BIN", 0 kernel: db "KERNEL BIN", 0
+91
View File
@@ -0,0 +1,91 @@
// vfs.c
// Author: Josh Holtrop
// Created: 12/31/03
// Modified: 01/04/04
void vfs_init()
{
firstDiskDevice = malloc(sizeof(DiskDevice));
firstDiskDevice->type = VFS_DISK_FD;
firstDiskDevice->fileSystem = VFS_FS_FAT12;
firstDiskDevice->location = VFS_LOC_FD0;
firstDiskDevice->link = 0;
strcpy(firstDiskDevice->id, "fd0");
rootDevice = firstDiskDevice;
if (*(byte *)0xC0090000) // the user chose to load an initial ram disk from the floppy
{
DiskDevice *rd = malloc(sizeof(DiskDevice));
firstDiskDevice->link = (dword)rd;
rd->type = VFS_DISK_RD;
rd->fileSystem = VFS_FS_FAT12;
rd->location = 0xC0200000;
rd->link = 0;
strcpy(rd->id, "rd0");
rootDevice = rd;
}
}
byte *vfs_readFile(char *fileName)
{
DiskDevice *dd;
dword fileStartPosition;
if (fileName[0] == '/')
{
dd = rootDevice;
fileStartPosition = 1;
}
else
{
if (strlen(fileName) < 5) //not a long enough file name
return 0;
if (!((fileName[3] == ':') && (fileName[4] == '/'))) //if we aren't using the root directory, then there must be a 3 character device explicitly specified
return 0; // followed by a colon and then a slash
char device[4];
memcpy(device, fileName, 3); //copy the 3 digit device id to device
device[3] = 0; //null-terminating character for device string
dd = vfs_getDiskDeviceByID(device);
if (!dd) //the specified device was not found
return 0;
fileStartPosition = 5;
}
switch (dd->fileSystem)
{
case VFS_FS_FAT12:
return fat12_readFile(fileName+fileStartPosition, dd);
}
return 0;
}
byte *vfs_readSector(DiskDevice *dd, dword sector, byte *dest, dword sectors)
{
byte *origDest = dest;
switch (dd->type)
{
case VFS_DISK_RD:
for (; sectors > 0; sectors--, dest += 512, sector++)
rd_readSector(dd, sector, dest);
return origDest;
}
return 0;
}
DiskDevice *vfs_getDiskDeviceByID(char *id)
{
DiskDevice *dd = firstDiskDevice;
for (;;)
{
if (strcmp(dd->id, id))
return dd;
dd = (DiskDevice *)dd->link;
if (!dd)
break;
}
return 0;
}
+33
View File
@@ -0,0 +1,33 @@
// vfs.h
// Author: Josh Holtrop
// Created: 12/31/03
// Modified: 01/04/04
#define VFS_DISK_RD 1
#define VFS_DISK_FD 2
#define VFS_DISK_HD 3
#define VFS_FS_FAT12 1
#define VFS_LOC_FD0 1
typedef struct {
dword type;
dword fileSystem;
dword location;
dword link;
char id[4];
} __attribute__((packed)) DiskDevice;
void vfs_init();
byte *vfs_readFile(char *fileName);
byte *vfs_readSector(DiskDevice *dd, dword sector, byte *dest, dword sectors);
DiskDevice *vfs_getDiskDeviceByID(char *id);
DiskDevice *rootDevice = 0;
DiskDevice *firstDiskDevice = 0;
+38 -5
View File
@@ -4,23 +4,25 @@
//Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display //Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display
void video_init(ModeInfoBlock *mib) void video_init()
{ {
video_mode = *mib; videoMode = *(word *)0xC0090002;
if (!videoMode) //we are in console mode
return;
video_mode = *(ModeInfoBlock *) 0xC0090306;
switch(video_mode.BitsPerPixel) switch(video_mode.BitsPerPixel)
{ {
case 16: case 16:
vid_ptr16 = (word *) video_mode.PhysBasePtr;
video_psetp = &video_psetp16; video_psetp = &video_psetp16;
break; break;
case 24: case 24:
vid_ptr24 = (byte *) video_mode.PhysBasePtr;
video_psetp = &video_psetp24; video_psetp = &video_psetp24;
break; break;
case 32: case 32:
video_psetp = &video_psetp32; video_psetp = &video_psetp32;
vid_ptr32 = (dword *) video_mode.PhysBasePtr;
} }
} }
@@ -139,5 +141,36 @@ void video_psetp32(int pixel, dword color)
vid_ptr32[pixel] = color; vid_ptr32[pixel] = color;
} }
//Dummy function to not draw anything if there is no graphical mode enabled
void video_psetpnull(int pixel, dword color) {}
// This function draws a simple "console" window in graphical mode to display text
void video_drawConsole()
{
video_rectf(9, 9, 490, 260, 0);
video_rect(8, 8, 491, 261, 0x00777777);
int x, y;
for (x = 0; x < 80; x++)
{
for (y = 0; y < 25; y++)
{
video_renderChar(x*6+10, y*10+10, console_memory[y*80+x], 0x00FFFFFF);
}
}
}
// This function draws a "console" character to the graphical video screen
void video_drawConsoleChar(dword position)
{
int x = position % 80;
int y = position / 80;
video_renderChar(x*6+10, y*10+10, console_memory[y*80+x], 0x00FFFFFF);
}
+12 -5
View File
@@ -1,6 +1,6 @@
//video.h //video.h
// 08/18/03 Josh Holtrop // 08/18/03 Josh Holtrop
// Modified: 11/12/03 // Modified: 12/28/03
void video_init(); void video_init();
void video_horiz(int y, int x1, int x2, dword color); void video_horiz(int y, int x1, int x2, dword color);
@@ -11,7 +11,11 @@ inline void video_pset(int x, int y, dword color);
void video_psetp16(int pixel, dword color); void video_psetp16(int pixel, dword color);
void video_psetp24(int pixel, dword color); void video_psetp24(int pixel, dword color);
void video_psetp32(int pixel, dword color); void video_psetp32(int pixel, dword color);
void video_psetpnull(int pixel, dword color);
void video_renderChar(int x, int y, int character, dword color); void video_renderChar(int x, int y, int character, dword color);
void video_drawConsole();
void video_drawConsoleChar(dword position);
typedef struct{ typedef struct{
word ModeAttributes; word ModeAttributes;
@@ -52,11 +56,14 @@ typedef struct{
byte Reserved[206]; byte Reserved[206];
} ModeInfoBlock; } ModeInfoBlock;
ModeInfoBlock video_mode; ModeInfoBlock video_mode;
byte *vid_ptr24; dword videoMode = 0; //what video mode # we are in, 0 for console mode
word *vid_ptr16; word *vid_ptr16 = (word *)0xF0000000;
dword *vid_ptr32; byte *vid_ptr24 = (byte *)0xF0000000;
void (*video_psetp)(int, dword); //function pointer to set a pixel dword *vid_ptr32 = (dword *)0xF0000000;
word console_memory[2000]; //holds a copy of the console's memory
void (*video_psetp)(int, dword) = video_psetpnull; //function pointer to set a pixel
+309 -137
View File
@@ -1,177 +1,349 @@
// vmm.c // vmm.c
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 09/30/03 // Date: 09/30/03
// Rewritten from scratch: 12/23/03
PageDirectory *vmm_PDBR = 0; // Modified: 12/30/03
dword vmm_first_virtual_address = 0;
// This is the initialization procedure for the Virtual Memory Manager
// It sets up the final page directory/page table setup and maps video memory, if present
void vmm_init() void vmm_init()
{ {
if (!(vmm_PDBR = mm_palloc(1, PID_KERNEL))) dword *pageTables = (dword *)0xC0104000; //this is the location of the page directory
pageTables[0x3FF] = 0x104000|0x03; //the last page directory entry points to the page directory itself
pageTables[0] = 0;
invlpg(0);
if (videoMode) //we are in a graphical mode
{ {
printf("ERROR! COULD NOT ALLOCATE PAGE FOR INITIAL PAGE DIRECTORY!!\n"); dword vidPages = video_mode.XResolution * video_mode.YResolution * (video_mode.BitsPerPixel >> 3);
halt(); if (vidPages % 4096)
} vidPages = (vidPages >> 12) + 1;
vmm_init_pagetable((dword)vmm_PDBR);
if (mm_totalmem % 4096)
vmm_first_virtual_address = mm_totalmem + (4096 - (mm_totalmem % 4096));
else else
vmm_first_virtual_address = mm_totalmem; vidPages = (vidPages >> 12);
vmm_mapn(0xF0000000, video_mode.PhysBasePtr, vidPages);
}
dword firstHeapEntryBlock = (dword)mm_palloc();
vmm_map1((dword)firstHeapEntry, firstHeapEntryBlock);
HeapEntryBlock *heb = (HeapEntryBlock *)firstHeapEntry;
vmm_heb_init(heb);
heb->entry[0].base = (dword)firstHeapEntry; //start of kernel's heap memory
heb->entry[0].size = 4096; //the first HeapEntryBlock is 1 page long
heb->entry[0].attributes = VMM_HE_HEB; //this is a HeapEntryBlock
heb->entry[1].base = (dword)firstHeapEntry+4096; //this is the start of the rest of the kernel's heap memory
heb->entry[1].size = 0x10000000-4096; //the rest of the kernel's heap memory: 256mb - 4kb
heb->entry[1].attributes = VMM_HE_HOLE; //this is a hold - an unmapped section of heap memory
}
if (vmm_mapn(0, 0, 0x03, mm_totalmem/4096+1))
// This function initialzes a Heap Entry Block to unused entries linked together
void vmm_heb_init(HeapEntryBlock *heb)
{ {
printf("Could not page in all physical RAM!\n"); int a;
halt(); for (a = 0; a < 256; a++)
{
heb->entry[a].base = 0;
heb->entry[a].size = 0;
heb->entry[a].attributes = VMM_HE_UNUSED;
heb->entry[a].link = (dword)&(heb->entry[a+1]);
} }
//we also need to map in the video framebuffer memory: heb->entry[255].link = 0;
if (video_mode.PhysBasePtr > 0 && video_mode.BitsPerPixel > 0)
{
if (vmm_mapn(video_mode.PhysBasePtr, video_mode.PhysBasePtr, 0x03, ((video_mode.BitsPerPixel>>3) * video_mode.XResolution * video_mode.YResolution)/4096+1))
{
printf("Could not page in video memory at 0x%x!\n", video_mode.PhysBasePtr);
halt();
} }
// This function maps a virtual address to a physical address using the page directory / page table
void vmm_map1(dword virt, dword physical)
{
dword pde = virt >> 22;
dword pte = (virt & 0x003FF000) >> 12;
dword *pageTables = (dword *)0xC0104000; //this is the location of the page directory
if (!(pageTables[pde] & 0x01)) //the page directory entry does not exist, we must allocate a page for it
{
dword *newpagetable = mm_palloc();
pageTables[pde] = ((dword)newpagetable) | 0x03;
invlpg(virt);
dword *newpteptr = (dword *)(0xFFC00000 | (pde << 12)); //points to first dword of newly allocated page table
int a;
for (a = 0; a < 1024; a++)
{
newpteptr[a] = 0;
}
}
dword *pteptr = (dword *)(0xFFC00000 | (pde << 12) | (pte << 2));
*pteptr = physical | 0x03;
invlpg(virt);
}
// This function maps a variable number of pages in a row
void vmm_mapn(dword virt, dword physical, dword n)
{
for (; n > 0; n--)
{
vmm_map1(virt, physical);
virt += 4096;
physical += 4096;
} }
} }
void vmm_enable_paging() // This function removes the virtual address's entry in the page directory / page table
void vmm_unmap1(dword virt)
{ {
write_cr3((dword)vmm_PDBR); dword *pteptr = (dword *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10));
write_cr0(0x80000000|read_cr0()); *pteptr = 0;
invlpg(virt);
} }
int vmm_map1(dword virtual, dword physical, dword flags) // This function removes multiple pages' entries
void vmm_unmapn(dword virt, dword n)
{ {
if (virtual & 0x00000FFF) for (; n > 0; n--)
return 1; // ERROR 1: address not page-aligned
if (physical & 0x00000FFF)
return 1; // ERROR 1: address not page-aligned
int pde = (virtual & 0xFFC00000) >> 22;
int pte = (virtual & 0x003FF000) >> 12;
if (!(vmm_PDBR->pageTables[pde] & 0x01))
{ {
vmm_PDBR->pageTables[pde] = (dword)mm_palloc(1, PID_KERNEL) | 0x7; //user, r/w, present vmm_unmap1(virt);
vmm_init_pagetable(vmm_PDBR->pageTables[pde] & 0xFFFFF000); virt += 4096;
if (vmm_PDBR->pageTables[pde] == 0x07)
return 2; // ERROR 2: page table could not be created
} }
PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
if (ptp->page[pte] & 0x01)
return 3; // ERROR 3: page table entry already exists
ptp->page[pte] = physical | flags;
//invlpg();
return 0;
}
int vmm_mapn(dword virtual, dword physical, dword flags, dword n)
{
int mapped;
int result = 0;
dword va = virtual;
dword pa = physical;
for (mapped = 0; mapped < n; mapped++)
{
if (result = vmm_map1(va, pa, flags))
{
if (mapped > 0)
vmm_unmapn(virtual, mapped);
return result;
}
va += 4096;
pa += 4096;
}
//invlpg();
return 0;
}
int vmm_unmap1(dword virtual)
{
if (virtual & 0x00000FFF)
return 1; // ERROR 1: address not page-aligned
int pde = (virtual & 0xFFC00000) >> 22;
int pte = (virtual & 0x003FF000) >> 12;
if (!(vmm_PDBR->pageTables[pde] & 0x01))
return 2; // ERROR 2: page table not present
PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
ptp->page[pte] = 0;
//invlpg();
return 0;
}
int vmm_unmapn(dword virtual, dword n)
{
int reslt;
int i;
for (i = 0; i < n; i++)
{
if (reslt = vmm_unmap1(virtual))
return reslt;
virtual += 4096;
}
vmm_walkPageTables();
//invlpg();
return 0;
}
void vmm_init_pagetable(dword address)
{
PageTable *ptp = (PageTable *)address;
int n;
for (n = 0; n < 1024; n++)
ptp->page[n] = 0;
}
int vmm_walkPageTables()
{
int pde;
int pte;
int used_ptes;
PageTable *ptp;
for (pde = 0; pde < 1024; pde++)
{
if (vmm_PDBR->pageTables[pde] & 0x01)
{
used_ptes = 0;
ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
for (pte = 0; pte < 1024; pte++)
{
if (ptp->page[pte] & 0x01) //page table entry present
used_ptes++;
}
if (!(used_ptes)) //no used pte's -- remove page table & page directory entry
{
mm_pfree(ptp);
vmm_PDBR->pageTables[pde] = 0;
}
}
}
return 0;
} }
// Virtual Memory allocator function
void *malloc(dword bytes) void *malloc(dword bytes)
{ {
if (bytes % VMM_MALLOC_GRANULARITY)
bytes = bytes + VMM_MALLOC_GRANULARITY - (bytes % VMM_MALLOC_GRANULARITY);
void *attempt = vmm_getFreeChunk(bytes);
if (attempt)
return attempt;
if(vmm_moreCore(bytes))
return 0; //we could not get any more heap memory
return vmm_getFreeChunk(bytes);
} }
// This function returns a pointer if a free chunk of memory exists
void *vmm_getFreeChunk(dword bytes)
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->attributes == VMM_HE_FREE)
{
if (he->size > bytes)
{
HeapEntry *nhe = vmm_nextHeapEntry();
nhe->base = he->base;
nhe->size = bytes;
nhe->attributes = VMM_HE_USED;
he->base += bytes;
he->size -= bytes;
return (void *)(nhe->base);
}
if (he->size == bytes)
{
he->attributes = VMM_HE_USED;
return (void *)(he->base);
}
}
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
}
// This function coalesces any two adjacent heap entries into one entry
void vmm_coalesceHeapEntry(HeapEntry *he)
{
if (!(he->attributes == VMM_HE_FREE || he->attributes == VMM_HE_HOLE))
return;
if (he->size == 0)
{
he->attributes = VMM_HE_UNUSED;
return;
}
HeapEntry *hec = firstHeapEntry;
for (;;)
{
if (hec->attributes == he->attributes)
{
if ((hec->base + hec->size) == he->base) //hec ends where he begins
{
he->base = hec->base;
he->size += hec->size;
hec->attributes = VMM_HE_UNUSED;
}
if ((he->base + he->size) == hec->base) //he ends where hec begins
{
he->size += hec->size;
hec->attributes = VMM_HE_UNUSED;
}
}
hec = (HeapEntry *)hec->link;
if (!hec)
break;
}
}
// This function retrieves more physical memory for the heap
int vmm_moreCore(dword bytes)
{
dword pages = (bytes >> 12) + 1;
bytes = pages << 12;
HeapEntry *he = vmm_getFirstHoleHeapEntry(bytes);
dword virt = he->base;
for (; pages > 0; pages--)
{
dword phys = (dword)mm_palloc();
if (!phys)
return 1;
vmm_map1(virt, phys);
virt += 4096;
}
if (he->size == bytes)
{
he->attributes = VMM_HE_FREE;
vmm_coalesceHeapEntry(he);
}
else
{
HeapEntry *nhe = vmm_nextHeapEntry();
nhe->base = he->base;
nhe->size = bytes;
nhe->attributes = VMM_HE_FREE;
he->base += bytes;
he->size -= bytes;
vmm_coalesceHeapEntry(nhe);
}
return 0;
}
// This function returns the next available heap entry, creates more entries if we are running low
HeapEntry *vmm_nextHeapEntry()
{
if (vmm_heapEntriesLeft() < 10)
vmm_addHeapEntryBlock();
return vmm_getFirstUnusedHeapEntry();
}
// This function creates a new block (page) of heap entries (256)
void vmm_addHeapEntryBlock()
{
HeapEntry *he = vmm_getFirstHoleHeapEntry(4096);
HeapEntry *newBlock = vmm_getFirstUnusedHeapEntry();
dword heb = (dword)mm_palloc();
vmm_map1(he->base, heb);
vmm_heb_init((HeapEntryBlock *)he->base);
HeapEntry *lhe = vmm_getLastHeapEntry();
if (he->size == 4096)
{
he->attributes = VMM_HE_HEB;
lhe->link = (dword)he->base;
}
else
{
newBlock->base = he->base;
newBlock->size = 4096;
newBlock->attributes = VMM_HE_HEB;
he->base += 4096;
he->size -= 4096;
lhe->link = (dword)newBlock->base;
}
return;
}
// This function returns the last heap entry in the linked list, useful for setting
// its link field to point to the first entry of a newly allocated list
HeapEntry *vmm_getLastHeapEntry()
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->link == 0)
return he;
he = (HeapEntry *)he->link;
}
}
// This function returns the first heap entry corresponding to a memory "hole"
HeapEntry *vmm_getFirstHoleHeapEntry(dword minBytes)
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if ((he->attributes == VMM_HE_HOLE) && (he->size >= minBytes))
return he;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
}
// This function returns the first heap entry that is not being used
HeapEntry *vmm_getFirstUnusedHeapEntry()
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->attributes == VMM_HE_UNUSED)
return he;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
}
// This function returns the number of heap entries available for use
dword vmm_heapEntriesLeft()
{
HeapEntry *he = firstHeapEntry;
dword entries = 0;
for (;;)
{
if (he->attributes == VMM_HE_UNUSED)
entries++;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return entries;
}
// This function "frees" an area of memory previously allocated with malloc()
int free(void *ptr) int free(void *ptr)
{ {
HeapEntry *he = vmm_getHeapEntryByBase((dword)ptr);
if (!he)
return 1; //a heap entry starting at the given address was not found
he->attributes = VMM_HE_FREE;
vmm_coalesceHeapEntry(he);
return 0;
}
// This function scans the heap entry linked list for an entry that begins at the given address
HeapEntry *vmm_getHeapEntryByBase(dword base)
{
HeapEntry *he = firstHeapEntry;
for (;;)
{
if (he->base == base)
return he;
he = (HeapEntry *)he->link;
if (!he)
break;
}
return 0;
} }
+38 -14
View File
@@ -1,28 +1,52 @@
// vmm.h // vmm.h
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 09/30/03 // Date: 09/30/03
// Rewritten from scratch: 12/23/03
// Modified: 12/30/03
#define VMM_HE_UNUSED 0 //available entry
#define VMM_HE_FREE 1 //free section of memory
#define VMM_HE_USED 2 //used section of memory
#define VMM_HE_HOLE 3 //a "hole" (unmapped) section of virtual memory
#define VMM_HE_HEB 4 //HeapEntryBlock
#define VMM_MALLOC_GRANULARITY 4 //granularity for all memory requests
typedef struct {
dword base; //virtual base address
dword size; //size in bytes
dword attributes; //free/used/hole
dword link; //link to next HeapEntry
} __attribute__((packed)) HeapEntry;
typedef struct { typedef struct {
dword page[1024]; HeapEntry entry[256]; //256 HeapEntry objects = 4kb (1 page)
} PageTable; } __attribute__((packed)) HeapEntryBlock;
typedef struct {
dword pageTables[1024];
} PageDirectory;
void vmm_enable_paging();
void vmm_init(); void vmm_init();
void *malloc(dword bytes); void *malloc(dword bytes);
int free(void *ptr); int free(void *ptr);
int vmm_map1(dword virtual, dword physical, dword flags); void vmm_map1(dword virt, dword physical);
int vmm_mapn(dword virtual, dword physical, dword flags, dword n); void vmm_mapn(dword virt, dword physical, dword n);
int vmm_unmap1(dword virtual); void vmm_unmap1(dword virt);
int vmm_unmapn(dword virtual, dword n); void vmm_unmapn(dword virt, dword n);
void vmm_init_pagetable(dword address); void vmm_heb_init(HeapEntryBlock *heb);
int vmm_walkPageTables(); void *vmm_getFreeChunk(dword bytes);
HeapEntry *vmm_nextHeapEntry();
dword vmm_heapEntriesLeft();
HeapEntry *vmm_getLastHeapEntry();
HeapEntry *vmm_getFirstUnusedHeapEntry();
HeapEntry *vmm_getFirstHoleHeapEntry(dword minBytes);
void vmm_addHeapEntryBlock();
int vmm_moreCore(dword bytes);
void vmm_coalesceHeapEntry(HeapEntry *he);
HeapEntry *vmm_getHeapEntryByBase(dword base);
HeapEntry *firstHeapEntry = (HeapEntry *)0xD0000000; //this is where heap memory starts