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");
|
asm("cli");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
char *strcat(char *dest, char *src)
|
||||||
|
{
|
||||||
|
strcpy(dest+strlen(dest), src);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//converts a binary-coded-decimal byte to its decimal equivalent
|
||||||
|
inline byte bcd2byte(byte bcd)
|
||||||
|
{
|
||||||
|
return (10* ((bcd & 0xF0) >> 4)) + (bcd & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
//converts a binary-coded-decimal byte to its decimal equivalent
|
||||||
|
inline byte byte2bcd(byte bite)
|
||||||
|
{
|
||||||
|
return ((bite / 10) << 4) | (bite % 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtrim(char *str)
|
||||||
|
{
|
||||||
|
str += strlen(str); //now points to the null character at the end of the string
|
||||||
|
str--;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((*str == ' ') || (*str == '\t') || (*str == '\n'))
|
||||||
|
*str-- = 0;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *ucase(char *str)
|
||||||
|
{
|
||||||
|
char *ret = str;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (*str == 0)
|
||||||
|
break;
|
||||||
|
if ((*str >= 'a') && (*str <= 'z'))
|
||||||
|
*str = (*str) - 32;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *lcase(char *str)
|
||||||
|
{
|
||||||
|
char *ret = str;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (*str == 0)
|
||||||
|
break;
|
||||||
|
if ((*str >= 'A') && (*str <= 'Z'))
|
||||||
|
*str = (*str) + 32;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address
|
//Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address
|
||||||
void remap_pics(int pic1, int pic2)
|
void remap_pics(int pic1, int pic2)
|
||||||
{
|
{
|
||||||
@@ -74,6 +137,7 @@ inline void pic2_mask(byte mask)
|
|||||||
//Restarts the computer
|
//Restarts the computer
|
||||||
inline void restart()
|
inline void restart()
|
||||||
{
|
{
|
||||||
|
enable_ints();
|
||||||
byte temp;
|
byte temp;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -107,13 +171,6 @@ inline void init_timer()
|
|||||||
outportb(0x40, 0x2e); //msb
|
outportb(0x40, 0x2e); //msb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Invalidates the page tables to re-cache the Translation Lookaside Buffer
|
|
||||||
/*inline void invlpg()
|
|
||||||
{
|
|
||||||
asm("invlpg");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//Signals an End Of Interrupt signal to the first PIC
|
//Signals an End Of Interrupt signal to the first PIC
|
||||||
inline void eoi()
|
inline void eoi()
|
||||||
{
|
{
|
||||||
@@ -137,6 +194,79 @@ inline dword kernel_size()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//These functions are for reading and writing various values stored on the CMOS Real Time Clock
|
||||||
|
byte rtc_readDay()
|
||||||
|
{
|
||||||
|
outportb(0x70, 7);
|
||||||
|
return bcd2byte(inportb(0x71));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte rtc_readMonth()
|
||||||
|
{
|
||||||
|
outportb(0x70, 8);
|
||||||
|
return bcd2byte(inportb(0x71));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte rtc_readYear()
|
||||||
|
{
|
||||||
|
outportb(0x70, 9);
|
||||||
|
return bcd2byte(inportb(0x71));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte rtc_readSecond()
|
||||||
|
{
|
||||||
|
outportb(0x70, 0);
|
||||||
|
return bcd2byte(inportb(0x71));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte rtc_readMinute()
|
||||||
|
{
|
||||||
|
outportb(0x70, 2);
|
||||||
|
return bcd2byte(inportb(0x71));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte rtc_readHour()
|
||||||
|
{
|
||||||
|
outportb(0x70, 4);
|
||||||
|
return bcd2byte(inportb(0x71));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_setDay(byte day)
|
||||||
|
{
|
||||||
|
outportb(0x70, 7);
|
||||||
|
outportb(0x71, byte2bcd(day));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_setMonth(byte month)
|
||||||
|
{
|
||||||
|
outportb(0x70, 8);
|
||||||
|
outportb(0x71, byte2bcd(month));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_setYear(byte year)
|
||||||
|
{
|
||||||
|
outportb(0x70, 9);
|
||||||
|
outportb(0x71, byte2bcd(year));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_setSecond(byte second)
|
||||||
|
{
|
||||||
|
outportb(0x70, 0);
|
||||||
|
outportb(0x71, byte2bcd(second));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_setMinute(byte minute)
|
||||||
|
{
|
||||||
|
outportb(0x70, 2);
|
||||||
|
outportb(0x71, byte2bcd(minute));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_setHour(byte hour)
|
||||||
|
{
|
||||||
|
outportb(0x70, 4);
|
||||||
|
outportb(0x71, byte2bcd(hour));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+426
-1
@@ -1,7 +1,20 @@
|
|||||||
; asmfuncs.asm
|
; asmfuncs.asm
|
||||||
; Josh Holtrop
|
; Josh Holtrop
|
||||||
; 10/23/03
|
; Created: 10/23/03
|
||||||
|
; Modified: 12/25/03
|
||||||
|
|
||||||
|
[extern _putc]
|
||||||
|
[extern _console_memory]
|
||||||
|
[extern _cursorPosition]
|
||||||
|
[extern _video_drawConsole]
|
||||||
|
[extern _videoMode]
|
||||||
|
|
||||||
|
%macro jzfar 1
|
||||||
|
jnz %%skip
|
||||||
|
jmp %1
|
||||||
|
%%skip:
|
||||||
|
|
||||||
|
%endmacro
|
||||||
|
|
||||||
;stores the parameter to the CR0 register
|
;stores the parameter to the CR0 register
|
||||||
;extern dword write_cr0(dword cr0);
|
;extern dword write_cr0(dword cr0);
|
||||||
@@ -32,6 +45,16 @@ _write_cr3:
|
|||||||
pop ebp
|
pop ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;returns the value in the CR2 register
|
||||||
|
;extern dword read_cr2();
|
||||||
|
[global _read_cr2]
|
||||||
|
_read_cr2:
|
||||||
|
mov eax, cr2;
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;returns the value in the CR3 register
|
;returns the value in the CR3 register
|
||||||
;extern dword read_cr3();
|
;extern dword read_cr3();
|
||||||
[global _read_cr3]
|
[global _read_cr3]
|
||||||
@@ -40,6 +63,408 @@ _read_cr3:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;compares one string to another
|
||||||
|
;returns 0 if the strings are different
|
||||||
|
;extern dword strcmp(char *str1, char *str2);
|
||||||
|
[global _strcmp]
|
||||||
|
_strcmp:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, [ebp+8]
|
||||||
|
mov edi, [ebp+12]
|
||||||
|
strcmp_loop1:
|
||||||
|
lodsb
|
||||||
|
mov ah, [edi]
|
||||||
|
inc edi
|
||||||
|
cmp ah, al
|
||||||
|
jnz strcmp_ne
|
||||||
|
or al, al
|
||||||
|
jz strcmp_e
|
||||||
|
jmp strcmp_loop1
|
||||||
|
strcmp_e:
|
||||||
|
mov eax, 1
|
||||||
|
jmp short strcmp_done
|
||||||
|
strcmp_ne:
|
||||||
|
xor eax, eax
|
||||||
|
strcmp_done:
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
;copies a string from the source to the destination parameter
|
||||||
|
;extern void strcpy(char *dest, char *src);
|
||||||
|
[global _strcpy]
|
||||||
|
_strcpy:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
mov edi, [ebp+8]
|
||||||
|
mov esi, [ebp+12]
|
||||||
|
strcpyloop:
|
||||||
|
lodsb
|
||||||
|
stosb
|
||||||
|
or al, al
|
||||||
|
jnz strcpyloop
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
;copies memory of n bytes from src to destination
|
||||||
|
;extern void memcpy(dword dest, dword src, dword n);
|
||||||
|
[global _memcpy]
|
||||||
|
_memcpy:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
push ecx
|
||||||
|
mov edi, [ebp+8]
|
||||||
|
mov esi, [ebp+12]
|
||||||
|
mov ecx, [ebp+16]
|
||||||
|
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
;returns the number of characters in a string
|
||||||
|
;extern dword strlen(char *str);
|
||||||
|
[global _strlen]
|
||||||
|
_strlen:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push esi
|
||||||
|
push ebx
|
||||||
|
mov esi, [ebp+8]
|
||||||
|
xor ebx, ebx
|
||||||
|
strlenloop:
|
||||||
|
lodsb
|
||||||
|
or al, al
|
||||||
|
jz strlendone
|
||||||
|
inc ebx
|
||||||
|
jmp strlenloop
|
||||||
|
strlendone:
|
||||||
|
mov eax, ebx
|
||||||
|
pop ebx
|
||||||
|
pop esi
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
;this function invalidates the page directory/table entry that
|
||||||
|
; would be used to access the memory address given in the parameter
|
||||||
|
;extern void invlpg(dword addr);
|
||||||
|
[global _invlpg]
|
||||||
|
_invlpg:
|
||||||
|
mov eax, [esp+4]
|
||||||
|
invlpg [eax]
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;void writeCursorPosition(word pos)
|
||||||
|
;
|
||||||
|
[global _writeCursorPosition]
|
||||||
|
_writeCursorPosition:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
push edx
|
||||||
|
|
||||||
|
mov eax, [ebp+8] ;cursor position in ax
|
||||||
|
|
||||||
|
mov bl, al
|
||||||
|
mov dx, 0x03D4
|
||||||
|
mov al, 0x0E
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
inc dx
|
||||||
|
mov al, ah
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
dec dx
|
||||||
|
mov al, 0x0F
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
inc dx
|
||||||
|
mov al, bl
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
pop edx
|
||||||
|
pop ebx
|
||||||
|
pop eax
|
||||||
|
pop ebp
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;word getCursorPosition()
|
||||||
|
;
|
||||||
|
[global _getCursorPosition]
|
||||||
|
_getCursorPosition:
|
||||||
|
push ebx
|
||||||
|
push edx
|
||||||
|
|
||||||
|
xor eax, eax
|
||||||
|
mov dx, 0x03D4
|
||||||
|
mov al, 0x0E
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
inc dx
|
||||||
|
in al, dx
|
||||||
|
mov bl, al
|
||||||
|
|
||||||
|
dec dx
|
||||||
|
mov al, 0x0F
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
inc dx
|
||||||
|
in al, dx
|
||||||
|
mov ah, bl
|
||||||
|
|
||||||
|
pop edx
|
||||||
|
pop ebx
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;void console_scroll()
|
||||||
|
;
|
||||||
|
[global _console_scroll]
|
||||||
|
_console_scroll:
|
||||||
|
pusha
|
||||||
|
mov esi, _console_memory+160
|
||||||
|
mov edi, _console_memory
|
||||||
|
mov ecx, 960 ;(2000-80)/2
|
||||||
|
rep movsd
|
||||||
|
mov ax, 0x0720
|
||||||
|
mov ecx, 80
|
||||||
|
rep stosw
|
||||||
|
mov esi, _console_memory
|
||||||
|
mov edi, 0xC00B8000
|
||||||
|
mov ecx, 1000
|
||||||
|
rep movsd
|
||||||
|
mov eax, [_videoMode]
|
||||||
|
cmp eax, 0
|
||||||
|
jz _console_scroll_end
|
||||||
|
call _video_drawConsole
|
||||||
|
_console_scroll_end:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;void console_cls()
|
||||||
|
;
|
||||||
|
[global _console_cls]
|
||||||
|
_console_cls:
|
||||||
|
pusha
|
||||||
|
mov edi, _console_memory
|
||||||
|
mov ax, 0x0720
|
||||||
|
mov ecx, 2000
|
||||||
|
rep stosw
|
||||||
|
push dword 0
|
||||||
|
call _writeCursorPosition
|
||||||
|
add esp, 4
|
||||||
|
mov [_cursorPosition], dword 0
|
||||||
|
mov esi, _console_memory
|
||||||
|
mov edi, 0xC00B8000
|
||||||
|
mov ecx, 1000
|
||||||
|
rep movsd
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;int puts(char *str)
|
||||||
|
;
|
||||||
|
[global _puts]
|
||||||
|
_puts:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push esi
|
||||||
|
push eax
|
||||||
|
mov esi, [ebp+8] ;esi = to string
|
||||||
|
puts_loop:
|
||||||
|
lodsb
|
||||||
|
cmp al, 0
|
||||||
|
jz puts_done
|
||||||
|
push eax
|
||||||
|
call _putc
|
||||||
|
add esp, 4
|
||||||
|
jmp puts_loop
|
||||||
|
|
||||||
|
puts_done:
|
||||||
|
pop eax
|
||||||
|
pop esi
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[global _putDecu]
|
||||||
|
_putDecu:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
sub esp, 24
|
||||||
|
mov DWORD [ebp-4], 1
|
||||||
|
mov BYTE [ebp-5], 0
|
||||||
|
L2:
|
||||||
|
mov edx, DWORD [ebp+8]
|
||||||
|
mov eax, -858993459
|
||||||
|
mul edx
|
||||||
|
mov eax, edx
|
||||||
|
shr eax, 3
|
||||||
|
cmp eax, DWORD [ebp-4]
|
||||||
|
jae L4
|
||||||
|
jmp L3
|
||||||
|
L4:
|
||||||
|
mov eax, DWORD [ebp-4]
|
||||||
|
mov edx, eax
|
||||||
|
sal edx, 2
|
||||||
|
add edx, eax
|
||||||
|
lea eax, [edx+edx]
|
||||||
|
mov DWORD [ebp-4], eax
|
||||||
|
jmp L2
|
||||||
|
L3:
|
||||||
|
nop
|
||||||
|
L5:
|
||||||
|
cmp DWORD [ebp-4], 1
|
||||||
|
ja L7
|
||||||
|
jmp L6
|
||||||
|
L7:
|
||||||
|
mov edx, DWORD [ebp+8]
|
||||||
|
mov eax, edx
|
||||||
|
mov edx, 0
|
||||||
|
div DWORD [ebp-4]
|
||||||
|
mov DWORD [ebp-12], eax
|
||||||
|
mov al, BYTE [ebp-12]
|
||||||
|
mov BYTE [ebp-5], al
|
||||||
|
mov eax, 0
|
||||||
|
mov al, BYTE [ebp-5]
|
||||||
|
imul eax, DWORD [ebp-4]
|
||||||
|
sub DWORD [ebp+8], eax
|
||||||
|
mov edx, DWORD [ebp-4]
|
||||||
|
mov eax, -858993459
|
||||||
|
mul edx
|
||||||
|
mov eax, edx
|
||||||
|
shr eax, 3
|
||||||
|
mov DWORD [ebp-4], eax
|
||||||
|
lea eax, [ebp-5]
|
||||||
|
add BYTE [eax], 48
|
||||||
|
sub esp, 12
|
||||||
|
mov eax, 0
|
||||||
|
mov al, BYTE [ebp-5]
|
||||||
|
push eax
|
||||||
|
call _putc
|
||||||
|
add esp, 16
|
||||||
|
jmp L5
|
||||||
|
L6:
|
||||||
|
sub esp, 12
|
||||||
|
mov al, BYTE [ebp+8]
|
||||||
|
add eax, 48
|
||||||
|
and eax, 255
|
||||||
|
push eax
|
||||||
|
call _putc
|
||||||
|
add esp, 16
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[global _putDec]
|
||||||
|
_putDec:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
sub esp, 24
|
||||||
|
cmp DWORD [ebp+8], 0
|
||||||
|
jns L9
|
||||||
|
sub esp, 12
|
||||||
|
push 45
|
||||||
|
call _putc
|
||||||
|
add esp, 16
|
||||||
|
neg DWORD [ebp+8]
|
||||||
|
L9:
|
||||||
|
mov DWORD [ebp-4], 1
|
||||||
|
mov BYTE [ebp-5], 0
|
||||||
|
L10:
|
||||||
|
mov eax, DWORD [ebp+8]
|
||||||
|
cmp eax, DWORD [ebp-4]
|
||||||
|
jae L12
|
||||||
|
jmp L11
|
||||||
|
L12:
|
||||||
|
mov eax, DWORD [ebp-4]
|
||||||
|
mov edx, eax
|
||||||
|
sal edx, 2
|
||||||
|
add edx, eax
|
||||||
|
lea eax, [edx+edx]
|
||||||
|
mov DWORD [ebp-4], eax
|
||||||
|
jmp L10
|
||||||
|
L11:
|
||||||
|
mov edx, DWORD [ebp-4]
|
||||||
|
mov eax, -858993459
|
||||||
|
mul edx
|
||||||
|
mov eax, edx
|
||||||
|
shr eax, 3
|
||||||
|
mov DWORD [ebp-4], eax
|
||||||
|
L13:
|
||||||
|
cmp DWORD [ebp-4], 1
|
||||||
|
ja L15
|
||||||
|
jmp L14
|
||||||
|
L15:
|
||||||
|
mov edx, DWORD [ebp+8]
|
||||||
|
mov eax, edx
|
||||||
|
mov edx, 0
|
||||||
|
div DWORD [ebp-4]
|
||||||
|
mov DWORD [ebp-12], eax
|
||||||
|
mov al, BYTE [ebp-12]
|
||||||
|
mov BYTE [ebp-5], al
|
||||||
|
mov eax, 0
|
||||||
|
mov al, BYTE [ebp-5]
|
||||||
|
imul eax, DWORD [ebp-4]
|
||||||
|
sub DWORD [ebp+8], eax
|
||||||
|
mov edx, DWORD [ebp-4]
|
||||||
|
mov eax, -858993459
|
||||||
|
mul edx
|
||||||
|
mov eax, edx
|
||||||
|
shr eax, 3
|
||||||
|
mov DWORD [ebp-4], eax
|
||||||
|
lea eax, [ebp-5]
|
||||||
|
add BYTE [eax], 48
|
||||||
|
sub esp, 12
|
||||||
|
mov eax, 0
|
||||||
|
mov al, BYTE [ebp-5]
|
||||||
|
push eax
|
||||||
|
call _putc
|
||||||
|
add esp, 16
|
||||||
|
jmp L13
|
||||||
|
L14:
|
||||||
|
sub esp, 12
|
||||||
|
mov al, BYTE [ebp+8]
|
||||||
|
add eax, 48
|
||||||
|
and eax, 255
|
||||||
|
push eax
|
||||||
|
call _putc
|
||||||
|
add esp, 16
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
echo Backing up to .\Backup\%1
|
echo Backing up to .\Backup\%1
|
||||||
|
|
||||||
mkdir .\Backup\%1
|
mkdir .\Backup\%1
|
||||||
mkdir .\Backup\%1\lib
|
|
||||||
|
|
||||||
copy *.h .\Backup\%1
|
copy *.h .\Backup\%1
|
||||||
copy *.c .\Backup\%1
|
copy *.c .\Backup\%1
|
||||||
@@ -11,9 +10,3 @@ copy *.asm .\Backup\%1
|
|||||||
copy *.ld .\Backup\%1
|
copy *.ld .\Backup\%1
|
||||||
copy *.bat .\Backup\%1
|
copy *.bat .\Backup\%1
|
||||||
|
|
||||||
copy .\lib\*.h .\Backup\%1\lib
|
|
||||||
copy .\lib\*.c .\Backup\%1\lib
|
|
||||||
copy .\lib\*.inc .\Backup\%1\lib
|
|
||||||
copy .\lib\*.asm .\Backup\%1\lib
|
|
||||||
copy .\lib\*.ld .\Backup\%1\lib
|
|
||||||
copy .\lib\*.bat .\Backup\%1\lib
|
|
||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
%define VERSION "0.12" ;HOS version
|
%define VERSION "0.13" ;HOS version
|
||||||
|
|
||||||
%define BOOT_FAT_SEG 0x07E0 ;right after boot sector
|
%define BOOT_FAT_SEG 0x07E0 ;right after boot sector
|
||||||
%define BOOT_ROOT_SEG 0x0900 ;right after FAT
|
%define BOOT_ROOT_SEG 0x0900 ;right after FAT
|
||||||
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
|
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
|
||||||
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
|
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
|
||||||
%define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at
|
%define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at
|
||||||
%define BOOT_KERNEL_ADD 0x104000 ;final pmode kernel destination - physical
|
%define BOOT_KERNEL_ADD 0x106000 ;final pmode kernel destination - physical
|
||||||
%define BOOT_RD_ADD 0x200000 ;2mb for ram disk
|
%define BOOT_RD_ADD 0x200000 ;2mb for ram disk
|
||||||
|
|
||||||
%define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
|
%define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
|
||||||
|
|||||||
@@ -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 void eoi2();
|
||||||
inline dword kernel_size();
|
inline dword kernel_size();
|
||||||
inline void init_timer();
|
inline void init_timer();
|
||||||
//inline void invlpg();
|
char *strcat(char *dest, char *src);
|
||||||
|
void rtrim(char *str);
|
||||||
|
char *ucase(char *str);
|
||||||
|
char *lcase(char *str);
|
||||||
|
inline byte bcd2byte(byte bcd);
|
||||||
|
inline byte byte2bcd(byte bite);
|
||||||
|
byte rtc_readDay();
|
||||||
|
byte rtc_readMonth();
|
||||||
|
byte rtc_readYear();
|
||||||
|
byte rtc_readSecond();
|
||||||
|
byte rtc_readMinute();
|
||||||
|
byte rtc_readHour();
|
||||||
|
void rtc_setDay(byte dat);
|
||||||
|
void rtc_setMonth(byte month);
|
||||||
|
void rtc_setYear(byte year);
|
||||||
|
void rtc_setSecond(byte second);
|
||||||
|
void rtc_setMinute(byte minute);
|
||||||
|
void rtc_setHour(byte hour);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
gcc -S kernel.c -masm=intel -fno-builtin
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
gdtr:
|
gdtr:
|
||||||
dw gdt_end-gdt-1
|
dw gdt_end-gdt-1
|
||||||
dd GDT
|
dd GDT_P
|
||||||
gdt:
|
gdt:
|
||||||
dd 0
|
dd 0
|
||||||
dd 0
|
dd 0
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
|
|
||||||
idtr:
|
idtr:
|
||||||
dw 50*8-1 ;size of idt
|
dw 50*8-1 ;size of idt
|
||||||
dd IDT ;address of idt
|
dd IDT_V ;address of idt
|
||||||
|
|
||||||
|
|
||||||
%macro isr_label 1
|
%macro isr_label 1
|
||||||
isr_%1:
|
isr_%1:
|
||||||
|
push eax
|
||||||
mov eax, %1
|
mov eax, %1
|
||||||
jmp isr_main
|
jmp isr_main
|
||||||
%endmacro
|
%endmacro
|
||||||
@@ -66,6 +67,9 @@ isr_label 48
|
|||||||
isr_label 49
|
isr_label 49
|
||||||
|
|
||||||
isr_main:
|
isr_main:
|
||||||
|
cmp eax, 0x30
|
||||||
|
jz isr_syscall
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
push ds
|
push ds
|
||||||
push es
|
push es
|
||||||
@@ -79,10 +83,27 @@ isr_main:
|
|||||||
pop es
|
pop es
|
||||||
pop ds
|
pop ds
|
||||||
popa
|
popa
|
||||||
|
pop eax
|
||||||
|
|
||||||
iret
|
iret
|
||||||
|
|
||||||
|
|
||||||
|
isr_syscall:
|
||||||
|
pop eax ;syscall function number
|
||||||
|
pusha
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
call _putc
|
||||||
|
add esp, 4
|
||||||
|
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
popa
|
||||||
|
iret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@
|
|||||||
#define YELLOW_TXT 0x0E
|
#define YELLOW_TXT 0x0E
|
||||||
#define BRWHITE_TXT 0x0F
|
#define BRWHITE_TXT 0x0F
|
||||||
|
|
||||||
#define FREERAM_START 0x268000
|
#define FREERAM_START 0x368000 // 0x368000 is first available byte (this is right after the initrd @ 2mb, 1440kb.
|
||||||
#define MAX_RAM 0x40000000 //1gb maximum RAM supported
|
#define MAX_RAM 0x40000000 //1gb maximum RAM supported
|
||||||
|
|
||||||
#define PID_KERNEL 0x02 //kernel's PID
|
#define PID_KERNEL 0x02 //kernel's PID
|
||||||
|
|||||||
+42
-8
@@ -2,21 +2,55 @@
|
|||||||
;Author: Josh Holtrop
|
;Author: Josh Holtrop
|
||||||
;Modified: 10/30/03
|
;Modified: 10/30/03
|
||||||
|
|
||||||
%include "bootdef.inc"
|
%define GDT_P 0x100000; ;1mb physical - Global Descriptor Table space
|
||||||
|
%define GDT_V GDT_P+0xC0000000
|
||||||
%define GDT 0x100000
|
%define IDT_P 0x102000 ;1mb+8kb - Interrupt Descriptor Table space
|
||||||
%define IDT 0x102000
|
%define IDT_V IDT_P+0xC0000000
|
||||||
|
%define PDBR_P 0x104000 ;1mb+16kb - Page Directory Base Register (first PD)
|
||||||
|
%define PDBR_V PDBR_P+0xC0000000
|
||||||
|
%define LOPT_P 0x105000 ;1mb+20kb - LOw Page Table for mapping first 4mb
|
||||||
|
%define LOPT_V LOPT_P+0xC0000000
|
||||||
|
%define KERNEL_P 0x106000 ;1mb+24kb - the kernel's physical address
|
||||||
|
%define KERNEL_V KERNEL_P+0xC0000000 ;3gb+1mb+24kb, the virtual address of the kernel
|
||||||
|
|
||||||
[global start]
|
[global start]
|
||||||
[extern _isr]
|
[extern _isr]
|
||||||
[extern _k_init]
|
[extern _k_init]
|
||||||
|
[extern _putc]
|
||||||
|
|
||||||
bits 32
|
bits 32
|
||||||
|
|
||||||
;This is where the kernel begins execution
|
;This is where the kernel begins execution
|
||||||
|
;At this point, the temporary gdt is set up to "map" 0xC000_0000 to 0x0.
|
||||||
|
;We must enable paging with the first 4mb mapped 1:1 virtual:physical
|
||||||
|
; and with the 4mb starting at 0xC000_0000 mapped to the first 4mb physical.
|
||||||
|
;Then we can start using our "real" gdt, then unmap the lower 4mb.
|
||||||
start:
|
start:
|
||||||
cli ;if they weren't already off
|
cli ;if they weren't already off
|
||||||
mov edi, GDT
|
|
||||||
|
xor eax, eax
|
||||||
|
mov edi, PDBR_V
|
||||||
|
mov ecx, 1024 ;clear the PDBR
|
||||||
|
rep stosd
|
||||||
|
mov [PDBR_V], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
||||||
|
mov [PDBR_V+0xC00], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
||||||
|
|
||||||
|
mov edi, LOPT_V
|
||||||
|
mov ecx, 1024
|
||||||
|
mov eax, 0x03 ;starting physical address = 0x0 (read/write, present flags)
|
||||||
|
fill_lopt_loop: ;fill the page table
|
||||||
|
stosd
|
||||||
|
add eax, 4096 ;increment next phsyical address by 4kb
|
||||||
|
loop fill_lopt_loop
|
||||||
|
|
||||||
|
mov eax, PDBR_P
|
||||||
|
mov cr3, eax ;store the Page Directory Base Address
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 0x80000000 ;set page enable bit
|
||||||
|
mov cr0, eax ;now paging is active!
|
||||||
|
|
||||||
|
|
||||||
|
mov edi, GDT_V
|
||||||
mov esi, gdt
|
mov esi, gdt
|
||||||
mov ecx, gdt_end-gdt
|
mov ecx, gdt_end-gdt
|
||||||
copy_gdt:
|
copy_gdt:
|
||||||
@@ -24,7 +58,7 @@ copy_gdt:
|
|||||||
stosb
|
stosb
|
||||||
loop copy_gdt
|
loop copy_gdt
|
||||||
|
|
||||||
mov edi, IDT ;destination
|
mov edi, IDT_V ;destination
|
||||||
mov esi, isr_0 ;address of isr0
|
mov esi, isr_0 ;address of isr0
|
||||||
mov edx, isr_1-isr_0 ;distance between isr labels
|
mov edx, isr_1-isr_0 ;distance between isr labels
|
||||||
mov ecx, 50 ;number of isrlabels
|
mov ecx, 50 ;number of isrlabels
|
||||||
@@ -42,7 +76,7 @@ fill_idt:
|
|||||||
mov esi, ebx
|
mov esi, ebx
|
||||||
add esi, edx
|
add esi, edx
|
||||||
loop fill_idt
|
loop fill_idt
|
||||||
mov word [IDT+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
|
mov word [IDT_V+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
|
||||||
|
|
||||||
lgdt [gdtr] ;load gdt
|
lgdt [gdtr] ;load gdt
|
||||||
jmp KERNEL_CODE:newgdtcontinue
|
jmp KERNEL_CODE:newgdtcontinue
|
||||||
@@ -53,7 +87,7 @@ newgdtcontinue:
|
|||||||
mov gs, ax
|
mov gs, ax
|
||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov esp, 0x1ffffc ;stack just under 2mb, moves downward
|
mov esp, 0xc01ffffc ;stack just under 3gb+2mb, moves downward
|
||||||
lidt [idtr] ;load idt
|
lidt [idtr] ;load idt
|
||||||
|
|
||||||
call _k_init
|
call _k_init
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
//08/13/03 Josh Holtrop
|
//08/13/03 Josh Holtrop
|
||||||
//Holtrop's Operating System
|
//Holtrop's Operating System
|
||||||
//Version: 0.12
|
//Version: 0.12
|
||||||
//Modified: 11/12/03
|
//Modified: 12/30/03
|
||||||
|
|
||||||
#include "k_defines.h" //#DEFINE's for kernel
|
#include "k_defines.h" //#DEFINE's for kernel
|
||||||
|
|
||||||
#include "lib/string.h" //library string functions
|
|
||||||
#include "lib/io.h" //library input/output functions
|
|
||||||
|
|
||||||
#include "functions.h" //general functions
|
#include "functions.h" //general functions
|
||||||
#include "video.h" //video functions
|
#include "video.h" //video functions
|
||||||
@@ -17,14 +15,35 @@
|
|||||||
#include "mouse.h" //generic ps/2 mouse driver & functions
|
#include "mouse.h" //generic ps/2 mouse driver & functions
|
||||||
#include "fdc.h" //Floppy Disk Controller functions
|
#include "fdc.h" //Floppy Disk Controller functions
|
||||||
#include "stdfont.h" //Standard font bitmask array
|
#include "stdfont.h" //Standard font bitmask array
|
||||||
|
#include "kio.h"
|
||||||
|
#include "vfs.h"
|
||||||
|
#include "rd.h"
|
||||||
|
#include "fat12.h"
|
||||||
|
|
||||||
void isr(dword num);
|
void isr(dword num);
|
||||||
void k_init();
|
void k_init();
|
||||||
|
|
||||||
|
/* These functions are defined in asmfuncs.asm */
|
||||||
extern dword write_cr0(dword cr0);
|
extern dword write_cr0(dword cr0);
|
||||||
extern dword read_cr0();
|
extern dword read_cr0();
|
||||||
extern dword write_cr3(dword cr3);
|
extern dword write_cr3(dword cr3);
|
||||||
|
extern dword read_cr2();
|
||||||
extern dword read_cr3();
|
extern dword read_cr3();
|
||||||
|
extern void writeCursorPosition(dword pos);
|
||||||
|
extern dword getCursorPosition();
|
||||||
|
extern void console_scroll();
|
||||||
|
extern void console_cls();
|
||||||
|
extern int puts(char *str);
|
||||||
|
extern int putDec(int number);
|
||||||
|
extern int putDecu(dword number);
|
||||||
|
extern void strcpy(char *dest, char *src);
|
||||||
|
extern void memcpy(void *dest, void *src, dword n);
|
||||||
|
extern dword strlen(char *str);
|
||||||
|
|
||||||
|
#include "fat12.c"
|
||||||
|
#include "rd.c"
|
||||||
|
#include "vfs.c"
|
||||||
|
#include "kio.c"
|
||||||
#include "fdc.c"
|
#include "fdc.c"
|
||||||
#include "mouse.c"
|
#include "mouse.c"
|
||||||
#include "keyboard.c"
|
#include "keyboard.c"
|
||||||
@@ -34,7 +53,6 @@ extern dword read_cr3();
|
|||||||
#include "video.c"
|
#include "video.c"
|
||||||
|
|
||||||
dword timer = 0;
|
dword timer = 0;
|
||||||
dword *videoMode;
|
|
||||||
|
|
||||||
//Main kernel initialization method
|
//Main kernel initialization method
|
||||||
void k_init()
|
void k_init()
|
||||||
@@ -42,39 +60,46 @@ void k_init()
|
|||||||
// ===== Initialization
|
// ===== Initialization
|
||||||
fdc_sendDOR(0x0C); //turn off floppy motor!!
|
fdc_sendDOR(0x0C); //turn off floppy motor!!
|
||||||
console_cls();
|
console_cls();
|
||||||
|
video_init();
|
||||||
|
mm_init();
|
||||||
|
vmm_init();
|
||||||
remap_pics(0x20, 0x28);
|
remap_pics(0x20, 0x28);
|
||||||
init_timer();
|
init_timer();
|
||||||
mm_init();
|
|
||||||
videoMode = (dword *)0x90002;
|
|
||||||
if (*videoMode)
|
|
||||||
video_init((ModeInfoBlock *) 0x90306);
|
|
||||||
vmm_init();
|
|
||||||
mouse_init();
|
mouse_init();
|
||||||
vmm_enable_paging();
|
|
||||||
pic1_mask(0); //unmask IRQ's 0-7
|
pic1_mask(0); //unmask IRQ's 0-7
|
||||||
pic2_mask(0); //unmask IRQ's 8-15
|
pic2_mask(0); //unmask IRQ's 8-15
|
||||||
|
vfs_init();
|
||||||
enable_ints();
|
enable_ints();
|
||||||
kbd_resetLEDs(); //after enabling interrupts!!
|
kbd_resetLEDs(); //after enabling interrupts!!
|
||||||
|
if (videoMode)
|
||||||
char *bmpptr = (char *)0x108000+54;
|
|
||||||
int a = 0;
|
|
||||||
int x = 0;
|
|
||||||
int y = 479;
|
|
||||||
for (a=0; a < 640*480; a++)
|
|
||||||
{
|
{
|
||||||
video_pset(x, y, *(dword *)bmpptr);
|
int p = video_mode.XResolution*video_mode.YResolution-1;
|
||||||
bmpptr += 3;
|
for (; p >= 0; p--)
|
||||||
x++;
|
video_psetp(p, 0x00000044);
|
||||||
if (x == 640)
|
video_drawConsole();
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("HOS 0.12 - Kernel Size: %d kb\n", kernel_size()/1024);
|
printf("HOS 0.13 - Kernel File Size: %u kb\tData Size: %u bytes\n", kernel_size()>>10, (dword)(&_end)-(dword)(&_code));
|
||||||
printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem);
|
printf("Memory available to OS: %u MB (%u bytes)\n", mm_megabytes, mm_totalmem);
|
||||||
printf("Free memory: %d bytes\n", mm_freemem());
|
printf("Free memory: %u bytes (%u pages)\n", mm_freemem(), mm_freemem()>>12);
|
||||||
|
printf("%d/%d/%d\t%d:%d:%d\n", rtc_readMonth(), rtc_readDay(), rtc_readYear(), rtc_readHour(), rtc_readMinute(), rtc_readSecond());
|
||||||
|
printf("Root Directory: %s/\n", rootDevice->id);
|
||||||
|
|
||||||
|
|
||||||
|
/* int a;
|
||||||
|
byte *addr = 0;
|
||||||
|
for (a = 0; a < 5; a++)
|
||||||
|
{
|
||||||
|
byte *app = mm_palloc();
|
||||||
|
vmm_map1((dword)addr, (dword)app);
|
||||||
|
addr += 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = vfs_readFile("/bin/hash.hos");
|
||||||
|
memcpy(0, addr, 4192);
|
||||||
|
asm("call 0");
|
||||||
|
free(addr);
|
||||||
|
*/
|
||||||
|
|
||||||
dword key = 0;
|
dword key = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -90,9 +115,13 @@ void isr(dword num)
|
|||||||
{
|
{
|
||||||
switch(num)
|
switch(num)
|
||||||
{
|
{
|
||||||
|
case 14:
|
||||||
|
printf("Page fault, CR2 = 0x%x\n", read_cr2());
|
||||||
|
halt();
|
||||||
|
break;
|
||||||
case 0x20: // IRQ0 - timer interrupt
|
case 0x20: // IRQ0 - timer interrupt
|
||||||
timer++;
|
timer++;
|
||||||
(*(byte *)(0xb8000))++;
|
(*(byte *)(0xc00b8000))++;
|
||||||
eoi();
|
eoi();
|
||||||
break;
|
break;
|
||||||
case 0x21: // IRQ1 - keyboard interrupt
|
case 0x21: // IRQ1 - keyboard interrupt
|
||||||
@@ -104,6 +133,7 @@ void isr(dword num)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Interrupt %d (0x%x) Unhandled!!\n", num, num);
|
printf("Interrupt %d (0x%x) Unhandled!!\n", num, num);
|
||||||
|
halt();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
ENTRY(start)
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
.text 0x104000 : {
|
.text 0xC0106000 : {
|
||||||
code = .; _code = .; __code = .;
|
code = .; _code = .; __code = .;
|
||||||
*(.text)
|
*(.text)
|
||||||
. = ALIGN(4096);
|
. = ALIGN(4096);
|
||||||
|
|||||||
@@ -1,273 +1,112 @@
|
|||||||
// mm.c
|
// mm.c
|
||||||
// 09/01/03 Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
|
// Created: 09/01/03
|
||||||
|
// Modified: 12/28/03
|
||||||
|
|
||||||
// 0x368000 is first available byte (this is right after the kernel @ 1mb and the initrd @ 2mb, 1440kb.
|
|
||||||
|
|
||||||
|
|
||||||
//Pointer to the first pageblock in the linked list
|
|
||||||
pageblock *first_pageblock = (pageblock *) 0;
|
|
||||||
//The total amount of physical memory available (bytes)
|
//The total amount of physical memory available (bytes)
|
||||||
dword mm_totalmem = 0x100000; //start counting from 1mb
|
#define BITMAP_SIZE 0x20000
|
||||||
//The highest physical address
|
dword mm_totalmem = 0;
|
||||||
dword mm_highestAddress = 0;
|
dword mm_megabytes;
|
||||||
|
byte page_bitmap[BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available
|
||||||
|
//0x20000*(8 bits/byte)=0x100000 pages in 4gb total
|
||||||
|
|
||||||
//This function initializes the memory manager's linked list, filling it with the
|
//This function initializes the memory manager's linked list, filling it with the
|
||||||
// memory areas returned by bios interrupt 0x8E20
|
// memory areas returned by bios interrupt 0x8E20
|
||||||
void mm_init()
|
void mm_init()
|
||||||
{
|
{
|
||||||
dword *memmap_entries = (dword *) 0x9040A;
|
dword memmap_entries = *(dword *)0xC009040A;
|
||||||
memmap_entry *maps = (memmap_entry *) 0x92000;
|
memmap_entry *maps = (memmap_entry *) 0xC0092000;
|
||||||
dword a;
|
dword a;
|
||||||
for (a=0;a<(*memmap_entries);a++)
|
for (a = 0; a < BITMAP_SIZE; a++)
|
||||||
|
{
|
||||||
|
page_bitmap[a] = 0xFF; //all pages used
|
||||||
|
}
|
||||||
|
for (a = 0; a < memmap_entries; a++)
|
||||||
{
|
{
|
||||||
if (maps[a].attributes == 1) // (1) mem free to OS
|
if (maps[a].attributes == 1) // (1) mem free to OS
|
||||||
{
|
{
|
||||||
mm_totalmem += maps[a].limit.lowdword;
|
mm_totalmem += maps[a].limit.lowdword;
|
||||||
if (mm_highestAddress < (maps[a].base.lowdword + maps[a].limit.lowdword))
|
if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram
|
||||||
mm_highestAddress = maps[a].base.lowdword + maps[a].limit.lowdword;
|
|
||||||
if ((maps[a].base.lowdword + maps[a].limit.lowdword) > (FREERAM_START+8192)) //goes past where we start freeram
|
|
||||||
{
|
{
|
||||||
if (maps[a].base.lowdword < FREERAM_START)
|
if (maps[a].base.lowdword < FREERAM_START)
|
||||||
{
|
{
|
||||||
maps[a].limit.lowdword = maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword);
|
mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
|
||||||
maps[a].base.lowdword = FREERAM_START; //block at least 4kb, starts >= FREERAM_START
|
|
||||||
}
|
}
|
||||||
if (first_pageblock == 0) //no pageblock page set up yet, so set it up here
|
|
||||||
{
|
|
||||||
first_pageblock = (pageblock *) maps[a].base.lowdword;
|
|
||||||
maps[a].base.lowdword += 4096;
|
|
||||||
maps[a].limit.lowdword -= 4096;
|
|
||||||
mm_init_pageblockpage(first_pageblock);
|
|
||||||
first_pageblock->base = maps[a].base.lowdword;
|
|
||||||
first_pageblock->length = maps[a].limit.lowdword / 4096;
|
|
||||||
first_pageblock->pid = MM_PB_AVAIL;
|
|
||||||
}
|
|
||||||
else //first_pageblock already set up, add on segment
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->pid == MM_PB_NP)
|
|
||||||
break;
|
|
||||||
else
|
else
|
||||||
pb++;
|
|
||||||
}
|
|
||||||
pb->base = maps[a].base.lowdword;
|
|
||||||
pb->length = maps[a].limit.lowdword / 4096;
|
|
||||||
pb->pid = MM_PB_AVAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (first_pageblock == 0)
|
|
||||||
{
|
{
|
||||||
printf("ERROR! NO INITIAL PAGE BLOCK CREATED.");
|
mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
|
||||||
asm("cli");
|
|
||||||
asm("hlt");
|
|
||||||
for (;;)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mm_totalmem % 0x100000)
|
||||||
//This function initializes a pageblock to be full of empty pointers
|
mm_megabytes = (mm_totalmem >> 20) + 1;
|
||||||
void mm_init_pageblockpage(pageblock *pbp)
|
|
||||||
{
|
|
||||||
int a;
|
|
||||||
for (a=0; a<256; a++) // 256 pageblock entries * 16 bytes per page block entry = 4096 bytes (1 page of pageblock entries)
|
|
||||||
{
|
|
||||||
pbp[a].base = 0;
|
|
||||||
pbp[a].length = 0;
|
|
||||||
pbp[a].pid = MM_PB_NP;
|
|
||||||
if (a<255)
|
|
||||||
pbp[a].link = (dword)(&pbp[a+1]);
|
|
||||||
else
|
else
|
||||||
pbp[a].link = 0;
|
mm_megabytes = mm_totalmem >> 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function frees a certain number of pages starting at the address
|
||||||
|
// specified in base for a length of pages pages
|
||||||
|
void mm_pfreen(dword base, dword pages)
|
||||||
|
{
|
||||||
|
dword a;
|
||||||
|
dword max = base + (pages << 12);
|
||||||
|
for (a = base; a < max; a += 4096)
|
||||||
|
{
|
||||||
|
mm_pfree(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//This function allocates a certain number of physical pages for a particular process
|
// This function frees a single page
|
||||||
//Returns:
|
void mm_pfree(dword base)
|
||||||
// 0 - no free mem, invalied PID
|
|
||||||
// void* - physical address of allocated pages
|
|
||||||
void *mm_palloc(dword numpages, dword proc_pid)
|
|
||||||
{
|
{
|
||||||
if (proc_pid < PID_KERNEL)
|
// dword pageNumber = base >> 12; // >>12 == /4096
|
||||||
return 0;
|
dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
|
||||||
pageblock *pb = first_pageblock;
|
dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
|
||||||
if (mm_freeentries() < 2)
|
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
|
||||||
{
|
|
||||||
if(mm_new_pageblock_page() == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pageblock *newentry = mm_nextpageblockentry();
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if ((pb->pid == MM_PB_AVAIL) && (pb->length >= numpages))
|
|
||||||
break;
|
|
||||||
if (pb->link == 0)
|
|
||||||
return 0;
|
|
||||||
pb = (pageblock *)pb->link;
|
|
||||||
}
|
|
||||||
if (pb->length == numpages) //dont need a new entry, just mark this one as used :)
|
|
||||||
{
|
|
||||||
pb->pid = proc_pid;
|
|
||||||
return (void *)pb->base;
|
|
||||||
}
|
|
||||||
else //subtract out allocated number of pages from length
|
|
||||||
{
|
|
||||||
newentry->base = pb->base;
|
|
||||||
newentry->length = numpages;
|
|
||||||
newentry->pid = proc_pid;
|
|
||||||
pb->base += (numpages * 4096);
|
|
||||||
pb->length -= numpages;
|
|
||||||
return (void *)newentry->base;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//This method returns the number of free pageblock entries at the end of the linked list
|
// This function allocates a single page, returning its physical address
|
||||||
dword mm_freeentries()
|
void *mm_palloc()
|
||||||
{
|
{
|
||||||
pageblock *pb = first_pageblock;
|
dword bite;
|
||||||
dword counter = 0;
|
for (bite = 0; bite < BITMAP_SIZE; bite++)
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
if (pb->pid == MM_PB_NP)
|
if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
|
||||||
counter++;
|
{
|
||||||
if (pb->link == 0)
|
int bit;
|
||||||
return counter;
|
for (bit = 0; bit < 8; bit++)
|
||||||
pb = (pageblock *) pb->link;
|
{
|
||||||
|
if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
|
||||||
|
{
|
||||||
|
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
|
||||||
|
return (void *)((bite << 15) | (bit << 12));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; //no free page
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//This method creates a new page used to hold more pageblock entries at the end of the linked list
|
// This function reports the number of bytes of free physical memory
|
||||||
//Returns:
|
|
||||||
// 0 - no free pages
|
|
||||||
// pageblock* - address of pageblock page
|
|
||||||
pageblock *mm_new_pageblock_page() //as of 09/26/03 this method leaks 4kb main memory per call, unrecoverable
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if ((pb->pid == MM_PB_AVAIL) && (pb->length > 1))
|
|
||||||
{
|
|
||||||
pageblock *retval = (pageblock *)pb->base;
|
|
||||||
pb->base += 4096;
|
|
||||||
pb->length--;
|
|
||||||
mm_init_pageblockpage(retval); //zeros out, links new pageblock page
|
|
||||||
mm_lastpageblockentry()->link = (dword)retval; //set up link to new pageblock page
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
pb = (pageblock *) pb->link;
|
|
||||||
if (pb == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//This method frees a physical page
|
|
||||||
//Returns:
|
|
||||||
// 2 - pointer to free was a null pointer
|
|
||||||
// 1 - address not found
|
|
||||||
// 0 - all went well
|
|
||||||
int mm_pfree(void *ptr)
|
|
||||||
{
|
|
||||||
if (ptr == 0)
|
|
||||||
return 2;
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
dword tofree = (dword) ptr;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->base == tofree) // && (pb->pid == MM_PB_USED))
|
|
||||||
{
|
|
||||||
pb->pid = MM_PB_AVAIL; //found block, mark available / coalesce it
|
|
||||||
mm_coalesce(pb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (pb->link == 0)
|
|
||||||
return 1;
|
|
||||||
pb = (pageblock *) pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//This method returns a pointer to the last pageblock in the linked list
|
|
||||||
pageblock *mm_lastpageblockentry()
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->link == 0)
|
|
||||||
return pb;
|
|
||||||
pb = (pageblock *)pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//This method returns the next available-for-use pageblock entry
|
|
||||||
// or 0, if they are all used
|
|
||||||
pageblock *mm_nextpageblockentry()
|
|
||||||
{
|
|
||||||
pageblock *pb = first_pageblock;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pb->pid == MM_PB_NP)
|
|
||||||
return pb;
|
|
||||||
if (pb->link == 0)
|
|
||||||
return 0;
|
|
||||||
pb = (pageblock *)pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//This method returns the amount of free physical RAM
|
|
||||||
dword mm_freemem()
|
dword mm_freemem()
|
||||||
{
|
{
|
||||||
dword amount = 0;
|
dword a;
|
||||||
pageblock *pb = first_pageblock;
|
dword pages = 0;
|
||||||
for (;;)
|
for (a = 0; a < BITMAP_SIZE; a++)
|
||||||
{
|
{
|
||||||
if (pb->pid == MM_PB_AVAIL)
|
int bit;
|
||||||
amount += (pb->length)*4096;
|
for (bit = 0; bit < 8; bit++)
|
||||||
if (pb->link == 0)
|
|
||||||
return amount;
|
|
||||||
pb = (pageblock *) pb->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//This method "walks" through the linked list of pageblock entries and
|
|
||||||
// combines any two entries that are adjacent and of the same type
|
|
||||||
void mm_coalesce(pageblock *pb)
|
|
||||||
{
|
{
|
||||||
pageblock *pbc = first_pageblock;
|
if (!(page_bitmap[a] & (1 << bit)))
|
||||||
for (;;)
|
pages++;
|
||||||
{
|
|
||||||
if (pbc->pid == pb->pid) //pid fields must match, both same process, both avail, or both not present
|
|
||||||
{
|
|
||||||
if ((pbc->base + (pbc->length * 4096)) == pb->base) //pbc ends where pb starts
|
|
||||||
{
|
|
||||||
pbc->length += pb->length;
|
|
||||||
pb->pid = MM_PB_NP;
|
|
||||||
mm_coalesce(pbc); //recursion: checks for any more page blocks to coalesce if one found
|
|
||||||
return; //exit this recursion...
|
|
||||||
}
|
|
||||||
if ((pb->base + (pb->length * 4096)) == pbc->base) //pb ends where pbc starts
|
|
||||||
{
|
|
||||||
pb->length += pbc->length;
|
|
||||||
pbc->pid = MM_PB_NP;
|
|
||||||
mm_coalesce(pb);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pbc->link == 0)
|
return pages << 12;
|
||||||
return;
|
|
||||||
pbc = (pageblock *)pbc->link;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,28 +7,14 @@ typedef struct {
|
|||||||
} __attribute__((packed)) memmap_entry;
|
} __attribute__((packed)) memmap_entry;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
dword base;
|
|
||||||
dword length; //in pages
|
|
||||||
dword pid; //normally PID of process, use NP, AVAIL for special flags
|
|
||||||
dword link; //leave dword instead of pointer so i dont have to worry about pointer arithmetic
|
|
||||||
} __attribute__ ((packed)) pageblock; //16 byte pageblock entry - 256 entries = 1 page
|
|
||||||
|
|
||||||
|
|
||||||
void mm_init();
|
void mm_init();
|
||||||
void mm_init_pageblockpage(pageblock *pbp);
|
void mm_pfreen(dword base, dword pages);
|
||||||
void *mm_palloc(dword numpages, dword proc_pid);
|
void mm_pfree(dword base);
|
||||||
void mm_coalesce(pageblock *pb);
|
void *mm_palloc();
|
||||||
int mm_pfree(void *ptr);
|
|
||||||
dword mm_freeentries();
|
|
||||||
dword mm_freemem();
|
dword mm_freemem();
|
||||||
pageblock *mm_new_pageblock_page();
|
|
||||||
pageblock *mm_lastpageblockentry();
|
|
||||||
pageblock *mm_nextpageblockentry();
|
|
||||||
|
|
||||||
|
|
||||||
#define MM_PB_NP 0x00 //00000000
|
|
||||||
#define MM_PB_AVAIL 0x01 //00000001
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ void mouse_init()
|
|||||||
void isr_mouse()
|
void isr_mouse()
|
||||||
{
|
{
|
||||||
byte inb = inportb(0x60); //read mouse byte
|
byte inb = inportb(0x60); //read mouse byte
|
||||||
//printf("InB: %x\n", inb);
|
|
||||||
//return;
|
|
||||||
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
|
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
|
||||||
return;
|
return;
|
||||||
mouse_inbuffer[mouse_bytesRead] = inb;
|
mouse_inbuffer[mouse_bytesRead] = inb;
|
||||||
@@ -50,15 +48,9 @@ void isr_mouse()
|
|||||||
if (mouse_y >= video_mode.YResolution)
|
if (mouse_y >= video_mode.YResolution)
|
||||||
mouse_y = video_mode.YResolution - 1;
|
mouse_y = video_mode.YResolution - 1;
|
||||||
if (mouse_inbuffer[0] & 0x01) //left button
|
if (mouse_inbuffer[0] & 0x01) //left button
|
||||||
{
|
|
||||||
video_pset(mouse_x, mouse_y, 0x00FF8800);
|
video_pset(mouse_x, mouse_y, 0x00FF8800);
|
||||||
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
video_pset(mouse_x, mouse_y, 0x00FFFFFF);
|
video_pset(mouse_x, mouse_y, 0x00FFFFFF);
|
||||||
printf("X: %d, Y: %d\n", mouse_x, mouse_y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 |
+65
-15
@@ -148,29 +148,43 @@ got_rd:
|
|||||||
mov [ds:BOOT_HASRD], al
|
mov [ds:BOOT_HASRD], al
|
||||||
pop ds ;ds=0
|
pop ds ;ds=0
|
||||||
cmp al, 0 ;dont load rd
|
cmp al, 0 ;dont load rd
|
||||||
jz no_rd
|
jnz yes_rd
|
||||||
|
jmp no_rd
|
||||||
|
yes_rd:
|
||||||
mov cx, 80
|
mov cx, 80
|
||||||
mov edi, 0xb8000+160*4
|
mov edi, 0xb8000+160*4
|
||||||
filler_loop:
|
filler_loop: ;draw a red bar
|
||||||
mov word [ds:edi], 0x0400+177
|
mov word [ds:edi], 0x0400+177
|
||||||
inc edi
|
inc edi
|
||||||
inc edi
|
inc edi
|
||||||
loop filler_loop
|
loop filler_loop
|
||||||
|
|
||||||
mov cx, 80 ;80 cylinders to read
|
mov cx, 80 ;80 cylinders to read
|
||||||
xor si, si
|
xor si, si ;start at cylinder 0
|
||||||
mov edi, BOOT_RD_ADD ;ram disk address
|
mov edi, BOOT_RD_ADD ;ram disk address
|
||||||
read_cylinder:
|
read_cylinder:
|
||||||
push cx
|
push cx
|
||||||
mov bx, 0x0100
|
|
||||||
|
mov bx, 0x0100 ;read sectors from head 0
|
||||||
mov es, bx
|
mov es, bx
|
||||||
xor bx, bx
|
xor bx, bx ;es:bx = data buffer for read
|
||||||
mov ax, 0x0224
|
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
|
||||||
mov cx, si
|
mov cx, si ;what cyl. we are on is now in cx
|
||||||
mov ch, cl
|
mov ch, cl ;ch = cyl. number
|
||||||
mov cl, 1
|
mov cl, 1 ;cl = sector number 1-63
|
||||||
xor dx, dx
|
xor dx, dx ;dh = head number
|
||||||
mov dl, [gs:BOOT_DRIVE]
|
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov bx, 0x0100 ;now read sectors from head 1
|
||||||
|
mov es, bx
|
||||||
|
mov bx, 9216 ;es:bx = data buffer for read
|
||||||
|
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
|
||||||
|
mov cx, si ;what cyl. we are on is now in cx
|
||||||
|
mov ch, cl ;ch = cyl. number
|
||||||
|
mov cl, 1 ;cl = sector number 1-63
|
||||||
|
mov dh, 1 ;dh = head number
|
||||||
|
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
|
||||||
int 0x13
|
int 0x13
|
||||||
|
|
||||||
mov ebx, 0xb8000
|
mov ebx, 0xb8000
|
||||||
@@ -890,11 +904,43 @@ KERNEL_DATA equ $-gdt
|
|||||||
db 0x00
|
db 0x00
|
||||||
db 0x00
|
db 0x00
|
||||||
db 0x92
|
db 0x92
|
||||||
db 0xcf ;cf
|
db 0xcf
|
||||||
db 0x00
|
db 0x00
|
||||||
|
|
||||||
gdt_end:
|
gdt_end:
|
||||||
|
|
||||||
|
|
||||||
|
;-------------------------------------------------------
|
||||||
|
gdtr32:
|
||||||
|
dw gdt_end32-gdt32-1
|
||||||
|
dd gdt32
|
||||||
|
gdt32:
|
||||||
|
dd 0
|
||||||
|
dd 0
|
||||||
|
|
||||||
|
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
|
||||||
|
KERNEL_CODE32 equ $-gdt32
|
||||||
|
db 0xff ;limit 7:0
|
||||||
|
db 0xff ;limit 15:8
|
||||||
|
db 0x00 ;base 7:0
|
||||||
|
db 0x00 ;base 15:8
|
||||||
|
db 0x00 ;base 23:16
|
||||||
|
db 0x9a ;access
|
||||||
|
db 0xcf ;flags / limit 19:16
|
||||||
|
db 0x40 ;base 31:24
|
||||||
|
|
||||||
|
KERNEL_DATA32 equ $-gdt32
|
||||||
|
db 0xff ;segment 16 = 4gb data
|
||||||
|
db 0xff
|
||||||
|
db 0x00
|
||||||
|
db 0x00
|
||||||
|
db 0x00
|
||||||
|
db 0x92
|
||||||
|
db 0xcf
|
||||||
|
db 0x40
|
||||||
|
|
||||||
|
gdt_end32:
|
||||||
|
|
||||||
;------------------------------------------------------
|
;------------------------------------------------------
|
||||||
go_pm:
|
go_pm:
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
@@ -909,12 +955,16 @@ go_pm:
|
|||||||
|
|
||||||
bits 32
|
bits 32
|
||||||
pmode:
|
pmode:
|
||||||
mov ax, KERNEL_DATA
|
lgdt [gdtr32]
|
||||||
|
jmp KERNEL_CODE32:pmode_offsetted+0xC0000000
|
||||||
|
|
||||||
|
pmode_offsetted:
|
||||||
|
mov ax, KERNEL_DATA32
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
jmp KERNEL_CODE:BOOT_KERNEL_ADD
|
jmp KERNEL_CODE:BOOT_KERNEL_ADD+0xC0000000
|
||||||
|
|
||||||
kernel: db "KERNEL BIN", 0
|
kernel: db "KERNEL BIN", 0
|
||||||
|
|
||||||
|
|||||||
@@ -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,23 +4,25 @@
|
|||||||
|
|
||||||
|
|
||||||
//Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display
|
//Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display
|
||||||
void video_init(ModeInfoBlock *mib)
|
void video_init()
|
||||||
{
|
{
|
||||||
video_mode = *mib;
|
videoMode = *(word *)0xC0090002;
|
||||||
|
|
||||||
|
if (!videoMode) //we are in console mode
|
||||||
|
return;
|
||||||
|
|
||||||
|
video_mode = *(ModeInfoBlock *) 0xC0090306;
|
||||||
|
|
||||||
switch(video_mode.BitsPerPixel)
|
switch(video_mode.BitsPerPixel)
|
||||||
{
|
{
|
||||||
case 16:
|
case 16:
|
||||||
vid_ptr16 = (word *) video_mode.PhysBasePtr;
|
|
||||||
video_psetp = &video_psetp16;
|
video_psetp = &video_psetp16;
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
vid_ptr24 = (byte *) video_mode.PhysBasePtr;
|
|
||||||
video_psetp = &video_psetp24;
|
video_psetp = &video_psetp24;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
video_psetp = &video_psetp32;
|
video_psetp = &video_psetp32;
|
||||||
vid_ptr32 = (dword *) video_mode.PhysBasePtr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,5 +141,36 @@ void video_psetp32(int pixel, dword color)
|
|||||||
vid_ptr32[pixel] = color;
|
vid_ptr32[pixel] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Dummy function to not draw anything if there is no graphical mode enabled
|
||||||
|
void video_psetpnull(int pixel, dword color) {}
|
||||||
|
|
||||||
|
|
||||||
|
// This function draws a simple "console" window in graphical mode to display text
|
||||||
|
void video_drawConsole()
|
||||||
|
{
|
||||||
|
video_rectf(9, 9, 490, 260, 0);
|
||||||
|
video_rect(8, 8, 491, 261, 0x00777777);
|
||||||
|
int x, y;
|
||||||
|
for (x = 0; x < 80; x++)
|
||||||
|
{
|
||||||
|
for (y = 0; y < 25; y++)
|
||||||
|
{
|
||||||
|
video_renderChar(x*6+10, y*10+10, console_memory[y*80+x], 0x00FFFFFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function draws a "console" character to the graphical video screen
|
||||||
|
void video_drawConsoleChar(dword position)
|
||||||
|
{
|
||||||
|
int x = position % 80;
|
||||||
|
int y = position / 80;
|
||||||
|
video_renderChar(x*6+10, y*10+10, console_memory[y*80+x], 0x00FFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
//video.h
|
//video.h
|
||||||
// 08/18/03 Josh Holtrop
|
// 08/18/03 Josh Holtrop
|
||||||
// Modified: 11/12/03
|
// Modified: 12/28/03
|
||||||
|
|
||||||
void video_init();
|
void video_init();
|
||||||
void video_horiz(int y, int x1, int x2, dword color);
|
void video_horiz(int y, int x1, int x2, dword color);
|
||||||
@@ -11,7 +11,11 @@ inline void video_pset(int x, int y, dword color);
|
|||||||
void video_psetp16(int pixel, dword color);
|
void video_psetp16(int pixel, dword color);
|
||||||
void video_psetp24(int pixel, dword color);
|
void video_psetp24(int pixel, dword color);
|
||||||
void video_psetp32(int pixel, dword color);
|
void video_psetp32(int pixel, dword color);
|
||||||
|
void video_psetpnull(int pixel, dword color);
|
||||||
void video_renderChar(int x, int y, int character, dword color);
|
void video_renderChar(int x, int y, int character, dword color);
|
||||||
|
void video_drawConsole();
|
||||||
|
void video_drawConsoleChar(dword position);
|
||||||
|
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
word ModeAttributes;
|
word ModeAttributes;
|
||||||
@@ -52,11 +56,14 @@ typedef struct{
|
|||||||
byte Reserved[206];
|
byte Reserved[206];
|
||||||
} ModeInfoBlock;
|
} ModeInfoBlock;
|
||||||
|
|
||||||
|
|
||||||
ModeInfoBlock video_mode;
|
ModeInfoBlock video_mode;
|
||||||
byte *vid_ptr24;
|
dword videoMode = 0; //what video mode # we are in, 0 for console mode
|
||||||
word *vid_ptr16;
|
word *vid_ptr16 = (word *)0xF0000000;
|
||||||
dword *vid_ptr32;
|
byte *vid_ptr24 = (byte *)0xF0000000;
|
||||||
void (*video_psetp)(int, dword); //function pointer to set a pixel
|
dword *vid_ptr32 = (dword *)0xF0000000;
|
||||||
|
word console_memory[2000]; //holds a copy of the console's memory
|
||||||
|
void (*video_psetp)(int, dword) = video_psetpnull; //function pointer to set a pixel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,177 +1,349 @@
|
|||||||
|
|
||||||
// vmm.c
|
// vmm.c
|
||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
// Date: 09/30/03
|
// Date: 09/30/03
|
||||||
|
// Rewritten from scratch: 12/23/03
|
||||||
PageDirectory *vmm_PDBR = 0;
|
// Modified: 12/30/03
|
||||||
dword vmm_first_virtual_address = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
// This is the initialization procedure for the Virtual Memory Manager
|
||||||
|
// It sets up the final page directory/page table setup and maps video memory, if present
|
||||||
void vmm_init()
|
void vmm_init()
|
||||||
{
|
{
|
||||||
if (!(vmm_PDBR = mm_palloc(1, PID_KERNEL)))
|
dword *pageTables = (dword *)0xC0104000; //this is the location of the page directory
|
||||||
|
pageTables[0x3FF] = 0x104000|0x03; //the last page directory entry points to the page directory itself
|
||||||
|
pageTables[0] = 0;
|
||||||
|
invlpg(0);
|
||||||
|
if (videoMode) //we are in a graphical mode
|
||||||
{
|
{
|
||||||
printf("ERROR! COULD NOT ALLOCATE PAGE FOR INITIAL PAGE DIRECTORY!!\n");
|
dword vidPages = video_mode.XResolution * video_mode.YResolution * (video_mode.BitsPerPixel >> 3);
|
||||||
halt();
|
if (vidPages % 4096)
|
||||||
}
|
vidPages = (vidPages >> 12) + 1;
|
||||||
vmm_init_pagetable((dword)vmm_PDBR);
|
|
||||||
|
|
||||||
if (mm_totalmem % 4096)
|
|
||||||
vmm_first_virtual_address = mm_totalmem + (4096 - (mm_totalmem % 4096));
|
|
||||||
else
|
else
|
||||||
vmm_first_virtual_address = mm_totalmem;
|
vidPages = (vidPages >> 12);
|
||||||
|
vmm_mapn(0xF0000000, video_mode.PhysBasePtr, vidPages);
|
||||||
|
}
|
||||||
|
dword firstHeapEntryBlock = (dword)mm_palloc();
|
||||||
|
vmm_map1((dword)firstHeapEntry, firstHeapEntryBlock);
|
||||||
|
HeapEntryBlock *heb = (HeapEntryBlock *)firstHeapEntry;
|
||||||
|
vmm_heb_init(heb);
|
||||||
|
heb->entry[0].base = (dword)firstHeapEntry; //start of kernel's heap memory
|
||||||
|
heb->entry[0].size = 4096; //the first HeapEntryBlock is 1 page long
|
||||||
|
heb->entry[0].attributes = VMM_HE_HEB; //this is a HeapEntryBlock
|
||||||
|
heb->entry[1].base = (dword)firstHeapEntry+4096; //this is the start of the rest of the kernel's heap memory
|
||||||
|
heb->entry[1].size = 0x10000000-4096; //the rest of the kernel's heap memory: 256mb - 4kb
|
||||||
|
heb->entry[1].attributes = VMM_HE_HOLE; //this is a hold - an unmapped section of heap memory
|
||||||
|
}
|
||||||
|
|
||||||
if (vmm_mapn(0, 0, 0x03, mm_totalmem/4096+1))
|
|
||||||
|
// This function initialzes a Heap Entry Block to unused entries linked together
|
||||||
|
void vmm_heb_init(HeapEntryBlock *heb)
|
||||||
{
|
{
|
||||||
printf("Could not page in all physical RAM!\n");
|
int a;
|
||||||
halt();
|
for (a = 0; a < 256; a++)
|
||||||
|
{
|
||||||
|
heb->entry[a].base = 0;
|
||||||
|
heb->entry[a].size = 0;
|
||||||
|
heb->entry[a].attributes = VMM_HE_UNUSED;
|
||||||
|
heb->entry[a].link = (dword)&(heb->entry[a+1]);
|
||||||
}
|
}
|
||||||
//we also need to map in the video framebuffer memory:
|
heb->entry[255].link = 0;
|
||||||
if (video_mode.PhysBasePtr > 0 && video_mode.BitsPerPixel > 0)
|
|
||||||
{
|
|
||||||
if (vmm_mapn(video_mode.PhysBasePtr, video_mode.PhysBasePtr, 0x03, ((video_mode.BitsPerPixel>>3) * video_mode.XResolution * video_mode.YResolution)/4096+1))
|
|
||||||
{
|
|
||||||
printf("Could not page in video memory at 0x%x!\n", video_mode.PhysBasePtr);
|
|
||||||
halt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function maps a virtual address to a physical address using the page directory / page table
|
||||||
|
void vmm_map1(dword virt, dword physical)
|
||||||
|
{
|
||||||
|
dword pde = virt >> 22;
|
||||||
|
dword pte = (virt & 0x003FF000) >> 12;
|
||||||
|
dword *pageTables = (dword *)0xC0104000; //this is the location of the page directory
|
||||||
|
if (!(pageTables[pde] & 0x01)) //the page directory entry does not exist, we must allocate a page for it
|
||||||
|
{
|
||||||
|
dword *newpagetable = mm_palloc();
|
||||||
|
pageTables[pde] = ((dword)newpagetable) | 0x03;
|
||||||
|
invlpg(virt);
|
||||||
|
dword *newpteptr = (dword *)(0xFFC00000 | (pde << 12)); //points to first dword of newly allocated page table
|
||||||
|
int a;
|
||||||
|
for (a = 0; a < 1024; a++)
|
||||||
|
{
|
||||||
|
newpteptr[a] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dword *pteptr = (dword *)(0xFFC00000 | (pde << 12) | (pte << 2));
|
||||||
|
*pteptr = physical | 0x03;
|
||||||
|
invlpg(virt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function maps a variable number of pages in a row
|
||||||
|
void vmm_mapn(dword virt, dword physical, dword n)
|
||||||
|
{
|
||||||
|
for (; n > 0; n--)
|
||||||
|
{
|
||||||
|
vmm_map1(virt, physical);
|
||||||
|
virt += 4096;
|
||||||
|
physical += 4096;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void vmm_enable_paging()
|
// This function removes the virtual address's entry in the page directory / page table
|
||||||
|
void vmm_unmap1(dword virt)
|
||||||
{
|
{
|
||||||
write_cr3((dword)vmm_PDBR);
|
dword *pteptr = (dword *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10));
|
||||||
write_cr0(0x80000000|read_cr0());
|
*pteptr = 0;
|
||||||
|
invlpg(virt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int vmm_map1(dword virtual, dword physical, dword flags)
|
// This function removes multiple pages' entries
|
||||||
|
void vmm_unmapn(dword virt, dword n)
|
||||||
{
|
{
|
||||||
if (virtual & 0x00000FFF)
|
for (; n > 0; n--)
|
||||||
return 1; // ERROR 1: address not page-aligned
|
|
||||||
if (physical & 0x00000FFF)
|
|
||||||
return 1; // ERROR 1: address not page-aligned
|
|
||||||
int pde = (virtual & 0xFFC00000) >> 22;
|
|
||||||
int pte = (virtual & 0x003FF000) >> 12;
|
|
||||||
if (!(vmm_PDBR->pageTables[pde] & 0x01))
|
|
||||||
{
|
{
|
||||||
vmm_PDBR->pageTables[pde] = (dword)mm_palloc(1, PID_KERNEL) | 0x7; //user, r/w, present
|
vmm_unmap1(virt);
|
||||||
vmm_init_pagetable(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
|
virt += 4096;
|
||||||
if (vmm_PDBR->pageTables[pde] == 0x07)
|
|
||||||
return 2; // ERROR 2: page table could not be created
|
|
||||||
}
|
}
|
||||||
PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
|
|
||||||
if (ptp->page[pte] & 0x01)
|
|
||||||
return 3; // ERROR 3: page table entry already exists
|
|
||||||
ptp->page[pte] = physical | flags;
|
|
||||||
//invlpg();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int vmm_mapn(dword virtual, dword physical, dword flags, dword n)
|
|
||||||
{
|
|
||||||
int mapped;
|
|
||||||
int result = 0;
|
|
||||||
dword va = virtual;
|
|
||||||
dword pa = physical;
|
|
||||||
for (mapped = 0; mapped < n; mapped++)
|
|
||||||
{
|
|
||||||
if (result = vmm_map1(va, pa, flags))
|
|
||||||
{
|
|
||||||
if (mapped > 0)
|
|
||||||
vmm_unmapn(virtual, mapped);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
va += 4096;
|
|
||||||
pa += 4096;
|
|
||||||
}
|
|
||||||
//invlpg();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vmm_unmap1(dword virtual)
|
|
||||||
{
|
|
||||||
if (virtual & 0x00000FFF)
|
|
||||||
return 1; // ERROR 1: address not page-aligned
|
|
||||||
int pde = (virtual & 0xFFC00000) >> 22;
|
|
||||||
int pte = (virtual & 0x003FF000) >> 12;
|
|
||||||
if (!(vmm_PDBR->pageTables[pde] & 0x01))
|
|
||||||
return 2; // ERROR 2: page table not present
|
|
||||||
PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
|
|
||||||
ptp->page[pte] = 0;
|
|
||||||
//invlpg();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int vmm_unmapn(dword virtual, dword n)
|
|
||||||
{
|
|
||||||
int reslt;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
if (reslt = vmm_unmap1(virtual))
|
|
||||||
return reslt;
|
|
||||||
virtual += 4096;
|
|
||||||
}
|
|
||||||
vmm_walkPageTables();
|
|
||||||
//invlpg();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void vmm_init_pagetable(dword address)
|
|
||||||
{
|
|
||||||
PageTable *ptp = (PageTable *)address;
|
|
||||||
int n;
|
|
||||||
for (n = 0; n < 1024; n++)
|
|
||||||
ptp->page[n] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int vmm_walkPageTables()
|
|
||||||
{
|
|
||||||
int pde;
|
|
||||||
int pte;
|
|
||||||
int used_ptes;
|
|
||||||
PageTable *ptp;
|
|
||||||
for (pde = 0; pde < 1024; pde++)
|
|
||||||
{
|
|
||||||
if (vmm_PDBR->pageTables[pde] & 0x01)
|
|
||||||
{
|
|
||||||
used_ptes = 0;
|
|
||||||
ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000);
|
|
||||||
for (pte = 0; pte < 1024; pte++)
|
|
||||||
{
|
|
||||||
if (ptp->page[pte] & 0x01) //page table entry present
|
|
||||||
used_ptes++;
|
|
||||||
}
|
|
||||||
if (!(used_ptes)) //no used pte's -- remove page table & page directory entry
|
|
||||||
{
|
|
||||||
mm_pfree(ptp);
|
|
||||||
vmm_PDBR->pageTables[pde] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Virtual Memory allocator function
|
||||||
void *malloc(dword bytes)
|
void *malloc(dword bytes)
|
||||||
{
|
{
|
||||||
|
if (bytes % VMM_MALLOC_GRANULARITY)
|
||||||
|
bytes = bytes + VMM_MALLOC_GRANULARITY - (bytes % VMM_MALLOC_GRANULARITY);
|
||||||
|
void *attempt = vmm_getFreeChunk(bytes);
|
||||||
|
if (attempt)
|
||||||
|
return attempt;
|
||||||
|
if(vmm_moreCore(bytes))
|
||||||
|
return 0; //we could not get any more heap memory
|
||||||
|
return vmm_getFreeChunk(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function returns a pointer if a free chunk of memory exists
|
||||||
|
void *vmm_getFreeChunk(dword bytes)
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (he->attributes == VMM_HE_FREE)
|
||||||
|
{
|
||||||
|
if (he->size > bytes)
|
||||||
|
{
|
||||||
|
HeapEntry *nhe = vmm_nextHeapEntry();
|
||||||
|
nhe->base = he->base;
|
||||||
|
nhe->size = bytes;
|
||||||
|
nhe->attributes = VMM_HE_USED;
|
||||||
|
he->base += bytes;
|
||||||
|
he->size -= bytes;
|
||||||
|
return (void *)(nhe->base);
|
||||||
|
}
|
||||||
|
if (he->size == bytes)
|
||||||
|
{
|
||||||
|
he->attributes = VMM_HE_USED;
|
||||||
|
return (void *)(he->base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
he = (HeapEntry *)he->link;
|
||||||
|
if (!he)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function coalesces any two adjacent heap entries into one entry
|
||||||
|
void vmm_coalesceHeapEntry(HeapEntry *he)
|
||||||
|
{
|
||||||
|
if (!(he->attributes == VMM_HE_FREE || he->attributes == VMM_HE_HOLE))
|
||||||
|
return;
|
||||||
|
if (he->size == 0)
|
||||||
|
{
|
||||||
|
he->attributes = VMM_HE_UNUSED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HeapEntry *hec = firstHeapEntry;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (hec->attributes == he->attributes)
|
||||||
|
{
|
||||||
|
if ((hec->base + hec->size) == he->base) //hec ends where he begins
|
||||||
|
{
|
||||||
|
he->base = hec->base;
|
||||||
|
he->size += hec->size;
|
||||||
|
hec->attributes = VMM_HE_UNUSED;
|
||||||
|
}
|
||||||
|
if ((he->base + he->size) == hec->base) //he ends where hec begins
|
||||||
|
{
|
||||||
|
he->size += hec->size;
|
||||||
|
hec->attributes = VMM_HE_UNUSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hec = (HeapEntry *)hec->link;
|
||||||
|
if (!hec)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function retrieves more physical memory for the heap
|
||||||
|
int vmm_moreCore(dword bytes)
|
||||||
|
{
|
||||||
|
dword pages = (bytes >> 12) + 1;
|
||||||
|
bytes = pages << 12;
|
||||||
|
HeapEntry *he = vmm_getFirstHoleHeapEntry(bytes);
|
||||||
|
dword virt = he->base;
|
||||||
|
for (; pages > 0; pages--)
|
||||||
|
{
|
||||||
|
dword phys = (dword)mm_palloc();
|
||||||
|
if (!phys)
|
||||||
|
return 1;
|
||||||
|
vmm_map1(virt, phys);
|
||||||
|
virt += 4096;
|
||||||
|
}
|
||||||
|
if (he->size == bytes)
|
||||||
|
{
|
||||||
|
he->attributes = VMM_HE_FREE;
|
||||||
|
vmm_coalesceHeapEntry(he);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HeapEntry *nhe = vmm_nextHeapEntry();
|
||||||
|
nhe->base = he->base;
|
||||||
|
nhe->size = bytes;
|
||||||
|
nhe->attributes = VMM_HE_FREE;
|
||||||
|
he->base += bytes;
|
||||||
|
he->size -= bytes;
|
||||||
|
vmm_coalesceHeapEntry(nhe);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function returns the next available heap entry, creates more entries if we are running low
|
||||||
|
HeapEntry *vmm_nextHeapEntry()
|
||||||
|
{
|
||||||
|
if (vmm_heapEntriesLeft() < 10)
|
||||||
|
vmm_addHeapEntryBlock();
|
||||||
|
return vmm_getFirstUnusedHeapEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function creates a new block (page) of heap entries (256)
|
||||||
|
void vmm_addHeapEntryBlock()
|
||||||
|
{
|
||||||
|
HeapEntry *he = vmm_getFirstHoleHeapEntry(4096);
|
||||||
|
HeapEntry *newBlock = vmm_getFirstUnusedHeapEntry();
|
||||||
|
dword heb = (dword)mm_palloc();
|
||||||
|
vmm_map1(he->base, heb);
|
||||||
|
vmm_heb_init((HeapEntryBlock *)he->base);
|
||||||
|
HeapEntry *lhe = vmm_getLastHeapEntry();
|
||||||
|
if (he->size == 4096)
|
||||||
|
{
|
||||||
|
he->attributes = VMM_HE_HEB;
|
||||||
|
lhe->link = (dword)he->base;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newBlock->base = he->base;
|
||||||
|
newBlock->size = 4096;
|
||||||
|
newBlock->attributes = VMM_HE_HEB;
|
||||||
|
he->base += 4096;
|
||||||
|
he->size -= 4096;
|
||||||
|
lhe->link = (dword)newBlock->base;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function returns the last heap entry in the linked list, useful for setting
|
||||||
|
// its link field to point to the first entry of a newly allocated list
|
||||||
|
HeapEntry *vmm_getLastHeapEntry()
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (he->link == 0)
|
||||||
|
return he;
|
||||||
|
he = (HeapEntry *)he->link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function returns the first heap entry corresponding to a memory "hole"
|
||||||
|
HeapEntry *vmm_getFirstHoleHeapEntry(dword minBytes)
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((he->attributes == VMM_HE_HOLE) && (he->size >= minBytes))
|
||||||
|
return he;
|
||||||
|
he = (HeapEntry *)he->link;
|
||||||
|
if (!he)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function returns the first heap entry that is not being used
|
||||||
|
HeapEntry *vmm_getFirstUnusedHeapEntry()
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (he->attributes == VMM_HE_UNUSED)
|
||||||
|
return he;
|
||||||
|
he = (HeapEntry *)he->link;
|
||||||
|
if (!he)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function returns the number of heap entries available for use
|
||||||
|
dword vmm_heapEntriesLeft()
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
dword entries = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (he->attributes == VMM_HE_UNUSED)
|
||||||
|
entries++;
|
||||||
|
he = (HeapEntry *)he->link;
|
||||||
|
if (!he)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function "frees" an area of memory previously allocated with malloc()
|
||||||
int free(void *ptr)
|
int free(void *ptr)
|
||||||
{
|
{
|
||||||
|
HeapEntry *he = vmm_getHeapEntryByBase((dword)ptr);
|
||||||
|
if (!he)
|
||||||
|
return 1; //a heap entry starting at the given address was not found
|
||||||
|
he->attributes = VMM_HE_FREE;
|
||||||
|
vmm_coalesceHeapEntry(he);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function scans the heap entry linked list for an entry that begins at the given address
|
||||||
|
HeapEntry *vmm_getHeapEntryByBase(dword base)
|
||||||
|
{
|
||||||
|
HeapEntry *he = firstHeapEntry;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (he->base == base)
|
||||||
|
return he;
|
||||||
|
he = (HeapEntry *)he->link;
|
||||||
|
if (!he)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,52 @@
|
|||||||
|
|
||||||
// vmm.h
|
// vmm.h
|
||||||
// Author: Josh Holtrop
|
// Author: Josh Holtrop
|
||||||
// Date: 09/30/03
|
// Date: 09/30/03
|
||||||
|
// Rewritten from scratch: 12/23/03
|
||||||
|
// Modified: 12/30/03
|
||||||
|
|
||||||
|
|
||||||
|
#define VMM_HE_UNUSED 0 //available entry
|
||||||
|
#define VMM_HE_FREE 1 //free section of memory
|
||||||
|
#define VMM_HE_USED 2 //used section of memory
|
||||||
|
#define VMM_HE_HOLE 3 //a "hole" (unmapped) section of virtual memory
|
||||||
|
#define VMM_HE_HEB 4 //HeapEntryBlock
|
||||||
|
|
||||||
|
#define VMM_MALLOC_GRANULARITY 4 //granularity for all memory requests
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
dword base; //virtual base address
|
||||||
|
dword size; //size in bytes
|
||||||
|
dword attributes; //free/used/hole
|
||||||
|
dword link; //link to next HeapEntry
|
||||||
|
} __attribute__((packed)) HeapEntry;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
dword page[1024];
|
HeapEntry entry[256]; //256 HeapEntry objects = 4kb (1 page)
|
||||||
} PageTable;
|
} __attribute__((packed)) HeapEntryBlock;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
dword pageTables[1024];
|
|
||||||
} PageDirectory;
|
|
||||||
|
|
||||||
|
|
||||||
void vmm_enable_paging();
|
|
||||||
void vmm_init();
|
void vmm_init();
|
||||||
void *malloc(dword bytes);
|
void *malloc(dword bytes);
|
||||||
int free(void *ptr);
|
int free(void *ptr);
|
||||||
int vmm_map1(dword virtual, dword physical, dword flags);
|
void vmm_map1(dword virt, dword physical);
|
||||||
int vmm_mapn(dword virtual, dword physical, dword flags, dword n);
|
void vmm_mapn(dword virt, dword physical, dword n);
|
||||||
int vmm_unmap1(dword virtual);
|
void vmm_unmap1(dword virt);
|
||||||
int vmm_unmapn(dword virtual, dword n);
|
void vmm_unmapn(dword virt, dword n);
|
||||||
void vmm_init_pagetable(dword address);
|
void vmm_heb_init(HeapEntryBlock *heb);
|
||||||
int vmm_walkPageTables();
|
void *vmm_getFreeChunk(dword bytes);
|
||||||
|
HeapEntry *vmm_nextHeapEntry();
|
||||||
|
dword vmm_heapEntriesLeft();
|
||||||
|
HeapEntry *vmm_getLastHeapEntry();
|
||||||
|
HeapEntry *vmm_getFirstUnusedHeapEntry();
|
||||||
|
HeapEntry *vmm_getFirstHoleHeapEntry(dword minBytes);
|
||||||
|
void vmm_addHeapEntryBlock();
|
||||||
|
int vmm_moreCore(dword bytes);
|
||||||
|
void vmm_coalesceHeapEntry(HeapEntry *he);
|
||||||
|
HeapEntry *vmm_getHeapEntryByBase(dword base);
|
||||||
|
|
||||||
|
|
||||||
|
HeapEntry *firstHeapEntry = (HeapEntry *)0xD0000000; //this is where heap memory starts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user