Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
311b8afc83 | ||
|
|
21e3943b5e | ||
|
|
10fd7102ca | ||
|
|
7de4f94423 | ||
|
|
0a546f1467 | ||
|
|
af6087ecec | ||
|
|
c613002307 | ||
|
|
76398df125 | ||
|
|
e83408ce83 | ||
|
|
715bb9341a | ||
|
|
e82bf2ecdf | ||
|
|
528527a7ed | ||
|
|
71aaa7a598 | ||
|
|
9070a76b18 | ||
|
|
5048a93ff7 | ||
|
|
282b856e24 | ||
|
|
3bb1e5fffc | ||
|
|
5ccfd0fc74 | ||
|
|
70d6bb1eb3 | ||
|
|
294b4b0e27 | ||
|
|
57980293e6 | ||
|
|
ba97e8a7f0 | ||
|
|
36b025ccb4 | ||
|
|
aab5ff3c90 | ||
|
|
8bf6e65a95 | ||
|
|
5da602b162 | ||
|
|
7a0351e123 | ||
|
|
3dc0fe5e2b | ||
|
|
82da40c9f0 | ||
|
|
8d5b28f823 | ||
|
|
68fd6cad70 | ||
|
|
c3309d4e5d | ||
|
|
06d7cbef47 | ||
|
|
e8b1abb265 |
No files matched your search
+219
-17
@@ -1,18 +1,21 @@
|
||||
//Functions.c
|
||||
//05/07/03 Josh Holtrop
|
||||
//for HOS
|
||||
//Modified: 10/30/03
|
||||
|
||||
|
||||
//Writes a byte out to a port
|
||||
inline void outportb(unsigned int port, unsigned char value) // Output a byte to a port
|
||||
{
|
||||
asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value));
|
||||
};
|
||||
|
||||
//Writes a word out to a port
|
||||
inline void outportw(unsigned int port, unsigned int value) // Output a word to a port
|
||||
{
|
||||
asm volatile ("outw %%ax,%%dx"::"d" (port), "a" (value));
|
||||
};
|
||||
|
||||
//Reads a byte from a port
|
||||
inline byte inportb(unsigned short port)
|
||||
{
|
||||
unsigned char ret_val;
|
||||
@@ -23,47 +26,245 @@ inline byte inportb(unsigned short port)
|
||||
return ret_val;
|
||||
};
|
||||
|
||||
void enable_ints()
|
||||
//Enables (SeTs) Interrupt Flag on the processor
|
||||
inline void enable_ints()
|
||||
{
|
||||
asm("sti");
|
||||
};
|
||||
|
||||
void disable_ints()
|
||||
//Disables (CLears) Interrupt Flag on the processor
|
||||
inline void disable_ints()
|
||||
{
|
||||
asm("cli");
|
||||
};
|
||||
|
||||
|
||||
char *strcat(char *dest, char *src)
|
||||
{
|
||||
strcpy(dest+strlen(dest), src);
|
||||
}
|
||||
|
||||
|
||||
//converts a binary-coded-decimal byte to its decimal equivalent
|
||||
inline byte bcd2byte(byte bcd)
|
||||
{
|
||||
return (10* ((bcd & 0xF0) >> 4)) + (bcd & 0x0F);
|
||||
}
|
||||
|
||||
//converts a binary-coded-decimal byte to its decimal equivalent
|
||||
inline byte byte2bcd(byte bite)
|
||||
{
|
||||
return ((bite / 10) << 4) | (bite % 10);
|
||||
}
|
||||
|
||||
void rtrim(char *str)
|
||||
{
|
||||
str += strlen(str); //now points to the null character at the end of the string
|
||||
str--;
|
||||
for (;;)
|
||||
{
|
||||
if ((*str == ' ') || (*str == '\t') || (*str == '\n'))
|
||||
*str-- = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *ucase(char *str)
|
||||
{
|
||||
char *ret = str;
|
||||
for (;;)
|
||||
{
|
||||
if (*str == 0)
|
||||
break;
|
||||
if ((*str >= 'a') && (*str <= 'z'))
|
||||
*str = (*str) - 32;
|
||||
str++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char *lcase(char *str)
|
||||
{
|
||||
char *ret = str;
|
||||
for (;;)
|
||||
{
|
||||
if (*str == 0)
|
||||
break;
|
||||
if ((*str >= 'A') && (*str <= 'Z'))
|
||||
*str = (*str) + 32;
|
||||
str++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address
|
||||
void remap_pics(int pic1, int pic2)
|
||||
{
|
||||
byte a1, a2;
|
||||
|
||||
a1 = inportb(PIC1_DATA);
|
||||
a2 = inportb(PIC2_DATA);
|
||||
a1 = inportb(PIC1_DATA); //0x21
|
||||
a2 = inportb(PIC2_DATA); //0xA1
|
||||
|
||||
outportb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);
|
||||
outportb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
|
||||
outportb(PIC1_DATA, pic1);
|
||||
outportb(PIC2_DATA, pic2);
|
||||
outportb(PIC1_DATA, 4);
|
||||
outportb(PIC2_DATA, 2);
|
||||
outportb(PIC1_DATA, ICW4_8086);
|
||||
outportb(PIC2_DATA, ICW4_8086);
|
||||
outportb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); //0x20, 0x10+0x01 00010001b
|
||||
outportb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); //0xA0, 0x10+0x01 00010001b
|
||||
outportb(PIC1_DATA, pic1); //0x21, pic1
|
||||
outportb(PIC2_DATA, pic2); //0xA1, pic2
|
||||
outportb(PIC1_DATA, 4); //0x21, 0x04 00000100b
|
||||
outportb(PIC2_DATA, 2); //0xA1, 0x02 00000010b
|
||||
outportb(PIC1_DATA, ICW4_8086); //0x21, 0x01 00000001b
|
||||
outportb(PIC2_DATA, ICW4_8086); //0xA1, 0x01 00000001b
|
||||
|
||||
outportb(PIC1_DATA, a1);
|
||||
outportb(PIC2_DATA, a2);
|
||||
};
|
||||
outportb(PIC1_DATA, a1); //0x21
|
||||
outportb(PIC2_DATA, a2); //0xA1
|
||||
}
|
||||
|
||||
//Masks interrupts on first Programmable Interrupt Controller
|
||||
inline void pic1_mask(byte mask)
|
||||
{
|
||||
outportb(PIC1_DATA, mask); //0x21, maskfield *OCW1*
|
||||
}
|
||||
|
||||
//Masks interrupts on second Programmable Interrupt Controller
|
||||
inline void pic2_mask(byte mask)
|
||||
{
|
||||
outportb(PIC2_DATA, mask); //0xA1, maskfield *OCW1*
|
||||
}
|
||||
|
||||
//Restarts the computer
|
||||
inline void restart()
|
||||
{
|
||||
enable_ints();
|
||||
byte temp;
|
||||
do
|
||||
{
|
||||
temp = inportb(0x64);
|
||||
if (temp & 1)
|
||||
inportb(0x60);
|
||||
} while(temp & 2);
|
||||
|
||||
|
||||
outportb (0x64, 0xfe);
|
||||
for (;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//Halts (freezes) the computer
|
||||
inline void halt()
|
||||
{
|
||||
asm("cli");
|
||||
asm("hlt");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
//Initializes 8253 Programmable Interrupt Timer
|
||||
inline void init_timer()
|
||||
{
|
||||
//set timer : 2e9c = 100hz
|
||||
outportb(0x43, 0x34);
|
||||
outportb(0x40, 0x9c); //lsb
|
||||
outportb(0x40, 0x2e); //msb
|
||||
}
|
||||
|
||||
//Signals an End Of Interrupt signal to the first PIC
|
||||
inline void eoi()
|
||||
{
|
||||
outportb(0x20, 0x20); //EOI
|
||||
outportb(0x20, 0x20);
|
||||
}
|
||||
|
||||
//Signals an End Of Interrupt signal to both the second and first PIC unit
|
||||
inline void eoi2()
|
||||
{
|
||||
outportb(0xA0, 0x20);
|
||||
outportb(0x20, 0x20);
|
||||
}
|
||||
|
||||
//Returns the size of the kernel (code & data)
|
||||
// - this does not include the bss section
|
||||
// - this should be 4kb aligned per the linker script
|
||||
// - this should be the size of kernel.bin
|
||||
inline dword kernel_size()
|
||||
{
|
||||
return (dword)(&_bss)-(dword)(&_code);
|
||||
}
|
||||
|
||||
|
||||
//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));
|
||||
}
|
||||
|
||||
|
||||
@@ -72,3 +273,4 @@ inline void eoi()
|
||||
|
||||
|
||||
|
||||
|
||||
+470
@@ -0,0 +1,470 @@
|
||||
; asmfuncs.asm
|
||||
; Josh Holtrop
|
||||
; Created: 10/23/03
|
||||
; Modified: 12/25/03
|
||||
|
||||
[extern _putc]
|
||||
[extern _console_memory]
|
||||
[extern _cursorPosition]
|
||||
[extern _video_drawConsole]
|
||||
[extern _videoMode]
|
||||
|
||||
%macro jzfar 1
|
||||
jnz %%skip
|
||||
jmp %1
|
||||
%%skip:
|
||||
|
||||
%endmacro
|
||||
|
||||
;stores the parameter to the CR0 register
|
||||
;extern dword write_cr0(dword cr0);
|
||||
[global _write_cr0]
|
||||
_write_cr0:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [ebp+8]
|
||||
mov cr0, eax
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
;returns the value in the CR0 register
|
||||
;extern dword read_cr0();
|
||||
[global _read_cr0]
|
||||
_read_cr0:
|
||||
mov eax, cr0;
|
||||
ret
|
||||
|
||||
;stores the parameter to the CR3 register
|
||||
;extern dword write_cr3(dword cr3);
|
||||
[global _write_cr3]
|
||||
_write_cr3:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [ebp+8]
|
||||
mov cr3, eax
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
;returns the value in the CR2 register
|
||||
;extern dword read_cr2();
|
||||
[global _read_cr2]
|
||||
_read_cr2:
|
||||
mov eax, cr2;
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;returns the value in the CR3 register
|
||||
;extern dword read_cr3();
|
||||
[global _read_cr3]
|
||||
_read_cr3:
|
||||
mov eax, cr3;
|
||||
ret
|
||||
|
||||
|
||||
;compares one string to another
|
||||
;returns 0 if the strings are different
|
||||
;extern dword strcmp(char *str1, char *str2);
|
||||
[global _strcmp]
|
||||
_strcmp:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, [ebp+8]
|
||||
mov edi, [ebp+12]
|
||||
strcmp_loop1:
|
||||
lodsb
|
||||
mov ah, [edi]
|
||||
inc edi
|
||||
cmp ah, al
|
||||
jnz strcmp_ne
|
||||
or al, al
|
||||
jz strcmp_e
|
||||
jmp strcmp_loop1
|
||||
strcmp_e:
|
||||
mov eax, 1
|
||||
jmp short strcmp_done
|
||||
strcmp_ne:
|
||||
xor eax, eax
|
||||
strcmp_done:
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
;copies a string from the source to the destination parameter
|
||||
;extern void strcpy(char *dest, char *src);
|
||||
[global _strcpy]
|
||||
_strcpy:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push esi
|
||||
push edi
|
||||
mov edi, [ebp+8]
|
||||
mov esi, [ebp+12]
|
||||
strcpyloop:
|
||||
lodsb
|
||||
stosb
|
||||
or al, al
|
||||
jnz strcpyloop
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
;copies memory of n bytes from src to destination
|
||||
;extern void memcpy(dword dest, dword src, dword n);
|
||||
[global _memcpy]
|
||||
_memcpy:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push esi
|
||||
push edi
|
||||
push ecx
|
||||
mov edi, [ebp+8]
|
||||
mov esi, [ebp+12]
|
||||
mov ecx, [ebp+16]
|
||||
|
||||
rep movsb
|
||||
|
||||
pop ecx
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
;returns the number of characters in a string
|
||||
;extern dword strlen(char *str);
|
||||
[global _strlen]
|
||||
_strlen:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push esi
|
||||
push ebx
|
||||
mov esi, [ebp+8]
|
||||
xor ebx, ebx
|
||||
strlenloop:
|
||||
lodsb
|
||||
or al, al
|
||||
jz strlendone
|
||||
inc ebx
|
||||
jmp strlenloop
|
||||
strlendone:
|
||||
mov eax, ebx
|
||||
pop ebx
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
;this function invalidates the page directory/table entry that
|
||||
; would be used to access the memory address given in the parameter
|
||||
;extern void invlpg(dword addr);
|
||||
[global _invlpg]
|
||||
_invlpg:
|
||||
mov eax, [esp+4]
|
||||
invlpg [eax]
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
;void writeCursorPosition(word pos)
|
||||
;
|
||||
[global _writeCursorPosition]
|
||||
_writeCursorPosition:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
push eax
|
||||
push ebx
|
||||
push edx
|
||||
|
||||
mov eax, [ebp+8] ;cursor position in ax
|
||||
|
||||
mov bl, al
|
||||
mov dx, 0x03D4
|
||||
mov al, 0x0E
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, ah
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x0F
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, bl
|
||||
out dx, al
|
||||
|
||||
pop edx
|
||||
pop ebx
|
||||
pop eax
|
||||
pop ebp
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
;word getCursorPosition()
|
||||
;
|
||||
[global _getCursorPosition]
|
||||
_getCursorPosition:
|
||||
push ebx
|
||||
push edx
|
||||
|
||||
xor eax, eax
|
||||
mov dx, 0x03D4
|
||||
mov al, 0x0E
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
in al, dx
|
||||
mov bl, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x0F
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
in al, dx
|
||||
mov ah, bl
|
||||
|
||||
pop edx
|
||||
pop ebx
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
;void console_scroll()
|
||||
;
|
||||
[global _console_scroll]
|
||||
_console_scroll:
|
||||
pusha
|
||||
mov esi, _console_memory+160
|
||||
mov edi, _console_memory
|
||||
mov ecx, 960 ;(2000-80)/2
|
||||
rep movsd
|
||||
mov ax, 0x0720
|
||||
mov ecx, 80
|
||||
rep stosw
|
||||
mov esi, _console_memory
|
||||
mov edi, 0xC00B8000
|
||||
mov ecx, 1000
|
||||
rep movsd
|
||||
mov eax, [_videoMode]
|
||||
cmp eax, 0
|
||||
jz _console_scroll_end
|
||||
call _video_drawConsole
|
||||
_console_scroll_end:
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;
|
||||
;void console_cls()
|
||||
;
|
||||
[global _console_cls]
|
||||
_console_cls:
|
||||
pusha
|
||||
mov edi, _console_memory
|
||||
mov ax, 0x0720
|
||||
mov ecx, 2000
|
||||
rep stosw
|
||||
push dword 0
|
||||
call _writeCursorPosition
|
||||
add esp, 4
|
||||
mov [_cursorPosition], dword 0
|
||||
mov esi, _console_memory
|
||||
mov edi, 0xC00B8000
|
||||
mov ecx, 1000
|
||||
rep movsd
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;
|
||||
;int puts(char *str)
|
||||
;
|
||||
[global _puts]
|
||||
_puts:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push esi
|
||||
push eax
|
||||
mov esi, [ebp+8] ;esi = to string
|
||||
puts_loop:
|
||||
lodsb
|
||||
cmp al, 0
|
||||
jz puts_done
|
||||
push eax
|
||||
call _putc
|
||||
add esp, 4
|
||||
jmp puts_loop
|
||||
|
||||
puts_done:
|
||||
pop eax
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
[global _putDecu]
|
||||
_putDecu:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 24
|
||||
mov DWORD [ebp-4], 1
|
||||
mov BYTE [ebp-5], 0
|
||||
L2:
|
||||
mov edx, DWORD [ebp+8]
|
||||
mov eax, -858993459
|
||||
mul edx
|
||||
mov eax, edx
|
||||
shr eax, 3
|
||||
cmp eax, DWORD [ebp-4]
|
||||
jae L4
|
||||
jmp L3
|
||||
L4:
|
||||
mov eax, DWORD [ebp-4]
|
||||
mov edx, eax
|
||||
sal edx, 2
|
||||
add edx, eax
|
||||
lea eax, [edx+edx]
|
||||
mov DWORD [ebp-4], eax
|
||||
jmp L2
|
||||
L3:
|
||||
nop
|
||||
L5:
|
||||
cmp DWORD [ebp-4], 1
|
||||
ja L7
|
||||
jmp L6
|
||||
L7:
|
||||
mov edx, DWORD [ebp+8]
|
||||
mov eax, edx
|
||||
mov edx, 0
|
||||
div DWORD [ebp-4]
|
||||
mov DWORD [ebp-12], eax
|
||||
mov al, BYTE [ebp-12]
|
||||
mov BYTE [ebp-5], al
|
||||
mov eax, 0
|
||||
mov al, BYTE [ebp-5]
|
||||
imul eax, DWORD [ebp-4]
|
||||
sub DWORD [ebp+8], eax
|
||||
mov edx, DWORD [ebp-4]
|
||||
mov eax, -858993459
|
||||
mul edx
|
||||
mov eax, edx
|
||||
shr eax, 3
|
||||
mov DWORD [ebp-4], eax
|
||||
lea eax, [ebp-5]
|
||||
add BYTE [eax], 48
|
||||
sub esp, 12
|
||||
mov eax, 0
|
||||
mov al, BYTE [ebp-5]
|
||||
push eax
|
||||
call _putc
|
||||
add esp, 16
|
||||
jmp L5
|
||||
L6:
|
||||
sub esp, 12
|
||||
mov al, BYTE [ebp+8]
|
||||
add eax, 48
|
||||
and eax, 255
|
||||
push eax
|
||||
call _putc
|
||||
add esp, 16
|
||||
leave
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
[global _putDec]
|
||||
_putDec:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 24
|
||||
cmp DWORD [ebp+8], 0
|
||||
jns L9
|
||||
sub esp, 12
|
||||
push 45
|
||||
call _putc
|
||||
add esp, 16
|
||||
neg DWORD [ebp+8]
|
||||
L9:
|
||||
mov DWORD [ebp-4], 1
|
||||
mov BYTE [ebp-5], 0
|
||||
L10:
|
||||
mov eax, DWORD [ebp+8]
|
||||
cmp eax, DWORD [ebp-4]
|
||||
jae L12
|
||||
jmp L11
|
||||
L12:
|
||||
mov eax, DWORD [ebp-4]
|
||||
mov edx, eax
|
||||
sal edx, 2
|
||||
add edx, eax
|
||||
lea eax, [edx+edx]
|
||||
mov DWORD [ebp-4], eax
|
||||
jmp L10
|
||||
L11:
|
||||
mov edx, DWORD [ebp-4]
|
||||
mov eax, -858993459
|
||||
mul edx
|
||||
mov eax, edx
|
||||
shr eax, 3
|
||||
mov DWORD [ebp-4], eax
|
||||
L13:
|
||||
cmp DWORD [ebp-4], 1
|
||||
ja L15
|
||||
jmp L14
|
||||
L15:
|
||||
mov edx, DWORD [ebp+8]
|
||||
mov eax, edx
|
||||
mov edx, 0
|
||||
div DWORD [ebp-4]
|
||||
mov DWORD [ebp-12], eax
|
||||
mov al, BYTE [ebp-12]
|
||||
mov BYTE [ebp-5], al
|
||||
mov eax, 0
|
||||
mov al, BYTE [ebp-5]
|
||||
imul eax, DWORD [ebp-4]
|
||||
sub DWORD [ebp+8], eax
|
||||
mov edx, DWORD [ebp-4]
|
||||
mov eax, -858993459
|
||||
mul edx
|
||||
mov eax, edx
|
||||
shr eax, 3
|
||||
mov DWORD [ebp-4], eax
|
||||
lea eax, [ebp-5]
|
||||
add BYTE [eax], 48
|
||||
sub esp, 12
|
||||
mov eax, 0
|
||||
mov al, BYTE [ebp-5]
|
||||
push eax
|
||||
call _putc
|
||||
add esp, 16
|
||||
jmp L13
|
||||
L14:
|
||||
sub esp, 12
|
||||
mov al, BYTE [ebp+8]
|
||||
add eax, 48
|
||||
and eax, 255
|
||||
push eax
|
||||
call _putc
|
||||
add esp, 16
|
||||
leave
|
||||
ret
|
||||
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
echo Backing up to .\Backup\%1
|
||||
|
||||
mkdir .\Backup\%1
|
||||
|
||||
copy *.h .\Backup\%1
|
||||
copy *.c .\Backup\%1
|
||||
copy *.inc .\Backup\%1
|
||||
copy *.asm .\Backup\%1
|
||||
copy *.ld .\Backup\%1
|
||||
copy *.bat .\Backup\%1
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
|
||||
%define VERSION "0.1.2" ;HOS version
|
||||
%define VERSION "0.13" ;HOS version
|
||||
|
||||
%define BOOT_FAT_SEG 0x07E0 ;right after boot sector
|
||||
%define BOOT_ROOT_SEG 0x0900 ;right after FAT
|
||||
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
|
||||
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
|
||||
%define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at
|
||||
%define BOOT_KERNEL_ADD 0x100000 ;final pmode kernel destination - physical
|
||||
%define BOOT_KERNEL_ADD 0x106000 ;final pmode kernel destination - physical
|
||||
%define BOOT_RD_ADD 0x200000 ;2mb for ram disk
|
||||
|
||||
%define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
gcc -ffreestanding -fno-builtin -nostdlib -nodefaultlibs -c kernel.c -o kernel.o
|
||||
@@ -0,0 +1 @@
|
||||
nasmw -f aout -o asmfuncs.o -l .\lst\asmfuncs.lst asmfuncs.asm
|
||||
@@ -0,0 +1,2 @@
|
||||
rem rawrite -f stage1.bin -d a -n
|
||||
partcopy stage1.bin 0 200 -f0
|
||||
@@ -0,0 +1 @@
|
||||
nasmw -f bin -o stage1.bin -l .\lst\stage1.lst stage1.asm
|
||||
@@ -0,0 +1 @@
|
||||
nasmw -f bin -o stage2.bin -l .\lst\stage2.lst stage2.asm
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned char byte;
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
//fdc.c
|
||||
//Author: Josh Holtrop
|
||||
//Date: 10/30/03
|
||||
|
||||
|
||||
inline void fdc_sendDOR(byte dor)
|
||||
{
|
||||
outportb(FDC_DOR, dor);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//fdc.h
|
||||
//Author: Josh Holtrop
|
||||
//Date: 10/30/03
|
||||
|
||||
|
||||
#define FDC_DOR 0x3f2
|
||||
#define FDC_MSR 0x3f4
|
||||
|
||||
|
||||
inline void fdc_sendDOR(byte dor);
|
||||
|
||||
|
||||
+30
-5
@@ -1,19 +1,44 @@
|
||||
//functions.h
|
||||
//05/07/03 Josh Holtrop
|
||||
//for HOS
|
||||
//Modified: 10/30/03
|
||||
|
||||
|
||||
extern dword _code;
|
||||
extern dword _bss;
|
||||
extern dword _end;
|
||||
|
||||
inline void outportb(unsigned int port, unsigned char value);
|
||||
inline void outportw(unsigned int port, unsigned int value);
|
||||
inline byte inportb(unsigned short port);
|
||||
void enable_ints();
|
||||
void disable_ints();
|
||||
inline void enable_ints();
|
||||
inline void disable_ints();
|
||||
inline void restart();
|
||||
inline void halt();
|
||||
void remap_pics(int pic1, int pic2);
|
||||
inline void pic1_mask(byte mask);
|
||||
inline void pic2_mask(byte mask);
|
||||
inline void eoi();
|
||||
|
||||
|
||||
inline void eoi2();
|
||||
inline dword kernel_size();
|
||||
inline void init_timer();
|
||||
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
|
||||
@@ -1,8 +1,11 @@
|
||||
|
||||
;gdt.inc
|
||||
;Author: Josh Holtrop
|
||||
;for HOS
|
||||
;Modified: 10/30/03
|
||||
|
||||
gdtr:
|
||||
dw gdt_end-gdt-1
|
||||
dd GDT
|
||||
dd GDT_P
|
||||
gdt:
|
||||
dd 0
|
||||
dd 0
|
||||
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
partcopy -f0 0 168000 flop.img
|
||||
@@ -1,11 +1,16 @@
|
||||
;idt.inc
|
||||
;Author: Josh Holtrop
|
||||
;for HOS
|
||||
;Modified: 10/30/03
|
||||
|
||||
idtr:
|
||||
dw 50*8-1 ;size of idt
|
||||
dd IDT ;address of idt
|
||||
dd IDT_V ;address of idt
|
||||
|
||||
|
||||
%macro isr_label 1
|
||||
isr_%1:
|
||||
push eax
|
||||
mov eax, %1
|
||||
jmp isr_main
|
||||
%endmacro
|
||||
@@ -62,6 +67,9 @@ isr_label 48
|
||||
isr_label 49
|
||||
|
||||
isr_main:
|
||||
cmp eax, 0x30
|
||||
jz isr_syscall
|
||||
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
@@ -75,10 +83,27 @@ isr_main:
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
pop eax
|
||||
|
||||
iret
|
||||
|
||||
|
||||
isr_syscall:
|
||||
pop eax ;syscall function number
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
|
||||
push ebx
|
||||
call _putc
|
||||
add esp, 4
|
||||
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
iret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,530 +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 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 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 = 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 al, '%'
|
||||
jzfar printf_percent
|
||||
cmp ecx, 1
|
||||
jz printf_special
|
||||
|
||||
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(word pos);
|
||||
word getCursorPosition();
|
||||
int putc(byte 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
|
||||
|
||||
+7
-1
@@ -1,5 +1,6 @@
|
||||
//k_defines.h
|
||||
//03/17/03 Josh Holtrop
|
||||
//Modified: 10/30/03
|
||||
|
||||
#define PIC1 0x20
|
||||
#define PIC2 0xA0
|
||||
@@ -28,7 +29,12 @@
|
||||
#define YELLOW_TXT 0x0E
|
||||
#define BRWHITE_TXT 0x0F
|
||||
|
||||
#define FREERAM_START 0x268000
|
||||
#define FREERAM_START 0x368000 // 0x368000 is first available byte (this is right after the initrd @ 2mb, 1440kb.
|
||||
#define MAX_RAM 0x40000000 //1gb maximum RAM supported
|
||||
|
||||
#define PID_KERNEL 0x02 //kernel's PID
|
||||
#define PID_VMM 0x03
|
||||
#define PID_USER 0x10000 //user processes' start PID
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
|
||||
+49
-10
@@ -1,18 +1,56 @@
|
||||
;kernel.asm
|
||||
;Author: Josh Holtrop
|
||||
;Modified: 10/30/03
|
||||
|
||||
%include "bootdef.inc"
|
||||
|
||||
%define GDT 0x140000
|
||||
%define IDT 0x150000
|
||||
%define GDT_P 0x100000; ;1mb physical - Global Descriptor Table space
|
||||
%define GDT_V GDT_P+0xC0000000
|
||||
%define IDT_P 0x102000 ;1mb+8kb - Interrupt Descriptor Table space
|
||||
%define IDT_V IDT_P+0xC0000000
|
||||
%define PDBR_P 0x104000 ;1mb+16kb - Page Directory Base Register (first PD)
|
||||
%define PDBR_V PDBR_P+0xC0000000
|
||||
%define LOPT_P 0x105000 ;1mb+20kb - LOw Page Table for mapping first 4mb
|
||||
%define LOPT_V LOPT_P+0xC0000000
|
||||
%define KERNEL_P 0x106000 ;1mb+24kb - the kernel's physical address
|
||||
%define KERNEL_V KERNEL_P+0xC0000000 ;3gb+1mb+24kb, the virtual address of the kernel
|
||||
|
||||
[global start]
|
||||
[extern _isr]
|
||||
[extern _k_init]
|
||||
[extern _putc]
|
||||
|
||||
bits 32
|
||||
|
||||
;This is where the kernel begins execution
|
||||
;At this point, the temporary gdt is set up to "map" 0xC000_0000 to 0x0.
|
||||
;We must enable paging with the first 4mb mapped 1:1 virtual:physical
|
||||
; and with the 4mb starting at 0xC000_0000 mapped to the first 4mb physical.
|
||||
;Then we can start using our "real" gdt, then unmap the lower 4mb.
|
||||
start:
|
||||
cli ;if they weren't already off
|
||||
mov edi, GDT
|
||||
cli ;if they weren't already off
|
||||
|
||||
xor eax, eax
|
||||
mov edi, PDBR_V
|
||||
mov ecx, 1024 ;clear the PDBR
|
||||
rep stosd
|
||||
mov [PDBR_V], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
||||
mov [PDBR_V+0xC00], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
||||
|
||||
mov edi, LOPT_V
|
||||
mov ecx, 1024
|
||||
mov eax, 0x03 ;starting physical address = 0x0 (read/write, present flags)
|
||||
fill_lopt_loop: ;fill the page table
|
||||
stosd
|
||||
add eax, 4096 ;increment next phsyical address by 4kb
|
||||
loop fill_lopt_loop
|
||||
|
||||
mov eax, PDBR_P
|
||||
mov cr3, eax ;store the Page Directory Base Address
|
||||
mov eax, cr0
|
||||
or eax, 0x80000000 ;set page enable bit
|
||||
mov cr0, eax ;now paging is active!
|
||||
|
||||
|
||||
mov edi, GDT_V
|
||||
mov esi, gdt
|
||||
mov ecx, gdt_end-gdt
|
||||
copy_gdt:
|
||||
@@ -20,7 +58,7 @@ copy_gdt:
|
||||
stosb
|
||||
loop copy_gdt
|
||||
|
||||
mov edi, IDT ;destination
|
||||
mov edi, IDT_V ;destination
|
||||
mov esi, isr_0 ;address of isr0
|
||||
mov edx, isr_1-isr_0 ;distance between isr labels
|
||||
mov ecx, 50 ;number of isrlabels
|
||||
@@ -38,6 +76,7 @@ fill_idt:
|
||||
mov esi, ebx
|
||||
add esi, edx
|
||||
loop fill_idt
|
||||
mov word [IDT_V+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
|
||||
|
||||
lgdt [gdtr] ;load gdt
|
||||
jmp KERNEL_CODE:newgdtcontinue
|
||||
@@ -48,15 +87,15 @@ newgdtcontinue:
|
||||
mov gs, ax
|
||||
mov fs, ax
|
||||
mov ss, ax
|
||||
mov esp, 0x1ffffc ;stack just under 2mb, moves downward
|
||||
mov esp, 0xc01ffffc ;stack just under 3gb+2mb, moves downward
|
||||
lidt [idtr] ;load idt
|
||||
|
||||
call _k_init
|
||||
haltit:
|
||||
hlt ;halt processor when k_init is done
|
||||
jmp $ ;shouldn't get here...
|
||||
jmp haltit ;shouldn't get here...
|
||||
|
||||
%include "gdt.inc"
|
||||
%include "idt.inc"
|
||||
|
||||
|
||||
|
||||
@@ -1,91 +1,139 @@
|
||||
//kernel.c
|
||||
//08/13/03 Josh Holtrop
|
||||
//Holtrop's Operating System
|
||||
//Version: 0.12
|
||||
//Modified: 12/30/03
|
||||
|
||||
#define VXR video_mode.XResolution
|
||||
#define VYR video_mode.YResolution
|
||||
#include "k_defines.h" //#DEFINE's for kernel
|
||||
|
||||
#include "k_defines.h"
|
||||
|
||||
#include "lib/string.h"
|
||||
#include "lib/io.h"
|
||||
|
||||
#include "functions.h"
|
||||
#include "video.h"
|
||||
#include "mm.h"
|
||||
#include "keyboard.h"
|
||||
#include "functions.h" //general functions
|
||||
#include "video.h" //video functions
|
||||
#include "mm.h" //physical memory management functions
|
||||
#include "vmm.h" //virtual memory management & paging functions
|
||||
#include "keyboard.h" //generic keyboard driver & functions
|
||||
#include "mouse.h" //generic ps/2 mouse driver & functions
|
||||
#include "fdc.h" //Floppy Disk Controller functions
|
||||
#include "stdfont.h" //Standard font bitmask array
|
||||
#include "kio.h"
|
||||
#include "vfs.h"
|
||||
#include "rd.h"
|
||||
#include "fat12.h"
|
||||
|
||||
void isr(dword num);
|
||||
void k_init();
|
||||
|
||||
/* These functions are defined in asmfuncs.asm */
|
||||
extern dword write_cr0(dword cr0);
|
||||
extern dword read_cr0();
|
||||
extern dword write_cr3(dword cr3);
|
||||
extern dword read_cr2();
|
||||
extern dword read_cr3();
|
||||
extern void writeCursorPosition(dword pos);
|
||||
extern dword getCursorPosition();
|
||||
extern void console_scroll();
|
||||
extern void console_cls();
|
||||
extern int puts(char *str);
|
||||
extern int putDec(int number);
|
||||
extern int putDecu(dword number);
|
||||
extern void strcpy(char *dest, char *src);
|
||||
extern void memcpy(void *dest, void *src, dword n);
|
||||
extern dword strlen(char *str);
|
||||
|
||||
#include "fat12.c"
|
||||
#include "rd.c"
|
||||
#include "vfs.c"
|
||||
#include "kio.c"
|
||||
#include "fdc.c"
|
||||
#include "mouse.c"
|
||||
#include "keyboard.c"
|
||||
#include "mm.c"
|
||||
#include "vmm.c"
|
||||
#include "functions.c"
|
||||
#include "video.c"
|
||||
|
||||
dword timer = 0;
|
||||
dword timer = 0;
|
||||
|
||||
//Main kernel initialization method
|
||||
void k_init()
|
||||
{
|
||||
remap_pics(0x20, 0x28);
|
||||
//set timer : 2e9c = 100hz
|
||||
outportb(0x43, 0x34);
|
||||
outportb(0x40, 0x9c); //lsb
|
||||
outportb(0x40, 0x2e); //msb
|
||||
video_init((ModeInfoBlock *) 0x90306);
|
||||
mm_init();
|
||||
enable_ints();
|
||||
// ===== Initialization
|
||||
fdc_sendDOR(0x0C); //turn off floppy motor!!
|
||||
console_cls();
|
||||
printf("Memory available to OS: %d MB\n (Bytes: %d)", mm_totalmem/0x100000, mm_totalmem);
|
||||
video_init();
|
||||
mm_init();
|
||||
vmm_init();
|
||||
remap_pics(0x20, 0x28);
|
||||
init_timer();
|
||||
mouse_init();
|
||||
pic1_mask(0); //unmask IRQ's 0-7
|
||||
pic2_mask(0); //unmask IRQ's 8-15
|
||||
vfs_init();
|
||||
enable_ints();
|
||||
kbd_resetLEDs(); //after enabling interrupts!!
|
||||
if (videoMode)
|
||||
{
|
||||
int p = video_mode.XResolution*video_mode.YResolution-1;
|
||||
for (; p >= 0; p--)
|
||||
video_psetp(p, 0x00000044);
|
||||
video_drawConsole();
|
||||
}
|
||||
|
||||
for (;;)
|
||||
printf("%c ", kbdWaitKey());
|
||||
/* pageblock *pb = first_pageblock;
|
||||
printf("HOS 0.13 - Kernel File Size: %u kb\tData Size: %u bytes\n", kernel_size()>>10, (dword)(&_end)-(dword)(&_code));
|
||||
printf("Memory available to OS: %u MB (%u bytes)\n", mm_megabytes, mm_totalmem);
|
||||
printf("Free memory: %u bytes (%u pages)\n", mm_freemem(), mm_freemem()>>12);
|
||||
printf("%d/%d/%d\t%d:%d:%d\n", rtc_readMonth(), rtc_readDay(), rtc_readYear(), rtc_readHour(), rtc_readMinute(), rtc_readSecond());
|
||||
printf("Root Directory: %s/\n", rootDevice->id);
|
||||
|
||||
|
||||
/* int a;
|
||||
byte *addr = 0;
|
||||
for (a = 0; a < 5; a++)
|
||||
{
|
||||
byte *app = mm_palloc();
|
||||
vmm_map1((dword)addr, (dword)app);
|
||||
addr += 4096;
|
||||
}
|
||||
|
||||
addr = vfs_readFile("/bin/hash.hos");
|
||||
memcpy(0, addr, 4192);
|
||||
asm("call 0");
|
||||
free(addr);
|
||||
*/
|
||||
|
||||
dword key = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->flags == MM_PB_NP)
|
||||
break;
|
||||
printf("\nBase: 0x%x; Limit: 0x%x; Flags: 0x%x, Link: 0x%x", pb->base, pb->length, pb->flags, pb->link);
|
||||
pb = (pageblock *) pb->link;
|
||||
} */
|
||||
key = kbdWaitKey();
|
||||
if ((key & 0xFF) > 2) //key is not a control key
|
||||
putc(key);
|
||||
}
|
||||
}
|
||||
|
||||
// main Interrupt Service Routine - handles all interrupts unless caught by kernel.asm
|
||||
void isr(dword num)
|
||||
{
|
||||
switch(num)
|
||||
{
|
||||
case 0x20:
|
||||
case 14:
|
||||
printf("Page fault, CR2 = 0x%x\n", read_cr2());
|
||||
halt();
|
||||
break;
|
||||
case 0x20: // IRQ0 - timer interrupt
|
||||
timer++;
|
||||
(*(byte *)0xb8000)++;
|
||||
switch(timer)
|
||||
{
|
||||
case 150:
|
||||
video_rectf(VXR*3/11, 0, VXR*4/11, VYR-1, 0x00000088);
|
||||
break;
|
||||
case 200:
|
||||
video_rectf(VXR*7/11, 0, VXR*8/11, VYR-1, 0x00000088);
|
||||
break;
|
||||
case 250:
|
||||
video_rectf(VXR/11, 0, VXR*2/11, VYR*2/5, 0x00000088);
|
||||
break;
|
||||
case 300:
|
||||
video_rectf(VXR/11, VYR*3/5, VXR*2/11, VYR-1, 0x00000088);
|
||||
break;
|
||||
case 350:
|
||||
video_rectf(VXR*5/11, VYR/5, VXR*6/11, VYR*4/5, 0x00000088);
|
||||
break;
|
||||
case 400:
|
||||
video_rectf(VXR*9/11, VYR/5, VXR-1, VYR*2/5, 0x00000088);
|
||||
break;
|
||||
case 450:
|
||||
video_rectf(VXR*8/11, VYR*3/5, VXR*10/11, VYR*4/5, 0x00000088);
|
||||
break;
|
||||
}
|
||||
(*(byte *)(0xc00b8000))++;
|
||||
eoi();
|
||||
break;
|
||||
case 0x21:
|
||||
printf("------------------KEYBOARD ISR--------------------------\n");
|
||||
isr_keyboard();
|
||||
case 0x21: // IRQ1 - keyboard interrupt
|
||||
isr_keyboard(); //isr_keybard() takes care of calling eoi()
|
||||
break;
|
||||
case 0x2C: // IRQ12 - PS/2 mouse
|
||||
isr_mouse();
|
||||
eoi2();
|
||||
break;
|
||||
default:
|
||||
printf("Interrupt %d (0x%x) Unhandled!!\n", num, num);
|
||||
halt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+43
-38
@@ -1,53 +1,55 @@
|
||||
//Keyboard.c
|
||||
// Created: 04/17/03 Josh Holtrop
|
||||
// Modified: 09/09/03
|
||||
// Modified: 10/30/03
|
||||
//for HOS
|
||||
|
||||
#define KBD_BUFFER_LENGTH 64
|
||||
|
||||
byte kbdFlags = 0;
|
||||
byte kbdAscii = 0;
|
||||
byte kbdScan = 0;
|
||||
byte kbdFlags = 0; //holds current keyboard flags - caps/num/scroll/shift/ctrl/alt
|
||||
byte kbdAscii = 0; //holds ASCII value of a key pressed
|
||||
byte kbdScan = 0; //holds the keyboard scan code of a key pressed
|
||||
|
||||
dword kbdBuffer[KBD_BUFFER_LENGTH];
|
||||
byte kbdBufferStart = 0;
|
||||
byte kbdBufferLen = 0;
|
||||
byte kbdExt = 0;
|
||||
byte kbdExt2 = 0;
|
||||
dword kbdBuffer[KBD_BUFFER_LENGTH]; //a buffer for all keypresses
|
||||
int kbdBufferStart = 0; //position of next key in buffer
|
||||
int kbdBufferLen = 0; //number of keys left in the buffer
|
||||
byte kbdExt = 0; //# of extended key codes left to input
|
||||
byte kbdExt2 = 0; //# of 2nd-set-extended key codes left to input
|
||||
byte ackReason = 0; //used to record the reason why we would get an acknowledge byte (0xFA)
|
||||
|
||||
|
||||
//these arrays convert a keyboard scan code to an ASCII character value
|
||||
//nul esc bksp tab lctl lsft rsft lalt caps F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 numScrlNumPad------- unknown---- F11 F12 unknown....
|
||||
const byte SCAN2ASCII[128] = "\000\0331234567890-=\010\011qwertyuiop[]\n\001asdfghjkl;'`\001\\zxcvbnm,./\001*\001 \001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001-\001\001\001+\001\001\001\001\001\002\002\002\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002";
|
||||
const byte SCAN2ASCIISHIFT[128] = "\000\033!@#$%^&*()_+\010\011QWERTYUIOP{}\n\001ASDFGHJKL:\"~\001|ZXCVBNM<>?\001*\001 \001\001\001\001\001\001\001\001\001\001\001\001\001789-456+1230.\002\002\002\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002";
|
||||
|
||||
//====FUNCTIONS:
|
||||
|
||||
// The Keyboard Interrupt Service Routine
|
||||
void isr_keyboard()
|
||||
{
|
||||
kbdScan = inportb(0x60);
|
||||
//printf("\nKEYBOARD INTERRUPT: 0x%x", kbdScan);
|
||||
byte inState = inportb(0x61);
|
||||
outportb(0x61, inState|0x80);
|
||||
outportb(0x61, inState);
|
||||
|
||||
printf("IRQ 1: %x\n", kbdScan);
|
||||
//printf("IRQ 1: %x\n", kbdScan);
|
||||
|
||||
if (kbdScan == 0xFA) //250 //ACKnowledge
|
||||
{
|
||||
//printf("KBD_ACK 0x%x!\n", ackReason);
|
||||
if (ackReason == 0xED) //reset LEDs
|
||||
{
|
||||
outportb(0x64, (kbdFlags & 0x07));
|
||||
printf("KBD_ACK!");
|
||||
outportb(0x60, (kbdFlags & 0x07));
|
||||
}
|
||||
ackReason = 0;
|
||||
}
|
||||
if (kbdScan == 224) //extended key
|
||||
if (kbdScan == 224) //extended key
|
||||
{
|
||||
kbdExt = 1;
|
||||
eoi();
|
||||
return;
|
||||
}
|
||||
if (kbdScan == 225)
|
||||
if (kbdScan == 225) //2nd-set-extended key
|
||||
{
|
||||
kbdExt2 = 2;
|
||||
eoi();
|
||||
@@ -56,7 +58,7 @@ void isr_keyboard()
|
||||
|
||||
//====handle control keys::
|
||||
kbdAscii = 2;
|
||||
switch (kbdScan) //control keys
|
||||
switch (kbdScan) //control keys
|
||||
{
|
||||
case KBD_SCAN_LSHIFT:
|
||||
kbdFlags |= KBD_SHIFT;
|
||||
@@ -95,17 +97,17 @@ void isr_keyboard()
|
||||
case KBD_SCAN_CAPS+KBD_SCAN_RELEASED:
|
||||
kbdFlags ^= KBD_CAPS;
|
||||
kbdAscii = 1;
|
||||
kbd_resetLEDs(); //update LEDs
|
||||
kbd_resetLEDs(); //update LEDs
|
||||
break;
|
||||
case KBD_SCAN_SCROLL+KBD_SCAN_RELEASED:
|
||||
kbdFlags ^= KBD_SCROLL;
|
||||
kbdAscii = 1;
|
||||
kbd_resetLEDs(); //update LEDs
|
||||
kbd_resetLEDs(); //update LEDs
|
||||
break;
|
||||
case KBD_SCAN_NUM+KBD_SCAN_RELEASED:
|
||||
kbdFlags ^= KBD_NUM;
|
||||
kbdAscii = 1;
|
||||
kbd_resetLEDs(); //update LEDs
|
||||
kbd_resetLEDs(); //update LEDs
|
||||
break;
|
||||
}
|
||||
if (kbdAscii == 1)
|
||||
@@ -169,7 +171,8 @@ void isr_keyboard()
|
||||
}
|
||||
|
||||
//====do something with key::
|
||||
if ((kbdScan == 83) & ((kbdFlags & KBD_CTRL) != 0) & ((kbdFlags & KBD_ALT) != 0))
|
||||
// printf("kbdScan == %d\nkbdAscii == %d\nkbdFlags == %d\n", kbdScan, kbdAscii, kbdFlags);
|
||||
if ((kbdScan == 83) && (kbdFlags & KBD_CTRL) && (kbdFlags & KBD_ALT))
|
||||
{
|
||||
printf("Initiating reboot.");
|
||||
restart();
|
||||
@@ -188,57 +191,59 @@ void isr_keyboard()
|
||||
}
|
||||
else
|
||||
{
|
||||
kbdBuffer[(kbdBufferStart+kbdBufferLen)%KBD_BUFFER_LENGTH] = (dword) ((kbdFlags << 16) | (kbdScan << 8) | kbdAscii);
|
||||
kbdBufferLen++;
|
||||
kbdBuffer[(kbdBufferStart+kbdBufferLen++)%KBD_BUFFER_LENGTH] = (dword) ((kbdFlags << 16) | (kbdScan << 8) | kbdAscii);
|
||||
// printf("S:%d\tL:%d\tR:%x\n", kbdBufferStart, kbdBufferLen, kbdBuffer[kbdBufferStart]);
|
||||
}
|
||||
}
|
||||
|
||||
eoi();
|
||||
|
||||
// if (key == 0xFA) //ACKnowledge
|
||||
// outportb(0x60, 0x3);
|
||||
};
|
||||
}
|
||||
|
||||
inline byte switchCase(byte asciiCode)
|
||||
//Switches the case of an ASCII character
|
||||
/*inline byte (byte asciiCode)
|
||||
{
|
||||
if ((asciiCode >= 'A') & (asciiCode <= 'Z'))
|
||||
return (asciiCode + ('a' - 'A'));
|
||||
if ((asciiCode >= 'a') & (asciiCode <= 'z'))
|
||||
return (asciiCode - ('a' - 'A'));
|
||||
return asciiCode;
|
||||
}
|
||||
}*/
|
||||
|
||||
//Gets a key from the buffer, returns 0 if no keys available, returns immediately
|
||||
dword kbdGetKey()
|
||||
{
|
||||
if (kbdBufferLen == 0) //buffer empty
|
||||
return 0;
|
||||
dword retVal = kbdBuffer[kbdBufferStart];
|
||||
printf("S:%d\tE:%d\tR:%x\n", kbdBufferStart, kbdBufferLen, retVal);
|
||||
kbdBufferStart++;
|
||||
kbdBufferLen--;
|
||||
if (kbdBufferStart == KBD_BUFFER_LENGTH)
|
||||
if (kbdBufferStart >= KBD_BUFFER_LENGTH)
|
||||
kbdBufferStart = 0;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//Gets a key from the buffer, if no keys available, waits for one to be entered
|
||||
dword kbdWaitKey()
|
||||
{
|
||||
dword retVal = 0;
|
||||
for (;;)
|
||||
{
|
||||
retVal = kbdGetKey();
|
||||
if (retVal != 0)
|
||||
{
|
||||
printf("S:%d\tE:%d\tR:%x\n", kbdBufferStart, kbdBufferLen, retVal);
|
||||
return retVal;
|
||||
}
|
||||
if (kbdBufferLen != 0) //buffer empty
|
||||
break;
|
||||
}
|
||||
dword retVal = kbdBuffer[kbdBufferStart];
|
||||
kbdBufferStart++;
|
||||
kbdBufferLen--;
|
||||
if (kbdBufferStart >= KBD_BUFFER_LENGTH)
|
||||
kbdBufferStart = 0;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//Resets the keyboard LEDs to reflect the current state of the num lock, caps lock, and scroll lock bits
|
||||
inline void kbd_resetLEDs()
|
||||
{
|
||||
outportb(0x64, 0xED);
|
||||
//outportb(0x64, (kbdFlags & 0x07));
|
||||
outportb(0x60, 0xED);
|
||||
//outportb(0x60, (kbdFlags & 0x07));
|
||||
ackReason = 0xED;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ld -nodefaultlibs -nostdlib -T link.ld -o kernel.bin -Map .\lst\LDout.doc ks.o kernel.o asmfuncs.o
|
||||
@@ -2,7 +2,7 @@ OUTPUT_FORMAT("binary")
|
||||
ENTRY(start)
|
||||
SECTIONS
|
||||
{
|
||||
.text 0x100000 : {
|
||||
.text 0xC0106000 : {
|
||||
code = .; _code = .; __code = .;
|
||||
*(.text)
|
||||
. = ALIGN(4096);
|
||||
|
||||
@@ -1,233 +1,112 @@
|
||||
// mm.c
|
||||
// 09/01/03 Josh Holtrop
|
||||
// Author: Josh Holtrop
|
||||
// Created: 09/01/03
|
||||
// Modified: 12/28/03
|
||||
|
||||
// 0x368000 is first available byte (this is right after the kernel @ 1mb and the initrd @ 2mb, 1440kb.
|
||||
|
||||
|
||||
pageblock *first_pageblock = (pageblock *) 0;
|
||||
dword mm_totalmem = 0x100000; //assume 1mb
|
||||
//The total amount of physical memory available (bytes)
|
||||
#define BITMAP_SIZE 0x20000
|
||||
dword mm_totalmem = 0;
|
||||
dword mm_megabytes;
|
||||
byte page_bitmap[BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available
|
||||
//0x20000*(8 bits/byte)=0x100000 pages in 4gb total
|
||||
|
||||
//This function initializes the memory manager's linked list, filling it with the
|
||||
// memory areas returned by bios interrupt 0x8E20
|
||||
void mm_init()
|
||||
{
|
||||
dword *memmap_entries = (dword *) 0x9040A;
|
||||
memmap_entry *maps = (memmap_entry *) 0x92000;
|
||||
dword memmap_entries = *(dword *)0xC009040A;
|
||||
memmap_entry *maps = (memmap_entry *) 0xC0092000;
|
||||
dword a;
|
||||
for (a=0;a<(*memmap_entries);a++)
|
||||
for (a = 0; a < BITMAP_SIZE; a++)
|
||||
{
|
||||
page_bitmap[a] = 0xFF; //all pages used
|
||||
}
|
||||
for (a = 0; a < memmap_entries; a++)
|
||||
{
|
||||
if (maps[a].attributes == 1) // (1) mem free to OS
|
||||
{
|
||||
mm_totalmem += maps[a].limit.lowdword;
|
||||
if ((maps[a].base.lowdword + maps[a].limit.lowdword) > (FREERAM_START+8192)) //goes past where we start freeram
|
||||
if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram
|
||||
{
|
||||
if (maps[a].base.lowdword < FREERAM_START)
|
||||
{
|
||||
maps[a].limit.lowdword = maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword);
|
||||
maps[a].base.lowdword = FREERAM_START; //block at least 4kb, starts >= FREERAM_START
|
||||
mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
|
||||
}
|
||||
if (first_pageblock == 0) //no pageblock page set up yet, so set it up here
|
||||
else
|
||||
{
|
||||
first_pageblock = (pageblock *) maps[a].base.lowdword ;
|
||||
maps[a].base.lowdword += 4096;
|
||||
maps[a].limit.lowdword -= 4096;
|
||||
mm_init_pageblockpage(first_pageblock);
|
||||
first_pageblock->base = maps[a].base.lowdword;
|
||||
first_pageblock->length = maps[a].limit.lowdword / 4096;
|
||||
first_pageblock->flags = MM_PB_AVAIL;
|
||||
}
|
||||
else //first_pageblock already set up, add on segment
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->flags == MM_PB_NP)
|
||||
break;
|
||||
else
|
||||
pb++;
|
||||
}
|
||||
pb->base = maps[a].base.lowdword;
|
||||
pb->length = maps[a].limit.lowdword / 4096;
|
||||
pb->flags = MM_PB_AVAIL;
|
||||
mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (first_pageblock == 0)
|
||||
if (mm_totalmem % 0x100000)
|
||||
mm_megabytes = (mm_totalmem >> 20) + 1;
|
||||
else
|
||||
mm_megabytes = mm_totalmem >> 20;
|
||||
}
|
||||
|
||||
|
||||
// This function frees a certain number of pages starting at the address
|
||||
// specified in base for a length of pages pages
|
||||
void mm_pfreen(dword base, dword pages)
|
||||
{
|
||||
dword a;
|
||||
dword max = base + (pages << 12);
|
||||
for (a = base; a < max; a += 4096)
|
||||
{
|
||||
printf("ERROR! NO INITIAL PAGE BLOCK COULD BE CREATED.");
|
||||
asm("cli");
|
||||
asm("hlt");
|
||||
mm_pfree(a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mm_init_pageblockpage(pageblock *pbp)
|
||||
// This function frees a single page
|
||||
void mm_pfree(dword base)
|
||||
{
|
||||
pageblock *pb = pbp;
|
||||
int a;
|
||||
for (a=0; a<512; a++)
|
||||
{
|
||||
pb->base = 0;
|
||||
pb->length = 0;
|
||||
pb->flags = MM_PB_NP;
|
||||
if (a<511)
|
||||
pb->link = (dword)pb + sizeof(pageblock);
|
||||
else
|
||||
pb->link = 0;
|
||||
pb++;
|
||||
}
|
||||
// dword pageNumber = base >> 12; // >>12 == /4096
|
||||
dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
|
||||
dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
|
||||
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
|
||||
}
|
||||
|
||||
|
||||
void *mm_palloc(dword numpages)
|
||||
// This function allocates a single page, returning its physical address
|
||||
void *mm_palloc()
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
dword freeentries = mm_freeentries();
|
||||
if (freeentries < 2)
|
||||
dword bite;
|
||||
for (bite = 0; bite < BITMAP_SIZE; bite++)
|
||||
{
|
||||
if(mm_new_pageblock_page() == 0)
|
||||
return 0;
|
||||
}
|
||||
pageblock *newentry = mm_nextpageblockentry();
|
||||
for (;;)
|
||||
{
|
||||
if ((pb->flags == 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->flags = MM_PB_USED;
|
||||
return pb;
|
||||
}
|
||||
else //subtract out allocated number of pages from length
|
||||
{
|
||||
newentry->base = pb->base;
|
||||
newentry->length = numpages;
|
||||
newentry->flags = MM_PB_USED;
|
||||
pb->base += (numpages * 4096);
|
||||
pb->length -= numpages;
|
||||
return (void *)newentry->base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dword mm_freeentries()
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
dword counter = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->flags == MM_PB_NP)
|
||||
counter++;
|
||||
if (pb->link == 0)
|
||||
return counter;
|
||||
pb = (pageblock *) pb->link;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pageblock *mm_new_pageblock_page()
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
for (;;)
|
||||
{
|
||||
if ((pb->flags == MM_PB_AVAIL) && (pb->length > 1))
|
||||
if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int mm_pfree(void *ptr)
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
dword tofree = (dword) ptr;
|
||||
for (;;)
|
||||
{
|
||||
if ((pb->base == tofree) && (pb->flags == MM_PB_USED))
|
||||
{
|
||||
pb->flags = MM_PB_AVAIL; //found block, mark available / coalesce it
|
||||
pageblock *pbc = first_pageblock;
|
||||
for (;;)
|
||||
int bit;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
if (pbc->flags == MM_PB_AVAIL)
|
||||
{
|
||||
if ((pbc->base + (pbc->length * 4096)) == pb->base) //pbc ends where pb starts
|
||||
{
|
||||
pbc->length += pb->length; //extend pbc's length by pb's length
|
||||
pb->flags = MM_PB_NP; //mark pb as an unused entry
|
||||
return 0;
|
||||
}
|
||||
if ((pb->base + (pb->length * 4096)) == pbc->base) //pb ends where pb starts
|
||||
{
|
||||
pb->length += pbc->length;
|
||||
pbc->flags = MM_PB_NP;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (pbc->link == 0) //no entry found to consolidate...
|
||||
return 0;
|
||||
pbc = (pageblock *) pbc->link; //next entry to test
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pb->link == 0)
|
||||
return 1;
|
||||
pb = (pageblock *) pb->link;
|
||||
}
|
||||
return 0; //no free page
|
||||
}
|
||||
|
||||
|
||||
pageblock *mm_lastpageblockentry()
|
||||
// This function reports the number of bytes of free physical memory
|
||||
dword mm_freemem()
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
for (;;)
|
||||
dword a;
|
||||
dword pages = 0;
|
||||
for (a = 0; a < BITMAP_SIZE; a++)
|
||||
{
|
||||
if (pb->link == 0)
|
||||
return pb;
|
||||
pb = (pageblock *)pb->link;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pageblock *mm_nextpageblockentry()
|
||||
{
|
||||
pageblock *pb = first_pageblock;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->flags == MM_PB_NP)
|
||||
return pb;
|
||||
if (pb->link == 0)
|
||||
return 0;
|
||||
pb = (pageblock *)pb->link;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dword mm_freemem()
|
||||
{
|
||||
dword amount = 0;
|
||||
pageblock *pb = first_pageblock;
|
||||
for (;;)
|
||||
{
|
||||
if (pb->flags == MM_PB_AVAIL)
|
||||
amount += (pb->length)*4096;
|
||||
if (pb->link == 0)
|
||||
return amount;
|
||||
pb = (pageblock *) pb->link;
|
||||
int bit;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
if (!(page_bitmap[a] & (1 << bit)))
|
||||
pages++;
|
||||
}
|
||||
}
|
||||
return pages << 12;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,29 +7,14 @@ typedef struct {
|
||||
} __attribute__((packed)) memmap_entry;
|
||||
|
||||
|
||||
typedef struct {
|
||||
dword base;
|
||||
dword length; //in pages
|
||||
dword flags;
|
||||
dword link;
|
||||
} __attribute__ ((packed)) pageblock; //16 byte pageblock entry - 512 entries = 1 page
|
||||
|
||||
|
||||
void mm_init();
|
||||
void mm_init_pageblockpage(pageblock *pbp);
|
||||
void *mm_palloc(dword numpages);
|
||||
int mm_pfree(void *ptr);
|
||||
dword mm_freeentries();
|
||||
pageblock *mm_new_pageblock_page();
|
||||
pageblock *mm_lastpageblockentry();
|
||||
pageblock *mm_nextpageblockentry();
|
||||
dword mm_freemem();
|
||||
|
||||
|
||||
#define MM_PB_FLAGMASK 0x03 //00000011
|
||||
#define MM_PB_NP 0x00 //00000000
|
||||
#define MM_PB_AVAIL 0x01 //00000001
|
||||
#define MM_PB_USED 0x02 //00000010
|
||||
void mm_pfreen(dword base, dword pages);
|
||||
void mm_pfree(dword base);
|
||||
void *mm_palloc();
|
||||
dword mm_freemem();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// mouse.c
|
||||
// 10/03/03
|
||||
// Author: Josh Holtrop
|
||||
|
||||
|
||||
//This method initializes the ps/2 mouse
|
||||
void mouse_init()
|
||||
{
|
||||
outportb(0x64, 0x20); //tell keyboard controller we are going to read keyboard controller command byte
|
||||
byte temp = inportb(0x60); //read keyboard controller command byte
|
||||
outportb(0x64, 0x60); //tell keyboard controller we are going to write keyboard controller command byte
|
||||
outportb(0x60, 0x03 | (temp&0x40)); //write keyboard controller command byte: enable mouse/keyboard ints, include original XLATE bit from temp (bit6)
|
||||
|
||||
outportb(0x64, 0xA8); //enable mouse port
|
||||
|
||||
outportb(0x64, 0xD4); //send command to mouse, not kbd
|
||||
outportb(0x60, 0xF4); //enable data reporting
|
||||
|
||||
mouse_x = video_mode.XResolution >> 1;
|
||||
mouse_y = video_mode.YResolution >> 1;
|
||||
|
||||
//outportb(0x64, 0xD4);
|
||||
//outportb(0x60, 0xE7); //scaling 2:1
|
||||
}
|
||||
|
||||
|
||||
//This method is called when a mouse interrupt occurs
|
||||
void isr_mouse()
|
||||
{
|
||||
byte inb = inportb(0x60); //read mouse byte
|
||||
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
|
||||
return;
|
||||
mouse_inbuffer[mouse_bytesRead] = inb;
|
||||
mouse_bytesRead++;
|
||||
if (mouse_bytesRead == 3) //complete packet received
|
||||
{
|
||||
mouse_bytesRead = 0;
|
||||
int adjx = (char) mouse_inbuffer[1];
|
||||
int adjy = (char) mouse_inbuffer[2];
|
||||
mouse_x += adjx;
|
||||
mouse_y -= adjy; //-= because screen y coordinates are opposite mouse y coordinates
|
||||
if (mouse_x < 0)
|
||||
mouse_x = 0;
|
||||
if (mouse_x >= video_mode.XResolution)
|
||||
mouse_x = video_mode.XResolution - 1;
|
||||
if (mouse_y < 0)
|
||||
mouse_y = 0;
|
||||
if (mouse_y >= video_mode.YResolution)
|
||||
mouse_y = video_mode.YResolution - 1;
|
||||
if (mouse_inbuffer[0] & 0x01) //left button
|
||||
video_pset(mouse_x, mouse_y, 0x00FF8800);
|
||||
else
|
||||
video_pset(mouse_x, mouse_y, 0x00FFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// mouse.h
|
||||
// 10/03/03
|
||||
// Author: Josh Holtrop
|
||||
|
||||
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
int mouse_bytesRead = 0;
|
||||
byte mouse_inbuffer[16];
|
||||
|
||||
void mouse_init();
|
||||
void isr_mouse();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+3
-3
@@ -28,12 +28,12 @@ brDrive DB 0 ; 0024h - Physical drive no.
|
||||
DB 0 ; 0025h - Reserved (FAT32)
|
||||
DB 29H ; 0026h - Extended boot record sig (FAT32)
|
||||
brSerialNum DD 404418EAH ; 0027h - Volume serial number
|
||||
brLabel DB 'HOS 0.1.1 ' ; 002Bh - Volume label
|
||||
brLabel DB 'Holtrops OS' ; 002Bh - Volume label
|
||||
brFSID DB 'FAT12 ' ; 0036h - File System ID
|
||||
;------------------------------------------------------------------------
|
||||
|
||||
start:
|
||||
jmp 0:jmphere ;ensure that cs=0 and ip=0x7c...
|
||||
jmp 0:jmphere ;ensure that cs=0 and ip=0x7c00...
|
||||
jmphere:
|
||||
;dl=drive number, save it!
|
||||
xor ax, ax
|
||||
@@ -88,7 +88,7 @@ unreal:
|
||||
pop es ;segments back, with 4gb limits!
|
||||
sti
|
||||
|
||||
;now lets read in the FAT and root directory so we can search for the kernel file...
|
||||
;now lets read in the FAT and root directory so we can search for the stage2 file...
|
||||
mov ax, 0x0209 ;FAT1
|
||||
mov cx, 0x0002
|
||||
xor dh, dh
|
||||
|
||||
+67
-16
@@ -30,6 +30,7 @@ loop_name:
|
||||
jmp found_file ;good file, ds:si points to start of root directory entry
|
||||
goon:
|
||||
pop si
|
||||
add si, 32
|
||||
pop cx
|
||||
loop loop_compare
|
||||
|
||||
@@ -147,29 +148,43 @@ got_rd:
|
||||
mov [ds:BOOT_HASRD], al
|
||||
pop ds ;ds=0
|
||||
cmp al, 0 ;dont load rd
|
||||
jz no_rd
|
||||
|
||||
jnz yes_rd
|
||||
jmp no_rd
|
||||
yes_rd:
|
||||
mov cx, 80
|
||||
mov edi, 0xb8000+160*4
|
||||
filler_loop:
|
||||
filler_loop: ;draw a red bar
|
||||
mov word [ds:edi], 0x0400+177
|
||||
inc edi
|
||||
inc edi
|
||||
loop filler_loop
|
||||
|
||||
mov cx, 80 ;80 cylinders to read
|
||||
xor si, si
|
||||
xor si, si ;start at cylinder 0
|
||||
mov edi, BOOT_RD_ADD ;ram disk address
|
||||
read_cylinder:
|
||||
push cx
|
||||
mov bx, 0x0100
|
||||
|
||||
mov bx, 0x0100 ;read sectors from head 0
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
mov ax, 0x0224
|
||||
mov cx, si
|
||||
mov ch, cl
|
||||
mov cl, 1
|
||||
xor dx, dx
|
||||
mov dl, [gs:BOOT_DRIVE]
|
||||
xor bx, bx ;es:bx = data buffer for read
|
||||
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
|
||||
mov cx, si ;what cyl. we are on is now in cx
|
||||
mov ch, cl ;ch = cyl. number
|
||||
mov cl, 1 ;cl = sector number 1-63
|
||||
xor dx, dx ;dh = head number
|
||||
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
|
||||
int 0x13
|
||||
|
||||
mov bx, 0x0100 ;now read sectors from head 1
|
||||
mov es, bx
|
||||
mov bx, 9216 ;es:bx = data buffer for read
|
||||
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
|
||||
mov cx, si ;what cyl. we are on is now in cx
|
||||
mov ch, cl ;ch = cyl. number
|
||||
mov cl, 1 ;cl = sector number 1-63
|
||||
mov dh, 1 ;dh = head number
|
||||
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
|
||||
int 0x13
|
||||
|
||||
mov ebx, 0xb8000
|
||||
@@ -836,7 +851,7 @@ puthex2_goon2:
|
||||
ret
|
||||
|
||||
;------------------------------------------------------
|
||||
txt_welcome: db " Welcome to HOS v", VERSION, "! ", 0
|
||||
txt_welcome: db " Welcome to HOS v", VERSION, "! ", 0
|
||||
txt_rd1: db "1. Do not load an initial ram disk", 0
|
||||
txt_rd2: db "2. Load initial ram disk from floppy", 0
|
||||
txt_input: db "Enter your selection: ", 0
|
||||
@@ -889,11 +904,43 @@ KERNEL_DATA equ $-gdt
|
||||
db 0x00
|
||||
db 0x00
|
||||
db 0x92
|
||||
db 0xcf ;cf
|
||||
db 0xcf
|
||||
db 0x00
|
||||
|
||||
gdt_end:
|
||||
|
||||
|
||||
;-------------------------------------------------------
|
||||
gdtr32:
|
||||
dw gdt_end32-gdt32-1
|
||||
dd gdt32
|
||||
gdt32:
|
||||
dd 0
|
||||
dd 0
|
||||
|
||||
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
|
||||
KERNEL_CODE32 equ $-gdt32
|
||||
db 0xff ;limit 7:0
|
||||
db 0xff ;limit 15:8
|
||||
db 0x00 ;base 7:0
|
||||
db 0x00 ;base 15:8
|
||||
db 0x00 ;base 23:16
|
||||
db 0x9a ;access
|
||||
db 0xcf ;flags / limit 19:16
|
||||
db 0x40 ;base 31:24
|
||||
|
||||
KERNEL_DATA32 equ $-gdt32
|
||||
db 0xff ;segment 16 = 4gb data
|
||||
db 0xff
|
||||
db 0x00
|
||||
db 0x00
|
||||
db 0x00
|
||||
db 0x92
|
||||
db 0xcf
|
||||
db 0x40
|
||||
|
||||
gdt_end32:
|
||||
|
||||
;------------------------------------------------------
|
||||
go_pm:
|
||||
xor ax, ax
|
||||
@@ -908,12 +955,16 @@ go_pm:
|
||||
|
||||
bits 32
|
||||
pmode:
|
||||
mov ax, KERNEL_DATA
|
||||
lgdt [gdtr32]
|
||||
jmp KERNEL_CODE32:pmode_offsetted+0xC0000000
|
||||
|
||||
pmode_offsetted:
|
||||
mov ax, KERNEL_DATA32
|
||||
mov es, ax
|
||||
mov ds, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
jmp KERNEL_CODE:BOOT_KERNEL_ADD
|
||||
jmp KERNEL_CODE:BOOT_KERNEL_ADD+0xC0000000
|
||||
|
||||
kernel: db "KERNEL BIN", 0
|
||||
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
const byte stdfont[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xE0, 0xC0, 0x80,
|
||||
0x00, 0x08, 0x18, 0x38, 0x78, 0x38, 0x18, 0x08,
|
||||
0x00, 0x20, 0x70, 0xA8, 0x20, 0xA8, 0x70, 0x20,
|
||||
0x00, 0xA0, 0xA0, 0xA0, 0xA0, 0x00, 0xA0, 0xA0,
|
||||
0x00, 0x78, 0xA8, 0xA8, 0x78, 0x28, 0x28, 0x68,
|
||||
0x00, 0x78, 0x80, 0x70, 0x88, 0x70, 0x08, 0xF0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8,
|
||||
0x00, 0x20, 0x70, 0xA8, 0x20, 0xA8, 0x70, 0xF8,
|
||||
0x00, 0x20, 0x70, 0xA8, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0xA8, 0x70, 0x20,
|
||||
0x00, 0x00, 0x20, 0x10, 0xF8, 0x10, 0x20, 0x00,
|
||||
0x00, 0x00, 0x20, 0x40, 0xF8, 0x40, 0x20, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x60, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x70, 0xF8, 0xF8, 0x00, 0x00,
|
||||
0x00, 0x00, 0xF8, 0xF8, 0x70, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20,
|
||||
0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x50, 0xF8, 0x50, 0x50, 0x50, 0xF8, 0x50,
|
||||
0x00, 0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20,
|
||||
0x00, 0x00, 0x08, 0x90, 0x20, 0x48, 0x80, 0x00,
|
||||
0x00, 0x20, 0x50, 0x50, 0x20, 0x58, 0x90, 0x68,
|
||||
0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20,
|
||||
0x00, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40,
|
||||
0x00, 0x00, 0xA8, 0x70, 0xF8, 0x70, 0xA8, 0x00,
|
||||
0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40,
|
||||
0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
|
||||
0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00,
|
||||
0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0x20, 0x60, 0xA0, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8,
|
||||
0x00, 0x70, 0x88, 0x08, 0x10, 0x08, 0x88, 0x70,
|
||||
0x00, 0x30, 0x50, 0x90, 0x90, 0xF8, 0x10, 0x10,
|
||||
0x00, 0xF8, 0x80, 0x80, 0xF8, 0x08, 0x88, 0x70,
|
||||
0x00, 0x38, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70,
|
||||
0x00, 0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40,
|
||||
0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70,
|
||||
0x00, 0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60,
|
||||
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00,
|
||||
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x40,
|
||||
0x00, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00,
|
||||
0x00, 0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80,
|
||||
0x00, 0x70, 0x88, 0x08, 0x10, 0x20, 0x00, 0x20,
|
||||
0x00, 0x70, 0x88, 0x88, 0xB8, 0xB0, 0x80, 0x78,
|
||||
0x00, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88,
|
||||
0x00, 0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0,
|
||||
0x00, 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70,
|
||||
0x00, 0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0,
|
||||
0x00, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8,
|
||||
0x00, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80,
|
||||
0x00, 0x70, 0x88, 0x80, 0xB8, 0x88, 0x88, 0x70,
|
||||
0x00, 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60,
|
||||
0x00, 0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88,
|
||||
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8,
|
||||
0x00, 0x88, 0xD8, 0xA8, 0x88, 0x88, 0x88, 0x88,
|
||||
0x00, 0x88, 0xC8, 0xE8, 0xB8, 0x98, 0x88, 0x88,
|
||||
0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80,
|
||||
0x00, 0x70, 0x88, 0x88, 0x88, 0xA8, 0x98, 0x70,
|
||||
0x00, 0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88,
|
||||
0x00, 0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70,
|
||||
0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20,
|
||||
0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0xA8, 0x50,
|
||||
0x00, 0x88, 0x50, 0x20, 0x20, 0x50, 0x88, 0x88,
|
||||
0x00, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8,
|
||||
0x00, 0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70,
|
||||
0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x08, 0x00,
|
||||
0x00, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0,
|
||||
0x00, 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
|
||||
0x00, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78,
|
||||
0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0xF0,
|
||||
0x00, 0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70,
|
||||
0x00, 0x08, 0x08, 0x78, 0x88, 0x88, 0x88, 0x78,
|
||||
0x00, 0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x78,
|
||||
0x00, 0x30, 0x40, 0x40, 0xE0, 0x40, 0x40, 0x40,
|
||||
0x00, 0x00, 0x00, 0x78, 0x88, 0x78, 0x08, 0x70,
|
||||
0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x88,
|
||||
0x00, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x90, 0x60,
|
||||
0x00, 0x80, 0x80, 0x90, 0xA0, 0xC0, 0xA0, 0x90,
|
||||
0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0,
|
||||
0x00, 0x00, 0x00, 0xD0, 0xA8, 0xA8, 0xA8, 0xA8,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x88, 0x88, 0x88, 0x88,
|
||||
0x00, 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x88, 0xF0, 0x80, 0x80,
|
||||
0x00, 0x00, 0x00, 0x78, 0x88, 0x78, 0x08, 0x38,
|
||||
0x00, 0x00, 0x00, 0x70, 0x48, 0x40, 0x40, 0x40,
|
||||
0x00, 0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0,
|
||||
0x00, 0x40, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x20,
|
||||
0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x78,
|
||||
0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20,
|
||||
0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0xA8, 0x50,
|
||||
0x00, 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88,
|
||||
0x00, 0x00, 0x00, 0x88, 0x88, 0x78, 0x08, 0xF0,
|
||||
0x00, 0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8,
|
||||
0x00, 0x30, 0x40, 0x40, 0x80, 0x40, 0x40, 0x30,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0xC0, 0x20, 0x20, 0x10, 0x20, 0x20, 0xC0,
|
||||
0x00, 0x00, 0x68, 0x90, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88,
|
||||
0x00, 0xF8, 0x88, 0x80, 0xF0, 0x88, 0x88, 0xF0,
|
||||
0x00, 0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0,
|
||||
0x00, 0xF8, 0x48, 0x40, 0x40, 0x40, 0x40, 0xE0,
|
||||
0x00, 0xF0, 0x50, 0x50, 0x50, 0x50, 0x78, 0x88,
|
||||
0x00, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8,
|
||||
0x00, 0xA8, 0xA8, 0x70, 0x20, 0x70, 0xA8, 0xA8,
|
||||
0x00, 0x70, 0x88, 0x08, 0x30, 0x08, 0x88, 0x70,
|
||||
0x00, 0x88, 0x98, 0xA8, 0xA8, 0xA8, 0xC8, 0x88,
|
||||
0x00, 0xA8, 0xC8, 0x98, 0xA8, 0xA8, 0xC8, 0x88,
|
||||
0x00, 0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88,
|
||||
0x00, 0xF8, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90,
|
||||
0x00, 0x88, 0xD8, 0xA8, 0x88, 0x88, 0x88, 0x88,
|
||||
0x00, 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88,
|
||||
0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x00, 0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80,
|
||||
0x00, 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70,
|
||||
0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x40, 0x80,
|
||||
0x00, 0x70, 0x20, 0xF8, 0xA8, 0xF8, 0x20, 0x70,
|
||||
0x00, 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88,
|
||||
0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF8, 0x08,
|
||||
0x00, 0x88, 0x88, 0x88, 0xF8, 0x08, 0x08, 0x38,
|
||||
0x00, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xF8,
|
||||
0x00, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xF8, 0x08,
|
||||
0x00, 0xC0, 0x40, 0x40, 0x78, 0x48, 0x48, 0x78,
|
||||
0x00, 0x88, 0x88, 0xC8, 0xA8, 0xA8, 0xA8, 0xE8,
|
||||
0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0xF0,
|
||||
0x00, 0xF0, 0x88, 0x08, 0x78, 0x08, 0x88, 0xF0,
|
||||
0x00, 0x90, 0xA8, 0xA8, 0xE8, 0xA8, 0xA8, 0x90,
|
||||
0x00, 0x78, 0x88, 0x88, 0x78, 0x28, 0x48, 0x88,
|
||||
0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x88, 0x78,
|
||||
0x00, 0x00, 0xF8, 0x80, 0xF0, 0x88, 0x88, 0xF0,
|
||||
0x00, 0x00, 0xF0, 0x88, 0xF0, 0x88, 0x88, 0xF0,
|
||||
0x00, 0x00, 0xF8, 0x48, 0x48, 0x40, 0x40, 0xE0,
|
||||
0x00, 0x00, 0x78, 0x50, 0x50, 0x50, 0x70, 0x88,
|
||||
0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x88, 0x70,
|
||||
0x00, 0x00, 0xA8, 0x70, 0x20, 0x70, 0xA8, 0xA8,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x88, 0x30, 0x88, 0x70,
|
||||
0x00, 0x00, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x88,
|
||||
0x00, 0x50, 0x20, 0x88, 0x98, 0xA8, 0xC8, 0x88,
|
||||
0x00, 0x00, 0x88, 0x90, 0xA0, 0xE0, 0x90, 0x88,
|
||||
0x00, 0x00, 0xF8, 0x48, 0x48, 0x48, 0x48, 0xC8,
|
||||
0x00, 0x00, 0x88, 0xD8, 0xA8, 0x88, 0x88, 0x88,
|
||||
0x00, 0x00, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88,
|
||||
0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x70, 0x50, 0x70, 0x08, 0x78, 0x88, 0x78,
|
||||
0x00, 0x88, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78,
|
||||
0x00, 0x88, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0x88, 0x00, 0x88, 0x88, 0x88, 0x88, 0x78,
|
||||
0x00, 0x90, 0x00, 0xF0, 0x80, 0xE0, 0x80, 0xF0,
|
||||
0x00, 0x00, 0x70, 0x48, 0x70, 0x48, 0x48, 0xF0,
|
||||
0x00, 0x88, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x88, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x78,
|
||||
0x00, 0x70, 0x50, 0x70, 0x88, 0xF8, 0x88, 0x88,
|
||||
0x00, 0x88, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88,
|
||||
0x00, 0x88, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70,
|
||||
0x00, 0x88, 0x00, 0x88, 0x88, 0x88, 0x88, 0x78,
|
||||
0x00, 0x88, 0xF8, 0x80, 0xE0, 0x80, 0x80, 0xF8,
|
||||
0x00, 0x40, 0x20, 0x70, 0x88, 0xF8, 0x80, 0x78,
|
||||
0x00, 0x10, 0x20, 0x70, 0x88, 0xF8, 0x80, 0x78,
|
||||
0x00, 0x20, 0x50, 0x70, 0x88, 0xF8, 0x80, 0x78,
|
||||
0x00, 0x40, 0x20, 0x70, 0x08, 0x78, 0x88, 0x78,
|
||||
0x00, 0x20, 0x50, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x20, 0x10, 0x88, 0x88, 0x88, 0x88, 0x78,
|
||||
0x00, 0x00, 0x00, 0x70, 0x80, 0x80, 0x70, 0x20,
|
||||
0x00, 0x70, 0x88, 0x40, 0xF0, 0x40, 0x40, 0xF8,
|
||||
0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x88, 0x88, 0x88, 0xF0, 0x80, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80,
|
||||
0x00, 0x00, 0x70, 0x88, 0x80, 0x80, 0x88, 0x70,
|
||||
0x00, 0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x00, 0x88, 0x88, 0x50, 0x20, 0x40, 0x80,
|
||||
0x00, 0x00, 0x70, 0x20, 0xF8, 0xF8, 0x20, 0x70,
|
||||
0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88,
|
||||
0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0xF8, 0x08,
|
||||
0x00, 0x00, 0x88, 0x88, 0x88, 0xF8, 0x08, 0x38,
|
||||
0x00, 0x00, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xF8,
|
||||
0x00, 0x00, 0xA8, 0xA8, 0xA8, 0xA8, 0xF8, 0x08,
|
||||
0x00, 0x00, 0xC0, 0x40, 0x70, 0x48, 0x48, 0x70,
|
||||
0x00, 0x00, 0x88, 0x88, 0xC8, 0xA8, 0xA8, 0xE8,
|
||||
0x00, 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0xF0,
|
||||
0x00, 0x00, 0x70, 0x88, 0x38, 0x08, 0x88, 0x70,
|
||||
0x00, 0x00, 0x90, 0xA8, 0xA8, 0xE8, 0xA8, 0x90,
|
||||
0x00, 0x00, 0x38, 0x48, 0x48, 0x38, 0x28, 0x48,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,151 +1,176 @@
|
||||
//video.c
|
||||
// 08/13/03 Josh Holtrop
|
||||
// Modified: 11/12/03
|
||||
|
||||
ModeInfoBlock video_mode;
|
||||
byte *vid_ptr24;
|
||||
word *vid_ptr16;
|
||||
dword *vid_ptr32;
|
||||
|
||||
void video_init(ModeInfoBlock *mib)
|
||||
//Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display
|
||||
void video_init()
|
||||
{
|
||||
video_mode = *mib;
|
||||
videoMode = *(word *)0xC0090002;
|
||||
|
||||
if (!videoMode) //we are in console mode
|
||||
return;
|
||||
|
||||
video_mode = *(ModeInfoBlock *) 0xC0090306;
|
||||
|
||||
switch(video_mode.BitsPerPixel)
|
||||
{
|
||||
case 16:
|
||||
vid_ptr16 = (word *) video_mode.PhysBasePtr;
|
||||
video_psetp = &video_psetp16;
|
||||
break;
|
||||
case 24:
|
||||
vid_ptr24 = (byte *) video_mode.PhysBasePtr;
|
||||
video_psetp = &video_psetp24;
|
||||
break;
|
||||
case 32:
|
||||
vid_ptr32 = (dword *) video_mode.PhysBasePtr;
|
||||
}
|
||||
|
||||
dword tot = ((video_mode.XResolution) * (video_mode.YResolution));
|
||||
int a;
|
||||
for (a = 0; a < tot; a++)
|
||||
{
|
||||
if (a < (tot / 4))
|
||||
video_psetp(a, 0x00FF0000);
|
||||
else if (a < (tot / 2))
|
||||
video_psetp(a, 0x0000FF00);
|
||||
else if (a < ((tot * 3) / 4))
|
||||
video_psetp(a, 0x000000FF);
|
||||
else
|
||||
video_psetp(a, 0x00FFFFFF);
|
||||
video_psetp = &video_psetp32;
|
||||
}
|
||||
}
|
||||
|
||||
void video_horiz(int y, int x1, int x2, dword color)
|
||||
//Renders a character using stdfont[] as a bitmask
|
||||
void video_renderChar(int x, int y, int character, dword color)
|
||||
{
|
||||
int charpos = (character & 0xFF) * 8;
|
||||
int row;
|
||||
int col;
|
||||
for (row = 0; row < 8; row++)
|
||||
{
|
||||
for (col = 0; col < 5; col++)
|
||||
{
|
||||
if ((stdfont[charpos+row] >> (col+3)) & 0x01)
|
||||
video_pset(x+(5-col), y+row, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Draws a horizontal line
|
||||
void video_horiz(int y, int x1, int x2, dword color)
|
||||
{
|
||||
checkBoundsy(y);
|
||||
checkBoundsx(x1);
|
||||
checkBoundsx(x2);
|
||||
if (x1 > x2)
|
||||
{
|
||||
int tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
x1 = tmp; //x2 >= x1 now
|
||||
}
|
||||
if (x2 < 0)
|
||||
return;
|
||||
if (x1 > video_mode.XResolution)
|
||||
return;
|
||||
if (x1 < 0)
|
||||
x1 = 0;
|
||||
if (x2 > video_mode.XResolution)
|
||||
x2 = video_mode.XResolution;
|
||||
int pixel = y*video_mode.XResolution+x1;
|
||||
int a;
|
||||
for (a = 0; a <= (x2-x1); a++)
|
||||
for (; x1 <= x2; x1++)
|
||||
{
|
||||
video_psetp(pixel, color);
|
||||
pixel++;
|
||||
video_psetp(pixel++, color);
|
||||
}
|
||||
}
|
||||
|
||||
void video_vert(int x, int y1, int y2, dword color)
|
||||
//Draws a vertical line
|
||||
void video_vert(int x, int y1, int y2, dword color)
|
||||
{
|
||||
checkBoundsx(x);
|
||||
checkBoundsy(y1);
|
||||
checkBoundsy(y2);
|
||||
if (y1 > y2)
|
||||
{
|
||||
int tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
y1 = tmp; //y2 >= y1 now
|
||||
}
|
||||
if (y2 < 0)
|
||||
return;
|
||||
if (y1 > video_mode.YResolution)
|
||||
return;
|
||||
if (y1 < 0)
|
||||
y1 = 0;
|
||||
if (y2 > video_mode.YResolution)
|
||||
y2 = video_mode.YResolution;
|
||||
int pixel = y1*video_mode.XResolution+x;
|
||||
int a;
|
||||
for (a = 0; a <= (y2-y1); a++)
|
||||
for (; y1 <= y2; y1++)
|
||||
{
|
||||
video_psetp(pixel, color);
|
||||
pixel+=video_mode.XResolution;
|
||||
}
|
||||
}
|
||||
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color)
|
||||
//Draws a rectangle
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color)
|
||||
{
|
||||
checkBoundsx(x1);
|
||||
checkBoundsx(x2);
|
||||
checkBoundsy(y1);
|
||||
checkBoundsy(y2);
|
||||
if (x2 < x1)
|
||||
{
|
||||
int tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y2 < y1)
|
||||
{
|
||||
int tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
video_horiz(y1, x1, x2, color);
|
||||
video_horiz(y2, x1, x2, color);
|
||||
video_vert(x1, y1, y2, color);
|
||||
video_vert(x2, y1, y2, color);
|
||||
}
|
||||
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color)
|
||||
//Draws a filled rectangle
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color)
|
||||
{
|
||||
checkBoundsx(x1);
|
||||
checkBoundsx(x2);
|
||||
checkBoundsy(y1);
|
||||
checkBoundsy(y2);
|
||||
if (x2 < x1)
|
||||
{
|
||||
int tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y2 < y1)
|
||||
{
|
||||
int tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
int a;
|
||||
for (a = 0; a <= (y2-y1); a++)
|
||||
video_horiz(y1+a, x1, x2, color);
|
||||
for (; y1 <= y2; y1++)
|
||||
video_horiz(y1, x1, x2, color);
|
||||
}
|
||||
|
||||
//Draws a single pixel
|
||||
inline void video_pset(int x, int y, dword color)
|
||||
{
|
||||
if ((x < 0) || (x > video_mode.XResolution) || (y < 0) || (y > video_mode.YResolution))
|
||||
return;
|
||||
video_psetp(y*video_mode.XResolution+x, color);
|
||||
}
|
||||
|
||||
void video_psetp(int pixel, dword color)
|
||||
//Draws a pixel at the specified pixel position
|
||||
void video_psetp16(int pixel, dword color)
|
||||
{
|
||||
switch(video_mode.BitsPerPixel)
|
||||
vid_ptr16[pixel] = ((color&0xFF)>>3) | ((((color>>8)&0xFF)>>2)<<5) | ((((color>>16)&0xFF)>>3)<<11);
|
||||
}
|
||||
|
||||
//Draws a pixel at the specified pixel position
|
||||
void video_psetp24(int pixel, dword color)
|
||||
{
|
||||
vid_ptr24[pixel*3] = color & 0xFF;
|
||||
vid_ptr24[pixel*3+1] = (color>>8) & 0xFF;
|
||||
vid_ptr24[pixel*3+2] = (color>>16) & 0xFF;
|
||||
}
|
||||
|
||||
//Draws a pixel at the specified pixel position
|
||||
void video_psetp32(int pixel, dword color)
|
||||
{
|
||||
vid_ptr32[pixel] = color;
|
||||
}
|
||||
|
||||
//Dummy function to not draw anything if there is no graphical mode enabled
|
||||
void video_psetpnull(int pixel, dword color) {}
|
||||
|
||||
|
||||
// This function draws a simple "console" window in graphical mode to display text
|
||||
void video_drawConsole()
|
||||
{
|
||||
video_rectf(9, 9, 490, 260, 0);
|
||||
video_rect(8, 8, 491, 261, 0x00777777);
|
||||
int x, y;
|
||||
for (x = 0; x < 80; x++)
|
||||
{
|
||||
case 16:
|
||||
vid_ptr16[pixel] = ((color&0xFF)>>3) | ((((color>>8)&0xFF)>>2)<<6) | ((((color>>16)&0xFF)>>3)<<11);
|
||||
//vid_ptr16[pixel] = ((color&0xFF)>>3) | ((((color>>8)&0xFF)>>3)<<5) | ((((color>>16)&0xFF)>>3)<<10);
|
||||
break;
|
||||
case 24:
|
||||
vid_ptr24[pixel*3] = color & 0xFF;
|
||||
vid_ptr24[pixel*3+1] = (color>>8) & 0xFF;
|
||||
vid_ptr24[pixel*3+2] = (color>>16) & 0xFF;
|
||||
break;
|
||||
case 32:
|
||||
vid_ptr32[pixel] = color;
|
||||
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,18 +1,22 @@
|
||||
//video.h
|
||||
// 08/18/03 Josh Holtrop
|
||||
// Modified: 12/28/03
|
||||
|
||||
void video_init();
|
||||
void video_horiz(int y, int x1, int x2, dword color);
|
||||
void video_vert(int x, int y1, int y2, dword color);
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color);
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color);
|
||||
void video_init();
|
||||
void video_horiz(int y, int x1, int x2, dword color);
|
||||
void video_vert(int x, int y1, int y2, dword color);
|
||||
void video_rect(int x1, int y1, int x2, int y2, dword color);
|
||||
void video_rectf(int x1, int y1, int x2, int y2, dword color);
|
||||
inline void video_pset(int x, int y, dword color);
|
||||
void video_psetp(int pixel, dword color);
|
||||
void video_psetp16(int pixel, dword color);
|
||||
void video_psetp24(int pixel, dword color);
|
||||
void video_psetp32(int pixel, dword color);
|
||||
void video_psetpnull(int pixel, dword color);
|
||||
void video_renderChar(int x, int y, int character, dword color);
|
||||
void video_drawConsole();
|
||||
void video_drawConsoleChar(dword position);
|
||||
|
||||
|
||||
#define checkBoundsx(x) (x<0 ? x=0 : (x>=video_mode.XResolution ? x=video_mode.XResolution-1 : 0))
|
||||
#define checkBoundsy(x) (x<0 ? x=0 : (x>=video_mode.YResolution ? x=video_mode.YResolution-1 : 0))
|
||||
|
||||
typedef struct{
|
||||
word ModeAttributes;
|
||||
byte WinAAttributes;
|
||||
@@ -53,6 +57,15 @@ typedef struct{
|
||||
} ModeInfoBlock;
|
||||
|
||||
|
||||
ModeInfoBlock video_mode;
|
||||
dword videoMode = 0; //what video mode # we are in, 0 for console mode
|
||||
word *vid_ptr16 = (word *)0xF0000000;
|
||||
byte *vid_ptr24 = (byte *)0xF0000000;
|
||||
dword *vid_ptr32 = (dword *)0xF0000000;
|
||||
word console_memory[2000]; //holds a copy of the console's memory
|
||||
void (*video_psetp)(int, dword) = video_psetpnull; //function pointer to set a pixel
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
// vmm.c
|
||||
// Author: Josh Holtrop
|
||||
// Date: 09/30/03
|
||||
// Rewritten from scratch: 12/23/03
|
||||
// Modified: 12/30/03
|
||||
|
||||
|
||||
// This is the initialization procedure for the Virtual Memory Manager
|
||||
// It sets up the final page directory/page table setup and maps video memory, if present
|
||||
void vmm_init()
|
||||
{
|
||||
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
|
||||
{
|
||||
dword vidPages = video_mode.XResolution * video_mode.YResolution * (video_mode.BitsPerPixel >> 3);
|
||||
if (vidPages % 4096)
|
||||
vidPages = (vidPages >> 12) + 1;
|
||||
else
|
||||
vidPages = (vidPages >> 12);
|
||||
vmm_mapn(0xF0000000, video_mode.PhysBasePtr, vidPages);
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
// This function initialzes a Heap Entry Block to unused entries linked together
|
||||
void vmm_heb_init(HeapEntryBlock *heb)
|
||||
{
|
||||
int a;
|
||||
for (a = 0; a < 256; a++)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
heb->entry[255].link = 0;
|
||||
}
|
||||
|
||||
|
||||
// This function maps a virtual address to a physical address using the page directory / page table
|
||||
void vmm_map1(dword virt, dword physical)
|
||||
{
|
||||
dword pde = virt >> 22;
|
||||
dword pte = (virt & 0x003FF000) >> 12;
|
||||
dword *pageTables = (dword *)0xC0104000; //this is the location of the page directory
|
||||
if (!(pageTables[pde] & 0x01)) //the page directory entry does not exist, we must allocate a page for it
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function removes the virtual address's entry in the page directory / page table
|
||||
void vmm_unmap1(dword virt)
|
||||
{
|
||||
dword *pteptr = (dword *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10));
|
||||
*pteptr = 0;
|
||||
invlpg(virt);
|
||||
}
|
||||
|
||||
|
||||
// This function removes multiple pages' entries
|
||||
void vmm_unmapn(dword virt, dword n)
|
||||
{
|
||||
for (; n > 0; n--)
|
||||
{
|
||||
vmm_unmap1(virt);
|
||||
virt += 4096;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Virtual Memory allocator function
|
||||
void *malloc(dword bytes)
|
||||
{
|
||||
if (bytes % VMM_MALLOC_GRANULARITY)
|
||||
bytes = bytes + VMM_MALLOC_GRANULARITY - (bytes % VMM_MALLOC_GRANULARITY);
|
||||
void *attempt = vmm_getFreeChunk(bytes);
|
||||
if (attempt)
|
||||
return attempt;
|
||||
if(vmm_moreCore(bytes))
|
||||
return 0; //we could not get any more heap memory
|
||||
return vmm_getFreeChunk(bytes);
|
||||
}
|
||||
|
||||
|
||||
// This function returns a pointer if a free chunk of memory exists
|
||||
void *vmm_getFreeChunk(dword bytes)
|
||||
{
|
||||
HeapEntry *he = firstHeapEntry;
|
||||
for (;;)
|
||||
{
|
||||
if (he->attributes == VMM_HE_FREE)
|
||||
{
|
||||
if (he->size > bytes)
|
||||
{
|
||||
HeapEntry *nhe = vmm_nextHeapEntry();
|
||||
nhe->base = he->base;
|
||||
nhe->size = bytes;
|
||||
nhe->attributes = VMM_HE_USED;
|
||||
he->base += bytes;
|
||||
he->size -= bytes;
|
||||
return (void *)(nhe->base);
|
||||
}
|
||||
if (he->size == bytes)
|
||||
{
|
||||
he->attributes = VMM_HE_USED;
|
||||
return (void *)(he->base);
|
||||
}
|
||||
}
|
||||
he = (HeapEntry *)he->link;
|
||||
if (!he)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This function coalesces any two adjacent heap entries into one entry
|
||||
void vmm_coalesceHeapEntry(HeapEntry *he)
|
||||
{
|
||||
if (!(he->attributes == VMM_HE_FREE || he->attributes == VMM_HE_HOLE))
|
||||
return;
|
||||
if (he->size == 0)
|
||||
{
|
||||
he->attributes = VMM_HE_UNUSED;
|
||||
return;
|
||||
}
|
||||
HeapEntry *hec = firstHeapEntry;
|
||||
for (;;)
|
||||
{
|
||||
if (hec->attributes == he->attributes)
|
||||
{
|
||||
if ((hec->base + hec->size) == he->base) //hec ends where he begins
|
||||
{
|
||||
he->base = hec->base;
|
||||
he->size += hec->size;
|
||||
hec->attributes = VMM_HE_UNUSED;
|
||||
}
|
||||
if ((he->base + he->size) == hec->base) //he ends where hec begins
|
||||
{
|
||||
he->size += hec->size;
|
||||
hec->attributes = VMM_HE_UNUSED;
|
||||
}
|
||||
}
|
||||
hec = (HeapEntry *)hec->link;
|
||||
if (!hec)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function retrieves more physical memory for the heap
|
||||
int vmm_moreCore(dword bytes)
|
||||
{
|
||||
dword pages = (bytes >> 12) + 1;
|
||||
bytes = pages << 12;
|
||||
HeapEntry *he = vmm_getFirstHoleHeapEntry(bytes);
|
||||
dword virt = he->base;
|
||||
for (; pages > 0; pages--)
|
||||
{
|
||||
dword phys = (dword)mm_palloc();
|
||||
if (!phys)
|
||||
return 1;
|
||||
vmm_map1(virt, phys);
|
||||
virt += 4096;
|
||||
}
|
||||
if (he->size == bytes)
|
||||
{
|
||||
he->attributes = VMM_HE_FREE;
|
||||
vmm_coalesceHeapEntry(he);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapEntry *nhe = vmm_nextHeapEntry();
|
||||
nhe->base = he->base;
|
||||
nhe->size = bytes;
|
||||
nhe->attributes = VMM_HE_FREE;
|
||||
he->base += bytes;
|
||||
he->size -= bytes;
|
||||
vmm_coalesceHeapEntry(nhe);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This function returns the next available heap entry, creates more entries if we are running low
|
||||
HeapEntry *vmm_nextHeapEntry()
|
||||
{
|
||||
if (vmm_heapEntriesLeft() < 10)
|
||||
vmm_addHeapEntryBlock();
|
||||
return vmm_getFirstUnusedHeapEntry();
|
||||
}
|
||||
|
||||
|
||||
// This function creates a new block (page) of heap entries (256)
|
||||
void vmm_addHeapEntryBlock()
|
||||
{
|
||||
HeapEntry *he = vmm_getFirstHoleHeapEntry(4096);
|
||||
HeapEntry *newBlock = vmm_getFirstUnusedHeapEntry();
|
||||
dword heb = (dword)mm_palloc();
|
||||
vmm_map1(he->base, heb);
|
||||
vmm_heb_init((HeapEntryBlock *)he->base);
|
||||
HeapEntry *lhe = vmm_getLastHeapEntry();
|
||||
if (he->size == 4096)
|
||||
{
|
||||
he->attributes = VMM_HE_HEB;
|
||||
lhe->link = (dword)he->base;
|
||||
}
|
||||
else
|
||||
{
|
||||
newBlock->base = he->base;
|
||||
newBlock->size = 4096;
|
||||
newBlock->attributes = VMM_HE_HEB;
|
||||
he->base += 4096;
|
||||
he->size -= 4096;
|
||||
lhe->link = (dword)newBlock->base;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// This function returns the last heap entry in the linked list, useful for setting
|
||||
// its link field to point to the first entry of a newly allocated list
|
||||
HeapEntry *vmm_getLastHeapEntry()
|
||||
{
|
||||
HeapEntry *he = firstHeapEntry;
|
||||
for (;;)
|
||||
{
|
||||
if (he->link == 0)
|
||||
return he;
|
||||
he = (HeapEntry *)he->link;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function returns the first heap entry corresponding to a memory "hole"
|
||||
HeapEntry *vmm_getFirstHoleHeapEntry(dword minBytes)
|
||||
{
|
||||
HeapEntry *he = firstHeapEntry;
|
||||
for (;;)
|
||||
{
|
||||
if ((he->attributes == VMM_HE_HOLE) && (he->size >= minBytes))
|
||||
return he;
|
||||
he = (HeapEntry *)he->link;
|
||||
if (!he)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This function returns the first heap entry that is not being used
|
||||
HeapEntry *vmm_getFirstUnusedHeapEntry()
|
||||
{
|
||||
HeapEntry *he = firstHeapEntry;
|
||||
for (;;)
|
||||
{
|
||||
if (he->attributes == VMM_HE_UNUSED)
|
||||
return he;
|
||||
he = (HeapEntry *)he->link;
|
||||
if (!he)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This function returns the number of heap entries available for use
|
||||
dword vmm_heapEntriesLeft()
|
||||
{
|
||||
HeapEntry *he = firstHeapEntry;
|
||||
dword entries = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (he->attributes == VMM_HE_UNUSED)
|
||||
entries++;
|
||||
he = (HeapEntry *)he->link;
|
||||
if (!he)
|
||||
break;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
// This function "frees" an area of memory previously allocated with malloc()
|
||||
int free(void *ptr)
|
||||
{
|
||||
HeapEntry *he = vmm_getHeapEntryByBase((dword)ptr);
|
||||
if (!he)
|
||||
return 1; //a heap entry starting at the given address was not found
|
||||
he->attributes = VMM_HE_FREE;
|
||||
vmm_coalesceHeapEntry(he);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This function scans the heap entry linked list for an entry that begins at the given address
|
||||
HeapEntry *vmm_getHeapEntryByBase(dword base)
|
||||
{
|
||||
HeapEntry *he = firstHeapEntry;
|
||||
for (;;)
|
||||
{
|
||||
if (he->base == base)
|
||||
return he;
|
||||
he = (HeapEntry *)he->link;
|
||||
if (!he)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// vmm.h
|
||||
// Author: Josh Holtrop
|
||||
// Date: 09/30/03
|
||||
// Rewritten from scratch: 12/23/03
|
||||
// Modified: 12/30/03
|
||||
|
||||
|
||||
#define VMM_HE_UNUSED 0 //available entry
|
||||
#define VMM_HE_FREE 1 //free section of memory
|
||||
#define VMM_HE_USED 2 //used section of memory
|
||||
#define VMM_HE_HOLE 3 //a "hole" (unmapped) section of virtual memory
|
||||
#define VMM_HE_HEB 4 //HeapEntryBlock
|
||||
|
||||
#define VMM_MALLOC_GRANULARITY 4 //granularity for all memory requests
|
||||
|
||||
typedef struct {
|
||||
dword base; //virtual base address
|
||||
dword size; //size in bytes
|
||||
dword attributes; //free/used/hole
|
||||
dword link; //link to next HeapEntry
|
||||
} __attribute__((packed)) HeapEntry;
|
||||
|
||||
|
||||
typedef struct {
|
||||
HeapEntry entry[256]; //256 HeapEntry objects = 4kb (1 page)
|
||||
} __attribute__((packed)) HeapEntryBlock;
|
||||
|
||||
|
||||
void vmm_init();
|
||||
void *malloc(dword bytes);
|
||||
int free(void *ptr);
|
||||
void vmm_map1(dword virt, dword physical);
|
||||
void vmm_mapn(dword virt, dword physical, dword n);
|
||||
void vmm_unmap1(dword virt);
|
||||
void vmm_unmapn(dword virt, dword n);
|
||||
void vmm_heb_init(HeapEntryBlock *heb);
|
||||
void *vmm_getFreeChunk(dword bytes);
|
||||
HeapEntry *vmm_nextHeapEntry();
|
||||
dword vmm_heapEntriesLeft();
|
||||
HeapEntry *vmm_getLastHeapEntry();
|
||||
HeapEntry *vmm_getFirstUnusedHeapEntry();
|
||||
HeapEntry *vmm_getFirstHoleHeapEntry(dword minBytes);
|
||||
void vmm_addHeapEntryBlock();
|
||||
int vmm_moreCore(dword bytes);
|
||||
void vmm_coalesceHeapEntry(HeapEntry *he);
|
||||
HeapEntry *vmm_getHeapEntryByBase(dword base);
|
||||
|
||||
|
||||
HeapEntry *firstHeapEntry = (HeapEntry *)0xD0000000; //this is where heap memory starts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user