Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
311b8afc83 | ||
|
|
21e3943b5e | ||
|
|
10fd7102ca | ||
|
|
7de4f94423 | ||
|
|
0a546f1467 | ||
|
|
af6087ecec | ||
|
|
c613002307 | ||
|
|
76398df125 | ||
|
|
e83408ce83 | ||
|
|
715bb9341a | ||
|
|
e82bf2ecdf | ||
|
|
528527a7ed | ||
|
|
71aaa7a598 | ||
|
|
9070a76b18 | ||
|
|
5048a93ff7 |
No files matched your search
+137
-7
@@ -38,6 +38,69 @@ inline void disable_ints()
|
||||
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
|
||||
void remap_pics(int pic1, int pic2)
|
||||
{
|
||||
@@ -74,6 +137,7 @@ inline void pic2_mask(byte mask)
|
||||
//Restarts the computer
|
||||
inline void restart()
|
||||
{
|
||||
enable_ints();
|
||||
byte temp;
|
||||
do
|
||||
{
|
||||
@@ -107,13 +171,6 @@ inline void init_timer()
|
||||
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
|
||||
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
@@ -1,7 +1,20 @@
|
||||
; asmfuncs.asm
|
||||
; 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
|
||||
;extern dword write_cr0(dword cr0);
|
||||
@@ -32,6 +45,16 @@ _write_cr3:
|
||||
pop ebp
|
||||
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
|
||||
;extern dword read_cr3();
|
||||
[global _read_cr3]
|
||||
@@ -40,6 +63,408 @@ _read_cr3:
|
||||
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
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
echo Backing up to .\Backup\%1
|
||||
|
||||
mkdir .\Backup\%1
|
||||
mkdir .\Backup\%1\lib
|
||||
|
||||
copy *.h .\Backup\%1
|
||||
copy *.c .\Backup\%1
|
||||
@@ -11,9 +10,3 @@ copy *.asm .\Backup\%1
|
||||
copy *.ld .\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
@@ -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_ROOT_SEG 0x0900 ;right after FAT
|
||||
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
|
||||
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
|
||||
%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_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -21,10 +21,24 @@ inline void eoi();
|
||||
inline void eoi2();
|
||||
inline dword kernel_size();
|
||||
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
@@ -0,0 +1 @@
|
||||
gcc -S kernel.c -masm=intel -fno-builtin
|
||||
@@ -5,11 +5,12 @@
|
||||
|
||||
idtr:
|
||||
dw 50*8-1 ;size of idt
|
||||
dd IDT ;address of idt
|
||||
dd IDT_V ;address of idt
|
||||
|
||||
|
||||
%macro isr_label 1
|
||||
isr_%1:
|
||||
push eax
|
||||
mov eax, %1
|
||||
jmp isr_main
|
||||
%endmacro
|
||||
@@ -66,6 +67,9 @@ isr_label 48
|
||||
isr_label 49
|
||||
|
||||
isr_main:
|
||||
cmp eax, 0x30
|
||||
jz isr_syscall
|
||||
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
@@ -79,10 +83,27 @@ isr_main:
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
pop eax
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
#define YELLOW_TXT 0x0E
|
||||
#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 PID_KERNEL 0x02 //kernel's PID
|
||||
|
||||
+43
-9
@@ -2,21 +2,55 @@
|
||||
;Author: Josh Holtrop
|
||||
;Modified: 10/30/03
|
||||
|
||||
%include "bootdef.inc"
|
||||
|
||||
%define GDT 0x100000
|
||||
%define IDT 0x102000
|
||||
%define GDT_P 0x100000; ;1mb physical - Global Descriptor Table space
|
||||
%define GDT_V GDT_P+0xC0000000
|
||||
%define IDT_P 0x102000 ;1mb+8kb - Interrupt Descriptor Table space
|
||||
%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]
|
||||
[extern _isr]
|
||||
[extern _k_init]
|
||||
[extern _putc]
|
||||
|
||||
bits 32
|
||||
|
||||
;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:
|
||||
cli ;if they weren't already off
|
||||
mov edi, GDT
|
||||
cli ;if they weren't already off
|
||||
|
||||
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 ecx, gdt_end-gdt
|
||||
copy_gdt:
|
||||
@@ -24,7 +58,7 @@ copy_gdt:
|
||||
stosb
|
||||
loop copy_gdt
|
||||
|
||||
mov edi, IDT ;destination
|
||||
mov edi, IDT_V ;destination
|
||||
mov esi, isr_0 ;address of isr0
|
||||
mov edx, isr_1-isr_0 ;distance between isr labels
|
||||
mov ecx, 50 ;number of isrlabels
|
||||
@@ -42,7 +76,7 @@ fill_idt:
|
||||
mov esi, ebx
|
||||
add esi, edx
|
||||
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
|
||||
jmp KERNEL_CODE:newgdtcontinue
|
||||
@@ -53,7 +87,7 @@ newgdtcontinue:
|
||||
mov gs, ax
|
||||
mov fs, 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
|
||||
|
||||
call _k_init
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
//08/13/03 Josh Holtrop
|
||||
//Holtrop's Operating System
|
||||
//Version: 0.12
|
||||
//Modified: 11/12/03
|
||||
//Modified: 12/30/03
|
||||
|
||||
#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 "video.h" //video functions
|
||||
@@ -17,14 +15,35 @@
|
||||
#include "mouse.h" //generic ps/2 mouse driver & functions
|
||||
#include "fdc.h" //Floppy Disk Controller functions
|
||||
#include "stdfont.h" //Standard font bitmask array
|
||||
#include "kio.h"
|
||||
#include "vfs.h"
|
||||
#include "rd.h"
|
||||
#include "fat12.h"
|
||||
|
||||
void isr(dword num);
|
||||
void k_init();
|
||||
|
||||
/* These functions are defined in asmfuncs.asm */
|
||||
extern dword write_cr0(dword cr0);
|
||||
extern dword read_cr0();
|
||||
extern dword write_cr3(dword cr3);
|
||||
extern dword read_cr2();
|
||||
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 "mouse.c"
|
||||
#include "keyboard.c"
|
||||
@@ -34,7 +53,6 @@ extern dword read_cr3();
|
||||
#include "video.c"
|
||||
|
||||
dword timer = 0;
|
||||
dword *videoMode;
|
||||
|
||||
//Main kernel initialization method
|
||||
void k_init()
|
||||
@@ -42,39 +60,46 @@ void k_init()
|
||||
// ===== Initialization
|
||||
fdc_sendDOR(0x0C); //turn off floppy motor!!
|
||||
console_cls();
|
||||
video_init();
|
||||
mm_init();
|
||||
vmm_init();
|
||||
remap_pics(0x20, 0x28);
|
||||
init_timer();
|
||||
mm_init();
|
||||
videoMode = (dword *)0x90002;
|
||||
if (*videoMode)
|
||||
video_init((ModeInfoBlock *) 0x90306);
|
||||
vmm_init();
|
||||
mouse_init();
|
||||
vmm_enable_paging();
|
||||
pic1_mask(0); //unmask IRQ's 0-7
|
||||
pic2_mask(0); //unmask IRQ's 8-15
|
||||
vfs_init();
|
||||
enable_ints();
|
||||
kbd_resetLEDs(); //after enabling interrupts!!
|
||||
|
||||
char *bmpptr = (char *)0x108000+54;
|
||||
int a = 0;
|
||||
int x = 0;
|
||||
int y = 479;
|
||||
for (a=0; a < 640*480; a++)
|
||||
if (videoMode)
|
||||
{
|
||||
video_pset(x, y, *(dword *)bmpptr);
|
||||
bmpptr += 3;
|
||||
x++;
|
||||
if (x == 640)
|
||||
{
|
||||
x = 0;
|
||||
y--;
|
||||
}
|
||||
int p = video_mode.XResolution*video_mode.YResolution-1;
|
||||
for (; p >= 0; p--)
|
||||
video_psetp(p, 0x00000044);
|
||||
video_drawConsole();
|
||||
}
|
||||
|
||||
printf("HOS 0.12 - Kernel Size: %d kb\n", kernel_size()/1024);
|
||||
printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem);
|
||||
printf("Free memory: %d bytes\n", mm_freemem());
|
||||
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: %u MB (%u bytes)\n", mm_megabytes, mm_totalmem);
|
||||
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;
|
||||
for (;;)
|
||||
@@ -90,9 +115,13 @@ void isr(dword num)
|
||||
{
|
||||
switch(num)
|
||||
{
|
||||
case 14:
|
||||
printf("Page fault, CR2 = 0x%x\n", read_cr2());
|
||||
halt();
|
||||
break;
|
||||
case 0x20: // IRQ0 - timer interrupt
|
||||
timer++;
|
||||
(*(byte *)(0xb8000))++;
|
||||
(*(byte *)(0xc00b8000))++;
|
||||
eoi();
|
||||
break;
|
||||
case 0x21: // IRQ1 - keyboard interrupt
|
||||
@@ -104,6 +133,7 @@ void isr(dword num)
|
||||
break;
|
||||
default:
|
||||
printf("Interrupt %d (0x%x) Unhandled!!\n", num, num);
|
||||
halt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
del hlibc.a
|
||||
ar -r hlibc.a *.o
|
||||
@@ -1 +0,0 @@
|
||||
gcc -ffreestanding -fno-builtin -c *.c
|
||||
@@ -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
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned char byte;
|
||||
|
||||
|
||||
|
||||
-532
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
#ifndef __HMISC_H__
|
||||
#define __HMISC_H__ __HMISC_H__
|
||||
|
||||
void memcpy(dword src, dword dest, dword length);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
#include "string.h"
|
||||
|
||||
int strlen(char *str)
|
||||
{
|
||||
int retn = 0;
|
||||
while (*str++ != 0)
|
||||
retn++;
|
||||
return retn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
#ifndef __HSTRING_H__
|
||||
#define __HSTRING_H__ __HSTRING_H__
|
||||
|
||||
int strlen(char *str);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
@@ -2,7 +2,7 @@ OUTPUT_FORMAT("binary")
|
||||
ENTRY(start)
|
||||
SECTIONS
|
||||
{
|
||||
.text 0x104000 : {
|
||||
.text 0xC0106000 : {
|
||||
code = .; _code = .; __code = .;
|
||||
*(.text)
|
||||
. = ALIGN(4096);
|
||||
|
||||
@@ -1,273 +1,112 @@
|
||||
// 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)
|
||||
dword mm_totalmem = 0x100000; //start counting from 1mb
|
||||
//The highest physical address
|
||||
dword mm_highestAddress = 0;
|
||||
#define BITMAP_SIZE 0x20000
|
||||
dword mm_totalmem = 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
|
||||
// memory areas returned by bios interrupt 0x8E20
|
||||
void mm_init()
|
||||
{
|
||||
dword *memmap_entries = (dword *) 0x9040A;
|
||||
memmap_entry *maps = (memmap_entry *) 0x92000;
|
||||
dword memmap_entries = *(dword *)0xC009040A;
|
||||
memmap_entry *maps = (memmap_entry *) 0xC0092000;
|
||||
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
|
||||
{
|
||||
mm_totalmem += maps[a].limit.lowdword;
|
||||
if (mm_highestAddress < (maps[a].base.lowdword + maps[a].limit.lowdword))
|
||||
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 + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram
|
||||
{
|
||||
if (maps[a].base.lowdword < FREERAM_START)
|
||||
{
|
||||
maps[a].limit.lowdword = maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword);
|
||||
maps[a].base.lowdword = FREERAM_START; //block at least 4kb, starts >= FREERAM_START
|
||||
mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
|
||||
}
|
||||
if (first_pageblock == 0) //no pageblock page set up yet, so set it up here
|
||||
else
|
||||
{
|
||||
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;
|
||||
mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
|
||||
}
|
||||
else //first_pageblock already set up, add on segment
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mm_totalmem % 0x100000)
|
||||
mm_megabytes = (mm_totalmem >> 20) + 1;
|
||||
else
|
||||
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 frees a single page
|
||||
void mm_pfree(dword base)
|
||||
{
|
||||
// dword pageNumber = base >> 12; // >>12 == /4096
|
||||
dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
|
||||
dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
|
||||
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
|
||||
}
|
||||
|
||||
|
||||
// This function allocates a single page, returning its physical address
|
||||
void *mm_palloc()
|
||||
{
|
||||
dword bite;
|
||||
for (bite = 0; bite < BITMAP_SIZE; bite++)
|
||||
{
|
||||
if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
|
||||
{
|
||||
int bit;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->pid == MM_PB_NP)
|
||||
break;
|
||||
else
|
||||
pb++;
|
||||
}
|
||||
pb->base = maps[a].base.lowdword;
|
||||
pb->length = maps[a].limit.lowdword / 4096;
|
||||
pb->pid = MM_PB_AVAIL;
|
||||
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
|
||||
return (void *)((bite << 15) | (bit << 12));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (first_pageblock == 0)
|
||||
{
|
||||
printf("ERROR! NO INITIAL PAGE BLOCK CREATED.");
|
||||
asm("cli");
|
||||
asm("hlt");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
return 0; //no free page
|
||||
}
|
||||
|
||||
|
||||
|
||||
//This function initializes a pageblock to be full of empty pointers
|
||||
void mm_init_pageblockpage(pageblock *pbp)
|
||||
// This function reports the number of bytes of free physical memory
|
||||
dword mm_freemem()
|
||||
{
|
||||
int a;
|
||||
for (a=0; a<256; a++) // 256 pageblock entries * 16 bytes per page block entry = 4096 bytes (1 page of pageblock entries)
|
||||
dword a;
|
||||
dword pages = 0;
|
||||
for (a = 0; a < BITMAP_SIZE; a++)
|
||||
{
|
||||
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
|
||||
pbp[a].link = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//This function allocates a certain number of physical pages for a particular process
|
||||
//Returns:
|
||||
// 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)
|
||||
return 0;
|
||||
pageblock *pb = first_pageblock;
|
||||
if (mm_freeentries() < 2)
|
||||
{
|
||||
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
|
||||
dword mm_freeentries()
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
dword counter = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->pid == MM_PB_NP)
|
||||
counter++;
|
||||
if (pb->link == 0)
|
||||
return counter;
|
||||
pb = (pageblock *) pb->link;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//This method creates a new page used to hold more pageblock entries at the end of the linked list
|
||||
//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))
|
||||
int bit;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
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;
|
||||
if (!(page_bitmap[a] & (1 << bit)))
|
||||
pages++;
|
||||
}
|
||||
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 amount = 0;
|
||||
pageblock *pb = first_pageblock;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->pid == MM_PB_AVAIL)
|
||||
amount += (pb->length)*4096;
|
||||
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;
|
||||
for (;;)
|
||||
{
|
||||
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;
|
||||
pbc = (pageblock *)pbc->link;
|
||||
}
|
||||
return pages << 12;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,28 +7,14 @@ typedef struct {
|
||||
} __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_pageblockpage(pageblock *pbp);
|
||||
void *mm_palloc(dword numpages, dword proc_pid);
|
||||
void mm_coalesce(pageblock *pb);
|
||||
int mm_pfree(void *ptr);
|
||||
dword mm_freeentries();
|
||||
void mm_pfreen(dword base, dword pages);
|
||||
void mm_pfree(dword base);
|
||||
void *mm_palloc();
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ void mouse_init()
|
||||
void isr_mouse()
|
||||
{
|
||||
byte inb = inportb(0x60); //read mouse byte
|
||||
//printf("InB: %x\n", inb);
|
||||
//return;
|
||||
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
|
||||
return;
|
||||
mouse_inbuffer[mouse_bytesRead] = inb;
|
||||
@@ -50,15 +48,9 @@ void isr_mouse()
|
||||
if (mouse_y >= video_mode.YResolution)
|
||||
mouse_y = video_mode.YResolution - 1;
|
||||
if (mouse_inbuffer[0] & 0x01) //left button
|
||||
{
|
||||
video_pset(mouse_x, mouse_y, 0x00FF8800);
|
||||
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
video_pset(mouse_x, mouse_y, 0x00FFFFFF);
|
||||
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 900 KiB |
+66
-16
@@ -148,29 +148,43 @@ got_rd:
|
||||
mov [ds:BOOT_HASRD], al
|
||||
pop ds ;ds=0
|
||||
cmp al, 0 ;dont load rd
|
||||
jz no_rd
|
||||
|
||||
jnz yes_rd
|
||||
jmp no_rd
|
||||
yes_rd:
|
||||
mov cx, 80
|
||||
mov edi, 0xb8000+160*4
|
||||
filler_loop:
|
||||
filler_loop: ;draw a red bar
|
||||
mov word [ds:edi], 0x0400+177
|
||||
inc edi
|
||||
inc edi
|
||||
loop filler_loop
|
||||
|
||||
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
|
||||
read_cylinder:
|
||||
push cx
|
||||
mov bx, 0x0100
|
||||
|
||||
mov bx, 0x0100 ;read sectors from head 0
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
mov ax, 0x0224
|
||||
mov cx, si
|
||||
mov ch, cl
|
||||
mov cl, 1
|
||||
xor dx, dx
|
||||
mov dl, [gs:BOOT_DRIVE]
|
||||
xor bx, bx ;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
|
||||
xor dx, dx ;dh = head number
|
||||
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
|
||||
|
||||
mov ebx, 0xb8000
|
||||
@@ -837,7 +851,7 @@ puthex2_goon2:
|
||||
ret
|
||||
|
||||
;------------------------------------------------------
|
||||
txt_welcome: db " Welcome to HOS v", VERSION, "! ", 0
|
||||
txt_welcome: db " Welcome to HOS v", VERSION, "! ", 0
|
||||
txt_rd1: db "1. Do not load an initial ram disk", 0
|
||||
txt_rd2: db "2. Load initial ram disk from floppy", 0
|
||||
txt_input: db "Enter your selection: ", 0
|
||||
@@ -890,11 +904,43 @@ KERNEL_DATA equ $-gdt
|
||||
db 0x00
|
||||
db 0x00
|
||||
db 0x92
|
||||
db 0xcf ;cf
|
||||
db 0xcf
|
||||
db 0x00
|
||||
|
||||
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:
|
||||
xor ax, ax
|
||||
@@ -909,12 +955,16 @@ go_pm:
|
||||
|
||||
bits 32
|
||||
pmode:
|
||||
mov ax, KERNEL_DATA
|
||||
lgdt [gdtr32]
|
||||
jmp KERNEL_CODE32:pmode_offsetted+0xC0000000
|
||||
|
||||
pmode_offsetted:
|
||||
mov ax, KERNEL_DATA32
|
||||
mov es, ax
|
||||
mov ds, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
jmp KERNEL_CODE:BOOT_KERNEL_ADD
|
||||
jmp KERNEL_CODE:BOOT_KERNEL_ADD+0xC0000000
|
||||
|
||||
kernel: db "KERNEL BIN", 0
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -4,28 +4,30 @@
|
||||
|
||||
|
||||
//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)
|
||||
{
|
||||
case 16:
|
||||
vid_ptr16 = (word *) video_mode.PhysBasePtr;
|
||||
video_psetp = &video_psetp16;
|
||||
break;
|
||||
case 24:
|
||||
vid_ptr24 = (byte *) video_mode.PhysBasePtr;
|
||||
video_psetp = &video_psetp24;
|
||||
break;
|
||||
case 32:
|
||||
video_psetp = &video_psetp32;
|
||||
vid_ptr32 = (dword *) video_mode.PhysBasePtr;
|
||||
}
|
||||
}
|
||||
|
||||
//Renders a character using stdfont[] as a bitmask
|
||||
void video_renderChar(int x, int y, int character, dword color)
|
||||
void video_renderChar(int x, int y, int character, dword color)
|
||||
{
|
||||
int charpos = (character & 0xFF) * 8;
|
||||
int row;
|
||||
@@ -41,7 +43,7 @@ void video_renderChar(int x, int y, int character, dword color)
|
||||
}
|
||||
|
||||
//Draws a horizontal line
|
||||
void video_horiz(int y, int x1, int x2, dword color)
|
||||
void video_horiz(int y, int x1, int x2, dword color)
|
||||
{
|
||||
if (x1 > x2)
|
||||
{
|
||||
@@ -65,7 +67,7 @@ void video_horiz(int y, int x1, int x2, dword color)
|
||||
}
|
||||
|
||||
//Draws a vertical line
|
||||
void video_vert(int x, int y1, int y2, dword color)
|
||||
void video_vert(int x, int y1, int y2, dword color)
|
||||
{
|
||||
if (y1 > y2)
|
||||
{
|
||||
@@ -90,7 +92,7 @@ void video_vert(int x, int y1, int y2, dword color)
|
||||
}
|
||||
|
||||
//Draws a rectangle
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color)
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color)
|
||||
{
|
||||
video_horiz(y1, x1, x2, color);
|
||||
video_horiz(y2, x1, x2, color);
|
||||
@@ -99,7 +101,7 @@ void video_rect(int x1, int y1, int x2, int y2, dword color)
|
||||
}
|
||||
|
||||
//Draws a filled rectangle
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color)
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color)
|
||||
{
|
||||
if (y2 < y1)
|
||||
{
|
||||
@@ -120,13 +122,13 @@ inline void video_pset(int x, int y, dword color)
|
||||
}
|
||||
|
||||
//Draws a pixel at the specified pixel position
|
||||
void video_psetp16(int pixel, dword color)
|
||||
void video_psetp16(int pixel, dword color)
|
||||
{
|
||||
vid_ptr16[pixel] = ((color&0xFF)>>3) | ((((color>>8)&0xFF)>>2)<<5) | ((((color>>16)&0xFF)>>3)<<11);
|
||||
}
|
||||
|
||||
//Draws a pixel at the specified pixel position
|
||||
void video_psetp24(int pixel, dword color)
|
||||
void video_psetp24(int pixel, dword color)
|
||||
{
|
||||
vid_ptr24[pixel*3] = color & 0xFF;
|
||||
vid_ptr24[pixel*3+1] = (color>>8) & 0xFF;
|
||||
@@ -134,10 +136,41 @@ void video_psetp24(int pixel, dword color)
|
||||
}
|
||||
|
||||
//Draws a pixel at the specified pixel position
|
||||
void video_psetp32(int pixel, dword color)
|
||||
void video_psetp32(int pixel, dword 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
//video.h
|
||||
// 08/18/03 Josh Holtrop
|
||||
// Modified: 11/12/03
|
||||
// Modified: 12/28/03
|
||||
|
||||
void video_init();
|
||||
void video_horiz(int y, int x1, int x2, dword color);
|
||||
void video_vert(int x, int y1, int y2, dword color);
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color);
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color);
|
||||
void video_init();
|
||||
void video_horiz(int y, int x1, int x2, dword color);
|
||||
void video_vert(int x, int y1, int y2, dword color);
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color);
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color);
|
||||
inline void video_pset(int x, int y, dword color);
|
||||
void video_psetp16(int pixel, dword color);
|
||||
void video_psetp24(int pixel, dword color);
|
||||
void video_psetp32(int pixel, dword color);
|
||||
void video_renderChar(int x, int y, int character, dword color);
|
||||
void video_psetp16(int pixel, dword color);
|
||||
void video_psetp24(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_drawConsole();
|
||||
void video_drawConsoleChar(dword position);
|
||||
|
||||
|
||||
typedef struct{
|
||||
word ModeAttributes;
|
||||
@@ -52,11 +56,14 @@ typedef struct{
|
||||
byte Reserved[206];
|
||||
} ModeInfoBlock;
|
||||
|
||||
|
||||
ModeInfoBlock video_mode;
|
||||
byte *vid_ptr24;
|
||||
word *vid_ptr16;
|
||||
dword *vid_ptr32;
|
||||
void (*video_psetp)(int, dword); //function pointer to set a pixel
|
||||
dword videoMode = 0; //what video mode # we are in, 0 for console mode
|
||||
word *vid_ptr16 = (word *)0xF0000000;
|
||||
byte *vid_ptr24 = (byte *)0xF0000000;
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,177 +1,349 @@
|
||||
|
||||
// vmm.c
|
||||
// Author: Josh Holtrop
|
||||
// Date: 09/30/03
|
||||
|
||||
PageDirectory *vmm_PDBR = 0;
|
||||
dword vmm_first_virtual_address = 0;
|
||||
// Rewritten from scratch: 12/23/03
|
||||
// Modified: 12/30/03
|
||||
|
||||
|
||||
// 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()
|
||||
{
|
||||
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");
|
||||
halt();
|
||||
dword vidPages = video_mode.XResolution * video_mode.YResolution * (video_mode.BitsPerPixel >> 3);
|
||||
if (vidPages % 4096)
|
||||
vidPages = (vidPages >> 12) + 1;
|
||||
else
|
||||
vidPages = (vidPages >> 12);
|
||||
vmm_mapn(0xF0000000, video_mode.PhysBasePtr, vidPages);
|
||||
}
|
||||
vmm_init_pagetable((dword)vmm_PDBR);
|
||||
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 (mm_totalmem % 4096)
|
||||
vmm_first_virtual_address = mm_totalmem + (4096 - (mm_totalmem % 4096));
|
||||
else
|
||||
vmm_first_virtual_address = mm_totalmem;
|
||||
|
||||
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)
|
||||
{
|
||||
int a;
|
||||
for (a = 0; a < 256; a++)
|
||||
{
|
||||
printf("Could not page in all physical RAM!\n");
|
||||
halt();
|
||||
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:
|
||||
if (video_mode.PhysBasePtr > 0 && video_mode.BitsPerPixel > 0)
|
||||
heb->entry[255].link = 0;
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
{
|
||||
if (vmm_mapn(video_mode.PhysBasePtr, video_mode.PhysBasePtr, 0x03, ((video_mode.BitsPerPixel>>3) * video_mode.XResolution * video_mode.YResolution)/4096+1))
|
||||
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++)
|
||||
{
|
||||
printf("Could not page in video memory at 0x%x!\n", video_mode.PhysBasePtr);
|
||||
halt();
|
||||
newpteptr[a] = 0;
|
||||
}
|
||||
}
|
||||
dword *pteptr = (dword *)(0xFFC00000 | (pde << 12) | (pte << 2));
|
||||
*pteptr = physical | 0x03;
|
||||
invlpg(virt);
|
||||
}
|
||||
|
||||
|
||||
void vmm_enable_paging()
|
||||
// This function maps a variable number of pages in a row
|
||||
void vmm_mapn(dword virt, dword physical, dword n)
|
||||
{
|
||||
write_cr3((dword)vmm_PDBR);
|
||||
write_cr0(0x80000000|read_cr0());
|
||||
}
|
||||
|
||||
|
||||
int vmm_map1(dword virtual, dword physical, dword flags)
|
||||
{
|
||||
if (virtual & 0x00000FFF)
|
||||
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))
|
||||
for (; n > 0; n--)
|
||||
{
|
||||
vmm_PDBR->pageTables[pde] = (dword)mm_palloc(1, PID_KERNEL) | 0x7; //user, r/w, present
|
||||
vmm_init_pagetable(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
|
||||
if (vmm_PDBR->pageTables[pde] == 0x07)
|
||||
return 2; // ERROR 2: page table could not be created
|
||||
vmm_map1(virt, physical);
|
||||
virt += 4096;
|
||||
physical += 4096;
|
||||
}
|
||||
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)
|
||||
// This function removes the virtual address's entry in the page directory / page table
|
||||
void vmm_unmap1(dword virt)
|
||||
{
|
||||
int mapped;
|
||||
int result = 0;
|
||||
dword va = virtual;
|
||||
dword pa = physical;
|
||||
for (mapped = 0; mapped < n; mapped++)
|
||||
dword *pteptr = (dword *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10));
|
||||
*pteptr = 0;
|
||||
invlpg(virt);
|
||||
}
|
||||
|
||||
|
||||
// This function removes multiple pages' entries
|
||||
void vmm_unmapn(dword virt, dword n)
|
||||
{
|
||||
for (; n > 0; n--)
|
||||
{
|
||||
if (result = vmm_map1(va, pa, flags))
|
||||
{
|
||||
if (mapped > 0)
|
||||
vmm_unmapn(virtual, mapped);
|
||||
return result;
|
||||
}
|
||||
va += 4096;
|
||||
pa += 4096;
|
||||
vmm_unmap1(virt);
|
||||
virt += 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)
|
||||
{
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,28 +1,52 @@
|
||||
|
||||
// vmm.h
|
||||
// Author: Josh Holtrop
|
||||
// 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 {
|
||||
dword page[1024];
|
||||
} PageTable;
|
||||
|
||||
typedef struct {
|
||||
dword pageTables[1024];
|
||||
} PageDirectory;
|
||||
HeapEntry entry[256]; //256 HeapEntry objects = 4kb (1 page)
|
||||
} __attribute__((packed)) HeapEntryBlock;
|
||||
|
||||
|
||||
void vmm_enable_paging();
|
||||
void vmm_init();
|
||||
void *malloc(dword bytes);
|
||||
int free(void *ptr);
|
||||
int vmm_map1(dword virtual, dword physical, dword flags);
|
||||
int vmm_mapn(dword virtual, dword physical, dword flags, dword n);
|
||||
int vmm_unmap1(dword virtual);
|
||||
int vmm_unmapn(dword virtual, dword n);
|
||||
void vmm_init_pagetable(dword address);
|
||||
int vmm_walkPageTables();
|
||||
void vmm_map1(dword virt, dword physical);
|
||||
void vmm_mapn(dword virt, dword physical, dword n);
|
||||
void vmm_unmap1(dword virt);
|
||||
void vmm_unmapn(dword virt, dword n);
|
||||
void vmm_heb_init(HeapEntryBlock *heb);
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user